@jonmilner/ui 0.5.2 → 0.5.3

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.
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { PopupScope as e, useRecordOpenChange as t } from "../popup/client.mjs";
3
+ import { AlertDialog as n } from "@base-ui/react/alert-dialog";
4
+ import { jsx as r } from "react/jsx-runtime";
5
+ //#region src/AlertDialog/client.tsx
6
+ function i(t) {
7
+ return /* @__PURE__ */ r(e, { children: /* @__PURE__ */ r(a, { ...t }) });
8
+ }
9
+ function a({ onOpenChange: e, ...i }) {
10
+ return /* @__PURE__ */ r(n.Root, {
11
+ ...i,
12
+ onOpenChange: t(e)
13
+ });
14
+ }
15
+ //#endregion
16
+ export { i as AlertDialogRootScope };
@@ -1,5 +1,5 @@
1
- import { DialogTrigger, DialogTriggerProps } from "../Dialog/client.mjs";
2
1
  import "../Dialog/index.mjs";
2
+ import { DialogTrigger, DialogTriggerProps } from "../Dialog/client.mjs";
3
3
  import { ReactNode } from "react";
4
4
  import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
5
5
  //#region src/AlertDialog/index.d.ts
@@ -1,17 +1,17 @@
1
1
  import { Button as e } from "../Button/index.mjs";
2
- import { PopupScope as t } from "../popup/client.mjs";
3
- import { Dialog as n } from "../Dialog/index.mjs";
2
+ import { Dialog as t } from "../Dialog/index.mjs";
3
+ import { AlertDialogRootScope as n } from "./client.mjs";
4
4
  import { AlertDialog as r } from "@base-ui/react/alert-dialog";
5
5
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
6
6
  //#region src/AlertDialog/index.tsx
7
7
  function o({ title: o, description: s, confirmLabel: c, cancelLabel: l = "Cancel", tone: u = "default", onConfirm: d, children: f, ...p }) {
8
- return /* @__PURE__ */ i(t, { children: /* @__PURE__ */ a(r.Root, {
8
+ return /* @__PURE__ */ a(n, {
9
9
  ...p,
10
- children: [f, /* @__PURE__ */ i(n.Popup, {
10
+ children: [f, /* @__PURE__ */ i(t.Popup, {
11
11
  description: s,
12
12
  size: "sm",
13
13
  title: o,
14
- children: /* @__PURE__ */ a(n.Actions, { children: [/* @__PURE__ */ i(n.Close, {
14
+ children: /* @__PURE__ */ a(t.Actions, { children: [/* @__PURE__ */ i(t.Close, {
15
15
  variant: "secondary",
16
16
  children: l
17
17
  }), /* @__PURE__ */ i(r.Close, {
@@ -22,8 +22,8 @@ function o({ title: o, description: s, confirmLabel: c, cancelLabel: l = "Cancel
22
22
  children: c
23
23
  })] })
24
24
  })]
25
- }) });
25
+ });
26
26
  }
27
- var s = Object.assign(o, { Trigger: n.Trigger });
27
+ var s = Object.assign(o, { Trigger: t.Trigger });
28
28
  //#endregion
29
29
  export { s as AlertDialog };
@@ -1,4 +1,6 @@
1
+ import "../Box/index.mjs";
1
2
  import { TriggerElementProps, TriggerLookProps } from "../popup/client.mjs";
3
+ import "./index.mjs";
2
4
  import { Dialog } from "@base-ui/react/dialog";
3
5
  import { ReactNode } from "react";
4
6
  //#region src/Dialog/client.d.ts
@@ -1,31 +1,74 @@
1
1
  "use client";
2
- import { triggerElement as e, usePopupScope as t } from "../popup/client.mjs";
3
- import { jsx as n } from "react/jsx-runtime";
4
- import { Dialog as r } from "@base-ui/react/dialog";
2
+ import { join as e } from "../styles/join.mjs";
3
+ import { splitStyleProps as t } from "../styles/split-style-props.mjs";
4
+ import { Box as n } from "../Box/index.mjs";
5
+ import { PopupScope as r, triggerElement as i, useClosingRule as a, usePopupScope as o, useRecordOpenChange as s } from "../popup/client.mjs";
6
+ import { jsx as c } from "react/jsx-runtime";
7
+ import { Dialog as l } from "@base-ui/react/dialog";
5
8
  //#region src/Dialog/client.tsx
6
- function i({ disabled: i = !1, handle: a, payload: o, id: s, ...c }) {
7
- let { ref: l } = t();
8
- return /* @__PURE__ */ n(r.Trigger, {
9
- disabled: i,
10
- handle: a,
11
- payload: o,
12
- id: s,
13
- ref: l,
14
- render: e(c)
9
+ function u({ disabled: e = !1, handle: t, payload: n, id: r, ...a }) {
10
+ let { ref: s } = o();
11
+ return /* @__PURE__ */ c(l.Trigger, {
12
+ disabled: e,
13
+ handle: t,
14
+ payload: n,
15
+ id: r,
16
+ ref: s,
17
+ render: i(a)
15
18
  });
16
19
  }
17
- function a({ disabled: t = !1, ...i }) {
18
- return /* @__PURE__ */ n(r.Close, {
19
- disabled: t,
20
- render: e(i)
20
+ function d({ disabled: e = !1, ...t }) {
21
+ return /* @__PURE__ */ c(l.Close, {
22
+ disabled: e,
23
+ render: i(t)
21
24
  });
22
25
  }
23
- function o({ children: e }) {
24
- let { container: i } = t();
25
- return /* @__PURE__ */ n(r.Portal, {
26
- container: i,
26
+ function f({ children: e }) {
27
+ let { container: t } = o();
28
+ return /* @__PURE__ */ c(l.Portal, {
29
+ container: t,
27
30
  children: e
28
31
  });
29
32
  }
33
+ function p(e) {
34
+ return /* @__PURE__ */ c(r, { children: /* @__PURE__ */ c(m, { ...e }) });
35
+ }
36
+ function m({ onOpenChange: e, ...t }) {
37
+ return /* @__PURE__ */ c(l.Root, {
38
+ ...t,
39
+ onOpenChange: s(e)
40
+ });
41
+ }
42
+ function h({ frame: e, ...n }) {
43
+ let r = n.finalFocus !== void 0 && n.finalFocus !== !0;
44
+ return /* @__PURE__ */ c(l.Popup, {
45
+ ...n,
46
+ render: (n, { open: i }) => {
47
+ let [, a] = t(n);
48
+ return /* @__PURE__ */ c(g, {
49
+ ...a,
50
+ finalFocus: r,
51
+ frame: e,
52
+ open: i
53
+ });
54
+ }
55
+ });
56
+ }
57
+ function g({ open: t, finalFocus: r, frame: i, ref: o, className: s, style: l, ...u }) {
58
+ return /* @__PURE__ */ c(n, {
59
+ ...u,
60
+ ...i,
61
+ ...a(o, {
62
+ finalFocus: r,
63
+ modal: !0,
64
+ open: t
65
+ }),
66
+ className: e(s, i.className),
67
+ style: {
68
+ ...l,
69
+ ...i.style
70
+ }
71
+ });
72
+ }
30
73
  //#endregion
31
- export { a as DialogClose, o as DialogPortal, i as DialogTrigger };
74
+ export { d as DialogClose, h as DialogPopupFrame, f as DialogPortal, p as DialogRootScope, u as DialogTrigger };
@@ -1,7 +1,7 @@
1
1
  import { BoxProps } from "../Box/index.mjs";
2
- import { DialogClose, DialogCloseProps, DialogTrigger, DialogTriggerProps } from "./client.mjs";
3
2
  import { PartProps } from "../styles/part-props.mjs";
4
3
  import { size as size$1 } from "./Dialog.css.mjs";
4
+ import { DialogClose, DialogCloseProps, DialogTrigger, DialogTriggerProps } from "./client.mjs";
5
5
  import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
6
6
  import { ReactNode } from "react";
7
7
  //#region src/Dialog/index.d.ts
@@ -15,7 +15,7 @@ export type DialogPopupProps = PartProps<Omit<Dialog$1.Popup.Props, "title">> &
15
15
  };
16
16
  export type DialogBodyProps = Omit<BoxProps<"div">, "as">;
17
17
  export type DialogActionsProps = Omit<BoxProps<"div">, "as">;
18
- declare function DialogRoot({ children, ...props }: DialogProps): import("react").JSX.Element;
18
+ declare function DialogRoot(props: DialogProps): import("react").JSX.Element;
19
19
  declare function DialogPopup({ title, description, size, position, margin, blockSize, display, flexDirection, gap, padding, backgroundColor, borderRadius, boxShadow, overflow, className, style, children, ...props }: DialogPopupProps): import("react").JSX.Element;
20
20
  declare function DialogBody({ display, flexDirection, gap, ...props }: DialogBodyProps): import("react").JSX.Element;
21
21
  declare function DialogActions({ display, flexWrap, justifyContent, gap, ...props }: DialogActionsProps): import("react").JSX.Element;
@@ -3,71 +3,67 @@ import { splitStyleProps as t } from "../styles/split-style-props.mjs";
3
3
  import { Box as n } from "../Box/index.mjs";
4
4
  import { Text as r } from "../Text/index.mjs";
5
5
  import { Heading as i } from "../Heading/index.mjs";
6
- import { PopupScope as a } from "../popup/client.mjs";
7
- import { DialogClose as o, DialogPortal as s, DialogTrigger as c } from "./client.mjs";
8
- import { backdrop as l, popup as u, size as d } from "./Dialog.css.mjs";
9
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
10
- import { Dialog as m } from "@base-ui/react/dialog";
6
+ import { DialogClose as a, DialogPopupFrame as o, DialogPortal as s, DialogRootScope as c, DialogTrigger as l } from "./client.mjs";
7
+ import { backdrop as u, popup as d, size as f } from "./Dialog.css.mjs";
8
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
9
+ import { Dialog as h } from "@base-ui/react/dialog";
11
10
  //#region src/Dialog/index.tsx
12
- function h({ children: e, ...t }) {
13
- return /* @__PURE__ */ f(a, { children: /* @__PURE__ */ f(m.Root, {
14
- ...t,
15
- children: e
16
- }) });
11
+ function g(e) {
12
+ return /* @__PURE__ */ p(c, { ...e });
17
13
  }
18
- function g({ title: a, description: o, size: c = "med", position: h = "fixed", margin: g = "auto", blockSize: _ = "fit", display: v = "flex", flexDirection: y = "column", gap: b = "16", padding: x = "24", backgroundColor: S = "bgRaised", borderRadius: C = "lg", boxShadow: w = "lg", overflow: T = "auto", className: E, style: D, children: O, ...k }) {
19
- let [A, j] = t(k);
20
- return /* @__PURE__ */ p(s, { children: [/* @__PURE__ */ f(m.Backdrop, { render: /* @__PURE__ */ f(n, {
21
- className: l,
14
+ function _({ title: a, description: c, size: l = "med", position: g = "fixed", margin: _ = "auto", blockSize: v = "fit", display: y = "flex", flexDirection: b = "column", gap: x = "16", padding: S = "24", backgroundColor: C = "bgRaised", borderRadius: w = "lg", boxShadow: T = "lg", overflow: E = "auto", className: D, style: O, children: k, ...A }) {
15
+ let [j, M] = t(A);
16
+ return /* @__PURE__ */ m(s, { children: [/* @__PURE__ */ p(h.Backdrop, { render: /* @__PURE__ */ p(n, {
17
+ className: u,
22
18
  position: "fixed",
23
19
  zIndex: "modal"
24
- }) }), /* @__PURE__ */ p(m.Popup, {
20
+ }) }), /* @__PURE__ */ m(o, {
25
21
  "aria-modal": !0,
26
- ...j,
27
- render: /* @__PURE__ */ f(n, {
22
+ ...M,
23
+ frame: {
28
24
  zIndex: "modal",
29
- position: h,
30
- margin: g,
31
- blockSize: _,
32
- display: v,
33
- flexDirection: y,
34
- gap: b,
35
- padding: x,
36
- backgroundColor: S,
37
- borderRadius: C,
38
- boxShadow: w,
39
- overflow: T,
40
- ...A,
41
- className: e(u, d[c], E),
42
- style: D
43
- }),
44
- children: [/* @__PURE__ */ p(n, {
25
+ position: g,
26
+ margin: _,
27
+ blockSize: v,
28
+ display: y,
29
+ flexDirection: b,
30
+ gap: x,
31
+ padding: S,
32
+ backgroundColor: C,
33
+ borderRadius: w,
34
+ boxShadow: T,
35
+ overflow: E,
36
+ ...j,
37
+ className: e(d, f[l], D),
38
+ style: O
39
+ },
40
+ children: [/* @__PURE__ */ m(n, {
45
41
  display: "flex",
46
42
  flexDirection: "column",
47
43
  gap: "8",
48
- children: [/* @__PURE__ */ f(m.Title, {
49
- render: /* @__PURE__ */ f(i, {
44
+ children: [/* @__PURE__ */ p(h.Title, {
45
+ render: /* @__PURE__ */ p(i, {
50
46
  as: "h2",
51
47
  size: "lg"
52
48
  }),
53
49
  children: a
54
- }), o == null ? null : /* @__PURE__ */ f(m.Description, {
55
- render: /* @__PURE__ */ f(r, { color: "fgMuted" }),
56
- children: o
50
+ }), c == null ? null : /* @__PURE__ */ p(h.Description, {
51
+ render: /* @__PURE__ */ p(r, { color: "fgMuted" }),
52
+ children: c
57
53
  })]
58
- }), O]
54
+ }), k]
59
55
  })] });
60
56
  }
61
- function _({ display: e = "flex", flexDirection: t = "column", gap: r = "12", ...i }) {
62
- return /* @__PURE__ */ f(n, {
57
+ function v({ display: e = "flex", flexDirection: t = "column", gap: r = "12", ...i }) {
58
+ return /* @__PURE__ */ p(n, {
63
59
  display: e,
64
60
  flexDirection: t,
65
61
  gap: r,
66
62
  ...i
67
63
  });
68
64
  }
69
- function v({ display: e = "flex", flexWrap: t = "wrap", justifyContent: r = "end", gap: i = "8", ...a }) {
70
- return /* @__PURE__ */ f(n, {
65
+ function y({ display: e = "flex", flexWrap: t = "wrap", justifyContent: r = "end", gap: i = "8", ...a }) {
66
+ return /* @__PURE__ */ p(n, {
71
67
  display: e,
72
68
  flexWrap: t,
73
69
  justifyContent: r,
@@ -75,12 +71,12 @@ function v({ display: e = "flex", flexWrap: t = "wrap", justifyContent: r = "end
75
71
  ...a
76
72
  });
77
73
  }
78
- var y = Object.assign(h, {
79
- Trigger: c,
80
- Popup: g,
81
- Body: _,
82
- Actions: v,
83
- Close: o
74
+ var b = Object.assign(g, {
75
+ Trigger: l,
76
+ Popup: _,
77
+ Body: v,
78
+ Actions: y,
79
+ Close: a
84
80
  });
85
81
  //#endregion
86
- export { y as Dialog };
82
+ export { b as Dialog };
@@ -75,6 +75,7 @@ const [open, setOpen] = useState(false);
75
75
 
76
76
  - The trigger has `aria-haspopup="dialog"` and `aria-expanded`. The popup is `role="alertdialog"` with `aria-modal`, labelled by the title and described by the description.
77
77
  - Opening moves focus to Cancel; Tab and Shift+Tab cycle between the two buttons, and the page behind is inert. Esc or Cancel closes it, and focus returns to the trigger. A click outside does nothing.
78
+ - A closed alert dialog stays on the page while it fades out, but is `inert` and `aria-hidden` from the moment it closes, and focus is back on the trigger at once, so a dialog opened during the fade is the only one a screen reader or a role query finds, and nothing in the fading one takes focus or a click (ADR 0113).
78
79
  - The danger confirm button is told apart by its label as well as its color.
79
80
  - Under reduced motion the panel only fades.
80
81
 
@@ -99,6 +99,7 @@ const [open, setOpen] = useState(false);
99
99
 
100
100
  - The trigger has `aria-haspopup="dialog"` and `aria-expanded`. The popup is `role="dialog"` with `aria-modal`, labelled by the title and described by the description.
101
101
  - Opening moves focus into the popup; Tab and Shift+Tab cycle inside it, and the page behind is inert. Esc or a backdrop click closes it, and focus returns to the trigger.
102
+ - A closed dialog stays on the page while it fades out, but is `inert` and `aria-hidden` from the moment it closes, and focus is back on the trigger at once, so a dialog opened during the fade is the only one a screen reader or a role query finds, and nothing in the fading one takes focus or a click (ADR 0113).
102
103
  - The panel takes the shared focus ring when focused from the keyboard. Under forced colors it keeps its border, so it stays apart from the page.
103
104
  - The backdrop is 40% of the shadow color over the page; it only dims, and carries no text.
104
105
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "./manifest.schema.json",
3
3
  "package": "@jonmilner/ui",
4
- "version": "0.5.2",
4
+ "version": "0.5.3",
5
5
  "components": [
6
6
  {
7
7
  "name": "AlertDialog",
package/dist/index.d.mts CHANGED
@@ -2,8 +2,8 @@ import { Box, BoxProps, StyleProps } from "./Box/index.mjs";
2
2
  import { Clickable, ClickableProps } from "./Clickable/index.mjs";
3
3
  import { Icon, IconProps } from "./Icon/index.mjs";
4
4
  import { Button, ButtonProps } from "./Button/index.mjs";
5
- import { DialogCloseProps, DialogTriggerProps } from "./Dialog/client.mjs";
6
5
  import { Dialog, DialogActionsProps, DialogBodyProps, DialogPopupProps, DialogProps } from "./Dialog/index.mjs";
6
+ import { DialogCloseProps, DialogTriggerProps } from "./Dialog/client.mjs";
7
7
  import { AlertDialog, AlertDialogProps, AlertDialogTriggerProps } from "./AlertDialog/index.mjs";
8
8
  import { Badge, BadgeProps } from "./Badge/index.mjs";
9
9
  import { Checkbox, CheckboxProps } from "./Checkbox/index.mjs";
@@ -43,11 +43,13 @@ function m(e) {
43
43
  return (n, r) => {
44
44
  t.current = n ? {
45
45
  keyboard: !1,
46
- opener: r.trigger ?? null
46
+ opener: r.trigger ?? null,
47
+ recorded: !0
47
48
  } : {
48
49
  ...t.current,
49
50
  keyboard: r.event instanceof KeyboardEvent,
50
- reason: r.reason
51
+ reason: r.reason,
52
+ recorded: !1
51
53
  }, e?.(n, r);
52
54
  };
53
55
  }
@@ -64,37 +66,53 @@ var g = /* @__PURE__ */ new Set([
64
66
  "trigger-hover",
65
67
  "focus-out",
66
68
  "outside-press"
67
- ]);
68
- function _(e, { finalFocus: t, open: n }) {
69
- let { trigger: r } = f(), i = a(u), l = c(null), d = o((t) => {
70
- l.current = t;
69
+ ]), _;
70
+ function v(e) {
71
+ return _ === void 0 && (_ = !1, e.createElement("div").focus({ get preventScroll() {
72
+ return _ = !0, !1;
73
+ } })), _;
74
+ }
75
+ function y(e, { finalFocus: t, modal: n = !1, open: r }) {
76
+ let { trigger: i } = f(), l = a(u), d = c(null), p = o((t) => {
77
+ d.current = t;
71
78
  let n = h(e, t);
72
79
  return () => {
73
- l.current = null, n();
80
+ d.current = null, n();
74
81
  };
75
82
  }, [e]);
76
83
  return s(() => {
77
- let e = l.current;
84
+ let e = d.current;
85
+ if (!r || !e || l.current.recorded) return;
86
+ let { activeElement: t, body: n } = e.ownerDocument, i = t === n || e.contains(t) ? null : t;
87
+ l.current = {
88
+ keyboard: !1,
89
+ opener: i
90
+ };
91
+ }, [r, l]), s(() => {
92
+ let e = d.current;
78
93
  if (!e) return;
79
- if (n) {
94
+ if (r) {
80
95
  e.inert = !1;
81
96
  return;
82
97
  }
83
- let { reason: a, keyboard: o, opener: s } = i.current, c = s?.isConnected ? s : r.current;
84
- if (e.contains(e.ownerDocument.activeElement) && !t && !g.has(a ?? "") && c instanceof HTMLElement) {
98
+ let { reason: a, keyboard: o, opener: s } = l.current;
99
+ l.current.recorded = !1;
100
+ let c = s?.isConnected ? s : i.current, { activeElement: u } = e.ownerDocument, f = n && a === "outside-press" && v(e.ownerDocument);
101
+ if (!t && c instanceof HTMLElement && (f || e.contains(u) && !g.has(a ?? ""))) {
85
102
  let e = { preventScroll: !0 };
86
103
  o && (e.focusVisible = !0), c.focus(e);
87
104
  }
88
105
  e.inert = !0;
89
106
  }, [
90
- n,
107
+ r,
91
108
  t,
92
- i,
93
- r
109
+ n,
110
+ l,
111
+ i
94
112
  ]), {
95
- "aria-hidden": !n || void 0,
96
- ref: d
113
+ "aria-hidden": !r || void 0,
114
+ ref: p
97
115
  };
98
116
  }
99
117
  //#endregion
100
- export { d as PopupScope, p as triggerElement, _ as useClosingRule, f as usePopupScope, m as useRecordOpenChange };
118
+ export { d as PopupScope, p as triggerElement, y as useClosingRule, f as usePopupScope, m as useRecordOpenChange };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jonmilner/ui",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "files": [
5
5
  "dist",
6
6
  "THIRD_PARTY_NOTICES.md"