@rokkit/chart 1.0.0-next.13 → 1.0.0-next.131

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 (149) hide show
  1. package/README.md +140 -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 +95 -0
  31. package/src/Plot/Bar.svelte +96 -0
  32. package/src/Plot/Grid.svelte +68 -0
  33. package/src/Plot/Legend.svelte +127 -0
  34. package/src/Plot/Root.svelte +107 -0
  35. package/src/Plot/index.js +5 -0
  36. package/src/Symbol.svelte +21 -0
  37. package/src/Texture.svelte +10 -0
  38. package/src/elements/Bar.svelte +22 -24
  39. package/src/elements/ColorRamp.svelte +20 -22
  40. package/src/elements/ContinuousLegend.svelte +20 -17
  41. package/src/elements/DefinePatterns.svelte +24 -0
  42. package/src/elements/DiscreteLegend.svelte +15 -15
  43. package/src/elements/Label.svelte +11 -8
  44. package/src/elements/SymbolGrid.svelte +27 -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 +177 -0
  49. package/src/lib/brewing/bars.svelte.js +114 -0
  50. package/src/lib/brewing/dimensions.svelte.js +56 -0
  51. package/src/lib/brewing/index.svelte.js +202 -0
  52. package/src/lib/brewing/legends.svelte.js +94 -0
  53. package/src/lib/brewing/scales.svelte.js +85 -0
  54. package/src/lib/brewing/types.js +73 -0
  55. package/src/lib/context.js +132 -0
  56. package/src/lib/scales.svelte.js +122 -0
  57. package/src/lib/utils.js +96 -120
  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 +15 -0
  67. package/src/patterns/Circles.svelte +18 -0
  68. package/src/patterns/CrossHatch.svelte +12 -0
  69. package/src/patterns/CurvedWave.svelte +7 -0
  70. package/src/patterns/Dots.svelte +20 -0
  71. package/src/patterns/OutlineCircles.svelte +13 -0
  72. package/src/patterns/Tile.svelte +16 -0
  73. package/src/patterns/Triangles.svelte +13 -0
  74. package/src/patterns/Waves.svelte +9 -0
  75. package/src/patterns/index.js +14 -0
  76. package/src/patterns/paths/NamedPattern.svelte +9 -0
  77. package/src/patterns/paths/constants.js +4 -0
  78. package/src/symbols/RoundedSquare.svelte +22 -0
  79. package/src/symbols/Shape.svelte +24 -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 +13 -0
  85. package/src/template/constants.js +43 -0
  86. package/src/template/shapes/Circles.svelte +13 -0
  87. package/src/template/shapes/Lines.svelte +14 -0
  88. package/src/template/shapes/Path.svelte +9 -0
  89. package/src/template/shapes/Polygons.svelte +9 -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/Texture.svelte +0 -16
  101. package/src/chart/TexturedShape.svelte +0 -27
  102. package/src/chart/TimelapseChart.svelte +0 -97
  103. package/src/chart/Timer.svelte +0 -27
  104. package/src/chart.js +0 -9
  105. package/src/components/charts/Axis.svelte +0 -66
  106. package/src/components/charts/Chart.svelte +0 -35
  107. package/src/components/index.js +0 -23
  108. package/src/components/lib/axis.js +0 -0
  109. package/src/components/lib/chart.js +0 -187
  110. package/src/components/lib/color.js +0 -327
  111. package/src/components/lib/funnel.js +0 -204
  112. package/src/components/lib/index.js +0 -19
  113. package/src/components/lib/pattern.js +0 -190
  114. package/src/components/lib/rollup.js +0 -55
  115. package/src/components/lib/shape.js +0 -199
  116. package/src/components/lib/summary.js +0 -145
  117. package/src/components/lib/theme.js +0 -23
  118. package/src/components/lib/timer.js +0 -41
  119. package/src/components/lib/utils.js +0 -165
  120. package/src/components/plots/BarPlot.svelte +0 -36
  121. package/src/components/plots/BoxPlot.svelte +0 -54
  122. package/src/components/plots/ScatterPlot.svelte +0 -30
  123. package/src/components/store.js +0 -70
  124. package/src/constants.js +0 -66
  125. package/src/elements/PatternDefs.svelte +0 -13
  126. package/src/elements/PatternMask.svelte +0 -20
  127. package/src/elements/Symbol.svelte +0 -38
  128. package/src/elements/Tooltip.svelte +0 -23
  129. package/src/funnel.svelte +0 -35
  130. package/src/geom.js +0 -105
  131. package/src/lib/axis.js +0 -75
  132. package/src/lib/colors.js +0 -32
  133. package/src/lib/geom.js +0 -4
  134. package/src/lib/shapes.js +0 -144
  135. package/src/lib/timer.js +0 -44
  136. package/src/lookup.js +0 -29
  137. package/src/plots/BarPlot.svelte +0 -55
  138. package/src/plots/BoxPlot.svelte +0 -0
  139. package/src/plots/FunnelPlot.svelte +0 -33
  140. package/src/plots/HeatMap.svelte +0 -5
  141. package/src/plots/HeatMapCalendar.svelte +0 -129
  142. package/src/plots/LinePlot.svelte +0 -55
  143. package/src/plots/Plot.svelte +0 -25
  144. package/src/plots/RankBarPlot.svelte +0 -38
  145. package/src/plots/ScatterPlot.svelte +0 -20
  146. package/src/plots/ViolinPlot.svelte +0 -11
  147. package/src/plots/heatmap.js +0 -70
  148. package/src/plots/index.js +0 -10
  149. 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,56 @@
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 =
51
+ newDimensions.width - newDimensions.margin.left - newDimensions.margin.right
52
+ newDimensions.innerHeight =
53
+ newDimensions.height - newDimensions.margin.top - newDimensions.margin.bottom
54
+
55
+ return newDimensions
56
+ }
@@ -0,0 +1,202 @@
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 { createXAxis, createYAxis, createGrid, createTickAttributes } from './axes.svelte.js'
5
+ import { createLegend, filterByLegend, createLegendItemAttributes } from './legends.svelte.js'
6
+
7
+ /**
8
+ * Chart Brewing - A collection of pure functions for chart data preparation
9
+ */
10
+ export {
11
+ // Dimensions
12
+ createDimensions,
13
+ updateDimensions,
14
+
15
+ // Scales
16
+ createScales,
17
+ getOrigin,
18
+
19
+ // Bars
20
+ createBars,
21
+ filterBars,
22
+ createGroupedBars,
23
+
24
+ // Axes
25
+ createXAxis,
26
+ createYAxis,
27
+ createGrid,
28
+ createTickAttributes,
29
+
30
+ // Legends
31
+ createLegend,
32
+ filterByLegend,
33
+ createLegendItemAttributes
34
+ }
35
+
36
+ /**
37
+ * Main class that manages chart state and provides access to all brewing functions
38
+ */
39
+ export class ChartBrewer {
40
+ #data = []
41
+ #dimensions = createDimensions()
42
+ #scales = { x: null, y: null, color: null }
43
+ #fields = { x: null, y: null, color: null }
44
+ #options = {
45
+ padding: 0.2,
46
+ animationDuration: 300
47
+ }
48
+
49
+ /**
50
+ * Creates a new ChartBrewer instance
51
+ *
52
+ * @param {Object} options Configuration options
53
+ */
54
+ constructor(options = {}) {
55
+ this.#dimensions = createDimensions(options.width, options.height, options.margin)
56
+
57
+ if (options.padding !== undefined) this.#options.padding = options.padding
58
+ if (options.animationDuration !== undefined)
59
+ this.#options.animationDuration = options.animationDuration
60
+ }
61
+
62
+ /**
63
+ * Sets the data for the chart
64
+ *
65
+ * @param {Array} data Data array
66
+ * @returns {ChartBrewer} this for method chaining
67
+ */
68
+ setData(data) {
69
+ this.#data = Array.isArray(data) ? data : []
70
+ return this
71
+ }
72
+
73
+ /**
74
+ * Sets the field mappings for axes and color
75
+ *
76
+ * @param {Object} fields Field mappings
77
+ * @returns {ChartBrewer} this for method chaining
78
+ */
79
+ setFields({ x, y, color }) {
80
+ if (x !== undefined) this.#fields.x = x
81
+ if (y !== undefined) this.#fields.y = y
82
+ if (color !== undefined) this.#fields.color = color
83
+ return this
84
+ }
85
+
86
+ /**
87
+ * Sets the dimensions of the chart
88
+ *
89
+ * @param {Object} dimensions Chart dimensions
90
+ * @returns {ChartBrewer} this for method chaining
91
+ */
92
+ setDimensions({ width, height, margin }) {
93
+ this.#dimensions = updateDimensions(this.#dimensions, { width, height, margin })
94
+ return this
95
+ }
96
+
97
+ /**
98
+ * Creates scales based on data and dimensions
99
+ *
100
+ * @returns {ChartBrewer} this for method chaining
101
+ */
102
+ createScales() {
103
+ this.#scales = createScales(this.#data, this.#fields, this.#dimensions, {
104
+ padding: this.#options.padding
105
+ })
106
+ return this
107
+ }
108
+
109
+ /**
110
+ * Creates bar data for rendering
111
+ *
112
+ * @returns {Array} Data for rendering bars
113
+ */
114
+ createBars() {
115
+ return createBars(this.#data, this.#fields, this.#scales, this.#dimensions)
116
+ }
117
+
118
+ /**
119
+ * Creates x-axis tick data for rendering
120
+ *
121
+ * @param {Object} options Axis options
122
+ * @returns {Object} Axis rendering data
123
+ */
124
+ createXAxis(options = {}) {
125
+ return createXAxis(this.#scales, this.#dimensions, options)
126
+ }
127
+
128
+ /**
129
+ * Creates y-axis tick data for rendering
130
+ *
131
+ * @param {Object} options Axis options
132
+ * @returns {Object} Axis rendering data
133
+ */
134
+ createYAxis(options = {}) {
135
+ return createYAxis(this.#scales, this.#dimensions, options)
136
+ }
137
+
138
+ /**
139
+ * Creates grid line data for rendering
140
+ *
141
+ * @param {Object} options Grid options
142
+ * @returns {Object} Grid rendering data
143
+ */
144
+ createGrid(options = {}) {
145
+ return createGrid(this.#scales, this.#dimensions, options)
146
+ }
147
+
148
+ /**
149
+ * Creates legend data for rendering
150
+ *
151
+ * @param {Object} options Legend options
152
+ * @returns {Object} Legend rendering data
153
+ */
154
+ createLegend(options = {}) {
155
+ return createLegend(this.#data, this.#fields, this.#scales, this.#dimensions, options)
156
+ }
157
+
158
+ /**
159
+ * Gets all chart dimensions
160
+ *
161
+ * @returns {Object} Chart dimensions
162
+ */
163
+ getDimensions() {
164
+ return { ...this.#dimensions }
165
+ }
166
+
167
+ /**
168
+ * Gets all chart scales
169
+ *
170
+ * @returns {Object} Chart scales
171
+ */
172
+ getScales() {
173
+ return { ...this.#scales }
174
+ }
175
+
176
+ /**
177
+ * Gets the animation duration
178
+ *
179
+ * @returns {number} Animation duration in ms
180
+ */
181
+ getAnimationDuration() {
182
+ return this.#options.animationDuration
183
+ }
184
+
185
+ /**
186
+ * Gets the data being used
187
+ *
188
+ * @returns {Array} Chart data
189
+ */
190
+ getData() {
191
+ return [...this.#data]
192
+ }
193
+
194
+ /**
195
+ * Gets the fields configuration
196
+ *
197
+ * @returns {Object} Fields configuration
198
+ */
199
+ getFields() {
200
+ return { ...this.#fields }
201
+ }
202
+ }
@@ -0,0 +1,94 @@
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 =
48
+ Math.max(...colorValues.map((v) => v.toString().length)) * 8 + markerSize + 10
49
+
50
+ // Calculate position based on alignment
51
+ let x = 0
52
+ if (align === 'right') {
53
+ x = dimensions.innerWidth - approximateWidth
54
+ } else if (align === 'center') {
55
+ x = (dimensions.innerWidth - approximateWidth) / 2
56
+ }
57
+
58
+ return {
59
+ items,
60
+ title,
61
+ transform: `translate(${x}, 0)`
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Filter data based on legend selection
67
+ *
68
+ * @param {Array} data - Chart data
69
+ * @param {string} colorField - Field used for color mapping
70
+ * @param {Array} selectedValues - Selected legend values
71
+ * @returns {Array} Filtered data
72
+ */
73
+ export function filterByLegend(data, colorField, selectedValues) {
74
+ if (!selectedValues || selectedValues.length === 0) {
75
+ return data
76
+ }
77
+
78
+ return data.filter((d) => selectedValues.includes(d[colorField]))
79
+ }
80
+
81
+ /**
82
+ * Create attributes for legend items
83
+ *
84
+ * @param {LegendItem} item - Legend item
85
+ * @returns {Object} Attributes for the legend item
86
+ */
87
+ export function createLegendItemAttributes(item) {
88
+ return {
89
+ 'data-plot-legend-item': '',
90
+ transform: `translate(0, ${item.y})`,
91
+ role: 'img',
92
+ 'aria-label': `Legend item for ${item.value}`
93
+ }
94
+ }
@@ -0,0 +1,85 @@
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().domain(xValues).range([0, dimensions.innerWidth]).padding(padding)
56
+ }
57
+
58
+ // Create y scale
59
+ scales.y = scaleLinear()
60
+ .domain([0, max(yValues) * 1.1]) // Add 10% padding on top
61
+ .nice()
62
+ .range([dimensions.innerHeight, 0])
63
+
64
+ // Create color scale if color field is set
65
+ if (fields.color) {
66
+ const colorValues = [...new Set(data.map((d) => d[fields.color]))]
67
+ scales.color = scaleOrdinal().domain(colorValues).range(schemeCategory10)
68
+ }
69
+
70
+ return scales
71
+ }
72
+
73
+ /**
74
+ * Gets the origin coordinates for the axes
75
+ *
76
+ * @param {ChartScales} scales - Chart scales
77
+ * @param {Object} dimensions - Chart dimensions
78
+ * @returns {Object} Origin coordinates
79
+ */
80
+ export function getOrigin(scales, dimensions) {
81
+ return {
82
+ x: scales.y ? scales.y(0) : dimensions.innerHeight,
83
+ y: scales.x ? (scales.x.ticks ? scales.x(Math.max(0, min(scales.x.domain()))) : 0) : 0
84
+ }
85
+ }
@@ -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 {}