@nqmcreative/ui 0.1.1 → 0.2.1
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 +89 -34
- package/cli/index.mjs +83 -33
- package/dist/core/calendar.d.ts +3 -0
- package/dist/core/calendar.js +36 -0
- package/dist/core/dialog.svelte.d.ts +14 -0
- package/dist/core/dialog.svelte.js +23 -0
- package/dist/core/files.d.ts +35 -0
- package/dist/core/files.js +62 -0
- package/dist/core/index.d.ts +37 -0
- package/dist/core/index.js +35 -0
- package/dist/core/list.svelte.d.ts +41 -0
- package/dist/core/list.svelte.js +77 -0
- package/dist/core/number.d.ts +7 -0
- package/dist/core/number.js +17 -0
- package/dist/core/pagination.d.ts +6 -0
- package/dist/core/pagination.js +21 -0
- package/dist/core/password.d.ts +8 -0
- package/dist/core/password.js +23 -0
- package/dist/core/table.d.ts +22 -0
- package/dist/core/table.js +41 -0
- package/dist/core/theme.svelte.d.ts +16 -0
- package/dist/core/theme.svelte.js +34 -0
- package/dist/core/trigger.d.ts +35 -0
- package/dist/core/trigger.js +77 -0
- package/dist/index.d.ts +11 -103
- package/dist/index.js +11 -75
- package/dist/{components → styles/matte}/AccordionItem.svelte +1 -1
- package/dist/{components → styles/matte}/AccordionItem.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Alert.svelte +8 -2
- package/dist/{components → styles/matte}/Alert.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Avatar.svelte +1 -1
- package/dist/{components → styles/matte}/Avatar.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Badge.svelte +8 -3
- package/dist/{components → styles/matte}/Badge.svelte.d.ts +1 -3
- package/dist/{components → styles/matte}/Breadcrumb.svelte +2 -2
- package/dist/{components → styles/matte}/Breadcrumb.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Button.svelte +1 -1
- package/dist/{components → styles/matte}/Button.svelte.d.ts +1 -1
- package/dist/styles/matte/CTASection.svelte +76 -0
- package/dist/styles/matte/CTASection.svelte.d.ts +18 -0
- package/dist/{components → styles/matte}/Calendar.svelte +7 -17
- package/dist/{components → styles/matte}/Calendar.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Card.svelte +1 -1
- package/dist/{components → styles/matte}/Card.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Checkbox.svelte +1 -1
- package/dist/{components → styles/matte}/Checkbox.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/CheckboxGroup.svelte +1 -1
- package/dist/{components → styles/matte}/CheckboxGroup.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Combobox.svelte +31 -42
- package/dist/{components → styles/matte}/Combobox.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/CommandPalette.svelte +26 -41
- package/dist/{components → styles/matte}/CommandPalette.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/ConfirmDialog.svelte +2 -2
- package/dist/{components → styles/matte}/ConfirmDialog.svelte.d.ts +2 -2
- package/dist/{components → styles/matte}/ContextMenu.svelte +5 -7
- package/dist/{components → styles/matte}/DatePicker.svelte +7 -11
- package/dist/{components → styles/matte}/DatePicker.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Drawer.svelte +4 -7
- package/dist/{components → styles/matte}/Dropdown.svelte +18 -36
- package/dist/{components → styles/matte}/Dropdown.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Dropzone.svelte +11 -43
- package/dist/{components → styles/matte}/Dropzone.svelte.d.ts +2 -5
- package/dist/{components → styles/matte}/EmptyState.svelte +1 -1
- package/dist/{components → styles/matte}/EmptyState.svelte.d.ts +1 -1
- package/dist/styles/matte/FeatureCard.svelte +58 -0
- package/dist/styles/matte/FeatureCard.svelte.d.ts +16 -0
- package/dist/styles/matte/FeatureGrid.svelte +62 -0
- package/dist/styles/matte/FeatureGrid.svelte.d.ts +16 -0
- package/dist/{components → styles/matte}/Footer.svelte +1 -1
- package/dist/{components → styles/matte}/Footer.svelte.d.ts +1 -1
- package/dist/styles/matte/HeroSection.svelte +80 -0
- package/dist/styles/matte/HeroSection.svelte.d.ts +21 -0
- package/dist/{components → styles/matte}/Input.svelte +1 -1
- package/dist/{components → styles/matte}/Input.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Link.svelte +1 -1
- package/dist/{components → styles/matte}/Link.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/LocaleProvider.svelte +1 -1
- package/dist/{components → styles/matte}/LocaleProvider.svelte.d.ts +1 -1
- package/dist/styles/matte/LogoCloud.svelte +61 -0
- package/dist/styles/matte/LogoCloud.svelte.d.ts +19 -0
- package/dist/{components → styles/matte}/MenuItem.svelte +1 -1
- package/dist/{components → styles/matte}/MenuItem.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Modal.svelte +4 -7
- package/dist/{components → styles/matte}/MultiSelect.svelte +18 -37
- package/dist/{components → styles/matte}/MultiSelect.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Navbar.svelte +2 -2
- package/dist/{components → styles/matte}/Navbar.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/NumberInput.svelte +4 -8
- package/dist/{components → styles/matte}/NumberInput.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Pagination.svelte +4 -15
- package/dist/{components → styles/matte}/Pagination.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/PasswordInput.svelte +4 -13
- package/dist/{components → styles/matte}/PasswordInput.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Popover.svelte +16 -41
- package/dist/{components → styles/matte}/Popover.svelte.d.ts +1 -1
- package/dist/styles/matte/PricingCard.svelte +107 -0
- package/dist/styles/matte/PricingCard.svelte.d.ts +25 -0
- package/dist/{components → styles/matte}/Progress.svelte +3 -2
- package/dist/{components → styles/matte}/Progress.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Radio.svelte +1 -1
- package/dist/{components → styles/matte}/Radio.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/RadioGroup.svelte +1 -1
- package/dist/{components → styles/matte}/RadioGroup.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/SegmentedControl.svelte +1 -1
- package/dist/{components → styles/matte}/SegmentedControl.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Select.svelte +1 -1
- package/dist/{components → styles/matte}/Select.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Sidebar.svelte +2 -2
- package/dist/{components → styles/matte}/Sidebar.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Slider.svelte +3 -2
- package/dist/{components → styles/matte}/Slider.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Spinner.svelte +2 -2
- package/dist/{components → styles/matte}/Spinner.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Stat.svelte +1 -1
- package/dist/{components → styles/matte}/Stat.svelte.d.ts +1 -1
- package/dist/styles/matte/StatsBand.svelte +57 -0
- package/dist/styles/matte/StatsBand.svelte.d.ts +20 -0
- package/dist/{components → styles/matte}/Steps.svelte +1 -1
- package/dist/{components → styles/matte}/Steps.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Switch.svelte +1 -1
- package/dist/{components → styles/matte}/Switch.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/Table.svelte +6 -28
- package/dist/{components → styles/matte}/Table.svelte.d.ts +2 -6
- package/dist/{components → styles/matte}/Tabs.svelte +8 -1
- package/dist/{components → styles/matte}/Tabs.svelte.d.ts +1 -1
- package/dist/styles/matte/Testimonial.svelte +67 -0
- package/dist/styles/matte/Testimonial.svelte.d.ts +19 -0
- package/dist/{components → styles/matte}/Textarea.svelte +1 -1
- package/dist/{components → styles/matte}/Textarea.svelte.d.ts +1 -1
- package/dist/{components → styles/matte}/ThemeToggle.svelte +14 -27
- package/dist/{components → styles/matte}/ThemeToggle.svelte.d.ts +2 -6
- package/dist/{components → styles/matte}/Toaster.svelte +4 -4
- package/dist/styles/matte/index.d.ts +109 -0
- package/dist/styles/matte/index.js +83 -0
- package/dist/styles/paper/Accordion.svelte +17 -0
- package/dist/styles/paper/Accordion.svelte.d.ts +8 -0
- package/dist/styles/paper/AccordionItem.svelte +46 -0
- package/dist/styles/paper/AccordionItem.svelte.d.ts +14 -0
- package/dist/styles/paper/Alert.svelte +99 -0
- package/dist/styles/paper/Alert.svelte.d.ts +18 -0
- package/dist/styles/paper/Avatar.svelte +60 -0
- package/dist/styles/paper/Avatar.svelte.d.ts +16 -0
- package/dist/styles/paper/AvatarGroup.svelte +17 -0
- package/dist/styles/paper/AvatarGroup.svelte.d.ts +8 -0
- package/dist/styles/paper/Badge.svelte +58 -0
- package/dist/styles/paper/Badge.svelte.d.ts +16 -0
- package/dist/styles/paper/Breadcrumb.svelte +49 -0
- package/dist/styles/paper/Breadcrumb.svelte.d.ts +14 -0
- package/dist/styles/paper/Button.svelte +96 -0
- package/dist/styles/paper/Button.svelte.d.ts +21 -0
- package/dist/styles/paper/CTASection.svelte +76 -0
- package/dist/styles/paper/CTASection.svelte.d.ts +18 -0
- package/dist/styles/paper/Calendar.svelte +202 -0
- package/dist/styles/paper/Calendar.svelte.d.ts +22 -0
- package/dist/styles/paper/Card.svelte +78 -0
- package/dist/styles/paper/Card.svelte.d.ts +21 -0
- package/dist/styles/paper/Checkbox.svelte +75 -0
- package/dist/styles/paper/Checkbox.svelte.d.ts +15 -0
- package/dist/styles/paper/CheckboxGroup.svelte +111 -0
- package/dist/styles/paper/CheckboxGroup.svelte.d.ts +30 -0
- package/dist/styles/paper/Combobox.svelte +266 -0
- package/dist/styles/paper/Combobox.svelte.d.ts +29 -0
- package/dist/styles/paper/CommandPalette.svelte +209 -0
- package/dist/styles/paper/CommandPalette.svelte.d.ts +32 -0
- package/dist/styles/paper/ConfirmDialog.svelte +97 -0
- package/dist/styles/paper/ConfirmDialog.svelte.d.ts +22 -0
- package/dist/styles/paper/ContextMenu.svelte +88 -0
- package/dist/styles/paper/ContextMenu.svelte.d.ts +15 -0
- package/dist/styles/paper/DatePicker.svelte +192 -0
- package/dist/styles/paper/DatePicker.svelte.d.ts +23 -0
- package/dist/styles/paper/Divider.svelte +30 -0
- package/dist/styles/paper/Divider.svelte.d.ts +10 -0
- package/dist/styles/paper/Drawer.svelte +165 -0
- package/dist/styles/paper/Drawer.svelte.d.ts +20 -0
- package/dist/styles/paper/Dropdown.svelte +94 -0
- package/dist/styles/paper/Dropdown.svelte.d.ts +23 -0
- package/dist/styles/paper/Dropzone.svelte +210 -0
- package/dist/styles/paper/Dropzone.svelte.d.ts +29 -0
- package/dist/styles/paper/EmptyState.svelte +71 -0
- package/dist/styles/paper/EmptyState.svelte.d.ts +18 -0
- package/dist/styles/paper/FeatureCard.svelte +58 -0
- package/dist/styles/paper/FeatureCard.svelte.d.ts +16 -0
- package/dist/styles/paper/FeatureGrid.svelte +62 -0
- package/dist/styles/paper/FeatureGrid.svelte.d.ts +16 -0
- package/dist/styles/paper/Field.svelte +42 -0
- package/dist/styles/paper/Field.svelte.d.ts +16 -0
- package/dist/styles/paper/Footer.svelte +91 -0
- package/dist/styles/paper/Footer.svelte.d.ts +25 -0
- package/dist/styles/paper/HeroSection.svelte +86 -0
- package/dist/styles/paper/HeroSection.svelte.d.ts +21 -0
- package/dist/styles/paper/Input.svelte +60 -0
- package/dist/styles/paper/Input.svelte.d.ts +18 -0
- package/dist/styles/paper/InputGroup.svelte +20 -0
- package/dist/styles/paper/InputGroup.svelte.d.ts +11 -0
- package/dist/styles/paper/Kbd.svelte +17 -0
- package/dist/styles/paper/Kbd.svelte.d.ts +8 -0
- package/dist/styles/paper/Label.svelte +16 -0
- package/dist/styles/paper/Label.svelte.d.ts +9 -0
- package/dist/styles/paper/Link.svelte +44 -0
- package/dist/styles/paper/Link.svelte.d.ts +16 -0
- package/dist/styles/paper/LocaleProvider.svelte +24 -0
- package/dist/styles/paper/LocaleProvider.svelte.d.ts +10 -0
- package/dist/styles/paper/LogoCloud.svelte +61 -0
- package/dist/styles/paper/LogoCloud.svelte.d.ts +19 -0
- package/dist/styles/paper/MenuItem.svelte +64 -0
- package/dist/styles/paper/MenuItem.svelte.d.ts +18 -0
- package/dist/styles/paper/MenuSeparator.svelte +22 -0
- package/dist/styles/paper/MenuSeparator.svelte.d.ts +8 -0
- package/dist/styles/paper/Modal.svelte +118 -0
- package/dist/styles/paper/Modal.svelte.d.ts +21 -0
- package/dist/styles/paper/MultiSelect.svelte +287 -0
- package/dist/styles/paper/MultiSelect.svelte.d.ts +31 -0
- package/dist/styles/paper/Navbar.svelte +201 -0
- package/dist/styles/paper/Navbar.svelte.d.ts +33 -0
- package/dist/styles/paper/NumberInput.svelte +96 -0
- package/dist/styles/paper/NumberInput.svelte.d.ts +15 -0
- package/dist/styles/paper/Pagination.svelte +83 -0
- package/dist/styles/paper/Pagination.svelte.d.ts +15 -0
- package/dist/styles/paper/PasswordInput.svelte +100 -0
- package/dist/styles/paper/PasswordInput.svelte.d.ts +12 -0
- package/dist/styles/paper/Popover.svelte +89 -0
- package/dist/styles/paper/Popover.svelte.d.ts +19 -0
- package/dist/styles/paper/PricingCard.svelte +108 -0
- package/dist/styles/paper/PricingCard.svelte.d.ts +25 -0
- package/dist/styles/paper/Progress.svelte +59 -0
- package/dist/styles/paper/Progress.svelte.d.ts +17 -0
- package/dist/styles/paper/Radio.svelte +55 -0
- package/dist/styles/paper/Radio.svelte.d.ts +15 -0
- package/dist/styles/paper/RadioGroup.svelte +95 -0
- package/dist/styles/paper/RadioGroup.svelte.d.ts +27 -0
- package/dist/styles/paper/SegmentedControl.svelte +88 -0
- package/dist/styles/paper/SegmentedControl.svelte.d.ts +25 -0
- package/dist/styles/paper/Select.svelte +61 -0
- package/dist/styles/paper/Select.svelte.d.ts +20 -0
- package/dist/styles/paper/Sidebar.svelte +206 -0
- package/dist/styles/paper/Sidebar.svelte.d.ts +36 -0
- package/dist/styles/paper/Skeleton.svelte +46 -0
- package/dist/styles/paper/Skeleton.svelte.d.ts +13 -0
- package/dist/styles/paper/Slider.svelte +80 -0
- package/dist/styles/paper/Slider.svelte.d.ts +19 -0
- package/dist/styles/paper/Spinner.svelte +34 -0
- package/dist/styles/paper/Spinner.svelte.d.ts +13 -0
- package/dist/styles/paper/Stat.svelte +51 -0
- package/dist/styles/paper/Stat.svelte.d.ts +16 -0
- package/dist/styles/paper/StatsBand.svelte +63 -0
- package/dist/styles/paper/StatsBand.svelte.d.ts +20 -0
- package/dist/styles/paper/Steps.svelte +141 -0
- package/dist/styles/paper/Steps.svelte.d.ts +24 -0
- package/dist/styles/paper/Switch.svelte +64 -0
- package/dist/styles/paper/Switch.svelte.d.ts +14 -0
- package/dist/styles/paper/Table.svelte +217 -0
- package/dist/styles/paper/Table.svelte.d.ts +66 -0
- package/dist/styles/paper/Tabs.svelte +102 -0
- package/dist/styles/paper/Tabs.svelte.d.ts +23 -0
- package/dist/styles/paper/Testimonial.svelte +64 -0
- package/dist/styles/paper/Testimonial.svelte.d.ts +19 -0
- package/dist/styles/paper/Textarea.svelte +54 -0
- package/dist/styles/paper/Textarea.svelte.d.ts +12 -0
- package/dist/styles/paper/ThemeToggle.svelte +130 -0
- package/dist/styles/paper/ThemeToggle.svelte.d.ts +16 -0
- package/dist/styles/paper/Toaster.svelte +132 -0
- package/dist/styles/paper/Toaster.svelte.d.ts +8 -0
- package/dist/styles/paper/Tooltip.svelte +33 -0
- package/dist/styles/paper/Tooltip.svelte.d.ts +12 -0
- package/dist/styles/paper/fonts.css +46 -0
- package/dist/styles/paper/index.d.ts +109 -0
- package/dist/styles/paper/index.js +83 -0
- package/dist/styles/paper/theme.css +222 -0
- package/package.json +531 -201
- package/registry.json +658 -339
- /package/dist/{actions → core/actions}/anchor.d.ts +0 -0
- /package/dist/{actions → core/actions}/anchor.js +0 -0
- /package/dist/{actions → core/actions}/dismissable.d.ts +0 -0
- /package/dist/{actions → core/actions}/dismissable.js +0 -0
- /package/dist/{date.d.ts → core/date.d.ts} +0 -0
- /package/dist/{date.js → core/date.js} +0 -0
- /package/dist/{locale.svelte.d.ts → core/locale.svelte.d.ts} +0 -0
- /package/dist/{locale.svelte.js → core/locale.svelte.js} +0 -0
- /package/dist/{toast.svelte.d.ts → core/toast.svelte.d.ts} +0 -0
- /package/dist/{toast.svelte.js → core/toast.svelte.js} +0 -0
- /package/dist/{tones.d.ts → core/tones.d.ts} +0 -0
- /package/dist/{tones.js → core/tones.js} +0 -0
- /package/dist/{components → styles/matte}/Accordion.svelte +0 -0
- /package/dist/{components → styles/matte}/Accordion.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/AvatarGroup.svelte +0 -0
- /package/dist/{components → styles/matte}/AvatarGroup.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/ContextMenu.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Divider.svelte +0 -0
- /package/dist/{components → styles/matte}/Divider.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Drawer.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Field.svelte +0 -0
- /package/dist/{components → styles/matte}/Field.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/InputGroup.svelte +0 -0
- /package/dist/{components → styles/matte}/InputGroup.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Kbd.svelte +0 -0
- /package/dist/{components → styles/matte}/Kbd.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Label.svelte +0 -0
- /package/dist/{components → styles/matte}/Label.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/MenuSeparator.svelte +0 -0
- /package/dist/{components → styles/matte}/MenuSeparator.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Modal.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Skeleton.svelte +0 -0
- /package/dist/{components → styles/matte}/Skeleton.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Toaster.svelte.d.ts +0 -0
- /package/dist/{components → styles/matte}/Tooltip.svelte +0 -0
- /package/dist/{components → styles/matte}/Tooltip.svelte.d.ts +0 -0
- /package/dist/{fonts.css → styles/matte/fonts.css} +0 -0
- /package/dist/{theme.css → styles/matte/theme.css} +0 -0
|
@@ -16,9 +16,11 @@
|
|
|
16
16
|
</script>
|
|
17
17
|
|
|
18
18
|
<script lang="ts">
|
|
19
|
-
import { focusTrap } from '
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
19
|
+
import { focusTrap } from '../../core/actions/dismissable.js';
|
|
20
|
+
import { syncDialog } from '../../core/dialog.svelte.js';
|
|
21
|
+
import { ListCursor, groupItems, matchQuery, revealIndex } from '../../core/list.svelte.js';
|
|
22
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
23
|
+
import { toneSoft, type Tone } from '../../core/tones.js';
|
|
22
24
|
import Kbd from './Kbd.svelte';
|
|
23
25
|
|
|
24
26
|
interface Props {
|
|
@@ -53,40 +55,29 @@
|
|
|
53
55
|
let inputEl: HTMLInputElement | null = $state(null);
|
|
54
56
|
let listEl: HTMLElement | null = $state(null);
|
|
55
57
|
let query = $state('');
|
|
56
|
-
let active = $state(0);
|
|
57
58
|
|
|
58
|
-
const matches = $derived
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`${item.label} ${item.description ?? ''} ${item.keywords ?? ''} ${item.group ?? ''}`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const groups = $derived.by(() => {
|
|
69
|
-
const out: [string, CommandItem[]][] = [];
|
|
70
|
-
for (const item of matches) {
|
|
71
|
-
const key = item.group ?? '';
|
|
72
|
-
const bucket = out.find(([name]) => name === key);
|
|
73
|
-
if (bucket) bucket[1].push(item);
|
|
74
|
-
else out.push([key, [item]]);
|
|
75
|
-
}
|
|
76
|
-
return out;
|
|
77
|
-
});
|
|
59
|
+
const matches = $derived(
|
|
60
|
+
matchQuery(
|
|
61
|
+
items,
|
|
62
|
+
query,
|
|
63
|
+
(item) => `${item.label} ${item.description ?? ''} ${item.keywords ?? ''} ${item.group ?? ''}`
|
|
64
|
+
)
|
|
65
|
+
);
|
|
78
66
|
|
|
67
|
+
const groups = $derived(groupItems(matches));
|
|
79
68
|
const flat = $derived(groups.flatMap(([, group]) => group));
|
|
80
69
|
|
|
70
|
+
const cursor = new ListCursor(() => flat);
|
|
71
|
+
const active = $derived(cursor.index);
|
|
72
|
+
|
|
81
73
|
$effect(() => {
|
|
82
74
|
if (!dialog) return;
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
const wasOpen = dialog.open;
|
|
76
|
+
syncDialog(dialog, open);
|
|
77
|
+
if (open && !wasOpen) {
|
|
85
78
|
query = '';
|
|
86
|
-
|
|
79
|
+
cursor.reset();
|
|
87
80
|
queueMicrotask(() => inputEl?.focus());
|
|
88
|
-
} else if (!open && dialog.open) {
|
|
89
|
-
dialog.close();
|
|
90
81
|
}
|
|
91
82
|
});
|
|
92
83
|
|
|
@@ -110,14 +101,8 @@
|
|
|
110
101
|
}
|
|
111
102
|
|
|
112
103
|
function move(step: number) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
for (let i = 0; i < flat.length; i++) {
|
|
116
|
-
next = (next + step + flat.length) % flat.length;
|
|
117
|
-
if (!flat[next].disabled) break;
|
|
118
|
-
}
|
|
119
|
-
active = next;
|
|
120
|
-
listEl?.querySelector(`[data-index="${next}"]`)?.scrollIntoView({ block: 'nearest' });
|
|
104
|
+
cursor.move(step);
|
|
105
|
+
revealIndex(listEl, cursor.index);
|
|
121
106
|
}
|
|
122
107
|
|
|
123
108
|
function onKeydown(event: KeyboardEvent) {
|
|
@@ -131,9 +116,9 @@
|
|
|
131
116
|
move(-1);
|
|
132
117
|
break;
|
|
133
118
|
case 'Enter':
|
|
134
|
-
if (
|
|
119
|
+
if (cursor.current) {
|
|
135
120
|
event.preventDefault();
|
|
136
|
-
run(
|
|
121
|
+
run(cursor.current);
|
|
137
122
|
}
|
|
138
123
|
break;
|
|
139
124
|
case 'Escape':
|
|
@@ -166,7 +151,7 @@
|
|
|
166
151
|
<input
|
|
167
152
|
bind:this={inputEl}
|
|
168
153
|
bind:value={query}
|
|
169
|
-
oninput={() => (
|
|
154
|
+
oninput={() => cursor.reset()}
|
|
170
155
|
type="text"
|
|
171
156
|
autocomplete="off"
|
|
172
157
|
aria-label={placeholder ?? t.current.commandPlaceholder}
|
|
@@ -203,7 +188,7 @@
|
|
|
203
188
|
aria-selected={index === active}
|
|
204
189
|
aria-disabled={item.disabled}
|
|
205
190
|
onclick={() => run(item)}
|
|
206
|
-
onpointermove={() => (
|
|
191
|
+
onpointermove={() => (cursor.index = index)}
|
|
207
192
|
class="flex cursor-pointer items-center gap-3 px-4 py-2.5 font-sans text-[14px] transition-colors duration-100
|
|
208
193
|
{item.disabled ? 'pointer-events-none opacity-40' : ''}
|
|
209
194
|
{index === active ? toneSoft[tone] : 'text-text-secondary'}"
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import Button from './Button.svelte';
|
|
4
4
|
import Modal from './Modal.svelte';
|
|
5
|
-
import { useLocale } from '
|
|
6
|
-
import { toneSoft, type Tone } from '
|
|
5
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
6
|
+
import { toneSoft, type Tone } from '../../core/tones.js';
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
9
9
|
open?: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
import { type Tone } from '
|
|
2
|
+
import { type Tone } from '../../core/tones.js';
|
|
3
3
|
interface Props {
|
|
4
4
|
open?: boolean;
|
|
5
5
|
title: string;
|
|
@@ -17,6 +17,6 @@ interface Props {
|
|
|
17
17
|
/** Extra content between the description and the buttons. */
|
|
18
18
|
children?: Snippet;
|
|
19
19
|
}
|
|
20
|
-
declare const ConfirmDialog: import("svelte").Component<Props, {}, "
|
|
20
|
+
declare const ConfirmDialog: import("svelte").Component<Props, {}, "open" | "loading">;
|
|
21
21
|
type ConfirmDialog = ReturnType<typeof ConfirmDialog>;
|
|
22
22
|
export default ConfirmDialog;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { anchored } from '
|
|
4
|
-
import { clickOutside, focusTrap, navigateList, portal } from '
|
|
5
|
-
import {
|
|
3
|
+
import { anchored } from '../../core/actions/anchor.js';
|
|
4
|
+
import { clickOutside, focusTrap, navigateList, portal } from '../../core/actions/dismissable.js';
|
|
5
|
+
import { menuItems } from '../../core/trigger.js';
|
|
6
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
6
7
|
|
|
7
8
|
interface Props {
|
|
8
9
|
/** The region that responds to a right-click. */
|
|
@@ -57,10 +58,7 @@
|
|
|
57
58
|
open = false;
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
-
navigateList(event, [
|
|
62
|
-
...menuEl.querySelectorAll<HTMLElement>('[role="menuitem"]:not([disabled])')
|
|
63
|
-
]);
|
|
61
|
+
navigateList(event, menuItems(menuEl));
|
|
64
62
|
}
|
|
65
63
|
</script>
|
|
66
64
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { anchored } from '
|
|
3
|
-
import { clickOutside, portal } from '
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { anchored } from '../../core/actions/anchor.js';
|
|
3
|
+
import { clickOutside, portal } from '../../core/actions/dismissable.js';
|
|
4
|
+
import { dateHint } from '../../core/calendar.js';
|
|
5
|
+
import { formatISO, parseFormatted } from '../../core/date.js';
|
|
6
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
7
|
+
import { toneFocusWithinBorder, type Tone } from '../../core/tones.js';
|
|
7
8
|
import Calendar from './Calendar.svelte';
|
|
8
9
|
|
|
9
10
|
interface Props {
|
|
@@ -53,12 +54,7 @@
|
|
|
53
54
|
|
|
54
55
|
/** While typing the field shows the raw text; otherwise the formatted value. */
|
|
55
56
|
const display = $derived(editing ? text : formatISO(value, t.current.dateFormat));
|
|
56
|
-
const hint = $derived(placeholder ??
|
|
57
|
-
|
|
58
|
-
function formatHint() {
|
|
59
|
-
const parts = { dmy: 'DD/MM/YYYY', mdy: 'MM/DD/YYYY', ymd: 'YYYY/MM/DD' };
|
|
60
|
-
return parts[t.current.dateFormat];
|
|
61
|
-
}
|
|
57
|
+
const hint = $derived(placeholder ?? dateHint(t.current.dateFormat));
|
|
62
58
|
|
|
63
59
|
function commit() {
|
|
64
60
|
editing = false;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLDialogAttributes } from 'svelte/elements';
|
|
4
|
-
import { useLocale } from '
|
|
4
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
5
|
+
import { isBackdropClick, syncDialog } from '../../core/dialog.svelte.js';
|
|
5
6
|
|
|
6
7
|
export type DrawerSide = 'left' | 'right' | 'top' | 'bottom';
|
|
7
8
|
export type DrawerSize = 'sm' | 'md' | 'lg' | 'full';
|
|
@@ -67,11 +68,7 @@
|
|
|
67
68
|
bottom: 'animate-[drawer-bottom_220ms_cubic-bezier(0.16,1,0.3,1)]'
|
|
68
69
|
};
|
|
69
70
|
|
|
70
|
-
$effect(() =>
|
|
71
|
-
if (!dialog) return;
|
|
72
|
-
if (open && !dialog.open) dialog.showModal();
|
|
73
|
-
else if (!open && dialog.open) dialog.close();
|
|
74
|
-
});
|
|
71
|
+
$effect(() => syncDialog(dialog, open));
|
|
75
72
|
|
|
76
73
|
function close() {
|
|
77
74
|
open = false;
|
|
@@ -83,7 +80,7 @@
|
|
|
83
80
|
bind:this={dialog}
|
|
84
81
|
onclose={close}
|
|
85
82
|
onclick={(event) => {
|
|
86
|
-
if (dismissible && event
|
|
83
|
+
if (dismissible && isBackdropClick(event, dialog)) close();
|
|
87
84
|
}}
|
|
88
85
|
oncancel={(event) => {
|
|
89
86
|
if (!dismissible) event.preventDefault();
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { anchored, type Placement } from '
|
|
4
|
-
import { clickOutside, focusTrap, navigateList, portal } from '
|
|
5
|
-
import {
|
|
3
|
+
import { anchored, type Placement } from '../../core/actions/anchor.js';
|
|
4
|
+
import { clickOutside, focusTrap, navigateList, portal } from '../../core/actions/dismissable.js';
|
|
5
|
+
import { describeTrigger, menuItems, popupTrigger } from '../../core/trigger.js';
|
|
6
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
6
7
|
|
|
7
8
|
interface Props {
|
|
8
9
|
/** The control that opens the menu — put a `Button` in here. */
|
|
@@ -41,34 +42,8 @@
|
|
|
41
42
|
let anchorEl: HTMLElement | null = $state(null);
|
|
42
43
|
let menuEl: HTMLElement | null = $state(null);
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* button: the ARIA state belongs on the real control, not on our span.
|
|
47
|
-
*/
|
|
48
|
-
function triggerBehaviour(node: HTMLElement) {
|
|
49
|
-
const toggle = () => (open = !open);
|
|
50
|
-
const onKeydown = (event: KeyboardEvent) => {
|
|
51
|
-
if (event.key === 'ArrowDown' && !open) {
|
|
52
|
-
event.preventDefault();
|
|
53
|
-
open = true;
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
node.addEventListener('click', toggle);
|
|
57
|
-
node.addEventListener('keydown', onKeydown);
|
|
58
|
-
return {
|
|
59
|
-
destroy() {
|
|
60
|
-
node.removeEventListener('click', toggle);
|
|
61
|
-
node.removeEventListener('keydown', onKeydown);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
$effect(() => {
|
|
67
|
-
const control = anchorEl?.querySelector('button, a, [role="button"]');
|
|
68
|
-
if (!control) return;
|
|
69
|
-
control.setAttribute('aria-haspopup', 'menu');
|
|
70
|
-
control.setAttribute('aria-expanded', String(open));
|
|
71
|
-
});
|
|
45
|
+
// The ARIA state goes on the consumer's own control, not on our wrapper.
|
|
46
|
+
$effect(() => describeTrigger(anchorEl, 'menu', open));
|
|
72
47
|
|
|
73
48
|
function onMenuKeydown(event: KeyboardEvent) {
|
|
74
49
|
if (event.key === 'Escape' || event.key === 'Tab') {
|
|
@@ -77,10 +52,7 @@
|
|
|
77
52
|
open = false;
|
|
78
53
|
return;
|
|
79
54
|
}
|
|
80
|
-
|
|
81
|
-
navigateList(event, [
|
|
82
|
-
...menuEl.querySelectorAll<HTMLElement>('[role="menuitem"]:not([disabled])')
|
|
83
|
-
]);
|
|
55
|
+
navigateList(event, menuItems(menuEl));
|
|
84
56
|
}
|
|
85
57
|
|
|
86
58
|
function onMenuClick(event: MouseEvent) {
|
|
@@ -89,7 +61,17 @@
|
|
|
89
61
|
}
|
|
90
62
|
</script>
|
|
91
63
|
|
|
92
|
-
<span
|
|
64
|
+
<span
|
|
65
|
+
bind:this={anchorEl}
|
|
66
|
+
use:popupTrigger={{
|
|
67
|
+
toggle: () => (open = !open),
|
|
68
|
+
open: () => (open = true),
|
|
69
|
+
close: () => (open = false),
|
|
70
|
+
arrowOpens: true,
|
|
71
|
+
isOpen: () => open
|
|
72
|
+
}}
|
|
73
|
+
class="inline-flex {triggerClass}"
|
|
74
|
+
>
|
|
93
75
|
{@render trigger()}
|
|
94
76
|
</span>
|
|
95
77
|
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { toneBorder, toneSoft, toneSurface, toneText, type Tone } from '
|
|
4
|
-
import { useLocale } from '
|
|
5
|
-
|
|
6
|
-
export interface RejectedFile {
|
|
7
|
-
file: File;
|
|
8
|
-
reason: 'type' | 'size' | 'count';
|
|
9
|
-
}
|
|
3
|
+
import { toneBorder, toneSoft, toneSurface, toneText, type Tone } from '../../core/tones.js';
|
|
4
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
5
|
+
import { formatSize as toReadableSize, sortFiles, type RejectedFile } from '../../core/files.js';
|
|
10
6
|
|
|
11
7
|
interface Props {
|
|
12
8
|
/** Bindable list of accepted files. */
|
|
@@ -67,46 +63,18 @@
|
|
|
67
63
|
return parts.join(' · ');
|
|
68
64
|
});
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
const units = t.current.byteUnits;
|
|
72
|
-
if (bytes < 1024) return `${bytes} ${units[0]}`;
|
|
73
|
-
let value = bytes / 1024;
|
|
74
|
-
let i = 1;
|
|
75
|
-
while (value >= 1024 && i < units.length - 1) {
|
|
76
|
-
value /= 1024;
|
|
77
|
-
i++;
|
|
78
|
-
}
|
|
79
|
-
return `${value.toFixed(Number.isInteger(value) || value >= 10 ? 0 : 1)} ${units[i]}`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function matchesAccept(file: File) {
|
|
83
|
-
if (!accept) return true;
|
|
84
|
-
return accept.split(',').some((raw) => {
|
|
85
|
-
const rule = raw.trim().toLowerCase();
|
|
86
|
-
if (!rule) return true;
|
|
87
|
-
if (rule.startsWith('.')) return file.name.toLowerCase().endsWith(rule);
|
|
88
|
-
if (rule.endsWith('/*')) return file.type.startsWith(rule.slice(0, -1));
|
|
89
|
-
return file.type.toLowerCase() === rule;
|
|
90
|
-
});
|
|
91
|
-
}
|
|
66
|
+
const formatSize = (bytes: number) => toReadableSize(bytes, t.current.byteUnits);
|
|
92
67
|
|
|
93
68
|
function add(incoming: FileList | File[] | null) {
|
|
94
69
|
if (!incoming || disabled) return;
|
|
95
70
|
|
|
96
|
-
const accepted:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
else if (room <= 0) bad.push({ file, reason: 'count' });
|
|
104
|
-
else {
|
|
105
|
-
accepted.push(file);
|
|
106
|
-
room--;
|
|
107
|
-
}
|
|
108
|
-
if (!multiple && accepted.length === 1) break;
|
|
109
|
-
}
|
|
71
|
+
const { accepted, rejected: bad } = sortFiles(incoming, {
|
|
72
|
+
accept,
|
|
73
|
+
maxSize,
|
|
74
|
+
maxFiles,
|
|
75
|
+
multiple,
|
|
76
|
+
held: files.length
|
|
77
|
+
});
|
|
110
78
|
|
|
111
79
|
rejected = bad;
|
|
112
80
|
if (bad.length) onreject?.(bad);
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
import { type Tone } from '
|
|
3
|
-
|
|
4
|
-
file: File;
|
|
5
|
-
reason: 'type' | 'size' | 'count';
|
|
6
|
-
}
|
|
2
|
+
import { type Tone } from '../../core/tones.js';
|
|
3
|
+
import { type RejectedFile } from '../../core/files.js';
|
|
7
4
|
interface Props {
|
|
8
5
|
/** Bindable list of accepted files. */
|
|
9
6
|
files?: File[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import { toneSoft, type Tone } from '
|
|
4
|
+
import { toneSoft, type Tone } from '../../core/tones.js';
|
|
5
5
|
|
|
6
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
7
|
title: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
import { type Tone } from '
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
4
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
5
5
|
title: string;
|
|
6
6
|
description?: string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { focusRing, toneHoverText, toneRing, toneSoft, type Tone } from '../../core/tones.js';
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
|
+
title: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
tone?: Tone;
|
|
10
|
+
/** Turns the whole card into a link. */
|
|
11
|
+
href?: string;
|
|
12
|
+
/** Glyph inside the tinted square. */
|
|
13
|
+
icon?: Snippet;
|
|
14
|
+
children?: Snippet;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
title,
|
|
19
|
+
description,
|
|
20
|
+
tone = 'brand',
|
|
21
|
+
href,
|
|
22
|
+
icon,
|
|
23
|
+
class: className = '',
|
|
24
|
+
children,
|
|
25
|
+
...rest
|
|
26
|
+
}: Props = $props();
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<svelte:element
|
|
30
|
+
this={href ? 'a' : 'div'}
|
|
31
|
+
{href}
|
|
32
|
+
class="group flex flex-col gap-3 bg-bg p-6 {href
|
|
33
|
+
? `transition-colors duration-150 ease-brand-out ${focusRing} ${toneRing[tone]}`
|
|
34
|
+
: ''} {className}"
|
|
35
|
+
{...rest}
|
|
36
|
+
>
|
|
37
|
+
{#if icon}
|
|
38
|
+
<span class="flex size-10 items-center justify-center {toneSoft[tone]}">
|
|
39
|
+
{@render icon()}
|
|
40
|
+
</span>
|
|
41
|
+
{/if}
|
|
42
|
+
|
|
43
|
+
<h3
|
|
44
|
+
class="font-heading text-base font-medium text-text {href
|
|
45
|
+
? `transition-colors duration-150 ${toneHoverText[tone]}`
|
|
46
|
+
: ''}"
|
|
47
|
+
>
|
|
48
|
+
{title}
|
|
49
|
+
</h3>
|
|
50
|
+
|
|
51
|
+
{#if description}
|
|
52
|
+
<p class="font-sans text-sm leading-relaxed text-text-secondary">{description}</p>
|
|
53
|
+
{/if}
|
|
54
|
+
|
|
55
|
+
{#if children}
|
|
56
|
+
{@render children()}
|
|
57
|
+
{/if}
|
|
58
|
+
</svelte:element>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
tone?: Tone;
|
|
8
|
+
/** Turns the whole card into a link. */
|
|
9
|
+
href?: string;
|
|
10
|
+
/** Glyph inside the tinted square. */
|
|
11
|
+
icon?: Snippet;
|
|
12
|
+
children?: Snippet;
|
|
13
|
+
}
|
|
14
|
+
declare const FeatureCard: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type FeatureCard = ReturnType<typeof FeatureCard>;
|
|
16
|
+
export default FeatureCard;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
export type FeatureColumns = 2 | 3 | 4;
|
|
6
|
+
|
|
7
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
8
|
+
eyebrow?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
columns?: FeatureColumns;
|
|
12
|
+
/** Hairline grid rather than free-standing cards. */
|
|
13
|
+
bordered?: boolean;
|
|
14
|
+
/** `FeatureCard`s, or anything else. */
|
|
15
|
+
children: Snippet;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
eyebrow,
|
|
20
|
+
title,
|
|
21
|
+
description,
|
|
22
|
+
columns = 3,
|
|
23
|
+
bordered = false,
|
|
24
|
+
class: className = '',
|
|
25
|
+
children,
|
|
26
|
+
...rest
|
|
27
|
+
}: Props = $props();
|
|
28
|
+
|
|
29
|
+
const cols: Record<FeatureColumns, string> = {
|
|
30
|
+
2: 'sm:grid-cols-2',
|
|
31
|
+
3: 'sm:grid-cols-2 lg:grid-cols-3',
|
|
32
|
+
4: 'sm:grid-cols-2 lg:grid-cols-4'
|
|
33
|
+
};
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<section class="w-full px-6 py-20 {className}" {...rest}>
|
|
37
|
+
<div class="mx-auto flex w-full max-w-6xl flex-col gap-12">
|
|
38
|
+
{#if eyebrow || title || description}
|
|
39
|
+
<div class="flex max-w-xl flex-col gap-3">
|
|
40
|
+
{#if eyebrow}
|
|
41
|
+
<span class="font-mono text-xs tracking-wide text-text-muted uppercase">{eyebrow}</span>
|
|
42
|
+
{/if}
|
|
43
|
+
{#if title}
|
|
44
|
+
<h2 class="font-heading text-3xl font-medium tracking-tight text-balance text-text">
|
|
45
|
+
{title}
|
|
46
|
+
</h2>
|
|
47
|
+
{/if}
|
|
48
|
+
{#if description}
|
|
49
|
+
<p class="font-sans leading-relaxed text-pretty text-text-secondary">{description}</p>
|
|
50
|
+
{/if}
|
|
51
|
+
</div>
|
|
52
|
+
{/if}
|
|
53
|
+
|
|
54
|
+
<div
|
|
55
|
+
class="grid {cols[columns]} {bordered
|
|
56
|
+
? 'gap-px border border-hairline bg-hairline'
|
|
57
|
+
: 'gap-10'}"
|
|
58
|
+
>
|
|
59
|
+
{@render children()}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</section>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
export type FeatureColumns = 2 | 3 | 4;
|
|
4
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
eyebrow?: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
columns?: FeatureColumns;
|
|
9
|
+
/** Hairline grid rather than free-standing cards. */
|
|
10
|
+
bordered?: boolean;
|
|
11
|
+
/** `FeatureCard`s, or anything else. */
|
|
12
|
+
children: Snippet;
|
|
13
|
+
}
|
|
14
|
+
declare const FeatureGrid: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type FeatureGrid = ReturnType<typeof FeatureGrid>;
|
|
16
|
+
export default FeatureGrid;
|
|
@@ -8,7 +8,7 @@ export interface FooterColumn {
|
|
|
8
8
|
links: FooterLink[];
|
|
9
9
|
}
|
|
10
10
|
import type { Snippet } from 'svelte';
|
|
11
|
-
import { type Tone } from '
|
|
11
|
+
import { type Tone } from '../../core/tones.js';
|
|
12
12
|
interface Props {
|
|
13
13
|
columns?: FooterColumn[];
|
|
14
14
|
/** Logo, wordmark and a line of copy on the left. */
|