@jobber/components 8.24.0 → 8.24.2-visual-reg-5479aeb.18

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 (75) hide show
  1. package/ProgressIndicator.d.ts +1 -0
  2. package/{DescriptionList.js → ProgressIndicator.js} +3 -3
  3. package/dist/AtlantisThemeContext/AtlantisThemeContext.d.ts +1 -1
  4. package/dist/AtlantisThemeContext/index.cjs +1 -2
  5. package/dist/AtlantisThemeContext/index.mjs +1 -2
  6. package/dist/AtlantisThemeContext/themeStore.d.ts +11 -0
  7. package/dist/AtlantisThemeContext/types.d.ts +14 -0
  8. package/dist/AtlantisThemeContext/updateTheme.d.ts +1 -1
  9. package/dist/AtlantisThemeContext-cjs.js +58 -17
  10. package/dist/AtlantisThemeContext-es.js +60 -20
  11. package/dist/Avatar-cjs.js +3 -2
  12. package/dist/Avatar-es.js +3 -2
  13. package/dist/BottomSheet-cjs.js +8 -7
  14. package/dist/BottomSheet-es.js +9 -8
  15. package/dist/ComboboxChipRemove-es.js +2 -2
  16. package/dist/DatePicker-es.js +1 -1
  17. package/dist/Dialog/Dialog.d.ts +47 -3
  18. package/dist/Dialog/Dialog.types.d.ts +1 -15
  19. package/dist/Dialog/DialogBottomSheet.d.ts +12 -13
  20. package/dist/Dialog/DialogModal.d.ts +11 -11
  21. package/dist/Dialog/dialogComposableShared.d.ts +13 -3
  22. package/dist/DrawerDescription-cjs.js +4 -97
  23. package/dist/DrawerDescription-es.js +6 -98
  24. package/dist/InputNumberExperimental-cjs.js +21 -25
  25. package/dist/InputNumberExperimental-es.js +22 -26
  26. package/dist/MenuSubmenuTrigger-es.js +3 -3
  27. package/dist/Modal/index.cjs +12 -2
  28. package/dist/Modal/index.mjs +13 -3
  29. package/dist/ProgressBar/ProgressBar.d.ts +7 -0
  30. package/dist/ProgressBar-cjs.js +4 -0
  31. package/dist/ProgressBar-es.js +4 -0
  32. package/dist/ProgressIndicator/ProgressIndicator.d.ts +60 -0
  33. package/dist/ProgressIndicator/index.cjs +9 -0
  34. package/dist/ProgressIndicator/index.d.ts +1 -0
  35. package/dist/ProgressIndicator/index.mjs +3 -0
  36. package/dist/ProgressIndicator-cjs.js +43 -0
  37. package/dist/ProgressIndicator-es.js +41 -0
  38. package/dist/ScrollAreaViewport-cjs.js +2122 -12
  39. package/dist/ScrollAreaViewport-es.js +2118 -13
  40. package/dist/dialogReturnFocus-cjs.js +61 -34
  41. package/dist/dialogReturnFocus-es.js +63 -36
  42. package/dist/docs/AtlantisThemeContext/AtlantisThemeContext.md +41 -0
  43. package/dist/docs/DataTable/DataTable.md +0 -4
  44. package/dist/docs/Dialog/Dialog.md +1006 -0
  45. package/dist/docs/Icon/Icon.md +60 -53
  46. package/dist/docs/InputNumberExperimental/InputNumberExperimental.md +578 -0
  47. package/dist/docs/ProgressBar/ProgressBar.md +9 -0
  48. package/dist/docs/ProgressIndicator/ProgressIndicator.md +105 -0
  49. package/dist/docs/Table/Table.md +1 -3
  50. package/dist/docs/index.md +3 -1
  51. package/dist/index.cjs +3 -4
  52. package/dist/index.d.mts +1 -1
  53. package/dist/index.d.ts +1 -1
  54. package/dist/index.mjs +2 -3
  55. package/dist/isTypedArray-es.js +1 -1
  56. package/dist/primitives/InputNumberExperimental/InputNumberExperimental.d.ts +31 -15
  57. package/dist/primitives/InputNumberExperimental/types.d.ts +0 -1
  58. package/dist/styles.css +172 -51
  59. package/dist/unstyledPrimitives/index.cjs +218 -2230
  60. package/dist/unstyledPrimitives/index.mjs +224 -2236
  61. package/dist/useButton-es.js +1 -1
  62. package/dist/useScrollLock-es.js +2 -2
  63. package/dist/useScrollToActive-es.js +1 -1
  64. package/dist/utils/meta/meta.json +1 -1
  65. package/package.json +7 -7
  66. package/DescriptionList.d.ts +0 -1
  67. package/dist/DescriptionList/DescriptionList.d.ts +0 -11
  68. package/dist/DescriptionList/index.cjs +0 -10
  69. package/dist/DescriptionList/index.d.ts +0 -1
  70. package/dist/DescriptionList/index.mjs +0 -4
  71. package/dist/DescriptionList-cjs.js +0 -14
  72. package/dist/DescriptionList-es.js +0 -12
  73. package/dist/docs/DescriptionList/DescriptionList.md +0 -25
  74. package/dist/updateTheme-cjs.js +0 -20
  75. package/dist/updateTheme-es.js +0 -18
@@ -7,10 +7,10 @@ var classnames = require('classnames');
7
7
  var buttonRenderAdapter = require('./buttonRenderAdapter-cjs.js');
8
8
  var Button = require('./Button-cjs.js');
9
9
  var ScrollAreaViewport = require('./ScrollAreaViewport-cjs.js');
10
+ var useRenderElement = require('./useRenderElement-cjs.js');
10
11
  var Heading = require('./Heading-cjs.js');
11
12
  var BottomSheet = require('./BottomSheet-cjs.js');
12
13
  var DrawerTitle = require('./DrawerTitle-cjs.js');
13
- var useRenderElement = require('./useRenderElement-cjs.js');
14
14
  var DrawerDescription = require('./DrawerDescription-cjs.js');
15
15
 
16
16
  // Copied from Menu's constant so the two surfaces agree on what "mobile" means.
@@ -81,6 +81,24 @@ function resolveComposableCloseRender({ children, render, }) {
81
81
  return buttonRenderAdapter.renderAtlantisButtonTarget(React.createElement(Button.Button, { type: "tertiary", variation: "subtle", ariaLabel: "Close dialog" },
82
82
  React.createElement(Button.Button.Icon, { name: "remove" })));
83
83
  }
84
+ /**
85
+ * Adapts a `Dialog.Content` `render` for the bottom sheet's drawer popup. A
86
+ * render element passes through; a render function is wrapped to receive the
87
+ * drawer's state re-shaped as the dialog popup's state (e.g. `nestedDrawerOpen`
88
+ * becomes `nestedDialogOpen`), so `render` sees the same shape as the desktop
89
+ * dialog.
90
+ */
91
+ function resolveBottomSheetContentRender(render) {
92
+ if (typeof render !== "function") {
93
+ return render;
94
+ }
95
+ return (props, drawerState) => render(props, {
96
+ open: drawerState.open,
97
+ transitionStatus: drawerState.transitionStatus,
98
+ nested: drawerState.nested,
99
+ nestedDialogOpen: drawerState.nestedDrawerOpen,
100
+ });
101
+ }
84
102
  const DialogContext = React.createContext({
85
103
  type: "dialog",
86
104
  size: "base",
@@ -115,11 +133,11 @@ function useInsideDialogScrollArea() {
115
133
  * backed by the BottomSheet primitive's scroll area, for its fade.)
116
134
  */
117
135
  function DialogScrollArea$1({ children, className, style, }) {
118
- return (React.createElement(ScrollAreaViewport.ScrollAreaRoot, { className: classnames(styles.scrollRegion, className), style: style },
136
+ return (React.createElement(ScrollAreaViewport.ScrollAreaRoot, { className: classnames(styles.scrollRegion, className), style: style, "data-testid": "ATL-Dialog-ScrollRegion" },
119
137
  React.createElement(ScrollAreaViewport.ScrollAreaViewport, { className: styles.scrollViewport,
120
138
  // BaseUI defaults the viewport to `overflow: scroll`; `auto` so the
121
139
  // native scrollbar only shows when the content overflows.
122
- style: { overflow: "auto" } },
140
+ style: { overflow: "auto" }, "data-testid": "ATL-Dialog-ScrollViewport" },
123
141
  React.createElement(DialogScrollAreaContext.Provider, { value: true }, children))));
124
142
  }
125
143
  /** Layout-only header row; sticky unless nested inside a `Dialog.ScrollArea`. */
@@ -134,15 +152,26 @@ function SharedDialogFooter(_a) {
134
152
  const sticky = !useInsideDialogScrollArea();
135
153
  return (React.createElement("div", Object.assign({}, rest, { className: classnames(styles.footer, className), style: style, "data-sticky": sticky || undefined, "data-testid": "ATL-Dialog-Footer" }), children));
136
154
  }
155
+ function renderActionButton(action, defaults) {
156
+ if (!action)
157
+ return null;
158
+ return React.isValidElement(action) ? (action) : (React.createElement(Button.Button, Object.assign({}, useRenderElement.mergeProps(defaults, action))));
159
+ }
137
160
  /**
138
161
  * The action-button layout: tertiary on the left, primary/secondary grouped on
139
162
  * the right. Drop it inside a `Dialog.Footer`.
140
163
  */
141
164
  function DialogActions(_a) {
142
165
  var { primary, secondary, tertiary, align = "right", className, style } = _a, rest = tslib_es6.__rest(_a, ["primary", "secondary", "tertiary", "align", "className", "style"]);
143
- const secondaryAction = secondary && React.isValidElement(secondary) ? (secondary) : (React.createElement(Button.Button, Object.assign({ type: "primary", variation: "subtle" }, secondary)));
144
- const primaryAction = primary && React.isValidElement(primary) ? (primary) : (React.createElement(Button.Button, Object.assign({ type: "primary" }, primary)));
145
- const tertiaryAction = tertiary && React.isValidElement(tertiary) ? (tertiary) : (React.createElement(Button.Button, Object.assign({ type: "secondary", variation: "destructive" }, tertiary)));
166
+ const primaryAction = renderActionButton(primary, { type: "primary" });
167
+ const secondaryAction = renderActionButton(secondary, {
168
+ type: "primary",
169
+ variation: "subtle",
170
+ });
171
+ const tertiaryAction = renderActionButton(tertiary, {
172
+ type: "secondary",
173
+ variation: "destructive",
174
+ });
146
175
  return (React.createElement("div", Object.assign({}, rest, { className: classnames(actionsStyles.actions, [actionsStyles[`align-${align}`]], className), style: style, "data-testid": "ATL-Dialog-Actions" }),
147
176
  tertiary && (React.createElement("div", { className: actionsStyles.leftActions }, tertiaryAction)),
148
177
  React.createElement("div", { className: classnames(actionsStyles.buttonGroup, actionsStyles[`align-${align}`]) },
@@ -150,20 +179,24 @@ function DialogActions(_a) {
150
179
  primary && primaryAction)));
151
180
  }
152
181
 
153
- function DialogBottomSheetRoot(props) {
182
+ function DialogBottomSheet(props) {
154
183
  return (React.createElement(BottomSheet.BottomSheet.Root, Object.assign({}, props)));
155
184
  }
156
185
  function DialogBottomSheetTrigger(props) {
157
186
  return (React.createElement(BottomSheet.BottomSheet.Trigger, Object.assign({}, props)));
158
187
  }
159
188
  function DialogBottomSheetContent(_a) {
160
- var { children, className, style } = _a, rest = tslib_es6.__rest(_a, ["children", "className", "style"]);
189
+ var { children, className, style, render } = _a, rest = tslib_es6.__rest(_a, ["children", "className", "style", "render"]);
161
190
  const { type, size, finalFocus } = useDialogContext();
162
191
  return (
163
192
  // Opt-out of the BottomSheet's built-in scroll area.
164
193
  // Dialog will handle the scroll area itself.
165
194
  React.createElement(BottomSheet.BottomSheetScrollAreaContext.Provider, { value: false },
166
- React.createElement(BottomSheet.BottomSheet.Popup, Object.assign({}, rest, { className: classnames(styles.sheetSurface, className), style: style, role: type, finalFocus: finalFocus, "data-dialog-variant": "sheet", "data-size": size }), children)));
195
+ React.createElement(BottomSheet.BottomSheet.Popup, Object.assign({}, rest, {
196
+ // The bottom sheet is backed by a drawer popup, so re-shape its state
197
+ // into the dialog popup state the consumer's `render` is typed against.
198
+ render: resolveBottomSheetContentRender(render), className: classnames(styles.sheetSurface, className), style: style, role: type, finalFocus: finalFocus, "data-dialog-variant": "sheet", "data-size": size }),
199
+ React.createElement(ScrollAreaViewport.DrawerContent, { "data-base-ui-swipe-ignore": true }, children))));
167
200
  }
168
201
  function DialogBottomSheetTitle(_a) {
169
202
  var { children } = _a, rest = tslib_es6.__rest(_a, ["children"]);
@@ -194,18 +227,16 @@ function DialogBottomSheetBody(_a) {
194
227
  return insideScrollArea ? (content) : (React.createElement(DialogBottomSheetScrollArea, null, content));
195
228
  }
196
229
  /** Mobile shell: a bottom sheet built on the BottomSheet/Drawer primitives. */
197
- const DialogBottomSheet = Object.assign(DialogBottomSheetRoot, {
198
- Trigger: DialogBottomSheetTrigger,
199
- Content: DialogBottomSheetContent,
200
- Header: SharedDialogHeader,
201
- Title: DialogBottomSheetTitle,
202
- Close: DialogBottomSheetClose,
203
- Body: DialogBottomSheetBody,
204
- Footer: SharedDialogFooter,
205
- ScrollArea: DialogBottomSheetScrollArea,
206
- });
230
+ DialogBottomSheet.Trigger = DialogBottomSheetTrigger;
231
+ DialogBottomSheet.Content = DialogBottomSheetContent;
232
+ DialogBottomSheet.Header = SharedDialogHeader;
233
+ DialogBottomSheet.Title = DialogBottomSheetTitle;
234
+ DialogBottomSheet.Close = DialogBottomSheetClose;
235
+ DialogBottomSheet.Body = DialogBottomSheetBody;
236
+ DialogBottomSheet.Footer = SharedDialogFooter;
237
+ DialogBottomSheet.ScrollArea = DialogBottomSheetScrollArea;
207
238
 
208
- function DialogModalRoot(props) {
239
+ function DialogModal(props) {
209
240
  return React.createElement(ScrollAreaViewport.DialogRoot, Object.assign({}, props));
210
241
  }
211
242
  function DialogModalTrigger(_a) {
@@ -217,7 +248,7 @@ function DialogModalContent(_a) {
217
248
  const { type, size, finalFocus } = useDialogContext();
218
249
  return (React.createElement(ScrollAreaViewport.DialogPortal, null,
219
250
  React.createElement(DrawerDescription.DialogBackdrop, { forceRender: true, className: styles.backdrop, "data-testid": "ATL-Dialog-Backdrop" }),
220
- React.createElement(DrawerDescription.DialogViewport, { className: styles.viewport },
251
+ React.createElement(ScrollAreaViewport.DialogViewport, { className: styles.viewport },
221
252
  React.createElement(DrawerDescription.DialogPopup, Object.assign({}, rest, { className: classnames(styles.popup, styles[size], className), style: style, role: type, finalFocus: finalFocus, "data-dialog-variant": "modal" }), children))));
222
253
  }
223
254
  function DialogModalTitle(_a) {
@@ -238,17 +269,14 @@ function DialogModalBody(_a) {
238
269
  const content = (React.createElement(DrawerDescription.DialogDescription, { render: descriptionProps => (React.createElement("div", Object.assign({}, rest, descriptionProps, { className: classnames(styles.body, { [styles.fullBleed]: fullBleed }, className), style: style }), children)) }));
239
270
  return insideScrollArea ? (content) : (React.createElement(DialogScrollArea$1, null, content));
240
271
  }
241
- const DialogModal = Object.assign(DialogModalRoot, {
242
- Trigger: DialogModalTrigger,
243
- Content: DialogModalContent,
244
- Header: SharedDialogHeader,
245
- Title: DialogModalTitle,
246
- Close: DialogModalClose,
247
- Body: DialogModalBody,
248
- Footer: SharedDialogFooter,
249
- // The modal keeps the plain native-scrollbar scroll region.
250
- ScrollArea: DialogScrollArea$1,
251
- });
272
+ DialogModal.Trigger = DialogModalTrigger;
273
+ DialogModal.Content = DialogModalContent;
274
+ DialogModal.Header = SharedDialogHeader;
275
+ DialogModal.Title = DialogModalTitle;
276
+ DialogModal.Close = DialogModalClose;
277
+ DialogModal.Body = DialogModalBody;
278
+ DialogModal.Footer = SharedDialogFooter;
279
+ DialogModal.ScrollArea = DialogScrollArea$1;
252
280
 
253
281
  /**
254
282
  * Creates a handle that opens/closes a `Dialog` from detached triggers (e.g. an
@@ -273,7 +301,7 @@ function useDialogShell() {
273
301
  * desktop, a bottom sheet on mobile. Compose it with `Dialog.Trigger`,
274
302
  * `Dialog.Content`, and the layout parts.
275
303
  */
276
- function DialogRoot(_a) {
304
+ function Dialog(_a) {
277
305
  var { onRequestClose, size = "base", type = "dialog", finalFocus, children, onOpenChange } = _a, rest = tslib_es6.__rest(_a, ["onRequestClose", "size", "type", "finalFocus", "children", "onOpenChange"]);
278
306
  function handleOpenChange(nextOpen, eventDetails) {
279
307
  if (!nextOpen) {
@@ -339,7 +367,6 @@ function DialogScrollArea(props) {
339
367
  const Shell = useDialogShell();
340
368
  return React.createElement(Shell.ScrollArea, Object.assign({}, props));
341
369
  }
342
- const Dialog = DialogRoot;
343
370
  Dialog.Trigger = DialogTrigger;
344
371
  Dialog.Content = DialogContent;
345
372
  Dialog.Header = DialogHeader;
@@ -4,12 +4,12 @@ import { useWindowDimensions } from '@jobber/hooks';
4
4
  import classnames from 'classnames';
5
5
  import { n as normalizeBaseUiButtonProps, i as isAtlantisButtonRenderTarget, s as stripNativeTypeFromButtonRenderTarget, r as renderAtlantisButtonTarget } from './buttonRenderAdapter-es.js';
6
6
  import { B as Button } from './Button-es.js';
7
- import { S as ScrollAreaRoot, e as ScrollAreaViewport, g as DialogRoot$1, h as DialogTrigger$1, i as DialogPortal } from './ScrollAreaViewport-es.js';
7
+ import { S as ScrollAreaRoot, f as ScrollAreaViewport, g as DrawerContent, j as DialogRoot, k as DialogTrigger$1, l as DialogPortal, m as DialogViewport } from './ScrollAreaViewport-es.js';
8
+ import { m as mergeProps } from './useRenderElement-es.js';
8
9
  import { H as Heading } from './Heading-es.js';
9
10
  import { a as BottomSheet, B as BottomSheetScrollAreaContext } from './BottomSheet-es.js';
10
11
  import { D as DrawerTitle, a as DrawerClose, b as DialogTitle$1, c as DialogClose$1 } from './DrawerTitle-es.js';
11
- import { m as mergeProps } from './useRenderElement-es.js';
12
- import { D as DrawerDescription, a as DialogBackdrop, b as DialogViewport, c as DialogPopup, d as DialogDescription, e as createDialogHandle } from './DrawerDescription-es.js';
12
+ import { D as DrawerDescription, a as DialogBackdrop, b as DialogPopup, c as DialogDescription, d as createDialogHandle } from './DrawerDescription-es.js';
13
13
 
14
14
  // Copied from Menu's constant so the two surfaces agree on what "mobile" means.
15
15
  // (The proposal calls for copying shared Menu values into the component first
@@ -79,6 +79,24 @@ function resolveComposableCloseRender({ children, render, }) {
79
79
  return renderAtlantisButtonTarget(React__default.createElement(Button, { type: "tertiary", variation: "subtle", ariaLabel: "Close dialog" },
80
80
  React__default.createElement(Button.Icon, { name: "remove" })));
81
81
  }
82
+ /**
83
+ * Adapts a `Dialog.Content` `render` for the bottom sheet's drawer popup. A
84
+ * render element passes through; a render function is wrapped to receive the
85
+ * drawer's state re-shaped as the dialog popup's state (e.g. `nestedDrawerOpen`
86
+ * becomes `nestedDialogOpen`), so `render` sees the same shape as the desktop
87
+ * dialog.
88
+ */
89
+ function resolveBottomSheetContentRender(render) {
90
+ if (typeof render !== "function") {
91
+ return render;
92
+ }
93
+ return (props, drawerState) => render(props, {
94
+ open: drawerState.open,
95
+ transitionStatus: drawerState.transitionStatus,
96
+ nested: drawerState.nested,
97
+ nestedDialogOpen: drawerState.nestedDrawerOpen,
98
+ });
99
+ }
82
100
  const DialogContext = React__default.createContext({
83
101
  type: "dialog",
84
102
  size: "base",
@@ -113,11 +131,11 @@ function useInsideDialogScrollArea() {
113
131
  * backed by the BottomSheet primitive's scroll area, for its fade.)
114
132
  */
115
133
  function DialogScrollArea$1({ children, className, style, }) {
116
- return (React__default.createElement(ScrollAreaRoot, { className: classnames(styles.scrollRegion, className), style: style },
134
+ return (React__default.createElement(ScrollAreaRoot, { className: classnames(styles.scrollRegion, className), style: style, "data-testid": "ATL-Dialog-ScrollRegion" },
117
135
  React__default.createElement(ScrollAreaViewport, { className: styles.scrollViewport,
118
136
  // BaseUI defaults the viewport to `overflow: scroll`; `auto` so the
119
137
  // native scrollbar only shows when the content overflows.
120
- style: { overflow: "auto" } },
138
+ style: { overflow: "auto" }, "data-testid": "ATL-Dialog-ScrollViewport" },
121
139
  React__default.createElement(DialogScrollAreaContext.Provider, { value: true }, children))));
122
140
  }
123
141
  /** Layout-only header row; sticky unless nested inside a `Dialog.ScrollArea`. */
@@ -132,15 +150,26 @@ function SharedDialogFooter(_a) {
132
150
  const sticky = !useInsideDialogScrollArea();
133
151
  return (React__default.createElement("div", Object.assign({}, rest, { className: classnames(styles.footer, className), style: style, "data-sticky": sticky || undefined, "data-testid": "ATL-Dialog-Footer" }), children));
134
152
  }
153
+ function renderActionButton(action, defaults) {
154
+ if (!action)
155
+ return null;
156
+ return isValidElement(action) ? (action) : (React__default.createElement(Button, Object.assign({}, mergeProps(defaults, action))));
157
+ }
135
158
  /**
136
159
  * The action-button layout: tertiary on the left, primary/secondary grouped on
137
160
  * the right. Drop it inside a `Dialog.Footer`.
138
161
  */
139
162
  function DialogActions(_a) {
140
163
  var { primary, secondary, tertiary, align = "right", className, style } = _a, rest = __rest(_a, ["primary", "secondary", "tertiary", "align", "className", "style"]);
141
- const secondaryAction = secondary && isValidElement(secondary) ? (secondary) : (React__default.createElement(Button, Object.assign({ type: "primary", variation: "subtle" }, secondary)));
142
- const primaryAction = primary && isValidElement(primary) ? (primary) : (React__default.createElement(Button, Object.assign({ type: "primary" }, primary)));
143
- const tertiaryAction = tertiary && isValidElement(tertiary) ? (tertiary) : (React__default.createElement(Button, Object.assign({ type: "secondary", variation: "destructive" }, tertiary)));
164
+ const primaryAction = renderActionButton(primary, { type: "primary" });
165
+ const secondaryAction = renderActionButton(secondary, {
166
+ type: "primary",
167
+ variation: "subtle",
168
+ });
169
+ const tertiaryAction = renderActionButton(tertiary, {
170
+ type: "secondary",
171
+ variation: "destructive",
172
+ });
144
173
  return (React__default.createElement("div", Object.assign({}, rest, { className: classnames(actionsStyles.actions, [actionsStyles[`align-${align}`]], className), style: style, "data-testid": "ATL-Dialog-Actions" }),
145
174
  tertiary && (React__default.createElement("div", { className: actionsStyles.leftActions }, tertiaryAction)),
146
175
  React__default.createElement("div", { className: classnames(actionsStyles.buttonGroup, actionsStyles[`align-${align}`]) },
@@ -148,20 +177,24 @@ function DialogActions(_a) {
148
177
  primary && primaryAction)));
149
178
  }
150
179
 
151
- function DialogBottomSheetRoot(props) {
180
+ function DialogBottomSheet(props) {
152
181
  return (React__default.createElement(BottomSheet.Root, Object.assign({}, props)));
153
182
  }
154
183
  function DialogBottomSheetTrigger(props) {
155
184
  return (React__default.createElement(BottomSheet.Trigger, Object.assign({}, props)));
156
185
  }
157
186
  function DialogBottomSheetContent(_a) {
158
- var { children, className, style } = _a, rest = __rest(_a, ["children", "className", "style"]);
187
+ var { children, className, style, render } = _a, rest = __rest(_a, ["children", "className", "style", "render"]);
159
188
  const { type, size, finalFocus } = useDialogContext();
160
189
  return (
161
190
  // Opt-out of the BottomSheet's built-in scroll area.
162
191
  // Dialog will handle the scroll area itself.
163
192
  React__default.createElement(BottomSheetScrollAreaContext.Provider, { value: false },
164
- React__default.createElement(BottomSheet.Popup, Object.assign({}, rest, { className: classnames(styles.sheetSurface, className), style: style, role: type, finalFocus: finalFocus, "data-dialog-variant": "sheet", "data-size": size }), children)));
193
+ React__default.createElement(BottomSheet.Popup, Object.assign({}, rest, {
194
+ // The bottom sheet is backed by a drawer popup, so re-shape its state
195
+ // into the dialog popup state the consumer's `render` is typed against.
196
+ render: resolveBottomSheetContentRender(render), className: classnames(styles.sheetSurface, className), style: style, role: type, finalFocus: finalFocus, "data-dialog-variant": "sheet", "data-size": size }),
197
+ React__default.createElement(DrawerContent, { "data-base-ui-swipe-ignore": true }, children))));
165
198
  }
166
199
  function DialogBottomSheetTitle(_a) {
167
200
  var { children } = _a, rest = __rest(_a, ["children"]);
@@ -192,19 +225,17 @@ function DialogBottomSheetBody(_a) {
192
225
  return insideScrollArea ? (content) : (React__default.createElement(DialogBottomSheetScrollArea, null, content));
193
226
  }
194
227
  /** Mobile shell: a bottom sheet built on the BottomSheet/Drawer primitives. */
195
- const DialogBottomSheet = Object.assign(DialogBottomSheetRoot, {
196
- Trigger: DialogBottomSheetTrigger,
197
- Content: DialogBottomSheetContent,
198
- Header: SharedDialogHeader,
199
- Title: DialogBottomSheetTitle,
200
- Close: DialogBottomSheetClose,
201
- Body: DialogBottomSheetBody,
202
- Footer: SharedDialogFooter,
203
- ScrollArea: DialogBottomSheetScrollArea,
204
- });
228
+ DialogBottomSheet.Trigger = DialogBottomSheetTrigger;
229
+ DialogBottomSheet.Content = DialogBottomSheetContent;
230
+ DialogBottomSheet.Header = SharedDialogHeader;
231
+ DialogBottomSheet.Title = DialogBottomSheetTitle;
232
+ DialogBottomSheet.Close = DialogBottomSheetClose;
233
+ DialogBottomSheet.Body = DialogBottomSheetBody;
234
+ DialogBottomSheet.Footer = SharedDialogFooter;
235
+ DialogBottomSheet.ScrollArea = DialogBottomSheetScrollArea;
205
236
 
206
- function DialogModalRoot(props) {
207
- return React__default.createElement(DialogRoot$1, Object.assign({}, props));
237
+ function DialogModal(props) {
238
+ return React__default.createElement(DialogRoot, Object.assign({}, props));
208
239
  }
209
240
  function DialogModalTrigger(_a) {
210
241
  var { children, render, handle, payload, className, style } = _a, rest = __rest(_a, ["children", "render", "handle", "payload", "className", "style"]);
@@ -236,17 +267,14 @@ function DialogModalBody(_a) {
236
267
  const content = (React__default.createElement(DialogDescription, { render: descriptionProps => (React__default.createElement("div", Object.assign({}, rest, descriptionProps, { className: classnames(styles.body, { [styles.fullBleed]: fullBleed }, className), style: style }), children)) }));
237
268
  return insideScrollArea ? (content) : (React__default.createElement(DialogScrollArea$1, null, content));
238
269
  }
239
- const DialogModal = Object.assign(DialogModalRoot, {
240
- Trigger: DialogModalTrigger,
241
- Content: DialogModalContent,
242
- Header: SharedDialogHeader,
243
- Title: DialogModalTitle,
244
- Close: DialogModalClose,
245
- Body: DialogModalBody,
246
- Footer: SharedDialogFooter,
247
- // The modal keeps the plain native-scrollbar scroll region.
248
- ScrollArea: DialogScrollArea$1,
249
- });
270
+ DialogModal.Trigger = DialogModalTrigger;
271
+ DialogModal.Content = DialogModalContent;
272
+ DialogModal.Header = SharedDialogHeader;
273
+ DialogModal.Title = DialogModalTitle;
274
+ DialogModal.Close = DialogModalClose;
275
+ DialogModal.Body = DialogModalBody;
276
+ DialogModal.Footer = SharedDialogFooter;
277
+ DialogModal.ScrollArea = DialogScrollArea$1;
250
278
 
251
279
  /**
252
280
  * Creates a handle that opens/closes a `Dialog` from detached triggers (e.g. an
@@ -271,7 +299,7 @@ function useDialogShell() {
271
299
  * desktop, a bottom sheet on mobile. Compose it with `Dialog.Trigger`,
272
300
  * `Dialog.Content`, and the layout parts.
273
301
  */
274
- function DialogRoot(_a) {
302
+ function Dialog(_a) {
275
303
  var { onRequestClose, size = "base", type = "dialog", finalFocus, children, onOpenChange } = _a, rest = __rest(_a, ["onRequestClose", "size", "type", "finalFocus", "children", "onOpenChange"]);
276
304
  function handleOpenChange(nextOpen, eventDetails) {
277
305
  if (!nextOpen) {
@@ -337,7 +365,6 @@ function DialogScrollArea(props) {
337
365
  const Shell = useDialogShell();
338
366
  return React__default.createElement(Shell.ScrollArea, Object.assign({}, props));
339
367
  }
340
- const Dialog = DialogRoot;
341
368
  Dialog.Trigger = DialogTrigger;
342
369
  Dialog.Content = DialogContent;
343
370
  Dialog.Header = DialogHeader;
@@ -116,6 +116,46 @@ function ThemedComponent() {
116
116
  }
117
117
  ```
118
118
 
119
+ ### Cross-tab theme sync (Web Only)
120
+
121
+ The provider can keep the theme in sync across a user's open browser tabs. This
122
+ is opt-in: pass the `localStorage` key your app writes to as the `storageKey`
123
+ prop. The provider then listens for
124
+ [`storage` events](https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event)
125
+ on that key and applies theme changes from other tabs. The `storage` event fires
126
+ only in tabs *other* than the one that wrote the value, so there's no feedback
127
+ loop.
128
+
129
+ **Your app is responsible for writing to `localStorage`** when the theme changes
130
+ — Atlantis only handles the listen-and-react side.
131
+
132
+ ```tsx
133
+ <AtlantisThemeContextProvider storageKey="my_app_theme">
134
+ <ThemedComponent />
135
+ </AtlantisThemeContextProvider>
136
+ ```
137
+
138
+ ```tsx
139
+ // Theme toggle — write to the same key after calling updateTheme
140
+ import { updateTheme } from "@jobber/components/AtlantisThemeContext";
141
+
142
+ function toggleTheme(newTheme: "light" | "dark") {
143
+ updateTheme(newTheme); // updates all providers in this tab immediately
144
+
145
+ try {
146
+ localStorage.setItem("my_app_theme", newTheme); // signals other tabs
147
+ } catch {
148
+ // localStorage unavailable (e.g. private mode) — degrades gracefully
149
+ }
150
+ }
151
+ ```
152
+
153
+ Omit `storageKey` and no `storage` listener is added, keeping the previous
154
+ within-tab-only behavior. Multiple dynamic providers on the same page all share
155
+ the same internal store, so a single provider with a `storageKey` is enough — a
156
+ cross-tab signal updates every dynamic provider at once. Providers mounted with
157
+ `dangerouslyOverrideTheme` are unaffected.
158
+
119
159
  ### Forcing a theme for an AtlantisThemeContextProvider
120
160
 
121
161
  In some scenarios you may want to force a theme for specific components
@@ -255,3 +295,4 @@ Key features:
255
295
  | `children` | `ReactNode` | Yes | — | The children to render. |
256
296
  | `dangerouslyOverrideTheme` | `Theme` | No | — | Force the theme for this provider to always be the same as the provided theme. Useful for sections that should remain... |
257
297
  | `dangerouslyOverrideTokens` | `OverrideTokens` | No | — | Overrides existing design tokens with custom values. Can also supply custom tokens which will be accessible via useAt... |
298
+ | `storageKey` | `string` | No | — | The `localStorage` key your app writes to when toggling the theme (e.g. `"jobber_theme"`). When set, the provider lis... |
@@ -33,10 +33,6 @@ numerical data (and their headers) round to the same decimal point, and are
33
33
  right-aligned. This makes it much easier for the reader to quickly parse large
34
34
  distinctions in dollar amounts, inventory counts, and other key business data.
35
35
 
36
- If you have a small list of information with a 1:1 label-to-data relationship
37
- (for example, the issued and due dates on an invoice), consider using
38
- [DescriptionList](../DescriptionList/DescriptionList.md).
39
-
40
36
  **Note**: The atomic DataTable components are the path forward and should be
41
37
  considered prior to using the [DataList](../DataList/DataList.md) and
42
38
  [Table](../Table/Table.md) components.