@cratis/components 2.6.1 → 2.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 (36) hide show
  1. package/dist/cjs/CommandDialog/CommandDialog.js +30 -4
  2. package/dist/cjs/CommandDialog/CommandDialog.js.map +1 -1
  3. package/dist/cjs/Dialogs/BusyIndicatorDialog.js +6 -2
  4. package/dist/cjs/Dialogs/BusyIndicatorDialog.js.map +1 -1
  5. package/dist/cjs/Dialogs/Dialog.js +61 -7
  6. package/dist/cjs/Dialogs/Dialog.js.map +1 -1
  7. package/dist/cjs/Dialogs/DialogInitialFocus.js +49 -0
  8. package/dist/cjs/Dialogs/DialogInitialFocus.js.map +1 -0
  9. package/dist/cjs/Dialogs/index.js +5 -0
  10. package/dist/cjs/Dialogs/index.js.map +1 -1
  11. package/dist/cjs/useOverlayZIndex.js +39 -8
  12. package/dist/cjs/useOverlayZIndex.js.map +1 -1
  13. package/dist/esm/CommandDialog/CommandDialog.d.ts.map +1 -1
  14. package/dist/esm/CommandDialog/CommandDialog.js +30 -4
  15. package/dist/esm/CommandDialog/CommandDialog.js.map +1 -1
  16. package/dist/esm/Dialogs/BusyIndicatorDialog.d.ts.map +1 -1
  17. package/dist/esm/Dialogs/BusyIndicatorDialog.js +6 -2
  18. package/dist/esm/Dialogs/BusyIndicatorDialog.js.map +1 -1
  19. package/dist/esm/Dialogs/Dialog.d.ts +3 -1
  20. package/dist/esm/Dialogs/Dialog.d.ts.map +1 -1
  21. package/dist/esm/Dialogs/Dialog.js +62 -8
  22. package/dist/esm/Dialogs/Dialog.js.map +1 -1
  23. package/dist/esm/Dialogs/DialogInitialFocus.d.ts +6 -0
  24. package/dist/esm/Dialogs/DialogInitialFocus.d.ts.map +1 -0
  25. package/dist/esm/Dialogs/DialogInitialFocus.js +49 -0
  26. package/dist/esm/Dialogs/DialogInitialFocus.js.map +1 -0
  27. package/dist/esm/Dialogs/index.d.ts +1 -0
  28. package/dist/esm/Dialogs/index.d.ts.map +1 -1
  29. package/dist/esm/Dialogs/index.js +1 -0
  30. package/dist/esm/Dialogs/index.js.map +1 -1
  31. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  32. package/dist/esm/useOverlayZIndex.d.ts +2 -1
  33. package/dist/esm/useOverlayZIndex.d.ts.map +1 -1
  34. package/dist/esm/useOverlayZIndex.js +39 -9
  35. package/dist/esm/useOverlayZIndex.js.map +1 -1
  36. package/package.json +1 -1
@@ -1,7 +1,9 @@
1
1
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
2
  import { Dialog as Dialog$1 } from 'primereact/dialog';
3
3
  import { Button } from 'primereact/button';
4
- import { useDialogContext, DialogResult, DialogButtons } from '@cratis/arc.react/dialogs';
4
+ import { useDialogContext, DialogButtons, DialogResult } from '@cratis/arc.react/dialogs';
5
+ import { useRef } from 'react';
6
+ import { DialogInitialFocus } from './DialogInitialFocus.js';
5
7
 
6
8
  /**
7
9
  * Cratis wrapper around PrimeReact's `Dialog` that adds the surface every Arc
@@ -23,6 +25,36 @@ import { useDialogContext, DialogResult, DialogButtons } from '@cratis/arc.react
23
25
  * - **Validity gate** (`isValid`) that disables the confirm button without
24
26
  * disabling the cancel button. Used by command-executing wrappers to
25
27
  * block submission while form validation fails.
28
+ * - **Initial focus** (`initialFocus`) choosing which element inside the
29
+ * dialog the keyboard lands on when it opens.
30
+ *
31
+ * ## Initial focus
32
+ *
33
+ * By default the confirm button is focused when the dialog opens, so the
34
+ * common "read it, press Enter" flow costs one keystroke. That default also
35
+ * *arms* the confirm button: browsers fire `click` from the `keydown` of
36
+ * `Enter`, so the key still held down from opening the dialog — or the very
37
+ * ordinary habit of pressing `Enter` twice — confirms it immediately.
38
+ *
39
+ * A dialog whose confirm action is destructive **and** needs no input to
40
+ * become valid gets no protection from `isValid`, because there is nothing
41
+ * to fill in. Give those dialogs an explicit
42
+ * {@link DialogInitialFocus} instead:
43
+ *
44
+ * ```tsx
45
+ * <Dialog title="Delete personal data?"
46
+ * buttons={DialogButtons.YesNo}
47
+ * initialFocus={DialogInitialFocus.Cancel}
48
+ * onConfirm={...} onCancel={...}>
49
+ * This permanently removes the person and every record about them.
50
+ * </Dialog>
51
+ * ```
52
+ *
53
+ * `Cancel` focuses the dismissing button (`Cancel`, or `No` when the set has
54
+ * no `Cancel`); `Content` focuses the dialog's title so nothing at all is
55
+ * armed and screen readers announce the dialog from the top. Both keep the
56
+ * footer, the close (X), `Escape`, and every callback intact — unlike
57
+ * replacing `buttons` with a custom node.
26
58
  *
27
59
  * ## Arc dialog host integration
28
60
  *
@@ -75,7 +107,7 @@ import { useDialogContext, DialogResult, DialogButtons } from '@cratis/arc.react
75
107
  *
76
108
  * @param props - {@link DialogProps}.
77
109
  */
78
- const Dialog = ({ title, visible = true, onClose, onConfirm, onCancel, buttons = DialogButtons.OkCancel, children, width = '450px', style, contentStyle, resizable = false, isValid, isBusy = false, okLabel = 'Ok', cancelLabel = 'Cancel', yesLabel = 'Yes', noLabel = 'No', className, pt, ptOptions, unstyled }) => {
110
+ const Dialog = ({ title, visible = true, onClose, onConfirm, onCancel, buttons = DialogButtons.OkCancel, initialFocus = DialogInitialFocus.Confirm, children, width = '450px', style, contentStyle, resizable = false, isValid, isBusy = false, okLabel = 'Ok', cancelLabel = 'Cancel', yesLabel = 'Yes', noLabel = 'No', className, pt, ptOptions, unstyled }) => {
79
111
  // useDialogContext() is called unconditionally on every render — the try/catch only suppresses
80
112
  // the exception when Dialog is used standalone (outside a provider). React's Rules of Hooks
81
113
  // are not violated because the hook is always called; the try/catch never skips the call.
@@ -88,7 +120,29 @@ const Dialog = ({ title, visible = true, onClose, onConfirm, onCancel, buttons =
88
120
  contextCloseDialog = undefined;
89
121
  }
90
122
  const isDialogValid = isValid !== false;
91
- const headerElement = (jsx("div", { className: "inline-flex items-center justify-center gap-2", children: jsx("span", { className: "font-bold whitespace-nowrap", children: title }) }));
123
+ // A dismissing button only exists for the predefined sets that have one Cancel for
124
+ // OkCancel / YesNoCancel, No for YesNo. Asking for Cancel focus without one (DialogButtons.Ok,
125
+ // a custom footer node, or no footer) degrades to focusing the title rather than silently
126
+ // leaving focus on document.body outside the modal.
127
+ const hasDismissingButton = typeof buttons === 'number' && buttons !== DialogButtons.Ok;
128
+ const resolvedInitialFocus = (initialFocus === DialogInitialFocus.Cancel && !hasDismissingButton)
129
+ ? DialogInitialFocus.Content
130
+ : initialFocus;
131
+ const focusesConfirmButton = resolvedInitialFocus === DialogInitialFocus.Confirm;
132
+ const focusesDismissingButton = resolvedInitialFocus === DialogInitialFocus.Cancel;
133
+ const focusesTitle = resolvedInitialFocus === DialogInitialFocus.Content;
134
+ // PrimeReact's focus trap parks focus on the first focusable element inside the dialog while
135
+ // it transitions in, and its own onShow focus only fires when nothing in the dialog has focus.
136
+ // Moving focus to the title from onShow therefore runs last and wins, without having to fight
137
+ // the trap or turn focusOnShow off (which would leave focus outside the modal for the duration
138
+ // of the transition).
139
+ const titleRef = useRef(null);
140
+ const handleShow = () => {
141
+ if (focusesTitle) {
142
+ titleRef.current?.focus({ preventScroll: true });
143
+ }
144
+ };
145
+ const headerElement = (jsx("div", { className: "inline-flex items-center justify-center gap-2", children: jsx("span", { ref: titleRef, tabIndex: focusesTitle ? -1 : undefined, className: "font-bold whitespace-nowrap", children: title }) }));
92
146
  const handleClose = async (result) => {
93
147
  let shouldCloseThroughContext = true;
94
148
  if (result === DialogResult.Ok || result === DialogResult.Yes) {
@@ -115,10 +169,10 @@ const Dialog = ({ title, visible = true, onClose, onConfirm, onCancel, buttons =
115
169
  contextCloseDialog?.(result);
116
170
  }
117
171
  };
118
- const okFooter = (jsx(Fragment, { children: jsx(Button, { label: okLabel, icon: "pi pi-check", onClick: () => handleClose(DialogResult.Ok), disabled: !isDialogValid || isBusy, loading: isBusy, autoFocus: true }) }));
119
- const okCancelFooter = (jsxs(Fragment, { children: [jsx(Button, { label: okLabel, icon: "pi pi-check", onClick: () => handleClose(DialogResult.Ok), disabled: !isDialogValid || isBusy, loading: isBusy, autoFocus: true }), jsx(Button, { label: cancelLabel, icon: "pi pi-times", outlined: true, onClick: () => handleClose(DialogResult.Cancelled), disabled: isBusy })] }));
120
- const yesNoFooter = (jsxs(Fragment, { children: [jsx(Button, { label: yesLabel, icon: "pi pi-check", onClick: () => handleClose(DialogResult.Yes), disabled: !isDialogValid || isBusy, loading: isBusy, autoFocus: true }), jsx(Button, { label: noLabel, icon: "pi pi-times", outlined: true, onClick: () => handleClose(DialogResult.No), disabled: isBusy })] }));
121
- const yesNoCancelFooter = (jsxs(Fragment, { children: [jsx(Button, { label: yesLabel, icon: "pi pi-check", onClick: () => handleClose(DialogResult.Yes), disabled: !isDialogValid || isBusy, loading: isBusy, autoFocus: true }), jsx(Button, { label: noLabel, icon: "pi pi-times", outlined: true, onClick: () => handleClose(DialogResult.No), disabled: isBusy }), jsx(Button, { label: cancelLabel, icon: "pi pi-times", outlined: true, onClick: () => handleClose(DialogResult.Cancelled), disabled: isBusy })] }));
172
+ const okFooter = (jsx(Fragment, { children: jsx(Button, { label: okLabel, icon: "pi pi-check", onClick: () => handleClose(DialogResult.Ok), disabled: !isDialogValid || isBusy, loading: isBusy, autoFocus: focusesConfirmButton }) }));
173
+ const okCancelFooter = (jsxs(Fragment, { children: [jsx(Button, { label: okLabel, icon: "pi pi-check", onClick: () => handleClose(DialogResult.Ok), disabled: !isDialogValid || isBusy, loading: isBusy, autoFocus: focusesConfirmButton }), jsx(Button, { label: cancelLabel, icon: "pi pi-times", outlined: true, onClick: () => handleClose(DialogResult.Cancelled), disabled: isBusy, autoFocus: focusesDismissingButton })] }));
174
+ const yesNoFooter = (jsxs(Fragment, { children: [jsx(Button, { label: yesLabel, icon: "pi pi-check", onClick: () => handleClose(DialogResult.Yes), disabled: !isDialogValid || isBusy, loading: isBusy, autoFocus: focusesConfirmButton }), jsx(Button, { label: noLabel, icon: "pi pi-times", outlined: true, onClick: () => handleClose(DialogResult.No), disabled: isBusy, autoFocus: focusesDismissingButton })] }));
175
+ const yesNoCancelFooter = (jsxs(Fragment, { children: [jsx(Button, { label: yesLabel, icon: "pi pi-check", onClick: () => handleClose(DialogResult.Yes), disabled: !isDialogValid || isBusy, loading: isBusy, autoFocus: focusesConfirmButton }), jsx(Button, { label: noLabel, icon: "pi pi-times", outlined: true, onClick: () => handleClose(DialogResult.No), disabled: isBusy }), jsx(Button, { label: cancelLabel, icon: "pi pi-times", outlined: true, onClick: () => handleClose(DialogResult.Cancelled), disabled: isBusy, autoFocus: focusesDismissingButton })] }));
122
176
  const getFooterInterior = () => {
123
177
  // If buttons is a ReactNode (custom buttons), use it directly
124
178
  if (typeof buttons !== 'number') {
@@ -140,7 +194,7 @@ const Dialog = ({ title, visible = true, onClose, onConfirm, onCancel, buttons =
140
194
  const footer = (jsx("div", { className: "flex flex-wrap justify-start gap-3", children: getFooterInterior() }));
141
195
  return (jsx(Dialog$1, { header: headerElement, modal: true, footer: footer,
142
196
  // eslint-disable-next-line @typescript-eslint/no-empty-function
143
- onHide: typeof buttons === 'number' ? () => handleClose(DialogResult.Cancelled) : () => { }, visible: visible, style: { width, ...style }, contentStyle: contentStyle, resizable: resizable, closable: typeof buttons === 'number', className: className, pt: pt, ptOptions: ptOptions, unstyled: unstyled, children: children }));
197
+ onHide: typeof buttons === 'number' ? () => handleClose(DialogResult.Cancelled) : () => { }, onShow: handleShow, visible: visible, style: { width, ...style }, contentStyle: contentStyle, resizable: resizable, closable: typeof buttons === 'number', className: className, pt: pt, ptOptions: ptOptions, unstyled: unstyled, children: children }));
144
198
  };
145
199
 
146
200
  export { Dialog };
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.js","sources":["../../../Dialogs/Dialog.tsx"],"sourcesContent":[null],"names":["_jsx","_jsxs","_Fragment","PrimeDialog"],"mappings":"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"}
1
+ {"version":3,"file":"Dialog.js","sources":["../../../Dialogs/Dialog.tsx"],"sourcesContent":[null],"names":["_jsx","_Fragment","_jsxs","PrimeDialog"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare enum DialogInitialFocus {
2
+ Confirm = 1,
3
+ Cancel = 2,
4
+ Content = 3
5
+ }
6
+ //# sourceMappingURL=DialogInitialFocus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DialogInitialFocus.d.ts","sourceRoot":"","sources":["../../../Dialogs/DialogInitialFocus.ts"],"names":[],"mappings":"AAYA,oBAAY,kBAAkB;IAY1B,OAAO,IAAI;IAYX,MAAM,IAAI;IAWV,OAAO,IAAI;CACd"}
@@ -0,0 +1,49 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /**
4
+ * Defines where keyboard focus lands when a dialog becomes visible.
5
+ *
6
+ * A modal must move focus into itself when it opens — leaving focus on
7
+ * `document.body` strands keyboard and screen-reader users outside the
8
+ * content they were just interrupted with. Every member of this enum
9
+ * therefore names a real element inside the dialog; there is deliberately
10
+ * no "focus nothing" member.
11
+ */
12
+ var DialogInitialFocus;
13
+ (function (DialogInitialFocus) {
14
+ /**
15
+ * Focus the confirming button (`Ok` / `Yes`). This is the default and
16
+ * the fastest path for a dialog whose expected answer is "go ahead".
17
+ *
18
+ * ⚠️ It also *arms* that button: a browser fires `click` on a native
19
+ * button from the `keydown` of `Enter` or `Space`, so a held key or a
20
+ * second press of the key that opened the dialog confirms it. For a
21
+ * destructive action that needs no input to become valid, prefer
22
+ * {@link DialogInitialFocus.Cancel} or {@link DialogInitialFocus.Content}.
23
+ */
24
+ DialogInitialFocus[DialogInitialFocus["Confirm"] = 1] = "Confirm";
25
+ /**
26
+ * Focus the dismissing button — `Cancel` when the button set has one,
27
+ * otherwise `No`. This is the least destructive action, which is what
28
+ * the WAI-ARIA authoring practices recommend focusing for a dialog that
29
+ * confirms something irreversible.
30
+ *
31
+ * Falls back to {@link DialogInitialFocus.Content} when the button set
32
+ * has no dismissing button (`DialogButtons.Ok`), when the footer is a
33
+ * custom `ReactNode`, or when there is no footer at all.
34
+ */
35
+ DialogInitialFocus[DialogInitialFocus["Cancel"] = 2] = "Cancel";
36
+ /**
37
+ * Focus the dialog's own title instead of any button, so nothing is
38
+ * armed. Screen readers announce the dialog and its title, and the
39
+ * first `Tab` walks the content from the top.
40
+ *
41
+ * This is the right choice for a dialog that should be *read* before it
42
+ * is answered, and the only sensible choice for a dialog with no footer
43
+ * buttons at all.
44
+ */
45
+ DialogInitialFocus[DialogInitialFocus["Content"] = 3] = "Content";
46
+ })(DialogInitialFocus || (DialogInitialFocus = {}));
47
+
48
+ export { DialogInitialFocus };
49
+ //# sourceMappingURL=DialogInitialFocus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DialogInitialFocus.js","sources":["../../../Dialogs/DialogInitialFocus.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AAEA;;;;;;;;AAQG;IACS;AAAZ,CAAA,UAAY,kBAAkB,EAAA;AAE1B;;;;;;;;;AASG;AACH,IAAA,kBAAA,CAAA,kBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AAEX;;;;;;;;;AASG;AACH,IAAA,kBAAA,CAAA,kBAAA,CAAA,QAAA,CAAA,GAAA,CAAA,CAAA,GAAA,QAAU;AAEV;;;;;;;;AAQG;AACH,IAAA,kBAAA,CAAA,kBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAW;AACf,CAAC,EApCW,kBAAkB,KAAlB,kBAAkB,GAAA,EAAA,CAAA,CAAA;;;;"}
@@ -1,4 +1,5 @@
1
1
  export * from './BusyIndicatorDialog';
2
2
  export * from './ConfirmationDialog';
3
3
  export * from './Dialog';
4
+ export * from './DialogInitialFocus';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../Dialogs/index.ts"],"names":[],"mappings":"AAGA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../Dialogs/index.ts"],"names":[],"mappings":"AAGA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  export { BusyIndicatorDialog } from './BusyIndicatorDialog.js';
2
2
  export { ConfirmationDialog } from './ConfirmationDialog.js';
3
3
  export { Dialog } from './Dialog.js';
4
+ export { DialogInitialFocus } from './DialogInitialFocus.js';
4
5
 
5
6
  // Copyright (c) Cratis. All rights reserved.
6
7
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../Dialogs/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAA;AACA"}
1
+ {"version":3,"file":"index.js","sources":["../../../Dialogs/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAAA;AACA"}