@widgetic/design-system 0.5.22 → 0.5.24

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 (258) hide show
  1. package/README.md +2 -0
  2. package/dist/components/CopyableHeader.svelte +260 -448
  3. package/dist/components/CopyableHeader.svelte.d.ts +8 -5
  4. package/dist/components/EmptyState.svelte +100 -128
  5. package/dist/components/EmptyState.svelte.d.ts +16 -19
  6. package/dist/components/GenerateLoader.svelte +17 -10
  7. package/dist/components/PasswordInput.svelte +41 -44
  8. package/dist/components/PasswordInput.svelte.d.ts +2 -0
  9. package/dist/components/ThumbHashImage.svelte +117 -119
  10. package/dist/components/WScrollArea.svelte +47 -41
  11. package/dist/components/chat/ActivityRow.svelte +115 -0
  12. package/dist/components/chat/ActivityRow.svelte.d.ts +18 -0
  13. package/dist/components/chat/ChatHeader.svelte +114 -0
  14. package/dist/components/chat/ChatHeader.svelte.d.ts +26 -0
  15. package/dist/components/chat/Composer.svelte +172 -0
  16. package/dist/components/chat/Composer.svelte.d.ts +27 -0
  17. package/dist/components/chat/Message.svelte +158 -0
  18. package/dist/components/chat/Message.svelte.d.ts +28 -0
  19. package/dist/components/chat/OptionRow.svelte +59 -0
  20. package/dist/components/chat/OptionRow.svelte.d.ts +14 -0
  21. package/dist/components/chat/PlanCard.svelte +220 -0
  22. package/dist/components/chat/PlanCard.svelte.d.ts +34 -0
  23. package/dist/components/chat/QuestionCard.svelte +265 -0
  24. package/dist/components/chat/QuestionCard.svelte.d.ts +38 -0
  25. package/dist/components/chat/ScrollToBottom.svelte +51 -0
  26. package/dist/components/chat/ScrollToBottom.svelte.d.ts +11 -0
  27. package/dist/components/chat/SuggestionCard.svelte +79 -0
  28. package/dist/components/chat/SuggestionCard.svelte.d.ts +20 -0
  29. package/dist/components/chat/TaskRow.svelte +59 -0
  30. package/dist/components/chat/TaskRow.svelte.d.ts +11 -0
  31. package/dist/components/chat/composerLogic.d.ts +16 -0
  32. package/dist/components/chat/composerLogic.js +29 -0
  33. package/dist/components/chat/index.d.ts +16 -0
  34. package/dist/components/chat/index.js +16 -0
  35. package/dist/components/chat/questionCardLogic.d.ts +11 -0
  36. package/dist/components/chat/questionCardLogic.js +39 -0
  37. package/dist/components/index.d.ts +10 -1
  38. package/dist/components/index.js +10 -0
  39. package/dist/components/modals/ActionModal.svelte +186 -180
  40. package/dist/components/modals/BaseModal.svelte +495 -401
  41. package/dist/components/modals/BaseModal.svelte.d.ts +4 -0
  42. package/dist/components/modals/NewItemDialog.svelte +198 -243
  43. package/dist/components/modals/Portal.svelte +109 -105
  44. package/dist/components/modals/README.md +16 -2
  45. package/dist/components/modals/RenameDialog.svelte +232 -292
  46. package/dist/components/modals/modalStore.d.ts +9 -1
  47. package/dist/components/modals/modalStore.js +44 -11
  48. package/dist/components/navigation/Breadcrumbs.svelte +421 -377
  49. package/dist/components/navigation/Breadcrumbs.svelte.d.ts +3 -2
  50. package/dist/components/navigation/breadcrumbsAvailableWidth.d.ts +10 -0
  51. package/dist/components/navigation/breadcrumbsAvailableWidth.js +10 -0
  52. package/dist/components/navigation/types.d.ts +2 -0
  53. package/dist/components/pdf/PDFViewer.svelte +1 -1
  54. package/dist/components/search-input/SearchInput.svelte +63 -104
  55. package/dist/components/search-input/SearchInput.svelte.d.ts +13 -27
  56. package/dist/components/search-input/index2.d.ts +14 -9
  57. package/dist/components/shad-editor/editor.css +1 -1
  58. package/dist/components/shad-editor/i18n/messages.d.ts +1 -1
  59. package/dist/components/shad-editor/i18n/messages.js +1 -1
  60. package/dist/components/shell/AppShell.svelte +52 -0
  61. package/dist/components/shell/AppShell.svelte.d.ts +13 -0
  62. package/dist/components/shell/Banner.svelte +90 -0
  63. package/dist/components/shell/Banner.svelte.d.ts +61 -0
  64. package/dist/components/shell/ErrorState.svelte +60 -0
  65. package/dist/components/shell/ErrorState.svelte.d.ts +13 -0
  66. package/dist/components/shell/Link.svelte +63 -0
  67. package/dist/components/shell/Link.svelte.d.ts +53 -0
  68. package/dist/components/shell/NavDrawer.svelte +117 -0
  69. package/dist/components/shell/NavDrawer.svelte.d.ts +10 -0
  70. package/dist/components/shell/NavRow.svelte +128 -0
  71. package/dist/components/shell/NavRow.svelte.d.ts +65 -0
  72. package/dist/components/shell/NavSectionLabel.svelte +27 -0
  73. package/dist/components/shell/NavSectionLabel.svelte.d.ts +9 -0
  74. package/dist/components/shell/NotificationRow.svelte +76 -0
  75. package/dist/components/shell/NotificationRow.svelte.d.ts +16 -0
  76. package/dist/components/shell/PageHeader.svelte +42 -0
  77. package/dist/components/shell/PageHeader.svelte.d.ts +12 -0
  78. package/dist/components/shell/ProfileRow.svelte +95 -0
  79. package/dist/components/shell/ProfileRow.svelte.d.ts +54 -0
  80. package/dist/components/shell/SettingsDialog.svelte +163 -0
  81. package/dist/components/shell/SettingsDialog.svelte.d.ts +19 -0
  82. package/dist/components/shell/SettingsNav.svelte +46 -0
  83. package/dist/components/shell/SettingsNav.svelte.d.ts +11 -0
  84. package/dist/components/shell/Sidebar.svelte +82 -0
  85. package/dist/components/shell/Sidebar.svelte.d.ts +25 -0
  86. package/dist/components/shell/Stat.svelte +63 -0
  87. package/dist/components/shell/Stat.svelte.d.ts +58 -0
  88. package/dist/components/shell/TopBar.svelte +37 -0
  89. package/dist/components/shell/TopBar.svelte.d.ts +11 -0
  90. package/dist/components/shell/WidgetRow.svelte +126 -0
  91. package/dist/components/shell/WidgetRow.svelte.d.ts +78 -0
  92. package/dist/components/shell/error-state-messages.d.ts +7 -0
  93. package/dist/components/shell/error-state-messages.js +9 -0
  94. package/dist/components/shell/index.d.ts +22 -0
  95. package/dist/components/shell/index.js +25 -0
  96. package/dist/components/shell/link-external.d.ts +2 -0
  97. package/dist/components/shell/link-external.js +7 -0
  98. package/dist/components/shell/messages.d.ts +7 -0
  99. package/dist/components/shell/messages.js +5 -0
  100. package/dist/components/shell/nested-modal-guard.d.ts +25 -0
  101. package/dist/components/shell/nested-modal-guard.js +33 -0
  102. package/dist/components/shell/settings-nav-types.d.ts +12 -0
  103. package/dist/components/shell/settings-nav-types.js +3 -0
  104. package/dist/components/shell/shell-utils.d.ts +7 -0
  105. package/dist/components/shell/shell-utils.js +27 -0
  106. package/dist/components/shell/stat-tone.d.ts +3 -0
  107. package/dist/components/shell/stat-tone.js +11 -0
  108. package/dist/components/toast/ToasterModal.svelte +102 -168
  109. package/dist/components/toast/ToasterModal.svelte.d.ts +2 -12
  110. package/dist/components/ui/accordion/accordion-content.svelte +3 -2
  111. package/dist/components/ui/accordion/accordion-item.svelte +10 -1
  112. package/dist/components/ui/accordion/accordion-trigger.svelte +4 -3
  113. package/dist/components/ui/alert/alert-description.svelte +5 -1
  114. package/dist/components/ui/alert/alert-title.svelte +2 -1
  115. package/dist/components/ui/alert/index.d.ts +13 -11
  116. package/dist/components/ui/alert/index.js +4 -4
  117. package/dist/components/ui/avatar/avatar-utils.d.ts +2 -0
  118. package/dist/components/ui/avatar/avatar-utils.js +9 -0
  119. package/dist/components/ui/avatar/avatar.svelte +63 -0
  120. package/dist/components/ui/avatar/avatar.svelte.d.ts +80 -0
  121. package/dist/components/ui/avatar/index.d.ts +4 -0
  122. package/dist/components/ui/avatar/index.js +4 -0
  123. package/dist/components/ui/badge/badge.svelte +22 -10
  124. package/dist/components/ui/badge/badge.svelte.d.ts +14 -15
  125. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
  126. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte +1 -1
  127. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte +1 -1
  128. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +2 -2
  129. package/dist/components/ui/button/button-padding.d.ts +9 -0
  130. package/dist/components/ui/button/button-padding.js +15 -0
  131. package/dist/components/ui/button/button.svelte +81 -31
  132. package/dist/components/ui/button/button.svelte.d.ts +48 -29
  133. package/dist/components/ui/calendar/calendar-cell.svelte +1 -1
  134. package/dist/components/ui/calendar/calendar-head-cell.svelte +1 -1
  135. package/dist/components/ui/calendar/calendar-next-button.svelte +2 -2
  136. package/dist/components/ui/calendar/calendar-prev-button.svelte +2 -2
  137. package/dist/components/ui/calendar/calendar.svelte.d.ts +1 -1
  138. package/dist/components/ui/card/card-description.svelte +1 -1
  139. package/dist/components/ui/card/card-title.svelte +1 -1
  140. package/dist/components/ui/card/card.svelte +1 -1
  141. package/dist/components/ui/checkbox/checkbox.svelte +9 -5
  142. package/dist/components/ui/chip/chip.svelte +48 -0
  143. package/dist/components/ui/chip/chip.svelte.d.ts +13 -0
  144. package/dist/components/ui/chip/index.d.ts +2 -0
  145. package/dist/components/ui/chip/index.js +2 -0
  146. package/dist/components/ui/command/command-dialog.svelte +1 -1
  147. package/dist/components/ui/command/command-input.svelte +4 -4
  148. package/dist/components/ui/command/command-item.svelte +1 -1
  149. package/dist/components/ui/command/command-link-item.svelte +1 -1
  150. package/dist/components/ui/command/command.svelte +1 -1
  151. package/dist/components/ui/dialog/dialog-content.svelte +11 -4
  152. package/dist/components/ui/dialog/dialog-description.svelte +1 -1
  153. package/dist/components/ui/dialog/dialog-overlay.svelte +8 -1
  154. package/dist/components/ui/dialog/dialog-title.svelte +1 -1
  155. package/dist/components/ui/drawer/drawer-content.svelte +1 -1
  156. package/dist/components/ui/drawer/drawer-overlay.svelte +1 -1
  157. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +5 -5
  158. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +1 -1
  159. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +1 -1
  160. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +20 -2
  161. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +4 -0
  162. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +5 -1
  163. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +3 -3
  164. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -1
  165. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  166. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +3 -3
  167. package/dist/components/ui/field/field-ids.d.ts +7 -0
  168. package/dist/components/ui/field/field-ids.js +15 -0
  169. package/dist/components/ui/field/field.svelte +62 -0
  170. package/dist/components/ui/field/field.svelte.d.ts +21 -0
  171. package/dist/components/ui/field/index.d.ts +3 -0
  172. package/dist/components/ui/field/index.js +3 -0
  173. package/dist/components/ui/hover-card/hover-card-content.svelte +1 -1
  174. package/dist/components/ui/icon-button/icon-button.svelte +72 -0
  175. package/dist/components/ui/icon-button/icon-button.svelte.d.ts +90 -0
  176. package/dist/components/ui/icon-button/index.d.ts +2 -0
  177. package/dist/components/ui/icon-button/index.js +4 -0
  178. package/dist/components/ui/input/index.d.ts +1 -0
  179. package/dist/components/ui/input/input.svelte +11 -4
  180. package/dist/components/ui/input/input.svelte.d.ts +4 -1
  181. package/dist/components/ui/input-otp/input-otp-separator.svelte +2 -2
  182. package/dist/components/ui/input-otp/input-otp-slot.svelte +5 -4
  183. package/dist/components/ui/input-otp/input-otp-slot.svelte.d.ts +1 -1
  184. package/dist/components/ui/input-otp/input-otp.svelte +1 -1
  185. package/dist/components/ui/label/label.svelte +3 -2
  186. package/dist/components/ui/popover/popover-content.svelte +1 -1
  187. package/dist/components/ui/progress/progress.svelte +19 -5
  188. package/dist/components/ui/progress/progress.svelte.d.ts +4 -2
  189. package/dist/components/ui/radio-group/radio-group-item.svelte +4 -4
  190. package/dist/components/ui/range-calendar/range-calendar-head-cell.svelte +1 -1
  191. package/dist/components/ui/range-calendar/range-calendar-next-button.svelte +2 -2
  192. package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte +2 -2
  193. package/dist/components/ui/range-calendar/range-calendar.svelte.d.ts +1 -1
  194. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +4 -1
  195. package/dist/components/ui/scroll-area/scroll-area.svelte +1 -1
  196. package/dist/components/ui/select/select-content.svelte +1 -3
  197. package/dist/components/ui/select/select-item.svelte +5 -4
  198. package/dist/components/ui/select/select-scroll-down-button.svelte +2 -2
  199. package/dist/components/ui/select/select-scroll-up-button.svelte +2 -2
  200. package/dist/components/ui/select/select-trigger.svelte +4 -3
  201. package/dist/components/ui/skeleton/index.d.ts +2 -0
  202. package/dist/components/ui/skeleton/index.js +2 -0
  203. package/dist/components/ui/skeleton/skeleton.svelte +24 -0
  204. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +8 -0
  205. package/dist/components/ui/slider/slider.svelte +5 -10
  206. package/dist/components/ui/sonner/sonner.svelte +19 -13
  207. package/dist/components/ui/stepper-button/index.d.ts +3 -0
  208. package/dist/components/ui/stepper-button/index.js +2 -0
  209. package/dist/components/ui/stepper-button/stepper-button.svelte +37 -0
  210. package/dist/components/ui/stepper-button/stepper-button.svelte.d.ts +9 -0
  211. package/dist/components/ui/switch/switch.svelte +8 -3
  212. package/dist/components/ui/table/table-cell.svelte +1 -1
  213. package/dist/components/ui/table/table-head.svelte +1 -1
  214. package/dist/components/ui/table/table-row.svelte +1 -1
  215. package/dist/components/ui/tabs/tabs-list.svelte +1 -1
  216. package/dist/components/ui/tabs/tabs-trigger.svelte +1 -1
  217. package/dist/components/ui/tag/index.d.ts +2 -0
  218. package/dist/components/ui/tag/index.js +2 -0
  219. package/dist/components/ui/tag/tag.svelte +42 -0
  220. package/dist/components/ui/tag/tag.svelte.d.ts +11 -0
  221. package/dist/components/ui/textarea/textarea.svelte +4 -3
  222. package/dist/components/ui/textarea/textarea.svelte.d.ts +2 -2
  223. package/dist/components/ui/toggle/toggle.svelte +9 -9
  224. package/dist/components/ui/toggle/toggle.svelte.d.ts +14 -21
  225. package/dist/components/ui/tooltip/tooltip-content.svelte +1 -1
  226. package/dist/fonts/Inter/Inter-Black.woff2 +0 -0
  227. package/dist/fonts/Inter/Inter-BlackItalic.woff2 +0 -0
  228. package/dist/fonts/Inter/Inter-Bold.woff2 +0 -0
  229. package/dist/fonts/Inter/Inter-BoldItalic.woff2 +0 -0
  230. package/dist/fonts/Inter/Inter-ExtraBold.woff2 +0 -0
  231. package/dist/fonts/Inter/Inter-ExtraBoldItalic.woff2 +0 -0
  232. package/dist/fonts/Inter/Inter-ExtraLight-BETA.woff2 +0 -0
  233. package/dist/fonts/Inter/Inter-ExtraLightItalic-BETA.woff2 +0 -0
  234. package/dist/fonts/Inter/Inter-Italic.woff2 +0 -0
  235. package/dist/fonts/Inter/Inter-Light-BETA.woff2 +0 -0
  236. package/dist/fonts/Inter/Inter-LightItalic-BETA.woff2 +0 -0
  237. package/dist/fonts/Inter/Inter-Medium.woff2 +0 -0
  238. package/dist/fonts/Inter/Inter-MediumItalic.woff2 +0 -0
  239. package/dist/fonts/Inter/Inter-Regular.woff2 +0 -0
  240. package/dist/fonts/Inter/Inter-SemiBold.woff2 +0 -0
  241. package/dist/fonts/Inter/Inter-SemiBoldItalic.woff2 +0 -0
  242. package/dist/fonts/Inter/Inter-Thin-BETA.woff2 +0 -0
  243. package/dist/fonts/Inter/Inter-ThinItalic-BETA.woff2 +0 -0
  244. package/dist/fonts/Inter/Inter-italic.var.woff2 +0 -0
  245. package/dist/fonts/Inter/Inter-upright.var.woff2 +0 -0
  246. package/dist/fonts/Inter/Inter.var.woff2 +0 -0
  247. package/dist/fonts/JetBrainsMono/JetBrainsMono-Regular.woff2 +0 -0
  248. package/dist/i18n/audit/designSystemWords.d.ts +1 -1
  249. package/dist/i18n/audit/designSystemWords.js +1 -1
  250. package/dist/styles/fonts.css +18 -14
  251. package/dist/styles/global.css +10 -21
  252. package/dist/styles/tokens.css +332 -0
  253. package/dist/utils/overlayMotion.d.ts +49 -0
  254. package/dist/utils/overlayMotion.js +71 -0
  255. package/dist/utils.d.ts +27 -0
  256. package/dist/utils.js +33 -2
  257. package/package.json +2 -1
  258. package/tailwind.config.ts +7 -47
@@ -0,0 +1,95 @@
1
+ <!-- Figma: Profile Row (component set 53:3, node 53:3). -->
2
+ <script lang="ts" module>
3
+ export const profileRowVariants = tv({
4
+ base: 'flex h-12 w-full min-w-0 items-center gap-2 rounded-lg p-2 text-start transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-sidebar-ring focus-visible:ring-offset-2 focus-visible:ring-offset-sidebar',
5
+ variants: {
6
+ interactive: {
7
+ true: 'cursor-pointer hover:bg-sidebar-accent',
8
+ false: ''
9
+ }
10
+ },
11
+ defaultVariants: {
12
+ interactive: true
13
+ }
14
+ });
15
+
16
+ export type ProfileRowVisualState = 'default' | 'hover' | 'focus';
17
+ </script>
18
+
19
+ <script lang="ts">
20
+ import type { HTMLAttributes } from 'svelte/elements';
21
+ import type { Snippet } from 'svelte';
22
+ import IconSelector from '@tabler/icons-svelte/icons/selector';
23
+ import { cn, tv } from '../../utils.js';
24
+ import { Avatar } from '../ui/avatar/index.js';
25
+
26
+ let {
27
+ class: className,
28
+ title,
29
+ subtitle = '',
30
+ showSubtitle = false,
31
+ showTrailingIcon = true,
32
+ name = '',
33
+ src = undefined,
34
+ visualState = undefined,
35
+ menu,
36
+ onclick,
37
+ ...restProps
38
+ }: HTMLAttributes<HTMLElement> & {
39
+ title: string;
40
+ subtitle?: string;
41
+ showSubtitle?: boolean;
42
+ showTrailingIcon?: boolean;
43
+ name?: string;
44
+ src?: string;
45
+ visualState?: ProfileRowVisualState;
46
+ menu?: Snippet;
47
+ } = $props();
48
+
49
+ const showcaseClass = $derived.by(() => {
50
+ if (!visualState || visualState === 'default') return '';
51
+ if (visualState === 'hover') return 'bg-sidebar-accent';
52
+ if (visualState === 'focus')
53
+ return 'ring-2 ring-sidebar-ring ring-offset-2 ring-offset-sidebar';
54
+ return '';
55
+ });
56
+
57
+ const asButton = $derived(Boolean(onclick || menu));
58
+ </script>
59
+
60
+ {#if asButton}
61
+ <button
62
+ type="button"
63
+ class={cn(profileRowVariants({ interactive: true }), showcaseClass, className)}
64
+ {onclick}
65
+ {...restProps}
66
+ >
67
+ <Avatar size="default" {name} {src} class="shrink-0" />
68
+ <span class="min-w-0 flex-1 flex-col gap-0 overflow-hidden">
69
+ <span class="text-body-medium text-foreground block truncate">{title}</span>
70
+ {#if showSubtitle && subtitle}
71
+ <span class="text-caption text-muted-foreground block truncate">{subtitle}</span>
72
+ {/if}
73
+ </span>
74
+ {#if showTrailingIcon}
75
+ <IconSelector class="text-muted-foreground size-4 shrink-0" aria-hidden="true" />
76
+ {/if}
77
+ {@render menu?.()}
78
+ </button>
79
+ {:else}
80
+ <div
81
+ class={cn(profileRowVariants({ interactive: false }), showcaseClass, className)}
82
+ {...restProps}
83
+ >
84
+ <Avatar size="default" {name} {src} class="shrink-0" />
85
+ <span class="min-w-0 flex-1 flex-col gap-0 overflow-hidden">
86
+ <span class="text-body-medium text-foreground block truncate">{title}</span>
87
+ {#if showSubtitle && subtitle}
88
+ <span class="text-caption text-muted-foreground block truncate">{subtitle}</span>
89
+ {/if}
90
+ </span>
91
+ {#if showTrailingIcon}
92
+ <IconSelector class="text-muted-foreground size-4 shrink-0" aria-hidden="true" />
93
+ {/if}
94
+ </div>
95
+ {/if}
@@ -0,0 +1,54 @@
1
+ export declare const profileRowVariants: import("tailwind-variants").TVReturnType<{
2
+ interactive: {
3
+ true: string;
4
+ false: string;
5
+ };
6
+ }, undefined, "flex h-12 w-full min-w-0 items-center gap-2 rounded-lg p-2 text-start transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-sidebar-ring focus-visible:ring-offset-2 focus-visible:ring-offset-sidebar", {
7
+ responsiveVariants?: boolean | (string | number | symbol)[] | {
8
+ interactive?: boolean | (string | number | symbol)[] | undefined;
9
+ } | undefined;
10
+ } & import("tailwind-variants/dist/config.js").TWMConfig & {
11
+ twMergeConfig: {
12
+ classGroups: {
13
+ "font-size": {
14
+ text: ("display-hero" | "heading-page" | "heading-section" | "body" | "body-medium" | "body-large" | "caption" | "caption-medium" | "label" | "label-small" | "code")[];
15
+ }[];
16
+ };
17
+ };
18
+ }, {
19
+ interactive: {
20
+ true: string;
21
+ false: string;
22
+ };
23
+ }, undefined, import("tailwind-variants").TVReturnType<{
24
+ interactive: {
25
+ true: string;
26
+ false: string;
27
+ };
28
+ }, undefined, "flex h-12 w-full min-w-0 items-center gap-2 rounded-lg p-2 text-start transition-colors duration-fast focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-sidebar-ring focus-visible:ring-offset-2 focus-visible:ring-offset-sidebar", import("tailwind-variants/dist/config.js").TVConfig<{
29
+ interactive: {
30
+ true: string;
31
+ false: string;
32
+ };
33
+ }, {
34
+ interactive: {
35
+ true: string;
36
+ false: string;
37
+ };
38
+ }>, unknown, unknown, undefined>>;
39
+ export type ProfileRowVisualState = 'default' | 'hover' | 'focus';
40
+ import type { HTMLAttributes } from 'svelte/elements';
41
+ import type { Snippet } from 'svelte';
42
+ type $$ComponentProps = HTMLAttributes<HTMLElement> & {
43
+ title: string;
44
+ subtitle?: string;
45
+ showSubtitle?: boolean;
46
+ showTrailingIcon?: boolean;
47
+ name?: string;
48
+ src?: string;
49
+ visualState?: ProfileRowVisualState;
50
+ menu?: Snippet;
51
+ };
52
+ declare const ProfileRow: import("svelte").Component<$$ComponentProps, {}, "">;
53
+ type ProfileRow = ReturnType<typeof ProfileRow>;
54
+ export default ProfileRow;
@@ -0,0 +1,163 @@
1
+ <!--
2
+ Figma: Settings Dialog (component set 107:618, page Settings Dialog)
3
+ -->
4
+ <script lang="ts" module>
5
+ export type SettingsDialogProps = {
6
+ open?: boolean;
7
+ class?: string;
8
+ title: string;
9
+ description?: string;
10
+ activeId: string;
11
+ groups: import('./settings-nav-types.js').SettingsNavGroup[];
12
+ onSelect?: (id: string) => void;
13
+ closeLabel?: string;
14
+ messages?: import('./messages.js').SettingsDialogMessages;
15
+ privacyHref?: string;
16
+ termsHref?: string;
17
+ cookieHref?: string;
18
+ children: import('svelte').Snippet;
19
+ descriptionSlot?: import('svelte').Snippet;
20
+ };
21
+ </script>
22
+
23
+ <script lang="ts">
24
+ import { Dialog as DialogPrimitive } from 'bits-ui';
25
+ import IconX from '@tabler/icons-svelte/icons/x';
26
+ import type { Snippet } from 'svelte';
27
+ import * as Dialog from '../ui/dialog/index.js';
28
+ import { cn } from '../../utils.js';
29
+ import { modalState } from '../modals/modalStore.js';
30
+ import SettingsNav from './SettingsNav.svelte';
31
+ import { defaultSettingsDialogMessages, type SettingsDialogMessages } from './messages.js';
32
+ import type { SettingsNavGroup } from './settings-nav-types.js';
33
+ import { createNestedModalTracker } from './nested-modal-guard.js';
34
+
35
+ let {
36
+ open = $bindable(false),
37
+ class: className,
38
+ title,
39
+ description = undefined,
40
+ activeId,
41
+ groups,
42
+ onSelect,
43
+ closeLabel = 'Close',
44
+ messages = defaultSettingsDialogMessages,
45
+ privacyHref = '#',
46
+ termsHref = '#',
47
+ cookieHref = '#',
48
+ children,
49
+ descriptionSlot
50
+ }: SettingsDialogProps = $props();
51
+
52
+ // bits-ui sets `contain: layout style` inline on every dialog content, and `contain: layout` makes that box the containing
53
+ // block of every `position: fixed` element inside it. A pane can hold an inline overlay of its own (a confirm dialog written
54
+ // as `fixed inset-0`): with containment on it would be drawn, and clipped, inside this box instead of over the viewport.
55
+ // The Content below therefore carries `contain-none!`.
56
+
57
+ // A modal a pane opens (ActionModal, RenameDialog, ...) is drawn outside this dialog: while one is open, a click or
58
+ // Escape in it must not close the settings dialog, and the focus trap must let its fields take the focus.
59
+ const nestedModalTracker = createNestedModalTracker();
60
+ const nestedModalOpen = $derived($modalState.isOpen);
61
+ $effect(() => {
62
+ nestedModalTracker.update(nestedModalOpen);
63
+ });
64
+
65
+ // Every way the dialog closes (X, Escape, a click outside) arrives here. The request is refused while a nested modal
66
+ // holds the dialog; the click itself is left alone so the modal still reads its own click.
67
+ function requestOpenChange(nextOpen: boolean): void {
68
+ if (!nextOpen && nestedModalTracker.holdsDialog()) return;
69
+ open = nextOpen;
70
+ }
71
+
72
+ // bits-ui marks the original Escape key event as handled before BaseModal (a window listener) reads it, and BaseModal
73
+ // leaves a handled Escape alone. While a nested modal is open the key therefore belongs to the modal: this dialog
74
+ // stays open and hands the modal a fresh Escape, so one press closes the modal only.
75
+ function handleEscapeKeydown(event: KeyboardEvent): void {
76
+ if (!nestedModalTracker.open) return;
77
+ event.preventDefault();
78
+ window.dispatchEvent(
79
+ new KeyboardEvent('keydown', {
80
+ key: 'Escape',
81
+ code: 'Escape',
82
+ bubbles: true,
83
+ cancelable: true
84
+ })
85
+ );
86
+ }
87
+ </script>
88
+
89
+ <Dialog.Root bind:open={() => open, requestOpenChange}>
90
+ <Dialog.Portal>
91
+ <!-- The scrim is the shared one of every overlay (muted foreground at 80%, 3px blur), set by the dialog overlay itself -->
92
+ <Dialog.Overlay />
93
+ <DialogPrimitive.Content
94
+ class={cn(
95
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 border-border bg-background duration-base fixed z-50 flex overflow-hidden border',
96
+ 'inset-0 h-full max-h-none w-full rounded-none',
97
+ // Centred with auto margins, not with a translate: a CSS transform would make this box the containing block
98
+ // of every `position: fixed` element inside a pane (a legacy confirm dialog would be drawn, and clipped, inside it).
99
+ 'lg:h-settings-modal lg:w-settings-modal lg:rounded-panel lg:m-auto lg:max-h-[calc(100vh-2rem)] lg:max-w-[calc(100vw-2rem)]',
100
+ // bits-ui's inline `contain: layout style` wins over a `style` prop, so the override has to be `!important`.
101
+ 'contain-none!',
102
+ className
103
+ )}
104
+ aria-describedby={description || descriptionSlot ? 'settings-dialog-description' : undefined}
105
+ trapFocus={!nestedModalOpen}
106
+ onEscapeKeydown={handleEscapeKeydown}
107
+ >
108
+ <div class="flex min-h-0 min-w-0 flex-1 flex-col lg:flex-row">
109
+ <aside
110
+ class="border-border bg-sidebar flex w-full shrink-0 flex-col border-b p-3 lg:w-64 lg:border-e lg:border-b-0"
111
+ >
112
+ <SettingsNav {groups} {activeId} {onSelect} class="flex-1" />
113
+ <div class="mt-auto flex flex-col gap-1 px-2 pt-4 pb-1">
114
+ <a
115
+ href={privacyHref}
116
+ class="text-caption text-muted-foreground duration-fast hover:text-foreground w-fit transition-colors"
117
+ >{messages.privacyPolicy}</a
118
+ >
119
+ <a
120
+ href={termsHref}
121
+ class="text-caption text-muted-foreground duration-fast hover:text-foreground w-fit transition-colors"
122
+ >{messages.termsOfService}</a
123
+ >
124
+ <a
125
+ href={cookieHref}
126
+ class="text-caption text-muted-foreground duration-fast hover:text-foreground w-fit transition-colors"
127
+ >{messages.cookieSettings}</a
128
+ >
129
+ </div>
130
+ </aside>
131
+ <div class="flex min-h-0 min-w-0 flex-1 flex-col gap-6 overflow-y-auto p-8">
132
+ <header class="flex flex-col gap-1 pe-10">
133
+ <DialogPrimitive.Title class="text-heading-page text-foreground"
134
+ >{title}</DialogPrimitive.Title
135
+ >
136
+ {#if descriptionSlot}
137
+ <DialogPrimitive.Description
138
+ id="settings-dialog-description"
139
+ class="text-body text-muted-foreground"
140
+ >
141
+ {@render descriptionSlot()}
142
+ </DialogPrimitive.Description>
143
+ {:else if description}
144
+ <DialogPrimitive.Description
145
+ id="settings-dialog-description"
146
+ class="text-body text-muted-foreground"
147
+ >
148
+ {description}
149
+ </DialogPrimitive.Description>
150
+ {/if}
151
+ </header>
152
+ <div class="flex min-h-0 flex-1 flex-col gap-6">{@render children()}</div>
153
+ </div>
154
+ </div>
155
+ <DialogPrimitive.Close
156
+ class="text-foreground hover:bg-accent duration-fast focus-visible:ring-ring focus-visible:ring-offset-background absolute end-4 top-4 inline-flex size-8 items-center justify-center rounded-lg transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden"
157
+ >
158
+ <IconX class="size-4 stroke-[1.333]" aria-hidden="true" />
159
+ <span class="sr-only">{closeLabel}</span>
160
+ </DialogPrimitive.Close>
161
+ </DialogPrimitive.Content>
162
+ </Dialog.Portal>
163
+ </Dialog.Root>
@@ -0,0 +1,19 @@
1
+ export type SettingsDialogProps = {
2
+ open?: boolean;
3
+ class?: string;
4
+ title: string;
5
+ description?: string;
6
+ activeId: string;
7
+ groups: import('./settings-nav-types.js').SettingsNavGroup[];
8
+ onSelect?: (id: string) => void;
9
+ closeLabel?: string;
10
+ messages?: import('./messages.js').SettingsDialogMessages;
11
+ privacyHref?: string;
12
+ termsHref?: string;
13
+ cookieHref?: string;
14
+ children: import('svelte').Snippet;
15
+ descriptionSlot?: import('svelte').Snippet;
16
+ };
17
+ declare const SettingsDialog: import("svelte").Component<SettingsDialogProps, {}, "open">;
18
+ type SettingsDialog = ReturnType<typeof SettingsDialog>;
19
+ export default SettingsDialog;
@@ -0,0 +1,46 @@
1
+ <!--
2
+ Figma: Settings Nav (component set 106:467, page Settings Dialog)
3
+ -->
4
+ <script lang="ts" module>
5
+ import type { HTMLAttributes } from 'svelte/elements';
6
+ import type { SettingsNavGroup } from './settings-nav-types.js';
7
+
8
+ export type SettingsNavProps = HTMLAttributes<HTMLElement> & {
9
+ class?: string;
10
+ groups: SettingsNavGroup[];
11
+ activeId: string;
12
+ onSelect?: (id: string) => void;
13
+ };
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ import { cn } from '../../utils.js';
18
+ import NavRow from './NavRow.svelte';
19
+ import NavSectionLabel from './NavSectionLabel.svelte';
20
+ import { settingsNavItemIsActive } from './settings-nav-types.js';
21
+
22
+ let { class: className, groups, activeId, onSelect, ...restProps }: SettingsNavProps = $props();
23
+ </script>
24
+
25
+ <nav class={cn('flex w-full flex-col gap-0.5', className)} aria-label="Settings" {...restProps}>
26
+ {#each groups as group (group.id)}
27
+ <div class="flex flex-col gap-0.5">
28
+ <NavSectionLabel label={group.label} />
29
+ {#each group.items as item (item.id)}
30
+ {@const active = settingsNavItemIsActive(activeId, item.id)}
31
+ <NavRow
32
+ label={item.label}
33
+ {active}
34
+ showIcon={Boolean(item.icon)}
35
+ onclick={() => onSelect?.(item.id)}
36
+ >
37
+ {#snippet icon()}
38
+ {#if item.icon}
39
+ {@render item.icon()}
40
+ {/if}
41
+ {/snippet}
42
+ </NavRow>
43
+ {/each}
44
+ </div>
45
+ {/each}
46
+ </nav>
@@ -0,0 +1,11 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { SettingsNavGroup } from './settings-nav-types.js';
3
+ export type SettingsNavProps = HTMLAttributes<HTMLElement> & {
4
+ class?: string;
5
+ groups: SettingsNavGroup[];
6
+ activeId: string;
7
+ onSelect?: (id: string) => void;
8
+ };
9
+ declare const SettingsNav: import("svelte").Component<SettingsNavProps, {}, "">;
10
+ type SettingsNav = ReturnType<typeof SettingsNav>;
11
+ export default SettingsNav;
@@ -0,0 +1,82 @@
1
+ <!-- Figma: Sidebar (component set 53:33, node 53:33). -->
2
+ <script lang="ts">
3
+ import type { Icon } from '@tabler/icons-svelte';
4
+ import type { HTMLAttributes } from 'svelte/elements';
5
+ import type { Snippet } from 'svelte';
6
+ import { cn } from '../../utils.js';
7
+ import NavRow from './NavRow.svelte';
8
+
9
+ export type SidebarNavItem = {
10
+ id: string;
11
+ label: string;
12
+ /** Custom icon markup (advanced). */
13
+ icon?: Snippet;
14
+ /** Tabler icon component (preferred for standard nav icons). */
15
+ iconComponent?: Icon;
16
+ href?: string;
17
+ count?: string | number;
18
+ disabled?: boolean;
19
+ };
20
+
21
+ let {
22
+ class: className,
23
+ activeId = undefined,
24
+ items = undefined,
25
+ onNavigate,
26
+ header,
27
+ nav,
28
+ footer,
29
+ ...restProps
30
+ }: HTMLAttributes<HTMLElement> & {
31
+ activeId?: string;
32
+ items?: SidebarNavItem[];
33
+ onNavigate?: (id: string) => void;
34
+ header?: Snippet;
35
+ nav?: Snippet;
36
+ footer?: Snippet;
37
+ } = $props();
38
+
39
+ function handleItemClick(id: string, href?: string) {
40
+ if (href) return;
41
+ onNavigate?.(id);
42
+ }
43
+ </script>
44
+
45
+ <aside
46
+ class={cn(
47
+ 'w-sidebar bg-sidebar text-sidebar-foreground flex h-full shrink-0 flex-col gap-0.5 p-3',
48
+ className
49
+ )}
50
+ {...restProps}
51
+ >
52
+ {#if header}
53
+ <div class="mb-0 shrink-0">{@render header()}</div>
54
+ {/if}
55
+
56
+ {#if items?.length}
57
+ <nav class="flex min-h-0 flex-1 flex-col gap-0.5" aria-label="Main">
58
+ {#each items as item (item.id)}
59
+ <NavRow
60
+ label={item.label}
61
+ href={item.href}
62
+ active={activeId === item.id}
63
+ disabled={item.disabled}
64
+ showIcon={Boolean(item.icon) || Boolean(item.iconComponent)}
65
+ showTrailing={item.count !== undefined && item.count !== null && item.count !== ''}
66
+ trailing={item.count != null ? String(item.count) : ''}
67
+ icon={item.icon}
68
+ iconComponent={item.iconComponent}
69
+ onclick={item.href ? undefined : () => handleItemClick(item.id, item.href)}
70
+ />
71
+ {/each}
72
+ </nav>
73
+ {:else if nav}
74
+ <nav class="flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto" aria-label="Main">
75
+ {@render nav()}
76
+ </nav>
77
+ {/if}
78
+
79
+ {#if footer}
80
+ <div class="mt-auto shrink-0 pt-2">{@render footer()}</div>
81
+ {/if}
82
+ </aside>
@@ -0,0 +1,25 @@
1
+ import type { Icon } from '@tabler/icons-svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { Snippet } from 'svelte';
4
+ export type SidebarNavItem = {
5
+ id: string;
6
+ label: string;
7
+ /** Custom icon markup (advanced). */
8
+ icon?: Snippet;
9
+ /** Tabler icon component (preferred for standard nav icons). */
10
+ iconComponent?: Icon;
11
+ href?: string;
12
+ count?: string | number;
13
+ disabled?: boolean;
14
+ };
15
+ type $$ComponentProps = HTMLAttributes<HTMLElement> & {
16
+ activeId?: string;
17
+ items?: SidebarNavItem[];
18
+ onNavigate?: (id: string) => void;
19
+ header?: Snippet;
20
+ nav?: Snippet;
21
+ footer?: Snippet;
22
+ };
23
+ declare const Sidebar: import("svelte").Component<$$ComponentProps, {}, "">;
24
+ type Sidebar = ReturnType<typeof Sidebar>;
25
+ export default Sidebar;
@@ -0,0 +1,63 @@
1
+ <!--
2
+ Figma: Stat (component set 327:243, page Experiments)
3
+ -->
4
+ <script lang="ts" module>
5
+ import type { HTMLAttributes } from 'svelte/elements';
6
+ import type { Snippet } from 'svelte';
7
+ import { type StatTone, statHintClass } from './stat-tone.js';
8
+
9
+ export const statVariants = tv({
10
+ base: 'flex flex-col gap-0.5 rounded-xl border border-border bg-background p-4',
11
+ variants: {
12
+ tone: {
13
+ default: '',
14
+ positive: '',
15
+ negative: ''
16
+ }
17
+ },
18
+ defaultVariants: {
19
+ tone: 'default'
20
+ }
21
+ });
22
+
23
+ export type StatProps = HTMLAttributes<HTMLDivElement> & {
24
+ class?: string;
25
+ label: string;
26
+ value: string;
27
+ hint?: string;
28
+ delta?: string;
29
+ tone?: StatTone;
30
+ trendIcon?: Snippet;
31
+ };
32
+ </script>
33
+
34
+ <script lang="ts">
35
+ import { cn, tv } from '../../utils.js';
36
+
37
+ let {
38
+ class: className,
39
+ label,
40
+ value,
41
+ hint = undefined,
42
+ delta = undefined,
43
+ tone = 'default',
44
+ trendIcon,
45
+ ...restProps
46
+ }: StatProps = $props();
47
+
48
+ const hintLine = $derived(delta ?? hint);
49
+ const hintClass = $derived(statHintClass(tone));
50
+ </script>
51
+
52
+ <div class={cn(statVariants({ tone }), className)} {...restProps}>
53
+ <p class="text-caption-medium text-muted-foreground">{label}</p>
54
+ <p class="text-heading-page text-foreground">{value}</p>
55
+ {#if hintLine}
56
+ <p class={cn('text-caption flex items-center gap-1', hintClass)}>
57
+ {#if trendIcon}
58
+ <span class="inline-flex shrink-0 items-center">{@render trendIcon()}</span>
59
+ {/if}
60
+ <span>{hintLine}</span>
61
+ </p>
62
+ {/if}
63
+ </div>
@@ -0,0 +1,58 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { Snippet } from 'svelte';
3
+ import { type StatTone } from './stat-tone.js';
4
+ export declare const statVariants: import("tailwind-variants").TVReturnType<{
5
+ tone: {
6
+ default: string;
7
+ positive: string;
8
+ negative: string;
9
+ };
10
+ }, undefined, "flex flex-col gap-0.5 rounded-xl border border-border bg-background p-4", {
11
+ responsiveVariants?: boolean | (string | number | symbol)[] | {
12
+ tone?: boolean | (string | number | symbol)[] | undefined;
13
+ } | undefined;
14
+ } & import("tailwind-variants/dist/config.js").TWMConfig & {
15
+ twMergeConfig: {
16
+ classGroups: {
17
+ "font-size": {
18
+ text: ("display-hero" | "heading-page" | "heading-section" | "body" | "body-medium" | "body-large" | "caption" | "caption-medium" | "label" | "label-small" | "code")[];
19
+ }[];
20
+ };
21
+ };
22
+ }, {
23
+ tone: {
24
+ default: string;
25
+ positive: string;
26
+ negative: string;
27
+ };
28
+ }, undefined, import("tailwind-variants").TVReturnType<{
29
+ tone: {
30
+ default: string;
31
+ positive: string;
32
+ negative: string;
33
+ };
34
+ }, undefined, "flex flex-col gap-0.5 rounded-xl border border-border bg-background p-4", import("tailwind-variants/dist/config.js").TVConfig<{
35
+ tone: {
36
+ default: string;
37
+ positive: string;
38
+ negative: string;
39
+ };
40
+ }, {
41
+ tone: {
42
+ default: string;
43
+ positive: string;
44
+ negative: string;
45
+ };
46
+ }>, unknown, unknown, undefined>>;
47
+ export type StatProps = HTMLAttributes<HTMLDivElement> & {
48
+ class?: string;
49
+ label: string;
50
+ value: string;
51
+ hint?: string;
52
+ delta?: string;
53
+ tone?: StatTone;
54
+ trendIcon?: Snippet;
55
+ };
56
+ declare const Stat: import("svelte").Component<StatProps, {}, "">;
57
+ type Stat = ReturnType<typeof Stat>;
58
+ export default Stat;
@@ -0,0 +1,37 @@
1
+ <!-- Figma: Top Bar (component set 142:2, node 142:2). -->
2
+ <script lang="ts">
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import type { Snippet } from 'svelte';
5
+ import IconMenu2 from '@tabler/icons-svelte/icons/menu-2';
6
+ import { cn } from '../../utils.js';
7
+ import { IconButton } from '../ui/icon-button/index.js';
8
+
9
+ let {
10
+ class: className,
11
+ title,
12
+ menuLabel = 'Open navigation',
13
+ onMenuClick,
14
+ action,
15
+ ...restProps
16
+ }: HTMLAttributes<HTMLElement> & {
17
+ title: string;
18
+ menuLabel?: string;
19
+ onMenuClick?: () => void;
20
+ action?: Snippet;
21
+ } = $props();
22
+ </script>
23
+
24
+ <header
25
+ class={cn('bg-sidebar flex h-14 w-full shrink-0 items-center gap-2 px-3 lg:hidden', className)}
26
+ {...restProps}
27
+ >
28
+ <IconButton variant="ghost" label={menuLabel} onclick={onMenuClick}>
29
+ <IconMenu2 />
30
+ </IconButton>
31
+ <h1 class="text-heading-section text-foreground min-w-0 flex-1 truncate">{title}</h1>
32
+ {#if action}
33
+ <div class="shrink-0">{@render action()}</div>
34
+ {:else}
35
+ <span class="size-8 shrink-0" aria-hidden="true"></span>
36
+ {/if}
37
+ </header>
@@ -0,0 +1,11 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { Snippet } from 'svelte';
3
+ type $$ComponentProps = HTMLAttributes<HTMLElement> & {
4
+ title: string;
5
+ menuLabel?: string;
6
+ onMenuClick?: () => void;
7
+ action?: Snippet;
8
+ };
9
+ declare const TopBar: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type TopBar = ReturnType<typeof TopBar>;
11
+ export default TopBar;