@thomasfosterau/components 0.1.0 → 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.
- package/README.md +241 -56
- package/dist/canvas/VectorCanvas.svelte +89 -8
- package/dist/canvas/VectorCanvas.svelte.d.ts +19 -1
- package/dist/canvas/types.d.ts +1 -1
- package/dist/charts/types.d.ts +1 -1
- package/dist/citations/list-format.js +3 -1
- package/dist/data/ChatBubble.svelte +48 -0
- package/dist/data/ChatBubble.svelte.d.ts +33 -0
- package/dist/data/DescriptionList.svelte +9 -3
- package/dist/data/DescriptionList.svelte.d.ts +1 -1
- package/dist/data/DescriptionRow.svelte +6 -5
- package/dist/data/MessageThread.svelte +29 -0
- package/dist/data/MessageThread.svelte.d.ts +17 -0
- package/dist/data/Pagination.svelte +5 -5
- package/dist/data/Pagination.svelte.d.ts +8 -0
- package/dist/data/PaginationFooter.svelte +2 -1
- package/dist/data/PaginationFooter.svelte.d.ts +2 -0
- package/dist/data/Table.svelte +9 -3
- package/dist/data/description-context.d.ts +12 -6
- package/dist/data/description-context.js +6 -5
- package/dist/data/index.d.ts +2 -0
- package/dist/data/index.js +2 -0
- package/dist/data/table-types.d.ts +7 -0
- package/dist/feedback/Dialog.svelte +19 -49
- package/dist/feedback/Dialog.svelte.d.ts +0 -1
- package/dist/feedback/DialogFrame.svelte +64 -0
- package/dist/feedback/DialogFrame.svelte.d.ts +23 -0
- package/dist/feedback/Drawer.svelte +43 -0
- package/dist/feedback/Drawer.svelte.d.ts +43 -0
- package/dist/feedback/SegmentBar.svelte.d.ts +1 -0
- package/dist/feedback/StatTile.svelte.d.ts +1 -0
- package/dist/feedback/Steps.svelte +72 -0
- package/dist/feedback/Steps.svelte.d.ts +61 -0
- package/dist/feedback/Timeline.svelte.d.ts +3 -0
- package/dist/feedback/index.d.ts +3 -0
- package/dist/feedback/index.js +2 -0
- package/dist/feedback/sizes.d.ts +14 -0
- package/dist/feedback/sizes.js +28 -0
- package/dist/fields/Calendar.svelte +60 -0
- package/dist/fields/Calendar.svelte.d.ts +11 -0
- package/dist/fields/CalendarMonths.svelte +86 -0
- package/dist/fields/CalendarMonths.svelte.d.ts +30 -0
- package/dist/fields/Checkbox.svelte +1 -1
- package/dist/fields/Checkbox.svelte.d.ts +6 -0
- package/dist/fields/Combobox.svelte +61 -54
- package/dist/fields/Combobox.svelte.d.ts +38 -3
- package/dist/fields/DateField.svelte +37 -0
- package/dist/fields/DateField.svelte.d.ts +20 -0
- package/dist/fields/DateInput.svelte +1 -1
- package/dist/fields/DateInput.svelte.d.ts +6 -0
- package/dist/fields/DatePicker.svelte +47 -0
- package/dist/fields/DatePicker.svelte.d.ts +25 -0
- package/dist/fields/DateRangePicker.svelte +70 -0
- package/dist/fields/DateRangePicker.svelte.d.ts +43 -0
- package/dist/fields/Dropzone.svelte +232 -0
- package/dist/fields/Dropzone.svelte.d.ts +103 -0
- package/dist/fields/Fieldset.svelte +7 -2
- package/dist/fields/Fieldset.svelte.d.ts +3 -2
- package/dist/fields/FileInput.svelte +3 -2
- package/dist/fields/FileInput.svelte.d.ts +6 -0
- package/dist/fields/FormField.svelte +27 -3
- package/dist/fields/ImageInput.svelte.d.ts +6 -0
- package/dist/fields/MultiSelect.svelte +112 -0
- package/dist/fields/MultiSelect.svelte.d.ts +75 -0
- package/dist/fields/NumberField.svelte +190 -0
- package/dist/fields/NumberField.svelte.d.ts +76 -0
- package/dist/fields/PasswordInput.svelte +95 -0
- package/dist/fields/PasswordInput.svelte.d.ts +58 -0
- package/dist/fields/PickerPopover.svelte +47 -0
- package/dist/fields/PickerPopover.svelte.d.ts +16 -0
- package/dist/fields/PinInput.svelte +83 -0
- package/dist/fields/PinInput.svelte.d.ts +66 -0
- package/dist/fields/RadioGroup.svelte +3 -0
- package/dist/fields/RangeCalendar.svelte +51 -0
- package/dist/fields/RangeCalendar.svelte.d.ts +23 -0
- package/dist/fields/Rating.svelte +127 -0
- package/dist/fields/Rating.svelte.d.ts +86 -0
- package/dist/fields/SearchInput.svelte +2 -1
- package/dist/fields/SegmentGroup.svelte +91 -0
- package/dist/fields/SegmentGroup.svelte.d.ts +20 -0
- package/dist/fields/Select.svelte +1 -1
- package/dist/fields/Select.svelte.d.ts +6 -0
- package/dist/fields/Slider.svelte +194 -0
- package/dist/fields/Slider.svelte.d.ts +100 -0
- package/dist/fields/TagsInput.svelte +256 -0
- package/dist/fields/TagsInput.svelte.d.ts +102 -0
- package/dist/fields/TextInput.svelte +1 -1
- package/dist/fields/TextInput.svelte.d.ts +6 -0
- package/dist/fields/Textarea.svelte +1 -1
- package/dist/fields/Textarea.svelte.d.ts +6 -0
- package/dist/fields/TimeField.svelte +30 -0
- package/dist/fields/TimeField.svelte.d.ts +19 -0
- package/dist/fields/Toggle.svelte +1 -1
- package/dist/fields/Toggle.svelte.d.ts +6 -0
- package/dist/fields/VideoInput.svelte.d.ts +6 -0
- package/dist/fields/calendar-props.d.ts +119 -0
- package/dist/fields/calendar-props.js +51 -0
- package/dist/fields/dates.d.ts +28 -0
- package/dist/fields/dates.js +26 -0
- package/dist/fields/field-types.d.ts +29 -0
- package/dist/fields/field-types.js +32 -0
- package/dist/fields/file-validation.d.ts +30 -0
- package/dist/fields/file-validation.js +51 -0
- package/dist/fields/index.d.ts +9 -0
- package/dist/fields/index.js +8 -0
- package/dist/fields/latest-search.svelte.d.ts +38 -0
- package/dist/fields/latest-search.svelte.js +85 -0
- package/dist/fields/number-format.d.ts +52 -0
- package/dist/fields/number-format.js +89 -0
- package/dist/fields/segmented-field.d.ts +128 -0
- package/dist/fields/segmented-field.js +52 -0
- package/dist/fields/slider-keys.d.ts +21 -0
- package/dist/fields/slider-keys.js +37 -0
- package/dist/formatting/Countdown.svelte +110 -0
- package/dist/formatting/Countdown.svelte.d.ts +35 -0
- package/dist/formatting/Duration.svelte +18 -0
- package/dist/formatting/Duration.svelte.d.ts +20 -0
- package/dist/formatting/Highlight.svelte +4 -0
- package/dist/formatting/Highlight.svelte.d.ts +4 -0
- package/dist/formatting/duration.d.ts +44 -0
- package/dist/formatting/duration.js +125 -0
- package/dist/formatting/index.d.ts +3 -0
- package/dist/formatting/index.js +3 -0
- package/dist/forms/EntityForm.svelte +53 -45
- package/dist/forms/EntityForm.svelte.d.ts +12 -3
- package/dist/hotkeys/index.d.ts +5 -0
- package/dist/hotkeys/index.js +5 -0
- package/dist/hotkeys/match.js +12 -10
- package/dist/hotkeys/types.d.ts +4 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/infobox/Infobox.svelte +2 -2
- package/dist/infobox/Infobox.svelte.d.ts +7 -0
- package/dist/infobox/InfoboxHeader.svelte +15 -7
- package/dist/infobox/InfoboxHeader.svelte.d.ts +7 -0
- package/dist/infobox/types.d.ts +5 -5
- package/dist/layout/AppShell.svelte +50 -0
- package/dist/layout/AppShell.svelte.d.ts +28 -0
- package/dist/layout/Cluster.svelte +28 -0
- package/dist/layout/Cluster.svelte.d.ts +27 -0
- package/dist/layout/Fits.svelte +27 -0
- package/dist/layout/Fits.svelte.d.ts +13 -0
- package/dist/layout/Flow.svelte +46 -0
- package/dist/layout/Flow.svelte.d.ts +16 -0
- package/dist/layout/Grid.svelte +23 -0
- package/dist/layout/Grid.svelte.d.ts +26 -0
- package/dist/layout/HStack.svelte +12 -0
- package/dist/layout/HStack.svelte.d.ts +34 -0
- package/dist/layout/Hero.svelte +76 -0
- package/dist/layout/Hero.svelte.d.ts +36 -0
- package/dist/layout/Navbar.svelte +2 -2
- package/dist/layout/Sidebar.svelte +1 -1
- package/dist/layout/Spacer.svelte +12 -0
- package/dist/layout/Spacer.svelte.d.ts +6 -0
- package/dist/layout/VStack.svelte +12 -0
- package/dist/layout/VStack.svelte.d.ts +29 -0
- package/dist/layout/index.d.ts +9 -0
- package/dist/layout/index.js +9 -0
- package/dist/layout/space.d.ts +44 -0
- package/dist/layout/space.js +76 -0
- package/dist/search/types.d.ts +3 -0
- package/dist/seo/og-image.d.ts +4 -3
- package/dist/seo/og-image.js +4 -3
- package/dist/tips/tip-stack.d.ts +1 -0
- package/dist/tips/tip-store.svelte.d.ts +2 -1
- package/dist/ui/Accordion.svelte +75 -0
- package/dist/ui/Accordion.svelte.d.ts +50 -0
- package/dist/ui/AccordionItem.svelte +73 -0
- package/dist/ui/AccordionItem.svelte.d.ts +18 -0
- package/dist/ui/Button.svelte +3 -2
- package/dist/ui/ButtonGroup.svelte +24 -0
- package/dist/ui/ButtonGroup.svelte.d.ts +17 -0
- package/dist/ui/ContextMenu.svelte +75 -0
- package/dist/ui/ContextMenu.svelte.d.ts +25 -0
- package/dist/ui/Disclosure.svelte +7 -0
- package/dist/ui/Disclosure.svelte.d.ts +2 -2
- package/dist/ui/Divider.svelte +47 -0
- package/dist/ui/Divider.svelte.d.ts +28 -0
- package/dist/ui/DropdownMenu.svelte +44 -0
- package/dist/ui/DropdownMenu.svelte.d.ts +30 -0
- package/dist/ui/Menu.svelte +17 -47
- package/dist/ui/Menu.svelte.d.ts +3 -24
- package/dist/ui/MenuCheckboxItem.svelte +33 -0
- package/dist/ui/MenuCheckboxItem.svelte.d.ts +20 -0
- package/dist/ui/MenuItem.svelte +29 -31
- package/dist/ui/MenuItem.svelte.d.ts +2 -2
- package/dist/ui/MenuRadioGroup.svelte +25 -0
- package/dist/ui/MenuRadioGroup.svelte.d.ts +20 -0
- package/dist/ui/MenuRadioItem.svelte +20 -0
- package/dist/ui/MenuRadioItem.svelte.d.ts +15 -0
- package/dist/ui/MenuSeparator.svelte +12 -11
- package/dist/ui/MenuSub.svelte +24 -0
- package/dist/ui/MenuSub.svelte.d.ts +15 -0
- package/dist/ui/Spinner.svelte +41 -0
- package/dist/ui/Spinner.svelte.d.ts +35 -0
- package/dist/ui/Stack.svelte +36 -0
- package/dist/ui/Stack.svelte.d.ts +48 -0
- package/dist/ui/ToggleButton.svelte +58 -0
- package/dist/ui/ToggleButton.svelte.d.ts +45 -0
- package/dist/ui/ToggleGroup.svelte +142 -0
- package/dist/ui/ToggleGroup.svelte.d.ts +86 -0
- package/dist/ui/Toolbar.svelte +40 -0
- package/dist/ui/Toolbar.svelte.d.ts +20 -0
- package/dist/ui/ToolbarButton.svelte +29 -0
- package/dist/ui/ToolbarButton.svelte.d.ts +21 -0
- package/dist/ui/ToolbarLink.svelte +21 -0
- package/dist/ui/ToolbarLink.svelte.d.ts +12 -0
- package/dist/ui/ToolbarSeparator.svelte +22 -0
- package/dist/ui/ToolbarSeparator.svelte.d.ts +12 -0
- package/dist/ui/ToolbarToggleGroup.svelte +66 -0
- package/dist/ui/ToolbarToggleGroup.svelte.d.ts +52 -0
- package/dist/ui/accordion-context.d.ts +26 -0
- package/dist/ui/accordion-context.js +23 -0
- package/dist/ui/context-menu.d.ts +13 -0
- package/dist/ui/context-menu.js +13 -0
- package/dist/ui/index.d.ts +19 -0
- package/dist/ui/index.js +18 -0
- package/dist/ui/menu-context.d.ts +13 -15
- package/dist/ui/menu-context.js +14 -18
- package/dist/ui/menu-parts/CheckboxItemPart.svelte +26 -0
- package/dist/ui/menu-parts/CheckboxItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/ItemPart.svelte +29 -0
- package/dist/ui/menu-parts/ItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/RadioGroupPart.svelte +24 -0
- package/dist/ui/menu-parts/RadioGroupPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/RadioItemPart.svelte +22 -0
- package/dist/ui/menu-parts/RadioItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/SeparatorPart.svelte +16 -0
- package/dist/ui/menu-parts/SeparatorPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/SubPart.svelte +28 -0
- package/dist/ui/menu-parts/SubPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/menu-parts.d.ts +104 -0
- package/dist/ui/menu-parts/menu-parts.js +31 -0
- package/dist/ui/menu-parts/parts.d.ts +12 -0
- package/dist/ui/menu-parts/parts.js +27 -0
- package/dist/ui/toggle-classes.d.ts +39 -0
- package/dist/ui/toggle-classes.js +36 -0
- package/dist/ui/tones.d.ts +35 -0
- package/dist/ui/tones.js +90 -0
- package/package.json +34 -18
|
@@ -21,57 +21,27 @@ A modal on bits-ui’s `Dialog`, wearing daisyUI’s `modal-box`.
|
|
|
21
21
|
`trigger` receives the props to spread, so an existing `Button` keeps its
|
|
22
22
|
own markup and its own accessible name; `actions` receives `close`, so the
|
|
23
23
|
action row's buttons can dismiss without reaching for the bindable `open`.
|
|
24
|
+
|
|
25
|
+
The modal itself is `DialogFrame`, shared with `Drawer`: this file only
|
|
26
|
+
chooses the centred `modal-box`.
|
|
24
27
|
-->
|
|
25
|
-
<script lang="ts">import
|
|
26
|
-
import { Dialog } from "bits-ui";
|
|
27
|
-
import Button from "../ui/Button.svelte";
|
|
28
|
-
import VisuallyHidden from "../ui/VisuallyHidden.svelte";
|
|
28
|
+
<script lang="ts">import DialogFrame from "./DialogFrame.svelte";
|
|
29
29
|
import { dialogSize } from "./sizes.js";
|
|
30
30
|
let { open = $bindable(false), title, description, closeLabel = "Close", size = "md", class: className, trigger, actions, children } = $props();
|
|
31
|
-
const close = () => {
|
|
32
|
-
open = false;
|
|
33
|
-
};
|
|
34
31
|
</script>
|
|
35
32
|
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
dialogSize[size],
|
|
52
|
-
className,
|
|
53
|
-
]}
|
|
54
|
-
>
|
|
55
|
-
<div class="flex items-start justify-between gap-4">
|
|
56
|
-
<Dialog.Title class="text-lg font-semibold">{title}</Dialog.Title>
|
|
57
|
-
<Dialog.Close>
|
|
58
|
-
{#snippet child({ props })}
|
|
59
|
-
<Button {...props} variant="ghost" size="sm" class="btn-square -mt-1 -mr-1">
|
|
60
|
-
<X class="size-4" aria-hidden="true" />
|
|
61
|
-
<VisuallyHidden>{closeLabel}</VisuallyHidden>
|
|
62
|
-
</Button>
|
|
63
|
-
{/snippet}
|
|
64
|
-
</Dialog.Close>
|
|
65
|
-
</div>
|
|
66
|
-
{#if description !== undefined}
|
|
67
|
-
<Dialog.Description class="text-base-content/70 mt-1 text-sm leading-6">
|
|
68
|
-
{description}
|
|
69
|
-
</Dialog.Description>
|
|
70
|
-
{/if}
|
|
71
|
-
<div class="py-4">{@render children()}</div>
|
|
72
|
-
{#if actions}
|
|
73
|
-
<div class="modal-action">{@render actions({ close })}</div>
|
|
74
|
-
{/if}
|
|
75
|
-
</Dialog.Content>
|
|
76
|
-
</Dialog.Portal>
|
|
77
|
-
</Dialog.Root>
|
|
33
|
+
<DialogFrame
|
|
34
|
+
bind:open
|
|
35
|
+
{title}
|
|
36
|
+
{description}
|
|
37
|
+
{closeLabel}
|
|
38
|
+
{trigger}
|
|
39
|
+
{actions}
|
|
40
|
+
{children}
|
|
41
|
+
layout="modal"
|
|
42
|
+
contentClass={[
|
|
43
|
+
'modal-box fixed top-1/2 left-1/2 z-50 max-h-[calc(100svh-2rem)] w-[calc(100vw-2rem)] -translate-x-1/2 -translate-y-1/2',
|
|
44
|
+
dialogSize[size],
|
|
45
|
+
className,
|
|
46
|
+
]}
|
|
47
|
+
/>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The modal body `Dialog` and `Drawer` share; internal, not exported.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
DialogFrame — one implementation of everything that makes a modal a
|
|
6
|
+
modal, on bits-ui's `Dialog`: the trigger, overlay, focus trap and
|
|
7
|
+
return, Escape, scroll lock, the title and description wiring, the
|
|
8
|
+
labelled close button and the `actions({ close })` row. `Dialog` (a
|
|
9
|
+
centred `modal-box`) and `Drawer` (a panel at an edge) differ only in
|
|
10
|
+
`layout` and the content classes they pass, so the two cannot drift on
|
|
11
|
+
focus, dismissal or labelling.
|
|
12
|
+
|
|
13
|
+
`hideTitle` keeps the title as the accessible name but hides it
|
|
14
|
+
visually: a mobile navigation drawer needs a name, not a heading.
|
|
15
|
+
-->
|
|
16
|
+
<script lang="ts">import { X } from "@lucide/svelte";
|
|
17
|
+
import { Dialog } from "bits-ui";
|
|
18
|
+
import Button from "../ui/Button.svelte";
|
|
19
|
+
import VisuallyHidden from "../ui/VisuallyHidden.svelte";
|
|
20
|
+
let { open = $bindable(false), title, description, closeLabel, hideTitle = false, layout, contentClass, trigger, actions, children } = $props();
|
|
21
|
+
const close = () => {
|
|
22
|
+
open = false;
|
|
23
|
+
};
|
|
24
|
+
const sheet = $derived(layout === "sheet");
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<Dialog.Root bind:open>
|
|
28
|
+
{#if trigger}
|
|
29
|
+
<Dialog.Trigger>
|
|
30
|
+
{#snippet child({ props })}
|
|
31
|
+
{@render trigger({ props })}
|
|
32
|
+
{/snippet}
|
|
33
|
+
</Dialog.Trigger>
|
|
34
|
+
{/if}
|
|
35
|
+
<Dialog.Portal>
|
|
36
|
+
<!-- daisyUI's `modal-backdrop` is a child of an open `.modal`; this is
|
|
37
|
+
the same scrim as an element bits-ui can animate and dismiss from. -->
|
|
38
|
+
<Dialog.Overlay class="bg-base-300/60 fixed inset-0 z-40" />
|
|
39
|
+
<Dialog.Content class={contentClass}>
|
|
40
|
+
<div class={['flex items-start justify-between gap-4', sheet && 'px-4 pt-4']}>
|
|
41
|
+
<Dialog.Title class={hideTitle ? 'sr-only' : 'text-lg font-semibold'}>{title}</Dialog.Title>
|
|
42
|
+
<Dialog.Close>
|
|
43
|
+
{#snippet child({ props })}
|
|
44
|
+
<Button {...props} variant="ghost" size="sm" class="btn-square -mt-1 -mr-1 ms-auto">
|
|
45
|
+
<X class="size-4" aria-hidden="true" />
|
|
46
|
+
<VisuallyHidden>{closeLabel}</VisuallyHidden>
|
|
47
|
+
</Button>
|
|
48
|
+
{/snippet}
|
|
49
|
+
</Dialog.Close>
|
|
50
|
+
</div>
|
|
51
|
+
{#if description !== undefined}
|
|
52
|
+
<Dialog.Description class={['text-base-content/70 mt-1 text-sm leading-6', sheet && 'px-4']}>
|
|
53
|
+
{description}
|
|
54
|
+
</Dialog.Description>
|
|
55
|
+
{/if}
|
|
56
|
+
<div class={sheet ? 'min-h-0 flex-1 overflow-y-auto p-4' : 'py-4'}>{@render children()}</div>
|
|
57
|
+
{#if actions}
|
|
58
|
+
<div class={sheet ? 'border-base-300 flex justify-end gap-2 border-t p-4' : 'modal-action'}>
|
|
59
|
+
{@render actions({ close })}
|
|
60
|
+
</div>
|
|
61
|
+
{/if}
|
|
62
|
+
</Dialog.Content>
|
|
63
|
+
</Dialog.Portal>
|
|
64
|
+
</Dialog.Root>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ClassValue } from 'svelte/elements';
|
|
3
|
+
interface Props {
|
|
4
|
+
open?: boolean | undefined;
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string | undefined;
|
|
7
|
+
closeLabel: string;
|
|
8
|
+
hideTitle?: boolean | undefined;
|
|
9
|
+
/** `modal`: daisyUI `modal-box` flow. `sheet`: a column with a scrolling body and a pinned footer. */
|
|
10
|
+
layout: 'modal' | 'sheet';
|
|
11
|
+
contentClass: ClassValue;
|
|
12
|
+
trigger?: Snippet<[{
|
|
13
|
+
props: Record<string, unknown>;
|
|
14
|
+
}]> | undefined;
|
|
15
|
+
actions?: Snippet<[{
|
|
16
|
+
close: () => void;
|
|
17
|
+
}]> | undefined;
|
|
18
|
+
children: Snippet<[]>;
|
|
19
|
+
}
|
|
20
|
+
/** The modal body `Dialog` and `Drawer` share; internal, not exported. */
|
|
21
|
+
declare const DialogFrame: import("svelte").Component<Props, {}, "open">;
|
|
22
|
+
type DialogFrame = ReturnType<typeof DialogFrame>;
|
|
23
|
+
export default DialogFrame;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A modal panel that slides in from an edge: a filters sheet, a mobile action sheet, mobile navigation.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Drawer — `Dialog`'s contract at an edge of the screen. It shares
|
|
6
|
+
`DialogFrame` with `Dialog`, so the focus trap and return, Escape and
|
|
7
|
+
overlay dismissal, scroll lock, `aria-modal`, the title as the accessible
|
|
8
|
+
name and the labelled close button are one implementation.
|
|
9
|
+
|
|
10
|
+
Not daisyUI's `drawer`: that is driven by a hidden checkbox and a
|
|
11
|
+
`<label>` overlay, which gives no focus trap, no focus move or return, no
|
|
12
|
+
Escape, no `aria-modal` and no name, and leaves the page behind it in the
|
|
13
|
+
Tab order. Only daisyUI's look is borrowed here.
|
|
14
|
+
|
|
15
|
+
The panel is a column: the title row, a body that scrolls on its own, and
|
|
16
|
+
an `actions({ close })` footer that stays put. `start` / `end` follow
|
|
17
|
+
the writing direction, so a `start` drawer opens from the right in RTL.
|
|
18
|
+
It does not animate, so there is no motion to reduce; swipe-to-dismiss is
|
|
19
|
+
out of v1.
|
|
20
|
+
-->
|
|
21
|
+
<script lang="ts">import DialogFrame from "./DialogFrame.svelte";
|
|
22
|
+
import { drawerHeight, drawerSide, drawerWidth } from "./sizes.js";
|
|
23
|
+
let { open = $bindable(false), title, description, side = "end", size = "md", closeLabel = "Close", hideTitle = false, class: className, trigger, actions, children } = $props();
|
|
24
|
+
const horizontal = $derived(side === "start" || side === "end");
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<DialogFrame
|
|
28
|
+
bind:open
|
|
29
|
+
{title}
|
|
30
|
+
{description}
|
|
31
|
+
{closeLabel}
|
|
32
|
+
{hideTitle}
|
|
33
|
+
{trigger}
|
|
34
|
+
{actions}
|
|
35
|
+
{children}
|
|
36
|
+
layout="sheet"
|
|
37
|
+
contentClass={[
|
|
38
|
+
'bg-base-100 fixed z-50 flex flex-col shadow-xl outline-none',
|
|
39
|
+
drawerSide[side],
|
|
40
|
+
horizontal ? drawerWidth[size] : drawerHeight[size],
|
|
41
|
+
className,
|
|
42
|
+
]}
|
|
43
|
+
/>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type DrawerSide, type DrawerSize } from './sizes.ts';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** Whether the drawer is shown. Bindable. */
|
|
5
|
+
open?: boolean | undefined;
|
|
6
|
+
/** Heading — the panel's accessible name. */
|
|
7
|
+
title: string;
|
|
8
|
+
/** Supporting line under the heading — the accessible description. */
|
|
9
|
+
description?: string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The edge the panel enters from.
|
|
12
|
+
* @defaultValue `'end'`
|
|
13
|
+
*/
|
|
14
|
+
side?: DrawerSide | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Width at `start` / `end`, height at `top` / `bottom`.
|
|
17
|
+
* @defaultValue `'md'`
|
|
18
|
+
*/
|
|
19
|
+
size?: DrawerSize | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Accessible name of the corner close button.
|
|
22
|
+
* @defaultValue `'Close'`
|
|
23
|
+
*/
|
|
24
|
+
closeLabel?: string | undefined;
|
|
25
|
+
/** Hide the title visually; it stays the accessible name (mobile navigation). */
|
|
26
|
+
hideTitle?: boolean | undefined;
|
|
27
|
+
/** Extra classes on the panel. */
|
|
28
|
+
class?: string | undefined;
|
|
29
|
+
/** The opening control — the caller's own element, spreading `props`. */
|
|
30
|
+
trigger?: Snippet<[{
|
|
31
|
+
props: Record<string, unknown>;
|
|
32
|
+
}]> | undefined;
|
|
33
|
+
/** A footer row that stays in view; receives `close`. */
|
|
34
|
+
actions?: Snippet<[{
|
|
35
|
+
close: () => void;
|
|
36
|
+
}]> | undefined;
|
|
37
|
+
/** The panel body; it scrolls when long. */
|
|
38
|
+
children: Snippet<[]>;
|
|
39
|
+
}
|
|
40
|
+
/** A modal panel that slides in from an edge: a filters sheet, a mobile action sheet, mobile navigation. */
|
|
41
|
+
declare const Drawer: import("svelte").Component<Props, {}, "open">;
|
|
42
|
+
type Drawer = ReturnType<typeof Drawer>;
|
|
43
|
+
export default Drawer;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
2
|
import { type Tone } from '../ui/tones.ts';
|
|
3
3
|
import { type BarSize } from './sizes.ts';
|
|
4
|
+
/** One part of a `SegmentBar`: its label, its share of the bar, and its colour. */
|
|
4
5
|
export interface BarSegment {
|
|
5
6
|
/** Read out for this segment in the bar's accessible label. */
|
|
6
7
|
readonly label: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
/** The change line a `StatTile` shows under its value: a signed amount, how to render it, and trailing words. */
|
|
3
4
|
export interface StatDelta {
|
|
4
5
|
/**
|
|
5
6
|
* The change. Positive is up. With `unit: 'percent'` it is read as a
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The stages of a multi-step flow as daisyUI `steps`, with the current one marked.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Steps — a short, fixed sequence (a sign-up wizard, an order's fulfilment,
|
|
6
|
+
"Plan → Sow → Transplant → Harvest") where position and state are the
|
|
7
|
+
content. Unlike `Timeline`, which is dated, open-ended history.
|
|
8
|
+
|
|
9
|
+
Each step's state comes from its own `state`, or, when that is omitted,
|
|
10
|
+
from the list's `current` index: before it is complete, at it is current,
|
|
11
|
+
after it is upcoming. An explicit `state` always wins, so an `error` step
|
|
12
|
+
can sit in a `current`-driven wizard.
|
|
13
|
+
|
|
14
|
+
ARIA contract: an `<ol>` named by `label`, because order is the content.
|
|
15
|
+
Colour carries nothing on its own (WCAG 1.4.1): each step reads its label
|
|
16
|
+
followed by a visually hidden state ("Sow, Completed"). The marker, the
|
|
17
|
+
step number or a ✓ / ✕ glyph, is always a real `step-icon` span with
|
|
18
|
+
`aria-hidden`. Rendering one suppresses daisyUI's `::after` number, and
|
|
19
|
+
CSS generated content would otherwise join the accessible name. The
|
|
20
|
+
current step carries `aria-current="step"`: on its link in link mode, on
|
|
21
|
+
the `<li>` otherwise. Only steps with an `href` are links; whether an
|
|
22
|
+
upcoming step is navigable is the caller's call, not this component's.
|
|
23
|
+
-->
|
|
24
|
+
<script lang="ts">import { getComponentsContext } from "../context.svelte.js";
|
|
25
|
+
import { stepTone } from "../ui/tones.js";
|
|
26
|
+
import { stepsOrientation } from "./sizes.js";
|
|
27
|
+
let { items, label, current, orientation = "horizontal", tone = "primary", completeLabel = "Completed", currentLabel = "Current step", upcomingLabel = "Not started", errorLabel = "Error", marker, class: className, ...rest } = $props();
|
|
28
|
+
const context = getComponentsContext();
|
|
29
|
+
function stateOf(step, index) {
|
|
30
|
+
if (step.state !== undefined) return step.state;
|
|
31
|
+
if (current === undefined || index > current) return "upcoming";
|
|
32
|
+
return index < current ? "complete" : "current";
|
|
33
|
+
}
|
|
34
|
+
const stateLabels = $derived({
|
|
35
|
+
complete: completeLabel,
|
|
36
|
+
current: currentLabel,
|
|
37
|
+
upcoming: upcomingLabel,
|
|
38
|
+
error: errorLabel
|
|
39
|
+
});
|
|
40
|
+
const stateClasses = $derived({
|
|
41
|
+
complete: stepTone[tone],
|
|
42
|
+
current: stepTone[tone],
|
|
43
|
+
upcoming: "",
|
|
44
|
+
error: stepTone.error
|
|
45
|
+
});
|
|
46
|
+
const glyphs = {
|
|
47
|
+
complete: "✓",
|
|
48
|
+
error: "✕"
|
|
49
|
+
};
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<ol {...rest} aria-label={label} class={['steps', stepsOrientation[orientation], className]}>
|
|
53
|
+
{#each items as step, index (step.id)}
|
|
54
|
+
{@const state = stateOf(step, index)}
|
|
55
|
+
{@const ariaCurrent = state === 'current' ? 'step' : undefined}
|
|
56
|
+
<li
|
|
57
|
+
class={['step', stateClasses[state]]}
|
|
58
|
+
aria-current={step.href === undefined ? ariaCurrent : undefined}
|
|
59
|
+
>
|
|
60
|
+
<span class="step-icon" aria-hidden="true">
|
|
61
|
+
{#if marker}{@render marker(step, index)}{:else}{glyphs[state] ?? index + 1}{/if}
|
|
62
|
+
</span>
|
|
63
|
+
{#if step.href !== undefined}
|
|
64
|
+
<a href={context.href(step.href)} class="link link-hover" aria-current={ariaCurrent}>
|
|
65
|
+
{step.label}<span class="sr-only">, {stateLabels[state]}</span>
|
|
66
|
+
</a>
|
|
67
|
+
{:else}
|
|
68
|
+
<span>{step.label}<span class="sr-only">, {stateLabels[state]}</span></span>
|
|
69
|
+
{/if}
|
|
70
|
+
</li>
|
|
71
|
+
{/each}
|
|
72
|
+
</ol>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLOlAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../ui/tones.ts';
|
|
4
|
+
import { type StepsOrientation } from './sizes.ts';
|
|
5
|
+
/** Where a step stands in the flow. */
|
|
6
|
+
export type StepState = 'complete' | 'current' | 'upcoming' | 'error';
|
|
7
|
+
/** One stage of a `Steps` list. */
|
|
8
|
+
export interface StepItem {
|
|
9
|
+
/** Stable key for the step. */
|
|
10
|
+
readonly id: string;
|
|
11
|
+
/** The step's name, read first. */
|
|
12
|
+
readonly label: string;
|
|
13
|
+
/** Overrides the state derived from the list's `current` index. */
|
|
14
|
+
readonly state?: StepState | undefined;
|
|
15
|
+
/** Makes the step a link (to revisit it), resolved through the components context's `href`. */
|
|
16
|
+
readonly href?: string | undefined;
|
|
17
|
+
}
|
|
18
|
+
interface Props extends Omit<HTMLOlAttributes, 'children'> {
|
|
19
|
+
/** The steps, in order. */
|
|
20
|
+
items: readonly StepItem[];
|
|
21
|
+
/** Accessible name of the list, e.g. `'Checkout progress'`. */
|
|
22
|
+
label: string;
|
|
23
|
+
/**
|
|
24
|
+
* Index of the current step. Steps before it are complete and steps after
|
|
25
|
+
* it upcoming, unless a step sets its own `state`.
|
|
26
|
+
*/
|
|
27
|
+
current?: number | undefined;
|
|
28
|
+
/** @defaultValue `'horizontal'` */
|
|
29
|
+
orientation?: StepsOrientation | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Tone of the complete and current steps.
|
|
32
|
+
* @defaultValue `'primary'`
|
|
33
|
+
*/
|
|
34
|
+
tone?: Tone | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Read after a complete step's label.
|
|
37
|
+
* @defaultValue `'Completed'`
|
|
38
|
+
*/
|
|
39
|
+
completeLabel?: string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Read after the current step's label.
|
|
42
|
+
* @defaultValue `'Current step'`
|
|
43
|
+
*/
|
|
44
|
+
currentLabel?: string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Read after an upcoming step's label.
|
|
47
|
+
* @defaultValue `'Not started'`
|
|
48
|
+
*/
|
|
49
|
+
upcomingLabel?: string | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Read after a failed step's label.
|
|
52
|
+
* @defaultValue `'Error'`
|
|
53
|
+
*/
|
|
54
|
+
errorLabel?: string | undefined;
|
|
55
|
+
/** Custom marker content per step (an icon), rendered in the `aria-hidden` `step-icon`. */
|
|
56
|
+
marker?: Snippet<[StepItem, number]> | undefined;
|
|
57
|
+
}
|
|
58
|
+
/** The stages of a multi-step flow as daisyUI `steps`, with the current one marked. */
|
|
59
|
+
declare const Steps: import("svelte").Component<Props, {}, "">;
|
|
60
|
+
type Steps = ReturnType<typeof Steps>;
|
|
61
|
+
export default Steps;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLOlAttributes } from 'svelte/elements';
|
|
3
|
+
/** One end of a `Timeline` entry's span: display text plus an optional machine-readable `datetime`. */
|
|
3
4
|
export interface TimelineDate {
|
|
4
5
|
/** Display text, e.g. `March 1996`. */
|
|
5
6
|
readonly label: string;
|
|
6
7
|
/** Machine-readable `<time datetime>` value, e.g. `1996-03-02`. */
|
|
7
8
|
readonly dateTime?: string | undefined;
|
|
8
9
|
}
|
|
10
|
+
/** One dated entry of a `Timeline`: a label, a start, an optional end and link, and an optional theme colour. */
|
|
9
11
|
export interface TimelineEntry {
|
|
12
|
+
/** Stable key for the entry. */
|
|
10
13
|
readonly id: string;
|
|
11
14
|
/** The entry itself — the line in the box. */
|
|
12
15
|
readonly label: string;
|
package/dist/feedback/index.d.ts
CHANGED
|
@@ -16,16 +16,19 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export { default as ConfirmDialog } from './ConfirmDialog.svelte';
|
|
18
18
|
export { default as Dialog } from './Dialog.svelte';
|
|
19
|
+
export { default as Drawer } from './Drawer.svelte';
|
|
19
20
|
export { default as LoadingBoundary } from './LoadingBoundary.svelte';
|
|
20
21
|
export { default as ProgressBar } from './ProgressBar.svelte';
|
|
21
22
|
export { default as SegmentBar } from './SegmentBar.svelte';
|
|
22
23
|
export { default as StatTile } from './StatTile.svelte';
|
|
23
24
|
export { default as Stats } from './Stats.svelte';
|
|
25
|
+
export { default as Steps } from './Steps.svelte';
|
|
24
26
|
export { default as Timeline } from './Timeline.svelte';
|
|
25
27
|
export { default as Toaster } from './Toaster.svelte';
|
|
26
28
|
export type { ConfirmForm } from './ConfirmDialog.svelte';
|
|
27
29
|
export type { BarSegment } from './SegmentBar.svelte';
|
|
28
30
|
export type { StatDelta } from './StatTile.svelte';
|
|
31
|
+
export type { StepItem, StepState } from './Steps.svelte';
|
|
29
32
|
export type { TimelineDate, TimelineEntry } from './Timeline.svelte';
|
|
30
33
|
export * from './sizes.ts';
|
|
31
34
|
export * from './toaster.ts';
|
package/dist/feedback/index.js
CHANGED
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export { default as ConfirmDialog } from './ConfirmDialog.svelte';
|
|
18
18
|
export { default as Dialog } from './Dialog.svelte';
|
|
19
|
+
export { default as Drawer } from './Drawer.svelte';
|
|
19
20
|
export { default as LoadingBoundary } from './LoadingBoundary.svelte';
|
|
20
21
|
export { default as ProgressBar } from './ProgressBar.svelte';
|
|
21
22
|
export { default as SegmentBar } from './SegmentBar.svelte';
|
|
22
23
|
export { default as StatTile } from './StatTile.svelte';
|
|
23
24
|
export { default as Stats } from './Stats.svelte';
|
|
25
|
+
export { default as Steps } from './Steps.svelte';
|
|
24
26
|
export { default as Timeline } from './Timeline.svelte';
|
|
25
27
|
export { default as Toaster } from './Toaster.svelte';
|
|
26
28
|
export * from "./sizes.js";
|
package/dist/feedback/sizes.d.ts
CHANGED
|
@@ -25,3 +25,17 @@ export declare const barSize: Record<BarSize, string>;
|
|
|
25
25
|
export type StatsOrientation = 'horizontal' | 'vertical' | 'responsive';
|
|
26
26
|
/** Literal daisyUI class per `StatsOrientation` for `Stats`; a lookup table so Tailwind's scanner sees every class. */
|
|
27
27
|
export declare const statsOrientation: Record<StatsOrientation, string>;
|
|
28
|
+
/** How a `Steps` list lays its steps out. */
|
|
29
|
+
export type StepsOrientation = 'horizontal' | 'vertical' | 'responsive';
|
|
30
|
+
/** Literal daisyUI class per `StepsOrientation` for `Steps`; a lookup table so Tailwind's scanner sees every class. */
|
|
31
|
+
export declare const stepsOrientation: Record<StepsOrientation, string>;
|
|
32
|
+
/** The edge a `Drawer` enters from; `start` / `end` follow the writing direction. */
|
|
33
|
+
export type DrawerSide = 'start' | 'end' | 'top' | 'bottom';
|
|
34
|
+
/** Literal placement classes per `DrawerSide`; a lookup table so Tailwind's scanner sees every class. */
|
|
35
|
+
export declare const drawerSide: Record<DrawerSide, string>;
|
|
36
|
+
/** Size steps of a `Drawer`: its width at `start` / `end`, its height at `top` / `bottom`. */
|
|
37
|
+
export type DrawerSize = 'sm' | 'md' | 'lg' | 'full';
|
|
38
|
+
/** Literal width class per `DrawerSize` for a `start` / `end` drawer. */
|
|
39
|
+
export declare const drawerWidth: Record<DrawerSize, string>;
|
|
40
|
+
/** Literal height class per `DrawerSize` for a `top` / `bottom` drawer. */
|
|
41
|
+
export declare const drawerHeight: Record<DrawerSize, string>;
|
package/dist/feedback/sizes.js
CHANGED
|
@@ -39,3 +39,31 @@ export const statsOrientation = {
|
|
|
39
39
|
// dashboard reached for by hand.
|
|
40
40
|
responsive: 'stats-vertical sm:stats-horizontal',
|
|
41
41
|
};
|
|
42
|
+
/** Literal daisyUI class per `StepsOrientation` for `Steps`; a lookup table so Tailwind's scanner sees every class. */
|
|
43
|
+
export const stepsOrientation = {
|
|
44
|
+
horizontal: 'steps-horizontal',
|
|
45
|
+
vertical: 'steps-vertical',
|
|
46
|
+
// A column on a phone, a row from `sm` up, as `statsOrientation` does.
|
|
47
|
+
responsive: 'steps-vertical sm:steps-horizontal',
|
|
48
|
+
};
|
|
49
|
+
/** Literal placement classes per `DrawerSide`; a lookup table so Tailwind's scanner sees every class. */
|
|
50
|
+
export const drawerSide = {
|
|
51
|
+
start: 'inset-y-0 start-0 h-full max-w-[calc(100vw-2rem)]',
|
|
52
|
+
end: 'inset-y-0 end-0 h-full max-w-[calc(100vw-2rem)]',
|
|
53
|
+
top: 'inset-x-0 top-0 max-h-[85dvh] rounded-b-box',
|
|
54
|
+
bottom: 'inset-x-0 bottom-0 max-h-[85dvh] rounded-t-box',
|
|
55
|
+
};
|
|
56
|
+
/** Literal width class per `DrawerSize` for a `start` / `end` drawer. */
|
|
57
|
+
export const drawerWidth = {
|
|
58
|
+
sm: 'w-72',
|
|
59
|
+
md: 'w-96',
|
|
60
|
+
lg: 'w-[32rem]',
|
|
61
|
+
full: 'w-screen max-w-none',
|
|
62
|
+
};
|
|
63
|
+
/** Literal height class per `DrawerSize` for a `top` / `bottom` drawer. */
|
|
64
|
+
export const drawerHeight = {
|
|
65
|
+
sm: 'h-[33dvh]',
|
|
66
|
+
md: 'h-[50dvh]',
|
|
67
|
+
lg: 'h-[75dvh]',
|
|
68
|
+
full: 'h-dvh max-h-none rounded-none',
|
|
69
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
An inline, always-visible month grid for picking a date, on bits-ui's `Calendar`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Calendar — a month (or several side by side) to choose one date from,
|
|
6
|
+
inline rather than in a popover: a booking sidebar, a "sown on" planner, an
|
|
7
|
+
availability view. The popover pickers compose it. `DateInput` (the native
|
|
8
|
+
control) stays the default for a single date on a form; this is for when
|
|
9
|
+
the reader benefits from seeing the month.
|
|
10
|
+
|
|
11
|
+
The value is a `DateValue` from `@internationalized/date`, bits-ui's own
|
|
12
|
+
type: lossless, and it carries its calendar system. Convert at the edge with
|
|
13
|
+
`parseDate('2026-10-23')` and `value.toString()`, both re-exported from the
|
|
14
|
+
`./dates` entry.
|
|
15
|
+
|
|
16
|
+
ARIA contract (APG date-picker grid), from bits-ui: a `role="application"`
|
|
17
|
+
wrapper named by `calendarLabel` and the visible month, one `role="grid"`
|
|
18
|
+
per month, `gridcell`s with `aria-selected` / `aria-disabled`, a roving
|
|
19
|
+
tabindex, and the keys — arrows by day and week, Home / End to the week's
|
|
20
|
+
ends, Page Up / Page Down by month, Enter / Space to select. This file
|
|
21
|
+
adds the labelled previous / next buttons (`previousLabel` / `nextLabel`),
|
|
22
|
+
each grid's name ("October 2026"), a struck-through
|
|
23
|
+
unavailable day, and the `FieldControl` wiring: inside a `FormField` the
|
|
24
|
+
root is `aria-labelledby` the label (`labelId`) and `aria-describedby` the
|
|
25
|
+
hint and errors. `invalid` draws the error border; the `application` role
|
|
26
|
+
does not take `aria-invalid`, so the error text reaches it through
|
|
27
|
+
`describedBy`.
|
|
28
|
+
-->
|
|
29
|
+
<script lang="ts">import { Calendar } from "bits-ui";
|
|
30
|
+
import { getComponentsContext } from "../context.svelte.js";
|
|
31
|
+
import CalendarMonths from "./CalendarMonths.svelte";
|
|
32
|
+
import { calendarRoot } from "./calendar-props.js";
|
|
33
|
+
let { value = $bindable(), month = $bindable(), ...props } = $props();
|
|
34
|
+
const context = getComponentsContext();
|
|
35
|
+
const shared = $derived(calendarRoot(props, context.locale()));
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<Calendar.Root
|
|
39
|
+
{...shared.root}
|
|
40
|
+
type="single"
|
|
41
|
+
bind:placeholder={
|
|
42
|
+
// Unset, bits-ui picks the value's month or today's.
|
|
43
|
+
() => month as DateValue,
|
|
44
|
+
(next: DateValue) => {
|
|
45
|
+
month = next;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
bind:value={
|
|
49
|
+
// bits-ui declares `value?: DateValue` (no `| undefined`) but reads an
|
|
50
|
+
// unset value as `undefined` at runtime; the binding passes it through.
|
|
51
|
+
() => value as DateValue,
|
|
52
|
+
(next: DateValue | undefined) => {
|
|
53
|
+
value = next;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
>
|
|
57
|
+
{#snippet children({ months, weekdays })}
|
|
58
|
+
<CalendarMonths parts={Calendar} {...shared.months} {months} {weekdays} />
|
|
59
|
+
{/snippet}
|
|
60
|
+
</Calendar.Root>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DateValue } from '@internationalized/date';
|
|
2
|
+
import { Calendar } from 'bits-ui';
|
|
3
|
+
import { type CalendarBaseProps } from './calendar-props.ts';
|
|
4
|
+
interface Props extends CalendarBaseProps {
|
|
5
|
+
/** The selected date; `undefined` when none. Bindable. */
|
|
6
|
+
value?: DateValue | undefined;
|
|
7
|
+
}
|
|
8
|
+
/** An inline, always-visible month grid for picking a date, on bits-ui's `Calendar`. */
|
|
9
|
+
declare const Calendar: import("svelte").Component<Props, {}, "value" | "month">;
|
|
10
|
+
type Calendar = ReturnType<typeof Calendar>;
|
|
11
|
+
export default Calendar;
|