@duestel/ui 0.1.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 (226) hide show
  1. package/README.md +110 -0
  2. package/dist/components/accordion/Accordion.d.ts +34 -0
  3. package/dist/components/accordion/Accordion.js +54 -0
  4. package/dist/components/accordion/Accordion.js.map +1 -0
  5. package/dist/components/accordion/index.d.ts +1 -0
  6. package/dist/components/accordion/index.js +2 -0
  7. package/dist/components/alert-dialog/AlertDialog.d.ts +53 -0
  8. package/dist/components/alert-dialog/AlertDialog.js +69 -0
  9. package/dist/components/alert-dialog/AlertDialog.js.map +1 -0
  10. package/dist/components/alert-dialog/index.d.ts +1 -0
  11. package/dist/components/alert-dialog/index.js +2 -0
  12. package/dist/components/autocomplete/Autocomplete.d.ts +90 -0
  13. package/dist/components/autocomplete/Autocomplete.js +137 -0
  14. package/dist/components/autocomplete/Autocomplete.js.map +1 -0
  15. package/dist/components/autocomplete/index.d.ts +1 -0
  16. package/dist/components/autocomplete/index.js +2 -0
  17. package/dist/components/avatar/Avatar.d.ts +44 -0
  18. package/dist/components/avatar/Avatar.js +45 -0
  19. package/dist/components/avatar/Avatar.js.map +1 -0
  20. package/dist/components/avatar/index.d.ts +2 -0
  21. package/dist/components/avatar/index.js +2 -0
  22. package/dist/components/badge/Badge.d.ts +43 -0
  23. package/dist/components/badge/Badge.js +32 -0
  24. package/dist/components/badge/Badge.js.map +1 -0
  25. package/dist/components/badge/index.d.ts +2 -0
  26. package/dist/components/badge/index.js +2 -0
  27. package/dist/components/button/Button.d.ts +60 -0
  28. package/dist/components/button/Button.js +61 -0
  29. package/dist/components/button/Button.js.map +1 -0
  30. package/dist/components/button/index.d.ts +1 -0
  31. package/dist/components/button/index.js +2 -0
  32. package/dist/components/carousel/Carousel.d.ts +32 -0
  33. package/dist/components/carousel/Carousel.js +113 -0
  34. package/dist/components/carousel/Carousel.js.map +1 -0
  35. package/dist/components/carousel/index.d.ts +1 -0
  36. package/dist/components/carousel/index.js +2 -0
  37. package/dist/components/checkbox/Checkbox.d.ts +64 -0
  38. package/dist/components/checkbox/Checkbox.js +59 -0
  39. package/dist/components/checkbox/Checkbox.js.map +1 -0
  40. package/dist/components/checkbox/index.d.ts +1 -0
  41. package/dist/components/checkbox/index.js +2 -0
  42. package/dist/components/collapsible/Collapsible.d.ts +28 -0
  43. package/dist/components/collapsible/Collapsible.js +40 -0
  44. package/dist/components/collapsible/Collapsible.js.map +1 -0
  45. package/dist/components/collapsible/index.d.ts +1 -0
  46. package/dist/components/collapsible/index.js +2 -0
  47. package/dist/components/combobox/Combobox.d.ts +113 -0
  48. package/dist/components/combobox/Combobox.js +189 -0
  49. package/dist/components/combobox/Combobox.js.map +1 -0
  50. package/dist/components/combobox/index.d.ts +1 -0
  51. package/dist/components/combobox/index.js +2 -0
  52. package/dist/components/command/Command.d.ts +37 -0
  53. package/dist/components/command/Command.js +90 -0
  54. package/dist/components/command/Command.js.map +1 -0
  55. package/dist/components/command/index.d.ts +1 -0
  56. package/dist/components/command/index.js +2 -0
  57. package/dist/components/context-menu/ContextMenu.d.ts +76 -0
  58. package/dist/components/context-menu/ContextMenu.js +132 -0
  59. package/dist/components/context-menu/ContextMenu.js.map +1 -0
  60. package/dist/components/context-menu/index.d.ts +1 -0
  61. package/dist/components/context-menu/index.js +2 -0
  62. package/dist/components/data-table/DataTable.d.ts +32 -0
  63. package/dist/components/data-table/DataTable.js +102 -0
  64. package/dist/components/data-table/DataTable.js.map +1 -0
  65. package/dist/components/data-table/Table.d.ts +51 -0
  66. package/dist/components/data-table/Table.js +69 -0
  67. package/dist/components/data-table/Table.js.map +1 -0
  68. package/dist/components/data-table/index.d.ts +3 -0
  69. package/dist/components/data-table/index.js +3 -0
  70. package/dist/components/date-picker/DatePicker.d.ts +63 -0
  71. package/dist/components/date-picker/DatePicker.js +247 -0
  72. package/dist/components/date-picker/DatePicker.js.map +1 -0
  73. package/dist/components/date-picker/index.d.ts +2 -0
  74. package/dist/components/date-picker/index.js +2 -0
  75. package/dist/components/dialog/Dialog.d.ts +59 -0
  76. package/dist/components/dialog/Dialog.js +71 -0
  77. package/dist/components/dialog/Dialog.js.map +1 -0
  78. package/dist/components/dialog/index.d.ts +1 -0
  79. package/dist/components/dialog/index.js +2 -0
  80. package/dist/components/drawer/Drawer.d.ts +93 -0
  81. package/dist/components/drawer/Drawer.js +106 -0
  82. package/dist/components/drawer/Drawer.js.map +1 -0
  83. package/dist/components/drawer/index.d.ts +1 -0
  84. package/dist/components/drawer/index.js +2 -0
  85. package/dist/components/form/Field.d.ts +52 -0
  86. package/dist/components/form/Field.js +54 -0
  87. package/dist/components/form/Field.js.map +1 -0
  88. package/dist/components/form/Fieldset.d.ts +24 -0
  89. package/dist/components/form/Fieldset.js +24 -0
  90. package/dist/components/form/Fieldset.js.map +1 -0
  91. package/dist/components/form/Form.d.ts +18 -0
  92. package/dist/components/form/Form.js +14 -0
  93. package/dist/components/form/Form.js.map +1 -0
  94. package/dist/components/form/Input.d.ts +33 -0
  95. package/dist/components/form/Input.js +99 -0
  96. package/dist/components/form/Input.js.map +1 -0
  97. package/dist/components/form/app-form.d.ts +71 -0
  98. package/dist/components/form/app-form.js +95 -0
  99. package/dist/components/form/app-form.js.map +1 -0
  100. package/dist/components/form/index.d.ts +5 -0
  101. package/dist/components/form/index.js +6 -0
  102. package/dist/components/hotkeys/Kbd.d.ts +20 -0
  103. package/dist/components/hotkeys/Kbd.js +31 -0
  104. package/dist/components/hotkeys/Kbd.js.map +1 -0
  105. package/dist/components/hotkeys/hotkeys.d.ts +14 -0
  106. package/dist/components/hotkeys/hotkeys.js +2 -0
  107. package/dist/components/hotkeys/index.d.ts +2 -0
  108. package/dist/components/hotkeys/index.js +3 -0
  109. package/dist/components/menu/Menu.d.ts +84 -0
  110. package/dist/components/menu/Menu.js +142 -0
  111. package/dist/components/menu/Menu.js.map +1 -0
  112. package/dist/components/menu/index.d.ts +1 -0
  113. package/dist/components/menu/index.js +2 -0
  114. package/dist/components/menubar/Menubar.d.ts +87 -0
  115. package/dist/components/menubar/Menubar.js +142 -0
  116. package/dist/components/menubar/Menubar.js.map +1 -0
  117. package/dist/components/menubar/index.d.ts +1 -0
  118. package/dist/components/menubar/index.js +2 -0
  119. package/dist/components/meter/Meter.d.ts +33 -0
  120. package/dist/components/meter/Meter.js +45 -0
  121. package/dist/components/meter/Meter.js.map +1 -0
  122. package/dist/components/meter/index.d.ts +1 -0
  123. package/dist/components/meter/index.js +2 -0
  124. package/dist/components/navigation-menu/NavigationMenu.d.ts +81 -0
  125. package/dist/components/navigation-menu/NavigationMenu.js +112 -0
  126. package/dist/components/navigation-menu/NavigationMenu.js.map +1 -0
  127. package/dist/components/navigation-menu/index.d.ts +1 -0
  128. package/dist/components/navigation-menu/index.js +2 -0
  129. package/dist/components/number-field/NumberField.d.ts +53 -0
  130. package/dist/components/number-field/NumberField.js +72 -0
  131. package/dist/components/number-field/NumberField.js.map +1 -0
  132. package/dist/components/number-field/index.d.ts +1 -0
  133. package/dist/components/number-field/index.js +2 -0
  134. package/dist/components/otp-field/OtpField.d.ts +33 -0
  135. package/dist/components/otp-field/OtpField.js +31 -0
  136. package/dist/components/otp-field/OtpField.js.map +1 -0
  137. package/dist/components/otp-field/index.d.ts +1 -0
  138. package/dist/components/otp-field/index.js +2 -0
  139. package/dist/components/pagination/Pagination.d.ts +17 -0
  140. package/dist/components/pagination/Pagination.js +75 -0
  141. package/dist/components/pagination/Pagination.js.map +1 -0
  142. package/dist/components/pagination/index.d.ts +1 -0
  143. package/dist/components/pagination/index.js +2 -0
  144. package/dist/components/popover/Popover.d.ts +73 -0
  145. package/dist/components/popover/Popover.js +97 -0
  146. package/dist/components/popover/Popover.js.map +1 -0
  147. package/dist/components/popover/index.d.ts +1 -0
  148. package/dist/components/popover/index.js +2 -0
  149. package/dist/components/preview-card/PreviewCard.d.ts +60 -0
  150. package/dist/components/preview-card/PreviewCard.js +83 -0
  151. package/dist/components/preview-card/PreviewCard.js.map +1 -0
  152. package/dist/components/preview-card/index.d.ts +1 -0
  153. package/dist/components/preview-card/index.js +2 -0
  154. package/dist/components/progress/Progress.d.ts +36 -0
  155. package/dist/components/progress/Progress.js +45 -0
  156. package/dist/components/progress/Progress.js.map +1 -0
  157. package/dist/components/progress/index.d.ts +1 -0
  158. package/dist/components/progress/index.js +2 -0
  159. package/dist/components/radio/Radio.d.ts +39 -0
  160. package/dist/components/radio/Radio.js +39 -0
  161. package/dist/components/radio/Radio.js.map +1 -0
  162. package/dist/components/radio/index.d.ts +1 -0
  163. package/dist/components/radio/index.js +2 -0
  164. package/dist/components/resizable/Resizable.d.ts +35 -0
  165. package/dist/components/resizable/Resizable.js +38 -0
  166. package/dist/components/resizable/Resizable.js.map +1 -0
  167. package/dist/components/resizable/index.d.ts +1 -0
  168. package/dist/components/resizable/index.js +2 -0
  169. package/dist/components/scroll-area/ScrollArea.d.ts +37 -0
  170. package/dist/components/scroll-area/ScrollArea.js +52 -0
  171. package/dist/components/scroll-area/ScrollArea.js.map +1 -0
  172. package/dist/components/scroll-area/index.d.ts +1 -0
  173. package/dist/components/scroll-area/index.js +2 -0
  174. package/dist/components/select/Select.d.ts +94 -0
  175. package/dist/components/select/Select.js +151 -0
  176. package/dist/components/select/Select.js.map +1 -0
  177. package/dist/components/select/index.d.ts +1 -0
  178. package/dist/components/select/index.js +2 -0
  179. package/dist/components/separator/Separator.d.ts +29 -0
  180. package/dist/components/separator/Separator.js +20 -0
  181. package/dist/components/separator/Separator.js.map +1 -0
  182. package/dist/components/separator/index.d.ts +1 -0
  183. package/dist/components/separator/index.js +2 -0
  184. package/dist/components/slider/Slider.d.ts +53 -0
  185. package/dist/components/slider/Slider.js +70 -0
  186. package/dist/components/slider/Slider.js.map +1 -0
  187. package/dist/components/slider/index.d.ts +1 -0
  188. package/dist/components/slider/index.js +2 -0
  189. package/dist/components/switch/Switch.d.ts +28 -0
  190. package/dist/components/switch/Switch.js +31 -0
  191. package/dist/components/switch/Switch.js.map +1 -0
  192. package/dist/components/switch/index.d.ts +1 -0
  193. package/dist/components/switch/index.js +2 -0
  194. package/dist/components/tabs/Tabs.d.ts +41 -0
  195. package/dist/components/tabs/Tabs.js +45 -0
  196. package/dist/components/tabs/Tabs.js.map +1 -0
  197. package/dist/components/tabs/index.d.ts +1 -0
  198. package/dist/components/tabs/index.js +2 -0
  199. package/dist/components/toast/Toast.d.ts +70 -0
  200. package/dist/components/toast/Toast.js +95 -0
  201. package/dist/components/toast/Toast.js.map +1 -0
  202. package/dist/components/toast/index.d.ts +1 -0
  203. package/dist/components/toast/index.js +2 -0
  204. package/dist/components/toggle/Toggle.d.ts +38 -0
  205. package/dist/components/toggle/Toggle.js +30 -0
  206. package/dist/components/toggle/Toggle.js.map +1 -0
  207. package/dist/components/toggle/index.d.ts +1 -0
  208. package/dist/components/toggle/index.js +2 -0
  209. package/dist/components/toolbar/Toolbar.d.ts +50 -0
  210. package/dist/components/toolbar/Toolbar.js +59 -0
  211. package/dist/components/toolbar/Toolbar.js.map +1 -0
  212. package/dist/components/toolbar/index.d.ts +1 -0
  213. package/dist/components/toolbar/index.js +2 -0
  214. package/dist/components/tooltip/Tooltip.d.ts +58 -0
  215. package/dist/components/tooltip/Tooltip.js +57 -0
  216. package/dist/components/tooltip/Tooltip.js.map +1 -0
  217. package/dist/components/tooltip/index.d.ts +1 -0
  218. package/dist/components/tooltip/index.js +2 -0
  219. package/dist/index.d.ts +60 -0
  220. package/dist/index.js +48 -0
  221. package/dist/lib/cn.d.ts +3 -0
  222. package/dist/lib/cn.js +29 -0
  223. package/dist/lib/cn.js.map +1 -0
  224. package/dist/styles.css +2 -0
  225. package/dist/theme.css +109 -0
  226. package/package.json +131 -0
@@ -0,0 +1,44 @@
1
+ import { Avatar as BaseAvatar } from '@base-ui/react/avatar';
2
+ import { ComponentProps } from 'react';
3
+ /**
4
+ * Avatar — Material 3 styled wrapper over Base UI's headless Avatar.
5
+ * Behaviour/accessibility (image load tracking, fallback swap): Base UI
6
+ * (https://base-ui.com/react/components/avatar).
7
+ * Visuals: M3 avatar anatomy — circular shape, surface-container fill,
8
+ * on-surface-variant initials in the label/title type scale, size tokens
9
+ * 24/32/40/48/64. Stack mirrors the overlapping avatar-group pattern.
10
+ * Design refs: port/core/ui/components/avatar, port/core/ui/components/avatar-stack
11
+ * (see CLAUDE.md).
12
+ *
13
+ * Compound API mirrors Base UI (plus a layout-only Stack):
14
+ * <Avatar.Root size="md">
15
+ * <Avatar.Image src="…" />
16
+ * <Avatar.Fallback>JD</Avatar.Fallback>
17
+ * </Avatar.Root>
18
+ *
19
+ * <Avatar.Stack>
20
+ * <Avatar.Root>…</Avatar.Root>
21
+ * <Avatar.Root>…</Avatar.Root>
22
+ * </Avatar.Stack>
23
+ */
24
+ export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
25
+ type RootProps = ComponentProps<typeof BaseAvatar.Root> & {
26
+ /** M3 size token: xs 24, sm 32, md 40 (default), lg 48, xl 64. */
27
+ size?: AvatarSize;
28
+ };
29
+ declare function Root({ className, size, ...props }: RootProps): import("react").JSX.Element;
30
+ declare function Image({ className, ...props }: ComponentProps<typeof BaseAvatar.Image>): import("react").JSX.Element;
31
+ declare function Fallback({ className, ...props }: ComponentProps<typeof BaseAvatar.Fallback>): import("react").JSX.Element;
32
+ /**
33
+ * Overlapping avatar group (layout-only, no Base UI part). Each child avatar
34
+ * gets a surface-colored ring so overlaps read cleanly, plus a small hover
35
+ * lift, mirroring port/core/ui/components/avatar-stack.
36
+ */
37
+ declare function Stack({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
38
+ export declare const Avatar: {
39
+ Root: typeof Root;
40
+ Image: typeof Image;
41
+ Fallback: typeof Fallback;
42
+ Stack: typeof Stack;
43
+ };
44
+ export { Root, Image, Fallback, Stack };
@@ -0,0 +1,45 @@
1
+ import { cn as e } from "../../lib/cn.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ import { Avatar as n } from "@base-ui/react/avatar";
4
+ //#region src/components/avatar/Avatar.tsx
5
+ var r = {
6
+ xs: "size-6 text-label-small",
7
+ sm: "size-8 text-label-medium",
8
+ md: "size-10 text-label-large",
9
+ lg: "size-12 text-title-medium",
10
+ xl: "size-16 text-title-large"
11
+ };
12
+ function i({ className: i, size: a = "md", ...o }) {
13
+ return /* @__PURE__ */ t(n.Root, {
14
+ className: e("relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden", "rounded-full bg-surface-container align-middle font-medium text-on-surface-variant", r[a], i),
15
+ ...o
16
+ });
17
+ }
18
+ function a({ className: r, ...i }) {
19
+ return /* @__PURE__ */ t(n.Image, {
20
+ className: e("size-full rounded-[inherit] object-cover", "transition-opacity duration-200 ease-out data-[starting-style]:opacity-0", r),
21
+ ...i
22
+ });
23
+ }
24
+ function o({ className: r, ...i }) {
25
+ return /* @__PURE__ */ t(n.Fallback, {
26
+ className: e("flex size-full items-center justify-center leading-none", r),
27
+ ...i
28
+ });
29
+ }
30
+ function s({ className: n, ...r }) {
31
+ return /* @__PURE__ */ t("div", {
32
+ className: e("flex flex-row items-center -space-x-2", "*:ring-2 *:ring-surface", "*:transition-transform *:duration-200 *:ease-out *:hover:-translate-y-0.5", n),
33
+ ...r
34
+ });
35
+ }
36
+ var c = {
37
+ Root: i,
38
+ Image: a,
39
+ Fallback: o,
40
+ Stack: s
41
+ };
42
+ //#endregion
43
+ export { c as Avatar, o as Fallback, a as Image, i as Root, s as Stack };
44
+
45
+ //# sourceMappingURL=Avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.js","names":[],"sources":["../../../src/components/avatar/Avatar.tsx"],"sourcesContent":["import { Avatar as BaseAvatar } from '@base-ui/react/avatar'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * Avatar — Material 3 styled wrapper over Base UI's headless Avatar.\n * Behaviour/accessibility (image load tracking, fallback swap): Base UI\n * (https://base-ui.com/react/components/avatar).\n * Visuals: M3 avatar anatomy — circular shape, surface-container fill,\n * on-surface-variant initials in the label/title type scale, size tokens\n * 24/32/40/48/64. Stack mirrors the overlapping avatar-group pattern.\n * Design refs: port/core/ui/components/avatar, port/core/ui/components/avatar-stack\n * (see CLAUDE.md).\n *\n * Compound API mirrors Base UI (plus a layout-only Stack):\n * <Avatar.Root size=\"md\">\n * <Avatar.Image src=\"…\" />\n * <Avatar.Fallback>JD</Avatar.Fallback>\n * </Avatar.Root>\n *\n * <Avatar.Stack>\n * <Avatar.Root>…</Avatar.Root>\n * <Avatar.Root>…</Avatar.Root>\n * </Avatar.Stack>\n */\n\nexport type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n\nconst sizeClasses: Record<AvatarSize, string> = {\n xs: 'size-6 text-label-small',\n sm: 'size-8 text-label-medium',\n md: 'size-10 text-label-large',\n lg: 'size-12 text-title-medium',\n xl: 'size-16 text-title-large',\n}\n\ntype RootProps = ComponentProps<typeof BaseAvatar.Root> & {\n /** M3 size token: xs 24, sm 32, md 40 (default), lg 48, xl 64. */\n size?: AvatarSize\n}\n\nfunction Root({ className, size = 'md', ...props }: RootProps) {\n return (\n <BaseAvatar.Root\n className={cn(\n 'relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden',\n 'rounded-full bg-surface-container align-middle font-medium text-on-surface-variant',\n sizeClasses[size],\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Image({ className, ...props }: ComponentProps<typeof BaseAvatar.Image>) {\n return (\n <BaseAvatar.Image\n className={cn(\n 'size-full rounded-[inherit] object-cover',\n 'transition-opacity duration-200 ease-out data-[starting-style]:opacity-0',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Fallback({ className, ...props }: ComponentProps<typeof BaseAvatar.Fallback>) {\n return (\n <BaseAvatar.Fallback\n className={cn('flex size-full items-center justify-center leading-none', className)}\n {...props}\n />\n )\n}\n\n/**\n * Overlapping avatar group (layout-only, no Base UI part). Each child avatar\n * gets a surface-colored ring so overlaps read cleanly, plus a small hover\n * lift, mirroring port/core/ui/components/avatar-stack.\n */\nfunction Stack({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n className={cn(\n 'flex flex-row items-center -space-x-2',\n '*:ring-2 *:ring-surface',\n '*:transition-transform *:duration-200 *:ease-out *:hover:-translate-y-0.5',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport const Avatar = { Root, Image, Fallback, Stack }\nexport { Root, Image, Fallback, Stack }\n"],"mappings":";;;;AA6BA,IAAM,IAA0C;CAC9C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAOA,SAAS,EAAK,EAAE,cAAW,UAAO,MAAM,GAAG,KAAoB;CAC7D,OACE,kBAAC,EAAW,MAAZ;EACE,WAAW,EACT,yFACA,sFACA,EAAY,IACZ,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAkD;CAC/E,OACE,kBAAC,EAAW,OAAZ;EACE,WAAW,EACT,4CACA,4EACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAS,EAAE,cAAW,GAAG,KAAqD;CACrF,OACE,kBAAC,EAAW,UAAZ;EACE,WAAW,EAAG,2DAA2D,CAAS;EAClF,GAAI;CACL,CAAA;AAEL;AAOA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAgC;CAC7D,OACE,kBAAC,OAAD;EACE,WAAW,EACT,yCACA,2BACA,6EACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,IAAS;CAAE;CAAM;CAAO;CAAU;AAAM"}
@@ -0,0 +1,2 @@
1
+ export { Avatar, Root, Image, Fallback, Stack } from './Avatar';
2
+ export type { AvatarSize } from './Avatar';
@@ -0,0 +1,2 @@
1
+ import { Avatar as e, Fallback as t, Image as n, Root as r, Stack as i } from "./Avatar.js";
2
+ export { e as Avatar, t as Fallback, n as Image, r as Root, i as Stack };
@@ -0,0 +1,43 @@
1
+ import { ComponentProps, ReactNode } from 'react';
2
+ /**
3
+ * Badge — Material 3 notification badges, ported from
4
+ * port/core/ui/components/badge (Badge / DotBadge / OnIconBadge) + the
5
+ * .badge/.dotBadge/.onIconBadge classes in port/styles/globals.css
6
+ * (see CLAUDE.md). Pure presentational divs — no headless primitive needed.
7
+ *
8
+ * Visuals: error fill with on-error label-small text. Badge is the 20px
9
+ * pill with 4px-gap icon slots; DotBadge is the bare 12px dot; OnIconBadge
10
+ * is the absolutely-positioned min-8px count bubble for icon corners.
11
+ *
12
+ * Port API (prop names preserved):
13
+ * <Badge text="Badge" iconLeft={…} icon={…} iconRight={…} />
14
+ * <Badge>Text</Badge>
15
+ * <DotBadge />
16
+ * <div className="relative">…icon…<OnIconBadge count={12} /></div>
17
+ */
18
+ export type BadgeProps = ComponentProps<'div'> & {
19
+ /** Badge label (port API; children work too). */
20
+ text?: string;
21
+ /** Centered icon slot after the label — port's icon-only badge. */
22
+ icon?: ReactNode;
23
+ /** Icon before the label. */
24
+ iconLeft?: ReactNode;
25
+ /** Icon after the label (outermost trailing slot). */
26
+ iconRight?: ReactNode;
27
+ };
28
+ /** 20px pill badge with label text and optional icon slots (port `.badge`). */
29
+ declare function Badge({ className, text, icon, iconLeft, iconRight, children, ...props }: BadgeProps): import("react").JSX.Element;
30
+ export type DotBadgeProps = ComponentProps<'div'>;
31
+ /** Bare 12px error dot — presence-only indicator (port `.dotBadge`). */
32
+ declare function DotBadge({ className, ...props }: DotBadgeProps): import("react").JSX.Element;
33
+ export type OnIconBadgeProps = ComponentProps<'div'> & {
34
+ /** Count shown in the bubble (port API; children work too). */
35
+ count?: string | number;
36
+ };
37
+ /**
38
+ * Count bubble for icon corners (port `.onIconBadge`). Absolutely positioned —
39
+ * place it inside a `relative` wrapper and offset via className. Without a
40
+ * count it collapses to the minimum 8px dot.
41
+ */
42
+ declare function OnIconBadge({ className, count, children, ...props }: OnIconBadgeProps): import("react").JSX.Element;
43
+ export { Badge, DotBadge, OnIconBadge };
@@ -0,0 +1,32 @@
1
+ import { cn as e } from "../../lib/cn.js";
2
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
+ //#region src/components/badge/Badge.tsx
4
+ function r({ className: t, text: r, icon: i, iconLeft: a, iconRight: o, children: s, ...c }) {
5
+ return /* @__PURE__ */ n("div", {
6
+ className: e("flex h-[20px] w-max cursor-pointer items-center gap-[4px] rounded-full", "bg-error px-[6px] py-[6px] text-label-small text-on-error", t),
7
+ ...c,
8
+ children: [
9
+ a,
10
+ r || s,
11
+ i,
12
+ o
13
+ ]
14
+ });
15
+ }
16
+ function i({ className: n, ...r }) {
17
+ return /* @__PURE__ */ t("div", {
18
+ className: e("flex h-[12px] w-[12px] cursor-pointer rounded-full bg-error px-[4px] py-[4px] text-on-error", n),
19
+ ...r
20
+ });
21
+ }
22
+ function a({ className: n, count: r, children: i, ...a }) {
23
+ return /* @__PURE__ */ t("div", {
24
+ className: e("absolute flex min-h-[8px] min-w-[8px] cursor-pointer rounded-full", "bg-error px-[4px] text-label-small text-on-error", n),
25
+ ...a,
26
+ children: r ?? i
27
+ });
28
+ }
29
+ //#endregion
30
+ export { r as Badge, i as DotBadge, a as OnIconBadge };
31
+
32
+ //# sourceMappingURL=Badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.js","names":[],"sources":["../../../src/components/badge/Badge.tsx"],"sourcesContent":["import { cn } from '#/lib/cn'\n\nimport type { ComponentProps, ReactNode } from 'react'\n\n/**\n * Badge — Material 3 notification badges, ported from\n * port/core/ui/components/badge (Badge / DotBadge / OnIconBadge) + the\n * .badge/.dotBadge/.onIconBadge classes in port/styles/globals.css\n * (see CLAUDE.md). Pure presentational divs — no headless primitive needed.\n *\n * Visuals: error fill with on-error label-small text. Badge is the 20px\n * pill with 4px-gap icon slots; DotBadge is the bare 12px dot; OnIconBadge\n * is the absolutely-positioned min-8px count bubble for icon corners.\n *\n * Port API (prop names preserved):\n * <Badge text=\"Badge\" iconLeft={…} icon={…} iconRight={…} />\n * <Badge>Text</Badge>\n * <DotBadge />\n * <div className=\"relative\">…icon…<OnIconBadge count={12} /></div>\n */\n\nexport type BadgeProps = ComponentProps<'div'> & {\n /** Badge label (port API; children work too). */\n text?: string\n /** Centered icon slot after the label — port's icon-only badge. */\n icon?: ReactNode\n /** Icon before the label. */\n iconLeft?: ReactNode\n /** Icon after the label (outermost trailing slot). */\n iconRight?: ReactNode\n}\n\n/** 20px pill badge with label text and optional icon slots (port `.badge`). */\nfunction Badge({ className, text, icon, iconLeft, iconRight, children, ...props }: BadgeProps) {\n return (\n <div\n className={cn(\n // Port .badge: 20px-tall w-max pill, error fill, label-small on-error\n // text, 4px slot gap, 6px padding (cursor-pointer kept from port).\n 'flex h-[20px] w-max cursor-pointer items-center gap-[4px] rounded-full',\n 'bg-error px-[6px] py-[6px] text-label-small text-on-error',\n className,\n )}\n {...props}\n >\n {iconLeft}\n {text || children}\n {icon}\n {iconRight}\n </div>\n )\n}\n\nexport type DotBadgeProps = ComponentProps<'div'>\n\n/** Bare 12px error dot — presence-only indicator (port `.dotBadge`). */\nfunction DotBadge({ className, ...props }: DotBadgeProps) {\n return (\n <div\n className={cn(\n // Port .dotBadge: fixed 12px error circle.\n 'flex h-[12px] w-[12px] cursor-pointer rounded-full bg-error px-[4px] py-[4px] text-on-error',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport type OnIconBadgeProps = ComponentProps<'div'> & {\n /** Count shown in the bubble (port API; children work too). */\n count?: string | number\n}\n\n/**\n * Count bubble for icon corners (port `.onIconBadge`). Absolutely positioned —\n * place it inside a `relative` wrapper and offset via className. Without a\n * count it collapses to the minimum 8px dot.\n */\nfunction OnIconBadge({ className, count, children, ...props }: OnIconBadgeProps) {\n return (\n <div\n className={cn(\n // Port .onIconBadge: absolute min-8px error bubble, grows with count.\n 'absolute flex min-h-[8px] min-w-[8px] cursor-pointer rounded-full',\n 'bg-error px-[4px] text-label-small text-on-error',\n className,\n )}\n {...props}\n >\n {count ?? children}\n </div>\n )\n}\n\nexport { Badge, DotBadge, OnIconBadge }\n"],"mappings":";;;AAiCA,SAAS,EAAM,EAAE,cAAW,SAAM,SAAM,aAAU,cAAW,aAAU,GAAG,KAAqB;CAC7F,OACE,kBAAC,OAAD;EACE,WAAW,EAGT,0EACA,6DACA,CACF;EACA,GAAI;YARN;GAUG;GACA,KAAQ;GACR;GACA;EACE;;AAET;AAKA,SAAS,EAAS,EAAE,cAAW,GAAG,KAAwB;CACxD,OACE,kBAAC,OAAD;EACE,WAAW,EAET,+FACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAYA,SAAS,EAAY,EAAE,cAAW,UAAO,aAAU,GAAG,KAA2B;CAC/E,OACE,kBAAC,OAAD;EACE,WAAW,EAET,qEACA,oDACA,CACF;EACA,GAAI;YAEH,KAAS;CACP,CAAA;AAET"}
@@ -0,0 +1,2 @@
1
+ export { Badge, DotBadge, OnIconBadge } from './Badge';
2
+ export type { BadgeProps, DotBadgeProps, OnIconBadgeProps } from './Badge';
@@ -0,0 +1,2 @@
1
+ import { Badge as e, DotBadge as t, OnIconBadge as n } from "./Badge.js";
2
+ export { e as Badge, t as DotBadge, n as OnIconBadge };
@@ -0,0 +1,60 @@
1
+ import { Button as BaseButton } from '@base-ui/react/button';
2
+ import { ComponentProps } from 'react';
3
+ /**
4
+ * Button — Material 3 styled wrapper over Base UI's headless Button.
5
+ * Behaviour/accessibility (native <button>, focusableWhenDisabled):
6
+ * Base UI (https://base-ui.com/react/components/button).
7
+ * Visuals: M3 common button anatomy — 40px height, full corner, label-large,
8
+ * state layers, 0.38 disabled opacity — plus icon button and FAB shapes.
9
+ * Design ref: port/core/ui/components/button (common-button, icon-button,
10
+ * fab-standard, fab-extended) + .btn/.filled/.tonal/.outlined/.elevated/.text
11
+ * classes in port/styles/globals.css (see CLAUDE.md).
12
+ *
13
+ * Compound API:
14
+ * <Button.Root variant="filled|tonal|outlined|elevated|text">Label</Button.Root>
15
+ * <Button.Icon variant="standard|filled|tonal|outlined"><Plus /></Button.Icon>
16
+ * <Button.Fab size="small|medium|large" variant="primary|surface|secondary|tertiary"><Plus /></Button.Fab>
17
+ * <Button.ExtendedFab variant="primary|surface|secondary|tertiary"><Plus />Label</Button.ExtendedFab>
18
+ */
19
+ type ButtonVariant = 'filled' | 'tonal' | 'outlined' | 'elevated' | 'text';
20
+ type RootProps = ComponentProps<typeof BaseButton> & {
21
+ /** M3 common-button color/emphasis style. @default 'filled' */
22
+ variant?: ButtonVariant;
23
+ };
24
+ /** M3 common button — 40px tall, pill shaped, label-large. */
25
+ declare function Root({ className, variant, ...props }: RootProps): import("react").JSX.Element;
26
+ type IconButtonVariant = 'standard' | 'filled' | 'tonal' | 'outlined';
27
+ type IconButtonProps = ComponentProps<typeof BaseButton> & {
28
+ /** M3 icon-button style. @default 'standard' */
29
+ variant?: IconButtonVariant;
30
+ };
31
+ /** M3 icon button — 40×40 circular target around a 24px icon. */
32
+ declare function IconButton({ className, variant, ...props }: IconButtonProps): import("react").JSX.Element;
33
+ type FabVariant = 'primary' | 'surface' | 'secondary' | 'tertiary';
34
+ declare const fabSizeClasses: {
35
+ readonly small: "size-10 rounded-medium [&_svg]:size-6";
36
+ readonly medium: "size-14 rounded-large [&_svg]:size-6";
37
+ readonly large: "size-24 rounded-extra-large [&_svg]:size-9";
38
+ };
39
+ type FabProps = ComponentProps<typeof BaseButton> & {
40
+ /** M3 FAB container color. @default 'primary' */
41
+ variant?: FabVariant;
42
+ /** M3 FAB size — small 40px, medium 56px, large 96px. @default 'medium' */
43
+ size?: keyof typeof fabSizeClasses;
44
+ };
45
+ /** M3 floating action button — elevated container around a single icon. */
46
+ declare function Fab({ className, variant, size, ...props }: FabProps): import("react").JSX.Element;
47
+ type ExtendedFabProps = ComponentProps<typeof BaseButton> & {
48
+ /** M3 FAB container color. @default 'primary' */
49
+ variant?: FabVariant;
50
+ };
51
+ /** M3 extended FAB — 56px tall pill with icon + label-large text. */
52
+ declare function ExtendedFab({ className, variant, ...props }: ExtendedFabProps): import("react").JSX.Element;
53
+ export declare const Button: {
54
+ Root: typeof Root;
55
+ Icon: typeof IconButton;
56
+ Fab: typeof Fab;
57
+ ExtendedFab: typeof ExtendedFab;
58
+ };
59
+ export { Root, IconButton, Fab, ExtendedFab };
60
+ export type { ButtonVariant, IconButtonVariant, FabVariant };
@@ -0,0 +1,61 @@
1
+ import { cn as e } from "../../lib/cn.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ import { Button as n } from "@base-ui/react/button";
4
+ //#region src/components/button/Button.tsx
5
+ var r = {
6
+ filled: "bg-primary text-on-primary hover:bg-primary-hover",
7
+ tonal: "bg-secondary-container text-on-secondary-container hover:bg-secondary-container-hover",
8
+ outlined: "border border-outline text-primary hover:bg-primary/[0.08]",
9
+ elevated: "bg-surface-container-low text-primary shadow-mm-1 hover:bg-primary/[0.08] hover:shadow-mm-2",
10
+ text: "px-3 text-primary hover:bg-primary/[0.08]"
11
+ };
12
+ function i({ className: i, variant: a = "filled", ...o }) {
13
+ return /* @__PURE__ */ t(n, {
14
+ className: e("inline-flex h-10 w-max cursor-pointer items-center justify-center gap-2 rounded-full px-6", "text-label-large transition-all", "[&_svg]:size-[18px] [&_svg]:shrink-0", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary", "disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none", r[a], i),
15
+ ...o
16
+ });
17
+ }
18
+ var a = {
19
+ standard: "text-on-surface-variant hover:bg-on-surface/[0.08]",
20
+ filled: "bg-primary text-on-primary hover:bg-primary-hover",
21
+ tonal: "bg-secondary-container text-on-secondary-container hover:bg-secondary-container-hover",
22
+ outlined: "border border-outline text-on-surface-variant hover:bg-on-surface/[0.08]"
23
+ };
24
+ function o({ className: r, variant: i = "standard", ...o }) {
25
+ return /* @__PURE__ */ t(n, {
26
+ className: e("inline-flex size-10 cursor-pointer items-center justify-center rounded-full", "transition-colors [&_svg]:size-6 [&_svg]:shrink-0", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary", "disabled:cursor-not-allowed disabled:opacity-[0.38]", a[i], r),
27
+ ...o
28
+ });
29
+ }
30
+ var s = {
31
+ primary: "bg-primary-container text-on-primary-container hover:bg-primary-container-hover",
32
+ surface: "bg-surface-container-high text-primary hover:bg-primary/[0.08]",
33
+ secondary: "bg-secondary-container text-on-secondary-container hover:bg-secondary-container-hover",
34
+ tertiary: "bg-tertiary-container text-on-tertiary-container hover:bg-tertiary-container-hover"
35
+ }, c = {
36
+ small: "size-10 rounded-medium [&_svg]:size-6",
37
+ medium: "size-14 rounded-large [&_svg]:size-6",
38
+ large: "size-24 rounded-extra-large [&_svg]:size-9"
39
+ };
40
+ function l({ className: r, variant: i = "primary", size: a = "medium", ...o }) {
41
+ return /* @__PURE__ */ t(n, {
42
+ className: e("inline-flex cursor-pointer items-center justify-center shadow-mm-3", "transition-all hover:shadow-mm-4 [&_svg]:shrink-0", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary", "disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none", c[a], s[i], r),
43
+ ...o
44
+ });
45
+ }
46
+ function u({ className: r, variant: i = "primary", ...a }) {
47
+ return /* @__PURE__ */ t(n, {
48
+ className: e("inline-flex h-14 w-max cursor-pointer items-center justify-center gap-3 rounded-large px-4", "text-label-large shadow-mm-3 transition-all hover:shadow-mm-4", "[&_svg]:size-6 [&_svg]:shrink-0", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary", "disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none", s[i], r),
49
+ ...a
50
+ });
51
+ }
52
+ var d = {
53
+ Root: i,
54
+ Icon: o,
55
+ Fab: l,
56
+ ExtendedFab: u
57
+ };
58
+ //#endregion
59
+ export { d as Button, u as ExtendedFab, l as Fab, o as IconButton, i as Root };
60
+
61
+ //# sourceMappingURL=Button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.js","names":[],"sources":["../../../src/components/button/Button.tsx"],"sourcesContent":["import { Button as BaseButton } from '@base-ui/react/button'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * Button — Material 3 styled wrapper over Base UI's headless Button.\n * Behaviour/accessibility (native <button>, focusableWhenDisabled):\n * Base UI (https://base-ui.com/react/components/button).\n * Visuals: M3 common button anatomy — 40px height, full corner, label-large,\n * state layers, 0.38 disabled opacity — plus icon button and FAB shapes.\n * Design ref: port/core/ui/components/button (common-button, icon-button,\n * fab-standard, fab-extended) + .btn/.filled/.tonal/.outlined/.elevated/.text\n * classes in port/styles/globals.css (see CLAUDE.md).\n *\n * Compound API:\n * <Button.Root variant=\"filled|tonal|outlined|elevated|text\">Label</Button.Root>\n * <Button.Icon variant=\"standard|filled|tonal|outlined\"><Plus /></Button.Icon>\n * <Button.Fab size=\"small|medium|large\" variant=\"primary|surface|secondary|tertiary\"><Plus /></Button.Fab>\n * <Button.ExtendedFab variant=\"primary|surface|secondary|tertiary\"><Plus />Label</Button.ExtendedFab>\n */\n\ntype ButtonVariant = 'filled' | 'tonal' | 'outlined' | 'elevated' | 'text'\n\nconst rootVariantClasses: Record<ButtonVariant, string> = {\n filled: 'bg-primary text-on-primary hover:bg-primary-hover',\n tonal:\n 'bg-secondary-container text-on-secondary-container hover:bg-secondary-container-hover',\n outlined: 'border border-outline text-primary hover:bg-primary/[0.08]',\n elevated:\n 'bg-surface-container-low text-primary shadow-mm-1 hover:bg-primary/[0.08] hover:shadow-mm-2',\n text: 'px-3 text-primary hover:bg-primary/[0.08]',\n}\n\ntype RootProps = ComponentProps<typeof BaseButton> & {\n /** M3 common-button color/emphasis style. @default 'filled' */\n variant?: ButtonVariant\n}\n\n/** M3 common button — 40px tall, pill shaped, label-large. */\nfunction Root({ className, variant = 'filled', ...props }: RootProps) {\n return (\n <BaseButton\n className={cn(\n 'inline-flex h-10 w-max cursor-pointer items-center justify-center gap-2 rounded-full px-6',\n 'text-label-large transition-all',\n '[&_svg]:size-[18px] [&_svg]:shrink-0',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none',\n rootVariantClasses[variant],\n className,\n )}\n {...props}\n />\n )\n}\n\ntype IconButtonVariant = 'standard' | 'filled' | 'tonal' | 'outlined'\n\nconst iconVariantClasses: Record<IconButtonVariant, string> = {\n standard: 'text-on-surface-variant hover:bg-on-surface/[0.08]',\n filled: 'bg-primary text-on-primary hover:bg-primary-hover',\n tonal:\n 'bg-secondary-container text-on-secondary-container hover:bg-secondary-container-hover',\n outlined: 'border border-outline text-on-surface-variant hover:bg-on-surface/[0.08]',\n}\n\ntype IconButtonProps = ComponentProps<typeof BaseButton> & {\n /** M3 icon-button style. @default 'standard' */\n variant?: IconButtonVariant\n}\n\n/** M3 icon button — 40×40 circular target around a 24px icon. */\nfunction IconButton({ className, variant = 'standard', ...props }: IconButtonProps) {\n return (\n <BaseButton\n className={cn(\n 'inline-flex size-10 cursor-pointer items-center justify-center rounded-full',\n 'transition-colors [&_svg]:size-6 [&_svg]:shrink-0',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]',\n iconVariantClasses[variant],\n className,\n )}\n {...props}\n />\n )\n}\n\ntype FabVariant = 'primary' | 'surface' | 'secondary' | 'tertiary'\n\nconst fabVariantClasses: Record<FabVariant, string> = {\n primary:\n 'bg-primary-container text-on-primary-container hover:bg-primary-container-hover',\n surface: 'bg-surface-container-high text-primary hover:bg-primary/[0.08]',\n secondary:\n 'bg-secondary-container text-on-secondary-container hover:bg-secondary-container-hover',\n tertiary:\n 'bg-tertiary-container text-on-tertiary-container hover:bg-tertiary-container-hover',\n}\n\nconst fabSizeClasses = {\n small: 'size-10 rounded-medium [&_svg]:size-6',\n medium: 'size-14 rounded-large [&_svg]:size-6',\n large: 'size-24 rounded-extra-large [&_svg]:size-9',\n} as const\n\ntype FabProps = ComponentProps<typeof BaseButton> & {\n /** M3 FAB container color. @default 'primary' */\n variant?: FabVariant\n /** M3 FAB size — small 40px, medium 56px, large 96px. @default 'medium' */\n size?: keyof typeof fabSizeClasses\n}\n\n/** M3 floating action button — elevated container around a single icon. */\nfunction Fab({ className, variant = 'primary', size = 'medium', ...props }: FabProps) {\n return (\n <BaseButton\n className={cn(\n 'inline-flex cursor-pointer items-center justify-center shadow-mm-3',\n 'transition-all hover:shadow-mm-4 [&_svg]:shrink-0',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none',\n fabSizeClasses[size],\n fabVariantClasses[variant],\n className,\n )}\n {...props}\n />\n )\n}\n\ntype ExtendedFabProps = ComponentProps<typeof BaseButton> & {\n /** M3 FAB container color. @default 'primary' */\n variant?: FabVariant\n}\n\n/** M3 extended FAB — 56px tall pill with icon + label-large text. */\nfunction ExtendedFab({ className, variant = 'primary', ...props }: ExtendedFabProps) {\n return (\n <BaseButton\n className={cn(\n 'inline-flex h-14 w-max cursor-pointer items-center justify-center gap-3 rounded-large px-4',\n 'text-label-large shadow-mm-3 transition-all hover:shadow-mm-4',\n '[&_svg]:size-6 [&_svg]:shrink-0',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none',\n fabVariantClasses[variant],\n className,\n )}\n {...props}\n />\n )\n}\n\nexport const Button = { Root, Icon: IconButton, Fab, ExtendedFab }\nexport { Root, IconButton, Fab, ExtendedFab }\nexport type { ButtonVariant, IconButtonVariant, FabVariant }\n"],"mappings":";;;;AAwBA,IAAM,IAAoD;CACxD,QAAQ;CACR,OACE;CACF,UAAU;CACV,UACE;CACF,MAAM;AACR;AAQA,SAAS,EAAK,EAAE,cAAW,aAAU,UAAU,GAAG,KAAoB;CACpE,OACE,kBAAC,GAAD;EACE,WAAW,EACT,6FACA,mCACA,wCACA,wFACA,4EACA,EAAmB,IACnB,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAIA,IAAM,IAAwD;CAC5D,UAAU;CACV,QAAQ;CACR,OACE;CACF,UAAU;AACZ;AAQA,SAAS,EAAW,EAAE,cAAW,aAAU,YAAY,GAAG,KAA0B;CAClF,OACE,kBAAC,GAAD;EACE,WAAW,EACT,+EACA,qDACA,wFACA,uDACA,EAAmB,IACnB,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAIA,IAAM,IAAgD;CACpD,SACE;CACF,SAAS;CACT,WACE;CACF,UACE;AACJ,GAEM,IAAiB;CACrB,OAAO;CACP,QAAQ;CACR,OAAO;AACT;AAUA,SAAS,EAAI,EAAE,cAAW,aAAU,WAAW,UAAO,UAAU,GAAG,KAAmB;CACpF,OACE,kBAAC,GAAD;EACE,WAAW,EACT,sEACA,qDACA,wFACA,4EACA,EAAe,IACf,EAAkB,IAClB,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAQA,SAAS,EAAY,EAAE,cAAW,aAAU,WAAW,GAAG,KAA2B;CACnF,OACE,kBAAC,GAAD;EACE,WAAW,EACT,8FACA,iEACA,mCACA,wFACA,4EACA,EAAkB,IAClB,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,IAAS;CAAE;CAAM,MAAM;CAAY;CAAK;AAAY"}
@@ -0,0 +1 @@
1
+ export * from './Button';
@@ -0,0 +1,2 @@
1
+ import { Button as e, ExtendedFab as t, Fab as n, IconButton as r, Root as i } from "./Button.js";
2
+ export { e as Button, t as ExtendedFab, n as Fab, r as IconButton, i as Root };
@@ -0,0 +1,32 @@
1
+ import { Button } from '../../../components/button';
2
+ import { EmblaOptionsType } from 'embla-carousel';
3
+ import { ComponentProps } from 'react';
4
+ type RootProps = ComponentProps<'div'> & {
5
+ /** Embla options — `loop`, `align`, `slidesToScroll`, … @default {} */
6
+ options?: EmblaOptionsType;
7
+ };
8
+ /** Sets up the Embla engine and provides api + selection state to all parts. */
9
+ declare function Root({ options, className, children, ...props }: RootProps): import("react").JSX.Element;
10
+ /** Embla viewport (overflow-hidden) wrapping the flex track of slides. */
11
+ declare function Container({ className, children, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
12
+ /**
13
+ * One slide — set its width via flex basis (`basis-4/5` hero, `basis-1/3`
14
+ * multi-browse). The `pl-4` + container `-ml-4` pair is Embla's gap pattern.
15
+ */
16
+ declare function Slide({ className, children, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
17
+ type NavButtonProps = ComponentProps<typeof Button.Icon>;
18
+ /** Previous-slide icon button — disabled at the start when not looping. */
19
+ declare function Previous({ className, children, ...props }: NavButtonProps): import("react").JSX.Element;
20
+ /** Next-slide icon button — disabled at the end when not looping. */
21
+ declare function Next({ className, children, ...props }: NavButtonProps): import("react").JSX.Element;
22
+ /** M3 dot indicators — 8px dots; the active dot stretches to a 16px pill. */
23
+ declare function Dots({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
24
+ export declare const Carousel: {
25
+ Root: typeof Root;
26
+ Container: typeof Container;
27
+ Slide: typeof Slide;
28
+ Previous: typeof Previous;
29
+ Next: typeof Next;
30
+ Dots: typeof Dots;
31
+ };
32
+ export { Root, Container, Slide, Previous, Next, Dots };
@@ -0,0 +1,113 @@
1
+ import { cn as e } from "../../lib/cn.js";
2
+ import { Button as t } from "../button/Button.js";
3
+ import { ChevronLeft as n, ChevronRight as r } from "lucide-react";
4
+ import { jsx as i } from "react/jsx-runtime";
5
+ import { createContext as a, useContext as o, useEffect as s, useState as c } from "react";
6
+ import l from "embla-carousel-react";
7
+ //#region src/components/carousel/Carousel.tsx
8
+ var u = a(null);
9
+ function d() {
10
+ let e = o(u);
11
+ if (!e) throw Error("Carousel parts must be used within <Carousel.Root>");
12
+ return e;
13
+ }
14
+ function f({ options: t, className: n, children: r, ...a }) {
15
+ let [o, d] = l(t), [f, p] = c(0), [m, h] = c([]), [g, _] = c(!1), [v, y] = c(!1);
16
+ return s(() => {
17
+ if (!d) return;
18
+ let e = (e) => {
19
+ p(e.selectedScrollSnap()), _(e.canScrollPrev()), y(e.canScrollNext());
20
+ }, t = (t) => {
21
+ h(t.scrollSnapList()), e(t);
22
+ };
23
+ return t(d), d.on("select", e).on("reInit", t), () => {
24
+ d.off("select", e).off("reInit", t);
25
+ };
26
+ }, [d]), /* @__PURE__ */ i(u.Provider, {
27
+ value: {
28
+ api: d,
29
+ viewportRef: o,
30
+ selectedIndex: f,
31
+ scrollSnaps: m,
32
+ canScrollPrev: g,
33
+ canScrollNext: v
34
+ },
35
+ children: /* @__PURE__ */ i("div", {
36
+ role: "region",
37
+ "aria-roledescription": "carousel",
38
+ className: e("relative", n),
39
+ ...a,
40
+ children: r
41
+ })
42
+ });
43
+ }
44
+ function p({ className: t, children: n, ...r }) {
45
+ let { viewportRef: a } = d();
46
+ return /* @__PURE__ */ i("div", {
47
+ ref: a,
48
+ className: "overflow-hidden",
49
+ children: /* @__PURE__ */ i("div", {
50
+ className: e("-ml-4 flex touch-pan-y", t),
51
+ ...r,
52
+ children: n
53
+ })
54
+ });
55
+ }
56
+ function m({ className: t, children: n, ...r }) {
57
+ return /* @__PURE__ */ i("div", {
58
+ className: e("min-w-0 shrink-0 grow-0 basis-full pl-4", t),
59
+ ...r,
60
+ children: /* @__PURE__ */ i("div", {
61
+ className: "h-full overflow-hidden rounded-extra-large",
62
+ children: n
63
+ })
64
+ });
65
+ }
66
+ function h({ className: e, children: r, ...a }) {
67
+ let { api: o, canScrollPrev: s } = d();
68
+ return /* @__PURE__ */ i(t.Icon, {
69
+ "aria-label": "Previous slide",
70
+ disabled: !s,
71
+ onClick: () => o?.scrollPrev(),
72
+ className: e,
73
+ ...a,
74
+ children: r ?? /* @__PURE__ */ i(n, {})
75
+ });
76
+ }
77
+ function g({ className: e, children: n, ...a }) {
78
+ let { api: o, canScrollNext: s } = d();
79
+ return /* @__PURE__ */ i(t.Icon, {
80
+ "aria-label": "Next slide",
81
+ disabled: !s,
82
+ onClick: () => o?.scrollNext(),
83
+ className: e,
84
+ ...a,
85
+ children: n ?? /* @__PURE__ */ i(r, {})
86
+ });
87
+ }
88
+ function _({ className: t, ...n }) {
89
+ let { api: r, selectedIndex: a, scrollSnaps: o } = d();
90
+ return /* @__PURE__ */ i("div", {
91
+ className: e("flex items-center justify-center gap-2", t),
92
+ ...n,
93
+ children: o.map((t, n) => /* @__PURE__ */ i("button", {
94
+ type: "button",
95
+ "aria-label": `Go to slide ${n + 1}`,
96
+ "aria-current": n === a ? "true" : void 0,
97
+ onClick: () => r?.scrollTo(n),
98
+ className: e("h-2 cursor-pointer rounded-full transition-all duration-200 ease-out", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary", n === a ? "w-4 bg-primary" : "w-2 bg-on-surface-variant/40 hover:bg-on-surface-variant/60")
99
+ }, n))
100
+ });
101
+ }
102
+ var v = {
103
+ Root: f,
104
+ Container: p,
105
+ Slide: m,
106
+ Previous: h,
107
+ Next: g,
108
+ Dots: _
109
+ };
110
+ //#endregion
111
+ export { v as Carousel, p as Container, _ as Dots, g as Next, h as Previous, f as Root, m as Slide };
112
+
113
+ //# sourceMappingURL=Carousel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Carousel.js","names":[],"sources":["../../../src/components/carousel/Carousel.tsx"],"sourcesContent":["import { createContext, useContext, useEffect, useState } from 'react'\nimport useEmblaCarousel from 'embla-carousel-react'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { Button } from '#/components/button'\nimport { cn } from '#/lib/cn'\n\nimport type { EmblaCarouselType, EmblaOptionsType } from 'embla-carousel'\nimport type { ComponentProps } from 'react'\n\n/**\n * Carousel — Material 3 styled carousel over the Embla engine.\n * Behaviour (drag, snap, loop): embla-carousel-react (https://www.embla-carousel.com).\n * Visuals: M3 carousel — rounded-extra-large slides with gaps, icon-button\n * navigation, and a dot indicator row whose active dot stretches into a pill\n * (https://m3.material.io/components/carousel — see CLAUDE.md).\n *\n * Slide width comes from the slide's flex basis: `basis-4/5` reads as a hero\n * layout, `basis-1/3` as multi-browse.\n *\n * Compound API:\n * <Carousel.Root options={{ loop: true }}>\n * <Carousel.Container>\n * <Carousel.Slide className=\"basis-4/5\">…</Carousel.Slide>\n * </Carousel.Container>\n * <div className=\"mt-4 flex items-center justify-center gap-4\">\n * <Carousel.Previous />\n * <Carousel.Dots />\n * <Carousel.Next />\n * </div>\n * </Carousel.Root>\n */\n\ntype CarouselContextValue = {\n api: EmblaCarouselType | undefined\n viewportRef: ReturnType<typeof useEmblaCarousel>[0]\n selectedIndex: number\n scrollSnaps: Array<number>\n canScrollPrev: boolean\n canScrollNext: boolean\n}\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null)\n\nfunction useCarousel() {\n const context = useContext(CarouselContext)\n if (!context) throw new Error('Carousel parts must be used within <Carousel.Root>')\n return context\n}\n\ntype RootProps = ComponentProps<'div'> & {\n /** Embla options — `loop`, `align`, `slidesToScroll`, … @default {} */\n options?: EmblaOptionsType\n}\n\n/** Sets up the Embla engine and provides api + selection state to all parts. */\nfunction Root({ options, className, children, ...props }: RootProps) {\n const [viewportRef, api] = useEmblaCarousel(options)\n const [selectedIndex, setSelectedIndex] = useState(0)\n const [scrollSnaps, setScrollSnaps] = useState<Array<number>>([])\n const [canScrollPrev, setCanScrollPrev] = useState(false)\n const [canScrollNext, setCanScrollNext] = useState(false)\n\n useEffect(() => {\n if (!api) return\n const onSelect = (emblaApi: EmblaCarouselType) => {\n setSelectedIndex(emblaApi.selectedScrollSnap())\n setCanScrollPrev(emblaApi.canScrollPrev())\n setCanScrollNext(emblaApi.canScrollNext())\n }\n const onReInit = (emblaApi: EmblaCarouselType) => {\n setScrollSnaps(emblaApi.scrollSnapList())\n onSelect(emblaApi)\n }\n onReInit(api)\n api.on('select', onSelect).on('reInit', onReInit)\n return () => {\n api.off('select', onSelect).off('reInit', onReInit)\n }\n }, [api])\n\n return (\n <CarouselContext.Provider\n value={{ api, viewportRef, selectedIndex, scrollSnaps, canScrollPrev, canScrollNext }}\n >\n <div\n role=\"region\"\n aria-roledescription=\"carousel\"\n className={cn('relative', className)}\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n )\n}\n\n/** Embla viewport (overflow-hidden) wrapping the flex track of slides. */\nfunction Container({ className, children, ...props }: ComponentProps<'div'>) {\n const { viewportRef } = useCarousel()\n return (\n <div ref={viewportRef} className=\"overflow-hidden\">\n <div className={cn('-ml-4 flex touch-pan-y', className)} {...props}>\n {children}\n </div>\n </div>\n )\n}\n\n/**\n * One slide — set its width via flex basis (`basis-4/5` hero, `basis-1/3`\n * multi-browse). The `pl-4` + container `-ml-4` pair is Embla's gap pattern.\n */\nfunction Slide({ className, children, ...props }: ComponentProps<'div'>) {\n return (\n <div\n className={cn('min-w-0 shrink-0 grow-0 basis-full pl-4', className)}\n {...props}\n >\n <div className=\"h-full overflow-hidden rounded-extra-large\">{children}</div>\n </div>\n )\n}\n\ntype NavButtonProps = ComponentProps<typeof Button.Icon>\n\n/** Previous-slide icon button — disabled at the start when not looping. */\nfunction Previous({ className, children, ...props }: NavButtonProps) {\n const { api, canScrollPrev } = useCarousel()\n return (\n <Button.Icon\n aria-label=\"Previous slide\"\n disabled={!canScrollPrev}\n onClick={() => api?.scrollPrev()}\n className={className}\n {...props}\n >\n {children ?? <ChevronLeft />}\n </Button.Icon>\n )\n}\n\n/** Next-slide icon button — disabled at the end when not looping. */\nfunction Next({ className, children, ...props }: NavButtonProps) {\n const { api, canScrollNext } = useCarousel()\n return (\n <Button.Icon\n aria-label=\"Next slide\"\n disabled={!canScrollNext}\n onClick={() => api?.scrollNext()}\n className={className}\n {...props}\n >\n {children ?? <ChevronRight />}\n </Button.Icon>\n )\n}\n\n/** M3 dot indicators — 8px dots; the active dot stretches to a 16px pill. */\nfunction Dots({ className, ...props }: ComponentProps<'div'>) {\n const { api, selectedIndex, scrollSnaps } = useCarousel()\n return (\n <div className={cn('flex items-center justify-center gap-2', className)} {...props}>\n {scrollSnaps.map((_, index) => (\n <button\n key={index}\n type=\"button\"\n aria-label={`Go to slide ${index + 1}`}\n aria-current={index === selectedIndex ? 'true' : undefined}\n onClick={() => api?.scrollTo(index)}\n className={cn(\n 'h-2 cursor-pointer rounded-full transition-all duration-200 ease-out',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',\n index === selectedIndex\n ? 'w-4 bg-primary'\n : 'w-2 bg-on-surface-variant/40 hover:bg-on-surface-variant/60',\n )}\n />\n ))}\n </div>\n )\n}\n\nexport const Carousel = { Root, Container, Slide, Previous, Next, Dots }\nexport { Root, Container, Slide, Previous, Next, Dots }\n"],"mappings":";;;;;;;AAyCA,IAAM,IAAkB,EAA2C,IAAI;AAEvE,SAAS,IAAc;CACrB,IAAM,IAAU,EAAW,CAAe;CAC1C,IAAI,CAAC,GAAS,MAAU,MAAM,oDAAoD;CAClF,OAAO;AACT;AAQA,SAAS,EAAK,EAAE,YAAS,cAAW,aAAU,GAAG,KAAoB;CACnE,IAAM,CAAC,GAAa,KAAO,EAAiB,CAAO,GAC7C,CAAC,GAAe,KAAoB,EAAS,CAAC,GAC9C,CAAC,GAAa,KAAkB,EAAwB,CAAC,CAAC,GAC1D,CAAC,GAAe,KAAoB,EAAS,EAAK,GAClD,CAAC,GAAe,KAAoB,EAAS,EAAK;CAoBxD,OAlBA,QAAgB;EACd,IAAI,CAAC,GAAK;EACV,IAAM,KAAY,MAAgC;GAGhD,AAFA,EAAiB,EAAS,mBAAmB,CAAC,GAC9C,EAAiB,EAAS,cAAc,CAAC,GACzC,EAAiB,EAAS,cAAc,CAAC;EAC3C,GACM,KAAY,MAAgC;GAEhD,AADA,EAAe,EAAS,eAAe,CAAC,GACxC,EAAS,CAAQ;EACnB;EAGA,OAFA,EAAS,CAAG,GACZ,EAAI,GAAG,UAAU,CAAQ,EAAE,GAAG,UAAU,CAAQ,SACnC;GACX,EAAI,IAAI,UAAU,CAAQ,EAAE,IAAI,UAAU,CAAQ;EACpD;CACF,GAAG,CAAC,CAAG,CAAC,GAGN,kBAAC,EAAgB,UAAjB;EACE,OAAO;GAAE;GAAK;GAAa;GAAe;GAAa;GAAe;EAAc;YAEpF,kBAAC,OAAD;GACE,MAAK;GACL,wBAAqB;GACrB,WAAW,EAAG,YAAY,CAAS;GACnC,GAAI;GAEH;EACE,CAAA;CACmB,CAAA;AAE9B;AAGA,SAAS,EAAU,EAAE,cAAW,aAAU,GAAG,KAAgC;CAC3E,IAAM,EAAE,mBAAgB,EAAY;CACpC,OACE,kBAAC,OAAD;EAAK,KAAK;EAAa,WAAU;YAC/B,kBAAC,OAAD;GAAK,WAAW,EAAG,0BAA0B,CAAS;GAAG,GAAI;GAC1D;EACE,CAAA;CACF,CAAA;AAET;AAMA,SAAS,EAAM,EAAE,cAAW,aAAU,GAAG,KAAgC;CACvE,OACE,kBAAC,OAAD;EACE,WAAW,EAAG,2CAA2C,CAAS;EAClE,GAAI;YAEJ,kBAAC,OAAD;GAAK,WAAU;GAA8C;EAAc,CAAA;CACxE,CAAA;AAET;AAKA,SAAS,EAAS,EAAE,cAAW,aAAU,GAAG,KAAyB;CACnE,IAAM,EAAE,QAAK,qBAAkB,EAAY;CAC3C,OACE,kBAAC,EAAO,MAAR;EACE,cAAW;EACX,UAAU,CAAC;EACX,eAAe,GAAK,WAAW;EACpB;EACX,GAAI;YAEH,KAAY,kBAAC,GAAD,CAAc,CAAA;CAChB,CAAA;AAEjB;AAGA,SAAS,EAAK,EAAE,cAAW,aAAU,GAAG,KAAyB;CAC/D,IAAM,EAAE,QAAK,qBAAkB,EAAY;CAC3C,OACE,kBAAC,EAAO,MAAR;EACE,cAAW;EACX,UAAU,CAAC;EACX,eAAe,GAAK,WAAW;EACpB;EACX,GAAI;YAEH,KAAY,kBAAC,GAAD,CAAe,CAAA;CACjB,CAAA;AAEjB;AAGA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAgC;CAC5D,IAAM,EAAE,QAAK,kBAAe,mBAAgB,EAAY;CACxD,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,0CAA0C,CAAS;EAAG,GAAI;YAC1E,EAAY,KAAK,GAAG,MACnB,kBAAC,UAAD;GAEE,MAAK;GACL,cAAY,eAAe,IAAQ;GACnC,gBAAc,MAAU,IAAgB,SAAS,KAAA;GACjD,eAAe,GAAK,SAAS,CAAK;GAClC,WAAW,EACT,wEACA,wFACA,MAAU,IACN,mBACA,6DACN;EACD,GAZM,CAYN,CACF;CACE,CAAA;AAET;AAEA,IAAa,IAAW;CAAE;CAAM;CAAW;CAAO;CAAU;CAAM;AAAK"}
@@ -0,0 +1 @@
1
+ export { Carousel, Root, Container, Slide, Previous, Next, Dots } from './Carousel';
@@ -0,0 +1,2 @@
1
+ import { Carousel as e, Container as t, Dots as n, Next as r, Previous as i, Root as a, Slide as o } from "./Carousel.js";
2
+ export { e as Carousel, t as Container, n as Dots, r as Next, i as Previous, a as Root, o as Slide };
@@ -0,0 +1,64 @@
1
+ import { Checkbox as BaseCheckbox } from '@base-ui/react/checkbox';
2
+ import { CheckboxGroup as BaseCheckboxGroup } from '@base-ui/react/checkbox-group';
3
+ import { ComponentProps, ReactNode } from 'react';
4
+ /**
5
+ * Checkbox — Material 3 styled wrapper over Base UI's headless Checkbox +
6
+ * Checkbox Group.
7
+ * Behaviour/accessibility (hidden input, aria-checked incl. "mixed",
8
+ * keyboard toggling, parent/child group state): Base UI
9
+ * (https://base-ui.com/react/components/checkbox and
10
+ * https://base-ui.com/react/components/checkbox-group).
11
+ * Visuals ported from port/core/ui/elements/common/Checkbox.tsx +
12
+ * port/pages/examples/selection (see CLAUDE.md): 20px box with the port's
13
+ * 6px corner on a 40px circular state layer (surface-container-highest/30
14
+ * hover, slow fade), surface-container-highest fill when unticked,
15
+ * inverse-primary fill with a white check when ticked (the port's native
16
+ * `text-inverse-primary` accent), indeterminate dash, body-small label.
17
+ *
18
+ * Primary API is the port's single component (port/core/ui/elements/common):
19
+ * <Checkbox ariaLabel="Checkbox" />
20
+ * <Checkbox label="I agree to everything" defaultChecked />
21
+ * <Checkbox>I only agree to the <a href="#">Terms of Service</a></Checkbox>
22
+ *
23
+ * Compound parts remain for advanced composition (parent/child groups):
24
+ * <Checkbox.Group allValues={...} defaultValue={...}>
25
+ * <Checkbox.Label>
26
+ * <Checkbox.Root parent><Checkbox.Indicator /></Checkbox.Root>
27
+ * Select all
28
+ * </Checkbox.Label>
29
+ * …
30
+ * </Checkbox.Group>
31
+ */
32
+ declare function Root({ className, ...props }: ComponentProps<typeof BaseCheckbox.Root>): import("react").JSX.Element;
33
+ declare function Indicator({ className, children, ...props }: ComponentProps<typeof BaseCheckbox.Indicator>): import("react").JSX.Element;
34
+ /** Shared state for a series of checkboxes; pass `allValues` to enable a parent checkbox. */
35
+ declare function Group({ className, ...props }: ComponentProps<typeof BaseCheckboxGroup>): import("react").JSX.Element;
36
+ /**
37
+ * Convenience `<label>` row pairing a checkbox box with its label text —
38
+ * port spacing (4px after the 40px state layer ≈ gap-3.5 from the 20px box)
39
+ * and the port's body-small label.
40
+ */
41
+ declare function Label({ className, ...props }: ComponentProps<'label'>): import("react").JSX.Element;
42
+ type CheckboxProps = Omit<ComponentProps<typeof Root>, 'onChange' | 'children'> & {
43
+ /** Label text to the right of the box (port API; children work too). */
44
+ label?: ReactNode;
45
+ /** Label content, port style: <Checkbox>I agree…</Checkbox>. */
46
+ children?: ReactNode;
47
+ /** Accessible name for a bare box without a visible label (port API). */
48
+ ariaLabel?: string;
49
+ /** Port-compat change callback; receives the new checked state. */
50
+ onChange?: (checked: boolean) => void;
51
+ };
52
+ /**
53
+ * Port-style single checkbox: box + optional label row in one element.
54
+ * `label` (or children) renders the port's body-small label; without either
55
+ * it's a bare box — pass `ariaLabel`.
56
+ */
57
+ declare function CheckboxComponent({ label, children, ariaLabel, onChange, onCheckedChange, className, ...props }: CheckboxProps): import("react").JSX.Element;
58
+ export declare const Checkbox: typeof CheckboxComponent & {
59
+ Root: typeof Root;
60
+ Indicator: typeof Indicator;
61
+ Group: typeof Group;
62
+ Label: typeof Label;
63
+ };
64
+ export { Root, Indicator, Group, Label };