@funstack/ui 0.1.0-alpha.1 → 0.1.0-alpha.2

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 (94) hide show
  1. package/dist/combobox/combobox-clear.d.mts +34 -0
  2. package/dist/combobox/combobox-clear.d.mts.map +1 -0
  3. package/dist/combobox/combobox-clear.mjs +58 -0
  4. package/dist/combobox/combobox-clear.mjs.map +1 -0
  5. package/dist/combobox/combobox-context.mjs +23 -0
  6. package/dist/combobox/combobox-context.mjs.map +1 -0
  7. package/dist/combobox/combobox-group.d.mts +72 -0
  8. package/dist/combobox/combobox-group.d.mts.map +1 -0
  9. package/dist/combobox/combobox-group.mjs +104 -0
  10. package/dist/combobox/combobox-group.mjs.map +1 -0
  11. package/dist/combobox/combobox-input.d.mts +40 -0
  12. package/dist/combobox/combobox-input.d.mts.map +1 -0
  13. package/dist/combobox/combobox-input.mjs +88 -0
  14. package/dist/combobox/combobox-input.mjs.map +1 -0
  15. package/dist/combobox/combobox-label.d.mts +22 -0
  16. package/dist/combobox/combobox-label.d.mts.map +1 -0
  17. package/dist/combobox/combobox-label.mjs +32 -0
  18. package/dist/combobox/combobox-label.mjs.map +1 -0
  19. package/dist/combobox/combobox-list.d.mts +37 -0
  20. package/dist/combobox/combobox-list.d.mts.map +1 -0
  21. package/dist/combobox/combobox-list.mjs +70 -0
  22. package/dist/combobox/combobox-list.mjs.map +1 -0
  23. package/dist/combobox/combobox-option.d.mts +45 -0
  24. package/dist/combobox/combobox-option.d.mts.map +1 -0
  25. package/dist/combobox/combobox-option.mjs +88 -0
  26. package/dist/combobox/combobox-option.mjs.map +1 -0
  27. package/dist/combobox/combobox-popup.d.mts +49 -0
  28. package/dist/combobox/combobox-popup.d.mts.map +1 -0
  29. package/dist/combobox/combobox-popup.mjs +86 -0
  30. package/dist/combobox/combobox-popup.mjs.map +1 -0
  31. package/dist/combobox/combobox-root.d.mts +135 -0
  32. package/dist/combobox/combobox-root.d.mts.map +1 -0
  33. package/dist/combobox/combobox-root.mjs +508 -0
  34. package/dist/combobox/combobox-root.mjs.map +1 -0
  35. package/dist/combobox/combobox-trigger.d.mts +36 -0
  36. package/dist/combobox/combobox-trigger.d.mts.map +1 -0
  37. package/dist/combobox/combobox-trigger.mjs +92 -0
  38. package/dist/combobox/combobox-trigger.mjs.map +1 -0
  39. package/dist/combobox/index.d.mts +36 -0
  40. package/dist/combobox/index.d.mts.map +1 -0
  41. package/dist/combobox/index.mjs +36 -0
  42. package/dist/combobox/index.mjs.map +1 -0
  43. package/dist/index.d.mts +20 -2
  44. package/dist/index.mjs +3 -1
  45. package/dist/internal/platform-attributes.d.mts +12 -1
  46. package/dist/internal/platform-attributes.d.mts.map +1 -1
  47. package/dist/internal/types.d.mts +8 -0
  48. package/dist/internal/types.d.mts.map +1 -1
  49. package/dist/internal/use-controllable-action.mjs +5 -1
  50. package/dist/internal/use-controllable-action.mjs.map +1 -1
  51. package/dist/internal/use-form-reset.mjs +5 -1
  52. package/dist/internal/use-form-reset.mjs.map +1 -1
  53. package/dist/internal/use-hydrated-mount.mjs +21 -0
  54. package/dist/internal/use-hydrated-mount.mjs.map +1 -0
  55. package/dist/internal/use-native-group-reconciliation.mjs.map +1 -1
  56. package/dist/internal/use-native-select-value.mjs +182 -0
  57. package/dist/internal/use-native-select-value.mjs.map +1 -0
  58. package/dist/select/index.d.mts +30 -0
  59. package/dist/select/index.d.mts.map +1 -0
  60. package/dist/select/index.mjs +30 -0
  61. package/dist/select/index.mjs.map +1 -0
  62. package/dist/select/select-context.mjs +13 -0
  63. package/dist/select/select-context.mjs.map +1 -0
  64. package/dist/select/select-dom.mjs +44 -0
  65. package/dist/select/select-dom.mjs.map +1 -0
  66. package/dist/select/select-group-label.d.mts +22 -0
  67. package/dist/select/select-group-label.d.mts.map +1 -0
  68. package/dist/select/select-group-label.mjs +39 -0
  69. package/dist/select/select-group-label.mjs.map +1 -0
  70. package/dist/select/select-group.d.mts +28 -0
  71. package/dist/select/select-group.d.mts.map +1 -0
  72. package/dist/select/select-group.mjs +45 -0
  73. package/dist/select/select-group.mjs.map +1 -0
  74. package/dist/select/select-option.d.mts +42 -0
  75. package/dist/select/select-option.d.mts.map +1 -0
  76. package/dist/select/select-option.mjs +65 -0
  77. package/dist/select/select-option.mjs.map +1 -0
  78. package/dist/select/select-root.d.mts +66 -0
  79. package/dist/select/select-root.d.mts.map +1 -0
  80. package/dist/select/select-root.mjs +94 -0
  81. package/dist/select/select-root.mjs.map +1 -0
  82. package/dist/select/select-separator.d.mts +20 -0
  83. package/dist/select/select-separator.d.mts.map +1 -0
  84. package/dist/select/select-separator.mjs +30 -0
  85. package/dist/select/select-separator.mjs.map +1 -0
  86. package/dist/select/select-trigger.d.mts +29 -0
  87. package/dist/select/select-trigger.d.mts.map +1 -0
  88. package/dist/select/select-trigger.mjs +48 -0
  89. package/dist/select/select-trigger.mjs.map +1 -0
  90. package/dist/select/select-value.d.mts +31 -0
  91. package/dist/select/select-value.d.mts.map +1 -0
  92. package/dist/select/select-value.mjs +101 -0
  93. package/dist/select/select-value.mjs.map +1 -0
  94. package/package.json +3 -1
@@ -0,0 +1,70 @@
1
+ "use client";
2
+ import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { resolveStateValue, useRender } from "../internal/use-render.mjs";
4
+ import { useDevWarning } from "../internal/use-dev-warning.mjs";
5
+ import { ComboboxListContext, ComboboxPopupContext, useComboboxContext } from "./combobox-context.mjs";
6
+ import { use, useCallback, useRef } from "react";
7
+ import { jsx } from "react/jsx-runtime";
8
+ //#region src/combobox/combobox-list.tsx
9
+ const isDev = process.env.NODE_ENV !== "production";
10
+ /**
11
+ * The listbox: `<div role="listbox" aria-labelledby={label}>` (only while a `Combobox.Label` is
12
+ * mounted), the element the input's `aria-controls` names. Its children are the results for the
13
+ * deferred `query` (the library filters nothing, design 6.1); while they are for an older text it
14
+ * carries `aria-busy="true"` and `data-stale`. Contains only Options and Groups; a `Status`
15
+ * rendered as a Suspense fallback inside it marks the results as loading (`aria-busy="true"`).
16
+ *
17
+ * Owned keys (conventions 1.2): `id`, `role`, `aria-labelledby` (token-merged), `aria-busy`,
18
+ * `data-stale`, `data-empty`.
19
+ */
20
+ function ComboboxList({ className, style, children, render, ...rest }) {
21
+ const ctx = useComboboxContext("Combobox.List");
22
+ const inPopup = use(ComboboxPopupContext);
23
+ useDevWarning(!inPopup, "Combobox.List: rendered outside a Combobox.Popup. The listbox must be inside the Popup, which is the element the library shows and hides.");
24
+ const { listRef } = ctx;
25
+ const warnedName = useRef(false);
26
+ const ref = useCallback((element) => {
27
+ listRef.current = element;
28
+ if (isDev && !warnedName.current) queueMicrotask(() => {
29
+ if (warnedName.current || !element.isConnected) return;
30
+ if (element.hasAttribute("aria-labelledby") || element.hasAttribute("aria-label")) return;
31
+ warnedName.current = true;
32
+ console.error("Combobox.List: the listbox has no accessible name. Render a Combobox.Label, or give the List an `aria-label` / `aria-labelledby`.");
33
+ });
34
+ return () => {
35
+ if (listRef.current === element) listRef.current = null;
36
+ };
37
+ }, [listRef]);
38
+ const state = {
39
+ query: ctx.query,
40
+ stale: ctx.stale,
41
+ empty: ctx.empty
42
+ };
43
+ const libraryProps = {
44
+ id: ctx.ids.list,
45
+ role: "listbox",
46
+ ...ctx.hasLabel && { "aria-labelledby": ctx.ids.label },
47
+ "aria-busy": ctx.stale || ctx.loading ? true : void 0,
48
+ "data-stale": dataAttr(ctx.stale),
49
+ "data-empty": dataAttr(ctx.empty)
50
+ };
51
+ return useRender({
52
+ defaultElement: "div",
53
+ render,
54
+ state,
55
+ className,
56
+ style,
57
+ children: (s) => /* @__PURE__ */ jsx(ComboboxListContext, {
58
+ value: true,
59
+ children: resolveStateValue(children, s)
60
+ }),
61
+ props: rest,
62
+ libraryProps,
63
+ ref
64
+ });
65
+ }
66
+ ComboboxList.displayName = "ComboboxList";
67
+ //#endregion
68
+ export { ComboboxList };
69
+
70
+ //# sourceMappingURL=combobox-list.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-list.mjs","names":[],"sources":["../../src/combobox/combobox-list.tsx"],"sourcesContent":["\"use client\";\nimport { use, useCallback, useRef } from \"react\";\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 { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport {\n ComboboxListContext,\n ComboboxPopupContext,\n useComboboxContext,\n} from \"./combobox-context.js\";\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\nexport interface ComboboxListState {\n /** The deferred text the results are for: render the Options for it. */\n readonly query: string;\n /** The results shown are for an older text (`aria-busy`). */\n readonly stale: boolean;\n /** No option is mounted and the results are settled. */\n readonly empty: boolean;\n}\n\nexport interface ComboboxListProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n \"id\" | \"role\" | \"aria-busy\" | \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, ComboboxListState>;\n style?: StateValue<CSSProperties | undefined, ComboboxListState>;\n /**\n * Usually a function of `{ query }` rendering the Options for it, under your own `<Suspense>`\n * for an async search. The previous results stay visible while the next ones load.\n */\n children?: StateValue<ReactNode, ComboboxListState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ComboboxListState>;\n}\n\n/**\n * The listbox: `<div role=\"listbox\" aria-labelledby={label}>` (only while a `Combobox.Label` is\n * mounted), the element the input's `aria-controls` names. Its children are the results for the\n * deferred `query` (the library filters nothing, design 6.1); while they are for an older text it\n * carries `aria-busy=\"true\"` and `data-stale`. Contains only Options and Groups; a `Status`\n * rendered as a Suspense fallback inside it marks the results as loading (`aria-busy=\"true\"`).\n *\n * Owned keys (conventions 1.2): `id`, `role`, `aria-labelledby` (token-merged), `aria-busy`,\n * `data-stale`, `data-empty`.\n */\nexport function ComboboxList({ className, style, children, render, ...rest }: ComboboxListProps) {\n const ctx = useComboboxContext(\"Combobox.List\");\n const inPopup = use(ComboboxPopupContext);\n useDevWarning(\n !inPopup,\n \"Combobox.List: rendered outside a Combobox.Popup. The listbox must be inside the Popup, \" +\n \"which is the element the library shows and hides.\",\n );\n const { listRef } = ctx;\n const warnedName = useRef(false);\n\n const ref = useCallback(\n (element: HTMLElement) => {\n listRef.current = element;\n if (isDev && !warnedName.current) {\n // A mounted Label registers in a layout effect whose re-render is flushed before this\n // microtask, so `aria-labelledby` is in the DOM by then if it ever will be.\n queueMicrotask(() => {\n if (warnedName.current || !element.isConnected) return;\n if (element.hasAttribute(\"aria-labelledby\") || element.hasAttribute(\"aria-label\")) return;\n warnedName.current = true;\n console.error(\n \"Combobox.List: the listbox has no accessible name. Render a Combobox.Label, or give \" +\n \"the List an `aria-label` / `aria-labelledby`.\",\n );\n });\n }\n return () => {\n if (listRef.current === element) listRef.current = null;\n };\n },\n [listRef],\n );\n\n const state: ComboboxListState = { query: ctx.query, stale: ctx.stale, empty: ctx.empty };\n\n const libraryProps: ComponentPropsWithRef<\"div\"> & DataAttributes = {\n id: ctx.ids.list,\n role: \"listbox\",\n ...(ctx.hasLabel && { \"aria-labelledby\": ctx.ids.label }),\n \"aria-busy\": ctx.stale || ctx.loading ? true : undefined,\n \"data-stale\": dataAttr(ctx.stale),\n \"data-empty\": dataAttr(ctx.empty),\n };\n\n return useRender<ComponentPropsWithRef<\"div\">, ComboboxListState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n style,\n children: (s) => (\n <ComboboxListContext value={true}>{resolveStateValue(children, s)}</ComboboxListContext>\n ),\n props: rest,\n libraryProps,\n ref,\n });\n}\n\nComboboxList.displayName = \"ComboboxList\";\n"],"mappings":";;;;;;;;AAcA,MAAM,QAAQ,QAAQ,IAAI,aAAa;;;;;;;;;;;AAmCvC,SAAgB,aAAa,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA2B;CAC/F,MAAM,MAAM,mBAAmB,eAAe;CAC9C,MAAM,UAAU,IAAI,oBAAoB;CACxC,cACE,CAAC,SACD,2IAEF;CACA,MAAM,EAAE,YAAY;CACpB,MAAM,aAAa,OAAO,KAAK;CAE/B,MAAM,MAAM,aACT,YAAyB;EACxB,QAAQ,UAAU;EAClB,IAAI,SAAS,CAAC,WAAW,SAGvB,qBAAqB;GACnB,IAAI,WAAW,WAAW,CAAC,QAAQ,aAAa;GAChD,IAAI,QAAQ,aAAa,iBAAiB,KAAK,QAAQ,aAAa,YAAY,GAAG;GACnF,WAAW,UAAU;GACrB,QAAQ,MACN,mIAEF;EACF,CAAC;EAEH,aAAa;GACX,IAAI,QAAQ,YAAY,SAAS,QAAQ,UAAU;EACrD;CACF,GACA,CAAC,OAAO,CACV;CAEA,MAAM,QAA2B;EAAE,OAAO,IAAI;EAAO,OAAO,IAAI;EAAO,OAAO,IAAI;CAAM;CAExF,MAAM,eAA8D;EAClE,IAAI,IAAI,IAAI;EACZ,MAAM;EACN,GAAI,IAAI,YAAY,EAAE,mBAAmB,IAAI,IAAI,MAAM;EACvD,aAAa,IAAI,SAAS,IAAI,UAAU,OAAO,KAAA;EAC/C,cAAc,SAAS,IAAI,KAAK;EAChC,cAAc,SAAS,IAAI,KAAK;CAClC;CAEA,OAAO,UAA2D;EAChE,gBAAgB;EAChB;EACA;EACA;EACA;EACA,WAAW,MACT,oBAAC,qBAAD;GAAqB,OAAO;GAAO,UAAA,kBAAkB,UAAU,CAAC;EAAuB,CAAA;EAEzF,OAAO;EACP;EACA;CACF,CAAC;AACH;AAEA,aAAa,cAAc"}
@@ -0,0 +1,45 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
3
+ //#region src/combobox/combobox-option.d.ts
4
+ export interface ComboboxOptionState {
5
+ readonly value: string;
6
+ /** Optimistic: this option's value is the (optimistic) selection. */
7
+ readonly selected: boolean;
8
+ /** `aria-activedescendant` points here (urgent). */
9
+ readonly active: boolean;
10
+ /** The selection is pending and this option is its optimistic target. */
11
+ readonly pending: boolean;
12
+ readonly disabled: boolean;
13
+ }
14
+ export interface ComboboxOptionProps extends Omit<ComponentPropsWithRef<"div">, "id" | "role" | "aria-selected" | "aria-disabled" | "onClick" | "onPointerDown" | "onMouseDown" | "onPointerMove" | "className" | "style" | "children"> {
15
+ /** The selection this option stands for. Unique within the Combobox; also its id fragment. */
16
+ value: string;
17
+ /**
18
+ * The text written into the input when this option is accepted. Default: the element's
19
+ * trimmed `textContent` at that moment. Not used for matching: the library filters nothing.
20
+ */
21
+ label?: string;
22
+ /** `aria-disabled`: shown, skipped by the arrow keys, never accepted. */
23
+ disabled?: boolean;
24
+ className?: StateValue<string | undefined, ComboboxOptionState>;
25
+ style?: StateValue<CSSProperties | undefined, ComboboxOptionState>;
26
+ /** Rendered from optimistic state; must not suspend. */
27
+ children?: StateValue<ReactNode, ComboboxOptionState>;
28
+ render?: RenderProp<ComponentPropsWithRef<"div">, ComboboxOptionState>;
29
+ }
30
+ /**
31
+ * One result: `<div role="option" id aria-selected>`, never focused (virtual focus through the
32
+ * input's `aria-activedescendant`). A click (or Enter while it is active) accepts it: the input
33
+ * text becomes its label at once, it shows `data-selected` and `data-pending`, and the listbox
34
+ * closes when `valueChangeAction` settles. Hovering makes it active.
35
+ *
36
+ * Owned keys (conventions 1.2): `id` (derived from `value`), `role`, `aria-selected`,
37
+ * `aria-disabled`, `onClick`, `onPointerDown`, `onMouseDown`, `onPointerMove`, `data-selected`,
38
+ * `data-active`, `data-pending`, `data-disabled`.
39
+ */
40
+ export declare function ComboboxOption({ value, label, disabled, className, style, children, render, ...rest }: ComboboxOptionProps): ReactNode;
41
+ export declare namespace ComboboxOption {
42
+ var displayName: string;
43
+ }
44
+ //#endregion
45
+ //# sourceMappingURL=combobox-option.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-option.d.mts","names":[],"sources":["../../src/combobox/combobox-option.tsx"],"mappings":";;;iBAgBiB;WACN;;WAEA;;WAEA;;WAEA;WACA;;iBAGM,4BAA4B,KAC3C;;EAcA;;;;;EAKA;;EAEA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,8BAA8B;;;;;;;;;;;;wBAepC,iBACd,OACA,OACA,UACA,WACA,OACA,UACA,WACG,QACF,sBAAmB;yBATN"}
@@ -0,0 +1,88 @@
1
+ "use client";
2
+ import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { useRender } from "../internal/use-render.mjs";
4
+ import { useDevWarning } from "../internal/use-dev-warning.mjs";
5
+ import { ComboboxListContext, optionId, useComboboxContext } from "./combobox-context.mjs";
6
+ import { use, useCallback, useLayoutEffect, useRef } from "react";
7
+ //#region src/combobox/combobox-option.tsx
8
+ const preventDefault = (event) => event.preventDefault();
9
+ /**
10
+ * One result: `<div role="option" id aria-selected>`, never focused (virtual focus through the
11
+ * input's `aria-activedescendant`). A click (or Enter while it is active) accepts it: the input
12
+ * text becomes its label at once, it shows `data-selected` and `data-pending`, and the listbox
13
+ * closes when `valueChangeAction` settles. Hovering makes it active.
14
+ *
15
+ * Owned keys (conventions 1.2): `id` (derived from `value`), `role`, `aria-selected`,
16
+ * `aria-disabled`, `onClick`, `onPointerDown`, `onMouseDown`, `onPointerMove`, `data-selected`,
17
+ * `data-active`, `data-pending`, `data-disabled`.
18
+ */
19
+ function ComboboxOption({ value, label, disabled = false, className, style, children, render, ...rest }) {
20
+ const ctx = useComboboxContext("Combobox.Option");
21
+ const inList = use(ComboboxListContext);
22
+ useDevWarning(!inList, "Combobox.Option: rendered outside a Combobox.List. Options belong in the listbox.");
23
+ const { registerOption } = ctx;
24
+ const elementRef = useRef(null);
25
+ const ref = useCallback((element) => {
26
+ elementRef.current = element;
27
+ return () => {
28
+ if (elementRef.current === element) elementRef.current = null;
29
+ };
30
+ }, []);
31
+ useLayoutEffect(() => {
32
+ const element = elementRef.current;
33
+ if (element === null) return;
34
+ return registerOption(value, {
35
+ element,
36
+ label,
37
+ disabled
38
+ });
39
+ }, [
40
+ registerOption,
41
+ value,
42
+ label,
43
+ disabled
44
+ ]);
45
+ const selected = ctx.value === value;
46
+ const state = {
47
+ value,
48
+ selected,
49
+ active: ctx.activeValue === value,
50
+ pending: ctx.valuePending && selected,
51
+ disabled
52
+ };
53
+ const libraryProps = {
54
+ id: optionId(ctx.ids.optionPrefix, value),
55
+ role: "option",
56
+ "aria-selected": selected,
57
+ "aria-disabled": disabled ? true : void 0,
58
+ onClick: (event) => {
59
+ if (disabled) return;
60
+ ctx.accept(value, event.nativeEvent);
61
+ },
62
+ onPointerDown: (event) => preventDefault(event),
63
+ onMouseDown: (event) => preventDefault(event),
64
+ onPointerMove: () => {
65
+ if (!disabled && ctx.activeValue !== value) ctx.setActive(value);
66
+ },
67
+ "data-selected": dataAttr(selected),
68
+ "data-active": dataAttr(state.active),
69
+ "data-pending": dataAttr(state.pending),
70
+ "data-disabled": dataAttr(disabled)
71
+ };
72
+ return useRender({
73
+ defaultElement: "div",
74
+ render,
75
+ state,
76
+ className,
77
+ style,
78
+ children,
79
+ props: rest,
80
+ libraryProps,
81
+ ref
82
+ });
83
+ }
84
+ ComboboxOption.displayName = "ComboboxOption";
85
+ //#endregion
86
+ export { ComboboxOption };
87
+
88
+ //# sourceMappingURL=combobox-option.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-option.mjs","names":[],"sources":["../../src/combobox/combobox-option.tsx"],"sourcesContent":["\"use client\";\nimport { use, useCallback, useLayoutEffect, 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 { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { ComboboxListContext, optionId, useComboboxContext } from \"./combobox-context.js\";\n\nexport interface ComboboxOptionState {\n readonly value: string;\n /** Optimistic: this option's value is the (optimistic) selection. */\n readonly selected: boolean;\n /** `aria-activedescendant` points here (urgent). */\n readonly active: boolean;\n /** The selection is pending and this option is its optimistic target. */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface ComboboxOptionProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n | \"id\"\n | \"role\"\n | \"aria-selected\"\n | \"aria-disabled\"\n | \"onClick\"\n | \"onPointerDown\"\n | \"onMouseDown\"\n | \"onPointerMove\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** The selection this option stands for. Unique within the Combobox; also its id fragment. */\n value: string;\n /**\n * The text written into the input when this option is accepted. Default: the element's\n * trimmed `textContent` at that moment. Not used for matching: the library filters nothing.\n */\n label?: string;\n /** `aria-disabled`: shown, skipped by the arrow keys, never accepted. */\n disabled?: boolean;\n className?: StateValue<string | undefined, ComboboxOptionState>;\n style?: StateValue<CSSProperties | undefined, ComboboxOptionState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, ComboboxOptionState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ComboboxOptionState>;\n}\n\nconst preventDefault = (event: { preventDefault(): void }) => event.preventDefault();\n\n/**\n * One result: `<div role=\"option\" id aria-selected>`, never focused (virtual focus through the\n * input's `aria-activedescendant`). A click (or Enter while it is active) accepts it: the input\n * text becomes its label at once, it shows `data-selected` and `data-pending`, and the listbox\n * closes when `valueChangeAction` settles. Hovering makes it active.\n *\n * Owned keys (conventions 1.2): `id` (derived from `value`), `role`, `aria-selected`,\n * `aria-disabled`, `onClick`, `onPointerDown`, `onMouseDown`, `onPointerMove`, `data-selected`,\n * `data-active`, `data-pending`, `data-disabled`.\n */\nexport function ComboboxOption({\n value,\n label,\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: ComboboxOptionProps) {\n const ctx = useComboboxContext(\"Combobox.Option\");\n const inList = use(ComboboxListContext);\n useDevWarning(\n !inList,\n \"Combobox.Option: rendered outside a Combobox.List. Options belong in the listbox.\",\n );\n const { registerOption } = ctx;\n\n const elementRef = useRef<HTMLElement | null>(null);\n const ref = useCallback((element: HTMLElement) => {\n elementRef.current = element;\n return () => {\n if (elementRef.current === element) elementRef.current = null;\n };\n }, []);\n\n // Registration (design 14): the Root's registry drives the arrow keys, `Empty`, the active\n // option's revalidation, the announcements and the label cache.\n useLayoutEffect(() => {\n const element = elementRef.current;\n if (element === null) return;\n return registerOption(value, { element, label, disabled });\n }, [registerOption, value, label, disabled]);\n\n const selected = ctx.value === value;\n const state: ComboboxOptionState = {\n value,\n selected,\n active: ctx.activeValue === value,\n pending: ctx.valuePending && selected,\n disabled,\n };\n\n const libraryProps: ComponentPropsWithRef<\"div\"> & DataAttributes = {\n id: optionId(ctx.ids.optionPrefix, value),\n role: \"option\",\n \"aria-selected\": selected,\n \"aria-disabled\": disabled ? true : undefined,\n onClick: (event: MouseEvent<HTMLDivElement>) => {\n if (disabled) return;\n ctx.accept(value, event.nativeEvent);\n },\n // The input keeps focus (design 7.1), also for an Option rendered outside a Popup.\n onPointerDown: (event: PointerEvent<HTMLDivElement>) => preventDefault(event),\n onMouseDown: (event: MouseEvent<HTMLDivElement>) => preventDefault(event),\n onPointerMove: () => {\n if (!disabled && ctx.activeValue !== value) ctx.setActive(value);\n },\n \"data-selected\": dataAttr(selected),\n \"data-active\": dataAttr(state.active),\n \"data-pending\": dataAttr(state.pending),\n \"data-disabled\": dataAttr(disabled),\n };\n\n return useRender<ComponentPropsWithRef<\"div\">, ComboboxOptionState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps,\n ref,\n });\n}\n\nComboboxOption.displayName = \"ComboboxOption\";\n"],"mappings":";;;;;;;AAyDA,MAAM,kBAAkB,UAAsC,MAAM,eAAe;;;;;;;;;;;AAYnF,SAAgB,eAAe,EAC7B,OACA,OACA,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACmB;CACtB,MAAM,MAAM,mBAAmB,iBAAiB;CAChD,MAAM,SAAS,IAAI,mBAAmB;CACtC,cACE,CAAC,QACD,mFACF;CACA,MAAM,EAAE,mBAAmB;CAE3B,MAAM,aAAa,OAA2B,IAAI;CAClD,MAAM,MAAM,aAAa,YAAyB;EAChD,WAAW,UAAU;EACrB,aAAa;GACX,IAAI,WAAW,YAAY,SAAS,WAAW,UAAU;EAC3D;CACF,GAAG,CAAC,CAAC;CAIL,sBAAsB;EACpB,MAAM,UAAU,WAAW;EAC3B,IAAI,YAAY,MAAM;EACtB,OAAO,eAAe,OAAO;GAAE;GAAS;GAAO;EAAS,CAAC;CAC3D,GAAG;EAAC;EAAgB;EAAO;EAAO;CAAQ,CAAC;CAE3C,MAAM,WAAW,IAAI,UAAU;CAC/B,MAAM,QAA6B;EACjC;EACA;EACA,QAAQ,IAAI,gBAAgB;EAC5B,SAAS,IAAI,gBAAgB;EAC7B;CACF;CAEA,MAAM,eAA8D;EAClE,IAAI,SAAS,IAAI,IAAI,cAAc,KAAK;EACxC,MAAM;EACN,iBAAiB;EACjB,iBAAiB,WAAW,OAAO,KAAA;EACnC,UAAU,UAAsC;GAC9C,IAAI,UAAU;GACd,IAAI,OAAO,OAAO,MAAM,WAAW;EACrC;EAEA,gBAAgB,UAAwC,eAAe,KAAK;EAC5E,cAAc,UAAsC,eAAe,KAAK;EACxE,qBAAqB;GACnB,IAAI,CAAC,YAAY,IAAI,gBAAgB,OAAO,IAAI,UAAU,KAAK;EACjE;EACA,iBAAiB,SAAS,QAAQ;EAClC,eAAe,SAAS,MAAM,MAAM;EACpC,gBAAgB,SAAS,MAAM,OAAO;EACtC,iBAAiB,SAAS,QAAQ;CACpC;CAEA,OAAO,UAA6D;EAClE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;CACF,CAAC;AACH;AAEA,eAAe,cAAc"}
@@ -0,0 +1,49 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { CSSProperties, ComponentPropsWithRef, ReactNode, ViewTransitionClass } from "react";
3
+ //#region src/combobox/combobox-popup.d.ts
4
+ export interface ComboboxPopupState {
5
+ /** Committed open state. Read `:popover-open` for the DOM truth. */
6
+ readonly open: boolean;
7
+ /** The results shown are for an older text. */
8
+ readonly stale: boolean;
9
+ /** The deferred text the results are for. */
10
+ readonly query: string;
11
+ }
12
+ export interface ComboboxPopupProps extends Omit<ComponentPropsWithRef<"div">, "id" | "popover" | "onToggle" | "onBeforeToggle" | "onPointerDown" | "onMouseDown" | "className" | "style" | "children"> {
13
+ /**
14
+ * `false` (default): the children are not rendered while the listbox is closed. `true`: they
15
+ * stay mounted inside `<Activity mode="hidden">`.
16
+ */
17
+ keepMounted?: boolean;
18
+ /**
19
+ * Forwarded to the `<ViewTransition default>` around the popover element itself. Animates
20
+ * library-driven opens and closes (typing, the Trigger, an accepted option) in every engine;
21
+ * dismissals are the browser's (CSS only). **A deferred results render also activates the
22
+ * boundary** (React: updates from `useDeferredValue` animate), so use a type map with
23
+ * `default: "none"` unless every result change should cross-fade. Static.
24
+ */
25
+ transition?: ViewTransitionClass;
26
+ className?: StateValue<string | undefined, ComboboxPopupState>;
27
+ style?: StateValue<CSSProperties | undefined, ComboboxPopupState>;
28
+ children?: StateValue<ReactNode, ComboboxPopupState>;
29
+ /** Must render a `<div>`: a `<dialog>` would pull focus out of the input. */
30
+ render?: RenderProp<ComponentPropsWithRef<"div">, ComboboxPopupState>;
31
+ }
32
+ /**
33
+ * The listbox's container: `<div popover="auto">`, opened by the library with
34
+ * `showPopover({ source: input })` and placed below (or, flipped, above) the input with CSS
35
+ * Anchor Positioning, at least as wide as the input. Focus never enters it: a press anywhere in
36
+ * it is `preventDefault()`ed so the input keeps focus (design 7.1). Holds the `List` and, outside
37
+ * it, `Empty` and `Status`. Style it with `:popover-open`; it emits `data-stale` but no
38
+ * `data-open`.
39
+ *
40
+ * Owned keys (conventions 1.2): `id`, `popover`, `onPointerDown`, `onMouseDown`, `data-stale`.
41
+ * Inline `position-area`, `position-try-fallbacks` and `min-width` sit under the consumer's
42
+ * `style` (`style={{ positionTryFallbacks: "none" }}` removes the flip).
43
+ */
44
+ export declare function ComboboxPopup({ keepMounted, transition, className, style, children, render, ...rest }: ComboboxPopupProps): ReactNode;
45
+ export declare namespace ComboboxPopup {
46
+ var displayName: string;
47
+ }
48
+ //#endregion
49
+ //# sourceMappingURL=combobox-popup.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-popup.d.mts","names":[],"sources":["../../src/combobox/combobox-popup.tsx"],"mappings":";;;iBAmBiB;;WAEN;;WAEA;;WAEA;;iBAGM,2BAA2B,KAC1C;;;;;EAeA;;;;;;;;EAQA,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,8BAA8B;;;;;;;;;;;;;;wBAmBpC,gBACd,aACA,YACA,WACA,OACA,UACA,WACG,QACF,qBAAkB;yBARL"}
@@ -0,0 +1,86 @@
1
+ "use client";
2
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
+ import { dataAttr } from "../internal/data-attr.mjs";
4
+ import { mergeRefs } from "../internal/merge-props.mjs";
5
+ import { resolveStateValue, useRender } from "../internal/use-render.mjs";
6
+ import { usePopoverPopup } from "../internal/use-popover-popup.mjs";
7
+ import { ComboboxPopupContext, useComboboxContext } from "./combobox-context.mjs";
8
+ import { Activity, useCallback, useMemo } from "react";
9
+ import { jsx } from "react/jsx-runtime";
10
+ //#region src/combobox/combobox-popup.tsx
11
+ const isDev = process.env.NODE_ENV !== "production";
12
+ const preventDefault = (event) => event.preventDefault();
13
+ /**
14
+ * The listbox's container: `<div popover="auto">`, opened by the library with
15
+ * `showPopover({ source: input })` and placed below (or, flipped, above) the input with CSS
16
+ * Anchor Positioning, at least as wide as the input. Focus never enters it: a press anywhere in
17
+ * it is `preventDefault()`ed so the input keeps focus (design 7.1). Holds the `List` and, outside
18
+ * it, `Empty` and `Status`. Style it with `:popover-open`; it emits `data-stale` but no
19
+ * `data-open`.
20
+ *
21
+ * Owned keys (conventions 1.2): `id`, `popover`, `onPointerDown`, `onMouseDown`, `data-stale`.
22
+ * Inline `position-area`, `position-try-fallbacks` and `min-width` sit under the consumer's
23
+ * `style` (`style={{ positionTryFallbacks: "none" }}` removes the flip).
24
+ */
25
+ function ComboboxPopup({ keepMounted, transition, className, style, children, render, ...rest }) {
26
+ const ctx = useComboboxContext("Combobox.Popup");
27
+ const { popover } = ctx;
28
+ const { setElement, visible, wrapContent } = usePopoverPopup(popover, {
29
+ part: "Combobox.Popup",
30
+ initialFocus: void 0,
31
+ resolveInitialFocus: () => null,
32
+ keepMounted,
33
+ transition
34
+ });
35
+ const devRef = useCallback((element) => {
36
+ if (isDev && element.tagName !== "DIV") console.error(`Combobox.Popup: rendered a <${element.tagName.toLowerCase()}>. Render a <div>: a <dialog popover> runs the dialog focusing steps and takes focus out of the input.`);
37
+ return () => {};
38
+ }, []);
39
+ const ref = useMemo(() => mergeRefs(setElement, devRef), [setElement, devRef]);
40
+ const state = {
41
+ open: popover.committed,
42
+ stale: ctx.stale,
43
+ query: ctx.query
44
+ };
45
+ const libraryProps = {
46
+ id: popover.ids.popup,
47
+ popover: "auto",
48
+ onPointerDown: (event) => preventDefault(event),
49
+ onMouseDown: (event) => preventDefault(event),
50
+ "data-stale": dataAttr(ctx.stale)
51
+ };
52
+ const content = (s) => {
53
+ let node;
54
+ if (keepMounted === true) node = /* @__PURE__ */ jsx(Activity, {
55
+ mode: visible ? "visible" : "hidden",
56
+ children: wrapContent(resolveStateValue(children, s))
57
+ });
58
+ else node = visible ? wrapContent(resolveStateValue(children, s)) : null;
59
+ return /* @__PURE__ */ jsx(ComboboxPopupContext, {
60
+ value: true,
61
+ children: node
62
+ });
63
+ };
64
+ const element = useRender({
65
+ defaultElement: "div",
66
+ render,
67
+ state,
68
+ className,
69
+ style: (s) => ({
70
+ positionArea: "block-end span-inline-end",
71
+ positionTryFallbacks: "flip-block",
72
+ minWidth: "anchor-size(width)",
73
+ ...resolveStateValue(style, s)
74
+ }),
75
+ children: content,
76
+ props: rest,
77
+ libraryProps,
78
+ ref
79
+ });
80
+ return useTransitionBoundary("Combobox.Popup", transition, element);
81
+ }
82
+ ComboboxPopup.displayName = "ComboboxPopup";
83
+ //#endregion
84
+ export { ComboboxPopup };
85
+
86
+ //# sourceMappingURL=combobox-popup.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-popup.mjs","names":[],"sources":["../../src/combobox/combobox-popup.tsx"],"sourcesContent":["\"use client\";\nimport { Activity, useCallback, useMemo } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n MouseEvent,\n PointerEvent,\n ReactNode,\n ViewTransitionClass,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { mergeRefs } from \"../internal/merge-props.js\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { usePopoverPopup } from \"../internal/use-popover-popup.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { ComboboxPopupContext, useComboboxContext } from \"./combobox-context.js\";\n\nexport interface ComboboxPopupState {\n /** Committed open state. Read `:popover-open` for the DOM truth. */\n readonly open: boolean;\n /** The results shown are for an older text. */\n readonly stale: boolean;\n /** The deferred text the results are for. */\n readonly query: string;\n}\n\nexport interface ComboboxPopupProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n | \"id\"\n | \"popover\"\n | \"onToggle\"\n | \"onBeforeToggle\"\n | \"onPointerDown\"\n | \"onMouseDown\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /**\n * `false` (default): the children are not rendered while the listbox is closed. `true`: they\n * stay mounted inside `<Activity mode=\"hidden\">`.\n */\n keepMounted?: boolean;\n /**\n * Forwarded to the `<ViewTransition default>` around the popover element itself. Animates\n * library-driven opens and closes (typing, the Trigger, an accepted option) in every engine;\n * dismissals are the browser's (CSS only). **A deferred results render also activates the\n * boundary** (React: updates from `useDeferredValue` animate), so use a type map with\n * `default: \"none\"` unless every result change should cross-fade. Static.\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, ComboboxPopupState>;\n style?: StateValue<CSSProperties | undefined, ComboboxPopupState>;\n children?: StateValue<ReactNode, ComboboxPopupState>;\n /** Must render a `<div>`: a `<dialog>` would pull focus out of the input. */\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ComboboxPopupState>;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\nconst preventDefault = (event: { preventDefault(): void }) => event.preventDefault();\n\n/**\n * The listbox's container: `<div popover=\"auto\">`, opened by the library with\n * `showPopover({ source: input })` and placed below (or, flipped, above) the input with CSS\n * Anchor Positioning, at least as wide as the input. Focus never enters it: a press anywhere in\n * it is `preventDefault()`ed so the input keeps focus (design 7.1). Holds the `List` and, outside\n * it, `Empty` and `Status`. Style it with `:popover-open`; it emits `data-stale` but no\n * `data-open`.\n *\n * Owned keys (conventions 1.2): `id`, `popover`, `onPointerDown`, `onMouseDown`, `data-stale`.\n * Inline `position-area`, `position-try-fallbacks` and `min-width` sit under the consumer's\n * `style` (`style={{ positionTryFallbacks: \"none\" }}` removes the flip).\n */\nexport function ComboboxPopup({\n keepMounted,\n transition,\n className,\n style,\n children,\n render,\n ...rest\n}: ComboboxPopupProps) {\n const ctx = useComboboxContext(\"Combobox.Popup\");\n const { popover } = ctx;\n\n const { setElement, visible, wrapContent } = usePopoverPopup(popover, {\n part: \"Combobox.Popup\",\n initialFocus: undefined,\n // Focus stays in the input: nothing inside the popup is ever focused.\n resolveInitialFocus: () => null,\n keepMounted,\n transition,\n });\n\n const devRef = useCallback((element: HTMLElement) => {\n if (isDev && element.tagName !== \"DIV\") {\n console.error(\n `Combobox.Popup: rendered a <${element.tagName.toLowerCase()}>. Render a <div>: a ` +\n \"<dialog popover> runs the dialog focusing steps and takes focus out of the input.\",\n );\n }\n return () => {};\n }, []);\n const ref = useMemo(() => mergeRefs(setElement, devRef), [setElement, devRef]);\n\n const state: ComboboxPopupState = {\n open: popover.committed,\n stale: ctx.stale,\n query: ctx.query,\n };\n\n const libraryProps: ComponentPropsWithRef<\"div\"> & DataAttributes = {\n id: popover.ids.popup,\n popover: \"auto\",\n onPointerDown: (event: PointerEvent<HTMLDivElement>) => preventDefault(event),\n onMouseDown: (event: MouseEvent<HTMLDivElement>) => preventDefault(event),\n \"data-stale\": dataAttr(ctx.stale),\n };\n\n const content = (s: ComboboxPopupState): ReactNode => {\n let node: ReactNode;\n if (keepMounted === true) {\n node = (\n <Activity mode={visible ? \"visible\" : \"hidden\"}>\n {wrapContent(resolveStateValue(children, s))}\n </Activity>\n );\n } else {\n node = visible ? wrapContent(resolveStateValue(children, s)) : null;\n }\n return <ComboboxPopupContext value={true}>{node}</ComboboxPopupContext>;\n };\n\n const element = useRender<ComponentPropsWithRef<\"div\">, ComboboxPopupState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n // Logical keywords: right under `direction: rtl` with no JS (design 7.2). The consumer wins.\n style: (s) => ({\n positionArea: \"block-end span-inline-end\",\n positionTryFallbacks: \"flip-block\",\n minWidth: \"anchor-size(width)\",\n ...resolveStateValue(style, s),\n }),\n children: content,\n props: rest,\n libraryProps,\n ref,\n });\n\n return useTransitionBoundary(\"Combobox.Popup\", transition, element);\n}\n\nComboboxPopup.displayName = \"ComboboxPopup\";\n"],"mappings":";;;;;;;;;;AA4DA,MAAM,QAAQ,QAAQ,IAAI,aAAa;AAEvC,MAAM,kBAAkB,UAAsC,MAAM,eAAe;;;;;;;;;;;;;AAcnF,SAAgB,cAAc,EAC5B,aACA,YACA,WACA,OACA,UACA,QACA,GAAG,QACkB;CACrB,MAAM,MAAM,mBAAmB,gBAAgB;CAC/C,MAAM,EAAE,YAAY;CAEpB,MAAM,EAAE,YAAY,SAAS,gBAAgB,gBAAgB,SAAS;EACpE,MAAM;EACN,cAAc,KAAA;EAEd,2BAA2B;EAC3B;EACA;CACF,CAAC;CAED,MAAM,SAAS,aAAa,YAAyB;EACnD,IAAI,SAAS,QAAQ,YAAY,OAC/B,QAAQ,MACN,+BAA+B,QAAQ,QAAQ,YAAY,EAAE,uGAE/D;EAEF,aAAa,CAAC;CAChB,GAAG,CAAC,CAAC;CACL,MAAM,MAAM,cAAc,UAAU,YAAY,MAAM,GAAG,CAAC,YAAY,MAAM,CAAC;CAE7E,MAAM,QAA4B;EAChC,MAAM,QAAQ;EACd,OAAO,IAAI;EACX,OAAO,IAAI;CACb;CAEA,MAAM,eAA8D;EAClE,IAAI,QAAQ,IAAI;EAChB,SAAS;EACT,gBAAgB,UAAwC,eAAe,KAAK;EAC5E,cAAc,UAAsC,eAAe,KAAK;EACxE,cAAc,SAAS,IAAI,KAAK;CAClC;CAEA,MAAM,WAAW,MAAqC;EACpD,IAAI;EACJ,IAAI,gBAAgB,MAClB,OACE,oBAAC,UAAD;GAAU,MAAM,UAAU,YAAY;GACnC,UAAA,YAAY,kBAAkB,UAAU,CAAC,CAAC;EACnC,CAAA;OAGZ,OAAO,UAAU,YAAY,kBAAkB,UAAU,CAAC,CAAC,IAAI;EAEjE,OAAO,oBAAC,sBAAD;GAAsB,OAAO;GAAO,UAAA;EAA2B,CAAA;CACxE;CAEA,MAAM,UAAU,UAA4D;EAC1E,gBAAgB;EAChB;EACA;EACA;EAEA,QAAQ,OAAO;GACb,cAAc;GACd,sBAAsB;GACtB,UAAU;GACV,GAAG,kBAAkB,OAAO,CAAC;EAC/B;EACA,UAAU;EACV,OAAO;EACP;EACA;CACF,CAAC;CAED,OAAO,sBAAsB,kBAAkB,YAAY,OAAO;AACpE;AAEA,cAAc,cAAc"}
@@ -0,0 +1,135 @@
1
+ import { ActionDetails, ChangeAction, ChangeReason, StateValue, UrgentChangeAction } from "../internal/types.mjs";
2
+ import { ReactNode } from "react";
3
+ //#region src/combobox/combobox-root.d.ts
4
+ /** Details passed as the second argument of `Combobox.Root`'s `valueChangeAction`. */
5
+ export interface ComboboxValueChangeDetails extends ActionDetails {
6
+ /**
7
+ * `"activate"`: the user accepted an option (Enter, click; `details.event` is the `keydown` or
8
+ * `click`), committed free text with `allowCustomValue` (Enter: the `keydown`; focus leaving:
9
+ * the `focusout`), or pressed Clear (`click`).
10
+ * `"platform"`: a form reset (`details.event` is the `reset` event).
11
+ */
12
+ readonly reason: ChangeReason;
13
+ /** `true` when `next` is free text committed under `allowCustomValue`, not an option's value. */
14
+ readonly custom: boolean;
15
+ }
16
+ /** Details passed as the second argument of `Combobox.Root`'s `inputValueChangeAction`. */
17
+ export interface ComboboxInputValueChangeDetails extends ActionDetails {
18
+ /**
19
+ * `"activate"`: typing (the `input` event), an accepted option's label, Clear.
20
+ * `"dismiss"`: a revert: focus left with unmatched text, or the selection rolled back.
21
+ * `"platform"`: form reset (the `reset` event), or text found in the input at mount
22
+ * (`undefined`).
23
+ */
24
+ readonly reason: ChangeReason;
25
+ }
26
+ /** Details passed as the second argument of `Combobox.Root`'s `openChangeAction`. */
27
+ export interface ComboboxOpenChangeDetails extends ActionDetails {
28
+ /**
29
+ * `"activate"`: typing, ArrowDown / ArrowUp / Alt+ArrowDown, the Trigger, a click on the input
30
+ * with `openOnClick`, an accepted option (the close after it), a foreign `showPopover()`.
31
+ * `"dismiss"`: Escape, light dismiss, focus leaving the combobox, another top-layer element.
32
+ * `"platform"`: the popup was found open on mount (only script can cause it).
33
+ */
34
+ readonly reason: ChangeReason;
35
+ }
36
+ export interface ComboboxRootState {
37
+ /** Optimistic selection. Content rendered from it must not suspend. */
38
+ readonly value: string | null;
39
+ /** The text in the input (urgent). */
40
+ readonly inputValue: string;
41
+ /** The deferred text the mounted results are for. */
42
+ readonly query: string;
43
+ /** `inputValue !== query`: the results shown are for an older text. */
44
+ readonly stale: boolean;
45
+ /** The value of the option `aria-activedescendant` points at, or `null`. */
46
+ readonly activeValue: string | null;
47
+ /** Optimistic open state. */
48
+ readonly open: boolean;
49
+ /** A `valueChangeAction` or `openChangeAction` dispatched through this Combobox is in flight. */
50
+ readonly pending: boolean;
51
+ readonly disabled: boolean;
52
+ }
53
+ export interface ComboboxRootProps {
54
+ /** Controlled selection. `null`: nothing selected. `undefined`: uncontrolled. */
55
+ value?: string | null;
56
+ /** Initial selection in uncontrolled mode. Default `null`. */
57
+ defaultValue?: string | null;
58
+ /**
59
+ * Runs inside the Root's transition when the user accepts an option, commits free text
60
+ * (`allowCustomValue`), presses Clear, or the form resets. Awaited; the listbox closes in the
61
+ * commit that ends it; a rejection rolls the input text and `data-selected` back and leaves
62
+ * the listbox open. May be a Server Function. A `setState` after your own `await` needs
63
+ * `startTransition`.
64
+ */
65
+ valueChangeAction?: ChangeAction<string | null, ComboboxValueChangeDetails>;
66
+ /** Controlled input text. `undefined`: uncontrolled. */
67
+ inputValue?: string;
68
+ /**
69
+ * Initial input text. Default `""`. Pass the selected value's label when `defaultValue` is
70
+ * set: the library never derives the text from the value.
71
+ */
72
+ defaultInputValue?: string;
73
+ /**
74
+ * The urgent lane: called synchronously, outside any Transition, on every change of the text
75
+ * (typing, and the library's own writes: an accepted option's label, a revert, Clear, a form
76
+ * reset, text typed before hydration). Not awaited; nothing is pending for it. A controlled
77
+ * parent updates its state in the body (an urgent update, which is what a controlled text
78
+ * input needs).
79
+ */
80
+ inputValueChangeAction?: UrgentChangeAction<string, ComboboxInputValueChangeDetails>;
81
+ /** Controlled open state. `undefined`: uncontrolled. */
82
+ open?: boolean;
83
+ /** Initial open state when uncontrolled. Opens after hydration. */
84
+ defaultOpen?: boolean;
85
+ /**
86
+ * Awaited for opens and for the close after an accepted option (or the Trigger); a
87
+ * notification for dismissals (Escape, a click outside, focus leaving).
88
+ */
89
+ openChangeAction?: ChangeAction<boolean, ComboboxOpenChangeDetails>;
90
+ /**
91
+ * Free text is a value: Enter with no active option, or focus leaving with text that is not
92
+ * the selected option's label, dispatches the text with `details.custom: true` (empty text
93
+ * dispatches `null`). Default `false`: unmatched text reverts to the selection's label when
94
+ * focus leaves.
95
+ */
96
+ allowCustomValue?: boolean;
97
+ /**
98
+ * Make the first enabled option active when the results for an open or an edit settle (APG
99
+ * "automatic selection"). Stale results are never highlighted. Default `false`.
100
+ */
101
+ autoHighlight?: boolean;
102
+ /** Open the listbox on a pointer click in the input (not on focus). Default `false`. */
103
+ openOnClick?: boolean;
104
+ /** Wrap from the last option to the first and back with the arrow keys. Default `false`. */
105
+ loop?: boolean;
106
+ /**
107
+ * The message `ariaNotify()` announces on the List when the results settle, from the number
108
+ * of mounted options. Default (English): `"No results"`, `"1 result"`, `"N results"`. Override
109
+ * for localisation or a richer message; return `null` to announce nothing. Ignored where
110
+ * `ariaNotify` is missing.
111
+ */
112
+ announce?: (count: number, state: ComboboxRootState) => string | null;
113
+ /** Form participation through a hidden input with this name (value `""` for `null`). */
114
+ name?: string;
115
+ /** The `form` attribute of the hidden input. */
116
+ form?: string;
117
+ /** Disables the Input, Trigger and Clear; nothing dispatches for user interaction. */
118
+ disabled?: boolean;
119
+ children?: StateValue<ReactNode, ComboboxRootState>;
120
+ }
121
+ /**
122
+ * Owns the two states of a combobox (design/components/combobox.md 2): the selection (`value`,
123
+ * a transition with `useOptimistic`, like every other value) and the text (`inputValue`, the
124
+ * library's **urgent** lane: `inputValueChangeAction` is called synchronously, outside any
125
+ * transition). The results render from `useDeferredValue(inputValue)`; the active option is
126
+ * urgent virtual focus (`aria-activedescendant`); the listbox is a `popover="auto"` opened by the
127
+ * library with the input as `source`. Renders no DOM, except one `<input type="hidden">` when
128
+ * `name` is given.
129
+ */
130
+ export declare function ComboboxRoot(props: ComboboxRootProps): import("react").JSX.Element;
131
+ export declare namespace ComboboxRoot {
132
+ var displayName: string;
133
+ }
134
+ //#endregion
135
+ //# sourceMappingURL=combobox-root.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox-root.d.mts","names":[],"sources":["../../src/combobox/combobox-root.tsx"],"mappings":";;;;iBAgCiB,mCAAmC;;;;;;;WAOzC,QAAQ;;WAER;;;iBAIM,wCAAwC;;;;;;;WAO9C,QAAQ;;;iBAIF,kCAAkC;;;;;;;WAOxC,QAAQ;;iBAGF;;WAEN;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;;iBAGM;;EAEf;;EAEA;;;;;;;;EAQA,oBAAoB,4BAA4B;;EAGhD;;;;;EAKA;;;;;;;;EAQA,yBAAyB,2BAA2B;;EAGpD;;EAEA;;;;;EAKA,mBAAmB,sBAAsB;;;;;;;EAQzC;;;;;EAKA;;EAEA;;EAEA;;;;;;;EAOA,YAAY,eAAe,OAAO;;EAGlC;;EAEA;;EAEA;EACA,WAAW,WAAW,WAAW;;;;;;;;;;;wBA+DnB,aAAa,OAAO,oCAAiB,IAAA;yBAArC"}