svelteplot 0.0.1-alpha.0 → 0.0.1-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/Plot.svelte +172 -0
  2. package/dist/Plot.svelte.d.ts +15 -0
  3. package/dist/classes/Channel.svelte.js +74 -0
  4. package/dist/classes/Mark.svelte.js +17 -0
  5. package/dist/classes/Plot.svelte.js +98 -0
  6. package/dist/contants.d.ts +3 -0
  7. package/dist/contants.js +40 -0
  8. package/dist/helpers/GroupMultiple.svelte +8 -0
  9. package/dist/helpers/GroupMultiple.svelte.d.ts +19 -0
  10. package/dist/helpers/autoTimeFormat.d.ts +2 -0
  11. package/dist/helpers/autoTimeFormat.js +10 -0
  12. package/dist/helpers/callWithProps.d.ts +4 -0
  13. package/dist/helpers/callWithProps.js +9 -0
  14. package/dist/helpers/colors.d.ts +13 -0
  15. package/dist/helpers/colors.js +200 -0
  16. package/dist/helpers/createScale.d.ts +5 -0
  17. package/dist/helpers/createScale.js +57 -0
  18. package/dist/helpers/getBaseStyles.d.ts +2 -0
  19. package/dist/helpers/getBaseStyles.js +18 -0
  20. package/dist/helpers/getLogTicks.d.ts +1 -0
  21. package/dist/helpers/getLogTicks.js +57 -0
  22. package/dist/helpers/isDataRecord.d.ts +2 -0
  23. package/dist/helpers/isDataRecord.js +13 -0
  24. package/dist/helpers/mergeDeep.d.ts +5 -0
  25. package/dist/helpers/mergeDeep.js +26 -0
  26. package/dist/helpers/removeIdenticalLines.d.ts +1 -0
  27. package/dist/helpers/removeIdenticalLines.js +16 -0
  28. package/dist/helpers/resolveChannel.d.ts +2 -0
  29. package/dist/helpers/resolveChannel.js +28 -0
  30. package/dist/helpers/symbols.d.ts +5 -0
  31. package/dist/helpers/symbols.js +51 -0
  32. package/dist/helpers/typeChecks.d.ts +7 -0
  33. package/dist/helpers/typeChecks.js +21 -0
  34. package/dist/helpers/wrapArray.d.ts +2 -0
  35. package/dist/helpers/wrapArray.js +4 -0
  36. package/dist/index.d.ts +19 -0
  37. package/dist/index.js +20 -0
  38. package/dist/marks/Area.svelte +81 -0
  39. package/dist/marks/Area.svelte.d.ts +15 -0
  40. package/dist/marks/AreaX.svelte +19 -0
  41. package/dist/marks/AreaX.svelte.d.ts +17 -0
  42. package/dist/marks/AreaY.svelte +14 -0
  43. package/dist/marks/AreaY.svelte.d.ts +17 -0
  44. package/dist/marks/AxisX.svelte +102 -0
  45. package/dist/marks/AxisX.svelte.d.ts +17 -0
  46. package/dist/marks/AxisY.svelte +80 -0
  47. package/dist/marks/AxisY.svelte.d.ts +15 -0
  48. package/dist/marks/BaseMark.svelte +22 -0
  49. package/dist/marks/BaseMark.svelte.d.ts +19 -0
  50. package/dist/marks/ColorLegend.svelte +54 -0
  51. package/dist/marks/ColorLegend.svelte.d.ts +14 -0
  52. package/dist/marks/Dot.svelte +82 -0
  53. package/dist/marks/Dot.svelte.d.ts +15 -0
  54. package/dist/marks/DotX.svelte +5 -0
  55. package/dist/marks/DotX.svelte.d.ts +17 -0
  56. package/dist/marks/DotY.svelte +5 -0
  57. package/dist/marks/DotY.svelte.d.ts +17 -0
  58. package/dist/marks/Frame.svelte +37 -0
  59. package/dist/marks/Frame.svelte.d.ts +15 -0
  60. package/dist/marks/GridX.svelte +42 -0
  61. package/dist/marks/GridX.svelte.d.ts +19 -0
  62. package/dist/marks/GridY.svelte +31 -0
  63. package/dist/marks/GridY.svelte.d.ts +15 -0
  64. package/dist/marks/Line.svelte +59 -0
  65. package/dist/marks/Line.svelte.d.ts +15 -0
  66. package/dist/marks/LineX.svelte +10 -0
  67. package/dist/marks/LineX.svelte.d.ts +17 -0
  68. package/dist/marks/LineY.svelte +10 -0
  69. package/dist/marks/LineY.svelte.d.ts +17 -0
  70. package/dist/marks/RuleX.svelte +30 -0
  71. package/dist/marks/RuleX.svelte.d.ts +15 -0
  72. package/dist/marks/RuleY.svelte +30 -0
  73. package/dist/marks/RuleY.svelte.d.ts +15 -0
  74. package/dist/marks/SymbolLegend.svelte +50 -0
  75. package/dist/marks/SymbolLegend.svelte.d.ts +14 -0
  76. package/dist/types.d.ts +209 -0
  77. package/dist/types.js +1 -0
  78. package/package.json +5 -3
@@ -0,0 +1,172 @@
1
+ <script>import { setContext } from "svelte";
2
+ import { Frame, GridX, GridY, AxisX, AxisY, ColorLegend, SymbolLegend } from "./index.js";
3
+ import { DEFAULT_PLOT_OPTIONS, Plot } from "./classes/Plot.svelte";
4
+ import mergeDeep from "./helpers/mergeDeep.js";
5
+ let {
6
+ // snippets
7
+ header,
8
+ footer,
9
+ overlay,
10
+ children,
11
+ // props
12
+ height = "auto",
13
+ marginLeft = 30,
14
+ marginRight = 10,
15
+ marginTop = 20,
16
+ marginBottom = 40,
17
+ inset = null,
18
+ grid = false,
19
+ frame = false,
20
+ maxWidth = null,
21
+ title = "",
22
+ subtitle = "",
23
+ caption = "",
24
+ // scales
25
+ radius = null,
26
+ color = null,
27
+ symbol = null,
28
+ x = null,
29
+ y = null,
30
+ onmousemove = null
31
+ } = $props();
32
+ let width = $state(400);
33
+ const plot = new Plot(600, height || defaultPlotHeight, {
34
+ marginTop,
35
+ marginLeft,
36
+ marginRight,
37
+ marginBottom,
38
+ // scales
39
+ symbol,
40
+ radius,
41
+ x,
42
+ y,
43
+ color,
44
+ // other
45
+ title,
46
+ subtitle,
47
+ caption
48
+ });
49
+ setContext("svelteplot", plot);
50
+ $effect(() => {
51
+ plot.width = width;
52
+ plot._height = height;
53
+ plot.options = mergeDeep({}, DEFAULT_PLOT_OPTIONS, {
54
+ marginBottom,
55
+ marginLeft,
56
+ marginRight,
57
+ marginTop,
58
+ inset,
59
+ symbol,
60
+ radius,
61
+ color,
62
+ x,
63
+ y,
64
+ title,
65
+ subtitle,
66
+ caption
67
+ });
68
+ });
69
+ function onMouseMove(evt) {
70
+ if (onmousemove)
71
+ onmousemove({ ...evt, plot });
72
+ }
73
+ $inspect(plot.x.domain);
74
+ let hasLegend = $derived(color?.legend || symbol?.legend);
75
+ </script>
76
+
77
+ <figure class="svelteplot" bind:clientWidth={width} style:max-width={maxWidth}>
78
+ <svg
79
+ role="document"
80
+ {width}
81
+ height={plot.height}
82
+ onmousemove={onmousemove ? onMouseMove : null}
83
+ >
84
+ <!-- automatic grids -->
85
+ {#if grid || x?.grid}<GridX automatic />{/if}
86
+ {#if grid || y?.grid}<GridY automatic />{/if}
87
+
88
+ {#if !plot.hasAxisXMark && plot.hasChannelX}
89
+ <!-- automatic x axis -->
90
+ {#if plot.options.x.axis === 'bottom' || plot.options.x.axis === 'both'}
91
+ <AxisX anchor="bottom" automatic />
92
+ {/if}
93
+ {#if plot.options.x.axis === 'top' || plot.options.x.axis === 'both'}
94
+ <AxisX anchor="top" automatic />
95
+ {/if}
96
+ {/if}
97
+ {#if !plot.hasAxisYMark && plot.hasChannelY}
98
+ <!-- automatic y axis -->
99
+ {#if plot.options.y.axis === 'left' || plot.options.y.axis === 'both'}
100
+ <AxisY anchor="left" automatic />
101
+ {/if}
102
+ {#if plot.options.y.axis === 'right' || plot.options.y.axis === 'both'}
103
+ <AxisY anchor="right" automatic />
104
+ {/if}
105
+ {/if}
106
+ <!-- automatic frame -->
107
+ {#if frame}<Frame />{/if}
108
+ {#if children}{@render children(plot)}{/if}
109
+ </svg>
110
+
111
+ {#if plot.options.title || plot.options.subtitle || header || hasLegend}
112
+ <div class="plot-header">
113
+ {#if plot.options.title}
114
+ <h2>{@html plot.options.title}</h2>
115
+ {/if}
116
+ {#if plot.options.subtitle}
117
+ <h3>{@html plot.options.subtitle}</h3>
118
+ {/if}
119
+ {#if color?.legend}
120
+ <ColorLegend />
121
+ {/if}
122
+ {#if symbol?.legend}
123
+ <SymbolLegend />
124
+ {/if}
125
+ {#if header}{@render header(plot)}{/if}
126
+ </div>
127
+ {/if}
128
+
129
+ {#if footer || plot.options.caption}
130
+ <div class="plot-footer">
131
+ {#if plot.options.caption}
132
+ <figcaption>{@html plot.options.caption}</figcaption>
133
+ {/if}
134
+ {#if footer}{@render footer(plot)}{/if}
135
+ </div>
136
+ {/if}
137
+
138
+ <div class="overlay">
139
+ {#if overlay}{@render overlay(plot)}{/if}
140
+ </div>
141
+ </figure>
142
+
143
+ <style>
144
+ figure {
145
+ margin: 1em 0;
146
+ position: relative;
147
+ display: flex;
148
+ flex-direction: column;
149
+ }
150
+ figure .plot-header {
151
+ order: 1;
152
+ }
153
+ h2,
154
+ h3 {
155
+ margin: 0;
156
+ }
157
+ svg {
158
+ order: 2;
159
+ overflow: visible;
160
+ }
161
+ figure .plot-footer {
162
+ order: 3;
163
+ }
164
+ .overlay {
165
+ position: absolute;
166
+ pointer-events: none;
167
+ top: 0;
168
+ left: 0;
169
+ bottom: 0;
170
+ right: 0;
171
+ }
172
+ </style>
@@ -0,0 +1,15 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { PlotProps } from './types.js';
3
+ declare const __propDef: {
4
+ props: PlotProps;
5
+ events: {
6
+ [evt: string]: CustomEvent<any>;
7
+ };
8
+ slots: {};
9
+ };
10
+ type PlotProps_ = typeof __propDef.props;
11
+ export { PlotProps_ as PlotProps };
12
+ export type PlotEvents = typeof __propDef.events;
13
+ export type PlotSlots = typeof __propDef.slots;
14
+ export default class Plot extends SvelteComponent<PlotProps, PlotEvents, PlotSlots> {
15
+ }
@@ -0,0 +1,74 @@
1
+ import resolveChannel from '../helpers/resolveChannel.js';
2
+ import { extent } from 'd3-array';
3
+ import { MARK_PROP_CHANNEL } from '../contants.js';
4
+ import { isBooleanOrNull, isColorOrNull, isDateOrNull, isNumberOrNull, isStringOrNull } from '../helpers/typeChecks.js';
5
+ import { uniq } from 'underscore';
6
+ export class Channel {
7
+ name = undefined;
8
+ plot = undefined;
9
+ constructor(name, plot) {
10
+ this.name = name;
11
+ this.plot = plot;
12
+ }
13
+ // readonly type: ChannelType = CHANNEL_TYPES.position;
14
+ // all marks that have this channel
15
+ marks = $derived(this.plot?.marks ?? []);
16
+ forceDomain = $derived(this.plot && (this.name === 'x' || this.name === 'y')
17
+ ? this.plot.options[this.name]?.domain || null
18
+ : null);
19
+ possibleProps = $derived(Object.entries(MARK_PROP_CHANNEL)
20
+ .filter(([, channel]) => channel === this.name)
21
+ .map(([prop]) => prop));
22
+ activeMarks = $derived(this.marks.filter((mark) => mark.channels.has(this.name) && this.possibleProps.find((prop) => mark.props[prop])));
23
+ manualActiveMarks = $derived(this.activeMarks.filter((mark) => !mark.automatic));
24
+ autoTitle = $derived(this.manualActiveMarks.length === 1 &&
25
+ typeof this.manualActiveMarks[0].props?.[this.name] === 'string'
26
+ ? this.manualActiveMarks[0].props?.[this.name]
27
+ : null);
28
+ uniqueMarkProps = $derived(uniq(this.manualActiveMarks
29
+ .map((mark) => this.possibleProps
30
+ .filter((prop) => mark.props[prop])
31
+ .map((prop) => mark.props[prop]))
32
+ .flat(2)));
33
+ dataValues = $derived([
34
+ ...this.activeMarks
35
+ // only check marks with data
36
+ .filter((mark) => mark.props.data.length)
37
+ .map((mark) => this.possibleProps.map((prop) => mark.props.data.map((row) => resolveChannel(this.name, row, mark.props[prop]))))
38
+ .flat(3)
39
+ .filter((d) => d != null),
40
+ ...(this.forceDomain || [])
41
+ ]);
42
+ valueType = $derived(this.dataValues.every((v) => v == null)
43
+ ? 'null'
44
+ : this.dataValues.every(isColorOrNull)
45
+ ? 'color'
46
+ : this.dataValues.every(isBooleanOrNull)
47
+ ? 'boolean'
48
+ : this.dataValues.every(isStringOrNull)
49
+ ? 'text'
50
+ : this.dataValues.every(isNumberOrNull)
51
+ ? 'number'
52
+ : this.dataValues.every(isDateOrNull)
53
+ ? 'date'
54
+ : 'mixed');
55
+ domain = $derived(!this.dataValues.length
56
+ ? [0, 1]
57
+ : this.valueType === 'boolean' ||
58
+ this.valueType === 'text' ||
59
+ this.valueType === 'color'
60
+ ? uniq(this.dataValues)
61
+ : extent(this.dataValues));
62
+ scaleType = $derived(this.name === 'radius'
63
+ ? 'sqrt'
64
+ : this.valueType === 'date'
65
+ ? 'time'
66
+ : this.valueType === 'number'
67
+ ? 'linear'
68
+ : this.valueType === 'text'
69
+ ? 'band'
70
+ : this.valueType === 'color'
71
+ ? 'identity'
72
+ : 'linear');
73
+ }
74
+ // opacity: typeof === 'number' && between [0,1]
@@ -0,0 +1,17 @@
1
+ export class Mark {
2
+ id;
3
+ type;
4
+ automatic;
5
+ channels = $state(new Set());
6
+ props = $state();
7
+ constructor(type, channels, automatic, props) {
8
+ this.id = Symbol();
9
+ this.type = type;
10
+ this.automatic = automatic;
11
+ this.channels = new Set(channels);
12
+ this.props = props;
13
+ }
14
+ toString() {
15
+ return `Mark[${this.type}]`;
16
+ }
17
+ }
@@ -0,0 +1,98 @@
1
+ import { createScale, createColorScale } from '../helpers/createScale.js';
2
+ import mergeDeep from '../helpers/mergeDeep.js';
3
+ import { Channel } from './Channel.svelte';
4
+ import { get } from 'underscore';
5
+ export const DEFAULT_PLOT_OPTIONS = {
6
+ title: '',
7
+ subtitle: '',
8
+ caption: '',
9
+ marginLeft: 0,
10
+ marginRight: 0,
11
+ marginTop: 30,
12
+ marginBottom: 0,
13
+ radius: { range: [1, 10] },
14
+ symbol: {},
15
+ color: {},
16
+ x: {
17
+ domain: undefined,
18
+ grid: false,
19
+ ticks: undefined,
20
+ tickSpacing: 80,
21
+ axis: 'bottom',
22
+ log: false,
23
+ reverse: false
24
+ },
25
+ y: {
26
+ domain: undefined,
27
+ grid: false,
28
+ ticks: undefined,
29
+ tickSpacing: 60,
30
+ axis: 'left',
31
+ log: false,
32
+ reverse: false
33
+ }
34
+ };
35
+ export class Plot {
36
+ width = $state(600);
37
+ _height = $state(400);
38
+ options = $state(DEFAULT_PLOT_OPTIONS);
39
+ marks = $state([]);
40
+ hasChannelX = $derived(!!this.marks.find((mark) => mark.channels.has('x')));
41
+ hasChannelY = $derived(!!this.marks.find((mark) => mark.channels.has('y')));
42
+ hasFilledDotMarks = $derived(!!this.marks.find((d) => d.type === 'dot' && d.props?.fill));
43
+ manualMarks = $derived(this.marks.filter((mark) => !mark.automatic));
44
+ singlePosChannelMark = $derived(this.manualMarks.length === 1 &&
45
+ (!this.manualMarks[0].channels.has('x') || !this.manualMarks[0].channels.has('y')));
46
+ height = $derived(this._height === 'auto' ? (this.hasChannelY ? 400 : 90) : this._height);
47
+ inset = $derived(typeof this.options.inset === 'number'
48
+ ? this.options.inset
49
+ : this.singlePosChannelMark
50
+ ? 10
51
+ : 0);
52
+ // derived props
53
+ margins = $derived({
54
+ top: this.options.marginTop,
55
+ left: this.options.marginLeft,
56
+ bottom: this.options.marginBottom,
57
+ right: this.options.marginRight
58
+ });
59
+ // margins = $state<Margins>({ left: 0, right: 0, top: 0, bottom: 0 });
60
+ plotWidth = $derived(this.width - this.margins.left - this.margins.right);
61
+ plotHeight = $derived(this.height - this.margins.top - this.margins.bottom);
62
+ x = new Channel('x', this);
63
+ y = new Channel('y', this);
64
+ radius = new Channel('radius', this);
65
+ color = new Channel('color', this);
66
+ symbol = new Channel('symbol', this);
67
+ colorSymbolRedundant = $derived(this.color.uniqueMarkProps.length === 1 &&
68
+ this.symbol.uniqueMarkProps.length === 1 &&
69
+ this.color.uniqueMarkProps[0] === this.symbol.uniqueMarkProps[0]);
70
+ xScale = $derived(createScale(this.x.scaleType === 'linear' && this.options.x.log ? 'log' : this.x.scaleType, this.options?.x?.domain || this.x.domain, this.options?.x?.reverse
71
+ ? [this.margins.left + this.plotWidth - this.inset, this.margins.left + this.inset]
72
+ : [this.margins.left + this.inset, this.margins.left + this.plotWidth - this.inset], this.x.scaleType === 'linear' && this.options.x.log ? { base: 10 } : {}));
73
+ yScale = $derived(createScale(this.y.scaleType === 'linear' && this.options.y.log ? 'log' : this.y.scaleType, this.options.y?.domain || this.y.domain, this.options.y?.reverse
74
+ ? [this.margins.top + this.inset, this.height - this.margins.bottom - this.inset]
75
+ : [this.height - this.margins.bottom - this.inset, this.margins.top + this.inset], this.y.scaleType === 'linear' && this.options.y.log ? { base: '10' } : {}));
76
+ radiusScale = $derived(createScale(this.radius.scaleType, [0, Math.max(this.radius.domain[0], this.radius.domain[1])], this.options.radius.range));
77
+ symbolScale = $derived(createScale('ordinal', this.symbol.domain, this.options.symbol?.range || this.hasFilledDotMarks
78
+ ? ['circle', 'cross', 'diamond', 'square', 'star', 'triangle', 'wye']
79
+ : ['circle', 'plus', 'times', 'triangle2', 'asterisk', 'square2', 'diamond2']));
80
+ colorScale = $derived(createColorScale(this.color.scaleType, this.color.domain, this.options.color?.range || null, this.options.color?.scheme));
81
+ hasAxisXMark = $derived(!!this.marks.find((mark) => mark.type === 'axis-x' && !mark.automatic));
82
+ hasAxisYMark = $derived(!!this.marks.find((mark) => mark.type === 'axis-y' && !mark.automatic));
83
+ constructor(width, height, options) {
84
+ const opts = mergeDeep({}, DEFAULT_PLOT_OPTIONS, options);
85
+ this.width = width;
86
+ this._height = height;
87
+ this.options = opts;
88
+ }
89
+ addMark(mark) {
90
+ // console.log('addMark: ' + mark);
91
+ this.marks = [...this.marks, mark];
92
+ // add mark to respective channels
93
+ // console.log(this.x.domain);
94
+ }
95
+ removeMark(removeMark) {
96
+ this.marks = this.marks.filter((mark) => mark.id !== removeMark.id);
97
+ }
98
+ }
@@ -0,0 +1,3 @@
1
+ import type { ChannelName, MarkProps, MarkStyleProps } from './types';
2
+ export declare const CHANNEL_TYPES: Record<ChannelName, symbol>;
3
+ export declare const MARK_PROP_CHANNEL: Record<MarkProps & MarkStyleProps, ChannelName>;
@@ -0,0 +1,40 @@
1
+ export const CHANNEL_TYPES = {
2
+ opacity: Symbol('opacity'),
3
+ color: Symbol('color'),
4
+ x: Symbol('position'),
5
+ y: Symbol('position'),
6
+ angle: Symbol('angle'),
7
+ symbol: Symbol('symbol'),
8
+ radius: Symbol('radius'),
9
+ width: Symbol('width')
10
+ };
11
+ export const MARK_PROP_CHANNEL = {
12
+ x: 'x',
13
+ x1: 'x',
14
+ x2: 'x',
15
+ y: 'y',
16
+ y1: 'y',
17
+ y2: 'y',
18
+ rotate: 'angle',
19
+ r: 'radius',
20
+ symbol: 'symbol',
21
+ fill: 'color',
22
+ stroke: 'color',
23
+ opacity: 'opacity',
24
+ fillOpacity: 'opacity',
25
+ strokeOpacity: 'opacity',
26
+ strokeWidth: 'width'
27
+ };
28
+ // export const CHANNEL_MAP: Record<ChannelName, ValueOf<typeof CHANNEL_TYPES>> = {
29
+ // x: CHANNEL_TYPES.x,
30
+ // y: CHANNEL_TYPES.y,
31
+ // opacity: CHANNEL_TYPES.opacity,
32
+ // strokeOpacity: CHANNEL_TYPES.opacity,
33
+ // strokeWidth: CHANNEL_TYPES.width,
34
+ // fillOpacity: CHANNEL_TYPES.opacity,
35
+ // stroke: CHANNEL_TYPES.color,
36
+ // fill: CHANNEL_TYPES.color,
37
+ // r: CHANNEL_TYPES.radius,
38
+ // rotate: CHANNEL_TYPES.angle,
39
+ // symbol: CHANNEL_TYPES.symbol
40
+ // };
@@ -0,0 +1,8 @@
1
+ <script>let { data = [], ...rest } = $props();
2
+ </script>
3
+
4
+ {#if data.length !== 1}
5
+ <g {...rest}><slot /></g>
6
+ {:else}
7
+ <slot />
8
+ {/if}
@@ -0,0 +1,19 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { DataRow } from '../types.js';
3
+ declare const __propDef: {
4
+ props: {
5
+ data: DataRow[];
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {
11
+ default: {};
12
+ };
13
+ };
14
+ export type GroupMultipleProps = typeof __propDef.props;
15
+ export type GroupMultipleEvents = typeof __propDef.events;
16
+ export type GroupMultipleSlots = typeof __propDef.slots;
17
+ export default class GroupMultiple extends SvelteComponent<GroupMultipleProps, GroupMultipleEvents, GroupMultipleSlots> {
18
+ }
19
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { Channel } from '../classes/Channel.svelte';
2
+ export default function autoTimeFormat(x: Channel, plotWidth: number): (date: Date) => string[];
@@ -0,0 +1,10 @@
1
+ import dayjs from 'dayjs';
2
+ import { isDate } from 'underscore';
3
+ export default function autoTimeFormat(x, plotWidth) {
4
+ const daysPer100Px = ((toNumber(x.domain[1]) - toNumber(x.domain[0])) / plotWidth / 864e5) * 100;
5
+ const format = daysPer100Px < 1 ? 'HH:mm\nMMM DD' : daysPer100Px < 30 ? 'DD\nMMM' : 'MMM\nYYYY';
6
+ return (date) => dayjs(date).format(format).split('\n');
7
+ }
8
+ function toNumber(d) {
9
+ return isDate(d) ? d.getTime() : +d;
10
+ }
@@ -0,0 +1,4 @@
1
+ import type { RawValue } from '../types.js';
2
+ type Setter = (v: any) => void;
3
+ export default function (d3func: () => Record<string, Setter>, args: RawValue[], props?: Record<string, RawValue>): Record<string, Setter>;
4
+ export {};
@@ -0,0 +1,9 @@
1
+ export default function (d3func, args, props = {}) {
2
+ const res = d3func(...args);
3
+ for (const [key, val] of Object.entries(props)) {
4
+ if (typeof res[key] !== 'function')
5
+ throw new Error(`function ${key} does not exist`);
6
+ res[key](val);
7
+ }
8
+ return res;
9
+ }
@@ -0,0 +1,13 @@
1
+ import { interpolateBrBG } from 'd3-scale-chromatic';
2
+ import type { ColorScheme } from '../types.js';
3
+ export declare const categoricalSchemes: Map<string, readonly string[]>;
4
+ export declare function isCategoricalScheme(scheme: string): boolean;
5
+ type SchemeGetter = (n: number) => readonly string[];
6
+ export declare function isOrdinalScheme(scheme: ColorScheme): boolean;
7
+ export declare function ordinalScheme(scheme: string): SchemeGetter | undefined;
8
+ export declare function ordinalRange(scheme: string, length: number): readonly string[] | undefined;
9
+ export declare function maybeBooleanRange(domain: boolean[], scheme?: string): unknown[] | undefined;
10
+ export declare function isQuantitativeScheme(scheme: string): boolean;
11
+ export declare function quantitativeScheme(scheme: string): typeof interpolateBrBG | undefined;
12
+ export declare function isDivergingScheme(scheme: string): boolean;
13
+ export {};