@surflane/ui 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/README.md +4 -4
  2. package/dist/accordion.d.ts +33 -17
  3. package/dist/accordion.js +10 -11
  4. package/dist/alert-dialog.d.ts +8 -4
  5. package/dist/alert-dialog.js +3 -4
  6. package/dist/app-shell.d.ts +81 -44
  7. package/dist/app-shell.js +67 -29
  8. package/dist/autocomplete.d.ts +117 -61
  9. package/dist/autocomplete.js +8 -8
  10. package/dist/avatar.d.ts +34 -17
  11. package/dist/avatar.js +8 -9
  12. package/dist/badge.d.ts +6 -10
  13. package/dist/badge.js +5 -6
  14. package/dist/bottom-navigation.d.ts +11 -41
  15. package/dist/bottom-navigation.js +9 -10
  16. package/dist/breadcrumbs.d.ts +21 -5
  17. package/dist/breadcrumbs.js +12 -14
  18. package/dist/button.d.ts +15 -8
  19. package/dist/button.js +8 -9
  20. package/dist/card.d.ts +610 -35
  21. package/dist/card.js +12 -12
  22. package/dist/chart.d.ts +9 -32
  23. package/dist/chart.js +65 -26
  24. package/dist/checkbox-group.d.ts +4 -1
  25. package/dist/checkbox-group.js +3 -4
  26. package/dist/checkbox.d.ts +13 -4
  27. package/dist/checkbox.js +6 -6
  28. package/dist/choice-label.d.ts +3 -11
  29. package/dist/choice-label.js +4 -4
  30. package/dist/class-names.d.ts +6 -0
  31. package/dist/class-names.js +18 -0
  32. package/dist/code.d.ts +13 -10
  33. package/dist/code.js +8 -5
  34. package/dist/collapsible.d.ts +25 -12
  35. package/dist/collapsible.js +7 -8
  36. package/dist/combobox.d.ts +145 -73
  37. package/dist/combobox.js +27 -27
  38. package/dist/context-menu.d.ts +106 -54
  39. package/dist/context-menu.js +4 -5
  40. package/dist/css/accordion.css +1 -1
  41. package/dist/css/alert-dialog.css +2 -2
  42. package/dist/css/all.css +7 -5
  43. package/dist/css/app-shell.css +1 -1
  44. package/dist/css/autocomplete.css +1 -1
  45. package/dist/css/avatar.css +2 -2
  46. package/dist/css/badge.css +2 -2
  47. package/dist/css/bottom-navigation.css +1 -1
  48. package/dist/css/breadcrumbs.css +3 -3
  49. package/dist/css/button.css +1 -1
  50. package/dist/css/card.css +3 -3
  51. package/dist/css/chart.css +2 -2
  52. package/dist/css/checkbox-group.css +1 -1
  53. package/dist/css/checkbox.css +1 -1
  54. package/dist/css/choice-label.css +1 -1
  55. package/dist/css/code.css +2 -2
  56. package/dist/css/collapsible.css +1 -1
  57. package/dist/css/combobox.css +1 -1
  58. package/dist/css/context-menu.css +1 -1
  59. package/dist/css/date-picker.css +1 -1
  60. package/dist/css/dialog.css +2 -2
  61. package/dist/css/drawer.css +2 -2
  62. package/dist/css/empty-state.css +2 -2
  63. package/dist/css/field.css +1 -1
  64. package/dist/css/fieldset.css +1 -1
  65. package/dist/css/file-upload.css +2 -2
  66. package/dist/css/filter-bar.css +1 -1
  67. package/dist/css/form.css +1 -1
  68. package/dist/css/icon.css +1 -1
  69. package/dist/css/inline-message.css +2 -2
  70. package/dist/css/input.css +1 -1
  71. package/dist/css/layout.css +2 -2
  72. package/dist/css/link.css +2 -2
  73. package/dist/css/list.css +2 -2
  74. package/dist/css/markdown.css +4 -4
  75. package/dist/css/menu.css +1 -1
  76. package/dist/css/menubar.css +1 -1
  77. package/dist/css/meter.css +1 -1
  78. package/dist/css/native-select.css +1 -1
  79. package/dist/css/navigation-menu.css +1 -1
  80. package/dist/css/number-field.css +1 -1
  81. package/dist/css/otp-field.css +1 -1
  82. package/dist/css/page-header.css +3 -3
  83. package/dist/css/pagination.css +2 -2
  84. package/dist/css/popover.css +1 -1
  85. package/dist/css/preview-card.css +2 -2
  86. package/dist/css/progress.css +1 -1
  87. package/dist/css/radio-group.css +1 -1
  88. package/dist/css/rules/accordion.css +5 -5
  89. package/dist/css/rules/alert-dialog.css +9 -9
  90. package/dist/css/rules/app-shell.css +274 -82
  91. package/dist/css/rules/avatar.css +7 -7
  92. package/dist/css/rules/badge.css +6 -6
  93. package/dist/css/rules/bar.css +11 -11
  94. package/dist/css/rules/base.css +30 -30
  95. package/dist/css/rules/bottom-navigation.css +57 -56
  96. package/dist/css/rules/breadcrumbs.css +2 -2
  97. package/dist/css/rules/button.css +66 -65
  98. package/dist/css/rules/card.css +3 -3
  99. package/dist/css/rules/chart.css +134 -124
  100. package/dist/css/rules/checkbox.css +5 -5
  101. package/dist/css/rules/choice-label.css +19 -18
  102. package/dist/css/rules/choice.css +65 -60
  103. package/dist/css/rules/code.css +2 -2
  104. package/dist/css/rules/collapsible.css +2 -2
  105. package/dist/css/rules/combobox.css +87 -83
  106. package/dist/css/rules/context-menu.css +1 -1
  107. package/dist/css/rules/date-picker.css +150 -144
  108. package/dist/css/rules/dialog.css +85 -79
  109. package/dist/css/rules/disclosure.css +49 -47
  110. package/dist/css/rules/drawer.css +6 -6
  111. package/dist/css/rules/empty-state.css +2 -2
  112. package/dist/css/rules/field-control.css +51 -42
  113. package/dist/css/rules/field.css +26 -24
  114. package/dist/css/rules/fieldset.css +10 -8
  115. package/dist/css/rules/file-upload.css +73 -72
  116. package/dist/css/rules/filter-bar.css +19 -18
  117. package/dist/css/rules/form.css +3 -3
  118. package/dist/css/rules/gauge.css +22 -22
  119. package/dist/css/rules/icon.css +16 -11
  120. package/dist/css/rules/inline-message.css +3 -3
  121. package/dist/css/rules/input-group.css +50 -43
  122. package/dist/css/rules/input.css +11 -11
  123. package/dist/css/rules/item.css +7 -7
  124. package/dist/css/rules/link.css +2 -2
  125. package/dist/css/rules/list.css +3 -3
  126. package/dist/css/rules/markdown.css +27 -27
  127. package/dist/css/rules/menu.css +45 -42
  128. package/dist/css/rules/menubar.css +6 -6
  129. package/dist/css/rules/navigation-menu.css +69 -66
  130. package/dist/css/rules/number-field.css +22 -21
  131. package/dist/css/rules/otp-field.css +28 -27
  132. package/dist/css/rules/panel.css +105 -100
  133. package/dist/css/rules/popover.css +23 -20
  134. package/dist/css/rules/popup.css +15 -14
  135. package/dist/css/rules/preview-card.css +20 -19
  136. package/dist/css/rules/progress.css +3 -3
  137. package/dist/css/rules/radio-group.css +8 -8
  138. package/dist/css/rules/scroll-area.css +50 -39
  139. package/dist/css/rules/select.css +39 -36
  140. package/dist/css/rules/sizing.css +119 -116
  141. package/dist/css/rules/skeleton.css +18 -11
  142. package/dist/css/rules/slider.css +43 -43
  143. package/dist/css/rules/sparkline.css +21 -21
  144. package/dist/css/rules/spinner.css +9 -9
  145. package/dist/css/rules/stat.css +32 -32
  146. package/dist/css/rules/switch.css +28 -21
  147. package/dist/css/rules/syntax-highlighter.css +37 -36
  148. package/dist/css/rules/table.css +10 -10
  149. package/dist/css/rules/tabs.css +53 -52
  150. package/dist/css/rules/textarea.css +9 -7
  151. package/dist/css/rules/toast.css +94 -90
  152. package/dist/css/rules/toggle.css +12 -12
  153. package/dist/css/rules/toolbar.css +27 -27
  154. package/dist/css/rules/tooltip.css +14 -14
  155. package/dist/css/rules/tree.css +38 -38
  156. package/dist/css/scroll-area.css +1 -1
  157. package/dist/css/select.css +1 -1
  158. package/dist/css/separator.css +2 -2
  159. package/dist/css/sheet.css +2 -2
  160. package/dist/css/sizing.css +1 -1
  161. package/dist/css/skeleton.css +1 -1
  162. package/dist/css/slider.css +1 -1
  163. package/dist/css/sparkline.css +1 -1
  164. package/dist/css/spinner.css +1 -1
  165. package/dist/css/stat.css +1 -1
  166. package/dist/css/styles.css +17 -17
  167. package/dist/css/switch.css +1 -1
  168. package/dist/css/syntax-highlighter.css +1 -1
  169. package/dist/css/table.css +2 -2
  170. package/dist/css/tabs.css +1 -1
  171. package/dist/css/textarea.css +1 -1
  172. package/dist/css/toast.css +1 -1
  173. package/dist/css/toggle-group.css +1 -1
  174. package/dist/css/toggle.css +1 -1
  175. package/dist/css/toolbar.css +1 -1
  176. package/dist/css/tooltip.css +1 -1
  177. package/dist/css/tree.css +1 -1
  178. package/dist/css/typography.css +2 -2
  179. package/dist/date-picker.js +28 -8
  180. package/dist/dialog.d.ts +20 -8
  181. package/dist/dialog.js +11 -12
  182. package/dist/drawer.d.ts +12 -4
  183. package/dist/drawer.js +5 -5
  184. package/dist/element-part.d.ts +8 -0
  185. package/dist/element-part.js +21 -0
  186. package/dist/empty-state.d.ts +602 -24
  187. package/dist/empty-state.js +9 -9
  188. package/dist/field.d.ts +60 -36
  189. package/dist/field.js +6 -6
  190. package/dist/fieldset.d.ts +19 -11
  191. package/dist/fieldset.js +2 -2
  192. package/dist/file-upload.d.ts +8 -23
  193. package/dist/file-upload.js +23 -16
  194. package/dist/filter-bar.d.ts +30 -10
  195. package/dist/filter-bar.js +16 -18
  196. package/dist/form.js +1 -1
  197. package/dist/icon.d.ts +9 -2
  198. package/dist/icon.js +6 -6
  199. package/dist/index.d.ts +4 -4
  200. package/dist/index.js +2 -3
  201. package/dist/inline-message.d.ts +51 -27
  202. package/dist/inline-message.js +10 -11
  203. package/dist/input.d.ts +4 -2
  204. package/dist/input.js +3 -4
  205. package/dist/layout.d.ts +24 -12
  206. package/dist/layout.js +27 -27
  207. package/dist/link.d.ts +3 -1
  208. package/dist/link.js +3 -4
  209. package/dist/list.d.ts +43 -27
  210. package/dist/list.js +12 -13
  211. package/dist/markdown.d.ts +14 -6
  212. package/dist/markdown.js +28 -11
  213. package/dist/menu.d.ts +113 -57
  214. package/dist/menu.js +24 -25
  215. package/dist/menubar.d.ts +5 -3
  216. package/dist/menubar.js +1 -1
  217. package/dist/meter.d.ts +46 -26
  218. package/dist/meter.js +5 -5
  219. package/dist/native-select.d.ts +4 -2
  220. package/dist/native-select.js +2 -2
  221. package/dist/navigation-menu.d.ts +76 -40
  222. package/dist/navigation-menu.js +15 -16
  223. package/dist/number-field.d.ts +44 -19
  224. package/dist/number-field.js +12 -13
  225. package/dist/otp-field.d.ts +26 -9
  226. package/dist/otp-field.js +10 -11
  227. package/dist/page-header.js +3 -4
  228. package/dist/pagination.d.ts +11 -8
  229. package/dist/pagination.js +4 -5
  230. package/dist/panel.d.ts +3 -1
  231. package/dist/panel.js +5 -6
  232. package/dist/parts.d.ts +5 -7
  233. package/dist/parts.js +8 -16
  234. package/dist/popover.d.ts +20 -12
  235. package/dist/popover.js +3 -3
  236. package/dist/preview-card.d.ts +22 -10
  237. package/dist/preview-card.js +7 -8
  238. package/dist/progress.d.ts +46 -26
  239. package/dist/progress.js +5 -5
  240. package/dist/radio-group.d.ts +16 -8
  241. package/dist/radio-group.js +5 -5
  242. package/dist/scroll-area.d.ts +4 -2
  243. package/dist/scroll-area.js +6 -6
  244. package/dist/select.d.ts +3 -1
  245. package/dist/select.js +5 -5
  246. package/dist/separator.d.ts +5 -2
  247. package/dist/separator.js +3 -4
  248. package/dist/sheet.d.ts +12 -4
  249. package/dist/sheet.js +5 -5
  250. package/dist/size.d.ts +7 -0
  251. package/dist/size.js +9 -0
  252. package/dist/sizing.d.ts +8 -3
  253. package/dist/sizing.js +8 -10
  254. package/dist/skeleton.d.ts +3 -3
  255. package/dist/skeleton.js +4 -6
  256. package/dist/slider.d.ts +55 -31
  257. package/dist/slider.js +7 -7
  258. package/dist/sparkline.d.ts +5 -20
  259. package/dist/sparkline.js +5 -7
  260. package/dist/spinner.d.ts +4 -6
  261. package/dist/spinner.js +7 -8
  262. package/dist/stat.d.ts +34 -42
  263. package/dist/stat.js +9 -10
  264. package/dist/status.js +0 -1
  265. package/dist/switch.d.ts +17 -8
  266. package/dist/switch.js +4 -5
  267. package/dist/syntax-engine.js +9 -1
  268. package/dist/syntax-highlighter.d.ts +3 -7
  269. package/dist/syntax-highlighter.js +4 -4
  270. package/dist/syntax-highlighting.js +2 -2
  271. package/dist/table.d.ts +111 -75
  272. package/dist/table.js +32 -33
  273. package/dist/tabs.d.ts +46 -26
  274. package/dist/tabs.js +5 -5
  275. package/dist/textarea.d.ts +4 -2
  276. package/dist/textarea.js +3 -4
  277. package/dist/toast.d.ts +76 -42
  278. package/dist/toast.js +28 -28
  279. package/dist/toggle-group.js +1 -1
  280. package/dist/toggle.js +1 -1
  281. package/dist/tone-transition.d.ts +1 -1
  282. package/dist/tone-transition.js +9 -8
  283. package/dist/toolbar.d.ts +55 -31
  284. package/dist/toolbar.js +6 -6
  285. package/dist/tooltip.d.ts +4 -1
  286. package/dist/tooltip.js +2 -2
  287. package/dist/tree.d.ts +12 -1
  288. package/dist/tree.js +13 -9
  289. package/dist/typography.d.ts +3 -1
  290. package/dist/typography.js +6 -8
  291. package/package.json +6 -5
package/README.md CHANGED
@@ -5,20 +5,20 @@
5
5
  React 19 components for the Surflane design system, built on [Base UI](https://base-ui.com), with data, chart, date, tree, code highlighting and Markdown components. Browse them in the [catalog](https://surflane.page).
6
6
 
7
7
  ```sh
8
- npm install @surflane/ui @surflane/design-tokens
8
+ npm install @surflane/ui @surflane/design-tokens @surflane/css @base-ui/react
9
9
  ```
10
10
 
11
- `@surflane/ui` and `@surflane/design-tokens` are released together with the same version. The package is ESM-only.
11
+ `@surflane/ui`, `@surflane/design-tokens` and `@surflane/css` are released together with one version. Base UI is a peer dependency, 1.9 or later, so your app and Surflane share one copy. The package is ESM-only.
12
12
 
13
13
  ## Usage
14
14
 
15
- Import the stylesheets once at the application root. `all.css` brings the tokens, controls, composition, document typography and component styles:
15
+ Import the stylesheets once at the application root. `all.css` brings the tokens, the theme transition, controls, composition, document typography and component styles:
16
16
 
17
17
  ```css
18
18
  @import '@surflane/ui/all.css';
19
19
  ```
20
20
 
21
- To ship only what you use, import component stylesheets instead, such as `@surflane/ui/button.css` and `@surflane/ui/dialog.css`. Each brings the tokens and the styles of what its component renders. The rules sit in `surflane.*` cascade layers, so your unlayered CSS overrides them. Set `data-theme="light"` or `data-theme="dark"` on `<html>` before the first paint and add `pui-typography` to `<body>`. With AppShell, which fills the window, also give `<body>` no margin and the `--chrome` background. The [install guide](https://surflane.page/install) walks through Vite, Next.js, React Router and Astro, with or without Tailwind CSS.
21
+ To ship only what you use, import component stylesheets instead, such as `@surflane/ui/button.css` and `@surflane/ui/dialog.css`. Each brings the tokens and the styles of what its component renders. The rules sit in `surflane.*` cascade layers, so your unlayered CSS overrides them. Set `data-theme="light"` or `data-theme="dark"` on `<html>` before the first paint and add `surf-typography` to `<body>`. With AppShell, which fills the window, also give `<body>` no margin and the `--surf-chrome` background. The [install guide](https://surflane.page/install) walks through Vite, Next.js, React Router and Astro, with or without Tailwind CSS.
22
22
 
23
23
  ```tsx
24
24
  import {
@@ -1,26 +1,42 @@
1
1
  import * as React from 'react';
2
2
  import { Accordion as BaseAccordion } from '@base-ui/react/accordion';
3
3
  declare function AccordionRoot<Value = string>({ className, ...props }: BaseAccordion.Root.Props<Value>): React.JSX.Element;
4
- declare const AccordionTrigger: React.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react/accordion").AccordionTriggerProps, "ref"> & React.RefAttributes<HTMLElement>, "ref"> & {
4
+ declare const AccordionTrigger: ({ className, children, indicator, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseAccordion.Trigger> & {
5
5
  indicator?: React.ReactNode;
6
- } & React.RefAttributes<HTMLElement>>;
7
- declare const AccordionPanel: React.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react/accordion").AccordionPanelProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
6
+ } & {
7
+ ref?: React.Ref<React.ComponentRef<typeof BaseAccordion.Trigger>>;
8
+ }) => React.JSX.Element;
9
+ declare const AccordionPanel: ({ className, children, render, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseAccordion.Panel> & {
10
+ ref?: React.Ref<React.ComponentRef<typeof BaseAccordion.Panel>>;
11
+ }) => React.JSX.Element;
8
12
  export declare const Accordion: {
9
13
  Root: typeof AccordionRoot;
10
- Item: React.ForwardRefExoticComponent<Omit<Omit<Omit<import("@base-ui/react/accordion").AccordionItemProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
11
- size?: import("./sizing.js").ComponentSize;
12
- } & React.RefAttributes<HTMLDivElement>>;
13
- Header: React.ForwardRefExoticComponent<Omit<Omit<Omit<import("@base-ui/react/accordion").AccordionHeaderProps, "ref"> & React.RefAttributes<HTMLHeadingElement>, "ref">, "size"> & {
14
- size?: import("./sizing.js").ComponentSize;
15
- } & React.RefAttributes<HTMLHeadingElement>>;
16
- Trigger: React.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react/accordion").AccordionTriggerProps, "ref"> & React.RefAttributes<HTMLElement>, "ref"> & {
14
+ Item: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/accordion").AccordionItemProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
15
+ size?: import("./size.js").ComponentSize;
16
+ } & {
17
+ ref?: React.Ref<HTMLDivElement> | undefined;
18
+ }) => React.JSX.Element;
19
+ Header: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/accordion").AccordionHeaderProps, "ref"> & React.RefAttributes<HTMLHeadingElement>, "ref">, "size"> & {
20
+ size?: import("./size.js").ComponentSize;
21
+ } & {
22
+ ref?: React.Ref<HTMLHeadingElement> | undefined;
23
+ }) => React.JSX.Element;
24
+ Trigger: ({ className, children, indicator, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseAccordion.Trigger> & {
17
25
  indicator?: React.ReactNode;
18
- } & React.RefAttributes<HTMLElement>>;
19
- Panel: React.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react/accordion").AccordionPanelProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
26
+ } & {
27
+ ref?: React.Ref<React.ComponentRef<typeof BaseAccordion.Trigger>>;
28
+ }) => React.JSX.Element;
29
+ Panel: ({ className, children, render, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseAccordion.Panel> & {
30
+ ref?: React.Ref<React.ComponentRef<typeof BaseAccordion.Panel>>;
31
+ }) => React.JSX.Element;
20
32
  };
21
33
  export { AccordionPanel, AccordionRoot, AccordionTrigger };
22
- export declare const AccordionHeader: React.ForwardRefExoticComponent<Omit<Omit<Omit<import("@base-ui/react/accordion").AccordionHeaderProps, "ref"> & React.RefAttributes<HTMLHeadingElement>, "ref">, "size"> & {
23
- size?: import("./sizing.js").ComponentSize;
24
- } & React.RefAttributes<HTMLHeadingElement>>, AccordionItem: React.ForwardRefExoticComponent<Omit<Omit<Omit<import("@base-ui/react/accordion").AccordionItemProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
25
- size?: import("./sizing.js").ComponentSize;
26
- } & React.RefAttributes<HTMLDivElement>>;
34
+ export declare const AccordionHeader: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/accordion").AccordionHeaderProps, "ref"> & React.RefAttributes<HTMLHeadingElement>, "ref">, "size"> & {
35
+ size?: import("./size.js").ComponentSize;
36
+ } & {
37
+ ref?: React.Ref<HTMLHeadingElement> | undefined;
38
+ }) => React.JSX.Element, AccordionItem: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/accordion").AccordionItemProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
39
+ size?: import("./size.js").ComponentSize;
40
+ } & {
41
+ ref?: React.Ref<HTMLDivElement> | undefined;
42
+ }) => React.JSX.Element;
package/dist/accordion.js CHANGED
@@ -1,24 +1,23 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import * as React from 'react';
4
3
  import { Accordion as BaseAccordion } from '@base-ui/react/accordion';
5
4
  import { Icon } from './icon.js';
6
5
  import { skin, part } from './parts.js';
7
6
  function AccordionRoot({ className, ...props }) {
8
- return (_jsx(BaseAccordion.Root, { ...props, className: skin('pui-accordion', className) }));
7
+ return (_jsx(BaseAccordion.Root, { ...props, className: skin('surf-accordion', className) }));
9
8
  }
10
- const AccordionTrigger = /* @__PURE__ */ React.forwardRef(function AccordionTrigger({ className, children, indicator, ...props }, ref) {
11
- return (_jsxs(BaseAccordion.Trigger, { ...props, ref: ref, className: skin('pui-disclosure-trigger', className), children: [_jsx("span", { className: 'pui-disclosure-label', children: children }), indicator === undefined ? (_jsx(Icon, { name: 'chevron-forward', className: 'pui-disclosure-chevron' })) : (indicator)] }));
12
- });
13
- const AccordionPanel = /* @__PURE__ */ React.forwardRef(function AccordionPanel({ className, children, render, ...props }, ref) {
14
- return (_jsx(BaseAccordion.Panel, { ...props, ref: ref, className: skin('pui-accordion-panel', className), render: render ??
15
- ((panelProps, state) => (_jsx("div", { ...panelProps, inert: state.transitionStatus === 'ending' || undefined, "aria-hidden": state.transitionStatus === 'ending' || undefined }))), children: _jsx("div", { className: 'pui-disclosure-body', children: children }) }));
16
- });
9
+ const AccordionTrigger = function AccordionTrigger({ className, children, indicator, ref, ...props }) {
10
+ return (_jsxs(BaseAccordion.Trigger, { ...props, ref: ref, className: skin('surf-disclosure-trigger', className), children: [_jsx("span", { className: 'surf-disclosure-label', children: children }), indicator === undefined ? (_jsx(Icon, { name: 'chevron-forward', className: 'surf-disclosure-chevron' })) : (indicator)] }));
11
+ };
12
+ const AccordionPanel = function AccordionPanel({ className, children, render, ref, ...props }) {
13
+ return (_jsx(BaseAccordion.Panel, { ...props, ref: ref, className: skin('surf-accordion-panel', className), render: render ??
14
+ ((panelProps, state) => (_jsx("div", { ...panelProps, inert: state.transitionStatus === 'ending' || undefined, "aria-hidden": state.transitionStatus === 'ending' || undefined }))), children: _jsx("div", { className: 'surf-disclosure-body', children: children }) }));
15
+ };
17
16
  export const Accordion = {
18
17
  ...BaseAccordion,
19
18
  Root: AccordionRoot,
20
- Item: /* @__PURE__ */ part(BaseAccordion.Item, 'pui-accordion-item'),
21
- Header: /* @__PURE__ */ part(BaseAccordion.Header, 'pui-accordion-header'),
19
+ Item: /* @__PURE__ */ part(BaseAccordion.Item, 'surf-accordion-item'),
20
+ Header: /* @__PURE__ */ part(BaseAccordion.Header, 'surf-accordion-header'),
22
21
  Trigger: AccordionTrigger,
23
22
  Panel: AccordionPanel,
24
23
  };
@@ -2,17 +2,21 @@ import * as React from 'react';
2
2
  import { type ComponentSizeAlias } from './sizing.js';
3
3
  import { AlertDialog as BaseAlertDialog } from '@base-ui/react/alert-dialog';
4
4
  import { DialogFooter, DialogHeader } from './dialog.js';
5
- declare const AlertDialogContent: React.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react/alert-dialog").AlertDialogPopupProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref"> & {
5
+ declare const AlertDialogContent: ({ size, className, focusBoundaryLabel, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Popup> & {
6
6
  /** Width and density; an alert dialog is small unless set. */
7
7
  size?: ComponentSizeAlias;
8
8
  focusBoundaryLabel?: string;
9
- } & React.RefAttributes<HTMLDivElement>>;
9
+ } & {
10
+ ref?: React.Ref<HTMLDivElement>;
11
+ }) => React.JSX.Element;
10
12
  export declare const AlertDialog: {
11
- Content: React.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react/alert-dialog").AlertDialogPopupProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref"> & {
13
+ Content: ({ size, className, focusBoundaryLabel, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Popup> & {
12
14
  /** Width and density; an alert dialog is small unless set. */
13
15
  size?: ComponentSizeAlias;
14
16
  focusBoundaryLabel?: string;
15
- } & React.RefAttributes<HTMLDivElement>>;
17
+ } & {
18
+ ref?: React.Ref<HTMLDivElement>;
19
+ }) => React.JSX.Element;
16
20
  Header: typeof DialogHeader;
17
21
  Footer: typeof DialogFooter;
18
22
  Root: typeof BaseAlertDialog.Root;
@@ -1,16 +1,15 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import * as React from 'react';
4
3
  import { sizeName, skin } from './parts.js';
5
4
  import { useDialogFocusBoundary } from './dialog-focus.js';
6
5
  import { useComponentSize } from './sizing.js';
7
6
  import { AlertDialog as BaseAlertDialog } from '@base-ui/react/alert-dialog';
8
7
  import { DialogFooter, DialogHeader } from './dialog.js';
9
- const AlertDialogContent = /* @__PURE__ */ React.forwardRef(function AlertDialogContent({ size, className, focusBoundaryLabel = 'Continue dialog navigation', ...props }, ref) {
8
+ const AlertDialogContent = function AlertDialogContent({ size, className, focusBoundaryLabel = 'Continue dialog navigation', ref, ...props }) {
10
9
  const scheme = useComponentSize(size);
11
10
  const portalRef = useDialogFocusBoundary(focusBoundaryLabel);
12
- return (_jsxs(BaseAlertDialog.Portal, { ref: portalRef, children: [_jsx(BaseAlertDialog.Backdrop, { className: 'pui-dialog-backdrop' }), _jsx(BaseAlertDialog.Popup, { "data-ui-size": scheme, "data-size": sizeName(size), ...props, ref: ref, className: skin('pui-dialog-popup pui-dialog-content pui-confirm-content', className) })] }));
13
- });
11
+ return (_jsxs(BaseAlertDialog.Portal, { ref: portalRef, children: [_jsx(BaseAlertDialog.Backdrop, { className: 'surf-dialog-backdrop' }), _jsx(BaseAlertDialog.Popup, { "data-ui-size": scheme, "data-size": sizeName(size), ...props, ref: ref, className: skin('surf-dialog-popup surf-dialog-content surf-confirm-content', className) })] }));
12
+ };
14
13
  export const AlertDialog = {
15
14
  ...BaseAlertDialog,
16
15
  Content: AlertDialogContent,
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
2
3
  import { type ButtonProps } from './button.js';
3
4
  export type AppShellRootProps = React.ComponentPropsWithoutRef<'div'> & {
4
5
  layout?: 'header' | 'workspace';
@@ -13,53 +14,89 @@ export type AppShellRootProps = React.ComponentPropsWithoutRef<'div'> & {
13
14
  /** ⌘B, or Ctrl+B, toggles the sidebar unless focus is in a text field. */
14
15
  shortcut?: boolean;
15
16
  };
16
- export type AppShellSidebarToggleProps = Omit<ButtonProps, 'children'> & {
17
+ export type AppShellSidebarToggleLabels = {
17
18
  /** The button's name in each state; it is also the tooltip. */
18
- labels?: {
19
- collapse?: string;
20
- expand?: string;
21
- };
19
+ collapse: string;
20
+ expand: string;
21
+ /** The shortcut the tooltip shows; ⌘B on Apple platforms, Ctrl+B elsewhere. */
22
+ shortcut: string;
23
+ };
24
+ export type AppShellSidebarToggleProps = Omit<ButtonProps, 'children'> & {
25
+ labels?: Partial<AppShellSidebarToggleLabels>;
22
26
  children?: React.ReactNode;
23
27
  };
24
- export declare const AppShell: {
25
- Root: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
26
- layout?: "header" | "workspace";
27
- /** Whether the sidebar is collapsed to its rail. Pass it to control the state. */
28
- collapsed?: boolean;
29
- /** The starting state when the shell controls it. */
30
- defaultCollapsed?: boolean;
31
- onCollapsedChange?: (collapsed: boolean) => void;
32
- /** A localStorage key that remembers the state across visits. A server-rendered
33
- * app reads a cookie into defaultCollapsed instead, so the first paint is right. */
34
- persist?: string;
35
- /** ⌘B, or Ctrl+B, toggles the sidebar unless focus is in a text field. */
36
- shortcut?: boolean;
37
- } & React.RefAttributes<HTMLDivElement>>;
38
- Header: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
39
- Sidebar: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & React.RefAttributes<HTMLElement>>;
40
- SidebarToggle: React.ForwardRefExoticComponent<Omit<AppShellSidebarToggleProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
41
- Content: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
42
- Page: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
43
- Footer: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
44
- Label: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
45
- Link: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref">, "children"> & {
46
- icon: React.ReactNode;
47
- label: string;
48
- } & React.RefAttributes<HTMLAnchorElement>>;
28
+ export type AppShellBrandProps = Omit<useRender.ComponentProps<'div'>, 'ref' | 'children'> & {
29
+ /** The product mark, about 24px. It is decorative: the name names the brand. */
30
+ mark?: React.ReactNode;
31
+ /** The product name, on one line. A long one truncates and keeps its text in title. */
32
+ name: string;
33
+ /** An optional second line, such as the workspace. */
34
+ description?: React.ReactNode;
49
35
  };
50
- export declare const AppShellRoot: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
51
- layout?: "header" | "workspace";
52
- /** Whether the sidebar is collapsed to its rail. Pass it to control the state. */
53
- collapsed?: boolean;
54
- /** The starting state when the shell controls it. */
55
- defaultCollapsed?: boolean;
56
- onCollapsedChange?: (collapsed: boolean) => void;
57
- /** A localStorage key that remembers the state across visits. A server-rendered
58
- * app reads a cookie into defaultCollapsed instead, so the first paint is right. */
59
- persist?: string;
60
- /** ⌘B, or Ctrl+B, toggles the sidebar unless focus is in a text field. */
61
- shortcut?: boolean;
62
- } & React.RefAttributes<HTMLDivElement>>, AppShellHeader: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>, AppShellSidebar: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & React.RefAttributes<HTMLElement>>, AppShellSidebarToggle: React.ForwardRefExoticComponent<Omit<AppShellSidebarToggleProps, "ref"> & React.RefAttributes<HTMLButtonElement>>, AppShellContent: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>, AppShellPage: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>, AppShellFooter: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>, AppShellLabel: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>, AppShellLink: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref">, "children"> & {
36
+ export type AppShellNavProps = React.ComponentPropsWithoutRef<'nav'> & {
37
+ /** A visible name over the links, which also names the navigation. Without it,
38
+ * name the navigation with aria-label. */
39
+ label?: string;
40
+ };
41
+ export type AppShellLinkProps = Omit<useRender.ComponentProps<'a'>, 'ref' | 'children'> & {
63
42
  icon: React.ReactNode;
64
43
  label: string;
65
- } & React.RefAttributes<HTMLAnchorElement>>;
44
+ };
45
+ export declare const AppShell: {
46
+ Root: ({ collapsed, defaultCollapsed, onCollapsedChange, persist, shortcut, layout, className, children, ref, ...props }: AppShellRootProps & {
47
+ ref?: React.Ref<HTMLDivElement>;
48
+ }) => React.JSX.Element;
49
+ Header: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"div"> & {
50
+ ref?: React.Ref<HTMLDivElement>;
51
+ }) => React.JSX.Element;
52
+ Sidebar: ({ className, id, ref, ...props }: React.ComponentPropsWithoutRef<"aside"> & {
53
+ ref?: React.Ref<HTMLElement>;
54
+ }) => React.JSX.Element;
55
+ SidebarToggle: ({ labels, className, children, onClick, ref, ...props }: AppShellSidebarToggleProps & {
56
+ ref?: React.Ref<HTMLButtonElement>;
57
+ }) => React.JSX.Element;
58
+ Brand: ({ mark, name, description, render, className, ref, ...props }: AppShellBrandProps & {
59
+ ref?: React.Ref<HTMLDivElement>;
60
+ }) => React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
61
+ Nav: ({ label, className, children, ref, ...props }: AppShellNavProps & {
62
+ ref?: React.Ref<HTMLElement>;
63
+ }) => React.JSX.Element;
64
+ Content: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"div"> & {
65
+ ref?: React.Ref<HTMLDivElement>;
66
+ }) => React.JSX.Element;
67
+ Page: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"div"> & {
68
+ ref?: React.Ref<HTMLDivElement>;
69
+ }) => React.JSX.Element;
70
+ Footer: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"div"> & {
71
+ ref?: React.Ref<HTMLDivElement>;
72
+ }) => React.JSX.Element;
73
+ Label: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"span"> & {
74
+ ref?: React.Ref<HTMLSpanElement>;
75
+ }) => React.JSX.Element;
76
+ Link: ({ icon, label, render, className, ref, ...props }: AppShellLinkProps & {
77
+ ref?: React.Ref<HTMLAnchorElement>;
78
+ }) => React.JSX.Element;
79
+ };
80
+ export declare const AppShellRoot: ({ collapsed, defaultCollapsed, onCollapsedChange, persist, shortcut, layout, className, children, ref, ...props }: AppShellRootProps & {
81
+ ref?: React.Ref<HTMLDivElement>;
82
+ }) => React.JSX.Element, AppShellHeader: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"div"> & {
83
+ ref?: React.Ref<HTMLDivElement>;
84
+ }) => React.JSX.Element, AppShellSidebar: ({ className, id, ref, ...props }: React.ComponentPropsWithoutRef<"aside"> & {
85
+ ref?: React.Ref<HTMLElement>;
86
+ }) => React.JSX.Element, AppShellSidebarToggle: ({ labels, className, children, onClick, ref, ...props }: AppShellSidebarToggleProps & {
87
+ ref?: React.Ref<HTMLButtonElement>;
88
+ }) => React.JSX.Element, AppShellBrand: ({ mark, name, description, render, className, ref, ...props }: AppShellBrandProps & {
89
+ ref?: React.Ref<HTMLDivElement>;
90
+ }) => React.ReactElement<unknown, string | React.JSXElementConstructor<any>>, AppShellNav: ({ label, className, children, ref, ...props }: AppShellNavProps & {
91
+ ref?: React.Ref<HTMLElement>;
92
+ }) => React.JSX.Element, AppShellContent: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"div"> & {
93
+ ref?: React.Ref<HTMLDivElement>;
94
+ }) => React.JSX.Element, AppShellPage: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"div"> & {
95
+ ref?: React.Ref<HTMLDivElement>;
96
+ }) => React.JSX.Element, AppShellFooter: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"div"> & {
97
+ ref?: React.Ref<HTMLDivElement>;
98
+ }) => React.JSX.Element, AppShellLabel: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"span"> & {
99
+ ref?: React.Ref<HTMLSpanElement>;
100
+ }) => React.JSX.Element, AppShellLink: ({ icon, label, render, className, ref, ...props }: AppShellLinkProps & {
101
+ ref?: React.Ref<HTMLAnchorElement>;
102
+ }) => React.JSX.Element;
package/dist/app-shell.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import * as React from 'react';
4
+ import { useRender } from '@base-ui/react/use-render';
4
5
  import { cx, skin } from './parts.js';
5
6
  import { Button } from './button.js';
6
7
  import { Icon } from './icon.js';
@@ -15,7 +16,7 @@ const apple = () => typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(n
15
16
  const shortcutLabel = () => (apple() ? '⌘B' : 'Ctrl+B');
16
17
  /** Layout only. Routing, session, theme and mobile disclosure belong to the caller;
17
18
  * the shell keeps the sidebar's collapsed state unless you control it. */
18
- const Root = /* @__PURE__ */ React.forwardRef(function AppShellRoot({ collapsed, defaultCollapsed = false, onCollapsedChange, persist, shortcut = true, layout = 'header', className, children, ...props }, ref) {
19
+ const Root = function AppShellRoot({ collapsed, defaultCollapsed = false, onCollapsedChange, persist, shortcut = true, layout = 'header', className, children, ref, ...props }) {
19
20
  const [own, setOwn] = React.useState(defaultCollapsed);
20
21
  const value = collapsed ?? own;
21
22
  const latest = React.useRef(value);
@@ -58,56 +59,93 @@ const Root = /* @__PURE__ */ React.forwardRef(function AppShellRoot({ collapsed,
58
59
  }, [shortcut, setCollapsed]);
59
60
  const sidebarId = React.useId();
60
61
  const shell = React.useMemo(() => ({ collapsed: value, setCollapsed, sidebarId, shortcut }), [value, setCollapsed, sidebarId, shortcut]);
61
- return (_jsx(ShellContext.Provider, { value: shell, children: _jsx("div", { ...props, ref: ref, "data-layout": layout, "data-sidebar": value ? 'collapsed' : 'expanded', className: cx('pui-app-shell', className), children: children }) }));
62
- });
62
+ return (_jsx(ShellContext.Provider, { value: shell, children: _jsx("div", { ...props, ref: ref, "data-layout": layout, "data-sidebar": value ? 'collapsed' : 'expanded', className: cx('surf-app-shell', className), children: children }) }));
63
+ };
63
64
  /** Collapses the sidebar to its rail and back. Its tooltip names the shortcut. */
64
- const SidebarToggle = /* @__PURE__ */ React.forwardRef(function AppShellSidebarToggle({ labels, className, children, onClick, ...props }, ref) {
65
+ const SidebarToggle = function AppShellSidebarToggle({ labels, className, children, onClick, ref, ...props }) {
65
66
  const shell = React.useContext(ShellContext);
66
67
  if (!shell)
67
68
  throw new Error('AppShell.SidebarToggle belongs in AppShell.Root');
68
69
  const label = shell.collapsed
69
70
  ? (labels?.expand ?? 'Expand sidebar')
70
71
  : (labels?.collapse ?? 'Collapse sidebar');
71
- return (_jsx(Tooltip, { label: label, shortcut: shell.shortcut ? shortcutLabel() : undefined, children: _jsx(Button, { variant: 'ghost', size: 'icon', ...props, ref: ref, "aria-label": label, "aria-expanded": !shell.collapsed, "aria-controls": shell.sidebarId, className: skin('pui-app-shell-toggle', className), onClick: (event) => {
72
+ return (_jsx(Tooltip, { label: label, shortcut: shell.shortcut ? (labels?.shortcut ?? shortcutLabel()) : undefined, children: _jsx(Button, { variant: 'ghost', size: 'icon', ...props, ref: ref, "aria-label": label, "aria-expanded": !shell.collapsed, "aria-controls": shell.sidebarId, className: skin('surf-app-shell-toggle', className), onClick: (event) => {
72
73
  onClick?.(event);
73
74
  if (!event.defaultPrevented)
74
75
  shell.setCollapsed(!shell.collapsed);
75
76
  }, children: children ?? _jsx(Icon, { name: 'sidebar' }) }) }));
76
- });
77
- const Header = /* @__PURE__ */ React.forwardRef(function AppShellHeader({ className, ...props }, ref) {
78
- return (_jsx("div", { ...props, ref: ref, className: cx('pui-app-shell-header', className) }));
79
- });
80
- const Sidebar = /* @__PURE__ */ React.forwardRef(function AppShellSidebar({ className, id, ...props }, ref) {
77
+ };
78
+ const Header = function AppShellHeader({ className, ref, ...props }) {
79
+ return (_jsx("div", { ...props, ref: ref, className: cx('surf-app-shell-header', className) }));
80
+ };
81
+ const Sidebar = function AppShellSidebar({ className, id, ref, ...props }) {
81
82
  const shell = React.useContext(ShellContext);
82
- return (_jsx(SidebarContext.Provider, { value: true, children: _jsx("aside", { ...props, ref: ref, id: id ?? shell?.sidebarId, className: cx('pui-app-shell-sidebar', className) }) }));
83
- });
84
- const Content = /* @__PURE__ */ React.forwardRef(function AppShellContent({ className, ...props }, ref) {
85
- return (_jsx("div", { ...props, ref: ref, className: cx('pui-app-shell-content', className) }));
86
- });
83
+ return (_jsx(SidebarContext.Provider, { value: true, children: _jsx("aside", { ...props, ref: ref, id: id ?? shell?.sidebarId, className: cx('surf-app-shell-sidebar', className) }) }));
84
+ };
85
+ const Content = function AppShellContent({ className, ref, ...props }) {
86
+ return (_jsx("div", { ...props, ref: ref, className: cx('surf-app-shell-content', className) }));
87
+ };
87
88
  /**
88
89
  * The page surface inside a workspace Content. It insets from the shell on every
89
90
  * side but the sidebar's; without the sidebar, on narrow screens, it insets evenly.
90
91
  */
91
- const Page = /* @__PURE__ */ React.forwardRef(function AppShellPage({ className, ...props }, ref) {
92
- return (_jsx("div", { ...props, ref: ref, className: cx('pui-app-shell-page', className) }));
93
- });
94
- const Footer = /* @__PURE__ */ React.forwardRef(function AppShellFooter({ className, ...props }, ref) {
95
- return (_jsx("div", { ...props, ref: ref, className: cx('pui-app-shell-footer', className) }));
96
- });
97
- const Label = /* @__PURE__ */ React.forwardRef(function AppShellLabel({ className, ...props }, ref) {
98
- return (_jsx("span", { ...props, ref: ref, className: cx('pui-app-shell-label', className) }));
99
- });
100
- const Link = /* @__PURE__ */ React.forwardRef(function AppShellLink({ icon, label, className, ...props }, ref) {
92
+ const Page = function AppShellPage({ className, ref, ...props }) {
93
+ return (_jsx("div", { ...props, ref: ref, className: cx('surf-app-shell-page', className) }));
94
+ };
95
+ const Footer = function AppShellFooter({ className, ref, ...props }) {
96
+ return (_jsx("div", { ...props, ref: ref, className: cx('surf-app-shell-footer', className) }));
97
+ };
98
+ const Label = function AppShellLabel({ className, ref, ...props }) {
99
+ return (_jsx("span", { ...props, ref: ref, className: cx('surf-app-shell-label', className) }));
100
+ };
101
+ /** The product's mark and name. In the sidebar it is the top row, its mark centered
102
+ * on the links' icons; in the header it sits on one line. Pass `render`, such as
103
+ * `<a href='/' />`, to make it a link home. */
104
+ const Brand = function AppShellBrand({ mark, name, description, render, className, ref, ...props }) {
105
+ return useRender({
106
+ defaultTagName: 'div',
107
+ render,
108
+ ref,
109
+ props: {
110
+ ...props,
111
+ className: cx('surf-app-shell-brand', className),
112
+ children: (_jsxs(_Fragment, { children: [mark != null && (_jsx("span", { className: 'surf-app-shell-brand-mark', "aria-hidden": 'true', children: mark })), _jsxs("span", { className: 'surf-app-shell-label surf-app-shell-brand-text', children: [_jsx("span", { className: 'surf-app-shell-brand-name', title: name, children: name }), description != null && (_jsx("span", { className: 'surf-app-shell-brand-description', children: description }))] })] })),
113
+ },
114
+ });
115
+ };
116
+ /** A list of Links with even gaps. In the workspace sidebar it lines its links up
117
+ * with the brand and the rail. */
118
+ const Nav = function AppShellNav({ label, className, children, ref, ...props }) {
119
+ const id = React.useId();
120
+ return (_jsxs("nav", { "aria-labelledby": label ? id : undefined, ...props, ref: ref, className: cx('surf-app-shell-nav', className), children: [label && (_jsx("span", { id: id, className: 'surf-app-shell-nav-label', children: _jsx(Label, { children: label }) })), children] }));
121
+ };
122
+ /** A destination with an icon and a name. Pass a router's link as `render` to keep
123
+ * client navigation, or another element, such as a menu trigger for the account, to
124
+ * give it the same row. */
125
+ const Link = function AppShellLink({ icon, label, render, className, ref, ...props }) {
101
126
  const shell = React.useContext(ShellContext);
102
127
  const inSidebar = React.useContext(SidebarContext);
128
+ const element = useRender({
129
+ defaultTagName: 'a',
130
+ render,
131
+ ref,
132
+ props: {
133
+ ...props,
134
+ 'aria-label': props['aria-label'] ?? label,
135
+ className: cx('surf-app-shell-link', className),
136
+ children: (_jsxs(_Fragment, { children: [_jsx("span", { className: 'surf-app-shell-icon', "aria-hidden": 'true', children: icon }), _jsx(Label, { "aria-hidden": 'true', children: label })] })),
137
+ },
138
+ });
103
139
  // On the collapsed rail only the icon shows, so the name appears as a tooltip.
104
- return (_jsx(Tooltip, { label: label, enabled: Boolean(shell?.collapsed && inSidebar), children: _jsxs("a", { ...props, ref: ref, "aria-label": props['aria-label'] ?? label, className: cx('pui-app-shell-link', className), children: [_jsx("span", { className: 'pui-app-shell-icon', "aria-hidden": 'true', children: icon }), _jsx(Label, { "aria-hidden": 'true', children: label })] }) }));
105
- });
140
+ return (_jsx(Tooltip, { label: label, disabled: !(shell?.collapsed && inSidebar), children: element }));
141
+ };
106
142
  export const AppShell = {
107
143
  Root,
108
144
  Header,
109
145
  Sidebar,
110
146
  SidebarToggle,
147
+ Brand,
148
+ Nav,
111
149
  Content,
112
150
  Page,
113
151
  Footer,
@@ -115,4 +153,4 @@ export const AppShell = {
115
153
  Link,
116
154
  };
117
155
  // Flat names for React Server Components, which cannot dot into client exports.
118
- export const { Root: AppShellRoot, Header: AppShellHeader, Sidebar: AppShellSidebar, SidebarToggle: AppShellSidebarToggle, Content: AppShellContent, Page: AppShellPage, Footer: AppShellFooter, Label: AppShellLabel, Link: AppShellLink, } = AppShell;
156
+ export const { Root: AppShellRoot, Header: AppShellHeader, Sidebar: AppShellSidebar, SidebarToggle: AppShellSidebarToggle, Brand: AppShellBrand, Nav: AppShellNav, Content: AppShellContent, Page: AppShellPage, Footer: AppShellFooter, Label: AppShellLabel, Link: AppShellLink, } = AppShell;