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

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 +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 +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 +86 -0
  87. package/dist/marks/BarX.svelte.d.ts +4 -0
  88. package/dist/marks/BarY.svelte +98 -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 +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 +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 +14 -0
  209. package/dist/transforms/recordize.js +79 -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 +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 +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,189 @@
1
+ <script lang="ts">
2
+ import { getContext, type Snippet } from 'svelte';
3
+ import GroupMultiple from './helpers/GroupMultiple.svelte';
4
+ import type {
5
+ PlotContext,
6
+ DataRecord,
7
+ BaseMarkProps,
8
+ ConstantAccessor,
9
+ ChannelAccessor
10
+ } from '../types.js';
11
+ import { resolveProp, resolveStyles } from '../helpers/resolve.js';
12
+ import Mark from '../Mark.svelte';
13
+ import { sort } from '../index.js';
14
+
15
+ type TextMarkProps = BaseMarkProps & {
16
+ data: DataRecord[];
17
+ x: ChannelAccessor;
18
+ y: ChannelAccessor;
19
+ fill?: ChannelAccessor;
20
+ stroke?: ChannelAccessor;
21
+ children?: Snippet;
22
+ dx?: ConstantAccessor<number>;
23
+ dy?: ConstantAccessor<number>;
24
+ text: ConstantAccessor<string>;
25
+ title: ConstantAccessor<string>;
26
+ /**
27
+ * if you want to apply class names to individual text elements
28
+ */
29
+ textClass: ConstantAccessor<string>;
30
+ /**
31
+ * the line anchor for vertical position; top, bottom, or middle
32
+ */
33
+ lineAnchor?: ConstantAccessor<'bottom' | 'top' | 'middle'>;
34
+ frameAnchor?: ConstantAccessor<
35
+ | 'bottom'
36
+ | 'top'
37
+ | 'left'
38
+ | 'right'
39
+ | 'top-left'
40
+ | 'bottom-left'
41
+ | 'top-right'
42
+ | 'bottom-right'
43
+ >;
44
+ };
45
+
46
+ let { data = [{}], class: className = null, ...options }: TextMarkProps = $props();
47
+
48
+ const { getPlotState } = getContext<PlotContext>('svelteplot');
49
+ let plot = $derived(getPlotState());
50
+
51
+ const LINE_ANCHOR = {
52
+ bottom: 'auto',
53
+ middle: 'central',
54
+ top: 'hanging'
55
+ };
56
+
57
+ const args = $derived(
58
+ sort({
59
+ data,
60
+ ...options
61
+ })
62
+ );
63
+ </script>
64
+
65
+ <Mark
66
+ type="text"
67
+ channels={[
68
+ 'x',
69
+ 'y',
70
+ 'r',
71
+ 'symbol',
72
+ 'fill',
73
+ 'stroke',
74
+ 'opacity',
75
+ 'strokeOpacity',
76
+ 'fillOpacity'
77
+ ]}
78
+ {...args}>
79
+ {#snippet children({ mark, scaledData, usedScales })}
80
+ <GroupMultiple class="text {className || null}" length={className ? 2 : args.data.length}>
81
+ {#each scaledData as d}
82
+ {#if d.valid}
83
+ {@const title = resolveProp(args.title, d.datum, '')}
84
+ {@const frameAnchor = resolveProp(args.frameAnchor, d.datum)}
85
+ {@const isLeft =
86
+ frameAnchor === 'left' ||
87
+ frameAnchor === 'top-left' ||
88
+ frameAnchor === 'bottom-left'}
89
+ {@const isRight =
90
+ frameAnchor === 'right' ||
91
+ frameAnchor === 'top-right' ||
92
+ frameAnchor === 'bottom-right'}
93
+ {@const isTop =
94
+ frameAnchor === 'top' ||
95
+ frameAnchor === 'top-left' ||
96
+ frameAnchor === 'top-right'}
97
+ {@const isBottom =
98
+ frameAnchor === 'bottom' ||
99
+ frameAnchor === 'bottom-left' ||
100
+ frameAnchor === 'bottom-right'}
101
+ {@const [x, y] =
102
+ args.x != null && args.y != null
103
+ ? [d.x, d.y]
104
+ : [
105
+ args.x != null
106
+ ? d.x
107
+ : isLeft
108
+ ? plot.options.marginLeft
109
+ : isRight
110
+ ? plot.options.marginLeft + plot.facetWidth
111
+ : plot.options.marginLeft + plot.facetWidth * 0.5,
112
+ args.y != null
113
+ ? d.y
114
+ : isTop
115
+ ? plot.options.marginTop
116
+ : isBottom
117
+ ? plot.options.marginTop + plot.facetHeight
118
+ : plot.options.marginTop + plot.facetHeight * 0.5
119
+ ]}
120
+
121
+ {@const dx = +resolveProp(args.dx, d.datum, 0)}
122
+ {@const dy = +resolveProp(args.dy, d.datum, 0)}
123
+ {@const textLines = String(resolveProp(args.text, d.datum, '')).split('\n')}
124
+ {@const lineAnchor = resolveProp(
125
+ args.lineAnchor,
126
+ d.datum,
127
+ args.y != null ? 'middle' : isTop ? 'top' : isBottom ? 'bottom' : 'middle'
128
+ )}
129
+ {@const textClassName = resolveProp(args.textClass, d.datum, null)}
130
+
131
+ {@const [style, styleClass] = resolveStyles(
132
+ plot,
133
+ { ...d, __tspanIndex: 0 },
134
+ {
135
+ fontSize: 12,
136
+ fontWeight: 500,
137
+ strokeWidth: 1.6,
138
+ textAnchor: isLeft ? 'start' : isRight ? 'end' : 'middle',
139
+ ...args
140
+ },
141
+ 'fill',
142
+ usedScales
143
+ )}
144
+
145
+ {#if textLines.length > 1}
146
+ <!-- multiline text-->
147
+ {@const fontSize = resolveProp(args.fontSize, d.datum) || 12}
148
+ <text
149
+ class={[textClassName]}
150
+ dominant-baseline={LINE_ANCHOR[lineAnchor]}
151
+ transform="translate({[
152
+ Math.round(x + dx),
153
+ Math.round(
154
+ y +
155
+ dy -
156
+ (lineAnchor === 'bottom'
157
+ ? textLines.length - 1
158
+ : lineAnchor === 'middle'
159
+ ? (textLines.length - 1) * 0.5
160
+ : 0) *
161
+ fontSize
162
+ )
163
+ ]})"
164
+ >{#each textLines as line, l}<tspan
165
+ x="0"
166
+ dy={l ? fontSize : 0}
167
+ class={styleClass}
168
+ {style}>{line}</tspan
169
+ >{/each}{#if title}<title>{title}</title>{/if}</text>
170
+ {:else}
171
+ <!-- singleline text-->
172
+ <text
173
+ class={[textClassName, styleClass]}
174
+ dominant-baseline={LINE_ANCHOR[lineAnchor]}
175
+ transform="translate({[Math.round(x + dx), Math.round(y + dy)]})"
176
+ {style}
177
+ >{textLines[0]}{#if title}<title>{title}</title>{/if}</text>
178
+ {/if}
179
+ {/if}
180
+ {/each}
181
+ </GroupMultiple>
182
+ {/snippet}
183
+ </Mark>
184
+
185
+ <style>
186
+ text {
187
+ paint-order: stroke fill;
188
+ }
189
+ </style>
@@ -0,0 +1,26 @@
1
+ import { type Snippet } from 'svelte';
2
+ import type { DataRecord, BaseMarkProps, ConstantAccessor, ChannelAccessor } from '../types.js';
3
+ type TextMarkProps = BaseMarkProps & {
4
+ data: DataRecord[];
5
+ x: ChannelAccessor;
6
+ y: ChannelAccessor;
7
+ fill?: ChannelAccessor;
8
+ stroke?: ChannelAccessor;
9
+ children?: Snippet;
10
+ dx?: ConstantAccessor<number>;
11
+ dy?: ConstantAccessor<number>;
12
+ text: ConstantAccessor<string>;
13
+ title: ConstantAccessor<string>;
14
+ /**
15
+ * if you want to apply class names to individual text elements
16
+ */
17
+ textClass: ConstantAccessor<string>;
18
+ /**
19
+ * the line anchor for vertical position; top, bottom, or middle
20
+ */
21
+ lineAnchor?: ConstantAccessor<'bottom' | 'top' | 'middle'>;
22
+ frameAnchor?: ConstantAccessor<'bottom' | 'top' | 'left' | 'right' | 'top-left' | 'bottom-left' | 'top-right' | 'bottom-right'>;
23
+ };
24
+ declare const Text: import("svelte").Component<TextMarkProps, {}, "">;
25
+ type Text = ReturnType<typeof Text>;
26
+ export default Text;
@@ -0,0 +1,89 @@
1
+ <script lang="ts">
2
+ import Mark from '../Mark.svelte';
3
+ import { getContext } from 'svelte';
4
+ import { resolveChannel, resolveProp, resolveScaledStyles } from '../helpers/resolve.js';
5
+ import type {
6
+ PlotContext,
7
+ BaseMarkProps,
8
+ ChannelAccessor,
9
+ DataRow,
10
+ FacetContext
11
+ } from '../types.js';
12
+ import { recordizeX } from '../index.js';
13
+ import { projectX, projectY } from '../helpers/scales.js';
14
+ import { isValid } from '../helpers/isValid.js';
15
+ import { testFilter, parseInset } from '../helpers/index.js';
16
+
17
+ const { getPlotState } = getContext<PlotContext>('svelteplot');
18
+ let plot = $derived(getPlotState());
19
+
20
+ type TickXMarkProps = BaseMarkProps & {
21
+ data: DataRow[];
22
+ /**
23
+ * the horizontal position; bound to the x scale
24
+ */
25
+ x?: ChannelAccessor;
26
+ /**
27
+ * the vertical position; bound to the y scale, which must be band. If the y channel
28
+ * is not specified, the tick will span the full vertical extent of the frame.
29
+ */
30
+ y?: ChannelAccessor;
31
+ stroke?: ChannelAccessor;
32
+ /**
33
+ * if ticks are used on a non-bandwidth scale, this will determine the
34
+ * length of the tick. Defaults to 10 pixel
35
+ */
36
+ tickLength?: ConstantAccessor<number>;
37
+ };
38
+
39
+ let { data = [{}], ...options }: TickXMarkProps = $props();
40
+
41
+ let args = $derived(recordizeX({ data, ...options }, { withIndex: false }));
42
+
43
+ const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
44
+ let testFacet = $derived(getTestFacet());
45
+ </script>
46
+
47
+ <Mark type="tickX" channels={['x', 'y', 'stroke', 'opacity', 'strokeOpacity']} {...args}>
48
+ {#snippet children({ mark, usedScales })}
49
+ <g class="tick-x">
50
+ {#each args.data as datum}
51
+ {#if testFacet(datum, mark.options) && testFilter(datum, args)}
52
+ {@const x_ = resolveChannel('x', datum, args)}
53
+ {@const y_ = resolveChannel('y', datum, args)}
54
+ {@const inset_ = resolveProp(args.inset, datum, 0)}
55
+ {@const tickLength_ = resolveProp(args.tickLength, datum, 10)}
56
+ {@const dx_ = resolveProp(args.dx, datum, 0)}
57
+ {@const dy_ = resolveProp(args.dy, datum, 0)}
58
+ {#if isValid(x_) && (isValid(y_) || args.y == null) && (args.filter == null || resolveProp(args.filter, datum))}
59
+ {@const x = usedScales.x ? projectX('x', plot.scales, x_) : x_}
60
+ {@const y1 =
61
+ args.y != null
62
+ ? usedScales.y
63
+ ? projectY('y1', plot.scales, y_)
64
+ : y_
65
+ : plot.options.marginTop}
66
+ {@const y2 =
67
+ args.y != null
68
+ ? usedScales.y
69
+ ? Number(projectY('y2', plot.scales, y_))
70
+ : y_
71
+ : plot.options.marginTop + plot.plotHeight}
72
+ {@const inset = parseInset(inset_, Math.abs(y2 - y1))}
73
+ <line
74
+ transform="translate({x + dx_}, {dy_})"
75
+ style={resolveScaledStyles(datum, args, usedScales, plot, 'stroke')}
76
+ y1={y1 + inset + (y1 === y2 ? tickLength_ * 0.5 : 0)}
77
+ y2={y2 - inset - (y1 === y2 ? tickLength_ * 0.5 : 0)} />
78
+ {/if}
79
+ {/if}
80
+ {/each}
81
+ </g>
82
+ {/snippet}
83
+ </Mark>
84
+
85
+ <style>
86
+ .tick-x line {
87
+ stroke: currentColor;
88
+ }
89
+ </style>
@@ -0,0 +1,22 @@
1
+ import type { BaseMarkProps, ChannelAccessor, DataRow } from '../types.js';
2
+ type TickXMarkProps = BaseMarkProps & {
3
+ data: DataRow[];
4
+ /**
5
+ * the horizontal position; bound to the x scale
6
+ */
7
+ x?: ChannelAccessor;
8
+ /**
9
+ * the vertical position; bound to the y scale, which must be band. If the y channel
10
+ * is not specified, the tick will span the full vertical extent of the frame.
11
+ */
12
+ y?: ChannelAccessor;
13
+ stroke?: ChannelAccessor;
14
+ /**
15
+ * if ticks are used on a non-bandwidth scale, this will determine the
16
+ * length of the tick. Defaults to 10 pixel
17
+ */
18
+ tickLength?: ConstantAccessor<number>;
19
+ };
20
+ declare const TickX: import("svelte").Component<TickXMarkProps, {}, "">;
21
+ type TickX = ReturnType<typeof TickX>;
22
+ export default TickX;
@@ -0,0 +1,90 @@
1
+ <script lang="ts">
2
+ import Mark from '../Mark.svelte';
3
+ import { getContext } from 'svelte';
4
+ import { resolveChannel, resolveProp, resolveScaledStyles } from '../helpers/resolve.js';
5
+ import type {
6
+ PlotContext,
7
+ BaseMarkProps,
8
+ ChannelAccessor,
9
+ DataRow,
10
+ FacetContext,
11
+ ConstantAccessor
12
+ } from '../types.js';
13
+ import { recordizeY } from '../index.js';
14
+ import { projectX, projectY } from '../helpers/scales.js';
15
+ import { isValid } from '../helpers/isValid.js';
16
+ import { testFilter, parseInset } from '../helpers/index.js';
17
+
18
+ const { getPlotState } = getContext<PlotContext>('svelteplot');
19
+ let plot = $derived(getPlotState());
20
+
21
+ type TickYMarkProps = BaseMarkProps & {
22
+ data: DataRow[];
23
+ /**
24
+ * the vertical position; bound to the x scale
25
+ */
26
+ y?: ChannelAccessor;
27
+ /**
28
+ * the horizontal position; bound to the x scale, which must be band. If the x channel
29
+ * is not specified, the tick will span the full horizontal extent of the frame.
30
+ */
31
+ x?: ChannelAccessor;
32
+ stroke?: ChannelAccessor;
33
+ /**
34
+ * if ticks are used on a non-bandwidth scale, this will determine the
35
+ * length of the tick. Defaults to 10 pixel
36
+ */
37
+ tickLength?: ConstantAccessor<number>;
38
+ };
39
+
40
+ let { data = [{}], ...options }: TickYMarkProps = $props();
41
+
42
+ let args = $derived(recordizeY({ data, ...options }, { withIndex: false }));
43
+
44
+ const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
45
+ let testFacet = $derived(getTestFacet());
46
+ </script>
47
+
48
+ <Mark type="tickY" channels={['x', 'y', 'stroke', 'opacity', 'strokeOpacity']} {...args}>
49
+ {#snippet children({ mark, usedScales })}
50
+ <g class="tick-y">
51
+ {#each args.data as datum}
52
+ {#if testFacet(datum, mark.options) && testFilter(datum, args)}
53
+ {@const y_ = resolveChannel('y', datum, args)}
54
+ {@const x_ = resolveChannel('x', datum, args)}
55
+ {@const inset_ = resolveProp(args.inset, datum, 0)}
56
+ {@const tickLength_ = resolveProp(args.tickLength, datum, 10)}
57
+ {@const dx_ = resolveProp(args.dx, datum, 0)}
58
+ {@const dy_ = resolveProp(args.dy, datum, 0)}
59
+ {#if isValid(y_) && (isValid(x_) || args.x == null)}
60
+ {@const y = usedScales.y ? projectY('y', plot.scales, y_) : y_}
61
+ {@const x1 =
62
+ args.x != null
63
+ ? usedScales.x
64
+ ? projectX('x1', plot.scales, x_)
65
+ : x_
66
+ : plot.options.marginLeft}
67
+ {@const x2 =
68
+ args.x != null
69
+ ? usedScales.x
70
+ ? projectX('x2', plot.scales, x_)
71
+ : x_
72
+ : plot.options.marginLeft + plot.facetWidth}
73
+ {@const inset = parseInset(inset_, Math.abs(x2 - x1))}
74
+ <line
75
+ transform="translate({dx_}, {y + dy_})"
76
+ style={resolveScaledStyles(datum, args, usedScales, plot, 'stroke')}
77
+ x1={x1 + inset + (x1 === x2 ? tickLength_ * 0.5 : 0)}
78
+ x2={x2 - inset - (x1 === x2 ? tickLength_ * 0.5 : 0)} />
79
+ {/if}
80
+ {/if}
81
+ {/each}
82
+ </g>
83
+ {/snippet}
84
+ </Mark>
85
+
86
+ <style>
87
+ .tick-y line {
88
+ stroke: currentColor;
89
+ }
90
+ </style>
@@ -0,0 +1,22 @@
1
+ import type { BaseMarkProps, ChannelAccessor, DataRow, ConstantAccessor } from '../types.js';
2
+ type TickYMarkProps = BaseMarkProps & {
3
+ data: DataRow[];
4
+ /**
5
+ * the vertical position; bound to the x scale
6
+ */
7
+ y?: ChannelAccessor;
8
+ /**
9
+ * the horizontal position; bound to the x scale, which must be band. If the x channel
10
+ * is not specified, the tick will span the full horizontal extent of the frame.
11
+ */
12
+ x?: ChannelAccessor;
13
+ stroke?: ChannelAccessor;
14
+ /**
15
+ * if ticks are used on a non-bandwidth scale, this will determine the
16
+ * length of the tick. Defaults to 10 pixel
17
+ */
18
+ tickLength?: ConstantAccessor<number>;
19
+ };
20
+ declare const TickY: import("svelte").Component<TickYMarkProps, {}, "">;
21
+ type TickY = ReturnType<typeof TickY>;
22
+ export default TickY;
@@ -0,0 +1,219 @@
1
+ <script lang="ts" module>
2
+ import type {
3
+ PlotContext,
4
+ DataRecord,
5
+ BaseMarkProps,
6
+ ConstantAccessor,
7
+ ChannelAccessor,
8
+ FacetContext
9
+ } from '../types.js';
10
+
11
+ type D3Path = ReturnType<typeof import('d3-path').path>;
12
+
13
+ export type ShapeRenderer = {
14
+ draw(context: D3Path, l: number, r: number): void;
15
+ };
16
+
17
+ export type VectorMarkProps = BaseMarkProps & {
18
+ data: DataRecord[];
19
+ x: ChannelAccessor;
20
+ y: ChannelAccessor;
21
+ r?: number;
22
+ length?: ChannelAccessor;
23
+ rotate?: ChannelAccessor;
24
+ fill?: ChannelAccessor;
25
+ stroke?: ChannelAccessor;
26
+ /**
27
+ * Controls where the vector is anchored in relation to the x, y position.
28
+ * If set to 'start', the arrow will start at the x, y position. If set to
29
+ * 'middle', the arrow will be centered at the x, y position. If set to
30
+ * 'end', the arrow will end at the x, y position.
31
+ */
32
+ anchor: 'start' | 'middle' | 'end';
33
+ shape?: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer;
34
+ children?: Snippet;
35
+ dx?: ConstantAccessor<number>;
36
+ dy?: ConstantAccessor<number>;
37
+ canvas?: boolean;
38
+ };
39
+ </script>
40
+
41
+ <script lang="ts">
42
+ import { getContext, type Snippet } from 'svelte';
43
+ import { pathRound as path } from 'd3-path';
44
+
45
+ import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
46
+ import { projectXY } from '../helpers/scales.js';
47
+ import { sort } from '../index.js';
48
+ import Mark from '../Mark.svelte';
49
+ //import DotCanvas from './helpers/DotCanvas.svelte';
50
+ import { maybeData, testFilter, isValid } from '../helpers/index.js';
51
+ import { addEventHandlers } from './helpers/events.js';
52
+
53
+ const defaultRadius = 3.5;
54
+
55
+ // The size of the arrowhead is proportional to its length, but we still allow
56
+ // the relative size of the head to be controlled via the mark’s width option;
57
+ // doubling the default radius will produce an arrowhead that is twice as big.
58
+ // That said, we’ll probably want a arrow with a fixed head size, too.
59
+ const wingRatio = defaultRadius * 5;
60
+
61
+ let {
62
+ data = [{}],
63
+ canvas,
64
+ shape = 'arrow',
65
+ anchor = 'middle',
66
+ r = defaultRadius,
67
+ ...options
68
+ }: VectorMarkProps = $props();
69
+
70
+ const { getPlotState } = getContext<PlotContext>('svelteplot');
71
+ const plot = $derived(getPlotState());
72
+
73
+ const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
74
+ const testFacet = $derived(getTestFacet());
75
+
76
+ const shapeArrow: ShapeRenderer = {
77
+ draw(context: D3Path, l: number, r: number) {
78
+ const wing = (l * r) / wingRatio;
79
+ context.moveTo(0, 0);
80
+ context.lineTo(0, -l);
81
+ context.moveTo(-wing, wing - l);
82
+ context.lineTo(0, -l);
83
+ context.lineTo(wing, wing - l);
84
+ }
85
+ };
86
+
87
+ const shapeSpike: ShapeRenderer = {
88
+ draw(context: D3Path, l: number, r: number) {
89
+ context.moveTo(-r, 0);
90
+ context.lineTo(0, -l);
91
+ context.lineTo(r, 0);
92
+ }
93
+ };
94
+
95
+ const shapeArrowFilled: ShapeRenderer = {
96
+ draw(context: D3Path, l: number, r: number) {
97
+ // const wing = (l * r) / wingRatio;
98
+ const headLength = Math.max(3, l * 0.3);
99
+ const headSpike = headLength * 0.2;
100
+ const headWidth = Math.max(2, l * 0.3);
101
+ const tailWidth = Math.max(2, l * 0.3) * 0.3;
102
+
103
+ context.moveTo(0, 0);
104
+
105
+ context.lineTo(tailWidth * 0.5, -l + headLength - headSpike);
106
+ context.lineTo(headWidth * 0.5, -l + headLength);
107
+ context.lineTo(0, -l);
108
+ context.lineTo(-headWidth * 0.5, -l + headLength);
109
+ context.lineTo(-tailWidth * 0.5, -l + headLength - headSpike);
110
+
111
+ context.closePath();
112
+ }
113
+ };
114
+
115
+ const shapes = new Map([
116
+ ['arrow', shapeArrow],
117
+ ['arrow-filled', shapeArrowFilled],
118
+ ['spike', shapeSpike]
119
+ ]);
120
+
121
+ function isShapeObject(value: any): value is ShapeRenderer {
122
+ return value && typeof value.draw === 'function';
123
+ }
124
+
125
+ function maybeShape(shape: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer) {
126
+ if (isShapeObject(shape)) return shape;
127
+ const value = shapes.get(`${shape}`.toLowerCase());
128
+ if (value) return value;
129
+ throw new Error(`invalid shape: ${shape}`);
130
+ }
131
+
132
+ function shapePath(
133
+ shape: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer,
134
+ l: number,
135
+ r: number
136
+ ) {
137
+ const context = path();
138
+ maybeShape(shape).draw(context, l, r);
139
+ return context.toString();
140
+ }
141
+
142
+ const args = $derived(
143
+ sort({
144
+ data: maybeData(data),
145
+ // sort by descending radius by default
146
+ ...options
147
+ })
148
+ );
149
+ </script>
150
+
151
+ <Mark
152
+ type="vector"
153
+ required={['x', 'y']}
154
+ channels={[
155
+ 'x',
156
+ 'y',
157
+ 'r',
158
+ 'length',
159
+ 'symbol',
160
+ 'fill',
161
+ 'opacity',
162
+ 'stroke',
163
+ 'fillOpacity',
164
+ 'strokeOpacity'
165
+ ]}
166
+ {...args}>
167
+ {#snippet children({ mark, scaledData, usedScales })}
168
+ <g class="vector" data-l={usedScales.length}>
169
+ {#if canvas}
170
+ <text x="30" y="30" style="color:red"
171
+ >implement canvas rendering for vector mark</text>
172
+ {:else}
173
+ {#each scaledData as d}
174
+ {@const r = resolveChannel('r', d.datum, { r: 3, ...args })}
175
+ {#if d.valid && isValid(r)}
176
+ {@const dx = +resolveProp(args.dx, d.datum, 0)}
177
+ {@const dy = +resolveProp(args.dx, d.datum, 0)}
178
+ {@const [style, styleClass] = resolveStyles(
179
+ plot,
180
+ d,
181
+ {
182
+ strokeWidth: 1.5,
183
+ strokeLinejoin: 'round',
184
+ strokeLinecap: 'round',
185
+ ...args
186
+ },
187
+ shape === 'arrow-filled' ? 'fill' : 'stroke',
188
+ usedScales
189
+ )}
190
+ <path
191
+ d={shapePath(shape, d.length, r)}
192
+ transform="translate({d.x + dx}, {d.y + dy}) rotate({resolveProp(
193
+ args.rotate,
194
+ d.datum,
195
+ 0
196
+ )}) {anchor === 'start'
197
+ ? ''
198
+ : anchor === 'end'
199
+ ? `translate(0, ${d.length})`
200
+ : `translate(0, ${d.length / 2})`}"
201
+ {style}
202
+ use:addEventHandlers={{
203
+ getPlotState,
204
+ options: args,
205
+ datum: d.datum
206
+ }}
207
+ class={[styleClass]} />
208
+ {/if}
209
+ {/each}
210
+ {/if}
211
+ </g>
212
+ {/snippet}
213
+ </Mark>
214
+
215
+ <style>
216
+ path {
217
+ stroke-width: 1.5px;
218
+ }
219
+ </style>