svelteplot 0.10.3 → 0.11.0

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 (222) hide show
  1. package/dist/Mark.svelte +42 -25
  2. package/dist/Mark.svelte.d.ts +111 -32
  3. package/dist/Plot.svelte +21 -15
  4. package/dist/core/Facet.svelte +1 -1
  5. package/dist/core/FacetAxes.svelte +13 -8
  6. package/dist/core/FacetGrid.svelte +4 -4
  7. package/dist/core/Plot.svelte +41 -35
  8. package/dist/helpers/autoScales.d.ts +3 -3
  9. package/dist/helpers/autoScales.js +28 -18
  10. package/dist/helpers/autoTicks.js +2 -0
  11. package/dist/helpers/callWithProps.d.ts +1 -2
  12. package/dist/helpers/facets.js +0 -1
  13. package/dist/helpers/index.js +1 -1
  14. package/dist/helpers/mergeDeep.d.ts +1 -3
  15. package/dist/helpers/mergeDeep.js +15 -16
  16. package/dist/helpers/projection.d.ts +4 -3
  17. package/dist/helpers/projection.js +17 -5
  18. package/dist/helpers/reduce.d.ts +4 -4
  19. package/dist/helpers/reduce.js +6 -4
  20. package/dist/helpers/regressionLoess.js +2 -1
  21. package/dist/helpers/resolve.d.ts +6 -3
  22. package/dist/helpers/resolve.js +25 -16
  23. package/dist/helpers/scales.d.ts +10 -10
  24. package/dist/helpers/scales.js +43 -13
  25. package/dist/helpers/time.d.ts +10 -3
  26. package/dist/helpers/time.js +2 -1
  27. package/dist/hooks/index.d.ts +2 -0
  28. package/dist/hooks/index.js +2 -0
  29. package/dist/hooks/plotDefaults.d.ts +3 -1
  30. package/dist/hooks/plotDefaults.js +33 -1
  31. package/dist/hooks/usePlot.svelte.d.ts +10 -25
  32. package/dist/hooks/usePlot.svelte.js +8 -7
  33. package/dist/index.d.ts +1 -2
  34. package/dist/index.js +1 -3
  35. package/dist/marks/Area.svelte +24 -13
  36. package/dist/marks/Area.svelte.d.ts +118 -34
  37. package/dist/marks/AreaX.svelte +42 -8
  38. package/dist/marks/AreaX.svelte.d.ts +154 -71
  39. package/dist/marks/AreaY.svelte +42 -8
  40. package/dist/marks/AreaY.svelte.d.ts +154 -71
  41. package/dist/marks/Arrow.svelte +42 -23
  42. package/dist/marks/Arrow.svelte.d.ts +114 -35
  43. package/dist/marks/AxisX.svelte +43 -28
  44. package/dist/marks/AxisX.svelte.d.ts +125 -40
  45. package/dist/marks/AxisY.svelte +43 -26
  46. package/dist/marks/AxisY.svelte.d.ts +127 -40
  47. package/dist/marks/BarX.svelte +12 -10
  48. package/dist/marks/BarX.svelte.d.ts +104 -32
  49. package/dist/marks/BarY.svelte +11 -10
  50. package/dist/marks/BarY.svelte.d.ts +106 -34
  51. package/dist/marks/BollingerX.svelte +4 -7
  52. package/dist/marks/BollingerX.svelte.d.ts +105 -30
  53. package/dist/marks/BollingerY.svelte +3 -0
  54. package/dist/marks/BollingerY.svelte.d.ts +105 -30
  55. package/dist/marks/BoxX.svelte +3 -3
  56. package/dist/marks/BoxY.svelte +12 -9
  57. package/dist/marks/BoxY.svelte.d.ts +128 -53
  58. package/dist/marks/Brush.svelte +26 -21
  59. package/dist/marks/Brush.svelte.d.ts +119 -60
  60. package/dist/marks/Cell.svelte +13 -9
  61. package/dist/marks/Cell.svelte.d.ts +105 -30
  62. package/dist/marks/CellX.svelte +2 -1
  63. package/dist/marks/CellX.svelte.d.ts +105 -32
  64. package/dist/marks/CellY.svelte +2 -1
  65. package/dist/marks/CellY.svelte.d.ts +105 -32
  66. package/dist/marks/ColorLegend.svelte +24 -13
  67. package/dist/marks/ColorLegend.svelte.d.ts +1 -0
  68. package/dist/marks/CustomMark.svelte +16 -10
  69. package/dist/marks/CustomMark.svelte.d.ts +112 -31
  70. package/dist/marks/CustomMarkHTML.svelte +8 -2
  71. package/dist/marks/CustomMarkHTML.svelte.d.ts +8 -2
  72. package/dist/marks/DifferenceY.svelte +31 -20
  73. package/dist/marks/DifferenceY.svelte.d.ts +134 -55
  74. package/dist/marks/Dot.svelte +21 -11
  75. package/dist/marks/Dot.svelte.d.ts +117 -38
  76. package/dist/marks/DotX.svelte +2 -0
  77. package/dist/marks/DotX.svelte.d.ts +136 -62
  78. package/dist/marks/DotY.svelte +1 -0
  79. package/dist/marks/DotY.svelte.d.ts +135 -62
  80. package/dist/marks/Frame.svelte +47 -9
  81. package/dist/marks/Frame.svelte.d.ts +124 -41
  82. package/dist/marks/Geo.svelte +21 -12
  83. package/dist/marks/Geo.svelte.d.ts +105 -30
  84. package/dist/marks/Graticule.svelte +3 -0
  85. package/dist/marks/Graticule.svelte.d.ts +3 -0
  86. package/dist/marks/GridX.svelte +31 -16
  87. package/dist/marks/GridX.svelte.d.ts +108 -32
  88. package/dist/marks/GridY.svelte +30 -15
  89. package/dist/marks/GridY.svelte.d.ts +108 -32
  90. package/dist/marks/HTMLTooltip.svelte +14 -7
  91. package/dist/marks/HTMLTooltip.svelte.d.ts +7 -0
  92. package/dist/marks/Image.svelte +50 -25
  93. package/dist/marks/Image.svelte.d.ts +117 -35
  94. package/dist/marks/Line.svelte +67 -44
  95. package/dist/marks/Line.svelte.d.ts +119 -30
  96. package/dist/marks/LineX.svelte +2 -1
  97. package/dist/marks/LineX.svelte.d.ts +142 -69
  98. package/dist/marks/LineY.svelte +2 -1
  99. package/dist/marks/LineY.svelte.d.ts +142 -69
  100. package/dist/marks/Link.svelte +70 -46
  101. package/dist/marks/Link.svelte.d.ts +126 -41
  102. package/dist/marks/Pointer.svelte +24 -15
  103. package/dist/marks/Pointer.svelte.d.ts +7 -0
  104. package/dist/marks/Rect.svelte +13 -5
  105. package/dist/marks/Rect.svelte.d.ts +116 -35
  106. package/dist/marks/RectX.svelte +6 -3
  107. package/dist/marks/RectX.svelte.d.ts +158 -12
  108. package/dist/marks/RectY.svelte +6 -3
  109. package/dist/marks/RectY.svelte.d.ts +158 -12
  110. package/dist/marks/RegressionX.svelte +13 -6
  111. package/dist/marks/RegressionX.svelte.d.ts +8 -3
  112. package/dist/marks/RegressionY.svelte +13 -6
  113. package/dist/marks/RegressionY.svelte.d.ts +8 -3
  114. package/dist/marks/RuleX.svelte +18 -11
  115. package/dist/marks/RuleX.svelte.d.ts +112 -32
  116. package/dist/marks/RuleY.svelte +19 -12
  117. package/dist/marks/RuleY.svelte.d.ts +114 -34
  118. package/dist/marks/Spike.svelte +11 -5
  119. package/dist/marks/Spike.svelte.d.ts +146 -68
  120. package/dist/marks/Text.svelte +24 -7
  121. package/dist/marks/Text.svelte.d.ts +253 -75
  122. package/dist/marks/TickX.svelte +56 -48
  123. package/dist/marks/TickX.svelte.d.ts +114 -40
  124. package/dist/marks/TickY.svelte +59 -51
  125. package/dist/marks/TickY.svelte.d.ts +117 -43
  126. package/dist/marks/Trail.svelte +25 -13
  127. package/dist/marks/Trail.svelte.d.ts +116 -33
  128. package/dist/marks/Vector.svelte +20 -11
  129. package/dist/marks/Vector.svelte.d.ts +116 -35
  130. package/dist/marks/WaffleX.svelte +18 -16
  131. package/dist/marks/WaffleX.svelte.d.ts +131 -57
  132. package/dist/marks/WaffleY.svelte +16 -15
  133. package/dist/marks/WaffleY.svelte.d.ts +129 -56
  134. package/dist/marks/helpers/Anchor.svelte +17 -2
  135. package/dist/marks/helpers/Anchor.svelte.d.ts +16 -1
  136. package/dist/marks/helpers/AreaCanvas.svelte +8 -8
  137. package/dist/marks/helpers/BaseAxisX.svelte +38 -41
  138. package/dist/marks/helpers/BaseAxisX.svelte.d.ts +11 -17
  139. package/dist/marks/helpers/BaseAxisY.svelte +35 -35
  140. package/dist/marks/helpers/BaseAxisY.svelte.d.ts +12 -15
  141. package/dist/marks/helpers/Box.svelte +35 -28
  142. package/dist/marks/helpers/Box.svelte.d.ts +122 -50
  143. package/dist/marks/helpers/DotCanvas.svelte +11 -9
  144. package/dist/marks/helpers/GeoCanvas.svelte +7 -6
  145. package/dist/marks/helpers/LineCanvas.svelte +7 -7
  146. package/dist/marks/helpers/LinearGradientX.svelte +2 -2
  147. package/dist/marks/helpers/LinearGradientX.svelte.d.ts +1 -1
  148. package/dist/marks/helpers/LinearGradientY.svelte +2 -2
  149. package/dist/marks/helpers/LinearGradientY.svelte.d.ts +1 -1
  150. package/dist/marks/helpers/Marker.svelte +2 -2
  151. package/dist/marks/helpers/MarkerPath.svelte +15 -12
  152. package/dist/marks/helpers/MarkerPath.svelte.d.ts +105 -32
  153. package/dist/marks/helpers/MultilineText.svelte +24 -17
  154. package/dist/marks/helpers/MultilineText.svelte.d.ts +1 -1
  155. package/dist/marks/helpers/RectCanvas.svelte +31 -26
  156. package/dist/marks/helpers/RectPath.svelte +2 -2
  157. package/dist/marks/helpers/Regression.svelte +176 -86
  158. package/dist/marks/helpers/Regression.svelte.d.ts +20 -8
  159. package/dist/marks/helpers/RuleCanvas.svelte +9 -6
  160. package/dist/marks/helpers/TextCanvas.svelte +13 -9
  161. package/dist/marks/helpers/TextCanvas.svelte.d.ts +6 -6
  162. package/dist/marks/helpers/TickCanvas.svelte +6 -5
  163. package/dist/marks/helpers/TrailCanvas.svelte +16 -18
  164. package/dist/marks/helpers/TrailCanvas.svelte.d.ts +3 -5
  165. package/dist/marks/helpers/canvas.js +16 -9
  166. package/dist/marks/helpers/events.d.ts +2 -2
  167. package/dist/marks/helpers/events.js +14 -7
  168. package/dist/marks/helpers/waffle.d.ts +3 -3
  169. package/dist/marks/helpers/waffle.js +6 -4
  170. package/dist/regression/polynomial.d.ts +1 -1
  171. package/dist/regression/polynomial.js +5 -5
  172. package/dist/regression/utils/determination.d.ts +1 -1
  173. package/dist/regression/utils/determination.js +1 -1
  174. package/dist/regression/utils/geometry.d.ts +1 -1
  175. package/dist/regression/utils/interpose.d.ts +1 -1
  176. package/dist/regression/utils/interpose.js +1 -1
  177. package/dist/regression/utils/points.d.ts +1 -1
  178. package/dist/transforms/bin.d.ts +3 -3
  179. package/dist/transforms/bin.js +29 -20
  180. package/dist/transforms/bollinger.d.ts +8 -0
  181. package/dist/transforms/bollinger.js +9 -1
  182. package/dist/transforms/centroid.d.ts +4 -0
  183. package/dist/transforms/centroid.js +4 -0
  184. package/dist/transforms/density.d.ts +4 -4
  185. package/dist/transforms/density.js +20 -13
  186. package/dist/transforms/dodge.d.ts +12 -1
  187. package/dist/transforms/dodge.js +15 -6
  188. package/dist/transforms/group.d.ts +141 -4
  189. package/dist/transforms/group.js +4 -1
  190. package/dist/transforms/interval.d.ts +204 -60
  191. package/dist/transforms/jitter.d.ts +421 -4
  192. package/dist/transforms/jitter.js +10 -1
  193. package/dist/transforms/map.d.ts +412 -4
  194. package/dist/transforms/map.js +3 -3
  195. package/dist/transforms/normalize.d.ts +276 -5
  196. package/dist/transforms/normalize.js +5 -3
  197. package/dist/transforms/recordize.d.ts +17 -5
  198. package/dist/transforms/recordize.js +13 -9
  199. package/dist/transforms/rename.d.ts +11 -4
  200. package/dist/transforms/rename.js +7 -2
  201. package/dist/transforms/select.d.ts +722 -210
  202. package/dist/transforms/select.js +13 -1
  203. package/dist/transforms/shift.d.ts +8 -0
  204. package/dist/transforms/shift.js +20 -6
  205. package/dist/transforms/sort.d.ts +13 -258
  206. package/dist/transforms/sort.js +13 -10
  207. package/dist/transforms/stack.d.ts +58 -9
  208. package/dist/transforms/stack.js +27 -11
  209. package/dist/transforms/window.d.ts +221 -66
  210. package/dist/transforms/window.js +8 -2
  211. package/dist/types/axes.d.ts +43 -0
  212. package/dist/types/axes.js +1 -0
  213. package/dist/types/channel.d.ts +30 -2
  214. package/dist/types/data.d.ts +14 -1
  215. package/dist/types/facet.d.ts +5 -0
  216. package/dist/types/index.d.ts +33 -8
  217. package/dist/types/index.js +11 -7
  218. package/dist/types/mark.d.ts +124 -35
  219. package/dist/types/plot.d.ts +118 -16
  220. package/dist/types/scale.d.ts +125 -8
  221. package/package.json +178 -175
  222. package/dist/helpers/autoTicks.d.ts +0 -12
@@ -8,19 +8,21 @@ export function resolveProp(accessor, datum, _defaultValue = null) {
8
8
  if (typeof accessor === 'function') {
9
9
  const accessorFn = accessor;
10
10
  // datum[RAW_VALUE] exists if an array of raw values was used as dataset and got
11
- // "recordized" by the recordi e transform. We want to hide this wrapping to the user
11
+ // "recordized" by the recordize transform. We want to hide this wrapping to the user
12
12
  // so we're passing the original value to accessor functions instead of our wrapped record
13
+ const d = datum;
13
14
  return datum == null
14
15
  ? accessorFn()
15
- : accessorFn(datum.hasOwnProperty(RAW_VALUE) ? datum[RAW_VALUE] : datum, datum[INDEX]);
16
+ : accessorFn(d[RAW_VALUE] != null ? d[RAW_VALUE] : datum, d[INDEX]);
16
17
  }
17
18
  else {
18
19
  const accessorValue = accessor;
19
- // accessor may be a
20
- if ((typeof accessorValue === 'string' || typeof accessorValue === 'symbol') &&
21
- datum &&
22
- datum[accessorValue] !== undefined) {
23
- return datum[accessor];
20
+ // accessor may be a column name
21
+ if ((typeof accessorValue === 'string' || typeof accessorValue === 'symbol') && datum) {
22
+ const d = datum;
23
+ if (d[accessorValue] !== undefined) {
24
+ return d[accessorValue];
25
+ }
24
26
  }
25
27
  }
26
28
  return isRawValue(accessor) ? accessor : _defaultValue;
@@ -51,19 +53,20 @@ export function resolveChannel(channel, datum, channels) {
51
53
  }
52
54
  function resolve(datum, accessor, channel, scale) {
53
55
  if (isDataRecord(datum)) {
56
+ const d = datum;
54
57
  // use accessor function
55
58
  if (typeof accessor === 'function')
56
59
  // datum[RAW_VALUE] exists if an array of raw values was used as dataset and got
57
60
  // "recordized" by the recordize transform. We want to hide this wrapping to the user
58
61
  // so we're passing the original value to accessor functions instead of our wrapped record
59
- return accessor(datum[RAW_VALUE] != null ? datum[RAW_VALUE] : datum, datum?.[INDEX]);
62
+ return accessor(d[RAW_VALUE] != null ? d[RAW_VALUE] : datum, d[INDEX]);
60
63
  // use accessor string
61
64
  if ((typeof accessor === 'string' || typeof accessor === 'symbol') &&
62
- datum[accessor] !== undefined)
63
- return datum[accessor];
65
+ d[accessor] !== undefined)
66
+ return d[accessor];
64
67
  // fallback to channel name as accessor
65
- if (accessor === null && datum[channel] !== undefined)
66
- return datum[channel];
68
+ if (accessor === null && d[channel] !== undefined)
69
+ return d[channel];
67
70
  return isRawValue(accessor) ? accessor : null;
68
71
  }
69
72
  else if (Array.isArray(datum) &&
@@ -73,8 +76,9 @@ function resolve(datum, accessor, channel, scale) {
73
76
  }
74
77
  else {
75
78
  // return single value or accessor
79
+ const d = datum;
76
80
  return typeof accessor === 'function'
77
- ? accessor(datum, datum?.[INDEX])
81
+ ? accessor(datum, d?.[INDEX])
78
82
  : accessor !== null && isRawValue(accessor)
79
83
  ? accessor
80
84
  : !Array.isArray(datum) && (scale === 'x' || scale === 'y')
@@ -89,7 +93,6 @@ const scaledStyleProps = {
89
93
  strokeOpacity: 'stroke-opacity',
90
94
  opacity: 'opacity'
91
95
  };
92
- const scaledStylePropsKeys = Object.keys(scaledStyleProps);
93
96
  // TODO: find a better name
94
97
  const oppositeColor = {
95
98
  fill: 'stroke',
@@ -105,7 +108,11 @@ export function resolveScaledStyleProps(datum, channels, useScale, plot, default
105
108
  : {}),
106
109
  ...Object.fromEntries(Object.entries(scaledStyleProps)
107
110
  .filter(([key]) => channels[key] != null)
108
- .map(([key, cssAttr]) => [key, cssAttr, resolveChannel(key, datum, channels)])
111
+ .map(([key, cssAttr]) => [
112
+ key,
113
+ cssAttr,
114
+ resolveChannel(key, datum, channels)
115
+ ])
109
116
  .filter(([key, , value]) => isValid(value) || key === 'fill' || key === 'stroke')
110
117
  .map(([key, cssAttr, value]) => {
111
118
  if (useScale[key]) {
@@ -143,7 +150,9 @@ export function resolveStyles(plot, datum, channels, defaultColorProp = null, us
143
150
  .map(([key, cssAttr]) => [
144
151
  key,
145
152
  cssAttr,
146
- recomputeChannels ? resolveChannel(key, datum?.datum, channels) : datum?.[key]
153
+ (recomputeChannels
154
+ ? resolveChannel(key, datum?.datum, channels)
155
+ : datum?.[key])
147
156
  ])
148
157
  .filter(([key, , value]) => isValid(value) || key === 'fill' || key === 'stroke')
149
158
  .map(([key, cssAttr, value]) => {
@@ -1,23 +1,23 @@
1
- import type { ChannelAccessor, GenericMarkOptions, Mark, MarkType, PlotDefaults, PlotOptions, PlotScales, PlotState, RawValue, ScaleName, ScaleOptions, ScaleType, ScaledChannelName, UsedScales } from '../types/index.js';
1
+ import type { ChannelAccessor, GenericMarkOptions, Mark, MarkType, PlotDefaults, PlotScaleFunction, ResolvedPlotOptions, PlotScales, PlotState, RawValue, ScaleName, ScaleOptions, ScaleType, ScaledChannelName, UsedScales } from '../types/index.js';
2
2
  /**
3
3
  * compute the plot scales
4
4
  */
5
- export declare function computeScales(plotOptions: PlotOptions, plotWidth: number, plotHeight: number, plotHasFilledDotMarks: boolean, marks: Mark<GenericMarkOptions>[], plotDefaults: PlotDefaults): PlotScales;
6
- export declare function createScale<T extends ScaleOptions>(name: ScaleName, scaleOptions: T, marks: Mark<GenericMarkOptions>[], plotOptions: PlotOptions, plotWidth: number, plotHeight: number, plotHasFilledDotMarks: boolean, plotDefaults: PlotDefaults): {
7
- type: string;
5
+ export declare function computeScales(plotOptions: ResolvedPlotOptions, plotWidth: number, plotHeight: number, plotHasFilledDotMarks: boolean, marks: Mark<GenericMarkOptions>[], plotDefaults: PlotDefaults): PlotScales;
6
+ export declare function createScale(name: ScaleName, scaleOptions: Partial<ScaleOptions>, marks: Mark<GenericMarkOptions>[], plotOptions: ResolvedPlotOptions, plotWidth: number, plotHeight: number, plotHasFilledDotMarks: boolean, plotDefaults: PlotDefaults): {
7
+ type: ScaleType;
8
8
  domain: number[];
9
9
  range: number[];
10
- fn: (() => string) | (() => number);
10
+ fn: PlotScaleFunction;
11
11
  skip: Map<any, any>;
12
12
  isDummy: boolean;
13
- manualActiveMarks?: undefined;
14
- uniqueScaleProps?: undefined;
13
+ manualActiveMarks: number;
14
+ uniqueScaleProps: Set<unknown>;
15
15
  autoTitle?: undefined;
16
16
  } | {
17
17
  type: ScaleType;
18
- domain: RawValue[] | [undefined, undefined];
19
- range: any;
20
- fn: any;
18
+ domain: RawValue[];
19
+ range: RawValue[];
20
+ fn: PlotScaleFunction;
21
21
  skip: Map<ScaledChannelName, Set<symbol>>;
22
22
  manualActiveMarks: number;
23
23
  uniqueScaleProps: Set<ChannelAccessor>;
@@ -7,6 +7,17 @@ import isDataRecord from './isDataRecord.js';
7
7
  import { createProjection } from './projection.js';
8
8
  import { maybeInterval } from './autoTicks.js';
9
9
  import { IS_SORTED } from '../transforms/sort.js';
10
+ function normalizeScaleFn(fn) {
11
+ const out = fn;
12
+ out.range ||= () => [];
13
+ out.invert ||= (value) => value;
14
+ out.bandwidth ||= () => 0;
15
+ out.ticks ||= () => [];
16
+ out.quantiles ||= () => [];
17
+ out.thresholds ||= () => [];
18
+ out.domain ||= () => [];
19
+ return out;
20
+ }
10
21
  /**
11
22
  * compute the plot scales
12
23
  */
@@ -38,7 +49,17 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
38
49
  // no scale defined, return a dummy scale
39
50
  const fn = name === 'color' ? () => 'currentColor' : () => 0;
40
51
  fn.range = name === 'color' ? () => ['currentColor'] : () => [0];
41
- return { type: 'linear', domain: [0], range: [0], fn, skip: new Map(), isDummy: true };
52
+ const normalizedFn = normalizeScaleFn(fn);
53
+ return {
54
+ type: 'linear',
55
+ domain: [0],
56
+ range: [0],
57
+ fn: normalizedFn,
58
+ skip: new Map(),
59
+ isDummy: true,
60
+ manualActiveMarks: 0,
61
+ uniqueScaleProps: new Set()
62
+ };
42
63
  }
43
64
  // gather all marks that use channels which support this scale
44
65
  const dataValues = new Set();
@@ -145,7 +166,7 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
145
166
  }
146
167
  // construct domain from data values
147
168
  const valueArr = [...dataValues.values(), ...(scaleOptions.domain || [])].filter((d) => d != null);
148
- const type = scaleOptions.type === 'auto'
169
+ const type = !scaleOptions.type || scaleOptions.type === 'auto'
149
170
  ? inferScaleType(name, valueArr, markTypes, scaleOptions)
150
171
  : scaleOptions.type;
151
172
  if (VALID_SCALE_TYPES[name] && !VALID_SCALE_TYPES[name].has(type)) {
@@ -181,10 +202,12 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
181
202
  }
182
203
  }
183
204
  }
184
- if (!scaleOptions.scale) {
205
+ // `scale` is a factory function injected by Plot.svelte (autoScale/autoScaleColor)
206
+ const scaleFn = scaleOptions.scale;
207
+ if (!scaleFn) {
185
208
  throw new Error(`No scale function defined for ${name}`);
186
209
  }
187
- const fn = scaleOptions.scale({
210
+ const rawFn = scaleFn({
188
211
  name,
189
212
  type,
190
213
  domain,
@@ -195,6 +218,7 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
195
218
  plotHasFilledDotMarks,
196
219
  plotDefaults
197
220
  });
221
+ const fn = normalizeScaleFn(rawFn);
198
222
  const range = fn.range();
199
223
  return {
200
224
  type,
@@ -241,14 +265,16 @@ export function inferScaleType(name, dataValues, markTypes, scaleOptions = {}) {
241
265
  return 'ordinal';
242
266
  if (name === 'x' || name === 'y') {
243
267
  // if for a positional scale we may infer the scale type from the scale options
244
- if (scaleOptions.nice || scaleOptions.zero)
245
- return 'linear';
246
268
  if (scaleOptions.domain && scaleOptions.domain.length === 2) {
247
269
  if (scaleOptions.domain.every(Number.isFinite))
248
270
  return 'linear';
249
271
  if (scaleOptions.domain.every(isDate))
250
272
  return 'time';
251
273
  }
274
+ if (scaleOptions.zero)
275
+ return 'linear';
276
+ if (scaleOptions.nice)
277
+ return dataValues.length > 0 && dataValues.every(isDateOrNull) ? 'time' : 'linear';
252
278
  }
253
279
  // for positional scales, try to pick a scale that's required by the mark types
254
280
  if (name === 'y' && Array.from(markTypes).some((d) => markTypesWithBandDefault.y.has(d)))
@@ -316,7 +342,7 @@ export function projectXY(scales, x, y, useXScale = true, useYScale = true) {
316
342
  // TODO: pretty sure this is not how projection streams are supposed to be used
317
343
  // efficiently, in observable plot, all data points of a mark are projected using
318
344
  // the same stream
319
- let x_, y_;
345
+ let x_ = 0, y_ = 0;
320
346
  const stream = scales.projection.stream({
321
347
  point(px, py) {
322
348
  x_ = px;
@@ -332,19 +358,23 @@ export function projectXY(scales, x, y, useXScale = true, useYScale = true) {
332
358
  ];
333
359
  }
334
360
  export function projectX(channel, scales, value) {
335
- return (scales.x.fn(value) +
361
+ const x = scales.x.fn(value) ?? NaN;
362
+ const xBandwidth = scales.x.type === 'band' ? scales.x.fn.bandwidth() : 0;
363
+ return (x +
336
364
  (channel === 'x' && scales.x.type === 'band'
337
- ? scales.x.fn.bandwidth() * 0.5
365
+ ? xBandwidth * 0.5
338
366
  : channel === 'x2' && scales.x.type === 'band'
339
- ? scales.x.fn.bandwidth()
367
+ ? xBandwidth
340
368
  : 0));
341
369
  }
342
370
  export function projectY(channel, scales, value) {
343
- return (scales.y.fn(value) +
371
+ const y = scales.y.fn(value) ?? NaN;
372
+ const yBandwidth = scales.y.type === 'band' ? scales.y.fn.bandwidth() : 0;
373
+ return (y +
344
374
  (channel === 'y' && scales.y.type === 'band'
345
- ? scales.y.fn.bandwidth() * 0.5
375
+ ? yBandwidth * 0.5
346
376
  : channel === 'y2' && scales.y.type === 'band'
347
- ? scales.y.fn.bandwidth()
377
+ ? yBandwidth
348
378
  : 0));
349
379
  }
350
380
  export function isOrdinalScale(scaleType) {
@@ -1,7 +1,14 @@
1
+ type CountableTimeInterval = {
2
+ floor: (date: Date) => Date;
3
+ offset: (date: Date, step?: number) => Date;
4
+ range: (start: Date, stop: Date, step?: number) => Date[];
5
+ every: (step: number) => CountableTimeInterval | null | undefined;
6
+ };
1
7
  export declare const durations: Map<string, number>;
2
8
  export declare const intervalDuration: unique symbol;
3
9
  export declare const intervalType: unique symbol;
4
10
  export declare function parseTimeInterval(input: string): [string, number];
5
- export declare function maybeTimeInterval(input: string): any;
6
- export declare function maybeUtcInterval(input: string): any;
7
- export declare function generalizeTimeInterval(interval: any, n: any): any;
11
+ export declare function maybeTimeInterval(input: string): CountableTimeInterval | undefined;
12
+ export declare function maybeUtcInterval(input: string): CountableTimeInterval | undefined;
13
+ export declare function generalizeTimeInterval(interval: CountableTimeInterval, n: number): CountableTimeInterval | undefined;
14
+ export {};
@@ -8,7 +8,6 @@
8
8
  */
9
9
  import { bisector } from 'd3-array';
10
10
  import { utcSecond, utcMinute, utcHour, unixDay, utcWeek, utcMonth, utcYear, utcMonday, utcTuesday, utcWednesday, utcThursday, utcFriday, utcSaturday, utcSunday, timeSecond, timeMinute, timeHour, timeDay, timeWeek, timeMonth, timeYear, timeMonday, timeTuesday, timeWednesday, timeThursday, timeFriday, timeSaturday, timeSunday } from 'd3-time';
11
- // import {orderof} from "./options.js";
12
11
  const durationSecond = 1000;
13
12
  const durationMinute = durationSecond * 60;
14
13
  const durationHour = durationMinute * 60;
@@ -187,6 +186,8 @@ export function maybeUtcInterval(input) {
187
186
  }
188
187
  function asInterval([name, period], type) {
189
188
  let interval = (type === 'time' ? timeIntervals : utcIntervals).get(name);
189
+ if (!interval)
190
+ throw new Error('invalid interval: ' + name);
190
191
  if (period > 1) {
191
192
  interval = interval.every(period);
192
193
  interval[intervalDuration] = durations.get(name) * period;
@@ -0,0 +1,2 @@
1
+ export * from './plotDefaults.js';
2
+ export { usePlot } from './usePlot.svelte.js';
@@ -0,0 +1,2 @@
1
+ export * from './plotDefaults.js';
2
+ export { usePlot } from './usePlot.svelte.js';
@@ -1,3 +1,5 @@
1
- import type { PlotDefaults } from '../types';
1
+ import type { PlotDefaults } from '../types/index.js';
2
+ /** sets default options for all Plot components in this component tree, merging with any existing defaults from parent contexts */
2
3
  export declare function setPlotDefaults(plotDefaults: Partial<PlotDefaults>): void;
4
+ /** retrieves the current plot defaults from the Svelte context, or an empty object if none have been set */
3
5
  export declare function getPlotDefaults(): Partial<PlotDefaults>;
@@ -1,10 +1,13 @@
1
1
  import { getContext, hasContext, setContext } from 'svelte';
2
2
  const PLOT_DEFAULTS_KEY = Symbol('svelteplot/defaults');
3
+ /** sets default options for all Plot components in this component tree, merging with any existing defaults from parent contexts */
3
4
  export function setPlotDefaults(plotDefaults) {
4
5
  const existingDefaults = getPlotDefaults();
5
- const mergedDefaults = { ...existingDefaults, ...plotDefaults };
6
+ const normalizedDefaults = normalizePlotDefaults(plotDefaults, existingDefaults);
7
+ const mergedDefaults = { ...existingDefaults, ...normalizedDefaults };
6
8
  setContext(PLOT_DEFAULTS_KEY, mergedDefaults);
7
9
  }
10
+ /** retrieves the current plot defaults from the Svelte context, or an empty object if none have been set */
8
11
  export function getPlotDefaults() {
9
12
  return hasContext(PLOT_DEFAULTS_KEY)
10
13
  ? getContext(PLOT_DEFAULTS_KEY)
@@ -14,3 +17,32 @@ export function getPlotDefaults() {
14
17
  getContext('svelteplot/defaults'))
15
18
  : {};
16
19
  }
20
+ function normalizePlotDefaults(plotDefaults, existingDefaults) {
21
+ const grid = normalizeGridDefaults(plotDefaults.grid, existingDefaults.grid);
22
+ const gridX = normalizeGridDefaults(plotDefaults.gridX, existingDefaults.gridX);
23
+ const gridY = normalizeGridDefaults(plotDefaults.gridY, existingDefaults.gridY);
24
+ const frame = normalizeFrameDefaults(plotDefaults.frame, existingDefaults.frame);
25
+ return {
26
+ ...plotDefaults,
27
+ ...(grid !== undefined ? { grid } : {}),
28
+ ...(gridX !== undefined ? { gridX } : {}),
29
+ ...(gridY !== undefined ? { gridY } : {}),
30
+ ...(frame !== undefined ? { frame } : {})
31
+ };
32
+ }
33
+ function normalizeGridDefaults(input, existing) {
34
+ if (input !== true)
35
+ return input;
36
+ return {
37
+ ...(typeof existing === 'object' ? existing : {}),
38
+ implicit: true
39
+ };
40
+ }
41
+ function normalizeFrameDefaults(input, existing) {
42
+ if (input !== true)
43
+ return input;
44
+ return {
45
+ ...(typeof existing === 'object' ? existing : {}),
46
+ implicit: true
47
+ };
48
+ }
@@ -1,12 +1,12 @@
1
- import type { PlotOptions } from '../types/plot';
2
- import type { PlotScales, PlotState as TPlotState } from '../types';
1
+ import type { ResolvedPlotOptions } from '../types/plot.js';
2
+ import type { PlotScales, PlotState as TPlotState } from '../types/index.js';
3
3
  /**
4
- * Internal state representation of a Plot.
4
+ * internal state representation of a Plot, using Svelte 5 runes for reactivity
5
5
  */
6
6
  declare class PlotState implements TPlotState {
7
7
  width: number;
8
8
  height: number;
9
- options: PlotOptions;
9
+ options: ResolvedPlotOptions;
10
10
  facetWidth: number;
11
11
  facetHeight: number;
12
12
  plotWidth: number;
@@ -24,28 +24,13 @@ declare class PlotState implements TPlotState {
24
24
  hasFilledDotMarks: boolean;
25
25
  css: ((d: string) => string) | null;
26
26
  constructor(state: PlotState);
27
+ /** merges partial state into the current plot state */
27
28
  update(newState: Partial<PlotState>): void;
28
- get publicState(): PublicPlotState;
29
+ /** returns a read-only wrapper exposing only public properties */
30
+ get publicState(): Readonly<TPlotState>;
29
31
  }
30
- /**
31
- * A public-facing wrapper around PlotState that exposes only read-only properties.
32
- */
33
- declare class PublicPlotState {
34
- #private;
35
- constructor(plotState: PlotState);
36
- get width(): number;
37
- get height(): number;
38
- get options(): PlotOptions;
39
- get scales(): PlotScales;
40
- get plotWidth(): number;
41
- get plotHeight(): number;
42
- get facetWidth(): number;
43
- get facetHeight(): number;
44
- get body(): HTMLDivElement;
45
- get colorSymbolRedundant(): boolean;
46
- get hasFilledDotMarks(): boolean;
47
- get css(): ((d: string) => string) | null;
48
- }
49
- export declare function setPlot(initialState: PlotState): PlotState;
32
+ /** creates a new PlotState instance from the given initial state */
33
+ export declare function setPlot(initialState: TPlotState): PlotState;
34
+ /** returns the current Plot's public state from Svelte context. Must be called within a `<Plot>` component tree. */
50
35
  export declare function usePlot(): Readonly<TPlotState>;
51
36
  export {};
@@ -1,9 +1,8 @@
1
1
  import { getContext } from 'svelte';
2
2
  /**
3
- * Internal state representation of a Plot.
3
+ * internal state representation of a Plot, using Svelte 5 runes for reactivity
4
4
  */
5
5
  class PlotState {
6
- // Define properties and methods for PlotState as needed
7
6
  width = $state(50);
8
7
  height = $state(50);
9
8
  options = $state({});
@@ -11,8 +10,8 @@ class PlotState {
11
10
  facetHeight = $state(0);
12
11
  plotWidth = $state(0);
13
12
  plotHeight = $state(0);
14
- scales = $state();
15
- body = $state();
13
+ scales = $state(undefined);
14
+ body = $state(undefined);
16
15
  /**
17
16
  * True if there's a color scale and a symbol scale and both are bound to the same
18
17
  * single channel accessor.
@@ -27,16 +26,16 @@ class PlotState {
27
26
  // Initialization code here
28
27
  Object.assign(this, state);
29
28
  }
29
+ /** merges partial state into the current plot state */
30
30
  update(newState) {
31
31
  Object.assign(this, newState);
32
32
  }
33
+ /** returns a read-only wrapper exposing only public properties */
33
34
  get publicState() {
34
35
  return new PublicPlotState(this);
35
36
  }
36
37
  }
37
- /**
38
- * A public-facing wrapper around PlotState that exposes only read-only properties.
39
- */
38
+ /** read-only wrapper around PlotState that exposes only getter properties */
40
39
  class PublicPlotState {
41
40
  #plotState;
42
41
  constructor(plotState) {
@@ -79,11 +78,13 @@ class PublicPlotState {
79
78
  return this.#plotState.css;
80
79
  }
81
80
  }
81
+ /** creates a new PlotState instance from the given initial state */
82
82
  export function setPlot(initialState) {
83
83
  return new PlotState({
84
84
  ...initialState
85
85
  });
86
86
  }
87
+ /** returns the current Plot's public state from Svelte context. Must be called within a `<Plot>` component tree. */
87
88
  export function usePlot() {
88
89
  const { getPlotState } = getContext('svelteplot');
89
90
  return getPlotState().publicState;
package/dist/index.d.ts CHANGED
@@ -2,7 +2,6 @@ export { default as Plot } from './Plot.svelte';
2
2
  export { default as PlotCore } from './core/Plot.svelte';
3
3
  export * from './marks/index.js';
4
4
  export * from './transforms/index.js';
5
+ export * from './hooks/index.js';
5
6
  export { formatMonth } from './helpers/formats.js';
6
7
  export { default as wordwrap } from './helpers/wordwrap.js';
7
- export * from './hooks/plotDefaults.js';
8
- export { usePlot } from './hooks/usePlot.svelte.js';
package/dist/index.js CHANGED
@@ -2,9 +2,7 @@ export { default as Plot } from './Plot.svelte';
2
2
  export { default as PlotCore } from './core/Plot.svelte';
3
3
  export * from './marks/index.js';
4
4
  export * from './transforms/index.js';
5
+ export * from './hooks/index.js';
5
6
  // helpers
6
7
  export { formatMonth } from './helpers/formats.js';
7
8
  export { default as wordwrap } from './helpers/wordwrap.js';
8
- // hooks
9
- export * from './hooks/plotDefaults.js';
10
- export { usePlot } from './hooks/usePlot.svelte.js';
@@ -3,17 +3,29 @@
3
3
  -->
4
4
  <script lang="ts" generics="Datum extends DataRecord">
5
5
  interface AreaMarkProps extends BaseMarkProps<Datum>, LinkableMarkProps<Datum> {
6
- data: Datum[];
6
+ /** the input data array; each element becomes one point in the area */
7
+ data?: Datum[];
8
+ /** the starting horizontal position channel for the area baseline */
7
9
  x1?: ChannelAccessor<Datum>;
10
+ /** the ending horizontal position channel for the area topline */
8
11
  x2?: ChannelAccessor<Datum>;
12
+ /** the starting vertical position channel for the area baseline */
9
13
  y1?: ChannelAccessor<Datum>;
14
+ /** the ending vertical position channel for the area topline */
10
15
  y2?: ChannelAccessor<Datum>;
16
+ /** the series channel; data is grouped into separate areas by unique z values */
11
17
  z?: ChannelAccessor<Datum>;
18
+ /** the curve interpolation method for connecting data points */
12
19
  curve?: CurveName | CurveFactory;
20
+ /** the tension parameter for cardinal or Catmull-Rom curve interpolation */
13
21
  tension?: number;
22
+ /** controls the order of data points before rendering */
14
23
  sort?: ConstantAccessor<RawValue> | { channel: 'stroke' | 'fill' };
24
+ /** options for stacking area data values */
15
25
  stack?: Partial<StackOptions>;
26
+ /** if true, renders using Canvas instead of SVG */
16
27
  canvas?: boolean;
28
+ /** CSS class name(s) to apply to individual area path elements */
17
29
  areaClass?: ConstantAccessor<string, Datum>;
18
30
  }
19
31
 
@@ -21,7 +33,7 @@
21
33
  import GroupMultiple from './helpers/GroupMultiple.svelte';
22
34
  import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
23
35
  import { groups as d3Groups } from 'd3-array';
24
- import { area, type CurveFactory } from 'd3-shape';
36
+ import { area, type Area, type CurveFactory } from 'd3-shape';
25
37
  import callWithProps from '../helpers/callWithProps.js';
26
38
  import { maybeCurve } from '../helpers/curves.js';
27
39
  import { isValid } from '../helpers/index.js';
@@ -39,7 +51,7 @@
39
51
  RawValue
40
52
  } from '../types/index.js';
41
53
  import type { StackOptions } from '../transforms/stack.js';
42
- import { addEventHandlers } from './helpers/events';
54
+ import { addEventHandlers } from './helpers/events.js';
43
55
  import { getPlotDefaults } from '../hooks/plotDefaults.js';
44
56
  import { usePlot } from '../hooks/usePlot.svelte.js';
45
57
 
@@ -89,7 +101,7 @@
89
101
  y0: (d: ScaledDataRecord) => d.y1,
90
102
  y1: (d: ScaledDataRecord) => d.y2
91
103
  })
92
- })
104
+ }) as unknown as Area<ScaledDataRecord>
93
105
  );
94
106
 
95
107
  function groupAndSort(data: ScaledDataRecord[]) {
@@ -97,12 +109,11 @@
97
109
  ? d3Groups(data, (d) => resolveProp(groupByKey, d.datum)).map((d) => d[1])
98
110
  : [data];
99
111
  if (options.sort) {
100
- return groups.toSorted((a, b) =>
101
- resolveChannel('sort', a[0].datum, options) >
102
- resolveChannel('sort', b[0].datum, options)
103
- ? 1
104
- : -1
105
- );
112
+ return groups.toSorted((a, b) => {
113
+ const av = resolveChannel('sort', a[0].datum, options) as string | number | null;
114
+ const bv = resolveChannel('sort', b[0].datum, options) as string | number | null;
115
+ return av! > bv! ? 1 : -1;
116
+ });
106
117
  }
107
118
  return groups;
108
119
  }
@@ -113,8 +124,8 @@
113
124
  {data}
114
125
  channels={['x1', 'x2', 'y1', 'y2', 'fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity']}
115
126
  required={['x1', 'y1']}
116
- {...markProps}
117
- {...options}>
127
+ {...markProps as any}
128
+ {...options as any}>
118
129
  {#snippet children({ mark, usedScales, scaledData })}
119
130
  {@const grouped = groupAndSort(scaledData)}
120
131
  {#if canvas}
@@ -124,7 +135,7 @@
124
135
  {#each grouped as areaData, i (i)}
125
136
  {@const datum = areaData[0]}
126
137
  {#if areaData.length > 0}
127
- <Anchor {options} {datum}>
138
+ <Anchor options={options as any} {datum}>
128
139
  {@const title = resolveProp(options.title, datum.datum, '')}
129
140
  {@const [style, styleClass] = resolveStyles(
130
141
  plot,