@box-kite/react 0.0.1 → 2.0.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/.claude/rules/box-kite-rules.md +65 -0
- package/.claude/skills/box-kite/SKILL.md +138 -0
- package/.claude/skills/box-kite/references/components.md +235 -0
- package/.claude/skills/box-kite/references/extending.md +42 -0
- package/.claude/skills/box-kite/references/patterns.md +27 -0
- package/.claude/skills/box-kite/references/styling.md +222 -0
- package/.cursor/rules/box-kite.mdc +73 -0
- package/AGENTS.md +102 -0
- package/BOX_AI_CONTEXT.md +2804 -0
- package/BOX_KITE_AI_CONTEXT.md +2804 -0
- package/LICENSE +21 -0
- package/README.md +744 -7
- package/a11y.cjs +1 -0
- package/a11y.d.ts +15 -0
- package/a11y.mjs +4 -0
- package/anchor.cjs +1 -0
- package/anchor.d.ts +14 -0
- package/anchor.mjs +3 -0
- package/behavior.cjs +1 -0
- package/behavior.mjs +277 -0
- package/box.cjs +1 -0
- package/box.d.ts +46 -0
- package/box.mjs +23 -0
- package/client.cjs +1 -0
- package/client.mjs +164 -0
- package/components/accordion.cjs +1 -0
- package/components/accordion.d.ts +114 -0
- package/components/accordion.mjs +251 -0
- package/components/baseSvg.cjs +1 -0
- package/components/baseSvg.d.ts +5 -0
- package/components/baseSvg.mjs +21 -0
- package/components/button.cjs +1 -0
- package/components/button.d.ts +19 -0
- package/components/button.mjs +19 -0
- package/components/chart.cjs +1 -0
- package/components/chart.d.ts +83 -0
- package/components/chart.mjs +236 -0
- package/components/checkbox.cjs +1 -0
- package/components/checkbox.d.ts +36 -0
- package/components/checkbox.mjs +38 -0
- package/components/combobox/comboboxChips.d.ts +21 -0
- package/components/combobox/comboboxListbox.d.ts +47 -0
- package/components/combobox.cjs +1 -0
- package/components/combobox.d.ts +121 -0
- package/components/combobox.mjs +563 -0
- package/components/dataGrid/components/dataGridAggregateValue.d.ts +10 -0
- package/components/dataGrid/components/dataGridBody.d.ts +7 -0
- package/components/dataGrid/components/dataGridBottomBar.d.ts +6 -0
- package/components/dataGrid/components/dataGridCell.d.ts +16 -0
- package/components/dataGrid/components/dataGridCellEditor.d.ts +15 -0
- package/components/dataGrid/components/dataGridCellPlaceholder.d.ts +14 -0
- package/components/dataGrid/components/dataGridCellRowDetail.d.ts +6 -0
- package/components/dataGrid/components/dataGridCellRowSelection.d.ts +6 -0
- package/components/dataGrid/components/dataGridCellText.d.ts +6 -0
- package/components/dataGrid/components/dataGridCellTree.d.ts +16 -0
- package/components/dataGrid/components/dataGridColumnFilter.d.ts +9 -0
- package/components/dataGrid/components/dataGridColumnGroups.d.ts +7 -0
- package/components/dataGrid/components/dataGridContent.d.ts +6 -0
- package/components/dataGrid/components/dataGridDataSourceError.d.ts +12 -0
- package/components/dataGrid/components/dataGridDetailRow.d.ts +8 -0
- package/components/dataGrid/components/dataGridEmptyColumns.d.ts +6 -0
- package/components/dataGrid/components/dataGridExport.d.ts +10 -0
- package/components/dataGrid/components/dataGridFilterCell.d.ts +11 -0
- package/components/dataGrid/components/dataGridFilterRow.d.ts +6 -0
- package/components/dataGrid/components/dataGridFooter.d.ts +11 -0
- package/components/dataGrid/components/dataGridGlobalFilter.d.ts +6 -0
- package/components/dataGrid/components/dataGridGroupRow.d.ts +8 -0
- package/components/dataGrid/components/dataGridHeader.d.ts +6 -0
- package/components/dataGrid/components/dataGridHeaderCell.d.ts +9 -0
- package/components/dataGrid/components/dataGridHeaderCellContextMenu.d.ts +11 -0
- package/components/dataGrid/components/dataGridHeaderCellResizer.d.ts +14 -0
- package/components/dataGrid/components/dataGridLoader.d.ts +11 -0
- package/components/dataGrid/components/dataGridPagination.d.ts +6 -0
- package/components/dataGrid/components/dataGridRow.d.ts +8 -0
- package/components/dataGrid/components/dataGridTopBar.d.ts +6 -0
- package/components/dataGrid/components/dataGridTopBarContextMenu.d.ts +6 -0
- package/components/dataGrid/contracts/dataGridContract.d.ts +671 -0
- package/components/dataGrid/export/gridExport.d.ts +10 -0
- package/components/dataGrid/gridNavigationContext.d.ts +32 -0
- package/components/dataGrid/models/aggregateCellModel.d.ts +34 -0
- package/components/dataGrid/models/aggregationModel.d.ts +32 -0
- package/components/dataGrid/models/cellKeys.d.ts +11 -0
- package/components/dataGrid/models/cellModel.d.ts +44 -0
- package/components/dataGrid/models/columnModel.d.ts +160 -0
- package/components/dataGrid/models/columnVisibilityModel.d.ts +24 -0
- package/components/dataGrid/models/dataSourceModel.d.ts +177 -0
- package/components/dataGrid/models/detailRowModel.d.ts +22 -0
- package/components/dataGrid/models/editModel.d.ts +77 -0
- package/components/dataGrid/models/exportModel.d.ts +51 -0
- package/components/dataGrid/models/filterModel.d.ts +22 -0
- package/components/dataGrid/models/gridModel.d.ts +293 -0
- package/components/dataGrid/models/groupRowCellModel.d.ts +34 -0
- package/components/dataGrid/models/groupRowModel.d.ts +68 -0
- package/components/dataGrid/models/headerCellModel.d.ts +83 -0
- package/components/dataGrid/models/paginationModel.d.ts +32 -0
- package/components/dataGrid/models/rowModel.d.ts +46 -0
- package/components/dataGrid/models/sourceGroupRowModel.d.ts +45 -0
- package/components/dataGrid/models/sourceLevel.d.ts +71 -0
- package/components/dataGrid/models/sourceRowModel.d.ts +29 -0
- package/components/dataGrid/models/sourceTreeRowModel.d.ts +23 -0
- package/components/dataGrid/models/treeModel.d.ts +94 -0
- package/components/dataGrid/models/treeRow.d.ts +22 -0
- package/components/dataGrid/models/treeRowModel.d.ts +50 -0
- package/components/dataGrid/models/viewportModel.d.ts +44 -0
- package/components/dataGrid/useGrid.d.ts +8 -0
- package/components/dataGrid/useGridNavigation.d.ts +21 -0
- package/components/dataGrid.cjs +1 -0
- package/components/dataGrid.d.ts +4 -0
- package/components/dataGrid.mjs +4907 -0
- package/components/dialog.cjs +1 -0
- package/components/dialog.d.ts +151 -0
- package/components/dialog.mjs +223 -0
- package/components/dropdown/dropdownContext.d.ts +44 -0
- package/components/dropdown/dropdownItems.d.ts +22 -0
- package/components/dropdown/dropdownRowRenderer.d.ts +8 -0
- package/components/dropdown/dropdownSearch.d.ts +21 -0
- package/components/dropdown/utils.d.ts +1 -0
- package/components/dropdown.cjs +1 -0
- package/components/dropdown.d.ts +77 -0
- package/components/dropdown.mjs +491 -0
- package/components/flex.cjs +1 -0
- package/components/flex.d.ts +6 -0
- package/components/flex.mjs +16 -0
- package/components/form.cjs +1 -0
- package/components/form.d.ts +10 -0
- package/components/form.mjs +58 -0
- package/components/grid.cjs +1 -0
- package/components/grid.d.ts +6 -0
- package/components/grid.mjs +16 -0
- package/components/icon.cjs +1 -0
- package/components/icon.d.ts +37 -0
- package/components/icon.mjs +41 -0
- package/components/menu.cjs +1 -0
- package/components/menu.d.ts +234 -0
- package/components/menu.mjs +422 -0
- package/components/overlay.cjs +1 -0
- package/components/overlay.d.ts +47 -0
- package/components/overlay.mjs +52 -0
- package/components/popover.cjs +1 -0
- package/components/popover.d.ts +100 -0
- package/components/popover.mjs +69 -0
- package/components/presence.cjs +1 -0
- package/components/presence.d.ts +36 -0
- package/components/presence.mjs +11 -0
- package/components/progress.cjs +1 -0
- package/components/progress.d.ts +47 -0
- package/components/progress.mjs +28 -0
- package/components/radioButton.cjs +1 -0
- package/components/radioButton.d.ts +32 -0
- package/components/radioButton.mjs +32 -0
- package/components/radioGroup.cjs +1 -0
- package/components/radioGroup.d.ts +51 -0
- package/components/radioGroup.mjs +83 -0
- package/components/select.cjs +1 -0
- package/components/select.d.ts +51 -0
- package/components/select.mjs +36 -0
- package/components/semantics.cjs +1 -0
- package/components/semantics.d.ts +39 -0
- package/components/semantics.mjs +17 -0
- package/components/slider.cjs +1 -0
- package/components/slider.d.ts +98 -0
- package/components/slider.mjs +250 -0
- package/components/svg.cjs +1 -0
- package/components/svg.d.ts +65 -0
- package/components/svg.mjs +141 -0
- package/components/switch.cjs +1 -0
- package/components/switch.d.ts +29 -0
- package/components/switch.mjs +25 -0
- package/components/tabs.cjs +1 -0
- package/components/tabs.d.ts +87 -0
- package/components/tabs.mjs +324 -0
- package/components/textarea.cjs +1 -0
- package/components/textarea.d.ts +41 -0
- package/components/textarea.mjs +33 -0
- package/components/textbox.cjs +1 -0
- package/components/textbox.d.ts +38 -0
- package/components/textbox.mjs +33 -0
- package/components/toaster.cjs +1 -0
- package/components/toaster.d.ts +106 -0
- package/components/toaster.mjs +295 -0
- package/components/tooltip.cjs +1 -0
- package/components/tooltip.d.ts +98 -0
- package/components/tooltip.mjs +110 -0
- package/components/visuallyHidden.cjs +1 -0
- package/components/visuallyHidden.d.ts +6 -0
- package/components/visuallyHidden.mjs +23 -0
- package/docs/a11y.md +199 -0
- package/docs/anchor.md +139 -0
- package/docs/components.md +48 -0
- package/docs/index.md +11 -0
- package/docs/props.md +1777 -0
- package/effects.cjs +1 -0
- package/effects.mjs +6 -0
- package/forms.cjs +1 -0
- package/forms.mjs +21 -0
- package/gridExport.cjs +2 -0
- package/gridExport.mjs +244 -0
- package/icons/dotsIcon.d.ts +2 -0
- package/icons/expandIcon.d.ts +2 -0
- package/icons/groupingIcon.d.ts +2 -0
- package/icons/pinIcon.d.ts +2 -0
- package/icons/searchIcon.d.ts +2 -0
- package/icons/sortIcon.d.ts +2 -0
- package/identity.cjs +1 -0
- package/identity.mjs +12 -0
- package/keyboard.cjs +1 -0
- package/keyboard.mjs +30 -0
- package/layer.cjs +1 -0
- package/layer.mjs +127 -0
- package/motion.cjs +1 -0
- package/motion.mjs +66 -0
- package/package.json +327 -7
- package/placement.cjs +1 -0
- package/placement.mjs +180 -0
- package/platform.cjs +1 -0
- package/platform.mjs +45 -0
- package/react/a11y/callbacks.d.ts +12 -0
- package/react/a11y/useControllableState.d.ts +25 -0
- package/react/a11y/useDismiss.d.ts +25 -0
- package/react/a11y/useFocusReturn.d.ts +18 -0
- package/react/a11y/useRovingFocus.d.ts +84 -0
- package/react/anchor/useAnchorPosition.d.ts +79 -0
- package/react/animation/usePresence.d.ts +32 -0
- package/react/boxClassNames.d.ts +25 -0
- package/react/boxProps.d.ts +49 -0
- package/react/boxTagProps.d.ts +7 -0
- package/react/clientRuntime.d.ts +11 -0
- package/react/dialog/useScrollLock.d.ts +12 -0
- package/react/effects.d.ts +10 -0
- package/react/forms/labelledControl.d.ts +17 -0
- package/react/forms/placeholderProp.d.ts +13 -0
- package/react/hooks/usePortalContainer.d.ts +6 -0
- package/react/hooks/useVirtualization.d.ts +32 -0
- package/react/hooks/useVisibility.d.ts +9 -0
- package/react/identity/useIdentifier.d.ts +17 -0
- package/react/popover/usePopoverLayer.d.ts +87 -0
- package/react/reactTypes.d.ts +10 -0
- package/react/resolveStyles.d.ts +18 -0
- package/react/styleElements.d.ts +3 -0
- package/react/svg/attributesInProps.d.ts +4 -0
- package/react/svg/svgNaming.d.ts +15 -0
- package/react/theme/theme.d.ts +26 -0
- package/react/theme/themeContext.d.ts +7 -0
- package/react/useStyles.d.ts +22 -0
- package/react-shared.cjs +1 -0
- package/react-shared.mjs +122 -0
- package/rolldown-runtime.cjs +1 -0
- package/rsc.cjs +1 -0
- package/rsc.d.ts +27 -0
- package/rsc.mjs +18 -0
- package/ssg.cjs +1 -0
- package/ssg.d.ts +24 -0
- package/ssg.mjs +25 -0
- package/utils/accordion/accordionUtils.d.ts +48 -0
- package/utils/anchor/anchorUtils.d.ts +79 -0
- package/utils/animation/animationUtils.d.ts +29 -0
- package/utils/array/arrayUtils.d.ts +15 -0
- package/utils/array/lazyList.d.ts +10 -0
- package/utils/box/boxUtils.d.ts +5 -0
- package/utils/chart/chartPalette.d.ts +15 -0
- package/utils/chart/chartUtils.d.ts +92 -0
- package/utils/combobox/comboboxUtils.d.ts +89 -0
- package/utils/dom/domUtils.d.ts +32 -0
- package/utils/environment/environmentUtils.d.ts +28 -0
- package/utils/export/csvUtils.d.ts +23 -0
- package/utils/export/downloadUtils.d.ts +12 -0
- package/utils/export/xlsxUtils.d.ts +56 -0
- package/utils/export/zipUtils.d.ts +26 -0
- package/utils/fn/fnUtils.d.ts +4 -0
- package/utils/form/formUtils.d.ts +8 -0
- package/utils/keyboard/typeaheadUtils.d.ts +31 -0
- package/utils/memo.d.ts +10 -0
- package/utils/menu/menuUtils.d.ts +25 -0
- package/utils/object/objectUtils.d.ts +13 -0
- package/utils/slider/sliderUtils.d.ts +67 -0
- package/utils/string/fuzzySearch.d.ts +27 -0
- package/utils/string/stringUtils.d.ts +4 -0
- package/utils/tabs/tabsUtils.d.ts +75 -0
- package/utils/toast/toastStore.d.ts +73 -0
- package/utils/virtual/virtualUtils.d.ts +47 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { l as e, u as t } from "../platform.mjs";
|
|
3
|
+
import { n } from "../effects.mjs";
|
|
4
|
+
import r from "../box.mjs";
|
|
5
|
+
import { a as i, i as a } from "../behavior.mjs";
|
|
6
|
+
import { t as o } from "../identity.mjs";
|
|
7
|
+
import { t as s } from "../keyboard.mjs";
|
|
8
|
+
import { t as c } from "../placement.mjs";
|
|
9
|
+
import l from "./overlay.mjs";
|
|
10
|
+
import { t as u } from "../layer.mjs";
|
|
11
|
+
import { createContext as d, useCallback as f, useContext as p, useMemo as m, useRef as h, useState as g } from "react";
|
|
12
|
+
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
13
|
+
//#region src/utils/menu/menuUtils.ts
|
|
14
|
+
var b;
|
|
15
|
+
(function(e) {
|
|
16
|
+
let t = e.ITEM_SELECTOR = "[role=\"menuitem\"],[role=\"menuitemcheckbox\"],[role=\"menuitemradio\"]";
|
|
17
|
+
function n(e, t) {
|
|
18
|
+
return t instanceof Element && t.closest("[role=\"menu\"]") === e;
|
|
19
|
+
}
|
|
20
|
+
e.owns = n;
|
|
21
|
+
function r(e) {
|
|
22
|
+
return [...e.querySelectorAll(t)].filter((t) => n(e, t));
|
|
23
|
+
}
|
|
24
|
+
e.items = r;
|
|
25
|
+
function i(e) {
|
|
26
|
+
return e.getAttribute("aria-disabled") === "true";
|
|
27
|
+
}
|
|
28
|
+
e.isDisabled = i;
|
|
29
|
+
function a(e) {
|
|
30
|
+
return e.getAttribute("aria-haspopup") === "menu";
|
|
31
|
+
}
|
|
32
|
+
e.isSubTrigger = a;
|
|
33
|
+
function o(e, t, n) {
|
|
34
|
+
if (e.length !== 0) return e[t < 0 ? n > 0 ? 0 : e.length - 1 : ((t + n) % e.length + e.length) % e.length];
|
|
35
|
+
}
|
|
36
|
+
e.step = o;
|
|
37
|
+
function c(e, t, n) {
|
|
38
|
+
let r = s.target(t, n, e.length, (t) => e[t].textContent ?? "");
|
|
39
|
+
return r < 0 ? void 0 : e[r];
|
|
40
|
+
}
|
|
41
|
+
e.typeaheadTarget = c;
|
|
42
|
+
})(b ||= {});
|
|
43
|
+
var x = b, S = d(null);
|
|
44
|
+
function C(e) {
|
|
45
|
+
let t = p(S);
|
|
46
|
+
if (!t) throw Error(`<${e}> must be rendered inside a <Menu>.`);
|
|
47
|
+
return t;
|
|
48
|
+
}
|
|
49
|
+
function w(e) {
|
|
50
|
+
let [t, n] = g([]);
|
|
51
|
+
return {
|
|
52
|
+
panels: t,
|
|
53
|
+
registerLayer: f((t) => {
|
|
54
|
+
n((e) => [...e, t]);
|
|
55
|
+
let r = e?.(t);
|
|
56
|
+
return () => {
|
|
57
|
+
n((e) => e.filter((e) => e !== t)), r?.();
|
|
58
|
+
};
|
|
59
|
+
}, [e])
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
var T = d(null);
|
|
63
|
+
function E(e) {
|
|
64
|
+
let { trigger: t, children: n, open: r, defaultOpen: a = !1, onOpenChange: o, label: s, labelledBy: c, side: l = "bottom", align: d = "start", offset: f = 1, flip: p = !0, matchWidth: g = !1, props: b, ...C } = e, T = h("first"), E = i((e) => {
|
|
65
|
+
let t = x.items(e), n = T.current === "last" ? t[t.length - 1] : t[0];
|
|
66
|
+
T.current = "first", (n ?? e).focus();
|
|
67
|
+
}), { panels: O, registerLayer: k } = w(), A = u({
|
|
68
|
+
haspopup: "menu",
|
|
69
|
+
idPrefix: "menu",
|
|
70
|
+
id: C.id,
|
|
71
|
+
open: r,
|
|
72
|
+
defaultOpen: a,
|
|
73
|
+
onOpenChange: o,
|
|
74
|
+
onOpened: E,
|
|
75
|
+
inside: O
|
|
76
|
+
}), j = i((e) => {
|
|
77
|
+
(e.key === "ArrowDown" || e.key === "ArrowUp") && (e.preventDefault(), T.current = e.key === "ArrowUp" ? "last" : "first", A.isOpen && A.panelElement ? E(A.panelElement) : A.setOpen(!0, {
|
|
78
|
+
reason: "trigger",
|
|
79
|
+
event: e
|
|
80
|
+
}));
|
|
81
|
+
}), M = m(() => ({
|
|
82
|
+
ref: A.trigger.ref,
|
|
83
|
+
props: {
|
|
84
|
+
...A.trigger.props,
|
|
85
|
+
onKeyDown: j
|
|
86
|
+
}
|
|
87
|
+
}), [j, A.trigger]), N = i((e) => A.setOpen(!1, e)), P = m(() => ({
|
|
88
|
+
open: A.isOpen,
|
|
89
|
+
closeAll: N,
|
|
90
|
+
registerLayer: k
|
|
91
|
+
}), [
|
|
92
|
+
N,
|
|
93
|
+
A.isOpen,
|
|
94
|
+
k
|
|
95
|
+
]);
|
|
96
|
+
return /* @__PURE__ */ y(_, { children: [t(M), /* @__PURE__ */ v(S.Provider, {
|
|
97
|
+
value: P,
|
|
98
|
+
children: /* @__PURE__ */ v(D, {
|
|
99
|
+
layer: A,
|
|
100
|
+
side: l,
|
|
101
|
+
align: d,
|
|
102
|
+
offset: f,
|
|
103
|
+
flip: p,
|
|
104
|
+
matchWidth: g,
|
|
105
|
+
label: s,
|
|
106
|
+
labelledBy: c ?? (s ? void 0 : A.triggerId),
|
|
107
|
+
contentProps: b,
|
|
108
|
+
...C,
|
|
109
|
+
children: n
|
|
110
|
+
})
|
|
111
|
+
})] });
|
|
112
|
+
}
|
|
113
|
+
function D(e) {
|
|
114
|
+
let { layer: n, side: a, align: o, offset: u, flip: d, matchWidth: f, label: p, labelledBy: m, contentProps: g, closeSelf: _, children: y, ...b } = e, { platform: S, isOpen: w, id: T, triggerElement: E, setPanel: D } = n, O = C("Menu"), k = h({
|
|
115
|
+
query: "",
|
|
116
|
+
at: 0
|
|
117
|
+
}), A = c({
|
|
118
|
+
side: a,
|
|
119
|
+
align: o,
|
|
120
|
+
offset: u,
|
|
121
|
+
flip: d,
|
|
122
|
+
matchWidth: f,
|
|
123
|
+
anchor: E
|
|
124
|
+
}), j = {
|
|
125
|
+
role: "menu",
|
|
126
|
+
"aria-label": p,
|
|
127
|
+
"aria-labelledby": m,
|
|
128
|
+
tabIndex: -1,
|
|
129
|
+
onKeyDown: i((e) => {
|
|
130
|
+
let n = e.currentTarget;
|
|
131
|
+
if (!x.owns(n, e.target)) return;
|
|
132
|
+
let r = x.items(n), i = r.indexOf(document.activeElement), a = (t) => {
|
|
133
|
+
t && (e.preventDefault(), t.focus());
|
|
134
|
+
}, o = t(n) ? "ArrowRight" : "ArrowLeft";
|
|
135
|
+
switch (e.key) {
|
|
136
|
+
case "ArrowDown": return a(x.step(r, i, 1));
|
|
137
|
+
case "ArrowUp": return a(x.step(r, i, -1));
|
|
138
|
+
case "Home": return a(r[0]);
|
|
139
|
+
case "End": return a(r[r.length - 1]);
|
|
140
|
+
case "Tab": return O.closeAll({
|
|
141
|
+
reason: "tab",
|
|
142
|
+
event: e
|
|
143
|
+
});
|
|
144
|
+
case o: return _ ? (e.preventDefault(), _({
|
|
145
|
+
reason: "trigger",
|
|
146
|
+
event: e
|
|
147
|
+
})) : void 0;
|
|
148
|
+
}
|
|
149
|
+
if (s.isPrintable(e)) {
|
|
150
|
+
let t = s.push(k.current, e.key, e.timeStamp);
|
|
151
|
+
a(x.typeaheadTarget(r, t, i));
|
|
152
|
+
}
|
|
153
|
+
}),
|
|
154
|
+
onPointerOver: i((e) => {
|
|
155
|
+
let t = e.currentTarget, n = e.target?.closest(x.ITEM_SELECTOR);
|
|
156
|
+
!n || !x.owns(t, n) || n === document.activeElement || n.focus();
|
|
157
|
+
}),
|
|
158
|
+
...g
|
|
159
|
+
};
|
|
160
|
+
return S ? /* @__PURE__ */ v(r, {
|
|
161
|
+
ref: D,
|
|
162
|
+
component: "menu",
|
|
163
|
+
...b,
|
|
164
|
+
variant: [b.variant, { topLayer: !0 }],
|
|
165
|
+
...A.layerProps,
|
|
166
|
+
id: T,
|
|
167
|
+
props: {
|
|
168
|
+
popover: "auto",
|
|
169
|
+
...j
|
|
170
|
+
},
|
|
171
|
+
children: y
|
|
172
|
+
}) : w ? /* @__PURE__ */ v(l, {
|
|
173
|
+
contentRef: D,
|
|
174
|
+
anchor: E,
|
|
175
|
+
side: a,
|
|
176
|
+
align: o,
|
|
177
|
+
offset: u,
|
|
178
|
+
flip: d,
|
|
179
|
+
matchWidth: f,
|
|
180
|
+
component: "menu",
|
|
181
|
+
...b,
|
|
182
|
+
id: T,
|
|
183
|
+
props: j,
|
|
184
|
+
children: y
|
|
185
|
+
}) : null;
|
|
186
|
+
}
|
|
187
|
+
function O(a) {
|
|
188
|
+
let { label: s, children: c, disabled: l, side: d = "end", align: f = "start", offset: p = 0, flip: h = !0, itemProps: g, props: b, ...T } = a, E = C("Menu.Sub"), O = o("menu-sub"), k = i((e) => {
|
|
189
|
+
(x.items(e)[0] ?? e).focus();
|
|
190
|
+
}), A = i((e, t) => {
|
|
191
|
+
e && t?.focus();
|
|
192
|
+
}), { panels: j, registerLayer: M } = w(E.registerLayer), N = u({
|
|
193
|
+
haspopup: "menu",
|
|
194
|
+
idPrefix: "menu-sub",
|
|
195
|
+
id: T.id,
|
|
196
|
+
onOpened: k,
|
|
197
|
+
onClosing: A,
|
|
198
|
+
inside: j
|
|
199
|
+
});
|
|
200
|
+
n(() => {
|
|
201
|
+
if (!(!N.isOpen || !N.panelElement)) return E.registerLayer(N.panelElement);
|
|
202
|
+
}, [
|
|
203
|
+
N.isOpen,
|
|
204
|
+
N.panelElement,
|
|
205
|
+
E.registerLayer
|
|
206
|
+
]), n(() => {
|
|
207
|
+
E.open || N.setOpen(!1, { reason: "imperative" });
|
|
208
|
+
}, [E.open, N.setOpen]), n(() => {
|
|
209
|
+
if (!N.isOpen) return;
|
|
210
|
+
let t = new AbortController();
|
|
211
|
+
return document.addEventListener("focusin", (t) => {
|
|
212
|
+
e(t, [N.panelElement, N.triggerElement]) || N.setOpen(!1, {
|
|
213
|
+
reason: "imperative",
|
|
214
|
+
event: t
|
|
215
|
+
});
|
|
216
|
+
}, { signal: t.signal }), () => t.abort();
|
|
217
|
+
}, [
|
|
218
|
+
N.isOpen,
|
|
219
|
+
N.panelElement,
|
|
220
|
+
N.triggerElement,
|
|
221
|
+
N.setOpen
|
|
222
|
+
]);
|
|
223
|
+
let P = i((e) => {
|
|
224
|
+
let n = t(e.currentTarget) ? "ArrowLeft" : "ArrowRight";
|
|
225
|
+
l || e.key !== n || (e.preventDefault(), N.setOpen(!0, {
|
|
226
|
+
reason: "trigger",
|
|
227
|
+
event: e
|
|
228
|
+
}));
|
|
229
|
+
}), F = i((e) => {
|
|
230
|
+
l || N.setOpen(!0, {
|
|
231
|
+
reason: "trigger",
|
|
232
|
+
event: e
|
|
233
|
+
});
|
|
234
|
+
}), I = m(() => ({
|
|
235
|
+
open: N.isOpen,
|
|
236
|
+
closeAll: E.closeAll,
|
|
237
|
+
registerLayer: M
|
|
238
|
+
}), [
|
|
239
|
+
N.isOpen,
|
|
240
|
+
E.closeAll,
|
|
241
|
+
M
|
|
242
|
+
]);
|
|
243
|
+
return /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ y(r, {
|
|
244
|
+
tag: "button",
|
|
245
|
+
ref: l ? void 0 : N.trigger.ref,
|
|
246
|
+
component: "menu.item",
|
|
247
|
+
variant: { sub: !0 },
|
|
248
|
+
id: O,
|
|
249
|
+
props: {
|
|
250
|
+
type: "button",
|
|
251
|
+
role: "menuitem",
|
|
252
|
+
tabIndex: -1,
|
|
253
|
+
"aria-disabled": l || void 0,
|
|
254
|
+
...N.trigger.props,
|
|
255
|
+
...g,
|
|
256
|
+
onKeyDown: P,
|
|
257
|
+
onPointerEnter: F
|
|
258
|
+
},
|
|
259
|
+
children: [s, /* @__PURE__ */ v(r, { component: "menu.arrow" })]
|
|
260
|
+
}), !l && /* @__PURE__ */ v(S.Provider, {
|
|
261
|
+
value: I,
|
|
262
|
+
children: /* @__PURE__ */ v(D, {
|
|
263
|
+
layer: N,
|
|
264
|
+
side: d,
|
|
265
|
+
align: f,
|
|
266
|
+
offset: p,
|
|
267
|
+
flip: h,
|
|
268
|
+
matchWidth: !1,
|
|
269
|
+
labelledBy: O,
|
|
270
|
+
contentProps: b,
|
|
271
|
+
closeSelf: (e) => N.setOpen(!1, e),
|
|
272
|
+
...T,
|
|
273
|
+
children: c
|
|
274
|
+
})
|
|
275
|
+
})] });
|
|
276
|
+
}
|
|
277
|
+
function k(e) {
|
|
278
|
+
let { onSelect: t, disabled: n, closeOnSelect: a = !0, props: o, children: s, ...c } = e, l = C("Menu.Item"), u = i((e) => {
|
|
279
|
+
n || (t?.(e), a && l.closeAll({
|
|
280
|
+
reason: "select",
|
|
281
|
+
event: e
|
|
282
|
+
}));
|
|
283
|
+
});
|
|
284
|
+
return /* @__PURE__ */ v(r, {
|
|
285
|
+
tag: "button",
|
|
286
|
+
component: "menu.item",
|
|
287
|
+
...c,
|
|
288
|
+
props: {
|
|
289
|
+
type: "button",
|
|
290
|
+
role: "menuitem",
|
|
291
|
+
tabIndex: -1,
|
|
292
|
+
"aria-disabled": n || void 0,
|
|
293
|
+
...o,
|
|
294
|
+
onClick: u
|
|
295
|
+
},
|
|
296
|
+
children: s
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function A(e) {
|
|
300
|
+
let { checked: t, defaultChecked: n = !1, onCheckedChange: o, disabled: s, closeOnSelect: c = !1, props: l, children: u, ...d } = e, f = C("Menu.CheckboxItem"), [p, m] = a({
|
|
301
|
+
value: t,
|
|
302
|
+
defaultValue: n,
|
|
303
|
+
onChange: o
|
|
304
|
+
}), h = i((e) => {
|
|
305
|
+
s || (m(!p, {
|
|
306
|
+
reason: "select",
|
|
307
|
+
event: e
|
|
308
|
+
}), c && f.closeAll({
|
|
309
|
+
reason: "select",
|
|
310
|
+
event: e
|
|
311
|
+
}));
|
|
312
|
+
});
|
|
313
|
+
return /* @__PURE__ */ y(r, {
|
|
314
|
+
tag: "button",
|
|
315
|
+
component: "menu.item",
|
|
316
|
+
...d,
|
|
317
|
+
props: {
|
|
318
|
+
type: "button",
|
|
319
|
+
role: "menuitemcheckbox",
|
|
320
|
+
tabIndex: -1,
|
|
321
|
+
"aria-checked": p,
|
|
322
|
+
"aria-disabled": s || void 0,
|
|
323
|
+
...l,
|
|
324
|
+
onClick: h
|
|
325
|
+
},
|
|
326
|
+
children: [/* @__PURE__ */ v(r, {
|
|
327
|
+
component: "menu.indicator",
|
|
328
|
+
children: p && /* @__PURE__ */ v(r, { component: "menu.check" })
|
|
329
|
+
}), u]
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
function j(e) {
|
|
333
|
+
let { label: t, value: n, defaultValue: r = "", onValueChange: o, children: s, ...c } = e, [l, u] = a({
|
|
334
|
+
value: n,
|
|
335
|
+
defaultValue: r,
|
|
336
|
+
onChange: o
|
|
337
|
+
}), d = i((e, t) => u(e, {
|
|
338
|
+
reason: "select",
|
|
339
|
+
event: t
|
|
340
|
+
})), f = m(() => ({
|
|
341
|
+
value: l,
|
|
342
|
+
select: d
|
|
343
|
+
}), [l, d]);
|
|
344
|
+
return /* @__PURE__ */ v(T.Provider, {
|
|
345
|
+
value: f,
|
|
346
|
+
children: /* @__PURE__ */ v(N, {
|
|
347
|
+
label: t,
|
|
348
|
+
...c,
|
|
349
|
+
children: s
|
|
350
|
+
})
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
function M(e) {
|
|
354
|
+
let { value: t, disabled: n, closeOnSelect: a = !1, props: o, children: s, ...c } = e, l = C("Menu.RadioItem"), u = p(T);
|
|
355
|
+
if (!u) throw Error("<Menu.RadioItem> must be rendered inside a <Menu.RadioGroup>.");
|
|
356
|
+
let d = u.value === t, f = i((e) => {
|
|
357
|
+
n || (u.select(t, e), a && l.closeAll({
|
|
358
|
+
reason: "select",
|
|
359
|
+
event: e
|
|
360
|
+
}));
|
|
361
|
+
});
|
|
362
|
+
return /* @__PURE__ */ y(r, {
|
|
363
|
+
tag: "button",
|
|
364
|
+
component: "menu.item",
|
|
365
|
+
...c,
|
|
366
|
+
props: {
|
|
367
|
+
type: "button",
|
|
368
|
+
role: "menuitemradio",
|
|
369
|
+
tabIndex: -1,
|
|
370
|
+
"aria-checked": d,
|
|
371
|
+
"aria-disabled": n || void 0,
|
|
372
|
+
...o,
|
|
373
|
+
onClick: f
|
|
374
|
+
},
|
|
375
|
+
children: [/* @__PURE__ */ v(r, {
|
|
376
|
+
component: "menu.indicator",
|
|
377
|
+
children: d && /* @__PURE__ */ v(r, { component: "menu.dot" })
|
|
378
|
+
}), s]
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
function N(e) {
|
|
382
|
+
let { label: t, props: n, children: i, ...a } = e, s = o("menu-group");
|
|
383
|
+
return /* @__PURE__ */ y(r, {
|
|
384
|
+
component: "menu.group",
|
|
385
|
+
...a,
|
|
386
|
+
props: {
|
|
387
|
+
role: "group",
|
|
388
|
+
"aria-labelledby": t ? s : void 0,
|
|
389
|
+
...n
|
|
390
|
+
},
|
|
391
|
+
children: [t && /* @__PURE__ */ v(r, {
|
|
392
|
+
component: "menu.label",
|
|
393
|
+
id: s,
|
|
394
|
+
props: { role: "presentation" },
|
|
395
|
+
children: t
|
|
396
|
+
}), i]
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
function P(e) {
|
|
400
|
+
let { props: t, ...n } = e;
|
|
401
|
+
return /* @__PURE__ */ v(r, {
|
|
402
|
+
component: "menu.separator",
|
|
403
|
+
...n,
|
|
404
|
+
props: {
|
|
405
|
+
role: "separator",
|
|
406
|
+
...t
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
k.displayName = "Menu.Item", A.displayName = "Menu.CheckboxItem", j.displayName = "Menu.RadioGroup", M.displayName = "Menu.RadioItem", N.displayName = "Menu.Group", P.displayName = "Menu.Separator", O.displayName = "Menu.Sub";
|
|
411
|
+
var F = Object.assign(E, {
|
|
412
|
+
Item: k,
|
|
413
|
+
CheckboxItem: A,
|
|
414
|
+
RadioGroup: j,
|
|
415
|
+
RadioItem: M,
|
|
416
|
+
Group: N,
|
|
417
|
+
Separator: P,
|
|
418
|
+
Sub: O
|
|
419
|
+
});
|
|
420
|
+
E.displayName = "Menu";
|
|
421
|
+
//#endregion
|
|
422
|
+
export { F as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../platform.cjs"),t=require("../client.cjs"),n=require("../effects.cjs"),r=require("../box.cjs"),i=require("../placement.cjs");let a=require("react"),o=require("react/jsx-runtime"),s=require("react-dom");function c(c,l){let{side:u=`bottom`,align:d=`center`,offset:f=0,flip:p=!0,onSideChange:m,anchor:h,contentRef:g,matchWidth:_=!0,...v}=c,[y,b]=(0,a.useState)(null),[x,S]=(0,a.useState)(!1),C=(0,a.useRef)(null),[w]=(0,a.useState)(e.a),T=(0,a.useRef)(null),E=t.t(!w),D=i.t({side:u,align:d,offset:f,flip:p,matchWidth:_,anchor:h??y,trackSide:!!m});n.n(()=>{let e=T.current;!w||!e||!e.isConnected||e.matches(`:popover-open`)||e.showPopover()}),n.n(()=>{if(w)return;let t=e.c(h)??y;S(!!t&&e.u(t))},[h,y,w]),n.n(()=>{C.current!==D.side&&(C.current=D.side,m?.(D.side))});let O=D.layerProps.ref,k=(0,a.useCallback)(e=>{O?.(e),T.current=e,typeof l==`function`?l(e):l&&(l.current=e)},[O,l]),A=(0,o.jsx)(r.default,{...D.layerProps,ref:k,transition:`none`,props:w?{popover:`manual`}:{dir:x?`rtl`:`ltr`},children:(0,o.jsx)(r.default,{ref:g,...v})});return(0,o.jsxs)(o.Fragment,{children:[!h&&(0,o.jsx)(r.default,{ref:b}),w?A:E&&(0,s.createPortal)(A,E)]})}var l=(0,a.forwardRef)(c);l.displayName=`Overlay`,exports.default=l;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Ref, RefAttributes } from 'react';
|
|
2
|
+
import { BoxProps } from '../box';
|
|
3
|
+
import { ExtractElementFromTag } from '../react/reactTypes';
|
|
4
|
+
import { ComponentsAndVariants } from '@box-kite/core/types';
|
|
5
|
+
import { AnchorAlign, AnchorSide } from '../utils/anchor/anchorUtils';
|
|
6
|
+
import { ElementLike } from '../utils/dom/domUtils';
|
|
7
|
+
interface OverlayProps {
|
|
8
|
+
/**
|
|
9
|
+
* Which side of the anchor the layer sits on: `top`/`bottom` are the block axis, `start`/`end` the
|
|
10
|
+
* inline one, so a layer beside its anchor mirrors in a right-to-left page. Default `'bottom'`.
|
|
11
|
+
*/
|
|
12
|
+
side?: AnchorSide;
|
|
13
|
+
/** Which of the anchor's edges to line up with along the other axis. Default `'center'`. */
|
|
14
|
+
align?: AnchorAlign;
|
|
15
|
+
/** The gap between anchor and layer, on the ÷4 spacing scale — `offset={2}` is 8px. Default `0`. */
|
|
16
|
+
offset?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Whether a side with no room may be swapped for its opposite. Default `true`. It shadows the CSS prop
|
|
19
|
+
* of that name — a mirrored layer is a rarity, and one placement vocabulary across the hook, this and
|
|
20
|
+
* `Tooltip` is worth more than the transform, which a child of the layer can still take.
|
|
21
|
+
*/
|
|
22
|
+
flip?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Fires with the side the layer ended up on, which is the requested one unless a flip moved it — what
|
|
25
|
+
* a popup that grows away from its trigger needs to know to animate the right way. Asking for it is
|
|
26
|
+
* what turns on the one read the CSS path otherwise never does, so leave it out when nothing uses it.
|
|
27
|
+
*/
|
|
28
|
+
onSideChange?(side: AnchorSide): void;
|
|
29
|
+
/**
|
|
30
|
+
* Anchor to this element rather than to the spot the layer was declared in. A trigger is almost always
|
|
31
|
+
* the right answer: the placeholder is a real box with no size, so `align` and `matchWidth` have
|
|
32
|
+
* nothing to work from, and inside a flex row it becomes a flex item of its own.
|
|
33
|
+
*/
|
|
34
|
+
anchor?: ElementLike;
|
|
35
|
+
/**
|
|
36
|
+
* The content Box, which is the one that animates. `ref` is the anchored layer, which transitions
|
|
37
|
+
* nothing on purpose — so a `<Presence>` measuring an exit has to reach past it.
|
|
38
|
+
*/
|
|
39
|
+
contentRef?: Ref<HTMLDivElement>;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the layer is at least as wide as its anchor. Default true, so a dropdown popup lines up with
|
|
42
|
+
* its trigger; a tooltip sizes to its own content and turns it off.
|
|
43
|
+
*/
|
|
44
|
+
matchWidth?: boolean;
|
|
45
|
+
}
|
|
46
|
+
declare const _default: <TTag extends keyof React.JSX.IntrinsicElements = "div", TKey extends keyof ComponentsAndVariants = never>(props: Omit<BoxProps<TTag, TKey>, "flip"> & RefAttributes<ExtractElementFromTag<TTag>> & OverlayProps) => React.ReactNode;
|
|
47
|
+
export default _default;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { a as e, c as t, u as n } from "../platform.mjs";
|
|
3
|
+
import { t as r } from "../client.mjs";
|
|
4
|
+
import { n as i } from "../effects.mjs";
|
|
5
|
+
import a from "../box.mjs";
|
|
6
|
+
import { t as o } from "../placement.mjs";
|
|
7
|
+
import { forwardRef as s, useCallback as c, useRef as l, useState as u } from "react";
|
|
8
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
9
|
+
import { createPortal as m } from "react-dom";
|
|
10
|
+
//#region src/components/overlay.tsx
|
|
11
|
+
function h(s, h) {
|
|
12
|
+
let { side: g = "bottom", align: _ = "center", offset: v = 0, flip: y = !0, onSideChange: b, anchor: x, contentRef: S, matchWidth: C = !0, ...w } = s, [T, E] = u(null), [D, O] = u(!1), k = l(null), [A] = u(e), j = l(null), M = r(!A), N = o({
|
|
13
|
+
side: g,
|
|
14
|
+
align: _,
|
|
15
|
+
offset: v,
|
|
16
|
+
flip: y,
|
|
17
|
+
matchWidth: C,
|
|
18
|
+
anchor: x ?? T,
|
|
19
|
+
trackSide: !!b
|
|
20
|
+
});
|
|
21
|
+
i(() => {
|
|
22
|
+
let e = j.current;
|
|
23
|
+
!A || !e || !e.isConnected || e.matches(":popover-open") || e.showPopover();
|
|
24
|
+
}), i(() => {
|
|
25
|
+
if (A) return;
|
|
26
|
+
let e = t(x) ?? T;
|
|
27
|
+
O(!!e && n(e));
|
|
28
|
+
}, [
|
|
29
|
+
x,
|
|
30
|
+
T,
|
|
31
|
+
A
|
|
32
|
+
]), i(() => {
|
|
33
|
+
k.current !== N.side && (k.current = N.side, b?.(N.side));
|
|
34
|
+
});
|
|
35
|
+
let P = N.layerProps.ref, F = c((e) => {
|
|
36
|
+
P?.(e), j.current = e, typeof h == "function" ? h(e) : h && (h.current = e);
|
|
37
|
+
}, [P, h]), I = /* @__PURE__ */ f(a, {
|
|
38
|
+
...N.layerProps,
|
|
39
|
+
ref: F,
|
|
40
|
+
transition: "none",
|
|
41
|
+
props: A ? { popover: "manual" } : { dir: D ? "rtl" : "ltr" },
|
|
42
|
+
children: /* @__PURE__ */ f(a, {
|
|
43
|
+
ref: S,
|
|
44
|
+
...w
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
return /* @__PURE__ */ p(d, { children: [!x && /* @__PURE__ */ f(a, { ref: E }), A ? I : M && m(I, M)] });
|
|
48
|
+
}
|
|
49
|
+
var g = s(h);
|
|
50
|
+
g.displayName = "Overlay";
|
|
51
|
+
//#endregion
|
|
52
|
+
export { g as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../box.cjs"),t=require("../behavior.cjs"),n=require("../placement.cjs"),r=require("./overlay.cjs"),i=require("../layer.cjs");let a=require("react/jsx-runtime");function o(o){let{trigger:s,children:c,open:l,defaultOpen:u=!1,onOpenChange:d,label:f,labelledBy:p,side:m=`bottom`,align:h=`center`,offset:g=2,flip:_=!0,matchWidth:v=!1,autoFocus:y=!0,props:b,...x}=o,S=t.a(e=>{!y||e.contains(document.activeElement)||e.focus()}),{platform:C,isOpen:w,id:T,trigger:E,triggerElement:D,setPanel:O}=i.t({haspopup:`dialog`,idPrefix:`popover`,id:x.id,open:l,defaultOpen:u,onOpenChange:d,onOpened:S}),k=n.t({side:m,align:h,offset:g,flip:_,matchWidth:v,anchor:D}),A={"aria-label":f,"aria-labelledby":p},j=x;return C?(0,a.jsxs)(a.Fragment,{children:[s(E),(0,a.jsx)(e.default,{ref:O,component:`popover`,...j,variant:[j.variant,{topLayer:!0}],...k.layerProps,id:T,props:{popover:`auto`,role:`dialog`,...A,tabIndex:-1,...b},children:c})]}):(0,a.jsxs)(a.Fragment,{children:[s(E),w&&(0,a.jsx)(r.default,{contentRef:O,anchor:D,side:m,align:h,offset:g,flip:_,matchWidth:v,component:`popover`,...j,id:T,props:{role:`dialog`,...A,tabIndex:-1,...b},children:c})]})}var s=o;s.displayName=`Popover`,exports.default=s;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { BoxProps } from '../box';
|
|
2
|
+
import { ChangeHandler } from '../react/a11y/useControllableState';
|
|
3
|
+
import { PopoverReason, PopoverTrigger as PopoverLayerTrigger, PopoverTriggerAttributes as PopoverLayerTriggerAttributes } from '../react/popover/usePopoverLayer';
|
|
4
|
+
import { ComponentsAndVariants } from '@box-kite/core/types';
|
|
5
|
+
import { AnchorAlign, AnchorSide } from '../utils/anchor/anchorUtils';
|
|
6
|
+
export type { PopoverReason };
|
|
7
|
+
/** The DOM attributes the trigger has to carry. */
|
|
8
|
+
export type PopoverTriggerAttributes = PopoverLayerTriggerAttributes<'dialog'>;
|
|
9
|
+
/**
|
|
10
|
+
* What the trigger has to carry: spread it onto the control itself, not a wrapper. The `ref` is what the
|
|
11
|
+
* popover is anchored to, so it is not optional decoration (see `anchor` on `Overlay`).
|
|
12
|
+
*
|
|
13
|
+
* ```tsx
|
|
14
|
+
* {(trigger) => <Button {...trigger}>Options</Button>} // a Box component
|
|
15
|
+
* {(trigger) => <button ref={trigger.ref} {...trigger.props}>} // a plain element
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* It must be a **button**: `popovertarget` is what the browser toggles on, and it only reads it off one.
|
|
19
|
+
*/
|
|
20
|
+
export type PopoverTrigger = PopoverLayerTrigger<'dialog'>;
|
|
21
|
+
type PopoverBoxProps<TKey extends keyof ComponentsAndVariants> = Omit<BoxProps<'div', TKey>, 'open' | 'flip'>;
|
|
22
|
+
interface Props<TKey extends keyof ComponentsAndVariants> extends PopoverBoxProps<TKey> {
|
|
23
|
+
/** The trigger, handed the ref and props that wire it to the popover. It has to be a button. */
|
|
24
|
+
trigger: (trigger: PopoverTrigger) => React.ReactNode;
|
|
25
|
+
/** The panel's content. Rendered whether or not the popover is open — see the note on mounting. */
|
|
26
|
+
children?: React.ReactNode;
|
|
27
|
+
/** Controlled open state. Leave it out and the popover owns it. */
|
|
28
|
+
open?: boolean;
|
|
29
|
+
/** Whether it starts open, when the popover owns its own state. */
|
|
30
|
+
defaultOpen?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Fires with the new state and why it changed — `'trigger'`, `'escape'`, `'outside-pointer'` or
|
|
33
|
+
* `'imperative'`. A close cannot be refused: the browser has already done it by the time this runs.
|
|
34
|
+
*/
|
|
35
|
+
onOpenChange?: ChangeHandler<boolean, PopoverReason>;
|
|
36
|
+
/** The panel's accessible name. `role="dialog"` has none of its own, and a dialog without one is unusable. */
|
|
37
|
+
label?: string;
|
|
38
|
+
/** Names the panel after an element already on the page, instead of `label`. */
|
|
39
|
+
labelledBy?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Which side of the trigger the panel sits on — `top`/`bottom` are the block axis, `start`/`end` the
|
|
42
|
+
* inline one, so a panel beside its trigger mirrors in a right-to-left page. Default `'bottom'`.
|
|
43
|
+
*/
|
|
44
|
+
side?: AnchorSide;
|
|
45
|
+
/** Which of the trigger's edges to line the panel up with along the other axis. Default `'center'`. */
|
|
46
|
+
align?: AnchorAlign;
|
|
47
|
+
/** The gap between trigger and panel, on the ÷4 spacing scale. Default 2 — 8px. */
|
|
48
|
+
offset?: number;
|
|
49
|
+
/** Whether a side with no room may be swapped for its opposite. Default `true`. */
|
|
50
|
+
flip?: boolean;
|
|
51
|
+
/** Whether the panel is at least as wide as its trigger. Default `false` — a panel sizes to its content. */
|
|
52
|
+
matchWidth?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether opening moves focus into the panel. Default `true`, which is what APG asks of a dialog. An
|
|
55
|
+
* `autofocus` attribute inside wins: the browser applies it first and this only acts on what is left.
|
|
56
|
+
*/
|
|
57
|
+
autoFocus?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A panel anchored to a trigger, on the platform's own Popover API: the top layer, light dismiss and
|
|
61
|
+
* focus return are the browser's, and the position is CSS anchor positioning.
|
|
62
|
+
*
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <Popover label="Filters" trigger={(t) => <Button {...t}>Filters</Button>}>
|
|
65
|
+
* <Checkbox label="Only mine" />
|
|
66
|
+
* </Popover>
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* **There is no portal.** A top-layer element paints above every stacking context and outside every
|
|
70
|
+
* clipped ancestor, which is the whole class of bug a portal exists to work around — and because the
|
|
71
|
+
* panel stays where it was declared in the DOM, it inherits the theme, the custom properties and the text
|
|
72
|
+
* direction around it, and the tab order runs trigger → panel with nothing to arrange. (Measured against a
|
|
73
|
+
* `z-index: 9999` sibling, a `transform`ed ancestor and an `overflow: hidden` one.)
|
|
74
|
+
*
|
|
75
|
+
* **The panel is always rendered**, and closed means `display: none` from the UA stylesheet. That is what
|
|
76
|
+
* lets the browser own show and hide — and what makes the exit a plain CSS transition rather than a
|
|
77
|
+
* `<Presence>`, since nothing unmounts. Content that is expensive to render should be gated by the
|
|
78
|
+
* consumer: `{open && <Heavy />}`.
|
|
79
|
+
*
|
|
80
|
+
* **The panel keeps the side it chose when it opened.** Chrome re-evaluates `position-try-fallbacks` on
|
|
81
|
+
* scroll for an ordinary positioned element and never for one in the top layer (measured in 152), so a
|
|
82
|
+
* panel left open while the page scrolls does not flip when its side runs out of room. Every open picks
|
|
83
|
+
* the right side; it is only a scroll *while* open that this affects. See `Overlay`, which shares it.
|
|
84
|
+
*
|
|
85
|
+
* Where the browser has no Popover API the panel is an `Overlay` — a portal — with `useDismiss` and
|
|
86
|
+
* `useFocusReturn` supplying what the platform otherwise would.
|
|
87
|
+
*
|
|
88
|
+
* @a11y `role="dialog"` on the panel, named by `label` or `labelledBy`; the popover attribute supplies no
|
|
89
|
+
* role at all, and a panel with none is announced as a group of orphaned content.
|
|
90
|
+
* @a11y The trigger carries `aria-expanded`, `aria-haspopup="dialog"` and `aria-controls`, so the control
|
|
91
|
+
* says what it operates and what state it is in.
|
|
92
|
+
* @a11y Focus moves into the panel on open and back to the trigger on close. Nothing is trapped: this is a
|
|
93
|
+
* non-modal dialog, so Tab leaves it, and the panel follows the trigger in the DOM either way.
|
|
94
|
+
* @keyboard Enter, Space — On the trigger, toggles the panel.
|
|
95
|
+
* @keyboard Escape — Closes it and returns focus to the trigger, from anywhere inside.
|
|
96
|
+
* @keyboard Tab — Moves into the panel from the trigger, and out of the panel to whatever follows it.
|
|
97
|
+
*/
|
|
98
|
+
declare function PopoverImpl<TKey extends keyof ComponentsAndVariants = 'popover'>(props: Props<TKey>): import("react").JSX.Element;
|
|
99
|
+
declare const Popover: typeof PopoverImpl;
|
|
100
|
+
export default Popover;
|