@surflane/ui 0.4.0 → 0.6.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 (296) hide show
  1. package/README.md +2 -2
  2. package/dist/{disclosure.d.ts → accordion.d.ts} +1 -17
  3. package/dist/{disclosure.js → accordion.js} +3 -17
  4. package/dist/alert-dialog.d.ts +31 -0
  5. package/dist/alert-dialog.js +22 -0
  6. package/dist/app-shell.d.ts +44 -3
  7. package/dist/app-shell.js +86 -13
  8. package/dist/{input-extensions.d.ts → autocomplete.d.ts} +4 -42
  9. package/dist/{input-extensions.js → autocomplete.js} +7 -26
  10. package/dist/avatar.js +3 -5
  11. package/dist/badge.d.ts +20 -0
  12. package/dist/badge.js +16 -0
  13. package/dist/bottom-navigation.d.ts +66 -0
  14. package/dist/bottom-navigation.js +36 -0
  15. package/dist/{navigation.d.ts → breadcrumbs.d.ts} +2 -6
  16. package/dist/breadcrumbs.js +31 -0
  17. package/dist/button.d.ts +11 -0
  18. package/dist/button.js +27 -4
  19. package/dist/{content.d.ts → card.d.ts} +6 -24
  20. package/dist/card.js +26 -0
  21. package/dist/chart.d.ts +35 -0
  22. package/dist/chart.js +123 -50
  23. package/dist/checkbox-group.d.ts +2 -0
  24. package/dist/checkbox-group.js +16 -0
  25. package/dist/checkbox.d.ts +9 -0
  26. package/dist/checkbox.js +29 -0
  27. package/dist/choice-label.d.ts +25 -0
  28. package/dist/choice-label.js +14 -0
  29. package/dist/choice.d.ts +7 -0
  30. package/dist/choice.js +3 -0
  31. package/dist/code.d.ts +21 -0
  32. package/dist/{content.js → code.js} +5 -30
  33. package/dist/collapsible.d.ts +18 -0
  34. package/dist/collapsible.js +21 -0
  35. package/dist/{advanced-forms.d.ts → combobox.d.ts} +5 -25
  36. package/dist/{advanced-forms.js → combobox.js} +13 -49
  37. package/dist/{context-overlays.d.ts → context-menu.d.ts} +6 -28
  38. package/dist/{context-overlays.js → context-menu.js} +5 -25
  39. package/dist/css/accordion.css +11 -0
  40. package/dist/css/alert-dialog.css +11 -0
  41. package/{src → dist/css}/all.css +1 -1
  42. package/dist/css/app-shell.css +12 -0
  43. package/dist/css/autocomplete.css +15 -0
  44. package/dist/css/avatar.css +10 -0
  45. package/dist/css/badge.css +10 -0
  46. package/dist/css/bottom-navigation.css +8 -0
  47. package/dist/css/breadcrumbs.css +12 -0
  48. package/dist/css/button.css +8 -0
  49. package/dist/css/card.css +11 -0
  50. package/dist/css/chart.css +13 -0
  51. package/dist/css/checkbox-group.css +9 -0
  52. package/dist/css/checkbox.css +9 -0
  53. package/dist/css/choice-label.css +9 -0
  54. package/dist/css/code.css +13 -0
  55. package/dist/css/collapsible.css +11 -0
  56. package/dist/css/combobox.css +14 -0
  57. package/dist/css/context-menu.css +15 -0
  58. package/dist/css/date-picker.css +12 -0
  59. package/dist/css/dialog.css +10 -0
  60. package/dist/css/drawer.css +11 -0
  61. package/dist/css/empty-state.css +9 -0
  62. package/dist/css/field.css +10 -0
  63. package/dist/css/fieldset.css +8 -0
  64. package/dist/css/file-upload.css +17 -0
  65. package/dist/css/filter-bar.css +8 -0
  66. package/dist/css/form.css +8 -0
  67. package/dist/css/icon.css +8 -0
  68. package/dist/css/inline-message.css +10 -0
  69. package/dist/css/input.css +9 -0
  70. package/dist/css/layout.css +9 -0
  71. package/dist/css/link.css +9 -0
  72. package/dist/css/list.css +9 -0
  73. package/dist/css/markdown.css +18 -0
  74. package/dist/css/menu.css +14 -0
  75. package/dist/css/menubar.css +9 -0
  76. package/dist/css/meter.css +9 -0
  77. package/dist/css/native-select.css +13 -0
  78. package/dist/css/navigation-menu.css +11 -0
  79. package/dist/css/number-field.css +11 -0
  80. package/dist/css/otp-field.css +10 -0
  81. package/dist/css/page-header.css +11 -0
  82. package/dist/css/pagination.css +11 -0
  83. package/dist/css/popover.css +9 -0
  84. package/dist/css/preview-card.css +11 -0
  85. package/dist/css/progress.css +9 -0
  86. package/dist/css/radio-group.css +9 -0
  87. package/dist/css/rules/accordion.css +21 -0
  88. package/dist/css/rules/alert-dialog.css +23 -0
  89. package/dist/css/rules/app-shell.css +220 -0
  90. package/dist/css/rules/autocomplete.css +3 -0
  91. package/dist/css/rules/avatar.css +17 -0
  92. package/dist/css/rules/badge.css +17 -0
  93. package/dist/css/rules/bar.css +38 -0
  94. package/dist/css/rules/base.css +46 -0
  95. package/dist/css/rules/bottom-navigation.css +142 -0
  96. package/dist/css/rules/breadcrumbs.css +9 -0
  97. package/dist/css/rules/button.css +131 -0
  98. package/dist/css/rules/card.css +10 -0
  99. package/dist/css/rules/chart.css +256 -0
  100. package/dist/css/rules/checkbox-group.css +3 -0
  101. package/dist/css/rules/checkbox.css +25 -0
  102. package/dist/css/rules/choice-label.css +52 -0
  103. package/dist/css/rules/choice.css +104 -0
  104. package/dist/css/rules/code.css +9 -0
  105. package/dist/css/rules/collapsible.css +12 -0
  106. package/dist/css/rules/combobox.css +177 -0
  107. package/dist/css/rules/context-menu.css +9 -0
  108. package/dist/css/rules/date-picker.css +301 -0
  109. package/dist/css/rules/dialog.css +160 -0
  110. package/dist/css/rules/disclosure.css +107 -0
  111. package/dist/css/rules/drawer.css +18 -0
  112. package/dist/css/rules/empty-state.css +9 -0
  113. package/dist/css/rules/field-control.css +70 -0
  114. package/dist/css/rules/field.css +56 -0
  115. package/dist/css/rules/fieldset.css +23 -0
  116. package/dist/css/rules/file-upload.css +156 -0
  117. package/dist/css/rules/filter-bar.css +56 -0
  118. package/dist/css/rules/form.css +15 -0
  119. package/dist/css/rules/gauge.css +61 -0
  120. package/dist/css/rules/icon.css +27 -0
  121. package/dist/css/rules/inline-message.css +10 -0
  122. package/dist/css/rules/input-group.css +69 -0
  123. package/dist/css/rules/input.css +33 -0
  124. package/dist/css/rules/item.css +14 -0
  125. package/dist/css/rules/layout.css +3 -0
  126. package/dist/css/rules/link.css +9 -0
  127. package/dist/css/rules/list.css +10 -0
  128. package/dist/css/rules/markdown.css +63 -0
  129. package/dist/css/rules/menu.css +97 -0
  130. package/dist/css/rules/menubar.css +18 -0
  131. package/dist/css/rules/meter.css +3 -0
  132. package/dist/css/rules/native-select.css +3 -0
  133. package/dist/css/rules/navigation-menu.css +159 -0
  134. package/dist/css/rules/number-field.css +55 -0
  135. package/dist/css/rules/otp-field.css +68 -0
  136. package/dist/css/rules/page-header.css +3 -0
  137. package/dist/css/rules/pagination.css +3 -0
  138. package/dist/css/rules/panel.css +221 -0
  139. package/dist/css/rules/popover.css +41 -0
  140. package/dist/css/rules/popup.css +27 -0
  141. package/dist/css/rules/preview-card.css +60 -0
  142. package/dist/css/rules/progress.css +14 -0
  143. package/dist/css/rules/radio-group.css +26 -0
  144. package/dist/css/rules/scroll-area.css +101 -0
  145. package/dist/css/rules/select.css +88 -0
  146. package/dist/css/rules/separator.css +3 -0
  147. package/dist/css/rules/sheet.css +3 -0
  148. package/dist/css/rules/sizing.css +140 -0
  149. package/dist/css/rules/skeleton.css +41 -0
  150. package/dist/css/rules/slider.css +123 -0
  151. package/dist/css/rules/sparkline.css +52 -0
  152. package/dist/css/rules/spinner.css +38 -0
  153. package/dist/css/rules/stat.css +59 -0
  154. package/dist/css/rules/switch.css +50 -0
  155. package/dist/css/rules/syntax-highlighter.css +82 -0
  156. package/dist/css/rules/table.css +28 -0
  157. package/dist/css/rules/tabs.css +126 -0
  158. package/dist/css/rules/textarea.css +21 -0
  159. package/dist/css/rules/toast.css +247 -0
  160. package/dist/css/rules/toggle-group.css +3 -0
  161. package/dist/css/rules/toggle.css +27 -0
  162. package/dist/css/rules/toolbar.css +62 -0
  163. package/dist/css/rules/tooltip.css +38 -0
  164. package/dist/css/rules/tree.css +98 -0
  165. package/dist/css/rules/typography.css +3 -0
  166. package/dist/css/scroll-area.css +8 -0
  167. package/dist/css/select.css +12 -0
  168. package/dist/css/separator.css +9 -0
  169. package/dist/css/sheet.css +11 -0
  170. package/dist/css/sizing.css +7 -0
  171. package/dist/css/skeleton.css +8 -0
  172. package/dist/css/slider.css +8 -0
  173. package/dist/css/sparkline.css +8 -0
  174. package/dist/css/spinner.css +8 -0
  175. package/dist/css/stat.css +9 -0
  176. package/dist/css/styles.css +100 -0
  177. package/dist/css/switch.css +9 -0
  178. package/dist/css/syntax-highlighter.css +9 -0
  179. package/dist/css/table.css +12 -0
  180. package/dist/css/tabs.css +8 -0
  181. package/dist/css/textarea.css +10 -0
  182. package/dist/css/toast.css +11 -0
  183. package/dist/css/toggle-group.css +9 -0
  184. package/dist/css/toggle.css +10 -0
  185. package/dist/css/toolbar.css +12 -0
  186. package/dist/css/tooltip.css +9 -0
  187. package/dist/css/tree.css +10 -0
  188. package/dist/css/typography.css +9 -0
  189. package/dist/date-picker.js +3 -2
  190. package/dist/dialog.d.ts +6 -24
  191. package/dist/dialog.js +7 -20
  192. package/dist/{panels.d.ts → drawer.d.ts} +3 -34
  193. package/dist/drawer.js +47 -0
  194. package/dist/empty-state.d.ts +29 -0
  195. package/dist/empty-state.js +19 -0
  196. package/dist/field.d.ts +42 -0
  197. package/dist/field.js +21 -0
  198. package/dist/fieldset.d.ts +14 -0
  199. package/dist/fieldset.js +10 -0
  200. package/dist/file-upload.d.ts +3 -1
  201. package/dist/file-upload.js +7 -5
  202. package/dist/filter-bar.js +1 -1
  203. package/dist/form.d.ts +2 -0
  204. package/dist/form.js +7 -0
  205. package/dist/format.d.ts +25 -0
  206. package/dist/format.js +42 -0
  207. package/dist/icon.d.ts +11 -0
  208. package/dist/icon.js +19 -3
  209. package/dist/index.d.ts +61 -30
  210. package/dist/index.js +75 -33
  211. package/dist/{messages.d.ts → inline-message.d.ts} +0 -28
  212. package/dist/{messages.js → inline-message.js} +3 -18
  213. package/dist/input.js +2 -2
  214. package/dist/{foundations.d.ts → layout.d.ts} +5 -23
  215. package/dist/{foundations.js → layout.js} +4 -19
  216. package/dist/link.d.ts +6 -0
  217. package/dist/link.js +17 -0
  218. package/dist/list.d.ts +33 -0
  219. package/dist/list.js +21 -0
  220. package/dist/markdown.js +4 -5
  221. package/dist/menu.d.ts +7 -5
  222. package/dist/menu.js +12 -8
  223. package/dist/menubar.d.ts +4 -0
  224. package/dist/menubar.js +4 -0
  225. package/dist/meter.d.ts +29 -0
  226. package/dist/meter.js +13 -0
  227. package/dist/native-select.d.ts +8 -0
  228. package/dist/native-select.js +54 -0
  229. package/dist/navigation-menu.js +8 -5
  230. package/dist/number-field.d.ts +23 -0
  231. package/dist/number-field.js +33 -0
  232. package/dist/page-header.d.ts +12 -0
  233. package/dist/page-header.js +9 -0
  234. package/dist/pagination.js +3 -4
  235. package/dist/panel.d.ts +13 -0
  236. package/dist/panel.js +13 -0
  237. package/dist/parts.d.ts +19 -1
  238. package/dist/parts.js +32 -6
  239. package/dist/popover.d.ts +23 -6
  240. package/dist/popover.js +17 -7
  241. package/dist/preview-card.d.ts +29 -0
  242. package/dist/preview-card.js +27 -0
  243. package/dist/progress.d.ts +29 -0
  244. package/dist/progress.js +13 -0
  245. package/dist/radio-group.d.ts +16 -0
  246. package/dist/radio-group.js +31 -0
  247. package/dist/scroll-area.js +3 -4
  248. package/dist/select.d.ts +8 -8
  249. package/dist/select.js +19 -54
  250. package/dist/separator.d.ts +4 -0
  251. package/dist/separator.js +8 -0
  252. package/dist/sheet.d.ts +29 -0
  253. package/dist/sheet.js +39 -0
  254. package/dist/skeleton.d.ts +8 -0
  255. package/dist/skeleton.js +8 -0
  256. package/dist/slider.d.ts +40 -0
  257. package/dist/slider.js +27 -0
  258. package/dist/sparkline.d.ts +41 -0
  259. package/dist/sparkline.js +50 -0
  260. package/dist/spinner.d.ts +13 -0
  261. package/dist/spinner.js +10 -0
  262. package/dist/stat.d.ts +59 -0
  263. package/dist/stat.js +26 -0
  264. package/dist/status.d.ts +2 -20
  265. package/dist/status.js +11 -14
  266. package/dist/switch.d.ts +13 -0
  267. package/dist/switch.js +25 -0
  268. package/dist/syntax-highlighter.js +2 -1
  269. package/dist/{data.d.ts → table.d.ts} +8 -32
  270. package/dist/{data.js → table.js} +15 -30
  271. package/dist/textarea.d.ts +7 -0
  272. package/dist/textarea.js +12 -0
  273. package/dist/toast.d.ts +57 -1
  274. package/dist/toast.js +80 -8
  275. package/dist/toggle-group.d.ts +5 -0
  276. package/dist/toggle-group.js +7 -0
  277. package/dist/toggle.d.ts +7 -0
  278. package/dist/toggle.js +9 -0
  279. package/dist/{commands.d.ts → toolbar.d.ts} +0 -13
  280. package/dist/toolbar.js +14 -0
  281. package/dist/tooltip.d.ts +10 -3
  282. package/dist/tooltip.js +4 -4
  283. package/dist/tree.js +4 -2
  284. package/dist/typography.d.ts +12 -0
  285. package/dist/typography.js +14 -0
  286. package/package.json +324 -25
  287. package/dist/chevron.d.ts +0 -3
  288. package/dist/chevron.js +0 -6
  289. package/dist/commands.js +0 -27
  290. package/dist/feedback.d.ts +0 -76
  291. package/dist/feedback.js +0 -35
  292. package/dist/forms.d.ts +0 -91
  293. package/dist/forms.js +0 -109
  294. package/dist/navigation.js +0 -41
  295. package/dist/panels.js +0 -100
  296. package/src/styles.css +0 -3780
@@ -0,0 +1,66 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ export type BottomNavigationRootProps = React.ComponentPropsWithoutRef<'nav'> & {
4
+ /** Names the navigation, such as "Primary". */
5
+ 'aria-label': string;
6
+ /** mobile: shown at 760px and narrower, where AppShell hides its sidebar. always:
7
+ * at every width. */
8
+ visible?: 'mobile' | 'always';
9
+ /** fixed: pinned to the bottom of the viewport, above the safe area. static: in the
10
+ * flow, for a frame of your own. */
11
+ position?: 'fixed' | 'static';
12
+ };
13
+ export type BottomNavigationItemProps = Omit<useRender.ComponentProps<'a'>, 'ref' | 'children'> & {
14
+ icon: React.ReactNode;
15
+ label: string;
16
+ /** Marks the current destination with aria-current="page". */
17
+ current?: boolean;
18
+ /** A count, shown up to 99+, or true for a dot. */
19
+ badge?: number | boolean;
20
+ /** What the badge means, read after the label, such as "3 unread". A count reads
21
+ * as its number without it; a dot needs it. */
22
+ badgeLabel?: string;
23
+ };
24
+ export declare const BottomNavigation: {
25
+ Root: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & {
26
+ /** Names the navigation, such as "Primary". */
27
+ 'aria-label': string;
28
+ /** mobile: shown at 760px and narrower, where AppShell hides its sidebar. always:
29
+ * at every width. */
30
+ visible?: "mobile" | "always";
31
+ /** fixed: pinned to the bottom of the viewport, above the safe area. static: in the
32
+ * flow, for a frame of your own. */
33
+ position?: "fixed" | "static";
34
+ } & React.RefAttributes<HTMLElement>>;
35
+ Item: React.ForwardRefExoticComponent<Omit<useRender.ComponentProps<"a", {}, import("@base-ui/react/types").HTMLProps>, "children" | "ref"> & {
36
+ icon: React.ReactNode;
37
+ label: string;
38
+ /** Marks the current destination with aria-current="page". */
39
+ current?: boolean;
40
+ /** A count, shown up to 99+, or true for a dot. */
41
+ badge?: number | boolean;
42
+ /** What the badge means, read after the label, such as "3 unread". A count reads
43
+ * as its number without it; a dot needs it. */
44
+ badgeLabel?: string;
45
+ } & React.RefAttributes<HTMLAnchorElement>>;
46
+ };
47
+ export declare const BottomNavigationRoot: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & {
48
+ /** Names the navigation, such as "Primary". */
49
+ 'aria-label': string;
50
+ /** mobile: shown at 760px and narrower, where AppShell hides its sidebar. always:
51
+ * at every width. */
52
+ visible?: "mobile" | "always";
53
+ /** fixed: pinned to the bottom of the viewport, above the safe area. static: in the
54
+ * flow, for a frame of your own. */
55
+ position?: "fixed" | "static";
56
+ } & React.RefAttributes<HTMLElement>>, BottomNavigationItem: React.ForwardRefExoticComponent<Omit<useRender.ComponentProps<"a", {}, import("@base-ui/react/types").HTMLProps>, "children" | "ref"> & {
57
+ icon: React.ReactNode;
58
+ label: string;
59
+ /** Marks the current destination with aria-current="page". */
60
+ current?: boolean;
61
+ /** A count, shown up to 99+, or true for a dot. */
62
+ badge?: number | boolean;
63
+ /** What the badge means, read after the label, such as "3 unread". A count reads
64
+ * as its number without it; a dot needs it. */
65
+ badgeLabel?: string;
66
+ } & React.RefAttributes<HTMLAnchorElement>>;
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { useRender } from '@base-ui/react/use-render';
5
+ import { cx } from './parts.js';
6
+ /** A phone's primary destinations along the bottom edge, within thumb reach. Pad the
7
+ * scrolling content by --size-bottom-navigation so the last line stays visible. */
8
+ const Root = /* @__PURE__ */ React.forwardRef(function BottomNavigationRoot({ visible = 'mobile', position = 'fixed', className, children, ...props }, ref) {
9
+ return (_jsx("nav", { ...props, ref: ref, "data-visible": visible, "data-position": position, className: cx('pui-bottom-nav', className), children: _jsx("ul", { role: 'list', className: 'pui-bottom-nav-list', children: children }) }));
10
+ });
11
+ /** One destination: an icon above its label. Pass a router's link element as
12
+ * `render` to keep client navigation. */
13
+ const Item = /* @__PURE__ */ React.forwardRef(function BottomNavigationItem({ icon, label, current, badge, badgeLabel, render, className, ...props }, ref) {
14
+ const count = typeof badge === 'number' && badge > 0
15
+ ? badge > 99
16
+ ? '99+'
17
+ : String(badge)
18
+ : undefined;
19
+ const shown = Boolean(count || badge === true);
20
+ const spoken = badgeLabel ?? count;
21
+ const link = useRender({
22
+ defaultTagName: 'a',
23
+ render,
24
+ ref,
25
+ props: {
26
+ ...props,
27
+ 'aria-current': current ? 'page' : props['aria-current'],
28
+ className: cx('pui-bottom-nav-item', className),
29
+ children: (_jsxs(_Fragment, { children: [_jsxs("span", { className: 'pui-bottom-nav-icon', "aria-hidden": 'true', children: [icon, shown && (_jsx("span", { className: 'pui-bottom-nav-badge', "data-dot": count ? undefined : '', children: count }))] }), _jsx("span", { className: 'pui-bottom-nav-label', children: label }), shown && spoken && (_jsxs("span", { className: 'pui-feedback-sr', children: [", ", spoken] }))] })),
30
+ },
31
+ });
32
+ return _jsx("li", { className: 'pui-bottom-nav-entry', children: link });
33
+ });
34
+ export const BottomNavigation = { Root, Item };
35
+ // Flat names for React Server Components, which cannot dot into client exports.
36
+ export const { Root: BottomNavigationRoot, Item: BottomNavigationItem } = BottomNavigation;
@@ -1,17 +1,13 @@
1
1
  import * as React from 'react';
2
- export declare const Separator: React.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react/separator").SeparatorProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref"> & {
3
- inset?: boolean;
4
- } & React.RefAttributes<HTMLDivElement>>;
5
- export declare const Link: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
6
2
  declare function BreadcrumbSeparator({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
7
3
  declare function BreadcrumbCurrent({ className, ...props }: React.ComponentProps<'span'>): React.JSX.Element;
8
4
  export declare const Breadcrumbs: {
9
5
  Root: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & React.RefAttributes<HTMLElement>>;
10
6
  List: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.OlHTMLAttributes<HTMLOListElement>, HTMLOListElement>, "ref"> & React.RefAttributes<HTMLOListElement>>;
11
7
  Item: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & React.RefAttributes<HTMLLIElement>>;
12
- Link: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
8
+ Link: React.ForwardRefExoticComponent<import("./link.js").LinkProps & React.RefAttributes<HTMLAnchorElement>>;
13
9
  Separator: typeof BreadcrumbSeparator;
14
10
  Current: typeof BreadcrumbCurrent;
15
11
  };
16
- export declare const BreadcrumbsRoot: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & React.RefAttributes<HTMLElement>>, BreadcrumbsList: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.OlHTMLAttributes<HTMLOListElement>, HTMLOListElement>, "ref"> & React.RefAttributes<HTMLOListElement>>, BreadcrumbsItem: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & React.RefAttributes<HTMLLIElement>>, BreadcrumbsLink: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref"> & React.RefAttributes<HTMLAnchorElement>>, BreadcrumbsSeparator: typeof BreadcrumbSeparator, BreadcrumbsCurrent: typeof BreadcrumbCurrent;
12
+ export declare const BreadcrumbsRoot: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & React.RefAttributes<HTMLElement>>, BreadcrumbsList: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.OlHTMLAttributes<HTMLOListElement>, HTMLOListElement>, "ref"> & React.RefAttributes<HTMLOListElement>>, BreadcrumbsItem: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & React.RefAttributes<HTMLLIElement>>, BreadcrumbsLink: React.ForwardRefExoticComponent<import("./link.js").LinkProps & React.RefAttributes<HTMLAnchorElement>>, BreadcrumbsSeparator: typeof BreadcrumbSeparator, BreadcrumbsCurrent: typeof BreadcrumbCurrent;
17
13
  export {};
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { Icon } from './icon.js';
5
+ import { cx } from './parts.js';
6
+ import { Link } from './link.js';
7
+ const BreadcrumbRoot = /* @__PURE__ */ React.forwardRef(function BreadcrumbRoot({ className, 'aria-label': label = 'Breadcrumb', ...props }, ref) {
8
+ return (_jsx("nav", { ...props, ref: ref, "aria-label": label, className: cx('pui-breadcrumbs', className) }));
9
+ });
10
+ const BreadcrumbList = /* @__PURE__ */ React.forwardRef(function BreadcrumbList({ className, role = 'list', ...props }, ref) {
11
+ return (_jsx("ol", { ...props, role: role, ref: ref, className: cx('pui-breadcrumb-list', className) }));
12
+ });
13
+ const BreadcrumbItem = /* @__PURE__ */ React.forwardRef(function BreadcrumbItem({ className, ...props }, ref) {
14
+ return (_jsx("li", { ...props, ref: ref, className: cx('pui-breadcrumb-item', className) }));
15
+ });
16
+ function BreadcrumbSeparator({ className, ...props }) {
17
+ return (_jsx("span", { ...props, className: cx('pui-breadcrumb-separator', className), "aria-hidden": 'true', children: _jsx(Icon, { name: 'chevron-forward' }) }));
18
+ }
19
+ function BreadcrumbCurrent({ className, ...props }) {
20
+ return (_jsx("span", { ...props, className: cx('pui-breadcrumb-current', className), "aria-current": 'page' }));
21
+ }
22
+ export const Breadcrumbs = {
23
+ Root: BreadcrumbRoot,
24
+ List: BreadcrumbList,
25
+ Item: BreadcrumbItem,
26
+ Link,
27
+ Separator: BreadcrumbSeparator,
28
+ Current: BreadcrumbCurrent,
29
+ };
30
+ // Flat names for React Server Components, which cannot dot into client exports.
31
+ export const { Root: BreadcrumbsRoot, List: BreadcrumbsList, Item: BreadcrumbsItem, Link: BreadcrumbsLink, Separator: BreadcrumbsSeparator, Current: BreadcrumbsCurrent, } = Breadcrumbs;
package/dist/button.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { Button as BaseButton } from '@base-ui/react/button';
3
+ import { useRender } from '@base-ui/react/use-render';
3
4
  import { type ComponentSizeAlias } from './sizing.js';
4
5
  /** Visual priority. `default` remains a compatibility alias of `primary`. */
5
6
  export type ButtonVariant = 'primary' | 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link';
@@ -9,3 +10,13 @@ export type ButtonProps = React.ComponentProps<typeof BaseButton> & {
9
10
  size?: ButtonSize;
10
11
  };
11
12
  export declare const Button: React.ForwardRefExoticComponent<Omit<ButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
13
+ export type LinkButtonProps = Omit<useRender.ComponentProps<'a'>, 'ref'> & {
14
+ variant?: ButtonVariant;
15
+ size?: ButtonSize;
16
+ };
17
+ /** A link that looks like a Button. It navigates, so it stays a link for assistive
18
+ * technology; pass a router's link element as `render` to keep client navigation. */
19
+ export declare const LinkButton: React.ForwardRefExoticComponent<Omit<useRender.ComponentProps<"a", {}, import("@base-ui/react/types").HTMLProps>, "ref"> & {
20
+ variant?: ButtonVariant;
21
+ size?: ButtonSize;
22
+ } & React.RefAttributes<HTMLAnchorElement>>;
package/dist/button.js CHANGED
@@ -2,15 +2,38 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import * as React from 'react';
4
4
  import { Button as BaseButton } from '@base-ui/react/button';
5
+ import { useRender } from '@base-ui/react/use-render';
5
6
  import { useComponentSize } from './sizing.js';
6
- import { sizeName, skin } from './parts.js';
7
- export const Button = /* @__PURE__ */ React.forwardRef(function Button({ className, variant = 'default', size, ...props }, ref) {
8
- const scheme = useComponentSize(size === 'icon-sm' || size === 'icon-xs'
7
+ import { sizeName, skin, cx } from './parts.js';
8
+ /** The size scheme a button size implies: icon sizes follow the scale, xs and icon
9
+ * keep the surrounding scheme. */
10
+ function schemeOf(size) {
11
+ return size === 'icon-sm' || size === 'icon-xs'
9
12
  ? 'small'
10
13
  : size === 'icon-lg'
11
14
  ? 'large'
12
15
  : size === 'xs' || size === 'icon'
13
16
  ? undefined
14
- : size);
17
+ : size;
18
+ }
19
+ export const Button = /* @__PURE__ */ React.forwardRef(function Button({ className, variant = 'default', size, ...props }, ref) {
20
+ const scheme = useComponentSize(schemeOf(size));
15
21
  return (_jsx(BaseButton, { ref: ref, ...props, className: skin('pui-button', className), "data-variant": variant, "data-size": sizeName(size), "data-ui-size": scheme }));
16
22
  });
23
+ /** A link that looks like a Button. It navigates, so it stays a link for assistive
24
+ * technology; pass a router's link element as `render` to keep client navigation. */
25
+ export const LinkButton = /* @__PURE__ */ React.forwardRef(function LinkButton({ render, className, variant = 'default', size, ...props }, ref) {
26
+ const scheme = useComponentSize(schemeOf(size));
27
+ return useRender({
28
+ defaultTagName: 'a',
29
+ render,
30
+ ref,
31
+ props: {
32
+ ...props,
33
+ className: cx('pui-button', className),
34
+ 'data-variant': variant,
35
+ 'data-size': sizeName(size),
36
+ 'data-ui-size': scheme,
37
+ },
38
+ });
39
+ });
@@ -1,15 +1,17 @@
1
1
  import * as React from 'react';
2
2
  declare const CardRoot: React.ForwardRefExoticComponent<Omit<Omit<React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & {
3
- tone?: "canvas" | "subtle";
4
- padding?: import("./foundations.js").Space;
3
+ surface?: import("./layout.js").SurfaceKind;
4
+ tone?: import("./layout.js").SurfaceKind;
5
+ padding?: import("./layout.js").Space;
5
6
  }, "ref"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
6
7
  declare const CardTitle: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, "ref"> & {
7
8
  level?: 2 | 3 | 4 | 5 | 6;
8
9
  } & React.RefAttributes<HTMLHeadingElement>>;
9
10
  export declare const Card: {
10
11
  Root: React.ForwardRefExoticComponent<Omit<Omit<React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & {
11
- tone?: "canvas" | "subtle";
12
- padding?: import("./foundations.js").Space;
12
+ surface?: import("./layout.js").SurfaceKind;
13
+ tone?: import("./layout.js").SurfaceKind;
14
+ padding?: import("./layout.js").Space;
13
15
  }, "ref"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
14
16
  Header: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "size"> & {
15
17
  size?: import("./sizing.js").ComponentSize;
@@ -27,26 +29,6 @@ export declare const Card: {
27
29
  size?: import("./sizing.js").ComponentSize;
28
30
  } & React.RefAttributes<HTMLDivElement>>;
29
31
  };
30
- export type CodeBlockProps = Omit<React.ComponentPropsWithoutRef<'div'>, 'children' | 'onCopy'> & {
31
- code: string;
32
- label?: string;
33
- language?: string;
34
- wrap?: boolean;
35
- copyLabel?: string;
36
- copiedLabel?: string;
37
- copyErrorLabel?: string;
38
- onCopy?: (code: string) => void | Promise<void>;
39
- };
40
- export declare const CodeBlock: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "children" | "onCopy"> & {
41
- code: string;
42
- label?: string;
43
- language?: string;
44
- wrap?: boolean;
45
- copyLabel?: string;
46
- copiedLabel?: string;
47
- copyErrorLabel?: string;
48
- onCopy?: (code: string) => void | Promise<void>;
49
- } & React.RefAttributes<HTMLDivElement>>;
50
32
  export { CardRoot, CardTitle };
51
33
  export declare const CardHeader: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "size"> & {
52
34
  size?: import("./sizing.js").ComponentSize;
package/dist/card.js ADDED
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { Surface } from './layout.js';
5
+ import { part, cx } from './parts.js';
6
+ const CardRoot = /* @__PURE__ */ React.forwardRef(function CardRoot({ className, padding, ...props }, ref) {
7
+ return (_jsx(Surface, { ...props, padding: padding, ref: ref, className: cx('pui-card', className) }));
8
+ });
9
+ const CardTitle = /* @__PURE__ */ React.forwardRef(function CardTitle({ level = 3, className, ...props }, ref) {
10
+ return React.createElement(`h${level}`, {
11
+ ...props,
12
+ ref,
13
+ className: cx('pui-card-title', className),
14
+ });
15
+ });
16
+ export const Card = {
17
+ Root: CardRoot,
18
+ Header: /* @__PURE__ */ part('div', 'pui-card-header'),
19
+ Title: CardTitle,
20
+ Description: /* @__PURE__ */ part('p', 'pui-card-description'),
21
+ Body: /* @__PURE__ */ part('div', 'pui-card-body'),
22
+ Footer: /* @__PURE__ */ part('div', 'pui-card-footer'),
23
+ };
24
+ // Flat names for React Server Components, which cannot dot into client exports.
25
+ export { CardRoot, CardTitle };
26
+ export const { Header: CardHeader, Description: CardDescription, Body: CardBody, Footer: CardFooter, } = Card;
package/dist/chart.d.ts CHANGED
@@ -18,14 +18,39 @@ export type ChartProps = Omit<React.ComponentPropsWithoutRef<'figure'>, 'childre
18
18
  yLabel: string;
19
19
  type?: 'line' | 'bar' | 'area';
20
20
  height?: number;
21
+ /** Keeps 0 on the value axis. Turn it off for values far from zero, such as
22
+ * prices, so the line uses the height; bars always start at zero. */
23
+ includeZero?: boolean;
24
+ /** neutral tells series apart by ink, dashes and markers. categorical adds six hues,
25
+ * for categories that color must separate, such as buckets or sectors. */
26
+ palette?: 'neutral' | 'categorical';
21
27
  locale?: string;
22
28
  formatValue?: (value: number) => string;
29
+ /** Text the chart shows or announces; pass translations here. */
30
+ labels?: Partial<ChartLabels>;
31
+ /** @deprecated Use labels.missing. */
23
32
  missingLabel?: string;
33
+ /** @deprecated Use labels.empty. */
24
34
  emptyLabel?: string;
25
35
  hiddenSeries?: readonly string[];
26
36
  defaultHiddenSeries?: readonly string[];
27
37
  onHiddenSeriesChange?: (keys: string[]) => void;
28
38
  };
39
+ export type ChartLabels = {
40
+ missing: string;
41
+ empty: string;
42
+ noSeries: string;
43
+ showAll: string;
44
+ keyboardHelp: string;
45
+ values: (title: string) => string;
46
+ viewTable: string;
47
+ table: (title: string) => string;
48
+ tableCaption: (unit: string) => string;
49
+ /** The readout before any point is inspected. */
50
+ inspectHint: string;
51
+ /** The data table's only row when there is no data. */
52
+ noRows: string;
53
+ };
29
54
  /** Cartesian trends with a persistent, keyboard-readable tooltip region and a
30
55
  * full data-table alternative. Missing values are gaps, never fabricated zeros. */
31
56
  export declare const Chart: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref">, "children" | "title"> & {
@@ -38,9 +63,19 @@ export declare const Chart: React.ForwardRefExoticComponent<Omit<Omit<React.Deta
38
63
  yLabel: string;
39
64
  type?: "line" | "bar" | "area";
40
65
  height?: number;
66
+ /** Keeps 0 on the value axis. Turn it off for values far from zero, such as
67
+ * prices, so the line uses the height; bars always start at zero. */
68
+ includeZero?: boolean;
69
+ /** neutral tells series apart by ink, dashes and markers. categorical adds six hues,
70
+ * for categories that color must separate, such as buckets or sectors. */
71
+ palette?: "neutral" | "categorical";
41
72
  locale?: string;
42
73
  formatValue?: (value: number) => string;
74
+ /** Text the chart shows or announces; pass translations here. */
75
+ labels?: Partial<ChartLabels>;
76
+ /** @deprecated Use labels.missing. */
43
77
  missingLabel?: string;
78
+ /** @deprecated Use labels.empty. */
44
79
  emptyLabel?: string;
45
80
  hiddenSeries?: readonly string[];
46
81
  defaultHiddenSeries?: readonly string[];
package/dist/chart.js CHANGED
@@ -1,11 +1,32 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import * as React from 'react';
4
- import { Area, Bar, CartesianGrid, ComposedChart, Line, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
5
- import { Table } from './data.js';
4
+ import { Area, Bar, CartesianGrid, ComposedChart, Line, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, useActiveTooltipCoordinate, useActiveTooltipLabel, useIsTooltipActive, usePlotArea, } from 'recharts';
5
+ import { createPortal } from 'react-dom';
6
+ import { Table } from './table.js';
6
7
  import { Button } from './button.js';
8
+ import { cx } from './parts.js';
9
+ const chartLabels = {
10
+ missing: 'Not available',
11
+ empty: 'No numeric measurements to display.',
12
+ noSeries: 'No series selected.',
13
+ showAll: 'Show all series',
14
+ keyboardHelp: 'Focus the chart and use Left/Right to inspect points. Escape clears details. The data table includes every series.',
15
+ values: (title) => `${title} values`,
16
+ viewTable: 'View data table',
17
+ table: (title) => `${title} data table`,
18
+ tableCaption: (unit) => `All input measurements, including hidden series. Unit: ${unit}.`,
19
+ inspectHint: 'Hover, touch or use chart arrow keys to inspect a measurement.',
20
+ noRows: 'No rows.',
21
+ };
22
+ /** The round step at or above a raw step: 1, 2, 2.5 or 5 times a power of ten. */
23
+ function roundStep(raw) {
24
+ if (!(raw > 0))
25
+ return 0;
26
+ const power = 10 ** Math.floor(Math.log10(raw));
27
+ return power * ([1, 2, 2.5, 5, 10].find((f) => f * power >= raw) ?? 10);
28
+ }
7
29
  const dashes = [undefined, '7 4', '2 4', '10 3 2 3', '12 5', '4 3'];
8
- const colorFor = (index) => `var(--chart-series-${(index % 3) + 1})`;
9
30
  function Marker({ cx, cy, color, index, }) {
10
31
  if (typeof cx !== 'number' ||
11
32
  typeof cy !== 'number' ||
@@ -18,14 +39,52 @@ function Marker({ cx, cy, color, index, }) {
18
39
  function Pattern({ id, index, color, }) {
19
40
  return (_jsxs("pattern", { id: id, patternUnits: 'userSpaceOnUse', width: '8', height: '8', children: [_jsx("rect", { width: '8', height: '8', fill: color }), index % 3 === 1 ? (_jsx("path", { d: 'M-2 2L2-2M0 8L8 0M6 10L10 6', stroke: 'var(--canvas)', strokeWidth: '1.5' })) : index % 3 === 2 ? (_jsx("circle", { cx: '4', cy: '4', r: '1.4', fill: 'var(--canvas)' })) : null] }));
20
41
  }
42
+ /** A series' swatch, as the legend and the floating values draw it. */
43
+ function SeriesMark({ type, index, color, pattern, }) {
44
+ return (_jsx("svg", { className: 'pui-chart-mark', viewBox: '0 0 32 20', "aria-hidden": 'true', focusable: 'false', children: type === 'bar' ? (_jsxs(_Fragment, { children: [_jsx("defs", { children: _jsx(Pattern, { id: pattern, color: color, index: index }) }), _jsx("rect", { x: '4', y: '3', width: '24', height: '14', rx: '2', fill: `url(#${pattern})` })] })) : (_jsxs(_Fragment, { children: [_jsx("path", { d: 'M1 10h30', stroke: color, strokeWidth: '2', strokeDasharray: dashes[index % dashes.length] }), _jsx(Marker, { cx: 16, cy: 10, index: index, color: color })] })) }));
45
+ }
46
+ /** The active point's values beside it, for pointer and touch users. The readout
47
+ * below the plot announces the same values, so this copy stays out of the
48
+ * accessibility tree. It sits on the side of the point with more room and stays
49
+ * inside the plot. */
50
+ function FloatingValues({ host, hidden, render, }) {
51
+ const active = useIsTooltipActive();
52
+ const label = useActiveTooltipLabel();
53
+ const point = useActiveTooltipCoordinate();
54
+ const plot = usePlotArea();
55
+ const box = React.useRef(null);
56
+ const [width, setWidth] = React.useState(0);
57
+ const shown = Boolean(host && !hidden && active && label !== undefined && point && plot);
58
+ React.useLayoutEffect(() => {
59
+ if (shown && box.current)
60
+ setWidth(box.current.offsetWidth);
61
+ }, [shown, label, plot?.width]);
62
+ if (!shown || !point || !plot)
63
+ return null;
64
+ // The gap between the point and the box, in px: the --space-3 step.
65
+ const gap = 12;
66
+ const start = point.x > plot.x + plot.width / 2;
67
+ const left = Math.min(Math.max(start ? point.x - gap - width : point.x + gap, plot.x), plot.x + plot.width - width);
68
+ return createPortal(_jsx("div", { ref: box, className: 'pui-chart-tooltip', "aria-hidden": 'true', style: { left, top: plot.y, visibility: width ? undefined : 'hidden' }, children: render(String(label)) }), host);
69
+ }
21
70
  /** Cartesian trends with a persistent, keyboard-readable tooltip region and a
22
71
  * full data-table alternative. Missing values are gaps, never fabricated zeros. */
23
- export const Chart = /* @__PURE__ */ React.forwardRef(function Chart({ title, description, data, series, unit, xLabel, yLabel, type = 'line', height = 280, locale = 'en-US', formatValue, missingLabel = 'Not available', emptyLabel = 'No numeric measurements to display.', hiddenSeries, defaultHiddenSeries = [], onHiddenSeriesChange, className, ...props }, ref) {
72
+ export const Chart = /* @__PURE__ */ React.forwardRef(function Chart({ title, description, data, series, unit, xLabel, yLabel, type = 'line', height = 280, includeZero = true, palette = 'neutral', locale = 'en-US', formatValue, labels, missingLabel, emptyLabel, hiddenSeries, defaultHiddenSeries = [], onHiddenSeriesChange, className, ...props }, ref) {
73
+ const text = {
74
+ ...chartLabels,
75
+ ...(missingLabel === undefined ? {} : { missing: missingLabel }),
76
+ ...(emptyLabel === undefined ? {} : { empty: emptyLabel }),
77
+ ...labels,
78
+ };
24
79
  const id = React.useId().replace(/[^a-zA-Z0-9_-]/g, '_');
80
+ const colorFor = (index) => palette === 'categorical'
81
+ ? `var(--chart-category-${(index % 6) + 1})`
82
+ : `var(--chart-series-${(index % 3) + 1})`;
25
83
  const [internalHidden, setInternalHidden] = React.useState(defaultHiddenSeries);
26
84
  const hidden = new Set(hiddenSeries ?? internalHidden);
27
85
  const visible = series.filter((s) => !hidden.has(s.key));
28
86
  const [host, setHost] = React.useState(null);
87
+ const [floatHost, setFloatHost] = React.useState(null);
29
88
  const [dismissed, setDismissed] = React.useState(false);
30
89
  const firstLegend = React.useRef(null);
31
90
  const [restoreRequested, setRestoreRequested] = React.useState(false);
@@ -43,7 +102,7 @@ export const Chart = /* @__PURE__ */ React.forwardRef(function Chart({ title, de
43
102
  }), [locale]);
44
103
  const format = (value) => typeof value === 'number' && Number.isFinite(value)
45
104
  ? `${formatValue ? formatValue(value) : number.format(value)} ${unit}`
46
- : missingLabel;
105
+ : text.missing;
47
106
  const rows = React.useMemo(() => {
48
107
  const ids = new Set(), keys = new Set();
49
108
  for (const s of series) {
@@ -71,7 +130,16 @@ export const Chart = /* @__PURE__ */ React.forwardRef(function Chart({ title, de
71
130
  const values = rows
72
131
  .flatMap((row) => visible.map((s) => row.values[s.key]))
73
132
  .filter((value) => typeof value === 'number');
74
- const min = values.reduce((a, b) => Math.min(a, b), 0), max = values.reduce((a, b) => Math.max(a, b), 0);
133
+ // Bars grow from zero, so they always keep it on the axis. Without zero, the axis
134
+ // spans the values, widened to round steps so its ticks read cleanly.
135
+ const keepZero = includeZero || type === 'bar';
136
+ const start = keepZero ? 0 : (values[0] ?? 0);
137
+ const low = values.reduce((a, b) => Math.min(a, b), start), high = values.reduce((a, b) => Math.max(a, b), start);
138
+ const step = keepZero ? 0 : roundStep((high - low) / 4);
139
+ const min = step ? Math.floor(low / step) * step : low, max = step ? Math.ceil(high / step) * step : high;
140
+ const ticks = step
141
+ ? Array.from({ length: Math.round((max - min) / step) + 1 }, (_, index) => min + index * step)
142
+ : undefined;
75
143
  const hasValues = values.length > 0;
76
144
  const changeHidden = (next) => {
77
145
  if (hiddenSeries === undefined)
@@ -82,48 +150,53 @@ export const Chart = /* @__PURE__ */ React.forwardRef(function Chart({ title, de
82
150
  .filter((s) => (s.key === key ? !hidden.has(key) : hidden.has(s.key)))
83
151
  .map((s) => s.key));
84
152
  const chartHeight = Number.isFinite(height) ? Math.max(200, height) : 280;
85
- return (_jsxs("figure", { ...props, ref: ref, className: ['pui-chart', className].filter(Boolean).join(' '), "aria-labelledby": `${id}-title`, children: [_jsxs("figcaption", { className: 'pui-chart-caption', children: [_jsx("strong", { id: `${id}-title`, children: title }), _jsx("p", { id: `${id}-summary`, children: description })] }), _jsx("ul", { className: 'pui-chart-legend', "aria-label": `${title} series`, children: series.map((s, index) => (_jsx("li", { children: _jsxs("button", { ref: index === 0 ? firstLegend : undefined, type: 'button', className: 'pui-chart-legend-button', "aria-label": `${s.label} series`, "aria-pressed": !hidden.has(s.key), onClick: () => toggle(s.key), children: [_jsx("svg", { width: '32', height: '20', viewBox: '0 0 32 20', "aria-hidden": 'true', children: type === 'bar' ? (_jsxs(_Fragment, { children: [_jsx("defs", { children: _jsx(Pattern, { id: `${id}-legend-${index}`, color: colorFor(index), index: index }) }), _jsx("rect", { x: '4', y: '3', width: '24', height: '14', rx: '2', fill: `url(#${id}-legend-${index})` })] })) : (_jsxs(_Fragment, { children: [_jsx("path", { d: 'M1 10h30', stroke: colorFor(index), strokeWidth: '2', strokeDasharray: dashes[index % dashes.length] }), _jsx(Marker, { cx: 16, cy: 10, index: index, color: colorFor(index) })] })) }), _jsx("span", { children: s.label })] }) }, s.key))) }), _jsxs("p", { className: 'pui-chart-axis-label', children: [yLabel, " (", unit, ")"] }), hasValues ? (_jsxs(_Fragment, { children: [_jsx("p", { className: 'pui-chart-help', id: `${id}-keys`, children: "Focus the chart and use Left/Right to inspect points. Escape clears details. The data table includes every series." }), _jsx("div", { className: 'pui-chart-plot', onKeyDownCapture: (event) => {
86
- if (event.key === 'Escape')
87
- setDismissed(true);
88
- else if (event.key === 'ArrowLeft' ||
89
- event.key === 'ArrowRight')
90
- setDismissed(false);
91
- }, onMouseMoveCapture: () => setDismissed(false), onTouchStartCapture: () => setDismissed(false), onFocusCapture: () => setDismissed(false), children: _jsx(ResponsiveContainer, { width: '100%', height: chartHeight, minWidth: 0, initialDimension: { width: 320, height: chartHeight }, children: _jsxs(ComposedChart, { data: rows, accessibilityLayer: true, role: 'application', "aria-label": title, "aria-describedby": `${id}-summary ${id}-keys`, margin: { top: 16, right: 20, bottom: 8, left: 0 }, children: [_jsx("defs", { children: series.map((s, index) => (_jsx(Pattern, { id: `${id}-pattern-${index}`, index: index, color: colorFor(index) }, s.key))) }), _jsx(CartesianGrid, { vertical: false, stroke: 'var(--line)' }), _jsx(XAxis, { dataKey: 'id', tickFormatter: (value) => {
92
- const label = byId.get(String(value))?.label ?? String(value);
93
- // minTickGap already drops ticks that would overlap; the cap
94
- // only keeps one very long label from crowding the axis.
95
- return label.length > 24
96
- ? label.slice(0, 23) + '…'
97
- : label;
98
- }, tick: { fill: 'var(--ink-muted)', fontSize: 12 }, tickLine: false, axisLine: { stroke: 'var(--line)' }, minTickGap: 24, interval: 'preserveStartEnd' }), _jsx(YAxis, { width: 56, tickFormatter: (value) => compact.format(Number(value)), tick: { fill: 'var(--ink-muted)', fontSize: 12 }, tickLine: false, axisLine: false, domain: [min, max === min ? max + 1 : max] }), _jsx(ReferenceLine, { y: 0, stroke: 'var(--ink-muted)' }), host && (_jsx(Tooltip, { portal: host, isAnimationActive: false, active: dismissed ? false : undefined, filterNull: false, cursor: dismissed
99
- ? false
100
- : {
101
- stroke: 'var(--control-border)',
102
- fill: 'transparent',
103
- }, wrapperStyle: {
104
- position: 'static',
105
- visibility: 'visible',
106
- pointerEvents: 'auto',
107
- }, content: (tooltip) => {
108
- const row = tooltip.active && !dismissed
109
- ? byId.get(String(tooltip.label))
110
- : undefined;
111
- return (_jsx("div", { className: 'pui-chart-readout', "data-chart-readout": row?.id, children: row ? (_jsxs(_Fragment, { children: [_jsx("strong", { children: row.label }), _jsx("ul", { children: visible.map((s) => (_jsxs("li", { children: [s.label, ": ", format(row.values[s.key])] }, s.key))) })] })) : (_jsx("span", { children: "Hover, touch or use chart arrow keys to inspect a measurement." })) }));
112
- } })), series.map((s, index) => {
113
- const common = {
114
- name: s.label,
115
- dataKey: (row) => row.values[s.key] ?? null,
116
- hide: hidden.has(s.key),
117
- isAnimationActive: false,
118
- stroke: colorFor(index),
119
- };
120
- return type === 'bar' ? (_jsx(Bar, { ...common, fill: `url(#${id}-pattern-${index})`, maxBarSize: 48 }, s.key)) : type === 'area' ? (_jsx(Area, { ...common, type: 'linear', strokeWidth: 2, strokeDasharray: dashes[index % dashes.length], fill: `url(#${id}-pattern-${index})`, fillOpacity: 0.12, connectNulls: false, dot: rows.length > 40
121
- ? false
122
- : (dot) => (_jsx(Marker, { ...dot, color: colorFor(index), index: index })), activeDot: false }, s.key)) : (_jsx(Line, { ...common, type: 'linear', strokeWidth: 2, strokeDasharray: dashes[index % dashes.length], connectNulls: false, dot: rows.length > 40
123
- ? false
124
- : (dot) => (_jsx(Marker, { ...dot, color: colorFor(index), index: index })), activeDot: false }, s.key));
125
- })] }) }) }), _jsx("p", { className: 'pui-chart-axis-label pui-chart-x-label', children: xLabel })] })) : (_jsx("div", { className: 'pui-chart-empty', role: 'status', children: visible.length === 0 && series.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("p", { children: "No series selected." }), _jsx(Button, { variant: 'outline', onClick: () => {
126
- setRestoreRequested(true);
127
- changeHidden([]);
128
- }, children: "Show all series" })] })) : (_jsx("p", { children: emptyLabel })) })), _jsx("div", { className: 'pui-chart-inspector', ref: setHost, role: 'status', "aria-live": 'polite', "aria-atomic": 'true', "aria-label": `${title} values`, hidden: !hasValues }), _jsxs("details", { className: 'pui-chart-table', children: [_jsx("summary", { children: "View data table" }), _jsx(Table.Container, { label: `${title} data table`, orientation: 'both', scrollChain: 'contain', style: { maxHeight: 320 }, children: _jsxs(Table.Root, { children: [_jsxs(Table.Caption, { children: ["All input measurements, including hidden series. Unit: ", unit, "."] }), _jsx(Table.Head, { children: _jsxs(Table.Row, { children: [_jsx(Table.HeaderCell, { scope: 'col', children: xLabel }), series.map((s) => (_jsxs(Table.HeaderCell, { scope: 'col', children: [s.label, " (", unit, ")"] }, s.key)))] }) }), _jsx(Table.Body, { children: rows.length ? (rows.map((row) => (_jsxs(Table.Row, { children: [_jsx(Table.HeaderCell, { scope: 'row', children: row.label }), series.map((s) => (_jsx(Table.Cell, { children: format(row.values[s.key]) }, s.key)))] }, row.id)))) : (_jsx(Table.Row, { children: _jsx(Table.Cell, { colSpan: series.length + 1, children: "No rows." }) })) })] }) })] })] }));
153
+ return (_jsxs("figure", { ...props, ref: ref, className: cx('pui-chart', className), "aria-labelledby": `${id}-title`, children: [_jsxs("figcaption", { className: 'pui-chart-caption', children: [_jsx("strong", { id: `${id}-title`, children: title }), _jsx("p", { id: `${id}-summary`, children: description })] }), _jsxs("div", { className: 'pui-chart-frame', children: [_jsxs("div", { className: 'pui-chart-key', children: [_jsxs("p", { className: 'pui-chart-axis-label', children: [yLabel, " (", unit, ")"] }), _jsx("ul", { className: 'pui-chart-legend', "aria-label": `${title} series`, children: series.map((s, index) => (_jsx("li", { children: _jsxs("button", { ref: index === 0 ? firstLegend : undefined, type: 'button', className: 'pui-chart-legend-button', "aria-label": `${s.label} series`, "aria-pressed": !hidden.has(s.key), onClick: () => toggle(s.key), children: [_jsx(SeriesMark, { type: type, index: index, color: colorFor(index), pattern: `${id}-legend-${index}` }), _jsx("span", { children: s.label })] }) }, s.key))) })] }), hasValues ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: 'pui-chart-plot', onKeyDownCapture: (event) => {
154
+ if (event.key === 'Escape')
155
+ setDismissed(true);
156
+ else if (event.key === 'ArrowLeft' ||
157
+ event.key === 'ArrowRight')
158
+ setDismissed(false);
159
+ }, onMouseMoveCapture: () => setDismissed(false), onTouchStartCapture: () => setDismissed(false), onFocusCapture: () => setDismissed(false), children: [_jsx(ResponsiveContainer, { width: '100%', height: chartHeight, minWidth: 0, initialDimension: { width: 320, height: chartHeight }, children: _jsxs(ComposedChart, { data: rows, accessibilityLayer: true, role: 'application', "aria-label": title, "aria-describedby": `${id}-summary ${id}-keys`, margin: { top: 16, right: 20, bottom: 8, left: 0 }, children: [_jsx("defs", { children: series.map((s, index) => (_jsx(Pattern, { id: `${id}-pattern-${index}`, index: index, color: colorFor(index) }, s.key))) }), _jsx(CartesianGrid, { vertical: false, stroke: 'var(--line)' }), _jsx(XAxis, { dataKey: 'id', tickFormatter: (value) => {
160
+ const label = byId.get(String(value))?.label ?? String(value);
161
+ // minTickGap already drops ticks that would overlap; the cap
162
+ // only keeps one very long label from crowding the axis.
163
+ return label.length > 24
164
+ ? label.slice(0, 23) + '…'
165
+ : label;
166
+ }, tick: { fill: 'var(--ink-muted)', fontSize: 12 }, tickLine: false, axisLine: { stroke: 'var(--line)' }, minTickGap: 24, interval: 'preserveStartEnd' }), _jsx(YAxis, { width: 56, tickFormatter: (value) => compact.format(Number(value)), tick: { fill: 'var(--ink-muted)', fontSize: 12 }, tickLine: false, axisLine: false, domain: [min, max === min ? max + 1 : max], ticks: ticks }), _jsx(ReferenceLine, { y: 0, stroke: 'var(--ink-muted)' }), host && (_jsx(Tooltip, { portal: host, isAnimationActive: false, active: dismissed ? false : undefined, filterNull: false, cursor: dismissed
167
+ ? false
168
+ : {
169
+ stroke: 'var(--control-border)',
170
+ fill: 'transparent',
171
+ }, wrapperStyle: {
172
+ position: 'static',
173
+ visibility: 'visible',
174
+ pointerEvents: 'auto',
175
+ }, content: (tooltip) => {
176
+ const row = tooltip.active && !dismissed
177
+ ? byId.get(String(tooltip.label))
178
+ : undefined;
179
+ return (_jsx("div", { className: 'pui-chart-readout', "data-chart-readout": row?.id, children: row ? (_jsxs(_Fragment, { children: [_jsx("strong", { children: row.label }), _jsx("ul", { children: visible.map((s) => (_jsxs("li", { children: [s.label, ": ", format(row.values[s.key])] }, s.key))) })] })) : (_jsx("span", { children: text.inspectHint })) }));
180
+ } })), series.map((s, index) => {
181
+ const common = {
182
+ name: s.label,
183
+ dataKey: (row) => row.values[s.key] ?? null,
184
+ hide: hidden.has(s.key),
185
+ isAnimationActive: false,
186
+ stroke: colorFor(index),
187
+ };
188
+ return type === 'bar' ? (_jsx(Bar, { ...common, fill: `url(#${id}-pattern-${index})`, maxBarSize: 48 }, s.key)) : type === 'area' ? (_jsx(Area, { ...common, type: 'linear', strokeWidth: 2, strokeDasharray: dashes[index % dashes.length], fill: `url(#${id}-pattern-${index})`, fillOpacity: 0.12, connectNulls: false, dot: rows.length > 40
189
+ ? false
190
+ : (dot) => (_jsx(Marker, { ...dot, color: colorFor(index), index: index })), activeDot: false }, s.key)) : (_jsx(Line, { ...common, type: 'linear', strokeWidth: 2, strokeDasharray: dashes[index % dashes.length], connectNulls: false, dot: rows.length > 40
191
+ ? false
192
+ : (dot) => (_jsx(Marker, { ...dot, color: colorFor(index), index: index })), activeDot: false }, s.key));
193
+ }), _jsx(FloatingValues, { host: floatHost, hidden: dismissed, render: (label) => {
194
+ const row = byId.get(label);
195
+ if (!row)
196
+ return null;
197
+ return (_jsxs(_Fragment, { children: [_jsx("strong", { children: row.label }), _jsx("ul", { children: series.map((s, index) => hidden.has(s.key) ? null : (_jsxs("li", { children: [_jsx(SeriesMark, { type: type, index: index, color: colorFor(index), pattern: `${id}-float-${index}` }), _jsx("span", { children: s.label }), _jsx("span", { className: 'pui-chart-tooltip-value', children: format(row.values[s.key]) })] }, s.key))) })] }));
198
+ } })] }) }), _jsx("div", { className: 'pui-chart-float', ref: setFloatHost })] }), _jsx("p", { className: 'pui-chart-axis-label pui-chart-x-label', children: xLabel })] })) : (_jsx("div", { className: 'pui-chart-empty', role: 'status', children: visible.length === 0 && series.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("p", { children: text.noSeries }), _jsx(Button, { variant: 'outline', onClick: () => {
199
+ setRestoreRequested(true);
200
+ changeHidden([]);
201
+ }, children: text.showAll })] })) : (_jsx("p", { children: text.empty })) }))] }), hasValues && (_jsx("p", { className: 'pui-chart-help', id: `${id}-keys`, children: text.keyboardHelp })), _jsx("div", { className: 'pui-chart-inspector', ref: setHost, role: 'status', "aria-live": 'polite', "aria-atomic": 'true', "aria-label": text.values(title), hidden: !hasValues }), _jsxs("details", { className: 'pui-chart-table', children: [_jsx("summary", { children: text.viewTable }), _jsx(Table.Container, { label: text.table(title), orientation: 'both', scrollChain: 'contain', children: _jsxs(Table.Root, { children: [_jsx(Table.Caption, { children: text.tableCaption(unit) }), _jsx(Table.Head, { children: _jsxs(Table.Row, { children: [_jsx(Table.HeaderCell, { scope: 'col', children: xLabel }), series.map((s) => (_jsxs(Table.HeaderCell, { scope: 'col', children: [s.label, " (", unit, ")"] }, s.key)))] }) }), _jsx(Table.Body, { children: rows.length ? (rows.map((row) => (_jsxs(Table.Row, { children: [_jsx(Table.HeaderCell, { scope: 'row', children: row.label }), series.map((s) => (_jsx(Table.Cell, { children: format(row.values[s.key]) }, s.key)))] }, row.id)))) : (_jsx(Table.Row, { children: _jsx(Table.Cell, { colSpan: series.length + 1, children: text.noRows }) })) })] }) })] })] }));
129
202
  });
@@ -0,0 +1,2 @@
1
+ import * as React from 'react';
2
+ export declare const CheckboxGroup: React.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react/checkbox-group").CheckboxGroupProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;