@jonmilner/ui 0.4.4 → 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.
- package/dist/Menu/Menu.css +1 -1
- package/dist/Menu/client.mjs +33 -79
- package/dist/Menu/index.d.mts +1 -1
- package/dist/Menu/index.mjs +3 -3
- package/dist/docs/Menu.md +1 -0
- package/dist/docs/manifest.json +1 -1
- package/dist/docs/migrations/0.5.0.md +29 -0
- package/dist/popup/client.mjs +78 -10
- package/package.json +1 -1
package/dist/Menu/Menu.css
CHANGED
|
@@ -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
|
|
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}}}
|
package/dist/Menu/client.mjs
CHANGED
|
@@ -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,
|
|
6
|
-
import { positioner as
|
|
7
|
-
import { jsx as
|
|
8
|
-
import {
|
|
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
|
|
12
|
-
let { ref:
|
|
13
|
-
return /* @__PURE__ */
|
|
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:
|
|
19
|
-
payload:
|
|
20
|
-
ref:
|
|
21
|
-
render: i(
|
|
17
|
+
handle: a,
|
|
18
|
+
payload: s,
|
|
19
|
+
ref: d,
|
|
20
|
+
render: i(c)
|
|
22
21
|
});
|
|
23
22
|
}
|
|
24
|
-
function
|
|
25
|
-
let { container: t } =
|
|
26
|
-
return /* @__PURE__ */
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
58
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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 {
|
|
66
|
+
export { f as MenuPortal, h as MenuPositioner, p as MenuRootScope, d as MenuTrigger };
|
package/dist/Menu/index.d.mts
CHANGED
|
@@ -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({
|
|
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;
|
package/dist/Menu/index.mjs
CHANGED
|
@@ -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({
|
|
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
|
-
|
|
91
|
-
|
|
90
|
+
paddingBlock: r,
|
|
91
|
+
paddingInline: i,
|
|
92
92
|
...l,
|
|
93
93
|
className: e(s, a),
|
|
94
94
|
style: o
|
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.
|
package/dist/docs/manifest.json
CHANGED
|
@@ -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.
|
package/dist/popup/client.mjs
CHANGED
|
@@ -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
|
|
8
|
+
var l = i({
|
|
9
9
|
container: { current: null },
|
|
10
10
|
ref: () => {},
|
|
11
11
|
trigger: { current: null }
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
|
|
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:
|
|
23
|
+
children: /* @__PURE__ */ r(u, {
|
|
24
|
+
value: t,
|
|
25
|
+
children: e
|
|
26
|
+
})
|
|
17
27
|
});
|
|
18
28
|
}
|
|
19
|
-
function
|
|
20
|
-
return a(
|
|
29
|
+
function f() {
|
|
30
|
+
return a(l);
|
|
21
31
|
}
|
|
22
|
-
function
|
|
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 {
|
|
100
|
+
export { d as PopupScope, p as triggerElement, _ as useClosingRule, f as usePopupScope, m as useRecordOpenChange };
|