@funstack/ui 0.1.0-alpha.4 → 0.1.0-alpha.6
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/accordion/accordion-item.mjs +2 -2
- package/dist/accordion/accordion-panel.mjs +2 -2
- package/dist/accordion/accordion-root.mjs +3 -3
- package/dist/accordion/accordion-trigger.mjs +2 -2
- package/dist/button/button.d.mts +78 -0
- package/dist/button/button.d.mts.map +1 -0
- package/dist/button/button.mjs +77 -0
- package/dist/button/button.mjs.map +1 -0
- package/dist/button/index.d.mts +3 -0
- package/dist/button/index.mjs +1 -0
- package/dist/checkbox/checkbox.mjs +2 -2
- package/dist/checkbox-group/checkbox-group-item.mjs +1 -1
- package/dist/checkbox-group/checkbox-group-parent.mjs +1 -1
- package/dist/checkbox-group/checkbox-group-root.mjs +1 -1
- package/dist/combobox/combobox-group.mjs +1 -1
- package/dist/combobox/combobox-list.mjs +1 -1
- package/dist/combobox/combobox-option.mjs +1 -1
- package/dist/combobox/combobox-popup.mjs +2 -2
- package/dist/combobox/combobox-root.mjs +3 -3
- package/dist/dialog/dialog-close.mjs +1 -1
- package/dist/dialog/dialog-form.mjs +1 -1
- package/dist/dialog/dialog-popup.mjs +3 -3
- package/dist/dialog/dialog-root.mjs +2 -2
- package/dist/field/field-root.mjs +3 -3
- package/dist/form/form-root.mjs +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +2 -1
- package/dist/internal/render-element.mjs +18 -5
- package/dist/internal/render-element.mjs.map +1 -1
- package/dist/internal/use-action-trigger.mjs +15 -6
- package/dist/internal/use-action-trigger.mjs.map +1 -1
- package/dist/internal/use-field-control.mjs +1 -1
- package/dist/internal/use-popover-root.mjs +1 -1
- package/dist/internal/use-render.mjs +2 -2
- package/dist/internal/use-render.mjs.map +1 -1
- package/dist/internal/use-roving-focus.mjs +66 -20
- package/dist/internal/use-roving-focus.mjs.map +1 -1
- package/dist/menu/menu-checkbox-item.mjs +2 -2
- package/dist/menu/menu-group.mjs +1 -1
- package/dist/menu/menu-item.mjs +1 -1
- package/dist/menu/menu-popup.mjs +1 -1
- package/dist/menu/menu-radio-group.mjs +1 -1
- package/dist/menu/menu-root.mjs +1 -1
- package/dist/menu/menu-submenu-trigger.mjs +1 -1
- package/dist/menu/menu-trigger.mjs +1 -1
- package/dist/number-field/number-field-increment.mjs +1 -1
- package/dist/number-field/number-field-input.mjs +1 -1
- package/dist/number-field/number-field-root.mjs +4 -4
- package/dist/popover/popover-close.mjs +1 -1
- package/dist/popover/popover-popup.mjs +2 -2
- package/dist/radio-group/radio-group-item.mjs +1 -1
- package/dist/radio-group/radio-group-root.mjs +1 -1
- package/dist/select/select-root.mjs +1 -1
- package/dist/slider/slider-root.mjs +5 -5
- package/dist/slider/slider-thumb.mjs +1 -1
- package/dist/slider/slider-value.mjs +1 -1
- package/dist/switch/switch.mjs +2 -2
- package/dist/tabs/tabs-list.mjs +1 -1
- package/dist/tabs/tabs-panel.mjs +1 -1
- package/dist/tabs/tabs-root.mjs +2 -2
- package/dist/tabs/tabs-tab.mjs +1 -1
- package/dist/toast/toast-action.mjs +1 -1
- package/dist/toast/toast-root.mjs +1 -1
- package/dist/toast/toast-viewport.mjs +3 -3
- package/dist/toggle/toggle.mjs +3 -3
- package/dist/toggle-group/toggle-group-item.mjs +1 -1
- package/dist/toggle-group/toggle-group-root.mjs +3 -3
- package/dist/toolbar/index.d.mts +4 -5
- package/dist/toolbar/index.d.mts.map +1 -1
- package/dist/toolbar/index.mjs +3 -4
- package/dist/toolbar/index.mjs.map +1 -1
- package/dist/toolbar/toolbar-root.mjs +1 -1
- package/dist/toolbar/toolbar-separator.mjs +1 -1
- package/dist/tooltip/tooltip-root.mjs +4 -2
- package/dist/tooltip/tooltip-root.mjs.map +1 -1
- package/package.json +2 -1
- package/dist/toolbar/toolbar-button.d.mts +0 -42
- package/dist/toolbar/toolbar-button.d.mts.map +0 -1
- package/dist/toolbar/toolbar-button.mjs +0 -50
- package/dist/toolbar/toolbar-button.mjs.map +0 -1
|
@@ -7,19 +7,23 @@ function report(error) {
|
|
|
7
7
|
else console.error(error);
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* The transition of a pure-trigger part: an `action` with no state of its own (`
|
|
11
|
-
* `Popover.Close`, `Menu.Item`; conventions 3.4). Same superseded-rejection
|
|
12
|
-
* `useControllableAction`: React keeps only the newest thenable per `useTransition`,
|
|
13
|
-
* rejection of a run that a later run superseded would be dropped. The hook catches it and
|
|
14
|
-
* it from render, so it reaches the same boundary as the latest run's rejection does.
|
|
10
|
+
* The transition of a pure-trigger part: an `action` with no state of its own (`Button`,
|
|
11
|
+
* `Dialog.Close`, `Popover.Close`, `Menu.Item`; conventions 3.4). Same superseded-rejection
|
|
12
|
+
* surfacing as `useControllableAction`: React keeps only the newest thenable per `useTransition`,
|
|
13
|
+
* so the rejection of a run that a later run superseded would be dropped. The hook catches it and
|
|
14
|
+
* throws it from render, so it reaches the same boundary as the latest run's rejection does.
|
|
15
|
+
*
|
|
16
|
+
* The argument is the options object, or (the older positional form) `openGeneration` alone.
|
|
15
17
|
*/
|
|
16
|
-
function useActionTrigger(
|
|
18
|
+
function useActionTrigger(options) {
|
|
19
|
+
const { openGeneration, ignoreWhilePending = false } = typeof options === "function" ? { openGeneration: options } : options ?? {};
|
|
17
20
|
const [supersededError, setSupersededError] = useState(null);
|
|
18
21
|
const hasSupersededError = useRef(false);
|
|
19
22
|
if (supersededError !== null) throw supersededError.error;
|
|
20
23
|
const [pending, startOwnTransition] = useTransition();
|
|
21
24
|
const latest = useRef(0);
|
|
22
25
|
const mounted = useRef(false);
|
|
26
|
+
const inFlight = useRef(0);
|
|
23
27
|
useEffect(() => {
|
|
24
28
|
mounted.current = true;
|
|
25
29
|
return () => {
|
|
@@ -27,12 +31,15 @@ function useActionTrigger(openGeneration) {
|
|
|
27
31
|
};
|
|
28
32
|
}, []);
|
|
29
33
|
const run = (work, then) => {
|
|
34
|
+
if (ignoreWhilePending && inFlight.current > 0) return false;
|
|
35
|
+
inFlight.current++;
|
|
30
36
|
const id = ++latest.current;
|
|
31
37
|
const generation = openGeneration?.();
|
|
32
38
|
startOwnTransition(async () => {
|
|
33
39
|
try {
|
|
34
40
|
await work();
|
|
35
41
|
} catch (error) {
|
|
42
|
+
inFlight.current--;
|
|
36
43
|
if (id === latest.current) throw error;
|
|
37
44
|
if (!mounted.current) return;
|
|
38
45
|
if (hasSupersededError.current) {
|
|
@@ -43,9 +50,11 @@ function useActionTrigger(openGeneration) {
|
|
|
43
50
|
setSupersededError({ error });
|
|
44
51
|
return;
|
|
45
52
|
}
|
|
53
|
+
inFlight.current--;
|
|
46
54
|
if (openGeneration !== void 0 && openGeneration() !== generation) return;
|
|
47
55
|
then?.();
|
|
48
56
|
});
|
|
57
|
+
return true;
|
|
49
58
|
};
|
|
50
59
|
return {
|
|
51
60
|
pending,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-action-trigger.mjs","names":[],"sources":["../../src/internal/use-action-trigger.ts"],"sourcesContent":["\"use client\";\nimport { useEffect, useRef, useState, useTransition } from \"react\";\n\nexport interface ActionTrigger {\n /** A run started through this hook is in flight (the part's own transition). */\n readonly pending: boolean;\n /**\n * Runs `work` inside the part's own transition and, once it resolves, `then` (still inside the\n * transition: a Close part's close, a menu item's close). A rejection skips `then` and reaches\n * the nearest Error Boundary above the part, also when a later run superseded this one. With\n * `openGeneration
|
|
1
|
+
{"version":3,"file":"use-action-trigger.mjs","names":[],"sources":["../../src/internal/use-action-trigger.ts"],"sourcesContent":["\"use client\";\nimport { useEffect, useRef, useState, useTransition } from \"react\";\n\nexport interface ActionTriggerOptions {\n /**\n * Open generation of the overlay a `then` belongs to: `then` is skipped when a newer open of\n * the overlay started after the run began.\n */\n readonly openGeneration?: (() => number) | undefined;\n /**\n * Ignore `run` while a run is in flight (conventions 2.5): `run` returns `false` and starts\n * nothing. In flight means the hook's synchronous in-flight counter is non-zero (it also sees\n * two activations in one task, before React re-rendered); the last render's `pending` is not\n * consulted, so a click in a settled-but-held commit window runs. Default `false`; on for\n * `Button` (#79) until #81 makes it the only behaviour.\n */\n readonly ignoreWhilePending?: boolean | undefined;\n}\n\nexport interface ActionTrigger {\n /** A run started through this hook is in flight (the part's own transition). */\n readonly pending: boolean;\n /**\n * Runs `work` inside the part's own transition and, once it resolves, `then` (still inside the\n * transition: a Close part's close, a menu item's close). A rejection skips `then` and reaches\n * the nearest Error Boundary above the part, also when a later run superseded this one. With\n * `openGeneration`, `then` is skipped when a newer open of the overlay started after the run\n * began. Returns `false` when the run was ignored (`ignoreWhilePending`), so the part can\n * `preventDefault()` the activation, and `true` otherwise.\n */\n readonly run: (work: () => unknown, then?: () => void) => boolean;\n}\n\n/** Reports an error that cannot reach a boundary (conventions 2.4: never swallow). */\nfunction report(error: unknown): void {\n if (typeof reportError === \"function\") reportError(error);\n else console.error(error);\n}\n\n/**\n * The transition of a pure-trigger part: an `action` with no state of its own (`Button`,\n * `Dialog.Close`, `Popover.Close`, `Menu.Item`; conventions 3.4). Same superseded-rejection\n * surfacing as `useControllableAction`: React keeps only the newest thenable per `useTransition`,\n * so the rejection of a run that a later run superseded would be dropped. The hook catches it and\n * throws it from render, so it reaches the same boundary as the latest run's rejection does.\n *\n * The argument is the options object, or (the older positional form) `openGeneration` alone.\n */\nexport function useActionTrigger(options?: ActionTriggerOptions | (() => number)): ActionTrigger {\n const { openGeneration, ignoreWhilePending = false }: ActionTriggerOptions =\n typeof options === \"function\" ? { openGeneration: options } : (options ?? {});\n\n // Thrown before `useTransition` on purpose (see use-controllable-action.ts): in the retry of\n // an errored render `useTransition` would suspend on the newer run's pending thenable.\n const [supersededError, setSupersededError] = useState<{ readonly error: unknown } | null>(null);\n const hasSupersededError = useRef(false);\n if (supersededError !== null) throw supersededError.error;\n\n const [pending, startOwnTransition] = useTransition();\n const latest = useRef(0);\n const mounted = useRef(false);\n // Runs whose work has not settled yet. Updated synchronously, so a second activation in the\n // same task (React's `pending` is still the stale render value) is seen (conventions 2.5).\n const inFlight = useRef(0);\n\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n\n const run = (work: () => unknown, then?: () => void): boolean => {\n // The own counter only, not the rendered `pending` (design/components/button.md 5.2): after\n // the work settled, a commit held by entanglement must not drop a new activation.\n if (ignoreWhilePending && inFlight.current > 0) return false;\n inFlight.current++;\n const id = ++latest.current;\n // The open this run belongs to (design/components/popover.md, review M2 / PO rule): if the\n // user dismisses and re-opens while the action runs, its close must not close the new open.\n const generation = openGeneration?.();\n startOwnTransition(async () => {\n try {\n await work();\n } catch (error) {\n inFlight.current--;\n // The latest run's rejection takes React's own route to the boundary.\n if (id === latest.current) throw error;\n if (!mounted.current) return;\n if (hasSupersededError.current) {\n report(error);\n return;\n }\n hasSupersededError.current = true;\n // After an await, outside the transition: urgent, so the part re-renders and throws.\n setSupersededError({ error });\n return;\n }\n inFlight.current--;\n if (openGeneration !== undefined && openGeneration() !== generation) return;\n then?.();\n });\n return true;\n };\n\n return { pending, run };\n}\n"],"mappings":";;;;AAkCA,SAAS,OAAO,OAAsB;CACpC,IAAI,OAAO,gBAAgB,YAAY,YAAY,KAAK;MACnD,QAAQ,MAAM,KAAK;AAC1B;;;;;;;;;;AAWA,SAAgB,iBAAiB,SAAgE;CAC/F,MAAM,EAAE,gBAAgB,qBAAqB,UAC3C,OAAO,YAAY,aAAa,EAAE,gBAAgB,QAAQ,IAAK,WAAW,CAAC;CAI7E,MAAM,CAAC,iBAAiB,sBAAsB,SAA6C,IAAI;CAC/F,MAAM,qBAAqB,OAAO,KAAK;CACvC,IAAI,oBAAoB,MAAM,MAAM,gBAAgB;CAEpD,MAAM,CAAC,SAAS,sBAAsB,cAAc;CACpD,MAAM,SAAS,OAAO,CAAC;CACvB,MAAM,UAAU,OAAO,KAAK;CAG5B,MAAM,WAAW,OAAO,CAAC;CAEzB,gBAAgB;EACd,QAAQ,UAAU;EAClB,aAAa;GACX,QAAQ,UAAU;EACpB;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,OAAO,MAAqB,SAA+B;EAG/D,IAAI,sBAAsB,SAAS,UAAU,GAAG,OAAO;EACvD,SAAS;EACT,MAAM,KAAK,EAAE,OAAO;EAGpB,MAAM,aAAa,iBAAiB;EACpC,mBAAmB,YAAY;GAC7B,IAAI;IACF,MAAM,KAAK;GACb,SAAS,OAAO;IACd,SAAS;IAET,IAAI,OAAO,OAAO,SAAS,MAAM;IACjC,IAAI,CAAC,QAAQ,SAAS;IACtB,IAAI,mBAAmB,SAAS;KAC9B,OAAO,KAAK;KACZ;IACF;IACA,mBAAmB,UAAU;IAE7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B;GACF;GACA,SAAS;GACT,IAAI,mBAAmB,KAAA,KAAa,eAAe,MAAM,YAAY;GACrE,OAAO;EACT,CAAC;EACD,OAAO;CACT;CAEA,OAAO;EAAE;EAAS;CAAI;AACxB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { dataAttr } from "./data-attr.mjs";
|
|
3
|
-
import { mergeRefs } from "./merge-props.mjs";
|
|
4
3
|
import { useDevWarning } from "./use-dev-warning.mjs";
|
|
4
|
+
import { mergeRefs } from "./merge-props.mjs";
|
|
5
5
|
import { FieldContext } from "./field-context.mjs";
|
|
6
6
|
import { use, useCallback, useLayoutEffect, useMemo, useRef } from "react";
|
|
7
7
|
//#region src/internal/use-field-control.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "./action-details.mjs";
|
|
3
|
+
import { useDevWarning } from "./use-dev-warning.mjs";
|
|
3
4
|
import { transitionTypes } from "./transition-types.mjs";
|
|
4
5
|
import { useLatest } from "./use-latest.mjs";
|
|
5
6
|
import { useControllableAction } from "./use-controllable-action.mjs";
|
|
6
|
-
import { useDevWarning } from "./use-dev-warning.mjs";
|
|
7
7
|
import { useCallback, useId, useMemo, useRef, useState } from "react";
|
|
8
8
|
//#region src/internal/use-popover-root.ts
|
|
9
9
|
function isPopoverOpen(element) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { mergeRefs } from "./merge-props.mjs";
|
|
3
|
-
import { renderElement, rendersButton, resolveStateValue } from "./render-element.mjs";
|
|
3
|
+
import { isHostButton, renderElement, rendersButton, resolveStateValue } from "./render-element.mjs";
|
|
4
4
|
import { isValidElement, useMemo } from "react";
|
|
5
5
|
//#region src/internal/use-render.tsx
|
|
6
6
|
/**
|
|
@@ -23,6 +23,6 @@ function useRender(options) {
|
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
//#endregion
|
|
26
|
-
export { rendersButton, resolveStateValue, useRender };
|
|
26
|
+
export { isHostButton, rendersButton, resolveStateValue, useRender };
|
|
27
27
|
|
|
28
28
|
//# sourceMappingURL=use-render.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-render.mjs","names":[],"sources":["../../src/internal/use-render.tsx"],"sourcesContent":["\"use client\";\nimport { isValidElement, useMemo } from \"react\";\nimport type { ReactNode, Ref } from \"react\";\nimport { mergeRefs } from \"./merge-props.js\";\nimport { renderElement } from \"./render-element.js\";\nimport type { ElementLikeProps, RenderElementOptions } from \"./render-element.js\";\n\nexport { rendersButton, resolveStateValue } from \"./render-element.js\";\nexport type { DataAttributes } from \"./render-element.js\";\n\nexport interface UseRenderOptions<Props extends ElementLikeProps, State> extends Omit<\n RenderElementOptions<Props, State>,\n \"ref\"\n> {\n /** The library's own ref, if the part needs the DOM node. */\n ref?: Ref<unknown> | undefined;\n}\n\n/**\n * Resolves `render` and the function-form `className` / `style` / `children` of a part against\n * its state and produces the element (conventions 1.2, 1.3, 1.4). The pure work is\n * `renderElement` (`render-element.ts`); this hook adds the memoised ref merge.\n */\nexport function useRender<Props extends ElementLikeProps, State>(\n options: UseRenderOptions<Props, State>,\n): ReactNode {\n const { render, props, ref } = options;\n\n const consumerRef = (props as ElementLikeProps).ref;\n const elementRef = isValidElement<ElementLikeProps>(render) ? render.props.ref : undefined;\n // Memoised so that the callback ref keeps its identity across renders and React does not\n // detach and re-attach the node every time.\n const mergedRef = useMemo(\n () => mergeRefs(ref, consumerRef, elementRef),\n [ref, consumerRef, elementRef],\n );\n\n return renderElement<Props, State>({ ...options, ref: mergedRef });\n}\n"],"mappings":";;;;;;;;;;AAuBA,SAAgB,UACd,SACW;CACX,MAAM,EAAE,QAAQ,OAAO,QAAQ;CAE/B,MAAM,cAAe,MAA2B;CAChD,MAAM,aAAa,eAAiC,MAAM,IAAI,OAAO,MAAM,MAAM,KAAA;CAGjF,MAAM,YAAY,cACV,UAAU,KAAK,aAAa,UAAU,GAC5C;EAAC;EAAK;EAAa;CAAU,CAC/B;CAEA,OAAO,cAA4B;EAAE,GAAG;EAAS,KAAK;CAAU,CAAC;AACnE"}
|
|
1
|
+
{"version":3,"file":"use-render.mjs","names":[],"sources":["../../src/internal/use-render.tsx"],"sourcesContent":["\"use client\";\nimport { isValidElement, useMemo } from \"react\";\nimport type { ReactNode, Ref } from \"react\";\nimport { mergeRefs } from \"./merge-props.js\";\nimport { renderElement } from \"./render-element.js\";\nimport type { ElementLikeProps, RenderElementOptions } from \"./render-element.js\";\n\nexport { isHostButton, rendersButton, resolveStateValue } from \"./render-element.js\";\nexport type { DataAttributes } from \"./render-element.js\";\n\nexport interface UseRenderOptions<Props extends ElementLikeProps, State> extends Omit<\n RenderElementOptions<Props, State>,\n \"ref\"\n> {\n /** The library's own ref, if the part needs the DOM node. */\n ref?: Ref<unknown> | undefined;\n}\n\n/**\n * Resolves `render` and the function-form `className` / `style` / `children` of a part against\n * its state and produces the element (conventions 1.2, 1.3, 1.4). The pure work is\n * `renderElement` (`render-element.ts`); this hook adds the memoised ref merge.\n */\nexport function useRender<Props extends ElementLikeProps, State>(\n options: UseRenderOptions<Props, State>,\n): ReactNode {\n const { render, props, ref } = options;\n\n const consumerRef = (props as ElementLikeProps).ref;\n const elementRef = isValidElement<ElementLikeProps>(render) ? render.props.ref : undefined;\n // Memoised so that the callback ref keeps its identity across renders and React does not\n // detach and re-attach the node every time.\n const mergedRef = useMemo(\n () => mergeRefs(ref, consumerRef, elementRef),\n [ref, consumerRef, elementRef],\n );\n\n return renderElement<Props, State>({ ...options, ref: mergedRef });\n}\n"],"mappings":";;;;;;;;;;AAuBA,SAAgB,UACd,SACW;CACX,MAAM,EAAE,QAAQ,OAAO,QAAQ;CAE/B,MAAM,cAAe,MAA2B;CAChD,MAAM,aAAa,eAAiC,MAAM,IAAI,OAAO,MAAM,MAAM,KAAA;CAGjF,MAAM,YAAY,cACV,UAAU,KAAK,aAAa,UAAU,GAC5C;EAAC;EAAK;EAAa;CAAU,CAC/B;CAEA,OAAO,cAA4B;EAAE,GAAG;EAAS,KAAK;CAAU,CAAC;AACnE"}
|
|
@@ -24,29 +24,56 @@ function isNestedOut(el, root) {
|
|
|
24
24
|
for (let node = el; node !== null && node !== root; node = node.parentElement) if (node.getAttribute("role") === "toolbar" || node.hasAttribute("popover") || node.tagName === "DIALOG") return true;
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
|
+
function isRadio(el) {
|
|
28
|
+
return el instanceof HTMLInputElement && el.type === "radio";
|
|
29
|
+
}
|
|
30
|
+
/** The unit's representative: its checked radio, else its first (design 17.2 item 2). */
|
|
31
|
+
function representative(unit) {
|
|
32
|
+
return unit.find((radio) => radio.checked) ?? unit[0];
|
|
33
|
+
}
|
|
27
34
|
/**
|
|
28
|
-
* The items of `root`
|
|
35
|
+
* The items of `root` (design 6.2 and 17.2): its focusable descendants minus `:disabled`,
|
|
29
36
|
* `inert`, invisible, nested-toolbar / popover / dialog content, and elements whose own
|
|
30
37
|
* `tabindex="-1"` was not written by this engine (`managed`). `aria-disabled` elements are items.
|
|
38
|
+
* Native radios that share a `name` form one unit, represented in `items` by its checked radio
|
|
39
|
+
* (else its first), at the position of the unit's first radio.
|
|
31
40
|
*/
|
|
32
|
-
function
|
|
33
|
-
const
|
|
41
|
+
function collectItems(root, managed) {
|
|
42
|
+
const candidates = [];
|
|
43
|
+
const byName = /* @__PURE__ */ new Map();
|
|
44
|
+
const units = /* @__PURE__ */ new Map();
|
|
34
45
|
for (const el of root.querySelectorAll(FOCUSABLE)) {
|
|
35
46
|
if (el.matches(":disabled")) continue;
|
|
36
47
|
if (el.closest("[inert]") !== null) continue;
|
|
37
48
|
if (el.getAttribute("tabindex") === "-1" && !managed.has(el)) continue;
|
|
38
49
|
if (isNestedOut(el, root)) continue;
|
|
39
50
|
if (!isVisible(el)) continue;
|
|
40
|
-
|
|
51
|
+
if (isRadio(el)) {
|
|
52
|
+
const unit = el.name === "" ? void 0 : byName.get(el.name);
|
|
53
|
+
if (unit !== void 0) {
|
|
54
|
+
unit.push(el);
|
|
55
|
+
units.set(el, unit);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const created = [el];
|
|
59
|
+
if (el.name !== "") byName.set(el.name, created);
|
|
60
|
+
units.set(el, created);
|
|
61
|
+
}
|
|
62
|
+
candidates.push(el);
|
|
41
63
|
}
|
|
42
|
-
return
|
|
64
|
+
return {
|
|
65
|
+
items: candidates.map((el) => {
|
|
66
|
+
const unit = units.get(el);
|
|
67
|
+
return unit === void 0 ? el : representative(unit);
|
|
68
|
+
}),
|
|
69
|
+
units
|
|
70
|
+
};
|
|
43
71
|
}
|
|
44
72
|
const BUTTON_LIKE_INPUTS = /* @__PURE__ */ new Set([
|
|
45
73
|
"button",
|
|
46
74
|
"submit",
|
|
47
75
|
"reset",
|
|
48
76
|
"checkbox",
|
|
49
|
-
"radio",
|
|
50
77
|
"image",
|
|
51
78
|
"color",
|
|
52
79
|
"file"
|
|
@@ -58,10 +85,12 @@ const ARROW_OWNING_ROLES = /* @__PURE__ */ new Set([
|
|
|
58
85
|
"slider"
|
|
59
86
|
]);
|
|
60
87
|
/**
|
|
61
|
-
* An item that owns the arrow keys (design 6.3): text-like `input`s, `textarea`,
|
|
62
|
-
* `[contenteditable]`,
|
|
88
|
+
* An item that owns the arrow keys (design 6.3 and 17.2): text-like `input`s, `textarea`,
|
|
89
|
+
* `select`, `[contenteditable]`, `role` `textbox` / `combobox` / `spinbutton` / `slider`, and a
|
|
90
|
+
* native `input[type=radio]` (its group's own arrows check as they move). A custom
|
|
91
|
+
* `[role="radio"]` is an ordinary item, as it is under native `focusgroup`.
|
|
63
92
|
*/
|
|
64
|
-
function
|
|
93
|
+
function ownsArrows(el) {
|
|
65
94
|
const role = el.getAttribute("role");
|
|
66
95
|
if (role !== null && ARROW_OWNING_ROLES.has(role)) return true;
|
|
67
96
|
if (el instanceof HTMLInputElement) return !BUTTON_LIKE_INPUTS.has(el.type);
|
|
@@ -114,16 +143,24 @@ function createEngine() {
|
|
|
114
143
|
release();
|
|
115
144
|
return;
|
|
116
145
|
}
|
|
117
|
-
const items =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
for (const
|
|
146
|
+
const { items, units } = collectItems(root, managed);
|
|
147
|
+
/** Every element the engine writes: the items and the other radios of their units. */
|
|
148
|
+
const all = new Set(items);
|
|
149
|
+
for (const radio of units.keys()) all.add(radio);
|
|
150
|
+
/** The item standing for `el`: its unit's representative for a radio, else itself. */
|
|
151
|
+
const itemOf = (el) => {
|
|
152
|
+
const unit = units.get(el);
|
|
153
|
+
return unit === void 0 ? el : representative(unit);
|
|
154
|
+
};
|
|
155
|
+
if (!options.memory) current = focused instanceof HTMLElement && all.has(focused) ? focused : options.entry(items) ?? null;
|
|
156
|
+
else if (current === null || !all.has(current) || !items.includes(itemOf(current))) current = options.entry(items) ?? null;
|
|
157
|
+
for (const el of all) {
|
|
121
158
|
if (!managed.has(el)) managed.set(el, el.getAttribute("tabindex"));
|
|
122
159
|
const want = el === current ? "0" : "-1";
|
|
123
160
|
if (el.getAttribute("tabindex") !== want) el.setAttribute("tabindex", want);
|
|
124
161
|
}
|
|
125
162
|
for (const el of [...managed.keys()]) {
|
|
126
|
-
if (
|
|
163
|
+
if (all.has(el)) continue;
|
|
127
164
|
if (!root.contains(el)) restore(el);
|
|
128
165
|
else if (el.getAttribute("tabindex") !== "-1") el.setAttribute("tabindex", "-1");
|
|
129
166
|
}
|
|
@@ -133,7 +170,8 @@ function createEngine() {
|
|
|
133
170
|
if (!active(options) || options.native) return;
|
|
134
171
|
const target = event.target;
|
|
135
172
|
if (!(target instanceof HTMLElement)) return;
|
|
136
|
-
|
|
173
|
+
const { items, units } = collectItems(event.currentTarget, managed);
|
|
174
|
+
if (!items.includes(target) && !units.has(target)) return;
|
|
137
175
|
current = target;
|
|
138
176
|
apply(event.currentTarget, target);
|
|
139
177
|
};
|
|
@@ -149,7 +187,8 @@ function createEngine() {
|
|
|
149
187
|
if (!active(options) || options.native) return;
|
|
150
188
|
const target = event.target;
|
|
151
189
|
if (!(target instanceof Node)) return;
|
|
152
|
-
const
|
|
190
|
+
const { items, units } = collectItems(event.currentTarget, managed);
|
|
191
|
+
const item = [...items, ...units.keys()].find((el) => el.contains(target));
|
|
153
192
|
if (item === void 0) return;
|
|
154
193
|
current = item;
|
|
155
194
|
apply(event.currentTarget, options.memory ? item : event.currentTarget.ownerDocument.activeElement);
|
|
@@ -161,11 +200,18 @@ function createEngine() {
|
|
|
161
200
|
const root = event.currentTarget;
|
|
162
201
|
const target = event.target;
|
|
163
202
|
if (!(target instanceof HTMLElement)) return;
|
|
164
|
-
const items =
|
|
165
|
-
const
|
|
203
|
+
const { items, units } = collectItems(root, managed);
|
|
204
|
+
const unit = units.get(target);
|
|
205
|
+
const index = items.indexOf(unit === void 0 ? target : representative(unit));
|
|
166
206
|
if (index < 0) return;
|
|
167
|
-
if (
|
|
207
|
+
if (ownsArrows(target)) {
|
|
168
208
|
if (event.key !== "Tab") return;
|
|
209
|
+
const checked = unit?.find((radio) => radio.checked);
|
|
210
|
+
if (checked !== void 0 && checked !== target) {
|
|
211
|
+
event.preventDefault();
|
|
212
|
+
focusItem(checked);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
169
215
|
const next = items[index + (event.shiftKey ? -1 : 1)];
|
|
170
216
|
if (next === void 0) return;
|
|
171
217
|
event.preventDefault();
|
|
@@ -250,6 +296,6 @@ function useRovingFocus(ref, options) {
|
|
|
250
296
|
return engine.handlers;
|
|
251
297
|
}
|
|
252
298
|
//#endregion
|
|
253
|
-
export {
|
|
299
|
+
export { collectItems, ownsArrows, useRovingFocus };
|
|
254
300
|
|
|
255
301
|
//# sourceMappingURL=use-roving-focus.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-roving-focus.mjs","names":[],"sources":["../../src/internal/use-roving-focus.ts"],"sourcesContent":["\"use client\";\nimport { useEffect, useInsertionEffect, useLayoutEffect, useState } from \"react\";\nimport type { FocusEvent, KeyboardEvent, PointerEvent, RefObject } from \"react\";\n\n// The roving-focus engine shared by `Toolbar.Root` and a standalone `ToggleGroup.Root`\n// (design/components/toggle-group.md section 6, conventions 3.2 and 7.4). Items are the focusable\n// descendants of the container, found in the DOM; which one is the Tab stop is urgent library\n// state kept outside React and written to the items as `tabindex` through the DOM.\n\nexport type RovingOrientation = \"horizontal\" | \"vertical\";\n\nexport interface RovingFocusOptions {\n /** `false`: the engine writes nothing and handles nothing (a ToggleGroup inside a Toolbar). Default `true`. */\n readonly enabled?: boolean;\n readonly orientation: RovingOrientation;\n readonly loop: boolean;\n /** The native `focusgroup` path is active: write no `tabindex`, handle no navigation key. */\n readonly native: boolean;\n /** Which item is the Tab stop when there is no usable memory. */\n readonly entry: (items: readonly HTMLElement[]) => HTMLElement | undefined;\n /**\n * `true`: the last focused item stays the Tab stop after focus leaves (Toolbar). `false`: while\n * focus is inside, the focused item is the stop (so Tab and Shift+Tab leave the container);\n * once it leaves, the stop is re-derived from `entry` (ToggleGroup: the pressed Item).\n */\n readonly memory: boolean;\n}\n\nexport interface RovingFocusHandlers {\n readonly onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;\n readonly onFocus: (event: FocusEvent<HTMLElement>) => void;\n readonly onBlur: (event: FocusEvent<HTMLElement>) => void;\n readonly onPointerDown: (event: PointerEvent<HTMLElement>) => void;\n}\n\nconst FOCUSABLE = [\n \"button\",\n \"a[href]\",\n 'input:not([type=\"hidden\"])',\n \"select\",\n \"textarea\",\n \"summary\",\n '[contenteditable]:not([contenteditable=\"false\"])',\n \"[tabindex]\",\n].join(\",\");\n\nfunction isVisible(el: HTMLElement): boolean {\n // jsdom has no `checkVisibility`; `hidden` is the part of it a test can observe there.\n if (typeof el.checkVisibility === \"function\") return el.checkVisibility();\n return el.closest(\"[hidden]\") === null;\n}\n\n/**\n * Whether `el` or an ancestor below `root` takes it out of `root`'s sequence: a nested toolbar\n * (its own sequence), a popover or a dialog rendered inside the container (a `Menu.Popup`'s items\n * are the menu's).\n */\nfunction isNestedOut(el: HTMLElement, root: HTMLElement): boolean {\n for (let node: Element | null = el; node !== null && node !== root; node = node.parentElement) {\n if (\n node.getAttribute(\"role\") === \"toolbar\" ||\n node.hasAttribute(\"popover\") ||\n node.tagName === \"DIALOG\"\n ) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * The items of `root` in DOM order (design 6.2): its focusable descendants minus `:disabled`,\n * `inert`, invisible, nested-toolbar / popover / dialog content, and elements whose own\n * `tabindex=\"-1\"` was not written by this engine (`managed`). `aria-disabled` elements are items.\n */\nexport function itemsOf(root: HTMLElement, managed: { has(el: Element): boolean }): HTMLElement[] {\n const items: HTMLElement[] = [];\n for (const el of root.querySelectorAll<HTMLElement>(FOCUSABLE)) {\n if (el.matches(\":disabled\")) continue;\n if (el.closest(\"[inert]\") !== null) continue;\n if (el.getAttribute(\"tabindex\") === \"-1\" && !managed.has(el)) continue;\n if (isNestedOut(el, root)) continue;\n if (!isVisible(el)) continue;\n items.push(el);\n }\n return items;\n}\n\nconst BUTTON_LIKE_INPUTS = new Set([\n \"button\",\n \"submit\",\n \"reset\",\n \"checkbox\",\n \"radio\",\n \"image\",\n \"color\",\n \"file\",\n]);\nconst ARROW_OWNING_ROLES = new Set([\"textbox\", \"combobox\", \"spinbutton\", \"slider\"]);\n\n/**\n * An item that owns the arrow keys (design 6.3): text-like `input`s, `textarea`, `select`,\n * `[contenteditable]`, and `role` `textbox` / `combobox` / `spinbutton` / `slider`.\n */\nexport function isTextEntryItem(el: Element): boolean {\n const role = el.getAttribute(\"role\");\n if (role !== null && ARROW_OWNING_ROLES.has(role)) return true;\n if (el instanceof HTMLInputElement) return !BUTTON_LIKE_INPUTS.has(el.type);\n if (el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) return true;\n const editable = el.getAttribute(\"contenteditable\");\n if (editable !== null && editable !== \"false\") return true;\n return el instanceof HTMLElement && el.isContentEditable === true;\n}\n\ntype Move = \"next\" | \"prev\" | \"first\" | \"last\";\n\nfunction resolveKey(key: string, orientation: RovingOrientation, rtl: boolean): Move | null {\n switch (key) {\n case \"Home\":\n return \"first\";\n case \"End\":\n return \"last\";\n case \"ArrowRight\":\n return orientation === \"horizontal\" ? (rtl ? \"prev\" : \"next\") : null;\n case \"ArrowLeft\":\n return orientation === \"horizontal\" ? (rtl ? \"next\" : \"prev\") : null;\n case \"ArrowDown\":\n return orientation === \"vertical\" ? \"next\" : null;\n case \"ArrowUp\":\n return orientation === \"vertical\" ? \"prev\" : null;\n default:\n return null;\n }\n}\n\nfunction focusItem(item: HTMLElement): void {\n // Keyboard focus: the ring shows even where the engine's heuristic would not (as Tabs).\n item.focus({ focusVisible: true } as FocusOptions);\n}\n\ninterface Engine {\n /** The options of the last committed render (written from an insertion effect). */\n readonly setOptions: (options: RovingFocusOptions) => void;\n /**\n * Re-derives the Tab stop of `root` and writes `tabindex`. `focused`: the element focus is on,\n * if any.\n */\n readonly apply: (root: HTMLElement | null, focused: Element | null) => void;\n readonly handlers: RovingFocusHandlers;\n}\n\nfunction createEngine(): Engine {\n let current: HTMLElement | null = null;\n let latestOptions: RovingFocusOptions | null = null;\n /**\n * Elements this engine wrote `tabindex` on, with the attribute value they had before the first\n * write (`null`: none). Restored when the engine lets go of an element (native path, element\n * left the container): React does not re-write a `tabIndex` prop it believes it rendered, so a\n * `[tabindex=\"0\"]` widget would otherwise become unreachable.\n */\n const managed = new Map<HTMLElement, string | null>();\n\n const restore = (el: HTMLElement) => {\n const original = managed.get(el);\n managed.delete(el);\n if (!el.isConnected || original === undefined) return;\n if (original === null) el.removeAttribute(\"tabindex\");\n else el.setAttribute(\"tabindex\", original);\n };\n\n const active = (options: RovingFocusOptions | null): options is RovingFocusOptions =>\n options !== null && options.enabled !== false;\n\n /** Native path: give back every `tabindex` this engine wrote (a hydration render may have). */\n const release = () => {\n for (const el of [...managed.keys()]) restore(el);\n current = null;\n };\n\n const apply = (root: HTMLElement | null, focused: Element | null) => {\n const options = latestOptions;\n if (root === null || !active(options)) return;\n if (options.native) {\n release();\n return;\n }\n const items = itemsOf(root, managed);\n if (!options.memory) {\n current =\n focused instanceof HTMLElement && items.includes(focused)\n ? focused\n : (options.entry(items) ?? null);\n } else if (current === null || !items.includes(current)) {\n current = options.entry(items) ?? null;\n }\n for (const el of items) {\n if (!managed.has(el)) managed.set(el, el.getAttribute(\"tabindex\"));\n const want = el === current ? \"0\" : \"-1\";\n if (el.getAttribute(\"tabindex\") !== want) el.setAttribute(\"tabindex\", want);\n }\n // Elements written before that are no longer items: a stale `0` must not stay a Tab stop\n // (it would be one again when re-enabled); one that left the container gets its own back.\n for (const el of [...managed.keys()]) {\n if (items.includes(el)) continue;\n if (!root.contains(el)) {\n restore(el);\n } else if (el.getAttribute(\"tabindex\") !== \"-1\") {\n el.setAttribute(\"tabindex\", \"-1\");\n }\n }\n };\n\n const onFocus = (event: FocusEvent<HTMLElement>) => {\n const options = latestOptions;\n if (!active(options) || options.native) return;\n const target = event.target;\n if (!(target instanceof HTMLElement)) return;\n const items = itemsOf(event.currentTarget, managed);\n if (!items.includes(target)) return;\n current = target;\n apply(event.currentTarget, target);\n };\n\n const onBlur = (event: FocusEvent<HTMLElement>) => {\n const options = latestOptions;\n if (!active(options) || options.native || options.memory) return;\n // Focus moving to another item is handled by its focus event.\n const next = event.relatedTarget;\n if (next instanceof Node && event.currentTarget.contains(next)) return;\n apply(event.currentTarget, null);\n };\n\n const onPointerDown = (event: PointerEvent<HTMLElement>) => {\n const options = latestOptions;\n if (!active(options) || options.native) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n const items = itemsOf(event.currentTarget, managed);\n // Safari does not focus a button on click; the pointer still makes it the stop.\n const item = items.find((el) => el.contains(target));\n if (item === undefined) return;\n current = item;\n apply(\n event.currentTarget,\n options.memory ? item : event.currentTarget.ownerDocument.activeElement,\n );\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLElement>) => {\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey) return;\n const options = latestOptions;\n // The browser moves focus itself where `focusgroup` is implemented.\n if (!active(options) || options.native) return;\n const root = event.currentTarget;\n const target = event.target;\n if (!(target instanceof HTMLElement)) return;\n const items = itemsOf(root, managed);\n const index = items.indexOf(target);\n if (index < 0) return;\n\n if (isTextEntryItem(target)) {\n // The item keeps its arrows, Home and End; Tab / Shift+Tab move to the next / previous item\n // while one exists, as Chromium's `focusgroup=\"toolbar\"` does (design 6.3).\n if (event.key !== \"Tab\") return;\n const next = items[index + (event.shiftKey ? -1 : 1)];\n if (next === undefined) return;\n event.preventDefault();\n focusItem(next);\n return;\n }\n\n const rtl = options.orientation === \"horizontal\" && getComputedStyle(root).direction === \"rtl\";\n const move = resolveKey(event.key, options.orientation, rtl);\n if (move === null) return;\n event.preventDefault();\n const last = items.length - 1;\n let nextIndex: number;\n switch (move) {\n case \"first\":\n nextIndex = 0;\n break;\n case \"last\":\n nextIndex = last;\n break;\n case \"next\":\n nextIndex = index >= last ? (options.loop ? 0 : last) : index + 1;\n break;\n case \"prev\":\n nextIndex = index <= 0 ? (options.loop ? last : 0) : index - 1;\n break;\n }\n const next = items[nextIndex];\n if (next !== undefined && next !== target) focusItem(next);\n };\n\n return {\n setOptions: (options) => {\n latestOptions = options;\n },\n apply,\n handlers: { onFocus, onBlur, onPointerDown, onKeyDown },\n };\n}\n\n/**\n * Roving focus over the focusable descendants of `ref`'s element (design 6.2). Writes `tabindex`\n * (`0` on the Tab stop, `-1` on the other items) from a layout effect after every commit of the\n * calling component, from a `MutationObserver` on the subtree and from focus / pointer events;\n * the items render none. Returns the container's handlers for its library props.\n */\nexport function useRovingFocus(\n ref: RefObject<HTMLElement | null>,\n options: RovingFocusOptions,\n): RovingFocusHandlers {\n const [engine] = useState(createEngine);\n // Before every layout effect of the same commit (as `useLatest`): handlers and the observer\n // read the options of the last committed render.\n useInsertionEffect(() => {\n engine.setOptions(options);\n });\n const enabled = options.enabled !== false;\n\n // After every commit of the container (a deps-less layout effect).\n useLayoutEffect(() => {\n const root = ref.current;\n engine.apply(root, root?.ownerDocument.activeElement ?? null);\n });\n\n // Children that change without the container re-rendering.\n useEffect(() => {\n const root = ref.current;\n if (!enabled || root === null) return;\n const observer = new MutationObserver(() => {\n engine.apply(root, root.ownerDocument.activeElement);\n });\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"disabled\", \"hidden\", \"inert\", \"aria-disabled\"],\n });\n return () => {\n observer.disconnect();\n };\n }, [engine, enabled, ref]);\n\n return engine.handlers;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-roving-focus.mjs","names":[],"sources":["../../src/internal/use-roving-focus.ts"],"sourcesContent":["\"use client\";\nimport { useEffect, useInsertionEffect, useLayoutEffect, useState } from \"react\";\nimport type { FocusEvent, KeyboardEvent, PointerEvent, RefObject } from \"react\";\n\n// The roving-focus engine shared by `Toolbar.Root` and a standalone `ToggleGroup.Root`\n// (design/components/toggle-group.md section 6, conventions 3.2 and 7.4). Items are the focusable\n// descendants of the container, found in the DOM; which one is the Tab stop is urgent library\n// state kept outside React and written to the items as `tabindex` through the DOM.\n\nexport type RovingOrientation = \"horizontal\" | \"vertical\";\n\nexport interface RovingFocusOptions {\n /** `false`: the engine writes nothing and handles nothing (a ToggleGroup inside a Toolbar). Default `true`. */\n readonly enabled?: boolean;\n readonly orientation: RovingOrientation;\n readonly loop: boolean;\n /** The native `focusgroup` path is active: write no `tabindex`, handle no navigation key. */\n readonly native: boolean;\n /** Which item is the Tab stop when there is no usable memory. */\n readonly entry: (items: readonly HTMLElement[]) => HTMLElement | undefined;\n /**\n * `true`: the last focused item stays the Tab stop after focus leaves (Toolbar). `false`: while\n * focus is inside, the focused item is the stop (so Tab and Shift+Tab leave the container);\n * once it leaves, the stop is re-derived from `entry` (ToggleGroup: the pressed Item).\n */\n readonly memory: boolean;\n}\n\nexport interface RovingFocusHandlers {\n readonly onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;\n readonly onFocus: (event: FocusEvent<HTMLElement>) => void;\n readonly onBlur: (event: FocusEvent<HTMLElement>) => void;\n readonly onPointerDown: (event: PointerEvent<HTMLElement>) => void;\n}\n\nconst FOCUSABLE = [\n \"button\",\n \"a[href]\",\n 'input:not([type=\"hidden\"])',\n \"select\",\n \"textarea\",\n \"summary\",\n '[contenteditable]:not([contenteditable=\"false\"])',\n \"[tabindex]\",\n].join(\",\");\n\nfunction isVisible(el: HTMLElement): boolean {\n // jsdom has no `checkVisibility`; `hidden` is the part of it a test can observe there.\n if (typeof el.checkVisibility === \"function\") return el.checkVisibility();\n return el.closest(\"[hidden]\") === null;\n}\n\n/**\n * Whether `el` or an ancestor below `root` takes it out of `root`'s sequence: a nested toolbar\n * (its own sequence), a popover or a dialog rendered inside the container (a `Menu.Popup`'s items\n * are the menu's).\n */\nfunction isNestedOut(el: HTMLElement, root: HTMLElement): boolean {\n for (let node: Element | null = el; node !== null && node !== root; node = node.parentElement) {\n if (\n node.getAttribute(\"role\") === \"toolbar\" ||\n node.hasAttribute(\"popover\") ||\n node.tagName === \"DIALOG\"\n ) {\n return true;\n }\n }\n return false;\n}\n\nfunction isRadio(el: Element): el is HTMLInputElement {\n return el instanceof HTMLInputElement && el.type === \"radio\";\n}\n\n/** The items of a container, with native radio groups collapsed into units (design 17.2). */\nexport interface RovingItems {\n /** The toolbar's own destinations in DOM order; a radio unit appears as its representative. */\n readonly items: HTMLElement[];\n /**\n * Every native radio among the candidates → the radios of its unit (same `name` under the\n * container, DOM order). A radio without a `name` is a unit of one.\n */\n readonly units: Map<HTMLElement, readonly HTMLInputElement[]>;\n}\n\n/** The unit's representative: its checked radio, else its first (design 17.2 item 2). */\nfunction representative(unit: readonly HTMLInputElement[]): HTMLInputElement {\n return unit.find((radio) => radio.checked) ?? unit[0]!;\n}\n\n/**\n * The items of `root` (design 6.2 and 17.2): its focusable descendants minus `:disabled`,\n * `inert`, invisible, nested-toolbar / popover / dialog content, and elements whose own\n * `tabindex=\"-1\"` was not written by this engine (`managed`). `aria-disabled` elements are items.\n * Native radios that share a `name` form one unit, represented in `items` by its checked radio\n * (else its first), at the position of the unit's first radio.\n */\nexport function collectItems(\n root: HTMLElement,\n managed: { has(el: Element): boolean },\n): RovingItems {\n const candidates: HTMLElement[] = [];\n const byName = new Map<string, HTMLInputElement[]>();\n const units = new Map<HTMLElement, readonly HTMLInputElement[]>();\n for (const el of root.querySelectorAll<HTMLElement>(FOCUSABLE)) {\n if (el.matches(\":disabled\")) continue;\n if (el.closest(\"[inert]\") !== null) continue;\n if (el.getAttribute(\"tabindex\") === \"-1\" && !managed.has(el)) continue;\n if (isNestedOut(el, root)) continue;\n if (!isVisible(el)) continue;\n if (isRadio(el)) {\n // Same form owner assumed: a `form=` attribute that splits a `name` is not handled (v1).\n const unit = el.name === \"\" ? undefined : byName.get(el.name);\n if (unit !== undefined) {\n unit.push(el);\n units.set(el, unit);\n continue;\n }\n const created = [el];\n if (el.name !== \"\") byName.set(el.name, created);\n units.set(el, created);\n }\n candidates.push(el);\n }\n // `candidates` holds each unit's first radio in its place; swap in the representative.\n const items = candidates.map((el) => {\n const unit = units.get(el);\n return unit === undefined ? el : representative(unit);\n });\n return { items, units };\n}\n\n/** {@link collectItems}'s `items`: the container's destinations in DOM order. */\nexport function itemsOf(root: HTMLElement, managed: { has(el: Element): boolean }): HTMLElement[] {\n return collectItems(root, managed).items;\n}\n\nconst BUTTON_LIKE_INPUTS = new Set([\n \"button\",\n \"submit\",\n \"reset\",\n \"checkbox\",\n \"image\",\n \"color\",\n \"file\",\n]);\nconst ARROW_OWNING_ROLES = new Set([\"textbox\", \"combobox\", \"spinbutton\", \"slider\"]);\n\n/**\n * An item that owns the arrow keys (design 6.3 and 17.2): text-like `input`s, `textarea`,\n * `select`, `[contenteditable]`, `role` `textbox` / `combobox` / `spinbutton` / `slider`, and a\n * native `input[type=radio]` (its group's own arrows check as they move). A custom\n * `[role=\"radio\"]` is an ordinary item, as it is under native `focusgroup`.\n */\nexport function ownsArrows(el: Element): boolean {\n const role = el.getAttribute(\"role\");\n if (role !== null && ARROW_OWNING_ROLES.has(role)) return true;\n if (el instanceof HTMLInputElement) return !BUTTON_LIKE_INPUTS.has(el.type);\n if (el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) return true;\n const editable = el.getAttribute(\"contenteditable\");\n if (editable !== null && editable !== \"false\") return true;\n return el instanceof HTMLElement && el.isContentEditable === true;\n}\n\ntype Move = \"next\" | \"prev\" | \"first\" | \"last\";\n\nfunction resolveKey(key: string, orientation: RovingOrientation, rtl: boolean): Move | null {\n switch (key) {\n case \"Home\":\n return \"first\";\n case \"End\":\n return \"last\";\n case \"ArrowRight\":\n return orientation === \"horizontal\" ? (rtl ? \"prev\" : \"next\") : null;\n case \"ArrowLeft\":\n return orientation === \"horizontal\" ? (rtl ? \"next\" : \"prev\") : null;\n case \"ArrowDown\":\n return orientation === \"vertical\" ? \"next\" : null;\n case \"ArrowUp\":\n return orientation === \"vertical\" ? \"prev\" : null;\n default:\n return null;\n }\n}\n\nfunction focusItem(item: HTMLElement): void {\n // Keyboard focus: the ring shows even where the engine's heuristic would not (as Tabs).\n item.focus({ focusVisible: true } as FocusOptions);\n}\n\ninterface Engine {\n /** The options of the last committed render (written from an insertion effect). */\n readonly setOptions: (options: RovingFocusOptions) => void;\n /**\n * Re-derives the Tab stop of `root` and writes `tabindex`. `focused`: the element focus is on,\n * if any.\n */\n readonly apply: (root: HTMLElement | null, focused: Element | null) => void;\n readonly handlers: RovingFocusHandlers;\n}\n\nfunction createEngine(): Engine {\n let current: HTMLElement | null = null;\n let latestOptions: RovingFocusOptions | null = null;\n /**\n * Elements this engine wrote `tabindex` on, with the attribute value they had before the first\n * write (`null`: none). Restored when the engine lets go of an element (native path, element\n * left the container): React does not re-write a `tabIndex` prop it believes it rendered, so a\n * `[tabindex=\"0\"]` widget would otherwise become unreachable.\n */\n const managed = new Map<HTMLElement, string | null>();\n\n const restore = (el: HTMLElement) => {\n const original = managed.get(el);\n managed.delete(el);\n if (!el.isConnected || original === undefined) return;\n if (original === null) el.removeAttribute(\"tabindex\");\n else el.setAttribute(\"tabindex\", original);\n };\n\n const active = (options: RovingFocusOptions | null): options is RovingFocusOptions =>\n options !== null && options.enabled !== false;\n\n /** Native path: give back every `tabindex` this engine wrote (a hydration render may have). */\n const release = () => {\n for (const el of [...managed.keys()]) restore(el);\n current = null;\n };\n\n const apply = (root: HTMLElement | null, focused: Element | null) => {\n const options = latestOptions;\n if (root === null || !active(options)) return;\n if (options.native) {\n release();\n return;\n }\n const { items, units } = collectItems(root, managed);\n /** Every element the engine writes: the items and the other radios of their units. */\n const all = new Set<HTMLElement>(items);\n for (const radio of units.keys()) all.add(radio);\n /** The item standing for `el`: its unit's representative for a radio, else itself. */\n const itemOf = (el: HTMLElement): HTMLElement => {\n const unit = units.get(el);\n return unit === undefined ? el : representative(unit);\n };\n if (!options.memory) {\n current =\n focused instanceof HTMLElement && all.has(focused)\n ? focused\n : (options.entry(items) ?? null);\n } else if (current === null || !all.has(current) || !items.includes(itemOf(current))) {\n current = options.entry(items) ?? null;\n }\n // `current` may be any radio of its unit (focus landed on an unchecked one): `0` on it, `-1`\n // on the unit's other radios and on every other element (design 17.2 item 5).\n for (const el of all) {\n if (!managed.has(el)) managed.set(el, el.getAttribute(\"tabindex\"));\n const want = el === current ? \"0\" : \"-1\";\n if (el.getAttribute(\"tabindex\") !== want) el.setAttribute(\"tabindex\", want);\n }\n // Elements written before that are no longer items: a stale `0` must not stay a Tab stop\n // (it would be one again when re-enabled); one that left the container gets its own back.\n for (const el of [...managed.keys()]) {\n if (all.has(el)) continue;\n if (!root.contains(el)) {\n restore(el);\n } else if (el.getAttribute(\"tabindex\") !== \"-1\") {\n el.setAttribute(\"tabindex\", \"-1\");\n }\n }\n };\n\n const onFocus = (event: FocusEvent<HTMLElement>) => {\n const options = latestOptions;\n if (!active(options) || options.native) return;\n const target = event.target;\n if (!(target instanceof HTMLElement)) return;\n const { items, units } = collectItems(event.currentTarget, managed);\n if (!items.includes(target) && !units.has(target)) return;\n current = target;\n apply(event.currentTarget, target);\n };\n\n const onBlur = (event: FocusEvent<HTMLElement>) => {\n const options = latestOptions;\n if (!active(options) || options.native || options.memory) return;\n // Focus moving to another item is handled by its focus event.\n const next = event.relatedTarget;\n if (next instanceof Node && event.currentTarget.contains(next)) return;\n apply(event.currentTarget, null);\n };\n\n const onPointerDown = (event: PointerEvent<HTMLElement>) => {\n const options = latestOptions;\n if (!active(options) || options.native) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n const { items, units } = collectItems(event.currentTarget, managed);\n // Safari does not focus a button on click; the pointer still makes it the stop.\n const item = [...items, ...units.keys()].find((el) => el.contains(target));\n if (item === undefined) return;\n current = item;\n apply(\n event.currentTarget,\n options.memory ? item : event.currentTarget.ownerDocument.activeElement,\n );\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLElement>) => {\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey) return;\n const options = latestOptions;\n // The browser moves focus itself where `focusgroup` is implemented.\n if (!active(options) || options.native) return;\n const root = event.currentTarget;\n const target = event.target;\n if (!(target instanceof HTMLElement)) return;\n const { items, units } = collectItems(root, managed);\n const unit = units.get(target);\n // A radio stands in `items` through its unit's representative.\n const index = items.indexOf(unit === undefined ? target : representative(unit));\n if (index < 0) return;\n\n if (ownsArrows(target)) {\n // The item keeps its arrows, Home and End; Tab / Shift+Tab move to the next / previous item\n // while one exists, as Chromium's `focusgroup=\"toolbar\"` does (design 6.3, 17.2 item 4).\n if (event.key !== \"Tab\") return;\n // From an unchecked radio whose sibling is checked: that sibling first (only the checked\n // radio of a group is sequentially focusable natively).\n const checked = unit?.find((radio) => radio.checked);\n if (checked !== undefined && checked !== target) {\n event.preventDefault();\n focusItem(checked);\n return;\n }\n const next = items[index + (event.shiftKey ? -1 : 1)];\n if (next === undefined) return;\n event.preventDefault();\n focusItem(next);\n return;\n }\n\n const rtl = options.orientation === \"horizontal\" && getComputedStyle(root).direction === \"rtl\";\n const move = resolveKey(event.key, options.orientation, rtl);\n if (move === null) return;\n event.preventDefault();\n const last = items.length - 1;\n let nextIndex: number;\n switch (move) {\n case \"first\":\n nextIndex = 0;\n break;\n case \"last\":\n nextIndex = last;\n break;\n case \"next\":\n nextIndex = index >= last ? (options.loop ? 0 : last) : index + 1;\n break;\n case \"prev\":\n nextIndex = index <= 0 ? (options.loop ? last : 0) : index - 1;\n break;\n }\n const next = items[nextIndex];\n if (next !== undefined && next !== target) focusItem(next);\n };\n\n return {\n setOptions: (options) => {\n latestOptions = options;\n },\n apply,\n handlers: { onFocus, onBlur, onPointerDown, onKeyDown },\n };\n}\n\n/**\n * Roving focus over the focusable descendants of `ref`'s element (design 6.2). Writes `tabindex`\n * (`0` on the Tab stop, `-1` on the other items) from a layout effect after every commit of the\n * calling component, from a `MutationObserver` on the subtree and from focus / pointer events;\n * the items render none. Returns the container's handlers for its library props.\n */\nexport function useRovingFocus(\n ref: RefObject<HTMLElement | null>,\n options: RovingFocusOptions,\n): RovingFocusHandlers {\n const [engine] = useState(createEngine);\n // Before every layout effect of the same commit (as `useLatest`): handlers and the observer\n // read the options of the last committed render.\n useInsertionEffect(() => {\n engine.setOptions(options);\n });\n const enabled = options.enabled !== false;\n\n // After every commit of the container (a deps-less layout effect).\n useLayoutEffect(() => {\n const root = ref.current;\n engine.apply(root, root?.ownerDocument.activeElement ?? null);\n });\n\n // Children that change without the container re-rendering.\n useEffect(() => {\n const root = ref.current;\n if (!enabled || root === null) return;\n const observer = new MutationObserver(() => {\n engine.apply(root, root.ownerDocument.activeElement);\n });\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"disabled\", \"hidden\", \"inert\", \"aria-disabled\"],\n });\n return () => {\n observer.disconnect();\n };\n }, [engine, enabled, ref]);\n\n return engine.handlers;\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "../internal/action-details.mjs";
|
|
3
3
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
-
import { transitionTypes } from "../internal/transition-types.mjs";
|
|
5
|
-
import { useControllableAction } from "../internal/use-controllable-action.mjs";
|
|
6
4
|
import { rendersButton } from "../internal/render-element.mjs";
|
|
7
5
|
import { useRender } from "../internal/use-render.mjs";
|
|
6
|
+
import { transitionTypes } from "../internal/transition-types.mjs";
|
|
7
|
+
import { useControllableAction } from "../internal/use-controllable-action.mjs";
|
|
8
8
|
import { closeStackLater, useMenuContext } from "./menu-context.mjs";
|
|
9
9
|
import { useMenuItem } from "./use-menu-item.mjs";
|
|
10
10
|
import { useRef } from "react";
|
package/dist/menu/menu-group.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useRender } from "../internal/use-render.mjs";
|
|
3
2
|
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
3
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
4
4
|
import { MenuGroupContext } from "./menu-context.mjs";
|
|
5
5
|
import { use, useId, useMemo } from "react";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
package/dist/menu/menu-item.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "../internal/action-details.mjs";
|
|
3
3
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useActionTrigger } from "../internal/use-action-trigger.mjs";
|
|
4
5
|
import { rendersButton } from "../internal/render-element.mjs";
|
|
5
6
|
import { useRender } from "../internal/use-render.mjs";
|
|
6
|
-
import { useActionTrigger } from "../internal/use-action-trigger.mjs";
|
|
7
7
|
import { useMenuContext } from "./menu-context.mjs";
|
|
8
8
|
import { useMenuItem } from "./use-menu-item.mjs";
|
|
9
9
|
//#region src/menu/menu-item.tsx
|
package/dist/menu/menu-popup.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { ToolbarContext } from "../internal/toolbar-context.mjs";
|
|
2
3
|
import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
|
|
3
4
|
import { mergeRefs } from "../internal/merge-props.mjs";
|
|
4
5
|
import { resolveStateValue } from "../internal/render-element.mjs";
|
|
5
6
|
import { useRender } from "../internal/use-render.mjs";
|
|
6
|
-
import { ToolbarContext } from "../internal/toolbar-context.mjs";
|
|
7
7
|
import { POSITION_TRY_FALLBACKS, positionArea } from "../internal/anchor-position.mjs";
|
|
8
8
|
import { usePopoverPopup } from "../internal/use-popover-popup.mjs";
|
|
9
9
|
import { MenuListContext, useMenuContext } from "./menu-context.mjs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "../internal/action-details.mjs";
|
|
3
3
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
4
5
|
import { transitionTypes } from "../internal/transition-types.mjs";
|
|
5
6
|
import { useControllableAction } from "../internal/use-controllable-action.mjs";
|
|
6
|
-
import { useRender } from "../internal/use-render.mjs";
|
|
7
7
|
import { MenuGroupContext, MenuRadioGroupContext } from "./menu-context.mjs";
|
|
8
8
|
import { useId, useMemo, useRef } from "react";
|
|
9
9
|
import { jsx } from "react/jsx-runtime";
|
package/dist/menu/menu-root.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { resolveStateValue } from "../internal/render-element.mjs";
|
|
3
2
|
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
3
|
+
import { resolveStateValue } from "../internal/render-element.mjs";
|
|
4
4
|
import { useDelayedPair } from "../internal/use-delayed-pair.mjs";
|
|
5
5
|
import { usePopoverRoot } from "../internal/use-popover-root.mjs";
|
|
6
6
|
import { MenuContext, MenuListContext } from "./menu-context.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useRender } from "../internal/use-render.mjs";
|
|
3
2
|
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
3
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
4
4
|
import { usePopoverTrigger } from "../internal/use-popover-trigger.mjs";
|
|
5
5
|
import { useMenuContext } from "./menu-context.mjs";
|
|
6
6
|
import { hasModifier, isRtl } from "./menu-dom.mjs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useRender } from "../internal/use-render.mjs";
|
|
3
2
|
import { useToolbarContext } from "../internal/toolbar-context.mjs";
|
|
4
3
|
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
4
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
5
5
|
import { usePopoverTrigger } from "../internal/use-popover-trigger.mjs";
|
|
6
6
|
import { useMenuContext } from "./menu-context.mjs";
|
|
7
7
|
import { edgeItem, focusItem, hasModifier, isRtl } from "./menu-dom.mjs";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
3
|
+
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
3
4
|
import { rendersButton } from "../internal/render-element.mjs";
|
|
4
5
|
import { useRender } from "../internal/use-render.mjs";
|
|
5
|
-
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
6
6
|
import { isAtBound } from "./number-field-arithmetic.mjs";
|
|
7
7
|
import { useNumberFieldContext } from "./number-field-context.mjs";
|
|
8
8
|
import { useStepButton } from "./use-step-button.mjs";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
3
|
+
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
3
4
|
import { mergeRefs } from "../internal/merge-props.mjs";
|
|
4
5
|
import { useRender } from "../internal/use-render.mjs";
|
|
5
|
-
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
6
6
|
import { useFieldControl, useMergedRef } from "../internal/use-field-control.mjs";
|
|
7
7
|
import { useNumberFieldContext } from "./number-field-context.mjs";
|
|
8
8
|
import { hiddenText } from "./number-field-root.mjs";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "../internal/action-details.mjs";
|
|
3
3
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useActionTrigger } from "../internal/use-action-trigger.mjs";
|
|
5
|
+
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
6
|
+
import { mergeTokenLists } from "../internal/merge-props.mjs";
|
|
7
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
4
8
|
import { transitionTypes } from "../internal/transition-types.mjs";
|
|
5
9
|
import { useLatest } from "../internal/use-latest.mjs";
|
|
6
10
|
import { useControllableAction } from "../internal/use-controllable-action.mjs";
|
|
7
|
-
import { mergeTokenLists } from "../internal/merge-props.mjs";
|
|
8
|
-
import { useRender } from "../internal/use-render.mjs";
|
|
9
|
-
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
10
|
-
import { useActionTrigger } from "../internal/use-action-trigger.mjs";
|
|
11
11
|
import { FieldContext } from "../internal/field-context.mjs";
|
|
12
12
|
import { useFieldValueChange } from "../internal/use-field-control.mjs";
|
|
13
13
|
import { useNativeGroupReconciliation } from "../internal/use-native-group-reconciliation.mjs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "../internal/action-details.mjs";
|
|
3
3
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useActionTrigger } from "../internal/use-action-trigger.mjs";
|
|
4
5
|
import { rendersButton } from "../internal/render-element.mjs";
|
|
5
6
|
import { useRender } from "../internal/use-render.mjs";
|
|
6
|
-
import { useActionTrigger } from "../internal/use-action-trigger.mjs";
|
|
7
7
|
import { usePopoverContext } from "./popover-context.mjs";
|
|
8
8
|
import { useCallback } from "react";
|
|
9
9
|
//#region src/popover/popover-close.tsx
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { ToolbarContext } from "../internal/toolbar-context.mjs";
|
|
2
3
|
import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
|
|
4
|
+
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
3
5
|
import { resolveStateValue } from "../internal/render-element.mjs";
|
|
4
6
|
import { useRender } from "../internal/use-render.mjs";
|
|
5
|
-
import { ToolbarContext } from "../internal/toolbar-context.mjs";
|
|
6
|
-
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
7
7
|
import { POSITION_TRY_FALLBACKS, positionArea } from "../internal/anchor-position.mjs";
|
|
8
8
|
import { PopoverPopupContext, usePopoverContext } from "./popover-context.mjs";
|
|
9
9
|
import { usePopoverPopup } from "../internal/use-popover-popup.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
|
|
3
2
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
3
|
+
import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
|
|
4
4
|
import { useRender } from "../internal/use-render.mjs";
|
|
5
5
|
import { guardCheckableChange, useNativeChecked } from "../internal/use-native-checked.mjs";
|
|
6
6
|
import { syncPresence } from "../internal/sync-presence.mjs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "../internal/action-details.mjs";
|
|
3
3
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
4
5
|
import { transitionTypes } from "../internal/transition-types.mjs";
|
|
5
6
|
import { useControllableAction } from "../internal/use-controllable-action.mjs";
|
|
6
|
-
import { useRender } from "../internal/use-render.mjs";
|
|
7
7
|
import { useFieldControl, useFieldValueChange, useMergedRef } from "../internal/use-field-control.mjs";
|
|
8
8
|
import { RadioGroupContext } from "./radio-group-context.mjs";
|
|
9
9
|
import { useNativeGroupReconciliation } from "../internal/use-native-group-reconciliation.mjs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "../internal/action-details.mjs";
|
|
3
3
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
4
5
|
import { transitionTypes } from "../internal/transition-types.mjs";
|
|
5
6
|
import { useControllableAction } from "../internal/use-controllable-action.mjs";
|
|
6
|
-
import { useRender } from "../internal/use-render.mjs";
|
|
7
7
|
import { fieldInputProps, useFieldControl, useFieldValueChange, useMergedRef } from "../internal/use-field-control.mjs";
|
|
8
8
|
import { SelectContext } from "./select-context.mjs";
|
|
9
9
|
import { useSelectPartRef } from "./select-dom.mjs";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createActionDetails } from "../internal/action-details.mjs";
|
|
3
3
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { useControllableAction } from "../internal/use-controllable-action.mjs";
|
|
4
|
+
import { useActionTrigger } from "../internal/use-action-trigger.mjs";
|
|
5
|
+
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
7
6
|
import { mergeTokenLists } from "../internal/merge-props.mjs";
|
|
8
7
|
import { resolveStateValue } from "../internal/render-element.mjs";
|
|
9
8
|
import { useRender } from "../internal/use-render.mjs";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { transitionTypes } from "../internal/transition-types.mjs";
|
|
10
|
+
import { useLatest } from "../internal/use-latest.mjs";
|
|
11
|
+
import { useControllableAction } from "../internal/use-controllable-action.mjs";
|
|
12
12
|
import { FieldContext } from "../internal/field-context.mjs";
|
|
13
13
|
import { useFieldControl, useFieldValueChange, useMergedRef } from "../internal/use-field-control.mjs";
|
|
14
14
|
import { useNativeGroupReconciliation } from "../internal/use-native-group-reconciliation.mjs";
|