@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
|
@@ -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
|
+
export type BadgeVariant = 'soft' | 'solid' | 'outline';
|
|
5
|
+
export type BadgeSize = 'sm' | 'md';
|
|
6
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
7
|
+
tone?: Tone;
|
|
8
|
+
variant?: BadgeVariant;
|
|
9
|
+
size?: BadgeSize;
|
|
10
|
+
/** Small filled circle before the label. */
|
|
11
|
+
dot?: boolean;
|
|
12
|
+
children: Snippet;
|
|
13
|
+
}
|
|
14
|
+
declare const Badge: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type Badge = ReturnType<typeof Badge>;
|
|
16
|
+
export default Badge;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { toneHoverText, type Tone } from '../../core/tones.js';
|
|
4
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
5
|
+
|
|
6
|
+
export interface BreadcrumbItem {
|
|
7
|
+
label: string;
|
|
8
|
+
href?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
12
|
+
items: BreadcrumbItem[];
|
|
13
|
+
separator?: string;
|
|
14
|
+
tone?: Tone;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let { items, separator = '/', tone = 'brand', class: className = '', ...rest }: Props = $props();
|
|
18
|
+
|
|
19
|
+
const t = useLocale();
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<nav aria-label={t.current.breadcrumb} class="font-sans text-sm {className}" {...rest}>
|
|
23
|
+
<ol class="flex flex-wrap items-center gap-1.5">
|
|
24
|
+
{#each items as item, i (item.label)}
|
|
25
|
+
<li class="flex items-center gap-1.5">
|
|
26
|
+
{#if i > 0}
|
|
27
|
+
<span class="text-hairline-strong select-none" aria-hidden="true">{separator}</span>
|
|
28
|
+
{/if}
|
|
29
|
+
{#if item.href && i < items.length - 1}
|
|
30
|
+
<a
|
|
31
|
+
href={item.href}
|
|
32
|
+
class="rounded px-1 py-0.5 text-text-muted transition-colors duration-150 ease-brand-out hover:bg-bg-inset {toneHoverText[
|
|
33
|
+
tone
|
|
34
|
+
]}"
|
|
35
|
+
>
|
|
36
|
+
{item.label}
|
|
37
|
+
</a>
|
|
38
|
+
{:else}
|
|
39
|
+
<span
|
|
40
|
+
class="px-1 py-0.5 font-medium text-text"
|
|
41
|
+
aria-current={i === items.length - 1 ? 'page' : undefined}
|
|
42
|
+
>
|
|
43
|
+
{item.label}
|
|
44
|
+
</span>
|
|
45
|
+
{/if}
|
|
46
|
+
</li>
|
|
47
|
+
{/each}
|
|
48
|
+
</ol>
|
|
49
|
+
</nav>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
import { type Tone } from '../../core/tones.js';
|
|
3
|
+
export interface BreadcrumbItem {
|
|
4
|
+
label: string;
|
|
5
|
+
href?: string;
|
|
6
|
+
}
|
|
7
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
8
|
+
items: BreadcrumbItem[];
|
|
9
|
+
separator?: string;
|
|
10
|
+
tone?: Tone;
|
|
11
|
+
}
|
|
12
|
+
declare const Breadcrumb: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type Breadcrumb = ReturnType<typeof Breadcrumb>;
|
|
14
|
+
export default Breadcrumb;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
+
import Spinner from './Spinner.svelte';
|
|
5
|
+
import {
|
|
6
|
+
focusRing,
|
|
7
|
+
toneBorderSoft,
|
|
8
|
+
toneRing,
|
|
9
|
+
toneSoft,
|
|
10
|
+
toneSoftHover,
|
|
11
|
+
toneSolid,
|
|
12
|
+
toneSolidHover,
|
|
13
|
+
toneText,
|
|
14
|
+
type Tone
|
|
15
|
+
} from '../../core/tones.js';
|
|
16
|
+
|
|
17
|
+
export type ButtonVariant = 'solid' | 'soft' | 'outline' | 'ghost' | 'link' | 'primary';
|
|
18
|
+
export type ButtonSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
19
|
+
|
|
20
|
+
interface Props extends HTMLButtonAttributes {
|
|
21
|
+
variant?: ButtonVariant;
|
|
22
|
+
tone?: Tone;
|
|
23
|
+
size?: ButtonSize;
|
|
24
|
+
/** Renders an `<a>` instead of a `<button>`. */
|
|
25
|
+
href?: string;
|
|
26
|
+
target?: string;
|
|
27
|
+
rel?: string;
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
/** Stretch to the container's full width. */
|
|
30
|
+
block?: boolean;
|
|
31
|
+
children: Snippet;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let {
|
|
35
|
+
variant = 'solid',
|
|
36
|
+
tone = 'brand',
|
|
37
|
+
size = 'md',
|
|
38
|
+
href,
|
|
39
|
+
loading = false,
|
|
40
|
+
block = false,
|
|
41
|
+
disabled = false,
|
|
42
|
+
type = 'button',
|
|
43
|
+
class: className = '',
|
|
44
|
+
children,
|
|
45
|
+
...rest
|
|
46
|
+
}: Props = $props();
|
|
47
|
+
|
|
48
|
+
const base =
|
|
49
|
+
'inline-flex items-center justify-center gap-2 rounded-md border font-sans font-medium whitespace-nowrap transition-colors duration-150 ease-brand-out disabled:opacity-50 disabled:pointer-events-none aria-disabled:opacity-50 aria-disabled:pointer-events-none';
|
|
50
|
+
|
|
51
|
+
const sizes: Record<ButtonSize, string> = {
|
|
52
|
+
sm: 'h-8 px-3 text-[13px]',
|
|
53
|
+
md: 'h-10 px-4 text-sm',
|
|
54
|
+
lg: 'h-11 px-5 text-[15px]',
|
|
55
|
+
xl: 'h-12 px-6 text-base'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const variantClass = $derived.by(() => {
|
|
59
|
+
switch (variant) {
|
|
60
|
+
case 'primary':
|
|
61
|
+
case 'solid':
|
|
62
|
+
return `border-transparent shadow-xs ${toneSolid[tone]} ${toneSolidHover[tone]}`;
|
|
63
|
+
case 'soft':
|
|
64
|
+
return `border-transparent ${toneSoft[tone]} ${toneSoftHover[tone]}`;
|
|
65
|
+
// Outline keeps its own colours on hover here — swapping to a solid
|
|
66
|
+
// fill is matte's move, and it fights paper's quieter surfaces.
|
|
67
|
+
case 'outline':
|
|
68
|
+
return `bg-bg shadow-xs ${toneText[tone]} ${toneBorderSoft[tone]} hover:bg-bg-alt`;
|
|
69
|
+
case 'ghost':
|
|
70
|
+
return `border-transparent bg-transparent ${toneText[tone]} ${toneSoftHover[tone]}`;
|
|
71
|
+
case 'link':
|
|
72
|
+
return `border-transparent ${toneText[tone]} h-auto p-0 text-sm underline-offset-4 hover:underline`;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const isLink = $derived(variant === 'link');
|
|
77
|
+
const inert = $derived(disabled || loading);
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<svelte:element
|
|
81
|
+
this={href ? 'a' : 'button'}
|
|
82
|
+
{href}
|
|
83
|
+
type={href ? undefined : type}
|
|
84
|
+
disabled={href ? undefined : inert}
|
|
85
|
+
aria-disabled={href && inert ? 'true' : undefined}
|
|
86
|
+
aria-busy={loading ? 'true' : undefined}
|
|
87
|
+
role={href ? 'button' : undefined}
|
|
88
|
+
class="{base} {focusRing} {toneRing[tone]} {variantClass} {isLink ? '' : sizes[size]}
|
|
89
|
+
{block ? 'w-full' : ''} {className}"
|
|
90
|
+
{...rest}
|
|
91
|
+
>
|
|
92
|
+
{#if loading}
|
|
93
|
+
<Spinner size={size === 'sm' ? 'xs' : 'sm'} label="" />
|
|
94
|
+
{/if}
|
|
95
|
+
{@render children()}
|
|
96
|
+
</svelte:element>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
|
+
export type ButtonVariant = 'solid' | 'soft' | 'outline' | 'ghost' | 'link' | 'primary';
|
|
5
|
+
export type ButtonSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
6
|
+
interface Props extends HTMLButtonAttributes {
|
|
7
|
+
variant?: ButtonVariant;
|
|
8
|
+
tone?: Tone;
|
|
9
|
+
size?: ButtonSize;
|
|
10
|
+
/** Renders an `<a>` instead of a `<button>`. */
|
|
11
|
+
href?: string;
|
|
12
|
+
target?: string;
|
|
13
|
+
rel?: string;
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
/** Stretch to the container's full width. */
|
|
16
|
+
block?: boolean;
|
|
17
|
+
children: Snippet;
|
|
18
|
+
}
|
|
19
|
+
declare const Button: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type Button = ReturnType<typeof Button>;
|
|
21
|
+
export default Button;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { toneBorderSoft, toneSolid, toneSurface, type Tone } from '../../core/tones.js';
|
|
5
|
+
|
|
6
|
+
export type CTAVariant = 'tinted' | 'solid' | 'outline';
|
|
7
|
+
|
|
8
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
9
|
+
title: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
tone?: Tone;
|
|
12
|
+
variant?: CTAVariant;
|
|
13
|
+
/** Side by side on wide screens instead of stacked and centred. */
|
|
14
|
+
inline?: boolean;
|
|
15
|
+
/** The buttons. */
|
|
16
|
+
actions?: Snippet;
|
|
17
|
+
children?: Snippet;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
title,
|
|
22
|
+
description,
|
|
23
|
+
tone = 'brand',
|
|
24
|
+
variant = 'tinted',
|
|
25
|
+
inline = false,
|
|
26
|
+
actions,
|
|
27
|
+
class: className = '',
|
|
28
|
+
children,
|
|
29
|
+
...rest
|
|
30
|
+
}: Props = $props();
|
|
31
|
+
|
|
32
|
+
const variants = $derived({
|
|
33
|
+
tinted: `${toneSurface[tone]} border ${toneBorderSoft[tone]}`,
|
|
34
|
+
solid: `${toneSolid[tone]} shadow-lg`,
|
|
35
|
+
outline: `bg-bg border ${toneBorderSoft[tone]} shadow-xs`
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const onSolid = $derived(variant === 'solid');
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<section class="w-full px-6 py-16 {className}" {...rest}>
|
|
42
|
+
<div
|
|
43
|
+
class="mx-auto flex w-full max-w-6xl gap-8 rounded-xl p-10 sm:p-14 {variants[variant]}
|
|
44
|
+
{inline
|
|
45
|
+
? 'flex-col lg:flex-row lg:items-center lg:justify-between'
|
|
46
|
+
: 'flex-col items-center text-center'}"
|
|
47
|
+
>
|
|
48
|
+
<div class="flex min-w-0 flex-col gap-3 {inline ? '' : 'items-center'}">
|
|
49
|
+
<h2
|
|
50
|
+
class="max-w-2xl font-heading text-3xl font-semibold tracking-tight text-balance {onSolid
|
|
51
|
+
? 'text-text-inverse'
|
|
52
|
+
: 'text-text'}"
|
|
53
|
+
>
|
|
54
|
+
{title}
|
|
55
|
+
</h2>
|
|
56
|
+
{#if description}
|
|
57
|
+
<p
|
|
58
|
+
class="max-w-xl font-sans leading-relaxed text-pretty {onSolid
|
|
59
|
+
? 'text-text-inverse/80'
|
|
60
|
+
: 'text-text-secondary'}"
|
|
61
|
+
>
|
|
62
|
+
{description}
|
|
63
|
+
</p>
|
|
64
|
+
{/if}
|
|
65
|
+
{#if children}
|
|
66
|
+
{@render children()}
|
|
67
|
+
{/if}
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
{#if actions}
|
|
71
|
+
<div class="flex shrink-0 flex-wrap items-center gap-3 {inline ? '' : 'justify-center'}">
|
|
72
|
+
{@render actions()}
|
|
73
|
+
</div>
|
|
74
|
+
{/if}
|
|
75
|
+
</div>
|
|
76
|
+
</section>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
|
+
export type CTAVariant = 'tinted' | 'solid' | 'outline';
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
6
|
+
title: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
tone?: Tone;
|
|
9
|
+
variant?: CTAVariant;
|
|
10
|
+
/** Side by side on wide screens instead of stacked and centred. */
|
|
11
|
+
inline?: boolean;
|
|
12
|
+
/** The buttons. */
|
|
13
|
+
actions?: Snippet;
|
|
14
|
+
children?: Snippet;
|
|
15
|
+
}
|
|
16
|
+
declare const CTASection: import("svelte").Component<Props, {}, "">;
|
|
17
|
+
type CTASection = ReturnType<typeof CTASection>;
|
|
18
|
+
export default CTASection;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
addMonths,
|
|
4
|
+
fromISO,
|
|
5
|
+
isOutOfRange,
|
|
6
|
+
isSameDay,
|
|
7
|
+
monthGrid,
|
|
8
|
+
monthLabel,
|
|
9
|
+
toISO,
|
|
10
|
+
today,
|
|
11
|
+
weekdayNames
|
|
12
|
+
} from '../../core/date.js';
|
|
13
|
+
import { calendarKeyMove } from '../../core/calendar.js';
|
|
14
|
+
import { useLocale } from '../../core/locale.svelte.js';
|
|
15
|
+
import {
|
|
16
|
+
focusRing,
|
|
17
|
+
toneFill,
|
|
18
|
+
toneRing,
|
|
19
|
+
toneSoft,
|
|
20
|
+
toneText,
|
|
21
|
+
type Tone
|
|
22
|
+
} from '../../core/tones.js';
|
|
23
|
+
|
|
24
|
+
interface Props {
|
|
25
|
+
/** Bindable `YYYY-MM-DD`, or `''` for nothing selected. */
|
|
26
|
+
value?: string;
|
|
27
|
+
/** Bindable `YYYY-MM-DD` inside the month on show. */
|
|
28
|
+
month?: string;
|
|
29
|
+
/** Inclusive bounds, `YYYY-MM-DD`. */
|
|
30
|
+
min?: string;
|
|
31
|
+
max?: string;
|
|
32
|
+
/** Return true to grey out a specific day — weekends, holidays. */
|
|
33
|
+
isDisabled?: (date: Date) => boolean;
|
|
34
|
+
/** 1 = Monday (default), 0 = Sunday. */
|
|
35
|
+
weekStart?: 0 | 1;
|
|
36
|
+
tone?: Tone;
|
|
37
|
+
/** Show the "Today" shortcut under the grid. */
|
|
38
|
+
showToday?: boolean;
|
|
39
|
+
onselect?: (value: string) => void;
|
|
40
|
+
class?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let {
|
|
44
|
+
value = $bindable(''),
|
|
45
|
+
month = $bindable(''),
|
|
46
|
+
min,
|
|
47
|
+
max,
|
|
48
|
+
isDisabled,
|
|
49
|
+
weekStart = 1,
|
|
50
|
+
tone = 'brand',
|
|
51
|
+
showToday = true,
|
|
52
|
+
onselect,
|
|
53
|
+
class: className = ''
|
|
54
|
+
}: Props = $props();
|
|
55
|
+
|
|
56
|
+
const t = useLocale();
|
|
57
|
+
|
|
58
|
+
const selected = $derived(fromISO(value));
|
|
59
|
+
const now = today();
|
|
60
|
+
|
|
61
|
+
let view = $state(fromISO(month) ?? fromISO(value) ?? today());
|
|
62
|
+
/** The day the arrow keys are on — not necessarily the selected one. */
|
|
63
|
+
let focused = $state(fromISO(value) ?? today());
|
|
64
|
+
let grid: HTMLElement | null = $state(null);
|
|
65
|
+
|
|
66
|
+
// Follow the bound `month`/`value` when the parent changes them.
|
|
67
|
+
$effect(() => {
|
|
68
|
+
const next = fromISO(month) ?? fromISO(value);
|
|
69
|
+
if (next && (next.getMonth() !== view.getMonth() || next.getFullYear() !== view.getFullYear()))
|
|
70
|
+
view = next;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const days = $derived(monthGrid(view, weekStart));
|
|
74
|
+
const weekdays = $derived(weekdayNames(t.current.dateLocale, weekStart));
|
|
75
|
+
|
|
76
|
+
function blocked(date: Date) {
|
|
77
|
+
return isOutOfRange(date, min, max) || (isDisabled?.(date) ?? false);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function show(next: Date) {
|
|
81
|
+
view = next;
|
|
82
|
+
month = toISO(new Date(next.getFullYear(), next.getMonth(), 1));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function pick(date: Date) {
|
|
86
|
+
if (blocked(date)) return;
|
|
87
|
+
value = toISO(date);
|
|
88
|
+
focused = date;
|
|
89
|
+
if (date.getMonth() !== view.getMonth()) show(date);
|
|
90
|
+
onselect?.(value);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function moveFocus(next: Date) {
|
|
94
|
+
focused = next;
|
|
95
|
+
if (next.getMonth() !== view.getMonth() || next.getFullYear() !== view.getFullYear())
|
|
96
|
+
show(next);
|
|
97
|
+
queueMicrotask(() => grid?.querySelector<HTMLElement>('[data-focused="true"]')?.focus());
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function onKeydown(event: KeyboardEvent) {
|
|
101
|
+
const next = calendarKeyMove(event.key, focused, weekStart, event.shiftKey);
|
|
102
|
+
if (next) {
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
moveFocus(next);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
pick(focused);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const arrow =
|
|
114
|
+
'inline-flex size-8 items-center justify-center rounded-md text-text-secondary transition-colors duration-150 hover:bg-bg-inset hover:text-text';
|
|
115
|
+
</script>
|
|
116
|
+
|
|
117
|
+
<div class="flex w-[18rem] flex-col gap-3 p-3 font-sans {className}">
|
|
118
|
+
<div class="flex items-center justify-between gap-2">
|
|
119
|
+
<button
|
|
120
|
+
type="button"
|
|
121
|
+
onclick={() => show(addMonths(view, -1))}
|
|
122
|
+
aria-label={t.current.previousMonth}
|
|
123
|
+
class="{arrow} {focusRing} {toneRing[tone]}"
|
|
124
|
+
>
|
|
125
|
+
<svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
126
|
+
<path d="m10 4-4 4 4 4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
|
|
127
|
+
</svg>
|
|
128
|
+
</button>
|
|
129
|
+
|
|
130
|
+
<span aria-live="polite" class="text-sm font-semibold text-text">
|
|
131
|
+
{monthLabel(view, t.current.dateLocale)}
|
|
132
|
+
</span>
|
|
133
|
+
|
|
134
|
+
<button
|
|
135
|
+
type="button"
|
|
136
|
+
onclick={() => show(addMonths(view, 1))}
|
|
137
|
+
aria-label={t.current.nextMonth}
|
|
138
|
+
class="{arrow} {focusRing} {toneRing[tone]}"
|
|
139
|
+
>
|
|
140
|
+
<svg class="size-4" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
141
|
+
<path d="m6 4 4 4-4 4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
|
|
142
|
+
</svg>
|
|
143
|
+
</button>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<div class="grid grid-cols-7 gap-0.5">
|
|
147
|
+
{#each weekdays as name, i (i)}
|
|
148
|
+
<span class="pb-1 text-center text-[11px] font-medium text-text-muted">{name}</span>
|
|
149
|
+
{/each}
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
<!-- Roving tabindex: the grid itself is never a tab stop, the focused day is. -->
|
|
153
|
+
<div
|
|
154
|
+
bind:this={grid}
|
|
155
|
+
role="grid"
|
|
156
|
+
tabindex="-1"
|
|
157
|
+
aria-label={t.current.selectDate}
|
|
158
|
+
onkeydown={onKeydown}
|
|
159
|
+
class="grid grid-cols-7 gap-0.5 focus:outline-none"
|
|
160
|
+
>
|
|
161
|
+
{#each days as day (toISO(day))}
|
|
162
|
+
{@const outside = day.getMonth() !== view.getMonth()}
|
|
163
|
+
{@const off = blocked(day)}
|
|
164
|
+
{@const isSelected = isSameDay(day, selected)}
|
|
165
|
+
{@const isFocused = isSameDay(day, focused)}
|
|
166
|
+
<button
|
|
167
|
+
type="button"
|
|
168
|
+
role="gridcell"
|
|
169
|
+
data-focused={isFocused}
|
|
170
|
+
tabindex={isFocused ? 0 : -1}
|
|
171
|
+
disabled={off}
|
|
172
|
+
aria-selected={isSelected}
|
|
173
|
+
aria-current={isSameDay(day, now) ? 'date' : undefined}
|
|
174
|
+
onclick={() => pick(day)}
|
|
175
|
+
class="flex h-9 items-center justify-center rounded-md text-[13px] tabular-nums transition-colors duration-100 disabled:pointer-events-none disabled:opacity-30 {focusRing} {toneRing[
|
|
176
|
+
tone
|
|
177
|
+
]}
|
|
178
|
+
{isSelected
|
|
179
|
+
? `${toneFill[tone]} font-semibold text-text-inverse`
|
|
180
|
+
: outside
|
|
181
|
+
? 'text-text-muted/60 hover:bg-bg-inset'
|
|
182
|
+
: 'text-text-secondary hover:bg-bg-inset hover:text-text'}
|
|
183
|
+
{!isSelected && isSameDay(day, now) ? `${toneSoft[tone]} font-semibold` : ''}"
|
|
184
|
+
>
|
|
185
|
+
{day.getDate()}
|
|
186
|
+
</button>
|
|
187
|
+
{/each}
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
{#if showToday}
|
|
191
|
+
<button
|
|
192
|
+
type="button"
|
|
193
|
+
onclick={() => pick(now)}
|
|
194
|
+
disabled={blocked(now)}
|
|
195
|
+
class="self-start rounded px-1 text-[13px] font-medium transition-colors duration-150 disabled:pointer-events-none disabled:opacity-40 {toneText[
|
|
196
|
+
tone
|
|
197
|
+
]} hover:underline hover:underline-offset-2 {focusRing} {toneRing[tone]}"
|
|
198
|
+
>
|
|
199
|
+
{t.current.today}
|
|
200
|
+
</button>
|
|
201
|
+
{/if}
|
|
202
|
+
</div>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Tone } from '../../core/tones.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Bindable `YYYY-MM-DD`, or `''` for nothing selected. */
|
|
4
|
+
value?: string;
|
|
5
|
+
/** Bindable `YYYY-MM-DD` inside the month on show. */
|
|
6
|
+
month?: string;
|
|
7
|
+
/** Inclusive bounds, `YYYY-MM-DD`. */
|
|
8
|
+
min?: string;
|
|
9
|
+
max?: string;
|
|
10
|
+
/** Return true to grey out a specific day — weekends, holidays. */
|
|
11
|
+
isDisabled?: (date: Date) => boolean;
|
|
12
|
+
/** 1 = Monday (default), 0 = Sunday. */
|
|
13
|
+
weekStart?: 0 | 1;
|
|
14
|
+
tone?: Tone;
|
|
15
|
+
/** Show the "Today" shortcut under the grid. */
|
|
16
|
+
showToday?: boolean;
|
|
17
|
+
onselect?: (value: string) => void;
|
|
18
|
+
class?: string;
|
|
19
|
+
}
|
|
20
|
+
declare const Calendar: import("svelte").Component<Props, {}, "month" | "value">;
|
|
21
|
+
type Calendar = ReturnType<typeof Calendar>;
|
|
22
|
+
export default Calendar;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { toneBorderLeft, toneHoverBorder, toneSurface, type Tone } from '../../core/tones.js';
|
|
5
|
+
|
|
6
|
+
export type CardVariant = 'outline' | 'filled' | 'tinted';
|
|
7
|
+
|
|
8
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
9
|
+
variant?: CardVariant;
|
|
10
|
+
tone?: Tone;
|
|
11
|
+
/** Draws a tone-coloured rule down the left edge. */
|
|
12
|
+
accent?: boolean;
|
|
13
|
+
/** Lifts the card on hover — use for clickable cards. */
|
|
14
|
+
interactive?: boolean;
|
|
15
|
+
padded?: boolean;
|
|
16
|
+
title?: string;
|
|
17
|
+
eyebrow?: string;
|
|
18
|
+
header?: Snippet;
|
|
19
|
+
footer?: Snippet;
|
|
20
|
+
children: Snippet;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
variant = 'outline',
|
|
25
|
+
tone = 'brand',
|
|
26
|
+
accent = false,
|
|
27
|
+
interactive = false,
|
|
28
|
+
padded = true,
|
|
29
|
+
title,
|
|
30
|
+
eyebrow,
|
|
31
|
+
header,
|
|
32
|
+
footer,
|
|
33
|
+
class: className = '',
|
|
34
|
+
children,
|
|
35
|
+
...rest
|
|
36
|
+
}: Props = $props();
|
|
37
|
+
|
|
38
|
+
const variants = $derived({
|
|
39
|
+
outline: 'border border-hairline bg-bg shadow-xs',
|
|
40
|
+
filled: 'border border-hairline bg-bg-alt',
|
|
41
|
+
tinted: `border border-transparent ${toneSurface[tone]}`
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<div
|
|
46
|
+
class="flex flex-col rounded-lg {variants[variant]}
|
|
47
|
+
{accent ? `border-l-4 ${toneBorderLeft[tone]}` : ''}
|
|
48
|
+
{interactive
|
|
49
|
+
? `transition-shadow duration-150 ease-brand-out hover:shadow-md ${toneHoverBorder[tone]}`
|
|
50
|
+
: ''}
|
|
51
|
+
{className}"
|
|
52
|
+
{...rest}
|
|
53
|
+
>
|
|
54
|
+
{#if header || title || eyebrow}
|
|
55
|
+
<div class="flex flex-col gap-1 {padded ? 'px-5 pt-5' : ''}">
|
|
56
|
+
{#if header}
|
|
57
|
+
{@render header()}
|
|
58
|
+
{:else}
|
|
59
|
+
{#if eyebrow}
|
|
60
|
+
<span class="font-sans text-xs font-semibold text-text-muted">{eyebrow}</span>
|
|
61
|
+
{/if}
|
|
62
|
+
{#if title}
|
|
63
|
+
<h3 class="font-heading text-base font-semibold text-text">{title}</h3>
|
|
64
|
+
{/if}
|
|
65
|
+
{/if}
|
|
66
|
+
</div>
|
|
67
|
+
{/if}
|
|
68
|
+
|
|
69
|
+
<div class="flex-1 {padded ? (header || title || eyebrow ? 'px-5 pt-3 pb-5' : 'p-5') : ''}">
|
|
70
|
+
{@render children()}
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
{#if footer}
|
|
74
|
+
<div class="rounded-b-lg border-t border-hairline bg-bg-alt {padded ? 'px-5 py-3.5' : ''}">
|
|
75
|
+
{@render footer()}
|
|
76
|
+
</div>
|
|
77
|
+
{/if}
|
|
78
|
+
</div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
|
+
export type CardVariant = 'outline' | 'filled' | 'tinted';
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
variant?: CardVariant;
|
|
7
|
+
tone?: Tone;
|
|
8
|
+
/** Draws a tone-coloured rule down the left edge. */
|
|
9
|
+
accent?: boolean;
|
|
10
|
+
/** Lifts the card on hover — use for clickable cards. */
|
|
11
|
+
interactive?: boolean;
|
|
12
|
+
padded?: boolean;
|
|
13
|
+
title?: string;
|
|
14
|
+
eyebrow?: string;
|
|
15
|
+
header?: Snippet;
|
|
16
|
+
footer?: Snippet;
|
|
17
|
+
children: Snippet;
|
|
18
|
+
}
|
|
19
|
+
declare const Card: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type Card = ReturnType<typeof Card>;
|
|
21
|
+
export default Card;
|