@rokkit/chart 1.0.0-next.36 → 1.0.0-next.37

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 (47) hide show
  1. package/package.json +11 -10
  2. package/src/chart/FacetGrid.svelte +6 -6
  3. package/src/chart/Swatch.svelte +2 -3
  4. package/src/chart/TexturedShape.svelte +1 -1
  5. package/src/chart/TimelapseChart.svelte +2 -2
  6. package/src/elements/ColorRamp.svelte +1 -1
  7. package/src/elements/ContinuousLegend.svelte +1 -1
  8. package/src/index.js +1 -2
  9. package/src/{components/lib → lib}/chart.js +12 -0
  10. package/src/lib/color.js +59 -0
  11. package/src/{components/lib/color.js → lib/constants.js} +111 -56
  12. package/src/lib/geom.js +106 -0
  13. package/src/lib/index.js +0 -0
  14. package/src/lib/{colors.js → palette.js} +3 -3
  15. package/src/lib/shape.js +52 -0
  16. package/src/{swatch.js → lib/swatch.js} +4 -4
  17. package/src/{components/lib/utils.js → lib/utils-2.js} +1 -41
  18. package/src/lib/utils.js +4 -0
  19. package/src/plots/BarPlot.svelte +1 -1
  20. package/src/plots/FunnelPlot.svelte +2 -3
  21. package/src/plots/HeatMapCalendar.svelte +1 -1
  22. package/src/plots/LinePlot.svelte +1 -1
  23. package/src/plots/Plot.svelte +1 -1
  24. package/src/plots/ScatterPlot.svelte +1 -1
  25. package/src/chart/Symbol.svelte +0 -40
  26. package/src/chart.js +0 -11
  27. package/src/components/index.js +0 -2
  28. package/src/components/lib/index.js +0 -19
  29. package/src/components/lib/shape.js +0 -199
  30. package/src/components/lib/timer.js +0 -41
  31. package/src/constants.js +0 -66
  32. package/src/elements/PatternDefs.svelte +0 -13
  33. package/src/elements/PatternMask.svelte +0 -20
  34. package/src/elements/Symbol.svelte +0 -38
  35. package/src/funnel.svelte +0 -35
  36. package/src/geom.js +0 -105
  37. package/src/lib/shapes.js +0 -144
  38. package/src/plots/old_ScatterPlot.svelte +0 -20
  39. /package/src/chart/{Grid.svelte → AxisGrid.svelte} +0 -0
  40. /package/src/{components/lib → lib}/funnel.js +0 -0
  41. /package/src/{plots → lib}/heatmap.js +0 -0
  42. /package/src/{lookup.js → lib/lookup.js} +0 -0
  43. /package/src/{components/lib → lib}/pattern.js +0 -0
  44. /package/src/{components/lib → lib}/rollup.js +0 -0
  45. /package/src/{components → lib}/store.js +0 -0
  46. /package/src/{components/lib → lib}/summary.js +0 -0
  47. /package/src/{components/lib → lib}/theme.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/chart",
3
- "version": "1.0.0-next.36",
3
+ "version": "1.0.0-next.37",
4
4
  "description": "Components for making interactive charts.",
5
5
  "author": "Jerry Thomas <me@jerrythomas.name>",
6
6
  "license": "MIT",
@@ -13,35 +13,36 @@
13
13
  "access": "public"
14
14
  },
15
15
  "devDependencies": {
16
- "@sveltejs/vite-plugin-svelte": "^2.4.2",
16
+ "@sveltejs/vite-plugin-svelte": "^2.4.3",
17
17
  "@testing-library/svelte": "^4.0.3",
18
18
  "@vitest/coverage-v8": "^0.33.0",
19
19
  "@vitest/ui": "~0.33.0",
20
20
  "js-yaml": "^4.1.0",
21
21
  "jsdom": "^22.1.0",
22
- "svelte": "^4.0.5",
22
+ "svelte": "^4.1.1",
23
23
  "typescript": "^5.1.6",
24
- "vite": "^4.4.4",
24
+ "vite": "^4.4.7",
25
25
  "vitest": "~0.33.0",
26
- "shared-config": "1.0.0-next.36"
26
+ "shared-config": "1.0.0-next.37"
27
27
  },
28
28
  "dependencies": {
29
29
  "d3-array": "^3.2.4",
30
30
  "d3-collection": "^1.0.7",
31
+ "d3-format": "^3.1.0",
32
+ "d3-interpolate": "^3.0.1",
31
33
  "d3-scale": "^4.0.2",
32
34
  "d3-shape": "^3.2.0",
33
35
  "date-fns": "^2.30.0",
34
36
  "ramda": "^0.29.0",
35
- "rokkit": "latest",
36
37
  "yootils": "^0.3.1",
37
- "@rokkit/core": "1.0.0-next.36"
38
+ "@rokkit/core": "1.0.0-next.37",
39
+ "@rokkit/stores": "1.0.0-next.37",
40
+ "@rokkit/molecules": "1.0.0-next.37"
38
41
  },
39
42
  "files": [
40
43
  "src/**/*.js",
41
44
  "src/**/*.svelte",
42
- "!src/fixtures",
43
- "!src/mocks",
44
- "!src/**/*.spec.js"
45
+ "!spec"
45
46
  ],
46
47
  "exports": {
47
48
  "./src": "./src",
@@ -2,8 +2,8 @@
2
2
  import Chart from './Chart.svelte'
3
3
  import AxisGrid from './AxisGrid.svelte'
4
4
  import Axis from './Axis.svelte'
5
- import AxisTicks from './AxisTicks.svelte'
6
- import AxisLabels from './AxisLabels.svelte'
5
+ // import AxisTicks from './AxisTicks.svelte'
6
+ // import AxisLabels from './AxisLabels.svelte'
7
7
 
8
8
  export let data
9
9
  export let row
@@ -29,18 +29,18 @@
29
29
 
30
30
  <Chart data={dataFilteredByCol} {x} {y}>
31
31
  <Axis name="x" count={7} gap={10}>
32
- <AxisTicks side="bottom">
32
+ <!-- <AxisTicks side="bottom">
33
33
  {#if labels.x}
34
34
  <AxisLabels angle={-60} />
35
35
  {/if}
36
- </AxisTicks>
36
+ </AxisTicks> -->
37
37
  </Axis>
38
38
  <Axis name="y" gap={10}>
39
- <AxisTicks side="left">
39
+ <!-- <AxisTicks side="left">
40
40
  {#if labels.y}
41
41
  <AxisLabels />
42
42
  {/if}
43
- </AxisTicks>
43
+ </AxisTicks> -->
44
44
  <AxisGrid />
45
45
  </Axis>
46
46
  <svelte:component this={plot} />
@@ -3,8 +3,7 @@
3
3
 
4
4
  import { swatch } from '../lib/utils'
5
5
  import { clamp } from 'yootils'
6
- import Symbol from './Symbol.svelte'
7
- import PatternDefs from './PatternDefs.svelte'
6
+ import {Symbol, DefinePatterns} from '@rokkit/molecules'
8
7
 
9
8
  const dispatch = createEventDispatcher()
10
9
 
@@ -88,6 +87,6 @@
88
87
  on:focus={forwardEvent('focus', i + start)}
89
88
  />
90
89
  {/each}
91
- <PatternDefs patterns={items} />
90
+ <DefinePatterns patterns={items} />
92
91
  </svg>
93
92
  </div>
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import Symbol from './Symbol.svelte'
2
+ import {Symbol} from '@rokkit/molecules'
3
3
  import Texture from './Texture.svelte'
4
4
 
5
5
  export let pattern
@@ -3,11 +3,11 @@
3
3
  import { writable } from 'svelte/store'
4
4
  import { slidingWindow, uniques, brewer } from '../lib'
5
5
 
6
- import Grid from './Grid.svelte'
6
+ import Grid from './AxisGrid.svelte'
7
7
  import Axis from './Axis.svelte'
8
8
  import BoxPlot from '../plots/BoxPlot.svelte'
9
9
  import ViolinPlot from '../plots/ViolinPlot.svelte'
10
- import ScatterPlot from '../plots/old_ScatterPlot.svelte'
10
+ import ScatterPlot from '../plots/ScatterPlot.svelte'
11
11
 
12
12
  let chart = writable({})
13
13
  let axis
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { scaleLinear } from 'd3-scale'
3
- import { uniqueId } from '../lib/utils'
3
+ import { id as uniqueId } from '@rokkit/core'
4
4
 
5
5
  export let x = 0
6
6
  export let y = 0
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { scaleLinear } from 'd3-scale'
3
- import { uniqueId } from '../components/lib/utils'
3
+ import { id as uniqueId } from '@rokkit/core'
4
4
 
5
5
  export let x = 0
6
6
  export let y = 0
package/src/index.js CHANGED
@@ -12,5 +12,4 @@ export { default as BarPlot } from './plots/BarPlot.svelte'
12
12
  export { default as LinePlot } from './plots/LinePlot.svelte'
13
13
  export { default as BoxPlot } from './plots/BoxPlot.svelte'
14
14
  export { default as ViolinPlot } from './plots/ViolinPlot.svelte'
15
- export { default as ScatterPlot } from './plots/old_ScatterPlot.svelte'
16
- export * from './components/lib'
15
+ export * from './lib'
@@ -1,3 +1,15 @@
1
+ // export function scales(data, aes, opts) {
2
+ // const { x, y } = aes
3
+ // const { width, height, flipCoords } = {
4
+ // width: 800,
5
+ // height: 600,
6
+ // flipCoords: false,
7
+ // ...opts
8
+ // }
9
+
10
+ // return { x, y, width, height, flipCoords }
11
+ // }
12
+
1
13
  import { nest } from 'd3-collection'
2
14
  import { max, quantile, ascending, bin } from 'd3-array'
3
15
  import { scaleLinear } from 'd3-scale'
@@ -0,0 +1,59 @@
1
+ import { palette } from './constants'
2
+
3
+ export class ColorBrewer {
4
+ constructor() {
5
+ this.colors = ['blue', 'pink', 'teal', 'indigo', 'purple', 'amber', 'rose']
6
+ this.palette = palette
7
+ this.grayscale = this.palette['trueGray']
8
+ this.fill = 100
9
+ this.stroke = 600
10
+ this.contrast = 600
11
+ }
12
+
13
+ dark() {
14
+ this.fill = 500
15
+ this.stroke = 700
16
+ this.contrast = 100
17
+ return this
18
+ }
19
+
20
+ mix(fill, stroke, contrast) {
21
+ this.fill = Object.keys(this.grayscale).includes(fill) ? fill : this.fill
22
+ this.stroke = Object.keys(this.grayscale).includes(stroke)
23
+ ? stroke
24
+ : this.stroke
25
+ this.contrast = Object.keys(this.grayscale).includes(contrast)
26
+ ? contrast
27
+ : this.contrast
28
+
29
+ return this
30
+ }
31
+
32
+ swatch(colors) {
33
+ this.palette = colors
34
+ return this
35
+ }
36
+
37
+ filter(colors) {
38
+ this.colors = colors
39
+ return this
40
+ }
41
+
42
+ gray() {
43
+ return {
44
+ fill: this.grayscale[this.fill],
45
+ stroke: this.grayscale[this.stroke],
46
+ contrast: this.grayscale[this.contrast]
47
+ }
48
+ }
49
+
50
+ brew() {
51
+ const palette = this.colors.map((color) => ({
52
+ fill: this.palette[color][this.fill],
53
+ stroke: this.palette[color][this.stroke],
54
+ contrast: this.palette[color][this.contrast]
55
+ }))
56
+
57
+ return palette
58
+ }
59
+ }
@@ -1,3 +1,70 @@
1
+ export const __muted__ = {
2
+ color: '#eeeeee',
3
+ fill: 'empty',
4
+ shape: 'circle'
5
+ }
6
+ export const __colors__ = [
7
+ '#FFDE6B',
8
+ '#EF89EE',
9
+ '#F79F1E',
10
+ '#02B8FF',
11
+ '#9F84EC',
12
+ '#15CBC4',
13
+ '#0092FD',
14
+ '#F63A57',
15
+ '#A2CB39',
16
+ '#FF6E2F',
17
+ '#FEB8B9',
18
+ '#af7aa1',
19
+ '#7EFFF5'
20
+ ]
21
+
22
+ export const __patterns__ = {
23
+ A: 'M0 5A6 6 0 0 0 10 5',
24
+ B: 'M0 10L10 0',
25
+ C: 'M0 0A10 10 0 0 0 10 10',
26
+ D: 'M0 0L10 10',
27
+ E: 'M10 5A6 6 0 0 0 0 5',
28
+ F: 'M10 10A10 10 0 0 0 0 0',
29
+ G: 'M0 0L10 10ZM10 0L0 10Z',
30
+ H: 'M1 1L9 1L9 9L1 9Z',
31
+ I: 'M4 0L4 10M6 10L6 0M0 4L10 4M10 6L0 6',
32
+ J: 'M0 2L8 10M2 0L10 8M0 8L8 0M2 10L10 2',
33
+ K: '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',
34
+ L: 'M1 3L7 9M3 1L9 7M1 7L7 1M3 9L9 3',
35
+ M: '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',
36
+ N: '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',
37
+ O: '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',
38
+ P: 'M2 5L5 2L8 5L5 8Z',
39
+ Q: 'M3 5A2 2 0 0 0 7 5A2 2 0 0 0 3 5M1 5L9 5M5 1L5 9',
40
+ R: 'M2 8L8 2ZM1.5 3.5L3.5 1.5ZM6.5 8.5L8.5 6.5ZM0 0L10 10Z',
41
+ S:
42
+ 'M2 8L8 2ZM1.5 3.5L3.5 1.5Z' +
43
+ 'M6.5 8.5L8.5 6.5Z' +
44
+ 'M2 2L8 8M1.5 6.5L3.5 8.5' +
45
+ 'M6.5 1.5L8.5 3.5',
46
+ T:
47
+ 'M5 1 A6 6 0 0 0 5 9' +
48
+ 'A6 6 0 0 0 5 1' +
49
+ 'M1 5A6 6 0 0 0 9 5A6 6 0 0 0 1 5',
50
+ U:
51
+ 'M1.5 5A1 1 0 0 0 3.5 5A1 1 0 0 0 1.5 5' +
52
+ 'M6.5 5A1 1 0 0 0 8.5 5A1 1 0 0 0 6.5 5' +
53
+ 'M5 1.5A1 1 0 0 0 5 3.5A1 1 0 0 0 5 1.5' +
54
+ 'M5 6.5A1 1 0 0 0 5 8.5A1 1 0 0 0 5 6.5',
55
+ V:
56
+ 'M1.5 2.5A1 1 0 0 0 3.5 2.5A1 1 0 0 0 1.5 2.5' +
57
+ 'M6.5 2.5A1 1 0 0 0 8.5 2.5A1 1 0 0 0 6.5 2.5' +
58
+ 'M2.5 6.5A1 1 0 0 0 2.5 8.5A1 1 0 0 0 2.5 6.5' +
59
+ 'M7.5 6.5A1 1 0 0 0 7.5 8.5A1 1 0 0 0 7.5 6.5' +
60
+ 'M3.5 5A1 1 0 0 0 6.5 5A1 1 0 0 0 3.5 5',
61
+ W: 'M5 0L6 4L10 5L6 6L5 10L4 6L0 5L4 4Z' + 'M2 1V3M1 2H3' + 'M8 9V7M9 8H7',
62
+ X: 'M5 2L2.5 9L8.8 4.6L1.2 4.6L7.5 9Z',
63
+ Y: 'M0 5A5 5 0 0 0 5 0' + 'M5 10A5 5 0 0 0 0 5' + 'M5 10A5 5 0 0 0 5 0',
64
+ Z: 'M0 0L10 10M5 0L10 5M0 5 L5 10',
65
+ Z1: 'M0 0L10 10M3 0L10 7M0 7 L3 10'
66
+ }
67
+
1
68
  export const colors = [
2
69
  '#FFDE6B',
3
70
  '#EF89EE',
@@ -268,60 +335,48 @@ export const palette = {
268
335
  }
269
336
  }
270
337
 
271
- export class ColorBrewer {
272
- constructor() {
273
- this.colors = ['blue', 'pink', 'teal', 'indigo', 'purple', 'amber', 'rose']
274
- this.palette = palette
275
- this.grayscale = this.palette['trueGray']
276
- this.fill = 100
277
- this.stroke = 600
278
- this.contrast = 600
279
- }
280
-
281
- dark() {
282
- this.fill = 500
283
- this.stroke = 700
284
- this.contrast = 100
285
- return this
286
- }
287
-
288
- mix(fill, stroke, contrast) {
289
- this.fill = Object.keys(this.grayscale).includes(fill) ? fill : this.fill
290
- this.stroke = Object.keys(this.grayscale).includes(stroke)
291
- ? stroke
292
- : this.stroke
293
- this.contrast = Object.keys(this.grayscale).includes(contrast)
294
- ? contrast
295
- : this.contrast
296
-
297
- return this
298
- }
299
-
300
- swatch(colors) {
301
- this.palette = colors
302
- return this
303
- }
304
-
305
- filter(colors) {
306
- this.colors = colors
307
- return this
308
- }
309
-
310
- gray() {
311
- return {
312
- fill: this.grayscale[this.fill],
313
- stroke: this.grayscale[this.stroke],
314
- contrast: this.grayscale[this.contrast]
315
- }
316
- }
317
-
318
- brew() {
319
- const palette = this.colors.map((color) => ({
320
- fill: this.palette[color][this.fill],
321
- stroke: this.palette[color][this.stroke],
322
- contrast: this.palette[color][this.contrast]
323
- }))
324
-
325
- return palette
326
- }
338
+ export const shapePaths = {
339
+ // square: ['M', 1, 1, 'L', 9, 1, 'L', 9, 9, 'L', 1, 9, 'Z'],
340
+ square: [
341
+ ['M', 0.1, 0],
342
+ ['A', 0.1, 0.1, 0, 0, 0, 0, 0.1, 'V', 0.9],
343
+ ['A', 0.1, 0.1, 0, 0, 0, 0.1, 1, 'H', 0.9],
344
+ ['A', 0.1, 0.1, 0, 0, 0, 1, 0.9, 'V', 0.1],
345
+ ['A', 0.1, 0.1, 0, 0, 0, 0.9, 0, 'Z']
346
+ ],
347
+ circle: [
348
+ ['M', 0, 5],
349
+ ['A', 5, 5, 0, 0, 0, 10, 5],
350
+ ['A', 5, 5, 0, 0, 0, 0, 5]
351
+ ],
352
+ triangle: ['M', 5, 0, 'L', 10, 10, 'L', 0, 10, 'Z'],
353
+ diamond: [
354
+ ['M', 5, 0],
355
+ ['A', 7, 7, 0, 0, 0, 10, 5],
356
+ ['A', 7, 7, 0, 0, 0, 5, 10],
357
+ ['A', 7, 7, 0, 0, 0, 0, 5],
358
+ ['A', 7, 7, 0, 0, 0, 5, 0]
359
+ ],
360
+ rhombus: ['M', 0, 5, 'L', 5, 0, 'L', 10, 5, 'L', 5, 10, 'Z'],
361
+ heart: [
362
+ ['M', 9, 5],
363
+ ['A', 0.8, 0.8, 0, 0, 0, 5, 2],
364
+ ['A', 0.8, 0.8, 0, 0, 0, 1, 5],
365
+ ['L', 5, 9],
366
+ ['L', 9, 5]
367
+ ],
368
+ star: [
369
+ ['M', 4.80001, 0],
370
+ ['L', 5.92258, 3.45491],
371
+ ['H', 9.55529],
372
+ ['L', 6.61637, 5.59017],
373
+ ['L', 7.73894, 9.04509],
374
+ ['L', 4.80001, 6.90983],
375
+ ['L', 1.86108, 9.04509],
376
+ ['L', 2.98365, 5.59017],
377
+ ['L', 0.0447266, 3.45491],
378
+ ['H', 3.67744],
379
+ ['L', 4.80001, 0],
380
+ ['Z']
381
+ ]
327
382
  }
package/src/lib/geom.js CHANGED
@@ -1,3 +1,109 @@
1
+ import {
2
+ sum,
3
+ min,
4
+ max,
5
+ mean,
6
+ mode,
7
+ median,
8
+ deviation,
9
+ variance,
10
+ flatRollup
11
+ } from 'd3-array'
12
+
13
+ const summaries = {
14
+ identity: (value) => value,
15
+ count: (values) => values.length,
16
+ sum: (values) => sum(values),
17
+ min: (values) => min(values),
18
+ max: (values) => max(values),
19
+ mean: (values) => mean(values),
20
+ median: (values) => median(values),
21
+ mode: (values) => mode(values),
22
+ variance: (values) => variance(values),
23
+ deviation: (values) => deviation(values)
24
+ }
25
+
26
+ /**
27
+ * Returns an aggregator function for an input string or function.
28
+ *
29
+ * @param {string|function} stat
30
+ * @returns
31
+ */
32
+ export function rollup(stat) {
33
+ if (typeof stat === 'function') return stat
34
+ if (typeof stat !== 'string')
35
+ throw new TypeError('stat must be a string or function')
36
+ if (!(stat in summaries)) throw new TypeError('Unknown stat: ' + stat)
37
+
38
+ return summaries[stat]
39
+ }
40
+
41
+ /**
42
+ * Aesthetics for a chart.
43
+ *
44
+ * @typedef Aesthetics
45
+ * @property {string} x
46
+ * @property {string} y
47
+ * @property {string} [fill]
48
+ * @property {string} [size]
49
+ * @property {string} [color]
50
+ * @property {string} [shape]
51
+ * @property {string} [pattern]
52
+ */
53
+
54
+ /**
55
+ *
56
+ * @param {Array<any>} data
57
+ * @param {Aesthetics} aes
58
+ * @param {function|string} stat
59
+ * @returns
60
+ */
61
+ export function aggregate(data, aes, stat = 'identity') {
62
+ const agg = rollup(stat)
63
+ const keys = ['color', 'fill', 'pattern', 'shape', 'size'].filter((k) =>
64
+ Object.keys(aes).includes(k)
65
+ )
66
+
67
+ let groups = keys.map((k) => (d) => d[aes[k]])
68
+
69
+ return flatRollup(
70
+ data,
71
+ (v) => agg(v.map((d) => d[aes.y])),
72
+ (d) => d[aes.x],
73
+ ...groups
74
+ )
75
+ }
76
+
77
+ // export function geomBars(chart, aes) {
78
+ // const { x, y, fill, color, pattern } = { ...aes, ...chart.aes }
79
+ // return aggregate(chart.data, { x, y, fill, color, pattern })
80
+ // }
81
+
82
+ // export function geomLines(chart, aes) {
83
+ // const { x, y, color } = { ...aes, ...chart.aes }
84
+ // return aggregate(chart.data, { x, y, color })
85
+ // }
86
+
87
+ // export function geomViolin(chart, aes) {
88
+ // const { x, y, fill, color, pattern } = { ...aes, ...chart.aes }
89
+ // return { x, y, fill, color, pattern, ...opts }
90
+ // }
91
+
92
+ // export function geomArea(chart, aes) {
93
+ // const { x, y, fill, color, pattern } = { ...aes, ...chart.aes }
94
+ // return { x, y, fill, color, pattern, ...opts }
95
+ // }
96
+
97
+ // export function geomTrend(chart, aes) {
98
+ // const { x, y, fill, color, pattern } = { ...aes, ...chart.aes }
99
+ // return { x, y, fill, color, pattern, ...opts }
100
+ // }
101
+
102
+ // export function geomPoints(chart, aes) {
103
+ // const { x, y, fill, color, shape, size } = { ...aes, ...chart.aes }
104
+ // return { x, y, fill, color, shape, size, ...opts }
105
+ // }
106
+
1
107
  // export function violin(data, mapping) {}
2
108
  // export function bar(data, mapping) {}
3
109
  // export function scatter(data, mapping) {}
File without changes
@@ -1,5 +1,5 @@
1
1
  // import { writable } from 'svelte/store'
2
- import { repeatAcross } from '../lib/utils'
2
+ import { repeatAcross } from './utils'
3
3
 
4
4
  const palette = [
5
5
  '#FFDE6B',
@@ -18,8 +18,8 @@ const palette = [
18
18
  ]
19
19
 
20
20
  export class Palette {
21
- constructor(colors = palette) {
22
- this.colors = colors
21
+ constructor(palette) {
22
+ this.colors = palette
23
23
  }
24
24
 
25
25
  set colors(value) {
@@ -0,0 +1,52 @@
1
+ import { ColorBrewer } from './color'
2
+ import { scaledPath } from './utils'
3
+ import { shapePaths } from './constants'
4
+
5
+ export class ShapeBrewer {
6
+ constructor() {
7
+ this.shapes = Object.entries(shapePaths).reduce(
8
+ (acc, [name, path]) => ({ ...acc, [name]: (s) => scaledPath(s, path) }),
9
+ {}
10
+ )
11
+ this.repeat = false
12
+ this.keys = Object.keys(this.shapes)
13
+ this.gray = new ColorBrewer().gray()
14
+ this.shades = []
15
+ this.repeat = false
16
+ }
17
+
18
+ clear() {
19
+ this.shapes = {}
20
+ return this
21
+ }
22
+
23
+ add(shape) {
24
+ const shapes = typeof shape === 'object' ? shape : { shape }
25
+ this.shapes = { ...this.shapes, ...shapes }
26
+
27
+ return this
28
+ }
29
+
30
+ filter(keys) {
31
+ keys = Array.isArray(keys) ? keys : [keys]
32
+ this.keys = keys.filter((key) => key in this.shapes)
33
+
34
+ return this
35
+ }
36
+
37
+ colors(shades, repeat = false) {
38
+ this.shades = Array.isArray(shades) ? shades : [shades]
39
+ this.repeat = repeat
40
+ return this
41
+ }
42
+
43
+ brew() {
44
+ return this.keys
45
+ .map((i) => this.shapes[i])
46
+ .map((shape, i) => {
47
+ return i < this.shades.length || this.repeat
48
+ ? { shape, ...this.shades[i % this.shades.length] }
49
+ : { shape, ...this.gray }
50
+ })
51
+ }
52
+ }
@@ -5,7 +5,7 @@ import { writable } from 'svelte/store'
5
5
  export const swatchStore = writable({})
6
6
 
7
7
  // A set of 7 should be sufficient
8
- // array of names and patterns
9
- // array of names and shapes
10
- // array of colors
11
- // array of shades of one color.
8
+ // set of patterns
9
+ // set of shapes
10
+ // set of colors
11
+ // fill, stroke, text
@@ -2,47 +2,7 @@ import { scaleBand, scaleLinear } from 'd3-scale'
2
2
  import { min, max } from 'd3-array'
3
3
  import { ascending, quantile } from 'd3-array'
4
4
  import { nest } from 'd3-collection'
5
- import { omit, filter } from 'ramda'
6
-
7
- /**
8
- * Generates a unique id from current timestamp
9
- *
10
- * @returns {String} timestamp based unique id
11
- */
12
- export function uniqueId(prefix = '') {
13
- return prefix + Date.now().toString(36)
14
- }
15
-
16
- /**
17
- * Capitalizes the first letter of input string
18
- *
19
- * @param {String} str
20
- * @returns {String}
21
- */
22
- export function initCap(str) {
23
- return str.charAt(0).toUpperCase() + str.slice(1)
24
- }
25
-
26
- /**
27
- * Removes undefined and null values from the input object.
28
- *
29
- * @param {Object} obj
30
- * @returns {Object}
31
- */
32
- export function compact(obj) {
33
- return filter((x) => x !== undefined && x !== null, obj)
34
- }
35
-
36
- /**
37
- * Converts an input number into it's hexadecimal representation, with optional left padded zeroes based on the `size`
38
- *
39
- * @param {number} value
40
- * @param {number} size
41
- * @returns
42
- */
43
- export function toHexString(value, size = 2) {
44
- return value.toString(16).padStart(size, '0')
45
- }
5
+ import { omit } from 'ramda'
46
6
 
47
7
  /**
48
8
  * Calculates a grid of centres to fit a list of items of `size` within the number of `columns` and `rows`.
package/src/lib/utils.js CHANGED
@@ -4,6 +4,10 @@ import { ascending, quantile } from 'd3-array'
4
4
  import { nest } from 'd3-collection'
5
5
  import { omit } from 'ramda'
6
6
 
7
+ export function scaledPath(size, x) {
8
+ if (Array.isArray(x)) return x.map((x) => scaledPath(size, x)).join(' ')
9
+ return typeof size === 'number' ? x * size : x
10
+ }
7
11
  /**
8
12
  * Calculates a grid of centres to fit a list of items of `size` within the number of `columns` and `rows`.
9
13
  *
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { getContext } from 'svelte'
3
- import { colorBrewer } from '../lib/colors'
3
+ import { colorBrewer } from '../lib/palette'
4
4
 
5
5
  let chart = getContext('chart')
6
6