@rokkit/chart 1.0.0-next.87 → 1.0.0-next.88
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.
- package/package.json +11 -6
- package/src/Chart.svelte +67 -0
- package/src/PatternDefs.svelte +14 -0
- package/src/Symbol.svelte +17 -0
- package/src/{chart/Texture.svelte → Texture.svelte} +3 -3
- package/src/elements/Bar.svelte +2 -2
- package/src/elements/ContinuousLegend.svelte +3 -2
- package/src/elements/DefinePatterns.svelte +22 -0
- package/src/elements/DiscreteLegend.svelte +1 -1
- package/src/elements/Label.svelte +7 -5
- package/src/elements/SymbolGrid.svelte +23 -0
- package/src/elements/index.js +6 -0
- package/src/index.js +5 -15
- package/src/lib/brewer.js +17 -0
- package/src/lib/chart.js +179 -160
- package/src/lib/grid.js +68 -0
- package/src/lib/index.js +4 -0
- package/src/lib/palette.js +279 -28
- package/src/lib/plots.js +23 -0
- package/src/lib/swatch.js +24 -8
- package/src/lib/ticks.js +19 -0
- package/src/patterns/Brick.svelte +17 -0
- package/src/patterns/Circles.svelte +18 -0
- package/src/patterns/CrossHatch.svelte +14 -0
- package/src/patterns/CurvedWave.svelte +9 -0
- package/src/patterns/Dots.svelte +19 -0
- package/src/patterns/OutlineCircles.svelte +15 -0
- package/src/patterns/Texture.svelte +20 -0
- package/src/patterns/Tile.svelte +17 -0
- package/src/patterns/Triangles.svelte +15 -0
- package/src/patterns/Waves.svelte +13 -0
- package/src/patterns/constants.js +43 -0
- package/src/patterns/index.js +13 -0
- package/src/patterns/paths/NamedPattern.svelte +12 -0
- package/src/patterns/paths/constants.js +7 -0
- package/src/patterns/templates/Circles.svelte +18 -0
- package/src/patterns/templates/Lines.svelte +17 -0
- package/src/patterns/templates/Path.svelte +17 -0
- package/src/patterns/templates/index.js +3 -0
- package/src/plots/Plot.svelte +36 -21
- package/src/plots/index.js +1 -10
- package/src/symbols/Circle.svelte +22 -0
- package/src/symbols/Shape.svelte +31 -0
- package/src/symbols/Square.svelte +27 -0
- package/src/symbols/Triangle.svelte +24 -0
- package/src/symbols/constants/index.js +7 -0
- package/src/symbols/index.js +13 -0
- package/src/chart/Axis.svelte +0 -81
- package/src/chart/AxisGrid.svelte +0 -22
- package/src/chart/Chart.svelte +0 -40
- package/src/chart/FacetGrid.svelte +0 -49
- package/src/chart/Legend.svelte +0 -16
- package/src/chart/Swatch.svelte +0 -84
- package/src/chart/SwatchButton.svelte +0 -29
- package/src/chart/SwatchGrid.svelte +0 -53
- package/src/chart/TexturedShape.svelte +0 -20
- package/src/chart/TimelapseChart.svelte +0 -90
- package/src/chart/Timer.svelte +0 -27
- package/src/elements/Tooltip.svelte +0 -19
- package/src/lib/axis.js +0 -77
- package/src/lib/color.js +0 -55
- package/src/lib/constants.js +0 -41
- package/src/lib/funnel.js +0 -230
- package/src/lib/geom.js +0 -99
- package/src/lib/heatmap.js +0 -68
- package/src/lib/lookup.js +0 -29
- package/src/lib/pattern.js +0 -182
- package/src/lib/rollup.js +0 -49
- package/src/lib/shape.js +0 -46
- package/src/lib/store.js +0 -63
- package/src/lib/summary.js +0 -28
- package/src/lib/theme.js +0 -31
- package/src/lib/utils.js +0 -158
- package/src/plots/BarPlot.svelte +0 -51
- package/src/plots/BarPlot2.svelte +0 -34
- package/src/plots/BoxPlot.svelte +0 -54
- package/src/plots/FunnelPlot.svelte +0 -26
- package/src/plots/HeatMapCalendar.svelte +0 -121
- package/src/plots/LinePlot.svelte +0 -51
- package/src/plots/RankBarPlot.svelte +0 -38
- package/src/plots/ScatterPlot.svelte +0 -28
- package/src/plots/ViolinPlot.svelte +0 -10
package/src/lib/lookup.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { writable } from 'svelte/store'
|
|
2
|
-
|
|
3
|
-
// import { __patterns__, __colors__, __shapes__ } from './constants'
|
|
4
|
-
|
|
5
|
-
export const swatchStore = writable({})
|
|
6
|
-
|
|
7
|
-
// export function swatch(colors, patterns, shapes, defaults) {
|
|
8
|
-
// const limit = min([colors.length, patterns.length, shapes.length])
|
|
9
|
-
|
|
10
|
-
// swatchStore.set({
|
|
11
|
-
// colors: colors.slice(0, limit),
|
|
12
|
-
// patterns: patterns.slice(0, limit),
|
|
13
|
-
// shapes: shapes.slice(0, limit),
|
|
14
|
-
// defaults: {
|
|
15
|
-
// color: '#eeeeee',
|
|
16
|
-
// shape: __shapes__.circle,
|
|
17
|
-
// pattern: __patterns__.empty,
|
|
18
|
-
// ...defaults
|
|
19
|
-
// }
|
|
20
|
-
// })
|
|
21
|
-
// }
|
|
22
|
-
|
|
23
|
-
export function spread(values, across, filler) {
|
|
24
|
-
const unique = [...new Set(values)]
|
|
25
|
-
const lookup = unique.map((k, i) => ({
|
|
26
|
-
[k]: i < across.length ? across[i] : filler
|
|
27
|
-
}))
|
|
28
|
-
return (k) => lookup[k]
|
|
29
|
-
}
|
package/src/lib/pattern.js
DELETED
|
@@ -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()
|
package/src/lib/summary.js
DELETED
|
@@ -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
|
-
}
|
package/src/plots/BarPlot.svelte
DELETED
|
@@ -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}
|