svelteplot 0.0.1-alpha.8 → 0.1.3-next.3

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 (251) hide show
  1. package/LICENSE.md +5 -0
  2. package/README.md +3 -36
  3. package/dist/Mark.svelte +292 -0
  4. package/dist/Mark.svelte.d.ts +22 -0
  5. package/dist/Plot.svelte +148 -153
  6. package/dist/Plot.svelte.d.ts +15 -15
  7. package/dist/constants.d.ts +14 -0
  8. package/dist/constants.js +109 -0
  9. package/dist/core/Facet.svelte +59 -0
  10. package/dist/core/Facet.svelte.d.ts +18 -0
  11. package/dist/core/FacetAxes.svelte +66 -0
  12. package/dist/core/FacetAxes.svelte.d.ts +4 -0
  13. package/dist/core/FacetGrid.svelte +86 -0
  14. package/dist/core/FacetGrid.svelte.d.ts +13 -0
  15. package/dist/core/Plot.svelte +567 -0
  16. package/dist/core/Plot.svelte.d.ts +14 -0
  17. package/dist/helpers/arrowPath.d.ts +14 -0
  18. package/dist/helpers/arrowPath.js +129 -0
  19. package/dist/helpers/autoProjection.d.ts +19 -0
  20. package/dist/helpers/autoProjection.js +87 -0
  21. package/dist/helpers/autoScales.d.ts +23 -0
  22. package/dist/helpers/autoScales.js +203 -0
  23. package/dist/helpers/autoTicks.d.ts +3 -0
  24. package/dist/helpers/autoTicks.js +40 -0
  25. package/dist/helpers/autoTimeFormat.d.ts +2 -2
  26. package/dist/helpers/autoTimeFormat.js +34 -5
  27. package/dist/helpers/callWithProps.d.ts +8 -0
  28. package/dist/helpers/callWithProps.js +13 -0
  29. package/dist/helpers/colors.js +17 -2
  30. package/dist/helpers/curves.d.ts +3 -0
  31. package/dist/helpers/curves.js +42 -0
  32. package/dist/helpers/data.d.ts +9 -0
  33. package/dist/helpers/data.js +16 -0
  34. package/dist/helpers/facets.d.ts +12 -0
  35. package/dist/helpers/facets.js +49 -0
  36. package/dist/helpers/formats.d.ts +3 -0
  37. package/dist/helpers/formats.js +3 -0
  38. package/dist/helpers/getBaseStyles.d.ts +7 -2
  39. package/dist/helpers/getBaseStyles.js +34 -10
  40. package/dist/helpers/getLogTicks.js +5 -5
  41. package/dist/helpers/group.d.ts +6 -0
  42. package/dist/helpers/group.js +53 -0
  43. package/dist/helpers/index.d.ts +18 -0
  44. package/dist/helpers/index.js +53 -0
  45. package/dist/helpers/isRawValue.d.ts +2 -0
  46. package/dist/helpers/isRawValue.js +5 -0
  47. package/dist/helpers/isValid.d.ts +6 -0
  48. package/dist/helpers/isValid.js +6 -0
  49. package/dist/helpers/math.d.ts +19 -0
  50. package/dist/helpers/math.js +116 -0
  51. package/dist/helpers/mergeDeep.d.ts +1 -1
  52. package/dist/helpers/noise.d.ts +1 -0
  53. package/dist/helpers/noise.js +72 -0
  54. package/dist/helpers/projection.d.ts +33 -0
  55. package/dist/helpers/projection.js +100 -0
  56. package/dist/helpers/reduce.d.ts +10 -0
  57. package/dist/helpers/reduce.js +85 -0
  58. package/dist/helpers/regressionLoess.d.ts +12 -0
  59. package/dist/helpers/regressionLoess.js +47 -0
  60. package/dist/helpers/removeIdenticalLines.d.ts +8 -1
  61. package/dist/helpers/removeIdenticalLines.js +14 -7
  62. package/dist/helpers/resolve.d.ts +17 -0
  63. package/dist/helpers/resolve.js +152 -0
  64. package/dist/helpers/roundedRect.d.ts +9 -0
  65. package/dist/helpers/roundedRect.js +31 -0
  66. package/dist/helpers/scales.d.ts +42 -0
  67. package/dist/helpers/scales.js +309 -0
  68. package/dist/helpers/time.d.ts +6 -0
  69. package/dist/helpers/time.js +282 -0
  70. package/dist/helpers/typeChecks.d.ts +8 -5
  71. package/dist/helpers/typeChecks.js +27 -6
  72. package/dist/index.d.ts +49 -1
  73. package/dist/index.js +53 -2
  74. package/dist/marks/Area.svelte +146 -0
  75. package/dist/marks/Area.svelte.d.ts +30 -0
  76. package/dist/marks/AreaX.svelte +27 -0
  77. package/dist/marks/AreaX.svelte.d.ts +12 -0
  78. package/dist/marks/AreaY.svelte +38 -0
  79. package/dist/marks/AreaY.svelte.d.ts +19 -0
  80. package/dist/marks/Arrow.svelte +139 -0
  81. package/dist/marks/Arrow.svelte.d.ts +44 -0
  82. package/dist/marks/AxisX.svelte +198 -93
  83. package/dist/marks/AxisX.svelte.d.ts +17 -16
  84. package/dist/marks/AxisY.svelte +176 -62
  85. package/dist/marks/AxisY.svelte.d.ts +17 -14
  86. package/dist/marks/BarX.svelte +81 -0
  87. package/dist/marks/BarX.svelte.d.ts +4 -0
  88. package/dist/marks/BarY.svelte +95 -0
  89. package/dist/marks/BarY.svelte.d.ts +4 -0
  90. package/dist/marks/BollingerX.svelte +44 -0
  91. package/dist/marks/BollingerX.svelte.d.ts +18 -0
  92. package/dist/marks/BollingerY.svelte +39 -0
  93. package/dist/marks/BollingerY.svelte.d.ts +18 -0
  94. package/dist/marks/BoxX.svelte +89 -0
  95. package/dist/marks/BoxX.svelte.d.ts +4 -0
  96. package/dist/marks/BoxY.svelte +110 -0
  97. package/dist/marks/BoxY.svelte.d.ts +29 -0
  98. package/dist/marks/Cell.svelte +110 -0
  99. package/dist/marks/Cell.svelte.d.ts +16 -0
  100. package/dist/marks/CellX.svelte +24 -0
  101. package/dist/marks/CellX.svelte.d.ts +3 -0
  102. package/dist/marks/CellY.svelte +24 -0
  103. package/dist/marks/CellY.svelte.d.ts +3 -0
  104. package/dist/marks/ColorLegend.svelte +148 -27
  105. package/dist/marks/ColorLegend.svelte.d.ts +12 -13
  106. package/dist/marks/CustomMark.svelte +43 -0
  107. package/dist/marks/CustomMark.svelte.d.ts +16 -0
  108. package/dist/marks/CustomMarkHTML.svelte +103 -0
  109. package/dist/marks/CustomMarkHTML.svelte.d.ts +17 -0
  110. package/dist/marks/DifferenceY.svelte +144 -0
  111. package/dist/marks/DifferenceY.svelte.d.ts +30 -0
  112. package/dist/marks/Dot.svelte +128 -73
  113. package/dist/marks/Dot.svelte.d.ts +24 -14
  114. package/dist/marks/DotX.svelte +15 -3
  115. package/dist/marks/DotX.svelte.d.ts +8 -16
  116. package/dist/marks/DotY.svelte +8 -3
  117. package/dist/marks/DotY.svelte.d.ts +5 -17
  118. package/dist/marks/Frame.svelte +32 -31
  119. package/dist/marks/Frame.svelte.d.ts +7 -14
  120. package/dist/marks/Geo.svelte +102 -0
  121. package/dist/marks/Geo.svelte.d.ts +10 -0
  122. package/dist/marks/Graticule.svelte +28 -0
  123. package/dist/marks/Graticule.svelte.d.ts +9 -0
  124. package/dist/marks/GridX.svelte +67 -36
  125. package/dist/marks/GridX.svelte.d.ts +7 -18
  126. package/dist/marks/GridY.svelte +64 -25
  127. package/dist/marks/GridY.svelte.d.ts +7 -14
  128. package/dist/marks/HTMLTooltip.svelte +91 -0
  129. package/dist/marks/HTMLTooltip.svelte.d.ts +11 -0
  130. package/dist/marks/Line.svelte +219 -58
  131. package/dist/marks/Line.svelte.d.ts +30 -14
  132. package/dist/marks/LineX.svelte +8 -8
  133. package/dist/marks/LineX.svelte.d.ts +4 -17
  134. package/dist/marks/LineY.svelte +7 -8
  135. package/dist/marks/LineY.svelte.d.ts +4 -17
  136. package/dist/marks/Link.svelte +173 -0
  137. package/dist/marks/Link.svelte.d.ts +21 -0
  138. package/dist/marks/Pointer.svelte +126 -0
  139. package/dist/marks/Pointer.svelte.d.ts +23 -0
  140. package/dist/marks/Rect.svelte +103 -0
  141. package/dist/marks/Rect.svelte.d.ts +15 -0
  142. package/dist/marks/RectX.svelte +33 -0
  143. package/dist/marks/RectX.svelte.d.ts +15 -0
  144. package/dist/marks/RectY.svelte +33 -0
  145. package/dist/marks/RectY.svelte.d.ts +15 -0
  146. package/dist/marks/RegressionX.svelte +26 -0
  147. package/dist/marks/RegressionX.svelte.d.ts +4 -0
  148. package/dist/marks/RegressionY.svelte +26 -0
  149. package/dist/marks/RegressionY.svelte.d.ts +4 -0
  150. package/dist/marks/RuleX.svelte +52 -28
  151. package/dist/marks/RuleX.svelte.d.ts +14 -14
  152. package/dist/marks/RuleY.svelte +52 -28
  153. package/dist/marks/RuleY.svelte.d.ts +14 -14
  154. package/dist/marks/Sphere.svelte +8 -0
  155. package/dist/marks/Sphere.svelte.d.ts +51 -0
  156. package/dist/marks/Spike.svelte +15 -0
  157. package/dist/marks/Spike.svelte.d.ts +4 -0
  158. package/dist/marks/SymbolLegend.svelte +27 -12
  159. package/dist/marks/SymbolLegend.svelte.d.ts +8 -14
  160. package/dist/marks/Text.svelte +185 -0
  161. package/dist/marks/Text.svelte.d.ts +26 -0
  162. package/dist/marks/TickX.svelte +89 -0
  163. package/dist/marks/TickX.svelte.d.ts +22 -0
  164. package/dist/marks/TickY.svelte +90 -0
  165. package/dist/marks/TickY.svelte.d.ts +22 -0
  166. package/dist/marks/Vector.svelte +213 -0
  167. package/dist/marks/Vector.svelte.d.ts +31 -0
  168. package/dist/marks/helpers/BaseAxisX.svelte +210 -0
  169. package/dist/marks/helpers/BaseAxisX.svelte.d.ts +24 -0
  170. package/dist/marks/helpers/BaseAxisY.svelte +187 -0
  171. package/dist/marks/helpers/BaseAxisY.svelte.d.ts +23 -0
  172. package/dist/marks/helpers/CanvasLayer.svelte +38 -0
  173. package/dist/marks/helpers/CanvasLayer.svelte.d.ts +13 -0
  174. package/dist/marks/helpers/DotCanvas.svelte +184 -0
  175. package/dist/marks/helpers/DotCanvas.svelte.d.ts +11 -0
  176. package/dist/marks/helpers/GeoCanvas.svelte +165 -0
  177. package/dist/marks/helpers/GeoCanvas.svelte.d.ts +13 -0
  178. package/dist/marks/helpers/GroupMultiple.svelte +17 -0
  179. package/dist/marks/helpers/GroupMultiple.svelte.d.ts +9 -0
  180. package/dist/marks/helpers/Marker.svelte +93 -0
  181. package/dist/marks/helpers/Marker.svelte.d.ts +10 -0
  182. package/dist/marks/helpers/MarkerPath.svelte +164 -0
  183. package/dist/marks/helpers/MarkerPath.svelte.d.ts +44 -0
  184. package/dist/marks/helpers/Regression.svelte +174 -0
  185. package/dist/marks/helpers/Regression.svelte.d.ts +26 -0
  186. package/dist/marks/helpers/events.d.ts +8 -0
  187. package/dist/marks/helpers/events.js +64 -0
  188. package/dist/transforms/bin.d.ts +51 -0
  189. package/dist/transforms/bin.js +171 -0
  190. package/dist/transforms/bollinger.d.ts +21 -0
  191. package/dist/transforms/bollinger.js +53 -0
  192. package/dist/transforms/centroid.d.ts +9 -0
  193. package/dist/transforms/centroid.js +13 -0
  194. package/dist/transforms/facet.d.ts +1 -0
  195. package/dist/transforms/facet.js +1 -0
  196. package/dist/transforms/filter.d.ts +2 -0
  197. package/dist/transforms/filter.js +8 -0
  198. package/dist/transforms/group.d.ts +66 -0
  199. package/dist/transforms/group.js +109 -0
  200. package/dist/transforms/interval.d.ts +11 -0
  201. package/dist/transforms/interval.js +34 -0
  202. package/dist/transforms/jitter.d.ts +0 -0
  203. package/dist/transforms/jitter.js +1 -0
  204. package/dist/transforms/map.d.ts +10 -0
  205. package/dist/transforms/map.js +89 -0
  206. package/dist/transforms/normalize.d.ts +9 -0
  207. package/dist/transforms/normalize.js +86 -0
  208. package/dist/transforms/recordize.d.ts +13 -0
  209. package/dist/transforms/recordize.js +75 -0
  210. package/dist/transforms/rename.d.ts +14 -0
  211. package/dist/transforms/rename.js +42 -0
  212. package/dist/transforms/select.d.ts +35 -0
  213. package/dist/transforms/select.js +55 -0
  214. package/dist/transforms/shift.d.ts +13 -0
  215. package/dist/transforms/shift.js +45 -0
  216. package/dist/transforms/sort.d.ts +28 -0
  217. package/dist/transforms/sort.js +61 -0
  218. package/dist/transforms/stack.d.ts +10 -0
  219. package/dist/transforms/stack.js +110 -0
  220. package/dist/transforms/window.d.ts +22 -0
  221. package/dist/transforms/window.js +73 -0
  222. package/dist/types.d.ts +625 -188
  223. package/dist/ui/Checkbox.svelte +6 -0
  224. package/dist/ui/Checkbox.svelte.d.ts +13 -0
  225. package/dist/ui/RadioInput.svelte +27 -0
  226. package/dist/ui/RadioInput.svelte.d.ts +9 -0
  227. package/dist/ui/Select.svelte +27 -0
  228. package/dist/ui/Select.svelte.d.ts +9 -0
  229. package/dist/ui/Slider.svelte +47 -0
  230. package/dist/ui/Slider.svelte.d.ts +11 -0
  231. package/dist/ui/Spiral.svelte +46 -0
  232. package/dist/ui/Spiral.svelte.d.ts +15 -0
  233. package/dist/ui/index.d.ts +4 -0
  234. package/dist/ui/index.js +4 -0
  235. package/package.json +79 -40
  236. package/LICENSE +0 -11
  237. package/dist/classes/Channel.svelte.js +0 -74
  238. package/dist/classes/Mark.svelte.js +0 -17
  239. package/dist/classes/Plot.svelte.js +0 -98
  240. package/dist/contants.d.ts +0 -3
  241. package/dist/contants.js +0 -40
  242. package/dist/helpers/GroupMultiple.svelte +0 -8
  243. package/dist/helpers/GroupMultiple.svelte.d.ts +0 -19
  244. package/dist/helpers/createScale.d.ts +0 -5
  245. package/dist/helpers/createScale.js +0 -57
  246. package/dist/helpers/resolveChannel.d.ts +0 -2
  247. package/dist/helpers/resolveChannel.js +0 -28
  248. package/dist/helpers/wrapArray.d.ts +0 -2
  249. package/dist/helpers/wrapArray.js +0 -4
  250. package/dist/marks/BaseMark.svelte +0 -22
  251. package/dist/marks/BaseMark.svelte.d.ts +0 -19
@@ -0,0 +1,26 @@
1
+ import type { BaseMarkProps, ChannelAccessor } from '../../types.js';
2
+ type RegressionType = 'linear' | 'quad' | 'poly' | 'exp' | 'log' | 'pow' | 'loess';
3
+ export type RegressionMarkProps = BaseMarkProps & {
4
+ x: ChannelAccessor;
5
+ y: ChannelAccessor;
6
+ type: RegressionType;
7
+ /**
8
+ * If order is specified, sets the regression's order to the specified number.
9
+ * For example, if order is set to 4, the regression generator will perform a
10
+ * fourth-degree polynomial regression. Likewise, if order is set to 2, the
11
+ * regression generator will perform a quadratic regression. Be careful about
12
+ * attempting to fit your data with higher order polynomials; though the
13
+ * regression line will fit your data with a high determination coefficient,
14
+ * it may have little predictive power for data outside of your domain.
15
+ */
16
+ order: number;
17
+ base: number;
18
+ span: number;
19
+ confidence: number;
20
+ };
21
+ type $$ComponentProps = RegressionMarkProps & {
22
+ dependent: 'x' | 'y';
23
+ };
24
+ declare const Regression: import("svelte").Component<$$ComponentProps, {}, "">;
25
+ type Regression = ReturnType<typeof Regression>;
26
+ export default Regression;
@@ -0,0 +1,8 @@
1
+ import type { BaseMarkProps, DataRecord, PlotState } from '../../types.js';
2
+ export declare function addEventHandlers(node: SVGElement, { options, datum, getPlotState }: {
3
+ options: BaseMarkProps;
4
+ datum: DataRecord;
5
+ getPlotState: () => PlotState;
6
+ }): {
7
+ destroy(): void;
8
+ };
@@ -0,0 +1,64 @@
1
+ import { pick } from 'es-toolkit';
2
+ export function addEventHandlers(node, { options, datum, getPlotState }) {
3
+ const events = pick(options, [
4
+ 'onclick',
5
+ 'oncontextmenu',
6
+ 'ondblclick',
7
+ 'ondrag',
8
+ 'ondragend',
9
+ 'ondragenter',
10
+ 'ondragleave',
11
+ 'ondragover',
12
+ 'ondragstart',
13
+ 'ondrop',
14
+ 'onmousedown',
15
+ 'onmouseenter',
16
+ 'onmouseleave',
17
+ 'onmousemove',
18
+ 'onmouseout',
19
+ 'onmouseup',
20
+ 'onwheel',
21
+ 'ontouchcancel',
22
+ 'ontouchend',
23
+ 'ontouchmove'
24
+ ]);
25
+ const listeners = new Map();
26
+ // attach event handlers
27
+ for (const [eventName, eventHandler] of Object.entries(events)) {
28
+ if (eventHandler) {
29
+ const wrappedHandler = (origEvent) => {
30
+ const { scales } = getPlotState();
31
+ if (origEvent.layerX !== undefined) {
32
+ if (scales.projection) {
33
+ const [x, y] = scales.projection.invert([
34
+ origEvent.layerX,
35
+ origEvent.layerY
36
+ ]);
37
+ origEvent.dataX = x;
38
+ origEvent.dataY = y;
39
+ }
40
+ else {
41
+ origEvent.dataX =
42
+ scales.x.fn.invert && scales.x.fn.invert(origEvent.layerX);
43
+ origEvent.dataY =
44
+ scales.y.fn.invert && scales.y.fn.invert(origEvent.layerY);
45
+ }
46
+ }
47
+ eventHandler(origEvent, datum.___orig___ !== undefined ? datum.___orig___ : datum);
48
+ };
49
+ listeners.set(eventName, wrappedHandler);
50
+ node.addEventListener(eventName.substring(2), wrappedHandler);
51
+ }
52
+ }
53
+ if (events.onclick || events.onmousedown || events.onmouseup) {
54
+ // force role button
55
+ node.setAttribute('role', 'button');
56
+ }
57
+ return {
58
+ destroy() {
59
+ for (const [eventName, handler] of listeners.entries()) {
60
+ node.removeEventListener(eventName.substring(2), handler);
61
+ }
62
+ }
63
+ };
64
+ }
@@ -0,0 +1,51 @@
1
+ import type { DataRecord, RawValue } from '../types.js';
2
+ import type { TransformArg } from '../types.js';
3
+ import { type ThresholdCountGenerator } from 'd3-array';
4
+ import { Reducer, type ReducerName } from '../helpers/reduce.js';
5
+ type NamedThresholdsGenerator = 'auto' | 'scott' | 'sturges' | 'freedman-diaconis';
6
+ type BinBaseOptions = {
7
+ domain?: [number, number];
8
+ thresholds?: NamedThresholdsGenerator | number | number[] | ThresholdCountGenerator;
9
+ interval?: number | string;
10
+ cumulative?: false | 1 | -1;
11
+ reverse?: boolean;
12
+ };
13
+ type ReducerOption = ReducerName | ((group: DataRecord[]) => RawValue);
14
+ type AdditionalOutputChannels = Partial<{
15
+ fill: ReducerOption;
16
+ stroke: ReducerOption;
17
+ r: ReducerOption;
18
+ opacity: ReducerOption;
19
+ fillOpacity: ReducerOption;
20
+ strokeOpacity: ReducerOption;
21
+ }>;
22
+ export type BinXOptions = BinBaseOptions & AdditionalOutputChannels & Partial<{
23
+ y: typeof Reducer;
24
+ y1: typeof Reducer;
25
+ y2: typeof Reducer;
26
+ }>;
27
+ export type BinYOptions = BinBaseOptions & AdditionalOutputChannels & Partial<{
28
+ x: typeof Reducer;
29
+ x1: typeof Reducer;
30
+ x2: typeof Reducer;
31
+ }>;
32
+ type BinOptions = BinBaseOptions & AdditionalOutputChannels;
33
+ /**
34
+ * Bins on x. Also groups on y and the first channel of z, fill, or stroke, if any.
35
+ *
36
+ * @param param0
37
+ * @param options
38
+ */
39
+ export declare function binX<T>({ data, ...channels }: TransformArg<T, DataRecord>, options?: BinXOptions): TransformArg<T, DataRecord>;
40
+ /**
41
+ * Bins on y. Also groups on y and the first channel of z, fill, or stroke, if any.
42
+ *
43
+ * @param param0
44
+ * @param options
45
+ */
46
+ export declare function binY<T>({ data, ...channels }: TransformArg<T, DataRecord>, options?: BinYOptions): TransformArg<T, DataRecord>;
47
+ /**
48
+ * for binning in x and y dimension simulatenously
49
+ */
50
+ export declare function bin<T>({ data, ...channels }: TransformArg<T, DataRecord>, options?: BinOptions): TransformArg<T, DataRecord>;
51
+ export {};
@@ -0,0 +1,171 @@
1
+ import { resolveChannel } from '../helpers/resolve.js';
2
+ import { maybeInterval } from '../helpers/autoTicks.js';
3
+ import { bin as d3Bin, extent, groups as d3Groups, thresholdFreedmanDiaconis, thresholdScott, thresholdSturges } from 'd3-array';
4
+ import { Reducer, reduceOutputs } from '../helpers/reduce.js';
5
+ import { groupFacetsAndZ } from '../helpers/group.js';
6
+ import { isDate } from '../helpers/typeChecks';
7
+ const ThresholdGenerators = {
8
+ auto: thresholdScott,
9
+ scott: thresholdScott,
10
+ sturges: thresholdSturges,
11
+ 'freedman-diaconis': thresholdFreedmanDiaconis
12
+ };
13
+ function binBy(byDim, { data, ...channels }, options) {
14
+ const { domain, thresholds = 'auto', interval } = options;
15
+ const bin = d3Bin();
16
+ if (domain)
17
+ bin.domain(domain);
18
+ if (interval) {
19
+ const [lo, hi] = extent(data.map((d) => resolveChannel(byDim, d, channels)));
20
+ bin.thresholds(maybeInterval(interval).range(lo, hi));
21
+ }
22
+ else if (thresholds)
23
+ bin.thresholds(
24
+ // use a generator
25
+ typeof thresholds === 'string' && ThresholdGenerators[thresholds] !== undefined
26
+ ? ThresholdGenerators[thresholds]
27
+ : thresholds);
28
+ // channels.x is the input
29
+ bin.value((d) => resolveChannel(byDim, d, channels));
30
+ // y, y1, y2, fill, stroke, etc are outputs
31
+ const outputs = [
32
+ ...(byDim === 'x' ? ['y', 'y1', 'y2'] : ['x', 'x1', 'x2']),
33
+ 'fill',
34
+ 'stroke',
35
+ 'r',
36
+ 'opacity',
37
+ 'fillOpacity',
38
+ 'strokeOpacity'
39
+ ];
40
+ let newChannels = {
41
+ [byDim === 'x' ? 'insetLeft' : 'insetTop']: 0.5,
42
+ [byDim === 'x' ? 'insetRight' : 'insetBottom']: 0.5,
43
+ ...channels,
44
+ [`${byDim}`]: `__${byDim}`,
45
+ [`${byDim}1`]: `__${byDim}1`,
46
+ [`${byDim}2`]: `__${byDim}2`,
47
+ [`__${byDim}_origField`]: typeof channels[byDim] === 'string' ? channels[byDim] : null
48
+ };
49
+ const newData = [];
50
+ let passedGroups = [];
51
+ const bins = bin(data);
52
+ (options.cumulative < 0 ? bins.toReversed() : bins).forEach((group) => {
53
+ const itemBinProps = {
54
+ [`__${byDim}1`]: group.x0,
55
+ [`__${byDim}2`]: group.x1,
56
+ [`__${byDim}`]: isDate(group.x0)
57
+ ? new Date(Math.round((group.x0.getTime() + group.x1.getTime()) * 0.5))
58
+ : (group.x0 + group.x1) * 0.5
59
+ };
60
+ if (options.cumulative)
61
+ passedGroups = [...passedGroups, ...group];
62
+ const newGroupChannels = groupFacetsAndZ(options.cumulative ? passedGroups : group, channels, (items, itemGroupProps) => {
63
+ const item = { ...itemBinProps, ...itemGroupProps };
64
+ reduceOutputs(item, items, options, outputs, channels, newChannels);
65
+ newData.push(item);
66
+ });
67
+ newChannels = { ...newChannels, ...newGroupChannels };
68
+ });
69
+ return { data: options.reverse ? newData.toReversed() : newData, ...newChannels };
70
+ }
71
+ /**
72
+ * Bins on x. Also groups on y and the first channel of z, fill, or stroke, if any.
73
+ *
74
+ * @param param0
75
+ * @param options
76
+ */
77
+ export function binX({ data, ...channels }, options = { thresholds: 'auto', cumulative: false }) {
78
+ return binBy('x', { data, ...channels }, options);
79
+ }
80
+ /**
81
+ * Bins on y. Also groups on y and the first channel of z, fill, or stroke, if any.
82
+ *
83
+ * @param param0
84
+ * @param options
85
+ */
86
+ export function binY({ data, ...channels }, options = { thresholds: 'auto', cumulative: false }) {
87
+ return binBy('y', { data, ...channels }, options);
88
+ }
89
+ /**
90
+ * for binning in x and y dimension simulatenously
91
+ */
92
+ export function bin({ data, ...channels }, options = { thresholds: 'auto', cumulative: false }) {
93
+ const { domain, thresholds = 'auto', interval, cumulative = false } = options;
94
+ const binX = d3Bin();
95
+ const binY = d3Bin();
96
+ if (domain) {
97
+ // this really doesn't make sense...
98
+ binX.domain(domain);
99
+ binY.domain(domain);
100
+ }
101
+ // channels.x is the input
102
+ binX.value((d) => resolveChannel('x', d, channels));
103
+ binY.value((d) => resolveChannel('y', d, channels));
104
+ if (interval) {
105
+ const [xlo, xhi] = extent(data.map((d) => resolveChannel('x', d, channels)));
106
+ const [ylo, yhi] = extent(data.map((d) => resolveChannel('y', d, channels)));
107
+ binX.thresholds(maybeInterval(interval).range(xlo, xhi));
108
+ binY.thresholds(maybeInterval(interval).range(ylo, yhi));
109
+ }
110
+ else if (thresholds) {
111
+ // when binning in x and y, we need to ensure we are using consistent thresholds
112
+ const t = typeof thresholds === 'string' && ThresholdGenerators[thresholds] !== undefined
113
+ ? ThresholdGenerators[thresholds]
114
+ : thresholds;
115
+ binX.thresholds(t);
116
+ binY.thresholds(t);
117
+ const yThresholds = binY(data)
118
+ .slice(1)
119
+ .map((g) => g.x0);
120
+ binY.thresholds(yThresholds);
121
+ }
122
+ // y, y1, y2, fill, stroke, etc are outputs
123
+ const outputs = ['fill', 'stroke', 'r', 'opacity', 'fillOpacity', 'strokeOpacity'];
124
+ let newChannels = {
125
+ inset: 0.5,
126
+ ...channels,
127
+ x: '__x',
128
+ x1: '__x1',
129
+ x2: '__x2',
130
+ y: '__y',
131
+ y1: '__y1',
132
+ y2: '__y2',
133
+ __x_origField: typeof channels.x === 'string' ? channels.x : null,
134
+ __y_origField: typeof channels.y === 'string' ? channels.y : null
135
+ };
136
+ const groupBy = channels.z ? 'z' : channels.fill ? 'fill' : channels.stroke ? 'stroke' : true;
137
+ const groupByPropName = groupBy !== true && typeof channels[groupBy] === 'string' ? channels[groupBy] : '__group';
138
+ if (groupBy !== true)
139
+ newChannels[groupBy] = groupByPropName;
140
+ // consistent intervals
141
+ const newData = [];
142
+ binX(data).forEach((groupX) => {
143
+ const newRecordBaseX = {
144
+ __x1: groupX.x0,
145
+ __x2: groupX.x1,
146
+ __x: isDate(groupX.x0)
147
+ ? new Date(Math.round((groupX.x0.getTime() + groupX.x1.getTime()) * 0.5))
148
+ : (groupX.x0 + groupX.x1) * 0.5
149
+ };
150
+ binY(groupX).forEach((groupY) => {
151
+ const newRecordBaseY = {
152
+ ...newRecordBaseX,
153
+ __y1: groupY.x0,
154
+ __y2: groupY.x1,
155
+ __y: isDate(groupY.x0)
156
+ ? new Date(Math.round((groupY.x0.getTime() + groupY.x1.getTime()) * 0.5))
157
+ : (groupY.x0 + groupY.x1) * 0.5
158
+ };
159
+ const newGroupChannels = groupFacetsAndZ(groupY, channels, (items, itemGroupProps) => {
160
+ const newRecord = {
161
+ ...newRecordBaseY,
162
+ ...itemGroupProps
163
+ };
164
+ reduceOutputs(newRecord, items, options, outputs, channels, newChannels);
165
+ newData.push(newRecord);
166
+ });
167
+ newChannels = { ...newChannels, ...newGroupChannels };
168
+ });
169
+ });
170
+ return { data: options.reverse ? newData.toReversed() : newData, ...newChannels };
171
+ }
@@ -0,0 +1,21 @@
1
+ import type { DataRecord, TransformArg } from '../types.js';
2
+ export type BollingerOptions = {
3
+ /**
4
+ * the window size (the window transform’s k option), an integer; defaults to 20
5
+ */
6
+ n?: number;
7
+ /**
8
+ * the band radius, a number representing a multiple of standard deviations; defaults to 2
9
+ */
10
+ k?: number;
11
+ };
12
+ export declare function bollingerX(args: TransformArg<DataRecord>, options?: BollingerOptions): TransformArg<DataRecord>;
13
+ export declare function bollingerY(args: TransformArg<DataRecord>, options?: BollingerOptions): TransformArg<DataRecord>;
14
+ export declare function bollingerDim(dim: 'x' | 'y', { data, ...channels }: TransformArg<DataRecord>, options?: BollingerOptions): {
15
+ data: {
16
+ __x: import("../types.js").RawValue;
17
+ __lo: number;
18
+ __avg: number;
19
+ __hi: number;
20
+ }[];
21
+ };
@@ -0,0 +1,53 @@
1
+ import { resolveChannel } from '../helpers/resolve.js';
2
+ export function bollingerX(args, options = {}) {
3
+ return bollingerDim('x', args, options);
4
+ }
5
+ export function bollingerY(args, options = {}) {
6
+ return bollingerDim('y', args, options);
7
+ }
8
+ export function bollingerDim(dim, { data, ...channels }, options = {}) {
9
+ const { n = 20, k = 2 } = options;
10
+ const bands = bollinger(data.map((datum) => resolveChannel(dim, datum, channels)), n, [-k, 0, k]);
11
+ const otherDim = dim === 'x' ? 'y' : 'x';
12
+ return {
13
+ data: data.map((datum, i) => ({
14
+ __x: resolveChannel(otherDim, datum, channels),
15
+ __lo: bands[0][i],
16
+ __avg: bands[1][i],
17
+ __hi: bands[2][i]
18
+ })),
19
+ ...channels,
20
+ [otherDim]: '__x',
21
+ [dim]: '__avg',
22
+ [`${otherDim}1`]: '__x',
23
+ [`${dim}1`]: '__lo',
24
+ [`${dim}2`]: '__hi'
25
+ };
26
+ }
27
+ /**
28
+ * taken from https://observablehq.com/@d3/bollinger-bands/
29
+ */
30
+ function bollinger(values, N, K) {
31
+ let i = 0;
32
+ let sum = 0;
33
+ let sumSquared = 0;
34
+ // initialize bands
35
+ const bands = K.map(() => new Float64Array(values.length).fill(NaN));
36
+ // compute sum and square of sums
37
+ for (let n = Math.min(N - 1, values.length); i < n; ++i) {
38
+ const value = values[i];
39
+ (sum += value), (sumSquared += value ** 2);
40
+ }
41
+ for (let n = values.length, m = bands.length; i < n; ++i) {
42
+ const value = values[i];
43
+ (sum += value), (sumSquared += value ** 2);
44
+ const mean = sum / N;
45
+ const deviation = Math.sqrt((sumSquared - sum ** 2 / N) / (N - 1));
46
+ for (let j = 0; j < K.length; ++j) {
47
+ bands[j][i] = mean + deviation * K[j];
48
+ }
49
+ const value0 = values[i - N + 1];
50
+ (sum -= value0), (sumSquared -= value0 ** 2);
51
+ }
52
+ return bands;
53
+ }
@@ -0,0 +1,9 @@
1
+ import type { DataRecord, TransformArg } from '../types.js';
2
+ export declare function geoCentroid({ data, ...options }: TransformArg<DataRecord>): {
3
+ x: (d: any) => any;
4
+ y: (d: any) => any;
5
+ data: {
6
+ __centroid__: [number, number];
7
+ ___orig___?: import("../types.js").RawValue | [import("../types.js").RawValue, import("../types.js").RawValue];
8
+ }[];
9
+ };
@@ -0,0 +1,13 @@
1
+ import { resolveProp } from '../helpers/resolve.js';
2
+ import { geoCentroid as d3GeoCentroid } from 'd3-geo';
3
+ export function geoCentroid({ data, ...options }) {
4
+ return {
5
+ data: data.map((d) => ({
6
+ ...d,
7
+ __centroid__: d3GeoCentroid(resolveProp(options.geometry, d, d))
8
+ })),
9
+ ...options,
10
+ x: (d) => d.__centroid__[0],
11
+ y: (d) => d.__centroid__[1]
12
+ };
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { DataRecord, TransformArg } from '../types.js';
2
+ export declare function filter({ data, ...channels }: TransformArg<DataRecord>): TransformArg<DataRecord>;
@@ -0,0 +1,8 @@
1
+ import { testFilter } from '../helpers/index.js';
2
+ export function filter({ data, ...channels }) {
3
+ return {
4
+ data: data.filter((d) => testFilter(d, channels)),
5
+ ...channels,
6
+ filter: null
7
+ };
8
+ }
@@ -0,0 +1,66 @@
1
+ import { type ReducerName } from '../helpers/reduce.js';
2
+ import type { DataRecord, DataRow, RawValue, TransformArg } from '../types.js';
3
+ type ReducerFunc = (group: DataRow[]) => RawValue;
4
+ type ReducerOption = ReducerName | ReducerFunc;
5
+ type GroupBaseOptions = {
6
+ domain?: [number, number];
7
+ thresholds?: NamedThresholdsGenerator | number | number[] | ThresholdCountGenerator;
8
+ interval?: number | string;
9
+ cumulative?: false | 1 | -1;
10
+ reverse?: boolean;
11
+ /**
12
+ * copy properties from the first element of each group
13
+ */
14
+ copy?: string[];
15
+ };
16
+ type AdditionalOutputChannels = Partial<{
17
+ fill: ReducerOption;
18
+ stroke: ReducerOption;
19
+ r: ReducerOption;
20
+ opacity: ReducerOption;
21
+ fillOpacity: ReducerOption;
22
+ strokeOpacity: ReducerOption;
23
+ }>;
24
+ type GroupXOptions = GroupBaseOptions & AdditionalOutputChannels & Partial<{
25
+ y: ReducerOption;
26
+ y1: ReducerOption;
27
+ y2: ReducerOption;
28
+ xPropName: string;
29
+ }>;
30
+ type GroupYOptions = GroupBaseOptions & AdditionalOutputChannels & Partial<{
31
+ x: ReducerOption;
32
+ x1: ReducerOption;
33
+ x2: ReducerOption;
34
+ yPropName: string;
35
+ }>;
36
+ type GroupZOptions = GroupXOptions | GroupYOptions;
37
+ /**
38
+ * groups the dataset by x and y channel and optionally reduces the group items
39
+ * to output channels fill, stroke, r, opacity, fillOpacity, or strokeOpacity
40
+ */
41
+ export declare function group({ data, ...channels }: TransformArg<T, DataRecord>, options?: GroupXOptions): {
42
+ data: DataRecord[];
43
+ };
44
+ /**
45
+ * groups the dataset by the x channel and optionally reduces the group items
46
+ * to output channels y, y1, y2, fill, stroke, r, opacity, fillOpacity, or strokeOpacity
47
+ */
48
+ export declare function groupX(input: TransformArg<T, DataRecord>, options?: GroupXOptions): {
49
+ data: DataRecord[];
50
+ };
51
+ /**
52
+ * groups the dataset by the y channel and optionally reduces the group items
53
+ * to output channels x, x1, x2, fill, stroke, r, opacity, fillOpacity, or strokeOpacity
54
+ */
55
+ export declare function groupY(input: TransformArg<T, DataRecord>, options?: GroupYOptions): {
56
+ data: DataRecord[];
57
+ };
58
+ /**
59
+ * groups the dataset by the z channel and optionally reduces the group items
60
+ * to output channels x, x1, x2, y, y1, y2, fill, stroke, r, opacity, fillOpacity,
61
+ * or strokeOpacity
62
+ */
63
+ export declare function groupZ(input: TransformArg<T, DataRecord>, options?: GroupZOptions): {
64
+ data: DataRecord[];
65
+ };
66
+ export {};
@@ -0,0 +1,109 @@
1
+ import { groupFacetsAndZ } from '../helpers/group.js';
2
+ import { testFilter } from '../helpers/index.js';
3
+ import { reduceOutputs } from '../helpers/reduce.js';
4
+ import { resolveChannel } from '../helpers/resolve.js';
5
+ import { groups as d3Groups } from 'd3-array';
6
+ import { omit } from '../helpers';
7
+ import { maybeInterval } from '../helpers/autoTicks.js';
8
+ /**
9
+ * groups the dataset by x and y channel and optionally reduces the group items
10
+ * to output channels fill, stroke, r, opacity, fillOpacity, or strokeOpacity
11
+ */
12
+ export function group({ data, ...channels }, options = {}) {
13
+ if (channels.x == null || channels.y == null)
14
+ throw new Error('you must provide an x and y channel to group on');
15
+ // group by x or y
16
+ const groups = d3Groups(data.filter((d) => testFilter(d, channels)), (d) => resolveChannel('x', d, channels), (d) => resolveChannel('y', d, channels));
17
+ const newData = [];
18
+ const xChannel = typeof channels.x === 'string' ? channels.x : '__x';
19
+ const yChannel = typeof channels.y === 'string' ? channels.y : '__y';
20
+ let newChannels = omit({ ...channels, x: xChannel, y: yChannel }, 'filter');
21
+ const outputs = ['fill', 'stroke', 'r', 'opacity', 'fillOpacity', 'strokeOpacity'];
22
+ groups.forEach(([xGroupKey, xGroups]) => {
23
+ xGroups.forEach(([yGroupKey, items]) => {
24
+ const baseRecord = { [xChannel]: xGroupKey, [yChannel]: yGroupKey }; // dim === 'z' ? {} : { [`__${dim}`]: groupKey };
25
+ // copy properties from first item of each group
26
+ options.copy?.forEach((prop) => {
27
+ baseRecord[prop] = items[0][prop];
28
+ });
29
+ const newGroupChannels = groupFacetsAndZ(items, channels, (items, itemGroupProps) => {
30
+ const item = { ...baseRecord, ...itemGroupProps };
31
+ reduceOutputs(item, items, options, outputs, channels, newChannels);
32
+ newData.push(item);
33
+ });
34
+ newChannels = { ...newChannels, ...newGroupChannels };
35
+ });
36
+ });
37
+ return { data: newData, ...newChannels };
38
+ }
39
+ /**
40
+ * groups the dataset by the x channel and optionally reduces the group items
41
+ * to output channels y, y1, y2, fill, stroke, r, opacity, fillOpacity, or strokeOpacity
42
+ */
43
+ export function groupX(input, options = {}) {
44
+ return groupXYZ('x', input, options);
45
+ }
46
+ /**
47
+ * groups the dataset by the y channel and optionally reduces the group items
48
+ * to output channels x, x1, x2, fill, stroke, r, opacity, fillOpacity, or strokeOpacity
49
+ */
50
+ export function groupY(input, options = {}) {
51
+ return groupXYZ('y', input, options);
52
+ }
53
+ /**
54
+ * groups the dataset by the z channel and optionally reduces the group items
55
+ * to output channels x, x1, x2, y, y1, y2, fill, stroke, r, opacity, fillOpacity,
56
+ * or strokeOpacity
57
+ */
58
+ export function groupZ(input, options = {}) {
59
+ return groupXYZ('z', input, options);
60
+ }
61
+ function groupXYZ(dim, { data, ...channels }, options = {}) {
62
+ if ((dim === 'z' ? channels.z || channels.fill || channels.stroke : channels[dim]) == null)
63
+ throw new Error('you must provide a channel to group on ' + dim);
64
+ const propName = options[`${dim}PropName`] != null
65
+ ? options[`${dim}PropName`]
66
+ : typeof channels[dim] === 'string' && !options.interval
67
+ ? channels[dim]
68
+ : `__${dim}`;
69
+ const interval = options.interval ? maybeInterval(options.interval) : null;
70
+ // group by x or y
71
+ const groups = dim === 'z'
72
+ ? [[null, data]]
73
+ : d3Groups(data.filter((d) => testFilter(d, channels)), (d) => {
74
+ const v = resolveChannel(dim, d, channels);
75
+ return interval ? interval.round(v) : v;
76
+ });
77
+ const newData = [];
78
+ let newChannels = omit({ ...channels }, 'filter');
79
+ if (dim !== 'z')
80
+ newChannels[dim] = propName;
81
+ const outputs = [
82
+ ...(dim === 'x'
83
+ ? ['y', 'y1', 'y2']
84
+ : dim === 'y'
85
+ ? ['x', 'x1', 'x2']
86
+ : ['x', 'x1', 'x2', 'y', 'y1', 'y2']),
87
+ 'fill',
88
+ 'stroke',
89
+ 'r',
90
+ 'opacity',
91
+ 'fillOpacity',
92
+ 'strokeOpacity'
93
+ ];
94
+ groups.forEach(([groupKey, items]) => {
95
+ const baseRecord = dim === 'z' ? {} : { [propName]: groupKey };
96
+ const newGroupChannels = groupFacetsAndZ(items, channels, (items, itemGroupProps) => {
97
+ const copiedProps = {};
98
+ // copy properties from first item of each group
99
+ options.copy?.forEach((prop) => {
100
+ copiedProps[prop] = items[0][prop];
101
+ });
102
+ const item = { ...baseRecord, ...copiedProps, ...itemGroupProps };
103
+ reduceOutputs(item, items, options, outputs, channels, newChannels);
104
+ newData.push(item);
105
+ });
106
+ newChannels = { ...newChannels, ...newGroupChannels };
107
+ });
108
+ return { data: newData, ...newChannels };
109
+ }
@@ -0,0 +1,11 @@
1
+ import type { PlotState, TransformArg } from '../types.js';
2
+ export declare function intervalX<T>(args: TransformArg<T>, { plot }: {
3
+ plot: PlotState;
4
+ }): {
5
+ data: T[];
6
+ };
7
+ export declare function intervalY<T>(args: TransformArg<T>, { plot }: {
8
+ plot: PlotState;
9
+ }): {
10
+ data: T[];
11
+ };
@@ -0,0 +1,34 @@
1
+ import { maybeInterval } from '../helpers/autoTicks.js';
2
+ import { resolveChannel } from '../helpers/resolve.js';
3
+ export function intervalX(args, { plot }) {
4
+ return interval('x', plot, args);
5
+ }
6
+ export function intervalY(args, { plot }) {
7
+ return interval('y', plot, args);
8
+ }
9
+ function interval(dim, plot, { data, ...options }) {
10
+ if (options.interval &&
11
+ options[dim] &&
12
+ options[`${dim}1`] == null &&
13
+ options[`${dim}2`] == null) {
14
+ // derive x1 and x2 from x+interval
15
+ const interval = maybeInterval(options.interval, plot.scales[dim].type);
16
+ const newData = data.map((row) => {
17
+ const val = resolveChannel(dim, row, options);
18
+ return {
19
+ ...row,
20
+ [`__${dim}1`]: interval.floor(val),
21
+ [`__${dim}2`]: interval.offset(interval.floor(val))
22
+ };
23
+ });
24
+ return {
25
+ data: newData,
26
+ // set default inset
27
+ [`inset${dim === 'x' ? 'Right' : 'Bottom'}`]: 1,
28
+ ...options,
29
+ [`${dim}1`]: `__${dim}1`,
30
+ [`${dim}2`]: `__${dim}2`
31
+ };
32
+ }
33
+ return { data, ...options };
34
+ }
File without changes
@@ -0,0 +1 @@
1
+ "use strict";