@box-kite/react 1.0.0 → 2.0.1
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 +23 -1
- package/.claude/skills/box-kite/SKILL.md +134 -427
- 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 +1124 -153
- package/BOX_KITE_AI_CONTEXT.md +1124 -153
- package/README.md +36 -2
- package/a11y.cjs +1 -1
- package/a11y.d.ts +1 -1
- package/a11y.mjs +3 -2
- package/anchor.cjs +1 -0
- package/anchor.d.ts +14 -0
- package/anchor.mjs +3 -0
- package/behavior.cjs +1 -1
- package/behavior.mjs +118 -136
- package/box.cjs +1 -1
- package/box.mjs +1 -1
- package/client.cjs +1 -1
- package/client.mjs +15 -14
- package/components/accordion.cjs +1 -0
- package/components/accordion.d.ts +114 -0
- package/components/accordion.mjs +251 -0
- package/components/button.cjs +1 -1
- package/components/button.d.ts +3 -0
- package/components/button.mjs +1 -1
- package/components/chart.cjs +1 -1
- package/components/chart.d.ts +2 -1
- package/components/chart.mjs +159 -184
- package/components/checkbox.cjs +1 -1
- package/components/checkbox.d.ts +8 -0
- package/components/checkbox.mjs +1 -1
- 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/dataGridCell.d.ts +2 -1
- package/components/dataGrid/components/dataGridCellEditor.d.ts +15 -0
- package/components/dataGrid/components/dataGridCellPlaceholder.d.ts +14 -0
- package/components/dataGrid/components/dataGridCellTree.d.ts +16 -0
- package/components/dataGrid/components/dataGridDataSourceError.d.ts +12 -0
- package/components/dataGrid/components/dataGridExport.d.ts +10 -0
- package/components/dataGrid/components/dataGridFooter.d.ts +11 -0
- package/components/dataGrid/contracts/dataGridContract.d.ts +474 -16
- package/components/dataGrid/export/gridExport.d.ts +10 -0
- package/components/dataGrid/gridNavigationContext.d.ts +9 -1
- 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 +27 -1
- package/components/dataGrid/models/columnModel.d.ts +12 -2
- package/components/dataGrid/models/dataSourceModel.d.ts +177 -0
- package/components/dataGrid/models/editModel.d.ts +77 -0
- package/components/dataGrid/models/exportModel.d.ts +51 -0
- package/components/dataGrid/models/gridModel.d.ts +108 -21
- package/components/dataGrid/models/groupRowCellModel.d.ts +11 -3
- package/components/dataGrid/models/groupRowModel.d.ts +22 -2
- package/components/dataGrid/models/rowModel.d.ts +13 -1
- 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.cjs +1 -1
- package/components/dataGrid.d.ts +4 -2
- package/components/dataGrid.mjs +4484 -2755
- package/components/dialog.cjs +1 -0
- package/components/dialog.d.ts +151 -0
- package/components/dialog.mjs +223 -0
- package/components/dropdown.cjs +1 -1
- package/components/dropdown.d.ts +30 -0
- package/components/dropdown.mjs +256 -244
- package/components/icon.cjs +1 -1
- package/components/icon.d.ts +2 -1
- package/components/icon.mjs +3 -3
- package/components/menu.cjs +1 -0
- package/components/menu.d.ts +234 -0
- package/components/menu.mjs +422 -0
- package/components/overlay.cjs +1 -1
- package/components/overlay.d.ts +30 -26
- package/components/overlay.mjs +45 -75
- package/components/popover.cjs +1 -0
- package/components/popover.d.ts +100 -0
- package/components/popover.mjs +69 -0
- package/components/presence.d.ts +6 -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 -1
- package/components/radioButton.d.ts +8 -0
- package/components/radioButton.mjs +1 -1
- package/components/radioGroup.cjs +1 -1
- package/components/radioGroup.d.ts +15 -2
- package/components/radioGroup.mjs +34 -30
- package/components/select.d.ts +9 -0
- package/components/semantics.cjs +1 -1
- package/components/semantics.d.ts +33 -28
- package/components/semantics.mjs +3 -3
- package/components/slider.cjs +1 -0
- package/components/slider.d.ts +98 -0
- package/components/slider.mjs +250 -0
- package/components/svg.cjs +1 -1
- package/components/svg.d.ts +25 -23
- package/components/svg.mjs +3 -3
- package/components/switch.cjs +1 -1
- package/components/switch.d.ts +9 -0
- package/components/switch.mjs +1 -1
- package/components/tabs.cjs +1 -0
- package/components/tabs.d.ts +87 -0
- package/components/tabs.mjs +324 -0
- package/components/textarea.cjs +1 -1
- package/components/textarea.d.ts +14 -0
- package/components/textarea.mjs +1 -1
- package/components/textbox.cjs +1 -1
- package/components/textbox.d.ts +12 -0
- package/components/textbox.mjs +1 -1
- package/components/toaster.cjs +1 -0
- package/components/toaster.d.ts +106 -0
- package/components/toaster.mjs +295 -0
- package/components/tooltip.cjs +1 -1
- package/components/tooltip.d.ts +39 -4
- package/components/tooltip.mjs +56 -54
- 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 -1
- package/effects.mjs +1 -1
- package/gridExport.cjs +2 -0
- package/gridExport.mjs +244 -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 -1
- package/motion.mjs +1 -1
- package/package.json +134 -10
- package/placement.cjs +1 -0
- package/placement.mjs +180 -0
- package/platform.cjs +1 -1
- package/platform.mjs +18 -5
- package/react/anchor/useAnchorPosition.d.ts +79 -0
- package/react/dialog/useScrollLock.d.ts +12 -0
- package/react/hooks/usePortalContainer.d.ts +6 -1
- package/react/hooks/useVirtualization.d.ts +24 -35
- package/react/popover/usePopoverLayer.d.ts +87 -0
- package/react-shared.cjs +1 -1
- package/react-shared.mjs +19 -2
- package/rsc.cjs +1 -1
- package/rsc.mjs +1 -1
- package/utils/accordion/accordionUtils.d.ts +48 -0
- package/utils/anchor/anchorUtils.d.ts +79 -0
- package/utils/array/lazyList.d.ts +10 -0
- package/utils/chart/chartPalette.d.ts +15 -0
- package/utils/chart/chartUtils.d.ts +2 -8
- package/utils/combobox/comboboxUtils.d.ts +89 -0
- package/utils/dom/domUtils.d.ts +6 -0
- package/utils/environment/environmentUtils.d.ts +10 -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/keyboard/typeaheadUtils.d.ts +31 -0
- package/utils/menu/menuUtils.d.ts +25 -0
- package/utils/slider/sliderUtils.d.ts +67 -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
- /package/react/{a11y → identity}/useIdentifier.d.ts +0 -0
|
@@ -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;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import e from "../box.mjs";
|
|
3
|
+
import { a as t } from "../behavior.mjs";
|
|
4
|
+
import { t as n } from "../placement.mjs";
|
|
5
|
+
import r from "./overlay.mjs";
|
|
6
|
+
import { t as i } from "../layer.mjs";
|
|
7
|
+
import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/popover.tsx
|
|
9
|
+
function c(c) {
|
|
10
|
+
let { trigger: l, children: u, open: d, defaultOpen: f = !1, onOpenChange: p, label: m, labelledBy: h, side: g = "bottom", align: _ = "center", offset: v = 2, flip: y = !0, matchWidth: b = !1, autoFocus: x = !0, props: S, ...C } = c, w = t((e) => {
|
|
11
|
+
!x || e.contains(document.activeElement) || e.focus();
|
|
12
|
+
}), { platform: T, isOpen: E, id: D, trigger: O, triggerElement: k, setPanel: A } = i({
|
|
13
|
+
haspopup: "dialog",
|
|
14
|
+
idPrefix: "popover",
|
|
15
|
+
id: C.id,
|
|
16
|
+
open: d,
|
|
17
|
+
defaultOpen: f,
|
|
18
|
+
onOpenChange: p,
|
|
19
|
+
onOpened: w
|
|
20
|
+
}), j = n({
|
|
21
|
+
side: g,
|
|
22
|
+
align: _,
|
|
23
|
+
offset: v,
|
|
24
|
+
flip: y,
|
|
25
|
+
matchWidth: b,
|
|
26
|
+
anchor: k
|
|
27
|
+
}), M = {
|
|
28
|
+
"aria-label": m,
|
|
29
|
+
"aria-labelledby": h
|
|
30
|
+
}, N = C;
|
|
31
|
+
return T ? /* @__PURE__ */ s(a, { children: [l(O), /* @__PURE__ */ o(e, {
|
|
32
|
+
ref: A,
|
|
33
|
+
component: "popover",
|
|
34
|
+
...N,
|
|
35
|
+
variant: [N.variant, { topLayer: !0 }],
|
|
36
|
+
...j.layerProps,
|
|
37
|
+
id: D,
|
|
38
|
+
props: {
|
|
39
|
+
popover: "auto",
|
|
40
|
+
role: "dialog",
|
|
41
|
+
...M,
|
|
42
|
+
tabIndex: -1,
|
|
43
|
+
...S
|
|
44
|
+
},
|
|
45
|
+
children: u
|
|
46
|
+
})] }) : /* @__PURE__ */ s(a, { children: [l(O), E && /* @__PURE__ */ o(r, {
|
|
47
|
+
contentRef: A,
|
|
48
|
+
anchor: k,
|
|
49
|
+
side: g,
|
|
50
|
+
align: _,
|
|
51
|
+
offset: v,
|
|
52
|
+
flip: y,
|
|
53
|
+
matchWidth: b,
|
|
54
|
+
component: "popover",
|
|
55
|
+
...N,
|
|
56
|
+
id: D,
|
|
57
|
+
props: {
|
|
58
|
+
role: "dialog",
|
|
59
|
+
...M,
|
|
60
|
+
tabIndex: -1,
|
|
61
|
+
...S
|
|
62
|
+
},
|
|
63
|
+
children: u
|
|
64
|
+
})] });
|
|
65
|
+
}
|
|
66
|
+
var l = c;
|
|
67
|
+
l.displayName = "Popover";
|
|
68
|
+
//#endregion
|
|
69
|
+
export { l as default };
|
package/components/presence.d.ts
CHANGED
|
@@ -24,6 +24,12 @@ interface Props {
|
|
|
24
24
|
* takes DOM attributes in a `props` bag, a plain element takes them on top. The `ref` is not decoration
|
|
25
25
|
* either: whichever element it lands on is the one whose computed style the wait is measured from, so it
|
|
26
26
|
* belongs on the element that carries the transition.
|
|
27
|
+
*
|
|
28
|
+
* @a11y The exit is measured from the element's own `transition-duration`/`animation-duration`, so
|
|
29
|
+
* `prefers-reduced-motion` — which zeroes `--transitionTime` — removes the node in the same commit
|
|
30
|
+
* with no opt-in.
|
|
31
|
+
* @a11y `data-state` is `'open'` or `'closed'` on the child, which is what a CSS exit selects on. A
|
|
32
|
+
* node on its way out is still in the accessibility tree, so anything hiding it has to say so itself.
|
|
27
33
|
*/
|
|
28
34
|
declare function Presence(props: Props): import("react").JSX.Element;
|
|
29
35
|
export default Presence;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../rolldown-runtime.cjs");let t=require("react/jsx-runtime"),n=require("@box-kite/react");n=e.t(n,1);function r(e){let{value:r,min:i=0,max:a=100,label:o,labelledBy:s,format:c,props:l,...u}=e,d=r===void 0,f=d?i:Math.min(Math.max(r,i),a),p=a<=i?0:Math.round((f-i)/(a-i)*1e4)/100;return(0,t.jsx)(n.default,{component:`progress`,...u,props:{role:`progressbar`,"aria-valuemin":i,"aria-valuemax":a,"aria-valuenow":d?void 0:f,"aria-valuetext":d?void 0:c?.(f),"aria-label":o,"aria-labelledby":s,...l},children:(0,t.jsx)(n.default,{component:`progress.fill`,variant:{indeterminate:d},style:d?void 0:{inlineSize:`${p}%`}})})}r.displayName=`Progress`,exports.default=r;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { BoxProps } from '../box';
|
|
2
|
+
import { ComponentsAndVariants } from '@box-kite/core/types';
|
|
3
|
+
export interface ProgressProps<TKey extends keyof ComponentsAndVariants = 'progress'> extends BoxProps<'div', TKey> {
|
|
4
|
+
/** How far along it is. Leave it out for a task with no measurable end — the bar sweeps and reports nothing. */
|
|
5
|
+
value?: number;
|
|
6
|
+
/** The bottom of the range. Default `0`. */
|
|
7
|
+
min?: number;
|
|
8
|
+
/** The top of the range, and so what "full" means. Default `100`. */
|
|
9
|
+
max?: number;
|
|
10
|
+
/** What the bar is called. A progress bar has to be named — nothing about it is readable otherwise. */
|
|
11
|
+
label?: string;
|
|
12
|
+
/** The same, naming an element that already says it. */
|
|
13
|
+
labelledBy?: string;
|
|
14
|
+
/** The value as it should be read out: "3 of 10 files", "eleven minutes left". */
|
|
15
|
+
format?: (value: number) => string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* How far a task has got.
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <Progress label="Upload" value={62} />
|
|
22
|
+
* <Progress label="Preparing" />
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* **No `value` is the indeterminate bar**, which is a state and not a number: `aria-valuenow` is left off
|
|
26
|
+
* entirely — the one thing a reader must not be told is a progress that was never measured — and the bar
|
|
27
|
+
* sweeps instead, stopping under `prefers-reduced-motion` because a named duration is outside what
|
|
28
|
+
* `--transitionTime` zeroes.
|
|
29
|
+
*
|
|
30
|
+
* **The fill is an inline style and everything else is a class**, the exception `Slider` explains: a
|
|
31
|
+
* percentage that moves with a download is a rule per frame if it goes in a class name. Where the value
|
|
32
|
+
* is data rather than an animation, a `ProgressRing` from `components/chart` rounds it into a class
|
|
33
|
+
* instead and pays nothing.
|
|
34
|
+
*
|
|
35
|
+
* It renders on a server — no state, no effect, no measurement — so a page can paint a real figure
|
|
36
|
+
* before any JavaScript arrives.
|
|
37
|
+
*
|
|
38
|
+
* @a11y `role="progressbar"` with `aria-valuemin`, `aria-valuemax` and, when there is one, `aria-valuenow`.
|
|
39
|
+
* @a11y `label` or `labelledBy` is what names it. A bar with neither is a percentage nobody can attach
|
|
40
|
+
* to anything.
|
|
41
|
+
* @a11y `format` writes `aria-valuetext`, for a value the number alone does not read as.
|
|
42
|
+
*/
|
|
43
|
+
declare function Progress<TKey extends keyof ComponentsAndVariants = 'progress'>(props: ProgressProps<TKey>): import("react").JSX.Element;
|
|
44
|
+
declare namespace Progress {
|
|
45
|
+
var displayName: string;
|
|
46
|
+
}
|
|
47
|
+
export default Progress;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import t from "@box-kite/react";
|
|
3
|
+
//#region src/components/progress.tsx
|
|
4
|
+
function n(n) {
|
|
5
|
+
let { value: r, min: i = 0, max: a = 100, label: o, labelledBy: s, format: c, props: l, ...u } = n, d = r === void 0, f = d ? i : Math.min(Math.max(r, i), a), p = a <= i ? 0 : Math.round((f - i) / (a - i) * 1e4) / 100;
|
|
6
|
+
return /* @__PURE__ */ e(t, {
|
|
7
|
+
component: "progress",
|
|
8
|
+
...u,
|
|
9
|
+
props: {
|
|
10
|
+
role: "progressbar",
|
|
11
|
+
"aria-valuemin": i,
|
|
12
|
+
"aria-valuemax": a,
|
|
13
|
+
"aria-valuenow": d ? void 0 : f,
|
|
14
|
+
"aria-valuetext": d ? void 0 : c?.(f),
|
|
15
|
+
"aria-label": o,
|
|
16
|
+
"aria-labelledby": s,
|
|
17
|
+
...l
|
|
18
|
+
},
|
|
19
|
+
children: /* @__PURE__ */ e(t, {
|
|
20
|
+
component: "progress.fill",
|
|
21
|
+
variant: { indeterminate: d },
|
|
22
|
+
style: d ? void 0 : { inlineSize: `${p}%` }
|
|
23
|
+
})
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
n.displayName = "Progress";
|
|
27
|
+
//#endregion
|
|
28
|
+
export { n as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../rolldown-runtime.cjs"),t=require("../react-shared.cjs"),n=require("../forms.cjs");let r=require("react"),i=require("react/jsx-runtime"),a=require("@box-kite/react");a=e.t(a,1);var o=[`name`,`onInput`,`onChange`,`value`,`autoFocus`,`readOnly`,`defaultChecked`];function s(e,r){let{label:s,labelProps:c,...l}=e,u=t.
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../rolldown-runtime.cjs"),t=require("../react-shared.cjs"),n=require("../forms.cjs");let r=require("react"),i=require("react/jsx-runtime"),a=require("@box-kite/react");a=e.t(a,1);var o=[`name`,`onInput`,`onChange`,`value`,`autoFocus`,`readOnly`,`defaultChecked`];function s(e,r){let{label:s,labelProps:c,...l}=e,u=t.i.buildProps(l,o,{type:`radio`});return(0,i.jsx)(n.n,{label:s,labelProps:c,children:(0,i.jsx)(a.default,{ref:r,tag:`input`,component:`radioButton`,...u})})}var c=(0,r.forwardRef)(s);c.displayName=`RadioButton`,exports.default=c;
|
|
@@ -7,13 +7,21 @@ type TagPropsType = (typeof tagProps)[number];
|
|
|
7
7
|
type RadioButtonProps<TKey extends keyof ComponentsAndVariants> = Omit<BoxProps<'input', TKey>, 'tag' | 'props'>;
|
|
8
8
|
type RadioButtonTagProps = OmitTagProps<BoxTagProps<'input'>, TagPropsType | 'type'>;
|
|
9
9
|
interface Props<TKey extends keyof ComponentsAndVariants> extends RadioButtonProps<TKey> {
|
|
10
|
+
/** The name the radios of one set share — it is what makes them one choice rather than several. */
|
|
10
11
|
name?: string;
|
|
12
|
+
/** Attributes for the `<input>` itself. `type` is the component's. */
|
|
11
13
|
props?: RadioButtonTagProps;
|
|
14
|
+
/** Fires on every click or keystroke. On a radio this is the same moment as `onChange`. */
|
|
12
15
|
onInput?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
16
|
+
/** Fires when this radio becomes the chosen one. A radio never fires it on being cleared. */
|
|
13
17
|
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
18
|
+
/** What the set submits when this option is the chosen one. */
|
|
14
19
|
value?: string | number;
|
|
20
|
+
/** Focus it on mount. One per page at most — a stolen focus is a lost place in the document. */
|
|
15
21
|
autoFocus?: boolean;
|
|
22
|
+
/** Rendered and read, but not selectable. Unlike `disabled` it stays in the tab order and submits. */
|
|
16
23
|
readOnly?: boolean;
|
|
24
|
+
/** Makes this the chosen option to begin with, when the set is uncontrolled. */
|
|
17
25
|
defaultChecked?: boolean;
|
|
18
26
|
/** The text beside the radio, rendered inside a `<label>` that wraps the input. */
|
|
19
27
|
label?: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../behavior.cjs"),t=require("./flex.cjs"),
|
|
1
|
+
"use client";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../behavior.cjs"),t=require("../identity.cjs"),n=require("./flex.cjs"),r=require("./semantics.cjs"),i=require("./radioButton.cjs");let a=require("react"),o=require("react/jsx-runtime");var s=(0,a.createContext)(null);function c(e){return[...e?.querySelectorAll(`input[type="radio"]`)??[]].filter(e=>!e.disabled)}function l(e){return e===`ArrowDown`||e===`ArrowRight`?1:e===`ArrowUp`||e===`ArrowLeft`?-1:0}function u(i){let{label:u,name:d,value:f,defaultValue:p,onValueChange:m,onChange:h,orientation:g=`vertical`,children:_,props:v,...y}=i,b=t.t(`radiogroup`),x=(0,a.useRef)(null),S=(0,a.useRef)(`click`),C=e.a((e,t)=>{m?.(e,t),h?.(e,t)}),[w,T]=e.i({value:f,defaultValue:p,onChange:C}),E=e.a(e=>{let t=l(e.key);if(t===0||e.defaultPrevented)return;let n=c(x.current),r=n.indexOf(document.activeElement);if(r===-1)return;e.preventDefault();let i=n[(r+t+n.length)%n.length];i!==n[r]&&(S.current=`keyboard`,i.focus(),i.click(),S.current=`click`)}),D=`${b}-label`,O=u!=null,k=(0,a.useMemo)(()=>({name:d??b,value:w,select:(e,t)=>T(e,{reason:S.current,event:t})}),[b,d,w,T]);return(0,o.jsx)(s.Provider,{value:k,children:(0,o.jsxs)(n.default,{ref:x,component:`radioGroup`,variant:{horizontal:g===`horizontal`},...y,props:{role:`radiogroup`,"aria-labelledby":O?D:void 0,...v,onKeyDown:E},children:[O&&(0,o.jsx)(r.Span,{component:`radioGroup.label`,id:D,children:u}),_]})})}function d(t){let n=(0,a.useContext)(s),{value:r,...c}=t,l=e.a(e=>n?.select(r,e));return n?(0,o.jsx)(i.default,{name:n.name,value:r,checked:n.value===r,onChange:l,...c}):(0,o.jsx)(i.default,{value:r,...c})}d.displayName=`RadioGroup.Item`;var f=u;f.Item=d,f.displayName=`RadioGroup`,exports.default=f;
|
|
@@ -2,7 +2,7 @@ import { Ref, RefAttributes } from 'react';
|
|
|
2
2
|
import { BoxProps, BoxTagProps } from '../box';
|
|
3
3
|
import { ChangeHandler } from '../react/a11y/useControllableState';
|
|
4
4
|
import { ComponentsAndVariants } from '@box-kite/core/types';
|
|
5
|
-
/** Why the selection changed — `
|
|
5
|
+
/** Why the selection changed — `onValueChange` gets this alongside the event that did it. */
|
|
6
6
|
export type RadioGroupReason = 'click' | 'keyboard';
|
|
7
7
|
type RadioGroupBoxProps<TKey extends keyof ComponentsAndVariants> = Omit<BoxProps<'div', TKey>, 'tag' | 'onChange' | 'children'>;
|
|
8
8
|
interface Props<TKey extends keyof ComponentsAndVariants> extends RadioGroupBoxProps<TKey> {
|
|
@@ -12,10 +12,20 @@ interface Props<TKey extends keyof ComponentsAndVariants> extends RadioGroupBoxP
|
|
|
12
12
|
name?: string;
|
|
13
13
|
/** Controlled selection. Leave it out and the group owns it. */
|
|
14
14
|
value?: string;
|
|
15
|
+
/** The option chosen to begin with, when the group owns its value. */
|
|
15
16
|
defaultValue?: string;
|
|
17
|
+
/** Fires with the new value and why it changed — `'click'` or `'keyboard'`. A group can also hold
|
|
18
|
+
* nothing, so the value is `string | undefined`. */
|
|
19
|
+
onValueChange?: ChangeHandler<string | undefined, RadioGroupReason>;
|
|
20
|
+
/**
|
|
21
|
+
* The same callback under its old name. Both fire, so either one can be passed.
|
|
22
|
+
* @deprecated `onValueChange` is what every other component reports a value change under, and a group
|
|
23
|
+
* is not an `<input>` — this spelling still works and means the same thing.
|
|
24
|
+
*/
|
|
16
25
|
onChange?: ChangeHandler<string | undefined, RadioGroupReason>;
|
|
17
26
|
/** Which way the radios stack. Both arrow pairs navigate either way, as APG specifies. */
|
|
18
27
|
orientation?: 'vertical' | 'horizontal';
|
|
28
|
+
/** The options: `RadioGroup.Item` elements, or anything else the group should hold. */
|
|
19
29
|
children?: React.ReactNode;
|
|
20
30
|
}
|
|
21
31
|
interface ItemProps extends Omit<BoxProps<'input', 'radioButton'>, 'tag' | 'props' | 'onChange' | 'checked'> {
|
|
@@ -25,12 +35,15 @@ interface ItemProps extends Omit<BoxProps<'input', 'radioButton'>, 'tag' | 'prop
|
|
|
25
35
|
name?: string;
|
|
26
36
|
/** The text beside the radio, rendered inside a label that wraps the input. */
|
|
27
37
|
label?: React.ReactNode;
|
|
38
|
+
/** Styles for the wrapping `<label>`: the row's layout, not the radio's own appearance. */
|
|
28
39
|
labelProps?: BoxProps<'label'>;
|
|
40
|
+
/** Attributes for the `<input>` itself. `type`, `name` and `checked` are the group's. */
|
|
29
41
|
props?: BoxTagProps<'input'>;
|
|
42
|
+
/** The `<input>` element, for a caller that has to focus or measure this option. */
|
|
30
43
|
ref?: Ref<HTMLInputElement>;
|
|
31
44
|
}
|
|
32
45
|
interface RadioGroupType {
|
|
33
|
-
<TKey extends keyof ComponentsAndVariants =
|
|
46
|
+
<TKey extends keyof ComponentsAndVariants = 'radioGroup'>(props: Props<TKey>): React.ReactNode;
|
|
34
47
|
Item: (props: ItemProps & RefAttributes<HTMLInputElement>) => React.ReactNode;
|
|
35
48
|
displayName?: string;
|
|
36
49
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { a as e,
|
|
2
|
+
import { a as e, i as t } from "../behavior.mjs";
|
|
3
|
+
import { t as n } from "../identity.mjs";
|
|
3
4
|
import r from "./flex.mjs";
|
|
4
5
|
import { Span as i } from "./semantics.mjs";
|
|
5
6
|
import a from "./radioButton.mjs";
|
|
@@ -14,57 +15,60 @@ function m(e) {
|
|
|
14
15
|
return e === "ArrowDown" || e === "ArrowRight" ? 1 : e === "ArrowUp" || e === "ArrowLeft" ? -1 : 0;
|
|
15
16
|
}
|
|
16
17
|
function h(a) {
|
|
17
|
-
let { label: o, name: s, value: h, defaultValue: g,
|
|
18
|
+
let { label: o, name: s, value: h, defaultValue: g, onValueChange: _, onChange: v, orientation: y = "vertical", children: b, props: x, ...S } = a, C = n("radiogroup"), w = l(null), T = l("click"), E = e((e, t) => {
|
|
19
|
+
_?.(e, t), v?.(e, t);
|
|
20
|
+
}), [D, O] = t({
|
|
18
21
|
value: h,
|
|
19
22
|
defaultValue: g,
|
|
20
|
-
onChange:
|
|
21
|
-
}),
|
|
23
|
+
onChange: E
|
|
24
|
+
}), k = e((e) => {
|
|
22
25
|
let t = m(e.key);
|
|
23
26
|
if (t === 0 || e.defaultPrevented) return;
|
|
24
|
-
let n = p(
|
|
27
|
+
let n = p(w.current), r = n.indexOf(document.activeElement);
|
|
25
28
|
if (r === -1) return;
|
|
26
29
|
e.preventDefault();
|
|
27
30
|
let i = n[(r + t + n.length) % n.length];
|
|
28
|
-
i !== n[r] && (
|
|
29
|
-
}),
|
|
30
|
-
name: s ??
|
|
31
|
-
value:
|
|
32
|
-
select: (e, t) =>
|
|
33
|
-
reason:
|
|
31
|
+
i !== n[r] && (T.current = "keyboard", i.focus(), i.click(), T.current = "click");
|
|
32
|
+
}), A = `${C}-label`, j = o != null, M = c(() => ({
|
|
33
|
+
name: s ?? C,
|
|
34
|
+
value: D,
|
|
35
|
+
select: (e, t) => O(e, {
|
|
36
|
+
reason: T.current,
|
|
34
37
|
event: t
|
|
35
38
|
})
|
|
36
39
|
}), [
|
|
37
|
-
|
|
40
|
+
C,
|
|
38
41
|
s,
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
D,
|
|
43
|
+
O
|
|
41
44
|
]);
|
|
42
45
|
return /* @__PURE__ */ u(f.Provider, {
|
|
43
|
-
value:
|
|
46
|
+
value: M,
|
|
44
47
|
children: /* @__PURE__ */ d(r, {
|
|
45
|
-
ref:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
...
|
|
48
|
+
ref: w,
|
|
49
|
+
component: "radioGroup",
|
|
50
|
+
variant: { horizontal: y === "horizontal" },
|
|
51
|
+
...S,
|
|
49
52
|
props: {
|
|
50
53
|
role: "radiogroup",
|
|
51
|
-
"aria-labelledby":
|
|
52
|
-
...
|
|
53
|
-
onKeyDown:
|
|
54
|
+
"aria-labelledby": j ? A : void 0,
|
|
55
|
+
...x,
|
|
56
|
+
onKeyDown: k
|
|
54
57
|
},
|
|
55
|
-
children: [
|
|
56
|
-
|
|
58
|
+
children: [j && /* @__PURE__ */ u(i, {
|
|
59
|
+
component: "radioGroup.label",
|
|
60
|
+
id: A,
|
|
57
61
|
children: o
|
|
58
|
-
}),
|
|
62
|
+
}), b]
|
|
59
63
|
})
|
|
60
64
|
});
|
|
61
65
|
}
|
|
62
|
-
function g(
|
|
63
|
-
let
|
|
64
|
-
return
|
|
65
|
-
name:
|
|
66
|
+
function g(t) {
|
|
67
|
+
let n = s(f), { value: r, ...i } = t, o = e((e) => n?.select(r, e));
|
|
68
|
+
return n ? /* @__PURE__ */ u(a, {
|
|
69
|
+
name: n.name,
|
|
66
70
|
value: r,
|
|
67
|
-
checked:
|
|
71
|
+
checked: n.value === r,
|
|
68
72
|
onChange: o,
|
|
69
73
|
...i
|
|
70
74
|
}) : /* @__PURE__ */ u(a, {
|
package/components/select.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { RefAttributes } from 'react';
|
|
2
2
|
import { BoxProps } from '../box';
|
|
3
|
+
import { ChangeHandler } from '../react/a11y/useControllableState';
|
|
3
4
|
import { BoxStyleProps, ComponentsAndVariants } from '@box-kite/core/types';
|
|
5
|
+
import { DropdownValueReason } from './dropdown';
|
|
4
6
|
interface SelectDef<TRow> {
|
|
5
7
|
/** Key of TRow to use as the option value */
|
|
6
8
|
valueKey: keyof TRow & (string | number);
|
|
@@ -33,6 +35,13 @@ interface Props<TRow, TVal extends TRow[keyof TRow], TKey extends keyof Componen
|
|
|
33
35
|
labelProps?: BoxProps<'div'>;
|
|
34
36
|
itemsProps?: BoxStyleProps;
|
|
35
37
|
iconProps?: BoxStyleProps;
|
|
38
|
+
/** Fires with the selection in whatever shape `value` takes, and why it changed — see `Dropdown`. */
|
|
39
|
+
onValueChange?: ChangeHandler<TVal | TVal[] | undefined, DropdownValueReason>;
|
|
40
|
+
/**
|
|
41
|
+
* The older callback, whose first argument is the option *acted on*. Both fire.
|
|
42
|
+
* @deprecated `onValueChange` is what every component reports a value change under, and it carries the
|
|
43
|
+
* reason. This spelling still works.
|
|
44
|
+
*/
|
|
36
45
|
onChange?: (value: TVal | undefined, values: TVal[]) => void;
|
|
37
46
|
}
|
|
38
47
|
interface SelectType {
|
package/components/semantics.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../rolldown-runtime.cjs"),t=require("../react-shared.cjs");let n=require("react"),r=require("react/jsx-runtime"),i=require("@box-kite/react");i=e.t(i,1);function a(e){let a=(0,n.forwardRef)((t,n)=>(0,r.jsx)(i.default,{tag:e,ref:n,component:e,...t}));return a.displayName=t.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../rolldown-runtime.cjs"),t=require("../react-shared.cjs");let n=require("react"),r=require("react/jsx-runtime"),i=require("@box-kite/react");i=e.t(i,1);function a(e){let a=(0,n.forwardRef)((t,n)=>(0,r.jsx)(i.default,{tag:e,ref:n,component:e,...t}));return a.displayName=t.a.capitalize(e),a}var o=a(`label`),s=a(`span`),c=a(`article`),l=a(`aside`),u=a(`details`),d=a(`figcaption`),f=a(`figure`),p=a(`footer`),m=a(`header`),h=a(`main`),g=a(`mark`),_=a(`nav`),v=a(`menu`),y=v,b=a(`section`),x=a(`summary`),S=a(`time`),C=a(`p`),w=a(`ul`),T=a(`ol`),E=a(`li`),D=a(`h1`),O=a(`h2`),k=a(`h3`),A=a(`h4`),j=a(`h5`),M=a(`h6`),N=a(`a`),P=a(`img`);exports.Article=c,exports.Aside=l,exports.Details=u,exports.Figcaption=d,exports.Figure=f,exports.Footer=p,exports.H1=D,exports.H2=O,exports.H3=k,exports.H4=A,exports.H5=j,exports.H6=M,exports.Header=m,exports.Img=P,exports.Label=o,exports.Li=E,exports.Link=N,exports.Main=h,exports.Mark=g,exports.Menu=y,exports.MenuList=v,exports.Nav=_,exports.Ol=T,exports.P=C,exports.Section=b,exports.Span=s,exports.Summary=x,exports.Time=S,exports.Ul=w;
|