svelteplot 0.7.0 → 0.7.1

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 (65) hide show
  1. package/LICENSE.md +19 -1
  2. package/README.md +1 -1
  3. package/dist/Mark.svelte.d.ts +43 -36
  4. package/dist/helpers/data.d.ts +1 -0
  5. package/dist/helpers/data.js +1 -1
  6. package/dist/helpers/index.js +1 -2
  7. package/dist/helpers/time.js +1 -1
  8. package/dist/marks/Area.svelte.d.ts +11 -4
  9. package/dist/marks/AreaX.svelte.d.ts +11 -4
  10. package/dist/marks/Arrow.svelte.d.ts +42 -35
  11. package/dist/marks/AxisX.svelte.d.ts +15 -8
  12. package/dist/marks/AxisY.svelte.d.ts +14 -7
  13. package/dist/marks/BarX.svelte.d.ts +11 -4
  14. package/dist/marks/BarY.svelte.d.ts +11 -4
  15. package/dist/marks/BollingerX.svelte.d.ts +11 -4
  16. package/dist/marks/BollingerY.svelte.d.ts +11 -4
  17. package/dist/marks/BoxY.svelte.d.ts +13 -6
  18. package/dist/marks/Brush.svelte.d.ts +120 -31
  19. package/dist/marks/Cell.svelte.d.ts +41 -34
  20. package/dist/marks/CustomMark.svelte.d.ts +14 -7
  21. package/dist/marks/CustomMarkHTML.svelte.d.ts +15 -8
  22. package/dist/marks/DifferenceY.svelte.d.ts +11 -4
  23. package/dist/marks/Dot.svelte.d.ts +42 -35
  24. package/dist/marks/DotX.svelte.d.ts +11 -4
  25. package/dist/marks/DotY.svelte.d.ts +11 -4
  26. package/dist/marks/Frame.svelte.d.ts +84 -17
  27. package/dist/marks/Geo.svelte.d.ts +42 -35
  28. package/dist/marks/GridX.svelte.d.ts +12 -5
  29. package/dist/marks/GridY.svelte.d.ts +12 -5
  30. package/dist/marks/HTMLTooltip.svelte.d.ts +14 -7
  31. package/dist/marks/Image.svelte.d.ts +11 -4
  32. package/dist/marks/Line.svelte +1 -1
  33. package/dist/marks/Line.svelte.d.ts +42 -35
  34. package/dist/marks/LineX.svelte.d.ts +11 -4
  35. package/dist/marks/LineY.svelte.d.ts +11 -4
  36. package/dist/marks/Link.svelte.d.ts +41 -34
  37. package/dist/marks/Pointer.svelte.d.ts +13 -6
  38. package/dist/marks/Rect.svelte.d.ts +11 -4
  39. package/dist/marks/RectX.svelte.d.ts +10 -3
  40. package/dist/marks/RectY.svelte.d.ts +10 -3
  41. package/dist/marks/RuleX.svelte.d.ts +12 -5
  42. package/dist/marks/RuleY.svelte.d.ts +12 -5
  43. package/dist/marks/Spike.svelte.d.ts +11 -4
  44. package/dist/marks/Text.svelte.d.ts +18 -11
  45. package/dist/marks/TickX.svelte.d.ts +11 -4
  46. package/dist/marks/TickY.svelte.d.ts +11 -4
  47. package/dist/marks/Vector.svelte.d.ts +41 -34
  48. package/dist/marks/WaffleX.svelte.d.ts +12 -5
  49. package/dist/marks/WaffleY.svelte.d.ts +12 -5
  50. package/dist/marks/helpers/Anchor.svelte.d.ts +15 -8
  51. package/dist/marks/helpers/MarkerPath.svelte.d.ts +13 -68
  52. package/dist/marks/helpers/RectPath.svelte.d.ts +13 -68
  53. package/dist/marks/helpers/canvas.js +1 -1
  54. package/dist/marks/helpers/waffle.d.ts +6 -0
  55. package/dist/marks/helpers/waffle.js +6 -38
  56. package/dist/transforms/index.d.ts +1 -1
  57. package/dist/transforms/index.js +1 -1
  58. package/dist/transforms/normalize.js +45 -0
  59. package/dist/ui/ExamplesGrid.svelte +19 -3
  60. package/dist/ui/ExamplesPagePreview.svelte +149 -0
  61. package/dist/ui/ExamplesPagePreview.svelte.d.ts +12 -0
  62. package/dist/ui/isDark.svelte.d.ts +6 -0
  63. package/dist/ui/isDark.svelte.js +10 -0
  64. package/package.json +140 -128
  65. package/dist/transforms/normalize.d.ts +0 -5
@@ -1,77 +1,15 @@
1
- import type { BaseRectMarkProps } from '../../types/mark.js';
1
+ import type { BaseMarkProps, BaseRectMarkProps } from '../../types/mark.js';
2
2
  import type { DataRecord, ScaledDataRecord } from '../../types/data.js';
3
3
  import type { UsedScales } from '../../types/index.js';
4
- declare class __sveltets_Render<Datum extends DataRecord> {
5
- props(): {
4
+ declare function $$render<Datum extends DataRecord>(): {
5
+ props: {
6
6
  datum: ScaledDataRecord<Datum>;
7
7
  class: string | null;
8
8
  x: number;
9
9
  y: number;
10
10
  width: number;
11
11
  height: number;
12
- options: BaseRectMarkProps<Datum> & Partial<{
13
- filter: import("../../types/index.js").ConstantAccessor<boolean, Datum>;
14
- facet: "auto" | "include" | "exclude";
15
- fx: import("../../types/index.js").ChannelAccessor<Datum>;
16
- fy: import("../../types/index.js").ChannelAccessor<Datum>;
17
- dx: import("../../types/index.js").ConstantAccessor<number, Datum>;
18
- dy: import("../../types/index.js").ConstantAccessor<number, Datum>;
19
- dodgeX: import("../../transforms/dodge.js").DodgeXOptions;
20
- dodgeY: import("../../transforms/dodge.js").DodgeYOptions;
21
- fill: import("../../types/index.js").ChannelAccessor<Datum>;
22
- fillOpacity: import("../../types/index.js").ConstantAccessor<number, Datum>;
23
- sort: ((a: import("../../types/data.js").RawValue, b: import("../../types/data.js").RawValue) => number) | {
24
- channel: string;
25
- order?: "ascending" | "descending";
26
- } | import("../../types/index.js").ConstantAccessor<import("../../types/data.js").RawValue, Datum>;
27
- stroke: import("../../types/index.js").ChannelAccessor<Datum>;
28
- strokeWidth: import("../../types/index.js").ConstantAccessor<number, Datum>;
29
- strokeOpacity: import("../../types/index.js").ConstantAccessor<number, Datum>;
30
- strokeLinejoin: import("../../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinejoin, Datum>;
31
- strokeLinecap: import("../../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinecap, Datum>;
32
- strokeMiterlimit: import("../../types/index.js").ConstantAccessor<number, Datum>;
33
- opacity: import("../../types/index.js").ChannelAccessor<Datum>;
34
- strokeDasharray: import("../../types/index.js").ConstantAccessor<string, Datum>;
35
- strokeDashoffset: import("../../types/index.js").ConstantAccessor<number, Datum>;
36
- mixBlendMode: import("../../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Datum>;
37
- clipPath: string;
38
- imageFilter: import("../../types/index.js").ConstantAccessor<string, Datum>;
39
- shapeRendering: import("../../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Datum>;
40
- paintOrder: import("../../types/index.js").ConstantAccessor<string, Datum>;
41
- onclick: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
42
- ondblclick: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
43
- onmouseup: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
44
- onmousedown: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
45
- onmouseenter: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
46
- onmousemove: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
47
- onmouseleave: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
48
- onmouseout: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
49
- onmouseover: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
50
- onpointercancel: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
51
- onpointerdown: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
52
- onpointerup: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
53
- onpointerenter: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
54
- onpointerleave: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
55
- onpointermove: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
56
- onpointerover: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
57
- onpointerout: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
58
- ondrag: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
59
- ondrop: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
60
- ondragstart: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
61
- ondragenter: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
62
- ondragleave: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
63
- ondragover: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
64
- ondragend: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
65
- ontouchstart: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
66
- ontouchmove: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
67
- ontouchend: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
68
- ontouchcancel: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
69
- oncontextmenu: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
70
- onwheel: import("svelte/elements.js").MouseEventHandler<SVGPathElement>;
71
- class: string;
72
- style: string;
73
- cursor: import("../../types/index.js").ConstantAccessor<import("csstype").Property.Cursor, Datum>;
74
- }>;
12
+ options: BaseRectMarkProps<Datum> & BaseMarkProps<Datum>;
75
13
  /**
76
14
  * By default, the `inset` property is applied to all four insets. Mark components
77
15
  * can tweak this behavior for insetTop and insetBottom by setting the
@@ -87,8 +25,15 @@ declare class __sveltets_Render<Datum extends DataRecord> {
87
25
  usedScales: UsedScales;
88
26
  fallbackStyle?: "fill" | "stroke";
89
27
  };
90
- events(): {};
91
- slots(): {};
28
+ exports: {};
29
+ bindings: "";
30
+ slots: {};
31
+ events: {};
32
+ };
33
+ declare class __sveltets_Render<Datum extends DataRecord> {
34
+ props(): ReturnType<typeof $$render<Datum>>['props'];
35
+ events(): ReturnType<typeof $$render<Datum>>['events'];
36
+ slots(): ReturnType<typeof $$render<Datum>>['slots'];
92
37
  bindings(): "";
93
38
  exports(): {};
94
39
  }
@@ -8,7 +8,7 @@ export function resolveColor(color, canvas) {
8
8
  }
9
9
  if (CSS_URL.test(color)) {
10
10
  // might be a gradient we can parse!
11
- const m = color.match(/^url\((#[^\)]+)\)/);
11
+ const m = color.match(/^url\((#[^)]+)\)/);
12
12
  const gradientId = m[1];
13
13
  const gradient = canvas.ownerDocument.querySelector(gradientId);
14
14
  if (gradient) {
@@ -1,3 +1,9 @@
1
+ /**
2
+ * This implementation is based on the waffle chart implementation in Observable Plot!
3
+ * https://github.com/observablehq/plot/blob/main/src/marks/waffle.js
4
+ *
5
+ * Kept the comments from the original implementation for clarity.
6
+ */
1
7
  import type { Snippet } from 'svelte';
2
8
  import type { StackOptions } from '../../transforms/stack';
3
9
  import type { BorderRadius, ConstantAccessor, PlotScales, ScaledDataRecord } from '../../types';
@@ -1,41 +1,9 @@
1
- // A waffle is approximately a rectangular shape, but may have one or two corner
2
- // cuts if the starting or ending value is not an even multiple of the number of
3
- // columns (the width of the waffle in cells). We can represent any waffle by
4
- // 8 points; below is a waffle of five columns representing the interval 2–11:
5
- //
6
- // 1-0
7
- // |•7-------6
8
- // |• • • • •|
9
- // 2---3• • •|
10
- // 4-----5
11
- //
12
- // Note that points 0 and 1 always have the same y-value, points 1 and 2 have
13
- // the same x-value, and so on, so we don’t need to materialize the x- and y-
14
- // values of all points. Also note that we can’t use the already-projected y-
15
- // values because these assume that y-values are distributed linearly along y
16
- // rather than wrapping around in columns.
17
- //
18
- // The corner points may be coincident. If the ending value is an even multiple
19
- // of the number of columns, say representing the interval 2–10, then points 6,
20
- // 7, and 0 are the same.
21
- //
22
- // 1-----0/7/6
23
- // |• • • • •|
24
- // 2---3• • •|
25
- // 4-----5
26
- //
27
- // Likewise if the starting value is an even multiple, say representing the
28
- // interval 0–10, points 2–4 are coincident.
29
- //
30
- // 1-----0/7/6
31
- // |• • • • •|
32
- // |• • • • •|
33
- // 4/3/2-----5
34
- //
35
- // Waffles can also represent fractional intervals (e.g., 2.4–10.1). These
36
- // require additional corner cuts, so the implementation below generates a few
37
- // more points.
38
- //
1
+ /**
2
+ * This implementation is based on the waffle chart implementation in Observable Plot!
3
+ * https://github.com/observablehq/plot/blob/main/src/marks/waffle.js
4
+ *
5
+ * Kept the comments from the original implementation for clarity.
6
+ */
39
7
  import { getPatternId } from '../../helpers/getBaseStyles';
40
8
  export function wafflePolygon(y, options, scales) {
41
9
  const x = y === 'y' ? 'x' : 'y';
@@ -3,7 +3,7 @@ export { bollingerX, bollingerY } from './bollinger.js';
3
3
  export { geoCentroid } from './centroid.js';
4
4
  export { filter } from './filter.js';
5
5
  export { map, mapX, mapY } from './map.js';
6
- export { normalizeX, normalizeY } from './normalize.js';
6
+ export { normalizeX, normalizeY, normalizeParallelX, normalizeParallelY } from './normalize.js';
7
7
  export { group, groupX, groupY, groupZ } from './group.js';
8
8
  export { intervalX, intervalY } from './interval.js';
9
9
  export { jitterX, jitterY } from './jitter.js';
@@ -3,7 +3,7 @@ export { bollingerX, bollingerY } from './bollinger.js';
3
3
  export { geoCentroid } from './centroid.js';
4
4
  export { filter } from './filter.js';
5
5
  export { map, mapX, mapY } from './map.js';
6
- export { normalizeX, normalizeY } from './normalize.js';
6
+ export { normalizeX, normalizeY, normalizeParallelX, normalizeParallelY } from './normalize.js';
7
7
  export { group, groupX, groupY, groupZ } from './group.js';
8
8
  export { intervalX, intervalY } from './interval.js';
9
9
  export { jitterX, jitterY } from './jitter.js';
@@ -1,5 +1,6 @@
1
1
  import { mapX, mapY } from './map.js';
2
2
  import { min, max, mean, median, sum, deviation, extent } from 'd3-array';
3
+ import { sort } from './sort.js';
3
4
  export function normalizeX(args, basis) {
4
5
  return mapX(args, normalize(basis));
5
6
  }
@@ -84,3 +85,47 @@ const normalizeMean = normalizeAccessor(mean);
84
85
  const normalizeMedian = normalizeAccessor(median);
85
86
  const normalizeMin = normalizeAccessor(min);
86
87
  const normalizeSum = normalizeAccessor(sum);
88
+ /**
89
+ * Convenience wrapper for normalizeY for parallel coordinates.
90
+ *
91
+ * Channels:
92
+ * - x: the categorical axis (e.g., 'Measurement')
93
+ * - y: the value to normalize (e.g., 'Value')
94
+ * - z: the grouping variable (e.g., 'Id')
95
+ */
96
+ export function normalizeParallelY(args, basis) {
97
+ return sort({
98
+ ...normalizeY({
99
+ ...args,
100
+ // use x as the grouping variable for normalization to normalize
101
+ // each axis independently
102
+ z: args.x
103
+ }, basis),
104
+ // restore original grouping by line
105
+ z: args.z,
106
+ // sort by original order
107
+ sort: args.z
108
+ });
109
+ }
110
+ /**
111
+ * Convenience wrapper for normalizeY for parallel coordinates.
112
+ *
113
+ * Channels:
114
+ * - x: the categorical axis (e.g., 'Measurement')
115
+ * - y: the value to normalize (e.g., 'Value')
116
+ * - z: the grouping variable (e.g., 'Id')
117
+ */
118
+ export function normalizeParallelX(args, basis) {
119
+ return sort({
120
+ ...normalizeX({
121
+ ...args,
122
+ // use x as the grouping variable for normalization to normalize
123
+ // each axis independently
124
+ z: args.y
125
+ }, basis),
126
+ // restore original grouping by line
127
+ z: args.z,
128
+ // sort by original order
129
+ sort: args.z
130
+ });
131
+ }
@@ -1,14 +1,30 @@
1
1
  <script>
2
2
  import { resolve } from '$app/paths';
3
+ import { useDark } from './isDark.svelte';
3
4
  let { examples } = $props();
5
+
6
+ const exampleImages = import.meta.glob('../../snapshots/*/*.png', {
7
+ eager: true,
8
+ query: {
9
+ enhanced: true,
10
+ w: 640
11
+ }
12
+ });
13
+
14
+ const ds = useDark();
4
15
  </script>
5
16
 
6
17
  <div class="list">
7
18
  {#each examples as page, i (i)}
8
19
  <a href={resolve(page.url)}>
9
20
  <div>
10
- {#if page.screenshot}
11
- <img src={page.screenshot} alt={page.title} />{/if}
21
+ {#if exampleImages[`../../snapshots/${page.key}.png`]}
22
+ <enhanced:img
23
+ src={ds.isDark
24
+ ? exampleImages[`../../snapshots/${page.key}.dark.png`].default.img.src
25
+ : exampleImages[`../../snapshots/${page.key}.png`].default.img.src}
26
+ alt={page.title} />
27
+ {/if}
12
28
  </div>
13
29
  <h4>
14
30
  {page.title}
@@ -49,7 +65,7 @@
49
65
  }
50
66
  }
51
67
 
52
- .list img {
68
+ .list :global(img) {
53
69
  width: 100%;
54
70
  box-sizing: border-box;
55
71
  border-radius: 3px;
@@ -0,0 +1,149 @@
1
+ <script lang="ts">
2
+ import { resolve } from '$app/paths';
3
+ import { useDark } from './isDark.svelte';
4
+
5
+ const exampleImages = import.meta.glob('../../snapshots/*/*.png', {
6
+ eager: true,
7
+ query: {
8
+ enhanced: true,
9
+ w: 440
10
+ }
11
+ });
12
+
13
+ let {
14
+ paths,
15
+ pages
16
+ }: {
17
+ paths: Record<string, string[]>;
18
+ pages: Record<
19
+ string,
20
+ {
21
+ title: string;
22
+ description?: string;
23
+ sortKey?: number;
24
+ transforms?: string[];
25
+ }
26
+ >;
27
+ } = $props();
28
+
29
+ const ds = useDark();
30
+
31
+ function sortPages(a: string, b: string) {
32
+ const sortA = pages[a].sortKey ?? 10;
33
+ const sortB = pages[b].sortKey ?? 10;
34
+ return sortA - sortB;
35
+ }
36
+ </script>
37
+
38
+ <div class="column-container">
39
+ {#each Object.entries(paths).sort( (a, b) => a[0].localeCompare(b[0]) ) as [group, groupPages] (group)}
40
+ <div>
41
+ <h2 id={group}>
42
+ <a href={resolve(`/examples/${group}`)}
43
+ >{pages[groupPages.find((p) => p.endsWith('/_index.svelte'))]?.title ??
44
+ group}</a>
45
+ </h2>
46
+ <div class="example-grid">
47
+ {#each groupPages
48
+ .sort(sortPages)
49
+ .filter((p) => !p.endsWith('/_index.svelte')) as page (page)}
50
+ <a
51
+ animate:slide
52
+ href={resolve(page.replace('./', './examples/').replace('.svelte', ''))}
53
+ ><div>
54
+ <enhanced:img
55
+ title={pages[page].title}
56
+ src={exampleImages[
57
+ `../../snapshots/${page
58
+ .replace('./', '')
59
+ .replace('.svelte', ds.isDark ? '.dark.png' : '.png')}`
60
+ ].default}
61
+ alt={pages[page].title} />
62
+ <div class="title">{pages[page].title}</div>
63
+ </div></a>
64
+ {/each}
65
+ </div>
66
+ </div>
67
+ {/each}
68
+ </div>
69
+
70
+ <style>
71
+ :global(.content) h2 {
72
+ margin-top: 1rem !important;
73
+ margin-bottom: 1rem;
74
+ text-transform: capitalize;
75
+ border: 0;
76
+ a {
77
+ text-decoration: none;
78
+ color: inherit;
79
+ }
80
+ }
81
+
82
+ .column-container {
83
+ container-type: inline-size;
84
+
85
+ h3 {
86
+ break-before: avoid-column;
87
+ text-transform: capitalize;
88
+ }
89
+ }
90
+
91
+ .example-grid {
92
+ --example-grid-columns: 5;
93
+
94
+ /* width: 100%; */
95
+ display: grid;
96
+ /* overflow-x: clip; */
97
+ grid-template-columns: repeat(var(--example-grid-columns), 1fr);
98
+ grid-auto-rows: 1fr;
99
+ gap: 1.25rem;
100
+
101
+ a {
102
+ text-decoration: none;
103
+ color: inherit;
104
+ }
105
+
106
+ .title {
107
+ font-size: 0.75rem;
108
+ opacity: 0.8;
109
+ line-height: 1.2;
110
+ text-decoration: none;
111
+ }
112
+ }
113
+
114
+ @container (max-width: 800px) {
115
+ .example-grid {
116
+ --example-grid-columns: 4;
117
+ }
118
+ }
119
+ @container (max-width: 600px) {
120
+ .example-grid {
121
+ --example-grid-columns: 3;
122
+ }
123
+ }
124
+ @container (max-width: 500px) {
125
+ .example-grid {
126
+ --example-grid-columns: 2;
127
+ }
128
+ }
129
+
130
+ .example-grid :global(img) {
131
+ height: auto !important;
132
+ aspect-ratio: 4 / 3;
133
+ object-fit: cover;
134
+ width: 100%;
135
+ height: auto;
136
+
137
+ position: relative;
138
+ transition: transform 0.05s ease-out;
139
+ &:hover {
140
+ transform: scale(1.5);
141
+ object-fit: contain;
142
+ z-index: 1;
143
+
144
+ background: fixed var(--svelteplot-bg);
145
+
146
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
147
+ }
148
+ }
149
+ </style>
@@ -0,0 +1,12 @@
1
+ type $$ComponentProps = {
2
+ paths: Record<string, string[]>;
3
+ pages: Record<string, {
4
+ title: string;
5
+ description?: string;
6
+ sortKey?: number;
7
+ transforms?: string[];
8
+ }>;
9
+ };
10
+ declare const ExamplesPagePreview: import("svelte").Component<$$ComponentProps, {}, "">;
11
+ type ExamplesPagePreview = ReturnType<typeof ExamplesPagePreview>;
12
+ export default ExamplesPagePreview;
@@ -0,0 +1,6 @@
1
+ declare class DarkState {
2
+ isDark: boolean;
3
+ constructor();
4
+ }
5
+ export declare function useDark(): DarkState;
6
+ export {};
@@ -0,0 +1,10 @@
1
+ class DarkState {
2
+ isDark = $state(false);
3
+ constructor() {
4
+ this.isDark = false;
5
+ }
6
+ }
7
+ const darkState = new DarkState();
8
+ export function useDark() {
9
+ return darkState;
10
+ }