@rokkit/chart 1.0.0-next.15 → 1.0.0-next.150

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 (223) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +150 -46
  3. package/dist/Plot/index.d.ts +9 -0
  4. package/dist/PlotState.svelte.d.ts +47 -0
  5. package/dist/crossfilter/createCrossFilter.svelte.d.ts +15 -0
  6. package/dist/elements/index.d.ts +6 -0
  7. package/dist/geoms/lib/areas.d.ts +52 -0
  8. package/dist/geoms/lib/bars.d.ts +3 -0
  9. package/dist/index.d.ts +51 -0
  10. package/dist/lib/brewer.d.ts +9 -0
  11. package/dist/lib/brewing/BoxBrewer.svelte.d.ts +10 -0
  12. package/dist/lib/brewing/CartesianBrewer.svelte.d.ts +8 -0
  13. package/dist/lib/brewing/PieBrewer.svelte.d.ts +8 -0
  14. package/dist/lib/brewing/ViolinBrewer.svelte.d.ts +9 -0
  15. package/dist/lib/brewing/axes.svelte.d.ts +66 -0
  16. package/dist/lib/brewing/bars.svelte.d.ts +56 -0
  17. package/dist/lib/brewing/brewer.svelte.d.ts +145 -0
  18. package/dist/lib/brewing/colors.d.ts +17 -0
  19. package/dist/lib/brewing/dimensions.svelte.d.ts +35 -0
  20. package/dist/lib/brewing/index.svelte.d.ts +118 -0
  21. package/dist/lib/brewing/legends.svelte.d.ts +48 -0
  22. package/dist/lib/brewing/marks/arcs.d.ts +17 -0
  23. package/dist/lib/brewing/marks/areas.d.ts +31 -0
  24. package/dist/lib/brewing/marks/bars.d.ts +1 -0
  25. package/dist/lib/brewing/marks/boxes.d.ts +24 -0
  26. package/dist/lib/brewing/marks/lines.d.ts +24 -0
  27. package/dist/lib/brewing/marks/points.d.ts +40 -0
  28. package/dist/lib/brewing/marks/violins.d.ts +20 -0
  29. package/dist/lib/brewing/patterns.d.ts +14 -0
  30. package/dist/lib/brewing/scales.d.ts +28 -0
  31. package/dist/lib/brewing/scales.svelte.d.ts +24 -0
  32. package/dist/lib/brewing/stats.d.ts +31 -0
  33. package/dist/lib/brewing/symbols.d.ts +7 -0
  34. package/dist/lib/brewing/types.d.ts +162 -0
  35. package/dist/lib/chart.d.ts +40 -0
  36. package/dist/lib/context.d.ts +13 -0
  37. package/dist/lib/grid.d.ts +72 -0
  38. package/dist/lib/plot/chartProps.d.ts +177 -0
  39. package/dist/lib/plot/crossfilter.d.ts +13 -0
  40. package/dist/lib/plot/facet.d.ts +24 -0
  41. package/dist/lib/plot/frames.d.ts +47 -0
  42. package/dist/lib/plot/helpers.d.ts +3 -0
  43. package/dist/lib/plot/preset.d.ts +29 -0
  44. package/dist/lib/plot/scales.d.ts +5 -0
  45. package/dist/lib/plot/stat.d.ts +32 -0
  46. package/dist/lib/plot/types.d.ts +89 -0
  47. package/dist/lib/scales.svelte.d.ts +35 -0
  48. package/dist/lib/swatch.d.ts +12 -0
  49. package/dist/lib/ticks.d.ts +36 -0
  50. package/dist/lib/utils.d.ts +61 -0
  51. package/dist/lib/xscale.d.ts +11 -0
  52. package/dist/patterns/index.d.ts +4 -0
  53. package/dist/patterns/patterns.d.ts +72 -0
  54. package/dist/patterns/scale.d.ts +30 -0
  55. package/dist/symbols/constants/index.d.ts +1 -0
  56. package/dist/symbols/index.d.ts +5 -0
  57. package/package.json +41 -45
  58. package/src/AnimatedPlot.svelte +214 -0
  59. package/src/Chart.svelte +101 -0
  60. package/src/FacetPlot/Panel.svelte +23 -0
  61. package/src/FacetPlot.svelte +90 -0
  62. package/src/Plot/Arc.svelte +29 -0
  63. package/src/Plot/Area.svelte +25 -0
  64. package/src/Plot/Axis.svelte +73 -0
  65. package/src/Plot/Bar.svelte +96 -0
  66. package/src/Plot/Grid.svelte +30 -0
  67. package/src/Plot/Legend.svelte +167 -0
  68. package/src/Plot/Line.svelte +27 -0
  69. package/src/Plot/Point.svelte +27 -0
  70. package/src/Plot/Root.svelte +107 -0
  71. package/src/Plot/Timeline.svelte +95 -0
  72. package/src/Plot/Tooltip.svelte +81 -0
  73. package/src/Plot/index.js +9 -0
  74. package/src/Plot.svelte +189 -0
  75. package/src/PlotState.svelte.js +278 -0
  76. package/src/Sparkline.svelte +69 -0
  77. package/src/Symbol.svelte +21 -0
  78. package/src/Texture.svelte +18 -0
  79. package/src/charts/AreaChart.svelte +25 -0
  80. package/src/charts/BarChart.svelte +26 -0
  81. package/src/charts/BoxPlot.svelte +21 -0
  82. package/src/charts/BubbleChart.svelte +23 -0
  83. package/src/charts/LineChart.svelte +26 -0
  84. package/src/charts/PieChart.svelte +25 -0
  85. package/src/charts/ScatterPlot.svelte +25 -0
  86. package/src/charts/ViolinPlot.svelte +21 -0
  87. package/src/crossfilter/CrossFilter.svelte +38 -0
  88. package/src/crossfilter/FilterBar.svelte +32 -0
  89. package/src/crossfilter/FilterSlider.svelte +79 -0
  90. package/src/crossfilter/createCrossFilter.svelte.js +113 -0
  91. package/src/elements/Bar.svelte +22 -24
  92. package/src/elements/ColorRamp.svelte +20 -22
  93. package/src/elements/ContinuousLegend.svelte +20 -17
  94. package/src/elements/DefinePatterns.svelte +24 -0
  95. package/src/elements/DiscreteLegend.svelte +15 -15
  96. package/src/elements/Label.svelte +4 -8
  97. package/src/elements/SymbolGrid.svelte +22 -0
  98. package/src/elements/index.js +6 -0
  99. package/src/examples/BarChartExample.svelte +81 -0
  100. package/src/geoms/Arc.svelte +81 -0
  101. package/src/geoms/Area.svelte +50 -0
  102. package/src/geoms/Bar.svelte +142 -0
  103. package/src/geoms/Box.svelte +101 -0
  104. package/src/geoms/LabelPill.svelte +17 -0
  105. package/src/geoms/Line.svelte +100 -0
  106. package/src/geoms/Point.svelte +100 -0
  107. package/src/geoms/Violin.svelte +44 -0
  108. package/src/geoms/lib/areas.js +131 -0
  109. package/src/geoms/lib/bars.js +172 -0
  110. package/src/index.js +67 -16
  111. package/src/lib/brewer.js +25 -0
  112. package/src/lib/brewing/BoxBrewer.svelte.js +56 -0
  113. package/src/lib/brewing/CartesianBrewer.svelte.js +16 -0
  114. package/src/lib/brewing/PieBrewer.svelte.js +14 -0
  115. package/src/lib/brewing/ViolinBrewer.svelte.js +55 -0
  116. package/src/lib/brewing/axes.svelte.js +270 -0
  117. package/src/lib/brewing/bars.svelte.js +201 -0
  118. package/src/lib/brewing/brewer.svelte.js +229 -0
  119. package/src/lib/brewing/colors.js +22 -0
  120. package/src/lib/brewing/dimensions.svelte.js +56 -0
  121. package/src/lib/brewing/index.svelte.js +205 -0
  122. package/src/lib/brewing/legends.svelte.js +137 -0
  123. package/src/lib/brewing/marks/arcs.js +43 -0
  124. package/src/lib/brewing/marks/areas.js +59 -0
  125. package/src/lib/brewing/marks/bars.js +49 -0
  126. package/src/lib/brewing/marks/boxes.js +75 -0
  127. package/src/lib/brewing/marks/lines.js +48 -0
  128. package/src/lib/brewing/marks/points.js +57 -0
  129. package/src/lib/brewing/marks/violins.js +90 -0
  130. package/src/lib/brewing/patterns.js +31 -0
  131. package/src/lib/brewing/scales.js +51 -0
  132. package/src/lib/brewing/scales.svelte.js +82 -0
  133. package/src/lib/brewing/stats.js +62 -0
  134. package/src/lib/brewing/symbols.js +10 -0
  135. package/src/lib/brewing/types.js +73 -0
  136. package/src/lib/chart.js +213 -0
  137. package/src/lib/context.js +131 -0
  138. package/src/lib/grid.js +85 -0
  139. package/src/lib/plot/chartProps.js +76 -0
  140. package/src/lib/plot/crossfilter.js +16 -0
  141. package/src/lib/plot/facet.js +58 -0
  142. package/src/lib/plot/frames.js +80 -0
  143. package/src/lib/plot/helpers.js +14 -0
  144. package/src/lib/plot/preset.js +53 -0
  145. package/src/lib/plot/scales.js +56 -0
  146. package/src/lib/plot/stat.js +92 -0
  147. package/src/lib/plot/types.js +65 -0
  148. package/src/lib/scales.svelte.js +151 -0
  149. package/src/lib/swatch.js +13 -0
  150. package/src/lib/ticks.js +46 -0
  151. package/src/lib/utils.js +111 -118
  152. package/src/lib/xscale.js +31 -0
  153. package/src/patterns/DefinePatterns.svelte +32 -0
  154. package/src/patterns/PatternDef.svelte +27 -0
  155. package/src/patterns/README.md +3 -0
  156. package/src/patterns/index.js +4 -0
  157. package/src/patterns/patterns.js +208 -0
  158. package/src/patterns/scale.js +87 -0
  159. package/src/spec/chart-spec.js +29 -0
  160. package/src/symbols/RoundedSquare.svelte +33 -0
  161. package/src/symbols/Shape.svelte +37 -0
  162. package/src/symbols/constants/index.js +4 -0
  163. package/src/symbols/index.js +9 -0
  164. package/src/symbols/outline.svelte +60 -0
  165. package/src/symbols/solid.svelte +60 -0
  166. package/src/chart/FacetGrid.svelte +0 -51
  167. package/src/chart/Grid.svelte +0 -34
  168. package/src/chart/Legend.svelte +0 -16
  169. package/src/chart/PatternDefs.svelte +0 -13
  170. package/src/chart/Swatch.svelte +0 -93
  171. package/src/chart/SwatchButton.svelte +0 -29
  172. package/src/chart/SwatchGrid.svelte +0 -55
  173. package/src/chart/Symbol.svelte +0 -37
  174. package/src/chart/Texture.svelte +0 -16
  175. package/src/chart/TexturedShape.svelte +0 -27
  176. package/src/chart/TimelapseChart.svelte +0 -97
  177. package/src/chart/Timer.svelte +0 -27
  178. package/src/chart.js +0 -9
  179. package/src/components/charts/Axis.svelte +0 -66
  180. package/src/components/charts/Chart.svelte +0 -35
  181. package/src/components/index.js +0 -23
  182. package/src/components/lib/axis.js +0 -0
  183. package/src/components/lib/chart.js +0 -187
  184. package/src/components/lib/color.js +0 -327
  185. package/src/components/lib/funnel.js +0 -204
  186. package/src/components/lib/index.js +0 -19
  187. package/src/components/lib/pattern.js +0 -190
  188. package/src/components/lib/rollup.js +0 -55
  189. package/src/components/lib/shape.js +0 -199
  190. package/src/components/lib/summary.js +0 -145
  191. package/src/components/lib/theme.js +0 -23
  192. package/src/components/lib/timer.js +0 -41
  193. package/src/components/lib/utils.js +0 -165
  194. package/src/components/plots/BarPlot.svelte +0 -36
  195. package/src/components/plots/BoxPlot.svelte +0 -54
  196. package/src/components/plots/ScatterPlot.svelte +0 -30
  197. package/src/components/store.js +0 -70
  198. package/src/constants.js +0 -66
  199. package/src/elements/PatternDefs.svelte +0 -13
  200. package/src/elements/PatternMask.svelte +0 -20
  201. package/src/elements/Symbol.svelte +0 -38
  202. package/src/elements/Tooltip.svelte +0 -23
  203. package/src/funnel.svelte +0 -35
  204. package/src/geom.js +0 -105
  205. package/src/lib/axis.js +0 -75
  206. package/src/lib/colors.js +0 -32
  207. package/src/lib/geom.js +0 -4
  208. package/src/lib/shapes.js +0 -144
  209. package/src/lib/timer.js +0 -44
  210. package/src/lookup.js +0 -29
  211. package/src/plots/BarPlot.svelte +0 -55
  212. package/src/plots/BoxPlot.svelte +0 -0
  213. package/src/plots/FunnelPlot.svelte +0 -33
  214. package/src/plots/HeatMap.svelte +0 -5
  215. package/src/plots/HeatMapCalendar.svelte +0 -129
  216. package/src/plots/LinePlot.svelte +0 -55
  217. package/src/plots/Plot.svelte +0 -25
  218. package/src/plots/RankBarPlot.svelte +0 -38
  219. package/src/plots/ScatterPlot.svelte +0 -20
  220. package/src/plots/ViolinPlot.svelte +0 -11
  221. package/src/plots/heatmap.js +0 -70
  222. package/src/plots/index.js +0 -10
  223. package/src/swatch.js +0 -11
@@ -0,0 +1,172 @@
1
+ import { scaleBand } from 'd3-scale'
2
+ import { stack } from 'd3-shape'
3
+ import { toPatternId } from '../../lib/brewing/patterns.js'
4
+
5
+ /**
6
+ * Returns a band scale suitable for bar x-positioning.
7
+ * When xScale is already a band scale, returns it unchanged.
8
+ * When xScale is a linear scale (numeric x field like year/month),
9
+ * derives a band scale from the distinct values in the data.
10
+ */
11
+ function ensureBandX(xScale, data, xField) {
12
+ if (typeof xScale?.bandwidth === 'function') return xScale
13
+ const [r0, r1] = xScale.range()
14
+ const domain = [...new Set(data.map((d) => d[xField]))]
15
+ return scaleBand().domain(domain).range([r0, r1]).padding(0.2)
16
+ }
17
+
18
+ /**
19
+ * Returns the sub-band fields: distinct non-x fields among [color, pattern].
20
+ * These are the fields that cause multiple bars within a single x-band.
21
+ */
22
+ function subBandFields(channels) {
23
+ const { x: xf, color: cf, pattern: pf } = channels
24
+ const seen = new Set()
25
+ const out = []
26
+ for (const f of [cf, pf]) {
27
+ if (f && f !== xf && !seen.has(f)) { seen.add(f); out.push(f) }
28
+ }
29
+ return out
30
+ }
31
+
32
+ export function buildGroupedBars(data, channels, xScale, yScale, colors, innerHeight, patterns) {
33
+ const { x: xf, y: yf, color: cf, pattern: pf } = channels
34
+
35
+ const bandScale = ensureBandX(xScale, data, xf)
36
+
37
+ // Sub-banding: only fields that differ from x drive grouping within a band
38
+ const subFields = subBandFields(channels)
39
+ const getSubKey = (d) => subFields.map((f) => String(d[f])).join('::')
40
+ const subDomain = subFields.length > 0 ? [...new Set(data.map(getSubKey))] : []
41
+ const subScale = subDomain.length > 1
42
+ ? scaleBand().domain(subDomain).range([0, bandScale.bandwidth()]).padding(0.05)
43
+ : null
44
+
45
+ return data.map((d, i) => {
46
+ const xVal = d[xf]
47
+ const colorKey = cf ? d[cf] : null
48
+ const patternKey = pf ? d[pf] : null
49
+ const subKey = getSubKey(d)
50
+
51
+ const colorEntry = colors?.get(colorKey) ?? colors?.values().next().value ?? { fill: '#888', stroke: '#888' }
52
+ const patternId = patternKey !== null && patternKey !== undefined && patterns?.has(patternKey)
53
+ ? toPatternId(String(patternKey))
54
+ : null
55
+
56
+ const bandX = bandScale(xVal) ?? 0
57
+ const subX = subScale && subKey ? (subScale(subKey) ?? 0) : 0
58
+ const barX = bandX + subX
59
+ const barWidth = subScale ? subScale.bandwidth() : bandScale.bandwidth()
60
+ const barY = yScale(d[yf])
61
+ const barHeight = innerHeight - barY
62
+
63
+ return {
64
+ data: d,
65
+ key: `${String(xVal)}::${subKey}::${i}`,
66
+ x: barX,
67
+ y: barY,
68
+ width: barWidth,
69
+ height: barHeight,
70
+ fill: colorEntry.fill,
71
+ stroke: colorEntry.stroke,
72
+ patternId
73
+ }
74
+ })
75
+ }
76
+
77
+ export function buildStackedBars(data, channels, xScale, yScale, colors, innerHeight, patterns) {
78
+ const { x: xf, y: yf, color: cf, pattern: pf } = channels
79
+
80
+ const bandScale = ensureBandX(xScale, data, xf)
81
+
82
+ // Stack dimension: first non-x grouping field (prefer pattern, then color)
83
+ const subFields = subBandFields(channels)
84
+ if (subFields.length === 0) {
85
+ return buildGroupedBars(data, channels, xScale, yScale, colors, innerHeight, patterns)
86
+ }
87
+ const stackField = subFields[0]
88
+
89
+ const xCategories = [...new Set(data.map((d) => d[xf]))]
90
+ const stackCategories = [...new Set(data.map((d) => d[stackField]))]
91
+
92
+ const lookup = new Map()
93
+ for (const d of data) {
94
+ if (!lookup.has(d[xf])) lookup.set(d[xf], {})
95
+ lookup.get(d[xf])[d[stackField]] = Number(d[yf])
96
+ }
97
+
98
+ const wide = xCategories.map((xVal) => {
99
+ const row = { [xf]: xVal }
100
+ for (const sk of stackCategories) row[sk] = lookup.get(xVal)?.[sk] ?? 0
101
+ return row
102
+ })
103
+
104
+ const stackGen = stack().keys(stackCategories)
105
+ const layers = stackGen(wide)
106
+
107
+ const bars = []
108
+ for (const layer of layers) {
109
+ const stackKey = layer.key
110
+
111
+ for (const point of layer) {
112
+ const [y0, y1] = point
113
+ const xVal = point.data[xf]
114
+
115
+ // Color lookup: cf may equal xf (= xVal) or stackField (= stackKey)
116
+ const colorKey = cf
117
+ ? (cf === xf ? xVal : cf === stackField ? stackKey : null)
118
+ : null
119
+ const colorEntry = colors?.get(colorKey) ?? { fill: '#888', stroke: '#888' }
120
+
121
+ // Pattern lookup: pf may equal xf (= xVal) or stackField (= stackKey)
122
+ const patternKey = pf
123
+ ? (pf === xf ? xVal : pf === stackField ? stackKey : null)
124
+ : null
125
+ const patternId = patternKey !== null && patternKey !== undefined && patterns?.has(patternKey)
126
+ ? toPatternId(String(patternKey))
127
+ : null
128
+
129
+ bars.push({
130
+ data: point.data,
131
+ key: `${String(xVal)}::${String(stackKey)}`,
132
+ x: bandScale(xVal) ?? 0,
133
+ y: yScale(y1),
134
+ width: bandScale.bandwidth(),
135
+ height: yScale(y0) - yScale(y1),
136
+ fill: colorEntry.fill,
137
+ stroke: colorEntry.stroke,
138
+ patternId
139
+ })
140
+ }
141
+ }
142
+ return bars
143
+ }
144
+
145
+ export function buildHorizontalBars(data, channels, xScale, yScale, colors, _innerHeight) {
146
+ const { x: xf, y: yf, color: cf } = channels
147
+ const colorKeys = cf ? [...new Set(data.map((d) => d[cf]))] : []
148
+ const subScale = colorKeys.length > 1
149
+ ? scaleBand().domain(colorKeys).range([0, yScale.bandwidth()]).padding(0.05)
150
+ : null
151
+
152
+ return data.map((d) => {
153
+ const yVal = d[yf]
154
+ const colorKey = cf ? d[cf] : null
155
+ const colorEntry = colors?.get(colorKey) ?? colors?.values().next().value ?? { fill: '#888', stroke: '#888' }
156
+
157
+ const bandY = yScale(yVal) ?? 0
158
+ const subY = subScale ? (subScale(colorKey) ?? 0) : 0
159
+
160
+ return {
161
+ data: d,
162
+ key: `${String(yVal)}::${String(colorKey ?? '')}`,
163
+ x: 0,
164
+ y: bandY + subY,
165
+ width: xScale(d[xf]),
166
+ height: subScale ? subScale.bandwidth() : yScale.bandwidth(),
167
+ fill: colorEntry.fill,
168
+ stroke: colorEntry.stroke,
169
+ patternId: null
170
+ }
171
+ })
172
+ }
package/src/index.js CHANGED
@@ -1,16 +1,67 @@
1
- // export { aes } from './lib/aes'
2
- // export { timelapse } from './lib/timelapse'
3
- // export { axisTicks } from './lib/axis'
4
- export { timer, elapsed } from './lib/timer'
5
- // export { default as Chart } from './chart/Chart.svelte'
6
- // export { default as Axis } from './chart/Axis.svelte'
7
- export { default as Swatch } from './chart/Swatch.svelte'
8
- // export { default as AxisTicks } from './chart/AxisTicks.svelte'
9
- // export { default as AxisGrid } from './chart/AxisGrid.svelte'
10
- // export { default as AxisLabels } from './chart/AxisLabels.svelte'
11
- export { default as BarPlot } from './plots/BarPlot.svelte'
12
- export { default as LinePlot } from './plots/LinePlot.svelte'
13
- export { default as BoxPlot } from './plots/BoxPlot.svelte'
14
- export { default as ViolinPlot } from './plots/ViolinPlot.svelte'
15
- export { default as ScatterPlot } from './plots/ScatterPlot.svelte'
16
- export * from './components/lib'
1
+ import Root from './Plot/Root.svelte'
2
+ import Axis from './Plot/Axis.svelte'
3
+ import Bar from './Plot/Bar.svelte'
4
+ import Grid from './Plot/Grid.svelte'
5
+ import Legend from './Plot/Legend.svelte'
6
+ import Line from './Plot/Line.svelte'
7
+ import Area from './Plot/Area.svelte'
8
+ import Point from './Plot/Point.svelte'
9
+ import Arc from './Plot/Arc.svelte'
10
+
11
+ // Export components (old Plot namespace renamed to avoid collision with new PlotChart export)
12
+ export const PlotLayers = {
13
+ Root,
14
+ Axis,
15
+ Bar,
16
+ Grid,
17
+ Legend,
18
+ Line,
19
+ Area,
20
+ Point,
21
+ Arc
22
+ }
23
+
24
+ // New Plot system
25
+ export { default as PlotChart } from './Plot.svelte'
26
+
27
+ // Facets and Animation
28
+ export { default as FacetPlot } from './FacetPlot.svelte'
29
+ export { default as AnimatedPlot } from './AnimatedPlot.svelte'
30
+
31
+ // Geom components (for declarative use inside PlotChart)
32
+ export { default as GeomBar } from './geoms/Bar.svelte'
33
+ export { default as GeomLine } from './geoms/Line.svelte'
34
+ export { default as GeomArea } from './geoms/Area.svelte'
35
+ export { default as GeomPoint } from './geoms/Point.svelte'
36
+ export { default as GeomArc } from './geoms/Arc.svelte'
37
+ export { default as GeomBox } from './geoms/Box.svelte'
38
+ export { default as GeomViolin } from './geoms/Violin.svelte'
39
+
40
+ // Export standalone components
41
+ export { default as Chart } from './Chart.svelte'
42
+ export { default as Sparkline } from './Sparkline.svelte'
43
+ export { default as BarChart } from './charts/BarChart.svelte'
44
+ export { default as LineChart } from './charts/LineChart.svelte'
45
+ export { default as AreaChart } from './charts/AreaChart.svelte'
46
+ export { default as PieChart } from './charts/PieChart.svelte'
47
+ export { default as ScatterPlot } from './charts/ScatterPlot.svelte'
48
+ export { default as BoxPlot } from './charts/BoxPlot.svelte'
49
+ export { default as ViolinPlot } from './charts/ViolinPlot.svelte'
50
+ export { default as BubbleChart } from './charts/BubbleChart.svelte'
51
+
52
+ // Export state and types
53
+ export { PlotState } from './PlotState.svelte.js'
54
+
55
+ // Export utilities
56
+ export { ChartBrewer } from './lib/brewing/index.svelte.js'
57
+ export * from './lib/brewing/index.svelte.js'
58
+ export { CartesianBrewer } from './lib/brewing/CartesianBrewer.svelte.js'
59
+ export { PieBrewer } from './lib/brewing/PieBrewer.svelte.js'
60
+ export { BoxBrewer } from './lib/brewing/BoxBrewer.svelte.js'
61
+ export { ViolinBrewer } from './lib/brewing/ViolinBrewer.svelte.js'
62
+
63
+ // CrossFilter system
64
+ export { createCrossFilter } from './crossfilter/createCrossFilter.svelte.js'
65
+ export { default as CrossFilter } from './crossfilter/CrossFilter.svelte'
66
+ export { default as FilterBar } from './crossfilter/FilterBar.svelte'
67
+ export { default as FilterSlider } from './crossfilter/FilterSlider.svelte'
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Get fill patterns for a set of values
3
+ *
4
+ * @param {Array} values - Array of values
5
+ * @param {Object} swatch - Object with keys for color, gray, and pattern
6
+ * @param {Boolean} gray - Boolean to determine if gray or color
7
+ * @returns {Object} - Object with keys for pattern and color
8
+ */
9
+ export function getFillPatterns(values, swatch, gray = false) {
10
+ const colors = gray ? swatch.keys.gray : swatch.keys.color
11
+ const max_colors = colors.length
12
+ const max_patterns = swatch.keys.pattern.length
13
+
14
+ const mix = values
15
+ .map((value, index) => ({
16
+ [value]: {
17
+ pattern: swatch.keys.pattern[index % max_patterns],
18
+ color: colors[index % max_colors]
19
+ }
20
+ }))
21
+ .reduce((acc, current) => ({ ...acc, ...current }), {})
22
+ return mix
23
+ }
24
+
25
+ // export function getStrokePatterns() {}
@@ -0,0 +1,56 @@
1
+ import { quantile, ascending } from 'd3-array'
2
+ import { dataset } from '@rokkit/data'
3
+ import { ChartBrewer } from './brewer.svelte.js'
4
+ import { buildBoxes } from './marks/boxes.js'
5
+ import { buildXScale, buildYScale } from './scales.js'
6
+
7
+ function sortedQuantile(values, p) {
8
+ return quantile([...values].sort(ascending), p)
9
+ }
10
+
11
+ /**
12
+ * Brewer for box plots. Always computes quartile statistics regardless of the stat prop.
13
+ * Groups by x + fill (primary) or x + color (fallback).
14
+ * fill = box interior color, color = whisker/outline stroke.
15
+ */
16
+ export class BoxBrewer extends ChartBrewer {
17
+ transform(data, channels) {
18
+ if (!channels.x || !channels.y) return data
19
+ const by = [channels.x, channels.fill ?? channels.color].filter(Boolean)
20
+ return dataset(data)
21
+ .groupBy(...by)
22
+ .summarize((row) => row[channels.y], {
23
+ q1: (v) => sortedQuantile(v, 0.25),
24
+ median: (v) => sortedQuantile(v, 0.5),
25
+ q3: (v) => sortedQuantile(v, 0.75),
26
+ iqr_min: (v) => { const q1 = sortedQuantile(v, 0.25); const q3 = sortedQuantile(v, 0.75); return q1 - 1.5 * (q3 - q1) },
27
+ iqr_max: (v) => { const q1 = sortedQuantile(v, 0.25); const q3 = sortedQuantile(v, 0.75); return q3 + 1.5 * (q3 - q1) }
28
+ })
29
+ .rollup()
30
+ .select()
31
+ }
32
+
33
+ /**
34
+ * Override xScale to use processedData (post-transform rows have the x field).
35
+ */
36
+ xScale = $derived(
37
+ this.channels.x && this.processedData.length > 0
38
+ ? buildXScale(this.processedData, this.channels.x, this.innerWidth)
39
+ : null
40
+ )
41
+
42
+ /**
43
+ * Override yScale to use iqr_max as the upper bound of the quartile data.
44
+ */
45
+ yScale = $derived(
46
+ this.channels.y && this.processedData.length > 0
47
+ ? buildYScale(this.processedData, 'iqr_max', this.innerHeight)
48
+ : null
49
+ )
50
+
51
+ boxes = $derived(
52
+ this.xScale && this.yScale
53
+ ? buildBoxes(this.processedData, this.channels, this.xScale, this.yScale, this.colorMap)
54
+ : []
55
+ )
56
+ }
@@ -0,0 +1,16 @@
1
+ import { ChartBrewer } from './brewer.svelte.js'
2
+ import { applyAggregate } from './stats.js'
3
+
4
+ /**
5
+ * Brewer for cartesian charts (Bar, Line, Area).
6
+ * Groups by x (and fill/color if set) and applies the given stat.
7
+ */
8
+ export class CartesianBrewer extends ChartBrewer {
9
+ transform(data, channels, stat) {
10
+ if (stat === 'identity' || !channels.x || !channels.y) return data
11
+ // Group by all mapped aesthetic dimensions so they survive aggregation.
12
+ // e.g. x=region, fill=region, pattern=quarter → by=['region','quarter']
13
+ const by = [...new Set([channels.x, channels.fill, channels.color, channels.pattern].filter(Boolean))]
14
+ return applyAggregate(data, { by, value: channels.y, stat })
15
+ }
16
+ }
@@ -0,0 +1,14 @@
1
+ import { ChartBrewer } from './brewer.svelte.js'
2
+ import { applyAggregate } from './stats.js'
3
+
4
+ /**
5
+ * Brewer for pie charts. Always aggregates by the label field.
6
+ * 'identity' is not meaningful for pie charts — falls back to 'sum'.
7
+ */
8
+ export class PieBrewer extends ChartBrewer {
9
+ transform(data, channels, stat) {
10
+ if (!channels.label || !channels.y) return data
11
+ const effectiveStat = stat === 'identity' ? 'sum' : (stat ?? 'sum')
12
+ return applyAggregate(data, { by: [channels.label], value: channels.y, stat: effectiveStat })
13
+ }
14
+ }
@@ -0,0 +1,55 @@
1
+ import { quantile, ascending } from 'd3-array'
2
+ import { dataset } from '@rokkit/data'
3
+ import { ChartBrewer } from './brewer.svelte.js'
4
+ import { buildViolins } from './marks/violins.js'
5
+ import { buildXScale, buildYScale } from './scales.js'
6
+
7
+ function sortedQuantile(values, p) {
8
+ return quantile([...values].sort(ascending), p)
9
+ }
10
+
11
+ /**
12
+ * Brewer for violin plots. Computes the same quartile statistics as BoxBrewer.
13
+ * fill = violin body color, color = outline stroke.
14
+ */
15
+ export class ViolinBrewer extends ChartBrewer {
16
+ transform(data, channels) {
17
+ if (!channels.x || !channels.y) return data
18
+ const by = [channels.x, channels.fill ?? channels.color].filter(Boolean)
19
+ return dataset(data)
20
+ .groupBy(...by)
21
+ .summarize((row) => row[channels.y], {
22
+ q1: (v) => sortedQuantile(v, 0.25),
23
+ median: (v) => sortedQuantile(v, 0.5),
24
+ q3: (v) => sortedQuantile(v, 0.75),
25
+ iqr_min: (v) => { const q1 = sortedQuantile(v, 0.25); const q3 = sortedQuantile(v, 0.75); return q1 - 1.5 * (q3 - q1) },
26
+ iqr_max: (v) => { const q1 = sortedQuantile(v, 0.25); const q3 = sortedQuantile(v, 0.75); return q3 + 1.5 * (q3 - q1) }
27
+ })
28
+ .rollup()
29
+ .select()
30
+ }
31
+
32
+ /**
33
+ * Override xScale to use processedData (post-transform rows have the x field).
34
+ */
35
+ xScale = $derived(
36
+ this.channels.x && this.processedData.length > 0
37
+ ? buildXScale(this.processedData, this.channels.x, this.innerWidth)
38
+ : null
39
+ )
40
+
41
+ /**
42
+ * Override yScale to use iqr_max as the upper bound of the quartile data.
43
+ */
44
+ yScale = $derived(
45
+ this.channels.y && this.processedData.length > 0
46
+ ? buildYScale(this.processedData, 'iqr_max', this.innerHeight)
47
+ : null
48
+ )
49
+
50
+ violins = $derived(
51
+ this.xScale && this.yScale
52
+ ? buildViolins(this.processedData, this.channels, this.xScale, this.yScale, this.colorMap)
53
+ : []
54
+ )
55
+ }