@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.
Files changed (240) hide show
  1. package/README.md +241 -56
  2. package/dist/canvas/VectorCanvas.svelte +89 -8
  3. package/dist/canvas/VectorCanvas.svelte.d.ts +19 -1
  4. package/dist/canvas/types.d.ts +1 -1
  5. package/dist/charts/types.d.ts +1 -1
  6. package/dist/citations/list-format.js +3 -1
  7. package/dist/data/ChatBubble.svelte +48 -0
  8. package/dist/data/ChatBubble.svelte.d.ts +33 -0
  9. package/dist/data/DescriptionList.svelte +9 -3
  10. package/dist/data/DescriptionList.svelte.d.ts +1 -1
  11. package/dist/data/DescriptionRow.svelte +6 -5
  12. package/dist/data/MessageThread.svelte +29 -0
  13. package/dist/data/MessageThread.svelte.d.ts +17 -0
  14. package/dist/data/Pagination.svelte +5 -5
  15. package/dist/data/Pagination.svelte.d.ts +8 -0
  16. package/dist/data/PaginationFooter.svelte +2 -1
  17. package/dist/data/PaginationFooter.svelte.d.ts +2 -0
  18. package/dist/data/Table.svelte +9 -3
  19. package/dist/data/description-context.d.ts +12 -6
  20. package/dist/data/description-context.js +6 -5
  21. package/dist/data/index.d.ts +2 -0
  22. package/dist/data/index.js +2 -0
  23. package/dist/data/table-types.d.ts +7 -0
  24. package/dist/feedback/Dialog.svelte +19 -49
  25. package/dist/feedback/Dialog.svelte.d.ts +0 -1
  26. package/dist/feedback/DialogFrame.svelte +64 -0
  27. package/dist/feedback/DialogFrame.svelte.d.ts +23 -0
  28. package/dist/feedback/Drawer.svelte +43 -0
  29. package/dist/feedback/Drawer.svelte.d.ts +43 -0
  30. package/dist/feedback/SegmentBar.svelte.d.ts +1 -0
  31. package/dist/feedback/StatTile.svelte.d.ts +1 -0
  32. package/dist/feedback/Steps.svelte +72 -0
  33. package/dist/feedback/Steps.svelte.d.ts +61 -0
  34. package/dist/feedback/Timeline.svelte.d.ts +3 -0
  35. package/dist/feedback/index.d.ts +3 -0
  36. package/dist/feedback/index.js +2 -0
  37. package/dist/feedback/sizes.d.ts +14 -0
  38. package/dist/feedback/sizes.js +28 -0
  39. package/dist/fields/Calendar.svelte +60 -0
  40. package/dist/fields/Calendar.svelte.d.ts +11 -0
  41. package/dist/fields/CalendarMonths.svelte +86 -0
  42. package/dist/fields/CalendarMonths.svelte.d.ts +30 -0
  43. package/dist/fields/Checkbox.svelte +1 -1
  44. package/dist/fields/Checkbox.svelte.d.ts +6 -0
  45. package/dist/fields/Combobox.svelte +61 -54
  46. package/dist/fields/Combobox.svelte.d.ts +38 -3
  47. package/dist/fields/DateField.svelte +37 -0
  48. package/dist/fields/DateField.svelte.d.ts +20 -0
  49. package/dist/fields/DateInput.svelte +1 -1
  50. package/dist/fields/DateInput.svelte.d.ts +6 -0
  51. package/dist/fields/DatePicker.svelte +47 -0
  52. package/dist/fields/DatePicker.svelte.d.ts +25 -0
  53. package/dist/fields/DateRangePicker.svelte +70 -0
  54. package/dist/fields/DateRangePicker.svelte.d.ts +43 -0
  55. package/dist/fields/Dropzone.svelte +232 -0
  56. package/dist/fields/Dropzone.svelte.d.ts +103 -0
  57. package/dist/fields/Fieldset.svelte +7 -2
  58. package/dist/fields/Fieldset.svelte.d.ts +3 -2
  59. package/dist/fields/FileInput.svelte +3 -2
  60. package/dist/fields/FileInput.svelte.d.ts +6 -0
  61. package/dist/fields/FormField.svelte +27 -3
  62. package/dist/fields/ImageInput.svelte.d.ts +6 -0
  63. package/dist/fields/MultiSelect.svelte +112 -0
  64. package/dist/fields/MultiSelect.svelte.d.ts +75 -0
  65. package/dist/fields/NumberField.svelte +190 -0
  66. package/dist/fields/NumberField.svelte.d.ts +76 -0
  67. package/dist/fields/PasswordInput.svelte +95 -0
  68. package/dist/fields/PasswordInput.svelte.d.ts +58 -0
  69. package/dist/fields/PickerPopover.svelte +47 -0
  70. package/dist/fields/PickerPopover.svelte.d.ts +16 -0
  71. package/dist/fields/PinInput.svelte +83 -0
  72. package/dist/fields/PinInput.svelte.d.ts +66 -0
  73. package/dist/fields/RadioGroup.svelte +3 -0
  74. package/dist/fields/RangeCalendar.svelte +51 -0
  75. package/dist/fields/RangeCalendar.svelte.d.ts +23 -0
  76. package/dist/fields/Rating.svelte +127 -0
  77. package/dist/fields/Rating.svelte.d.ts +86 -0
  78. package/dist/fields/SearchInput.svelte +2 -1
  79. package/dist/fields/SegmentGroup.svelte +91 -0
  80. package/dist/fields/SegmentGroup.svelte.d.ts +20 -0
  81. package/dist/fields/Select.svelte +1 -1
  82. package/dist/fields/Select.svelte.d.ts +6 -0
  83. package/dist/fields/Slider.svelte +194 -0
  84. package/dist/fields/Slider.svelte.d.ts +100 -0
  85. package/dist/fields/TagsInput.svelte +256 -0
  86. package/dist/fields/TagsInput.svelte.d.ts +102 -0
  87. package/dist/fields/TextInput.svelte +1 -1
  88. package/dist/fields/TextInput.svelte.d.ts +6 -0
  89. package/dist/fields/Textarea.svelte +1 -1
  90. package/dist/fields/Textarea.svelte.d.ts +6 -0
  91. package/dist/fields/TimeField.svelte +30 -0
  92. package/dist/fields/TimeField.svelte.d.ts +19 -0
  93. package/dist/fields/Toggle.svelte +1 -1
  94. package/dist/fields/Toggle.svelte.d.ts +6 -0
  95. package/dist/fields/VideoInput.svelte.d.ts +6 -0
  96. package/dist/fields/calendar-props.d.ts +119 -0
  97. package/dist/fields/calendar-props.js +51 -0
  98. package/dist/fields/dates.d.ts +28 -0
  99. package/dist/fields/dates.js +26 -0
  100. package/dist/fields/field-types.d.ts +29 -0
  101. package/dist/fields/field-types.js +32 -0
  102. package/dist/fields/file-validation.d.ts +30 -0
  103. package/dist/fields/file-validation.js +51 -0
  104. package/dist/fields/index.d.ts +9 -0
  105. package/dist/fields/index.js +8 -0
  106. package/dist/fields/latest-search.svelte.d.ts +38 -0
  107. package/dist/fields/latest-search.svelte.js +85 -0
  108. package/dist/fields/number-format.d.ts +52 -0
  109. package/dist/fields/number-format.js +89 -0
  110. package/dist/fields/segmented-field.d.ts +128 -0
  111. package/dist/fields/segmented-field.js +52 -0
  112. package/dist/fields/slider-keys.d.ts +21 -0
  113. package/dist/fields/slider-keys.js +37 -0
  114. package/dist/formatting/Countdown.svelte +110 -0
  115. package/dist/formatting/Countdown.svelte.d.ts +35 -0
  116. package/dist/formatting/Duration.svelte +18 -0
  117. package/dist/formatting/Duration.svelte.d.ts +20 -0
  118. package/dist/formatting/Highlight.svelte +4 -0
  119. package/dist/formatting/Highlight.svelte.d.ts +4 -0
  120. package/dist/formatting/duration.d.ts +44 -0
  121. package/dist/formatting/duration.js +125 -0
  122. package/dist/formatting/index.d.ts +3 -0
  123. package/dist/formatting/index.js +3 -0
  124. package/dist/forms/EntityForm.svelte +53 -45
  125. package/dist/forms/EntityForm.svelte.d.ts +12 -3
  126. package/dist/hotkeys/index.d.ts +5 -0
  127. package/dist/hotkeys/index.js +5 -0
  128. package/dist/hotkeys/match.js +12 -10
  129. package/dist/hotkeys/types.d.ts +4 -2
  130. package/dist/index.d.ts +2 -1
  131. package/dist/index.js +2 -1
  132. package/dist/infobox/Infobox.svelte +2 -2
  133. package/dist/infobox/Infobox.svelte.d.ts +7 -0
  134. package/dist/infobox/InfoboxHeader.svelte +15 -7
  135. package/dist/infobox/InfoboxHeader.svelte.d.ts +7 -0
  136. package/dist/infobox/types.d.ts +5 -5
  137. package/dist/layout/AppShell.svelte +50 -0
  138. package/dist/layout/AppShell.svelte.d.ts +28 -0
  139. package/dist/layout/Cluster.svelte +28 -0
  140. package/dist/layout/Cluster.svelte.d.ts +27 -0
  141. package/dist/layout/Fits.svelte +27 -0
  142. package/dist/layout/Fits.svelte.d.ts +13 -0
  143. package/dist/layout/Flow.svelte +46 -0
  144. package/dist/layout/Flow.svelte.d.ts +16 -0
  145. package/dist/layout/Grid.svelte +23 -0
  146. package/dist/layout/Grid.svelte.d.ts +26 -0
  147. package/dist/layout/HStack.svelte +12 -0
  148. package/dist/layout/HStack.svelte.d.ts +34 -0
  149. package/dist/layout/Hero.svelte +76 -0
  150. package/dist/layout/Hero.svelte.d.ts +36 -0
  151. package/dist/layout/Navbar.svelte +2 -2
  152. package/dist/layout/Sidebar.svelte +1 -1
  153. package/dist/layout/Spacer.svelte +12 -0
  154. package/dist/layout/Spacer.svelte.d.ts +6 -0
  155. package/dist/layout/VStack.svelte +12 -0
  156. package/dist/layout/VStack.svelte.d.ts +29 -0
  157. package/dist/layout/index.d.ts +9 -0
  158. package/dist/layout/index.js +9 -0
  159. package/dist/layout/space.d.ts +44 -0
  160. package/dist/layout/space.js +76 -0
  161. package/dist/search/types.d.ts +3 -0
  162. package/dist/seo/og-image.d.ts +4 -3
  163. package/dist/seo/og-image.js +4 -3
  164. package/dist/tips/tip-stack.d.ts +1 -0
  165. package/dist/tips/tip-store.svelte.d.ts +2 -1
  166. package/dist/ui/Accordion.svelte +75 -0
  167. package/dist/ui/Accordion.svelte.d.ts +50 -0
  168. package/dist/ui/AccordionItem.svelte +73 -0
  169. package/dist/ui/AccordionItem.svelte.d.ts +18 -0
  170. package/dist/ui/Button.svelte +3 -2
  171. package/dist/ui/ButtonGroup.svelte +24 -0
  172. package/dist/ui/ButtonGroup.svelte.d.ts +17 -0
  173. package/dist/ui/ContextMenu.svelte +75 -0
  174. package/dist/ui/ContextMenu.svelte.d.ts +25 -0
  175. package/dist/ui/Disclosure.svelte +7 -0
  176. package/dist/ui/Disclosure.svelte.d.ts +2 -2
  177. package/dist/ui/Divider.svelte +47 -0
  178. package/dist/ui/Divider.svelte.d.ts +28 -0
  179. package/dist/ui/DropdownMenu.svelte +44 -0
  180. package/dist/ui/DropdownMenu.svelte.d.ts +30 -0
  181. package/dist/ui/Menu.svelte +17 -47
  182. package/dist/ui/Menu.svelte.d.ts +3 -24
  183. package/dist/ui/MenuCheckboxItem.svelte +33 -0
  184. package/dist/ui/MenuCheckboxItem.svelte.d.ts +20 -0
  185. package/dist/ui/MenuItem.svelte +29 -31
  186. package/dist/ui/MenuItem.svelte.d.ts +2 -2
  187. package/dist/ui/MenuRadioGroup.svelte +25 -0
  188. package/dist/ui/MenuRadioGroup.svelte.d.ts +20 -0
  189. package/dist/ui/MenuRadioItem.svelte +20 -0
  190. package/dist/ui/MenuRadioItem.svelte.d.ts +15 -0
  191. package/dist/ui/MenuSeparator.svelte +12 -11
  192. package/dist/ui/MenuSub.svelte +24 -0
  193. package/dist/ui/MenuSub.svelte.d.ts +15 -0
  194. package/dist/ui/Spinner.svelte +41 -0
  195. package/dist/ui/Spinner.svelte.d.ts +35 -0
  196. package/dist/ui/Stack.svelte +36 -0
  197. package/dist/ui/Stack.svelte.d.ts +48 -0
  198. package/dist/ui/ToggleButton.svelte +58 -0
  199. package/dist/ui/ToggleButton.svelte.d.ts +45 -0
  200. package/dist/ui/ToggleGroup.svelte +142 -0
  201. package/dist/ui/ToggleGroup.svelte.d.ts +86 -0
  202. package/dist/ui/Toolbar.svelte +40 -0
  203. package/dist/ui/Toolbar.svelte.d.ts +20 -0
  204. package/dist/ui/ToolbarButton.svelte +29 -0
  205. package/dist/ui/ToolbarButton.svelte.d.ts +21 -0
  206. package/dist/ui/ToolbarLink.svelte +21 -0
  207. package/dist/ui/ToolbarLink.svelte.d.ts +12 -0
  208. package/dist/ui/ToolbarSeparator.svelte +22 -0
  209. package/dist/ui/ToolbarSeparator.svelte.d.ts +12 -0
  210. package/dist/ui/ToolbarToggleGroup.svelte +66 -0
  211. package/dist/ui/ToolbarToggleGroup.svelte.d.ts +52 -0
  212. package/dist/ui/accordion-context.d.ts +26 -0
  213. package/dist/ui/accordion-context.js +23 -0
  214. package/dist/ui/context-menu.d.ts +13 -0
  215. package/dist/ui/context-menu.js +13 -0
  216. package/dist/ui/index.d.ts +19 -0
  217. package/dist/ui/index.js +18 -0
  218. package/dist/ui/menu-context.d.ts +13 -15
  219. package/dist/ui/menu-context.js +14 -18
  220. package/dist/ui/menu-parts/CheckboxItemPart.svelte +26 -0
  221. package/dist/ui/menu-parts/CheckboxItemPart.svelte.d.ts +5 -0
  222. package/dist/ui/menu-parts/ItemPart.svelte +29 -0
  223. package/dist/ui/menu-parts/ItemPart.svelte.d.ts +5 -0
  224. package/dist/ui/menu-parts/RadioGroupPart.svelte +24 -0
  225. package/dist/ui/menu-parts/RadioGroupPart.svelte.d.ts +5 -0
  226. package/dist/ui/menu-parts/RadioItemPart.svelte +22 -0
  227. package/dist/ui/menu-parts/RadioItemPart.svelte.d.ts +5 -0
  228. package/dist/ui/menu-parts/SeparatorPart.svelte +16 -0
  229. package/dist/ui/menu-parts/SeparatorPart.svelte.d.ts +5 -0
  230. package/dist/ui/menu-parts/SubPart.svelte +28 -0
  231. package/dist/ui/menu-parts/SubPart.svelte.d.ts +5 -0
  232. package/dist/ui/menu-parts/menu-parts.d.ts +104 -0
  233. package/dist/ui/menu-parts/menu-parts.js +31 -0
  234. package/dist/ui/menu-parts/parts.d.ts +12 -0
  235. package/dist/ui/menu-parts/parts.js +27 -0
  236. package/dist/ui/toggle-classes.d.ts +39 -0
  237. package/dist/ui/toggle-classes.js +36 -0
  238. package/dist/ui/tones.d.ts +35 -0
  239. package/dist/ui/tones.js +90 -0
  240. package/package.json +34 -18
@@ -0,0 +1,50 @@
1
+ <!-- @component
2
+ The responsive app frame: the sidebar as a standing column from `lg` up, and in a navigation drawer below it.
3
+ -->
4
+ <!--
5
+ AppShell — the frame every app with a `Sidebar` rebuilt by hand. From
6
+ `lg` up the `sidebar` snippet is a plain column beside the content; below
7
+ `lg` it moves into a `Drawer` (`side="start"`) opened from a top bar's
8
+ menu button.
9
+
10
+ The persistent column is never inside a dialog. The sidebar renders in
11
+ two places, but the column is `display: none` below `lg` and the drawer
12
+ only exists while it is open (and only its trigger bar below `lg`), so
13
+ exactly one copy, and one `navigation` landmark, is in the accessibility
14
+ tree at any width.
15
+
16
+ Closing the drawer on navigation is the app's job, because a library
17
+ cannot import `$app/navigation`. Bind `navOpen` and reset it in
18
+ SvelteKit's `afterNavigate(() => (navOpen = false))`, as with
19
+ `Navbar`'s `menuOpen`.
20
+ -->
21
+ <script lang="ts">import { Menu as MenuIcon } from "@lucide/svelte";
22
+ import Drawer from "../feedback/Drawer.svelte";
23
+ import Button from "../ui/Button.svelte";
24
+ import VisuallyHidden from "../ui/VisuallyHidden.svelte";
25
+ let { sidebar, header, children, navOpen = $bindable(false), navLabel = "Menu", navTitle = "Navigation", class: className, ...rest } = $props();
26
+ </script>
27
+
28
+ <div {...rest} class={['min-h-svh lg:flex', className]}>
29
+ <div class="hidden shrink-0 lg:block">{@render sidebar()}</div>
30
+ <div class="min-w-0 flex-1">
31
+ <div class="lg:hidden">
32
+ <Drawer bind:open={navOpen} title={navTitle} hideTitle side="start" size="sm">
33
+ {#snippet trigger({ props })}
34
+ {#if header}
35
+ {@render header({ triggerProps: props })}
36
+ {:else}
37
+ <div class="border-base-300 bg-base-100 flex h-14 items-center border-b px-2">
38
+ <Button {...props} variant="ghost" class="btn-square">
39
+ <MenuIcon class="size-5" aria-hidden="true" />
40
+ <VisuallyHidden>{navLabel}</VisuallyHidden>
41
+ </Button>
42
+ </div>
43
+ {/if}
44
+ {/snippet}
45
+ {@render sidebar()}
46
+ </Drawer>
47
+ </div>
48
+ {@render children()}
49
+ </div>
50
+ </div>
@@ -0,0 +1,28 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
4
+ /** The sidebar, usually a `Sidebar`: a column from `lg` up, the drawer's body below. */
5
+ sidebar: Snippet<[]>;
6
+ /** The top bar below `lg`; spread `triggerProps` onto the menu button. Omitted, a bar with a menu button. */
7
+ header?: Snippet<[{
8
+ triggerProps: Record<string, unknown>;
9
+ }]> | undefined;
10
+ /** The page content. */
11
+ children: Snippet<[]>;
12
+ /** Whether the narrow-viewport drawer is open. Bindable. */
13
+ navOpen?: boolean | undefined;
14
+ /**
15
+ * Accessible name of the default menu button.
16
+ * @defaultValue `'Menu'`
17
+ */
18
+ navLabel?: string | undefined;
19
+ /**
20
+ * The drawer's accessible name.
21
+ * @defaultValue `'Navigation'`
22
+ */
23
+ navTitle?: string | undefined;
24
+ }
25
+ /** The responsive app frame: the sidebar as a standing column from `lg` up, and in a navigation drawer below it. */
26
+ declare const AppShell: import("svelte").Component<Props, {}, "navOpen">;
27
+ type AppShell = ReturnType<typeof AppShell>;
28
+ export default AppShell;
@@ -0,0 +1,28 @@
1
+ <!-- @component
2
+ Inline items that wrap onto new lines with a token gap: a row of tags or buttons.
3
+ -->
4
+ <!--
5
+ Cluster — "every-layout"'s Cluster, Compose's `FlowRow`: items in a row
6
+ that wraps, with the same gap between rows as between items. With
7
+ `as="ul"` / `"ol"` it is a list (`role="list"` restored; children `<li>`).
8
+ -->
9
+ <script lang="ts">import { alignClass, gapClass, justifyClass } from "./space.js";
10
+ let { gap = "sm", align = "center", justify, as = "div", children, class: className, ...rest } = $props();
11
+ const list = $derived(as === "ul" || as === "ol");
12
+ </script>
13
+
14
+ <svelte:element
15
+ this={as}
16
+ {...rest}
17
+ role={list ? 'list' : rest.role}
18
+ class={[
19
+ 'flex flex-wrap',
20
+ gapClass[gap],
21
+ alignClass[align],
22
+ justify !== undefined && justifyClass[justify],
23
+ list && 'list-none',
24
+ className,
25
+ ]}
26
+ >
27
+ {@render children()}
28
+ </svelte:element>
@@ -0,0 +1,27 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { type FlowAlign, type FlowElement, type FlowJustify, type Gap } from './space.ts';
4
+ interface Props extends HTMLAttributes<HTMLElement> {
5
+ /**
6
+ * Space between items and between rows.
7
+ * @defaultValue `'sm'`
8
+ */
9
+ gap?: Gap | undefined;
10
+ /**
11
+ * Cross-axis alignment.
12
+ * @defaultValue `'center'`
13
+ */
14
+ align?: FlowAlign | undefined;
15
+ /** Main-axis distribution. */
16
+ justify?: FlowJustify | undefined;
17
+ /**
18
+ * The element. With `'ul'` / `'ol'`, children must be `<li>`s.
19
+ * @defaultValue `'div'`
20
+ */
21
+ as?: FlowElement | undefined;
22
+ children: Snippet<[]>;
23
+ }
24
+ /** Inline items that wrap onto new lines with a token gap: a row of tags or buttons. */
25
+ declare const Cluster: import("svelte").Component<Props, {}, "">;
26
+ type Cluster = ReturnType<typeof Cluster>;
27
+ export default Cluster;
@@ -0,0 +1,27 @@
1
+ <!-- @component
2
+ Shows the first of several layouts that fits its container, switching at declared container widths (CSS container queries, no JavaScript).
3
+ -->
4
+ <!--
5
+ Fits — the model is SwiftUI's `ViewThatFits`: "the horizontal button row
6
+ if it fits, else the stacked one, else a menu". CSS cannot measure
7
+ content's intrinsic width, so, unlike SwiftUI, it switches at declared
8
+ container widths: `breakpoints[i]` is the width below which `layouts[i]`
9
+ stops fitting. It is an `@container`, so the switch follows the space the
10
+ component actually has, not the viewport.
11
+
12
+ A JavaScript-measuring mode (render all, measure, hide) was considered and
13
+ left out: it shifts layout after first paint and cannot agree with
14
+ server-rendered HTML.
15
+
16
+ Every layout is rendered; all but the active one are `display: none`, so
17
+ assistive technology meets exactly one copy of each control at any width.
18
+ -->
19
+ <script lang="ts">import { fitsLayoutClass } from "./space.js";
20
+ let { layouts, breakpoints, class: className, ...rest } = $props();
21
+ </script>
22
+
23
+ <div {...rest} class={['@container', className]}>
24
+ {#each layouts as layout, index (index)}
25
+ <div class={fitsLayoutClass(index, layouts.length, breakpoints)}>{@render layout()}</div>
26
+ {/each}
27
+ </div>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { type FitsBreakpoint } from './space.ts';
4
+ interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
5
+ /** Layouts in order of preference, widest first. */
6
+ layouts: readonly Snippet<[]>[];
7
+ /** Container width below which each layout stops fitting; one fewer than `layouts`, descending. */
8
+ breakpoints: readonly FitsBreakpoint[];
9
+ }
10
+ /** Shows the first of several layouts that fits its container, switching at declared container widths (CSS container queries, no JavaScript). */
11
+ declare const Fits: import("svelte").Component<Props, {}, "">;
12
+ type Fits = ReturnType<typeof Fits>;
13
+ export default Fits;
@@ -0,0 +1,46 @@
1
+ <!-- @component
2
+ The flex flow `VStack` and `HStack` share; internal, not exported.
3
+ -->
4
+ <!--
5
+ Flow — one template for both stacks, so their tokens, list semantics and
6
+ dividers cannot drift. No `reverse` option, deliberately: a visual order
7
+ that contradicts the DOM order breaks WCAG 1.3.2 (meaningful sequence).
8
+
9
+ `as="ul"` / `"ol"` adds `role="list"`: Safari drops list semantics from a
10
+ list styled `list-style: none`. Its children must be `<li>`s. `divider`
11
+ draws a rule between children (Tailwind's `divide-*`, on the borders
12
+ between siblings, never around them); it is decorative, like a
13
+ `Divider` with `decorative`, and adds nothing to the accessibility tree.
14
+ -->
15
+ <script lang="ts">import { alignClass, gapClass, justifyClass } from "./space.js";
16
+ let { direction, gap = "md", align, justify, divider = false, as = "div", children, class: className, ...rest } = $props();
17
+ const directionClass = {
18
+ vertical: "flex-col",
19
+ horizontal: "flex-row",
20
+ responsive: "flex-col sm:flex-row"
21
+ };
22
+ const dividerClass = {
23
+ vertical: "divide-base-300 divide-y",
24
+ horizontal: "divide-base-300 divide-x",
25
+ responsive: "divide-base-300 divide-y sm:divide-x sm:divide-y-0"
26
+ };
27
+ const list = $derived(as === "ul" || as === "ol");
28
+ </script>
29
+
30
+ <svelte:element
31
+ this={as}
32
+ {...rest}
33
+ role={list ? 'list' : rest.role}
34
+ class={[
35
+ 'flex',
36
+ directionClass[direction],
37
+ gapClass[gap],
38
+ align !== undefined && alignClass[align],
39
+ justify !== undefined && justifyClass[justify],
40
+ divider && dividerClass[direction],
41
+ list && 'list-none',
42
+ className,
43
+ ]}
44
+ >
45
+ {@render children()}
46
+ </svelte:element>
@@ -0,0 +1,16 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { type FlowAlign, type FlowElement, type FlowJustify, type Gap } from './space.ts';
4
+ interface Props extends HTMLAttributes<HTMLElement> {
5
+ direction: 'vertical' | 'horizontal' | 'responsive';
6
+ gap?: Gap | undefined;
7
+ align?: FlowAlign | undefined;
8
+ justify?: FlowJustify | undefined;
9
+ divider?: boolean | undefined;
10
+ as?: FlowElement | undefined;
11
+ children: Snippet<[]>;
12
+ }
13
+ /** The flex flow `VStack` and `HStack` share; internal, not exported. */
14
+ declare const Flow: import("svelte").Component<Props, {}, "">;
15
+ type Flow = ReturnType<typeof Flow>;
16
+ export default Flow;
@@ -0,0 +1,23 @@
1
+ <!-- @component
2
+ A responsive grid sized by the narrowest an item may get, not by breakpoints.
3
+ -->
4
+ <!--
5
+ Grid — `repeat(auto-fill, minmax(<minItem>, 1fr))` (SwiftUI
6
+ `LazyVGrid(.adaptive(minimum:))`, Chakra `minChildWidth`): as many columns
7
+ as fit items at least `minItem` wide, so a card grid reflows by the space
8
+ it actually has, inside a sidebar or out. With `as="ul"` / `"ol"` it is a
9
+ list (`role="list"` restored; children `<li>`).
10
+ -->
11
+ <script lang="ts">import { gapClass, minItemClass } from "./space.js";
12
+ let { minItem = "md", gap = "md", as = "div", children, class: className, ...rest } = $props();
13
+ const list = $derived(as === "ul" || as === "ol");
14
+ </script>
15
+
16
+ <svelte:element
17
+ this={as}
18
+ {...rest}
19
+ role={list ? 'list' : rest.role}
20
+ class={['grid', minItemClass[minItem], gapClass[gap], list && 'list-none', className]}
21
+ >
22
+ {@render children()}
23
+ </svelte:element>
@@ -0,0 +1,26 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { type FlowElement, type Gap, type MinItem } from './space.ts';
4
+ interface Props extends HTMLAttributes<HTMLElement> {
5
+ /**
6
+ * The narrowest an item gets before the grid drops a column: `xs` 10rem,
7
+ * `sm` 12rem, `md` 16rem, `lg` 20rem.
8
+ * @defaultValue `'md'`
9
+ */
10
+ minItem?: MinItem | undefined;
11
+ /**
12
+ * Space between items.
13
+ * @defaultValue `'md'`
14
+ */
15
+ gap?: Gap | undefined;
16
+ /**
17
+ * The element. With `'ul'` / `'ol'`, children must be `<li>`s.
18
+ * @defaultValue `'div'`
19
+ */
20
+ as?: FlowElement | undefined;
21
+ children: Snippet<[]>;
22
+ }
23
+ /** A responsive grid sized by the narrowest an item may get, not by breakpoints. */
24
+ declare const Grid: import("svelte").Component<Props, {}, "">;
25
+ type Grid = ReturnType<typeof Grid>;
26
+ export default Grid;
@@ -0,0 +1,12 @@
1
+ <!-- @component
2
+ A horizontal stack: children side by side, on the spacing scale; optionally a column below `sm`.
3
+ -->
4
+ <!--
5
+ HStack — children in a row with a token gap (SwiftUI `HStack`, Compose `Row`). With `responsive`, a column on a narrow screen and a row from `sm` up. Tokens for gap and alignment come from `space.ts`, the
6
+ library's spacing scale. See `Flow` for the list and divider rules.
7
+ -->
8
+ <script lang="ts">import Flow from "./Flow.svelte";
9
+ let { responsive = false, ...props } = $props();
10
+ </script>
11
+
12
+ <Flow direction={responsive ? 'responsive' : 'horizontal'} {...props} />
@@ -0,0 +1,34 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { FlowAlign, FlowElement, FlowJustify, Gap } from './space.ts';
4
+ interface Props extends HTMLAttributes<HTMLElement> {
5
+ /**
6
+ * Stack vertically below the `sm` breakpoint.
7
+ * @defaultValue `false`
8
+ */
9
+ responsive?: boolean | undefined;
10
+ /**
11
+ * Space between children.
12
+ * @defaultValue `'md'`
13
+ */
14
+ gap?: Gap | undefined;
15
+ /** Cross-axis alignment. */
16
+ align?: FlowAlign | undefined;
17
+ /** Main-axis distribution. */
18
+ justify?: FlowJustify | undefined;
19
+ /**
20
+ * A decorative rule between children (never around them).
21
+ * @defaultValue `false`
22
+ */
23
+ divider?: boolean | undefined;
24
+ /**
25
+ * The element. With `'ul'` / `'ol'`, children must be `<li>`s.
26
+ * @defaultValue `'div'`
27
+ */
28
+ as?: FlowElement | undefined;
29
+ children: Snippet<[]>;
30
+ }
31
+ /** A horizontal stack: children side by side, on the spacing scale; optionally a column below `sm`. */
32
+ declare const HStack: import("svelte").Component<Props, {}, "">;
33
+ type HStack = ReturnType<typeof HStack>;
34
+ export default HStack;
@@ -0,0 +1,76 @@
1
+ <!-- @component
2
+ The large introductory block at the top of a landing or "about" page: a headline, supporting copy, calls to action, and an optional figure or background image, in daisyUI's `hero` styles.
3
+ -->
4
+ <!--
5
+ Hero — daisyUI's `hero` as a component: the top of a landing, marketing or
6
+ "about" page, where `PageHeader` is the top of an app page. It takes
7
+ arbitrary `children` rather than facts, which is why it is not a
8
+ `PageHeader` variant.
9
+
10
+ ARIA contract: the root is a `<section>` `aria-labelledby` its heading, so
11
+ it is a named region in the landmark list. The headline is a real heading
12
+ at `headingLevel`, `1` by default because a hero is normally the page's
13
+ title — a page with a `Hero` should not also render a `PageHeader` `<h1>`.
14
+ `actions` is a `role="group"` named by `actionsLabel`.
15
+
16
+ `backgroundImage` is decorative by definition, so it is a CSS
17
+ `background-image`, not an `<img>`: nothing enters the accessibility tree.
18
+ The copy over it sits on `hero-overlay` in `text-neutral-content`, so the
19
+ text keeps its contrast whatever the photo (WCAG 1.4.3). An image that
20
+ carries meaning belongs in `figure`, with alt text.
21
+ -->
22
+ <script lang="ts">let { title, headingLevel = 1, description, actions, actionsLabel = "Actions", figure, align, backgroundImage, children, class: className, style, ...rest } = $props();
23
+ const uid = $props.id();
24
+ const headingId = `${uid}-heading`;
25
+ const centred = $derived((align ?? (figure === undefined ? "center" : "start")) === "center");
26
+ const overlaid = $derived(backgroundImage !== undefined);
27
+ // `JSON.stringify` quotes the URL, so a value with parentheses or spaces
28
+ // cannot break out of `url(...)`.
29
+ const background = $derived(backgroundImage === undefined ? undefined : `background-image: url(${JSON.stringify(backgroundImage)});`);
30
+ export {};
31
+ </script>
32
+
33
+ {#snippet text(value: string | Snippet<[]>)}
34
+ {#if typeof value === 'string'}{value}{:else}{@render value()}{/if}
35
+ {/snippet}
36
+
37
+ <section
38
+ {...rest}
39
+ aria-labelledby={headingId}
40
+ style={[background, style].filter(Boolean).join(' ') || undefined}
41
+ class={['hero min-h-[50vh]', overlaid ? 'bg-cover bg-center' : 'bg-base-200', className]}
42
+ >
43
+ {#if overlaid}
44
+ <div class="hero-overlay bg-neutral/60"></div>
45
+ {/if}
46
+ <div
47
+ class={[
48
+ 'hero-content gap-8',
49
+ figure !== undefined && 'flex-col lg:flex-row',
50
+ centred && 'text-center',
51
+ overlaid && 'text-neutral-content',
52
+ ]}
53
+ >
54
+ <div class={['max-w-2xl space-y-5', centred && 'mx-auto']}>
55
+ <svelte:element
56
+ this={`h${headingLevel}`}
57
+ id={headingId}
58
+ class="text-4xl font-bold tracking-tight text-balance sm:text-5xl"
59
+ >
60
+ {@render text(title)}
61
+ </svelte:element>
62
+ {#if description !== undefined}
63
+ <p class={['text-lg leading-8', !overlaid && 'text-base-content/80']}>{@render text(description)}</p>
64
+ {/if}
65
+ {#if actions}
66
+ <div role="group" aria-label={actionsLabel} class={['flex flex-wrap gap-3', centred && 'justify-center']}>
67
+ {@render actions()}
68
+ </div>
69
+ {/if}
70
+ {#if children}<div>{@render children()}</div>{/if}
71
+ </div>
72
+ {#if figure}
73
+ <div class="w-full max-w-md shrink-0">{@render figure()}</div>
74
+ {/if}
75
+ </div>
76
+ </section>
@@ -0,0 +1,36 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { HeadingLevel } from '../ui/tones.ts';
4
+ interface Props extends Omit<HTMLAttributes<HTMLElement>, 'title' | 'children'> {
5
+ /** The headline: text, or a snippet for richer markup. */
6
+ title: string | Snippet<[]>;
7
+ /**
8
+ * The headline's level.
9
+ * @defaultValue `1`
10
+ */
11
+ headingLevel?: HeadingLevel | undefined;
12
+ /** Supporting copy under the headline. */
13
+ description?: string | Snippet<[]> | undefined;
14
+ /** The call-to-action row (`LinkButton`s), a group named by `actionsLabel`. */
15
+ actions?: Snippet<[]> | undefined;
16
+ /**
17
+ * Accessible name of the `actions` group.
18
+ * @defaultValue `'Actions'`
19
+ */
20
+ actionsLabel?: string | undefined;
21
+ /** A figure beside the copy; stacks under it on a phone. */
22
+ figure?: Snippet<[]> | undefined;
23
+ /**
24
+ * Where the copy aligns.
25
+ * @defaultValue `'start'` with a `figure`, `'center'` without
26
+ */
27
+ align?: 'start' | 'center' | undefined;
28
+ /** A decorative background image URL; the copy then sits on `hero-overlay` for contrast. */
29
+ backgroundImage?: string | undefined;
30
+ /** Extra content under the actions. */
31
+ children?: Snippet<[]> | undefined;
32
+ }
33
+ /** The large introductory block at the top of a landing or "about" page: a headline, supporting copy, calls to action, and an optional figure or background image, in daisyUI's `hero` styles. */
34
+ declare const Hero: import("svelte").Component<Props, {}, "">;
35
+ type Hero = ReturnType<typeof Hero>;
36
+ export default Hero;
@@ -7,8 +7,8 @@ The site banner: brand, primary links and account controls, with a disclosure fo
7
7
  not fit.
8
8
 
9
9
  The three regions are snippets (`start` / `center` / `end`) because the
10
- content is the app's — its brand mark, its search form, its `Menu
11
- mode="dropdown"` account menu. What this owns is the structure: the banner
10
+ content is the app's — its brand mark, its search form, its `DropdownMenu`
11
+ account menu. What this owns is the structure: the banner
12
12
  landmark, the named navigation inside it, the responsive bar, and the
13
13
  toggle.
14
14
 
@@ -6,7 +6,7 @@ The app shell’s navigation column: a brand mark, the primary links and an acco
6
6
  top, the primary links in the middle, an account block at the bottom.
7
7
 
8
8
  A thin composition and nothing more. The links themselves are `MenuItem`s
9
- inside a `Menu mode="nav"`, which already owns the whole navigation
9
+ inside a `Menu`, which already owns the whole navigation
10
10
  contract — the `<nav aria-label>` landmark, the `<ul class="menu">`, and
11
11
  `aria-current="page"` on the item the reader is on. This adds only what a
12
12
  sidebar has and a menu does not.
@@ -0,0 +1,12 @@
1
+ <!-- @component
2
+ Flexible space inside a `VStack` / `HStack`: pushes what follows to the far end.
3
+ -->
4
+ <!--
5
+ Spacer — SwiftUI's `Spacer()`, Compose's `Spacer(Modifier.weight(1f))`: an
6
+ empty `flex-1` element. It carries nothing, so it is `aria-hidden`.
7
+ -->
8
+ <script lang="ts">let { class: className, ...rest } = $props();
9
+ export {};
10
+ </script>
11
+
12
+ <div {...rest} aria-hidden="true" class={['flex-1', className]}></div>
@@ -0,0 +1,6 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
3
+ /** Flexible space inside a `VStack` / `HStack`: pushes what follows to the far end. */
4
+ declare const Spacer: import("svelte").Component<Props, {}, "">;
5
+ type Spacer = ReturnType<typeof Spacer>;
6
+ export default Spacer;
@@ -0,0 +1,12 @@
1
+ <!-- @component
2
+ A vertical stack: children one above the next, on the spacing scale.
3
+ -->
4
+ <!--
5
+ VStack — children in a column with a token gap (SwiftUI `VStack`, Compose `Column`). Tokens for gap and alignment come from `space.ts`, the
6
+ library's spacing scale. See `Flow` for the list and divider rules.
7
+ -->
8
+ <script lang="ts">import Flow from "./Flow.svelte";
9
+ let props = $props();
10
+ </script>
11
+
12
+ <Flow direction="vertical" {...props} />
@@ -0,0 +1,29 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { FlowAlign, FlowElement, FlowJustify, Gap } from './space.ts';
4
+ interface Props extends HTMLAttributes<HTMLElement> {
5
+ /**
6
+ * Space between children.
7
+ * @defaultValue `'md'`
8
+ */
9
+ gap?: Gap | undefined;
10
+ /** Cross-axis alignment. */
11
+ align?: FlowAlign | undefined;
12
+ /** Main-axis distribution. */
13
+ justify?: FlowJustify | undefined;
14
+ /**
15
+ * A decorative rule between children (never around them).
16
+ * @defaultValue `false`
17
+ */
18
+ divider?: boolean | undefined;
19
+ /**
20
+ * The element. With `'ul'` / `'ol'`, children must be `<li>`s.
21
+ * @defaultValue `'div'`
22
+ */
23
+ as?: FlowElement | undefined;
24
+ children: Snippet<[]>;
25
+ }
26
+ /** A vertical stack: children one above the next, on the spacing scale. */
27
+ declare const VStack: import("svelte").Component<Props, {}, "">;
28
+ type VStack = ReturnType<typeof VStack>;
29
+ export default VStack;
@@ -16,14 +16,23 @@
16
16
  *
17
17
  * @module
18
18
  */
19
+ export { default as AppShell } from './AppShell.svelte';
19
20
  export { default as Breadcrumbs } from './Breadcrumbs.svelte';
21
+ export { default as Cluster } from './Cluster.svelte';
20
22
  export { default as DetailLayout } from './DetailLayout.svelte';
21
23
  export { default as FilterBar } from './FilterBar.svelte';
24
+ export { default as Fits } from './Fits.svelte';
22
25
  export { default as Footer } from './Footer.svelte';
26
+ export { default as Grid } from './Grid.svelte';
27
+ export { default as HStack } from './HStack.svelte';
28
+ export { default as Hero } from './Hero.svelte';
23
29
  export { default as Main } from './Main.svelte';
24
30
  export { default as Navbar } from './Navbar.svelte';
25
31
  export { default as PageHeader } from './PageHeader.svelte';
26
32
  export { default as Section } from './Section.svelte';
27
33
  export { default as Sidebar } from './Sidebar.svelte';
34
+ export { default as Spacer } from './Spacer.svelte';
28
35
  export { default as Tabs } from './Tabs.svelte';
36
+ export { default as VStack } from './VStack.svelte';
37
+ export * from './space.ts';
29
38
  export * from './types.ts';
@@ -16,14 +16,23 @@
16
16
  *
17
17
  * @module
18
18
  */
19
+ export { default as AppShell } from './AppShell.svelte';
19
20
  export { default as Breadcrumbs } from './Breadcrumbs.svelte';
21
+ export { default as Cluster } from './Cluster.svelte';
20
22
  export { default as DetailLayout } from './DetailLayout.svelte';
21
23
  export { default as FilterBar } from './FilterBar.svelte';
24
+ export { default as Fits } from './Fits.svelte';
22
25
  export { default as Footer } from './Footer.svelte';
26
+ export { default as Grid } from './Grid.svelte';
27
+ export { default as HStack } from './HStack.svelte';
28
+ export { default as Hero } from './Hero.svelte';
23
29
  export { default as Main } from './Main.svelte';
24
30
  export { default as Navbar } from './Navbar.svelte';
25
31
  export { default as PageHeader } from './PageHeader.svelte';
26
32
  export { default as Section } from './Section.svelte';
27
33
  export { default as Sidebar } from './Sidebar.svelte';
34
+ export { default as Spacer } from './Spacer.svelte';
28
35
  export { default as Tabs } from './Tabs.svelte';
36
+ export { default as VStack } from './VStack.svelte';
37
+ export * from "./space.js";
29
38
  export * from "./types.js";
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The library's spacing rhythm and the layout primitives' vocabulary, as
3
+ * literal class tables.
4
+ *
5
+ * `VStack`, `HStack`, `Cluster`, `Grid` and `Fits` take tokens, not class
6
+ * names, so every app spaces things on the same scale. Tailwind only
7
+ * generates classes it can see verbatim in source, so each step is spelled
8
+ * out once here and looked up (the `ui/tones.ts` discipline).
9
+ *
10
+ * @module
11
+ */
12
+ /** A step on the spacing scale. */
13
+ export type Gap = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
14
+ /** Literal `gap-*` class per `Gap`; a lookup table so Tailwind's scanner sees every class. */
15
+ export declare const gapClass: Record<Gap, string>;
16
+ /** Cross-axis alignment of a stack's or cluster's items. */
17
+ export type FlowAlign = 'start' | 'center' | 'end' | 'stretch' | 'baseline';
18
+ /** Literal `items-*` class per `FlowAlign`; a lookup table so Tailwind's scanner sees every class. */
19
+ export declare const alignClass: Record<FlowAlign, string>;
20
+ /** Main-axis distribution of a stack's or cluster's items. */
21
+ export type FlowJustify = 'start' | 'center' | 'end' | 'between';
22
+ /** Literal `justify-*` class per `FlowJustify`; a lookup table so Tailwind's scanner sees every class. */
23
+ export declare const justifyClass: Record<FlowJustify, string>;
24
+ /** The narrowest an item of a `Grid` gets before the grid drops a column. */
25
+ export type MinItem = 'xs' | 'sm' | 'md' | 'lg';
26
+ /** Literal auto-fill column template per `MinItem`; a lookup table so Tailwind's scanner sees every class. */
27
+ export declare const minItemClass: Record<MinItem, string>;
28
+ /** The element a primitive renders. A list (`ul` / `ol`) takes `<li>` children. */
29
+ export type FlowElement = 'div' | 'ul' | 'ol' | 'section' | 'nav';
30
+ /** A container width at which a `Fits` layout stops fitting. */
31
+ export type FitsBreakpoint = '20rem' | '28rem' | '36rem' | '48rem' | '64rem';
32
+ /** Literal container-query class showing a `Fits` layout from this width up. */
33
+ export declare const fitsShowFrom: Record<FitsBreakpoint, string>;
34
+ /** Literal container-query class hiding a `Fits` layout from this width up. */
35
+ export declare const fitsHideFrom: Record<FitsBreakpoint, string>;
36
+ /**
37
+ * The classes of `Fits` layout `index` of `count`, given the widths at which
38
+ * each stops fitting (`breakpoints[i]` for layout `i`, one fewer than the
39
+ * layouts). The first shows from `breakpoints[0]` up, each next one between
40
+ * its own breakpoint and the previous one, and the last below the final
41
+ * breakpoint. Outside its band a layout is `display: none`, so it is out of
42
+ * the accessibility tree.
43
+ */
44
+ export declare function fitsLayoutClass(index: number, count: number, breakpoints: readonly FitsBreakpoint[]): string[];