|
| 1 | +import {labelof, maybeValue, valueof} from "../mark.js"; |
| 2 | + |
| 3 | +// TODO Allow the interval to be specified as a string, e.g. “day” or “hour”? |
| 4 | +// This will require the interval knowing the type of the associated scale to |
| 5 | +// chose between UTC and local time (or better, an explicit timeZone option). |
| 6 | +function maybeInterval(interval) { |
| 7 | + if (interval == null) return; |
| 8 | + if (typeof interval.floor !== "function" || typeof interval.offset !== "function") throw new Error("invalid interval"); |
| 9 | + return interval; |
| 10 | +} |
| 11 | + |
| 12 | +// The interval may be specified either as x: {value, interval} or as {x, |
| 13 | +// interval}. The former is used, for example, for Plot.rect. |
| 14 | +function maybeIntervalValue(value, {interval} = {}) { |
| 15 | + (value = {...maybeValue(value)}); |
| 16 | + value.interval = maybeInterval(value.interval === undefined ? interval : value.interval); |
| 17 | + return value; |
| 18 | +} |
| 19 | + |
| 20 | +function maybeIntervalK(k, options = {}) { |
| 21 | + const {[k]: v, [`${k}1`]: v1, [`${k}2`]: v2} = options; |
| 22 | + const {value, interval} = maybeIntervalValue(v, options); |
| 23 | + if (interval == null) return options; |
| 24 | + let V1; |
| 25 | + const tv1 = data => V1 || (V1 = valueof(data, value).map(v => interval.floor(v))); |
| 26 | + const label = labelof(v); |
| 27 | + return { |
| 28 | + ...options, |
| 29 | + [k]: undefined, |
| 30 | + [`${k}1`]: v1 === undefined ? {transform: tv1, label} : v1, |
| 31 | + [`${k}2`]: v2 === undefined ? {transform: () => tv1().map(v => interval.offset(v)), label} : v2 |
| 32 | + }; |
| 33 | +} |
| 34 | + |
| 35 | +export function maybeIntervalX(options) { |
| 36 | + return maybeIntervalK("x", options); |
| 37 | +} |
| 38 | + |
| 39 | +export function maybeIntervalY(options = {}) { |
| 40 | + return maybeIntervalK("y", options); |
| 41 | +} |
0 commit comments