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
package/LICENSE.md ADDED
@@ -0,0 +1,5 @@
1
+ Copyright 2024, Gregor Aisch
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,38 +1,6 @@
1
- # create-svelte
1
+ # SveltePlot
2
2
 
3
- Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
3
+ SveltePlot is a visualization framework based on the [layered grammar of graphics](https://vita.had.co.nz/papers/layered-grammar.html) ideas. It's API is heavily inspired by [Observable Plot](https://github.com/observablehq/plot). Created by Gregor Aisch.
4
4
 
5
- ## Creating a project
5
+ <img src="static/logo.png" alt="SveltePlot logo" width="400" />
6
6
 
7
- If you're seeing this, you've probably already done this step. Congrats!
8
-
9
- ```bash
10
- # create a new project in the current directory
11
- npm create svelte@latest
12
-
13
- # create a new project in my-app
14
- npm create svelte@latest my-app
15
- ```
16
-
17
- ## Developing
18
-
19
- Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20
-
21
- ```bash
22
- npm run dev
23
-
24
- # or start the server and open the app in a new browser tab
25
- npm run dev -- --open
26
- ```
27
-
28
- ## Building
29
-
30
- To create a production version of your app:
31
-
32
- ```bash
33
- npm run build
34
- ```
35
-
36
- You can preview the production build with `npm run preview`.
37
-
38
- > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
@@ -0,0 +1,292 @@
1
+ <script lang="ts">
2
+ import { getContext, untrack, type Snippet } from 'svelte';
3
+
4
+ import { CHANNEL_SCALE, INDEX } from './constants.js';
5
+ import type {
6
+ ScaledChannelName,
7
+ MarkType,
8
+ DataRecord,
9
+ PlotContext,
10
+ ChannelName,
11
+ GenericMarkOptions,
12
+ ChannelAccessor,
13
+ BaseMarkProps,
14
+ FacetContext,
15
+ ScaleName,
16
+ RawValue,
17
+ ResolvedDataRecord,
18
+ ScaledDataRecord,
19
+ ScaleType
20
+ } from './types.js';
21
+ import { getUsedScales, projectXY, projectX, projectY } from './helpers/scales.js';
22
+ import { testFilter, isValid } from './helpers/index.js';
23
+ import { resolveChannel, resolveProp } from './helpers/resolve.js';
24
+
25
+ type MarkProps = {
26
+ data?: DataRecord[];
27
+ automatic?: boolean;
28
+ type: MarkType;
29
+ channels?: ScaledChannelName[];
30
+ required?: ScaledChannelName[];
31
+ requiredScales?: Partial<Record<ScaleName, ScaleType[]>>;
32
+ children?: Snippet<
33
+ [
34
+ {
35
+ mark: Mark<GenericMarkOptions>;
36
+ usedScales: ReturnType<typeof getUsedScales>;
37
+ scaledData: ScaledDataRecord[];
38
+ }
39
+ ]
40
+ >;
41
+ defaults?: Partial<Record<ScaledChannelName, RawValue>>;
42
+ } & Partial<Record<ChannelName, ChannelAccessor>> &
43
+ Partial<BaseMarkProps>;
44
+
45
+ let {
46
+ data = [],
47
+ children,
48
+ type,
49
+ channels = [],
50
+ required = [],
51
+ requiredScales = {},
52
+ defaults = {},
53
+ ...options
54
+ }: MarkProps = $props();
55
+
56
+ const channelsWithFacets: ScaledChannelName[] = $derived([...channels, 'fx', 'fy']);
57
+
58
+ const { addMark, updateMark, updatePlotState, removeMark, getTopLevelFacet, getPlotState } =
59
+ getContext<PlotContext>('svelteplot');
60
+
61
+ const plot = $derived(getPlotState());
62
+ const facet = $derived(getTopLevelFacet());
63
+
64
+ const { getFacetState } = getContext<FacetContext>('svelteplot/facet');
65
+ const { left, top } = $derived(getFacetState());
66
+
67
+ class Mark {
68
+ id;
69
+ type;
70
+ channels: ScaledChannelName[] = $state.raw([]);
71
+ scales: Set<ScaleName> = $state.raw(new Set());
72
+ data: DataRecord[] = $state.raw([]);
73
+ options: GenericMarkOptions = $state.raw({});
74
+
75
+ constructor(type: MarkType) {
76
+ this.id = Symbol();
77
+ this.type = type;
78
+ }
79
+ }
80
+
81
+ const mark = new Mark(type);
82
+
83
+ $effect(() => {
84
+ return () => {
85
+ removeMark(mark);
86
+ added = false;
87
+ };
88
+ });
89
+
90
+ // let mark2 = $state(mark);
91
+ const facetMode = $derived(options.facet || 'auto');
92
+
93
+ const optionsWithAutoFacet = $derived({
94
+ ...options,
95
+ __firstFacet: left && top,
96
+ ...(facet &&
97
+ facet.data &&
98
+ ((facetMode === 'auto' && facet.data === data) || facetMode === 'include')
99
+ ? {
100
+ fx: facet.x,
101
+ fy: facet.y
102
+ }
103
+ : {})
104
+ });
105
+
106
+ let added = false;
107
+
108
+ $effect(() => {
109
+ if (added) return;
110
+ // without using untrack() here we end up with inexplicable
111
+ // circular dependency updates resulting in a stack overflow
112
+ const channels = untrack(() => channelsWithFacets);
113
+ mark.channels = channels;
114
+ mark.scales = new Set(
115
+ channels
116
+ .filter((channel) => options[channel] !== 0)
117
+ .map((channel) => CHANNEL_SCALE[channel])
118
+ );
119
+ mark.data = untrack(() => data);
120
+ mark.options = untrack(() => optionsWithAutoFacet);
121
+ addMark(mark);
122
+ added = true;
123
+ });
124
+
125
+ const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
126
+ const testFacet = $derived(getTestFacet());
127
+
128
+ const resolvedData: ResolvedDataRecord[] = $derived(
129
+ data
130
+ .map((d, i) => ({ ...d, [INDEX]: i }))
131
+ .flatMap((row) => {
132
+ const channels = options as Record<ChannelName, ChannelAccessor>;
133
+ if (!testFacet(row, channels) || !testFilter(row, channels)) return [];
134
+ const out: ResolvedDataRecord = {
135
+ datum: row
136
+ };
137
+ for (const [channel] of Object.entries(CHANNEL_SCALE) as [
138
+ ScaledChannelName,
139
+ ScaleName
140
+ ][]) {
141
+ // check if the mark has defined an accessor for this channel
142
+ if (options?.[channel] !== undefined && out[channel] === undefined) {
143
+ // resolve value
144
+ out[channel] = resolveChannel(channel, row, options);
145
+ }
146
+ }
147
+ return [out];
148
+ })
149
+ );
150
+
151
+ let prevResolvedData: ResolvedDataRecord[] = [];
152
+
153
+ $effect(() => {
154
+ if (isDifferent(resolvedData, prevResolvedData)) {
155
+ prevResolvedData = resolvedData;
156
+ // data has changed
157
+ mark.data = data;
158
+ }
159
+ });
160
+
161
+ function isDifferent(array1: ResolvedDataRecord[], array2: ResolvedDataRecord[]) {
162
+ if (array1.length !== array2.length) return true;
163
+ for (let i = 0; i < array1.length; i++) {
164
+ for (const [channel] of Object.entries(CHANNEL_SCALE) as [
165
+ ScaledChannelName,
166
+ ScaleName
167
+ ][]) {
168
+ if (array1[i][channel] !== array2[i][channel]) return true;
169
+ }
170
+ }
171
+ return false;
172
+ }
173
+
174
+ const errors = $derived([
175
+ ...required
176
+ .filter((name) => options[name] == null)
177
+ .map((name) => `missing channel value for ${mark.type} mark: ${name}`),
178
+ ...Object.entries(requiredScales)
179
+ .filter(([scale, types]) => {
180
+ return !types.includes(plot.scales[scale].type);
181
+ })
182
+ .map(
183
+ ([scale, types]) => `scale type mismatch for ${scale} (needs ${types.join(' or ')})`
184
+ )
185
+ ]);
186
+
187
+ $effect(() => {
188
+ for (const name of required) {
189
+ if (options[name] == null) throw new Error(`missing channel value: ${name}`);
190
+ }
191
+ });
192
+
193
+ const usedScales = $derived(getUsedScales(plot, optionsWithAutoFacet, mark));
194
+ /**
195
+ * based on the data and the global scales we can now map the data
196
+ * elements to the scales
197
+ */
198
+ const scaledData = $derived(
199
+ resolvedData.flatMap((row) => {
200
+ const out: ScaledDataRecord = {
201
+ datum: row.datum,
202
+ valid: true
203
+ };
204
+ // compute dx/dy
205
+ const dx = Number(resolveProp<number>(options.dx, out.datum, 0));
206
+ const dy = Number(resolveProp<number>(options.dy, out.datum, 0));
207
+
208
+ // special handling if there's a projection, e.g. a line mark
209
+ if (plot.scales.projection && mark.type !== 'geo') {
210
+ for (const suffix of ['', '1', '2']) {
211
+ if (
212
+ options?.[`x${suffix}`] !== undefined &&
213
+ options?.[`y${suffix}`] !== undefined
214
+ ) {
215
+ // we have two-dimensional accessors
216
+ // for the x and y channels
217
+ const [x, y] =
218
+ mark.type === 'line'
219
+ ? [row.x, row.y] // line paths are projected later
220
+ : projectXY(
221
+ plot.scales,
222
+ row.x,
223
+ row.y,
224
+ usedScales.x,
225
+ usedScales.y,
226
+ suffix
227
+ );
228
+ out[`x${suffix}`] = x;
229
+ out[`y${suffix}`] = y;
230
+ out.valid = out.valid && isValid(row.x) && isValid(row.y);
231
+ }
232
+ }
233
+ }
234
+
235
+ // iterate over all scaled channels
236
+ for (const [channel, scale] of Object.entries(CHANNEL_SCALE) as [
237
+ ScaledChannelName,
238
+ ScaleName
239
+ ][]) {
240
+ // check if the mark has defined an accessor for this channel
241
+ if (options?.[channel] !== undefined && out[channel] === undefined) {
242
+ // resolve value
243
+ const value = row[channel];
244
+
245
+ const scaled = usedScales[channel]
246
+ ? scale === 'x'
247
+ ? projectX(channel as 'x' | 'x1' | 'x2', plot.scales, value)
248
+ : scale === 'y'
249
+ ? projectY(channel as 'y' | 'y1' | 'y1', plot.scales, value)
250
+ : plot.scales[scale].fn(value)
251
+ : value;
252
+
253
+ out.valid = out.valid && isValid(value);
254
+ // apply dx/dy transform
255
+ out[channel] =
256
+ scale === 'x' && Number.isFinite(scaled) ? (scaled as number) + dx : scaled;
257
+ out[channel] =
258
+ scale === 'y' && Number.isFinite(scaled) ? (scaled as number) + dy : scaled;
259
+ } else if (defaults[channel]) {
260
+ out[channel] = defaults[channel];
261
+ }
262
+ }
263
+
264
+ return [out];
265
+ })
266
+ );
267
+ </script>
268
+
269
+ {#if errors.length}
270
+ <text transform="translate(10,10)">
271
+ {#each errors as error, i}
272
+ <tspan x="0" dy={i ? 14 : 0}>{error}</tspan>
273
+ {/each}
274
+ </text>
275
+ {:else if children}
276
+ {@render children({
277
+ mark,
278
+ usedScales,
279
+ scaledData
280
+ })}
281
+ {/if}
282
+
283
+ <style>
284
+ text {
285
+ stroke: var(--plot-bg);
286
+ fill: crimson;
287
+ font-size: 11px;
288
+ stroke-width: 3px;
289
+ font-weight: bold;
290
+ paint-order: stroke fill;
291
+ }
292
+ </style>
@@ -0,0 +1,22 @@
1
+ import { type Snippet } from 'svelte';
2
+ import type { ScaledChannelName, MarkType, DataRecord, ChannelName, GenericMarkOptions, ChannelAccessor, BaseMarkProps, ScaleName, RawValue, ScaledDataRecord, ScaleType } from './types.js';
3
+ import { getUsedScales } from './helpers/scales.js';
4
+ type MarkProps = {
5
+ data?: DataRecord[];
6
+ automatic?: boolean;
7
+ type: MarkType;
8
+ channels?: ScaledChannelName[];
9
+ required?: ScaledChannelName[];
10
+ requiredScales?: Partial<Record<ScaleName, ScaleType[]>>;
11
+ children?: Snippet<[
12
+ {
13
+ mark: Mark<GenericMarkOptions>;
14
+ usedScales: ReturnType<typeof getUsedScales>;
15
+ scaledData: ScaledDataRecord[];
16
+ }
17
+ ]>;
18
+ defaults?: Partial<Record<ScaledChannelName, RawValue>>;
19
+ } & Partial<Record<ChannelName, ChannelAccessor>> & Partial<BaseMarkProps>;
20
+ declare const Mark: import("svelte").Component<MarkProps, {}, "">;
21
+ type Mark = ReturnType<typeof Mark>;
22
+ export default Mark;