@swr-data-lab/components 2.34.8 → 2.35.0

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/dist/index.d.ts CHANGED
@@ -26,6 +26,7 @@ export { default as ArrowSource } from "./maplibre/ArrowSource/ArrowSource.svelt
26
26
  export { default as MapSource } from "./maplibre/Source/MapSource.svelte";
27
27
  export { default as Tooltip } from "./maplibre/Tooltip/Tooltip.svelte";
28
28
  export { default as WithLinkLocation } from "./maplibre/WithLinkLocation/WithLinkLocation.svelte";
29
+ export { default as AnnotationLine } from "./layercake/AnnotationLine/AnnotationLine.svelte";
29
30
  export { default as FormLabel } from "./FormLabel/FormLabel.svelte";
30
31
  export { default as Switcher } from "./Switcher/Switcher.svelte";
31
32
  export { default as Input } from "./Input/Input.svelte";
package/dist/index.js CHANGED
@@ -39,6 +39,9 @@ export { default as MapSource } from './maplibre/Source/MapSource.svelte';
39
39
  export { default as Tooltip } from './maplibre/Tooltip/Tooltip.svelte';
40
40
  export { default as WithLinkLocation } from './maplibre/WithLinkLocation/WithLinkLocation.svelte';
41
41
 
42
+ // Layercake
43
+ export { default as AnnotationLine } from './layercake/AnnotationLine/AnnotationLine.svelte';
44
+
42
45
  // Form
43
46
  export { default as FormLabel } from './FormLabel/FormLabel.svelte';
44
47
  export { default as Switcher } from './Switcher/Switcher.svelte';
@@ -0,0 +1,18 @@
1
+ <script lang="ts">import { getContext } from 'svelte';
2
+ const { xScale, yScale, width, height } = getContext('LayerCake');
3
+ let { axis = 'x', value = 0 } = $props();
4
+ </script>
5
+
6
+ {#if axis === 'x'}
7
+ <line class="annotation-line" x1={$xScale(value)} x2={$xScale(value)} y1={0} y2={$height}></line>
8
+ {:else}
9
+ <line class="annotation-line" x1={0} x2={$width} y1={$yScale(value)} y2={$yScale(value)}></line>
10
+ {/if}
11
+
12
+ <style>
13
+ line {
14
+ stroke: var(--color-textPrimary);
15
+ stroke-width: 1;
16
+ pointer-events: none;
17
+ }
18
+ </style>
@@ -0,0 +1,7 @@
1
+ interface AnnotationLineProps {
2
+ axis: 'x' | 'y';
3
+ value: number;
4
+ }
5
+ declare const AnnotationLine: import("svelte").Component<AnnotationLineProps, {}, "">;
6
+ type AnnotationLine = ReturnType<typeof AnnotationLine>;
7
+ export default AnnotationLine;
@@ -0,0 +1,2 @@
1
+ export default AnnotationLine;
2
+ import AnnotationLine from './AnnotationLine.svelte';
@@ -0,0 +1,2 @@
1
+ import AnnotationLine from './AnnotationLine.svelte';
2
+ export default AnnotationLine;
@@ -0,0 +1,118 @@
1
+ <!--
2
+ @component
3
+ Generates an SVG x-axis. This component is also configured to detect if your x-scale is an ordinal scale. If so, it will place the markers in the middle of the bandwidth.
4
+ -->
5
+ <script lang="ts">import { getContext } from 'svelte';
6
+ const { width, height, xScale, yRange } = getContext('LayerCake');
7
+ /**
8
+ * @typedef {Object} Props
9
+ * @property {boolean} [tickMarks=false] - Show a vertical mark for each tick.
10
+ * @property {boolean} [gridlines=true] - Show gridlines extending into the chart area.
11
+ * @property {number} [tickMarkLength=6] - The length of the tick mark.
12
+ * @property {boolean} [baseline=false] - Show a solid line at the bottom.
13
+ * @property {boolean} [snapLabels=false] - Instead of centering the text labels on the first and the last items, align them to the edges of the chart.
14
+ * @property {(d: any) => string} [format=d => d] - A function that passes the current tick value and expects a nicely formatted value in return.
15
+ * @property {number|Array<any>|Function} [ticks] - If this is a number, it passes that along to the [d3Scale.ticks](https://github.com/d3/d3-scale) function. If this is an array, hardcodes the ticks to those values. If it's a function, passes along the default tick values and expects an array of tick values in return. If nothing, it uses the default ticks supplied by the D3 function.
16
+ * @property {number} [tickGutter=0] - The amount of whitespace between the start of the tick and the chart drawing area (the yRange min).
17
+ * @property {number} [dx=0] - Any optional value passed to the `dx` attribute on the text label.
18
+ * @property {number} [dy=12] - Any optional value passed to the `dy` attribute on the text label.
19
+ */
20
+ /** @type {Props} */
21
+ let { tickMarks = false, gridlines = true, tickMarkLength = 6, baseline = false, snapLabels = false, format = (d) => d, ticks = undefined, tickGutter = 0, fade = false, dx = 0, dy = 12 } = $props();
22
+ function textAnchor(i, sl) {
23
+ if (sl === true) {
24
+ if (i === 0) {
25
+ return 'start';
26
+ }
27
+ if (i === tickVals.length - 1) {
28
+ return 'end';
29
+ }
30
+ }
31
+ return 'middle';
32
+ }
33
+ let tickLen = $derived(tickMarks === true ? (tickMarkLength ?? 6) : 0);
34
+ let isBandwidth = $derived(typeof $xScale.bandwidth === 'function');
35
+ /** @type {Array<any>} */
36
+ let tickVals = $derived(Array.isArray(ticks)
37
+ ? ticks
38
+ : isBandwidth
39
+ ? $xScale.domain()
40
+ : typeof ticks === 'function'
41
+ ? ticks($xScale.ticks())
42
+ : $xScale.ticks(ticks));
43
+ let halfBand = $derived(isBandwidth ? $xScale.bandwidth() / 2 : 0);
44
+ </script>
45
+
46
+ <defs>
47
+ <linearGradient id="fade" x1=".5" x2=".5" y1="0" y2="1">
48
+ <stop stop-color={'black'} offset="20%" />
49
+ <stop stop-color={'white'} offset="100%" />
50
+ </linearGradient>
51
+ <mask id="fade-mask">
52
+ <rect fill="url(#fade)" x={-15} width={$width + 15} y={0} height={$height + 100}></rect>
53
+ </mask>
54
+ </defs>
55
+ <g class="axis x-axis" class:snapLabels mask={fade ? 'url(#fade-mask)' : ''}>
56
+ {#each tickVals as tick, i (tick)}
57
+ {#if baseline === true}
58
+ <line class="baseline" y1={$height} y2={$height} x1="0" x2={$width} />
59
+ {/if}
60
+
61
+ <g class="tick tick-{i}" transform="translate({$xScale(tick)},{Math.max(...$yRange)})">
62
+ {#if gridlines === true}
63
+ <line class="gridline" x1={halfBand} x2={halfBand} y1={-$height} y2="0" />
64
+ {/if}
65
+ {#if tickMarks === true}
66
+ <line
67
+ class="tick-mark"
68
+ x1={halfBand}
69
+ x2={halfBand}
70
+ y1={tickGutter}
71
+ y2={tickGutter + tickLen}
72
+ />
73
+ {/if}
74
+ <text x={halfBand} y={tickGutter + tickLen} {dx} {dy} text-anchor={textAnchor(i, snapLabels)}
75
+ >{format(tick)}</text
76
+ >
77
+ </g>
78
+ {/each}
79
+ </g>
80
+
81
+ <style>
82
+ .tick {
83
+ font-size: var(--fs-small-3);
84
+ }
85
+
86
+ line,
87
+ .tick line {
88
+ stroke: var(--color-textSecondary);
89
+ }
90
+ .tick line {
91
+ opacity: 0.5;
92
+ stroke-dasharray: 2 5;
93
+ }
94
+
95
+ .tick text {
96
+ fill: var(--color-textSecondary);
97
+ }
98
+
99
+ .tick .tick-mark,
100
+ .baseline {
101
+ stroke-width: 1;
102
+ }
103
+ .baseline {
104
+ opacity: 1;
105
+ stroke: var(--color-textPrimary);
106
+ stroke-width: 1;
107
+ }
108
+ /* This looks slightly better */
109
+ .axis.snapLabels .tick:last-child text {
110
+ transform: translateX(3px);
111
+ }
112
+ .axis.snapLabels .tick.tick-0 text {
113
+ transform: translateX(-3px);
114
+ }
115
+ .fade {
116
+ fill: url('#fade');
117
+ }
118
+ </style>
@@ -0,0 +1,16 @@
1
+ /** Generates an SVG x-axis. This component is also configured to detect if your x-scale is an ordinal scale. If so, it will place the markers in the middle of the bandwidth. */
2
+ declare const AxisX: import("svelte").Component<{
3
+ tickMarks?: boolean;
4
+ gridlines?: boolean;
5
+ tickMarkLength?: number;
6
+ baseline?: boolean;
7
+ snapLabels?: boolean;
8
+ format?: Function;
9
+ ticks?: any;
10
+ tickGutter?: number;
11
+ fade?: boolean;
12
+ dx?: number;
13
+ dy?: number;
14
+ }, {}, "">;
15
+ type AxisX = ReturnType<typeof AxisX>;
16
+ export default AxisX;
@@ -0,0 +1,129 @@
1
+ <!--
2
+ @component
3
+ Generates an SVG y-axis. This component is also configured to detect if your y-scale is an ordinal scale. If so, it will place the tickMarks in the middle of the bandwidth.
4
+ -->
5
+ <script>
6
+ import { getContext } from 'svelte';
7
+
8
+ const { xRange, yScale, width, height } = getContext('LayerCake');
9
+
10
+ /**
11
+ * @typedef {Object} Props
12
+ * @property {boolean} [tickMarks=false] - Show marks next to the tick label.
13
+ * @property {string} [labelPosition='even'] - Whether the label sits even with its value ('even') or sits on top ('above') the tick mark. Default is 'even'.
14
+ * @property {boolean} [snapBaselineLabel=false] - When labelPosition='even', adjust the lowest label so that it sits above the tick mark.
15
+ * @property {boolean} [gridlines=true] - Show gridlines extending into the chart area.
16
+ * @property {number} [tickMarkLength] - The length of the tick mark. If not set, becomes the length of the widest tick.
17
+ * @property {(d: any) => string} [format=d => d] - A function that passes the current tick value and expects a nicely formatted value in return.
18
+ * @property {number|Array<any>|Function} [ticks=4] - If this is a number, it passes that along to the [d3Scale.ticks](https://github.com/d3/d3-scale) function. If this is an array, hardcodes the ticks to those values. If it's a function, passes along the default tick values and expects an array of tick values in return.
19
+ * @property {number} [tickGutter=0] - The amount of whitespace between the start of the tick and the chart drawing area (the xRange min).
20
+ * @property {number} [dx=0] - Any optional value passed to the `dx` attribute on the text label.
21
+ * @property {number} [dy=0] - Any optional value passed to the `dy` attribute on the text label.
22
+ * @property {number} [charPixelWidth=7.25] - Used to calculate the widest label length to offset labels. Adjust if the automatic tick length doesn't look right because you have a bigger font (or just set `tickMarkLength` to a pixel value).
23
+ */
24
+
25
+ /** @type {Props} */
26
+ let {
27
+ tickMarks = false,
28
+ labelPosition = 'even',
29
+ snapBaselineLabel = false,
30
+ gridlines = true,
31
+ baseline = true,
32
+ tickMarkLength = undefined,
33
+ format = (d) => d,
34
+ ticks = 4,
35
+ tickGutter = 0,
36
+ dx = 0,
37
+ dy = 0,
38
+ charPixelWidth = 7.25
39
+ } = $props();
40
+
41
+ /** @param {number} sum
42
+ * @param {string} val */
43
+ function calcStringLength(sum, val) {
44
+ if (val === ',' || val === '.') return sum + charPixelWidth * 0.5;
45
+ return sum + charPixelWidth;
46
+ }
47
+
48
+ let isBandwidth = $derived(typeof $yScale.bandwidth === 'function');
49
+ /** @type {Array<any>} */
50
+ let tickVals = $derived(
51
+ Array.isArray(ticks)
52
+ ? ticks
53
+ : isBandwidth
54
+ ? $yScale.domain()
55
+ : typeof ticks === 'function'
56
+ ? ticks($yScale.ticks())
57
+ : $yScale.ticks(ticks)
58
+ );
59
+ let widestTickLen = $derived(
60
+ Math.max(
61
+ 10,
62
+ Math.max(...tickVals.map((d) => format(d).toString().split('').reduce(calcStringLength, 0)))
63
+ )
64
+ );
65
+ let tickLen = $derived(
66
+ tickMarks === true
67
+ ? labelPosition === 'above'
68
+ ? (tickMarkLength ?? widestTickLen)
69
+ : (tickMarkLength ?? 6)
70
+ : 0
71
+ );
72
+ let x1 = $derived(labelPosition === 'above' ? widestTickLen : tickLen);
73
+ let y = $derived(isBandwidth ? $yScale.bandwidth() / 2 : 0);
74
+ let maxTickValPx = $derived(Math.max(...tickVals.map($yScale)));
75
+ </script>
76
+
77
+ <g class="axis y-axis">
78
+ {#if baseline === true}
79
+ <line class="baseline" y1={0} y2={$height} {x1} x2={x1} />
80
+ {/if}
81
+
82
+ {#each tickVals as tick (tick)}
83
+ {@const tickValPx = $yScale(tick)}
84
+ <g class="tick tick-{tick}" transform="translate({$xRange[0]}, {tickValPx})">
85
+ {#if gridlines === true}
86
+ <line class="gridline" {x1} x2={$width} y1={y} y2={y}></line>
87
+ {/if}
88
+ {#if tickMarks === true}
89
+ <line class="tick-mark" {x1} x2={x1 + tickLen} y1={y} y2={y}></line>
90
+ {/if}
91
+ <text
92
+ x={x1}
93
+ {y}
94
+ dx={dx + (labelPosition === 'even' ? -8 : 0)}
95
+ text-anchor={labelPosition === 'above' ? 'start' : 'end'}
96
+ dy={dy +
97
+ (labelPosition === 'above' || (snapBaselineLabel === true && tickValPx === maxTickValPx)
98
+ ? -3
99
+ : 4)}>{format(tick)}</text
100
+ >
101
+ </g>
102
+ {/each}
103
+ </g>
104
+
105
+ <style>
106
+ .tick {
107
+ font-size: 11px;
108
+ }
109
+
110
+ .tick line {
111
+ stroke: var(--color-textPrimary);
112
+ }
113
+ .tick .gridline {
114
+ stroke-dasharray: 1 3;
115
+ opacity: 0.5;
116
+ }
117
+
118
+ .tick text {
119
+ fill: var(--color-textPrimary);
120
+ }
121
+
122
+ .baseline {
123
+ stroke: var(--color-textPrimary);
124
+ }
125
+
126
+ .tick.tick-0 line {
127
+ stroke-dasharray: 0;
128
+ }
129
+ </style>
@@ -0,0 +1,98 @@
1
+ export default AxisY;
2
+ type AxisY = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<Props>): void;
5
+ };
6
+ /** Generates an SVG y-axis. This component is also configured to detect if your y-scale is an ordinal scale. If so, it will place the tickMarks in the middle of the bandwidth. */
7
+ declare const AxisY: import("svelte").Component<{
8
+ /**
9
+ * - Show marks next to the tick label.
10
+ */
11
+ tickMarks?: boolean | undefined;
12
+ /**
13
+ * - Whether the label sits even with its value ('even') or sits on top ('above') the tick mark. Default is 'even'.
14
+ */
15
+ labelPosition?: string | undefined;
16
+ /**
17
+ * - When labelPosition='even', adjust the lowest label so that it sits above the tick mark.
18
+ */
19
+ snapBaselineLabel?: boolean | undefined;
20
+ /**
21
+ * - Show gridlines extending into the chart area.
22
+ */
23
+ gridlines?: boolean | undefined;
24
+ /**
25
+ * - The length of the tick mark. If not set, becomes the length of the widest tick.
26
+ */
27
+ tickMarkLength?: number | undefined;
28
+ /**
29
+ * - A function that passes the current tick value and expects a nicely formatted value in return.
30
+ */
31
+ format?: ((d: any) => string) | undefined;
32
+ /**
33
+ * - If this is a number, it passes that along to the [d3Scale.ticks](https://github.com/d3/d3-scale) function. If this is an array, hardcodes the ticks to those values. If it's a function, passes along the default tick values and expects an array of tick values in return.
34
+ */
35
+ ticks?: number | Function | any[] | undefined;
36
+ /**
37
+ * - The amount of whitespace between the start of the tick and the chart drawing area (the xRange min).
38
+ */
39
+ tickGutter?: number | undefined;
40
+ /**
41
+ * - Any optional value passed to the `dx` attribute on the text label.
42
+ */
43
+ dx?: number | undefined;
44
+ /**
45
+ * - Any optional value passed to the `dy` attribute on the text label.
46
+ */
47
+ dy?: number | undefined;
48
+ /**
49
+ * - Used to calculate the widest label length to offset labels. Adjust if the automatic tick length doesn't look right because you have a bigger font (or just set `tickMarkLength` to a pixel value).
50
+ */
51
+ charPixelWidth?: number | undefined;
52
+ }, {}, "">;
53
+ type Props = {
54
+ /**
55
+ * - Show marks next to the tick label.
56
+ */
57
+ tickMarks?: boolean | undefined;
58
+ /**
59
+ * - Whether the label sits even with its value ('even') or sits on top ('above') the tick mark. Default is 'even'.
60
+ */
61
+ labelPosition?: string | undefined;
62
+ /**
63
+ * - When labelPosition='even', adjust the lowest label so that it sits above the tick mark.
64
+ */
65
+ snapBaselineLabel?: boolean | undefined;
66
+ /**
67
+ * - Show gridlines extending into the chart area.
68
+ */
69
+ gridlines?: boolean | undefined;
70
+ /**
71
+ * - The length of the tick mark. If not set, becomes the length of the widest tick.
72
+ */
73
+ tickMarkLength?: number | undefined;
74
+ /**
75
+ * - A function that passes the current tick value and expects a nicely formatted value in return.
76
+ */
77
+ format?: ((d: any) => string) | undefined;
78
+ /**
79
+ * - If this is a number, it passes that along to the [d3Scale.ticks](https://github.com/d3/d3-scale) function. If this is an array, hardcodes the ticks to those values. If it's a function, passes along the default tick values and expects an array of tick values in return.
80
+ */
81
+ ticks?: number | Function | any[] | undefined;
82
+ /**
83
+ * - The amount of whitespace between the start of the tick and the chart drawing area (the xRange min).
84
+ */
85
+ tickGutter?: number | undefined;
86
+ /**
87
+ * - Any optional value passed to the `dx` attribute on the text label.
88
+ */
89
+ dx?: number | undefined;
90
+ /**
91
+ * - Any optional value passed to the `dy` attribute on the text label.
92
+ */
93
+ dy?: number | undefined;
94
+ /**
95
+ * - Used to calculate the widest label length to offset labels. Adjust if the automatic tick length doesn't look right because you have a bigger font (or just set `tickMarkLength` to a pixel value).
96
+ */
97
+ charPixelWidth?: number | undefined;
98
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@swr-data-lab/components",
3
3
  "description": "SWR Data Lab component library",
4
- "version": "2.34.8",
4
+ "version": "2.35.0",
5
5
  "author": "SWR Data Lab",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -37,24 +37,25 @@
37
37
  "svelte-select": "5.8.3"
38
38
  },
39
39
  "devDependencies": {
40
+ "layercake": "^10.0.2",
40
41
  "@semantic-release/changelog": "6.0.3",
41
42
  "@semantic-release/git": "10.0.1",
42
- "@semantic-release/npm": "13.1.2",
43
- "@storybook/addon-docs": "10.1.4",
44
- "@storybook/addon-links": "10.1.4",
43
+ "@semantic-release/npm": "13.1.3",
44
+ "@storybook/addon-docs": "10.1.11",
45
+ "@storybook/addon-links": "10.1.11",
45
46
  "@storybook/addon-svelte-csf": "^5.0.10",
46
- "@storybook/addon-vitest": "10.1.4",
47
- "@storybook/sveltekit": "10.1.4",
47
+ "@storybook/addon-vitest": "10.1.11",
48
+ "@storybook/sveltekit": "10.1.11",
48
49
  "@storybook/test-runner": "^0.24.2",
49
50
  "@sveltejs/adapter-auto": "7.0.0",
50
51
  "@sveltejs/enhanced-img": "0.9.2",
51
- "@sveltejs/kit": "2.49.0",
52
+ "@sveltejs/kit": "2.49.2",
52
53
  "@sveltejs/package": "2.5.7",
53
54
  "@sveltejs/vite-plugin-svelte": "6.2.1",
54
55
  "@types/geojson": "7946.0.16",
55
56
  "@versatiles/style": "5.7.0",
56
- "@vitest/browser": "4.0.15",
57
- "@vitest/coverage-v8": "4.0.15",
57
+ "@vitest/browser": "4.0.16",
58
+ "@vitest/coverage-v8": "4.0.16",
58
59
  "@vueless/storybook-dark-mode": "9.0.8",
59
60
  "concurrently": "9.2.1",
60
61
  "http-server": "14.1.1",
@@ -64,14 +65,14 @@
64
65
  "sass": "1.93.2",
65
66
  "sass-embedded": "1.93.2",
66
67
  "semantic-release": "25.0.2",
67
- "storybook": "10.1.10",
68
+ "storybook": "10.1.11",
68
69
  "svelte": "5.33.6",
69
70
  "svelte-check": "4.3.2",
70
71
  "svelte-preprocess": "6.0.3",
71
72
  "typescript": "5.9.3",
72
- "vite": "7.1.11",
73
- "vitest": "4.0.15",
74
- "@vitest/browser-playwright": "4.0.15",
73
+ "vite": "7.3.0",
74
+ "vitest": "4.0.16",
75
+ "@vitest/browser-playwright": "4.0.16",
75
76
  "wait-on": "8.0.3"
76
77
  },
77
78
  "overrides": {