layerchart 2.0.0-next.1 → 2.0.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/dist/actions/movable.d.ts +28 -0
  2. package/dist/actions/movable.js +91 -0
  3. package/dist/components/AnnotationLine.svelte +143 -0
  4. package/dist/components/AnnotationLine.svelte.d.ts +30 -0
  5. package/dist/components/AnnotationPoint.svelte +119 -0
  6. package/dist/components/AnnotationPoint.svelte.d.ts +34 -0
  7. package/dist/components/AnnotationRange.svelte +147 -0
  8. package/dist/components/AnnotationRange.svelte.d.ts +40 -0
  9. package/dist/components/Arc.svelte +344 -151
  10. package/dist/components/Arc.svelte.d.ts +138 -0
  11. package/dist/components/Area.svelte +165 -149
  12. package/dist/components/Area.svelte.d.ts +45 -0
  13. package/dist/components/Axis.svelte +283 -180
  14. package/dist/components/Axis.svelte.d.ts +117 -0
  15. package/dist/components/Bar.svelte +166 -107
  16. package/dist/components/Bar.svelte.d.ts +51 -0
  17. package/dist/components/Bars.svelte +56 -67
  18. package/dist/components/Bars.svelte.d.ts +27 -0
  19. package/dist/components/Blur.svelte +42 -12
  20. package/dist/components/Blur.svelte.d.ts +23 -21
  21. package/dist/components/Bounds.svelte +49 -19
  22. package/dist/components/Bounds.svelte.d.ts +24 -50
  23. package/dist/components/BrushContext.svelte +296 -168
  24. package/dist/components/BrushContext.svelte.d.ts +97 -65
  25. package/dist/components/Calendar.svelte +116 -59
  26. package/dist/components/Calendar.svelte.d.ts +50 -31
  27. package/dist/components/Chart.svelte +1289 -398
  28. package/dist/components/Chart.svelte.d.ts +535 -410
  29. package/dist/components/ChartClipPath.svelte +37 -15
  30. package/dist/components/ChartClipPath.svelte.d.ts +21 -19
  31. package/dist/components/Circle.svelte +124 -85
  32. package/dist/components/Circle.svelte.d.ts +52 -0
  33. package/dist/components/CircleClipPath.svelte +76 -16
  34. package/dist/components/CircleClipPath.svelte.d.ts +46 -0
  35. package/dist/components/ClipPath.svelte +71 -21
  36. package/dist/components/ClipPath.svelte.d.ts +40 -27
  37. package/dist/components/ColorRamp.svelte +75 -9
  38. package/dist/components/ColorRamp.svelte.d.ts +37 -19
  39. package/dist/components/ComputedStyles.svelte +17 -5
  40. package/dist/components/ComputedStyles.svelte.d.ts +11 -19
  41. package/dist/components/Connector.svelte +149 -0
  42. package/dist/components/Connector.svelte.d.ts +51 -0
  43. package/dist/components/Dagre.svelte +211 -122
  44. package/dist/components/Dagre.svelte.d.ts +119 -56
  45. package/dist/components/ForceSimulation.svelte +215 -90
  46. package/dist/components/ForceSimulation.svelte.d.ts +82 -35
  47. package/dist/components/Frame.svelte +33 -13
  48. package/dist/components/Frame.svelte.d.ts +13 -17
  49. package/dist/components/GeoCircle.svelte +29 -16
  50. package/dist/components/GeoCircle.svelte.d.ts +22 -24
  51. package/dist/components/GeoContext.svelte +113 -72
  52. package/dist/components/GeoContext.svelte.d.ts +49 -41
  53. package/dist/components/GeoEdgeFade.svelte +49 -13
  54. package/dist/components/GeoEdgeFade.svelte.d.ts +17 -19
  55. package/dist/components/GeoPath.svelte +157 -127
  56. package/dist/components/GeoPath.svelte.d.ts +48 -36
  57. package/dist/components/GeoPoint.svelte +52 -20
  58. package/dist/components/GeoPoint.svelte.d.ts +25 -22
  59. package/dist/components/GeoSpline.svelte +75 -26
  60. package/dist/components/GeoSpline.svelte.d.ts +29 -20
  61. package/dist/components/GeoTile.svelte +100 -49
  62. package/dist/components/GeoTile.svelte.d.ts +38 -23
  63. package/dist/components/GeoVisible.svelte +17 -9
  64. package/dist/components/GeoVisible.svelte.d.ts +10 -18
  65. package/dist/components/Graticule.svelte +30 -14
  66. package/dist/components/Graticule.svelte.d.ts +11 -52
  67. package/dist/components/Grid.svelte +230 -117
  68. package/dist/components/Grid.svelte.d.ts +71 -0
  69. package/dist/components/Group.svelte +173 -106
  70. package/dist/components/Group.svelte.d.ts +81 -0
  71. package/dist/components/Highlight.svelte +410 -308
  72. package/dist/components/Highlight.svelte.d.ts +107 -0
  73. package/dist/components/Hull.svelte +97 -46
  74. package/dist/components/Hull.svelte.d.ts +40 -30
  75. package/dist/components/Labels.svelte +127 -47
  76. package/dist/components/Labels.svelte.d.ts +70 -27
  77. package/dist/components/Legend.svelte +374 -190
  78. package/dist/components/Legend.svelte.d.ts +95 -44
  79. package/dist/components/Line.svelte +163 -125
  80. package/dist/components/Line.svelte.d.ts +75 -0
  81. package/dist/components/LinearGradient.svelte +153 -78
  82. package/dist/components/LinearGradient.svelte.d.ts +66 -31
  83. package/dist/components/Link.svelte +160 -104
  84. package/dist/components/Link.svelte.d.ts +54 -0
  85. package/dist/components/Marker.svelte +100 -39
  86. package/dist/components/Marker.svelte.d.ts +59 -27
  87. package/dist/components/MarkerWrapper.svelte +35 -0
  88. package/dist/components/MarkerWrapper.svelte.d.ts +18 -0
  89. package/dist/components/MonthPath.svelte +65 -20
  90. package/dist/components/MonthPath.svelte.d.ts +23 -17
  91. package/dist/components/MotionPath.svelte +80 -24
  92. package/dist/components/MotionPath.svelte.d.ts +46 -27
  93. package/dist/components/Pack.svelte +53 -17
  94. package/dist/components/Pack.svelte.d.ts +42 -21
  95. package/dist/components/Partition.svelte +64 -22
  96. package/dist/components/Partition.svelte.d.ts +49 -26
  97. package/dist/components/Pattern.svelte +297 -11
  98. package/dist/components/Pattern.svelte.d.ts +103 -19
  99. package/dist/components/Pie.svelte +122 -76
  100. package/dist/components/Pie.svelte.d.ts +65 -51
  101. package/dist/components/Point.svelte +20 -9
  102. package/dist/components/Point.svelte.d.ts +16 -20
  103. package/dist/components/Points.svelte +148 -137
  104. package/dist/components/Points.svelte.d.ts +45 -34
  105. package/dist/components/RadialGradient.svelte +143 -70
  106. package/dist/components/RadialGradient.svelte.d.ts +69 -31
  107. package/dist/components/Rect.svelte +121 -102
  108. package/dist/components/Rect.svelte.d.ts +36 -0
  109. package/dist/components/RectClipPath.svelte +82 -18
  110. package/dist/components/RectClipPath.svelte.d.ts +55 -0
  111. package/dist/components/Rule.svelte +107 -63
  112. package/dist/components/Rule.svelte.d.ts +40 -19
  113. package/dist/components/Sankey.svelte +132 -55
  114. package/dist/components/Sankey.svelte.d.ts +61 -31
  115. package/dist/components/Spline.svelte +281 -218
  116. package/dist/components/Spline.svelte.d.ts +95 -0
  117. package/dist/components/Text.svelte +437 -176
  118. package/dist/components/Text.svelte.d.ts +130 -0
  119. package/dist/components/Threshold.svelte +48 -16
  120. package/dist/components/Threshold.svelte.d.ts +29 -31
  121. package/dist/components/TileImage.svelte +103 -30
  122. package/dist/components/TileImage.svelte.d.ts +48 -23
  123. package/dist/components/TransformContext.svelte +365 -171
  124. package/dist/components/TransformControls.svelte +50 -26
  125. package/dist/components/TransformControls.svelte.d.ts +27 -19
  126. package/dist/components/Tree.svelte +74 -33
  127. package/dist/components/Tree.svelte.d.ts +42 -30
  128. package/dist/components/Treemap.svelte +119 -42
  129. package/dist/components/Treemap.svelte.d.ts +75 -27
  130. package/dist/components/Voronoi.svelte +108 -76
  131. package/dist/components/Voronoi.svelte.d.ts +40 -41
  132. package/dist/components/charts/ArcChart.svelte +464 -0
  133. package/dist/components/charts/ArcChart.svelte.d.ts +90 -0
  134. package/dist/components/charts/AreaChart.svelte +450 -393
  135. package/dist/components/charts/AreaChart.svelte.d.ts +61 -0
  136. package/dist/components/charts/BarChart.svelte +454 -389
  137. package/dist/components/charts/BarChart.svelte.d.ts +76 -0
  138. package/dist/components/charts/ChartAnnotations.svelte +37 -0
  139. package/dist/components/charts/ChartAnnotations.svelte.d.ts +10 -0
  140. package/dist/components/charts/DefaultTooltip.svelte +60 -0
  141. package/dist/components/charts/DefaultTooltip.svelte.d.ts +10 -0
  142. package/dist/components/charts/LineChart.svelte +369 -314
  143. package/dist/components/charts/LineChart.svelte.d.ts +53 -0
  144. package/dist/components/charts/PieChart.svelte +458 -316
  145. package/dist/components/charts/PieChart.svelte.d.ts +137 -353
  146. package/dist/components/charts/ScatterChart.svelte +334 -296
  147. package/dist/components/charts/ScatterChart.svelte.d.ts +39 -0
  148. package/dist/components/charts/index.d.ts +8 -0
  149. package/dist/components/charts/index.js +7 -0
  150. package/dist/components/charts/types.d.ts +253 -0
  151. package/dist/components/charts/utils.svelte.d.ts +30 -0
  152. package/dist/components/charts/utils.svelte.js +55 -0
  153. package/dist/components/index.d.ts +76 -4
  154. package/dist/components/index.js +76 -5
  155. package/dist/components/layout/Canvas.svelte +321 -155
  156. package/dist/components/layout/Canvas.svelte.d.ts +104 -55
  157. package/dist/components/layout/Html.svelte +82 -42
  158. package/dist/components/layout/Html.svelte.d.ts +39 -28
  159. package/dist/components/layout/Layer.svelte +39 -0
  160. package/dist/components/layout/Layer.svelte.d.ts +17 -0
  161. package/dist/components/layout/Svg.svelte +122 -70
  162. package/dist/components/layout/Svg.svelte.d.ts +53 -34
  163. package/dist/components/layout/WebGL.svelte +135 -0
  164. package/dist/components/layout/WebGL.svelte.d.ts +50 -0
  165. package/dist/components/tooltip/Tooltip.svelte +246 -78
  166. package/dist/components/tooltip/Tooltip.svelte.d.ts +149 -31
  167. package/dist/components/tooltip/TooltipContext.svelte +409 -271
  168. package/dist/components/tooltip/TooltipContext.svelte.d.ts +86 -55
  169. package/dist/components/tooltip/TooltipHeader.svelte +100 -11
  170. package/dist/components/tooltip/TooltipHeader.svelte.d.ts +43 -23
  171. package/dist/components/tooltip/TooltipItem.svelte +167 -27
  172. package/dist/components/tooltip/TooltipItem.svelte.d.ts +63 -31
  173. package/dist/components/tooltip/TooltipList.svelte +22 -3
  174. package/dist/components/tooltip/TooltipList.svelte.d.ts +6 -17
  175. package/dist/components/tooltip/TooltipSeparator.svelte +27 -1
  176. package/dist/components/tooltip/TooltipSeparator.svelte.d.ts +6 -15
  177. package/dist/components/tooltip/index.d.ts +6 -0
  178. package/dist/components/tooltip/index.js +6 -0
  179. package/dist/components/tooltip/tooltipMetaContext.d.ts +79 -0
  180. package/dist/components/tooltip/tooltipMetaContext.js +139 -0
  181. package/dist/components/types.d.ts +1 -0
  182. package/dist/components/types.js +1 -0
  183. package/dist/docs/Blockquote.svelte.d.ts +18 -14
  184. package/dist/docs/Code.svelte.d.ts +26 -22
  185. package/dist/docs/ConnectorSweepMenuField.svelte +17 -0
  186. package/dist/docs/ConnectorSweepMenuField.svelte.d.ts +7 -0
  187. package/dist/docs/ConnectorTypeMenuField.svelte +17 -0
  188. package/dist/docs/ConnectorTypeMenuField.svelte.d.ts +7 -0
  189. package/dist/docs/CurveMenuField.svelte +14 -3
  190. package/dist/docs/CurveMenuField.svelte.d.ts +9 -18
  191. package/dist/docs/GeoDebug.svelte +47 -42
  192. package/dist/docs/GeoDebug.svelte.d.ts +4 -16
  193. package/dist/docs/Header1.svelte.d.ts +27 -16
  194. package/dist/docs/Json.svelte.d.ts +20 -16
  195. package/dist/docs/Layout.svelte.d.ts +18 -13
  196. package/dist/docs/Link.svelte.d.ts +33 -21
  197. package/dist/docs/PathDataMenuField.svelte +14 -10
  198. package/dist/docs/PathDataMenuField.svelte.d.ts +8 -18
  199. package/dist/docs/Preview.svelte +20 -7
  200. package/dist/docs/Preview.svelte.d.ts +12 -22
  201. package/dist/docs/TilesetField.svelte.d.ts +21 -17
  202. package/dist/docs/TransformDebug.svelte +5 -6
  203. package/dist/docs/TransformDebug.svelte.d.ts +18 -14
  204. package/dist/docs/ViewSourceButton.svelte.d.ts +21 -17
  205. package/dist/types/d3-shape-extentions.d.ts +7 -0
  206. package/dist/utils/afterTick.d.ts +5 -0
  207. package/dist/utils/afterTick.js +8 -0
  208. package/dist/utils/arcText.svelte.d.ts +57 -0
  209. package/dist/utils/arcText.svelte.js +262 -0
  210. package/dist/utils/array.d.ts +9 -1
  211. package/dist/utils/array.js +13 -0
  212. package/dist/utils/attributes.d.ts +29 -0
  213. package/dist/utils/attributes.js +40 -0
  214. package/dist/utils/canvas.js +47 -10
  215. package/dist/utils/chart.d.ts +78 -0
  216. package/dist/utils/chart.js +512 -0
  217. package/dist/utils/color.d.ts +1 -0
  218. package/dist/utils/color.js +8 -0
  219. package/dist/utils/common.d.ts +3 -5
  220. package/dist/utils/common.js +3 -2
  221. package/dist/utils/connectorUtils.d.ts +21 -0
  222. package/dist/utils/connectorUtils.js +111 -0
  223. package/dist/utils/createId.d.ts +7 -0
  224. package/dist/utils/createId.js +9 -0
  225. package/dist/utils/debug.d.ts +1 -0
  226. package/dist/utils/debug.js +84 -0
  227. package/dist/utils/filterObject.d.ts +9 -0
  228. package/dist/utils/filterObject.js +12 -0
  229. package/dist/utils/graph/dagre.d.ts +34 -0
  230. package/dist/utils/graph/dagre.js +78 -0
  231. package/dist/utils/graph/dagre.test.d.ts +1 -0
  232. package/dist/utils/{graph.test.js → graph/dagre.test.js} +19 -33
  233. package/dist/utils/graph/sankey.d.ts +28 -0
  234. package/dist/utils/{graph.js → graph/sankey.js} +13 -41
  235. package/dist/utils/index.d.ts +3 -1
  236. package/dist/utils/index.js +3 -1
  237. package/dist/utils/key.svelte.d.ts +3 -0
  238. package/dist/utils/key.svelte.js +11 -0
  239. package/dist/utils/legendPayload.d.ts +7 -0
  240. package/dist/utils/legendPayload.js +8 -0
  241. package/dist/utils/motion.svelte.d.ts +140 -0
  242. package/dist/utils/motion.svelte.js +180 -0
  243. package/dist/utils/motion.test.d.ts +1 -0
  244. package/dist/utils/motion.test.js +213 -0
  245. package/dist/utils/{rect.d.ts → rect.svelte.d.ts} +7 -4
  246. package/dist/utils/rect.svelte.js +105 -0
  247. package/dist/utils/scales.svelte.d.ts +90 -0
  248. package/dist/utils/{scales.js → scales.svelte.js} +100 -39
  249. package/dist/utils/stack.d.ts +2 -3
  250. package/dist/utils/stack.js +1 -1
  251. package/dist/utils/string.js +87 -0
  252. package/dist/utils/ticks.d.ts +8 -2
  253. package/dist/utils/ticks.js +28 -0
  254. package/dist/utils/ticks.test.d.ts +1 -0
  255. package/dist/utils/ticks.test.js +67 -0
  256. package/dist/utils/types.d.ts +81 -0
  257. package/package.json +21 -19
  258. package/dist/components/ChartContext.svelte +0 -295
  259. package/dist/components/ChartContext.svelte.d.ts +0 -139
  260. package/dist/components/TransformContext.svelte.d.ts +0 -158
  261. package/dist/stores/motionStore.d.ts +0 -30
  262. package/dist/stores/motionStore.js +0 -62
  263. package/dist/utils/graph.d.ts +0 -37
  264. package/dist/utils/rect.js +0 -107
  265. package/dist/utils/scales.d.ts +0 -66
  266. /package/dist/{utils/graph.test.d.ts → components/charts/types.js} +0 -0
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Reactive utilities to create and position text for Arc-based labels/annotations.
3
+ *
4
+ * TODO: we can probably simplify / pull some of these pieces out to not do a bunch
5
+ * of extra work when we don't need to. But for now while we work on the API, this is fine :)
6
+ */
7
+ import type { Getter, GetterValues } from './types.js';
8
+ import type { ComponentProps } from 'svelte';
9
+ import type { Text } from '../components/index.js';
10
+ export type ArcTextProps = GetterValues<{
11
+ innerRadius: number;
12
+ outerRadius: number;
13
+ cornerRadius: number;
14
+ startAngle: number;
15
+ endAngle: number;
16
+ centroid: [number, number];
17
+ }>;
18
+ export type InternalArcTextProps = ArcTextProps & {
19
+ /**
20
+ * Whether the corner radius should be inverted or not.
21
+ * This changes when text is rotated/flipped to ensure
22
+ * the corner offset is applied correctly.
23
+ */
24
+ invertCorner: Getter<boolean>;
25
+ };
26
+ export type ArcPathResult = {
27
+ current: string;
28
+ };
29
+ export type ArcTextPosition = 'inner' | 'outer' | 'middle' | 'centroid' | 'outer-radial';
30
+ export type ArcTextOptions = {
31
+ /**
32
+ * A percentage string (e.g., '50%') to offset the start angle of the text path.
33
+ * If a specific offset is needed, you should use option rather than passing it
34
+ * directly to the `<Text>` component to ensure it is taken into account when
35
+ * calculating the path the text should follow.
36
+ *
37
+ * This has no effect if the position is `'centroid'`.
38
+ */
39
+ startOffset?: string;
40
+ /**
41
+ * An amount of padding to add to the outer radius of the path to add space
42
+ * between the text and the arc.
43
+ */
44
+ outerPadding?: number;
45
+ /**
46
+ * Optional offset specifically for 'outer-radial' position from the outer arc edge.
47
+ * If not provided, 'outerPadding' will be used.
48
+ *
49
+ * // TODO: does 23 even make sense? It looks good but is it too arbitrary? needs sean's attention
50
+ * Defaults to 23 if neither is set.
51
+ */
52
+ radialOffset?: number;
53
+ };
54
+ export declare function createArcTextProps(props: ArcTextProps, opts: ArcTextOptions | undefined, position: ArcTextPosition): {
55
+ current: ComponentProps<typeof Text>;
56
+ };
57
+ export type GetArcTextProps = (position: ArcTextPosition, opts?: ArcTextOptions) => ComponentProps<typeof Text>;
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Reactive utilities to create and position text for Arc-based labels/annotations.
3
+ *
4
+ * TODO: we can probably simplify / pull some of these pieces out to not do a bunch
5
+ * of extra work when we don't need to. But for now while we work on the API, this is fine :)
6
+ */
7
+ import { arc as d3arc } from 'd3-shape';
8
+ import { radiansToDegrees } from './math.js';
9
+ function extractOutsideArc(arcPath) {
10
+ // Extract first arc until straight line to innerRadius (L) or close path (Z)
11
+ const matches = arcPath.match(/(^.+?)(L|Z)/);
12
+ if (!matches || !matches[1])
13
+ return arcPath;
14
+ return matches[1];
15
+ }
16
+ // Normalize angles to [0, 360) range
17
+ function normalizeAngle(angle) {
18
+ return ((angle % 360) + 360) % 360;
19
+ }
20
+ /**
21
+ * Calculates and generates a path in the middle/medial line of an arc.
22
+ */
23
+ function getArcPathMiddle(props) {
24
+ const centerRadius = $derived((props.innerRadius() + props.outerRadius()) / 2);
25
+ const cornerAngleOffset = $derived.by(() => {
26
+ if (props.cornerRadius() <= 0 || centerRadius <= 0)
27
+ return 0;
28
+ const effectiveCornerRadius = Math.min(props.cornerRadius(), centerRadius);
29
+ return (effectiveCornerRadius * 0.5) / centerRadius;
30
+ });
31
+ const effectiveStartAngle = $derived.by(() => {
32
+ if (props.invertCorner()) {
33
+ return props.startAngle() - cornerAngleOffset;
34
+ }
35
+ return props.startAngle() + cornerAngleOffset;
36
+ });
37
+ const effectiveEndAngle = $derived.by(() => {
38
+ if (props.invertCorner()) {
39
+ return props.endAngle() + cornerAngleOffset;
40
+ }
41
+ return props.endAngle() - cornerAngleOffset;
42
+ });
43
+ const path = $derived(extractOutsideArc(d3arc()
44
+ .outerRadius(centerRadius)
45
+ .innerRadius(centerRadius - 0.5)
46
+ .startAngle(effectiveStartAngle)
47
+ .endAngle(effectiveEndAngle)() ?? ''));
48
+ return {
49
+ get current() {
50
+ return path;
51
+ },
52
+ };
53
+ }
54
+ function getArcPathInner(props) {
55
+ const cornerAngleOffset = $derived.by(() => {
56
+ if (props.cornerRadius() <= 0 || props.innerRadius() <= 0)
57
+ return 0;
58
+ if (props.cornerRadius() >= props.innerRadius())
59
+ return Math.PI / 4;
60
+ return (props.cornerRadius() * 0.5) / props.innerRadius();
61
+ });
62
+ const effectiveStartAngle = $derived.by(() => {
63
+ if (props.invertCorner()) {
64
+ return props.startAngle() - cornerAngleOffset;
65
+ }
66
+ return props.startAngle() + cornerAngleOffset;
67
+ });
68
+ const effectiveEndAngle = $derived.by(() => {
69
+ if (props.invertCorner()) {
70
+ return props.endAngle() + cornerAngleOffset;
71
+ }
72
+ return props.endAngle() - cornerAngleOffset;
73
+ });
74
+ const path = $derived(extractOutsideArc(d3arc()
75
+ .innerRadius(props.innerRadius())
76
+ .outerRadius(props.innerRadius() + 0.5)
77
+ .startAngle(effectiveStartAngle)
78
+ .endAngle(effectiveEndAngle)() ?? ''));
79
+ return {
80
+ get current() {
81
+ return path;
82
+ },
83
+ };
84
+ }
85
+ function getArcPathOuter(props) {
86
+ const cornerAngleOffset = $derived.by(() => {
87
+ if (props.cornerRadius() <= 0 || props.outerRadius() <= 0)
88
+ return 0;
89
+ return (props.cornerRadius() * 0.5) / props.outerRadius();
90
+ });
91
+ const effectiveStartAngle = $derived.by(() => {
92
+ if (props.invertCorner()) {
93
+ return props.startAngle() - cornerAngleOffset;
94
+ }
95
+ return props.startAngle() + cornerAngleOffset;
96
+ });
97
+ const effectiveEndAngle = $derived.by(() => {
98
+ if (props.invertCorner()) {
99
+ return props.endAngle() + cornerAngleOffset;
100
+ }
101
+ return props.endAngle() - cornerAngleOffset;
102
+ });
103
+ const path = $derived(extractOutsideArc(d3arc()
104
+ .innerRadius(props.outerRadius() - 0.5)
105
+ .outerRadius(props.outerRadius())
106
+ .startAngle(effectiveStartAngle)
107
+ .endAngle(effectiveEndAngle)() ?? ''));
108
+ return {
109
+ get current() {
110
+ return path;
111
+ },
112
+ };
113
+ }
114
+ function pointOnCircle(radius, angle) {
115
+ const adjustedAngle = angle - Math.PI / 2;
116
+ return [radius * Math.cos(adjustedAngle), radius * Math.sin(adjustedAngle)];
117
+ }
118
+ export function createArcTextProps(props, opts = {}, position) {
119
+ const effectiveStartAngleRadians = $derived.by(() => {
120
+ const start = props.startAngle();
121
+ const end = props.endAngle();
122
+ const offset = opts.startOffset;
123
+ if (offset) {
124
+ try {
125
+ const percentage = parseFloat(offset.slice(0, -1)) / 100;
126
+ if (!isNaN(percentage) && percentage >= 0 && percentage <= 1) {
127
+ const span = end - start;
128
+ return start + span * percentage;
129
+ }
130
+ else {
131
+ console.warn('Invalid percentage for startOffset:', offset);
132
+ }
133
+ }
134
+ catch (e) {
135
+ console.warn('Could not parse startOffset percentage:', offset, e);
136
+ }
137
+ }
138
+ return start;
139
+ });
140
+ // Convert the effective start angle to degrees for orientation checks
141
+ const effectiveStartDegrees = $derived(radiansToDegrees(effectiveStartAngleRadians));
142
+ // Normalize the effective angle to the [0, 360) range
143
+ const normalizedStartDegrees = $derived(normalizeAngle(effectiveStartDegrees));
144
+ const startDegrees = $derived(radiansToDegrees(props.startAngle()));
145
+ const endDegrees = $derived(radiansToDegrees(props.endAngle()));
146
+ const isClockwise = $derived(startDegrees < endDegrees);
147
+ // Reverse direction of arc when text is on top going counterclockwise or bottom going clockwise
148
+ const isTopCw = $derived(isClockwise && (normalizedStartDegrees >= 270 || normalizedStartDegrees <= 90));
149
+ const isTopCcw = $derived(!isClockwise && (normalizedStartDegrees > 270 || normalizedStartDegrees <= 90));
150
+ const isBottomCw = $derived(isClockwise && normalizedStartDegrees < 270 && normalizedStartDegrees >= 90);
151
+ const isBottomCcw = $derived(!isClockwise && normalizedStartDegrees <= 270 && normalizedStartDegrees > 90);
152
+ const reverseText = $derived(isTopCcw || isBottomCw);
153
+ const pathGenProps = {
154
+ ...props,
155
+ startAngle: () => (reverseText ? props.endAngle() : props.startAngle()),
156
+ endAngle: () => (reverseText ? props.startAngle() : props.endAngle()),
157
+ invertCorner: () => isBottomCw || isBottomCcw,
158
+ };
159
+ const innerPath = getArcPathInner(pathGenProps);
160
+ const middlePath = getArcPathMiddle(pathGenProps);
161
+ const outerPath = getArcPathOuter(pathGenProps);
162
+ const innerDominantBaseline = $derived.by(() => {
163
+ if (isBottomCw || isBottomCcw)
164
+ return 'auto';
165
+ if (isTopCw || isTopCcw)
166
+ return 'hanging';
167
+ return 'auto';
168
+ });
169
+ const outerDominantBaseline = $derived.by(() => {
170
+ if (isBottomCw || isBottomCcw)
171
+ return 'hanging';
172
+ return undefined;
173
+ });
174
+ const sharedProps = $derived.by(() => {
175
+ if (reverseText) {
176
+ return {
177
+ startOffset: opts.startOffset ?? '100%',
178
+ textAnchor: 'end',
179
+ };
180
+ }
181
+ return {
182
+ startOffset: opts.startOffset ?? undefined,
183
+ };
184
+ });
185
+ const radialPositionProps = $derived.by(() => {
186
+ if (position !== 'outer-radial')
187
+ return {};
188
+ const midAngle = (props.startAngle() + props.endAngle()) / 2;
189
+ const basePadding = opts.radialOffset ?? opts.outerPadding ?? 23;
190
+ const midAngleDegrees = normalizeAngle(radiansToDegrees(midAngle));
191
+ let textAnchor = 'middle';
192
+ let effectivePadding = basePadding;
193
+ const isBottomZone = midAngleDegrees > 45 && midAngleDegrees < 135;
194
+ const isTopZone = midAngleDegrees > 225 && midAngleDegrees < 315;
195
+ const isRightZone = midAngleDegrees <= 45 || midAngleDegrees >= 315;
196
+ const isLeftZone = midAngleDegrees >= 135 && midAngleDegrees <= 225;
197
+ const positionRadius = props.outerRadius() + effectivePadding;
198
+ const [x, y] = pointOnCircle(positionRadius, midAngle);
199
+ if (isRightZone) {
200
+ textAnchor = 'start';
201
+ if (midAngleDegrees > 350 || midAngleDegrees < 10)
202
+ textAnchor = 'start';
203
+ }
204
+ else if (isLeftZone) {
205
+ textAnchor = 'end';
206
+ if (midAngleDegrees > 170 && midAngleDegrees < 190)
207
+ textAnchor = 'end';
208
+ }
209
+ else if (isBottomZone) {
210
+ textAnchor = 'middle';
211
+ }
212
+ else if (isTopZone) {
213
+ textAnchor = 'middle';
214
+ }
215
+ return {
216
+ x: x,
217
+ y: y,
218
+ textAnchor,
219
+ 'dominant-baseline': 'middle',
220
+ };
221
+ });
222
+ const current = $derived.by(() => {
223
+ if (position === 'inner') {
224
+ return {
225
+ path: innerPath.current,
226
+ ...sharedProps,
227
+ 'dominant-baseline': innerDominantBaseline,
228
+ };
229
+ }
230
+ else if (position === 'outer') {
231
+ return {
232
+ path: outerPath.current,
233
+ ...sharedProps,
234
+ 'dominant-baseline': outerDominantBaseline,
235
+ };
236
+ }
237
+ else if (position === 'middle') {
238
+ return {
239
+ path: middlePath.current,
240
+ ...sharedProps,
241
+ 'dominant-baseline': 'middle',
242
+ };
243
+ }
244
+ else if (position === 'centroid') {
245
+ const centroid = props.centroid();
246
+ return {
247
+ x: centroid[0],
248
+ y: centroid[1],
249
+ textAnchor: 'middle',
250
+ verticalAnchor: 'middle',
251
+ };
252
+ }
253
+ else {
254
+ return radialPositionProps;
255
+ }
256
+ });
257
+ return {
258
+ get current() {
259
+ return current;
260
+ },
261
+ };
262
+ }
@@ -1,5 +1,13 @@
1
- import { extent as d3extent, type Numeric } from 'd3-array';
1
+ import type { Numeric } from 'd3-array';
2
+ import { extent as d3extent } from 'd3-array';
2
3
  /**
3
4
  * Wrapper around d3-array's `extent()` but remove [undefined, undefined] return type
4
5
  */
5
6
  export declare function extent<T extends Numeric>(iterable: Parameters<typeof d3extent<T>>[0]): [T, T];
7
+ /**
8
+ * Determine whether two arrays equal one another, order not important.
9
+ * This uses includes instead of converting to a set because this is only
10
+ * used internally on a small array size and it's not worth the cost
11
+ * of making a set
12
+ */
13
+ export declare function arraysEqual(arr1: unknown[], arr2: unknown[]): boolean;
@@ -5,3 +5,16 @@ import { extent as d3extent } from 'd3-array';
5
5
  export function extent(iterable) {
6
6
  return d3extent(iterable);
7
7
  }
8
+ /**
9
+ * Determine whether two arrays equal one another, order not important.
10
+ * This uses includes instead of converting to a set because this is only
11
+ * used internally on a small array size and it's not worth the cost
12
+ * of making a set
13
+ */
14
+ export function arraysEqual(arr1, arr2) {
15
+ if (arr1.length !== arr2.length)
16
+ return false;
17
+ return arr1.every((k) => {
18
+ return arr2.includes(k);
19
+ });
20
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Creates a string containing a class name that can be used by
3
+ * developers to target a specific layer/element within a LayerChart.
4
+ *
5
+ * This is a function so that the class names remain consistent and the
6
+ * prefix/structure can be changed in the future if needed
7
+ *
8
+ * @param layerName - the name of the layer to be appended to the generated class name
9
+ * @returns a string to be used as a class on an element
10
+ */
11
+ export declare function layerClass(layerName: string): string;
12
+ type ExtractObjectType<T> = T extends object ? (T extends Function ? never : T) : never;
13
+ type WithClass<T> = T & {
14
+ class?: string;
15
+ };
16
+ type DefaultProps = WithClass<{
17
+ [key: string]: any;
18
+ }>;
19
+ /**
20
+ * Pulls out the props from an arbitrary object/function/boolean and appends
21
+ * a class name to its class property to identify the layer for CSS targeting.
22
+ *
23
+ * @param props The props to be extracted, can be an object, function or any other type
24
+ * @param layerName The name of the layer used to apply a layer classname for targeting styling
25
+ * @param extraClasses Additional classes to be applied to the layer if they don't exist in the props already
26
+ * @returns a typed spreadable object with props for the layer
27
+ */
28
+ export declare function extractLayerProps<T>(props: T, layerName: string, extraClasses?: string): WithClass<ExtractObjectType<T> extends never ? DefaultProps : ExtractObjectType<T>>;
29
+ export {};
@@ -0,0 +1,40 @@
1
+ import { cls } from '@layerstack/tailwind';
2
+ /**
3
+ * Creates a string containing a class name that can be used by
4
+ * developers to target a specific layer/element within a LayerChart.
5
+ *
6
+ * This is a function so that the class names remain consistent and the
7
+ * prefix/structure can be changed in the future if needed
8
+ *
9
+ * @param layerName - the name of the layer to be appended to the generated class name
10
+ * @returns a string to be used as a class on an element
11
+ */
12
+ export function layerClass(layerName) {
13
+ return `lc-${layerName}`;
14
+ }
15
+ // type guard to narrow props to an object with optional class
16
+ // for extractLayerProps
17
+ function isObjectWithClass(val) {
18
+ return typeof val === 'object' && val !== null && typeof val !== 'function';
19
+ }
20
+ /**
21
+ * Pulls out the props from an arbitrary object/function/boolean and appends
22
+ * a class name to its class property to identify the layer for CSS targeting.
23
+ *
24
+ * @param props The props to be extracted, can be an object, function or any other type
25
+ * @param layerName The name of the layer used to apply a layer classname for targeting styling
26
+ * @param extraClasses Additional classes to be applied to the layer if they don't exist in the props already
27
+ * @returns a typed spreadable object with props for the layer
28
+ */
29
+ export function extractLayerProps(props, layerName, extraClasses) {
30
+ const className = layerClass(layerName);
31
+ if (isObjectWithClass(props)) {
32
+ return {
33
+ ...props,
34
+ class: cls(className, props.class ?? '', extraClasses),
35
+ };
36
+ }
37
+ return {
38
+ class: cls(className, extraClasses),
39
+ };
40
+ }
@@ -49,7 +49,7 @@ function render(ctx, render, styleOptions = {}) {
49
49
  ctx.globalAlpha = Number(computedStyles?.opacity);
50
50
  }
51
51
  // Text properties
52
- ctx.font = `${computedStyles.fontSize} ${computedStyles.fontFamily}`; // build string instead of using `computedStyles.font` to fix/workaround `tabular-nums` returning `null`
52
+ ctx.font = `${computedStyles.fontWeight} ${computedStyles.fontSize} ${computedStyles.fontFamily}`; // build string instead of using `computedStyles.font` to fix/workaround `tabular-nums` returning `null`
53
53
  // TODO: Hack to handle `textAnchor` with canvas. Try to find a better approach
54
54
  if (computedStyles.textAnchor === 'middle') {
55
55
  ctx.textAlign = 'center';
@@ -74,10 +74,11 @@ function render(ctx, render, styleOptions = {}) {
74
74
  .map((s) => Number(s.replace('px', '')));
75
75
  ctx.setLineDash(dashArray);
76
76
  }
77
- paintOrder.forEach((attr) => {
77
+ for (const attr of paintOrder) {
78
78
  if (attr === 'fill') {
79
79
  const fill = styleOptions.styles?.fill &&
80
80
  (styleOptions.styles?.fill instanceof CanvasGradient ||
81
+ styleOptions.styles?.fill instanceof CanvasPattern ||
81
82
  !styleOptions.styles?.fill?.includes('var'))
82
83
  ? styleOptions.styles.fill
83
84
  : computedStyles?.fill;
@@ -107,7 +108,7 @@ function render(ctx, render, styleOptions = {}) {
107
108
  render.stroke(ctx);
108
109
  }
109
110
  }
110
- });
111
+ }
111
112
  }
112
113
  /** Render SVG path data onto canvas context. Supports CSS variables and classes by tranferring to hidden `<svg>` element before retrieval) */
113
114
  export function renderPathData(ctx, pathData, styleOptions = {}) {
@@ -163,11 +164,18 @@ export function scaleCanvas(ctx, width, height) {
163
164
  ctx.scale(devicePixelRatio, devicePixelRatio);
164
165
  return { width: ctx.canvas.width, height: ctx.canvas.height };
165
166
  }
167
+ /** Get pixel color (r,g,b,a) at canvas coordinates */
168
+ export function getPixelColor(ctx, x, y) {
169
+ const dpr = window.devicePixelRatio ?? 1;
170
+ const imageData = ctx.getImageData(x * dpr, y * dpr, 1, 1);
171
+ const [r, g, b, a] = imageData.data;
172
+ return { r, g, b, a };
173
+ }
166
174
  export function _createLinearGradient(ctx, x0, y0, x1, y1, stops) {
167
175
  const gradient = ctx.createLinearGradient(x0, y0, x1, y1);
168
- stops.forEach(({ offset, color }) => {
176
+ for (const { offset, color } of stops) {
169
177
  gradient.addColorStop(offset, color);
170
- });
178
+ }
171
179
  return gradient;
172
180
  }
173
181
  /** Create linear gradient and memoize result to fix reactivity */
@@ -175,9 +183,38 @@ export const createLinearGradient = memoize(_createLinearGradient, (ctx, x0, y0,
175
183
  const key = JSON.stringify({ x0, y0, x1, y1, stops });
176
184
  return key;
177
185
  });
178
- export function getPixelColor(ctx, x, y) {
179
- const dpr = window.devicePixelRatio ?? 1;
180
- const imageData = ctx.getImageData(x * dpr, y * dpr, 1, 1);
181
- const [r, g, b, a] = imageData.data;
182
- return { r, g, b, a };
186
+ export function _createPattern(ctx, width, height, shapes, background) {
187
+ const patternCanvas = document.createElement('canvas');
188
+ const patternCtx = patternCanvas.getContext('2d');
189
+ // Add pattern canvas to DOM to allow computed styles to be read (`getComputedStyles()`)
190
+ ctx.canvas.after(patternCanvas);
191
+ // TODO: Fix blurry pattern
192
+ // const newScale = scaleCanvas(patternCtx, width, height);
193
+ patternCanvas.width = width;
194
+ patternCanvas.height = height;
195
+ if (background) {
196
+ patternCtx.fillStyle = background;
197
+ patternCtx.fillRect(0, 0, width, height);
198
+ }
199
+ for (const shape of shapes) {
200
+ patternCtx.save();
201
+ if (shape.type === 'circle') {
202
+ renderCircle(patternCtx, { cx: shape.cx, cy: shape.cy, r: shape.r }, { styles: { fill: shape.fill, opacity: shape.opacity } });
203
+ }
204
+ else if (shape.type === 'line') {
205
+ renderPathData(patternCtx, shape.path, {
206
+ styles: { stroke: shape.stroke, strokeWidth: shape.strokeWidth, opacity: shape.opacity },
207
+ });
208
+ }
209
+ patternCtx.restore();
210
+ }
211
+ const pattern = ctx.createPattern(patternCanvas, 'repeat');
212
+ // Cleanup
213
+ ctx.canvas.parentElement?.removeChild(patternCanvas);
214
+ return pattern;
183
215
  }
216
+ /** Create pattern and memoize result to fix reactivity */
217
+ export const createPattern = memoize(_createPattern, (ctx, width, height, shapes, background) => {
218
+ const key = JSON.stringify({ width, height, shapes, background });
219
+ return key;
220
+ });
@@ -0,0 +1,78 @@
1
+ import type { DomainType } from './scales.svelte.js';
2
+ import type { AxisKey, BaseRange, DataType, Extents, FieldAccessors, Nice, PaddingArray } from './types.js';
3
+ import type { AnyScale } from './scales.svelte.js';
4
+ /**
5
+ * Creates a function to calculate a domain based on extents and a domain directive.
6
+ * @param s The key (e.g., 'x', 'y') to look up in the extents object
7
+ * @returns A function that computes the final domain from extents and a domain input
8
+ */
9
+ export declare function calcDomain<K extends AxisKey>(s: K, extents: Extents, domain: DomainType | undefined): number[];
10
+ /**
11
+ * If we have a domain from settings (the directive), fill in
12
+ * any null values with ones from our measured extents;
13
+ * otherwise, return the measured extent.
14
+ * @param domain A two-value array of numbers representing the measured extent
15
+ * @param directive A two-value array of numbers or nulls that will have any nulls filled in from the `domain` array
16
+ * @returns A two-value array of numbers representing the filled-in domain
17
+ */
18
+ export declare function partialDomain(domain?: number[] | undefined, directive?: Array<number | null>): number[];
19
+ type CreateChartScaleOpts = {
20
+ domain: number[];
21
+ scale: AnyScale & {
22
+ interpolator?: () => {
23
+ name: string;
24
+ };
25
+ nice?: (nice?: number) => void;
26
+ };
27
+ padding: PaddingArray | undefined;
28
+ nice: Nice;
29
+ reverse: boolean;
30
+ width: number;
31
+ height: number;
32
+ range: BaseRange | undefined;
33
+ percentRange: boolean;
34
+ extents: Extents;
35
+ };
36
+ export declare function createChartScale(axis: AxisKey, { domain, scale, padding, nice, reverse, width, height, range, percentRange, }: CreateChartScaleOpts): AnyScale;
37
+ /**
38
+ * Get a D3 scale name
39
+ * https://svelte.dev/repl/ec6491055208401ca41120c9c8a67737?version=3.49.0
40
+ */
41
+ export declare function findScaleName(scale: any): string;
42
+ interface ScaleInfo {
43
+ scale: AnyScale;
44
+ sort?: boolean;
45
+ }
46
+ interface ActiveScales {
47
+ [key: string]: ScaleInfo;
48
+ }
49
+ /**
50
+ * Calculates scale extents for given data and scales
51
+ * @template T The type of data objects in the input array
52
+ * @param {T[]} flatData Array of data objects
53
+ * @param {FieldAccessors<T>} getters Field accessor functions
54
+ * @param {ActiveScales} activeScales Object containing scale information
55
+ * @returns {Extents} Calculated extents for each scale
56
+ */
57
+ export declare function calcScaleExtents<T>(flatData: DataType<T>, getters: FieldAccessors<T>, activeScales: ActiveScales): UniqueResults;
58
+ export interface UniqueResults {
59
+ x?: (number | string)[];
60
+ y?: (number | string)[];
61
+ z?: (number | string)[];
62
+ r?: (number | string)[];
63
+ }
64
+ export declare function identity<T>(d: T): T;
65
+ export declare function createGetter<TData>(accessor: (d: TData) => any, scale: AnyScale | null): (d: TData) => any;
66
+ /**
67
+ * Move an element to the last child of its parent.
68
+ * Adapted from d3-selection `.raise`
69
+ */
70
+ export declare function raise(node: Element): void;
71
+ /**
72
+ * Flatten arrays of arrays one level deep
73
+ * @param list The list to flatten
74
+ * @param accessor An optional accessor function or string property key
75
+ * @returns Flattened array
76
+ */
77
+ export default function flatten<T, U>(list: T[], accessor?: string | ((item: T) => U[])): U[];
78
+ export {};