@delightstack/components 0.1.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/LICENSE +21 -0
- package/README.md +136 -0
- package/SKILL.md +149 -0
- package/bin/agents.js +63 -0
- package/dist/actions/Alert.svelte +202 -0
- package/dist/actions/Alert.svelte.d.ts +36 -0
- package/dist/actions/Alert.svelte.d.ts.map +1 -0
- package/dist/actions/Button.svelte +1450 -0
- package/dist/actions/Button.svelte.d.ts +56 -0
- package/dist/actions/Button.svelte.d.ts.map +1 -0
- package/dist/actions/ButtonGroup.svelte +111 -0
- package/dist/actions/ButtonGroup.svelte.d.ts +41 -0
- package/dist/actions/ButtonGroup.svelte.d.ts.map +1 -0
- package/dist/actions/CommandPalette.svelte +939 -0
- package/dist/actions/CommandPalette.svelte.d.ts +37 -0
- package/dist/actions/CommandPalette.svelte.d.ts.map +1 -0
- package/dist/actions/ContextMenu.svelte +138 -0
- package/dist/actions/ContextMenu.svelte.d.ts +54 -0
- package/dist/actions/ContextMenu.svelte.d.ts.map +1 -0
- package/dist/actions/Modal.svelte +474 -0
- package/dist/actions/Modal.svelte.d.ts +28 -0
- package/dist/actions/Modal.svelte.d.ts.map +1 -0
- package/dist/actions/Popover.svelte +1214 -0
- package/dist/actions/Popover.svelte.d.ts +31 -0
- package/dist/actions/Popover.svelte.d.ts.map +1 -0
- package/dist/actions/Portal.svelte +80 -0
- package/dist/actions/Portal.svelte.d.ts +17 -0
- package/dist/actions/Portal.svelte.d.ts.map +1 -0
- package/dist/actions/ThemeToggle.svelte +345 -0
- package/dist/actions/ThemeToggle.svelte.d.ts +15 -0
- package/dist/actions/ThemeToggle.svelte.d.ts.map +1 -0
- package/dist/actions/index.d.ts +13 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/actions/index.js +10 -0
- package/dist/actions/scrollbar.d.ts +48 -0
- package/dist/actions/scrollbar.d.ts.map +1 -0
- package/dist/actions/scrollbar.js +404 -0
- package/dist/display/Accordion.svelte +586 -0
- package/dist/display/Accordion.svelte.d.ts +41 -0
- package/dist/display/Accordion.svelte.d.ts.map +1 -0
- package/dist/display/Avatar.svelte +527 -0
- package/dist/display/Avatar.svelte.d.ts +22 -0
- package/dist/display/Avatar.svelte.d.ts.map +1 -0
- package/dist/display/AvatarGroup.svelte +298 -0
- package/dist/display/AvatarGroup.svelte.d.ts +31 -0
- package/dist/display/AvatarGroup.svelte.d.ts.map +1 -0
- package/dist/display/Calendar.svelte +1366 -0
- package/dist/display/Calendar.svelte.d.ts +58 -0
- package/dist/display/Calendar.svelte.d.ts.map +1 -0
- package/dist/display/Chart.svelte +1426 -0
- package/dist/display/Chart.svelte.d.ts +35 -0
- package/dist/display/Chart.svelte.d.ts.map +1 -0
- package/dist/display/Code.svelte +780 -0
- package/dist/display/Code.svelte.d.ts +19 -0
- package/dist/display/Code.svelte.d.ts.map +1 -0
- package/dist/display/Comparison.svelte +686 -0
- package/dist/display/Comparison.svelte.d.ts +22 -0
- package/dist/display/Comparison.svelte.d.ts.map +1 -0
- package/dist/display/Counter.svelte +285 -0
- package/dist/display/Counter.svelte.d.ts +21 -0
- package/dist/display/Counter.svelte.d.ts.map +1 -0
- package/dist/display/Expand.svelte +48 -0
- package/dist/display/Expand.svelte.d.ts +9 -0
- package/dist/display/Expand.svelte.d.ts.map +1 -0
- package/dist/display/List.svelte +294 -0
- package/dist/display/List.svelte.d.ts +40 -0
- package/dist/display/List.svelte.d.ts.map +1 -0
- package/dist/display/ListContextReset.svelte +19 -0
- package/dist/display/ListContextReset.svelte.d.ts +7 -0
- package/dist/display/ListContextReset.svelte.d.ts.map +1 -0
- package/dist/display/ListItem.svelte +834 -0
- package/dist/display/ListItem.svelte.d.ts +22 -0
- package/dist/display/ListItem.svelte.d.ts.map +1 -0
- package/dist/display/QR.svelte +1193 -0
- package/dist/display/QR.svelte.d.ts +23 -0
- package/dist/display/QR.svelte.d.ts.map +1 -0
- package/dist/display/SplitPane.svelte +744 -0
- package/dist/display/SplitPane.svelte.d.ts +25 -0
- package/dist/display/SplitPane.svelte.d.ts.map +1 -0
- package/dist/display/Stat.svelte +439 -0
- package/dist/display/Stat.svelte.d.ts +24 -0
- package/dist/display/Stat.svelte.d.ts.map +1 -0
- package/dist/display/Table.svelte +4654 -0
- package/dist/display/Table.svelte.d.ts +249 -0
- package/dist/display/Table.svelte.d.ts.map +1 -0
- package/dist/display/TableCellEditor.svelte +935 -0
- package/dist/display/TableCellEditor.svelte.d.ts +58 -0
- package/dist/display/TableCellEditor.svelte.d.ts.map +1 -0
- package/dist/display/Timeline.svelte +1258 -0
- package/dist/display/Timeline.svelte.d.ts +43 -0
- package/dist/display/Timeline.svelte.d.ts.map +1 -0
- package/dist/display/Tree.svelte +1740 -0
- package/dist/display/Tree.svelte.d.ts +74 -0
- package/dist/display/Tree.svelte.d.ts.map +1 -0
- package/dist/display/Typewriter.svelte +338 -0
- package/dist/display/Typewriter.svelte.d.ts +22 -0
- package/dist/display/Typewriter.svelte.d.ts.map +1 -0
- package/dist/display/index.d.ts +24 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.js +18 -0
- package/dist/feedback/Callout.svelte +529 -0
- package/dist/feedback/Callout.svelte.d.ts +24 -0
- package/dist/feedback/Callout.svelte.d.ts.map +1 -0
- package/dist/feedback/Confetti.svelte +631 -0
- package/dist/feedback/Confetti.svelte.d.ts +90 -0
- package/dist/feedback/Confetti.svelte.d.ts.map +1 -0
- package/dist/feedback/Progress.svelte +382 -0
- package/dist/feedback/Progress.svelte.d.ts +25 -0
- package/dist/feedback/Progress.svelte.d.ts.map +1 -0
- package/dist/feedback/Toast.svelte +967 -0
- package/dist/feedback/Toast.svelte.d.ts +54 -0
- package/dist/feedback/Toast.svelte.d.ts.map +1 -0
- package/dist/feedback/index.d.ts +7 -0
- package/dist/feedback/index.d.ts.map +1 -0
- package/dist/feedback/index.js +4 -0
- package/dist/form/Checkbox.svelte +449 -0
- package/dist/form/Checkbox.svelte.d.ts +27 -0
- package/dist/form/Checkbox.svelte.d.ts.map +1 -0
- package/dist/form/Fieldset.svelte +410 -0
- package/dist/form/Fieldset.svelte.d.ts +22 -0
- package/dist/form/Fieldset.svelte.d.ts.map +1 -0
- package/dist/form/FileUpload.svelte +934 -0
- package/dist/form/FileUpload.svelte.d.ts +41 -0
- package/dist/form/FileUpload.svelte.d.ts.map +1 -0
- package/dist/form/Form.svelte +530 -0
- package/dist/form/Form.svelte.d.ts +120 -0
- package/dist/form/Form.svelte.d.ts.map +1 -0
- package/dist/form/Input.svelte +2858 -0
- package/dist/form/Input.svelte.d.ts +66 -0
- package/dist/form/Input.svelte.d.ts.map +1 -0
- package/dist/form/Radio.svelte +507 -0
- package/dist/form/Radio.svelte.d.ts +39 -0
- package/dist/form/Radio.svelte.d.ts.map +1 -0
- package/dist/form/Range.svelte +912 -0
- package/dist/form/Range.svelte.d.ts +33 -0
- package/dist/form/Range.svelte.d.ts.map +1 -0
- package/dist/form/Rating.svelte +429 -0
- package/dist/form/Rating.svelte.d.ts +28 -0
- package/dist/form/Rating.svelte.d.ts.map +1 -0
- package/dist/form/Select.svelte +1933 -0
- package/dist/form/Select.svelte.d.ts +54 -0
- package/dist/form/Select.svelte.d.ts.map +1 -0
- package/dist/form/Toggle.svelte +645 -0
- package/dist/form/Toggle.svelte.d.ts +50 -0
- package/dist/form/Toggle.svelte.d.ts.map +1 -0
- package/dist/form/index.d.ts +15 -0
- package/dist/form/index.d.ts.map +1 -0
- package/dist/form/index.js +10 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/layout/README.md +172 -0
- package/dist/media/Carousel.svelte +2424 -0
- package/dist/media/Carousel.svelte.d.ts +47 -0
- package/dist/media/Carousel.svelte.d.ts.map +1 -0
- package/dist/media/Gallery.svelte +2881 -0
- package/dist/media/Gallery.svelte.d.ts +82 -0
- package/dist/media/Gallery.svelte.d.ts.map +1 -0
- package/dist/media/Image.svelte +389 -0
- package/dist/media/Image.svelte.d.ts +33 -0
- package/dist/media/Image.svelte.d.ts.map +1 -0
- package/dist/media/PDF.svelte +1793 -0
- package/dist/media/PDF.svelte.d.ts +44 -0
- package/dist/media/PDF.svelte.d.ts.map +1 -0
- package/dist/media/Panorama.svelte +1391 -0
- package/dist/media/Panorama.svelte.d.ts +47 -0
- package/dist/media/Panorama.svelte.d.ts.map +1 -0
- package/dist/media/Video.svelte +2501 -0
- package/dist/media/Video.svelte.d.ts +58 -0
- package/dist/media/Video.svelte.d.ts.map +1 -0
- package/dist/media/carousel.d.ts +211 -0
- package/dist/media/carousel.d.ts.map +1 -0
- package/dist/media/carousel.js +408 -0
- package/dist/media/index.d.ts +11 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +5 -0
- package/dist/navigation/BottomSheet.svelte +636 -0
- package/dist/navigation/BottomSheet.svelte.d.ts +27 -0
- package/dist/navigation/BottomSheet.svelte.d.ts.map +1 -0
- package/dist/navigation/Breadcrumbs.svelte +611 -0
- package/dist/navigation/Breadcrumbs.svelte.d.ts +28 -0
- package/dist/navigation/Breadcrumbs.svelte.d.ts.map +1 -0
- package/dist/navigation/Pagination.svelte +641 -0
- package/dist/navigation/Pagination.svelte.d.ts +27 -0
- package/dist/navigation/Pagination.svelte.d.ts.map +1 -0
- package/dist/navigation/Steps.svelte +965 -0
- package/dist/navigation/Steps.svelte.d.ts +43 -0
- package/dist/navigation/Steps.svelte.d.ts.map +1 -0
- package/dist/navigation/Tabs.svelte +698 -0
- package/dist/navigation/Tabs.svelte.d.ts +41 -0
- package/dist/navigation/Tabs.svelte.d.ts.map +1 -0
- package/dist/navigation/index.d.ts +8 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +5 -0
- package/package.json +139 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
type Position = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
2
|
+
export interface ToastOptions {
|
|
3
|
+
/** Optional secondary line shown beneath the title. */
|
|
4
|
+
description?: string;
|
|
5
|
+
/** Auto-dismiss delay in milliseconds (overrides the Toaster default) */
|
|
6
|
+
duration?: number;
|
|
7
|
+
/** Whether the toast shows a close button */
|
|
8
|
+
dismissible?: boolean;
|
|
9
|
+
/** Style the toast as a success message */
|
|
10
|
+
success?: boolean;
|
|
11
|
+
/** Style the toast as a warning message */
|
|
12
|
+
warning?: boolean;
|
|
13
|
+
/** Style the toast as an error message */
|
|
14
|
+
error?: boolean;
|
|
15
|
+
/** Style the toast as an informational message */
|
|
16
|
+
info?: boolean;
|
|
17
|
+
/** An action button shown in the toast */
|
|
18
|
+
action?: {
|
|
19
|
+
label: string;
|
|
20
|
+
onclick: () => void;
|
|
21
|
+
};
|
|
22
|
+
/** Whether the toast stays until manually dismissed (no auto-dismiss) */
|
|
23
|
+
persistent?: boolean;
|
|
24
|
+
/** Custom toast id — reusing an id updates the existing toast in place */
|
|
25
|
+
id?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Show a toast notification. Returns the toast ID for later dismissal. */
|
|
28
|
+
export declare function toast(message: string, options?: ToastOptions): string;
|
|
29
|
+
export declare namespace toast {
|
|
30
|
+
var success: (message: string, options?: ToastOptions) => string;
|
|
31
|
+
var error: (message: string, options?: ToastOptions) => string;
|
|
32
|
+
var warning: (message: string, options?: ToastOptions) => string;
|
|
33
|
+
var info: (message: string, options?: ToastOptions) => string;
|
|
34
|
+
var loading: (message: string, options?: ToastOptions) => string;
|
|
35
|
+
var promise: <T>(p: Promise<T>, messages: {
|
|
36
|
+
loading: string;
|
|
37
|
+
success: string | ((result: T) => string);
|
|
38
|
+
error: string | ((err: Error) => string);
|
|
39
|
+
}, options?: ToastOptions) => Promise<T>;
|
|
40
|
+
var dismiss: (id?: string) => void;
|
|
41
|
+
}
|
|
42
|
+
declare const Toast: import("svelte").Component<{
|
|
43
|
+
position?: Position;
|
|
44
|
+
max_visible?: number;
|
|
45
|
+
gap?: number;
|
|
46
|
+
width?: number;
|
|
47
|
+
duration?: number;
|
|
48
|
+
rich_colors?: boolean;
|
|
49
|
+
id?: string;
|
|
50
|
+
class?: string;
|
|
51
|
+
}, {}, "">;
|
|
52
|
+
type Toast = ReturnType<typeof Toast>;
|
|
53
|
+
export default Toast;
|
|
54
|
+
//# sourceMappingURL=Toast.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.svelte.d.ts","sourceRoot":"","sources":["../../src/feedback/Toast.svelte.ts"],"names":[],"mappings":"AAKC,KAAK,QAAQ,GACV,UAAU,GACV,YAAY,GACZ,WAAW,GACX,aAAa,GACb,eAAe,GACf,cAAc,CAAC;AAElB,MAAM,WAAW,YAAY;IAC5B,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kDAAkD;IAClD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0CAA0C;IAC1C,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IAChD,yEAAyE;IACzE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ;AAiGD,2EAA2E;AAC3E,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAErE;yBAFe,KAAK;2BAIqB,MAAM,YAAY,YAAY,KAAG,MAAM;yBAI3C,MAAM,YAAY,YAAY,KAAG,MAAM;2BAInC,MAAM,YAAY,YAAY,KAAG,MAAM;wBAI7C,MAAM,YAAY,YAAY,KAAG,MAAM;2BAIjC,MAAM,YAAY,YAAY,KAAG,MAAM;kBAI1C,CAAC,KACpC,OAAO,CAAC,CAAC,CAAC,YACH;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC,CAAC;QAC1C,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAC,CAAC;KACzC,YACS,YAAY,KACpB,OAAO,CAAC,CAAC,CAAC;uBAsByB,MAAM,KAAG,IAAI;;AAsYpD,QAAA,MAAM,KAAK;eAlXyE,QAAQ;kBAAgB,MAAM;UAAQ,MAAM;YAAU,MAAM;eAAa,MAAM;kBAAgB,OAAO;;YAA8B,MAAM;UAkX3K,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as Callout } from './Callout.svelte';
|
|
2
|
+
export { default as Confetti, confetti } from './Confetti.svelte';
|
|
3
|
+
export type { ConfettiOptions, ConfettiTarget, CannonOptions, RainOptions, } from './Confetti.svelte';
|
|
4
|
+
export { default as Progress } from './Progress.svelte';
|
|
5
|
+
export { default as Toaster, toast } from './Toast.svelte';
|
|
6
|
+
export type { ToastOptions } from './Toast.svelte';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/feedback/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClE,YAAY,EACX,eAAe,EACf,cAAc,EACd,aAAa,EACb,WAAW,GACX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ripple, tooltip } from '@delightstack/utilities';
|
|
3
|
+
import { getContext } from 'svelte';
|
|
4
|
+
import type { FormContext } from './Form.svelte';
|
|
5
|
+
|
|
6
|
+
const propId = $props.id();
|
|
7
|
+
let {
|
|
8
|
+
/** Whether the checkbox is checked. When omitted inside a Form (with a
|
|
9
|
+
* name), the checked state is driven by the form data instead. */
|
|
10
|
+
checked = $bindable() as boolean | undefined,
|
|
11
|
+
|
|
12
|
+
/** Whether the checkbox is in an indeterminate state */
|
|
13
|
+
indeterminate = false,
|
|
14
|
+
|
|
15
|
+
/** The value submitted with form data */
|
|
16
|
+
value = '',
|
|
17
|
+
|
|
18
|
+
/** Whether the checkbox is disabled */
|
|
19
|
+
disabled = false,
|
|
20
|
+
|
|
21
|
+
/** The size of the checkbox. 0=16px, 1=20px, 2=24px, 3=28px */
|
|
22
|
+
size = '1' as '0' | '1' | '2' | '3',
|
|
23
|
+
|
|
24
|
+
/** The label text for the checkbox */
|
|
25
|
+
label = '',
|
|
26
|
+
|
|
27
|
+
/** A description shown below the label */
|
|
28
|
+
description = '',
|
|
29
|
+
|
|
30
|
+
/** An error message shown below the checkbox */
|
|
31
|
+
error = '',
|
|
32
|
+
|
|
33
|
+
/** Parses & validates the value (e.g. a database table form field's
|
|
34
|
+
* `parse`). Inside a Form it is registered with the form, which runs it
|
|
35
|
+
* on the form's validation timing. */
|
|
36
|
+
parse = undefined as ((value: unknown) => unknown) | undefined,
|
|
37
|
+
|
|
38
|
+
/** Tri-state mode (set by optional non-defaulted boolean form fields):
|
|
39
|
+
* a null/undefined value means "unanswered" and displays as
|
|
40
|
+
* indeterminate. Clicking resolves to checked, matching the browser's
|
|
41
|
+
* native indeterminate-checkbox behavior — use Toggle for a control
|
|
42
|
+
* the user can cycle back to the middle state. */
|
|
43
|
+
tristate = false,
|
|
44
|
+
|
|
45
|
+
/** The field's default value (set by defaulted boolean form fields):
|
|
46
|
+
* shown when the form data has no value yet, so the display matches
|
|
47
|
+
* what saving would persist. */
|
|
48
|
+
default_checked = undefined as boolean | undefined,
|
|
49
|
+
|
|
50
|
+
/** Whether the checkbox is required */
|
|
51
|
+
required = false,
|
|
52
|
+
|
|
53
|
+
/** The tooltip message shown on hover */
|
|
54
|
+
tooltip: tooltip_message = '',
|
|
55
|
+
|
|
56
|
+
/** Whether the checkbox should display in a condensed view */
|
|
57
|
+
dense = false,
|
|
58
|
+
|
|
59
|
+
/** Whether the checkbox should display in an expanded view */
|
|
60
|
+
comfortable = false,
|
|
61
|
+
|
|
62
|
+
/** The ID of the checkbox element */
|
|
63
|
+
id = propId,
|
|
64
|
+
|
|
65
|
+
/** The name attribute for the hidden input */
|
|
66
|
+
name = '',
|
|
67
|
+
|
|
68
|
+
/** Specifies a custom class name for the container element */
|
|
69
|
+
class: class_name = '',
|
|
70
|
+
|
|
71
|
+
/** Called when the checked state changes */
|
|
72
|
+
onchange = undefined as
|
|
73
|
+
| ((detail: { checked: boolean; value: string }) => void)
|
|
74
|
+
| undefined,
|
|
75
|
+
} = $props();
|
|
76
|
+
|
|
77
|
+
const sizes: Record<string, number> = { '0': 16, '1': 20, '2': 24, '3': 28 };
|
|
78
|
+
const px = $derived(sizes[size] ?? 20);
|
|
79
|
+
|
|
80
|
+
let animation = $state<'none' | 'check' | 'uncheck'>('none');
|
|
81
|
+
let indicator_element = $state<HTMLElement | undefined>(undefined);
|
|
82
|
+
|
|
83
|
+
/* ------------------------------------------------------------------ */
|
|
84
|
+
/* Form context integration */
|
|
85
|
+
/* ------------------------------------------------------------------ */
|
|
86
|
+
|
|
87
|
+
const form_ctx = getContext<FormContext | undefined>('form');
|
|
88
|
+
|
|
89
|
+
$effect(() => {
|
|
90
|
+
if (!form_ctx || !name) return;
|
|
91
|
+
if (indicator_element) form_ctx.register(name, indicator_element, parse);
|
|
92
|
+
return () => {
|
|
93
|
+
if (name) form_ctx.unregister(name);
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Context-driven mode: inside a Form, with a name, and no checked prop,
|
|
99
|
+
* the checkbox mirrors the form data (e.g. an entity's draft) —
|
|
100
|
+
* `<Checkbox {...field.is_public} />` needs no bind:checked.
|
|
101
|
+
*/
|
|
102
|
+
const context_driven = !!(form_ctx && name && checked === undefined);
|
|
103
|
+
|
|
104
|
+
$effect(() => {
|
|
105
|
+
if (!context_driven || !form_ctx || !name) return;
|
|
106
|
+
const ctx_value = form_ctx.getValue(name);
|
|
107
|
+
let next: boolean | undefined;
|
|
108
|
+
if (ctx_value === undefined || ctx_value === null) {
|
|
109
|
+
// Unanswered: tri-state fields stay undefined (indeterminate display),
|
|
110
|
+
// defaulted fields show their default, plain booleans show unchecked
|
|
111
|
+
next = tristate ? undefined : (default_checked ?? false);
|
|
112
|
+
} else {
|
|
113
|
+
next = Boolean(ctx_value);
|
|
114
|
+
}
|
|
115
|
+
if (next !== checked) checked = next;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
/** The effective checked state (an omitted checked prop means unchecked) */
|
|
119
|
+
const is_checked = $derived(checked ?? false);
|
|
120
|
+
|
|
121
|
+
/** Indeterminate display: the explicit prop, or an unanswered tri-state value */
|
|
122
|
+
const show_indeterminate = $derived(
|
|
123
|
+
indeterminate || (tristate && (checked === undefined || checked === null)),
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
/** Error from the local prop or the form context */
|
|
127
|
+
const resolved_error = $derived.by(() => {
|
|
128
|
+
if (error) return error;
|
|
129
|
+
if (form_ctx && name && form_ctx.errors[name]) return form_ctx.errors[name];
|
|
130
|
+
return '';
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
function toggle() {
|
|
134
|
+
if (disabled) return;
|
|
135
|
+
checked = !is_checked;
|
|
136
|
+
animation = checked ? 'check' : 'uncheck';
|
|
137
|
+
setTimeout(() => (animation = 'none'), checked ? 350 : 50);
|
|
138
|
+
if (form_ctx && name) {
|
|
139
|
+
form_ctx.setValue(name, checked);
|
|
140
|
+
form_ctx.setTouched(name);
|
|
141
|
+
}
|
|
142
|
+
onchange?.({ checked, value });
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function onKeyDown(e: KeyboardEvent) {
|
|
146
|
+
if (e.key === ' ') {
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
toggle();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
</script>
|
|
152
|
+
|
|
153
|
+
<!-- The whole container is the click target so the hit area matches the
|
|
154
|
+
hover/press feedback (which keys off `.checkbox`). Keyboard activation
|
|
155
|
+
stays on the focusable role="checkbox" indicator below. -->
|
|
156
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
157
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
158
|
+
<div
|
|
159
|
+
class={['checkbox', class_name].filter(Boolean).join(' ')}
|
|
160
|
+
class:dense
|
|
161
|
+
class:comfortable
|
|
162
|
+
class:disabled
|
|
163
|
+
class:has-error={!!resolved_error}
|
|
164
|
+
{@attach tooltip(tooltip_message)}
|
|
165
|
+
style:--size="{px}px"
|
|
166
|
+
style:font-size={`var(--control-font-${size})`}
|
|
167
|
+
onclick={toggle}>
|
|
168
|
+
<!-- Hidden native input for form submission -->
|
|
169
|
+
<input
|
|
170
|
+
type="checkbox"
|
|
171
|
+
{id}
|
|
172
|
+
{name}
|
|
173
|
+
{value}
|
|
174
|
+
{required}
|
|
175
|
+
{disabled}
|
|
176
|
+
checked={is_checked}
|
|
177
|
+
indeterminate={show_indeterminate}
|
|
178
|
+
tabindex={-1}
|
|
179
|
+
aria-hidden="true" />
|
|
180
|
+
|
|
181
|
+
<div
|
|
182
|
+
bind:this={indicator_element}
|
|
183
|
+
class="indicator-wrapper"
|
|
184
|
+
class:checked={is_checked}
|
|
185
|
+
class:indeterminate={show_indeterminate}
|
|
186
|
+
role="checkbox"
|
|
187
|
+
tabindex={disabled ? -1 : 0}
|
|
188
|
+
aria-checked={show_indeterminate ? 'mixed' : is_checked}
|
|
189
|
+
aria-disabled={disabled}
|
|
190
|
+
aria-labelledby={label ? `${id}-label` : undefined}
|
|
191
|
+
{@attach ripple({ enabled: !disabled, centered: true, opacity: 0.15 })}
|
|
192
|
+
onkeydown={onKeyDown}>
|
|
193
|
+
<svg
|
|
194
|
+
class="indicator"
|
|
195
|
+
class:checked={is_checked}
|
|
196
|
+
class:indeterminate={show_indeterminate}
|
|
197
|
+
class:animating-check={animation === 'check'}
|
|
198
|
+
class:animating-uncheck={animation === 'uncheck'}
|
|
199
|
+
viewBox="0 0 24 24"
|
|
200
|
+
width={px}
|
|
201
|
+
height={px}
|
|
202
|
+
fill="none">
|
|
203
|
+
<rect class="box" x="2" y="2" width="20" height="20" rx="3" stroke-width="2" />
|
|
204
|
+
{#if show_indeterminate}
|
|
205
|
+
<line
|
|
206
|
+
class="dash"
|
|
207
|
+
x1="7"
|
|
208
|
+
y1="12"
|
|
209
|
+
x2="17"
|
|
210
|
+
y2="12"
|
|
211
|
+
stroke-width="2.5"
|
|
212
|
+
stroke-linecap="round" />
|
|
213
|
+
{:else}
|
|
214
|
+
<path
|
|
215
|
+
class="check"
|
|
216
|
+
d="M6 12.5 L10 16.5 L18 8"
|
|
217
|
+
stroke-width="2.5"
|
|
218
|
+
stroke-linecap="round"
|
|
219
|
+
stroke-linejoin="round" />
|
|
220
|
+
{/if}
|
|
221
|
+
</svg>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
{#if label || description}
|
|
225
|
+
<div class="content">
|
|
226
|
+
{#if label}
|
|
227
|
+
<span id="{id}-label" class="label">{label}</span>
|
|
228
|
+
{/if}
|
|
229
|
+
{#if description}
|
|
230
|
+
<span class="description">{description}</span>
|
|
231
|
+
{/if}
|
|
232
|
+
</div>
|
|
233
|
+
{/if}
|
|
234
|
+
|
|
235
|
+
{#if resolved_error}
|
|
236
|
+
<span class="error-text">{resolved_error}</span>
|
|
237
|
+
{/if}
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<style>
|
|
241
|
+
.checkbox {
|
|
242
|
+
display: flex;
|
|
243
|
+
flex-wrap: wrap;
|
|
244
|
+
align-items: flex-start;
|
|
245
|
+
gap: 0.5em;
|
|
246
|
+
/* The whole container is clickable, so the pointer cursor and the
|
|
247
|
+
hover/press feedback now line up with the actual hit area. Bound it
|
|
248
|
+
to its content (indicator + label + description) so a block-level
|
|
249
|
+
parent can't stretch the hit area across the whole row. */
|
|
250
|
+
width: fit-content;
|
|
251
|
+
cursor: pointer;
|
|
252
|
+
user-select: none;
|
|
253
|
+
position: relative;
|
|
254
|
+
perspective: 100px;
|
|
255
|
+
transition: translate 200ms ease;
|
|
256
|
+
|
|
257
|
+
&:not(.disabled):active {
|
|
258
|
+
translate: 0px 3px clamp(-10px, calc(0.2em - 12px), -2px);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
&.dense {
|
|
262
|
+
gap: 0.25em;
|
|
263
|
+
}
|
|
264
|
+
&.comfortable {
|
|
265
|
+
gap: 0.75em;
|
|
266
|
+
}
|
|
267
|
+
&.disabled {
|
|
268
|
+
opacity: 0.5;
|
|
269
|
+
pointer-events: none;
|
|
270
|
+
}
|
|
271
|
+
&.has-error {
|
|
272
|
+
.indicator .box {
|
|
273
|
+
stroke: var(--color-error, #d32f2f);
|
|
274
|
+
}
|
|
275
|
+
.error-text {
|
|
276
|
+
display: block;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* Hover: circular background tint on indicator (triggers from label hover too) */
|
|
281
|
+
&:not(.disabled):hover > .indicator-wrapper {
|
|
282
|
+
background: var(--hover-tint);
|
|
283
|
+
transition: none;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* Active: press scale on indicator (triggers from label click too) */
|
|
287
|
+
&:not(.disabled):active > .indicator-wrapper {
|
|
288
|
+
transform: scale(0.9);
|
|
289
|
+
transition:
|
|
290
|
+
transform 80ms ease,
|
|
291
|
+
background 200ms ease;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* Hidden native checkbox, kept for form submission */
|
|
296
|
+
input {
|
|
297
|
+
position: absolute;
|
|
298
|
+
width: 1px;
|
|
299
|
+
height: 1px;
|
|
300
|
+
overflow: hidden;
|
|
301
|
+
clip: rect(0, 0, 0, 0);
|
|
302
|
+
white-space: nowrap;
|
|
303
|
+
border: 0;
|
|
304
|
+
padding: 0;
|
|
305
|
+
margin: -1px;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.indicator-wrapper {
|
|
309
|
+
position: relative;
|
|
310
|
+
display: flex;
|
|
311
|
+
align-items: center;
|
|
312
|
+
justify-content: center;
|
|
313
|
+
width: calc(var(--size) + 20px);
|
|
314
|
+
height: calc(var(--size) + 20px);
|
|
315
|
+
border-radius: 50%;
|
|
316
|
+
cursor: pointer;
|
|
317
|
+
flex-shrink: 0;
|
|
318
|
+
overflow: hidden;
|
|
319
|
+
outline: none;
|
|
320
|
+
-webkit-tap-highlight-color: transparent;
|
|
321
|
+
--hover-tint: color-mix(in srgb, var(--color-text, currentColor) 12%, transparent);
|
|
322
|
+
transition:
|
|
323
|
+
background 200ms ease,
|
|
324
|
+
transform 150ms ease;
|
|
325
|
+
|
|
326
|
+
/* Accent-tinted hover when checked or indeterminate */
|
|
327
|
+
&.checked,
|
|
328
|
+
&.indeterminate {
|
|
329
|
+
--hover-tint: color-mix(in srgb, var(--color-action, #1976d2) 16%, transparent);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
&:focus-visible {
|
|
333
|
+
box-shadow: 0 0 0 2px var(--color-text, currentColor);
|
|
334
|
+
border-radius: 50%;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.indicator {
|
|
339
|
+
flex-shrink: 0;
|
|
340
|
+
|
|
341
|
+
.box {
|
|
342
|
+
stroke: var(--color-text-disabled, #999);
|
|
343
|
+
fill: transparent;
|
|
344
|
+
transition:
|
|
345
|
+
stroke 150ms ease,
|
|
346
|
+
fill 150ms ease;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.check {
|
|
350
|
+
stroke: transparent;
|
|
351
|
+
fill: none;
|
|
352
|
+
stroke-dasharray: 28;
|
|
353
|
+
stroke-dashoffset: 28;
|
|
354
|
+
transition:
|
|
355
|
+
stroke-dashoffset 250ms ease,
|
|
356
|
+
stroke 150ms ease;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.dash {
|
|
360
|
+
stroke: transparent;
|
|
361
|
+
transition: stroke 150ms ease;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
&.checked {
|
|
365
|
+
.box {
|
|
366
|
+
stroke: var(--color-action, #1976d2);
|
|
367
|
+
fill: var(--color-action, #1976d2);
|
|
368
|
+
}
|
|
369
|
+
.check {
|
|
370
|
+
stroke: var(--color-action-text, #fff);
|
|
371
|
+
stroke-dashoffset: 0;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
&.indeterminate {
|
|
376
|
+
.box {
|
|
377
|
+
stroke: var(--color-action, #1976d2);
|
|
378
|
+
fill: var(--color-action, #1976d2);
|
|
379
|
+
}
|
|
380
|
+
.dash {
|
|
381
|
+
stroke: var(--color-action-text, #fff);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* Check-in: elastic checkmark draw with overshoot + scale pulse */
|
|
386
|
+
&.animating-check {
|
|
387
|
+
animation: box-pulse 350ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
388
|
+
|
|
389
|
+
.check {
|
|
390
|
+
stroke-dashoffset: 0;
|
|
391
|
+
transition: stroke-dashoffset 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/* Uncheck: visible stroke retraction, box holds fill then fades */
|
|
396
|
+
&.animating-uncheck {
|
|
397
|
+
.check {
|
|
398
|
+
stroke: var(--color-action-text, #fff);
|
|
399
|
+
stroke-dashoffset: 28;
|
|
400
|
+
transition: stroke-dashoffset 50ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
401
|
+
}
|
|
402
|
+
.box {
|
|
403
|
+
stroke: var(--color-action, #1976d2);
|
|
404
|
+
fill: var(--color-action, #1976d2);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
@keyframes box-pulse {
|
|
410
|
+
0% {
|
|
411
|
+
transform: scale(1);
|
|
412
|
+
}
|
|
413
|
+
40% {
|
|
414
|
+
transform: scale(1.1);
|
|
415
|
+
}
|
|
416
|
+
100% {
|
|
417
|
+
transform: scale(1);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.content {
|
|
422
|
+
display: flex;
|
|
423
|
+
flex-direction: column;
|
|
424
|
+
gap: 0.1em;
|
|
425
|
+
padding-top: calc((var(--size) + 20px) / 2 - 0.7em);
|
|
426
|
+
margin-left: -8px;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.label {
|
|
430
|
+
cursor: pointer;
|
|
431
|
+
user-select: none;
|
|
432
|
+
line-height: 1.4;
|
|
433
|
+
color: var(--color-text, inherit);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.description {
|
|
437
|
+
font-size: 0.85em;
|
|
438
|
+
color: var(--color-text-disabled, #888);
|
|
439
|
+
line-height: 1.3;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.error-text {
|
|
443
|
+
display: none;
|
|
444
|
+
width: 100%;
|
|
445
|
+
font-size: 0.8em;
|
|
446
|
+
color: var(--color-error, #d32f2f);
|
|
447
|
+
margin-top: -0.25em;
|
|
448
|
+
}
|
|
449
|
+
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
declare const Checkbox: import("svelte").Component<{
|
|
2
|
+
checked?: boolean | undefined;
|
|
3
|
+
indeterminate?: boolean;
|
|
4
|
+
value?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
size?: "0" | "1" | "2" | "3";
|
|
7
|
+
label?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
parse?: ((value: unknown) => unknown) | undefined;
|
|
11
|
+
tristate?: boolean;
|
|
12
|
+
default_checked?: boolean | undefined;
|
|
13
|
+
required?: boolean;
|
|
14
|
+
tooltip?: string;
|
|
15
|
+
dense?: boolean;
|
|
16
|
+
comfortable?: boolean;
|
|
17
|
+
id?: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
class?: string;
|
|
20
|
+
onchange?: ((detail: {
|
|
21
|
+
checked: boolean;
|
|
22
|
+
value: string;
|
|
23
|
+
}) => void) | undefined;
|
|
24
|
+
}, {}, "checked">;
|
|
25
|
+
type Checkbox = ReturnType<typeof Checkbox>;
|
|
26
|
+
export default Checkbox;
|
|
27
|
+
//# sourceMappingURL=Checkbox.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Checkbox.svelte.d.ts","sourceRoot":"","sources":["../../src/form/Checkbox.svelte.ts"],"names":[],"mappings":"AAsMA,QAAA,MAAM,QAAQ;cA1LqE,OAAO,GAAG,SAAS;oBAAkB,OAAO;YAAU,MAAM;eAAa,OAAO;WAAS,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG;YAAU,MAAM;kBAAgB,MAAM;YAAU,MAAM;YAAU,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,SAAS;eAAa,OAAO;sBAAoB,OAAO,GAAG,SAAS;eAAa,OAAO;cAAY,MAAM;YAAU,OAAO;kBAAgB,OAAO;;WAA6B,MAAM;YAAU,MAAM;eAAe,CAAC,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC,GACviB,SAAS;iBAyLwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
|