@loidolt/theme-svelte 0.3.0 → 0.4.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 +24 -3
- package/dist/components/AlertDialog.svelte.d.ts +4 -1
- package/dist/components/AppShell.svelte +2 -1
- package/dist/components/AppShell.svelte.d.ts +1 -0
- 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 +25 -3
- package/dist/components/Dialog.svelte.d.ts +4 -1
- package/dist/components/Drawer.svelte +18 -3
- 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/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 +2 -0
- package/dist/toaster.svelte.js +30 -2
- package/package.json +8 -7
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends string = string">
|
|
2
|
+
import type { HTMLFieldsetAttributes } from 'svelte/elements';
|
|
3
|
+
import { cx } from '../utils.js';
|
|
4
|
+
|
|
5
|
+
interface SwatchOption<V extends string = string> {
|
|
6
|
+
value: V;
|
|
7
|
+
/** Accessible name of the swatch. Falls back to the color value. */
|
|
8
|
+
label?: string;
|
|
9
|
+
/** Any CSS color. */
|
|
10
|
+
color: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface Props extends HTMLFieldsetAttributes {
|
|
15
|
+
options: SwatchOption<T>[];
|
|
16
|
+
value?: T;
|
|
17
|
+
onValueChange?: (value: T) => void;
|
|
18
|
+
size?: 'sm' | 'md';
|
|
19
|
+
/** Visible group label, rendered as a `<legend>`. */
|
|
20
|
+
label?: string;
|
|
21
|
+
/** Shared `name` for the radios. Defaults to an SSR-stable generated id. */
|
|
22
|
+
name?: string;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
class?: string;
|
|
25
|
+
ref?: HTMLFieldSetElement | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const generatedName = $props.id();
|
|
29
|
+
|
|
30
|
+
let {
|
|
31
|
+
options,
|
|
32
|
+
value = $bindable(),
|
|
33
|
+
onValueChange,
|
|
34
|
+
size = 'md',
|
|
35
|
+
label,
|
|
36
|
+
name = generatedName,
|
|
37
|
+
disabled = false,
|
|
38
|
+
class: className,
|
|
39
|
+
ref = $bindable(null),
|
|
40
|
+
...rest
|
|
41
|
+
}: Props = $props();
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<fieldset bind:this={ref} class={cx('ldt-fieldset', className)} {disabled} {...rest}>
|
|
45
|
+
{#if label}<legend class="ldt-legend">{label}</legend>{/if}
|
|
46
|
+
<div class={cx('ldt-swatch-group', size === 'sm' && 'ldt-swatch-group--sm')}>
|
|
47
|
+
{#each options as option (option.value)}
|
|
48
|
+
<label
|
|
49
|
+
class="ldt-swatch-group__swatch"
|
|
50
|
+
style={`--ldt-swatch: ${option.color};`}
|
|
51
|
+
title={option.label ?? option.color}
|
|
52
|
+
>
|
|
53
|
+
<input
|
|
54
|
+
class="ldt-sr-only"
|
|
55
|
+
type="radio"
|
|
56
|
+
{name}
|
|
57
|
+
value={option.value}
|
|
58
|
+
checked={value === option.value}
|
|
59
|
+
disabled={option.disabled}
|
|
60
|
+
onchange={() => {
|
|
61
|
+
value = option.value;
|
|
62
|
+
onValueChange?.(option.value);
|
|
63
|
+
}}
|
|
64
|
+
/>
|
|
65
|
+
<span class="ldt-sr-only">{option.label ?? option.color}</span>
|
|
66
|
+
</label>
|
|
67
|
+
{/each}
|
|
68
|
+
</div>
|
|
69
|
+
</fieldset>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { HTMLFieldsetAttributes } from 'svelte/elements';
|
|
2
|
+
declare function $$render<T extends string = string>(): {
|
|
3
|
+
props: HTMLFieldsetAttributes & {
|
|
4
|
+
options: {
|
|
5
|
+
value: T;
|
|
6
|
+
/** Accessible name of the swatch. Falls back to the color value. */
|
|
7
|
+
label?: string;
|
|
8
|
+
/** Any CSS color. */
|
|
9
|
+
color: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}[];
|
|
12
|
+
value?: T;
|
|
13
|
+
onValueChange?: (value: T) => void;
|
|
14
|
+
size?: "sm" | "md";
|
|
15
|
+
/** Visible group label, rendered as a `<legend>`. */
|
|
16
|
+
label?: string;
|
|
17
|
+
/** Shared `name` for the radios. Defaults to an SSR-stable generated id. */
|
|
18
|
+
name?: string;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
class?: string;
|
|
21
|
+
ref?: HTMLFieldSetElement | null;
|
|
22
|
+
};
|
|
23
|
+
exports: {};
|
|
24
|
+
bindings: "value" | "ref";
|
|
25
|
+
slots: {};
|
|
26
|
+
events: {};
|
|
27
|
+
};
|
|
28
|
+
declare class __sveltets_Render<T extends string = string> {
|
|
29
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
30
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
31
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
32
|
+
bindings(): "value" | "ref";
|
|
33
|
+
exports(): {};
|
|
34
|
+
}
|
|
35
|
+
interface $$IsomorphicComponent {
|
|
36
|
+
new <T extends string = string>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
37
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
38
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
39
|
+
<T extends string = string>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
40
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
41
|
+
}
|
|
42
|
+
declare const SwatchGroup: $$IsomorphicComponent;
|
|
43
|
+
type SwatchGroup<T extends string = string> = InstanceType<typeof SwatchGroup<T>>;
|
|
44
|
+
export default SwatchGroup;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
5
|
import { cx } from '../utils.js';
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
checked = $bindable(false),
|
|
21
22
|
disabled = false,
|
|
22
23
|
name,
|
|
24
|
+
form,
|
|
23
25
|
value = 'on',
|
|
24
26
|
onCheckedChange,
|
|
25
27
|
onclick,
|
|
@@ -29,6 +31,20 @@
|
|
|
29
31
|
...rest
|
|
30
32
|
}: Props = $props();
|
|
31
33
|
|
|
34
|
+
let input = $state<HTMLInputElement | null>(null);
|
|
35
|
+
const initialChecked = checked;
|
|
36
|
+
|
|
37
|
+
onMount(() => {
|
|
38
|
+
const owner = input?.form;
|
|
39
|
+
if (!owner) return;
|
|
40
|
+
const reset = () => {
|
|
41
|
+
checked = initialChecked;
|
|
42
|
+
onCheckedChange?.(checked);
|
|
43
|
+
};
|
|
44
|
+
owner.addEventListener('reset', reset);
|
|
45
|
+
return () => owner.removeEventListener('reset', reset);
|
|
46
|
+
});
|
|
47
|
+
|
|
32
48
|
function handleClick(event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement }) {
|
|
33
49
|
if (disabled) return;
|
|
34
50
|
checked = !checked;
|
|
@@ -43,6 +59,7 @@
|
|
|
43
59
|
role="switch"
|
|
44
60
|
aria-checked={checked}
|
|
45
61
|
{disabled}
|
|
62
|
+
{form}
|
|
46
63
|
class={cx('ldt-switch', className)}
|
|
47
64
|
{...rest}
|
|
48
65
|
onclick={handleClick}
|
|
@@ -51,11 +68,13 @@
|
|
|
51
68
|
{#if children}<span>{@render children()}</span>{/if}
|
|
52
69
|
</button>
|
|
53
70
|
{#if name}<input
|
|
71
|
+
bind:this={input}
|
|
54
72
|
type="checkbox"
|
|
55
73
|
class="ldt-sr-only"
|
|
56
74
|
tabindex="-1"
|
|
57
75
|
aria-hidden="true"
|
|
58
76
|
{name}
|
|
77
|
+
{form}
|
|
59
78
|
{value}
|
|
60
79
|
{checked}
|
|
61
80
|
{disabled}
|
|
@@ -44,6 +44,16 @@
|
|
|
44
44
|
const active = $derived(
|
|
45
45
|
value !== undefined && tabs.some((tab) => tab.value === value) ? value : tabs[0]?.value
|
|
46
46
|
);
|
|
47
|
+
|
|
48
|
+
// Keep the public binding honest when a dynamic collection removes the selected tab. Effects
|
|
49
|
+
// do not run during SSR, so the server render remains side-effect free while the client and its
|
|
50
|
+
// parent converge on the fallback that is already being displayed.
|
|
51
|
+
$effect(() => {
|
|
52
|
+
if (active !== undefined && value !== active) {
|
|
53
|
+
value = active;
|
|
54
|
+
onValueChange?.(active);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
47
57
|
</script>
|
|
48
58
|
|
|
49
59
|
<TabsPrimitive.Root
|
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type {
|
|
3
|
-
import type { ControlSize
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
import type { ControlSize } from '../types.js';
|
|
4
4
|
import type { Theme, ThemePreference } from '../theme.svelte.js';
|
|
5
|
-
import
|
|
5
|
+
import { cx } from '../utils.js';
|
|
6
6
|
|
|
7
|
-
interface Props extends Omit<
|
|
7
|
+
interface Props extends Omit<HTMLButtonAttributes, 'children' | 'aria-label'> {
|
|
8
8
|
/** The store from `createTheme()`. */
|
|
9
9
|
theme: Theme;
|
|
10
|
-
/**
|
|
11
|
-
id?: string;
|
|
12
|
-
/** Accessible name of the group. */
|
|
10
|
+
/** Accessible name for the preference represented by the icon. */
|
|
13
11
|
label?: string;
|
|
14
12
|
lightLabel?: string;
|
|
15
13
|
darkLabel?: string;
|
|
16
14
|
systemLabel?: string;
|
|
17
|
-
/**
|
|
18
|
-
* Offers "system" alongside the two schemes. Worth keeping: without it a user who has not
|
|
19
|
-
* chosen is silently locked to whichever scheme they happened to land on.
|
|
20
|
-
*/
|
|
15
|
+
/** Include "system" in the cycle. */
|
|
21
16
|
showSystem?: boolean;
|
|
22
17
|
size?: ControlSize;
|
|
23
18
|
class?: string;
|
|
24
|
-
ref?:
|
|
19
|
+
ref?: HTMLButtonElement | null;
|
|
25
20
|
}
|
|
26
21
|
|
|
27
22
|
let {
|
|
@@ -33,30 +28,106 @@
|
|
|
33
28
|
showSystem = true,
|
|
34
29
|
size = 'sm',
|
|
35
30
|
class: className,
|
|
31
|
+
disabled = false,
|
|
32
|
+
type = 'button',
|
|
33
|
+
title,
|
|
34
|
+
onclick,
|
|
36
35
|
ref = $bindable(null),
|
|
37
36
|
...rest
|
|
38
37
|
}: Props = $props();
|
|
39
38
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
const preferences = $derived<ThemePreference[]>(
|
|
40
|
+
showSystem ? ['light', 'dark', 'system'] : ['light', 'dark']
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// If the system option is hidden, represent the scheme that is actually showing and toggle
|
|
44
|
+
// away from it on the first press.
|
|
45
|
+
const activePreference = $derived<ThemePreference>(
|
|
46
|
+
!showSystem && theme.preference === 'system' ? theme.resolved : theme.preference
|
|
47
|
+
);
|
|
48
|
+
const currentIndex = $derived(preferences.indexOf(activePreference));
|
|
49
|
+
const nextPreference = $derived(preferences[(currentIndex + 1) % preferences.length]);
|
|
50
|
+
|
|
51
|
+
const preferenceLabel = (preference: ThemePreference) => {
|
|
52
|
+
if (preference === 'light') return lightLabel;
|
|
53
|
+
if (preference === 'dark') return darkLabel;
|
|
54
|
+
return systemLabel;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const currentLabel = $derived(preferenceLabel(activePreference));
|
|
58
|
+
const nextLabel = $derived(preferenceLabel(nextPreference));
|
|
59
|
+
const buttonLabel = $derived(`${label}: ${currentLabel}`);
|
|
60
|
+
const buttonTitle = $derived(title ?? `${buttonLabel} → ${nextLabel}`);
|
|
45
61
|
</script>
|
|
46
62
|
|
|
47
|
-
<!--
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
<!-- A native button gives the three-state cycle standard keyboard behavior in one compact target. -->
|
|
64
|
+
<button
|
|
65
|
+
bind:this={ref}
|
|
66
|
+
{type}
|
|
67
|
+
{disabled}
|
|
68
|
+
aria-label={buttonLabel}
|
|
69
|
+
title={buttonTitle}
|
|
70
|
+
class={cx(
|
|
71
|
+
'ldt-button ldt-icon-button ldt-button--ghost',
|
|
72
|
+
size !== 'md' && `ldt-button--${size}`,
|
|
73
|
+
className
|
|
74
|
+
)}
|
|
75
|
+
data-theme-preference={activePreference}
|
|
76
|
+
onclick={(event) => {
|
|
77
|
+
theme.preference = nextPreference;
|
|
78
|
+
onclick?.(event);
|
|
59
79
|
}}
|
|
60
|
-
class={className}
|
|
61
80
|
{...rest}
|
|
62
|
-
|
|
81
|
+
>
|
|
82
|
+
{#if activePreference === 'light'}
|
|
83
|
+
<svg
|
|
84
|
+
data-theme-icon="light"
|
|
85
|
+
aria-hidden="true"
|
|
86
|
+
focusable="false"
|
|
87
|
+
width="18"
|
|
88
|
+
height="18"
|
|
89
|
+
viewBox="0 0 24 24"
|
|
90
|
+
fill="none"
|
|
91
|
+
stroke="currentColor"
|
|
92
|
+
stroke-width="1.8"
|
|
93
|
+
stroke-linecap="square"
|
|
94
|
+
>
|
|
95
|
+
<circle cx="12" cy="12" r="3.5" />
|
|
96
|
+
<path
|
|
97
|
+
d="M12 2v2M12 20v2M4.93 4.93l1.42 1.42M17.65 17.65l1.42 1.42M2 12h2M20 12h2M4.93 19.07l1.42-1.42M17.65 6.35l1.42-1.42"
|
|
98
|
+
/>
|
|
99
|
+
</svg>
|
|
100
|
+
{:else if activePreference === 'dark'}
|
|
101
|
+
<svg
|
|
102
|
+
data-theme-icon="dark"
|
|
103
|
+
aria-hidden="true"
|
|
104
|
+
focusable="false"
|
|
105
|
+
width="18"
|
|
106
|
+
height="18"
|
|
107
|
+
viewBox="0 0 24 24"
|
|
108
|
+
fill="none"
|
|
109
|
+
stroke="currentColor"
|
|
110
|
+
stroke-width="1.8"
|
|
111
|
+
stroke-linejoin="miter"
|
|
112
|
+
>
|
|
113
|
+
<path d="M20.4 15.4A8.5 8.5 0 0 1 8.6 3.6 8.5 8.5 0 1 0 20.4 15.4Z" />
|
|
114
|
+
</svg>
|
|
115
|
+
{:else}
|
|
116
|
+
<svg
|
|
117
|
+
data-theme-icon="system"
|
|
118
|
+
aria-hidden="true"
|
|
119
|
+
focusable="false"
|
|
120
|
+
width="18"
|
|
121
|
+
height="18"
|
|
122
|
+
viewBox="0 0 24 24"
|
|
123
|
+
fill="none"
|
|
124
|
+
stroke="currentColor"
|
|
125
|
+
stroke-width="1.8"
|
|
126
|
+
stroke-linecap="square"
|
|
127
|
+
stroke-linejoin="miter"
|
|
128
|
+
>
|
|
129
|
+
<rect x="3" y="4" width="18" height="13" />
|
|
130
|
+
<path d="M9 21h6M12 17v4" />
|
|
131
|
+
</svg>
|
|
132
|
+
{/if}
|
|
133
|
+
</button>
|
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
2
2
|
import type { ControlSize } from '../types.js';
|
|
3
3
|
import type { Theme } from '../theme.svelte.js';
|
|
4
|
-
interface Props extends Omit<
|
|
4
|
+
interface Props extends Omit<HTMLButtonAttributes, 'children' | 'aria-label'> {
|
|
5
5
|
/** The store from `createTheme()`. */
|
|
6
6
|
theme: Theme;
|
|
7
|
-
/**
|
|
8
|
-
id?: string;
|
|
9
|
-
/** Accessible name of the group. */
|
|
7
|
+
/** Accessible name for the preference represented by the icon. */
|
|
10
8
|
label?: string;
|
|
11
9
|
lightLabel?: string;
|
|
12
10
|
darkLabel?: string;
|
|
13
11
|
systemLabel?: string;
|
|
14
|
-
/**
|
|
15
|
-
* Offers "system" alongside the two schemes. Worth keeping: without it a user who has not
|
|
16
|
-
* chosen is silently locked to whichever scheme they happened to land on.
|
|
17
|
-
*/
|
|
12
|
+
/** Include "system" in the cycle. */
|
|
18
13
|
showSystem?: boolean;
|
|
19
14
|
size?: ControlSize;
|
|
20
15
|
class?: string;
|
|
21
|
-
ref?:
|
|
16
|
+
ref?: HTMLButtonElement | null;
|
|
22
17
|
}
|
|
23
18
|
declare const ThemeToggle: import("svelte").Component<Props, {}, "ref">;
|
|
24
19
|
type ThemeToggle = ReturnType<typeof ThemeToggle>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { cx } from '../utils.js';
|
|
5
|
+
|
|
6
|
+
interface Props extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
|
|
7
|
+
src?: string;
|
|
8
|
+
/** Required whenever `src` is set — decorative images should say so with `alt=""`. */
|
|
9
|
+
alt?: string;
|
|
10
|
+
/** CSS aspect-ratio value: `'4/3'`, `'1/1'`, or a number. */
|
|
11
|
+
ratio?: string | number;
|
|
12
|
+
fit?: 'contain' | 'cover';
|
|
13
|
+
/** `sunken` recesses into the page; `paper` stays white in every theme for artwork. */
|
|
14
|
+
surface?: 'sunken' | 'paper';
|
|
15
|
+
/** Alternative to `src` — inline SVG, canvas, anything that fills the frame. */
|
|
16
|
+
children?: Snippet;
|
|
17
|
+
class?: string;
|
|
18
|
+
ref?: HTMLElement | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
src,
|
|
23
|
+
alt = '',
|
|
24
|
+
ratio = '4/3',
|
|
25
|
+
fit = 'contain',
|
|
26
|
+
surface = 'sunken',
|
|
27
|
+
children,
|
|
28
|
+
class: className,
|
|
29
|
+
ref = $bindable(null),
|
|
30
|
+
...rest
|
|
31
|
+
}: Props = $props();
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<figure
|
|
35
|
+
bind:this={ref}
|
|
36
|
+
class={cx(
|
|
37
|
+
'ldt-thumbnail',
|
|
38
|
+
surface === 'paper' && 'ldt-thumbnail--paper',
|
|
39
|
+
fit === 'cover' && 'ldt-thumbnail--cover',
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
style={`--ldt-thumbnail-ratio: ${ratio};`}
|
|
43
|
+
{...rest}
|
|
44
|
+
>
|
|
45
|
+
{#if children}{@render children()}{:else if src}<img
|
|
46
|
+
class="ldt-thumbnail__image"
|
|
47
|
+
{src}
|
|
48
|
+
{alt}
|
|
49
|
+
loading="lazy"
|
|
50
|
+
/>{/if}
|
|
51
|
+
</figure>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
|
|
4
|
+
src?: string;
|
|
5
|
+
/** Required whenever `src` is set — decorative images should say so with `alt=""`. */
|
|
6
|
+
alt?: string;
|
|
7
|
+
/** CSS aspect-ratio value: `'4/3'`, `'1/1'`, or a number. */
|
|
8
|
+
ratio?: string | number;
|
|
9
|
+
fit?: 'contain' | 'cover';
|
|
10
|
+
/** `sunken` recesses into the page; `paper` stays white in every theme for artwork. */
|
|
11
|
+
surface?: 'sunken' | 'paper';
|
|
12
|
+
/** Alternative to `src` — inline SVG, canvas, anything that fills the frame. */
|
|
13
|
+
children?: Snippet;
|
|
14
|
+
class?: string;
|
|
15
|
+
ref?: HTMLElement | null;
|
|
16
|
+
}
|
|
17
|
+
declare const Thumbnail: import("svelte").Component<Props, {}, "ref">;
|
|
18
|
+
type Thumbnail = ReturnType<typeof Thumbnail>;
|
|
19
|
+
export default Thumbnail;
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import { cx } from '../utils.js';
|
|
5
5
|
|
|
6
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
|
+
/** Full-width row above the panes — a ContextBar or toolbar. */
|
|
8
|
+
header?: Snippet;
|
|
7
9
|
sidebar?: Snippet;
|
|
8
10
|
children: Snippet;
|
|
9
11
|
inspector?: Snippet;
|
|
@@ -16,16 +18,20 @@
|
|
|
16
18
|
/** The same for the inspector column. */
|
|
17
19
|
inspectorOpen?: boolean;
|
|
18
20
|
class?: string;
|
|
21
|
+
/** Extra classes for the main pane, replacing consumer reach-ins on `__main`. */
|
|
22
|
+
mainClass?: string;
|
|
19
23
|
ref?: HTMLDivElement | null;
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
let {
|
|
27
|
+
header,
|
|
23
28
|
sidebar,
|
|
24
29
|
children,
|
|
25
30
|
inspector,
|
|
26
31
|
sidebarOpen = true,
|
|
27
32
|
inspectorOpen = true,
|
|
28
33
|
class: className,
|
|
34
|
+
mainClass,
|
|
29
35
|
ref = $bindable(null),
|
|
30
36
|
...rest
|
|
31
37
|
}: Props = $props();
|
|
@@ -39,13 +45,15 @@
|
|
|
39
45
|
bind:this={ref}
|
|
40
46
|
class={cx(
|
|
41
47
|
'ldt-workspace',
|
|
48
|
+
header && 'ldt-workspace--header',
|
|
42
49
|
showSidebar && 'ldt-workspace--sidebar',
|
|
43
50
|
showInspector && 'ldt-workspace--inspector',
|
|
44
51
|
className
|
|
45
52
|
)}
|
|
46
53
|
{...rest}
|
|
47
54
|
>
|
|
55
|
+
{#if header}<div class="ldt-workspace__header">{@render header()}</div>{/if}
|
|
48
56
|
{#if showSidebar}{@render sidebar!()}{/if}
|
|
49
|
-
<div class=
|
|
57
|
+
<div class={cx('ldt-workspace__main', mainClass)}>{@render children()}</div>
|
|
50
58
|
{#if showInspector}{@render inspector!()}{/if}
|
|
51
59
|
</div>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** Full-width row above the panes — a ContextBar or toolbar. */
|
|
5
|
+
header?: Snippet;
|
|
4
6
|
sidebar?: Snippet;
|
|
5
7
|
children: Snippet;
|
|
6
8
|
inspector?: Snippet;
|
|
@@ -13,6 +15,8 @@ interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
|
13
15
|
/** The same for the inspector column. */
|
|
14
16
|
inspectorOpen?: boolean;
|
|
15
17
|
class?: string;
|
|
18
|
+
/** Extra classes for the main pane, replacing consumer reach-ins on `__main`. */
|
|
19
|
+
mainClass?: string;
|
|
16
20
|
ref?: HTMLDivElement | null;
|
|
17
21
|
}
|
|
18
22
|
declare const Workspace: import("svelte").Component<Props, {}, "ref">;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export { default as Breadcrumbs } from './components/Breadcrumbs.svelte';
|
|
|
8
8
|
export { default as Button } from './components/Button.svelte';
|
|
9
9
|
export { default as Card } from './components/Card.svelte';
|
|
10
10
|
export { default as Checkbox } from './components/Checkbox.svelte';
|
|
11
|
+
export { default as CodeBlock } from './components/CodeBlock.svelte';
|
|
12
|
+
export { default as CommentList } from './components/CommentList.svelte';
|
|
11
13
|
export { default as ContextBar } from './components/ContextBar.svelte';
|
|
12
14
|
export { default as Dialog } from './components/Dialog.svelte';
|
|
13
15
|
export { default as Drawer } from './components/Drawer.svelte';
|
|
@@ -15,9 +17,14 @@ export { default as DropdownMenu } from './components/DropdownMenu.svelte';
|
|
|
15
17
|
export { default as EmptyState } from './components/EmptyState.svelte';
|
|
16
18
|
export { default as Field } from './components/Field.svelte';
|
|
17
19
|
export { default as Fieldset } from './components/Fieldset.svelte';
|
|
20
|
+
export { default as FileInput } from './components/FileInput.svelte';
|
|
21
|
+
export { default as Filmstrip } from './components/Filmstrip.svelte';
|
|
22
|
+
export { default as FloatingBar } from './components/FloatingBar.svelte';
|
|
18
23
|
export { default as IconButton } from './components/IconButton.svelte';
|
|
19
24
|
export { default as Input } from './components/Input.svelte';
|
|
20
25
|
export { default as Label } from './components/Label.svelte';
|
|
26
|
+
export { default as ListRow } from './components/ListRow.svelte';
|
|
27
|
+
export { default as Marker } from './components/Marker.svelte';
|
|
21
28
|
export { default as NavMenu } from './components/NavMenu.svelte';
|
|
22
29
|
export { default as NumberField } from './components/NumberField.svelte';
|
|
23
30
|
export { default as PageHeader } from './components/PageHeader.svelte';
|
|
@@ -26,18 +33,24 @@ export { default as Panel } from './components/Panel.svelte';
|
|
|
26
33
|
export { default as Popover } from './components/Popover.svelte';
|
|
27
34
|
export { default as Progress } from './components/Progress.svelte';
|
|
28
35
|
export { default as RadioGroup } from './components/RadioGroup.svelte';
|
|
36
|
+
export { default as RecordStepper } from './components/RecordStepper.svelte';
|
|
29
37
|
export { default as Section } from './components/Section.svelte';
|
|
38
|
+
export { default as SegmentedNav } from './components/SegmentedNav.svelte';
|
|
30
39
|
export { default as Select } from './components/Select.svelte';
|
|
31
40
|
export { default as Separator } from './components/Separator.svelte';
|
|
32
41
|
export { default as Sidebar } from './components/Sidebar.svelte';
|
|
33
42
|
export { default as Skeleton } from './components/Skeleton.svelte';
|
|
34
43
|
export { default as Spinner } from './components/Spinner.svelte';
|
|
44
|
+
export { default as Stat } from './components/Stat.svelte';
|
|
45
|
+
export { default as StatusDot } from './components/StatusDot.svelte';
|
|
46
|
+
export { default as SwatchGroup } from './components/SwatchGroup.svelte';
|
|
35
47
|
export { default as Switch } from './components/Switch.svelte';
|
|
36
48
|
export { default as Table } from './components/Table.svelte';
|
|
37
49
|
export { default as TableHeader } from './components/TableHeader.svelte';
|
|
38
50
|
export { default as Tabs } from './components/Tabs.svelte';
|
|
39
51
|
export { default as Textarea } from './components/Textarea.svelte';
|
|
40
52
|
export { default as ThemeToggle } from './components/ThemeToggle.svelte';
|
|
53
|
+
export { default as Thumbnail } from './components/Thumbnail.svelte';
|
|
41
54
|
export { default as Toast } from './components/Toast.svelte';
|
|
42
55
|
export { default as ToastViewport } from './components/ToastViewport.svelte';
|
|
43
56
|
export { default as ToggleGroup } from './components/ToggleGroup.svelte';
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,8 @@ export { default as Breadcrumbs } from './components/Breadcrumbs.svelte';
|
|
|
8
8
|
export { default as Button } from './components/Button.svelte';
|
|
9
9
|
export { default as Card } from './components/Card.svelte';
|
|
10
10
|
export { default as Checkbox } from './components/Checkbox.svelte';
|
|
11
|
+
export { default as CodeBlock } from './components/CodeBlock.svelte';
|
|
12
|
+
export { default as CommentList } from './components/CommentList.svelte';
|
|
11
13
|
export { default as ContextBar } from './components/ContextBar.svelte';
|
|
12
14
|
export { default as Dialog } from './components/Dialog.svelte';
|
|
13
15
|
export { default as Drawer } from './components/Drawer.svelte';
|
|
@@ -15,9 +17,14 @@ export { default as DropdownMenu } from './components/DropdownMenu.svelte';
|
|
|
15
17
|
export { default as EmptyState } from './components/EmptyState.svelte';
|
|
16
18
|
export { default as Field } from './components/Field.svelte';
|
|
17
19
|
export { default as Fieldset } from './components/Fieldset.svelte';
|
|
20
|
+
export { default as FileInput } from './components/FileInput.svelte';
|
|
21
|
+
export { default as Filmstrip } from './components/Filmstrip.svelte';
|
|
22
|
+
export { default as FloatingBar } from './components/FloatingBar.svelte';
|
|
18
23
|
export { default as IconButton } from './components/IconButton.svelte';
|
|
19
24
|
export { default as Input } from './components/Input.svelte';
|
|
20
25
|
export { default as Label } from './components/Label.svelte';
|
|
26
|
+
export { default as ListRow } from './components/ListRow.svelte';
|
|
27
|
+
export { default as Marker } from './components/Marker.svelte';
|
|
21
28
|
export { default as NavMenu } from './components/NavMenu.svelte';
|
|
22
29
|
export { default as NumberField } from './components/NumberField.svelte';
|
|
23
30
|
export { default as PageHeader } from './components/PageHeader.svelte';
|
|
@@ -26,18 +33,24 @@ export { default as Panel } from './components/Panel.svelte';
|
|
|
26
33
|
export { default as Popover } from './components/Popover.svelte';
|
|
27
34
|
export { default as Progress } from './components/Progress.svelte';
|
|
28
35
|
export { default as RadioGroup } from './components/RadioGroup.svelte';
|
|
36
|
+
export { default as RecordStepper } from './components/RecordStepper.svelte';
|
|
29
37
|
export { default as Section } from './components/Section.svelte';
|
|
38
|
+
export { default as SegmentedNav } from './components/SegmentedNav.svelte';
|
|
30
39
|
export { default as Select } from './components/Select.svelte';
|
|
31
40
|
export { default as Separator } from './components/Separator.svelte';
|
|
32
41
|
export { default as Sidebar } from './components/Sidebar.svelte';
|
|
33
42
|
export { default as Skeleton } from './components/Skeleton.svelte';
|
|
34
43
|
export { default as Spinner } from './components/Spinner.svelte';
|
|
44
|
+
export { default as Stat } from './components/Stat.svelte';
|
|
45
|
+
export { default as StatusDot } from './components/StatusDot.svelte';
|
|
46
|
+
export { default as SwatchGroup } from './components/SwatchGroup.svelte';
|
|
35
47
|
export { default as Switch } from './components/Switch.svelte';
|
|
36
48
|
export { default as Table } from './components/Table.svelte';
|
|
37
49
|
export { default as TableHeader } from './components/TableHeader.svelte';
|
|
38
50
|
export { default as Tabs } from './components/Tabs.svelte';
|
|
39
51
|
export { default as Textarea } from './components/Textarea.svelte';
|
|
40
52
|
export { default as ThemeToggle } from './components/ThemeToggle.svelte';
|
|
53
|
+
export { default as Thumbnail } from './components/Thumbnail.svelte';
|
|
41
54
|
export { default as Toast } from './components/Toast.svelte';
|
|
42
55
|
export { default as ToastViewport } from './components/ToastViewport.svelte';
|
|
43
56
|
export { default as ToggleGroup } from './components/ToggleGroup.svelte';
|
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
|
@@ -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
|