@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.
Files changed (131) hide show
  1. package/dist/accordion/accordion-item.mjs +2 -2
  2. package/dist/accordion/accordion-panel.mjs +2 -2
  3. package/dist/accordion/accordion-root.mjs +3 -3
  4. package/dist/accordion/accordion-trigger.mjs +2 -2
  5. package/dist/button/button.d.mts +78 -0
  6. package/dist/button/button.d.mts.map +1 -0
  7. package/dist/button/button.mjs +77 -0
  8. package/dist/button/button.mjs.map +1 -0
  9. package/dist/button/index.d.mts +3 -0
  10. package/dist/button/index.mjs +1 -0
  11. package/dist/checkbox/checkbox.mjs +2 -2
  12. package/dist/checkbox-group/checkbox-group-item.mjs +1 -1
  13. package/dist/checkbox-group/checkbox-group-parent.mjs +1 -1
  14. package/dist/checkbox-group/checkbox-group-root.mjs +1 -1
  15. package/dist/combobox/combobox-clear.d.mts +6 -3
  16. package/dist/combobox/combobox-clear.d.mts.map +1 -1
  17. package/dist/combobox/combobox-clear.mjs +10 -5
  18. package/dist/combobox/combobox-clear.mjs.map +1 -1
  19. package/dist/combobox/combobox-group.mjs +1 -1
  20. package/dist/combobox/combobox-list.mjs +1 -1
  21. package/dist/combobox/combobox-option.mjs +1 -1
  22. package/dist/combobox/combobox-popup.mjs +2 -2
  23. package/dist/combobox/combobox-root.mjs +3 -3
  24. package/dist/combobox/combobox-trigger.d.mts +6 -2
  25. package/dist/combobox/combobox-trigger.d.mts.map +1 -1
  26. package/dist/combobox/combobox-trigger.mjs +10 -4
  27. package/dist/combobox/combobox-trigger.mjs.map +1 -1
  28. package/dist/dialog/dialog-close.d.mts +8 -3
  29. package/dist/dialog/dialog-close.d.mts.map +1 -1
  30. package/dist/dialog/dialog-close.mjs +12 -8
  31. package/dist/dialog/dialog-close.mjs.map +1 -1
  32. package/dist/dialog/dialog-form.mjs +1 -1
  33. package/dist/dialog/dialog-popup.mjs +3 -3
  34. package/dist/dialog/dialog-root.mjs +2 -2
  35. package/dist/dialog/dialog-trigger.d.mts +8 -3
  36. package/dist/dialog/dialog-trigger.d.mts.map +1 -1
  37. package/dist/dialog/dialog-trigger.mjs +15 -8
  38. package/dist/dialog/dialog-trigger.mjs.map +1 -1
  39. package/dist/field/field-root.mjs +3 -3
  40. package/dist/form/form-root.mjs +1 -1
  41. package/dist/form/form-submit.d.mts +4 -1
  42. package/dist/form/form-submit.d.mts.map +1 -1
  43. package/dist/form/form-submit.mjs.map +1 -1
  44. package/dist/index.d.mts +3 -2
  45. package/dist/index.mjs +2 -1
  46. package/dist/internal/render-element.mjs +18 -5
  47. package/dist/internal/render-element.mjs.map +1 -1
  48. package/dist/internal/use-action-trigger.mjs +17 -6
  49. package/dist/internal/use-action-trigger.mjs.map +1 -1
  50. package/dist/internal/use-field-control.mjs +1 -1
  51. package/dist/internal/use-popover-root.mjs +1 -1
  52. package/dist/internal/use-popover-trigger.mjs +6 -5
  53. package/dist/internal/use-popover-trigger.mjs.map +1 -1
  54. package/dist/internal/use-render.mjs +2 -2
  55. package/dist/internal/use-render.mjs.map +1 -1
  56. package/dist/menu/menu-checkbox-item.mjs +2 -2
  57. package/dist/menu/menu-dom.mjs +7 -1
  58. package/dist/menu/menu-dom.mjs.map +1 -1
  59. package/dist/menu/menu-group.mjs +1 -1
  60. package/dist/menu/menu-item.d.mts +6 -2
  61. package/dist/menu/menu-item.d.mts.map +1 -1
  62. package/dist/menu/menu-item.mjs +6 -4
  63. package/dist/menu/menu-item.mjs.map +1 -1
  64. package/dist/menu/menu-popup.mjs +1 -1
  65. package/dist/menu/menu-radio-group.mjs +1 -1
  66. package/dist/menu/menu-root.mjs +1 -1
  67. package/dist/menu/menu-submenu-trigger.mjs +1 -1
  68. package/dist/menu/menu-trigger.d.mts +6 -3
  69. package/dist/menu/menu-trigger.d.mts.map +1 -1
  70. package/dist/menu/menu-trigger.mjs +3 -3
  71. package/dist/menu/menu-trigger.mjs.map +1 -1
  72. package/dist/number-field/number-field-decrement.d.mts +4 -3
  73. package/dist/number-field/number-field-decrement.d.mts.map +1 -1
  74. package/dist/number-field/number-field-decrement.mjs +4 -3
  75. package/dist/number-field/number-field-decrement.mjs.map +1 -1
  76. package/dist/number-field/number-field-increment.d.mts +8 -3
  77. package/dist/number-field/number-field-increment.d.mts.map +1 -1
  78. package/dist/number-field/number-field-increment.mjs +9 -6
  79. package/dist/number-field/number-field-increment.mjs.map +1 -1
  80. package/dist/number-field/number-field-input.mjs +1 -1
  81. package/dist/number-field/number-field-root.mjs +5 -5
  82. package/dist/number-field/number-field-root.mjs.map +1 -1
  83. package/dist/number-field/use-step-button.mjs +6 -1
  84. package/dist/number-field/use-step-button.mjs.map +1 -1
  85. package/dist/popover/popover-close.d.mts +9 -3
  86. package/dist/popover/popover-close.d.mts.map +1 -1
  87. package/dist/popover/popover-close.mjs +13 -8
  88. package/dist/popover/popover-close.mjs.map +1 -1
  89. package/dist/popover/popover-popup.mjs +2 -2
  90. package/dist/popover/popover-trigger.d.mts +8 -4
  91. package/dist/popover/popover-trigger.d.mts.map +1 -1
  92. package/dist/popover/popover-trigger.mjs +3 -3
  93. package/dist/popover/popover-trigger.mjs.map +1 -1
  94. package/dist/radio-group/radio-group-item.mjs +1 -1
  95. package/dist/radio-group/radio-group-root.mjs +1 -1
  96. package/dist/select/select-root.mjs +1 -1
  97. package/dist/slider/slider-root.mjs +6 -6
  98. package/dist/slider/slider-root.mjs.map +1 -1
  99. package/dist/slider/slider-thumb.mjs +1 -1
  100. package/dist/slider/slider-value.mjs +1 -1
  101. package/dist/switch/switch.mjs +2 -2
  102. package/dist/tabs/tabs-list.mjs +1 -1
  103. package/dist/tabs/tabs-panel.mjs +1 -1
  104. package/dist/tabs/tabs-root.mjs +2 -2
  105. package/dist/tabs/tabs-tab.mjs +1 -1
  106. package/dist/toast/toast-action.d.mts +4 -3
  107. package/dist/toast/toast-action.d.mts.map +1 -1
  108. package/dist/toast/toast-action.mjs +8 -6
  109. package/dist/toast/toast-action.mjs.map +1 -1
  110. package/dist/toast/toast-root.mjs +1 -1
  111. package/dist/toast/toast-viewport.mjs +3 -3
  112. package/dist/toggle/toggle.d.mts +4 -1
  113. package/dist/toggle/toggle.d.mts.map +1 -1
  114. package/dist/toggle/toggle.mjs +16 -10
  115. package/dist/toggle/toggle.mjs.map +1 -1
  116. package/dist/toggle-group/toggle-group-item.d.mts +6 -2
  117. package/dist/toggle-group/toggle-group-item.d.mts.map +1 -1
  118. package/dist/toggle-group/toggle-group-item.mjs +10 -5
  119. package/dist/toggle-group/toggle-group-item.mjs.map +1 -1
  120. package/dist/toggle-group/toggle-group-root.mjs +3 -3
  121. package/dist/toolbar/index.d.mts +4 -5
  122. package/dist/toolbar/index.d.mts.map +1 -1
  123. package/dist/toolbar/index.mjs +3 -4
  124. package/dist/toolbar/index.mjs.map +1 -1
  125. package/dist/toolbar/toolbar-root.mjs +1 -1
  126. package/dist/toolbar/toolbar-separator.mjs +1 -1
  127. package/package.json +2 -1
  128. package/dist/toolbar/toolbar-button.d.mts +0 -42
  129. package/dist/toolbar/toolbar-button.d.mts.map +0 -1
  130. package/dist/toolbar/toolbar-button.mjs +0 -50
  131. package/dist/toolbar/toolbar-button.mjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
2
  import { dataAttr } from "../internal/data-attr.mjs";
4
- import { useRender } from "../internal/use-render.mjs";
3
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
5
4
  import { useDevWarning } from "../internal/use-dev-warning.mjs";
5
+ import { useRender } from "../internal/use-render.mjs";
6
6
  import { AccordionItemContext, AccordionRootContext } from "./accordion-context.mjs";
7
7
  import { use, useCallback, useMemo, useState } from "react";
8
8
  import { jsx } from "react/jsx-runtime";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
2
  import { dataAttr } from "../internal/data-attr.mjs";
4
- import { useRender } from "../internal/use-render.mjs";
3
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
5
4
  import { useDevWarning } from "../internal/use-dev-warning.mjs";
5
+ import { useRender } from "../internal/use-render.mjs";
6
6
  import { AccordionItemContext } from "./accordion-context.mjs";
7
7
  import { use } from "react";
8
8
  //#region src/accordion/accordion-panel.tsx
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import { createActionDetails } from "../internal/action-details.mjs";
3
3
  import { dataAttr } from "../internal/data-attr.mjs";
4
+ import { useDevWarning } from "../internal/use-dev-warning.mjs";
5
+ import { resolveStateValue } from "../internal/render-element.mjs";
6
+ import { useRender } from "../internal/use-render.mjs";
4
7
  import { transitionTypes } from "../internal/transition-types.mjs";
5
8
  import { useLatest } from "../internal/use-latest.mjs";
6
9
  import { useControllableAction } from "../internal/use-controllable-action.mjs";
7
- import { resolveStateValue } from "../internal/render-element.mjs";
8
- import { useRender } from "../internal/use-render.mjs";
9
- import { useDevWarning } from "../internal/use-dev-warning.mjs";
10
10
  import { AccordionRootContext } from "./accordion-context.mjs";
11
11
  import { useCallback, useEffectEvent, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
12
12
  import { jsx } from "react/jsx-runtime";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
2
  import { dataAttr } from "../internal/data-attr.mjs";
4
- import { useRender } from "../internal/use-render.mjs";
3
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
5
4
  import { useDevWarning } from "../internal/use-dev-warning.mjs";
5
+ import { useRender } from "../internal/use-render.mjs";
6
6
  import { AccordionItemContext } from "./accordion-context.mjs";
7
7
  import { use, useCallback } from "react";
8
8
  //#region src/accordion/accordion-trigger.tsx
@@ -0,0 +1,78 @@
1
+ import { Action, ActionDetails, RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { CSSProperties, ComponentPropsWithRef, ReactNode, ViewTransitionClass } from "react";
3
+ //#region src/button/button.d.ts
4
+ /** Details passed to `Button`'s `action`. Serialisable; `event` is virtual (conventions 2.2). */
5
+ export interface ButtonActionDetails extends ActionDetails {}
6
+ export interface ButtonState {
7
+ /**
8
+ * This Button's own `action` is in flight, or a submission it started through its own
9
+ * function `formAction` is pending.
10
+ */
11
+ readonly pending: boolean;
12
+ /** The `disabled` prop. Not set by pending. */
13
+ readonly disabled: boolean;
14
+ }
15
+ export interface ButtonProps extends Omit<ComponentPropsWithRef<"button">, "onClick" | "aria-disabled" | "className" | "style" | "children" | "type" | "formAction"> {
16
+ /**
17
+ * Runs inside this Button's own transition on click, Enter or Space (`data-pending`
18
+ * meanwhile). Sync or async; may be a Server Function. A rejection reaches the nearest Error
19
+ * Boundary above the Button. While it is pending the Button ignores further activation and
20
+ * renders `aria-disabled="true"`. Not combinable with `formAction` (development error).
21
+ */
22
+ action?: Action<[details: ButtonActionDetails]>;
23
+ /**
24
+ * React's `formAction`: a function (a Server Function, a `useActionState` dispatch, a client
25
+ * function) or a URL, run by React instead of the form's `action` when this Button submits the
26
+ * form. With a function, the Button is `pending` while its own submission runs (not while
27
+ * another submitter's does), ignores further activation meanwhile, and defaults to
28
+ * `type="submit"`.
29
+ */
30
+ formAction?: ComponentPropsWithRef<"button">["formAction"];
31
+ /**
32
+ * Default `"button"`, or `"submit"` when `formAction` is given. Owned on a `<button>` and on a
33
+ * component `render` element (set it here, not on the element; a component should spread it);
34
+ * omitted for a host element of another tag (`<a>`). `action` together with
35
+ * `"submit"` / `"reset"` warns in development: one click would do two things.
36
+ */
37
+ type?: "button" | "submit" | "reset";
38
+ /**
39
+ * Native `disabled` (owned; a `render` element cannot re-enable it) and `data-disabled`.
40
+ * Never dispatches. With `focusableWhenDisabled`, inside a `Toolbar.Root`, or when the
41
+ * rendered element is not a host `<button>` (`render={<a href />}`, a component), renders
42
+ * `aria-disabled="true"` instead.
43
+ */
44
+ disabled?: boolean;
45
+ /**
46
+ * Keep a disabled Button focusable: `aria-disabled="true"` instead of native `disabled`, so
47
+ * keyboard and screen-reader users still find it and a Tooltip on it still opens. Default
48
+ * `false`; implied `true` inside a `Toolbar.Root` (APG Toolbar) and for a `render` element that
49
+ * is not a host `<button>`.
50
+ */
51
+ focusableWhenDisabled?: boolean;
52
+ /**
53
+ * Forwarded as `default` to the Button's `<ViewTransition>`: animates the commit that ends the
54
+ * action (content keyed on `pending`), not a click. Static; any value makes a mount inside a
55
+ * transition start a document view transition (issue #35).
56
+ */
57
+ transition?: ViewTransitionClass;
58
+ className?: StateValue<string | undefined, ButtonState>;
59
+ style?: StateValue<CSSProperties | undefined, ButtonState>;
60
+ children?: StateValue<ReactNode, ButtonState>;
61
+ render?: RenderProp<ComponentPropsWithRef<"button">, ButtonState>;
62
+ }
63
+ /**
64
+ * A button whose click is a transition (design/components/button.md): `<button type="button">`
65
+ * that runs `action` in its own transition, with `data-pending` and `aria-disabled="true"` while
66
+ * it runs, and ignores further activation meanwhile (conventions 2.5). With a function
67
+ * `formAction` it is a form submitter with its own per-submitter pending. Inside a
68
+ * `Toolbar.Root` a disabled Button stays focusable (`aria-disabled`).
69
+ *
70
+ * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `aria-disabled`,
71
+ * `data-pending`, `data-disabled`, `onClick`.
72
+ */
73
+ export declare function Button({ action, formAction, type, disabled, focusableWhenDisabled, transition, className, style, children, render, ...rest }: ButtonProps): ReactNode;
74
+ export declare namespace Button {
75
+ var displayName: string;
76
+ }
77
+ //#endregion
78
+ //# sourceMappingURL=button.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.mts","names":[],"sources":["../../src/button/button.tsx"],"mappings":";;;;iBAoBiB,4BAA4B;iBAE5B;;;;;WAKN;;WAEA;;iBAGM,oBAAoB,KACnC;;;;;;;EASA,SAAS,QAAQ,SAAS;;;;;;;;EAQ1B,aAAa;;;;;;;EAOb;;;;;;;EAOA;;;;;;;EAOA;;;;;;EAMA,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;wBAavC,SACd,QACA,YACA,MACA,UACA,uBACA,YACA,WACA,OACA,UACA,WACG,QACF,cAAW;yBAZE"}
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { createActionDetails } from "../internal/action-details.mjs";
3
+ import { dataAttr } from "../internal/data-attr.mjs";
4
+ import { useToolbarContext } from "../internal/toolbar-context.mjs";
5
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
6
+ import { useActionTrigger } from "../internal/use-action-trigger.mjs";
7
+ import { useDevWarning } from "../internal/use-dev-warning.mjs";
8
+ import { isHostButton, rendersButton } from "../internal/render-element.mjs";
9
+ import { useRender } from "../internal/use-render.mjs";
10
+ import { useRef } from "react";
11
+ import { useFormStatus } from "react-dom";
12
+ //#region src/button/button.tsx
13
+ /**
14
+ * A button whose click is a transition (design/components/button.md): `<button type="button">`
15
+ * that runs `action` in its own transition, with `data-pending` and `aria-disabled="true"` while
16
+ * it runs, and ignores further activation meanwhile (conventions 2.5). With a function
17
+ * `formAction` it is a form submitter with its own per-submitter pending. Inside a
18
+ * `Toolbar.Root` a disabled Button stays focusable (`aria-disabled`).
19
+ *
20
+ * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `aria-disabled`,
21
+ * `data-pending`, `data-disabled`, `onClick`.
22
+ */
23
+ function Button({ action, formAction, type, disabled = false, focusableWhenDisabled = false, transition, className, style, children, render, ...rest }) {
24
+ const toolbar = useToolbarContext();
25
+ const focusable = focusableWhenDisabled || toolbar !== null || !isHostButton(render);
26
+ const { pending: ownPending, run } = useActionTrigger();
27
+ const status = useFormStatus();
28
+ const submittedWith = useRef(void 0);
29
+ const formPending = status.pending && typeof formAction === "function" && (status.action === formAction || status.action === submittedWith.current);
30
+ const pending = ownPending || formPending;
31
+ useDevWarning(action !== void 0 && formAction !== void 0, "Button: `action` and `formAction` were both given. One click would run two actions; the Button runs `action` and leaves `formAction` to the form submission. Pass one of them.");
32
+ useDevWarning(action !== void 0 && (type === "submit" || type === "reset"), `Button: \`action\` together with type="${type}". One click would run \`action\` in a transition and ${type === "reset" ? "reset" : "submit"} the form. Use \`formAction\` for a submitter, or drop \`type\`.`);
33
+ const element = useRender({
34
+ defaultElement: "button",
35
+ render,
36
+ state: {
37
+ pending,
38
+ disabled
39
+ },
40
+ className,
41
+ style,
42
+ children,
43
+ props: formAction === void 0 ? rest : {
44
+ ...rest,
45
+ formAction
46
+ },
47
+ libraryProps: {
48
+ ...rendersButton(render) && { type: type ?? (formAction !== void 0 ? "submit" : "button") },
49
+ disabled: disabled && !focusable ? true : void 0,
50
+ "aria-disabled": pending || disabled && focusable ? true : void 0,
51
+ "data-pending": dataAttr(pending),
52
+ "data-disabled": dataAttr(disabled),
53
+ onClick: (event) => {
54
+ if (disabled) {
55
+ event.preventDefault();
56
+ return;
57
+ }
58
+ if (action === void 0) {
59
+ if (formPending) {
60
+ event.preventDefault();
61
+ return;
62
+ }
63
+ submittedWith.current = formAction;
64
+ return;
65
+ }
66
+ const details = createActionDetails(event.nativeEvent, {});
67
+ if (!run(() => action(details))) event.preventDefault();
68
+ }
69
+ }
70
+ });
71
+ return useTransitionBoundary("Button", transition, element);
72
+ }
73
+ Button.displayName = "Button";
74
+ //#endregion
75
+ export { Button };
76
+
77
+ //# sourceMappingURL=button.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.mjs","names":[],"sources":["../../src/button/button.tsx"],"sourcesContent":["\"use client\";\nimport { useRef } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n ReactNode,\n ViewTransitionClass,\n} from \"react\";\nimport { useFormStatus } from \"react-dom\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { useToolbarContext } from \"../internal/toolbar-context.js\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport type { Action, ActionDetails, RenderProp, StateValue } from \"../internal/types.js\";\nimport { useActionTrigger } from \"../internal/use-action-trigger.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { isHostButton, rendersButton, useRender } from \"../internal/use-render.js\";\n\n/** Details passed to `Button`'s `action`. Serialisable; `event` is virtual (conventions 2.2). */\nexport interface ButtonActionDetails extends ActionDetails {}\n\nexport interface ButtonState {\n /**\n * This Button's own `action` is in flight, or a submission it started through its own\n * function `formAction` is pending.\n */\n readonly pending: boolean;\n /** The `disabled` prop. Not set by pending. */\n readonly disabled: boolean;\n}\n\nexport interface ButtonProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"aria-disabled\" | \"className\" | \"style\" | \"children\" | \"type\" | \"formAction\"\n> {\n /**\n * Runs inside this Button's own transition on click, Enter or Space (`data-pending`\n * meanwhile). Sync or async; may be a Server Function. A rejection reaches the nearest Error\n * Boundary above the Button. While it is pending the Button ignores further activation and\n * renders `aria-disabled=\"true\"`. Not combinable with `formAction` (development error).\n */\n action?: Action<[details: ButtonActionDetails]>;\n /**\n * React's `formAction`: a function (a Server Function, a `useActionState` dispatch, a client\n * function) or a URL, run by React instead of the form's `action` when this Button submits the\n * form. With a function, the Button is `pending` while its own submission runs (not while\n * another submitter's does), ignores further activation meanwhile, and defaults to\n * `type=\"submit\"`.\n */\n formAction?: ComponentPropsWithRef<\"button\">[\"formAction\"];\n /**\n * Default `\"button\"`, or `\"submit\"` when `formAction` is given. Owned on a `<button>` and on a\n * component `render` element (set it here, not on the element; a component should spread it);\n * omitted for a host element of another tag (`<a>`). `action` together with\n * `\"submit\"` / `\"reset\"` warns in development: one click would do two things.\n */\n type?: \"button\" | \"submit\" | \"reset\";\n /**\n * Native `disabled` (owned; a `render` element cannot re-enable it) and `data-disabled`.\n * Never dispatches. With `focusableWhenDisabled`, inside a `Toolbar.Root`, or when the\n * rendered element is not a host `<button>` (`render={<a href />}`, a component), renders\n * `aria-disabled=\"true\"` instead.\n */\n disabled?: boolean;\n /**\n * Keep a disabled Button focusable: `aria-disabled=\"true\"` instead of native `disabled`, so\n * keyboard and screen-reader users still find it and a Tooltip on it still opens. Default\n * `false`; implied `true` inside a `Toolbar.Root` (APG Toolbar) and for a `render` element that\n * is not a host `<button>`.\n */\n focusableWhenDisabled?: boolean;\n /**\n * Forwarded as `default` to the Button's `<ViewTransition>`: animates the commit that ends the\n * action (content keyed on `pending`), not a click. Static; any value makes a mount inside a\n * transition start a document view transition (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, ButtonState>;\n style?: StateValue<CSSProperties | undefined, ButtonState>;\n children?: StateValue<ReactNode, ButtonState>;\n render?: RenderProp<ComponentPropsWithRef<\"button\">, ButtonState>;\n}\n\n/**\n * A button whose click is a transition (design/components/button.md): `<button type=\"button\">`\n * that runs `action` in its own transition, with `data-pending` and `aria-disabled=\"true\"` while\n * it runs, and ignores further activation meanwhile (conventions 2.5). With a function\n * `formAction` it is a form submitter with its own per-submitter pending. Inside a\n * `Toolbar.Root` a disabled Button stays focusable (`aria-disabled`).\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `aria-disabled`,\n * `data-pending`, `data-disabled`, `onClick`.\n */\nexport function Button({\n action,\n formAction,\n type,\n disabled = false,\n focusableWhenDisabled = false,\n transition,\n className,\n style,\n children,\n render,\n ...rest\n}: ButtonProps) {\n const toolbar = useToolbarContext();\n // Not a host <button> (a link, a component): native `disabled` would mean nothing to the\n // browser and hide the state from AT, so the focusable-disabled branch (review fold F1).\n const focusable = focusableWhenDisabled || toolbar !== null || !isHostButton(render);\n const { pending: ownPending, run } = useActionTrigger();\n\n // Per-submitter pending (design 6.2): React reports the submitter's function as\n // `status.action`. `submittedWith` keeps the function this Button last submitted with, so an\n // inline `formAction` whose identity changes during the submission still matches.\n const status = useFormStatus();\n const submittedWith = useRef<unknown>(undefined);\n const formPending =\n status.pending &&\n typeof formAction === \"function\" &&\n // Written only by the click handler, before the submission whose status this render shows,\n // so the render that reads it is never stale for that submission.\n // oxlint-disable-next-line react/refs\n (status.action === formAction || status.action === submittedWith.current);\n const pending = ownPending || formPending;\n\n useDevWarning(\n action !== undefined && formAction !== undefined,\n \"Button: `action` and `formAction` were both given. One click would run two actions; the \" +\n \"Button runs `action` and leaves `formAction` to the form submission. Pass one of them.\",\n );\n useDevWarning(\n action !== undefined && (type === \"submit\" || type === \"reset\"),\n `Button: \\`action\\` together with type=\"${type}\". One click would run \\`action\\` in a ` +\n `transition and ${type === \"reset\" ? \"reset\" : \"submit\"} the form. Use \\`formAction\\` ` +\n `for a submitter, or drop \\`type\\`.`,\n );\n\n const state: ButtonState = { pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"button\">, ButtonState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: formAction === undefined ? rest : { ...rest, formAction },\n libraryProps: {\n ...(rendersButton(render) && {\n type: type ?? (formAction !== undefined ? \"submit\" : \"button\"),\n }),\n // `undefined` (not `false`) in the focusable case, so the owned key removes a render\n // element's `disabled` too.\n disabled: disabled && !focusable ? true : undefined,\n \"aria-disabled\": pending || (disabled && focusable) ? true : undefined,\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n onClick: (event: MouseEvent<HTMLButtonElement>) => {\n // `event.defaultPrevented` is never read: an outer part (`Dialog.Trigger`) cancels the\n // click as part of its own mechanism and the Button must still run (design 5.1).\n if (disabled) {\n // A disabled link must not navigate either.\n event.preventDefault();\n return;\n }\n if (action === undefined) {\n // A native button (a `formAction` submitter, a command, a link): only the guard.\n if (formPending) {\n event.preventDefault();\n return;\n }\n submittedWith.current = formAction;\n return;\n }\n const details: ButtonActionDetails = createActionDetails(event.nativeEvent, {});\n // Ignored while pending: do not navigate, submit or run a command either.\n if (!run(() => action(details))) event.preventDefault();\n },\n },\n });\n\n return useTransitionBoundary(\"Button\", transition, element);\n}\n\nButton.displayName = \"Button\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8FA,SAAgB,OAAO,EACrB,QACA,YACA,MACA,WAAW,OACX,wBAAwB,OACxB,YACA,WACA,OACA,UACA,QACA,GAAG,QACW;CACd,MAAM,UAAU,kBAAkB;CAGlC,MAAM,YAAY,yBAAyB,YAAY,QAAQ,CAAC,aAAa,MAAM;CACnF,MAAM,EAAE,SAAS,YAAY,QAAQ,iBAAiB;CAKtD,MAAM,SAAS,cAAc;CAC7B,MAAM,gBAAgB,OAAgB,KAAA,CAAS;CAC/C,MAAM,cACJ,OAAO,WACP,OAAO,eAAe,eAIrB,OAAO,WAAW,cAAc,OAAO,WAAW,cAAc;CACnE,MAAM,UAAU,cAAc;CAE9B,cACE,WAAW,KAAA,KAAa,eAAe,KAAA,GACvC,gLAEF;CACA,cACE,WAAW,KAAA,MAAc,SAAS,YAAY,SAAS,UACvD,0CAA0C,KAAK,wDAC3B,SAAS,UAAU,UAAU,SAAS,iEAE5D;CAIA,MAAM,UAAU,UAAwD;EACtE,gBAAgB;EAChB;EACA,OAAA;GAL2B;GAAS;EAKhC;EACJ;EACA;EACA;EACA,OAAO,eAAe,KAAA,IAAY,OAAO;GAAE,GAAG;GAAM;EAAW;EAC/D,cAAc;GACZ,GAAI,cAAc,MAAM,KAAK,EAC3B,MAAM,SAAS,eAAe,KAAA,IAAY,WAAW,UACvD;GAGA,UAAU,YAAY,CAAC,YAAY,OAAO,KAAA;GAC1C,iBAAiB,WAAY,YAAY,YAAa,OAAO,KAAA;GAC7D,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,UAAU,UAAyC;IAGjD,IAAI,UAAU;KAEZ,MAAM,eAAe;KACrB;IACF;IACA,IAAI,WAAW,KAAA,GAAW;KAExB,IAAI,aAAa;MACf,MAAM,eAAe;MACrB;KACF;KACA,cAAc,UAAU;KACxB;IACF;IACA,MAAM,UAA+B,oBAAoB,MAAM,aAAa,CAAC,CAAC;IAE9E,IAAI,CAAC,UAAU,OAAO,OAAO,CAAC,GAAG,MAAM,eAAe;GACxD;EACF;CACF,CAAC;CAED,OAAO,sBAAsB,UAAU,YAAY,OAAO;AAC5D;AAEA,OAAO,cAAc"}
@@ -0,0 +1,3 @@
1
+ import "../internal/platform-attributes.mjs";
2
+ import { Button, ButtonActionDetails, ButtonProps, ButtonState } from "./button.mjs";
3
+ export { Button, type ButtonActionDetails, type ButtonProps, type ButtonState };
@@ -0,0 +1 @@
1
+ export { Button } from "./button.mjs";
@@ -1,10 +1,10 @@
1
1
  "use client";
2
- import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
2
  import { createActionDetails } from "../internal/action-details.mjs";
4
3
  import { dataAttr } from "../internal/data-attr.mjs";
4
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
5
+ import { useRender } from "../internal/use-render.mjs";
5
6
  import { transitionTypes } from "../internal/transition-types.mjs";
6
7
  import { useControllableAction } from "../internal/use-controllable-action.mjs";
7
- import { useRender } from "../internal/use-render.mjs";
8
8
  import { fieldInputProps, useFieldControl, useFieldValueChange, useMergedRef } from "../internal/use-field-control.mjs";
9
9
  import { guardCheckableChange, useNativeChecked } from "../internal/use-native-checked.mjs";
10
10
  //#region src/checkbox/checkbox.tsx
@@ -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,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 { useFormReset } from "../internal/use-form-reset.mjs";
6
6
  import { guardCheckableChange, useNativeChecked } from "../internal/use-native-checked.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 { useNativeGroupReconciliation } from "../internal/use-native-group-reconciliation.mjs";
9
9
  import { CheckboxGroupContext, enabledValues } from "./checkbox-group-context.mjs";
@@ -8,7 +8,10 @@ export interface ComboboxClearState {
8
8
  readonly disabled: boolean;
9
9
  }
10
10
  export interface ComboboxClearProps extends Omit<ComponentPropsWithRef<"button">, "onClick" | "onPointerDown" | "onMouseDown" | "tabIndex" | "disabled" | "className" | "style" | "children"> {
11
- /** Disables this button; the Root's `disabled` does too. */
11
+ /**
12
+ * Disables this button; the Root's `disabled` does too. Native `disabled` on a `<button>`; with
13
+ * a link or component `render`, `aria-disabled="true"` instead.
14
+ */
12
15
  disabled?: boolean;
13
16
  className?: StateValue<string | undefined, ComboboxClearState>;
14
17
  style?: StateValue<CSSProperties | undefined, ComboboxClearState>;
@@ -23,8 +26,8 @@ export interface ComboboxClearProps extends Omit<ComponentPropsWithRef<"button">
23
26
  * A click while the listbox is open closes it (the platform's light dismiss: the button is
24
27
  * outside the popup).
25
28
  *
26
- * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `onClick`, `onPointerDown`,
27
- * `onMouseDown`, `data-disabled`.
29
+ * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-disabled` (link or component
30
+ * `render`), `onClick`, `onPointerDown`, `onMouseDown`, `data-disabled`.
28
31
  */
29
32
  export declare function ComboboxClear({ disabled: ownDisabled, className, style, children, render, ...rest }: ComboboxClearProps): ReactNode;
30
33
  export declare namespace ComboboxClear {
@@ -1 +1 @@
1
- {"version":3,"file":"combobox-clear.d.mts","names":[],"sources":["../../src/combobox/combobox-clear.tsx"],"mappings":";;;iBAeiB;;WAEN;WACA;WACA;;iBAGM,2BAA2B,KAC1C;;EAWA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;wBAavC,gBACd,UAAU,aACV,WACA,OACA,UACA,WACG,QACF,qBAAkB;yBAPL"}
1
+ {"version":3,"file":"combobox-clear.d.mts","names":[],"sources":["../../src/combobox/combobox-clear.tsx"],"mappings":";;;iBAeiB;;WAEN;WACA;WACA;;iBAGM,2BAA2B,KAC1C;;;;;EAcA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;wBAavC,gBACd,UAAU,aACV,WACA,OACA,UACA,WACG,QACF,qBAAkB;yBAPL"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { dataAttr } from "../internal/data-attr.mjs";
3
- import { rendersButton } from "../internal/render-element.mjs";
3
+ import { isHostButton, rendersButton } from "../internal/render-element.mjs";
4
4
  import { useRender } from "../internal/use-render.mjs";
5
5
  import { useComboboxContext } from "./combobox-context.mjs";
6
6
  import { useNameWarning } from "./combobox-trigger.mjs";
@@ -12,13 +12,14 @@ import { useNameWarning } from "./combobox-trigger.mjs";
12
12
  * A click while the listbox is open closes it (the platform's light dismiss: the button is
13
13
  * outside the popup).
14
14
  *
15
- * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `onClick`, `onPointerDown`,
16
- * `onMouseDown`, `data-disabled`.
15
+ * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-disabled` (link or component
16
+ * `render`), `onClick`, `onPointerDown`, `onMouseDown`, `data-disabled`.
17
17
  */
18
18
  function ComboboxClear({ disabled: ownDisabled = false, className, style, children, render, ...rest }) {
19
19
  const ctx = useComboboxContext("Combobox.Clear");
20
20
  const disabled = ownDisabled || ctx.disabled;
21
21
  const ref = useNameWarning("Combobox.Clear");
22
+ const focusable = !isHostButton(render);
22
23
  const state = {
23
24
  value: ctx.value,
24
25
  inputValue: ctx.inputValue,
@@ -27,7 +28,8 @@ function ComboboxClear({ disabled: ownDisabled = false, className, style, childr
27
28
  const libraryProps = {
28
29
  ...rendersButton(render) && { type: "button" },
29
30
  tabIndex: -1,
30
- disabled,
31
+ disabled: focusable ? void 0 : disabled,
32
+ ...focusable && { "aria-disabled": disabled ? true : void 0 },
31
33
  onPointerDown: (event) => {
32
34
  event.preventDefault();
33
35
  },
@@ -35,7 +37,10 @@ function ComboboxClear({ disabled: ownDisabled = false, className, style, childr
35
37
  event.preventDefault();
36
38
  },
37
39
  onClick: (event) => {
38
- if (disabled) return;
40
+ if (disabled) {
41
+ event.preventDefault();
42
+ return;
43
+ }
39
44
  ctx.clear(event.nativeEvent);
40
45
  },
41
46
  "data-disabled": dataAttr(disabled)
@@ -1 +1 @@
1
- {"version":3,"file":"combobox-clear.mjs","names":[],"sources":["../../src/combobox/combobox-clear.tsx"],"sourcesContent":["\"use client\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n PointerEvent,\n ReactNode,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { useComboboxContext } from \"./combobox-context.js\";\nimport { useNameWarning } from \"./combobox-trigger.js\";\n\nexport interface ComboboxClearState {\n /** Optimistic selection. */\n readonly value: string | null;\n readonly inputValue: string;\n readonly disabled: boolean;\n}\n\nexport interface ComboboxClearProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n | \"onClick\"\n | \"onPointerDown\"\n | \"onMouseDown\"\n | \"tabIndex\"\n | \"disabled\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** Disables this button; the Root's `disabled` does too. */\n disabled?: boolean;\n className?: StateValue<string | undefined, ComboboxClearState>;\n style?: StateValue<CSSProperties | undefined, ComboboxClearState>;\n children?: StateValue<ReactNode, ComboboxClearState>;\n /** Should render a `<button>`. */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, ComboboxClearState>;\n}\n\n/**\n * The optional button that clears the combobox: `<button type=\"button\" tabindex=\"-1\">`. A click\n * empties the text (urgent) and dispatches `valueChangeAction(null)` unless nothing is selected;\n * the input keeps focus. Always rendered: hide it with CSS (`:placeholder-shown`) or `state`.\n * A click while the listbox is open closes it (the platform's light dismiss: the button is\n * outside the popup).\n *\n * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `onClick`, `onPointerDown`,\n * `onMouseDown`, `data-disabled`.\n */\nexport function ComboboxClear({\n disabled: ownDisabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: ComboboxClearProps) {\n const ctx = useComboboxContext(\"Combobox.Clear\");\n const disabled = ownDisabled || ctx.disabled;\n const ref = useNameWarning(\"Combobox.Clear\");\n const state: ComboboxClearState = { value: ctx.value, inputValue: ctx.inputValue, disabled };\n\n const libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes = {\n ...(rendersButton(render) && { type: \"button\" as const }),\n tabIndex: -1,\n disabled,\n onPointerDown: (event: PointerEvent<HTMLButtonElement>) => {\n event.preventDefault();\n },\n onMouseDown: (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n },\n onClick: (event: MouseEvent<HTMLButtonElement>) => {\n if (disabled) return;\n ctx.clear(event.nativeEvent);\n },\n \"data-disabled\": dataAttr(disabled),\n };\n\n return useRender<ComponentPropsWithRef<\"button\">, ComboboxClearState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps,\n ref,\n });\n}\n\nComboboxClear.displayName = \"ComboboxClear\";\n"],"mappings":";;;;;;;;;;;;;;;;;AAoDA,SAAgB,cAAc,EAC5B,UAAU,cAAc,OACxB,WACA,OACA,UACA,QACA,GAAG,QACkB;CACrB,MAAM,MAAM,mBAAmB,gBAAgB;CAC/C,MAAM,WAAW,eAAe,IAAI;CACpC,MAAM,MAAM,eAAe,gBAAgB;CAC3C,MAAM,QAA4B;EAAE,OAAO,IAAI;EAAO,YAAY,IAAI;EAAY;CAAS;CAE3F,MAAM,eAAiE;EACrE,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;EACvD,UAAU;EACV;EACA,gBAAgB,UAA2C;GACzD,MAAM,eAAe;EACvB;EACA,cAAc,UAAyC;GACrD,MAAM,eAAe;EACvB;EACA,UAAU,UAAyC;GACjD,IAAI,UAAU;GACd,IAAI,MAAM,MAAM,WAAW;EAC7B;EACA,iBAAiB,SAAS,QAAQ;CACpC;CAEA,OAAO,UAA+D;EACpE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;CACF,CAAC;AACH;AAEA,cAAc,cAAc"}
1
+ {"version":3,"file":"combobox-clear.mjs","names":[],"sources":["../../src/combobox/combobox-clear.tsx"],"sourcesContent":["\"use client\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n PointerEvent,\n ReactNode,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { isHostButton, rendersButton, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { useComboboxContext } from \"./combobox-context.js\";\nimport { useNameWarning } from \"./combobox-trigger.js\";\n\nexport interface ComboboxClearState {\n /** Optimistic selection. */\n readonly value: string | null;\n readonly inputValue: string;\n readonly disabled: boolean;\n}\n\nexport interface ComboboxClearProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n | \"onClick\"\n | \"onPointerDown\"\n | \"onMouseDown\"\n | \"tabIndex\"\n | \"disabled\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /**\n * Disables this button; the Root's `disabled` does too. Native `disabled` on a `<button>`; with\n * a link or component `render`, `aria-disabled=\"true\"` instead.\n */\n disabled?: boolean;\n className?: StateValue<string | undefined, ComboboxClearState>;\n style?: StateValue<CSSProperties | undefined, ComboboxClearState>;\n children?: StateValue<ReactNode, ComboboxClearState>;\n /** Should render a `<button>`. */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, ComboboxClearState>;\n}\n\n/**\n * The optional button that clears the combobox: `<button type=\"button\" tabindex=\"-1\">`. A click\n * empties the text (urgent) and dispatches `valueChangeAction(null)` unless nothing is selected;\n * the input keeps focus. Always rendered: hide it with CSS (`:placeholder-shown`) or `state`.\n * A click while the listbox is open closes it (the platform's light dismiss: the button is\n * outside the popup).\n *\n * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-disabled` (link or component\n * `render`), `onClick`, `onPointerDown`, `onMouseDown`, `data-disabled`.\n */\nexport function ComboboxClear({\n disabled: ownDisabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: ComboboxClearProps) {\n const ctx = useComboboxContext(\"Combobox.Clear\");\n const disabled = ownDisabled || ctx.disabled;\n const ref = useNameWarning(\"Combobox.Clear\");\n // A link or component render: native `disabled` would mean nothing on a link; the click\n // handler refuses, so `aria-disabled` (#83).\n const focusable = !isHostButton(render);\n const state: ComboboxClearState = { value: ctx.value, inputValue: ctx.inputValue, disabled };\n\n const libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes = {\n ...(rendersButton(render) && { type: \"button\" as const }),\n tabIndex: -1,\n disabled: focusable ? undefined : disabled,\n ...(focusable && { \"aria-disabled\": disabled ? true : undefined }),\n onPointerDown: (event: PointerEvent<HTMLButtonElement>) => {\n event.preventDefault();\n },\n onMouseDown: (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n },\n onClick: (event: MouseEvent<HTMLButtonElement>) => {\n if (disabled) {\n // A disabled link must not navigate either.\n event.preventDefault();\n return;\n }\n ctx.clear(event.nativeEvent);\n },\n \"data-disabled\": dataAttr(disabled),\n };\n\n return useRender<ComponentPropsWithRef<\"button\">, ComboboxClearState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps,\n ref,\n });\n}\n\nComboboxClear.displayName = \"ComboboxClear\";\n"],"mappings":";;;;;;;;;;;;;;;;;AAuDA,SAAgB,cAAc,EAC5B,UAAU,cAAc,OACxB,WACA,OACA,UACA,QACA,GAAG,QACkB;CACrB,MAAM,MAAM,mBAAmB,gBAAgB;CAC/C,MAAM,WAAW,eAAe,IAAI;CACpC,MAAM,MAAM,eAAe,gBAAgB;CAG3C,MAAM,YAAY,CAAC,aAAa,MAAM;CACtC,MAAM,QAA4B;EAAE,OAAO,IAAI;EAAO,YAAY,IAAI;EAAY;CAAS;CAE3F,MAAM,eAAiE;EACrE,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;EACvD,UAAU;EACV,UAAU,YAAY,KAAA,IAAY;EAClC,GAAI,aAAa,EAAE,iBAAiB,WAAW,OAAO,KAAA,EAAU;EAChE,gBAAgB,UAA2C;GACzD,MAAM,eAAe;EACvB;EACA,cAAc,UAAyC;GACrD,MAAM,eAAe;EACvB;EACA,UAAU,UAAyC;GACjD,IAAI,UAAU;IAEZ,MAAM,eAAe;IACrB;GACF;GACA,IAAI,MAAM,MAAM,WAAW;EAC7B;EACA,iBAAiB,SAAS,QAAQ;CACpC;CAEA,OAAO,UAA+D;EACpE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;CACF,CAAC;AACH;AAEA,cAAc,cAAc"}
@@ -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 { ComboboxGroupContext, ComboboxListContext, useComboboxContext } from "./combobox-context.mjs";
5
5
  import { use, useId, useLayoutEffect } from "react";
6
6
  import { jsx } from "react/jsx-runtime";
@@ -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 { resolveStateValue } 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 { ComboboxListContext, ComboboxPopupContext, useComboboxContext } from "./combobox-context.mjs";
7
7
  import { use, useCallback, useRef } from "react";
8
8
  import { jsx } from "react/jsx-runtime";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { dataAttr } from "../internal/data-attr.mjs";
3
- import { useRender } from "../internal/use-render.mjs";
4
3
  import { useDevWarning } from "../internal/use-dev-warning.mjs";
4
+ import { useRender } from "../internal/use-render.mjs";
5
5
  import { ComboboxListContext, optionId, useComboboxContext } from "./combobox-context.mjs";
6
6
  import { use, useCallback, useLayoutEffect, useRef } from "react";
7
7
  //#region src/combobox/combobox-option.tsx
@@ -1,10 +1,10 @@
1
1
  "use client";
2
- import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
2
  import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { ToolbarContext } from "../internal/toolbar-context.mjs";
4
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
4
5
  import { mergeRefs } from "../internal/merge-props.mjs";
5
6
  import { resolveStateValue } from "../internal/render-element.mjs";
6
7
  import { useRender } from "../internal/use-render.mjs";
7
- import { ToolbarContext } from "../internal/toolbar-context.mjs";
8
8
  import { usePopoverPopup } from "../internal/use-popover-popup.mjs";
9
9
  import { ComboboxPopupContext, useComboboxContext } from "./combobox-context.mjs";
10
10
  import { Activity, useCallback, useMemo } from "react";
@@ -1,16 +1,16 @@
1
1
  "use client";
2
2
  import { createActionDetails } from "../internal/action-details.mjs";
3
- import { useControllableAction } from "../internal/use-controllable-action.mjs";
4
- import { resolveStateValue } from "../internal/render-element.mjs";
5
3
  import { useDevWarning } from "../internal/use-dev-warning.mjs";
4
+ import { resolveStateValue } from "../internal/render-element.mjs";
5
+ import { useControllableAction } from "../internal/use-controllable-action.mjs";
6
6
  import { FieldContext } from "../internal/field-context.mjs";
7
7
  import { useFieldValueChange } from "../internal/use-field-control.mjs";
8
8
  import { useFormReset } from "../internal/use-form-reset.mjs";
9
9
  import { usePopoverRoot } from "../internal/use-popover-root.mjs";
10
10
  import { ComboboxContext } from "./combobox-context.mjs";
11
11
  import { use, useCallback, useDeferredValue, useEffect, useId, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
12
- import { jsx, jsxs } from "react/jsx-runtime";
13
12
  import { flushSync } from "react-dom";
13
+ import { jsx, jsxs } from "react/jsx-runtime";
14
14
  //#region src/combobox/combobox-root.tsx
15
15
  /** The default announcement (design 6.4; conventions 11: English, always overridable). */
16
16
  function defaultComboboxAnnouncement(count) {
@@ -9,7 +9,10 @@ export interface ComboboxTriggerState {
9
9
  readonly disabled: boolean;
10
10
  }
11
11
  export interface ComboboxTriggerProps extends Omit<ComponentPropsWithRef<"button">, "onClick" | "onPointerDown" | "onMouseDown" | "onPointerCancel" | "tabIndex" | "aria-expanded" | "aria-controls" | "disabled" | "className" | "style" | "children"> {
12
- /** Disables this button; the Root's `disabled` does too. */
12
+ /**
13
+ * Disables this button; the Root's `disabled` does too. Native `disabled` on a `<button>`; with
14
+ * a link or component `render`, `aria-disabled="true"` instead.
15
+ */
13
16
  disabled?: boolean;
14
17
  className?: StateValue<string | undefined, ComboboxTriggerState>;
15
18
  style?: StateValue<CSSProperties | undefined, ComboboxTriggerState>;
@@ -24,7 +27,8 @@ export interface ComboboxTriggerProps extends Omit<ComponentPropsWithRef<"button
24
27
  * stop). A press does not take focus from the input, and a click focuses the input. No
25
28
  * `commandfor`: the listbox is anchored to the input, never to this button (design 1).
26
29
  *
27
- * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-expanded`,
30
+ * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-disabled` (link or
31
+ * component `render`), `aria-expanded`,
28
32
  * `aria-controls` (token-merged), `onClick`, `onPointerDown`, `onPointerCancel`, `onMouseDown`,
29
33
  * `data-open`, `data-pending`, `data-disabled`.
30
34
  */
@@ -1 +1 @@
1
- {"version":3,"file":"combobox-trigger.d.mts","names":[],"sources":["../../src/combobox/combobox-trigger.tsx"],"mappings":";;;iBAeiB;;WAEN;;WAEA;WACA;;iBAGM,6BAA6B,KAC5C;;EAcA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;wBAqCvC,kBACd,UAAU,aACV,WACA,OACA,UACA,WACG,QACF,uBAAoB;yBAPP"}
1
+ {"version":3,"file":"combobox-trigger.d.mts","names":[],"sources":["../../src/combobox/combobox-trigger.tsx"],"mappings":";;;iBAeiB;;WAEN;;WAEA;WACA;;iBAGM,6BAA6B,KAC5C;;;;;EAiBA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;;wBAsCvC,kBACd,UAAU,aACV,WACA,OACA,UACA,WACG,QACF,uBAAoB;yBAPP"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { dataAttr } from "../internal/data-attr.mjs";
3
- import { rendersButton } from "../internal/render-element.mjs";
3
+ import { isHostButton, rendersButton } from "../internal/render-element.mjs";
4
4
  import { useRender } from "../internal/use-render.mjs";
5
5
  import { useComboboxContext } from "./combobox-context.mjs";
6
6
  import { useCallback, useRef } from "react";
@@ -30,7 +30,8 @@ function useNameWarning(part) {
30
30
  * stop). A press does not take focus from the input, and a click focuses the input. No
31
31
  * `commandfor`: the listbox is anchored to the input, never to this button (design 1).
32
32
  *
33
- * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-expanded`,
33
+ * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-disabled` (link or
34
+ * component `render`), `aria-expanded`,
34
35
  * `aria-controls` (token-merged), `onClick`, `onPointerDown`, `onPointerCancel`, `onMouseDown`,
35
36
  * `data-open`, `data-pending`, `data-disabled`.
36
37
  */
@@ -40,6 +41,7 @@ function ComboboxTrigger({ disabled: ownDisabled = false, className, style, chil
40
41
  const disabled = ownDisabled || ctx.disabled;
41
42
  const openAtPress = useRef(null);
42
43
  const ref = useNameWarning("Combobox.Trigger");
44
+ const focusable = !isHostButton(render);
43
45
  const state = {
44
46
  open: popover.optimistic,
45
47
  pending: popover.pending,
@@ -48,7 +50,8 @@ function ComboboxTrigger({ disabled: ownDisabled = false, className, style, chil
48
50
  const libraryProps = {
49
51
  ...rendersButton(render) && { type: "button" },
50
52
  tabIndex: -1,
51
- disabled,
53
+ disabled: focusable ? void 0 : disabled,
54
+ ...focusable && { "aria-disabled": disabled ? true : void 0 },
52
55
  "aria-expanded": popover.optimistic,
53
56
  "aria-controls": ctx.ids.list,
54
57
  onPointerDown: (event) => {
@@ -64,7 +67,10 @@ function ComboboxTrigger({ disabled: ownDisabled = false, className, style, chil
64
67
  onClick: (event) => {
65
68
  const wasOpen = (event.detail === 0 ? null : openAtPress.current) ?? popover.intended();
66
69
  openAtPress.current = null;
67
- if (disabled) return;
70
+ if (disabled) {
71
+ event.preventDefault();
72
+ return;
73
+ }
68
74
  const native = event.nativeEvent;
69
75
  if (wasOpen) popover.requestClose(native, "activate");
70
76
  else popover.requestOpen(native, "activate");
@@ -1 +1 @@
1
- {"version":3,"file":"combobox-trigger.mjs","names":[],"sources":["../../src/combobox/combobox-trigger.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback, useRef } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n PointerEvent,\n ReactNode,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { useComboboxContext } from \"./combobox-context.js\";\n\nexport interface ComboboxTriggerState {\n /** Optimistic open state. */\n readonly open: boolean;\n /** The open (or close) transition is in flight. */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface ComboboxTriggerProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n | \"onClick\"\n | \"onPointerDown\"\n | \"onMouseDown\"\n | \"onPointerCancel\"\n | \"tabIndex\"\n | \"aria-expanded\"\n | \"aria-controls\"\n | \"disabled\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** Disables this button; the Root's `disabled` does too. */\n disabled?: boolean;\n className?: StateValue<string | undefined, ComboboxTriggerState>;\n style?: StateValue<CSSProperties | undefined, ComboboxTriggerState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, ComboboxTriggerState>;\n /** Should render a `<button>`. */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, ComboboxTriggerState>;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\n/**\n * Development check (design 9): an icon-only Trigger needs a name from the consumer. Checked a\n * microtask after the element attaches, once per instance.\n */\nexport function useNameWarning(part: string): (element: HTMLElement) => () => void {\n const warned = useRef(false);\n return useCallback(\n (element: HTMLElement) => {\n if (!isDev || warned.current) return () => {};\n queueMicrotask(() => {\n if (warned.current || !element.isConnected) return;\n if (element.hasAttribute(\"aria-label\") || element.hasAttribute(\"aria-labelledby\")) return;\n if ((element.textContent ?? \"\").trim() !== \"\" || element.hasAttribute(\"title\")) return;\n warned.current = true;\n console.error(`${part}: the button has no accessible name. Give it an \\`aria-label\\`.`);\n });\n return () => {};\n },\n [part],\n );\n}\n\n/**\n * The optional button that toggles the listbox: `<button type=\"button\" tabindex=\"-1\"\n * aria-expanded aria-controls>` (the APG keeps it out of the Tab sequence; the input is the one\n * stop). A press does not take focus from the input, and a click focuses the input. No\n * `commandfor`: the listbox is anchored to the input, never to this button (design 1).\n *\n * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-expanded`,\n * `aria-controls` (token-merged), `onClick`, `onPointerDown`, `onPointerCancel`, `onMouseDown`,\n * `data-open`, `data-pending`, `data-disabled`.\n */\nexport function ComboboxTrigger({\n disabled: ownDisabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: ComboboxTriggerProps) {\n const ctx = useComboboxContext(\"Combobox.Trigger\");\n const { popover } = ctx;\n const disabled = ownDisabled || ctx.disabled;\n // What the user saw at the press: a press outside the popup light-dismisses it before the\n // click arrives, so the toggle is decided against the state at `pointerdown`.\n const openAtPress = useRef<boolean | null>(null);\n const ref = useNameWarning(\"Combobox.Trigger\");\n\n const state: ComboboxTriggerState = {\n open: popover.optimistic,\n pending: popover.pending,\n disabled,\n };\n\n const libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes = {\n ...(rendersButton(render) && { type: \"button\" as const }),\n tabIndex: -1,\n disabled,\n \"aria-expanded\": popover.optimistic,\n \"aria-controls\": ctx.ids.list,\n onPointerDown: (event: PointerEvent<HTMLButtonElement>) => {\n openAtPress.current = popover.intended();\n event.preventDefault();\n },\n onPointerCancel: () => {\n // The press never becomes a click.\n openAtPress.current = null;\n },\n onMouseDown: (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n },\n onClick: (event: MouseEvent<HTMLButtonElement>) => {\n // `detail === 0`: a click without a press (assistive technology, `element.click()`); a\n // snapshot left by a press that never clicked (dragged off) does not belong to it.\n const pressed = event.detail === 0 ? null : openAtPress.current;\n const wasOpen = pressed ?? popover.intended();\n openAtPress.current = null;\n if (disabled) return;\n const native = event.nativeEvent;\n if (wasOpen) popover.requestClose(native, \"activate\");\n else popover.requestOpen(native, \"activate\");\n ctx.inputRef.current?.focus();\n },\n \"data-open\": dataAttr(popover.optimistic),\n \"data-pending\": dataAttr(popover.pending),\n \"data-disabled\": dataAttr(disabled),\n };\n\n return useRender<ComponentPropsWithRef<\"button\">, ComboboxTriggerState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps,\n ref,\n });\n}\n\nComboboxTrigger.displayName = \"ComboboxTrigger\";\n"],"mappings":";;;;;;;AA+CA,MAAM,QAAQ,QAAQ,IAAI,aAAa;;;;;AAMvC,SAAgB,eAAe,MAAoD;CACjF,MAAM,SAAS,OAAO,KAAK;CAC3B,OAAO,aACJ,YAAyB;EACxB,IAAI,CAAC,SAAS,OAAO,SAAS,aAAa,CAAC;EAC5C,qBAAqB;GACnB,IAAI,OAAO,WAAW,CAAC,QAAQ,aAAa;GAC5C,IAAI,QAAQ,aAAa,YAAY,KAAK,QAAQ,aAAa,iBAAiB,GAAG;GACnF,KAAK,QAAQ,eAAe,GAAA,CAAI,KAAK,MAAM,MAAM,QAAQ,aAAa,OAAO,GAAG;GAChF,OAAO,UAAU;GACjB,QAAQ,MAAM,GAAG,KAAK,gEAAgE;EACxF,CAAC;EACD,aAAa,CAAC;CAChB,GACA,CAAC,IAAI,CACP;AACF;;;;;;;;;;;AAYA,SAAgB,gBAAgB,EAC9B,UAAU,cAAc,OACxB,WACA,OACA,UACA,QACA,GAAG,QACoB;CACvB,MAAM,MAAM,mBAAmB,kBAAkB;CACjD,MAAM,EAAE,YAAY;CACpB,MAAM,WAAW,eAAe,IAAI;CAGpC,MAAM,cAAc,OAAuB,IAAI;CAC/C,MAAM,MAAM,eAAe,kBAAkB;CAE7C,MAAM,QAA8B;EAClC,MAAM,QAAQ;EACd,SAAS,QAAQ;EACjB;CACF;CAEA,MAAM,eAAiE;EACrE,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;EACvD,UAAU;EACV;EACA,iBAAiB,QAAQ;EACzB,iBAAiB,IAAI,IAAI;EACzB,gBAAgB,UAA2C;GACzD,YAAY,UAAU,QAAQ,SAAS;GACvC,MAAM,eAAe;EACvB;EACA,uBAAuB;GAErB,YAAY,UAAU;EACxB;EACA,cAAc,UAAyC;GACrD,MAAM,eAAe;EACvB;EACA,UAAU,UAAyC;GAIjD,MAAM,WADU,MAAM,WAAW,IAAI,OAAO,YAAY,YAC7B,QAAQ,SAAS;GAC5C,YAAY,UAAU;GACtB,IAAI,UAAU;GACd,MAAM,SAAS,MAAM;GACrB,IAAI,SAAS,QAAQ,aAAa,QAAQ,UAAU;QAC/C,QAAQ,YAAY,QAAQ,UAAU;GAC3C,IAAI,SAAS,SAAS,MAAM;EAC9B;EACA,aAAa,SAAS,QAAQ,UAAU;EACxC,gBAAgB,SAAS,QAAQ,OAAO;EACxC,iBAAiB,SAAS,QAAQ;CACpC;CAEA,OAAO,UAAiE;EACtE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;CACF,CAAC;AACH;AAEA,gBAAgB,cAAc"}
1
+ {"version":3,"file":"combobox-trigger.mjs","names":[],"sources":["../../src/combobox/combobox-trigger.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback, useRef } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n PointerEvent,\n ReactNode,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { isHostButton, rendersButton, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { useComboboxContext } from \"./combobox-context.js\";\n\nexport interface ComboboxTriggerState {\n /** Optimistic open state. */\n readonly open: boolean;\n /** The open (or close) transition is in flight. */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface ComboboxTriggerProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n | \"onClick\"\n | \"onPointerDown\"\n | \"onMouseDown\"\n | \"onPointerCancel\"\n | \"tabIndex\"\n | \"aria-expanded\"\n | \"aria-controls\"\n | \"disabled\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /**\n * Disables this button; the Root's `disabled` does too. Native `disabled` on a `<button>`; with\n * a link or component `render`, `aria-disabled=\"true\"` instead.\n */\n disabled?: boolean;\n className?: StateValue<string | undefined, ComboboxTriggerState>;\n style?: StateValue<CSSProperties | undefined, ComboboxTriggerState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, ComboboxTriggerState>;\n /** Should render a `<button>`. */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, ComboboxTriggerState>;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\n/**\n * Development check (design 9): an icon-only Trigger needs a name from the consumer. Checked a\n * microtask after the element attaches, once per instance.\n */\nexport function useNameWarning(part: string): (element: HTMLElement) => () => void {\n const warned = useRef(false);\n return useCallback(\n (element: HTMLElement) => {\n if (!isDev || warned.current) return () => {};\n queueMicrotask(() => {\n if (warned.current || !element.isConnected) return;\n if (element.hasAttribute(\"aria-label\") || element.hasAttribute(\"aria-labelledby\")) return;\n if ((element.textContent ?? \"\").trim() !== \"\" || element.hasAttribute(\"title\")) return;\n warned.current = true;\n console.error(`${part}: the button has no accessible name. Give it an \\`aria-label\\`.`);\n });\n return () => {};\n },\n [part],\n );\n}\n\n/**\n * The optional button that toggles the listbox: `<button type=\"button\" tabindex=\"-1\"\n * aria-expanded aria-controls>` (the APG keeps it out of the Tab sequence; the input is the one\n * stop). A press does not take focus from the input, and a click focuses the input. No\n * `commandfor`: the listbox is anchored to the input, never to this button (design 1).\n *\n * Owned keys: `type` (on a `<button>`), `tabIndex`, `disabled`, `aria-disabled` (link or\n * component `render`), `aria-expanded`,\n * `aria-controls` (token-merged), `onClick`, `onPointerDown`, `onPointerCancel`, `onMouseDown`,\n * `data-open`, `data-pending`, `data-disabled`.\n */\nexport function ComboboxTrigger({\n disabled: ownDisabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: ComboboxTriggerProps) {\n const ctx = useComboboxContext(\"Combobox.Trigger\");\n const { popover } = ctx;\n const disabled = ownDisabled || ctx.disabled;\n // What the user saw at the press: a press outside the popup light-dismisses it before the\n // click arrives, so the toggle is decided against the state at `pointerdown`.\n const openAtPress = useRef<boolean | null>(null);\n const ref = useNameWarning(\"Combobox.Trigger\");\n\n // A link or component render: native `disabled` would mean nothing on a link; the click\n // handler refuses, so `aria-disabled` (#83).\n const focusable = !isHostButton(render);\n\n const state: ComboboxTriggerState = {\n open: popover.optimistic,\n pending: popover.pending,\n disabled,\n };\n\n const libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes = {\n ...(rendersButton(render) && { type: \"button\" as const }),\n tabIndex: -1,\n disabled: focusable ? undefined : disabled,\n ...(focusable && { \"aria-disabled\": disabled ? true : undefined }),\n \"aria-expanded\": popover.optimistic,\n \"aria-controls\": ctx.ids.list,\n onPointerDown: (event: PointerEvent<HTMLButtonElement>) => {\n openAtPress.current = popover.intended();\n event.preventDefault();\n },\n onPointerCancel: () => {\n // The press never becomes a click.\n openAtPress.current = null;\n },\n onMouseDown: (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n },\n onClick: (event: MouseEvent<HTMLButtonElement>) => {\n // `detail === 0`: a click without a press (assistive technology, `element.click()`); a\n // snapshot left by a press that never clicked (dragged off) does not belong to it.\n const pressed = event.detail === 0 ? null : openAtPress.current;\n const wasOpen = pressed ?? popover.intended();\n openAtPress.current = null;\n if (disabled) {\n // A disabled link must not navigate either.\n event.preventDefault();\n return;\n }\n const native = event.nativeEvent;\n if (wasOpen) popover.requestClose(native, \"activate\");\n else popover.requestOpen(native, \"activate\");\n ctx.inputRef.current?.focus();\n },\n \"data-open\": dataAttr(popover.optimistic),\n \"data-pending\": dataAttr(popover.pending),\n \"data-disabled\": dataAttr(disabled),\n };\n\n return useRender<ComponentPropsWithRef<\"button\">, ComboboxTriggerState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps,\n ref,\n });\n}\n\nComboboxTrigger.displayName = \"ComboboxTrigger\";\n"],"mappings":";;;;;;;AAkDA,MAAM,QAAQ,QAAQ,IAAI,aAAa;;;;;AAMvC,SAAgB,eAAe,MAAoD;CACjF,MAAM,SAAS,OAAO,KAAK;CAC3B,OAAO,aACJ,YAAyB;EACxB,IAAI,CAAC,SAAS,OAAO,SAAS,aAAa,CAAC;EAC5C,qBAAqB;GACnB,IAAI,OAAO,WAAW,CAAC,QAAQ,aAAa;GAC5C,IAAI,QAAQ,aAAa,YAAY,KAAK,QAAQ,aAAa,iBAAiB,GAAG;GACnF,KAAK,QAAQ,eAAe,GAAA,CAAI,KAAK,MAAM,MAAM,QAAQ,aAAa,OAAO,GAAG;GAChF,OAAO,UAAU;GACjB,QAAQ,MAAM,GAAG,KAAK,gEAAgE;EACxF,CAAC;EACD,aAAa,CAAC;CAChB,GACA,CAAC,IAAI,CACP;AACF;;;;;;;;;;;;AAaA,SAAgB,gBAAgB,EAC9B,UAAU,cAAc,OACxB,WACA,OACA,UACA,QACA,GAAG,QACoB;CACvB,MAAM,MAAM,mBAAmB,kBAAkB;CACjD,MAAM,EAAE,YAAY;CACpB,MAAM,WAAW,eAAe,IAAI;CAGpC,MAAM,cAAc,OAAuB,IAAI;CAC/C,MAAM,MAAM,eAAe,kBAAkB;CAI7C,MAAM,YAAY,CAAC,aAAa,MAAM;CAEtC,MAAM,QAA8B;EAClC,MAAM,QAAQ;EACd,SAAS,QAAQ;EACjB;CACF;CAEA,MAAM,eAAiE;EACrE,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;EACvD,UAAU;EACV,UAAU,YAAY,KAAA,IAAY;EAClC,GAAI,aAAa,EAAE,iBAAiB,WAAW,OAAO,KAAA,EAAU;EAChE,iBAAiB,QAAQ;EACzB,iBAAiB,IAAI,IAAI;EACzB,gBAAgB,UAA2C;GACzD,YAAY,UAAU,QAAQ,SAAS;GACvC,MAAM,eAAe;EACvB;EACA,uBAAuB;GAErB,YAAY,UAAU;EACxB;EACA,cAAc,UAAyC;GACrD,MAAM,eAAe;EACvB;EACA,UAAU,UAAyC;GAIjD,MAAM,WADU,MAAM,WAAW,IAAI,OAAO,YAAY,YAC7B,QAAQ,SAAS;GAC5C,YAAY,UAAU;GACtB,IAAI,UAAU;IAEZ,MAAM,eAAe;IACrB;GACF;GACA,MAAM,SAAS,MAAM;GACrB,IAAI,SAAS,QAAQ,aAAa,QAAQ,UAAU;QAC/C,QAAQ,YAAY,QAAQ,UAAU;GAC3C,IAAI,SAAS,SAAS,MAAM;EAC9B;EACA,aAAa,SAAS,QAAQ,UAAU;EACxC,gBAAgB,SAAS,QAAQ,OAAO;EACxC,iBAAiB,SAAS,QAAQ;CACpC;CAEA,OAAO,UAAiE;EACtE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;CACF,CAAC;AACH;AAEA,gBAAgB,cAAc"}
@@ -24,7 +24,11 @@ export interface DialogCloseProps extends Omit<ComponentPropsWithRef<"button">,
24
24
  action?: Action<[details: DialogCloseDetails]>;
25
25
  /** Becomes `dialog.returnValue` (and `details.returnValue` of `openChangeAction(false)`). */
26
26
  value?: string;
27
- /** Native `disabled`; owned, so a `render` element cannot re-enable the button. */
27
+ /**
28
+ * Never closes. Native `disabled` on a `<button>`; owned, so a `render` element cannot
29
+ * re-enable it. With a link or component `render` whose click this part handles (library mode,
30
+ * or with `action`), `aria-disabled="true"` instead: the element stays focusable.
31
+ */
28
32
  disabled?: boolean;
29
33
  className?: StateValue<string | undefined, DialogCloseState>;
30
34
  style?: StateValue<CSSProperties | undefined, DialogCloseState>;
@@ -37,10 +41,11 @@ export interface DialogCloseProps extends Omit<ComponentPropsWithRef<"button">,
37
41
  * `value` as the `returnValue`. In library mode the click is always cancelled and the close goes
38
42
  * through the Root (`openChangeAction(false)` awaited, then `close(value)` in the commit, inside
39
43
  * the view transition if the Popup's `transition` is set). With `action` the action runs first in
40
- * this part's own transition (`data-pending` on the button); a rejection leaves the dialog open.
44
+ * this part's own transition (`data-pending` and `aria-disabled` on the button; a second click
45
+ * meanwhile is ignored); a rejection leaves the dialog open.
41
46
  *
42
47
  * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,
43
- * `command`, `value`, `onClick` (library mode, or with `action`), `data-pending`,
48
+ * `command`, `value`, `onClick` (library mode, or with `action`), `aria-disabled`, `data-pending`,
44
49
  * `data-disabled`.
45
50
  */
46
51
  export declare function DialogClose({ action, value, disabled, className, style, children, render, ...rest }: DialogCloseProps): ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"dialog-close.d.mts","names":[],"sources":["../../src/dialog/dialog-close.tsx"],"mappings":";;;iBAWiB;;WAEN;WACA;;;iBAIM,2BAA2B;;WAEjC;;iBAGM,yBAAyB,KACxC;;;;;;;;;;EAYA,SAAS,QAAQ,SAAS;;EAE1B;;EAEA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;;;wBAiBvC,cACd,QACA,OACA,UACA,WACA,OACA,UACA,WACG,QACF,mBAAgB;yBATH"}
1
+ {"version":3,"file":"dialog-close.d.mts","names":[],"sources":["../../src/dialog/dialog-close.tsx"],"mappings":";;;iBAWiB;;WAEN;WACA;;;iBAIM,2BAA2B;;WAEjC;;iBAGM,yBAAyB,KACxC;;;;;;;;;;EAYA,SAAS,QAAQ,SAAS;;EAE1B;;;;;;EAMA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;;;;wBAkBvC,cACd,QACA,OACA,UACA,WACA,OACA,UACA,WACG,QACF,mBAAgB;yBATH"}