@rokkit/chart 1.1.18 → 1.1.19

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 (156) hide show
  1. package/dist/AnimatedPlot.svelte.d.ts +35 -0
  2. package/dist/Chart.svelte.d.ts +21 -0
  3. package/dist/ChartExporter.svelte.d.ts +22 -0
  4. package/dist/ChartLegend.svelte.d.ts +30 -0
  5. package/dist/ChartProvider.svelte.d.ts +10 -0
  6. package/dist/FacetPlot/Panel.svelte.d.ts +22 -0
  7. package/dist/FacetPlot.svelte.d.ts +32 -0
  8. package/dist/Plot/Arc.svelte.d.ts +18 -0
  9. package/dist/Plot/Area.svelte.d.ts +14 -0
  10. package/dist/Plot/Axis.svelte.d.ts +13 -0
  11. package/dist/Plot/Bar.svelte.d.ts +11 -0
  12. package/dist/Plot/Grid.svelte.d.ts +3 -0
  13. package/dist/Plot/Legend.svelte.d.ts +6 -0
  14. package/dist/Plot/Line.svelte.d.ts +13 -0
  15. package/dist/Plot/Point.svelte.d.ts +13 -0
  16. package/dist/Plot/Root.svelte.d.ts +21 -0
  17. package/dist/Plot/Timeline.svelte.d.ts +13 -0
  18. package/dist/Plot/Tooltip.svelte.d.ts +7 -0
  19. package/dist/Plot.svelte.d.ts +34 -0
  20. package/dist/PlotState.svelte.d.ts +0 -3
  21. package/dist/Sparkline.svelte.d.ts +16 -0
  22. package/dist/Symbol.svelte.d.ts +12 -0
  23. package/dist/Texture.svelte.d.ts +12 -0
  24. package/dist/charts/AreaChart.svelte.d.ts +25 -0
  25. package/dist/charts/BarChart.svelte.d.ts +26 -0
  26. package/dist/charts/BoxPlot.svelte.d.ts +18 -0
  27. package/dist/charts/BubbleChart.svelte.d.ts +23 -0
  28. package/dist/charts/LineChart.svelte.d.ts +26 -0
  29. package/dist/charts/PieChart.svelte.d.ts +19 -0
  30. package/dist/charts/ScatterPlot.svelte.d.ts +29 -0
  31. package/dist/charts/ViolinPlot.svelte.d.ts +18 -0
  32. package/dist/crossfilter/CrossFilter.svelte.d.ts +12 -0
  33. package/dist/crossfilter/FilterBar.svelte.d.ts +12 -0
  34. package/dist/crossfilter/FilterHistogram.svelte.d.ts +19 -0
  35. package/dist/crossfilter/FilterSlider.svelte.d.ts +15 -0
  36. package/dist/elements/Bar.svelte.d.ts +17 -0
  37. package/dist/elements/ColorRamp.svelte.d.ts +17 -0
  38. package/dist/elements/ContinuousLegend.svelte.d.ts +18 -0
  39. package/dist/elements/DefinePatterns.svelte.d.ts +21 -0
  40. package/dist/elements/DiscreteLegend.svelte.d.ts +17 -0
  41. package/dist/elements/Label.svelte.d.ts +11 -0
  42. package/dist/elements/SymbolGrid.svelte.d.ts +8 -0
  43. package/dist/examples/BarChartExample.svelte.d.ts +18 -0
  44. package/dist/geoms/Arc.svelte.d.ts +20 -0
  45. package/dist/geoms/Area.svelte.d.ts +16 -0
  46. package/dist/geoms/Bar.svelte.d.ts +23 -0
  47. package/dist/geoms/Box.svelte.d.ts +12 -0
  48. package/dist/geoms/Candlestick.svelte.d.ts +20 -0
  49. package/dist/geoms/Heatmap.svelte.d.ts +13 -0
  50. package/dist/geoms/Hexbin.svelte.d.ts +13 -0
  51. package/dist/geoms/LabelPill.svelte.d.ts +9 -0
  52. package/dist/geoms/Line.svelte.d.ts +24 -0
  53. package/dist/geoms/Point.svelte.d.ts +30 -0
  54. package/dist/geoms/Ribbon.svelte.d.ts +16 -0
  55. package/dist/geoms/Violin.svelte.d.ts +12 -0
  56. package/dist/geoms/Waterfall.svelte.d.ts +18 -0
  57. package/dist/geoms/lib/areas.d.ts +5 -3
  58. package/dist/lib/brewing/brewer.svelte.d.ts +24 -15
  59. package/dist/lib/brewing/marks/arcs.d.ts +16 -6
  60. package/dist/lib/brewing/marks/areas.d.ts +2 -2
  61. package/dist/lib/brewing/marks/boxes.d.ts +3 -3
  62. package/dist/lib/brewing/marks/lines.d.ts +6 -6
  63. package/dist/lib/brewing/marks/points.d.ts +13 -12
  64. package/dist/lib/brewing/marks/violins.d.ts +3 -3
  65. package/dist/lib/brewing/scales.d.ts +3 -3
  66. package/dist/lib/chart.d.ts +2 -2
  67. package/dist/lib/keyboard-nav.d.ts +1 -1
  68. package/dist/lib/plot/facet.d.ts +2 -2
  69. package/dist/lib/plot/frames.d.ts +9 -9
  70. package/dist/lib/plot/scales.d.ts +3 -3
  71. package/dist/lib/plot/types.d.ts +7 -4
  72. package/dist/lib/scales.svelte.d.ts +2 -2
  73. package/dist/lib/utils.d.ts +7 -1
  74. package/dist/lib/xscale.d.ts +1 -1
  75. package/dist/patterns/DefinePatterns.svelte.d.ts +7 -0
  76. package/dist/patterns/PatternDef.svelte.d.ts +11 -0
  77. package/dist/spec/chart-spec.d.ts +22 -0
  78. package/dist/symbols/RoundedSquare.svelte.d.ts +11 -0
  79. package/dist/symbols/Shape.svelte.d.ts +18 -0
  80. package/dist/symbols/constants/index.d.ts +1 -1
  81. package/dist/symbols/index.d.ts +2 -2
  82. package/dist/symbols/outline.svelte.d.ts +18 -0
  83. package/dist/symbols/solid.svelte.d.ts +18 -0
  84. package/package.json +22 -3
  85. package/src/AnimatedPlot.svelte +49 -43
  86. package/src/Chart.svelte +34 -22
  87. package/src/ChartExporter.svelte +19 -16
  88. package/src/ChartLegend.svelte +24 -20
  89. package/src/ChartProvider.svelte +10 -2
  90. package/src/FacetPlot/Panel.svelte +23 -3
  91. package/src/FacetPlot.svelte +29 -26
  92. package/src/Plot/Arc.svelte +3 -2
  93. package/src/Plot/Area.svelte +30 -8
  94. package/src/Plot/Axis.svelte +26 -45
  95. package/src/Plot/Bar.svelte +20 -5
  96. package/src/Plot/Grid.svelte +5 -4
  97. package/src/Plot/Legend.svelte +8 -4
  98. package/src/Plot/Line.svelte +24 -7
  99. package/src/Plot/Point.svelte +24 -6
  100. package/src/Plot/Root.svelte +17 -2
  101. package/src/Plot/Timeline.svelte +13 -14
  102. package/src/Plot/Tooltip.svelte +12 -6
  103. package/src/Plot.svelte +41 -32
  104. package/src/PlotState.svelte.js +6 -2
  105. package/src/Sparkline.svelte +22 -8
  106. package/src/Symbol.svelte +15 -5
  107. package/src/Texture.svelte +12 -2
  108. package/src/charts/AreaChart.svelte +26 -3
  109. package/src/charts/BarChart.svelte +27 -3
  110. package/src/charts/BoxPlot.svelte +19 -3
  111. package/src/charts/BubbleChart.svelte +24 -3
  112. package/src/charts/LineChart.svelte +27 -3
  113. package/src/charts/PieChart.svelte +20 -3
  114. package/src/charts/ScatterPlot.svelte +27 -3
  115. package/src/charts/ViolinPlot.svelte +19 -3
  116. package/src/crossfilter/CrossFilter.svelte +13 -10
  117. package/src/crossfilter/FilterBar.svelte +14 -3
  118. package/src/crossfilter/FilterHistogram.svelte +49 -24
  119. package/src/crossfilter/FilterSlider.svelte +16 -5
  120. package/src/elements/Bar.svelte +16 -2
  121. package/src/elements/ColorRamp.svelte +28 -4
  122. package/src/elements/ContinuousLegend.svelte +20 -3
  123. package/src/elements/DefinePatterns.svelte +23 -7
  124. package/src/elements/DiscreteLegend.svelte +18 -2
  125. package/src/elements/Label.svelte +11 -2
  126. package/src/elements/SymbolGrid.svelte +13 -4
  127. package/src/examples/BarChartExample.svelte +12 -15
  128. package/src/geoms/Arc.svelte +18 -5
  129. package/src/geoms/Area.svelte +38 -20
  130. package/src/geoms/Bar.svelte +40 -23
  131. package/src/geoms/Box.svelte +13 -4
  132. package/src/geoms/Candlestick.svelte +27 -7
  133. package/src/geoms/Heatmap.svelte +20 -9
  134. package/src/geoms/Hexbin.svelte +35 -13
  135. package/src/geoms/LabelPill.svelte +9 -3
  136. package/src/geoms/Line.svelte +27 -10
  137. package/src/geoms/Point.svelte +33 -13
  138. package/src/geoms/Ribbon.svelte +26 -8
  139. package/src/geoms/Violin.svelte +13 -4
  140. package/src/geoms/Waterfall.svelte +32 -12
  141. package/src/geoms/lib/areas.js +2 -2
  142. package/src/lib/brewing/marks/arcs.js +3 -2
  143. package/src/lib/brewing/marks/boxes.js +1 -1
  144. package/src/lib/brewing/marks/lines.js +2 -2
  145. package/src/lib/brewing/marks/points.js +3 -2
  146. package/src/lib/brewing/marks/violins.js +1 -1
  147. package/src/lib/plot/facet.js +1 -1
  148. package/src/lib/plot/frames.js +4 -4
  149. package/src/lib/plot/types.js +6 -3
  150. package/src/lib/utils.js +7 -1
  151. package/src/patterns/DefinePatterns.svelte +9 -4
  152. package/src/patterns/PatternDef.svelte +11 -3
  153. package/src/symbols/RoundedSquare.svelte +15 -4
  154. package/src/symbols/Shape.svelte +21 -3
  155. package/src/symbols/outline.svelte +2 -0
  156. package/src/symbols/solid.svelte +2 -0
@@ -1,4 +1,6 @@
1
- <script>
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
3
+
2
4
  /**
3
5
  * ChartExporter — wraps a chart and provides export actions for SVG and PNG.
4
6
  *
@@ -9,26 +11,30 @@
9
11
  * <button onclick={() => exporter.exportSVG()}>SVG</button>
10
12
  * <button onclick={() => exporter.exportPNG()}>PNG</button>
11
13
  */
14
+ type Props = {
15
+ children?: Snippet
16
+ filename?: string
17
+ scale?: number
18
+ }
19
+
12
20
  let {
13
21
  children,
14
22
  filename = 'chart',
15
23
  scale = 2
16
- } = $props()
24
+ }: Props = $props()
17
25
 
18
- let containerEl = $state(null)
26
+ let containerEl = $state<HTMLDivElement | null>(null)
19
27
 
20
- function getSvgEl() {
21
- return containerEl?.querySelector('svg')
28
+ function getSvgEl(): SVGSVGElement | null {
29
+ return containerEl?.querySelector('svg') ?? null
22
30
  }
23
31
 
24
32
  /**
25
33
  * Inline all computed CSS custom property values into the SVG for portability.
26
- * @param {SVGSVGElement} svg
27
- * @returns {SVGSVGElement}
28
34
  */
29
35
  // eslint-disable-next-line complexity
30
- function inlineStyles(svg) {
31
- const clone = /** @type {SVGSVGElement} */ (svg.cloneNode(true))
36
+ function inlineStyles(svg: SVGSVGElement): SVGSVGElement {
37
+ const clone = svg.cloneNode(true) as SVGSVGElement
32
38
  const computed = getComputedStyle(svg)
33
39
 
34
40
  // Copy relevant CSS custom properties to inline styles on the root
@@ -70,9 +76,9 @@
70
76
 
71
77
  /**
72
78
  * Export the chart as a PNG file download.
73
- * @param {number} [scaleFactor] Override scale factor for this export
79
+ * @param scaleFactor Override scale factor for this export
74
80
  */
75
- export function exportPNG(scaleFactor) {
81
+ export function exportPNG(scaleFactor?: number) {
76
82
  const svg = getSvgEl()
77
83
  if (!svg) return
78
84
 
@@ -89,6 +95,7 @@
89
95
  canvas.width = svg.clientWidth * factor
90
96
  canvas.height = svg.clientHeight * factor
91
97
  const ctx = canvas.getContext('2d')
98
+ if (!ctx) return
92
99
  ctx.scale(factor, factor)
93
100
  ctx.drawImage(img, 0, 0)
94
101
  URL.revokeObjectURL(url)
@@ -100,11 +107,7 @@
100
107
  img.src = url
101
108
  }
102
109
 
103
- /**
104
- * @param {Blob} blob
105
- * @param {string} name
106
- */
107
- function download(blob, name) {
110
+ function download(blob: Blob, name: string) {
108
111
  const a = document.createElement('a')
109
112
  a.href = URL.createObjectURL(blob)
110
113
  a.download = name
@@ -1,34 +1,38 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { buildSymbolPath } from './lib/brewing/marks/points.js'
3
3
 
4
+ type LegendItem = {
5
+ key: string
6
+ label: string
7
+ fill?: string
8
+ stroke?: string
9
+ patternId?: string
10
+ shape?: string
11
+ }
12
+
13
+ type LegendGroup = {
14
+ type?: 'color' | 'pattern' | 'symbol'
15
+ label?: string
16
+ items: LegendItem[]
17
+ }
18
+
4
19
  /**
5
20
  * Standalone chart legend — HTML-based, usable outside of Plot context.
6
21
  * Accepts `groups` from a chart's brewer or from multiple charts for shared legends.
7
- *
8
- * @type {{
9
- * groups: Array<{
10
- * type?: 'color' | 'pattern' | 'symbol',
11
- * label?: string,
12
- * items: Array<{
13
- * key: string,
14
- * label: string,
15
- * fill?: string,
16
- * stroke?: string,
17
- * patternId?: string,
18
- * shape?: string,
19
- * }>
20
- * }>,
21
- * orientation?: 'horizontal' | 'vertical' | 'wrap',
22
- * gradient?: { style: string, min: string, max: string } | null,
23
- * swatchStyle?: 'fill' | 'line' | 'point',
24
- * }}
25
22
  */
23
+ type Props = {
24
+ groups?: LegendGroup[]
25
+ orientation?: 'horizontal' | 'vertical' | 'wrap'
26
+ gradient?: { style: string; min: string; max: string } | null
27
+ swatchStyle?: 'fill' | 'line' | 'point'
28
+ }
29
+
26
30
  let {
27
31
  groups = [],
28
32
  orientation = 'horizontal',
29
33
  gradient = null,
30
34
  swatchStyle = 'fill'
31
- } = $props()
35
+ }: Props = $props()
32
36
  </script>
33
37
 
34
38
  <div
@@ -1,8 +1,16 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { setContext } from 'svelte'
3
+ import type { Snippet } from 'svelte'
3
4
  import { createChartPreset } from './lib/preset.js'
4
5
 
5
- let { preset = createChartPreset(), children } = $props()
6
+ type Preset = ReturnType<typeof createChartPreset>
7
+
8
+ type Props = {
9
+ preset?: Preset
10
+ children?: Snippet
11
+ }
12
+
13
+ let { preset = createChartPreset(), children }: Props = $props()
6
14
 
7
15
  setContext('chart-preset', { get current() { return preset } })
8
16
  </script>
@@ -1,8 +1,28 @@
1
- <script>
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
2
3
  import PlotChart from '../Plot.svelte'
4
+ import type { GeomSpec, PlotHelpers } from '../lib/plot/types.js'
5
+
6
+ type Props = {
7
+ data?: Record<string, unknown>[]
8
+ x?: string
9
+ y?: string
10
+ color?: string
11
+ geoms?: GeomSpec[]
12
+ helpers?: PlotHelpers
13
+ width?: number
14
+ height?: number
15
+ mode?: 'light' | 'dark'
16
+ grid?: boolean
17
+ legend?: boolean
18
+ xDomain?: unknown[]
19
+ yDomain?: [number, number]
20
+ colorDomain?: unknown[]
21
+ children?: Snippet
22
+ }
3
23
 
4
24
  let {
5
- data,
25
+ data = [],
6
26
  x,
7
27
  y,
8
28
  color,
@@ -17,7 +37,7 @@
17
37
  yDomain,
18
38
  colorDomain,
19
39
  children
20
- } = $props()
40
+ }: Props = $props()
21
41
 
22
42
  // Build spec with domain overrides so PlotState uses them
23
43
  const spec = $derived({
@@ -1,32 +1,35 @@
1
- <script>
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
2
3
  import { splitByField, getFacetDomains } from './lib/plot/facet.js'
3
4
  import { distinct } from './lib/brewing/colors.js'
5
+ import type { GeomSpec, PlotHelpers } from './lib/plot/types.js'
4
6
  import PlotPanel from './FacetPlot/Panel.svelte'
5
7
 
6
- /**
7
- * @type {{
8
- * data: Object[],
9
- * facet: { by: string, cols?: number, scales?: 'fixed'|'free'|'free_x'|'free_y' },
10
- * x?: string,
11
- * y?: string,
12
- * color?: string,
13
- * fill?: string,
14
- * pattern?: string,
15
- * symbol?: string,
16
- * geom?: string,
17
- * stat?: string,
18
- * geoms?: import('./lib/plot/types.js').GeomSpec[],
19
- * helpers?: import('./lib/plot/types.js').PlotHelpers,
20
- * panelWidth?: number,
21
- * panelHeight?: number,
22
- * width?: number,
23
- * height?: number,
24
- * mode?: 'light' | 'dark',
25
- * grid?: boolean,
26
- * legend?: boolean,
27
- * children?: import('svelte').Snippet
28
- * }}
29
- */
8
+ type Facet = { by: string; cols?: number; scales?: 'fixed' | 'free' | 'free_x' | 'free_y' }
9
+
10
+ type Props = {
11
+ data?: Record<string, unknown>[]
12
+ facet: Facet
13
+ x?: string
14
+ y?: string
15
+ color?: string
16
+ fill?: string
17
+ pattern?: string
18
+ symbol?: string
19
+ geom?: string
20
+ stat?: string
21
+ geoms?: GeomSpec[]
22
+ helpers?: PlotHelpers
23
+ panelWidth?: number
24
+ panelHeight?: number
25
+ width?: number
26
+ height?: number
27
+ mode?: 'light' | 'dark'
28
+ grid?: boolean
29
+ legend?: boolean
30
+ children?: Snippet
31
+ }
32
+
30
33
  let {
31
34
  data = [],
32
35
  facet,
@@ -48,7 +51,7 @@
48
51
  grid = true,
49
52
  legend = false,
50
53
  children
51
- } = $props()
54
+ }: Props = $props()
52
55
 
53
56
  // `fill` is accepted as an alias for `color` (bar/area semantics vs line/point)
54
57
  const colorChannel = $derived(fill ?? color)
@@ -1,7 +1,8 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte'
3
+ import type { ChartBrewer } from '../lib/brewing/brewer.svelte.js'
3
4
 
4
- const brewer = getContext('chart-brewer')
5
+ const brewer = getContext<ChartBrewer>('chart-brewer')
5
6
  </script>
6
7
 
7
8
  {#if brewer && brewer.arcs && brewer.arcs.length > 0}
@@ -1,6 +1,19 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte'
3
- import { area as d3Area } from 'd3-shape'
3
+ import { area as d3Area, type CurveFactory } from 'd3-shape'
4
+ import type { PlotState } from '../PlotState.svelte.js'
5
+
6
+ type Datum = Record<string, unknown> | number
7
+
8
+ type Props = {
9
+ data?: Datum[]
10
+ x?: string
11
+ y?: string
12
+ y0?: string
13
+ fill?: string
14
+ opacity?: number
15
+ curve?: CurveFactory
16
+ }
4
17
 
5
18
  let {
6
19
  data = [],
@@ -10,17 +23,26 @@
10
23
  fill = 'steelblue',
11
24
  opacity = 0.7,
12
25
  curve = undefined
13
- } = $props()
26
+ }: Props = $props()
27
+
28
+ const state = getContext<PlotState>('plot-state')
14
29
 
15
- const state = getContext('plot-state')
30
+ const accessor = (d: Datum, field: string | undefined): unknown =>
31
+ field && typeof d === 'object' ? d[field] : d
16
32
 
17
33
  const path = $derived.by(() => {
18
34
  if (!state?.xScale || !state?.yScale || !data?.length) return null
35
+ const xScale = state.xScale
36
+ const yScale = state.yScale
19
37
  const innerHeight = state.innerHeight
20
- const areaGen = d3Area()
21
- .x((d) => state.xScale(x ? d[x] : d) ?? 0)
22
- .y1((d) => state.yScale(y ? d[y] : d) ?? 0)
23
- .y0((d) => (y0 !== undefined ? state.yScale(d[y0] ?? y0) : innerHeight) ?? innerHeight)
38
+ const areaGen = d3Area<Datum>()
39
+ .x((d) => xScale(accessor(d, x)) ?? 0)
40
+ .y1((d) => yScale(accessor(d, y)) ?? 0)
41
+ .y0((d) =>
42
+ y0 !== undefined
43
+ ? (yScale((typeof d === 'object' ? d[y0] : undefined) ?? y0) ?? innerHeight)
44
+ : innerHeight
45
+ )
24
46
  .defined((d) => d != null)
25
47
  if (curve) areaGen.curve(curve)
26
48
  return areaGen(data)
@@ -1,18 +1,20 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte'
3
+ import type { PlotState } from '../PlotState.svelte.js'
4
+
5
+ type Props = {
6
+ type?: 'x' | 'y'
7
+ label?: string
8
+ format?: (v: unknown) => string
9
+ ticks?: number
10
+ minorTicks?: boolean
11
+ showLine?: boolean
12
+ showTicks?: boolean
13
+ showLabels?: boolean
14
+ }
15
+
16
+ type Tick = { value: unknown; pos: number; minor: boolean }
3
17
 
4
- /**
5
- * @type {{
6
- * type?: 'x' | 'y',
7
- * label?: string,
8
- * format?: (v: unknown) => string,
9
- * ticks?: number,
10
- * minorTicks?: boolean,
11
- * showLine?: boolean,
12
- * showTicks?: boolean,
13
- * showLabels?: boolean,
14
- * }}
15
- */
16
18
  let {
17
19
  type = 'x',
18
20
  label = '',
@@ -22,25 +24,26 @@
22
24
  showLine = true,
23
25
  showTicks = true,
24
26
  showLabels = true
25
- } = $props()
27
+ }: Props = $props()
26
28
 
27
- const state = getContext('plot-state')
29
+ const state = getContext<PlotState>('plot-state')
28
30
 
29
31
  const MINOR_DIVISIONS = 4
30
32
 
31
- const xTicks = $derived.by(() => {
32
- const s = state.xScale
33
+ function buildTicks(s: PlotState['xScale']): Tick[] {
33
34
  if (!s) return []
34
35
  if (typeof s.bandwidth === 'function') {
35
- return s.domain().map((val) => ({
36
+ return s.domain().map((val: unknown) => ({
36
37
  value: val,
37
38
  pos: (s(val) ?? 0) + s.bandwidth() / 2,
38
39
  minor: false
39
40
  }))
40
41
  }
41
- const major = s.ticks(tickCount).map((val) => ({ value: val, pos: s(val), minor: false }))
42
+ const major: Tick[] = s
43
+ .ticks(tickCount)
44
+ .map((val: number) => ({ value: val, pos: s(val), minor: false }))
42
45
  if (!minorTicks || major.length < 2) return major
43
- const result = []
46
+ const result: Tick[] = []
44
47
  for (let i = 0; i < major.length; i++) {
45
48
  result.push(major[i])
46
49
  if (i < major.length - 1) {
@@ -51,32 +54,10 @@
51
54
  }
52
55
  }
53
56
  return result
54
- })
57
+ }
55
58
 
56
- const yTicks = $derived.by(() => {
57
- const s = state.yScale
58
- if (!s) return []
59
- if (typeof s.bandwidth === 'function') {
60
- return s.domain().map((val) => ({
61
- value: val,
62
- pos: (s(val) ?? 0) + s.bandwidth() / 2,
63
- minor: false
64
- }))
65
- }
66
- const major = s.ticks(tickCount).map((val) => ({ value: val, pos: s(val), minor: false }))
67
- if (!minorTicks || major.length < 2) return major
68
- const result = []
69
- for (let i = 0; i < major.length; i++) {
70
- result.push(major[i])
71
- if (i < major.length - 1) {
72
- const step = (major[i + 1].pos - major[i].pos) / MINOR_DIVISIONS
73
- for (let j = 1; j < MINOR_DIVISIONS; j++) {
74
- result.push({ value: null, pos: major[i].pos + step * j, minor: true })
75
- }
76
- }
77
- }
78
- return result
79
- })
59
+ const xTicks = $derived(buildTicks(state.xScale))
60
+ const yTicks = $derived(buildTicks(state.yScale))
80
61
 
81
62
  const xTransform = $derived(`translate(0, ${state.xAxisY ?? state.innerHeight})`)
82
63
  const yTransform = $derived(`translate(${state.yAxisX ?? 0}, 0)`)
@@ -1,9 +1,24 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte'
3
+ import type { PlotState } from '../PlotState.svelte.js'
3
4
 
4
- let { data = undefined, x = undefined, y = undefined, fill = 'steelblue', opacity = 1 } = $props()
5
+ type Datum = Record<string, unknown> | number
5
6
 
6
- const state = getContext('plot-state')
7
+ type Props = {
8
+ data?: Datum[]
9
+ x?: string
10
+ y?: string
11
+ fill?: string
12
+ opacity?: number
13
+ }
14
+
15
+ let { data = undefined, x = undefined, y = undefined, fill = 'steelblue', opacity = 1 }: Props =
16
+ $props()
17
+
18
+ const state = getContext<PlotState>('plot-state')
19
+
20
+ const accessor = (d: Datum, field: string | undefined): unknown =>
21
+ field && typeof d === 'object' ? d[field] : d
7
22
 
8
23
  const bars = $derived.by(() => {
9
24
  if (!state?.xScale || !state?.yScale) return []
@@ -24,8 +39,8 @@
24
39
  : innerHeight
25
40
 
26
41
  return src.map((d) => {
27
- const xVal = x ? d[x] : d
28
- const yVal = y ? d[y] : d
42
+ const xVal = accessor(d, x)
43
+ const yVal = accessor(d, y)
29
44
  const xPos = (xScale(xVal) ?? 0) + padding
30
45
  const yPos = yScale(yVal) ?? baseline
31
46
  return {
@@ -1,18 +1,19 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte'
3
+ import type { PlotState } from '../PlotState.svelte.js'
3
4
 
4
- const state = getContext('plot-state')
5
+ const state = getContext<PlotState>('plot-state')
5
6
 
6
7
  const xGridLines = $derived.by(() => {
7
8
  const s = state.xScale
8
9
  if (!s || typeof s.bandwidth !== 'function') return []
9
- return s.domain().map((val) => ({ pos: (s(val) ?? 0) + s.bandwidth() / 2 }))
10
+ return s.domain().map((val: unknown) => ({ pos: (s(val) ?? 0) + s.bandwidth() / 2 }))
10
11
  })
11
12
 
12
13
  const yGridLines = $derived.by(() => {
13
14
  const s = state.yScale
14
15
  if (!s || typeof s.ticks !== 'function') return []
15
- return s.ticks(6).map((val) => ({ pos: s(val) }))
16
+ return s.ticks(6).map((val: number) => ({ pos: s(val) }))
16
17
  })
17
18
  </script>
18
19
 
@@ -1,12 +1,16 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte'
3
+ import type { PlotState } from '../PlotState.svelte.js'
3
4
  import { toPatternId } from '../lib/brewing/patterns.js'
4
5
  import { buildSymbolPath } from '../lib/brewing/marks/points.js'
5
6
 
6
- /** @type {Record<string, string>} */
7
- let { labels = {} } = $props()
7
+ type Props = {
8
+ labels?: Record<string, string>
9
+ }
10
+
11
+ let { labels = {} }: Props = $props()
8
12
 
9
- const state = getContext('plot-state')
13
+ const state = getContext<PlotState>('plot-state')
10
14
 
11
15
  const isCategorical = $derived(state.colorScaleType === 'categorical')
12
16
  const isLineGeom = $derived(state.geomTypes?.has('line') ?? false)
@@ -1,6 +1,18 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte'
3
- import { line as d3Line } from 'd3-shape'
3
+ import { line as d3Line, type CurveFactory } from 'd3-shape'
4
+ import type { PlotState } from '../PlotState.svelte.js'
5
+
6
+ type Datum = Record<string, unknown> | number
7
+
8
+ type Props = {
9
+ data?: Datum[]
10
+ x?: string
11
+ y?: string
12
+ stroke?: string
13
+ strokeWidth?: number
14
+ curve?: CurveFactory
15
+ }
4
16
 
5
17
  let {
6
18
  data = [],
@@ -9,15 +21,20 @@
9
21
  stroke = 'steelblue',
10
22
  strokeWidth = 2,
11
23
  curve = undefined
12
- } = $props()
24
+ }: Props = $props()
25
+
26
+ const state = getContext<PlotState>('plot-state')
13
27
 
14
- const state = getContext('plot-state')
28
+ const accessor = (d: Datum, field: string | undefined): unknown =>
29
+ field && typeof d === 'object' ? d[field] : d
15
30
 
16
31
  const path = $derived.by(() => {
17
32
  if (!state?.xScale || !state?.yScale || !data?.length) return null
18
- const lineGen = d3Line()
19
- .x((d) => state.xScale(x ? d[x] : d) ?? 0)
20
- .y((d) => state.yScale(y ? d[y] : d) ?? 0)
33
+ const xScale = state.xScale
34
+ const yScale = state.yScale
35
+ const lineGen = d3Line<Datum>()
36
+ .x((d) => xScale(accessor(d, x)) ?? 0)
37
+ .y((d) => yScale(accessor(d, y)) ?? 0)
21
38
  .defined((d) => d != null)
22
39
  if (curve) lineGen.curve(curve)
23
40
  return lineGen(data)
@@ -1,5 +1,18 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte'
3
+ import type { PlotState } from '../PlotState.svelte.js'
4
+
5
+ type Datum = Record<string, unknown> | number
6
+
7
+ type Props = {
8
+ data?: Datum[]
9
+ x?: string
10
+ y?: string
11
+ r?: number
12
+ fill?: string
13
+ stroke?: string
14
+ strokeWidth?: number
15
+ }
3
16
 
4
17
  let {
5
18
  data = [],
@@ -9,17 +22,22 @@
9
22
  fill = 'steelblue',
10
23
  stroke = 'white',
11
24
  strokeWidth = 1
12
- } = $props()
25
+ }: Props = $props()
26
+
27
+ const state = getContext<PlotState>('plot-state')
13
28
 
14
- const state = getContext('plot-state')
29
+ const accessor = (d: Datum, field: string | undefined): unknown =>
30
+ field && typeof d === 'object' ? d[field] : d
15
31
 
16
32
  const points = $derived.by(() => {
17
33
  if (!state?.xScale || !state?.yScale || !data?.length) return []
34
+ const xScale = state.xScale
35
+ const yScale = state.yScale
18
36
  return data
19
37
  .map((d) => ({
20
- cx: state.xScale(x ? d[x] : d) ?? null,
21
- cy: state.yScale(y ? d[y] : d) ?? null,
22
- label: `(${x ? d[x] : d}, ${y ? d[y] : d})`
38
+ cx: xScale(accessor(d, x)) ?? null,
39
+ cy: yScale(accessor(d, y)) ?? null,
40
+ label: `(${accessor(d, x)}, ${accessor(d, y)})`
23
41
  }))
24
42
  .filter((p) => p.cx !== null && p.cy !== null)
25
43
  })
@@ -1,8 +1,23 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { setContext, untrack } from 'svelte'
3
+ import type { Snippet } from 'svelte'
3
4
  import { PlotState } from '../PlotState.svelte.js'
4
5
  import { defaultPreset } from '../lib/preset.js'
5
6
 
7
+ type Margin = { top?: number; right?: number; bottom?: number; left?: number }
8
+
9
+ type Props = {
10
+ data?: Record<string, unknown>[]
11
+ x?: string
12
+ y?: string
13
+ color?: string
14
+ width?: number
15
+ height?: number
16
+ margin?: Margin
17
+ mode?: 'light' | 'dark'
18
+ children?: Snippet
19
+ }
20
+
6
21
  let {
7
22
  data = [],
8
23
  x = undefined,
@@ -13,7 +28,7 @@
13
28
  margin = undefined,
14
29
  mode = 'light',
15
30
  children
16
- } = $props()
31
+ }: Props = $props()
17
32
 
18
33
  const plotState = untrack(
19
34
  () =>