@jonmilner/ui 0.4.3 → 0.5.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.
@@ -1,2 +1,2 @@
1
1
  @layer tokens, reset, atoms, components.box, components.checkbox, components.clickable, components.icon, components.icon-button, components.inline, components.stack, components.text, components.badge, components.button, components.chip, components.field, components.heading, components.dialog, components.alert-dialog, components.menu, components.multiselect, components.search-field, components.tabs, components.tag, components.text-field, components.toast, components.visually-hidden;
2
- @layer components.menu{._393eil1{border:var(--space-1) solid var(--color-border);transform-origin:var(--transform-origin);transition:opacity var(--duration-fast) var(--easing-standard), scale var(--duration-fast) var(--easing-enter)}._393eil1:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._393eil1[data-starting-style],._393eil1[data-ending-style]{opacity:0;scale:calc(1 - var(--scale-med))}._393eil2{cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}._393eil2:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._393eil2[data-highlighted]{background-color:light-dark(var(--color-bg-muted),color-mix(in srgb, var(--color-fg) 10%, var(--color-bg-raised)))}._393eil2[aria-disabled=true]{color:var(--color-fg-muted);cursor:not-allowed}._393eil3{text-decoration:none}._393eil4{border-block-start:var(--space-1) solid var(--color-border)}@media (forced-colors:active){._393eil2[data-highlighted]:not([aria-disabled=true]){forced-color-adjust:none;color:highlighttext;background-color:highlight}._393eil2[aria-disabled=true]{color:graytext}}}
2
+ @layer components.menu{._393eil1{border:var(--space-1) solid var(--color-border);transform-origin:var(--transform-origin);transition:opacity var(--duration-fast) var(--easing-standard), scale var(--duration-fast) var(--easing-enter)}._393eil1:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._393eil1[data-starting-style],._393eil1[data-ending-style]{opacity:0;scale:calc(1 - var(--scale-med))}._393eil2{cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}._393eil2:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._393eil2[data-highlighted]{background-color:light-dark(var(--color-bg-muted),color-mix(in srgb, var(--color-fg) 10%, var(--color-bg-raised)))}._393eil2[aria-disabled=true]{color:var(--color-fg-muted);cursor:not-allowed}._393eil3{text-decoration:none}._393eil4{border-block-start-color:var(--color-border)}._393eil4:before{content:"";border-block-start:var(--space-1) solid;border-block-start-color:inherit;display:block}@media (forced-colors:active){._393eil2[data-highlighted]:not([aria-disabled=true]){forced-color-adjust:none;color:highlighttext;background-color:highlight}._393eil2[aria-disabled=true]{color:graytext}}}
@@ -2,65 +2,47 @@
2
2
  import { join as e } from "../styles/join.mjs";
3
3
  import { splitStyleProps as t } from "../styles/split-style-props.mjs";
4
4
  import { Box as n } from "../Box/index.mjs";
5
- import { PopupScope as r, triggerElement as i, usePopupScope as a } from "../popup/client.mjs";
6
- import { positioner as o } from "./Menu.css.mjs";
7
- import { jsx as s } from "react/jsx-runtime";
8
- import { createContext as c, use as l, useCallback as u, useLayoutEffect as d, useRef as f } from "react";
9
- import { Menu as p } from "@base-ui/react/menu";
5
+ import { PopupScope as r, triggerElement as i, useClosingRule as a, usePopupScope as o, useRecordOpenChange as s } from "../popup/client.mjs";
6
+ import { positioner as c } from "./Menu.css.mjs";
7
+ import { jsx as l } from "react/jsx-runtime";
8
+ import { Menu as u } from "@base-ui/react/menu";
10
9
  //#region src/Menu/client.tsx
11
- function m({ disabled: e = !1, openOnHover: t, delay: n, closeDelay: r, handle: o, payload: c, ...l }) {
12
- let { ref: u } = a();
13
- return /* @__PURE__ */ s(p.Trigger, {
10
+ function d({ disabled: e = !1, openOnHover: t, delay: n, closeDelay: r, handle: a, payload: s, ...c }) {
11
+ let { ref: d } = o();
12
+ return /* @__PURE__ */ l(u.Trigger, {
14
13
  disabled: e,
15
14
  openOnHover: t,
16
15
  delay: n,
17
16
  closeDelay: r,
18
- handle: o,
19
- payload: c,
20
- ref: u,
21
- render: i(l)
17
+ handle: a,
18
+ payload: s,
19
+ ref: d,
20
+ render: i(c)
22
21
  });
23
22
  }
24
- function h({ children: e }) {
25
- let { container: t } = a();
26
- return /* @__PURE__ */ s(p.Portal, {
23
+ function f({ children: e }) {
24
+ let { container: t } = o();
25
+ return /* @__PURE__ */ l(u.Portal, {
27
26
  container: t,
28
27
  children: e
29
28
  });
30
29
  }
31
- var g = c({ current: {
32
- keyboard: !1,
33
- opener: null
34
- } });
35
- function _({ onOpenChange: e, ...t }) {
36
- let n = f({
37
- keyboard: !1,
38
- opener: null
30
+ function p(e) {
31
+ return /* @__PURE__ */ l(r, { children: /* @__PURE__ */ l(m, { ...e }) });
32
+ }
33
+ function m({ onOpenChange: e, ...t }) {
34
+ return /* @__PURE__ */ l(u.Root, {
35
+ ...t,
36
+ onOpenChange: s(e)
39
37
  });
40
- return /* @__PURE__ */ s(r, { children: /* @__PURE__ */ s(g, {
41
- value: n,
42
- children: /* @__PURE__ */ s(p.Root, {
43
- ...t,
44
- onOpenChange: (t, r) => {
45
- n.current = t ? {
46
- keyboard: !1,
47
- opener: r.trigger ?? null
48
- } : {
49
- ...n.current,
50
- keyboard: r.event instanceof KeyboardEvent,
51
- reason: r.reason
52
- }, e?.(t, r);
53
- }
54
- })
55
- }) });
56
38
  }
57
- function v({ finalFocus: e, ...n }) {
58
- return /* @__PURE__ */ s(p.Positioner, {
39
+ function h({ finalFocus: e, ...n }) {
40
+ return /* @__PURE__ */ l(u.Positioner, {
59
41
  ...n,
60
42
  collisionPadding: 8,
61
43
  render: (n, { open: r }) => {
62
44
  let [, i] = t(n);
63
- return /* @__PURE__ */ s(b, {
45
+ return /* @__PURE__ */ l(g, {
64
46
  ...i,
65
47
  finalFocus: e,
66
48
  open: r
@@ -69,44 +51,16 @@ function v({ finalFocus: e, ...n }) {
69
51
  sideOffset: 4
70
52
  });
71
53
  }
72
- var y = /* @__PURE__ */ new Set([
73
- "trigger-hover",
74
- "focus-out",
75
- "outside-press"
76
- ]);
77
- function b({ open: t, finalFocus: r, ref: i, className: c, ...p }) {
78
- let { trigger: m } = a(), h = l(g), _ = f(null), v = u((e) => {
79
- _.current = e;
80
- let t = typeof i == "function" ? i(e) : void 0;
81
- return i && typeof i != "function" && (i.current = e), () => {
82
- _.current = null, typeof t == "function" ? t() : typeof i == "function" ? i(null) : i && (i.current = null);
83
- };
84
- }, [i]);
85
- return d(() => {
86
- let e = _.current;
87
- if (!e) return;
88
- if (t) {
89
- e.inert = !1;
90
- return;
91
- }
92
- let { reason: n, keyboard: i, opener: a } = h.current, o = a?.isConnected ? a : m.current;
93
- if (e.contains(e.ownerDocument.activeElement) && !r && !y.has(n ?? "") && o instanceof HTMLElement) {
94
- let e = { preventScroll: !0 };
95
- i && (e.focusVisible = !0), o.focus(e);
96
- }
97
- e.inert = !0;
98
- }, [
99
- t,
100
- r,
101
- h,
102
- m
103
- ]), /* @__PURE__ */ s(n, {
104
- ...p,
105
- "aria-hidden": !t || void 0,
106
- className: e(o, c),
107
- ref: v,
54
+ function g({ open: t, finalFocus: r, ref: i, className: o, ...s }) {
55
+ return /* @__PURE__ */ l(n, {
56
+ ...s,
57
+ ...a(i, {
58
+ finalFocus: r,
59
+ open: t
60
+ }),
61
+ className: e(c, o),
108
62
  zIndex: "popover"
109
63
  });
110
64
  }
111
65
  //#endregion
112
- export { h as MenuPortal, v as MenuPositioner, _ as MenuRootScope, m as MenuTrigger };
66
+ export { f as MenuPortal, h as MenuPositioner, p as MenuRootScope, d as MenuTrigger };
@@ -26,7 +26,7 @@ declare function MenuRoot(props: MenuProps): import("react").JSX.Element;
26
26
  declare function MenuPopup({ side, align, backgroundColor, borderRadius, boxShadow, padding, className, style, ...props }: MenuPopupProps): import("react").JSX.Element;
27
27
  declare function MenuItem({ variant, display, alignItems, gap, minBlockSize, paddingInline, borderRadius, color, className, style, children, ...props }: MenuItemProps): import("react").JSX.Element;
28
28
  declare function MenuLinkItem({ href, disabled, closeOnClick, onClick, display, alignItems, gap, minBlockSize, paddingInline, borderRadius, color, className, style, children, ...props }: MenuLinkItemProps): import("react").JSX.Element;
29
- declare function MenuSeparator({ marginBlock, marginInline, className, style, ...props }: MenuSeparatorProps): import("react").JSX.Element;
29
+ declare function MenuSeparator({ paddingBlock, paddingInline, className, style, ...props }: MenuSeparatorProps): import("react").JSX.Element;
30
30
  declare function MenuGroup({ label, className, style, children, ...props }: MenuGroupProps): import("react").JSX.Element;
31
31
  export declare const Menu: typeof MenuRoot & {
32
32
  Trigger: typeof MenuTrigger;
@@ -82,13 +82,13 @@ function b({ href: r, disabled: o = !1, closeOnClick: s = !0, onClick: c, displa
82
82
  children: v(x)
83
83
  });
84
84
  }
85
- function x({ marginBlock: r = "4", marginInline: i = "8", className: a, style: o, ...c }) {
85
+ function x({ paddingBlock: r = "4", paddingInline: i = "8", className: a, style: o, ...c }) {
86
86
  let [l, u] = t(c);
87
87
  return /* @__PURE__ */ f(h.Separator, {
88
88
  ...u,
89
89
  render: /* @__PURE__ */ f(n, {
90
- marginBlock: r,
91
- marginInline: i,
90
+ paddingBlock: r,
91
+ paddingInline: i,
92
92
  ...l,
93
93
  className: e(s, a),
94
94
  style: o
package/dist/docs/Icon.md CHANGED
@@ -88,9 +88,12 @@ Generated from `src/icons/svg/` and exported from `@jonmilner/ui/icons`; each ta
88
88
  - `InboxIcon` (`inbox.svg`)
89
89
  - `InfoIcon` (`info.svg`)
90
90
  - `LoaderCircleIcon` (`loader-circle.svg`)
91
+ - `PencilIcon` (`pencil.svg`)
92
+ - `PlusIcon` (`plus.svg`)
91
93
  - `RefreshCwIcon` (`refresh-cw.svg`)
92
94
  - `SearchIcon` (`search.svg`)
93
95
  - `SettingsIcon` (`settings.svg`)
96
+ - `Trash2Icon` (`trash-2.svg`)
94
97
  - `XIcon` (`x.svg`)
95
98
 
96
99
  <!-- icons:end -->
package/dist/docs/Menu.md CHANGED
@@ -27,6 +27,7 @@ A list of actions that opens from a button: a row's "Edit, Duplicate, Delete", a
27
27
  - `variant="danger"` marks a destructive item. It still runs on one click, so open a confirm dialog from it (Cancel focused first) before anything irreversible happens.
28
28
  - `disabled` on an item renders `aria-disabled`: it stays announced and reachable with the arrow keys, and does nothing. A disabled `Menu.LinkItem` also drops its `href`, so no click or context menu reaches the URL. On the trigger it keeps the button focusable and stops it opening.
29
29
  - `Menu.Group` takes a `label` that is shown and names the group. Separate groups with `Menu.Separator`.
30
+ - `Menu.Separator` draws a line inside its own padding (`paddingBlock="4"`, `paddingInline="8"`) and sets no margin. Change its spacing with `paddingBlock` and `paddingInline` (the `padding` shorthand loses to these defaults, decision 0065); a `margin*` prop adds space outside the padding. `style={{ borderBlockStartColor }}` recolours the line.
30
31
  - The popup portals into the trigger's nearest `ThemeProvider`, so it keeps the brand and mode. That provider must not clip or stack its content: wrap the app root, and keep a nested provider off elements with `overflow: hidden`, a `transform` or their own `z-index`, or the popup is clipped or drawn under siblings. It sits on `zIndex` `popover`. A menu opened only through `open`, with no `Menu.Trigger`, has no provider to find and portals to `<body>`.
31
32
  - Item and link item text is wrapped in `Text` for you; an `Icon` beside it is spaced by the item's `gap`.
32
33
  - `side` (`bottom` by default) and `align` (`start`) place the popup against the trigger; it flips when it would overflow the viewport.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "./manifest.schema.json",
3
3
  "package": "@jonmilner/ui",
4
- "version": "0.4.3",
4
+ "version": "0.5.0",
5
5
  "components": [
6
6
  {
7
7
  "name": "AlertDialog",
@@ -2759,9 +2759,12 @@
2759
2759
  "InboxIcon",
2760
2760
  "InfoIcon",
2761
2761
  "LoaderCircleIcon",
2762
+ "PencilIcon",
2763
+ "PlusIcon",
2762
2764
  "RefreshCwIcon",
2763
2765
  "SearchIcon",
2764
2766
  "SettingsIcon",
2767
+ "Trash2Icon",
2765
2768
  "XIcon"
2766
2769
  ],
2767
2770
  "tokens": {
@@ -0,0 +1,29 @@
1
+ # 0.5.0
2
+
3
+ `Menu.Separator` drops its default `marginBlock="4"` and `marginInline="8"` for the same spacing as padding inside it, with its line drawn within, because a component never puts margin on its root (decision 0095); a bare separator looks the same, but a `margin*` prop you pass now adds outside the padding instead of replacing the old margin.
4
+
5
+ ## Find
6
+
7
+ In the app's source (`*.tsx`), every `Menu.Separator` that passes any prop: regex `<Menu\.Separator\s+[^/>\s]` searched multiline (`rg -U`), since a long tag's props sit on their own lines. A bare `<Menu.Separator />` needs nothing. Check each match for `margin*` and `padding*` props and for a `className` or `style` that sets margin, padding or the line's border. A match with props spread from elsewhere (`<Menu.Separator {...props} />`) needs a read of where they come from.
8
+
9
+ ## Replace
10
+
11
+ Move the spacing to the matching `paddingBlock` or `paddingInline` prop, so it replaces the default instead of adding to it. A margin the default padding already covers can go. The `padding` shorthand loses to those two defaults (decision 0065), so use the longhands. A `padding*` prop you already passed used to sit inside the default margin; it now replaces that spacing, so add the old 4px block or 8px inline to it to keep the gap.
12
+
13
+ ```tsx
14
+ // before: 8px above and below, 8px inset
15
+ <Menu.Separator marginBlock="8" />
16
+ // after
17
+ <Menu.Separator paddingBlock="8" />
18
+
19
+ // before: a full-width line
20
+ <Menu.Separator marginInline="0" />
21
+ // after
22
+ <Menu.Separator paddingInline="0" />
23
+ ```
24
+
25
+ A `className` that set `margin` on the separator moves to `padding` the same way. The line is now the separator's `::before`, not a border on its root, so a `className` that restyled the line's width or style targets `::before` instead (`.myDivider::before { border-block-start-width: 2px }`). Its colour still comes from the root: `className` or `style` setting `borderBlockStartColor` on the separator recolours the line; one that sets a border style on the root draws a second line, so drop it.
26
+
27
+ ## Verify
28
+
29
+ Run `rg -U '<Menu\.Separator\s+[^/>\s]' --glob '*.tsx'` again: no match passes a `margin*` prop, a `padding` shorthand, or a `className` or `style` that sets a border style on the root, except margin you meant to add outside the divider. Then open a menu with a separator: the line keeps the spacing it had before the upgrade.
@@ -0,0 +1,4 @@
1
+ import { IconProps } from "../Icon/index.mjs";
2
+ //#region src/icons/PencilIcon.d.ts
3
+ export declare function PencilIcon(props: Omit<IconProps, "children" | "viewBox">): import("react").JSX.Element;
4
+ //#endregion
@@ -0,0 +1,11 @@
1
+ import { Icon as e } from "../Icon/index.mjs";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/icons/PencilIcon.tsx
4
+ function n(n) {
5
+ return /* @__PURE__ */ t(e, {
6
+ ...n,
7
+ children: /* @__PURE__ */ t("path", { d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497zM15 5l4 4" })
8
+ });
9
+ }
10
+ //#endregion
11
+ export { n as PencilIcon };
@@ -0,0 +1,4 @@
1
+ import { IconProps } from "../Icon/index.mjs";
2
+ //#region src/icons/PlusIcon.d.ts
3
+ export declare function PlusIcon(props: Omit<IconProps, "children" | "viewBox">): import("react").JSX.Element;
4
+ //#endregion
@@ -0,0 +1,11 @@
1
+ import { Icon as e } from "../Icon/index.mjs";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/icons/PlusIcon.tsx
4
+ function n(n) {
5
+ return /* @__PURE__ */ t(e, {
6
+ ...n,
7
+ children: /* @__PURE__ */ t("path", { d: "M5 12h14M12 5v14" })
8
+ });
9
+ }
10
+ //#endregion
11
+ export { n as PlusIcon };
@@ -0,0 +1,4 @@
1
+ import { IconProps } from "../Icon/index.mjs";
2
+ //#region src/icons/Trash2Icon.d.ts
3
+ export declare function Trash2Icon(props: Omit<IconProps, "children" | "viewBox">): import("react").JSX.Element;
4
+ //#endregion
@@ -0,0 +1,11 @@
1
+ import { Icon as e } from "../Icon/index.mjs";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/icons/Trash2Icon.tsx
4
+ function n(n) {
5
+ return /* @__PURE__ */ t(e, {
6
+ ...n,
7
+ children: /* @__PURE__ */ t("path", { d: "M10 11v6M14 11v6M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
8
+ });
9
+ }
10
+ //#endregion
11
+ export { n as Trash2Icon };
@@ -14,12 +14,15 @@ import { GitPullRequestDraftIcon } from "./GitPullRequestDraftIcon.mjs";
14
14
  import { GitPullRequestIcon } from "./GitPullRequestIcon.mjs";
15
15
  import { InboxIcon } from "./InboxIcon.mjs";
16
16
  import { LoaderCircleIcon } from "./LoaderCircleIcon.mjs";
17
+ import { PencilIcon } from "./PencilIcon.mjs";
18
+ import { PlusIcon } from "./PlusIcon.mjs";
17
19
  import { RefreshCwIcon } from "./RefreshCwIcon.mjs";
18
20
  import { SearchIcon } from "./SearchIcon.mjs";
19
21
  import { SettingsIcon } from "./SettingsIcon.mjs";
22
+ import { Trash2Icon } from "./Trash2Icon.mjs";
20
23
  import { XIcon } from "./XIcon.mjs";
21
24
  //#region src/icons/index.d.ts
22
- export declare const iconNames: readonly ["ArrowLeftIcon", "ArrowRightIcon", "CheckIcon", "ChevronDownIcon", "ChevronRightIcon", "CircleAlertIcon", "CircleCheckIcon", "CircleDotIcon", "CircleSlashIcon", "GitMergeIcon", "GitPullRequestClosedIcon", "GitPullRequestDraftIcon", "GitPullRequestIcon", "InboxIcon", "InfoIcon", "LoaderCircleIcon", "RefreshCwIcon", "SearchIcon", "SettingsIcon", "XIcon"];
25
+ export declare const iconNames: readonly ["ArrowLeftIcon", "ArrowRightIcon", "CheckIcon", "ChevronDownIcon", "ChevronRightIcon", "CircleAlertIcon", "CircleCheckIcon", "CircleDotIcon", "CircleSlashIcon", "GitMergeIcon", "GitPullRequestClosedIcon", "GitPullRequestDraftIcon", "GitPullRequestIcon", "InboxIcon", "InfoIcon", "LoaderCircleIcon", "PencilIcon", "PlusIcon", "RefreshCwIcon", "SearchIcon", "SettingsIcon", "Trash2Icon", "XIcon"];
23
26
  export type IconName = (typeof iconNames)[number];
24
27
  //#endregion
25
- export { ArrowLeftIcon, ArrowRightIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, CircleAlertIcon, CircleCheckIcon, CircleDotIcon, CircleSlashIcon, GitMergeIcon, GitPullRequestClosedIcon, GitPullRequestDraftIcon, GitPullRequestIcon, InboxIcon, InfoIcon, LoaderCircleIcon, RefreshCwIcon, SearchIcon, SettingsIcon, XIcon };
28
+ export { ArrowLeftIcon, ArrowRightIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, CircleAlertIcon, CircleCheckIcon, CircleDotIcon, CircleSlashIcon, GitMergeIcon, GitPullRequestClosedIcon, GitPullRequestDraftIcon, GitPullRequestIcon, InboxIcon, InfoIcon, LoaderCircleIcon, PencilIcon, PlusIcon, RefreshCwIcon, SearchIcon, SettingsIcon, Trash2Icon, XIcon };
@@ -16,10 +16,13 @@ import { GitPullRequestDraftIcon as m } from "./GitPullRequestDraftIcon.mjs";
16
16
  import { GitPullRequestIcon as h } from "./GitPullRequestIcon.mjs";
17
17
  import { InboxIcon as g } from "./InboxIcon.mjs";
18
18
  import { LoaderCircleIcon as _ } from "./LoaderCircleIcon.mjs";
19
- import { RefreshCwIcon as v } from "./RefreshCwIcon.mjs";
20
- import { SettingsIcon as y } from "./SettingsIcon.mjs";
19
+ import { PencilIcon as v } from "./PencilIcon.mjs";
20
+ import { PlusIcon as y } from "./PlusIcon.mjs";
21
+ import { RefreshCwIcon as b } from "./RefreshCwIcon.mjs";
22
+ import { SettingsIcon as x } from "./SettingsIcon.mjs";
23
+ import { Trash2Icon as S } from "./Trash2Icon.mjs";
21
24
  //#region src/icons/index.ts
22
- var b = [
25
+ var C = [
23
26
  "ArrowLeftIcon",
24
27
  "ArrowRightIcon",
25
28
  "CheckIcon",
@@ -36,10 +39,13 @@ var b = [
36
39
  "InboxIcon",
37
40
  "InfoIcon",
38
41
  "LoaderCircleIcon",
42
+ "PencilIcon",
43
+ "PlusIcon",
39
44
  "RefreshCwIcon",
40
45
  "SearchIcon",
41
46
  "SettingsIcon",
47
+ "Trash2Icon",
42
48
  "XIcon"
43
49
  ];
44
50
  //#endregion
45
- export { s as ArrowLeftIcon, c as ArrowRightIcon, e as CheckIcon, n as ChevronDownIcon, l as ChevronRightIcon, t as CircleAlertIcon, a as CircleCheckIcon, u as CircleDotIcon, d as CircleSlashIcon, f as GitMergeIcon, p as GitPullRequestClosedIcon, m as GitPullRequestDraftIcon, h as GitPullRequestIcon, g as InboxIcon, o as InfoIcon, _ as LoaderCircleIcon, v as RefreshCwIcon, r as SearchIcon, y as SettingsIcon, i as XIcon, b as iconNames };
51
+ export { s as ArrowLeftIcon, c as ArrowRightIcon, e as CheckIcon, n as ChevronDownIcon, l as ChevronRightIcon, t as CircleAlertIcon, a as CircleCheckIcon, u as CircleDotIcon, d as CircleSlashIcon, f as GitMergeIcon, p as GitPullRequestClosedIcon, m as GitPullRequestDraftIcon, h as GitPullRequestIcon, g as InboxIcon, o as InfoIcon, _ as LoaderCircleIcon, v as PencilIcon, y as PlusIcon, b as RefreshCwIcon, r as SearchIcon, x as SettingsIcon, S as Trash2Icon, i as XIcon, C as iconNames };
@@ -3,23 +3,33 @@ import { Clickable as e } from "../Clickable/index.mjs";
3
3
  import { Button as t } from "../Button/index.mjs";
4
4
  import { useThemeContainer as n } from "../theme/use-theme-container.mjs";
5
5
  import { jsx as r } from "react/jsx-runtime";
6
- import { createContext as i, use as a } from "react";
6
+ import { createContext as i, use as a, useCallback as o, useLayoutEffect as s, useRef as c } from "react";
7
7
  //#region src/popup/client.tsx
8
- var o = i({
8
+ var l = i({
9
9
  container: { current: null },
10
10
  ref: () => {},
11
11
  trigger: { current: null }
12
- });
13
- function s({ children: e }) {
14
- return /* @__PURE__ */ r(o, {
12
+ }), u = i({ current: {
13
+ keyboard: !1,
14
+ opener: null
15
+ } });
16
+ function d({ children: e }) {
17
+ let t = c({
18
+ keyboard: !1,
19
+ opener: null
20
+ });
21
+ return /* @__PURE__ */ r(l, {
15
22
  value: n(),
16
- children: e
23
+ children: /* @__PURE__ */ r(u, {
24
+ value: t,
25
+ children: e
26
+ })
17
27
  });
18
28
  }
19
- function c() {
20
- return a(o);
29
+ function f() {
30
+ return a(l);
21
31
  }
22
- function l({ variant: n, size: i, iconStart: a, iconEnd: o, ...s }) {
32
+ function p({ variant: n, size: i, iconStart: a, iconEnd: o, ...s }) {
23
33
  return n || i || a || o ? /* @__PURE__ */ r(t, {
24
34
  ...s,
25
35
  variant: n,
@@ -28,5 +38,63 @@ function l({ variant: n, size: i, iconStart: a, iconEnd: o, ...s }) {
28
38
  iconEnd: o
29
39
  }) : /* @__PURE__ */ r(e, { ...s });
30
40
  }
41
+ function m(e) {
42
+ let t = a(u);
43
+ return (n, r) => {
44
+ t.current = n ? {
45
+ keyboard: !1,
46
+ opener: r.trigger ?? null
47
+ } : {
48
+ ...t.current,
49
+ keyboard: r.event instanceof KeyboardEvent,
50
+ reason: r.reason
51
+ }, e?.(n, r);
52
+ };
53
+ }
54
+ function h(e, t) {
55
+ if (typeof e == "function") {
56
+ let n = e(t);
57
+ return typeof n == "function" ? n : () => e(null);
58
+ }
59
+ return e && (e.current = t), () => {
60
+ e && (e.current = null);
61
+ };
62
+ }
63
+ var g = /* @__PURE__ */ new Set([
64
+ "trigger-hover",
65
+ "focus-out",
66
+ "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;
71
+ let n = h(e, t);
72
+ return () => {
73
+ l.current = null, n();
74
+ };
75
+ }, [e]);
76
+ return s(() => {
77
+ let e = l.current;
78
+ if (!e) return;
79
+ if (n) {
80
+ e.inert = !1;
81
+ return;
82
+ }
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) {
85
+ let e = { preventScroll: !0 };
86
+ o && (e.focusVisible = !0), c.focus(e);
87
+ }
88
+ e.inert = !0;
89
+ }, [
90
+ n,
91
+ t,
92
+ i,
93
+ r
94
+ ]), {
95
+ "aria-hidden": !n || void 0,
96
+ ref: d
97
+ };
98
+ }
31
99
  //#endregion
32
- export { s as PopupScope, l as triggerElement, c as usePopupScope };
100
+ export { d as PopupScope, p as triggerElement, _ 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.4.3",
3
+ "version": "0.5.0",
4
4
  "files": [
5
5
  "dist",
6
6
  "THIRD_PARTY_NOTICES.md"