@noahbaumgartner/svelte-ui 0.0.4 → 0.0.6

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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +28 -13
  3. package/dist/components/accordion/Accordion.svelte +44 -0
  4. package/dist/components/accordion/Accordion.svelte.d.ts +13 -0
  5. package/dist/components/accordion/AccordionItem.svelte +145 -0
  6. package/dist/components/accordion/AccordionItem.svelte.d.ts +17 -0
  7. package/dist/components/accordion/context.d.ts +5 -0
  8. package/dist/components/accordion/context.js +2 -0
  9. package/dist/components/alert-dialog/AlertDialog.svelte +108 -76
  10. package/dist/components/alert-dialog/AlertDialog.svelte.d.ts +5 -2
  11. package/dist/components/avatar/Avatar.svelte +71 -49
  12. package/dist/components/avatar/Avatar.svelte.d.ts +5 -2
  13. package/dist/components/avatar-group/AvatarGroup.svelte +103 -0
  14. package/dist/components/avatar-group/AvatarGroup.svelte.d.ts +19 -0
  15. package/dist/components/badge/Badge.svelte +50 -28
  16. package/dist/components/badge/Badge.svelte.d.ts +6 -4
  17. package/dist/components/breadcrumb/Breadcrumb.svelte +21 -17
  18. package/dist/components/breadcrumb/Breadcrumb.svelte.d.ts +3 -1
  19. package/dist/components/breadcrumb/BreadcrumbEllipsis.svelte +17 -6
  20. package/dist/components/breadcrumb/BreadcrumbEllipsis.svelte.d.ts +5 -2
  21. package/dist/components/breadcrumb/BreadcrumbItem.svelte +75 -36
  22. package/dist/components/breadcrumb/BreadcrumbItem.svelte.d.ts +8 -5
  23. package/dist/components/breadcrumb/BreadcrumbSeparator.svelte +32 -9
  24. package/dist/components/breadcrumb/BreadcrumbSeparator.svelte.d.ts +10 -17
  25. package/dist/components/button/Button.svelte +206 -168
  26. package/dist/components/button/Button.svelte.d.ts +9 -5
  27. package/dist/components/button-group/ButtonGroup.svelte +52 -55
  28. package/dist/components/button-group/ButtonGroup.svelte.d.ts +3 -1
  29. package/dist/components/calendar/Calendar.svelte +232 -144
  30. package/dist/components/calendar/Calendar.svelte.d.ts +19 -2
  31. package/dist/components/calendar/dates.d.ts +4 -1
  32. package/dist/components/calendar/dates.js +8 -2
  33. package/dist/components/card/Card.svelte +48 -32
  34. package/dist/components/card/Card.svelte.d.ts +3 -1
  35. package/dist/components/card/CardAction.svelte +11 -7
  36. package/dist/components/card/CardAction.svelte.d.ts +3 -1
  37. package/dist/components/card/CardContent.svelte +8 -4
  38. package/dist/components/card/CardContent.svelte.d.ts +3 -1
  39. package/dist/components/card/CardDescription.svelte +11 -7
  40. package/dist/components/card/CardDescription.svelte.d.ts +3 -1
  41. package/dist/components/card/CardFooter.svelte +15 -11
  42. package/dist/components/card/CardFooter.svelte.d.ts +3 -1
  43. package/dist/components/card/CardHeader.svelte +15 -11
  44. package/dist/components/card/CardHeader.svelte.d.ts +3 -1
  45. package/dist/components/card/CardTitle.svelte +11 -7
  46. package/dist/components/card/CardTitle.svelte.d.ts +3 -1
  47. package/dist/components/checkbox/Checkbox.svelte +152 -61
  48. package/dist/components/checkbox/Checkbox.svelte.d.ts +5 -2
  49. package/dist/components/color-picker/ColorPicker.svelte +131 -78
  50. package/dist/components/color-picker/ColorPicker.svelte.d.ts +10 -1
  51. package/dist/components/context-menu/ContextMenu.svelte +78 -61
  52. package/dist/components/context-menu/ContextMenu.svelte.d.ts +5 -2
  53. package/dist/components/context-menu/ContextMenuInfo.svelte +91 -0
  54. package/dist/components/context-menu/ContextMenuInfo.svelte.d.ts +19 -0
  55. package/dist/components/context-menu/ContextMenuItem.svelte +102 -57
  56. package/dist/components/context-menu/ContextMenuItem.svelte.d.ts +10 -5
  57. package/dist/components/context-menu/ContextMenuLabel.svelte +28 -0
  58. package/dist/components/context-menu/ContextMenuLabel.svelte.d.ts +10 -0
  59. package/dist/components/context-menu/ContextMenuSeparator.svelte +29 -0
  60. package/dist/components/context-menu/ContextMenuSeparator.svelte.d.ts +8 -0
  61. package/dist/components/dialog/Dialog.svelte +149 -108
  62. package/dist/components/dialog/Dialog.svelte.d.ts +7 -2
  63. package/dist/components/drawer/Drawer.svelte +419 -0
  64. package/dist/components/drawer/Drawer.svelte.d.ts +28 -0
  65. package/dist/components/empty-state/EmptyState.svelte +106 -0
  66. package/dist/components/empty-state/EmptyState.svelte.d.ts +19 -0
  67. package/dist/components/entry/Entry.svelte +94 -0
  68. package/dist/components/entry/Entry.svelte.d.ts +16 -0
  69. package/dist/components/field/Field.svelte +66 -45
  70. package/dist/components/field/Field.svelte.d.ts +2 -1
  71. package/dist/components/field/FieldContent.svelte +11 -8
  72. package/dist/components/field/FieldContent.svelte.d.ts +2 -1
  73. package/dist/components/field/FieldDescription.svelte +18 -15
  74. package/dist/components/field/FieldDescription.svelte.d.ts +2 -1
  75. package/dist/components/field/FieldError.svelte +22 -13
  76. package/dist/components/field/FieldError.svelte.d.ts +2 -1
  77. package/dist/components/field/FieldGroup.svelte +15 -12
  78. package/dist/components/field/FieldGroup.svelte.d.ts +2 -1
  79. package/dist/components/field/FieldLegend.svelte +23 -14
  80. package/dist/components/field/FieldLegend.svelte.d.ts +2 -1
  81. package/dist/components/field/FieldSeparator.svelte +12 -9
  82. package/dist/components/field/FieldSeparator.svelte.d.ts +2 -1
  83. package/dist/components/field/FieldSet.svelte +18 -15
  84. package/dist/components/field/FieldSet.svelte.d.ts +2 -1
  85. package/dist/components/footer/Footer.svelte +105 -0
  86. package/dist/components/footer/Footer.svelte.d.ts +14 -0
  87. package/dist/components/footer/FooterColumn.svelte +37 -0
  88. package/dist/components/footer/FooterColumn.svelte.d.ts +11 -0
  89. package/dist/components/image/Image.svelte +61 -0
  90. package/dist/components/image/Image.svelte.d.ts +18 -0
  91. package/dist/components/input/Input.svelte +307 -208
  92. package/dist/components/input/Input.svelte.d.ts +12 -1
  93. package/dist/components/input-group/InputGroup.svelte +101 -61
  94. package/dist/components/input-group/InputGroup.svelte.d.ts +2 -1
  95. package/dist/components/input-group/InputGroupAddon.svelte +58 -49
  96. package/dist/components/kbd/Kbd.svelte +39 -30
  97. package/dist/components/kbd/Kbd.svelte.d.ts +2 -1
  98. package/dist/components/kbd/KbdGroup.svelte +15 -12
  99. package/dist/components/kbd/KbdGroup.svelte.d.ts +2 -1
  100. package/dist/components/label/Label.svelte +47 -28
  101. package/dist/components/label/Label.svelte.d.ts +2 -1
  102. package/dist/components/link/Link.svelte +71 -17
  103. package/dist/components/link/Link.svelte.d.ts +2 -1
  104. package/dist/components/mesh-gradient/MeshGradient.svelte +97 -0
  105. package/dist/components/mesh-gradient/MeshGradient.svelte.d.ts +11 -0
  106. package/dist/components/navbar/Navbar.svelte +137 -99
  107. package/dist/components/navbar/Navbar.svelte.d.ts +4 -2
  108. package/dist/components/navigation-menu/NavigationMenu.svelte +37 -20
  109. package/dist/components/navigation-menu/NavigationMenu.svelte.d.ts +4 -2
  110. package/dist/components/navigation-menu/NavigationMenuItem.svelte +131 -89
  111. package/dist/components/navigation-menu/NavigationMenuItem.svelte.d.ts +4 -2
  112. package/dist/components/navigation-menu/NavigationMenuLink.svelte +90 -51
  113. package/dist/components/navigation-menu/NavigationMenuLink.svelte.d.ts +7 -5
  114. package/dist/components/number-stepper/NumberStepper.svelte +101 -0
  115. package/dist/components/number-stepper/NumberStepper.svelte.d.ts +21 -0
  116. package/dist/components/popover/Popover.svelte +85 -65
  117. package/dist/components/popover/Popover.svelte.d.ts +5 -2
  118. package/dist/components/preview-card/PreviewCard.svelte +184 -0
  119. package/dist/components/preview-card/PreviewCard.svelte.d.ts +23 -0
  120. package/dist/components/progress/Progress.svelte +111 -0
  121. package/dist/components/progress/Progress.svelte.d.ts +13 -0
  122. package/dist/components/radio-group/RadioGroup.svelte +24 -19
  123. package/dist/components/radio-group/RadioGroup.svelte.d.ts +2 -1
  124. package/dist/components/radio-group/RadioGroupItem.svelte +101 -54
  125. package/dist/components/radio-group/RadioGroupItem.svelte.d.ts +2 -1
  126. package/dist/components/section/Section.svelte +114 -0
  127. package/dist/components/section/Section.svelte.d.ts +22 -0
  128. package/dist/components/select/Select.svelte +474 -0
  129. package/dist/components/select/Select.svelte.d.ts +48 -0
  130. package/dist/components/separator/Separator.svelte +21 -10
  131. package/dist/components/separator/Separator.svelte.d.ts +2 -1
  132. package/dist/components/sidebar/Sidebar.svelte +158 -87
  133. package/dist/components/sidebar/Sidebar.svelte.d.ts +6 -1
  134. package/dist/components/sidebar/SidebarContent.svelte +15 -12
  135. package/dist/components/sidebar/SidebarContent.svelte.d.ts +2 -1
  136. package/dist/components/sidebar/SidebarFooter.svelte +10 -7
  137. package/dist/components/sidebar/SidebarFooter.svelte.d.ts +2 -1
  138. package/dist/components/sidebar/SidebarGroup.svelte +35 -25
  139. package/dist/components/sidebar/SidebarGroup.svelte.d.ts +2 -1
  140. package/dist/components/sidebar/SidebarHeader.svelte +37 -8
  141. package/dist/components/sidebar/SidebarHeader.svelte.d.ts +6 -1
  142. package/dist/components/sidebar/SidebarInset.svelte +11 -8
  143. package/dist/components/sidebar/SidebarInset.svelte.d.ts +2 -1
  144. package/dist/components/sidebar/SidebarMenu.svelte +13 -10
  145. package/dist/components/sidebar/SidebarMenu.svelte.d.ts +2 -1
  146. package/dist/components/sidebar/SidebarMenuItem.svelte +195 -114
  147. package/dist/components/sidebar/SidebarMenuItem.svelte.d.ts +11 -5
  148. package/dist/components/sidebar/SidebarProvider.svelte +18 -9
  149. package/dist/components/sidebar/SidebarProvider.svelte.d.ts +2 -1
  150. package/dist/components/sidebar/SidebarSeparator.svelte +6 -1
  151. package/dist/components/sidebar/SidebarSeparator.svelte.d.ts +6 -17
  152. package/dist/components/sidebar/SidebarTrigger.svelte +17 -5
  153. package/dist/components/sidebar/SidebarTrigger.svelte.d.ts +4 -2
  154. package/dist/components/skeleton/Skeleton.svelte +26 -16
  155. package/dist/components/skeleton/Skeleton.svelte.d.ts +4 -2
  156. package/dist/components/spinner/Spinner.svelte +71 -46
  157. package/dist/components/spinner/Spinner.svelte.d.ts +2 -1
  158. package/dist/components/switch/Switch.svelte +126 -65
  159. package/dist/components/switch/Switch.svelte.d.ts +4 -2
  160. package/dist/components/table/Table.svelte +135 -76
  161. package/dist/components/table/Table.svelte.d.ts +12 -2
  162. package/dist/components/tabs/Tabs.svelte +337 -0
  163. package/dist/components/tabs/Tabs.svelte.d.ts +50 -0
  164. package/dist/components/textarea/Textarea.svelte +76 -42
  165. package/dist/components/textarea/Textarea.svelte.d.ts +4 -1
  166. package/dist/components/time-picker/TimePicker.svelte +214 -85
  167. package/dist/components/time-picker/TimePicker.svelte.d.ts +18 -1
  168. package/dist/components/toaster/Toaster.svelte +132 -70
  169. package/dist/components/toaster/Toaster.svelte.d.ts +18 -2
  170. package/dist/components/toaster/toast.svelte.d.ts +3 -3
  171. package/dist/components/toggle/Toggle.svelte +25 -4
  172. package/dist/components/toggle/Toggle.svelte.d.ts +1 -1
  173. package/dist/components/tooltip/Tooltip.svelte +87 -58
  174. package/dist/components/tooltip/Tooltip.svelte.d.ts +4 -2
  175. package/dist/icon.d.ts +12 -0
  176. package/dist/icon.js +1 -0
  177. package/dist/index.d.ts +21 -0
  178. package/dist/index.js +19 -0
  179. package/dist/internal/icons/ArrowDown.svelte +14 -0
  180. package/dist/internal/icons/ArrowDown.svelte.d.ts +4 -0
  181. package/dist/internal/icons/ArrowUp.svelte +14 -0
  182. package/dist/internal/icons/ArrowUp.svelte.d.ts +4 -0
  183. package/dist/internal/icons/Calendar.svelte +16 -0
  184. package/dist/internal/icons/Calendar.svelte.d.ts +4 -0
  185. package/dist/internal/icons/Check.svelte +8 -0
  186. package/dist/internal/icons/Check.svelte.d.ts +4 -0
  187. package/dist/internal/icons/ChevronDown.svelte +8 -0
  188. package/dist/internal/icons/ChevronDown.svelte.d.ts +4 -0
  189. package/dist/internal/icons/ChevronLeft.svelte +8 -0
  190. package/dist/internal/icons/ChevronLeft.svelte.d.ts +4 -0
  191. package/dist/internal/icons/ChevronRight.svelte +8 -0
  192. package/dist/internal/icons/ChevronRight.svelte.d.ts +4 -0
  193. package/dist/internal/icons/ChevronUp.svelte +8 -0
  194. package/dist/internal/icons/ChevronUp.svelte.d.ts +4 -0
  195. package/dist/internal/icons/ChevronsUpDown.svelte +14 -0
  196. package/dist/internal/icons/ChevronsUpDown.svelte.d.ts +4 -0
  197. package/dist/internal/icons/Clock.svelte +14 -0
  198. package/dist/internal/icons/Clock.svelte.d.ts +4 -0
  199. package/dist/internal/icons/Ellipsis.svelte +15 -0
  200. package/dist/internal/icons/Ellipsis.svelte.d.ts +4 -0
  201. package/dist/internal/icons/Icon.svelte +33 -0
  202. package/dist/internal/icons/Icon.svelte.d.ts +8 -0
  203. package/dist/internal/icons/Minus.svelte +8 -0
  204. package/dist/internal/icons/Minus.svelte.d.ts +4 -0
  205. package/dist/internal/icons/PanelLeft.svelte +14 -0
  206. package/dist/internal/icons/PanelLeft.svelte.d.ts +4 -0
  207. package/dist/internal/icons/Plus.svelte +14 -0
  208. package/dist/internal/icons/Plus.svelte.d.ts +4 -0
  209. package/dist/internal/icons/User.svelte +14 -0
  210. package/dist/internal/icons/User.svelte.d.ts +4 -0
  211. package/dist/internal/icons/X.svelte +14 -0
  212. package/dist/internal/icons/X.svelte.d.ts +4 -0
  213. package/dist/styles/tokens.css +39 -41
  214. package/package.json +5 -10
  215. package/dist/icons.d.ts +0 -2
  216. package/dist/icons.js +0 -4
@@ -7,72 +7,93 @@
7
7
  orientation?: 'vertical' | 'horizontal' | 'responsive';
8
8
  /** A Label, the control, and optionally FieldDescription and FieldError. Horizontal fields wrap label and description in a FieldContent. */
9
9
  children: Snippet;
10
+ ref?: HTMLDivElement | null;
10
11
  };
11
12
 
12
- let { orientation = 'vertical', class: className, children, ...rest }: Props = $props();
13
+ let {
14
+ orientation = 'vertical',
15
+ class: className,
16
+ children,
17
+ ref = $bindable(null),
18
+ ...rest
19
+ }: Props = $props();
13
20
  </script>
14
21
 
15
- <div {...rest} role="group" class={['field', `field--${orientation}`, className]}>
22
+ <div {...rest} bind:this={ref} role="group" class={['field', `field--${orientation}`, className]}>
16
23
  {@render children()}
17
24
  </div>
18
25
 
19
26
  <style>
20
- .field {
21
- display: flex;
22
- flex-direction: column;
23
- gap: 8px;
24
- width: 100%;
25
- font-size: 13px;
26
- color: var(--color-text);
27
- }
28
-
29
- .field--horizontal {
30
- flex-direction: row;
31
- align-items: center;
32
- }
33
-
34
- .field--horizontal > :global(.label) {
35
- flex: auto;
36
- }
37
-
38
- .field--horizontal:has(> :global(.field-content)) {
39
- align-items: flex-start;
40
- }
41
-
42
- .field--horizontal:has(> :global(.field-content)) > :global(:is(.checkbox, .radio)) {
43
- margin-top: 2px;
44
- }
27
+ @layer svelte-ui {
28
+ .field {
29
+ display: flex;
30
+ flex-direction: column;
31
+ gap: 8px;
32
+ width: 100%;
33
+ font-size: 13px;
34
+ color: var(--color-text);
35
+ }
45
36
 
46
- @container field-group (min-width: 448px) {
47
- .field--responsive {
37
+ .field--horizontal {
48
38
  flex-direction: row;
49
39
  align-items: center;
50
40
  }
51
41
 
52
- .field--responsive > :global(:is(.label, .field-content)) {
42
+ .field--horizontal > :global(.label) {
53
43
  flex: auto;
54
44
  }
55
45
 
56
- .field--responsive:has(> :global(.field-content)) {
46
+ .field--horizontal:has(> :global(.field-content)) {
57
47
  align-items: flex-start;
58
48
  }
59
- }
60
49
 
61
- /* State follows the control, so there is no invalid or disabled prop to keep in sync */
62
- .field:has(:global([aria-invalid='true'])) :global(.label) {
63
- color: var(--color-destructive);
64
- }
50
+ .field--horizontal:has(> :global(.field-content)) > :global(:is(.checkbox, .radio)) {
51
+ margin-top: 2px;
52
+ }
65
53
 
66
- .field:has(:global(:is(.checkbox, .radio, .switch))) :global(.label) {
67
- cursor: pointer;
68
- }
54
+ @container field-group (min-width: 448px) {
55
+ .field--responsive {
56
+ flex-direction: row;
57
+ align-items: center;
58
+ }
69
59
 
70
- /* The control dims itself */
71
- .field:has(:global(:disabled)) > :global(:is(.label, .field-description, .field-content)) {
72
- opacity: 0.5;
73
- }
60
+ .field--responsive > :global(:is(.label, .field-content)) {
61
+ flex: auto;
62
+ }
63
+
64
+ .field--responsive:has(> :global(.field-content)) {
65
+ align-items: flex-start;
66
+ }
67
+ }
68
+
69
+ /* State follows the control, so there is no invalid or disabled prop to keep in sync */
70
+ .field:has(:global([aria-invalid='true'])) :global(.label) {
71
+ color: var(--color-destructive);
72
+ }
73
+
74
+ .field:has(:global(:is(.checkbox, .radio, .switch))) :global(.label) {
75
+ cursor: pointer;
76
+ }
74
77
 
75
- .field:has(:global(:disabled)) :global(.label) {
76
- cursor: not-allowed;
78
+ /* The control dims itself */
79
+ .field:has(:global(:disabled)) > :global(:is(.label, .field-description, .field-content)) {
80
+ opacity: 0.5;
81
+ }
82
+
83
+ .field:has(:global(:disabled)) :global(.label) {
84
+ cursor: not-allowed;
85
+ }
86
+
87
+ @media (forced-colors: active) {
88
+ .field:has(:global(:disabled)) > :global(:is(.label, .field-description, .field-content)) {
89
+ color: GrayText;
90
+ opacity: 1;
91
+ }
92
+
93
+ .field:has(:global([aria-invalid='true'])) :global(.label) {
94
+ color: Mark;
95
+ text-decoration: underline;
96
+ }
97
+ }
77
98
  }
78
99
  </style>
@@ -5,7 +5,8 @@ type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
5
5
  orientation?: 'vertical' | 'horizontal' | 'responsive';
6
6
  /** A Label, the control, and optionally FieldDescription and FieldError. Horizontal fields wrap label and description in a FieldContent. */
7
7
  children: Snippet;
8
+ ref?: HTMLDivElement | null;
8
9
  };
9
- declare const Field: import("svelte").Component<Props, {}, "">;
10
+ declare const Field: import("svelte").Component<Props, {}, "ref">;
10
11
  type Field = ReturnType<typeof Field>;
11
12
  export default Field;
@@ -5,21 +5,24 @@
5
5
  type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
6
6
  /** Label, FieldDescription and FieldError next to the control in a horizontal Field. */
7
7
  children: Snippet;
8
+ ref?: HTMLDivElement | null;
8
9
  };
9
10
 
10
- let { class: className, children, ...rest }: Props = $props();
11
+ let { class: className, children, ref = $bindable(null), ...rest }: Props = $props();
11
12
  </script>
12
13
 
13
- <div {...rest} class={['field-content', className]}>
14
+ <div {...rest} bind:this={ref} class={['field-content', className]}>
14
15
  {@render children()}
15
16
  </div>
16
17
 
17
18
  <style>
18
- .field-content {
19
- display: flex;
20
- flex: 1;
21
- flex-direction: column;
22
- gap: 4px;
23
- min-width: 0;
19
+ @layer svelte-ui {
20
+ .field-content {
21
+ display: flex;
22
+ flex: 1;
23
+ flex-direction: column;
24
+ gap: 4px;
25
+ min-width: 0;
26
+ }
24
27
  }
25
28
  </style>
@@ -3,7 +3,8 @@ import type { HTMLAttributes } from 'svelte/elements';
3
3
  type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
4
4
  /** Label, FieldDescription and FieldError next to the control in a horizontal Field. */
5
5
  children: Snippet;
6
+ ref?: HTMLDivElement | null;
6
7
  };
7
- declare const FieldContent: import("svelte").Component<Props, {}, "">;
8
+ declare const FieldContent: import("svelte").Component<Props, {}, "ref">;
8
9
  type FieldContent = ReturnType<typeof FieldContent>;
9
10
  export default FieldContent;
@@ -5,30 +5,33 @@
5
5
  type Props = Omit<HTMLAttributes<HTMLParagraphElement>, 'children'> & {
6
6
  /** Give it an id and reference it from the control's `aria-describedby`. */
7
7
  children: Snippet;
8
+ ref?: HTMLParagraphElement | null;
8
9
  };
9
10
 
10
- let { class: className, children, ...rest }: Props = $props();
11
+ let { class: className, children, ref = $bindable(null), ...rest }: Props = $props();
11
12
  </script>
12
13
 
13
- <p {...rest} class={['field-description', className]}>
14
+ <p {...rest} bind:this={ref} class={['field-description', className]}>
14
15
  {@render children()}
15
16
  </p>
16
17
 
17
18
  <style>
18
- .field-description {
19
- margin: 0;
20
- font-size: 12px;
21
- line-height: 1.5;
22
- color: var(--color-text-muted);
23
- }
19
+ @layer svelte-ui {
20
+ .field-description {
21
+ margin: 0;
22
+ font-size: 12px;
23
+ line-height: 1.5;
24
+ color: var(--color-text-muted);
25
+ }
24
26
 
25
- .field-description :global(a) {
26
- color: inherit;
27
- text-decoration: underline;
28
- text-underline-offset: 3px;
29
- }
27
+ .field-description :global(a) {
28
+ color: inherit;
29
+ text-decoration: underline;
30
+ text-underline-offset: 3px;
31
+ }
30
32
 
31
- .field-description :global(a:hover) {
32
- color: var(--color-text);
33
+ .field-description :global(a:hover) {
34
+ color: var(--color-text);
35
+ }
33
36
  }
34
37
  </style>
@@ -3,7 +3,8 @@ import type { HTMLAttributes } from 'svelte/elements';
3
3
  type Props = Omit<HTMLAttributes<HTMLParagraphElement>, 'children'> & {
4
4
  /** Give it an id and reference it from the control's `aria-describedby`. */
5
5
  children: Snippet;
6
+ ref?: HTMLParagraphElement | null;
6
7
  };
7
- declare const FieldDescription: import("svelte").Component<Props, {}, "">;
8
+ declare const FieldDescription: import("svelte").Component<Props, {}, "ref">;
8
9
  type FieldDescription = ReturnType<typeof FieldDescription>;
9
10
  export default FieldDescription;
@@ -7,15 +7,16 @@
7
7
  errors?: (string | undefined)[];
8
8
  /** Custom content instead of `errors`. */
9
9
  children?: Snippet;
10
+ ref?: HTMLDivElement | null;
10
11
  };
11
12
 
12
- let { errors = [], class: className, children, ...rest }: Props = $props();
13
+ let { errors = [], class: className, children, ref = $bindable(null), ...rest }: Props = $props();
13
14
 
14
15
  let messages = $derived([...new Set(errors.filter(Boolean))]);
15
16
  </script>
16
17
 
17
18
  {#if children || messages.length}
18
- <div {...rest} role="alert" class={['field-error', className]}>
19
+ <div {...rest} bind:this={ref} role="alert" class={['field-error', className]}>
19
20
  {#if children}
20
21
  {@render children()}
21
22
  {:else if messages.length === 1}
@@ -29,17 +30,25 @@
29
30
  {/if}
30
31
 
31
32
  <style>
32
- .field-error {
33
- font-size: 12px;
34
- line-height: 1.5;
35
- color: var(--color-destructive);
36
- }
33
+ @layer svelte-ui {
34
+ .field-error {
35
+ font-size: 12px;
36
+ line-height: 1.5;
37
+ color: var(--color-destructive);
38
+ }
39
+
40
+ ul {
41
+ display: flex;
42
+ flex-direction: column;
43
+ gap: 2px;
44
+ margin: 0;
45
+ padding-left: 16px;
46
+ }
37
47
 
38
- ul {
39
- display: flex;
40
- flex-direction: column;
41
- gap: 2px;
42
- margin: 0;
43
- padding-left: 16px;
48
+ @media (forced-colors: active) {
49
+ .field-error {
50
+ color: CanvasText;
51
+ }
52
+ }
44
53
  }
45
54
  </style>
@@ -5,7 +5,8 @@ type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
5
5
  errors?: (string | undefined)[];
6
6
  /** Custom content instead of `errors`. */
7
7
  children?: Snippet;
8
+ ref?: HTMLDivElement | null;
8
9
  };
9
- declare const FieldError: import("svelte").Component<Props, {}, "">;
10
+ declare const FieldError: import("svelte").Component<Props, {}, "ref">;
10
11
  type FieldError = ReturnType<typeof FieldError>;
11
12
  export default FieldError;
@@ -5,26 +5,29 @@
5
5
  type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
6
6
  /** Fields, FieldSets and FieldSeparators. */
7
7
  children: Snippet;
8
+ ref?: HTMLDivElement | null;
8
9
  };
9
10
 
10
- let { class: className, children, ...rest }: Props = $props();
11
+ let { class: className, children, ref = $bindable(null), ...rest }: Props = $props();
11
12
  </script>
12
13
 
13
- <div {...rest} class={['field-group', className]}>
14
+ <div {...rest} bind:this={ref} class={['field-group', className]}>
14
15
  {@render children()}
15
16
  </div>
16
17
 
17
18
  <style>
18
- .field-group {
19
- container: field-group / inline-size;
20
- display: flex;
21
- flex-direction: column;
22
- gap: 24px;
23
- width: 100%;
24
- }
19
+ @layer svelte-ui {
20
+ .field-group {
21
+ container: field-group / inline-size;
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: 24px;
25
+ width: 100%;
26
+ }
25
27
 
26
- /* Tighter spacing for lists of checkboxes or radios */
27
- .field-group:has(> :global(.field--horizontal)):not(:has(> :global(:not(.field--horizontal)))) {
28
- gap: 12px;
28
+ /* Tighter spacing for lists of checkboxes or radios */
29
+ .field-group:has(> :global(.field--horizontal)):not(:has(> :global(:not(.field--horizontal)))) {
30
+ gap: 12px;
31
+ }
29
32
  }
30
33
  </style>
@@ -3,7 +3,8 @@ import type { HTMLAttributes } from 'svelte/elements';
3
3
  type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
4
4
  /** Fields, FieldSets and FieldSeparators. */
5
5
  children: Snippet;
6
+ ref?: HTMLDivElement | null;
6
7
  };
7
- declare const FieldGroup: import("svelte").Component<Props, {}, "">;
8
+ declare const FieldGroup: import("svelte").Component<Props, {}, "ref">;
8
9
  type FieldGroup = ReturnType<typeof FieldGroup>;
9
10
  export default FieldGroup;
@@ -6,29 +6,38 @@
6
6
  /** `label` matches a Label, for a group of checkboxes or radios. */
7
7
  variant?: 'legend' | 'label';
8
8
  children: Snippet;
9
+ ref?: HTMLLegendElement | null;
9
10
  };
10
11
 
11
- let { variant = 'legend', class: className, children, ...rest }: Props = $props();
12
+ let {
13
+ variant = 'legend',
14
+ class: className,
15
+ children,
16
+ ref = $bindable(null),
17
+ ...rest
18
+ }: Props = $props();
12
19
  </script>
13
20
 
14
- <legend {...rest} class={['field-legend', `field-legend--${variant}`, className]}>
21
+ <legend {...rest} bind:this={ref} class={['field-legend', `field-legend--${variant}`, className]}>
15
22
  {@render children()}
16
23
  </legend>
17
24
 
18
25
  <style>
19
- .field-legend {
20
- margin-bottom: 12px;
21
- padding: 0;
22
- font-weight: 600;
23
- line-height: 1.4;
24
- }
26
+ @layer svelte-ui {
27
+ .field-legend {
28
+ margin-bottom: 12px;
29
+ padding: 0;
30
+ font-weight: 600;
31
+ line-height: 1.4;
32
+ }
25
33
 
26
- .field-legend--legend {
27
- font-size: 15px;
28
- }
34
+ .field-legend--legend {
35
+ font-size: 15px;
36
+ }
29
37
 
30
- .field-legend--label {
31
- font-size: 13px;
32
- font-weight: 500;
38
+ .field-legend--label {
39
+ font-size: 13px;
40
+ font-weight: 500;
41
+ }
33
42
  }
34
43
  </style>
@@ -4,7 +4,8 @@ type Props = Omit<HTMLAttributes<HTMLLegendElement>, 'children'> & {
4
4
  /** `label` matches a Label, for a group of checkboxes or radios. */
5
5
  variant?: 'legend' | 'label';
6
6
  children: Snippet;
7
+ ref?: HTMLLegendElement | null;
7
8
  };
8
- declare const FieldLegend: import("svelte").Component<Props, {}, "">;
9
+ declare const FieldLegend: import("svelte").Component<Props, {}, "ref">;
9
10
  type FieldLegend = ReturnType<typeof FieldLegend>;
10
11
  export default FieldLegend;
@@ -6,12 +6,13 @@
6
6
  type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
7
7
  /** Optional text in the middle of the line, e.g. "Or continue with". */
8
8
  children?: Snippet;
9
+ ref?: HTMLDivElement | null;
9
10
  };
10
11
 
11
- let { class: className, children, ...rest }: Props = $props();
12
+ let { class: className, children, ref = $bindable(null), ...rest }: Props = $props();
12
13
  </script>
13
14
 
14
- <div {...rest} role="separator" class={['field-separator', className]}>
15
+ <div {...rest} bind:this={ref} role="separator" class={['field-separator', className]}>
15
16
  <Separator style="flex: 1;" />
16
17
  {#if children}
17
18
  <span class="field-separator-content">{@render children()}</span>
@@ -20,12 +21,14 @@
20
21
  </div>
21
22
 
22
23
  <style>
23
- .field-separator {
24
- display: flex;
25
- align-items: center;
26
- gap: 8px;
27
- min-height: 20px;
28
- font-size: 13px;
29
- color: var(--color-text-muted);
24
+ @layer svelte-ui {
25
+ .field-separator {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: 8px;
29
+ min-height: 20px;
30
+ font-size: 13px;
31
+ color: var(--color-text-muted);
32
+ }
30
33
  }
31
34
  </style>
@@ -3,7 +3,8 @@ import type { HTMLAttributes } from 'svelte/elements';
3
3
  type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
4
4
  /** Optional text in the middle of the line, e.g. "Or continue with". */
5
5
  children?: Snippet;
6
+ ref?: HTMLDivElement | null;
6
7
  };
7
- declare const FieldSeparator: import("svelte").Component<Props, {}, "">;
8
+ declare const FieldSeparator: import("svelte").Component<Props, {}, "ref">;
8
9
  type FieldSeparator = ReturnType<typeof FieldSeparator>;
9
10
  export default FieldSeparator;
@@ -5,29 +5,32 @@
5
5
  type Props = Omit<HTMLFieldsetAttributes, 'children'> & {
6
6
  /** A FieldLegend, optionally a FieldDescription, then a FieldGroup. `disabled` disables every control inside. */
7
7
  children: Snippet;
8
+ ref?: HTMLFieldSetElement | null;
8
9
  };
9
10
 
10
- let { class: className, children, ...rest }: Props = $props();
11
+ let { class: className, children, ref = $bindable(null), ...rest }: Props = $props();
11
12
  </script>
12
13
 
13
- <fieldset {...rest} class={['field-set', className]}>
14
+ <fieldset {...rest} bind:this={ref} class={['field-set', className]}>
14
15
  {@render children()}
15
16
  </fieldset>
16
17
 
17
18
  <style>
18
- .field-set {
19
- display: flex;
20
- flex-direction: column;
21
- gap: 24px;
22
- min-width: 0;
23
- margin: 0;
24
- padding: 0;
25
- border: none;
26
- color: var(--color-text);
27
- }
19
+ @layer svelte-ui {
20
+ .field-set {
21
+ display: flex;
22
+ flex-direction: column;
23
+ gap: 24px;
24
+ min-width: 0;
25
+ margin: 0;
26
+ padding: 0;
27
+ border: none;
28
+ color: var(--color-text);
29
+ }
28
30
 
29
- /* The legend sits outside the flex layout, so only its own margin spaces it */
30
- .field-set > :global(.field-legend + .field-description) {
31
- margin-top: -8px;
31
+ /* The legend sits outside the flex layout, so only its own margin spaces it */
32
+ .field-set > :global(.field-legend + .field-description) {
33
+ margin-top: -8px;
34
+ }
32
35
  }
33
36
  </style>
@@ -3,7 +3,8 @@ import type { HTMLFieldsetAttributes } from 'svelte/elements';
3
3
  type Props = Omit<HTMLFieldsetAttributes, 'children'> & {
4
4
  /** A FieldLegend, optionally a FieldDescription, then a FieldGroup. `disabled` disables every control inside. */
5
5
  children: Snippet;
6
+ ref?: HTMLFieldSetElement | null;
6
7
  };
7
- declare const FieldSet: import("svelte").Component<Props, {}, "">;
8
+ declare const FieldSet: import("svelte").Component<Props, {}, "ref">;
8
9
  type FieldSet = ReturnType<typeof FieldSet>;
9
10
  export default FieldSet;
@@ -0,0 +1,105 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+
5
+ type Props = Omit<HTMLAttributes<HTMLElement>, 'children' | 'title'> & {
6
+ /** Message in the panel, rendered as an `<h2>`; `\n` breaks the line. */
7
+ title?: string;
8
+ /** Owner shown below the panel as "© <current year> <copyright>". */
9
+ copyright?: string;
10
+ /** FooterColumns. */
11
+ children?: Snippet;
12
+ ref?: HTMLElement | null;
13
+ };
14
+
15
+ let {
16
+ title,
17
+ copyright,
18
+ class: className,
19
+ children,
20
+ ref = $bindable(null),
21
+ ...rest
22
+ }: Props = $props();
23
+
24
+ const year = new Date().getFullYear();
25
+ </script>
26
+
27
+ <footer {...rest} bind:this={ref} class={['footer', className]}>
28
+ <div class="footer-panel">
29
+ {#if title}
30
+ <h2 class="footer-title">{title}</h2>
31
+ {/if}
32
+ {#if children}
33
+ <div class="footer-columns">{@render children()}</div>
34
+ {/if}
35
+ </div>
36
+ {#if copyright}
37
+ <p class="footer-copyright">© {year} {copyright}</p>
38
+ {/if}
39
+ </footer>
40
+
41
+ <style>
42
+ @layer svelte-ui {
43
+ .footer {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: 20px;
47
+ font-size: 14px;
48
+ }
49
+
50
+ .footer-panel {
51
+ display: flex;
52
+ flex-direction: column;
53
+ gap: 40px;
54
+ box-sizing: border-box;
55
+ min-height: 256px;
56
+ padding: 40px;
57
+ color: var(--color-base);
58
+ background-color: var(--color-ink);
59
+ border-radius: 10px;
60
+ }
61
+
62
+ .footer-title {
63
+ margin: 0;
64
+ font-size: 24px;
65
+ font-weight: 600;
66
+ line-height: 1.25;
67
+ white-space: pre-line;
68
+ user-select: none;
69
+ }
70
+
71
+ .footer-columns {
72
+ display: flex;
73
+ flex-direction: column;
74
+ gap: 40px;
75
+ }
76
+
77
+ .footer-copyright {
78
+ margin: 0;
79
+ text-align: center;
80
+ color: var(--color-text-muted);
81
+ user-select: none;
82
+ }
83
+
84
+ @media (min-width: 640px) {
85
+ .footer-panel {
86
+ flex-direction: row;
87
+ }
88
+
89
+ .footer-title {
90
+ flex: 1;
91
+ }
92
+
93
+ .footer-columns {
94
+ flex: 1;
95
+ flex-direction: row;
96
+ }
97
+ }
98
+
99
+ @media (forced-colors: active) {
100
+ .footer-panel {
101
+ border: 1px solid CanvasText;
102
+ }
103
+ }
104
+ }
105
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type Props = Omit<HTMLAttributes<HTMLElement>, 'children' | 'title'> & {
4
+ /** Message in the panel, rendered as an `<h2>`; `\n` breaks the line. */
5
+ title?: string;
6
+ /** Owner shown below the panel as "© <current year> <copyright>". */
7
+ copyright?: string;
8
+ /** FooterColumns. */
9
+ children?: Snippet;
10
+ ref?: HTMLElement | null;
11
+ };
12
+ declare const Footer: import("svelte").Component<Props, {}, "ref">;
13
+ type Footer = ReturnType<typeof Footer>;
14
+ export default Footer;