@rokkit/chart 1.0.0-next.12 → 1.0.0-next.121

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 (148) hide show
  1. package/README.md +132 -46
  2. package/dist/Plot/index.d.ts +5 -0
  3. package/dist/elements/index.d.ts +6 -0
  4. package/dist/index.d.ts +14 -0
  5. package/dist/lib/brewing/axes.svelte.d.ts +72 -0
  6. package/dist/lib/brewing/bars.svelte.d.ts +54 -0
  7. package/dist/lib/brewing/dimensions.svelte.d.ts +35 -0
  8. package/dist/lib/brewing/index.svelte.d.ts +118 -0
  9. package/dist/lib/brewing/legends.svelte.d.ts +54 -0
  10. package/dist/lib/brewing/scales.svelte.d.ts +29 -0
  11. package/dist/lib/brewing/types.d.ts +162 -0
  12. package/dist/lib/context.d.ts +13 -0
  13. package/dist/lib/scales.svelte.d.ts +35 -0
  14. package/dist/lib/utils.d.ts +58 -0
  15. package/dist/old_lib/brewer.d.ts +9 -0
  16. package/dist/old_lib/chart.d.ts +40 -0
  17. package/dist/old_lib/grid.d.ts +72 -0
  18. package/dist/old_lib/index.d.ts +4 -0
  19. package/dist/old_lib/plots.d.ts +3 -0
  20. package/dist/old_lib/swatch.d.ts +285 -0
  21. package/dist/old_lib/ticks.d.ts +36 -0
  22. package/dist/old_lib/utils.d.ts +1 -0
  23. package/dist/patterns/index.d.ts +9 -0
  24. package/dist/patterns/paths/constants.d.ts +1 -0
  25. package/dist/symbols/constants/index.d.ts +1 -0
  26. package/dist/symbols/index.d.ts +5 -0
  27. package/dist/template/constants.d.ts +43 -0
  28. package/dist/template/shapes/index.d.ts +4 -0
  29. package/package.json +28 -44
  30. package/src/Plot/Axis.svelte +103 -0
  31. package/src/Plot/Bar.svelte +95 -0
  32. package/src/Plot/Grid.svelte +68 -0
  33. package/src/Plot/Legend.svelte +129 -0
  34. package/src/Plot/Root.svelte +112 -0
  35. package/src/Plot/index.js +5 -0
  36. package/src/Symbol.svelte +21 -0
  37. package/src/{chart/Texture.svelte → Texture.svelte} +3 -3
  38. package/src/elements/Bar.svelte +2 -8
  39. package/src/elements/ColorRamp.svelte +3 -5
  40. package/src/elements/ContinuousLegend.svelte +4 -5
  41. package/src/elements/DefinePatterns.svelte +22 -0
  42. package/src/elements/DiscreteLegend.svelte +3 -5
  43. package/src/elements/Label.svelte +6 -5
  44. package/src/elements/SymbolGrid.svelte +23 -0
  45. package/src/elements/index.js +6 -0
  46. package/src/examples/BarChartExample.svelte +81 -0
  47. package/src/index.js +18 -16
  48. package/src/lib/brewing/axes.svelte.js +179 -0
  49. package/src/lib/brewing/bars.svelte.js +114 -0
  50. package/src/lib/brewing/dimensions.svelte.js +54 -0
  51. package/src/lib/brewing/index.svelte.js +214 -0
  52. package/src/lib/brewing/legends.svelte.js +95 -0
  53. package/src/lib/brewing/scales.svelte.js +94 -0
  54. package/src/lib/brewing/types.js +73 -0
  55. package/src/lib/context.js +122 -0
  56. package/src/lib/scales.svelte.js +129 -0
  57. package/src/lib/utils.js +110 -132
  58. package/src/old_lib/brewer.js +25 -0
  59. package/src/old_lib/chart.js +213 -0
  60. package/src/old_lib/grid.js +85 -0
  61. package/src/old_lib/index.js +4 -0
  62. package/src/old_lib/plots.js +27 -0
  63. package/src/old_lib/swatch.js +16 -0
  64. package/src/old_lib/ticks.js +46 -0
  65. package/src/old_lib/utils.js +8 -0
  66. package/src/patterns/Brick.svelte +17 -0
  67. package/src/patterns/Circles.svelte +18 -0
  68. package/src/patterns/CrossHatch.svelte +14 -0
  69. package/src/patterns/CurvedWave.svelte +9 -0
  70. package/src/patterns/Dots.svelte +19 -0
  71. package/src/patterns/OutlineCircles.svelte +15 -0
  72. package/src/patterns/Tile.svelte +17 -0
  73. package/src/patterns/Triangles.svelte +15 -0
  74. package/src/patterns/Waves.svelte +13 -0
  75. package/src/patterns/index.js +14 -0
  76. package/src/patterns/paths/NamedPattern.svelte +12 -0
  77. package/src/patterns/paths/constants.js +4 -0
  78. package/src/symbols/RoundedSquare.svelte +27 -0
  79. package/src/symbols/Shape.svelte +31 -0
  80. package/src/symbols/constants/index.js +4 -0
  81. package/src/symbols/index.js +9 -0
  82. package/src/symbols/outline.svelte +60 -0
  83. package/src/symbols/solid.svelte +60 -0
  84. package/src/template/Texture.svelte +16 -0
  85. package/src/template/constants.js +43 -0
  86. package/src/template/shapes/Circles.svelte +16 -0
  87. package/src/template/shapes/Lines.svelte +17 -0
  88. package/src/template/shapes/Path.svelte +12 -0
  89. package/src/template/shapes/Polygons.svelte +18 -0
  90. package/src/template/shapes/index.js +4 -0
  91. package/LICENSE +0 -21
  92. package/src/chart/FacetGrid.svelte +0 -51
  93. package/src/chart/Grid.svelte +0 -34
  94. package/src/chart/Legend.svelte +0 -16
  95. package/src/chart/PatternDefs.svelte +0 -13
  96. package/src/chart/Swatch.svelte +0 -93
  97. package/src/chart/SwatchButton.svelte +0 -29
  98. package/src/chart/SwatchGrid.svelte +0 -55
  99. package/src/chart/Symbol.svelte +0 -37
  100. package/src/chart/TexturedShape.svelte +0 -27
  101. package/src/chart/TimelapseChart.svelte +0 -97
  102. package/src/chart/Timer.svelte +0 -27
  103. package/src/chart.js +0 -9
  104. package/src/components/charts/Axis.svelte +0 -66
  105. package/src/components/charts/Chart.svelte +0 -35
  106. package/src/components/index.js +0 -23
  107. package/src/components/lib/axis.js +0 -0
  108. package/src/components/lib/chart.js +0 -187
  109. package/src/components/lib/color.js +0 -327
  110. package/src/components/lib/funnel.js +0 -204
  111. package/src/components/lib/index.js +0 -19
  112. package/src/components/lib/pattern.js +0 -190
  113. package/src/components/lib/rollup.js +0 -55
  114. package/src/components/lib/shape.js +0 -199
  115. package/src/components/lib/summary.js +0 -145
  116. package/src/components/lib/theme.js +0 -23
  117. package/src/components/lib/timer.js +0 -41
  118. package/src/components/lib/utils.js +0 -165
  119. package/src/components/plots/BarPlot.svelte +0 -36
  120. package/src/components/plots/BoxPlot.svelte +0 -54
  121. package/src/components/plots/ScatterPlot.svelte +0 -30
  122. package/src/components/store.js +0 -70
  123. package/src/constants.js +0 -66
  124. package/src/elements/PatternDefs.svelte +0 -13
  125. package/src/elements/PatternMask.svelte +0 -20
  126. package/src/elements/Symbol.svelte +0 -38
  127. package/src/elements/Tooltip.svelte +0 -23
  128. package/src/funnel.svelte +0 -35
  129. package/src/geom.js +0 -105
  130. package/src/lib/axis.js +0 -75
  131. package/src/lib/colors.js +0 -32
  132. package/src/lib/geom.js +0 -4
  133. package/src/lib/shapes.js +0 -144
  134. package/src/lib/timer.js +0 -44
  135. package/src/lookup.js +0 -29
  136. package/src/plots/BarPlot.svelte +0 -55
  137. package/src/plots/BoxPlot.svelte +0 -0
  138. package/src/plots/FunnelPlot.svelte +0 -33
  139. package/src/plots/HeatMap.svelte +0 -5
  140. package/src/plots/HeatMapCalendar.svelte +0 -129
  141. package/src/plots/LinePlot.svelte +0 -55
  142. package/src/plots/Plot.svelte +0 -25
  143. package/src/plots/RankBarPlot.svelte +0 -38
  144. package/src/plots/ScatterPlot.svelte +0 -20
  145. package/src/plots/ViolinPlot.svelte +0 -11
  146. package/src/plots/heatmap.js +0 -70
  147. package/src/plots/index.js +0 -10
  148. package/src/swatch.js +0 -11
@@ -0,0 +1,114 @@
1
+ import { } from './types.js';
2
+
3
+ /**
4
+ * @typedef {import('./types').BarData} BarData
5
+ * @typedef {import('./types').ScaleFields} ScaleFields
6
+ * @typedef {import('./types').ChartScales} ChartScales
7
+ * @typedef {import('./types').ChartDimensions} ChartDimensions
8
+ */
9
+
10
+ /**
11
+ * Creates bar data for rendering
12
+ *
13
+ * @param {Array} data - Chart data
14
+ * @param {Object} fields - Field mappings
15
+ * @param {string} fields.x - X-axis field
16
+ * @param {string} fields.y - Y-axis field
17
+ * @param {string} fields.color - Color field (optional)
18
+ * @param {Object} scales - Chart scales
19
+ * @param {Function} scales.x - X-axis scale
20
+ * @param {Function} scales.y - Y-axis scale
21
+ * @param {Function} scales.color - Color scale
22
+ * @param {Object} dimensions - Chart dimensions
23
+ * @param {string} defaultColor - Default color if no color scale is provided
24
+ * @returns {BarData[]} Bar data for rendering
25
+ */
26
+ export function createBars(data, fields, scales, dimensions, defaultColor = '#4682b4') {
27
+ if (!data || data.length === 0 || !scales.x || !scales.y) return [];
28
+
29
+ const { x: xField, y: yField, color: colorField } = fields;
30
+
31
+ return data.map(d => {
32
+ const barWidth = scales.x.bandwidth ? scales.x.bandwidth() : 10;
33
+ const barX = scales.x.bandwidth ? scales.x(d[xField]) : scales.x(d[xField]) - barWidth / 2;
34
+
35
+ return {
36
+ data: d,
37
+ x: barX,
38
+ y: scales.y(d[yField]),
39
+ width: barWidth,
40
+ height: dimensions.innerHeight - scales.y(d[yField]),
41
+ color: colorField && scales.color ? scales.color(d[colorField]) : defaultColor
42
+ };
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Filter bars based on a selection criteria
48
+ *
49
+ * @param {BarData[]} bars - Bar data array
50
+ * @param {Object} selection - Selection criteria
51
+ * @returns {BarData[]} Filtered bars
52
+ */
53
+ export function filterBars(bars, selection) {
54
+ if (!selection) return bars;
55
+
56
+ return bars.filter(bar => {
57
+ for (const [key, value] of Object.entries(selection)) {
58
+ if (bar.data[key] !== value) return false;
59
+ }
60
+ return true;
61
+ });
62
+ }
63
+
64
+ /**
65
+ * Creates a grouped bars layout
66
+ *
67
+ * @param {Array} data - Chart data
68
+ * @param {Object} fields - Field mappings
69
+ * @param {Object} scales - Chart scales
70
+ * @param {Object} dimensions - Chart dimensions
71
+ * @param {Object} options - Options
72
+ * @returns {Object} Grouped bar data
73
+ */
74
+ export function createGroupedBars(data, fields, scales, dimensions, options = {}) {
75
+ if (!data || data.length === 0 || !fields.group) return { groups: [], bars: [] };
76
+
77
+ const { x: xField, y: yField, group: groupField, color: colorField = groupField } = fields;
78
+ const { padding = 0.1 } = options;
79
+
80
+ // Get unique groups and x values
81
+ const groups = [...new Set(data.map(d => d[groupField]))];
82
+ const xValues = [...new Set(data.map(d => d[xField]))];
83
+
84
+ // Calculate group width and individual bar width
85
+ const xScale = scales.x;
86
+ const groupWidth = xScale.bandwidth ? xScale.bandwidth() : 20;
87
+ const barWidth = (groupWidth - padding * (groups.length - 1)) / groups.length;
88
+
89
+ // Create bars for each group
90
+ const bars = [];
91
+
92
+ xValues.forEach(xValue => {
93
+ const groupItems = data.filter(d => d[xField] === xValue);
94
+ const xPos = xScale(xValue);
95
+
96
+ groups.forEach((group, i) => {
97
+ const item = groupItems.find(d => d[groupField] === group);
98
+ if (!item) return;
99
+
100
+ const barX = xPos + i * (barWidth + padding);
101
+ bars.push({
102
+ data: item,
103
+ group,
104
+ x: barX,
105
+ y: scales.y(item[yField]),
106
+ width: barWidth,
107
+ height: dimensions.innerHeight - scales.y(item[yField]),
108
+ color: scales.color ? scales.color(item[colorField]) : '#4682b4'
109
+ });
110
+ });
111
+ });
112
+
113
+ return { groups, bars };
114
+ }
@@ -0,0 +1,54 @@
1
+ import { } from './types.js';
2
+
3
+ /**
4
+ * @typedef {import('./types').ChartMargin} ChartMargin
5
+ * @typedef {import('./types').ChartDimensions} ChartDimensions
6
+ */
7
+
8
+ /**
9
+ * Default chart margin
10
+ * @type {ChartMargin}
11
+ */
12
+ export const DEFAULT_MARGIN = { top: 20, right: 30, bottom: 40, left: 50 };
13
+
14
+ /**
15
+ * Creates chart dimensions based on width, height and margins
16
+ *
17
+ * @param {number} width - Total chart width
18
+ * @param {number} height - Total chart height
19
+ * @param {ChartMargin} margin - Chart margins
20
+ * @returns {ChartDimensions} Chart dimensions
21
+ */
22
+ export function createDimensions(width = 600, height = 400, margin = DEFAULT_MARGIN) {
23
+ return {
24
+ width,
25
+ height,
26
+ margin: { ...margin },
27
+ innerWidth: width - margin.left - margin.right,
28
+ innerHeight: height - margin.top - margin.bottom
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Updates existing dimensions with new values
34
+ *
35
+ * @param {ChartDimensions} dimensions - Current dimensions
36
+ * @param {Object} updates - Values to update
37
+ * @param {number} [updates.width] - New width
38
+ * @param {number} [updates.height] - New height
39
+ * @param {ChartMargin} [updates.margin] - New margin
40
+ * @returns {ChartDimensions} Updated dimensions
41
+ */
42
+ export function updateDimensions(dimensions, updates = {}) {
43
+ const newDimensions = { ...dimensions };
44
+
45
+ if (updates.width !== undefined) newDimensions.width = updates.width;
46
+ if (updates.height !== undefined) newDimensions.height = updates.height;
47
+ if (updates.margin !== undefined) newDimensions.margin = { ...updates.margin };
48
+
49
+ // Recalculate inner dimensions
50
+ newDimensions.innerWidth = newDimensions.width - newDimensions.margin.left - newDimensions.margin.right;
51
+ newDimensions.innerHeight = newDimensions.height - newDimensions.margin.top - newDimensions.margin.bottom;
52
+
53
+ return newDimensions;
54
+ }
@@ -0,0 +1,214 @@
1
+ import { createDimensions, updateDimensions } from './dimensions.svelte.js';
2
+ import { createScales, getOrigin } from './scales.svelte.js';
3
+ import { createBars, filterBars, createGroupedBars } from './bars.svelte.js';
4
+ import {
5
+ createXAxis,
6
+ createYAxis,
7
+ createGrid,
8
+ createTickAttributes
9
+ } from './axes.svelte.js';
10
+ import {
11
+ createLegend,
12
+ filterByLegend,
13
+ createLegendItemAttributes
14
+ } from './legends.svelte.js';
15
+
16
+ /**
17
+ * Chart Brewing - A collection of pure functions for chart data preparation
18
+ */
19
+ export {
20
+ // Dimensions
21
+ createDimensions,
22
+ updateDimensions,
23
+
24
+ // Scales
25
+ createScales,
26
+ getOrigin,
27
+
28
+ // Bars
29
+ createBars,
30
+ filterBars,
31
+ createGroupedBars,
32
+
33
+ // Axes
34
+ createXAxis,
35
+ createYAxis,
36
+ createGrid,
37
+ createTickAttributes,
38
+
39
+ // Legends
40
+ createLegend,
41
+ filterByLegend,
42
+ createLegendItemAttributes
43
+ };
44
+
45
+ /**
46
+ * Main class that manages chart state and provides access to all brewing functions
47
+ */
48
+ export class ChartBrewer {
49
+ #data = [];
50
+ #dimensions = createDimensions();
51
+ #scales = { x: null, y: null, color: null };
52
+ #fields = { x: null, y: null, color: null };
53
+ #options = {
54
+ padding: 0.2,
55
+ animationDuration: 300
56
+ };
57
+
58
+ /**
59
+ * Creates a new ChartBrewer instance
60
+ *
61
+ * @param {Object} options Configuration options
62
+ */
63
+ constructor(options = {}) {
64
+ this.#dimensions = createDimensions(
65
+ options.width,
66
+ options.height,
67
+ options.margin
68
+ );
69
+
70
+ if (options.padding !== undefined) this.#options.padding = options.padding;
71
+ if (options.animationDuration !== undefined) this.#options.animationDuration = options.animationDuration;
72
+ }
73
+
74
+ /**
75
+ * Sets the data for the chart
76
+ *
77
+ * @param {Array} data Data array
78
+ * @returns {ChartBrewer} this for method chaining
79
+ */
80
+ setData(data) {
81
+ this.#data = Array.isArray(data) ? data : [];
82
+ return this;
83
+ }
84
+
85
+ /**
86
+ * Sets the field mappings for axes and color
87
+ *
88
+ * @param {Object} fields Field mappings
89
+ * @returns {ChartBrewer} this for method chaining
90
+ */
91
+ setFields({ x, y, color }) {
92
+ if (x !== undefined) this.#fields.x = x;
93
+ if (y !== undefined) this.#fields.y = y;
94
+ if (color !== undefined) this.#fields.color = color;
95
+ return this;
96
+ }
97
+
98
+ /**
99
+ * Sets the dimensions of the chart
100
+ *
101
+ * @param {Object} dimensions Chart dimensions
102
+ * @returns {ChartBrewer} this for method chaining
103
+ */
104
+ setDimensions({ width, height, margin }) {
105
+ this.#dimensions = updateDimensions(this.#dimensions, { width, height, margin });
106
+ return this;
107
+ }
108
+
109
+ /**
110
+ * Creates scales based on data and dimensions
111
+ *
112
+ * @returns {ChartBrewer} this for method chaining
113
+ */
114
+ createScales() {
115
+ this.#scales = createScales(this.#data, this.#fields, this.#dimensions, {
116
+ padding: this.#options.padding
117
+ });
118
+ return this;
119
+ }
120
+
121
+ /**
122
+ * Creates bar data for rendering
123
+ *
124
+ * @returns {Array} Data for rendering bars
125
+ */
126
+ createBars() {
127
+ return createBars(this.#data, this.#fields, this.#scales, this.#dimensions);
128
+ }
129
+
130
+ /**
131
+ * Creates x-axis tick data for rendering
132
+ *
133
+ * @param {Object} options Axis options
134
+ * @returns {Object} Axis rendering data
135
+ */
136
+ createXAxis(options = {}) {
137
+ return createXAxis(this.#scales, this.#dimensions, options);
138
+ }
139
+
140
+ /**
141
+ * Creates y-axis tick data for rendering
142
+ *
143
+ * @param {Object} options Axis options
144
+ * @returns {Object} Axis rendering data
145
+ */
146
+ createYAxis(options = {}) {
147
+ return createYAxis(this.#scales, this.#dimensions, options);
148
+ }
149
+
150
+ /**
151
+ * Creates grid line data for rendering
152
+ *
153
+ * @param {Object} options Grid options
154
+ * @returns {Object} Grid rendering data
155
+ */
156
+ createGrid(options = {}) {
157
+ return createGrid(this.#scales, this.#dimensions, options);
158
+ }
159
+
160
+ /**
161
+ * Creates legend data for rendering
162
+ *
163
+ * @param {Object} options Legend options
164
+ * @returns {Object} Legend rendering data
165
+ */
166
+ createLegend(options = {}) {
167
+ return createLegend(this.#data, this.#fields, this.#scales, this.#dimensions, options);
168
+ }
169
+
170
+ /**
171
+ * Gets all chart dimensions
172
+ *
173
+ * @returns {Object} Chart dimensions
174
+ */
175
+ getDimensions() {
176
+ return { ...this.#dimensions };
177
+ }
178
+
179
+ /**
180
+ * Gets all chart scales
181
+ *
182
+ * @returns {Object} Chart scales
183
+ */
184
+ getScales() {
185
+ return { ...this.#scales };
186
+ }
187
+
188
+ /**
189
+ * Gets the animation duration
190
+ *
191
+ * @returns {number} Animation duration in ms
192
+ */
193
+ getAnimationDuration() {
194
+ return this.#options.animationDuration;
195
+ }
196
+
197
+ /**
198
+ * Gets the data being used
199
+ *
200
+ * @returns {Array} Chart data
201
+ */
202
+ getData() {
203
+ return [...this.#data];
204
+ }
205
+
206
+ /**
207
+ * Gets the fields configuration
208
+ *
209
+ * @returns {Object} Fields configuration
210
+ */
211
+ getFields() {
212
+ return { ...this.#fields };
213
+ }
214
+ }
@@ -0,0 +1,95 @@
1
+ import { } from './types.js';
2
+
3
+ /**
4
+ * @typedef {import('./types').LegendItem} LegendItem
5
+ * @typedef {import('./types').LegendData} LegendData
6
+ * @typedef {import('./types').ScaleFields} ScaleFields
7
+ * @typedef {import('./types').ChartScales} ChartScales
8
+ * @typedef {import('./types').ChartDimensions} ChartDimensions
9
+ */
10
+
11
+ /**
12
+ * Creates legend data for rendering
13
+ *
14
+ * @param {Array} data - Chart data
15
+ * @param {Object} fields - Field mappings
16
+ * @param {string} fields.color - Color field
17
+ * @param {Object} scales - Chart scales
18
+ * @param {Function} scales.color - Color scale
19
+ * @param {Object} dimensions - Chart dimensions
20
+ * @param {Object} options - Legend options
21
+ * @param {string} [options.title=''] - Legend title
22
+ * @param {string} [options.align='right'] - Legend alignment ('left', 'center', or 'right')
23
+ * @param {string} [options.shape='rect'] - Legend marker shape ('rect' or 'circle')
24
+ * @param {number} [options.markerSize=10] - Size of legend markers
25
+ * @returns {LegendData} Legend rendering data
26
+ */
27
+ export function createLegend(data, fields, scales, dimensions, options = {}) {
28
+ if (!data || !fields.color || !scales.color) {
29
+ return { items: [], title: '', transform: 'translate(0, 0)' };
30
+ }
31
+
32
+ const { title = '', align = 'right', shape = 'rect', markerSize = 10 } = options;
33
+
34
+ // Get unique color values
35
+ const colorValues = [...new Set(data.map(d => d[fields.color]))];
36
+
37
+ // Create legend items
38
+ const items = colorValues.map((value, index) => ({
39
+ value,
40
+ color: scales.color(value),
41
+ y: index * (markerSize + 5) + (title ? 15 : 0),
42
+ shape,
43
+ markerSize
44
+ }));
45
+
46
+ // Calculate approximate width for alignment
47
+ const approximateWidth = Math.max(
48
+ ...colorValues.map(v => v.toString().length)
49
+ ) * 8 + markerSize + 10;
50
+
51
+ // Calculate position based on alignment
52
+ let x = 0;
53
+ if (align === 'right') {
54
+ x = dimensions.innerWidth - approximateWidth;
55
+ } else if (align === 'center') {
56
+ x = (dimensions.innerWidth - approximateWidth) / 2;
57
+ }
58
+
59
+ return {
60
+ items,
61
+ title,
62
+ transform: `translate(${x}, 0)`
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Filter data based on legend selection
68
+ *
69
+ * @param {Array} data - Chart data
70
+ * @param {string} colorField - Field used for color mapping
71
+ * @param {Array} selectedValues - Selected legend values
72
+ * @returns {Array} Filtered data
73
+ */
74
+ export function filterByLegend(data, colorField, selectedValues) {
75
+ if (!selectedValues || selectedValues.length === 0) {
76
+ return data;
77
+ }
78
+
79
+ return data.filter(d => selectedValues.includes(d[colorField]));
80
+ }
81
+
82
+ /**
83
+ * Create attributes for legend items
84
+ *
85
+ * @param {LegendItem} item - Legend item
86
+ * @returns {Object} Attributes for the legend item
87
+ */
88
+ export function createLegendItemAttributes(item) {
89
+ return {
90
+ 'data-plot-legend-item': '',
91
+ 'transform': `translate(0, ${item.y})`,
92
+ 'role': 'img',
93
+ 'aria-label': `Legend item for ${item.value}`
94
+ };
95
+ }
@@ -0,0 +1,94 @@
1
+ import { min, max } from 'd3-array';
2
+ import { scaleBand, scaleLinear, scaleTime, scaleOrdinal } from 'd3-scale';
3
+ import { schemeCategory10 } from 'd3-scale-chromatic';
4
+ import { } from './types.js';
5
+
6
+ /**
7
+ * @typedef {import('./types').ChartScales} ChartScales
8
+ * @typedef {import('./types').ScaleFields} ScaleFields
9
+ * @typedef {import('./types').ChartDimensions} ChartDimensions
10
+ */
11
+
12
+ /**
13
+ * Creates scales based on data, fields, and dimensions
14
+ *
15
+ * @param {Array} data - Chart data
16
+ * @param {ScaleFields} fields - Field mappings
17
+ * @param {Object} dimensions - Chart dimensions
18
+ * @param {Object} options - Scale options
19
+ * @param {number} [options.padding=0.2] - Padding for band scales
20
+ * @returns {ChartScales} Chart scales
21
+ */
22
+ export function createScales(data, fields, dimensions, options = {}) {
23
+ const scales = {
24
+ x: null,
25
+ y: null,
26
+ color: null
27
+ };
28
+
29
+ if (!data || data.length === 0 || !fields.x || !fields.y) {
30
+ return scales;
31
+ }
32
+
33
+ const padding = options.padding !== undefined ? options.padding : 0.2;
34
+
35
+ // Extract values
36
+ const xValues = data.map(d => d[fields.x]);
37
+ const yValues = data.map(d => d[fields.y]);
38
+
39
+ // Determine x scale type
40
+ const xIsDate = xValues.some(v => v instanceof Date);
41
+ const xIsNumeric = !xIsDate && xValues.every(v => !isNaN(parseFloat(v)));
42
+
43
+ // Create x scale based on data type
44
+ if (xIsDate) {
45
+ scales.x = scaleTime()
46
+ .domain([min(xValues), max(xValues)])
47
+ .range([0, dimensions.innerWidth])
48
+ .nice();
49
+ } else if (xIsNumeric) {
50
+ scales.x = scaleLinear()
51
+ .domain([min([0, ...xValues]), max(xValues)])
52
+ .range([0, dimensions.innerWidth])
53
+ .nice();
54
+ } else {
55
+ scales.x = scaleBand()
56
+ .domain(xValues)
57
+ .range([0, dimensions.innerWidth])
58
+ .padding(padding);
59
+ }
60
+
61
+ // Create y scale
62
+ scales.y = scaleLinear()
63
+ .domain([0, max(yValues) * 1.1]) // Add 10% padding on top
64
+ .nice()
65
+ .range([dimensions.innerHeight, 0]);
66
+
67
+ // Create color scale if color field is set
68
+ if (fields.color) {
69
+ const colorValues = [...new Set(data.map(d => d[fields.color]))];
70
+ scales.color = scaleOrdinal()
71
+ .domain(colorValues)
72
+ .range(schemeCategory10);
73
+ }
74
+
75
+ return scales;
76
+ }
77
+
78
+ /**
79
+ * Gets the origin coordinates for the axes
80
+ *
81
+ * @param {ChartScales} scales - Chart scales
82
+ * @param {Object} dimensions - Chart dimensions
83
+ * @returns {Object} Origin coordinates
84
+ */
85
+ export function getOrigin(scales, dimensions) {
86
+ return {
87
+ x: scales.y ? scales.y(0) : dimensions.innerHeight,
88
+ y: scales.x ? (
89
+ scales.x.ticks
90
+ ? scales.x(Math.max(0, min(scales.x.domain())))
91
+ : 0
92
+ ) : 0
93
+ };
94
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @typedef {Object} ChartMargin
3
+ * @property {number} top - Top margin
4
+ * @property {number} right - Right margin
5
+ * @property {number} bottom - Bottom margin
6
+ * @property {number} left - Left margin
7
+ */
8
+
9
+ /**
10
+ * @typedef {Object} ChartDimensions
11
+ * @property {number} width - Total chart width
12
+ * @property {number} height - Total chart height
13
+ * @property {ChartMargin} margin - Chart margins
14
+ * @property {number} innerWidth - Chart width without margins
15
+ * @property {number} innerHeight - Chart height without margins
16
+ */
17
+
18
+ /**
19
+ * @typedef {Object} ChartScales
20
+ * @property {Function} x - X-axis scale function
21
+ * @property {Function} y - Y-axis scale function
22
+ * @property {Function} color - Color scale function
23
+ */
24
+
25
+ /**
26
+ * @typedef {Object} ScaleFields
27
+ * @property {string} x - X-axis field
28
+ * @property {string} y - Y-axis field
29
+ * @property {string} color - Color field
30
+ */
31
+
32
+ /**
33
+ * @typedef {Object} TickData
34
+ * @property {*} value - Tick value
35
+ * @property {number} position - Tick position in pixels
36
+ * @property {string} formattedValue - Formatted tick label
37
+ */
38
+
39
+ /**
40
+ * @typedef {Object} AxisData
41
+ * @property {TickData[]} ticks - Tick data
42
+ * @property {string} label - Axis label
43
+ * @property {string} transform - SVG transform attribute value
44
+ * @property {string} labelTransform - SVG transform for the label
45
+ */
46
+
47
+ /**
48
+ * @typedef {Object} BarData
49
+ * @property {Object} data - Original data point
50
+ * @property {number} x - X position
51
+ * @property {number} y - Y position
52
+ * @property {number} width - Width of the bar
53
+ * @property {number} height - Height of the bar
54
+ * @property {string} color - Color of the bar
55
+ */
56
+
57
+ /**
58
+ * @typedef {Object} LegendItem
59
+ * @property {*} value - Legend item value
60
+ * @property {string} color - Item color
61
+ * @property {number} y - Y position
62
+ * @property {string} shape - Shape type ('rect' or 'circle')
63
+ * @property {number} markerSize - Size of the marker
64
+ */
65
+
66
+ /**
67
+ * @typedef {Object} LegendData
68
+ * @property {LegendItem[]} items - Legend items
69
+ * @property {string} title - Legend title
70
+ * @property {string} transform - SVG transform attribute value
71
+ */
72
+
73
+ export {};