@kennycorrea/ui 0.11.4 → 1.7.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 (242) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/README.md +251 -1
  3. package/dist/atoms/ActionMenu/ActionMenu.d.ts +37 -0
  4. package/dist/atoms/ActionMenu/ActionMenu.js +28 -0
  5. package/dist/atoms/ActionMenu/index.d.ts +1 -0
  6. package/dist/atoms/ActionMenu/index.js +1 -0
  7. package/dist/atoms/ActionSheet/ActionSheet.d.ts +10 -4
  8. package/dist/atoms/ActionSheet/ActionSheet.js +6 -15
  9. package/dist/atoms/ActionSheet/confirm.d.ts +1 -1
  10. package/dist/atoms/ActionSheet/confirm.js +1 -1
  11. package/dist/atoms/Avatar/Avatar.d.ts +1 -1
  12. package/dist/atoms/Badge/Badge.js +4 -4
  13. package/dist/atoms/Button/Button.js +2 -3
  14. package/dist/atoms/Button/Button.types.d.ts +5 -8
  15. package/dist/atoms/ContextMenu/ContextMenu.d.ts +1 -1
  16. package/dist/atoms/ContextMenu/ContextMenu.js +1 -1
  17. package/dist/atoms/Icon/Icon.d.ts +7 -9
  18. package/dist/atoms/Icon/Icon.js +23 -8
  19. package/dist/atoms/Pill/Pill.d.ts +17 -0
  20. package/dist/atoms/Pill/Pill.js +12 -0
  21. package/dist/atoms/Pill/index.d.ts +1 -0
  22. package/dist/atoms/Pill/index.js +1 -0
  23. package/dist/atoms/ResponsiveDialog/ResponsiveDialog.d.ts +9 -2
  24. package/dist/atoms/ResponsiveDialog/ResponsiveDialog.js +6 -15
  25. package/dist/atoms/StatusIndicator/StatusIndicator.d.ts +14 -0
  26. package/dist/atoms/StatusIndicator/StatusIndicator.js +8 -0
  27. package/dist/atoms/StatusIndicator/index.d.ts +1 -0
  28. package/dist/atoms/StatusIndicator/index.js +1 -0
  29. package/dist/atoms/TextLink/TextLink.d.ts +36 -0
  30. package/dist/atoms/TextLink/TextLink.js +17 -0
  31. package/dist/atoms/TextLink/index.d.ts +1 -0
  32. package/dist/atoms/TextLink/index.js +1 -0
  33. package/dist/atoms/Toast/Toast.d.ts +1 -1
  34. package/dist/atoms/Toast/Toast.js +1 -1
  35. package/dist/atoms/index.d.ts +4 -0
  36. package/dist/atoms/index.js +4 -0
  37. package/dist/hooks/breakpoints.d.ts +20 -0
  38. package/dist/hooks/breakpoints.js +13 -0
  39. package/dist/hooks/index.d.ts +4 -0
  40. package/dist/hooks/index.js +4 -0
  41. package/dist/hooks/useControllableState.d.ts +17 -0
  42. package/dist/hooks/useControllableState.js +22 -0
  43. package/dist/hooks/useElementWidth.d.ts +7 -0
  44. package/dist/hooks/useElementWidth.js +22 -0
  45. package/dist/hooks/useMediaQuery.d.ts +18 -0
  46. package/dist/hooks/useMediaQuery.js +51 -0
  47. package/dist/index.d.ts +4 -0
  48. package/dist/index.js +4 -0
  49. package/dist/molecules/AccentPicker/AccentPicker.d.ts +30 -0
  50. package/dist/molecules/AccentPicker/AccentPicker.js +27 -0
  51. package/dist/molecules/AccentPicker/index.d.ts +1 -0
  52. package/dist/molecules/AccentPicker/index.js +1 -0
  53. package/dist/molecules/Breadcrumbs/Breadcrumbs.d.ts +27 -0
  54. package/dist/molecules/Breadcrumbs/Breadcrumbs.js +40 -0
  55. package/dist/molecules/Breadcrumbs/index.d.ts +1 -0
  56. package/dist/molecules/Breadcrumbs/index.js +1 -0
  57. package/dist/molecules/Calendar/Calendar.d.ts +42 -0
  58. package/dist/molecules/Calendar/Calendar.js +111 -0
  59. package/dist/molecules/Calendar/index.d.ts +1 -0
  60. package/dist/molecules/Calendar/index.js +1 -0
  61. package/dist/molecules/DateInput/DateInput.d.ts +35 -0
  62. package/dist/molecules/DateInput/DateInput.js +41 -0
  63. package/dist/molecules/DateInput/index.d.ts +1 -0
  64. package/dist/molecules/DateInput/index.js +1 -0
  65. package/dist/molecules/EmptyState/EmptyState.d.ts +19 -0
  66. package/dist/molecules/EmptyState/EmptyState.js +7 -0
  67. package/dist/molecules/EmptyState/index.d.ts +1 -0
  68. package/dist/molecules/EmptyState/index.js +1 -0
  69. package/dist/molecules/ErrorState/ErrorState.d.ts +18 -0
  70. package/dist/molecules/ErrorState/ErrorState.js +12 -0
  71. package/dist/molecules/ErrorState/index.d.ts +1 -0
  72. package/dist/molecules/ErrorState/index.js +1 -0
  73. package/dist/molecules/ErrorSummary/ErrorSummary.d.ts +25 -0
  74. package/dist/molecules/ErrorSummary/ErrorSummary.js +32 -0
  75. package/dist/molecules/ErrorSummary/index.d.ts +1 -0
  76. package/dist/molecules/ErrorSummary/index.js +1 -0
  77. package/dist/molecules/FilterChips/FilterChips.d.ts +10 -0
  78. package/dist/molecules/FilterChips/FilterChips.js +13 -0
  79. package/dist/molecules/FilterChips/index.d.ts +1 -0
  80. package/dist/molecules/FilterChips/index.js +1 -0
  81. package/dist/molecules/FilterPopover/FilterPopover.d.ts +27 -0
  82. package/dist/molecules/FilterPopover/FilterPopover.js +32 -0
  83. package/dist/molecules/FilterPopover/index.d.ts +1 -0
  84. package/dist/molecules/FilterPopover/index.js +1 -0
  85. package/dist/molecules/FormActions/FormActions.d.ts +16 -0
  86. package/dist/molecules/FormActions/FormActions.js +5 -0
  87. package/dist/molecules/FormActions/index.d.ts +1 -0
  88. package/dist/molecules/FormActions/index.js +1 -0
  89. package/dist/molecules/FormField/FormField.d.ts +52 -0
  90. package/dist/molecules/FormField/FormField.js +63 -0
  91. package/dist/molecules/FormField/index.d.ts +1 -0
  92. package/dist/molecules/FormField/index.js +1 -0
  93. package/dist/molecules/FormSection/FormSection.d.ts +14 -0
  94. package/dist/molecules/FormSection/FormSection.js +10 -0
  95. package/dist/molecules/FormSection/index.d.ts +1 -0
  96. package/dist/molecules/FormSection/index.js +1 -0
  97. package/dist/molecules/KeyValueList/KeyValueList.d.ts +22 -0
  98. package/dist/molecules/KeyValueList/KeyValueList.js +9 -0
  99. package/dist/molecules/KeyValueList/index.d.ts +1 -0
  100. package/dist/molecules/KeyValueList/index.js +1 -0
  101. package/dist/molecules/LoadingState/LoadingState.d.ts +20 -0
  102. package/dist/molecules/LoadingState/LoadingState.js +22 -0
  103. package/dist/molecules/LoadingState/index.d.ts +1 -0
  104. package/dist/molecules/LoadingState/index.js +1 -0
  105. package/dist/molecules/NavItem/NavItem.d.ts +34 -0
  106. package/dist/molecules/NavItem/NavItem.js +72 -0
  107. package/dist/molecules/NavItem/context.d.ts +19 -0
  108. package/dist/molecules/NavItem/context.js +5 -0
  109. package/dist/molecules/NavItem/index.d.ts +1 -0
  110. package/dist/molecules/NavItem/index.js +1 -0
  111. package/dist/molecules/Pagination/Pagination.d.ts +32 -0
  112. package/dist/molecules/Pagination/Pagination.js +57 -0
  113. package/dist/molecules/Pagination/index.d.ts +1 -0
  114. package/dist/molecules/Pagination/index.js +1 -0
  115. package/dist/molecules/PasswordInput/PasswordInput.d.ts +14 -0
  116. package/dist/molecules/PasswordInput/PasswordInput.js +16 -0
  117. package/dist/molecules/PasswordInput/index.d.ts +1 -0
  118. package/dist/molecules/PasswordInput/index.js +1 -0
  119. package/dist/molecules/SearchField/SearchField.d.ts +24 -0
  120. package/dist/molecules/SearchField/SearchField.js +58 -0
  121. package/dist/molecules/SearchField/index.d.ts +1 -0
  122. package/dist/molecules/SearchField/index.js +1 -0
  123. package/dist/molecules/StatGroup/StatGroup.d.ts +21 -0
  124. package/dist/molecules/StatGroup/StatGroup.js +10 -0
  125. package/dist/molecules/StatGroup/index.d.ts +1 -0
  126. package/dist/molecules/StatGroup/index.js +1 -0
  127. package/dist/molecules/ThemeToggle/ThemeToggle.d.ts +23 -0
  128. package/dist/molecules/ThemeToggle/ThemeToggle.js +26 -0
  129. package/dist/molecules/ThemeToggle/index.d.ts +1 -0
  130. package/dist/molecules/ThemeToggle/index.js +1 -0
  131. package/dist/molecules/UserMenu/UserMenu.d.ts +20 -0
  132. package/dist/molecules/UserMenu/UserMenu.js +14 -0
  133. package/dist/molecules/UserMenu/index.d.ts +1 -0
  134. package/dist/molecules/UserMenu/index.js +1 -0
  135. package/dist/molecules/index.d.ts +21 -0
  136. package/dist/molecules/index.js +21 -0
  137. package/dist/organisms/AppShell/AppShell.d.ts +29 -0
  138. package/dist/organisms/AppShell/AppShell.js +34 -0
  139. package/dist/organisms/AppShell/context.d.ts +14 -0
  140. package/dist/organisms/AppShell/context.js +6 -0
  141. package/dist/organisms/AppShell/index.d.ts +1 -0
  142. package/dist/organisms/AppShell/index.js +1 -0
  143. package/dist/organisms/AuthForms/AuthForms.d.ts +83 -0
  144. package/dist/organisms/AuthForms/AuthForms.js +57 -0
  145. package/dist/organisms/AuthForms/index.d.ts +2 -0
  146. package/dist/organisms/AuthForms/index.js +1 -0
  147. package/dist/organisms/AuthForms/shared.d.ts +36 -0
  148. package/dist/organisms/AuthForms/shared.js +36 -0
  149. package/dist/organisms/BulkActionBar/BulkActionBar.d.ts +25 -0
  150. package/dist/organisms/BulkActionBar/BulkActionBar.js +18 -0
  151. package/dist/organisms/BulkActionBar/index.d.ts +1 -0
  152. package/dist/organisms/BulkActionBar/index.js +1 -0
  153. package/dist/organisms/Chart/CategoryCharts.d.ts +34 -0
  154. package/dist/organisms/Chart/CategoryCharts.js +93 -0
  155. package/dist/organisms/Chart/ChartFrame.d.ts +26 -0
  156. package/dist/organisms/Chart/ChartFrame.js +18 -0
  157. package/dist/organisms/Chart/DonutChart.d.ts +25 -0
  158. package/dist/organisms/Chart/DonutChart.js +53 -0
  159. package/dist/organisms/Chart/Sparkline.d.ts +15 -0
  160. package/dist/organisms/Chart/Sparkline.js +18 -0
  161. package/dist/organisms/Chart/index.d.ts +5 -0
  162. package/dist/organisms/Chart/index.js +5 -0
  163. package/dist/organisms/Chart/shared.d.ts +51 -0
  164. package/dist/organisms/Chart/shared.js +113 -0
  165. package/dist/organisms/DataTable/DataTable.d.ts +63 -0
  166. package/dist/organisms/DataTable/DataTable.js +120 -0
  167. package/dist/organisms/DataTable/index.d.ts +3 -0
  168. package/dist/organisms/DataTable/index.js +3 -0
  169. package/dist/organisms/DataTable/types.d.ts +39 -0
  170. package/dist/organisms/DataTable/types.js +1 -0
  171. package/dist/organisms/DataTable/useClientTable.d.ts +27 -0
  172. package/dist/organisms/DataTable/useClientTable.js +51 -0
  173. package/dist/organisms/DateRangePicker/DateRangePicker.d.ts +43 -0
  174. package/dist/organisms/DateRangePicker/DateRangePicker.js +54 -0
  175. package/dist/organisms/DateRangePicker/index.d.ts +1 -0
  176. package/dist/organisms/DateRangePicker/index.js +1 -0
  177. package/dist/organisms/FilterBar/FilterBar.d.ts +28 -0
  178. package/dist/organisms/FilterBar/FilterBar.js +16 -0
  179. package/dist/organisms/FilterBar/index.d.ts +1 -0
  180. package/dist/organisms/FilterBar/index.js +1 -0
  181. package/dist/organisms/PageHeader/PageHeader.d.ts +31 -0
  182. package/dist/organisms/PageHeader/PageHeader.js +19 -0
  183. package/dist/organisms/PageHeader/index.d.ts +1 -0
  184. package/dist/organisms/PageHeader/index.js +1 -0
  185. package/dist/organisms/PageTabs/PageTabs.d.ts +27 -0
  186. package/dist/organisms/PageTabs/PageTabs.js +31 -0
  187. package/dist/organisms/PageTabs/index.d.ts +1 -0
  188. package/dist/organisms/PageTabs/index.js +1 -0
  189. package/dist/organisms/Sidebar/Sidebar.d.ts +48 -0
  190. package/dist/organisms/Sidebar/Sidebar.js +73 -0
  191. package/dist/organisms/Sidebar/index.d.ts +1 -0
  192. package/dist/organisms/Sidebar/index.js +1 -0
  193. package/dist/organisms/Topbar/Topbar.d.ts +24 -0
  194. package/dist/organisms/Topbar/Topbar.js +18 -0
  195. package/dist/organisms/Topbar/index.d.ts +1 -0
  196. package/dist/organisms/Topbar/index.js +1 -0
  197. package/dist/organisms/index.d.ts +11 -0
  198. package/dist/organisms/index.js +11 -0
  199. package/dist/strings.d.ts +108 -15
  200. package/dist/strings.js +73 -7
  201. package/dist/templates/AdminLayout/AdminLayout.d.ts +14 -0
  202. package/dist/templates/AdminLayout/AdminLayout.js +9 -0
  203. package/dist/templates/AdminLayout/index.d.ts +1 -0
  204. package/dist/templates/AdminLayout/index.js +1 -0
  205. package/dist/templates/AuthLayout/AuthLayout.d.ts +28 -0
  206. package/dist/templates/AuthLayout/AuthLayout.js +11 -0
  207. package/dist/templates/AuthLayout/index.d.ts +1 -0
  208. package/dist/templates/AuthLayout/index.js +1 -0
  209. package/dist/templates/DashboardPage/DashboardPage.d.ts +25 -0
  210. package/dist/templates/DashboardPage/DashboardPage.js +12 -0
  211. package/dist/templates/DashboardPage/index.d.ts +1 -0
  212. package/dist/templates/DashboardPage/index.js +1 -0
  213. package/dist/templates/DetailPage/DetailPage.d.ts +20 -0
  214. package/dist/templates/DetailPage/DetailPage.js +11 -0
  215. package/dist/templates/DetailPage/index.d.ts +1 -0
  216. package/dist/templates/DetailPage/index.js +1 -0
  217. package/dist/templates/FormPage/FormPage.d.ts +26 -0
  218. package/dist/templates/FormPage/FormPage.js +11 -0
  219. package/dist/templates/FormPage/index.d.ts +1 -0
  220. package/dist/templates/FormPage/index.js +1 -0
  221. package/dist/templates/ListPage/ListPage.d.ts +17 -0
  222. package/dist/templates/ListPage/ListPage.js +8 -0
  223. package/dist/templates/ListPage/index.d.ts +1 -0
  224. package/dist/templates/ListPage/index.js +1 -0
  225. package/dist/templates/SettingsPage/SettingsPage.d.ts +32 -0
  226. package/dist/templates/SettingsPage/SettingsPage.js +13 -0
  227. package/dist/templates/SettingsPage/index.d.ts +1 -0
  228. package/dist/templates/SettingsPage/index.js +1 -0
  229. package/dist/templates/StatusPage/StatusPage.d.ts +18 -0
  230. package/dist/templates/StatusPage/StatusPage.js +8 -0
  231. package/dist/templates/StatusPage/index.d.ts +1 -0
  232. package/dist/templates/StatusPage/index.js +1 -0
  233. package/dist/templates/index.d.ts +8 -0
  234. package/dist/templates/index.js +8 -0
  235. package/dist/utils/dates.d.ts +67 -0
  236. package/dist/utils/dates.js +154 -0
  237. package/dist/utils/index.d.ts +1 -0
  238. package/dist/utils/index.js +1 -0
  239. package/dist/utils/theme.d.ts +4 -0
  240. package/dist/utils/theme.js +7 -3
  241. package/package.json +4 -1
  242. package/tokens.css +500 -21
@@ -0,0 +1,73 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import * as RadixDialog from '@radix-ui/react-dialog';
3
+ import { Cross1Icon, DoubleArrowLeftIcon, DoubleArrowRightIcon } from '@radix-ui/react-icons';
4
+ import { Theme } from '@radix-ui/themes';
5
+ import { useId, useState } from 'react';
6
+ import { Tooltip } from '../../atoms/Tooltip/Tooltip.js';
7
+ import { minWidth } from '../../hooks/breakpoints.js';
8
+ import { useControllableState } from '../../hooks/useControllableState.js';
9
+ import { useMediaQuery } from '../../hooks/useMediaQuery.js';
10
+ import { NavContext } from '../../molecules/NavItem/context.js';
11
+ import { NavItem, navKey } from '../../molecules/NavItem/NavItem.js';
12
+ import { useUiStrings } from '../../strings.js';
13
+ import { useThemePortalTarget } from '../../utils/themePortal.js';
14
+ import { useShell } from '../AppShell/context.js';
15
+ function Sections({ sections, label, id, }) {
16
+ return (_jsx("nav", { id: id, "aria-label": label, className: "ui-sidebar__nav", children: sections.map((section, i) => {
17
+ const headingId = `${id}-s${i}`;
18
+ return (_jsxs("div", { className: "ui-sidebar__section", children: [section.label ? (_jsx("h2", { id: headingId, className: "ui-sidebar__section-label", children: section.label })) : null, _jsx("ul", { className: "ui-sidebar__list", "aria-labelledby": section.label ? headingId : undefined, children: section.items.map((item) => (_jsx(NavItem, { ...item }, item.id ?? item.label))) })] }, section.id ?? section.label ?? i));
19
+ }) }));
20
+ }
21
+ /**
22
+ * The main navigation. From `breakpoint` up it is a persistent column that can collapse to an
23
+ * icon rail; below it, an off-canvas panel from the start edge with a scrim, a focus trap and
24
+ * Escape, which closes again when an item is chosen.
25
+ *
26
+ * Inside an `AppShell`, the shell decides which and the Topbar's menu button opens the panel.
27
+ * Without matchMedia (on the server) it renders the persistent column.
28
+ */
29
+ export function Sidebar({ header, collapsedHeader, sections, footer, collapsed: collapsedProp, defaultCollapsed = false, onCollapsedChange, collapsible = true, 'aria-label': ariaLabel, breakpoint = 'md', open, onOpenChange, container, }) {
30
+ const strings = useUiStrings();
31
+ const shell = useShell();
32
+ const ownWide = useMediaQuery(minWidth(shell?.breakpoint ?? breakpoint));
33
+ const [ownOpen, setOwnOpen] = useState(false);
34
+ const [collapsed, setCollapsed] = useControllableState({
35
+ value: collapsedProp,
36
+ defaultValue: defaultCollapsed,
37
+ onChange: onCollapsedChange,
38
+ });
39
+ const { anchorRef, target, resolved } = useThemePortalTarget(container);
40
+ const navId = useId();
41
+ const [openGroup, setOpenGroup] = useState(() => {
42
+ for (const item of sections.flatMap((section) => section.items)) {
43
+ if (item.items && (item.defaultOpen ?? item.items.some((c) => c.active)))
44
+ return navKey(item);
45
+ }
46
+ return null;
47
+ });
48
+ const wide = shell ? shell.wide : ownWide;
49
+ const panelOpen = shell ? shell.navOpen : (open ?? ownOpen);
50
+ const setPanelOpen = (next) => {
51
+ if (shell)
52
+ shell.setNavOpen(next);
53
+ else if (open === undefined)
54
+ setOwnOpen(next);
55
+ onOpenChange?.(next);
56
+ };
57
+ const label = ariaLabel ?? strings.mainNavigation;
58
+ if (wide) {
59
+ const toggleLabel = collapsed ? strings.expandSidebar : strings.collapseSidebar;
60
+ const railHeader = collapsed ? (collapsedHeader ?? header) : header;
61
+ return (_jsxs("div", { className: "ui-sidebar", "data-collapsed": collapsed ? '' : undefined, children: [railHeader ? _jsx("div", { className: "ui-sidebar__header", children: railHeader }) : null, _jsx(NavContext.Provider, { value: { collapsed, openGroup, setOpenGroup, expand: () => setCollapsed(false) }, children: _jsx(Sections, { sections: sections, label: label, id: navId }) }), footer || collapsible ? (_jsxs("div", { className: "ui-sidebar__footer", children: [footer, collapsible ? (_jsx(Tooltip, { label: collapsed ? toggleLabel : undefined, children: _jsxs("button", { type: "button", className: "ui-nav-item", "aria-expanded": !collapsed, "aria-controls": navId, onClick: () => setCollapsed(!collapsed), children: [_jsx("span", { className: "ui-nav-item__icon", "aria-hidden": "true", children: collapsed ? _jsx(DoubleArrowRightIcon, {}) : _jsx(DoubleArrowLeftIcon, {}) }), _jsx("span", { className: "ui-nav-item__label", children: toggleLabel })] }) })) : null] })) : null] }));
62
+ }
63
+ const panel = (_jsxs(_Fragment, { children: [_jsx(RadixDialog.Overlay, { className: "ui-sidebar-overlay" }), _jsxs(RadixDialog.Content, { className: "ui-sidebar-panel", "aria-describedby": undefined, children: [_jsx(RadixDialog.Title, { className: "ui-sr-only", children: label }), _jsxs("div", { className: "ui-sidebar__header", children: [_jsx("div", { className: "min-w-0 flex-1", children: header }), _jsxs(RadixDialog.Close, { className: "ui-nav-item ui-sidebar__close", children: [_jsx("span", { className: "ui-nav-item__icon", "aria-hidden": "true", children: _jsx(Cross1Icon, {}) }), _jsx("span", { className: "ui-sr-only", children: strings.closeNavigation })] })] }), _jsx(NavContext.Provider, { value: {
64
+ collapsed: false,
65
+ onNavigate: () => setPanelOpen(false),
66
+ openGroup,
67
+ setOpenGroup,
68
+ }, children: _jsx(Sections, { sections: sections, label: label, id: navId }) }), footer ? _jsx("div", { className: "ui-sidebar__footer", children: footer }) : null] })] }));
69
+ const anchor = _jsx("span", { ref: anchorRef, hidden: true });
70
+ if (!resolved)
71
+ return anchor;
72
+ return (_jsxs(RadixDialog.Root, { open: panelOpen, onOpenChange: setPanelOpen, children: [anchor, _jsx(RadixDialog.Portal, { container: target ?? undefined, children: target ? _jsx(Theme, { hasBackground: false, children: panel }) : panel })] }));
73
+ }
@@ -0,0 +1 @@
1
+ export * from './Sidebar.js';
@@ -0,0 +1 @@
1
+ export * from './Sidebar.js';
@@ -0,0 +1,24 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface TopbarProps {
3
+ /** Before the title: breadcrumbs, a logo on narrow screens. */
4
+ leading?: ReactNode;
5
+ /** A short page or app title. Not a heading: the page's `h1` belongs to PageHeader. */
6
+ title?: ReactNode;
7
+ /** A search field. Sits between title and actions from 768px; on its own row below that. */
8
+ search?: ReactNode;
9
+ /** Icon buttons, a notification bell, a UserMenu. */
10
+ actions?: ReactNode;
11
+ /**
12
+ * The button that opens the off-canvas Sidebar. Default: shown inside an AppShell whenever
13
+ * the sidebar is off-canvas. Pass `false` to hide it, or `true` with `onMenuClick` outside one.
14
+ */
15
+ showMenuButton?: boolean;
16
+ onMenuClick?: () => void;
17
+ className?: string;
18
+ }
19
+ /**
20
+ * The bar across the top of the content column: a `header` landmark, sticky, on the bar
21
+ * material. Narrow screens get the menu button that opens the Sidebar, and the search moves to
22
+ * a second row so neither it nor the title is squeezed.
23
+ */
24
+ export declare function Topbar({ leading, title, search, actions, showMenuButton, onMenuClick, className, }: TopbarProps): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { HamburgerMenuIcon } from '@radix-ui/react-icons';
3
+ import { useUiStrings } from '../../strings.js';
4
+ import { useShell } from '../AppShell/context.js';
5
+ /**
6
+ * The bar across the top of the content column: a `header` landmark, sticky, on the bar
7
+ * material. Narrow screens get the menu button that opens the Sidebar, and the search moves to
8
+ * a second row so neither it nor the title is squeezed.
9
+ */
10
+ export function Topbar({ leading, title, search, actions, showMenuButton, onMenuClick, className, }) {
11
+ const strings = useUiStrings();
12
+ const shell = useShell();
13
+ const menu = showMenuButton ?? (shell ? !shell.wide : false);
14
+ return (_jsxs("header", { className: ['ui-topbar', className].filter(Boolean).join(' '), children: [_jsxs("div", { className: "ui-topbar__lead", children: [menu ? (_jsx("button", { type: "button", className: "ui-nav-item ui-topbar__menu", "aria-label": strings.openNavigation, "aria-expanded": shell?.navOpen ?? false, onClick: () => {
15
+ shell?.setNavOpen(true);
16
+ onMenuClick?.();
17
+ }, children: _jsx("span", { className: "ui-nav-item__icon", "aria-hidden": "true", children: _jsx(HamburgerMenuIcon, {}) }) })) : null, leading] }), title ? _jsx("div", { className: "ui-topbar__title", children: title }) : _jsx("div", {}), search ? _jsx("div", { className: "ui-topbar__search", children: search }) : null, actions ? _jsx("div", { className: "ui-topbar__actions", children: actions }) : null] }));
18
+ }
@@ -0,0 +1 @@
1
+ export * from './Topbar.js';
@@ -0,0 +1 @@
1
+ export * from './Topbar.js';
@@ -0,0 +1,11 @@
1
+ export * from './AppShell/index.js';
2
+ export * from './AuthForms/index.js';
3
+ export * from './BulkActionBar/index.js';
4
+ export * from './Chart/index.js';
5
+ export * from './DataTable/index.js';
6
+ export * from './DateRangePicker/index.js';
7
+ export * from './FilterBar/index.js';
8
+ export * from './PageHeader/index.js';
9
+ export * from './PageTabs/index.js';
10
+ export * from './Sidebar/index.js';
11
+ export * from './Topbar/index.js';
@@ -0,0 +1,11 @@
1
+ export * from './AppShell/index.js';
2
+ export * from './AuthForms/index.js';
3
+ export * from './BulkActionBar/index.js';
4
+ export * from './Chart/index.js';
5
+ export * from './DataTable/index.js';
6
+ export * from './DateRangePicker/index.js';
7
+ export * from './FilterBar/index.js';
8
+ export * from './PageHeader/index.js';
9
+ export * from './PageTabs/index.js';
10
+ export * from './Sidebar/index.js';
11
+ export * from './Topbar/index.js';
package/dist/strings.d.ts CHANGED
@@ -2,16 +2,16 @@ import { type ReactNode } from 'react';
2
2
  /**
3
3
  * The handful of strings the atoms say on their own behalf.
4
4
  *
5
- * **The dictionaries stay in the apps, deliberately** — that is a decision in the product
6
- * brief, and it is the right one: a shared dictionary would make every string in three
7
- * products one product's business. But two atoms do have something to say without being told.
8
- * A standing `Spinner` has to announce that a wait is in progress, and a `Select` with no
9
- * placeholder has to say something in the trigger.
5
+ * **The dictionaries stay in the apps, deliberately.** A shared dictionary would make every
6
+ * string in every consuming app this library's business. But some components do have
7
+ * something to say without being told: a standing `Spinner` has to announce that a wait is in
8
+ * progress, and a `Select` with no placeholder has to say something in the trigger.
10
9
  *
11
- * So the package declares what it needs and the host supplies it. English defaults, not
12
- * Portuguese: an app that forgets to wrap gets something legible rather than something wrong,
13
- * and Portuguese here would be a translatable string living in the shared package, which is
14
- * exactly what this avoids.
10
+ * So the package declares what it needs and the host supplies it. The defaults are English, so
11
+ * an app that forgets to wrap gets something legible, and no translation lives in the package.
12
+ *
13
+ * Anything that carries a value is a function, not a template string, so a language can put
14
+ * the number where its grammar wants it ("3 selected", "3 seleccionados").
15
15
  */
16
16
  export interface UiStrings {
17
17
  /** Announced by a standing spinner. */
@@ -46,22 +46,115 @@ export interface UiStrings {
46
46
  refreshing: string;
47
47
  /** ScrollStrip: the accessible name of the scrollable region, when none is passed. */
48
48
  scrollableRegion: string;
49
+ /** AppShell: the skip link that jumps past the navigation to the main content. */
50
+ skipToContent: string;
51
+ /** Sidebar: the navigation landmark's name. */
52
+ mainNavigation: string;
53
+ /** Topbar: the button that opens the navigation on small screens. */
54
+ openNavigation: string;
55
+ /** Sidebar: the close button of the navigation panel on small screens. */
56
+ closeNavigation: string;
57
+ /** Sidebar: the collapse toggle, while expanded. */
58
+ collapseSidebar: string;
59
+ /** Sidebar: the collapse toggle, while collapsed. */
60
+ expandSidebar: string;
61
+ /** Breadcrumbs: the landmark's name. */
62
+ breadcrumbs: string;
63
+ /** Breadcrumbs: the menu that holds the collapsed middle items. */
64
+ showMoreBreadcrumbs: string;
65
+ /** Link: appended, visually hidden, to links that open a new tab. */
66
+ opensInNewTab: string;
67
+ /** UserMenu: the trigger's name when the name itself is hidden. */
68
+ userMenu: string;
69
+ /** ThemeToggle: the group's name and its three options. */
70
+ appearance: string;
71
+ light: string;
72
+ dark: string;
73
+ system: string;
74
+ /** AccentPicker: the group's name. */
75
+ accent: string;
76
+ /** Pill: the remove button's name. */
77
+ remove: (label: string) => string;
78
+ /** EmptyState default inside DataTable when there are no rows. */
79
+ noResults: string;
80
+ /** ErrorState: the default title, the retry button, and the disclosure for details. */
81
+ somethingWentWrong: string;
82
+ retry: string;
83
+ showDetails: string;
84
+ /** Pagination: the landmark's name, the two step buttons, and the page-size label. */
85
+ pagination: string;
86
+ previousPage: string;
87
+ nextPage: string;
88
+ rowsPerPage: string;
89
+ /** Pagination: one page button's name. */
90
+ goToPage: (page: number) => string;
91
+ /** Pagination: the compact "page of" text. */
92
+ pageOf: (page: number, pageCount: number) => string;
93
+ /** Pagination: which rows are showing, e.g. "1–25 of 500". */
94
+ rangeOf: (from: number, to: number, total: number) => string;
95
+ /** DataTable: the header checkbox, and each row's. */
96
+ selectAll: string;
97
+ selectRow: (row: string) => string;
98
+ /** DataTable: the row-actions menu button's name. */
99
+ actionsFor: (row: string) => string;
100
+ /** BulkActionBar: the toolbar's name, the selection count, and the clear button. */
101
+ bulkActions: string;
102
+ selectedCount: (count: number) => string;
103
+ clearSelection: string;
104
+ /** SearchField: its accessible name when none is given, and the clear button. */
105
+ search: string;
106
+ clearSearch: string;
107
+ /** FilterPopover: the trigger's default label, and its footer. FilterBar: the clear-all. */
108
+ filters: string;
109
+ apply: string;
110
+ reset: string;
111
+ clearFilters: string;
112
+ /** FilterBar: names the group of active-filter pills. */
113
+ activeFilters: string;
114
+ /** FilterPopover: appended to the trigger's name when filters are active. */
115
+ activeCount: (count: number) => string;
116
+ /** ErrorSummary: its heading. */
117
+ fixErrors: (count: number) => string;
118
+ /** Calendar: the month step buttons. */
119
+ previousMonth: string;
120
+ nextMonth: string;
121
+ /** DateInput / DateRangePicker: the trigger text while nothing is chosen. */
122
+ chooseDate: string;
123
+ chooseDates: string;
124
+ /** DateRangePicker: names the list of preset ranges. */
125
+ datePresets: string;
126
+ /** ChartFrame: the toggle between the chart and its data table. */
127
+ viewAsTable: string;
128
+ viewAsChart: string;
129
+ /** PasswordInput: the visibility toggle's name. It is a toggle (`aria-pressed`), so one name. */
130
+ showPassword: string;
49
131
  }
50
132
  /**
51
- * Feeds the atoms their strings, once, near the root.
133
+ * Feeds the components their strings, once, near the root.
52
134
  *
53
135
  * Every app wraps its tree in this and passes its own dictionary's words through. It takes a
54
136
  * partial so an app that only cares about one of them says only that.
137
+ *
138
+ * `locale` is the BCP 47 tag that dates, numbers and money are formatted in (through `Intl`).
139
+ * Formatting rather than translating: "21 de setembro" comes from the locale, not from a
140
+ * string. Left out, it inherits from an outer provider, and with none the runtime's default.
55
141
  */
56
- export declare function UiStringsProvider({ strings, children, }: {
142
+ export declare function UiStringsProvider({ strings, locale, children, }: {
57
143
  strings: Partial<UiStrings>;
144
+ locale?: string;
58
145
  children: ReactNode;
59
146
  }): import("react").JSX.Element;
60
147
  /**
61
- * No error when there is no provider, unlike the apps' own `useCopy`.
148
+ * No error when there is no provider.
62
149
  *
63
- * A missing provider there is a bug — the dictionary is the app. Here it is a host that did
64
- * not need to override anything, which is a legitimate way to use this package and must not
65
- * throw in a component as ordinary as a spinner.
150
+ * A host that did not need to override anything is a legitimate way to use this package, and
151
+ * a component as ordinary as a spinner must not throw because of it.
66
152
  */
67
153
  export declare function useUiStrings(): UiStrings;
154
+ /**
155
+ * The locale passed to the nearest `UiStringsProvider`, for `Intl` formatters.
156
+ *
157
+ * `undefined` means "the runtime's default", which is what `Intl` already does with
158
+ * `undefined`, so the value can be passed straight through.
159
+ */
160
+ export declare function useUiLocale(): string | undefined;
package/dist/strings.js CHANGED
@@ -20,24 +20,90 @@ const DEFAULTS = {
20
20
  back: 'Back',
21
21
  refreshing: 'Refreshing',
22
22
  scrollableRegion: 'Scrollable content',
23
+ skipToContent: 'Skip to content',
24
+ mainNavigation: 'Main navigation',
25
+ openNavigation: 'Open navigation',
26
+ closeNavigation: 'Close navigation',
27
+ collapseSidebar: 'Collapse sidebar',
28
+ expandSidebar: 'Expand sidebar',
29
+ breadcrumbs: 'Breadcrumbs',
30
+ showMoreBreadcrumbs: 'Show hidden breadcrumbs',
31
+ opensInNewTab: '(opens in a new tab)',
32
+ userMenu: 'Account menu',
33
+ appearance: 'Appearance',
34
+ light: 'Light',
35
+ dark: 'Dark',
36
+ system: 'System',
37
+ accent: 'Accent colour',
38
+ remove: (label) => `Remove ${label}`,
39
+ noResults: 'No results',
40
+ somethingWentWrong: 'Something went wrong',
41
+ retry: 'Try again',
42
+ showDetails: 'Details',
43
+ pagination: 'Pagination',
44
+ previousPage: 'Previous page',
45
+ nextPage: 'Next page',
46
+ rowsPerPage: 'Rows per page',
47
+ goToPage: (page) => `Page ${page}`,
48
+ pageOf: (page, pageCount) => `Page ${page} of ${pageCount}`,
49
+ rangeOf: (from, to, total) => `${from}–${to} of ${total}`,
50
+ selectAll: 'Select all rows',
51
+ selectRow: (row) => `Select ${row}`,
52
+ actionsFor: (row) => `Actions for ${row}`,
53
+ bulkActions: 'Bulk actions',
54
+ selectedCount: (count) => `${count} selected`,
55
+ clearSelection: 'Clear selection',
56
+ search: 'Search',
57
+ clearSearch: 'Clear search',
58
+ filters: 'Filters',
59
+ apply: 'Apply',
60
+ reset: 'Reset',
61
+ clearFilters: 'Clear all',
62
+ activeFilters: 'Active filters',
63
+ activeCount: (count) => `${count} active`,
64
+ fixErrors: (count) => count === 1
65
+ ? 'There is 1 problem with this form'
66
+ : `There are ${count} problems with this form`,
67
+ previousMonth: 'Previous month',
68
+ nextMonth: 'Next month',
69
+ chooseDate: 'Choose a date',
70
+ chooseDates: 'Choose dates',
71
+ datePresets: 'Quick ranges',
72
+ viewAsTable: 'View as table',
73
+ viewAsChart: 'View as chart',
74
+ showPassword: 'Show password',
23
75
  };
24
76
  const StringsContext = createContext(DEFAULTS);
77
+ const LocaleContext = createContext(undefined);
25
78
  /**
26
- * Feeds the atoms their strings, once, near the root.
79
+ * Feeds the components their strings, once, near the root.
27
80
  *
28
81
  * Every app wraps its tree in this and passes its own dictionary's words through. It takes a
29
82
  * partial so an app that only cares about one of them says only that.
83
+ *
84
+ * `locale` is the BCP 47 tag that dates, numbers and money are formatted in (through `Intl`).
85
+ * Formatting rather than translating: "21 de setembro" comes from the locale, not from a
86
+ * string. Left out, it inherits from an outer provider, and with none the runtime's default.
30
87
  */
31
- export function UiStringsProvider({ strings, children, }) {
32
- return (_jsx(StringsContext.Provider, { value: { ...DEFAULTS, ...strings }, children: children }));
88
+ export function UiStringsProvider({ strings, locale, children, }) {
89
+ const outerLocale = useContext(LocaleContext);
90
+ return (_jsx(LocaleContext.Provider, { value: locale ?? outerLocale, children: _jsx(StringsContext.Provider, { value: { ...DEFAULTS, ...strings }, children: children }) }));
33
91
  }
34
92
  /**
35
- * No error when there is no provider, unlike the apps' own `useCopy`.
93
+ * No error when there is no provider.
36
94
  *
37
- * A missing provider there is a bug — the dictionary is the app. Here it is a host that did
38
- * not need to override anything, which is a legitimate way to use this package and must not
39
- * throw in a component as ordinary as a spinner.
95
+ * A host that did not need to override anything is a legitimate way to use this package, and
96
+ * a component as ordinary as a spinner must not throw because of it.
40
97
  */
41
98
  export function useUiStrings() {
42
99
  return useContext(StringsContext);
43
100
  }
101
+ /**
102
+ * The locale passed to the nearest `UiStringsProvider`, for `Intl` formatters.
103
+ *
104
+ * `undefined` means "the runtime's default", which is what `Intl` already does with
105
+ * `undefined`, so the value can be passed straight through.
106
+ */
107
+ export function useUiLocale() {
108
+ return useContext(LocaleContext);
109
+ }
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type AppShellProps } from '../../organisms/AppShell/AppShell.js';
3
+ export interface AdminLayoutProps extends Omit<AppShellProps, 'children'> {
4
+ /** A `PageHeader`, above the content and inside the same width. */
5
+ header?: ReactNode;
6
+ children: ReactNode;
7
+ /** `default` caps the content at `--content-max-width`; `full` uses the whole column. */
8
+ width?: 'default' | 'full';
9
+ }
10
+ /**
11
+ * An AppShell with a page inside it: the header and content share one centred column, padded
12
+ * by `--page-gutter`. A slot layout only; routing, data and auth belong to the app.
13
+ */
14
+ export declare function AdminLayout({ header, children, width, ...shell }: AdminLayoutProps): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { AppShell } from '../../organisms/AppShell/AppShell.js';
3
+ /**
4
+ * An AppShell with a page inside it: the header and content share one centred column, padded
5
+ * by `--page-gutter`. A slot layout only; routing, data and auth belong to the app.
6
+ */
7
+ export function AdminLayout({ header, children, width = 'default', ...shell }) {
8
+ return (_jsx(AppShell, { ...shell, children: _jsxs("div", { className: "ui-admin-content", "data-width": width, children: [header, children] }) }));
9
+ }
@@ -0,0 +1 @@
1
+ export * from './AdminLayout.js';
@@ -0,0 +1 @@
1
+ export * from './AdminLayout.js';
@@ -0,0 +1,28 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface AuthLayoutProps {
3
+ /** A logo, above the title. */
4
+ brand?: ReactNode;
5
+ /** The page's `h1`: "Sign in", "Create your account". */
6
+ title: ReactNode;
7
+ description?: ReactNode;
8
+ /** One of the auth forms, or your own. */
9
+ children: ReactNode;
10
+ /** Under the card: links to the other auth pages, legal text. */
11
+ footer?: ReactNode;
12
+ /**
13
+ * A panel beside the card from 1024px: a product image, a quote. Decorative from a reader's
14
+ * point of view, so keep anything essential in the card. Hidden on smaller screens.
15
+ */
16
+ aside?: ReactNode;
17
+ /** Top corner controls: a ThemeToggle, a language switch. */
18
+ toolbar?: ReactNode;
19
+ className?: string;
20
+ }
21
+ /**
22
+ * The frame for sign-in, sign-up and password pages, outside the app shell.
23
+ *
24
+ * A centred card on a canvas; from 1024px, an optional panel beside it. Below 520px the card
25
+ * loses its border and fills the screen, because a card inside a phone's edges only wastes
26
+ * width. The whole page is the `main` landmark, with the title as its `h1`.
27
+ */
28
+ export declare function AuthLayout({ brand, title, description, children, footer, aside, toolbar, className, }: AuthLayoutProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The frame for sign-in, sign-up and password pages, outside the app shell.
4
+ *
5
+ * A centred card on a canvas; from 1024px, an optional panel beside it. Below 520px the card
6
+ * loses its border and fills the screen, because a card inside a phone's edges only wastes
7
+ * width. The whole page is the `main` landmark, with the title as its `h1`.
8
+ */
9
+ export function AuthLayout({ brand, title, description, children, footer, aside, toolbar, className, }) {
10
+ return (_jsxs("div", { className: ['ui-auth', className].filter(Boolean).join(' '), "data-has-aside": aside ? '' : undefined, children: [aside ? _jsx("div", { className: "ui-auth__aside", children: aside }) : null, _jsxs("main", { className: "ui-auth__main", children: [toolbar ? _jsx("div", { className: "ui-auth__toolbar", children: toolbar }) : null, _jsxs("div", { className: "ui-auth__card", children: [brand ? _jsx("div", { className: "ui-auth__brand", children: brand }) : null, _jsx("h1", { className: "ui-auth__title", children: title }), description ? _jsx("p", { className: "ui-auth__description", children: description }) : null, children] }), footer ? _jsx("div", { className: "ui-auth__footer", children: footer }) : null] })] }));
11
+ }
@@ -0,0 +1 @@
1
+ export * from './AuthLayout.js';
@@ -0,0 +1 @@
1
+ export * from './AuthLayout.js';
@@ -0,0 +1,25 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface DashboardPageProps {
3
+ /** A PageHeader. */
4
+ header?: ReactNode;
5
+ /** A StatGroup. */
6
+ stats?: ReactNode;
7
+ /** Widgets: ChartFrames, Cards, tables. Wrap one in `DashboardWidget` to make it wider. */
8
+ children: ReactNode;
9
+ /** The most columns at full width. Default 3. */
10
+ columns?: 2 | 3 | 4;
11
+ className?: string;
12
+ }
13
+ /**
14
+ * A page of widgets. The grid follows the page's own width (a container query): one column
15
+ * below 640px, two from there, and `columns` from 1024px.
16
+ */
17
+ export declare function DashboardPage({ header, stats, children, columns, className, }: DashboardPageProps): import("react").JSX.Element;
18
+ export interface DashboardWidgetProps {
19
+ /** Columns to span once there is more than one. `full` spans the row. Default 1. */
20
+ span?: 1 | 2 | 'full';
21
+ children: ReactNode;
22
+ className?: string;
23
+ }
24
+ /** A grid cell in DashboardPage that spans more than one column on wide pages. */
25
+ export declare function DashboardWidget({ span, children, className }: DashboardWidgetProps): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * A page of widgets. The grid follows the page's own width (a container query): one column
4
+ * below 640px, two from there, and `columns` from 1024px.
5
+ */
6
+ export function DashboardPage({ header, stats, children, columns = 3, className, }) {
7
+ return (_jsxs("div", { className: ['ui-dashboard ui-list-page', className].filter(Boolean).join(' '), children: [header, stats, _jsx("div", { className: "ui-dashboard__grid", "data-columns": columns, children: children })] }));
8
+ }
9
+ /** A grid cell in DashboardPage that spans more than one column on wide pages. */
10
+ export function DashboardWidget({ span = 1, children, className }) {
11
+ return (_jsx("div", { className: ['ui-dashboard__widget', className].filter(Boolean).join(' '), "data-span": span, children: children }));
12
+ }
@@ -0,0 +1 @@
1
+ export * from './DashboardPage.js';
@@ -0,0 +1 @@
1
+ export * from './DashboardPage.js';
@@ -0,0 +1,20 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface DetailPageProps {
3
+ /** A PageHeader (with PageTabs in its `tabs` slot, usually). */
4
+ header?: ReactNode;
5
+ /** The main content. */
6
+ children: ReactNode;
7
+ /** A side column of facts: a KeyValueList in a Card, say. */
8
+ aside?: ReactNode;
9
+ /** Names the aside's `complementary` landmark. Required with `aside`. */
10
+ asideLabel?: string;
11
+ className?: string;
12
+ }
13
+ /**
14
+ * One record: header, main content and an optional side column.
15
+ *
16
+ * The side column sits beside the main content once the page is 960px wide (a container
17
+ * query, so a narrow panel counts as narrow), and below it otherwise. It comes after the main
18
+ * content in the DOM either way, so reading and tab order match what is primary.
19
+ */
20
+ export declare function DetailPage({ header, children, aside, asideLabel, className }: DetailPageProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * One record: header, main content and an optional side column.
4
+ *
5
+ * The side column sits beside the main content once the page is 960px wide (a container
6
+ * query, so a narrow panel counts as narrow), and below it otherwise. It comes after the main
7
+ * content in the DOM either way, so reading and tab order match what is primary.
8
+ */
9
+ export function DetailPage({ header, children, aside, asideLabel, className }) {
10
+ return (_jsxs("div", { className: ['ui-detail-page', className].filter(Boolean).join(' '), children: [header, _jsxs("div", { className: "ui-detail-page__body", "data-has-aside": aside ? '' : undefined, children: [_jsx("div", { className: "min-w-0", children: children }), aside ? _jsx("aside", { "aria-label": asideLabel, children: aside }) : null] })] }));
11
+ }
@@ -0,0 +1 @@
1
+ export * from './DetailPage.js';
@@ -0,0 +1 @@
1
+ export * from './DetailPage.js';
@@ -0,0 +1,26 @@
1
+ import type { FormEvent, ReactNode } from 'react';
2
+ export interface FormPageProps {
3
+ /** A PageHeader. Outside the form, so its actions are not form buttons. */
4
+ header?: ReactNode;
5
+ /** An ErrorSummary, placed first inside the form. */
6
+ errorSummary?: ReactNode;
7
+ /** FormSections. */
8
+ children: ReactNode;
9
+ /** A FormActions row. */
10
+ actions?: ReactNode;
11
+ onSubmit: (event: FormEvent<HTMLFormElement>) => void;
12
+ /**
13
+ * Turns off the browser's own validation bubbles, so the ErrorSummary and the FormFields'
14
+ * messages are the only ones. Default `true`.
15
+ */
16
+ noValidate?: boolean;
17
+ /** Names the form when the page has more than one. */
18
+ 'aria-label'?: string;
19
+ id?: string;
20
+ className?: string;
21
+ }
22
+ /**
23
+ * A page that is one form: header, error summary, sections, actions. Submitting calls
24
+ * `onSubmit` with the browser's default prevented; validation and state belong to the app.
25
+ */
26
+ export declare function FormPage({ header, errorSummary, children, actions, onSubmit, noValidate, 'aria-label': ariaLabel, id, className, }: FormPageProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * A page that is one form: header, error summary, sections, actions. Submitting calls
4
+ * `onSubmit` with the browser's default prevented; validation and state belong to the app.
5
+ */
6
+ export function FormPage({ header, errorSummary, children, actions, onSubmit, noValidate = true, 'aria-label': ariaLabel, id, className, }) {
7
+ return (_jsxs("div", { className: ['ui-list-page', className].filter(Boolean).join(' '), children: [header, _jsxs("form", { id: id, "aria-label": ariaLabel, noValidate: noValidate, onSubmit: (e) => {
8
+ e.preventDefault();
9
+ onSubmit(e);
10
+ }, children: [errorSummary, children, actions] })] }));
11
+ }
@@ -0,0 +1 @@
1
+ export * from './FormPage.js';
@@ -0,0 +1 @@
1
+ export * from './FormPage.js';