@jobber/components 8.21.1 → 8.23.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 (93) hide show
  1. package/Dialog.d.ts +1 -0
  2. package/Dialog.js +17 -0
  3. package/dist/BottomSheet-cjs.js +34 -7
  4. package/dist/BottomSheet-es.js +34 -8
  5. package/dist/CSPContext-cjs.js +69 -0
  6. package/dist/CSPContext-es.js +46 -0
  7. package/dist/Card/index.cjs +3 -0
  8. package/dist/Card/index.mjs +3 -0
  9. package/dist/ComboboxChipRemove-cjs.js +54 -211
  10. package/dist/ComboboxChipRemove-es.js +8 -164
  11. package/dist/DataDump/index.cjs +3 -0
  12. package/dist/DataDump/index.mjs +3 -0
  13. package/dist/Dialog/Dialog.d.ts +3 -0
  14. package/dist/Dialog/Dialog.types.d.ts +205 -0
  15. package/dist/Dialog/DialogBottomSheet.d.ts +28 -0
  16. package/dist/Dialog/DialogModal.d.ts +20 -0
  17. package/dist/Dialog/constants.d.ts +1 -0
  18. package/dist/Dialog/dialogComposableShared.d.ts +53 -0
  19. package/dist/Dialog/dialogReturnFocus.d.ts +43 -0
  20. package/dist/Dialog/index.cjs +33 -0
  21. package/dist/Dialog/index.d.ts +4 -0
  22. package/dist/Dialog/index.mjs +25 -0
  23. package/dist/DrawerDescription-cjs.js +410 -0
  24. package/dist/DrawerDescription-es.js +383 -0
  25. package/dist/DrawerTitle-cjs.js +116 -0
  26. package/dist/DrawerTitle-es.js +92 -0
  27. package/dist/InputNumberExperimental-cjs.js +24 -23
  28. package/dist/InputNumberExperimental-es.js +3 -2
  29. package/dist/InternalBackdrop-es.js +3 -3
  30. package/dist/Menu/index.cjs +3 -0
  31. package/dist/Menu/index.mjs +3 -0
  32. package/dist/Menu-cjs.js +6 -4
  33. package/dist/Menu-es.js +6 -4
  34. package/dist/MenuSubmenuTrigger-cjs.js +53 -103
  35. package/dist/MenuSubmenuTrigger-es.js +55 -103
  36. package/dist/NumberFieldInput-cjs.js +9 -9
  37. package/dist/NumberFieldInput-es.js +3 -3
  38. package/dist/Page/index.cjs +3 -0
  39. package/dist/Page/index.mjs +3 -0
  40. package/dist/ScrollAreaViewport-cjs.js +921 -960
  41. package/dist/ScrollAreaViewport-es.js +917 -958
  42. package/dist/SelectGroupLabel-cjs.js +1924 -0
  43. package/dist/SelectGroupLabel-es.js +1888 -0
  44. package/dist/SelectPrimitive-cjs.js +112 -0
  45. package/dist/SelectPrimitive-es.js +110 -0
  46. package/dist/ToolbarRootContext-cjs.js +35 -0
  47. package/dist/ToolbarRootContext-es.js +14 -0
  48. package/dist/dialogReturnFocus-cjs.js +427 -0
  49. package/dist/dialogReturnFocus-es.js +423 -0
  50. package/dist/docs/SelectPrimitive/SelectPrimitive.md +326 -0
  51. package/dist/docs/index.md +1 -0
  52. package/dist/floating-ui.react-dom-cjs.js +1 -0
  53. package/dist/floating-ui.react-dom-es.js +2 -2
  54. package/dist/floating-ui.utils.dom-es.js +1 -1
  55. package/dist/index.cjs +15 -7
  56. package/dist/index.d.mts +1 -0
  57. package/dist/index.d.ts +1 -0
  58. package/dist/index.mjs +12 -7
  59. package/dist/primitives/BottomSheet/BottomSheet.d.ts +19 -1
  60. package/dist/primitives/BottomSheet/BottomSheet.types.d.ts +8 -0
  61. package/dist/primitives/BottomSheet/index.cjs +2 -0
  62. package/dist/primitives/BottomSheet/index.d.ts +1 -1
  63. package/dist/primitives/BottomSheet/index.mjs +2 -1
  64. package/dist/primitives/ComboboxPrimitive/index.cjs +3 -1
  65. package/dist/primitives/ComboboxPrimitive/index.mjs +3 -1
  66. package/dist/primitives/InputNumberExperimental/index.cjs +2 -1
  67. package/dist/primitives/InputNumberExperimental/index.mjs +2 -1
  68. package/dist/primitives/SelectPrimitive/SelectPrimitive.d.ts +63 -0
  69. package/dist/primitives/SelectPrimitive/index.cjs +29 -0
  70. package/dist/primitives/SelectPrimitive/index.d.ts +2 -0
  71. package/dist/primitives/SelectPrimitive/index.mjs +23 -0
  72. package/dist/primitives/SelectPrimitive/types.d.ts +16 -0
  73. package/dist/primitives/index.cjs +9 -1
  74. package/dist/primitives/index.d.ts +1 -0
  75. package/dist/primitives/index.mjs +8 -2
  76. package/dist/primitives/mergeClassName.d.ts +12 -0
  77. package/dist/resolveAriaLabelledBy-cjs.js +195 -0
  78. package/dist/resolveAriaLabelledBy-es.js +162 -0
  79. package/dist/styles.css +685 -0
  80. package/dist/unstyledPrimitives/index.cjs +434 -259
  81. package/dist/unstyledPrimitives/index.d.ts +2 -0
  82. package/dist/unstyledPrimitives/index.mjs +425 -252
  83. package/dist/useButton-cjs.js +2 -0
  84. package/dist/useButton-es.js +3 -2
  85. package/dist/useCompositeListItem-es.js +4 -4
  86. package/dist/useLabel-cjs.js +3 -329
  87. package/dist/useLabel-es.js +4 -299
  88. package/dist/useLabelableId-cjs.js +332 -0
  89. package/dist/useLabelableId-es.js +300 -0
  90. package/dist/useRenderElement-cjs.js +3 -0
  91. package/dist/useRenderElement-es.js +4 -1
  92. package/dist/utils/meta/meta.json +11 -1
  93. package/package.json +2 -2
@@ -0,0 +1,423 @@
1
+ import { _ as __rest } from './tslib.es6-es.js';
2
+ import React__default, { isValidElement } from 'react';
3
+ import { useWindowDimensions } from '@jobber/hooks';
4
+ import classnames from 'classnames';
5
+ import { n as normalizeBaseUiButtonProps, i as isAtlantisButtonRenderTarget, s as stripNativeTypeFromButtonRenderTarget, r as renderAtlantisButtonTarget } from './buttonRenderAdapter-es.js';
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';
8
+ import { H as Heading } from './Heading-es.js';
9
+ import { a as BottomSheet, B as BottomSheetScrollAreaContext } from './BottomSheet-es.js';
10
+ 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';
13
+
14
+ // Copied from Menu's constant so the two surfaces agree on what "mobile" means.
15
+ // (The proposal calls for copying shared Menu values into the component first
16
+ // and deciding later whether to promote them to a shared location.)
17
+ const SMALL_SCREEN_BREAKPOINT = 490;
18
+
19
+ var styles = {"small":"uYYyCR3l6E8-","base":"X1jGz-sLWf4-","large":"_4zFf2PkFhaA-","fullScreen":"nJoCr8oWJ7w-","header":"XFKiCQ8QbQU-","close":"FDOhnO0TT08-","scrollRegion":"_8DjYA23vHXA-","scrollViewport":"Bwr9IUYpLfM-","body":"zp9kx9uue2I-","fullBleed":"EhtwBTy1ai4-","footer":"DRIJhI1knKw-","sheetSurface":"vmcZRwOcNMo-","popup":"mFX7qDCd17I-","backdrop":"NE-BIsVE-hE-","viewport":"hp70o-3Cf-w-","spinning":"Zf-Z8DJcC-Y-"};
20
+
21
+ var actionsStyles = {"actions":"hKVNddbxkmo-","leftActions":"nslrozOH-v4-","buttonGroup":"BrXAnQBttWE-","align-left":"_9Vgd-3YJxlI-","align-right":"_8HC9NqvmJdo-","align-fullWidth":"ZZ3XuxGv6ow-","spinning":"PWf7wHPhd2A-"};
22
+
23
+ /**
24
+ * Resolves the trigger element for `Dialog.Trigger`. Copied from Menu's
25
+ * `resolveMenuTriggerRender` so an Atlantis `<Button>` works as a trigger via
26
+ * `children` or `render` identically in both shells. Raw text children are
27
+ * wrapped in a default `Button`.
28
+ */
29
+ function resolveComposableTriggerRender({ children, render, }) {
30
+ if (render) {
31
+ if (typeof render === "function") {
32
+ return (props) => {
33
+ const renderedElement = render(normalizeBaseUiButtonProps(props));
34
+ return isAtlantisButtonRenderTarget(renderedElement)
35
+ ? stripNativeTypeFromButtonRenderTarget(renderedElement)
36
+ : renderedElement;
37
+ };
38
+ }
39
+ return isAtlantisButtonRenderTarget(render)
40
+ ? renderAtlantisButtonTarget(render)
41
+ : render;
42
+ }
43
+ if (isAtlantisButtonRenderTarget(children)) {
44
+ return renderAtlantisButtonTarget(children);
45
+ }
46
+ if (React__default.isValidElement(children)) {
47
+ return children;
48
+ }
49
+ return renderAtlantisButtonTarget(React__default.createElement(Button, { type: "primary" },
50
+ React__default.createElement(Button.Label, null, children)));
51
+ }
52
+ /**
53
+ * Resolves the dismiss element for `Dialog.Close`, mirroring
54
+ * `resolveComposableTriggerRender` so a custom render works in both shells.
55
+ * Falls back to the subtle "remove" `ButtonDismiss` when neither `render` nor
56
+ * `children` are supplied. An Atlantis `<Button>`/`<ButtonDismiss>` passed via
57
+ * `render` or `children` is adapted; any other valid element is used as-is.
58
+ */
59
+ function resolveComposableCloseRender({ children, render, }) {
60
+ if (render) {
61
+ if (typeof render === "function") {
62
+ return (props) => {
63
+ const renderedElement = render(normalizeBaseUiButtonProps(props));
64
+ return isAtlantisButtonRenderTarget(renderedElement)
65
+ ? stripNativeTypeFromButtonRenderTarget(renderedElement)
66
+ : renderedElement;
67
+ };
68
+ }
69
+ return isAtlantisButtonRenderTarget(render)
70
+ ? renderAtlantisButtonTarget(render)
71
+ : render;
72
+ }
73
+ if (isAtlantisButtonRenderTarget(children)) {
74
+ return renderAtlantisButtonTarget(children);
75
+ }
76
+ if (React__default.isValidElement(children)) {
77
+ return children;
78
+ }
79
+ return renderAtlantisButtonTarget(React__default.createElement(Button, { type: "tertiary", variation: "subtle", ariaLabel: "Close dialog" },
80
+ React__default.createElement(Button.Icon, { name: "remove" })));
81
+ }
82
+ const DialogContext = React__default.createContext({
83
+ type: "dialog",
84
+ size: "base",
85
+ isMobile: false,
86
+ finalFocus: undefined,
87
+ });
88
+ /** Supplies the static config (type/size/isMobile/finalFocus) to the parts. */
89
+ function DialogProvider({ children, type, size, isMobile, finalFocus, }) {
90
+ return (React__default.createElement(DialogContext.Provider, { value: { type, size, isMobile, finalFocus } }, children));
91
+ }
92
+ /** Reads the Dialog config; throws if a part is used outside `<Dialog>`. */
93
+ function useDialogContext() {
94
+ const context = React__default.useContext(DialogContext);
95
+ return context;
96
+ }
97
+ /**
98
+ * True when the current parts render inside a `Dialog.ScrollArea` (or the scroll
99
+ * region a `Dialog.Body` wraps itself in). Header/Footer read it to know whether
100
+ * they are sticky (not nested inside a `Dialog.ScrollArea`) or scroll (nested inside a `Dialog.ScrollArea`); `Dialog.Body`
101
+ * reads it to avoid creating a nested scroller.
102
+ */
103
+ const DialogScrollAreaContext = React__default.createContext(false);
104
+ /** Whether the current part is nested inside a `Dialog.ScrollArea`. */
105
+ function useInsideDialogScrollArea() {
106
+ return React__default.useContext(DialogScrollAreaContext);
107
+ }
108
+ /**
109
+ * The modal's scroll region — a BaseUI `ScrollArea` that scrolls its content
110
+ * with the browser's native scrollbar (re-enabled in Dialog.module.css). Content
111
+ * placed inside it scrolls and owns the scrollbar; `Dialog.Body` used on its own
112
+ * wraps itself in one. (The bottom sheet uses `DialogBottomSheetScrollArea`,
113
+ * backed by the BottomSheet primitive's scroll area, for its fade.)
114
+ */
115
+ function DialogScrollArea$1({ children, className, style, }) {
116
+ return (React__default.createElement(ScrollAreaRoot, { className: classnames(styles.scrollRegion, className), style: style },
117
+ React__default.createElement(ScrollAreaViewport, { className: styles.scrollViewport,
118
+ // BaseUI defaults the viewport to `overflow: scroll`; `auto` so the
119
+ // native scrollbar only shows when the content overflows.
120
+ style: { overflow: "auto" } },
121
+ React__default.createElement(DialogScrollAreaContext.Provider, { value: true }, children))));
122
+ }
123
+ /** Layout-only header row; sticky unless nested inside a `Dialog.ScrollArea`. */
124
+ function SharedDialogHeader(_a) {
125
+ var { children, className, style } = _a, rest = __rest(_a, ["children", "className", "style"]);
126
+ const sticky = !useInsideDialogScrollArea();
127
+ return (React__default.createElement("div", Object.assign({}, rest, { className: classnames(styles.header, className), style: style, "data-sticky": sticky || undefined }), children));
128
+ }
129
+ /** Generic footer region; sticky unless nested inside a `Dialog.ScrollArea`. */
130
+ function SharedDialogFooter(_a) {
131
+ var { children, className, style } = _a, rest = __rest(_a, ["children", "className", "style"]);
132
+ const sticky = !useInsideDialogScrollArea();
133
+ 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
+ }
135
+ /**
136
+ * The action-button layout: tertiary on the left, primary/secondary grouped on
137
+ * the right. Drop it inside a `Dialog.Footer`.
138
+ */
139
+ function DialogActions(_a) {
140
+ 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)));
144
+ return (React__default.createElement("div", Object.assign({}, rest, { className: classnames(actionsStyles.actions, [actionsStyles[`align-${align}`]], className), style: style, "data-testid": "ATL-Dialog-Actions" }),
145
+ tertiary && (React__default.createElement("div", { className: actionsStyles.leftActions }, tertiaryAction)),
146
+ React__default.createElement("div", { className: classnames(actionsStyles.buttonGroup, actionsStyles[`align-${align}`]) },
147
+ secondary && secondaryAction,
148
+ primary && primaryAction)));
149
+ }
150
+
151
+ function DialogBottomSheetRoot(props) {
152
+ return (React__default.createElement(BottomSheet.Root, Object.assign({}, props)));
153
+ }
154
+ function DialogBottomSheetTrigger(props) {
155
+ return (React__default.createElement(BottomSheet.Trigger, Object.assign({}, props)));
156
+ }
157
+ function DialogBottomSheetContent(_a) {
158
+ var { children, className, style } = _a, rest = __rest(_a, ["children", "className", "style"]);
159
+ const { type, size, finalFocus } = useDialogContext();
160
+ return (
161
+ // Opt-out of the BottomSheet's built-in scroll area.
162
+ // Dialog will handle the scroll area itself.
163
+ 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)));
165
+ }
166
+ function DialogBottomSheetTitle(_a) {
167
+ var { children } = _a, rest = __rest(_a, ["children"]);
168
+ return (React__default.createElement(DrawerTitle, Object.assign({}, rest, { render: titleProps => (React__default.createElement(Heading, Object.assign({ level: 2 }, titleProps), children)) })));
169
+ }
170
+ function DialogBottomSheetClose(_a) {
171
+ var { children, render } = _a, rest = __rest(_a, ["children", "render"]);
172
+ const closeProps = mergeProps({ className: styles.close }, Object.assign({}, rest));
173
+ return (React__default.createElement(DrawerClose, Object.assign({}, closeProps, { render: resolveComposableCloseRender({ children, render }) })));
174
+ }
175
+ /**
176
+ * The sheet's scroll region — backed by the BottomSheet primitive's styled
177
+ * scroll area (native scrollbar + bottom fade). Marks its content as inside a
178
+ * scroll area so a nested `Dialog.Body` renders plain and sticky regions know
179
+ * they scroll.
180
+ */
181
+ function DialogBottomSheetScrollArea({ children, className, style, }) {
182
+ return (React__default.createElement(BottomSheet.ScrollArea, { className: className, style: style },
183
+ React__default.createElement(DialogScrollAreaContext.Provider, { value: true }, children)));
184
+ }
185
+ function DialogBottomSheetBody(_a) {
186
+ var { children, fullBleed = false, className, style } = _a, rest = __rest(_a, ["children", "fullBleed", "className", "style"]);
187
+ const insideScrollArea = useInsideDialogScrollArea();
188
+ // Owns padding and the accessible-description wiring. By default it is the
189
+ // scroll region (wraps itself in the sheet's scroll area); inside an explicit
190
+ // `Dialog.ScrollArea` it renders as plain content (no nested scroller).
191
+ const content = (React__default.createElement(DrawerDescription, { render: descriptionProps => (React__default.createElement("div", Object.assign({}, rest, descriptionProps, { className: classnames(styles.body, { [styles.fullBleed]: fullBleed }, className), style: style }), children)) }));
192
+ return insideScrollArea ? (content) : (React__default.createElement(DialogBottomSheetScrollArea, null, content));
193
+ }
194
+ /** 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
+ });
205
+
206
+ function DialogModalRoot(props) {
207
+ return React__default.createElement(DialogRoot$1, Object.assign({}, props));
208
+ }
209
+ function DialogModalTrigger(_a) {
210
+ var { children, render, handle, payload, className, style } = _a, rest = __rest(_a, ["children", "render", "handle", "payload", "className", "style"]);
211
+ return (React__default.createElement(DialogTrigger$1, Object.assign({}, rest, { handle: handle, payload: payload, className: className, style: style, render: resolveComposableTriggerRender({ children, render }) })));
212
+ }
213
+ function DialogModalContent(_a) {
214
+ var { children, className, style } = _a, rest = __rest(_a, ["children", "className", "style"]);
215
+ const { type, size, finalFocus } = useDialogContext();
216
+ return (React__default.createElement(DialogPortal, null,
217
+ React__default.createElement(DialogBackdrop, { forceRender: true, className: styles.backdrop, "data-testid": "ATL-Dialog-Backdrop" }),
218
+ React__default.createElement(DialogViewport, { className: styles.viewport },
219
+ React__default.createElement(DialogPopup, Object.assign({}, rest, { className: classnames(styles.popup, styles[size], className), style: style, role: type, finalFocus: finalFocus, "data-dialog-variant": "modal" }), children))));
220
+ }
221
+ function DialogModalTitle(_a) {
222
+ var { children } = _a, rest = __rest(_a, ["children"]);
223
+ return (React__default.createElement(DialogTitle$1, Object.assign({}, rest, { render: titleProps => (React__default.createElement(Heading, Object.assign({ level: 2 }, titleProps), children)) })));
224
+ }
225
+ function DialogModalClose(_a) {
226
+ var { children, render } = _a, rest = __rest(_a, ["children", "render"]);
227
+ const closeProps = mergeProps({ className: styles.close }, Object.assign({}, rest));
228
+ return (React__default.createElement(DialogClose$1, Object.assign({}, closeProps, { render: resolveComposableCloseRender({ children, render }) })));
229
+ }
230
+ function DialogModalBody(_a) {
231
+ var { children, fullBleed = false, className, style } = _a, rest = __rest(_a, ["children", "fullBleed", "className", "style"]);
232
+ const insideScrollArea = useInsideDialogScrollArea();
233
+ // Owns padding and the accessible-description wiring. On its own the body is
234
+ // the scroll region, so it wraps itself in a `DialogScrollArea`; inside an
235
+ // explicit `Dialog.ScrollArea` it renders as plain content (no nested scroller).
236
+ 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
+ return insideScrollArea ? (content) : (React__default.createElement(DialogScrollArea$1, null, content));
238
+ }
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
+ });
250
+
251
+ /**
252
+ * Creates a handle that opens/closes a `Dialog` from detached triggers (e.g. an
253
+ * action inside a `Combobox`/`Menu`) without prop-drilling open state. Mirrors
254
+ * BaseUI's `Dialog.createHandle()`.
255
+ */
256
+ function createHandle() {
257
+ return createDialogHandle();
258
+ }
259
+ /**
260
+ * Returns the active shell — the bottom sheet on mobile, otherwise the centered
261
+ * modal. Each shell is a root component with
262
+ * its parts attached, so callers do `const Shell = useDialogShell()` then render
263
+ * `<Shell.Whatever />`.
264
+ */
265
+ function useDialogShell() {
266
+ const { isMobile } = useDialogContext();
267
+ return isMobile ? DialogBottomSheet : DialogModal;
268
+ }
269
+ /**
270
+ * The Dialog root is a centered modal on
271
+ * desktop, a bottom sheet on mobile. Compose it with `Dialog.Trigger`,
272
+ * `Dialog.Content`, and the layout parts.
273
+ */
274
+ function DialogRoot(_a) {
275
+ var { onRequestClose, size = "base", type = "dialog", finalFocus, children, onOpenChange } = _a, rest = __rest(_a, ["onRequestClose", "size", "type", "finalFocus", "children", "onOpenChange"]);
276
+ function handleOpenChange(nextOpen, eventDetails) {
277
+ if (!nextOpen) {
278
+ onRequestClose === null || onRequestClose === void 0 ? void 0 : onRequestClose(eventDetails);
279
+ }
280
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(nextOpen, eventDetails);
281
+ }
282
+ const { width } = useWindowDimensions();
283
+ const isMobile = width !== undefined && width <= SMALL_SCREEN_BREAKPOINT;
284
+ // The shell is the root component; its parts are reached via `useDialogShell`
285
+ // in each part below (the Menu pattern).
286
+ const RootComponent = isMobile ? DialogBottomSheet : DialogModal;
287
+ const rootProps = Object.assign(Object.assign({}, rest), { onOpenChange: handleOpenChange, modal: true, disablePointerDismissal: type === "alertdialog", children });
288
+ return (React__default.createElement(DialogProvider, { type: type, size: size, isMobile: isMobile, finalFocus: finalFocus },
289
+ React__default.createElement(RootComponent, Object.assign({}, rootProps))));
290
+ }
291
+ /**
292
+ * Opens the dialog. Accepts an Atlantis `<Button>` (via `children` or `render`)
293
+ * or links a detached `Dialog` through a matching `handle`.
294
+ */
295
+ function DialogTrigger(props) {
296
+ const Shell = useDialogShell();
297
+ return React__default.createElement(Shell.Trigger, Object.assign({}, props));
298
+ }
299
+ /**
300
+ * The dialog popup surface. Holds the `Header`, `Body`, and `Footer`; renders as a
301
+ * centered modal on desktop and a bottom sheet on mobile.
302
+ */
303
+ function DialogContent(props) {
304
+ const Shell = useDialogShell();
305
+ return React__default.createElement(Shell.Content, Object.assign({}, props));
306
+ }
307
+ /** Layout-only header row — typically a `Dialog.Title` and a `Dialog.Close`. */
308
+ function DialogHeader(props) {
309
+ const Shell = useDialogShell();
310
+ return React__default.createElement(Shell.Header, Object.assign({}, props));
311
+ }
312
+ /** The dialog's accessible title; wired to `aria-labelledby`. */
313
+ function DialogTitle(props) {
314
+ const Shell = useDialogShell();
315
+ return React__default.createElement(Shell.Title, Object.assign({}, props));
316
+ }
317
+ /** A dismiss button that closes the dialog. */
318
+ function DialogClose(props) {
319
+ const Shell = useDialogShell();
320
+ return React__default.createElement(Shell.Close, Object.assign({}, props));
321
+ }
322
+ /** The dialog body; wired to `aria-describedby`. */
323
+ function DialogBody(props) {
324
+ const Shell = useDialogShell();
325
+ return React__default.createElement(Shell.Body, Object.assign({}, props));
326
+ }
327
+ /** Footer region for actions or supporting content. */
328
+ function DialogFooter(props) {
329
+ const Shell = useDialogShell();
330
+ return React__default.createElement(Shell.Footer, Object.assign({}, props));
331
+ }
332
+ /**
333
+ * Advanced scroll region. Delegates to the shell: the modal uses a native
334
+ * scrollbar; the sheet uses the BottomSheet primitive's scroll area (with fade).
335
+ */
336
+ function DialogScrollArea(props) {
337
+ const Shell = useDialogShell();
338
+ return React__default.createElement(Shell.ScrollArea, Object.assign({}, props));
339
+ }
340
+ const Dialog = DialogRoot;
341
+ Dialog.Trigger = DialogTrigger;
342
+ Dialog.Content = DialogContent;
343
+ Dialog.Header = DialogHeader;
344
+ Dialog.Title = DialogTitle;
345
+ Dialog.Close = DialogClose;
346
+ Dialog.Body = DialogBody;
347
+ Dialog.Footer = DialogFooter;
348
+ Dialog.Actions = DialogActions;
349
+ Dialog.ScrollArea = DialogScrollArea;
350
+ Dialog.createHandle = createHandle;
351
+
352
+ /**
353
+ * Selector for elements that can receive focus. Mirrors the common
354
+ * "focus-trap"/"tabbable" baseline without pulling in a dependency: anything
355
+ * natively focusable plus explicit positive/zero tabindex, minus disabled
356
+ * controls and `tabindex="-1"`.
357
+ */
358
+ const FOCUSABLE_SELECTOR = [
359
+ "a[href]",
360
+ "area[href]",
361
+ "button:not([disabled])",
362
+ "input:not([disabled]):not([type='hidden'])",
363
+ "select:not([disabled])",
364
+ "textarea:not([disabled])",
365
+ "iframe",
366
+ "audio[controls]",
367
+ "video[controls]",
368
+ "[contenteditable]:not([contenteditable='false'])",
369
+ '[tabindex]:not([tabindex="-1"])',
370
+ ].join(",");
371
+ function isVisible(element) {
372
+ if (typeof element.checkVisibility === "function") {
373
+ return element.checkVisibility();
374
+ }
375
+ return Boolean(element.offsetWidth ||
376
+ element.offsetHeight ||
377
+ element.getClientRects().length);
378
+ }
379
+ /**
380
+ * The first focusable element within `container` (the container itself counts if
381
+ * it is focusable). Skips hidden elements. Returns `null` when nothing inside is
382
+ * focusable.
383
+ */
384
+ function getFirstFocusableWithin(container) {
385
+ var _a;
386
+ if (!container)
387
+ return null;
388
+ if (container.matches(FOCUSABLE_SELECTOR) && isVisible(container)) {
389
+ return container;
390
+ }
391
+ const candidates = Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
392
+ return (_a = candidates.find(isVisible)) !== null && _a !== void 0 ? _a : null;
393
+ }
394
+ /**
395
+ * Builds a `finalFocus` callback for `Dialog` that keeps keyboard focus near the
396
+ * trigger even when the trigger unmounts while the dialog is open (e.g. an
397
+ * autocomplete "Create" action whose row is replaced by a card on save).
398
+ *
399
+ * Resolution order on close:
400
+ * 1. the `trigger`, if it is still connected;
401
+ * 2. otherwise the first focusable element inside `boundary` (the "closest"
402
+ * landing spot);
403
+ * 3. otherwise `null`, which lets BaseUI fall back to its default behavior.
404
+ *
405
+ * @example
406
+ * const triggerRef = useRef<HTMLInputElement>(null);
407
+ * const boundaryRef = useRef<HTMLDivElement>(null);
408
+ * <div ref={boundaryRef}>…</div>
409
+ * <Dialog
410
+ * handle={handle}
411
+ * finalFocus={getDialogReturnFocus({ trigger: triggerRef, boundary: boundaryRef })}
412
+ * >
413
+ */
414
+ function getDialogReturnFocus({ trigger, boundary, }) {
415
+ return () => {
416
+ const target = trigger === null || trigger === void 0 ? void 0 : trigger.current;
417
+ if (target === null || target === void 0 ? void 0 : target.isConnected)
418
+ return target;
419
+ return getFirstFocusableWithin(boundary.current);
420
+ };
421
+ }
422
+
423
+ export { Dialog as D, getFirstFocusableWithin as a, getDialogReturnFocus as g };