svelteplot 0.0.1-alpha.9 → 0.1.3-next.12

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 -35
  3. package/dist/Mark.svelte +292 -0
  4. package/dist/Mark.svelte.d.ts +22 -0
  5. package/dist/Plot.svelte +148 -156
  6. package/dist/Plot.svelte.d.ts +15 -15
  7. package/dist/constants.d.ts +15 -0
  8. package/dist/constants.js +110 -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 +568 -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 +55 -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 +21 -0
  63. package/dist/helpers/resolve.js +156 -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 +311 -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 +93 -0
  87. package/dist/marks/BarX.svelte.d.ts +4 -0
  88. package/dist/marks/BarY.svelte +103 -0
  89. package/dist/marks/BarY.svelte.d.ts +25 -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 +39 -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 +180 -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 +189 -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 +219 -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 +141 -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 +74 -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 +1 -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 +15 -0
  209. package/dist/transforms/recordize.js +78 -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 +66 -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 +24 -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 +81 -42
  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,100 @@
1
+ import { geoClipRectangle, geoPath, geoTransform } from 'd3-geo';
2
+ import { constant, isObject, isValid } from './index.js';
3
+ const identity = constant({ stream: (stream) => stream });
4
+ const defaultAspectRatio = 0.618;
5
+ export function createProjection({ projOptions, inset: globalInset = 2, insetTop = globalInset, insetRight = globalInset, insetBottom = globalInset, insetLeft = globalInset } = {}, dimensions) {
6
+ // no projection defined
7
+ if (projOptions == null)
8
+ return;
9
+ // projection function passed as projection option
10
+ if (typeof projOptions.stream === 'function')
11
+ return projOptions; // d3 projection
12
+ let options;
13
+ let domain;
14
+ let clip = 'frame';
15
+ // If the projection was specified as an object with additional options,
16
+ // extract those. The order of precedence for insetTop (and other insets) is:
17
+ // projection.insetTop, projection.inset, (global) insetTop, (global) inset.
18
+ // Any other options on this object will be passed through to the initializer.
19
+ if (isObject(projOptions)) {
20
+ let inset;
21
+ ({
22
+ type: projOptions,
23
+ domain,
24
+ inset,
25
+ insetTop = inset !== undefined ? inset : insetTop,
26
+ insetRight = inset !== undefined ? inset : insetRight,
27
+ insetBottom = inset !== undefined ? inset : insetBottom,
28
+ insetLeft = inset !== undefined ? inset : insetLeft,
29
+ clip = clip,
30
+ ...options
31
+ } = projOptions);
32
+ if (projOptions == null)
33
+ return;
34
+ }
35
+ // let projFactory;
36
+ let aspectRatio = defaultAspectRatio;
37
+ const projFactory = projOptions;
38
+ // Compute the frame dimensions and invoke the projection initializer.
39
+ const { width, height, marginLeft, marginRight, marginTop, marginBottom } = dimensions;
40
+ const dx = width - marginLeft - marginRight - insetLeft - insetRight;
41
+ const dy = height - marginTop - marginBottom - insetTop - insetBottom;
42
+ const projInstance = projFactory?.({ width: dx, height: dy, clip, ...options });
43
+ // The projection initializer might decide to not use a projection.
44
+ if (projInstance == null)
45
+ return;
46
+ clip = maybePostClip(clip, marginLeft, marginTop, width - marginRight, height - marginBottom);
47
+ // Translate the origin to the top-left corner, respecting margins and insets.
48
+ let tx = marginLeft + insetLeft;
49
+ let ty = marginTop + insetTop;
50
+ let transform;
51
+ let invertTransform = (d) => d;
52
+ // If a domain is specified, fit the projection to the frame.
53
+ if (domain != null) {
54
+ const [[x0, y0], [x1, y1]] = geoPath(projInstance).bounds(domain);
55
+ const k = Math.min(dx / (x1 - x0), dy / (y1 - y0));
56
+ aspectRatio = (y1 - y0) / (x1 - x0);
57
+ // aspectRatio = 1/k;
58
+ if (k > 0) {
59
+ tx -= (k * (x0 + x1) - dx) / 2;
60
+ ty -= (k * (y0 + y1) - dy) / 2;
61
+ transform = geoTransform({
62
+ point(x, y) {
63
+ this.stream.point(x * k + tx, y * k + ty);
64
+ }
65
+ });
66
+ invertTransform = ([x, y]) => [(x - tx) / k, (y - ty) / k];
67
+ }
68
+ else {
69
+ throw new Error(`Warning: the projection could not be fit to the specified domain; using the default scale.`);
70
+ }
71
+ }
72
+ transform ??=
73
+ tx === 0 && ty === 0
74
+ ? identity()
75
+ : geoTransform({
76
+ point(x, y) {
77
+ this.stream.point(x + tx, y + ty);
78
+ }
79
+ });
80
+ invertTransform ??= ([x, y]) => [x - tx, y - ty];
81
+ return {
82
+ aspectRatio,
83
+ invert([x, y]) {
84
+ return projInstance.invert(invertTransform([x, y]));
85
+ },
86
+ stream: (s) => projInstance.stream(transform.stream(clip(s)))
87
+ };
88
+ }
89
+ function maybePostClip(clip, x1, y1, x2, y2) {
90
+ if (clip === false || clip == null || typeof clip === 'number')
91
+ return (s) => s;
92
+ if (clip === true)
93
+ clip = 'frame';
94
+ switch (`${clip}`.toLowerCase()) {
95
+ case 'frame':
96
+ return geoClipRectangle(x1, y1, x2, y2);
97
+ default:
98
+ throw new Error(`unknown projection clip type: ${clip}`);
99
+ }
100
+ }
@@ -0,0 +1,10 @@
1
+ import type { ChannelName, Channels, DataRecord, DataRow, RawValue } from '../types.js';
2
+ type ReducerFunc = (group: Iterable<DataRow>) => RawValue;
3
+ type ReducerOption = ReducerName | ReducerFunc;
4
+ type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
5
+ export type ReducerPercentile = (`p${Digit}${Digit}` & Record<never, never>) | 'p25' | 'p50' | 'p75';
6
+ export type ReducerName = 'count' | 'deviation' | 'difference' | 'first' | 'last' | 'max' | 'mean' | 'median' | 'min' | 'mode' | 'ratio' | 'sum' | 'variance' | ReducerPercentile;
7
+ export declare const Reducer: Record<ReducerName, ReducerFunc>;
8
+ export declare function mayberReducer(r: ReducerOption): ReducerFunc;
9
+ export declare function reduceOutputs(newDatum: DataRecord, data: DataRecord[], options: Record<ChannelName, ReducerOption>, outputs: Iterable<ChannelName>, channels: Channels, newChannels: Channels): void;
10
+ export {};
@@ -0,0 +1,85 @@
1
+ import { min, max, mode, sum, mean, median, variance, deviation, quantile, range } from 'd3-array';
2
+ import { resolveChannel } from './resolve.js';
3
+ import { POSITION_CHANNELS } from './index.js';
4
+ const niceReduceNames = {
5
+ count: 'Frequency',
6
+ deviation: 'Standard Deviation',
7
+ mean: 'Average'
8
+ };
9
+ const StaticReducer = {
10
+ count: (d) => Array.from(d).length,
11
+ min,
12
+ max,
13
+ mode,
14
+ sum,
15
+ mean,
16
+ median,
17
+ identity: (d) => d,
18
+ variance,
19
+ deviation,
20
+ first: (d) => d[0],
21
+ last: (d) => d.at(-1),
22
+ difference: (d) => d.at(-1) - d[0],
23
+ ratio: (d) => d.at(-1) / d[0]
24
+ // TODO: proportion
25
+ // TODO: proportion-facet
26
+ // TODO: min-index
27
+ // TODO: max-index
28
+ };
29
+ // use proxy to allow for percentile reducers
30
+ export const Reducer = new Proxy(StaticReducer, {
31
+ get(target, prop) {
32
+ if (String(prop).charAt(0) === 'p' && String(prop).length === 3) {
33
+ const p = +String(prop).slice(1) / 100;
34
+ return percentile(p);
35
+ }
36
+ return Reflect.get(target, prop);
37
+ },
38
+ has(target, prop) {
39
+ if (String(prop).charAt(0) === 'p' && String(prop).length === 3) {
40
+ return true;
41
+ }
42
+ return Reflect.has(target, prop);
43
+ }
44
+ });
45
+ function percentile(p) {
46
+ return (I, f) => quantile(I, p, f);
47
+ }
48
+ function isReducerName(r) {
49
+ return typeof r === 'string' && r in Reducer;
50
+ }
51
+ export function mayberReducer(r) {
52
+ if (typeof r === 'function')
53
+ return r;
54
+ if (typeof r === 'string' && isReducerName(r)) {
55
+ return Reducer[r];
56
+ }
57
+ throw new Error('unknown reducer ' + r);
58
+ }
59
+ export function reduceOutputs(newDatum, data, options, outputs, channels, newChannels) {
60
+ for (const k of outputs) {
61
+ if (options[k] != null) {
62
+ const values = channels[k] == null ? data : data.map((d) => resolveChannel(k, d, channels));
63
+ const reducer = mayberReducer(options[k]);
64
+ newDatum[`__${k}`] = reducer(values);
65
+ newChannels[k] = `__${k}`;
66
+ if (typeof options[k] === 'string') {
67
+ const reducerName = niceReduceNames[options[k]] ??
68
+ `${String(options[k]).charAt(0).toUpperCase()}${String(options[k]).slice(1)}`;
69
+ // we have a named reducer like 'count', so let's try to preserve the
70
+ // source channel mapping for axis labels
71
+ if (POSITION_CHANNELS.has(k)) {
72
+ if (typeof channels[k] === 'string') {
73
+ // the named reducer is applied to a column name, so we can use a combination
74
+ // of both as axis labels, e.g. MEAN(weight)
75
+ // eslint-disable-next-line no-irregular-whitespace
76
+ newChannels[`__${k}_origField`] = `${reducerName} ( ${channels[k]} )`;
77
+ }
78
+ else {
79
+ newChannels[`__${k}_origField`] = reducerName;
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,12 @@
1
+ import type { DataRow } from '../types.js';
2
+ type AccessorFn = (d: any) => number;
3
+ export default function (): {
4
+ (data: DataRow[]): {
5
+ predict(x: number): any;
6
+ predictMany(x: number[]): any;
7
+ };
8
+ x(_: AccessorFn): void;
9
+ y(_: AccessorFn): void;
10
+ span(_: number): void;
11
+ };
12
+ export {};
@@ -0,0 +1,47 @@
1
+ import Loess from 'loess';
2
+ function toNumber(d) {
3
+ if (typeof d.getTime === 'function')
4
+ return d.getTime();
5
+ return d;
6
+ }
7
+ export default function () {
8
+ let accessX = (d) => d[0];
9
+ let accessY = (d) => d[1];
10
+ let span = 0.75;
11
+ // const degree = 2;
12
+ const fn = (data) => {
13
+ const filteredData = data
14
+ .map((d) => ({
15
+ x: toNumber(accessX(d)),
16
+ y: accessY(d)
17
+ }))
18
+ .filter((d) => Number.isFinite(d.x) && Number.isFinite(d.y));
19
+ // .sort((a,b) => a.x - b.x);
20
+ // compute loess regression for data
21
+ const model = new Loess({
22
+ x: filteredData.map((d) => d.x),
23
+ y: filteredData.map((d) => d.y)
24
+ }, { span: Math.max(0.1, span), iterations: 2 });
25
+ // return;
26
+ return {
27
+ predict(x) {
28
+ const fit = model.predict({ x: [toNumber(x)] });
29
+ return fit.fitted[0];
30
+ },
31
+ predictMany(x) {
32
+ const fit = model.predict({ x: x.map(toNumber) });
33
+ return fit.fitted;
34
+ }
35
+ };
36
+ };
37
+ fn.x = (_) => {
38
+ accessX = _;
39
+ };
40
+ fn.y = (_) => {
41
+ accessY = _;
42
+ };
43
+ fn.span = (_) => {
44
+ span = _;
45
+ };
46
+ return fn;
47
+ }
@@ -1 +1,8 @@
1
- export default function removeIdenticalLines(input: string[][]): string[][];
1
+ type Tick = {
2
+ text: string[];
3
+ };
4
+ /**
5
+ * Remove identical lines from a set of ticks
6
+ */
7
+ export default function removeIdenticalLines(input: Tick[]): Tick[];
8
+ export {};
@@ -1,16 +1,23 @@
1
+ /**
2
+ * Remove identical lines from a set of ticks
3
+ */
1
4
  export default function removeIdenticalLines(input) {
2
- const uniqueLines = [];
5
+ const uniqueTicks = [];
3
6
  if (!input.length)
4
7
  return input;
5
8
  for (let c = 0; c < input.length; c++) {
6
- uniqueLines.push([]);
9
+ // initialize new tick array with empty text lines
10
+ uniqueTicks.push({
11
+ ...input[c],
12
+ text: []
13
+ });
7
14
  }
8
- for (let l = 0; l < input[0].length; l++) {
9
- const isIdentical = input.every((value) => input[0][l] === value[l]);
15
+ for (let l = 0; l < input[0].text.length; l++) {
16
+ const isIdentical = input.length > 1 && input.every((tick) => input[0].text[l] === tick.text[l]);
10
17
  for (let c = 0; c < input.length; c++) {
11
- if (!isIdentical)
12
- uniqueLines[c].push(input[c][l]);
18
+ if (!isIdentical && input[c].text[l])
19
+ uniqueTicks[c].text.push(input[c].text[l]);
13
20
  }
14
21
  }
15
- return uniqueLines;
22
+ return uniqueTicks;
16
23
  }
@@ -0,0 +1,21 @@
1
+ import type { MarkStyleProps, PlotState, ScaledDataRecord } from '../types.js';
2
+ import type { ScaleName, ChannelName, ScaledChannelName, ChannelAccessor, DataRow, RawValue, DataRecord, ConstantAccessor } from '../types.js';
3
+ type ChannelAlias = {
4
+ channel: ScaledChannelName;
5
+ };
6
+ export declare function resolveProp<T>(accessor: ConstantAccessor<T>, datum: DataRecord | null, _defaultValue?: T | null): T | null;
7
+ type ChannelOptions = {
8
+ value: ChannelAccessor;
9
+ scale?: ScaleName | null;
10
+ channel?: ScaledChannelName | null;
11
+ };
12
+ export declare function toChannelOption(name: ScaledChannelName, channel: ChannelAccessor | ChannelAlias): ChannelOptions;
13
+ export declare function resolveChannel(channel: ChannelName, datum: DataRow, channels: Partial<Record<ChannelName, ChannelAccessor | ChannelAlias>>): RawValue;
14
+ export declare function resolveScaledStyleProps(datum: DataRecord, channels: Partial<Record<ScaledChannelName, ChannelAccessor>>, useScale: Record<ScaledChannelName, boolean>, plot: PlotState, defaultColorProp?: 'fill' | 'stroke' | null): any;
15
+ export declare function resolveScaledStyles(datum: DataRecord, channels: Partial<Record<ScaledChannelName, ChannelAccessor> & {
16
+ style: string;
17
+ }>, useScale: Record<ScaledChannelName, boolean>, plot: PlotState, defaultColorProp?: 'fill' | 'stroke' | null): string;
18
+ export declare function resolveStyles(plot: PlotState, datum: ScaledDataRecord, channels: Partial<Record<ChannelName & MarkStyleProps, ChannelAccessor> & {
19
+ style: string;
20
+ }>, defaultColorProp: "fill" | "stroke" | null | undefined, useScale: Record<ScaledChannelName, boolean>, recomputeChannels?: boolean): [string | null, string | null];
21
+ export {};
@@ -0,0 +1,156 @@
1
+ import { CHANNEL_SCALE } from '../constants.js';
2
+ import isDataRecord from './isDataRecord.js';
3
+ import isRawValue from './isRawValue.js';
4
+ import { isValid } from './isValid.js';
5
+ import { pick } from 'es-toolkit';
6
+ import { getBaseStylesObject } from './getBaseStyles.js';
7
+ export function resolveProp(accessor, datum, _defaultValue = null) {
8
+ if (typeof accessor === 'function') {
9
+ // datum.___orig___ exists if an array of raw values was used as dataset and got
10
+ // "recordized" by the recordize transform. We want to hide this wrapping to the user
11
+ // so we're passing the original value to accessor functions instead of our wrapped record
12
+ return datum == null
13
+ ? accessor()
14
+ : accessor(datum.___orig___ != null ? datum.___orig___ : datum);
15
+ }
16
+ else if (typeof accessor === 'string' && datum && datum[accessor] !== undefined) {
17
+ return datum[accessor];
18
+ }
19
+ return isRawValue(accessor) ? accessor : _defaultValue;
20
+ }
21
+ export function toChannelOption(name, channel) {
22
+ const isPositionScale = CHANNEL_SCALE[name] === 'x' || CHANNEL_SCALE[name] === 'y';
23
+ const isOpacityScale = CHANNEL_SCALE[name] === 'opacity';
24
+ return isDataRecord(channel)
25
+ ? channel
26
+ : {
27
+ value: channel,
28
+ scale: (!isPositionScale && !isOpacityScale && typeof channel === 'number') ||
29
+ typeof channel === 'undefined'
30
+ ? null
31
+ : CHANNEL_SCALE[name],
32
+ channel: null
33
+ };
34
+ }
35
+ export function resolveChannel(channel, datum, channels) {
36
+ const scale = CHANNEL_SCALE[channel];
37
+ // the z channel has an automatic alias mechanism
38
+ const accessor = channel === 'z' ? channels.z || channels.fill || channels.stroke : channels[channel];
39
+ const channelOptions = toChannelOption(channel, accessor);
40
+ if (channelOptions.channel) {
41
+ return resolveChannel(channelOptions.channel, datum, channels);
42
+ }
43
+ return resolve(datum, channelOptions.value, channel, scale);
44
+ }
45
+ function resolve(datum, accessor, channel, scale) {
46
+ if (isDataRecord(datum)) {
47
+ // use accessor function
48
+ if (typeof accessor === 'function')
49
+ // datum.___orig___ exists if an array of raw values was used as dataset and got
50
+ // "recordized" by the recordize transform. We want to hide this wrapping to the user
51
+ // so we're passing the original value to accessor functions instead of our wrapped record
52
+ return accessor(datum.___orig___ != null ? datum.___orig___ : datum);
53
+ // use accessor string
54
+ if (typeof accessor === 'string' && datum[accessor] !== undefined)
55
+ return datum[accessor];
56
+ // fallback to channel name as accessor
57
+ if (accessor === null && datum[channel] !== undefined)
58
+ return datum[channel];
59
+ return isRawValue(accessor) ? accessor : null;
60
+ }
61
+ else if (Array.isArray(datum) &&
62
+ (typeof accessor === 'string' || typeof accessor === 'number') &&
63
+ datum[accessor] != null) {
64
+ return datum[accessor];
65
+ }
66
+ else {
67
+ // return single value or accessor
68
+ return typeof accessor === 'function'
69
+ ? accessor(datum)
70
+ : accessor !== null && isRawValue(accessor)
71
+ ? accessor
72
+ : !Array.isArray(datum) && (scale === 'x' || scale === 'y')
73
+ ? datum
74
+ : null;
75
+ }
76
+ }
77
+ const scaledStyleProps = {
78
+ fill: 'fill',
79
+ stroke: 'stroke',
80
+ fillOpacity: 'fill-opacity',
81
+ strokeOpacity: 'stroke-opacity',
82
+ opacity: 'opacity'
83
+ };
84
+ const scaledStylePropsKeys = Object.keys(scaledStyleProps);
85
+ // TODO: find a better name
86
+ const oppositeColor = {
87
+ fill: 'stroke',
88
+ stroke: 'fill'
89
+ };
90
+ export function resolveScaledStyleProps(datum, channels, useScale, plot, defaultColorProp = null) {
91
+ return {
92
+ ...getBaseStylesObject(datum, channels),
93
+ fill: 'none',
94
+ stroke: 'none',
95
+ ...(defaultColorProp && channels[oppositeColor[defaultColorProp]] == null
96
+ ? { [defaultColorProp]: 'currentColor' }
97
+ : {}),
98
+ ...Object.fromEntries(Object.entries(scaledStyleProps)
99
+ .filter(([key]) => channels[key] != null)
100
+ .map(([key, cssAttr]) => [key, cssAttr, resolveChannel(key, datum, channels)])
101
+ .filter(([key, , value]) => isValid(value) || key === 'fill' || key === 'stroke')
102
+ .map(([key, cssAttr, value]) => {
103
+ if (useScale[key]) {
104
+ if (value == undefined &&
105
+ (key === 'fill' || key === 'stroke') &&
106
+ plot.options.color.unknown) {
107
+ return [cssAttr, plot.options.color.unknown];
108
+ }
109
+ return [cssAttr, plot.scales[CHANNEL_SCALE[key]].fn(value)];
110
+ }
111
+ return [cssAttr, value];
112
+ }))
113
+ };
114
+ }
115
+ export function resolveScaledStyles(datum, channels, useScale, plot, defaultColorProp = null) {
116
+ return `${stylePropsToCSS(resolveScaledStyleProps(datum, channels, useScale, plot, defaultColorProp))};${channels.style || ''}`;
117
+ }
118
+ function stylePropsToCSS(props) {
119
+ return `${Object.entries(props)
120
+ .map(([key, value]) => `${key}: ${value}`)
121
+ .join(';')}`;
122
+ }
123
+ export function resolveStyles(plot, datum, channels, defaultColorProp = null, useScale, recomputeChannels = false) {
124
+ const styleProps = {
125
+ ...getBaseStylesObject(datum.datum, channels),
126
+ fill: 'none',
127
+ stroke: 'none',
128
+ ...(defaultColorProp && channels[oppositeColor[defaultColorProp]] == null
129
+ ? { [defaultColorProp]: 'currentColor' }
130
+ : {}),
131
+ ...Object.fromEntries(Object.entries(scaledStyleProps)
132
+ .filter(([key]) => channels[key] != null)
133
+ .map(([key, cssAttr]) => [
134
+ key,
135
+ cssAttr,
136
+ recomputeChannels ? resolveChannel(key, datum.datum, channels) : datum[key]
137
+ ])
138
+ .filter(([key, , value]) => isValid(value) || key === 'fill' || key === 'stroke')
139
+ .map(([key, cssAttr, value]) => {
140
+ if (useScale[key]) {
141
+ if (value == undefined &&
142
+ (key === 'fill' || key === 'stroke') &&
143
+ plot.options.color.unknown) {
144
+ return [cssAttr, plot.options.color.unknown];
145
+ }
146
+ }
147
+ return [cssAttr, value];
148
+ }))
149
+ };
150
+ if (plot.css) {
151
+ return [null, plot.css(`${stylePropsToCSS(styleProps)};${channels.style ?? ''}`)];
152
+ }
153
+ else {
154
+ return [`${stylePropsToCSS(styleProps)};${channels.style ?? ''}`, null];
155
+ }
156
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ *
3
+ */
4
+ export declare function roundedRect(x: number, y: number, width: number, height: number, borderRadius?: number | {
5
+ topLeft?: number;
6
+ topRight?: number;
7
+ bottomLeft?: number;
8
+ bottomRight?: number;
9
+ }): string;
@@ -0,0 +1,31 @@
1
+ /**
2
+ *
3
+ */
4
+ export function roundedRect(x, y, width, height, borderRadius = {
5
+ topLeft: 0,
6
+ topRight: 0,
7
+ bottomLeft: 0,
8
+ bottomRight: 0
9
+ }) {
10
+ const maxRadius = Math.min(width, height) / 2;
11
+ const [tl, tr, bl, br] = (typeof borderRadius === 'number'
12
+ ? new Array(4).fill(borderRadius)
13
+ : [
14
+ borderRadius?.topLeft || 0,
15
+ borderRadius?.topRight || 0,
16
+ borderRadius?.bottomLeft || 0,
17
+ borderRadius?.bottomRight || 0
18
+ ]).map((r) => Math.min(r, maxRadius));
19
+ return `
20
+ M ${x + tl} ${y}
21
+ H ${x + width - tr}
22
+ ${tr ? `A ${tr} ${tr} 0 0 1 ${x + width} ${y + tr}` : ''}
23
+ V ${y + height - br}
24
+ ${br ? `A ${br} ${br} 0 0 1 ${x + width - br} ${y + height}` : ''}
25
+ H ${x + bl}
26
+ ${bl ? `A ${bl} ${bl} 0 0 1 ${x} ${y + height - bl}` : ''}
27
+ V ${y + tl}
28
+ ${tl ? `A ${tl} ${tl} 0 0 1 ${x + tl} ${y}` : ''}
29
+ Z
30
+ `;
31
+ }
@@ -0,0 +1,42 @@
1
+ import type { ChannelAccessor, GenericMarkOptions, Mark, MarkType, PlotDefaults, PlotOptions, PlotScales, PlotState, RawValue, ScaleName, ScaleOptions, ScaleType, ScaledChannelName } from '../types.js';
2
+ /**
3
+ * compute the plot scales
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;
8
+ domain: number[];
9
+ range: number[];
10
+ fn: (() => string) | (() => number);
11
+ skip: Map<any, any>;
12
+ isDummy: boolean;
13
+ manualActiveMarks?: undefined;
14
+ uniqueScaleProps?: undefined;
15
+ autoTitle?: undefined;
16
+ } | {
17
+ type: ScaleType;
18
+ domain: RawValue[] | [undefined, undefined];
19
+ range: any;
20
+ fn: any;
21
+ skip: Map<ScaledChannelName, Set<symbol>>;
22
+ manualActiveMarks: number;
23
+ uniqueScaleProps: Set<ChannelAccessor>;
24
+ autoTitle: string | null;
25
+ isDummy?: undefined;
26
+ };
27
+ /**
28
+ * Infer a scale type based on the scale name, the data values mapped to it and
29
+ * the mark types that are bound to the scale
30
+ */
31
+ export declare function inferScaleType(name: ScaleName, dataValues: RawValue[], markTypes: Set<MarkType>): ScaleType;
32
+ /**
33
+ * Mark channels can explicitely or implicitely be exempt from being
34
+ * mapped to a scale, so everywhere where values are being mapped to
35
+ * scales, we need to check if the the scale is supposed to be used
36
+ * not. That's what this function is used for.
37
+ */
38
+ export declare function getUsedScales(plot: PlotState, options: GenericMarkOptions, mark: Mark<GenericMarkOptions>): { [k in ScaledChannelName]: boolean; };
39
+ export declare function looksLikeANumber(input: string | number): boolean;
40
+ export declare function projectXY(scales: PlotScales, x: RawValue, y: RawValue, useXScale?: boolean, useYScale?: boolean): [number, number];
41
+ export declare function projectX(channel: 'x' | 'x1' | 'x2', scales: PlotScales, value: RawValue): number;
42
+ export declare function projectY(channel: 'y' | 'y1' | 'y2', scales: PlotScales, value: RawValue): number;