@loidolt/theme-svelte 0.3.0 → 0.5.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/README.md +21 -0
- package/dist/components/AlertDialog.svelte +28 -7
- package/dist/components/AlertDialog.svelte.d.ts +4 -1
- package/dist/components/AppShell.svelte +11 -3
- package/dist/components/AppShell.svelte.d.ts +4 -1
- package/dist/components/Card.svelte +23 -5
- package/dist/components/Card.svelte.d.ts +11 -4
- package/dist/components/CodeBlock.svelte +55 -0
- package/dist/components/CodeBlock.svelte.d.ts +14 -0
- package/dist/components/CommentList.svelte +67 -0
- package/dist/components/CommentList.svelte.d.ts +53 -0
- package/dist/components/Dialog.svelte +28 -6
- package/dist/components/Dialog.svelte.d.ts +4 -1
- package/dist/components/Drawer.svelte +21 -6
- package/dist/components/Drawer.svelte.d.ts +4 -1
- package/dist/components/FileInput.svelte +47 -0
- package/dist/components/FileInput.svelte.d.ts +15 -0
- package/dist/components/Filmstrip.svelte +72 -0
- package/dist/components/Filmstrip.svelte.d.ts +50 -0
- package/dist/components/FloatingBar.svelte +43 -0
- package/dist/components/FloatingBar.svelte.d.ts +16 -0
- package/dist/components/ListRow.svelte +50 -0
- package/dist/components/ListRow.svelte.d.ts +18 -0
- package/dist/components/Marker.svelte +38 -0
- package/dist/components/Marker.svelte.d.ts +14 -0
- package/dist/components/Popover.svelte +24 -3
- package/dist/components/Popover.svelte.d.ts +4 -1
- package/dist/components/RecordStepper.svelte +58 -0
- package/dist/components/RecordStepper.svelte.d.ts +18 -0
- package/dist/components/SegmentedNav.svelte +53 -0
- package/dist/components/SegmentedNav.svelte.d.ts +22 -0
- package/dist/components/Stat.svelte +41 -0
- package/dist/components/Stat.svelte.d.ts +17 -0
- package/dist/components/StatusDot.svelte +27 -0
- package/dist/components/StatusDot.svelte.d.ts +12 -0
- package/dist/components/SwatchGroup.svelte +69 -0
- package/dist/components/SwatchGroup.svelte.d.ts +44 -0
- package/dist/components/Switch.svelte +19 -0
- package/dist/components/Tabs.svelte +10 -0
- package/dist/components/ThemeToggle.svelte +102 -31
- package/dist/components/ThemeToggle.svelte.d.ts +5 -10
- package/dist/components/Thumbnail.svelte +51 -0
- package/dist/components/Thumbnail.svelte.d.ts +19 -0
- package/dist/components/ToastViewport.svelte +1 -0
- package/dist/components/Workspace.svelte +9 -1
- package/dist/components/Workspace.svelte.d.ts +4 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/theme.svelte.js +17 -7
- package/dist/toaster.svelte.d.ts +9 -2
- package/dist/toaster.svelte.js +37 -4
- package/package.json +8 -7
package/dist/theme.svelte.js
CHANGED
|
@@ -138,14 +138,24 @@ export function createTheme(options = {}) {
|
|
|
138
138
|
*/
|
|
139
139
|
export function themeScript(options = {}) {
|
|
140
140
|
const { storageKey = 'loidolt-theme', attribute = 'data-theme', defaultPreference = 'system', defaultScheme = 'light', tag = false, } = options;
|
|
141
|
-
// JSON
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
141
|
+
// JSON string escaping alone leaves `<` intact, including a literal `</script>` that would end
|
|
142
|
+
// an inline script element. Escaping HTML-significant characters and the two JavaScript line
|
|
143
|
+
// separators keeps every option inside its string literal in both source-only and tagged forms.
|
|
144
|
+
const serialize = (value) => JSON.stringify(value)
|
|
145
|
+
.replaceAll('<', '\\u003c')
|
|
146
|
+
.replaceAll('>', '\\u003e')
|
|
147
|
+
.replaceAll('&', '\\u0026')
|
|
148
|
+
.replaceAll('\u2028', '\\u2028')
|
|
149
|
+
.replaceAll('\u2029', '\\u2029');
|
|
150
|
+
const key = serialize(storageKey);
|
|
151
|
+
const attr = serialize(attribute);
|
|
152
|
+
const fallback = serialize(defaultPreference);
|
|
153
|
+
const scheme = serialize(defaultScheme);
|
|
146
154
|
const source = `(function(){try{` +
|
|
147
|
-
`var p=${
|
|
148
|
-
|
|
155
|
+
`var p=${fallback};` +
|
|
156
|
+
// Storage failure must not skip system resolution and attribute application.
|
|
157
|
+
`try{var v=${key}===null?null:localStorage.getItem(${key});` +
|
|
158
|
+
`if(v==="light"||v==="dark"||v==="system")p=v;}catch(e){}` +
|
|
149
159
|
`var s=${scheme};` +
|
|
150
160
|
`if(typeof matchMedia==="function")s=matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";` +
|
|
151
161
|
`document.documentElement.setAttribute(${attr},p==="system"?s:p);` +
|
package/dist/toaster.svelte.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface ToastRecord extends ToastOptions {
|
|
|
10
10
|
id: string;
|
|
11
11
|
}
|
|
12
12
|
export interface ToasterOptions {
|
|
13
|
-
/** Default `duration` for toasts that do not set one. */
|
|
13
|
+
/** Default `duration` for toasts that do not set one. Defaults to persistent (`0`). */
|
|
14
14
|
duration?: number;
|
|
15
15
|
/** Oldest toasts past this count are dropped. */
|
|
16
16
|
max?: number;
|
|
@@ -26,6 +26,8 @@ export interface Toaster {
|
|
|
26
26
|
pause(): void;
|
|
27
27
|
/** Resumes with the time each toast had left — call on pointer leave / focus out. */
|
|
28
28
|
resume(): void;
|
|
29
|
+
/** Clears the queue and every timer. Automatic for a component-scoped instance. */
|
|
30
|
+
destroy(): void;
|
|
29
31
|
}
|
|
30
32
|
/**
|
|
31
33
|
* Queue behind `Toast` / `ToastViewport`: auto-dismiss with the remaining time preserved
|
|
@@ -33,7 +35,12 @@ export interface Toaster {
|
|
|
33
35
|
*
|
|
34
36
|
* ```svelte
|
|
35
37
|
* const toaster = createToaster();
|
|
36
|
-
* <ToastViewport
|
|
38
|
+
* <ToastViewport
|
|
39
|
+
* onpointerenter={toaster.pause}
|
|
40
|
+
* onpointerleave={toaster.resume}
|
|
41
|
+
* onfocusin={toaster.pause}
|
|
42
|
+
* onfocusout={toaster.resume}
|
|
43
|
+
* >
|
|
37
44
|
* {#each toaster.toasts as toast (toast.id)}
|
|
38
45
|
* <Toast {...toast} onDismiss={() => toaster.dismiss(toast.id)} />
|
|
39
46
|
* {/each}
|
package/dist/toaster.svelte.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import { onDestroy } from 'svelte';
|
|
1
2
|
/**
|
|
2
3
|
* Queue behind `Toast` / `ToastViewport`: auto-dismiss with the remaining time preserved
|
|
3
4
|
* across `pause()`/`resume()`, so hovering a toast does not lose the countdown.
|
|
4
5
|
*
|
|
5
6
|
* ```svelte
|
|
6
7
|
* const toaster = createToaster();
|
|
7
|
-
* <ToastViewport
|
|
8
|
+
* <ToastViewport
|
|
9
|
+
* onpointerenter={toaster.pause}
|
|
10
|
+
* onpointerleave={toaster.resume}
|
|
11
|
+
* onfocusin={toaster.pause}
|
|
12
|
+
* onfocusout={toaster.resume}
|
|
13
|
+
* >
|
|
8
14
|
* {#each toaster.toasts as toast (toast.id)}
|
|
9
15
|
* <Toast {...toast} onDismiss={() => toaster.dismiss(toast.id)} />
|
|
10
16
|
* {/each}
|
|
@@ -12,7 +18,14 @@
|
|
|
12
18
|
* ```
|
|
13
19
|
*/
|
|
14
20
|
export function createToaster(options = {}) {
|
|
15
|
-
const { duration: defaultDuration =
|
|
21
|
+
const { duration: defaultDuration = 0, max = 5 } = options;
|
|
22
|
+
if (!Number.isInteger(max) || max < 1) {
|
|
23
|
+
throw new RangeError('createToaster: `max` must be a positive integer');
|
|
24
|
+
}
|
|
25
|
+
const validDuration = (duration) => duration === Infinity || (Number.isFinite(duration) && duration >= 0);
|
|
26
|
+
if (!validDuration(defaultDuration)) {
|
|
27
|
+
throw new RangeError('createToaster: `duration` must be non-negative or Infinity');
|
|
28
|
+
}
|
|
16
29
|
const toasts = $state([]);
|
|
17
30
|
// Plain Map on purpose: these are timer handles, not UI state, and nothing renders from them.
|
|
18
31
|
// `startedAt` lives per entry: toasts are pushed at different moments, so a shared start
|
|
@@ -44,17 +57,36 @@ export function createToaster(options = {}) {
|
|
|
44
57
|
toasts.splice(index, 1);
|
|
45
58
|
}
|
|
46
59
|
function push(toast) {
|
|
60
|
+
const duration = toast.duration ?? defaultDuration;
|
|
61
|
+
if (!validDuration(duration)) {
|
|
62
|
+
throw new RangeError('createToaster: toast `duration` must be non-negative or Infinity');
|
|
63
|
+
}
|
|
47
64
|
const id = `ldt-toast-${++counter}`;
|
|
48
65
|
toasts.push({ ...toast, id });
|
|
49
66
|
while (toasts.length > max)
|
|
50
67
|
dismiss(toasts[0].id);
|
|
51
68
|
if (!paused)
|
|
52
|
-
arm(id,
|
|
69
|
+
arm(id, duration);
|
|
53
70
|
else {
|
|
54
|
-
timers.set(id, { timeout: null, remaining:
|
|
71
|
+
timers.set(id, { timeout: null, remaining: duration, startedAt: 0 });
|
|
55
72
|
}
|
|
56
73
|
return id;
|
|
57
74
|
}
|
|
75
|
+
const destroy = () => {
|
|
76
|
+
for (const timer of timers.values()) {
|
|
77
|
+
if (timer.timeout !== null)
|
|
78
|
+
clearTimeout(timer.timeout);
|
|
79
|
+
}
|
|
80
|
+
timers.clear();
|
|
81
|
+
toasts.splice(0);
|
|
82
|
+
paused = false;
|
|
83
|
+
};
|
|
84
|
+
try {
|
|
85
|
+
onDestroy(destroy);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* module scope: the caller owns `destroy()` */
|
|
89
|
+
}
|
|
58
90
|
return {
|
|
59
91
|
get toasts() {
|
|
60
92
|
return toasts;
|
|
@@ -92,5 +124,6 @@ export function createToaster(options = {}) {
|
|
|
92
124
|
arm(id, timer.remaining);
|
|
93
125
|
}
|
|
94
126
|
},
|
|
127
|
+
destroy,
|
|
95
128
|
};
|
|
96
129
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loidolt/theme-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Accessible Svelte 5 components for Loidolt applications",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,32 +21,33 @@
|
|
|
21
21
|
"sideEffects": [
|
|
22
22
|
"**/*.css"
|
|
23
23
|
],
|
|
24
|
-
"engines": {
|
|
25
|
-
"node": ">=22"
|
|
26
|
-
},
|
|
27
24
|
"scripts": {
|
|
28
25
|
"build": "svelte-package -i src/lib -o dist && cp src/styles.css dist/styles.css",
|
|
29
26
|
"prepack": "npm run build",
|
|
30
27
|
"typecheck": "svelte-check --tsconfig ./tsconfig.json",
|
|
31
28
|
"test": "vitest run && vitest run --config vitest.config.ssr.ts",
|
|
29
|
+
"test:coverage": "vitest run --coverage",
|
|
32
30
|
"test:a11y": "vitest run tests/a11y.test.ts",
|
|
33
31
|
"clean": "rimraf dist"
|
|
34
32
|
},
|
|
35
33
|
"dependencies": {
|
|
36
|
-
"@loidolt/theme-styles": "^0.
|
|
37
|
-
"@loidolt/theme-tokens": "^0.
|
|
34
|
+
"@loidolt/theme-styles": "^0.5.0",
|
|
35
|
+
"@loidolt/theme-tokens": "^0.5.0",
|
|
38
36
|
"bits-ui": "^2.19.0"
|
|
39
37
|
},
|
|
40
38
|
"peerDependencies": {
|
|
41
39
|
"svelte": "^5.33.0"
|
|
42
40
|
},
|
|
43
41
|
"devDependencies": {
|
|
42
|
+
"@axe-core/playwright": "^4.13.0",
|
|
43
|
+
"@playwright/test": "^1.62.1",
|
|
44
44
|
"@sveltejs/package": "^2.5.8",
|
|
45
|
-
"@types/node": "^24.3.0",
|
|
46
45
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
47
46
|
"@testing-library/jest-dom": "^6.8.0",
|
|
48
47
|
"@testing-library/svelte": "^5.2.8",
|
|
49
48
|
"@testing-library/user-event": "^14.6.1",
|
|
49
|
+
"@types/node": "^24.3.0",
|
|
50
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
50
51
|
"jsdom": "^27.0.0",
|
|
51
52
|
"rimraf": "^6.0.1",
|
|
52
53
|
"svelte": "^5.56.10",
|