@rokkit/chart 1.0.0-next.87 → 1.0.0-next.89

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 (80) hide show
  1. package/package.json +11 -6
  2. package/src/Chart.svelte +67 -0
  3. package/src/PatternDefs.svelte +14 -0
  4. package/src/Symbol.svelte +17 -0
  5. package/src/{chart/Texture.svelte → Texture.svelte} +3 -3
  6. package/src/elements/Bar.svelte +2 -2
  7. package/src/elements/ContinuousLegend.svelte +3 -2
  8. package/src/elements/DefinePatterns.svelte +22 -0
  9. package/src/elements/DiscreteLegend.svelte +1 -1
  10. package/src/elements/Label.svelte +7 -5
  11. package/src/elements/SymbolGrid.svelte +23 -0
  12. package/src/elements/index.js +6 -0
  13. package/src/index.js +5 -15
  14. package/src/lib/brewer.js +17 -0
  15. package/src/lib/chart.js +179 -160
  16. package/src/lib/grid.js +68 -0
  17. package/src/lib/index.js +4 -0
  18. package/src/lib/palette.js +279 -28
  19. package/src/lib/plots.js +23 -0
  20. package/src/lib/swatch.js +24 -8
  21. package/src/lib/ticks.js +19 -0
  22. package/src/patterns/Brick.svelte +17 -0
  23. package/src/patterns/Circles.svelte +18 -0
  24. package/src/patterns/CrossHatch.svelte +14 -0
  25. package/src/patterns/CurvedWave.svelte +9 -0
  26. package/src/patterns/Dots.svelte +19 -0
  27. package/src/patterns/OutlineCircles.svelte +15 -0
  28. package/src/patterns/Texture.svelte +20 -0
  29. package/src/patterns/Tile.svelte +17 -0
  30. package/src/patterns/Triangles.svelte +15 -0
  31. package/src/patterns/Waves.svelte +13 -0
  32. package/src/patterns/constants.js +43 -0
  33. package/src/patterns/index.js +13 -0
  34. package/src/patterns/paths/NamedPattern.svelte +12 -0
  35. package/src/patterns/paths/constants.js +7 -0
  36. package/src/patterns/templates/Circles.svelte +18 -0
  37. package/src/patterns/templates/Lines.svelte +17 -0
  38. package/src/patterns/templates/Path.svelte +17 -0
  39. package/src/patterns/templates/index.js +3 -0
  40. package/src/plots/Plot.svelte +36 -21
  41. package/src/plots/index.js +1 -10
  42. package/src/symbols/RoundedSquare.svelte +27 -0
  43. package/src/symbols/Shape.svelte +31 -0
  44. package/src/symbols/constants/index.js +7 -0
  45. package/src/symbols/index.js +9 -0
  46. package/src/chart/Axis.svelte +0 -81
  47. package/src/chart/AxisGrid.svelte +0 -22
  48. package/src/chart/Chart.svelte +0 -40
  49. package/src/chart/FacetGrid.svelte +0 -49
  50. package/src/chart/Legend.svelte +0 -16
  51. package/src/chart/Swatch.svelte +0 -84
  52. package/src/chart/SwatchButton.svelte +0 -29
  53. package/src/chart/SwatchGrid.svelte +0 -53
  54. package/src/chart/TexturedShape.svelte +0 -20
  55. package/src/chart/TimelapseChart.svelte +0 -90
  56. package/src/chart/Timer.svelte +0 -27
  57. package/src/elements/Tooltip.svelte +0 -19
  58. package/src/lib/axis.js +0 -77
  59. package/src/lib/color.js +0 -55
  60. package/src/lib/constants.js +0 -41
  61. package/src/lib/funnel.js +0 -230
  62. package/src/lib/geom.js +0 -99
  63. package/src/lib/heatmap.js +0 -68
  64. package/src/lib/lookup.js +0 -29
  65. package/src/lib/pattern.js +0 -182
  66. package/src/lib/rollup.js +0 -49
  67. package/src/lib/shape.js +0 -46
  68. package/src/lib/store.js +0 -63
  69. package/src/lib/summary.js +0 -28
  70. package/src/lib/theme.js +0 -31
  71. package/src/lib/utils.js +0 -158
  72. package/src/plots/BarPlot.svelte +0 -51
  73. package/src/plots/BarPlot2.svelte +0 -34
  74. package/src/plots/BoxPlot.svelte +0 -54
  75. package/src/plots/FunnelPlot.svelte +0 -26
  76. package/src/plots/HeatMapCalendar.svelte +0 -121
  77. package/src/plots/LinePlot.svelte +0 -51
  78. package/src/plots/RankBarPlot.svelte +0 -38
  79. package/src/plots/ScatterPlot.svelte +0 -28
  80. package/src/plots/ViolinPlot.svelte +0 -10
@@ -1,182 +0,0 @@
1
- import { clamp } from 'yootils'
2
- import { ColorBrewer } from './color'
3
- import { toHexString, uniqueId, addToArray, toArray } from './utils'
4
-
5
- export const builtIn = [
6
- { path: 'M0 5A6 6 0 0 0 10 5', minAngle: 0, maxAngle: 90 },
7
- { path: 'M0 10L10 0', minAngle: 0, maxAngle: 90 },
8
- { path: 'M0 0A10 10 0 0 0 10 10', minAngle: 0, maxAngle: 90 },
9
- { path: 'M0 0L10 10', minAngle: 0, maxAngle: 90 },
10
- { path: 'M10 5A6 6 0 0 0 0 5', minAngle: 0, maxAngle: 90 },
11
-
12
- { path: 'M10 10A10 10 0 0 0 0 0', minAngle: 0, maxAngle: 90 },
13
- { path: 'M0 0L10 10ZM10 0L0 10Z', minAngle: 0, maxAngle: 90 },
14
- { path: 'M1 1L9 1L9 9L1 9Z', minAngle: 0, maxAngle: 90 },
15
- { path: 'M4 0L4 10M6 10L6 0M0 4L10 4M10 6L0 6', minAngle: 0, maxAngle: 90 },
16
- { path: 'M0 2L8 10M2 0L10 8M0 8L8 0M2 10L10 2', minAngle: 0, maxAngle: 90 },
17
-
18
- {
19
- path: 'M5 1A 4 4 0 0 0 9 5A4 4 0 0 0 5 9A4 4 0 0 0 1 5A4 4 0 0 0 5 1',
20
- minAngle: 0,
21
- maxAngle: 45
22
- },
23
- { path: 'M1 3L7 9M3 1L9 7M1 7L7 1M3 9L9 3', minAngle: 0, maxAngle: 90 },
24
- {
25
- path: 'M2 2A4 4 0 0 0 8 2A4 4 0 0 0 8 8A4 4 0 0 0 2 8A4 4 0 0 0 2 2',
26
- minAngle: 0,
27
- maxAngle: 90
28
- },
29
- {
30
- path: 'M0 0A5 5 0 0 0 10 0A5 5 0 0 0 10 10A5 5 0 0 0 0 10A5 5 0 0 0 0 0',
31
- minAngle: 0,
32
- maxAngle: 45
33
- },
34
- {
35
- path: 'M5 2A 3 3 0 0 0 8 5A3 3 0 0 0 5 8A3 3 0 0 0 2 5A3 3 0 0 0 5 2',
36
- minAngle: 0,
37
- maxAngle: 90
38
- },
39
-
40
- { path: 'M2 5L5 2L8 5L5 8Z', minAngle: 0, maxAngle: 90 },
41
- {
42
- path: 'M3 5A2 2 0 0 0 7 5A2 2 0 0 0 3 5M1 5L9 5M5 1L5 9',
43
- minAngle: 0,
44
- maxAngle: 90
45
- },
46
- {
47
- path: 'M2 8L8 2ZM1.5 3.5L3.5 1.5ZM6.5 8.5L8.5 6.5ZM0 0L10 10Z',
48
- minAngle: 0,
49
- maxAngle: 90
50
- },
51
-
52
- {
53
- path:
54
- 'M2 8L8 2ZM1.5 3.5L3.5 1.5Z' +
55
- 'M6.5 8.5L8.5 6.5Z' +
56
- 'M2 2L8 8M1.5 6.5L3.5 8.5' +
57
- 'M6.5 1.5L8.5 3.5',
58
- minAngle: 0,
59
- maxAngle: 90
60
- },
61
-
62
- {
63
- path: 'M5 1 A6 6 0 0 0 5 9' + 'A6 6 0 0 0 5 1' + 'M1 5A6 6 0 0 0 9 5A6 6 0 0 0 1 5',
64
- minAngle: 0,
65
- maxAngle: 90
66
- },
67
- {
68
- path:
69
- 'M1.5 5A1 1 0 0 0 3.5 5A1 1 0 0 0 1.5 5' +
70
- 'M6.5 5A1 1 0 0 0 8.5 5A1 1 0 0 0 6.5 5' +
71
- 'M5 1.5A1 1 0 0 0 5 3.5A1 1 0 0 0 5 1.5' +
72
- 'M5 6.5A1 1 0 0 0 5 8.5A1 1 0 0 0 5 6.5',
73
- minAngle: 0,
74
- maxAngle: 90
75
- },
76
- {
77
- path:
78
- 'M1.5 2.5A1 1 0 0 0 3.5 2.5A1 1 0 0 0 1.5 2.5' +
79
- 'M6.5 2.5A1 1 0 0 0 8.5 2.5A1 1 0 0 0 6.5 2.5' +
80
- 'M2.5 6.5A1 1 0 0 0 2.5 8.5A1 1 0 0 0 2.5 6.5' +
81
- 'M7.5 6.5A1 1 0 0 0 7.5 8.5A1 1 0 0 0 7.5 6.5' +
82
- 'M3.5 5A1 1 0 0 0 6.5 5A1 1 0 0 0 3.5 5',
83
- minAngle: 0,
84
- maxAngle: 90
85
- },
86
- {
87
- path: 'M5 0L6 4L10 5L6 6L5 10L4 6L0 5L4 4Z' + 'M2 1V3M1 2H3' + 'M8 9V7M9 8H7',
88
- minAngle: 0,
89
- maxAngle: 90
90
- },
91
- { path: 'M5 2L2.5 9L8.8 4.6L1.2 4.6L7.5 9Z', minAngle: 0, maxAngle: 90 },
92
- {
93
- path: 'M0 5A5 5 0 0 0 5 0' + 'M5 10A5 5 0 0 0 0 5' + 'M5 10A5 5 0 0 0 5 0',
94
- minAngle: 0,
95
- maxAngle: 90
96
- },
97
- {
98
- path: 'M0 0L10 10M5 0L10 5M0 5 L5 10',
99
- minAngle: 0,
100
- maxAngle: 90
101
- },
102
- {
103
- path: 'M0 0L10 10M3 0L10 7M0 7 L3 10',
104
- minAngle: 0,
105
- maxAngle: 90
106
- }
107
- ]
108
-
109
- export class PatternBrewer {
110
- constructor() {
111
- this.paths = builtIn
112
- this.shades = []
113
- this.gray = new ColorBrewer().gray()
114
- this.bw = false
115
- this.repeat = false
116
- this.indices = [...this.paths.keys()]
117
- }
118
-
119
- clear() {
120
- this.paths = []
121
- }
122
-
123
- add(path) {
124
- this.paths = addToArray(this.pathc, path)
125
- return this
126
- }
127
-
128
- filter(indices) {
129
- indices = toArray(indices)
130
- this.indices = indices.filter((i) => i >= 0 && i < this.paths.length)
131
- return this
132
- }
133
-
134
- colors(shades, repeat = false) {
135
- this.shades = toArray(shades)
136
- this.repeat = repeat
137
- return this
138
- }
139
-
140
- variants(count) {
141
- count = clamp(count, 1, 15)
142
- this.paths = this.paths.map((path) => ({
143
- ...path,
144
- angles: [...Array(count).keys()].map((i) => (i * (path.maxAngle - path.minAngle)) / count)
145
- }))
146
- return this
147
- }
148
-
149
- brew() {
150
- // const hexPrefix = toHexString(prefix)
151
- const hexPrefix = uniqueId()
152
-
153
- let patterns = []
154
-
155
- // apply filter and add angle variations
156
- this.indices
157
- .map((i) => this.paths[i])
158
- .map((path) => {
159
- if ('angles' in path) {
160
- path.angles.map((angle) => patterns.push({ ...path, angle }))
161
- } else {
162
- patterns.push(path)
163
- }
164
- })
165
-
166
- patterns = patterns
167
- // Add reference ids
168
- .map((path, index) => ({
169
- id: hexPrefix + '-' + toHexString(index),
170
- ...path,
171
- fillUrl: `url(#${hexPrefix}-${toHexString(index)})`
172
- }))
173
- // Add colors
174
- .map((pattern, i) => {
175
- return i < this.shades.length || this.repeat
176
- ? { ...pattern, ...this.shades[i % this.shades.length] }
177
- : { ...pattern, ...this.gray }
178
- })
179
-
180
- return patterns
181
- }
182
- }
package/src/lib/rollup.js DELETED
@@ -1,49 +0,0 @@
1
- import { min, max, add, format } from 'date-fns'
2
-
3
- export function uniques(data, attr) {
4
- return data && attr ? [...new Set(data.map((item) => item[attr]))] : []
5
- }
6
-
7
- export function slidingWindow(values, size, step, offset, fmt) {
8
- return size && typeof size === 'object'
9
- ? slidingWindowForDates(values, size, step, offset, fmt)
10
- : slidingWindowForNumbers(values, size, step, offset, fmt)
11
- }
12
-
13
- function slidingWindowForNumbers(values, size, step, offset = 0, fmt = 0) {
14
- const smallest = Number(Math.min(...values).toFixed(fmt))
15
- let largest = Math.max(...values)
16
- let count = Math.ceil((largest - smallest + offset) / step)
17
-
18
- if (smallest + count * step + offset == largest) {
19
- count += 1
20
- }
21
-
22
- const range = [...Array(count).keys()]
23
-
24
- const result = range.map((key) => ({
25
- key: smallest + key * step,
26
- lowerBound: smallest + key * step + offset,
27
- upperBound: smallest + key * step + offset + size
28
- }))
29
- return result
30
- }
31
-
32
- function slidingWindowForDates(values, size, step, offset = {}, fmt = 'yyyy-MM-dd') {
33
- const largest = max(values)
34
- let current = new Date(format(min(values), fmt))
35
- let blocks = []
36
- let lowerBound = current
37
-
38
- while (lowerBound <= largest) {
39
- lowerBound = add(current, offset)
40
-
41
- blocks.push({
42
- key: current,
43
- lowerBound,
44
- upperBound: add(lowerBound, size)
45
- })
46
- current = add(current, step)
47
- }
48
- return blocks
49
- }
package/src/lib/shape.js DELETED
@@ -1,46 +0,0 @@
1
- import { ColorBrewer } from './color'
2
- import { symbols } from '@rokkit/atoms/symbols'
3
- import { addToArray, toArray } from './utils'
4
- export class ShapeBrewer {
5
- constructor() {
6
- this.shapes = Object.keys(symbols)
7
- this.repeat = false
8
- this.keys = Object.keys(this.shapes)
9
- this.gray = new ColorBrewer().gray()
10
- this.shades = []
11
- this.repeat = false
12
- }
13
-
14
- clear() {
15
- this.shapes = []
16
- return this
17
- }
18
-
19
- add(shape) {
20
- this.shapes = addToArray(this.shapes, shape)
21
-
22
- return this
23
- }
24
-
25
- filter(keys) {
26
- this.keys = toArray(keys).filter((key) => key in this.shapes)
27
-
28
- return this
29
- }
30
-
31
- colors(shades, repeat = false) {
32
- this.shades = toArray(shades)
33
- this.repeat = repeat
34
- return this
35
- }
36
-
37
- brew() {
38
- return this.keys
39
- .map((i) => this.shapes[i])
40
- .map((shape, i) => {
41
- return i < this.shades.length || this.repeat
42
- ? { shape, ...this.shades[i % this.shades.length] }
43
- : { shape, ...this.gray }
44
- })
45
- }
46
- }
package/src/lib/store.js DELETED
@@ -1,63 +0,0 @@
1
- // import { writable } from 'svelte/store'
2
- import { tweened, cubicOut } from 'svelte/motion'
3
- // function createChart() {
4
- // const { subscribe, set } = writable({
5
- // data: [],
6
- // x: '',
7
- // y: ''
8
- // })
9
- // return { subscribe, set }
10
- // }
11
-
12
- export function animatedChart(input, key, valueFields = [], previous = []) {
13
- const previousKeys = new Set(previous.map((item) => item[key]))
14
- const currentKeys = new Set(input.map((item) => item[key]))
15
- const toAdd = new Set([...currentKeys].filter((key) => !previousKeys.has(key)))
16
- const toRemove = new Set([...previousKeys].filter((key) => !currentKeys.has(key)))
17
-
18
- let data = input
19
- .filter((item) => toAdd.has(item[key]))
20
- .map((item) => {
21
- let el = { ...item }
22
- valueFields.forEach(
23
- ({ field, initialValue, attrs }) =>
24
- (el[field] = typeof initialValue === 'function' ? initialValue(el, attrs) : initialValue)
25
- )
26
- return el
27
- })
28
- let prev = previous
29
- .filter((item) => !toRemove.has(item[key]))
30
- .map((item) => {
31
- let el = { ...item }
32
- valueFields.forEach(
33
- ({ field, initialValue, attrs }) =>
34
- (el[field] =
35
- typeof initialValue === 'function'
36
- ? initialValue(el, { ...attrs, isPrevious: true })
37
- : initialValue)
38
- )
39
- return el
40
- })
41
- data = [...prev, ...data]
42
-
43
- return tweened(data, { duration: 500, easing: cubicOut })
44
- }
45
- // function createAxis() {
46
- // const { subscribe, set } = writable({})
47
-
48
- // let data
49
- // let x = {}
50
- // let y = {}
51
-
52
- // // find origin & orientation
53
- // function getOriginAndOrientation(data, x, y) {
54
- // this.data = data
55
- // this.x = x
56
- // this.y = y
57
- // }
58
- // function init(config, data) {}
59
- // return { subscribe, init, set, getOriginAndOrientation }
60
- // }
61
-
62
- // export const chart = createChart()
63
- // export const axis = createAxis()
@@ -1,28 +0,0 @@
1
- import { sum, median, max, mean, min, quantile, cumsum } from 'd3-array'
2
- import { nest } from 'd3-collection'
3
- import { pick, flatten } from 'ramda'
4
-
5
- export const aggregate = {
6
- count: (values) => values.length,
7
- sum: (values) => sum(values),
8
- min: (values) => min(values),
9
- max: (values) => max(values),
10
- mean: (values) => mean(values),
11
- median: (values) => median(values),
12
- cumsum: (values) => cumsum(values),
13
- q1: (values) => quantile(values, 0.25),
14
- q3: (values) => quantile(values, 0.75)
15
- }
16
-
17
- export function summarize(data, by, attr, stat = 'count') {
18
- const stats = Array.isArray(stat) ? stat : [stat]
19
- const grouped = nest()
20
- .key((d) => by.map((f) => d[f]).join('|'))
21
- .rollup((rows) => {
22
- let agg = pick(by, rows[0])
23
- stats.map((stat) => (agg[stat] = aggregate[stat](rows.map((d) => d[attr]))))
24
- return [agg]
25
- })
26
- .entries(data)
27
- return flatten(grouped.map((group) => group.value))
28
- }
package/src/lib/theme.js DELETED
@@ -1,31 +0,0 @@
1
- import { builtIn as patterns } from './pattern'
2
- import { namedShapes as shapes } from './shape'
3
- import { builtIn as symbols } from './shape'
4
- import { colors, palette } from './color'
5
- /**
6
- *
7
- */
8
- export class ThemeBrewer {
9
- constructor() {
10
- this.patterns = []
11
- this.shapes = []
12
- this.palette = []
13
- this.defaults = {}
14
- }
15
- }
16
-
17
- export const builtIn = {
18
- colors,
19
- palette,
20
- patterns,
21
- shapes,
22
- symbols,
23
- tick: {
24
- size: {
25
- major: 6,
26
- minor: 4,
27
- end: 6,
28
- padding: 3
29
- }
30
- }
31
- }
package/src/lib/utils.js DELETED
@@ -1,158 +0,0 @@
1
- import { scaleBand, scaleLinear } from 'd3-scale'
2
- import { min, max } from 'd3-array'
3
- import { ascending, quantile } from 'd3-array'
4
- import { nest } from 'd3-collection'
5
- import { omit } from 'ramda'
6
-
7
- export function toArray(value) {
8
- return Array.isArray(value) ? value : [value]
9
- }
10
- export function addToArray(array, value) {
11
- return [...array, ...toArray(value)]
12
- }
13
- /**
14
- * Calculates a grid of centres to fit a list of items of `size` within the number of `columns` and `rows`.
15
- *
16
- * - Attempts to find a best fit square if both columns and rows are not specified
17
- * - Value in columns is prioritized over rows for recalculating the grid
18
- * - Supports padding between the items
19
- *
20
- * @param {number} count
21
- * @param {number} size
22
- * @param {number} pad
23
- * @param {number} columns
24
- * @param {number} rows
25
- * @returns
26
- */
27
- export function swatch(count, size, pad = 0, columns, rows) {
28
- if (columns > 0) {
29
- rows = Math.ceil(count / columns)
30
- } else if (rows > 0) {
31
- columns = Math.ceil(count / rows)
32
- } else {
33
- columns = Math.ceil(Math.sqrt(count))
34
- rows = Math.ceil(count / columns)
35
- }
36
-
37
- const width = (size + pad) * columns + pad
38
- const height = (size + pad) * rows + pad
39
- const data = [...Array(count).keys()].map((index) => ({
40
- cx: (size + pad) / 2 + (index % columns) * (size + pad),
41
- cy: (size + pad) / 2 + Math.floor(index / columns) * (size + pad),
42
- r: size / 2
43
- }))
44
-
45
- return { width, height, data }
46
- }
47
- /**
48
- * Get a scale function mapping the values between a range of lower and upper values
49
- *
50
- * @param {Array} values
51
- * @param {Array[2]} bounds
52
- * @param {number} buffer
53
- * @returns
54
- */
55
- export function getScale(values, bounds, buffer = 0, ordinal = false) {
56
- if (ordinal || values.some(isNaN)) {
57
- return scaleBand().range(bounds).domain(values).padding(0.5)
58
- } else {
59
- values = values.map((x) => +x)
60
-
61
- let minValue = min([...values, 0])
62
- let maxValue = max(values)
63
-
64
- if (minValue < 0 && maxValue > 0) {
65
- maxValue = max([-1 * minValue, maxValue])
66
- minValue = -1 * maxValue
67
- }
68
- const margin = (maxValue - minValue) * buffer
69
- return scaleLinear()
70
- .domain([minValue - margin, maxValue + margin])
71
- .range(bounds)
72
- }
73
- }
74
- /**
75
- * Obtain the scale function for the `x` and `y` fields in the data set.
76
- *
77
- * @param {array<dict>} data
78
- * @param {string} x
79
- * @param {string} y
80
- * @param {number} width
81
- * @param {number} height
82
- * @returns
83
- */
84
- export function getScales(data, x, y, width, height, margin, ordinal) {
85
- const xValues = [...new Set(data.map((item) => item[x]))]
86
- const yValues = [...new Set(data.map((item) => item[y]))]
87
-
88
- return {
89
- x: getScale(xValues, [0 + margin.left, width - margin.right], 0, ordinal.x),
90
- y: getScale(yValues, [height - margin.top, margin.bottom], 0.1, ordinal.y)
91
- }
92
- }
93
-
94
- /**
95
- * Summarize `data` by fields `x` and `y` and return a nested array with
96
- * key as unique `x` values and value as statistical summaries of `y` values
97
- *
98
- * @param {*} data
99
- * @param {*} x
100
- * @param {*} y
101
- * @returns
102
- */
103
- export function aggregate(data, x, y) {
104
- const summary = nest()
105
- .key((d) => d[x])
106
- .rollup((d) => {
107
- let values = d.map((g) => g[y]).sort(ascending)
108
- let q1 = quantile(values, 0.25)
109
- let q3 = quantile(values, 0.75)
110
- let median = quantile(values, 0.5)
111
- let interQuantileRange = q3 - q1
112
- let min = q1 - 1.5 * interQuantileRange
113
- let max = q3 + 1.5 * interQuantileRange
114
- return { q1, q3, median, interQuantileRange, min, max }
115
- })
116
- .entries(data)
117
- return summary
118
- }
119
-
120
- /**
121
- * Generate a palette with same size as input data containing values from palette array.
122
- * After the palette array is exhausted the fallback value is used
123
- *
124
- * @param {Array} values
125
- * @param {Array} palette
126
- * @param {*} fallback
127
- * @returns
128
- */
129
- export function getPaletteForValues(values, palette, fallback) {
130
- return values.map((_, index) => (index < palette.length ? palette[index] : fallback))
131
- }
132
-
133
- /**
134
- * Converts input object array into a nested key,value array.
135
- * 'key' contains unique values for the attribute specified by the key parameter
136
- * and value contains array of all remaining attributes in an array.
137
- *
138
- * @param {Array<Object>} data
139
- * @param {string} key
140
- * @param {string} label
141
- * @returns
142
- */
143
- export function toNested(data, key, label) {
144
- return nest()
145
- .key((d) => d[key])
146
- .rollup((values) => values.map((value) => omit([key], value)))
147
- .entries(data.sort((a, b) => ascending(a[label], b[label])))
148
- }
149
- /**
150
- * Repeats array items of b using array items of a ask keys
151
- *
152
- * @param {Array} b
153
- * @param {Array} a
154
- * @returns {Object} with keys as items in a and values as items in b
155
- */
156
- export function repeatAcross(b, a) {
157
- return a.reduce((acc, item, index) => ({ ...acc, [item]: b[index % b.length] }), {})
158
- }
@@ -1,51 +0,0 @@
1
- <script>
2
- import { getContext } from 'svelte'
3
- import { colorBrewer } from '../lib/palette'
4
-
5
- let chart = getContext('chart')
6
-
7
- export let labels = false
8
- export let fontSize = $chart.height / 32
9
- export let color = 'white'
10
-
11
- $: fills = colorBrewer($chart.data.map((d) => d.fill))
12
- // export let limit = 8
13
-
14
- $: data = $chart.data.map((d) => ({
15
- x: $chart.flipCoords ? $chart.scale.x(0) : $chart.scale.x(d.x),
16
- y: $chart.flipCoords ? $chart.scale.y(d.y) : $chart.scale.y(d.y),
17
- y0: $chart.scale.y(0),
18
- width: $chart.flipCoords ? $chart.scale.x(d.x) - $chart.scale.x(0) : $chart.scale.x.bandwidth(),
19
- height: $chart.flipCoords
20
- ? $chart.scale.y.bandwidth()
21
- : $chart.scale.y(0) - $chart.scale.y(d.y),
22
- fill: fills[d.fill],
23
- label: {
24
- x: $chart.flipCoords
25
- ? $chart.scale.x(d.x) - $chart.scale.x(0) - 10
26
- : $chart.scale.x.bandwidth() / 2,
27
- y: $chart.flipCoords ? $chart.scale.y.bandwidth() / 2 : 10,
28
- angle: $chart.flipCoords ? 0 : -90,
29
- text: $chart.flipCoords ? d.y + ' (' + d.x + ')' : d.x + ' (' + d.y + ')'
30
- }
31
- }))
32
- </script>
33
-
34
- {#each data as { x, y, width, height, fill, label }}
35
- <rect {x} {y} {width} {height} {fill} />
36
- {#if labels}
37
- {@const tx = x + label.x}
38
- {@const ty = y + label.y}
39
- <text
40
- x={tx}
41
- y={ty}
42
- transform="rotate({label.angle},{tx},{ty})"
43
- font-size={fontSize}
44
- text-anchor="end"
45
- alignment-baseline="middle"
46
- fill={color}
47
- >
48
- {label.text}
49
- </text>
50
- {/if}
51
- {/each}
@@ -1,34 +0,0 @@
1
- <script>
2
- import { getContext } from 'svelte'
3
-
4
- let chart = getContext('chart')
5
-
6
- // export let data = []
7
- export let limit = 8
8
- export let fields
9
- // export let valueFormat
10
- // export let scales
11
- export let colors
12
- export let h = 10
13
-
14
- function size(value) {
15
- return $chart.axis.x.scale(value)
16
- }
17
- function top(value) {
18
- return $chart.axis.y.scale(value)
19
- }
20
-
21
- $: bars = $chart.data.slice(0, limit)
22
- </script>
23
-
24
- {#each bars as item}
25
- <rect
26
- x="0"
27
- y={top(item[fields.y]) + h / 2}
28
- width={size(item[fields.x])}
29
- height={h * 3}
30
- fill={colors[item[fields.label]]}
31
- />
32
- <text x="10" y={top(item[fields.y]) + 2.5 * h}>{item[fields.label]}</text>
33
- <!-- <text x="10" y={top(item[fields.y]) + 10}>{item[fields.x]}</text> -->
34
- {/each}
@@ -1,54 +0,0 @@
1
- <script>
2
- import { getContext } from 'svelte'
3
-
4
- let chart = getContext('chart')
5
-
6
- export let whisker = true
7
- export let boxWidth = 150
8
- export let stroke = 'green'
9
- export let fill = '#69b3a2' // fixed color or attribute to be used for color
10
- export let scaleFill = () => fill // defaults to fill color
11
-
12
- $: data = $chart.summary()
13
- </script>
14
-
15
- {#each data as { key, value }}
16
- <rect
17
- width={boxWidth}
18
- height={$chart.axis.y.scale(value.q1) - $chart.axis.y.scale(value.q3)}
19
- x={$chart.axis.x.scale(key) - boxWidth / 2}
20
- y={$chart.axis.y.scale(value.q3)}
21
- fill={scaleFill(value[fill])}
22
- {stroke}
23
- />
24
- <line
25
- x1={$chart.axis.x.scale(key) - boxWidth / 2}
26
- x2={$chart.axis.x.scale(key) + boxWidth / 2}
27
- y1={$chart.axis.y.scale(value.median)}
28
- y2={$chart.axis.y.scale(value.median)}
29
- {stroke}
30
- />
31
- <line
32
- x1={$chart.axis.x.scale(key)}
33
- x2={$chart.axis.x.scale(key)}
34
- y1={$chart.axis.y.scale(value.min)}
35
- y2={$chart.axis.y.scale(value.max)}
36
- {stroke}
37
- />
38
- {#if whisker}
39
- <line
40
- x1={$chart.axis.x.scale(key) - boxWidth / 8}
41
- x2={$chart.axis.x.scale(key) + boxWidth / 8}
42
- y1={$chart.axis.y.scale(value.min)}
43
- y2={$chart.axis.y.scale(value.min)}
44
- {stroke}
45
- />
46
- <line
47
- x1={$chart.axis.x.scale(key) - boxWidth / 8}
48
- x2={$chart.axis.x.scale(key) + boxWidth / 8}
49
- y1={$chart.axis.y.scale(value.max)}
50
- y2={$chart.axis.y.scale(value.max)}
51
- {stroke}
52
- />
53
- {/if}
54
- {/each}