@loidolt/theme-svelte 0.2.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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/dist/components/Alert.svelte +36 -0
  3. package/dist/components/Alert.svelte.d.ts +15 -0
  4. package/dist/components/AppShell.svelte +31 -0
  5. package/dist/components/AppShell.svelte.d.ts +14 -0
  6. package/dist/components/Badge.svelte +27 -0
  7. package/dist/components/Badge.svelte.d.ts +12 -0
  8. package/dist/components/Brand.svelte +35 -0
  9. package/dist/components/Brand.svelte.d.ts +15 -0
  10. package/dist/components/Button.svelte +85 -0
  11. package/dist/components/Button.svelte.d.ts +21 -0
  12. package/dist/components/Card.svelte +43 -0
  13. package/dist/components/Card.svelte.d.ts +18 -0
  14. package/dist/components/Checkbox.svelte +54 -0
  15. package/dist/components/Checkbox.svelte.d.ts +21 -0
  16. package/dist/components/ContextBar.svelte +33 -0
  17. package/dist/components/ContextBar.svelte.d.ts +13 -0
  18. package/dist/components/Dialog.svelte +84 -0
  19. package/dist/components/Dialog.svelte.d.ts +28 -0
  20. package/dist/components/DropdownMenu.svelte +99 -0
  21. package/dist/components/DropdownMenu.svelte.d.ts +47 -0
  22. package/dist/components/Field.svelte +52 -0
  23. package/dist/components/Field.svelte.d.ts +24 -0
  24. package/dist/components/IconButton.svelte +43 -0
  25. package/dist/components/IconButton.svelte.d.ts +16 -0
  26. package/dist/components/Input.svelte +27 -0
  27. package/dist/components/Input.svelte.d.ts +11 -0
  28. package/dist/components/Label.svelte +24 -0
  29. package/dist/components/Label.svelte.d.ts +11 -0
  30. package/dist/components/NavMenu.svelte +62 -0
  31. package/dist/components/NavMenu.svelte.d.ts +43 -0
  32. package/dist/components/NumberField.svelte +78 -0
  33. package/dist/components/NumberField.svelte.d.ts +21 -0
  34. package/dist/components/PageHeader.svelte +37 -0
  35. package/dist/components/PageHeader.svelte.d.ts +15 -0
  36. package/dist/components/Panel.svelte +38 -0
  37. package/dist/components/Panel.svelte.d.ts +15 -0
  38. package/dist/components/Popover.svelte +58 -0
  39. package/dist/components/Popover.svelte.d.ts +21 -0
  40. package/dist/components/Progress.svelte +43 -0
  41. package/dist/components/Progress.svelte.d.ts +12 -0
  42. package/dist/components/RadioGroup.svelte +49 -0
  43. package/dist/components/RadioGroup.svelte.d.ts +37 -0
  44. package/dist/components/Section.svelte +39 -0
  45. package/dist/components/Section.svelte.d.ts +15 -0
  46. package/dist/components/Select.svelte +57 -0
  47. package/dist/components/Select.svelte.d.ts +41 -0
  48. package/dist/components/Separator.svelte +29 -0
  49. package/dist/components/Separator.svelte.d.ts +10 -0
  50. package/dist/components/Sidebar.svelte +35 -0
  51. package/dist/components/Sidebar.svelte.d.ts +16 -0
  52. package/dist/components/Skeleton.svelte +26 -0
  53. package/dist/components/Skeleton.svelte.d.ts +11 -0
  54. package/dist/components/Spinner.svelte +22 -0
  55. package/dist/components/Spinner.svelte.d.ts +10 -0
  56. package/dist/components/Switch.svelte +62 -0
  57. package/dist/components/Switch.svelte.d.ts +17 -0
  58. package/dist/components/Table.svelte +43 -0
  59. package/dist/components/Table.svelte.d.ts +17 -0
  60. package/dist/components/Tabs.svelte +63 -0
  61. package/dist/components/Tabs.svelte.d.ts +41 -0
  62. package/dist/components/Textarea.svelte +27 -0
  63. package/dist/components/Textarea.svelte.d.ts +11 -0
  64. package/dist/components/Toast.svelte +53 -0
  65. package/dist/components/Toast.svelte.d.ts +16 -0
  66. package/dist/components/ToastViewport.svelte +38 -0
  67. package/dist/components/ToastViewport.svelte.d.ts +13 -0
  68. package/dist/components/Tooltip.svelte +76 -0
  69. package/dist/components/Tooltip.svelte.d.ts +28 -0
  70. package/dist/components/TooltipProvider.svelte +33 -0
  71. package/dist/components/TooltipProvider.svelte.d.ts +14 -0
  72. package/dist/components/Topbar.svelte +32 -0
  73. package/dist/components/Topbar.svelte.d.ts +14 -0
  74. package/dist/components/Workspace.svelte +38 -0
  75. package/dist/components/Workspace.svelte.d.ts +12 -0
  76. package/dist/index.d.ts +46 -0
  77. package/dist/index.js +44 -0
  78. package/dist/styles.css +1 -0
  79. package/dist/toaster.svelte.d.ts +43 -0
  80. package/dist/toaster.svelte.js +82 -0
  81. package/dist/types.d.ts +39 -0
  82. package/dist/types.js +1 -0
  83. package/dist/utils.d.ts +5 -0
  84. package/dist/utils.js +7 -0
  85. package/package.json +66 -0
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ export { default as Alert } from './components/Alert.svelte';
2
+ export { default as AppShell } from './components/AppShell.svelte';
3
+ export { default as Badge } from './components/Badge.svelte';
4
+ export { default as Brand } from './components/Brand.svelte';
5
+ export { default as Button } from './components/Button.svelte';
6
+ export { default as Card } from './components/Card.svelte';
7
+ export { default as Checkbox } from './components/Checkbox.svelte';
8
+ export { default as ContextBar } from './components/ContextBar.svelte';
9
+ export { default as Dialog } from './components/Dialog.svelte';
10
+ export { default as DropdownMenu } from './components/DropdownMenu.svelte';
11
+ export { default as Field } from './components/Field.svelte';
12
+ export { default as IconButton } from './components/IconButton.svelte';
13
+ export { default as Input } from './components/Input.svelte';
14
+ export { default as Label } from './components/Label.svelte';
15
+ export { default as NavMenu } from './components/NavMenu.svelte';
16
+ export { default as NumberField } from './components/NumberField.svelte';
17
+ export { default as PageHeader } from './components/PageHeader.svelte';
18
+ export { default as Panel } from './components/Panel.svelte';
19
+ export { default as Popover } from './components/Popover.svelte';
20
+ export { default as Progress } from './components/Progress.svelte';
21
+ export { default as RadioGroup } from './components/RadioGroup.svelte';
22
+ export { default as Section } from './components/Section.svelte';
23
+ export { default as Select } from './components/Select.svelte';
24
+ export { default as Separator } from './components/Separator.svelte';
25
+ export { default as Sidebar } from './components/Sidebar.svelte';
26
+ export { default as Skeleton } from './components/Skeleton.svelte';
27
+ export { default as Spinner } from './components/Spinner.svelte';
28
+ export { default as Switch } from './components/Switch.svelte';
29
+ export { default as Table } from './components/Table.svelte';
30
+ export { default as Tabs } from './components/Tabs.svelte';
31
+ export { default as Textarea } from './components/Textarea.svelte';
32
+ export { default as Toast } from './components/Toast.svelte';
33
+ export { default as ToastViewport } from './components/ToastViewport.svelte';
34
+ export { default as Tooltip } from './components/Tooltip.svelte';
35
+ export { default as TooltipProvider } from './components/TooltipProvider.svelte';
36
+ export { default as Topbar } from './components/Topbar.svelte';
37
+ export { default as Workspace } from './components/Workspace.svelte';
38
+ /**
39
+ * Bits UI primitives behind the wrappers, for menus and overlays this package does not
40
+ * model declaratively (checkbox/radio items, submenus, custom overlay composition).
41
+ */
42
+ export { Dialog as DialogPrimitive, DropdownMenu as DropdownMenuPrimitive, Popover as PopoverPrimitive, Tabs as TabsPrimitive, Tooltip as TooltipPrimitive, } from 'bits-ui';
43
+ export { cx } from './utils.js';
44
+ export { createToaster } from './toaster.svelte.js';
@@ -0,0 +1 @@
1
+ @import '@loidolt/theme-styles';
@@ -0,0 +1,43 @@
1
+ import type { StatusVariant } from './types.js';
2
+ export interface ToastOptions {
3
+ title: string;
4
+ description?: string;
5
+ variant?: StatusVariant;
6
+ /** Milliseconds before auto-dismiss. `0` or `Infinity` keeps the toast until dismissed. */
7
+ duration?: number;
8
+ }
9
+ export interface ToastRecord extends ToastOptions {
10
+ id: string;
11
+ }
12
+ export interface ToasterOptions {
13
+ /** Default `duration` for toasts that do not set one. */
14
+ duration?: number;
15
+ /** Oldest toasts past this count are dropped. */
16
+ max?: number;
17
+ }
18
+ export interface Toaster {
19
+ /** Live queue, oldest first. Feed it to `ToastViewport`. */
20
+ readonly toasts: ToastRecord[];
21
+ /** Adds a toast and returns its id. */
22
+ push(toast: ToastOptions): string;
23
+ dismiss(id: string): void;
24
+ clear(): void;
25
+ /** Suspends every auto-dismiss timer — call on pointer enter / focus in. */
26
+ pause(): void;
27
+ /** Resumes with the time each toast had left — call on pointer leave / focus out. */
28
+ resume(): void;
29
+ }
30
+ /**
31
+ * Queue behind `Toast` / `ToastViewport`: auto-dismiss with the remaining time preserved
32
+ * across `pause()`/`resume()`, so hovering a toast does not lose the countdown.
33
+ *
34
+ * ```svelte
35
+ * const toaster = createToaster();
36
+ * <ToastViewport onpointerenter={toaster.pause} onpointerleave={toaster.resume}>
37
+ * {#each toaster.toasts as toast (toast.id)}
38
+ * <Toast {...toast} onDismiss={() => toaster.dismiss(toast.id)} />
39
+ * {/each}
40
+ * </ToastViewport>
41
+ * ```
42
+ */
43
+ export declare function createToaster(options?: ToasterOptions): Toaster;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Queue behind `Toast` / `ToastViewport`: auto-dismiss with the remaining time preserved
3
+ * across `pause()`/`resume()`, so hovering a toast does not lose the countdown.
4
+ *
5
+ * ```svelte
6
+ * const toaster = createToaster();
7
+ * <ToastViewport onpointerenter={toaster.pause} onpointerleave={toaster.resume}>
8
+ * {#each toaster.toasts as toast (toast.id)}
9
+ * <Toast {...toast} onDismiss={() => toaster.dismiss(toast.id)} />
10
+ * {/each}
11
+ * </ToastViewport>
12
+ * ```
13
+ */
14
+ export function createToaster(options = {}) {
15
+ const { duration: defaultDuration = 5000, max = 5 } = options;
16
+ const toasts = $state([]);
17
+ // Plain Map on purpose: these are timer handles, not UI state, and nothing renders from them.
18
+ // eslint-disable-next-line svelte/prefer-svelte-reactivity
19
+ const timers = new Map();
20
+ let startedAt = 0;
21
+ let paused = false;
22
+ let counter = 0;
23
+ function clearTimer(id) {
24
+ const timer = timers.get(id);
25
+ if (timer)
26
+ clearTimeout(timer.timeout);
27
+ timers.delete(id);
28
+ }
29
+ function arm(id, remaining) {
30
+ if (!Number.isFinite(remaining) || remaining <= 0)
31
+ return;
32
+ startedAt = Date.now();
33
+ timers.set(id, { timeout: setTimeout(() => dismiss(id), remaining), remaining });
34
+ }
35
+ function dismiss(id) {
36
+ clearTimer(id);
37
+ const index = toasts.findIndex((toast) => toast.id === id);
38
+ if (index !== -1)
39
+ toasts.splice(index, 1);
40
+ }
41
+ function push(toast) {
42
+ const id = `ldt-toast-${++counter}`;
43
+ toasts.push({ ...toast, id });
44
+ while (toasts.length > max)
45
+ dismiss(toasts[0].id);
46
+ if (!paused)
47
+ arm(id, toast.duration ?? defaultDuration);
48
+ else
49
+ timers.set(id, { timeout: 0, remaining: toast.duration ?? defaultDuration });
50
+ return id;
51
+ }
52
+ return {
53
+ get toasts() {
54
+ return toasts;
55
+ },
56
+ push,
57
+ dismiss,
58
+ clear() {
59
+ for (const toast of [...toasts])
60
+ dismiss(toast.id);
61
+ },
62
+ pause() {
63
+ if (paused)
64
+ return;
65
+ paused = true;
66
+ const elapsed = Date.now() - startedAt;
67
+ for (const [id, timer] of timers) {
68
+ clearTimeout(timer.timeout);
69
+ timers.set(id, { timeout: 0, remaining: Math.max(0, timer.remaining - elapsed) });
70
+ }
71
+ },
72
+ resume() {
73
+ if (!paused)
74
+ return;
75
+ paused = false;
76
+ for (const [id, timer] of [...timers]) {
77
+ timers.delete(id);
78
+ arm(id, timer.remaining);
79
+ }
80
+ },
81
+ };
82
+ }
@@ -0,0 +1,39 @@
1
+ import type { Snippet } from 'svelte';
2
+ /** Action colour set — anything the user can press. */
3
+ export type ActionVariant = 'default' | 'primary' | 'quiet' | 'danger' | 'ghost' | 'text';
4
+ /** Status colour set — anything that reports state. */
5
+ export type StatusVariant = 'info' | 'success' | 'warning' | 'error';
6
+ /** Badge spans both sets: neutral, brand accent, or a status. */
7
+ export type BadgeVariant = 'default' | 'accent' | StatusVariant;
8
+ /** Shared control scale. Dialogs extend it with `xl`. */
9
+ export type ControlSize = 'sm' | 'md' | 'lg';
10
+ export type DialogSize = ControlSize | 'xl';
11
+ export type Placement = 'top' | 'right' | 'bottom' | 'left';
12
+ export type Alignment = 'start' | 'center' | 'end';
13
+ export type Orientation = 'horizontal' | 'vertical';
14
+ export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
15
+ /** A selectable value with a human label. Used by Select, RadioGroup, Tabs and menus. */
16
+ export interface Option<T extends string = string> {
17
+ value: T;
18
+ label: string;
19
+ disabled?: boolean;
20
+ }
21
+ /** `Option` is the single vocabulary for choice lists; `NavItem` is kept as a readable alias. */
22
+ export type NavItem<T extends string = string> = Option<T>;
23
+ /** A `DropdownMenu` row. Renders as a link when `href` is set. */
24
+ export interface MenuItem<T extends string = string> extends Option<T> {
25
+ href?: string;
26
+ /** Trailing hint, e.g. a keyboard shortcut. */
27
+ hint?: string;
28
+ /** Leading visual. */
29
+ icon?: Snippet;
30
+ /** Draw a separator above this item. */
31
+ separatorBefore?: boolean;
32
+ }
33
+ /**
34
+ * Payload of Bits UI's `child` snippet: spread `props` onto your own element to take over
35
+ * rendering of a trigger without nesting an extra button inside it.
36
+ */
37
+ export interface TriggerChildProps {
38
+ props: Record<string, unknown>;
39
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Joins truthy class names. Falsy entries are dropped, so `condition && 'ldt-x'` is safe.
3
+ * Accepts the `class` prop of any component in this package.
4
+ */
5
+ export declare function cx(...values: Array<string | false | null | undefined>): string;
package/dist/utils.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Joins truthy class names. Falsy entries are dropped, so `condition && 'ldt-x'` is safe.
3
+ * Accepts the `class` prop of any component in this package.
4
+ */
5
+ export function cx(...values) {
6
+ return values.filter(Boolean).join(' ');
7
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@loidolt/theme-svelte",
3
+ "version": "0.2.0",
4
+ "description": "Accessible Svelte 5 components for Loidolt applications",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "svelte": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "svelte": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./styles.css": "./dist/styles.css",
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "sideEffects": [
22
+ "**/*.css"
23
+ ],
24
+ "engines": {
25
+ "node": ">=22"
26
+ },
27
+ "scripts": {
28
+ "build": "svelte-package -i src/lib -o dist && cp src/styles.css dist/styles.css",
29
+ "typecheck": "svelte-check --tsconfig ./tsconfig.json",
30
+ "test": "vitest run",
31
+ "test:a11y": "vitest run tests/a11y.test.ts",
32
+ "clean": "rimraf dist"
33
+ },
34
+ "dependencies": {
35
+ "@loidolt/theme-styles": "^0.2.0",
36
+ "@loidolt/theme-tokens": "^0.2.0",
37
+ "bits-ui": "^2.19.0"
38
+ },
39
+ "peerDependencies": {
40
+ "svelte": "^5.33.0"
41
+ },
42
+ "devDependencies": {
43
+ "@sveltejs/package": "^2.5.8",
44
+ "@types/node": "^24.3.0",
45
+ "@sveltejs/vite-plugin-svelte": "^7.0.0",
46
+ "@testing-library/jest-dom": "^6.8.0",
47
+ "@testing-library/svelte": "^5.2.8",
48
+ "@testing-library/user-event": "^14.6.1",
49
+ "jsdom": "^27.0.0",
50
+ "rimraf": "^6.0.1",
51
+ "svelte": "^5.56.10",
52
+ "svelte-check": "^4.3.2",
53
+ "typescript": "^6.0.3",
54
+ "vitest": "^4.0.0",
55
+ "vitest-axe": "^0.1.0"
56
+ },
57
+ "publishConfig": {
58
+ "access": "public",
59
+ "provenance": true
60
+ },
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/loidolt/loidolt-theme.git",
64
+ "directory": "packages/svelte"
65
+ }
66
+ }