@funstack/ui 0.1.0-alpha.5 → 0.1.0-alpha.7
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-clear.d.mts +6 -3
- package/dist/combobox/combobox-clear.d.mts.map +1 -1
- package/dist/combobox/combobox-clear.mjs +10 -5
- package/dist/combobox/combobox-clear.mjs.map +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/combobox/combobox-trigger.d.mts +6 -2
- package/dist/combobox/combobox-trigger.d.mts.map +1 -1
- package/dist/combobox/combobox-trigger.mjs +10 -4
- package/dist/combobox/combobox-trigger.mjs.map +1 -1
- package/dist/dialog/dialog-close.d.mts +8 -3
- package/dist/dialog/dialog-close.d.mts.map +1 -1
- package/dist/dialog/dialog-close.mjs +12 -8
- package/dist/dialog/dialog-close.mjs.map +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/dialog/dialog-trigger.d.mts +8 -3
- package/dist/dialog/dialog-trigger.d.mts.map +1 -1
- package/dist/dialog/dialog-trigger.mjs +15 -8
- package/dist/dialog/dialog-trigger.mjs.map +1 -1
- package/dist/field/field-root.mjs +3 -3
- package/dist/form/form-root.mjs +1 -1
- package/dist/form/form-submit.d.mts +4 -1
- package/dist/form/form-submit.d.mts.map +1 -1
- package/dist/form/form-submit.mjs.map +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 +17 -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-popover-trigger.mjs +6 -5
- package/dist/internal/use-popover-trigger.mjs.map +1 -1
- package/dist/internal/use-render.mjs +2 -2
- package/dist/internal/use-render.mjs.map +1 -1
- package/dist/menu/menu-checkbox-item.mjs +2 -2
- package/dist/menu/menu-dom.mjs +7 -1
- package/dist/menu/menu-dom.mjs.map +1 -1
- package/dist/menu/menu-group.mjs +1 -1
- package/dist/menu/menu-item.d.mts +6 -2
- package/dist/menu/menu-item.d.mts.map +1 -1
- package/dist/menu/menu-item.mjs +6 -4
- package/dist/menu/menu-item.mjs.map +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.d.mts +6 -3
- package/dist/menu/menu-trigger.d.mts.map +1 -1
- package/dist/menu/menu-trigger.mjs +3 -3
- package/dist/menu/menu-trigger.mjs.map +1 -1
- package/dist/number-field/number-field-decrement.d.mts +4 -3
- package/dist/number-field/number-field-decrement.d.mts.map +1 -1
- package/dist/number-field/number-field-decrement.mjs +4 -3
- package/dist/number-field/number-field-decrement.mjs.map +1 -1
- package/dist/number-field/number-field-increment.d.mts +8 -3
- package/dist/number-field/number-field-increment.d.mts.map +1 -1
- package/dist/number-field/number-field-increment.mjs +9 -6
- package/dist/number-field/number-field-increment.mjs.map +1 -1
- package/dist/number-field/number-field-input.mjs +1 -1
- package/dist/number-field/number-field-root.mjs +5 -5
- package/dist/number-field/number-field-root.mjs.map +1 -1
- package/dist/number-field/use-step-button.mjs +6 -1
- package/dist/number-field/use-step-button.mjs.map +1 -1
- package/dist/popover/popover-close.d.mts +9 -3
- package/dist/popover/popover-close.d.mts.map +1 -1
- package/dist/popover/popover-close.mjs +13 -8
- package/dist/popover/popover-close.mjs.map +1 -1
- package/dist/popover/popover-popup.mjs +2 -2
- package/dist/popover/popover-trigger.d.mts +8 -4
- package/dist/popover/popover-trigger.d.mts.map +1 -1
- package/dist/popover/popover-trigger.mjs +3 -3
- package/dist/popover/popover-trigger.mjs.map +1 -1
- 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 +6 -6
- package/dist/slider/slider-root.mjs.map +1 -1
- 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.d.mts +4 -3
- package/dist/toast/toast-action.d.mts.map +1 -1
- package/dist/toast/toast-action.mjs +8 -6
- package/dist/toast/toast-action.mjs.map +1 -1
- package/dist/toast/toast-root.mjs +1 -1
- package/dist/toast/toast-viewport.mjs +3 -3
- package/dist/toggle/toggle.d.mts +4 -1
- package/dist/toggle/toggle.d.mts.map +1 -1
- package/dist/toggle/toggle.mjs +16 -10
- package/dist/toggle/toggle.mjs.map +1 -1
- package/dist/toggle-group/toggle-group-item.d.mts +6 -2
- package/dist/toggle-group/toggle-group-item.d.mts.map +1 -1
- package/dist/toggle-group/toggle-group-item.mjs +10 -5
- package/dist/toggle-group/toggle-group-item.mjs.map +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/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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { dataAttr } from "./data-attr.mjs";
|
|
3
|
-
import { rendersButton } from "./render-element.mjs";
|
|
3
|
+
import { isHostButton, rendersButton } from "./render-element.mjs";
|
|
4
4
|
import { useCallback } from "react";
|
|
5
5
|
//#region src/internal/use-popover-trigger.ts
|
|
6
6
|
const isDev = process.env.NODE_ENV !== "production";
|
|
@@ -62,20 +62,21 @@ function usePopoverTrigger(ctx, options) {
|
|
|
62
62
|
onClick(event);
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
const ariaDisabled = disabledAs === "aria";
|
|
65
|
+
const ariaDisabled = disabledAs === "aria" || isLibrary && !isHostButton(render);
|
|
66
|
+
const noInvoker = ariaDisabled && disabled;
|
|
66
67
|
return {
|
|
67
68
|
state,
|
|
68
69
|
libraryProps: {
|
|
69
70
|
...rendersButton(render) && { type: "button" },
|
|
70
71
|
disabled: ariaDisabled ? void 0 : disabled,
|
|
71
72
|
...ariaDisabled && { "aria-disabled": disabled ? true : void 0 },
|
|
72
|
-
commandfor: ids.popup,
|
|
73
|
-
command: "toggle-popover",
|
|
73
|
+
commandfor: noInvoker ? void 0 : ids.popup,
|
|
74
|
+
command: noInvoker ? void 0 : "toggle-popover",
|
|
74
75
|
"aria-expanded": isLibrary ? state.open : false,
|
|
75
76
|
...merged,
|
|
76
77
|
"data-open": dataAttr(state.open),
|
|
77
78
|
"data-pending": dataAttr(state.pending),
|
|
78
|
-
"data-disabled": dataAttr(
|
|
79
|
+
"data-disabled": dataAttr(disabled)
|
|
79
80
|
},
|
|
80
81
|
ref
|
|
81
82
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-popover-trigger.mjs","names":[],"sources":["../../src/internal/use-popover-trigger.ts"],"sourcesContent":["\"use client\";\nimport { useCallback } from \"react\";\nimport type { ComponentPropsWithRef, DOMAttributes, MouseEvent } from \"react\";\nimport { dataAttr } from \"./data-attr.js\";\nimport type { RenderProp } from \"./types.js\";\nimport { rendersButton } from \"./use-render.js\";\nimport type { DataAttributes } from \"./use-render.js\";\nimport type { PopoverRootValue } from \"./use-popover-root.js\";\n\nexport interface PopoverTriggerHookState {\n /** Optimistic open state (library mode); `false` in JS-free mode. */\n readonly open: boolean;\n /** The Root's transition is pending (an open, a part-initiated close or a notification). */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\n/** Event handlers a component layers onto the Trigger's own (Menu's keys and hover intent). */\nexport type PopoverTriggerHandlers = Pick<\n DOMAttributes<HTMLButtonElement>,\n \"onClick\" | \"onKeyDown\" | \"onPointerMove\" | \"onPointerEnter\" | \"onPointerLeave\"\n>;\n\nexport interface UsePopoverTriggerOptions<State> {\n /** Public name of the part for development warnings (`\"Popover.Trigger\"`). */\n readonly part: string;\n readonly disabled: boolean;\n readonly render: RenderProp<ComponentPropsWithRef<\"button\">, State> | undefined;\n /**\n * Extra handlers, merged in front of the Trigger's own: for a key both define, the extra one\n * runs first (the consumer's pass-through handler still runs before both, conventions 1.2).\n */\n readonly handlers?: PopoverTriggerHandlers;\n /**\n * What a click does in library mode, after the command has been cancelled and `disabled`\n * checked. Default: toggle against `intended()` (`requestOpen` / `requestClose`). Menu's\n * SubmenuTrigger opens, or moves focus into an already open submenu, and never closes.\n */\n readonly activate?: (event: MouseEvent<HTMLElement>) => void;\n /**\n * How `disabled` is rendered. `\"native\"` (default): the `disabled` attribute, so the button is\n * no invoker at all. `\"aria\"`: `aria-disabled=\"true\"` and no `disabled` (a menu item stays\n * focusable); the click handler still refuses.\n */\n readonly disabledAs?: \"native\" | \"aria\";\n}\n\nexport interface PopoverTriggerHook {\n readonly state: PopoverTriggerHookState;\n /** Owned props (conventions 1.2) for `useRender`'s `libraryProps`. */\n readonly libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes;\n /** Registers the element as the Root's Trigger; pass as `useRender`'s `ref`. */\n readonly ref: (element: HTMLElement) => () => void;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\nfunction isPopoverOpen(element: Element | null): boolean {\n if (element === null) return false;\n try {\n return element.matches(\":popover-open\");\n } catch {\n return false;\n }\n}\n\n/**\n * The Trigger of a popover-like component (design/components/popover.md 14.3):\n * `button[commandfor][command=\"toggle-popover\"]` with `aria-expanded`. In JS-free mode the\n * browser runs the command and the Popup keeps `aria-expanded` current on the element. In library\n * mode the click is cancelled (so the command does not run) and toggles against what the user\n * already intends: an open through `requestOpen`, a library-owned close through `requestClose`.\n *\n * Menu adds `aria-haspopup=\"menu\"` and its own key handling on top.\n */\nexport function usePopoverTrigger<State>(\n ctx: PopoverRootValue,\n options: UsePopoverTriggerOptions<State>,\n): PopoverTriggerHook {\n const { part, disabled, render, handlers, activate, disabledAs = \"native\" } = options;\n const isLibrary = ctx.mode === \"library\";\n const { ids, triggerRef, popupRef } = ctx;\n\n const state: PopoverTriggerHookState = {\n open: ctx.optimistic,\n // Opens, part-initiated closes and dismissal notifications all belong to the Trigger (4.2).\n pending: ctx.pending,\n disabled,\n };\n\n const ref = useCallback(\n (element: HTMLElement) => {\n if (isDev && !isLibrary && element.tagName !== \"BUTTON\") {\n console.error(\n `${part}: rendered a <${element.tagName.toLowerCase()}> in JS-free mode. Only a ` +\n '<button> runs `command=\"toggle-popover\"`; this trigger will not open the popover. ' +\n \"Render a <button>, or put the component in library mode (`defaultOpen={false}`).\",\n );\n }\n triggerRef.current = element;\n // JS-free mode: the DOM owns `aria-expanded` (design 9). A Trigger that mounts after the\n // Popup (or is re-created) picks up the current state here.\n if (!isLibrary && popupRef.current !== null) {\n element.setAttribute(\"aria-expanded\", String(isPopoverOpen(popupRef.current)));\n }\n return () => {\n if (triggerRef.current === element) triggerRef.current = null;\n };\n },\n [isLibrary, part, triggerRef, popupRef],\n );\n\n const onClick = (event: MouseEvent<HTMLElement>) => {\n // Cancelling the click cancels the command (it runs as the button's activation behaviour,\n // only if the click was not cancelled). Enter and Space synthesise the same click.\n event.preventDefault();\n if (disabled) return;\n if (activate !== undefined) {\n activate(event);\n return;\n }\n const native = event.nativeEvent;\n if (ctx.intended()) ctx.requestClose(native, \"activate\");\n else ctx.requestOpen(native, \"activate\");\n };\n\n // The component's handlers first, then the Trigger's (design/components/menu.md 14). The click\n // handler is only owned when installed, so a render element keeps its own `onClick` in JS-free\n // mode.\n const merged: PopoverTriggerHandlers = { ...handlers };\n if (isLibrary) {\n const extra = handlers?.onClick;\n merged.onClick =\n extra === undefined\n ? onClick\n : (event) => {\n extra(event);\n onClick(event);\n };\n }\n const ariaDisabled = disabledAs === \"aria\";\n\n const libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes = {\n // `type` only applies to a <button>; on any other element the key is not owned.\n ...(rendersButton(render) && { type: \"button\" as const }),\n // Owned: a render element must not re-enable a disabled Trigger (in JS-free mode the browser\n // would run its command).
|
|
1
|
+
{"version":3,"file":"use-popover-trigger.mjs","names":[],"sources":["../../src/internal/use-popover-trigger.ts"],"sourcesContent":["\"use client\";\nimport { useCallback } from \"react\";\nimport type { ComponentPropsWithRef, DOMAttributes, MouseEvent } from \"react\";\nimport { dataAttr } from \"./data-attr.js\";\nimport type { RenderProp } from \"./types.js\";\nimport { isHostButton, rendersButton } from \"./use-render.js\";\nimport type { DataAttributes } from \"./use-render.js\";\nimport type { PopoverRootValue } from \"./use-popover-root.js\";\n\nexport interface PopoverTriggerHookState {\n /** Optimistic open state (library mode); `false` in JS-free mode. */\n readonly open: boolean;\n /** The Root's transition is pending (an open, a part-initiated close or a notification). */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\n/** Event handlers a component layers onto the Trigger's own (Menu's keys and hover intent). */\nexport type PopoverTriggerHandlers = Pick<\n DOMAttributes<HTMLButtonElement>,\n \"onClick\" | \"onKeyDown\" | \"onPointerMove\" | \"onPointerEnter\" | \"onPointerLeave\"\n>;\n\nexport interface UsePopoverTriggerOptions<State> {\n /** Public name of the part for development warnings (`\"Popover.Trigger\"`). */\n readonly part: string;\n readonly disabled: boolean;\n readonly render: RenderProp<ComponentPropsWithRef<\"button\">, State> | undefined;\n /**\n * Extra handlers, merged in front of the Trigger's own: for a key both define, the extra one\n * runs first (the consumer's pass-through handler still runs before both, conventions 1.2).\n */\n readonly handlers?: PopoverTriggerHandlers;\n /**\n * What a click does in library mode, after the command has been cancelled and `disabled`\n * checked. Default: toggle against `intended()` (`requestOpen` / `requestClose`). Menu's\n * SubmenuTrigger opens, or moves focus into an already open submenu, and never closes.\n */\n readonly activate?: (event: MouseEvent<HTMLElement>) => void;\n /**\n * How `disabled` is rendered. `\"native\"` (default): the `disabled` attribute, so the button is\n * no invoker at all; in library mode a link or component `render` still gets the `\"aria\"`\n * branch, because native `disabled` means nothing on a link and the installed click handler is\n * what refuses (#83). `\"aria\"`: `aria-disabled=\"true\"` and no `disabled` (a menu item stays\n * focusable); the click handler still refuses.\n */\n readonly disabledAs?: \"native\" | \"aria\";\n}\n\nexport interface PopoverTriggerHook {\n readonly state: PopoverTriggerHookState;\n /** Owned props (conventions 1.2) for `useRender`'s `libraryProps`. */\n readonly libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes;\n /** Registers the element as the Root's Trigger; pass as `useRender`'s `ref`. */\n readonly ref: (element: HTMLElement) => () => void;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\nfunction isPopoverOpen(element: Element | null): boolean {\n if (element === null) return false;\n try {\n return element.matches(\":popover-open\");\n } catch {\n return false;\n }\n}\n\n/**\n * The Trigger of a popover-like component (design/components/popover.md 14.3):\n * `button[commandfor][command=\"toggle-popover\"]` with `aria-expanded`. In JS-free mode the\n * browser runs the command and the Popup keeps `aria-expanded` current on the element. In library\n * mode the click is cancelled (so the command does not run) and toggles against what the user\n * already intends: an open through `requestOpen`, a library-owned close through `requestClose`.\n *\n * Menu adds `aria-haspopup=\"menu\"` and its own key handling on top.\n */\nexport function usePopoverTrigger<State>(\n ctx: PopoverRootValue,\n options: UsePopoverTriggerOptions<State>,\n): PopoverTriggerHook {\n const { part, disabled, render, handlers, activate, disabledAs = \"native\" } = options;\n const isLibrary = ctx.mode === \"library\";\n const { ids, triggerRef, popupRef } = ctx;\n\n const state: PopoverTriggerHookState = {\n open: ctx.optimistic,\n // Opens, part-initiated closes and dismissal notifications all belong to the Trigger (4.2).\n pending: ctx.pending,\n disabled,\n };\n\n const ref = useCallback(\n (element: HTMLElement) => {\n if (isDev && !isLibrary && element.tagName !== \"BUTTON\") {\n console.error(\n `${part}: rendered a <${element.tagName.toLowerCase()}> in JS-free mode. Only a ` +\n '<button> runs `command=\"toggle-popover\"`; this trigger will not open the popover. ' +\n \"Render a <button>, or put the component in library mode (`defaultOpen={false}`).\",\n );\n }\n triggerRef.current = element;\n // JS-free mode: the DOM owns `aria-expanded` (design 9). A Trigger that mounts after the\n // Popup (or is re-created) picks up the current state here.\n if (!isLibrary && popupRef.current !== null) {\n element.setAttribute(\"aria-expanded\", String(isPopoverOpen(popupRef.current)));\n }\n return () => {\n if (triggerRef.current === element) triggerRef.current = null;\n };\n },\n [isLibrary, part, triggerRef, popupRef],\n );\n\n const onClick = (event: MouseEvent<HTMLElement>) => {\n // Cancelling the click cancels the command (it runs as the button's activation behaviour,\n // only if the click was not cancelled). Enter and Space synthesise the same click.\n event.preventDefault();\n if (disabled) return;\n if (activate !== undefined) {\n activate(event);\n return;\n }\n const native = event.nativeEvent;\n if (ctx.intended()) ctx.requestClose(native, \"activate\");\n else ctx.requestOpen(native, \"activate\");\n };\n\n // The component's handlers first, then the Trigger's (design/components/menu.md 14). The click\n // handler is only owned when installed, so a render element keeps its own `onClick` in JS-free\n // mode.\n const merged: PopoverTriggerHandlers = { ...handlers };\n if (isLibrary) {\n const extra = handlers?.onClick;\n merged.onClick =\n extra === undefined\n ? onClick\n : (event) => {\n extra(event);\n onClick(event);\n };\n }\n // A link or component render in library mode: the click handler (installed only there) cancels\n // and refuses, so `aria-disabled` is safe and native `disabled` would mean nothing (#83). In\n // JS-free mode the command needs native `disabled` to stop it.\n const ariaDisabled = disabledAs === \"aria\" || (isLibrary && !isHostButton(render));\n // Disabled in the `aria-disabled` branch: no `commandfor` / `command` either. Without native\n // `disabled` the element would still be a live invoker before hydration (a component render\n // spreading onto a real <button>), and the command would run (wave 9 review M1).\n const noInvoker = ariaDisabled && disabled;\n\n const libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes = {\n // `type` only applies to a <button>; on any other element the key is not owned.\n ...(rendersButton(render) && { type: \"button\" as const }),\n // Owned: a render element must not re-enable a disabled Trigger (in JS-free mode the browser\n // would run its command). In the `aria-disabled` branch it is owned as absent.\n disabled: ariaDisabled ? undefined : disabled,\n ...(ariaDisabled && { \"aria-disabled\": disabled ? true : undefined }),\n commandfor: noInvoker ? undefined : ids.popup,\n command: noInvoker ? undefined : \"toggle-popover\",\n // Library mode: optimistic. JS-free mode: \"false\" in React; the Popup's `toggle` listener\n // writes the DOM value, and React never rewrites an unchanged prop.\n \"aria-expanded\": isLibrary ? state.open : false,\n ...merged,\n \"data-open\": dataAttr(state.open),\n \"data-pending\": dataAttr(state.pending),\n // Every mode: the styling hook agrees with the rendered `disabled` / `aria-disabled`\n // (conventions 1.2, wave 9 fold W8).\n \"data-disabled\": dataAttr(disabled),\n };\n\n return { state, libraryProps, ref };\n}\n"],"mappings":";;;;;AAyDA,MAAM,QAAQ,QAAQ,IAAI,aAAa;AAEvC,SAAS,cAAc,SAAkC;CACvD,IAAI,YAAY,MAAM,OAAO;CAC7B,IAAI;EACF,OAAO,QAAQ,QAAQ,eAAe;CACxC,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;AAWA,SAAgB,kBACd,KACA,SACoB;CACpB,MAAM,EAAE,MAAM,UAAU,QAAQ,UAAU,UAAU,aAAa,aAAa;CAC9E,MAAM,YAAY,IAAI,SAAS;CAC/B,MAAM,EAAE,KAAK,YAAY,aAAa;CAEtC,MAAM,QAAiC;EACrC,MAAM,IAAI;EAEV,SAAS,IAAI;EACb;CACF;CAEA,MAAM,MAAM,aACT,YAAyB;EACxB,IAAI,SAAS,CAAC,aAAa,QAAQ,YAAY,UAC7C,QAAQ,MACN,GAAG,KAAK,gBAAgB,QAAQ,QAAQ,YAAY,EAAE,iMAGxD;EAEF,WAAW,UAAU;EAGrB,IAAI,CAAC,aAAa,SAAS,YAAY,MACrC,QAAQ,aAAa,iBAAiB,OAAO,cAAc,SAAS,OAAO,CAAC,CAAC;EAE/E,aAAa;GACX,IAAI,WAAW,YAAY,SAAS,WAAW,UAAU;EAC3D;CACF,GACA;EAAC;EAAW;EAAM;EAAY;CAAQ,CACxC;CAEA,MAAM,WAAW,UAAmC;EAGlD,MAAM,eAAe;EACrB,IAAI,UAAU;EACd,IAAI,aAAa,KAAA,GAAW;GAC1B,SAAS,KAAK;GACd;EACF;EACA,MAAM,SAAS,MAAM;EACrB,IAAI,IAAI,SAAS,GAAG,IAAI,aAAa,QAAQ,UAAU;OAClD,IAAI,YAAY,QAAQ,UAAU;CACzC;CAKA,MAAM,SAAiC,EAAE,GAAG,SAAS;CACrD,IAAI,WAAW;EACb,MAAM,QAAQ,UAAU;EACxB,OAAO,UACL,UAAU,KAAA,IACN,WACC,UAAU;GACT,MAAM,KAAK;GACX,QAAQ,KAAK;EACf;CACR;CAIA,MAAM,eAAe,eAAe,UAAW,aAAa,CAAC,aAAa,MAAM;CAIhF,MAAM,YAAY,gBAAgB;CAsBlC,OAAO;EAAE;EAAO,cAAA;GAlBd,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;GAGvD,UAAU,eAAe,KAAA,IAAY;GACrC,GAAI,gBAAgB,EAAE,iBAAiB,WAAW,OAAO,KAAA,EAAU;GACnE,YAAY,YAAY,KAAA,IAAY,IAAI;GACxC,SAAS,YAAY,KAAA,IAAY;GAGjC,iBAAiB,YAAY,MAAM,OAAO;GAC1C,GAAG;GACH,aAAa,SAAS,MAAM,IAAI;GAChC,gBAAgB,SAAS,MAAM,OAAO;GAGtC,iBAAiB,SAAS,QAAQ;EAGT;EAAG;CAAI;AACpC"}
|
|
@@ -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"}
|
|
@@ -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-dom.mjs
CHANGED
|
@@ -8,8 +8,14 @@ function menuItems(popup) {
|
|
|
8
8
|
function isMenuItem(element, popup) {
|
|
9
9
|
return element.matches(ITEM_SELECTOR) && element.closest("[role=\"menu\"]") === popup;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Disabled by its `disabled` prop. Keys on `data-disabled`, not `aria-disabled`: an item is also
|
|
13
|
+
* `aria-disabled` while its own action is pending (#81). A pending item is an ordinary item for
|
|
14
|
+
* navigation; only the open focus (`edgeItem`) skips items with the `disabled` prop. Arrow keys,
|
|
15
|
+
* Home / End and typeahead skip nothing.
|
|
16
|
+
*/
|
|
11
17
|
function isDisabledItem(item) {
|
|
12
|
-
return item.
|
|
18
|
+
return item.hasAttribute("data-disabled");
|
|
13
19
|
}
|
|
14
20
|
/** The first (or last) enabled item; the first (or last) item if all are disabled. */
|
|
15
21
|
function edgeItem(popup, which) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-dom.mjs","names":[],"sources":["../../src/menu/menu-dom.ts"],"sourcesContent":["\"use client\";\n// DOM helpers shared by the Menu parts. Items are read from the DOM when they are needed (a key\n// press, an open), never registered (design/components/menu.md 13 and 14).\n\nconst ITEM_SELECTOR = '[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]';\n\n/** The items of `popup` in DOM order, without the items of its submenus. Disabled included. */\nexport function menuItems(popup: Element): HTMLElement[] {\n return Array.from(popup.querySelectorAll<HTMLElement>(ITEM_SELECTOR)).filter(\n (item) => item.closest('[role=\"menu\"]') === popup,\n );\n}\n\nexport function isMenuItem(element: Element, popup: Element): boolean {\n return element.matches(ITEM_SELECTOR) && element.closest('[role=\"menu\"]') === popup;\n}\n\nexport function isDisabledItem(item: Element): boolean {\n return item.
|
|
1
|
+
{"version":3,"file":"menu-dom.mjs","names":[],"sources":["../../src/menu/menu-dom.ts"],"sourcesContent":["\"use client\";\n// DOM helpers shared by the Menu parts. Items are read from the DOM when they are needed (a key\n// press, an open), never registered (design/components/menu.md 13 and 14).\n\nconst ITEM_SELECTOR = '[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]';\n\n/** The items of `popup` in DOM order, without the items of its submenus. Disabled included. */\nexport function menuItems(popup: Element): HTMLElement[] {\n return Array.from(popup.querySelectorAll<HTMLElement>(ITEM_SELECTOR)).filter(\n (item) => item.closest('[role=\"menu\"]') === popup,\n );\n}\n\nexport function isMenuItem(element: Element, popup: Element): boolean {\n return element.matches(ITEM_SELECTOR) && element.closest('[role=\"menu\"]') === popup;\n}\n\n/**\n * Disabled by its `disabled` prop. Keys on `data-disabled`, not `aria-disabled`: an item is also\n * `aria-disabled` while its own action is pending (#81). A pending item is an ordinary item for\n * navigation; only the open focus (`edgeItem`) skips items with the `disabled` prop. Arrow keys,\n * Home / End and typeahead skip nothing.\n */\nexport function isDisabledItem(item: Element): boolean {\n return item.hasAttribute(\"data-disabled\");\n}\n\n/** The first (or last) enabled item; the first (or last) item if all are disabled. */\nexport function edgeItem(popup: Element, which: \"first\" | \"last\"): HTMLElement | null {\n const items = menuItems(popup);\n const ordered = which === \"first\" ? items : [...items].reverse();\n return ordered.find((item) => !isDisabledItem(item)) ?? ordered[0] ?? null;\n}\n\n/** Keyboard focus: the ring shows even where the engine's heuristic would not (as Tabs). */\nexport function focusItem(item: HTMLElement): void {\n item.focus({ focusVisible: true } as FocusOptions);\n}\n\n/** The text typeahead matches: the item's `label` prop, else its text content. */\nexport function typeaheadText(item: Element): string {\n return (item.getAttribute(\"data-typeahead\") ?? item.textContent ?? \"\").trim().toLowerCase();\n}\n\nexport function isRtl(element: Element): boolean {\n return getComputedStyle(element).direction === \"rtl\";\n}\n\nexport function hasModifier(event: { altKey: boolean; ctrlKey: boolean; metaKey: boolean }) {\n return event.altKey || event.ctrlKey || event.metaKey;\n}\n"],"mappings":";;AAIA,MAAM,gBAAgB;;AAGtB,SAAgB,UAAU,OAA+B;CACvD,OAAO,MAAM,KAAK,MAAM,iBAA8B,aAAa,CAAC,CAAC,CAAC,QACnE,SAAS,KAAK,QAAQ,iBAAe,MAAM,KAC9C;AACF;AAEA,SAAgB,WAAW,SAAkB,OAAyB;CACpE,OAAO,QAAQ,QAAQ,aAAa,KAAK,QAAQ,QAAQ,iBAAe,MAAM;AAChF;;;;;;;AAQA,SAAgB,eAAe,MAAwB;CACrD,OAAO,KAAK,aAAa,eAAe;AAC1C;;AAGA,SAAgB,SAAS,OAAgB,OAA6C;CACpF,MAAM,QAAQ,UAAU,KAAK;CAC7B,MAAM,UAAU,UAAU,UAAU,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,QAAQ;CAC/D,OAAO,QAAQ,MAAM,SAAS,CAAC,eAAe,IAAI,CAAC,KAAK,QAAQ,MAAM;AACxE;;AAGA,SAAgB,UAAU,MAAyB;CACjD,KAAK,MAAM,EAAE,cAAc,KAAK,CAAiB;AACnD;;AAGA,SAAgB,cAAc,MAAuB;CACnD,QAAQ,KAAK,aAAa,gBAAgB,KAAK,KAAK,eAAe,GAAA,CAAI,KAAK,CAAC,CAAC,YAAY;AAC5F;AAEA,SAAgB,MAAM,SAA2B;CAC/C,OAAO,iBAAiB,OAAO,CAAC,CAAC,cAAc;AACjD;AAEA,SAAgB,YAAY,OAAgE;CAC1F,OAAO,MAAM,UAAU,MAAM,WAAW,MAAM;AAChD"}
|
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";
|
|
@@ -18,7 +18,10 @@ export interface MenuItemProps extends Omit<ComponentPropsWithRef<"button">, "on
|
|
|
18
18
|
action?: Action<[details: MenuItemDetails]>;
|
|
19
19
|
/** Close the whole menu once `action` settles. Default `true`. */
|
|
20
20
|
closeOnActivate?: boolean;
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Renders `aria-disabled` and `data-disabled`: the item stays focusable and never activates.
|
|
23
|
+
* It is an ordinary item for navigation; only the open focus skips items with `disabled`.
|
|
24
|
+
*/
|
|
22
25
|
disabled?: boolean;
|
|
23
26
|
/** Text typeahead matches when the item's text content is not representative (an icon). */
|
|
24
27
|
label?: string;
|
|
@@ -29,7 +32,8 @@ export interface MenuItemProps extends Omit<ComponentPropsWithRef<"button">, "on
|
|
|
29
32
|
}
|
|
30
33
|
/**
|
|
31
34
|
* A menu command: `<button type="button" role="menuitem" tabindex="-1">`. Click, Enter or Space
|
|
32
|
-
* runs `action` in the item's own transition
|
|
35
|
+
* runs `action` in the item's own transition (`data-pending` and `aria-disabled` on the item; a
|
|
36
|
+
* second activation meanwhile is ignored); once it resolves the whole menu stack closes
|
|
33
37
|
* through the top-level Root (`openChangeAction(false, { reason: "activate" })` awaited, view
|
|
34
38
|
* transition if set). Hovering the item focuses it.
|
|
35
39
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-item.d.mts","names":[],"sources":["../../src/menu/menu-item.tsx"],"mappings":";;;;iBAWiB,wBAAwB;iBAExB;;WAEN;WACA;;iBAGM,sBAAsB,KACrC;;;;;;;EASA,SAAS,QAAQ,SAAS;;EAE1B;;EAEA
|
|
1
|
+
{"version":3,"file":"menu-item.d.mts","names":[],"sources":["../../src/menu/menu-item.tsx"],"mappings":";;;;iBAWiB,wBAAwB;iBAExB;;WAEN;WACA;;iBAGM,sBAAsB,KACrC;;;;;;;EASA,SAAS,QAAQ,SAAS;;EAE1B;;;;;EAKA;;EAEA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;;wBAcvC,WACd,QACA,iBACA,UACA,OACA,WACA,OACA,UACA,WACG,QACF,gBAAa;yBAVA"}
|
package/dist/menu/menu-item.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
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
|
|
10
10
|
/**
|
|
11
11
|
* A menu command: `<button type="button" role="menuitem" tabindex="-1">`. Click, Enter or Space
|
|
12
|
-
* runs `action` in the item's own transition
|
|
12
|
+
* runs `action` in the item's own transition (`data-pending` and `aria-disabled` on the item; a
|
|
13
|
+
* second activation meanwhile is ignored); once it resolves the whole menu stack closes
|
|
13
14
|
* through the top-level Root (`openChangeAction(false, { reason: "activate" })` awaited, view
|
|
14
15
|
* transition if set). Hovering the item focuses it.
|
|
15
16
|
*
|
|
@@ -19,7 +20,7 @@ import { useMenuItem } from "./use-menu-item.mjs";
|
|
|
19
20
|
*/
|
|
20
21
|
function MenuItem({ action, closeOnActivate = true, disabled = false, label, className, style, children, render, ...rest }) {
|
|
21
22
|
const menu = useMenuContext("Menu.Item");
|
|
22
|
-
const { pending, run } = useActionTrigger(menu.root.popover.openGeneration);
|
|
23
|
+
const { pending, run } = useActionTrigger({ openGeneration: menu.root.popover.openGeneration });
|
|
23
24
|
const { libraryProps } = useMenuItem({
|
|
24
25
|
part: "Menu.Item",
|
|
25
26
|
role: "menuitem",
|
|
@@ -27,7 +28,7 @@ function MenuItem({ action, closeOnActivate = true, disabled = false, label, cla
|
|
|
27
28
|
label,
|
|
28
29
|
activate: (event) => {
|
|
29
30
|
const details = createActionDetails(event, {});
|
|
30
|
-
run(() => action?.(details), closeOnActivate ? () => menu.root.popover.requestClose(event, "activate") : void 0);
|
|
31
|
+
if (!run(() => action?.(details), closeOnActivate ? () => menu.root.popover.requestClose(event, "activate") : void 0)) event.preventDefault();
|
|
31
32
|
}
|
|
32
33
|
});
|
|
33
34
|
return useRender({
|
|
@@ -44,6 +45,7 @@ function MenuItem({ action, closeOnActivate = true, disabled = false, label, cla
|
|
|
44
45
|
libraryProps: {
|
|
45
46
|
...rendersButton(render) && { type: "button" },
|
|
46
47
|
...libraryProps,
|
|
48
|
+
"aria-disabled": disabled || pending ? true : void 0,
|
|
47
49
|
"data-pending": dataAttr(pending)
|
|
48
50
|
}
|
|
49
51
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-item.mjs","names":[],"sources":["../../src/menu/menu-item.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { Action, ActionDetails, RenderProp, StateValue } from \"../internal/types.js\";\nimport { useActionTrigger } from \"../internal/use-action-trigger.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\nimport { useMenuContext } from \"./menu-context.js\";\nimport { useMenuItem } from \"./use-menu-item.js\";\n\n/** Details passed to `Menu.Item`'s `action`. */\nexport interface MenuItemDetails extends ActionDetails {}\n\nexport interface MenuItemState {\n /** This item's `action` is in flight. */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface MenuItemProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"onKeyDown\" | \"onPointerMove\" | \"disabled\" | \"className\" | \"style\" | \"children\"\n> {\n /**\n * Runs inside this item's own transition (`data-pending` on the item); the menu stays open\n * until it settles, then the whole menu closes (`closeOnActivate`). May be a Server Function\n * (`details.event` is virtual). A rejection leaves the menu open and reaches the nearest Error\n * Boundary above the item. Without `action`, activation only closes.\n */\n action?: Action<[details: MenuItemDetails]>;\n /** Close the whole menu once `action` settles. Default `true`. */\n closeOnActivate?: boolean;\n
|
|
1
|
+
{"version":3,"file":"menu-item.mjs","names":[],"sources":["../../src/menu/menu-item.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { Action, ActionDetails, RenderProp, StateValue } from \"../internal/types.js\";\nimport { useActionTrigger } from \"../internal/use-action-trigger.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\nimport { useMenuContext } from \"./menu-context.js\";\nimport { useMenuItem } from \"./use-menu-item.js\";\n\n/** Details passed to `Menu.Item`'s `action`. */\nexport interface MenuItemDetails extends ActionDetails {}\n\nexport interface MenuItemState {\n /** This item's `action` is in flight. */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface MenuItemProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"onKeyDown\" | \"onPointerMove\" | \"disabled\" | \"className\" | \"style\" | \"children\"\n> {\n /**\n * Runs inside this item's own transition (`data-pending` on the item); the menu stays open\n * until it settles, then the whole menu closes (`closeOnActivate`). May be a Server Function\n * (`details.event` is virtual). A rejection leaves the menu open and reaches the nearest Error\n * Boundary above the item. Without `action`, activation only closes.\n */\n action?: Action<[details: MenuItemDetails]>;\n /** Close the whole menu once `action` settles. Default `true`. */\n closeOnActivate?: boolean;\n /**\n * Renders `aria-disabled` and `data-disabled`: the item stays focusable and never activates.\n * It is an ordinary item for navigation; only the open focus skips items with `disabled`.\n */\n disabled?: boolean;\n /** Text typeahead matches when the item's text content is not representative (an icon). */\n label?: string;\n className?: StateValue<string | undefined, MenuItemState>;\n style?: StateValue<CSSProperties | undefined, MenuItemState>;\n children?: StateValue<ReactNode, MenuItemState>;\n render?: RenderProp<ComponentPropsWithRef<\"button\">, MenuItemState>;\n}\n\n/**\n * A menu command: `<button type=\"button\" role=\"menuitem\" tabindex=\"-1\">`. Click, Enter or Space\n * runs `action` in the item's own transition (`data-pending` and `aria-disabled` on the item; a\n * second activation meanwhile is ignored); once it resolves the whole menu stack closes\n * through the top-level Root (`openChangeAction(false, { reason: \"activate\" })` awaited, view\n * transition if set). Hovering the item focuses it.\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>`), `role`, `tabIndex`, `disabled`\n * (always absent), `aria-disabled`, `onClick`, `onKeyDown`, `onPointerMove`, `data-pending`,\n * `data-disabled`, `data-typeahead`.\n */\nexport function MenuItem({\n action,\n closeOnActivate = true,\n disabled = false,\n label,\n className,\n style,\n children,\n render,\n ...rest\n}: MenuItemProps) {\n const menu = useMenuContext(\"Menu.Item\");\n // The close belongs to the top-level menu, so its open generation guards it.\n const { pending, run } = useActionTrigger({ openGeneration: menu.root.popover.openGeneration });\n\n const { libraryProps } = useMenuItem({\n part: \"Menu.Item\",\n role: \"menuitem\",\n disabled,\n label,\n activate: (event) => {\n const details: MenuItemDetails = createActionDetails(event, {});\n // A second activation while this item's own run is in flight starts nothing and is\n // cancelled (the hook's guard, #81): a link does not navigate, a composed command does not\n // run. Enter / Space reach here through the element's click, their keydown is cancelled.\n const started = run(\n () => action?.(details),\n closeOnActivate ? () => menu.root.popover.requestClose(event, \"activate\") : undefined,\n );\n if (!started) event.preventDefault();\n },\n });\n\n const state: MenuItemState = { pending, disabled };\n\n return useRender<ComponentPropsWithRef<\"button\">, MenuItemState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n ...(rendersButton(render) && { type: \"button\" as const }),\n ...libraryProps,\n // Also while pending (#81): an item that will not act is unavailable to AT. Navigation keys\n // on `data-disabled` (the `disabled` prop), so a pending item is still an enabled item.\n \"aria-disabled\": disabled || pending ? true : undefined,\n \"data-pending\": dataAttr(pending),\n },\n });\n}\n\nMenuItem.displayName = \"MenuItem\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAwDA,SAAgB,SAAS,EACvB,QACA,kBAAkB,MAClB,WAAW,OACX,OACA,WACA,OACA,UACA,QACA,GAAG,QACa;CAChB,MAAM,OAAO,eAAe,WAAW;CAEvC,MAAM,EAAE,SAAS,QAAQ,iBAAiB,EAAE,gBAAgB,KAAK,KAAK,QAAQ,eAAe,CAAC;CAE9F,MAAM,EAAE,iBAAiB,YAAY;EACnC,MAAM;EACN,MAAM;EACN;EACA;EACA,WAAW,UAAU;GACnB,MAAM,UAA2B,oBAAoB,OAAO,CAAC,CAAC;GAQ9D,IAAI,CAJY,UACR,SAAS,OAAO,GACtB,wBAAwB,KAAK,KAAK,QAAQ,aAAa,OAAO,UAAU,IAAI,KAAA,CAEnE,GAAG,MAAM,eAAe;EACrC;CACF,CAAC;CAID,OAAO,UAA0D;EAC/D,gBAAgB;EAChB;EACA,OAAA;GAL6B;GAAS;EAKlC;EACJ;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;GACvD,GAAG;GAGH,iBAAiB,YAAY,UAAU,OAAO,KAAA;GAC9C,gBAAgB,SAAS,OAAO;EAClC;CACF,CAAC;AACH;AAEA,SAAS,cAAc"}
|
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";
|
|
@@ -10,7 +10,10 @@ export interface MenuTriggerState {
|
|
|
10
10
|
readonly disabled: boolean;
|
|
11
11
|
}
|
|
12
12
|
export interface MenuTriggerProps extends Omit<ComponentPropsWithRef<"button">, "onClick" | "onKeyDown" | "aria-expanded" | "aria-haspopup" | "className" | "style" | "children"> {
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* The menu cannot be opened from this button. Native `disabled` on a `<button>`; with a link or
|
|
15
|
+
* component `render`, `aria-disabled="true"` instead (the element stays focusable).
|
|
16
|
+
*/
|
|
14
17
|
disabled?: boolean;
|
|
15
18
|
className?: StateValue<string | undefined, MenuTriggerState>;
|
|
16
19
|
style?: StateValue<CSSProperties | undefined, MenuTriggerState>;
|
|
@@ -25,8 +28,8 @@ export interface MenuTriggerProps extends Omit<ComponentPropsWithRef<"button">,
|
|
|
25
28
|
* Root's transition; ArrowDown / ArrowUp open it with the first / last item focused (inside a
|
|
26
29
|
* vertical `Toolbar.Root`: the inline-end arrow, with the first item focused).
|
|
27
30
|
*
|
|
28
|
-
* Owned keys (conventions 1.2): `type` (on a `<button>` only), `id`, `disabled`, `
|
|
29
|
-
* `command`, `aria-haspopup`, `aria-expanded`, `onClick`, `onKeyDown`, `data-open`,
|
|
31
|
+
* Owned keys (conventions 1.2): `type` (on a `<button>` only), `id`, `disabled`, `aria-disabled`
|
|
32
|
+
* (link or component `render`), `commandfor`, `command`, `aria-haspopup`, `aria-expanded`, `onClick`, `onKeyDown`, `data-open`,
|
|
30
33
|
* `data-pending`, `data-disabled`.
|
|
31
34
|
*/
|
|
32
35
|
export declare function MenuTrigger({ disabled, className, style, children, render, ...rest }: MenuTriggerProps): ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-trigger.d.mts","names":[],"sources":["../../src/menu/menu-trigger.tsx"],"mappings":";;;;iBAWiB;;WAEN;;WAEA;WACA;;iBAGM,yBAAyB,KACxC
|
|
1
|
+
{"version":3,"file":"menu-trigger.d.mts","names":[],"sources":["../../src/menu/menu-trigger.tsx"],"mappings":";;;;iBAWiB;;WAEN;;WAEA;WACA;;iBAGM,yBAAyB,KACxC;;;;;EAOA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;wBAwCvC,cACd,UACA,WACA,OACA,UACA,WACG,QACF,mBAAgB;yBAPH"}
|
|
@@ -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";
|
|
@@ -33,8 +33,8 @@ function isPointerClick(event) {
|
|
|
33
33
|
* Root's transition; ArrowDown / ArrowUp open it with the first / last item focused (inside a
|
|
34
34
|
* vertical `Toolbar.Root`: the inline-end arrow, with the first item focused).
|
|
35
35
|
*
|
|
36
|
-
* Owned keys (conventions 1.2): `type` (on a `<button>` only), `id`, `disabled`, `
|
|
37
|
-
* `command`, `aria-haspopup`, `aria-expanded`, `onClick`, `onKeyDown`, `data-open`,
|
|
36
|
+
* Owned keys (conventions 1.2): `type` (on a `<button>` only), `id`, `disabled`, `aria-disabled`
|
|
37
|
+
* (link or component `render`), `commandfor`, `command`, `aria-haspopup`, `aria-expanded`, `onClick`, `onKeyDown`, `data-open`,
|
|
38
38
|
* `data-pending`, `data-disabled`.
|
|
39
39
|
*/
|
|
40
40
|
function MenuTrigger({ disabled = false, className, style, children, render, ...rest }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-trigger.mjs","names":[],"sources":["../../src/menu/menu-trigger.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, KeyboardEvent, ReactNode } from \"react\";\nimport { useToolbarContext } from \"../internal/toolbar-context.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { usePopoverTrigger } from \"../internal/use-popover-trigger.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useMenuContext } from \"./menu-context.js\";\nimport type { MenuContextValue } from \"./menu-context.js\";\nimport { edgeItem, focusItem, hasModifier, isRtl } from \"./menu-dom.js\";\n\nexport interface MenuTriggerState {\n /** Optimistic open state. */\n readonly open: boolean;\n /** The Root's transition is pending (an open, a part-initiated close or a dismissal notification). */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface MenuTriggerProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"onKeyDown\" | \"aria-expanded\" | \"aria-haspopup\" | \"className\" | \"style\" | \"children\"\n> {\n
|
|
1
|
+
{"version":3,"file":"menu-trigger.mjs","names":[],"sources":["../../src/menu/menu-trigger.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, KeyboardEvent, ReactNode } from \"react\";\nimport { useToolbarContext } from \"../internal/toolbar-context.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { usePopoverTrigger } from \"../internal/use-popover-trigger.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useMenuContext } from \"./menu-context.js\";\nimport type { MenuContextValue } from \"./menu-context.js\";\nimport { edgeItem, focusItem, hasModifier, isRtl } from \"./menu-dom.js\";\n\nexport interface MenuTriggerState {\n /** Optimistic open state. */\n readonly open: boolean;\n /** The Root's transition is pending (an open, a part-initiated close or a dismissal notification). */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface MenuTriggerProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"onKeyDown\" | \"aria-expanded\" | \"aria-haspopup\" | \"className\" | \"style\" | \"children\"\n> {\n /**\n * The menu cannot be opened from this button. Native `disabled` on a `<button>`; with a link or\n * component `render`, `aria-disabled=\"true\"` instead (the element stays focusable).\n */\n disabled?: boolean;\n className?: StateValue<string | undefined, MenuTriggerState>;\n style?: StateValue<CSSProperties | undefined, MenuTriggerState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, MenuTriggerState>;\n /** Should render a `<button>` (the command path before hydration). */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, MenuTriggerState>;\n}\n\n/**\n * Opens with the first (`\"first\"`) or last (`\"last\"`) item focused, or focuses that item when the\n * menu is already open (a pre-hydration open, walkthrough 10). Shared with SubmenuTrigger.\n */\nexport function openMenuWithFocus(\n menu: MenuContextValue,\n event: Event,\n which: \"first\" | \"last\",\n): void {\n const { popover } = menu;\n if (popover.intended()) {\n const popup = popover.popupRef.current;\n if (popup !== null && popup.matches(\":popover-open\")) {\n const item = edgeItem(popup, which);\n if (item !== null) focusItem(item);\n }\n return;\n }\n menu.setOpenCause(which, isPointerClick(event));\n popover.requestOpen(event, \"activate\");\n}\n\n/** A click from a pointing device (`detail` counts clicks; keyboard and `click()` give 0). */\nexport function isPointerClick(event: Event): boolean {\n return event.type === \"click\" && (event as MouseEvent).detail > 0;\n}\n\n/**\n * The menu button: `<button type=\"button\" commandfor command=\"toggle-popover\"\n * aria-haspopup=\"menu\" aria-expanded>`. A click (Enter, Space) toggles the menu through the\n * Root's transition; ArrowDown / ArrowUp open it with the first / last item focused (inside a\n * vertical `Toolbar.Root`: the inline-end arrow, with the first item focused).\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `id`, `disabled`, `aria-disabled`\n * (link or component `render`), `commandfor`, `command`, `aria-haspopup`, `aria-expanded`, `onClick`, `onKeyDown`, `data-open`,\n * `data-pending`, `data-disabled`.\n */\nexport function MenuTrigger({\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: MenuTriggerProps) {\n const menu = useMenuContext(\"Menu.Trigger\");\n useDevWarning(\n menu.submenu,\n \"Menu.Trigger: rendered in a submenu. Use Menu.SubmenuTrigger, which is also an item of the \" +\n \"parent menu.\",\n );\n\n // Inside a vertical Toolbar, ArrowDown / ArrowUp are the Toolbar's: the trigger opens on the\n // inline-end arrow instead, as a submenu trigger does (design/components/toggle-group.md 7.4).\n const toolbar = useToolbarContext();\n const onKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (disabled || hasModifier(event)) return;\n let which: \"first\" | \"last\";\n if (toolbar?.orientation === \"vertical\") {\n const openKey = isRtl(event.currentTarget) ? \"ArrowLeft\" : \"ArrowRight\";\n if (event.key !== openKey) return;\n which = \"first\";\n } else {\n if (event.key !== \"ArrowDown\" && event.key !== \"ArrowUp\") return;\n which = event.key === \"ArrowDown\" ? \"first\" : \"last\";\n }\n // No page scroll, and an enclosing Toolbar sees `defaultPrevented`; Enter and Space stay the\n // native click.\n event.preventDefault();\n openMenuWithFocus(menu, event.nativeEvent, which);\n };\n\n const { state, libraryProps, ref } = usePopoverTrigger(menu.popover, {\n part: \"Menu.Trigger\",\n disabled,\n render,\n handlers: { onKeyDown },\n activate: (event) => {\n const native = event.nativeEvent;\n if (menu.popover.intended()) {\n menu.popover.requestClose(native, \"activate\");\n } else {\n menu.setOpenCause(\"first\", isPointerClick(native));\n menu.popover.requestOpen(native, \"activate\");\n }\n },\n });\n\n return useRender<ComponentPropsWithRef<\"button\">, MenuTriggerState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n ...libraryProps,\n id: menu.triggerId,\n \"aria-haspopup\": \"menu\",\n },\n ref,\n });\n}\n\nMenuTrigger.displayName = \"MenuTrigger\";\n"],"mappings":";;;;;;;;;;;;AAwCA,SAAgB,kBACd,MACA,OACA,OACM;CACN,MAAM,EAAE,YAAY;CACpB,IAAI,QAAQ,SAAS,GAAG;EACtB,MAAM,QAAQ,QAAQ,SAAS;EAC/B,IAAI,UAAU,QAAQ,MAAM,QAAQ,eAAe,GAAG;GACpD,MAAM,OAAO,SAAS,OAAO,KAAK;GAClC,IAAI,SAAS,MAAM,UAAU,IAAI;EACnC;EACA;CACF;CACA,KAAK,aAAa,OAAO,eAAe,KAAK,CAAC;CAC9C,QAAQ,YAAY,OAAO,UAAU;AACvC;;AAGA,SAAgB,eAAe,OAAuB;CACpD,OAAO,MAAM,SAAS,WAAY,MAAqB,SAAS;AAClE;;;;;;;;;;;AAYA,SAAgB,YAAY,EAC1B,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACgB;CACnB,MAAM,OAAO,eAAe,cAAc;CAC1C,cACE,KAAK,SACL,yGAEF;CAIA,MAAM,UAAU,kBAAkB;CAClC,MAAM,aAAa,UAA4C;EAC7D,IAAI,YAAY,YAAY,KAAK,GAAG;EACpC,IAAI;EACJ,IAAI,SAAS,gBAAgB,YAAY;GACvC,MAAM,UAAU,MAAM,MAAM,aAAa,IAAI,cAAc;GAC3D,IAAI,MAAM,QAAQ,SAAS;GAC3B,QAAQ;EACV,OAAO;GACL,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;GAC1D,QAAQ,MAAM,QAAQ,cAAc,UAAU;EAChD;EAGA,MAAM,eAAe;EACrB,kBAAkB,MAAM,MAAM,aAAa,KAAK;CAClD;CAEA,MAAM,EAAE,OAAO,cAAc,QAAQ,kBAAkB,KAAK,SAAS;EACnE,MAAM;EACN;EACA;EACA,UAAU,EAAE,UAAU;EACtB,WAAW,UAAU;GACnB,MAAM,SAAS,MAAM;GACrB,IAAI,KAAK,QAAQ,SAAS,GACxB,KAAK,QAAQ,aAAa,QAAQ,UAAU;QACvC;IACL,KAAK,aAAa,SAAS,eAAe,MAAM,CAAC;IACjD,KAAK,QAAQ,YAAY,QAAQ,UAAU;GAC7C;EACF;CACF,CAAC;CAED,OAAO,UAA6D;EAClE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,GAAG;GACH,IAAI,KAAK;GACT,iBAAiB;EACnB;EACA;CACF,CAAC;AACH;AAEA,YAAY,cAAc"}
|
|
@@ -3,10 +3,11 @@ import { NumberFieldDecrementProps } from "./number-field-increment.mjs";
|
|
|
3
3
|
/**
|
|
4
4
|
* Steps the value down: `button[type=button][tabindex=-1]` with `aria-controls` → the input and
|
|
5
5
|
* the default `aria-label` `"Decrease"`; one step at the press, then repeated while held, one
|
|
6
|
-
* commit at the release. Natively `disabled` when the next step would change nothing
|
|
6
|
+
* commit at the release. Natively `disabled` when the next step would change nothing
|
|
7
|
+
* (`aria-disabled` with a link or component `render`).
|
|
7
8
|
*
|
|
8
|
-
* Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `
|
|
9
|
-
* `onContextMenu`, `data-pending`, `data-disabled`.
|
|
9
|
+
* Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `aria-disabled` (link or component
|
|
10
|
+
* `render`), `onPointerDown`, `onClick`, `onContextMenu`, `data-pending`, `data-disabled`.
|
|
10
11
|
*/
|
|
11
12
|
export declare function NumberFieldDecrement(props: NumberFieldDecrementProps): import("react").ReactNode;
|
|
12
13
|
export declare namespace NumberFieldDecrement {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-field-decrement.d.mts","names":[],"sources":["../../src/number-field/number-field-decrement.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"number-field-decrement.d.mts","names":[],"sources":["../../src/number-field/number-field-decrement.tsx"],"mappings":";;;;;;;;;;;wBAegB,qBAAqB,OAAO,4CAAyB;yBAArD"}
|
|
@@ -4,10 +4,11 @@ import { useStepButtonElement } from "./number-field-increment.mjs";
|
|
|
4
4
|
/**
|
|
5
5
|
* Steps the value down: `button[type=button][tabindex=-1]` with `aria-controls` → the input and
|
|
6
6
|
* the default `aria-label` `"Decrease"`; one step at the press, then repeated while held, one
|
|
7
|
-
* commit at the release. Natively `disabled` when the next step would change nothing
|
|
7
|
+
* commit at the release. Natively `disabled` when the next step would change nothing
|
|
8
|
+
* (`aria-disabled` with a link or component `render`).
|
|
8
9
|
*
|
|
9
|
-
* Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `
|
|
10
|
-
* `onContextMenu`, `data-pending`, `data-disabled`.
|
|
10
|
+
* Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `aria-disabled` (link or component
|
|
11
|
+
* `render`), `onPointerDown`, `onClick`, `onContextMenu`, `data-pending`, `data-disabled`.
|
|
11
12
|
*/
|
|
12
13
|
function NumberFieldDecrement(props) {
|
|
13
14
|
return useStepButtonElement("decrement", "NumberField.Decrement", props);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-field-decrement.mjs","names":[],"sources":["../../src/number-field/number-field-decrement.tsx"],"sourcesContent":["\"use client\";\nimport { useStepButtonElement } from \"./number-field-increment.js\";\nimport type { NumberFieldDecrementProps } from \"./number-field-increment.js\";\n\nexport type { NumberFieldDecrementProps } from \"./number-field-increment.js\";\n\n/**\n * Steps the value down: `button[type=button][tabindex=-1]` with `aria-controls` → the input and\n * the default `aria-label` `\"Decrease\"`; one step at the press, then repeated while held, one\n * commit at the release. Natively `disabled` when the next step would change nothing.\n *\n * Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `onPointerDown`, `onClick
|
|
1
|
+
{"version":3,"file":"number-field-decrement.mjs","names":[],"sources":["../../src/number-field/number-field-decrement.tsx"],"sourcesContent":["\"use client\";\nimport { useStepButtonElement } from \"./number-field-increment.js\";\nimport type { NumberFieldDecrementProps } from \"./number-field-increment.js\";\n\nexport type { NumberFieldDecrementProps } from \"./number-field-increment.js\";\n\n/**\n * Steps the value down: `button[type=button][tabindex=-1]` with `aria-controls` → the input and\n * the default `aria-label` `\"Decrease\"`; one step at the press, then repeated while held, one\n * commit at the release. Natively `disabled` when the next step would change nothing\n * (`aria-disabled` with a link or component `render`).\n *\n * Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `aria-disabled` (link or component\n * `render`), `onPointerDown`, `onClick`, `onContextMenu`, `data-pending`, `data-disabled`.\n */\nexport function NumberFieldDecrement(props: NumberFieldDecrementProps) {\n return useStepButtonElement(\"decrement\", \"NumberField.Decrement\", props);\n}\n\nNumberFieldDecrement.displayName = \"NumberFieldDecrement\";\n"],"mappings":";;;;;;;;;;;;AAeA,SAAgB,qBAAqB,OAAkC;CACrE,OAAO,qBAAqB,aAAa,yBAAyB,KAAK;AACzE;AAEA,qBAAqB,cAAc"}
|
|
@@ -9,6 +9,10 @@ export interface NumberFieldButtonState {
|
|
|
9
9
|
readonly disabled: boolean;
|
|
10
10
|
}
|
|
11
11
|
export interface NumberFieldIncrementProps extends Omit<ComponentPropsWithRef<"button">, "type" | "tabIndex" | "disabled" | "onPointerDown" | "onClick" | "onContextMenu" | "aria-controls" | "className" | "style" | "children"> {
|
|
12
|
+
/**
|
|
13
|
+
* Never steps. Native `disabled` on a `<button>` (also at the bound and under `readOnly`); with
|
|
14
|
+
* a link or component `render`, `aria-disabled="true"` instead.
|
|
15
|
+
*/
|
|
12
16
|
disabled?: boolean;
|
|
13
17
|
className?: StateValue<string | undefined, NumberFieldButtonState>;
|
|
14
18
|
style?: StateValue<CSSProperties | undefined, NumberFieldButtonState>;
|
|
@@ -19,10 +23,11 @@ export type NumberFieldDecrementProps = NumberFieldIncrementProps;
|
|
|
19
23
|
/**
|
|
20
24
|
* Steps the value up: `button[type=button][tabindex=-1]` with `aria-controls` → the input and the
|
|
21
25
|
* default `aria-label` `"Increase"`; one step at the press, then repeated while held, one commit
|
|
22
|
-
* at the release. Natively `disabled` when the next step would change nothing
|
|
26
|
+
* at the release. Natively `disabled` when the next step would change nothing (`aria-disabled`
|
|
27
|
+
* with a link or component `render`).
|
|
23
28
|
*
|
|
24
|
-
* Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `
|
|
25
|
-
* `onContextMenu`, `data-pending`, `data-disabled`.
|
|
29
|
+
* Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `aria-disabled` (link or component
|
|
30
|
+
* `render`), `onPointerDown`, `onClick`, `onContextMenu`, `data-pending`, `data-disabled`.
|
|
26
31
|
*/
|
|
27
32
|
export declare function NumberFieldIncrement(props: NumberFieldIncrementProps): ReactNode;
|
|
28
33
|
export declare namespace NumberFieldIncrement {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-field-increment.d.mts","names":[],"sources":["../../src/number-field/number-field-increment.tsx"],"mappings":";;;;iBAYiB;;WAEN;;WAEA;;iBAGM,kCAAkC,KACjD;
|
|
1
|
+
{"version":3,"file":"number-field-increment.d.mts","names":[],"sources":["../../src/number-field/number-field-increment.tsx"],"mappings":";;;;iBAYiB;;WAEN;;WAEA;;iBAGM,kCAAkC,KACjD;;;;;EAgBA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,iCAAiC;;YAG3C,4BAA4B;;;;;;;;;;wBAkExB,qBAAqB,OAAO,4BAAyB;yBAArD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { dataAttr } from "../internal/data-attr.mjs";
|
|
3
|
-
import { rendersButton } from "../internal/render-element.mjs";
|
|
4
|
-
import { useRender } from "../internal/use-render.mjs";
|
|
5
3
|
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
4
|
+
import { isHostButton, rendersButton } from "../internal/render-element.mjs";
|
|
5
|
+
import { useRender } from "../internal/use-render.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";
|
|
@@ -24,6 +24,7 @@ function useStepButtonElement(direction, part, props) {
|
|
|
24
24
|
disabled
|
|
25
25
|
};
|
|
26
26
|
const handlers = useStepButton(ctx, direction, disabled);
|
|
27
|
+
const focusable = !isHostButton(render);
|
|
27
28
|
useDevWarning(rest["aria-label"] === "", `${part}: \`aria-label=""\` leaves the button without a name. Pass the label text instead (the default is "${LABELS[direction]}").`);
|
|
28
29
|
const props$ = {
|
|
29
30
|
...rest["aria-labelledby"] === void 0 ? { "aria-label": LABELS[direction] } : {},
|
|
@@ -41,7 +42,8 @@ function useStepButtonElement(direction, part, props) {
|
|
|
41
42
|
...rendersButton(render) ? { type: "button" } : {},
|
|
42
43
|
tabIndex: -1,
|
|
43
44
|
"aria-controls": ctx.inputId,
|
|
44
|
-
disabled,
|
|
45
|
+
disabled: focusable ? void 0 : disabled,
|
|
46
|
+
...focusable && { "aria-disabled": disabled ? true : void 0 },
|
|
45
47
|
onPointerDown: handlers.onPointerDown,
|
|
46
48
|
onClick: handlers.onClick,
|
|
47
49
|
onContextMenu: handlers.onContextMenu,
|
|
@@ -53,10 +55,11 @@ function useStepButtonElement(direction, part, props) {
|
|
|
53
55
|
/**
|
|
54
56
|
* Steps the value up: `button[type=button][tabindex=-1]` with `aria-controls` → the input and the
|
|
55
57
|
* default `aria-label` `"Increase"`; one step at the press, then repeated while held, one commit
|
|
56
|
-
* at the release. Natively `disabled` when the next step would change nothing
|
|
58
|
+
* at the release. Natively `disabled` when the next step would change nothing (`aria-disabled`
|
|
59
|
+
* with a link or component `render`).
|
|
57
60
|
*
|
|
58
|
-
* Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `
|
|
59
|
-
* `onContextMenu`, `data-pending`, `data-disabled`.
|
|
61
|
+
* Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `aria-disabled` (link or component
|
|
62
|
+
* `render`), `onPointerDown`, `onClick`, `onContextMenu`, `data-pending`, `data-disabled`.
|
|
60
63
|
*/
|
|
61
64
|
function NumberFieldIncrement(props) {
|
|
62
65
|
return useStepButtonElement("increment", "NumberField.Increment", props);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-field-increment.mjs","names":[],"sources":["../../src/number-field/number-field-increment.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { isAtBound } from \"./number-field-arithmetic.js\";\nimport { useNumberFieldContext } from \"./number-field-context.js\";\nimport type { StepDirection } from \"./number-field-context.js\";\nimport { useStepButton } from \"./use-step-button.js\";\n\nexport interface NumberFieldButtonState {\n /** The Root is pending and the latest step or commit came from this button. */\n readonly pending: boolean;\n /** The prop, the Root's `disabled` or `readOnly`, or the next step would change nothing. */\n readonly disabled: boolean;\n}\n\nexport interface NumberFieldIncrementProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n | \"type\"\n | \"tabIndex\"\n | \"disabled\"\n | \"onPointerDown\"\n | \"onClick\"\n | \"onContextMenu\"\n | \"aria-controls\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n disabled?: boolean;\n className?: StateValue<string | undefined, NumberFieldButtonState>;\n style?: StateValue<CSSProperties | undefined, NumberFieldButtonState>;\n children?: StateValue<ReactNode, NumberFieldButtonState>;\n render?: RenderProp<ComponentPropsWithRef<\"button\">, NumberFieldButtonState>;\n}\n\nexport type NumberFieldDecrementProps = NumberFieldIncrementProps;\n\nconst LABELS: Record<StepDirection, string> = { increment: \"Increase\", decrement: \"Decrease\" };\n\n/** Shared by `NumberField.Increment` and `NumberField.Decrement` (design 3.3, 4.3). */\nexport function useStepButtonElement(\n direction: StepDirection,\n part: string,\n props: NumberFieldIncrementProps,\n): ReactNode {\n const { disabled: disabledProp = false, className, style, children, render, ...rest } = props;\n const ctx = useNumberFieldContext(part);\n const { state } = ctx;\n const atBound = isAtBound(ctx.stepBase, direction === \"increment\" ? 1 : -1, ctx.bounds);\n const disabled = disabledProp || state.disabled || state.readOnly || atBound;\n const pending = ctx.pendingSource === direction;\n const buttonState: NumberFieldButtonState = { pending, disabled };\n const handlers = useStepButton(ctx, direction, disabled);\n\n useDevWarning(\n rest[\"aria-label\"] === \"\",\n `${part}: \\`aria-label=\"\"\\` leaves the button without a name. Pass the label text instead ` +\n `(the default is \"${LABELS[direction]}\").`,\n );\n\n // The built-in name is a default the consumer's `aria-label` or `aria-labelledby` replaces.\n const props$ = {\n ...(rest[\"aria-labelledby\"] === undefined ? { \"aria-label\": LABELS[direction] } : {}),\n ...rest,\n };\n\n return useRender<ComponentPropsWithRef<\"button\">, NumberFieldButtonState>({\n defaultElement: \"button\",\n render,\n state: buttonState,\n className,\n style,\n children,\n props: props$,\n libraryProps: {\n ...(rendersButton(render) ? { type: \"button\" as const } : {}),\n tabIndex: -1,\n \"aria-controls\": ctx.inputId,\n disabled,\n onPointerDown: handlers.onPointerDown,\n onClick: handlers.onClick,\n onContextMenu: handlers.onContextMenu,\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n } as Partial<ComponentPropsWithRef<\"button\">> & DataAttributes,\n });\n}\n\n/**\n * Steps the value up: `button[type=button][tabindex=-1]` with `aria-controls` → the input and the\n * default `aria-label` `\"Increase\"`; one step at the press, then repeated while held, one commit\n * at the release. Natively `disabled` when the next step would change nothing.\n *\n * Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `onPointerDown`, `onClick
|
|
1
|
+
{"version":3,"file":"number-field-increment.mjs","names":[],"sources":["../../src/number-field/number-field-increment.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { isHostButton, rendersButton, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { isAtBound } from \"./number-field-arithmetic.js\";\nimport { useNumberFieldContext } from \"./number-field-context.js\";\nimport type { StepDirection } from \"./number-field-context.js\";\nimport { useStepButton } from \"./use-step-button.js\";\n\nexport interface NumberFieldButtonState {\n /** The Root is pending and the latest step or commit came from this button. */\n readonly pending: boolean;\n /** The prop, the Root's `disabled` or `readOnly`, or the next step would change nothing. */\n readonly disabled: boolean;\n}\n\nexport interface NumberFieldIncrementProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n | \"type\"\n | \"tabIndex\"\n | \"disabled\"\n | \"onPointerDown\"\n | \"onClick\"\n | \"onContextMenu\"\n | \"aria-controls\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /**\n * Never steps. Native `disabled` on a `<button>` (also at the bound and under `readOnly`); with\n * a link or component `render`, `aria-disabled=\"true\"` instead.\n */\n disabled?: boolean;\n className?: StateValue<string | undefined, NumberFieldButtonState>;\n style?: StateValue<CSSProperties | undefined, NumberFieldButtonState>;\n children?: StateValue<ReactNode, NumberFieldButtonState>;\n render?: RenderProp<ComponentPropsWithRef<\"button\">, NumberFieldButtonState>;\n}\n\nexport type NumberFieldDecrementProps = NumberFieldIncrementProps;\n\nconst LABELS: Record<StepDirection, string> = { increment: \"Increase\", decrement: \"Decrease\" };\n\n/** Shared by `NumberField.Increment` and `NumberField.Decrement` (design 3.3, 4.3). */\nexport function useStepButtonElement(\n direction: StepDirection,\n part: string,\n props: NumberFieldIncrementProps,\n): ReactNode {\n const { disabled: disabledProp = false, className, style, children, render, ...rest } = props;\n const ctx = useNumberFieldContext(part);\n const { state } = ctx;\n const atBound = isAtBound(ctx.stepBase, direction === \"increment\" ? 1 : -1, ctx.bounds);\n const disabled = disabledProp || state.disabled || state.readOnly || atBound;\n const pending = ctx.pendingSource === direction;\n const buttonState: NumberFieldButtonState = { pending, disabled };\n const handlers = useStepButton(ctx, direction, disabled);\n // A link or component render: native `disabled` would mean nothing on a link; the press and\n // click handlers refuse, so `aria-disabled` (#83). The at-bound case follows the same branch.\n const focusable = !isHostButton(render);\n\n useDevWarning(\n rest[\"aria-label\"] === \"\",\n `${part}: \\`aria-label=\"\"\\` leaves the button without a name. Pass the label text instead ` +\n `(the default is \"${LABELS[direction]}\").`,\n );\n\n // The built-in name is a default the consumer's `aria-label` or `aria-labelledby` replaces.\n const props$ = {\n ...(rest[\"aria-labelledby\"] === undefined ? { \"aria-label\": LABELS[direction] } : {}),\n ...rest,\n };\n\n return useRender<ComponentPropsWithRef<\"button\">, NumberFieldButtonState>({\n defaultElement: \"button\",\n render,\n state: buttonState,\n className,\n style,\n children,\n props: props$,\n libraryProps: {\n ...(rendersButton(render) ? { type: \"button\" as const } : {}),\n tabIndex: -1,\n \"aria-controls\": ctx.inputId,\n disabled: focusable ? undefined : disabled,\n ...(focusable && { \"aria-disabled\": disabled ? true : undefined }),\n onPointerDown: handlers.onPointerDown,\n onClick: handlers.onClick,\n onContextMenu: handlers.onContextMenu,\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n } as Partial<ComponentPropsWithRef<\"button\">> & DataAttributes,\n });\n}\n\n/**\n * Steps the value up: `button[type=button][tabindex=-1]` with `aria-controls` → the input and the\n * default `aria-label` `\"Increase\"`; one step at the press, then repeated while held, one commit\n * at the release. Natively `disabled` when the next step would change nothing (`aria-disabled`\n * with a link or component `render`).\n *\n * Owned keys: `type`, `tabIndex`, `aria-controls`, `disabled`, `aria-disabled` (link or component\n * `render`), `onPointerDown`, `onClick`, `onContextMenu`, `data-pending`, `data-disabled`.\n */\nexport function NumberFieldIncrement(props: NumberFieldIncrementProps) {\n return useStepButtonElement(\"increment\", \"NumberField.Increment\", props);\n}\n\nNumberFieldIncrement.displayName = \"NumberFieldIncrement\";\n"],"mappings":";;;;;;;;;AA6CA,MAAM,SAAwC;CAAE,WAAW;CAAY,WAAW;AAAW;;AAG7F,SAAgB,qBACd,WACA,MACA,OACW;CACX,MAAM,EAAE,UAAU,eAAe,OAAO,WAAW,OAAO,UAAU,QAAQ,GAAG,SAAS;CACxF,MAAM,MAAM,sBAAsB,IAAI;CACtC,MAAM,EAAE,UAAU;CAClB,MAAM,UAAU,UAAU,IAAI,UAAU,cAAc,cAAc,IAAI,IAAI,IAAI,MAAM;CACtF,MAAM,WAAW,gBAAgB,MAAM,YAAY,MAAM,YAAY;CACrE,MAAM,UAAU,IAAI,kBAAkB;CACtC,MAAM,cAAsC;EAAE;EAAS;CAAS;CAChE,MAAM,WAAW,cAAc,KAAK,WAAW,QAAQ;CAGvD,MAAM,YAAY,CAAC,aAAa,MAAM;CAEtC,cACE,KAAK,kBAAkB,IACvB,GAAG,KAAK,qGACc,OAAO,WAAW,IAC1C;CAGA,MAAM,SAAS;EACb,GAAI,KAAK,uBAAuB,KAAA,IAAY,EAAE,cAAc,OAAO,WAAW,IAAI,CAAC;EACnF,GAAG;CACL;CAEA,OAAO,UAAmE;EACxE,gBAAgB;EAChB;EACA,OAAO;EACP;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,GAAI,cAAc,MAAM,IAAI,EAAE,MAAM,SAAkB,IAAI,CAAC;GAC3D,UAAU;GACV,iBAAiB,IAAI;GACrB,UAAU,YAAY,KAAA,IAAY;GAClC,GAAI,aAAa,EAAE,iBAAiB,WAAW,OAAO,KAAA,EAAU;GAChE,eAAe,SAAS;GACxB,SAAS,SAAS;GAClB,eAAe,SAAS;GACxB,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;EACpC;CACF,CAAC;AACH;;;;;;;;;;AAWA,SAAgB,qBAAqB,OAAkC;CACrE,OAAO,qBAAqB,aAAa,yBAAyB,KAAK;AACzE;AAEA,qBAAqB,cAAc"}
|
|
@@ -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";
|