@funstack/ui 0.1.0-alpha.0 → 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/checkbox-group/checkbox-group-context.mjs +24 -0
- package/dist/checkbox-group/checkbox-group-context.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-item.d.mts +55 -0
- package/dist/checkbox-group/checkbox-group-item.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-item.mjs +90 -0
- package/dist/checkbox-group/checkbox-group-item.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-label.d.mts +21 -0
- package/dist/checkbox-group/checkbox-group-label.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-label.mjs +30 -0
- package/dist/checkbox-group/checkbox-group-label.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-parent.d.mts +68 -0
- package/dist/checkbox-group/checkbox-group-parent.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-parent.mjs +145 -0
- package/dist/checkbox-group/checkbox-group-parent.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-root.d.mts +100 -0
- package/dist/checkbox-group/checkbox-group-root.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-root.mjs +291 -0
- package/dist/checkbox-group/checkbox-group-root.mjs.map +1 -0
- package/dist/checkbox-group/index.d.mts +23 -0
- package/dist/checkbox-group/index.d.mts.map +1 -0
- package/dist/checkbox-group/index.mjs +23 -0
- package/dist/checkbox-group/index.mjs.map +1 -0
- package/dist/dialog/dialog-close.d.mts.map +1 -1
- package/dist/dialog/dialog-close.mjs +4 -4
- package/dist/dialog/dialog-close.mjs.map +1 -1
- package/dist/dialog/dialog-context.mjs.map +1 -1
- package/dist/dialog/dialog-popup.mjs +1 -0
- package/dist/dialog/dialog-popup.mjs.map +1 -1
- package/dist/dialog/dialog-root.mjs +9 -1
- package/dist/dialog/dialog-root.mjs.map +1 -1
- package/dist/index.d.mts +23 -1
- package/dist/index.mjs +4 -1
- package/dist/internal/anchor-position.d.mts +7 -0
- package/dist/internal/anchor-position.d.mts.map +1 -0
- package/dist/internal/anchor-position.mjs +16 -0
- package/dist/internal/anchor-position.mjs.map +1 -0
- package/dist/internal/platform-attributes.d.mts +6 -0
- package/dist/internal/platform-attributes.d.mts.map +1 -1
- package/dist/internal/sync-presence.mjs +19 -0
- package/dist/internal/sync-presence.mjs.map +1 -0
- package/dist/internal/use-action-trigger.mjs +58 -0
- package/dist/internal/use-action-trigger.mjs.map +1 -0
- package/dist/internal/use-delayed-pair.mjs +40 -0
- package/dist/internal/use-delayed-pair.mjs.map +1 -0
- package/dist/internal/use-exit-animation.mjs +55 -0
- package/dist/internal/use-exit-animation.mjs.map +1 -0
- package/dist/internal/use-native-group-reconciliation.mjs +2 -2
- package/dist/internal/use-native-group-reconciliation.mjs.map +1 -1
- package/dist/internal/use-popover-popup.mjs +274 -0
- package/dist/internal/use-popover-popup.mjs.map +1 -0
- package/dist/internal/use-popover-root.d.mts +2 -0
- package/dist/internal/use-popover-root.mjs +112 -0
- package/dist/internal/use-popover-root.mjs.map +1 -0
- package/dist/internal/use-popover-trigger.mjs +86 -0
- package/dist/internal/use-popover-trigger.mjs.map +1 -0
- package/dist/menu/index.d.mts +34 -0
- package/dist/menu/index.d.mts.map +1 -0
- package/dist/menu/index.mjs +34 -0
- package/dist/menu/index.mjs.map +1 -0
- package/dist/menu/menu-checkbox-item.d.mts +42 -0
- package/dist/menu/menu-checkbox-item.d.mts.map +1 -0
- package/dist/menu/menu-checkbox-item.mjs +71 -0
- package/dist/menu/menu-checkbox-item.mjs.map +1 -0
- package/dist/menu/menu-context.d.mts +1 -0
- package/dist/menu/menu-context.mjs +28 -0
- package/dist/menu/menu-context.mjs.map +1 -0
- package/dist/menu/menu-dom.mjs +37 -0
- package/dist/menu/menu-dom.mjs.map +1 -0
- package/dist/menu/menu-group.d.mts +48 -0
- package/dist/menu/menu-group.d.mts.map +1 -0
- package/dist/menu/menu-group.mjs +69 -0
- package/dist/menu/menu-group.mjs.map +1 -0
- package/dist/menu/menu-hover.mjs +29 -0
- package/dist/menu/menu-hover.mjs.map +1 -0
- package/dist/menu/menu-item.d.mts +45 -0
- package/dist/menu/menu-item.d.mts.map +1 -0
- package/dist/menu/menu-item.mjs +54 -0
- package/dist/menu/menu-item.mjs.map +1 -0
- package/dist/menu/menu-popup.d.mts +69 -0
- package/dist/menu/menu-popup.d.mts.map +1 -0
- package/dist/menu/menu-popup.mjs +207 -0
- package/dist/menu/menu-popup.mjs.map +1 -0
- package/dist/menu/menu-radio-group.d.mts +37 -0
- package/dist/menu/menu-radio-group.d.mts.map +1 -0
- package/dist/menu/menu-radio-group.mjs +72 -0
- package/dist/menu/menu-radio-group.mjs.map +1 -0
- package/dist/menu/menu-radio-item.d.mts +33 -0
- package/dist/menu/menu-radio-item.d.mts.map +1 -0
- package/dist/menu/menu-radio-item.mjs +62 -0
- package/dist/menu/menu-radio-item.mjs.map +1 -0
- package/dist/menu/menu-root.d.mts +54 -0
- package/dist/menu/menu-root.d.mts.map +1 -0
- package/dist/menu/menu-root.mjs +102 -0
- package/dist/menu/menu-root.mjs.map +1 -0
- package/dist/menu/menu-submenu-trigger.d.mts +31 -0
- package/dist/menu/menu-submenu-trigger.d.mts.map +1 -0
- package/dist/menu/menu-submenu-trigger.mjs +92 -0
- package/dist/menu/menu-submenu-trigger.mjs.map +1 -0
- package/dist/menu/menu-trigger.d.mts +36 -0
- package/dist/menu/menu-trigger.d.mts.map +1 -0
- package/dist/menu/menu-trigger.mjs +81 -0
- package/dist/menu/menu-trigger.mjs.map +1 -0
- package/dist/menu/use-menu-item.mjs +54 -0
- package/dist/menu/use-menu-item.mjs.map +1 -0
- package/dist/popover/index.d.mts +28 -0
- package/dist/popover/index.d.mts.map +1 -0
- package/dist/popover/index.mjs +28 -0
- package/dist/popover/index.mjs.map +1 -0
- package/dist/popover/popover-close.d.mts +41 -0
- package/dist/popover/popover-close.d.mts.map +1 -0
- package/dist/popover/popover-close.mjs +90 -0
- package/dist/popover/popover-close.mjs.map +1 -0
- package/dist/popover/popover-context.mjs +26 -0
- package/dist/popover/popover-context.mjs.map +1 -0
- package/dist/popover/popover-description.d.mts +22 -0
- package/dist/popover/popover-description.d.mts.map +1 -0
- package/dist/popover/popover-description.mjs +28 -0
- package/dist/popover/popover-description.mjs.map +1 -0
- package/dist/popover/popover-popup.d.mts +82 -0
- package/dist/popover/popover-popup.d.mts.map +1 -0
- package/dist/popover/popover-popup.mjs +93 -0
- package/dist/popover/popover-popup.mjs.map +1 -0
- package/dist/popover/popover-root.d.mts +64 -0
- package/dist/popover/popover-root.d.mts.map +1 -0
- package/dist/popover/popover-root.mjs +39 -0
- package/dist/popover/popover-root.mjs.map +1 -0
- package/dist/popover/popover-title.d.mts +23 -0
- package/dist/popover/popover-title.d.mts.map +1 -0
- package/dist/popover/popover-title.mjs +28 -0
- package/dist/popover/popover-title.mjs.map +1 -0
- package/dist/popover/popover-trigger.d.mts +37 -0
- package/dist/popover/popover-trigger.d.mts.map +1 -0
- package/dist/popover/popover-trigger.mjs +40 -0
- package/dist/popover/popover-trigger.mjs.map +1 -0
- package/dist/radio-group/radio-group-item.d.mts.map +1 -1
- package/dist/radio-group/radio-group-item.mjs +1 -6
- package/dist/radio-group/radio-group-item.mjs.map +1 -1
- package/dist/tabs/tabs-context.mjs +2 -1
- package/dist/tabs/tabs-context.mjs.map +1 -1
- package/dist/tabs/tabs-list.d.mts +1 -1
- package/dist/tabs/tabs-list.d.mts.map +1 -1
- package/dist/tabs/tabs-list.mjs +17 -9
- package/dist/tabs/tabs-list.mjs.map +1 -1
- package/dist/tabs/tabs-tab.d.mts +1 -1
- package/dist/tabs/tabs-tab.d.mts.map +1 -1
- package/dist/tabs/tabs-tab.mjs +6 -3
- package/dist/tabs/tabs-tab.mjs.map +1 -1
- package/dist/tooltip/tooltip-popup.d.mts.map +1 -1
- package/dist/tooltip/tooltip-popup.mjs +2 -7
- package/dist/tooltip/tooltip-popup.mjs.map +1 -1
- package/dist/tooltip/use-tooltip-interaction.mjs +5 -17
- package/dist/tooltip/use-tooltip-interaction.mjs.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, use } from "react";
|
|
3
|
+
//#region src/checkbox-group/checkbox-group-context.ts
|
|
4
|
+
/**
|
|
5
|
+
* The values a Parent over `values` acts on and derives from: those not in `disabledItems`
|
|
6
|
+
* (values with no Item included). When that leaves nothing (every value has only disabled
|
|
7
|
+
* Items), all of `values`: a Parent the consumer left enabled over disabled Items still shows and
|
|
8
|
+
* changes their state (disable the Parent to make it inert).
|
|
9
|
+
*/
|
|
10
|
+
function enabledValues(values, disabledItems) {
|
|
11
|
+
if (disabledItems.size === 0) return values;
|
|
12
|
+
const enabled = values.filter((v) => !disabledItems.has(v));
|
|
13
|
+
return enabled.length > 0 ? enabled : values;
|
|
14
|
+
}
|
|
15
|
+
const CheckboxGroupContext = createContext(null);
|
|
16
|
+
function useCheckboxGroupContext(part) {
|
|
17
|
+
const context = use(CheckboxGroupContext);
|
|
18
|
+
if (context === null) throw new Error(`${part} must be rendered inside a CheckboxGroup.Root.`);
|
|
19
|
+
return context;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { CheckboxGroupContext, enabledValues, useCheckboxGroupContext };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=checkbox-group-context.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-group-context.mjs","names":[],"sources":["../../src/checkbox-group/checkbox-group-context.ts"],"sourcesContent":["\"use client\";\nimport { createContext, use } from \"react\";\n\n/** A change to the group's set of checked values (design/components/checkbox-group.md 5.2). */\nexport interface CheckboxGroupPatch {\n readonly added: readonly string[];\n readonly removed: readonly string[];\n}\n\nexport interface CheckboxGroupContextValue {\n /** The `name` shared by every Item of the group (prop or `useId()`). */\n readonly name: string;\n readonly form: string | undefined;\n /**\n * The Root's `required` while no value of an enabled Item is checked (design section 7):\n * rendered as native `required` on every Item. Before the Items have registered (server render,\n * hydration render) it is `required && optimistic.size === 0`, which is what the server can\n * compute.\n */\n readonly required: boolean;\n /** Optimistic checked values: Items and Parents render from it. */\n readonly optimistic: ReadonlySet<string>;\n /** Committed checked values. For per-part pending and the Parent's restore memory only. */\n readonly committed: ReadonlySet<string>;\n readonly pending: boolean;\n /** `Root disabled` (reaches the boxes natively through `<fieldset disabled>`). */\n readonly disabled: boolean;\n /**\n * Uncontrolled mode: the latest `defaultValue` as a set, mirrored by each Item into\n * `el.defaultChecked` (and by each Parent, derived) so that a form reset returns to it.\n * `undefined` in controlled mode, where React's mount-time value stays the reset target\n * (conventions 3.8 rule 6).\n */\n readonly defaultValue: ReadonlySet<string> | undefined;\n /**\n * Item click. No-op when `optimistic.has(value) === checked`. Checks neither `disabled` nor\n * `defaultPrevented` (the Item's `guardCheckableChange` does).\n */\n readonly toggle: (value: string, checked: boolean, event: Event) => void;\n /** Parent click: a whole patch. No-op when it changes nothing against the optimistic set. */\n readonly apply: (patch: CheckboxGroupPatch, event: Event) => void;\n /**\n * Values whose every mounted Item has its own `disabled` prop (`Root disabled` is not counted).\n * A Parent leaves them alone (design 6.2). Empty until the Items registered.\n */\n readonly disabledItems: ReadonlySet<string>;\n /**\n * Stable. Each Item calls it from a layout effect with its value and its own `disabled` prop;\n * returns the unregister function.\n */\n readonly registerItem: (value: string, disabled: boolean) => () => void;\n /** From `useNativeGroupReconciliation`; Items and Parents call it from their mount layout effect. */\n readonly onItemMounted: (element: HTMLInputElement | null) => void;\n /**\n * A Parent mounted with a DOM `checked` that differs from its derivation (a click before\n * hydration). Folded into the Root's next mount read as \"check all\" / \"uncheck all\" of\n * `values` (design 8.1). Call before `onItemMounted`.\n */\n readonly reportParent: (values: readonly string[], checked: boolean) => void;\n /**\n * The optimistic set as the Root state's `value`: an array in the Items' document order as of\n * the Root's last render (see `CheckboxGroupRootState.value`).\n */\n readonly value: readonly string[];\n /**\n * Sorts values by the current document order of the group's Items (a DOM read); values with no\n * Item keep their iteration order, after them. Call from handlers and effects only.\n */\n readonly sortByDocument: (values: Iterable<string>) => string[];\n}\n\n/**\n * The values a Parent over `values` acts on and derives from: those not in `disabledItems`\n * (values with no Item included). When that leaves nothing (every value has only disabled\n * Items), all of `values`: a Parent the consumer left enabled over disabled Items still shows and\n * changes their state (disable the Parent to make it inert).\n */\nexport function enabledValues(\n values: readonly string[],\n disabledItems: ReadonlySet<string>,\n): readonly string[] {\n if (disabledItems.size === 0) return values;\n const enabled = values.filter((v) => !disabledItems.has(v));\n return enabled.length > 0 ? enabled : values;\n}\n\nexport const CheckboxGroupContext = createContext<CheckboxGroupContextValue | null>(null);\n\nexport function useCheckboxGroupContext(part: string): CheckboxGroupContextValue {\n const context = use(CheckboxGroupContext);\n if (context === null) {\n throw new Error(`${part} must be rendered inside a CheckboxGroup.Root.`);\n }\n return context;\n}\n"],"mappings":";;;;;;;;;AA6EA,SAAgB,cACd,QACA,eACmB;CACnB,IAAI,cAAc,SAAS,GAAG,OAAO;CACrC,MAAM,UAAU,OAAO,QAAQ,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC;CAC1D,OAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,MAAa,uBAAuB,cAAgD,IAAI;AAExF,SAAgB,wBAAwB,MAAyC;CAC/E,MAAM,UAAU,IAAI,oBAAoB;CACxC,IAAI,YAAY,MACd,MAAM,IAAI,MAAM,GAAG,KAAK,+CAA+C;CAEzE,OAAO;AACT"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { CSSProperties, ComponentPropsWithRef, ViewTransitionClass } from "react";
|
|
3
|
+
//#region src/checkbox-group/checkbox-group-item.d.ts
|
|
4
|
+
export interface CheckboxGroupItemState {
|
|
5
|
+
readonly value: string;
|
|
6
|
+
/** Optimistic: true as soon as the user checks this box, before the action settles. */
|
|
7
|
+
readonly checked: boolean;
|
|
8
|
+
/** The Root is pending and this box's optimistic state differs from its committed state. */
|
|
9
|
+
readonly pending: boolean;
|
|
10
|
+
/** Disabled by its own prop or by `Root disabled`. */
|
|
11
|
+
readonly disabled: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface CheckboxGroupItemProps extends Omit<ComponentPropsWithRef<"input">, "type" | "name" | "value" | "checked" | "defaultChecked" | "defaultValue" | "form" | "required" | "aria-checked" | "onChange" | "className" | "style" | "children"> {
|
|
14
|
+
/** The value this box contributes when checked. Must be unique within the Root. */
|
|
15
|
+
value: string;
|
|
16
|
+
/**
|
|
17
|
+
* Native `disabled`: unfocusable, never dispatches, barred from constraint validation. A
|
|
18
|
+
* `Parent` leaves a disabled Item's value alone and derives its state without it; a checked
|
|
19
|
+
* disabled Item does not satisfy the group's `required`.
|
|
20
|
+
*/
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Forwarded to the Item's `<ViewTransition default>`. Default: no boundary. Fires only on the
|
|
24
|
+
* commit that settles the action (or rolls it back), never on the optimistic check; animate the
|
|
25
|
+
* check itself with CSS on `:checked`.
|
|
26
|
+
*
|
|
27
|
+
* Static: without `transition` the part renders no `<ViewTransition>`; changing it between
|
|
28
|
+
* `undefined` and a value remounts the element. Any value, `"none"` included, makes a mount or
|
|
29
|
+
* `<Activity>` reveal of this part inside a transition start a document view transition: the
|
|
30
|
+
* page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).
|
|
31
|
+
*/
|
|
32
|
+
transition?: ViewTransitionClass;
|
|
33
|
+
className?: StateValue<string | undefined, CheckboxGroupItemState>;
|
|
34
|
+
style?: StateValue<CSSProperties | undefined, CheckboxGroupItemState>;
|
|
35
|
+
/** Replace the rendered element. Must keep an `<input>`; the library sets `type="checkbox"`. */
|
|
36
|
+
render?: RenderProp<ComponentPropsWithRef<"input">, CheckboxGroupItemState>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* One `<input type="checkbox">` of the group, checked while its `value` is in the group's set.
|
|
40
|
+
* Its DOM `checked` is the optimistic state (`checked={optimistic.has(value)}`): react-dom
|
|
41
|
+
* restores a controlled input to its props after every event, and only the sync-lane optimistic
|
|
42
|
+
* value survives that restore.
|
|
43
|
+
*
|
|
44
|
+
* Owned keys (conventions 1.2; a `render` element's value is overridden): `type`, `name`,
|
|
45
|
+
* `value`, `checked`, `defaultChecked` (never rendered), `disabled`, `form`, `required`
|
|
46
|
+
* (computed by the Root from its `required` prop), `aria-checked` (removed), `data-checked`,
|
|
47
|
+
* `data-pending`, `data-disabled`. `onChange` is merged: a `render` element's own handler runs
|
|
48
|
+
* first, then the library's. `role` passes through.
|
|
49
|
+
*/
|
|
50
|
+
export declare function CheckboxGroupItem({ value, disabled: disabledProp, transition, className, style, render, ...rest }: CheckboxGroupItemProps): import("react").ReactNode;
|
|
51
|
+
export declare namespace CheckboxGroupItem {
|
|
52
|
+
var displayName: string;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//# sourceMappingURL=checkbox-group-item.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-group-item.d.mts","names":[],"sources":["../../src/checkbox-group/checkbox-group-item.tsx"],"mappings":";;;iBAWiB;WACN;;WAEA;;WAEA;;WAEA;;iBAGM,+BAA+B,KAC9C;;EAgBA;;;;;;EAMA;;;;;;;;;;;EAWA,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,SAAS,WAAW,gCAAgC;;;;;;;;;;;;;;wBAetC,oBACd,OACA,UAAU,cACV,YACA,WACA,OACA,WACG,QACF,yCAAsB;yBART"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
|
|
3
|
+
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
5
|
+
import { guardCheckableChange, useNativeChecked } from "../internal/use-native-checked.mjs";
|
|
6
|
+
import { syncPresence } from "../internal/sync-presence.mjs";
|
|
7
|
+
import { useCheckboxGroupContext } from "./checkbox-group-context.mjs";
|
|
8
|
+
import { useLayoutEffect } from "react";
|
|
9
|
+
//#region src/checkbox-group/checkbox-group-item.tsx
|
|
10
|
+
/**
|
|
11
|
+
* One `<input type="checkbox">` of the group, checked while its `value` is in the group's set.
|
|
12
|
+
* Its DOM `checked` is the optimistic state (`checked={optimistic.has(value)}`): react-dom
|
|
13
|
+
* restores a controlled input to its props after every event, and only the sync-lane optimistic
|
|
14
|
+
* value survives that restore.
|
|
15
|
+
*
|
|
16
|
+
* Owned keys (conventions 1.2; a `render` element's value is overridden): `type`, `name`,
|
|
17
|
+
* `value`, `checked`, `defaultChecked` (never rendered), `disabled`, `form`, `required`
|
|
18
|
+
* (computed by the Root from its `required` prop), `aria-checked` (removed), `data-checked`,
|
|
19
|
+
* `data-pending`, `data-disabled`. `onChange` is merged: a `render` element's own handler runs
|
|
20
|
+
* first, then the library's. `role` passes through.
|
|
21
|
+
*/
|
|
22
|
+
function CheckboxGroupItem({ value, disabled: disabledProp = false, transition, className, style, render, ...rest }) {
|
|
23
|
+
const ctx = useCheckboxGroupContext("CheckboxGroup.Item");
|
|
24
|
+
const checked = ctx.optimistic.has(value);
|
|
25
|
+
const pending = ctx.pending && checked !== ctx.committed.has(value);
|
|
26
|
+
const disabled = ctx.disabled || disabledProp;
|
|
27
|
+
const required = ctx.required;
|
|
28
|
+
const { registerItem } = ctx;
|
|
29
|
+
useLayoutEffect(() => registerItem(value, disabledProp), [
|
|
30
|
+
registerItem,
|
|
31
|
+
value,
|
|
32
|
+
disabledProp
|
|
33
|
+
]);
|
|
34
|
+
const inputRef = useNativeChecked({
|
|
35
|
+
type: "checkbox",
|
|
36
|
+
component: "CheckboxGroup.Item",
|
|
37
|
+
checked,
|
|
38
|
+
group: true,
|
|
39
|
+
onItemMounted: (el) => {
|
|
40
|
+
if (el !== null) {
|
|
41
|
+
syncPresence(el, "data-checked", checked);
|
|
42
|
+
syncPresence(el, "data-pending", pending);
|
|
43
|
+
syncPresence(el, "data-disabled", disabled);
|
|
44
|
+
syncPresence(el, "required", required);
|
|
45
|
+
}
|
|
46
|
+
ctx.onItemMounted(el);
|
|
47
|
+
},
|
|
48
|
+
defaultChecked: ctx.defaultValue === void 0 ? void 0 : ctx.defaultValue.has(value)
|
|
49
|
+
});
|
|
50
|
+
const element = useRender({
|
|
51
|
+
defaultElement: "input",
|
|
52
|
+
render,
|
|
53
|
+
state: {
|
|
54
|
+
value,
|
|
55
|
+
checked,
|
|
56
|
+
pending,
|
|
57
|
+
disabled
|
|
58
|
+
},
|
|
59
|
+
className,
|
|
60
|
+
style,
|
|
61
|
+
children: void 0,
|
|
62
|
+
ref: inputRef,
|
|
63
|
+
props: rest,
|
|
64
|
+
libraryProps: {
|
|
65
|
+
type: "checkbox",
|
|
66
|
+
name: ctx.name,
|
|
67
|
+
value,
|
|
68
|
+
checked,
|
|
69
|
+
defaultChecked: void 0,
|
|
70
|
+
"aria-checked": void 0,
|
|
71
|
+
disabled: disabledProp,
|
|
72
|
+
form: ctx.form,
|
|
73
|
+
required,
|
|
74
|
+
"data-checked": dataAttr(checked),
|
|
75
|
+
"data-pending": dataAttr(pending),
|
|
76
|
+
"data-disabled": dataAttr(disabled),
|
|
77
|
+
onChange: (event) => {
|
|
78
|
+
if (disabled) return;
|
|
79
|
+
const nativeEvent = event.nativeEvent;
|
|
80
|
+
guardCheckableChange(nativeEvent, () => ctx.toggle(value, !checked, nativeEvent), "CheckboxGroup.Item");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return useTransitionBoundary("CheckboxGroup.Item", transition, element);
|
|
85
|
+
}
|
|
86
|
+
CheckboxGroupItem.displayName = "CheckboxGroupItem";
|
|
87
|
+
//#endregion
|
|
88
|
+
export { CheckboxGroupItem };
|
|
89
|
+
|
|
90
|
+
//# sourceMappingURL=checkbox-group-item.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-group-item.mjs","names":[],"sources":["../../src/checkbox-group/checkbox-group-item.tsx"],"sourcesContent":["\"use client\";\nimport { useLayoutEffect } from \"react\";\nimport type { ChangeEvent, ComponentPropsWithRef, CSSProperties, ViewTransitionClass } from \"react\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { guardCheckableChange, useNativeChecked } from \"../internal/use-native-checked.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useCheckboxGroupContext } from \"./checkbox-group-context.js\";\nimport { syncPresence } from \"../internal/sync-presence.js\";\n\nexport interface CheckboxGroupItemState {\n readonly value: string;\n /** Optimistic: true as soon as the user checks this box, before the action settles. */\n readonly checked: boolean;\n /** The Root is pending and this box's optimistic state differs from its committed state. */\n readonly pending: boolean;\n /** Disabled by its own prop or by `Root disabled`. */\n readonly disabled: boolean;\n}\n\nexport interface CheckboxGroupItemProps extends Omit<\n ComponentPropsWithRef<\"input\">,\n | \"type\"\n | \"name\"\n | \"value\"\n | \"checked\"\n | \"defaultChecked\"\n | \"defaultValue\"\n | \"form\"\n | \"required\"\n | \"aria-checked\"\n | \"onChange\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** The value this box contributes when checked. Must be unique within the Root. */\n value: string;\n /**\n * Native `disabled`: unfocusable, never dispatches, barred from constraint validation. A\n * `Parent` leaves a disabled Item's value alone and derives its state without it; a checked\n * disabled Item does not satisfy the group's `required`.\n */\n disabled?: boolean;\n /**\n * Forwarded to the Item's `<ViewTransition default>`. Default: no boundary. Fires only on the\n * commit that settles the action (or rolls it back), never on the optimistic check; animate the\n * check itself with CSS on `:checked`.\n *\n * Static: without `transition` the part renders no `<ViewTransition>`; changing it between\n * `undefined` and a value remounts the element. Any value, `\"none\"` included, makes a mount or\n * `<Activity>` reveal of this part inside a transition start a document view transition: the\n * page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, CheckboxGroupItemState>;\n style?: StateValue<CSSProperties | undefined, CheckboxGroupItemState>;\n /** Replace the rendered element. Must keep an `<input>`; the library sets `type=\"checkbox\"`. */\n render?: RenderProp<ComponentPropsWithRef<\"input\">, CheckboxGroupItemState>;\n}\n\n/**\n * One `<input type=\"checkbox\">` of the group, checked while its `value` is in the group's set.\n * Its DOM `checked` is the optimistic state (`checked={optimistic.has(value)}`): react-dom\n * restores a controlled input to its props after every event, and only the sync-lane optimistic\n * value survives that restore.\n *\n * Owned keys (conventions 1.2; a `render` element's value is overridden): `type`, `name`,\n * `value`, `checked`, `defaultChecked` (never rendered), `disabled`, `form`, `required`\n * (computed by the Root from its `required` prop), `aria-checked` (removed), `data-checked`,\n * `data-pending`, `data-disabled`. `onChange` is merged: a `render` element's own handler runs\n * first, then the library's. `role` passes through.\n */\nexport function CheckboxGroupItem({\n value,\n disabled: disabledProp = false,\n transition,\n className,\n style,\n render,\n ...rest\n}: CheckboxGroupItemProps) {\n const ctx = useCheckboxGroupContext(\"CheckboxGroup.Item\");\n const checked = ctx.optimistic.has(value);\n const pending = ctx.pending && checked !== ctx.committed.has(value);\n const disabled = ctx.disabled || disabledProp;\n const required = ctx.required;\n\n // The Root needs every Item's own `disabled` for the Parents and `required` (design 6.2, 7).\n const { registerItem } = ctx;\n useLayoutEffect(() => registerItem(value, disabledProp), [registerItem, value, disabledProp]);\n\n // Group mode: element check and re-apply only; the Root reports the residual paths once.\n const inputRef = useNativeChecked({\n type: \"checkbox\",\n component: \"CheckboxGroup.Item\",\n checked,\n group: true,\n onItemMounted: (el) => {\n // Hydration keeps server attributes that differ from the client render (React only warns).\n // An Item hydrating after its Root can render a different state than the server did (a\n // click on an already hydrated box), and stale attributes would stay until the next change.\n if (el !== null) {\n syncPresence(el, \"data-checked\", checked);\n syncPresence(el, \"data-pending\", pending);\n syncPresence(el, \"data-disabled\", disabled);\n syncPresence(el, \"required\", required);\n }\n ctx.onItemMounted(el);\n },\n defaultChecked: ctx.defaultValue === undefined ? undefined : ctx.defaultValue.has(value),\n });\n\n const state: CheckboxGroupItemState = { value, checked, pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"input\">, CheckboxGroupItemState>({\n defaultElement: \"input\",\n render,\n state,\n className,\n style,\n children: undefined,\n ref: inputRef,\n // Pass-through layer: a `render` element's own props win over these.\n props: rest,\n libraryProps: {\n type: \"checkbox\",\n name: ctx.name,\n value,\n checked,\n defaultChecked: undefined,\n \"aria-checked\": undefined,\n // Owned (Switch precedent) so that native disabledness, `data-disabled` and the click guard\n // agree. Only the Item's own prop: `Root disabled` reaches the box through the fieldset.\n disabled: disabledProp,\n form: ctx.form,\n required,\n \"data-checked\": dataAttr(checked),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n onChange: (event: ChangeEvent<HTMLInputElement>) => {\n // A natively disabled box fires no click; this covers `render` elements that do not\n // honour `disabled`.\n if (disabled) return;\n const nativeEvent = event.nativeEvent;\n guardCheckableChange(\n nativeEvent,\n () => ctx.toggle(value, !checked, nativeEvent),\n \"CheckboxGroup.Item\",\n );\n },\n },\n });\n\n return useTransitionBoundary(\"CheckboxGroup.Item\", transition, element);\n}\n\nCheckboxGroupItem.displayName = \"CheckboxGroupItem\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0EA,SAAgB,kBAAkB,EAChC,OACA,UAAU,eAAe,OACzB,YACA,WACA,OACA,QACA,GAAG,QACsB;CACzB,MAAM,MAAM,wBAAwB,oBAAoB;CACxD,MAAM,UAAU,IAAI,WAAW,IAAI,KAAK;CACxC,MAAM,UAAU,IAAI,WAAW,YAAY,IAAI,UAAU,IAAI,KAAK;CAClE,MAAM,WAAW,IAAI,YAAY;CACjC,MAAM,WAAW,IAAI;CAGrB,MAAM,EAAE,iBAAiB;CACzB,sBAAsB,aAAa,OAAO,YAAY,GAAG;EAAC;EAAc;EAAO;CAAY,CAAC;CAG5F,MAAM,WAAW,iBAAiB;EAChC,MAAM;EACN,WAAW;EACX;EACA,OAAO;EACP,gBAAgB,OAAO;GAIrB,IAAI,OAAO,MAAM;IACf,aAAa,IAAI,gBAAgB,OAAO;IACxC,aAAa,IAAI,gBAAgB,OAAO;IACxC,aAAa,IAAI,iBAAiB,QAAQ;IAC1C,aAAa,IAAI,YAAY,QAAQ;GACvC;GACA,IAAI,cAAc,EAAE;EACtB;EACA,gBAAgB,IAAI,iBAAiB,KAAA,IAAY,KAAA,IAAY,IAAI,aAAa,IAAI,KAAK;CACzF,CAAC;CAID,MAAM,UAAU,UAAkE;EAChF,gBAAgB;EAChB;EACA,OAAA;GALsC;GAAO;GAAS;GAAS;EAK3D;EACJ;EACA;EACA,UAAU,KAAA;EACV,KAAK;EAEL,OAAO;EACP,cAAc;GACZ,MAAM;GACN,MAAM,IAAI;GACV;GACA;GACA,gBAAgB,KAAA;GAChB,gBAAgB,KAAA;GAGhB,UAAU;GACV,MAAM,IAAI;GACV;GACA,gBAAgB,SAAS,OAAO;GAChC,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,WAAW,UAAyC;IAGlD,IAAI,UAAU;IACd,MAAM,cAAc,MAAM;IAC1B,qBACE,mBACM,IAAI,OAAO,OAAO,CAAC,SAAS,WAAW,GAC7C,oBACF;GACF;EACF;CACF,CAAC;CAED,OAAO,sBAAsB,sBAAsB,YAAY,OAAO;AACxE;AAEA,kBAAkB,cAAc"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { CheckboxGroupRootState } from "./checkbox-group-root.mjs";
|
|
3
|
+
import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
|
|
4
|
+
//#region src/checkbox-group/checkbox-group-label.d.ts
|
|
5
|
+
export interface CheckboxGroupLabelProps extends Omit<ComponentPropsWithRef<"legend">, "className" | "style" | "children"> {
|
|
6
|
+
className?: StateValue<string | undefined, CheckboxGroupRootState>;
|
|
7
|
+
style?: StateValue<CSSProperties | undefined, CheckboxGroupRootState>;
|
|
8
|
+
/** Receives the Root's state: a group-level pending indicator goes here. */
|
|
9
|
+
children?: StateValue<ReactNode, CheckboxGroupRootState>;
|
|
10
|
+
render?: RenderProp<ComponentPropsWithRef<"legend">, CheckboxGroupRootState>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The group's `<legend>`, which names the fieldset natively. Optional; must be the **first child**
|
|
14
|
+
* of `CheckboxGroup.Root` (HTML content model). Its state is the Root's state. Owns no keys.
|
|
15
|
+
*/
|
|
16
|
+
export declare function CheckboxGroupLabel({ className, style, children, render, ...rest }: CheckboxGroupLabelProps): ReactNode;
|
|
17
|
+
export declare namespace CheckboxGroupLabel {
|
|
18
|
+
var displayName: string;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//# sourceMappingURL=checkbox-group-label.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-group-label.d.mts","names":[],"sources":["../../src/checkbox-group/checkbox-group-label.tsx"],"mappings":";;;;iBAOiB,gCAAgC,KAC/C;EAGA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,iCAAiC;;;;;;wBAOvC,qBACd,WACA,OACA,UACA,WACG,QACF,0BAAuB;yBANV"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
3
|
+
import { useCheckboxGroupContext } from "./checkbox-group-context.mjs";
|
|
4
|
+
//#region src/checkbox-group/checkbox-group-label.tsx
|
|
5
|
+
/**
|
|
6
|
+
* The group's `<legend>`, which names the fieldset natively. Optional; must be the **first child**
|
|
7
|
+
* of `CheckboxGroup.Root` (HTML content model). Its state is the Root's state. Owns no keys.
|
|
8
|
+
*/
|
|
9
|
+
function CheckboxGroupLabel({ className, style, children, render, ...rest }) {
|
|
10
|
+
const ctx = useCheckboxGroupContext("CheckboxGroup.Label");
|
|
11
|
+
const state = {
|
|
12
|
+
value: ctx.value,
|
|
13
|
+
pending: ctx.pending,
|
|
14
|
+
disabled: ctx.disabled
|
|
15
|
+
};
|
|
16
|
+
return useRender({
|
|
17
|
+
defaultElement: "legend",
|
|
18
|
+
render,
|
|
19
|
+
state,
|
|
20
|
+
className,
|
|
21
|
+
style,
|
|
22
|
+
children,
|
|
23
|
+
props: rest
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
CheckboxGroupLabel.displayName = "CheckboxGroupLabel";
|
|
27
|
+
//#endregion
|
|
28
|
+
export { CheckboxGroupLabel };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=checkbox-group-label.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-group-label.mjs","names":[],"sources":["../../src/checkbox-group/checkbox-group-label.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useCheckboxGroupContext } from \"./checkbox-group-context.js\";\nimport type { CheckboxGroupRootState } from \"./checkbox-group-root.js\";\n\nexport interface CheckboxGroupLabelProps extends Omit<\n ComponentPropsWithRef<\"legend\">,\n \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, CheckboxGroupRootState>;\n style?: StateValue<CSSProperties | undefined, CheckboxGroupRootState>;\n /** Receives the Root's state: a group-level pending indicator goes here. */\n children?: StateValue<ReactNode, CheckboxGroupRootState>;\n render?: RenderProp<ComponentPropsWithRef<\"legend\">, CheckboxGroupRootState>;\n}\n\n/**\n * The group's `<legend>`, which names the fieldset natively. Optional; must be the **first child**\n * of `CheckboxGroup.Root` (HTML content model). Its state is the Root's state. Owns no keys.\n */\nexport function CheckboxGroupLabel({\n className,\n style,\n children,\n render,\n ...rest\n}: CheckboxGroupLabelProps) {\n const ctx = useCheckboxGroupContext(\"CheckboxGroup.Label\");\n const state: CheckboxGroupRootState = {\n value: ctx.value,\n pending: ctx.pending,\n disabled: ctx.disabled,\n };\n return useRender<ComponentPropsWithRef<\"legend\">, CheckboxGroupRootState>({\n defaultElement: \"legend\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n });\n}\n\nCheckboxGroupLabel.displayName = \"CheckboxGroupLabel\";\n"],"mappings":";;;;;;;;AAsBA,SAAgB,mBAAmB,EACjC,WACA,OACA,UACA,QACA,GAAG,QACuB;CAC1B,MAAM,MAAM,wBAAwB,qBAAqB;CACzD,MAAM,QAAgC;EACpC,OAAO,IAAI;EACX,SAAS,IAAI;EACb,UAAU,IAAI;CAChB;CACA,OAAO,UAAmE;EACxE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;CACT,CAAC;AACH;AAEA,mBAAmB,cAAc"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { CSSProperties, ComponentPropsWithRef, ViewTransitionClass } from "react";
|
|
3
|
+
//#region src/checkbox-group/checkbox-group-parent.d.ts
|
|
4
|
+
export interface CheckboxGroupParentState {
|
|
5
|
+
readonly values: readonly string[];
|
|
6
|
+
/** Every value in `values` is optimistically checked (`false` when `values` is empty). */
|
|
7
|
+
readonly checked: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Some but not all of `values` are optimistically checked. Never true together with
|
|
10
|
+
* `checked`. Not suspended while pending (it is derived from optimistic state).
|
|
11
|
+
*/
|
|
12
|
+
readonly indeterminate: boolean;
|
|
13
|
+
/** The Root is pending and at least one of `values` differs between optimistic and committed. */
|
|
14
|
+
readonly pending: boolean;
|
|
15
|
+
/** Disabled by its own prop or by `Root disabled`. */
|
|
16
|
+
readonly disabled: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface CheckboxGroupParentProps extends Omit<ComponentPropsWithRef<"input">, "type" | "name" | "value" | "checked" | "defaultChecked" | "defaultValue" | "form" | "required" | "autoComplete" | "aria-checked" | "onChange" | "className" | "style" | "children"> {
|
|
19
|
+
/**
|
|
20
|
+
* The Item values this Parent controls (usually every Item of the group). Its checked and
|
|
21
|
+
* mixed states are derived from them; its click checks or unchecks all of them. Values with
|
|
22
|
+
* no Item are still added to / removed from the group's value.
|
|
23
|
+
*
|
|
24
|
+
* Values whose Items are disabled (their own `disabled` prop) are left alone: the click does
|
|
25
|
+
* not change them and the derivation ignores them, so the Parent shows checked when every
|
|
26
|
+
* enabled Item is. When every value has only disabled Items, the Parent acts on all of them
|
|
27
|
+
* (disable the Parent to make it inert). Before hydration the server-rendered state counts
|
|
28
|
+
* disabled Items too; it settles when the Items hydrate.
|
|
29
|
+
*/
|
|
30
|
+
values: string[];
|
|
31
|
+
/** Native `disabled`: unfocusable, never dispatches. */
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Forwarded to the Parent's `<ViewTransition default>`. Default: no boundary. Fires only on the
|
|
35
|
+
* commit that settles the action (or rolls it back), never on the optimistic flip; animate the
|
|
36
|
+
* flip itself with CSS on `:checked` / `:indeterminate`.
|
|
37
|
+
*
|
|
38
|
+
* Static: without `transition` the part renders no `<ViewTransition>`; changing it between
|
|
39
|
+
* `undefined` and a value remounts the element. Any value, `"none"` included, makes a mount or
|
|
40
|
+
* `<Activity>` reveal of this part inside a transition start a document view transition: the
|
|
41
|
+
* page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).
|
|
42
|
+
*/
|
|
43
|
+
transition?: ViewTransitionClass;
|
|
44
|
+
className?: StateValue<string | undefined, CheckboxGroupParentState>;
|
|
45
|
+
style?: StateValue<CSSProperties | undefined, CheckboxGroupParentState>;
|
|
46
|
+
/** Replace the rendered element. Must keep an `<input>`; the library sets `type="checkbox"`. */
|
|
47
|
+
render?: RenderProp<ComponentPropsWithRef<"input">, CheckboxGroupParentState>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The mixed-state "select all" checkbox of a group (WAI-ARIA APG "Checkbox (Mixed-State)"):
|
|
51
|
+
* `<input type="checkbox">` checked when every value in `values` is in the group's optimistic
|
|
52
|
+
* set, mixed (`el.indeterminate`, `data-indeterminate`) when some are. A click checks every value
|
|
53
|
+
* when mixed, unchecks every value when checked, and from unchecked restores the last partial
|
|
54
|
+
* combination of its values the group committed (seeded at mount), else checks every value. Each
|
|
55
|
+
* click is one dispatch through the Root's `valueChangeAction`. Never submitted (no `name`).
|
|
56
|
+
* "Its values" are those whose Items are enabled: disabled Items are left alone (see `values`).
|
|
57
|
+
*
|
|
58
|
+
* Owned keys (conventions 1.2): `type`, `name` (removed), `value` (removed), `checked`,
|
|
59
|
+
* `defaultChecked`, `indeterminate` (stripped; the property is set), `required` (removed), `form`
|
|
60
|
+
* (removed), `autoComplete` (`"off"`), `disabled`, `aria-checked` (removed), `data-checked`, `data-indeterminate`,
|
|
61
|
+
* `data-pending`, `data-disabled`. `onChange` is merged.
|
|
62
|
+
*/
|
|
63
|
+
export declare function CheckboxGroupParent({ values, disabled: disabledProp, transition, className, style, render, ...rest }: CheckboxGroupParentProps): import("react").ReactNode;
|
|
64
|
+
export declare namespace CheckboxGroupParent {
|
|
65
|
+
var displayName: string;
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
//# sourceMappingURL=checkbox-group-parent.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-group-parent.d.mts","names":[],"sources":["../../src/checkbox-group/checkbox-group-parent.tsx"],"mappings":";;;iBAaiB;WACN;;WAEA;;;;;WAKA;;WAEA;;WAEA;;iBAGM,iCAAiC,KAChD;;;;;;;;;;;;EA2BA;;EAEA;;;;;;;;;;;EAWA,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,SAAS,WAAW,gCAAgC;;;;;;;;;;;;;;;;wBA2BtC,sBACd,QACA,UAAU,cACV,YACA,WACA,OACA,WACG,QACF,2CAAwB;yBARX"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
|
|
3
|
+
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
5
|
+
import { useFormReset } from "../internal/use-form-reset.mjs";
|
|
6
|
+
import { guardCheckableChange, useNativeChecked } from "../internal/use-native-checked.mjs";
|
|
7
|
+
import { syncPresence } from "../internal/sync-presence.mjs";
|
|
8
|
+
import { enabledValues, useCheckboxGroupContext } from "./checkbox-group-context.mjs";
|
|
9
|
+
import { useCallback, useLayoutEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
|
10
|
+
//#region src/checkbox-group/checkbox-group-parent.tsx
|
|
11
|
+
const subscribeNothing = () => () => {};
|
|
12
|
+
/** `checked` / `indeterminate` of a Parent over `values` against `set` (design 6.1). */
|
|
13
|
+
function derive(values, set) {
|
|
14
|
+
let inSet = 0;
|
|
15
|
+
for (const v of values) if (set.has(v)) inSet += 1;
|
|
16
|
+
const checked = values.length > 0 && inSet === values.length;
|
|
17
|
+
return {
|
|
18
|
+
checked,
|
|
19
|
+
indeterminate: inSet > 0 && !checked
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The mixed-state "select all" checkbox of a group (WAI-ARIA APG "Checkbox (Mixed-State)"):
|
|
24
|
+
* `<input type="checkbox">` checked when every value in `values` is in the group's optimistic
|
|
25
|
+
* set, mixed (`el.indeterminate`, `data-indeterminate`) when some are. A click checks every value
|
|
26
|
+
* when mixed, unchecks every value when checked, and from unchecked restores the last partial
|
|
27
|
+
* combination of its values the group committed (seeded at mount), else checks every value. Each
|
|
28
|
+
* click is one dispatch through the Root's `valueChangeAction`. Never submitted (no `name`).
|
|
29
|
+
* "Its values" are those whose Items are enabled: disabled Items are left alone (see `values`).
|
|
30
|
+
*
|
|
31
|
+
* Owned keys (conventions 1.2): `type`, `name` (removed), `value` (removed), `checked`,
|
|
32
|
+
* `defaultChecked`, `indeterminate` (stripped; the property is set), `required` (removed), `form`
|
|
33
|
+
* (removed), `autoComplete` (`"off"`), `disabled`, `aria-checked` (removed), `data-checked`, `data-indeterminate`,
|
|
34
|
+
* `data-pending`, `data-disabled`. `onChange` is merged.
|
|
35
|
+
*/
|
|
36
|
+
function CheckboxGroupParent({ values, disabled: disabledProp = false, transition, className, style, render, ...rest }) {
|
|
37
|
+
const ctx = useCheckboxGroupContext("CheckboxGroup.Parent");
|
|
38
|
+
const hydrating = useSyncExternalStore(subscribeNothing, () => false, () => true);
|
|
39
|
+
const { disabledItems } = ctx;
|
|
40
|
+
const effective = useMemo(() => hydrating ? values : enabledValues(values, disabledItems), [
|
|
41
|
+
hydrating,
|
|
42
|
+
values,
|
|
43
|
+
disabledItems
|
|
44
|
+
]);
|
|
45
|
+
const { checked, indeterminate } = derive(effective, ctx.optimistic);
|
|
46
|
+
const pending = ctx.pending && values.some((v) => ctx.optimistic.has(v) !== ctx.committed.has(v));
|
|
47
|
+
const disabled = ctx.disabled || disabledProp;
|
|
48
|
+
const memory = useRef(null);
|
|
49
|
+
const { committed } = ctx;
|
|
50
|
+
useLayoutEffect(() => {
|
|
51
|
+
const inCommitted = effective.filter((v) => committed.has(v));
|
|
52
|
+
if (inCommitted.length > 0 && inCommitted.length < effective.length) memory.current = inCommitted;
|
|
53
|
+
}, [committed, effective]);
|
|
54
|
+
const inputRef = useNativeChecked({
|
|
55
|
+
type: "checkbox",
|
|
56
|
+
component: "CheckboxGroup.Parent",
|
|
57
|
+
checked,
|
|
58
|
+
indeterminate,
|
|
59
|
+
group: true,
|
|
60
|
+
onItemMounted: (el) => {
|
|
61
|
+
if (el !== null) {
|
|
62
|
+
if (el.checked !== checked) ctx.reportParent(values, el.checked);
|
|
63
|
+
syncPresence(el, "data-checked", checked);
|
|
64
|
+
syncPresence(el, "data-indeterminate", indeterminate);
|
|
65
|
+
syncPresence(el, "data-pending", pending);
|
|
66
|
+
syncPresence(el, "data-disabled", disabled);
|
|
67
|
+
}
|
|
68
|
+
ctx.onItemMounted(el);
|
|
69
|
+
},
|
|
70
|
+
defaultChecked: ctx.defaultValue === void 0 ? void 0 : derive(effective, ctx.defaultValue).checked
|
|
71
|
+
});
|
|
72
|
+
const node = useRef(null);
|
|
73
|
+
const ref = useCallback((el) => {
|
|
74
|
+
node.current = el;
|
|
75
|
+
const cleanup = inputRef(el);
|
|
76
|
+
return () => {
|
|
77
|
+
node.current = null;
|
|
78
|
+
if (typeof cleanup === "function") cleanup();
|
|
79
|
+
};
|
|
80
|
+
}, [inputRef]);
|
|
81
|
+
useFormReset(node, () => {
|
|
82
|
+
const el = node.current;
|
|
83
|
+
if (el !== null && el.checked !== checked) el.checked = checked;
|
|
84
|
+
});
|
|
85
|
+
/** The click cycle of design 6.2. */
|
|
86
|
+
const cyclePatch = () => {
|
|
87
|
+
if (checked) return {
|
|
88
|
+
added: [],
|
|
89
|
+
removed: [...effective]
|
|
90
|
+
};
|
|
91
|
+
if (indeterminate) return {
|
|
92
|
+
added: effective.filter((v) => !ctx.optimistic.has(v)),
|
|
93
|
+
removed: []
|
|
94
|
+
};
|
|
95
|
+
const restore = memory.current?.filter((v) => effective.includes(v)) ?? [];
|
|
96
|
+
return {
|
|
97
|
+
added: restore.length > 0 ? restore : [...effective],
|
|
98
|
+
removed: []
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
const element = useRender({
|
|
102
|
+
defaultElement: "input",
|
|
103
|
+
render,
|
|
104
|
+
state: {
|
|
105
|
+
values,
|
|
106
|
+
checked,
|
|
107
|
+
indeterminate,
|
|
108
|
+
pending,
|
|
109
|
+
disabled
|
|
110
|
+
},
|
|
111
|
+
className,
|
|
112
|
+
style,
|
|
113
|
+
children: void 0,
|
|
114
|
+
ref,
|
|
115
|
+
props: rest,
|
|
116
|
+
libraryProps: {
|
|
117
|
+
type: "checkbox",
|
|
118
|
+
name: void 0,
|
|
119
|
+
value: void 0,
|
|
120
|
+
required: void 0,
|
|
121
|
+
form: void 0,
|
|
122
|
+
autoComplete: "off",
|
|
123
|
+
checked,
|
|
124
|
+
defaultChecked: void 0,
|
|
125
|
+
indeterminate: void 0,
|
|
126
|
+
"aria-checked": void 0,
|
|
127
|
+
disabled: disabledProp,
|
|
128
|
+
"data-checked": dataAttr(checked),
|
|
129
|
+
"data-indeterminate": dataAttr(indeterminate),
|
|
130
|
+
"data-pending": dataAttr(pending),
|
|
131
|
+
"data-disabled": dataAttr(disabled),
|
|
132
|
+
onChange: (event) => {
|
|
133
|
+
if (disabled) return;
|
|
134
|
+
const nativeEvent = event.nativeEvent;
|
|
135
|
+
guardCheckableChange(nativeEvent, () => ctx.apply(cyclePatch(), nativeEvent), "CheckboxGroup.Parent");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
return useTransitionBoundary("CheckboxGroup.Parent", transition, element);
|
|
140
|
+
}
|
|
141
|
+
CheckboxGroupParent.displayName = "CheckboxGroupParent";
|
|
142
|
+
//#endregion
|
|
143
|
+
export { CheckboxGroupParent };
|
|
144
|
+
|
|
145
|
+
//# sourceMappingURL=checkbox-group-parent.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-group-parent.mjs","names":[],"sources":["../../src/checkbox-group/checkbox-group-parent.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback, useLayoutEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport type { ChangeEvent, ComponentPropsWithRef, CSSProperties, ViewTransitionClass } from \"react\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { guardCheckableChange, useNativeChecked } from \"../internal/use-native-checked.js\";\nimport { useFormReset } from \"../internal/use-form-reset.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { enabledValues, useCheckboxGroupContext } from \"./checkbox-group-context.js\";\nimport type { CheckboxGroupPatch } from \"./checkbox-group-context.js\";\nimport { syncPresence } from \"../internal/sync-presence.js\";\n\nexport interface CheckboxGroupParentState {\n readonly values: readonly string[];\n /** Every value in `values` is optimistically checked (`false` when `values` is empty). */\n readonly checked: boolean;\n /**\n * Some but not all of `values` are optimistically checked. Never true together with\n * `checked`. Not suspended while pending (it is derived from optimistic state).\n */\n readonly indeterminate: boolean;\n /** The Root is pending and at least one of `values` differs between optimistic and committed. */\n readonly pending: boolean;\n /** Disabled by its own prop or by `Root disabled`. */\n readonly disabled: boolean;\n}\n\nexport interface CheckboxGroupParentProps extends Omit<\n ComponentPropsWithRef<\"input\">,\n | \"type\"\n | \"name\"\n | \"value\"\n | \"checked\"\n | \"defaultChecked\"\n | \"defaultValue\"\n | \"form\"\n | \"required\"\n | \"autoComplete\"\n | \"aria-checked\"\n | \"onChange\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /**\n * The Item values this Parent controls (usually every Item of the group). Its checked and\n * mixed states are derived from them; its click checks or unchecks all of them. Values with\n * no Item are still added to / removed from the group's value.\n *\n * Values whose Items are disabled (their own `disabled` prop) are left alone: the click does\n * not change them and the derivation ignores them, so the Parent shows checked when every\n * enabled Item is. When every value has only disabled Items, the Parent acts on all of them\n * (disable the Parent to make it inert). Before hydration the server-rendered state counts\n * disabled Items too; it settles when the Items hydrate.\n */\n values: string[];\n /** Native `disabled`: unfocusable, never dispatches. */\n disabled?: boolean;\n /**\n * Forwarded to the Parent's `<ViewTransition default>`. Default: no boundary. Fires only on the\n * commit that settles the action (or rolls it back), never on the optimistic flip; animate the\n * flip itself with CSS on `:checked` / `:indeterminate`.\n *\n * Static: without `transition` the part renders no `<ViewTransition>`; changing it between\n * `undefined` and a value remounts the element. Any value, `\"none\"` included, makes a mount or\n * `<Activity>` reveal of this part inside a transition start a document view transition: the\n * page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, CheckboxGroupParentState>;\n style?: StateValue<CSSProperties | undefined, CheckboxGroupParentState>;\n /** Replace the rendered element. Must keep an `<input>`; the library sets `type=\"checkbox\"`. */\n render?: RenderProp<ComponentPropsWithRef<\"input\">, CheckboxGroupParentState>;\n}\n\nconst subscribeNothing = () => () => {};\n\n/** `checked` / `indeterminate` of a Parent over `values` against `set` (design 6.1). */\nfunction derive(values: readonly string[], set: ReadonlySet<string>) {\n let inSet = 0;\n for (const v of values) if (set.has(v)) inSet += 1;\n const checked = values.length > 0 && inSet === values.length;\n return { checked, indeterminate: inSet > 0 && !checked };\n}\n\n/**\n * The mixed-state \"select all\" checkbox of a group (WAI-ARIA APG \"Checkbox (Mixed-State)\"):\n * `<input type=\"checkbox\">` checked when every value in `values` is in the group's optimistic\n * set, mixed (`el.indeterminate`, `data-indeterminate`) when some are. A click checks every value\n * when mixed, unchecks every value when checked, and from unchecked restores the last partial\n * combination of its values the group committed (seeded at mount), else checks every value. Each\n * click is one dispatch through the Root's `valueChangeAction`. Never submitted (no `name`).\n * \"Its values\" are those whose Items are enabled: disabled Items are left alone (see `values`).\n *\n * Owned keys (conventions 1.2): `type`, `name` (removed), `value` (removed), `checked`,\n * `defaultChecked`, `indeterminate` (stripped; the property is set), `required` (removed), `form`\n * (removed), `autoComplete` (`\"off\"`), `disabled`, `aria-checked` (removed), `data-checked`, `data-indeterminate`,\n * `data-pending`, `data-disabled`. `onChange` is merged.\n */\nexport function CheckboxGroupParent({\n values,\n disabled: disabledProp = false,\n transition,\n className,\n style,\n render,\n ...rest\n}: CheckboxGroupParentProps) {\n const ctx = useCheckboxGroupContext(\"CheckboxGroup.Parent\");\n // The values the Parent acts on: `values` minus disabled Items (design 6.2). A hydration\n // render uses every value, as the server did (it cannot know which Items are disabled), so\n // that the DOM `checked` it hydrates can be compared with the derivation for the\n // pre-hydration report below, also when this Parent hydrates after the Items registered.\n const hydrating = useSyncExternalStore(\n subscribeNothing,\n () => false,\n () => true,\n );\n const { disabledItems } = ctx;\n const effective = useMemo(\n () => (hydrating ? values : enabledValues(values, disabledItems)),\n [hydrating, values, disabledItems],\n );\n const { checked, indeterminate } = derive(effective, ctx.optimistic);\n const pending = ctx.pending && values.some((v) => ctx.optimistic.has(v) !== ctx.committed.has(v));\n const disabled = ctx.disabled || disabledProp;\n\n // The APG restore memory: the last partial combination of `values` the group committed\n // (design 6.2). Committed, not optimistic, so a partial state that only ever rolled back is\n // never restored. The first run seeds it from the mount-time value.\n const memory = useRef<readonly string[] | null>(null);\n const { committed } = ctx;\n useLayoutEffect(() => {\n const inCommitted = effective.filter((v) => committed.has(v));\n if (inCommitted.length > 0 && inCommitted.length < effective.length) {\n memory.current = inCommitted;\n }\n }, [committed, effective]);\n\n const inputRef = useNativeChecked({\n type: \"checkbox\",\n component: \"CheckboxGroup.Parent\",\n checked,\n indeterminate,\n group: true,\n onItemMounted: (el) => {\n if (el !== null) {\n // A click before hydration flipped the box (design 8.1): report it as the Parent's\n // semantic before the Root reads the group (which leaves disabled Items alone). Firefox's\n // form-state restoration cannot cause this: the Parent renders `autocomplete=\"off\"`.\n if (el.checked !== checked) ctx.reportParent(values, el.checked);\n syncPresence(el, \"data-checked\", checked);\n syncPresence(el, \"data-indeterminate\", indeterminate);\n syncPresence(el, \"data-pending\", pending);\n syncPresence(el, \"data-disabled\", disabled);\n }\n ctx.onItemMounted(el);\n },\n defaultChecked:\n ctx.defaultValue === undefined ? undefined : derive(effective, ctx.defaultValue).checked,\n });\n\n // A form reset sets the Parent's DOM `checked` to its `defaultChecked`, which in controlled\n // mode is React's mount-time value and can be stale (its `values` changed, it mounted after the\n // Items with another value). The Parent re-renders only if the Root dispatches; otherwise put\n // the derivation back (the Root's own microtask, queued after this one, may still dispatch,\n // and the re-render re-applies `checked`).\n const node = useRef<HTMLInputElement | null>(null);\n const ref = useCallback(\n (el: HTMLInputElement) => {\n node.current = el;\n const cleanup = inputRef(el);\n return () => {\n node.current = null;\n if (typeof cleanup === \"function\") cleanup();\n };\n },\n [inputRef],\n );\n useFormReset(node, () => {\n const el = node.current;\n if (el !== null && el.checked !== checked) el.checked = checked;\n });\n\n /** The click cycle of design 6.2. */\n const cyclePatch = (): CheckboxGroupPatch => {\n if (checked) return { added: [], removed: [...effective] };\n if (indeterminate) {\n return { added: effective.filter((v) => !ctx.optimistic.has(v)), removed: [] };\n }\n const restore = memory.current?.filter((v) => effective.includes(v)) ?? [];\n return { added: restore.length > 0 ? restore : [...effective], removed: [] };\n };\n\n const state: CheckboxGroupParentState = { values, checked, indeterminate, pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"input\">, CheckboxGroupParentState>({\n defaultElement: \"input\",\n render,\n state,\n className,\n style,\n children: undefined,\n ref,\n props: rest,\n libraryProps: {\n type: \"checkbox\",\n // A Parent is not a value: it never posts and is never required.\n name: undefined,\n value: undefined,\n required: undefined,\n form: undefined,\n // Nothing to restore (it is not a value): without this, Firefox restores its `checked` on\n // reload and the mount read would take it for a click before hydration (design 8.1).\n autoComplete: \"off\",\n checked,\n defaultChecked: undefined,\n // Not a DOM attribute; the hook sets the property. Owned so that a `render` element's own\n // `indeterminate` prop (which react-dom would warn about) is stripped.\n ...({ indeterminate: undefined } as object),\n \"aria-checked\": undefined,\n disabled: disabledProp,\n \"data-checked\": dataAttr(checked),\n \"data-indeterminate\": dataAttr(indeterminate),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n onChange: (event: ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n const nativeEvent = event.nativeEvent;\n guardCheckableChange(\n nativeEvent,\n () => ctx.apply(cyclePatch(), nativeEvent),\n \"CheckboxGroup.Parent\",\n );\n },\n },\n });\n\n return useTransitionBoundary(\"CheckboxGroup.Parent\", transition, element);\n}\n\nCheckboxGroupParent.displayName = \"CheckboxGroupParent\";\n"],"mappings":";;;;;;;;;;AA4EA,MAAM,+BAA+B,CAAC;;AAGtC,SAAS,OAAO,QAA2B,KAA0B;CACnE,IAAI,QAAQ;CACZ,KAAK,MAAM,KAAK,QAAQ,IAAI,IAAI,IAAI,CAAC,GAAG,SAAS;CACjD,MAAM,UAAU,OAAO,SAAS,KAAK,UAAU,OAAO;CACtD,OAAO;EAAE;EAAS,eAAe,QAAQ,KAAK,CAAC;CAAQ;AACzD;;;;;;;;;;;;;;;AAgBA,SAAgB,oBAAoB,EAClC,QACA,UAAU,eAAe,OACzB,YACA,WACA,OACA,QACA,GAAG,QACwB;CAC3B,MAAM,MAAM,wBAAwB,sBAAsB;CAK1D,MAAM,YAAY,qBAChB,wBACM,aACA,IACR;CACA,MAAM,EAAE,kBAAkB;CAC1B,MAAM,YAAY,cACT,YAAY,SAAS,cAAc,QAAQ,aAAa,GAC/D;EAAC;EAAW;EAAQ;CAAa,CACnC;CACA,MAAM,EAAE,SAAS,kBAAkB,OAAO,WAAW,IAAI,UAAU;CACnE,MAAM,UAAU,IAAI,WAAW,OAAO,MAAM,MAAM,IAAI,WAAW,IAAI,CAAC,MAAM,IAAI,UAAU,IAAI,CAAC,CAAC;CAChG,MAAM,WAAW,IAAI,YAAY;CAKjC,MAAM,SAAS,OAAiC,IAAI;CACpD,MAAM,EAAE,cAAc;CACtB,sBAAsB;EACpB,MAAM,cAAc,UAAU,QAAQ,MAAM,UAAU,IAAI,CAAC,CAAC;EAC5D,IAAI,YAAY,SAAS,KAAK,YAAY,SAAS,UAAU,QAC3D,OAAO,UAAU;CAErB,GAAG,CAAC,WAAW,SAAS,CAAC;CAEzB,MAAM,WAAW,iBAAiB;EAChC,MAAM;EACN,WAAW;EACX;EACA;EACA,OAAO;EACP,gBAAgB,OAAO;GACrB,IAAI,OAAO,MAAM;IAIf,IAAI,GAAG,YAAY,SAAS,IAAI,aAAa,QAAQ,GAAG,OAAO;IAC/D,aAAa,IAAI,gBAAgB,OAAO;IACxC,aAAa,IAAI,sBAAsB,aAAa;IACpD,aAAa,IAAI,gBAAgB,OAAO;IACxC,aAAa,IAAI,iBAAiB,QAAQ;GAC5C;GACA,IAAI,cAAc,EAAE;EACtB;EACA,gBACE,IAAI,iBAAiB,KAAA,IAAY,KAAA,IAAY,OAAO,WAAW,IAAI,YAAY,CAAC,CAAC;CACrF,CAAC;CAOD,MAAM,OAAO,OAAgC,IAAI;CACjD,MAAM,MAAM,aACT,OAAyB;EACxB,KAAK,UAAU;EACf,MAAM,UAAU,SAAS,EAAE;EAC3B,aAAa;GACX,KAAK,UAAU;GACf,IAAI,OAAO,YAAY,YAAY,QAAQ;EAC7C;CACF,GACA,CAAC,QAAQ,CACX;CACA,aAAa,YAAY;EACvB,MAAM,KAAK,KAAK;EAChB,IAAI,OAAO,QAAQ,GAAG,YAAY,SAAS,GAAG,UAAU;CAC1D,CAAC;;CAGD,MAAM,mBAAuC;EAC3C,IAAI,SAAS,OAAO;GAAE,OAAO,CAAC;GAAG,SAAS,CAAC,GAAG,SAAS;EAAE;EACzD,IAAI,eACF,OAAO;GAAE,OAAO,UAAU,QAAQ,MAAM,CAAC,IAAI,WAAW,IAAI,CAAC,CAAC;GAAG,SAAS,CAAC;EAAE;EAE/E,MAAM,UAAU,OAAO,SAAS,QAAQ,MAAM,UAAU,SAAS,CAAC,CAAC,KAAK,CAAC;EACzE,OAAO;GAAE,OAAO,QAAQ,SAAS,IAAI,UAAU,CAAC,GAAG,SAAS;GAAG,SAAS,CAAC;EAAE;CAC7E;CAIA,MAAM,UAAU,UAAoE;EAClF,gBAAgB;EAChB;EACA,OAAA;GALwC;GAAQ;GAAS;GAAe;GAAS;EAK7E;EACJ;EACA;EACA,UAAU,KAAA;EACV;EACA,OAAO;EACP,cAAc;GACZ,MAAM;GAEN,MAAM,KAAA;GACN,OAAO,KAAA;GACP,UAAU,KAAA;GACV,MAAM,KAAA;GAGN,cAAc;GACd;GACA,gBAAgB,KAAA;GAGV,eAAe,KAAA;GACrB,gBAAgB,KAAA;GAChB,UAAU;GACV,gBAAgB,SAAS,OAAO;GAChC,sBAAsB,SAAS,aAAa;GAC5C,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,WAAW,UAAyC;IAClD,IAAI,UAAU;IACd,MAAM,cAAc,MAAM;IAC1B,qBACE,mBACM,IAAI,MAAM,WAAW,GAAG,WAAW,GACzC,sBACF;GACF;EACF;CACF,CAAC;CAED,OAAO,sBAAsB,wBAAwB,YAAY,OAAO;AAC1E;AAEA,oBAAoB,cAAc"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ActionDetails, ChangeAction, ChangeReason, RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
|
|
3
|
+
//#region src/checkbox-group/checkbox-group-root.d.ts
|
|
4
|
+
/** Details passed as the second argument of `valueChangeAction`. */
|
|
5
|
+
export interface CheckboxGroupValueChangeDetails extends ActionDetails {
|
|
6
|
+
/**
|
|
7
|
+
* `"activate"`: the user toggled an Item or a Parent (click, Space, label click; `event` is the
|
|
8
|
+
* native `click`). `"platform"`: the browser changed the checked boxes itself: a form reset
|
|
9
|
+
* (`event` is the `reset` event), or clicks before hydration / Firefox form-state restoration
|
|
10
|
+
* found at mount (`event` is `undefined`).
|
|
11
|
+
*/
|
|
12
|
+
readonly reason: ChangeReason;
|
|
13
|
+
/** Values this dispatch checked, in document order of their Items (values with no Item last). */
|
|
14
|
+
readonly added: readonly string[];
|
|
15
|
+
/** Values this dispatch unchecked, same order. */
|
|
16
|
+
readonly removed: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
export interface CheckboxGroupRootState {
|
|
19
|
+
/**
|
|
20
|
+
* Optimistic checked values, in document order of the Items as of the Root's last render
|
|
21
|
+
* (values with no Item last). Items reordered by a component that re-renders without the Root
|
|
22
|
+
* keep the previous order here until the Root renders again; `next` and `details` of
|
|
23
|
+
* `valueChangeAction` always read the current DOM order. The server render and the first client
|
|
24
|
+
* render use the value's own order. Content rendered from it must not suspend.
|
|
25
|
+
*/
|
|
26
|
+
readonly value: readonly string[];
|
|
27
|
+
/** An action dispatched through this group is in flight. */
|
|
28
|
+
readonly pending: boolean;
|
|
29
|
+
/** The `disabled` prop. */
|
|
30
|
+
readonly disabled: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface CheckboxGroupRootProps extends Omit<ComponentPropsWithRef<"fieldset">, "className" | "style" | "children" | "defaultValue" | "defaultChecked" | "name" | "disabled" | "form"> {
|
|
33
|
+
/**
|
|
34
|
+
* Controlled checked values. `[]` checks nothing; `undefined` means uncontrolled. Order is not
|
|
35
|
+
* significant and duplicates are ignored: the value is a set.
|
|
36
|
+
*
|
|
37
|
+
* A form reset returns each box to the `checked` it had when *that box* mounted (React sets
|
|
38
|
+
* `defaultChecked` once, from the initial `checked`). The reset is offered to
|
|
39
|
+
* `valueChangeAction` as a `"platform"` change; for a stable target use `defaultValue`.
|
|
40
|
+
*/
|
|
41
|
+
value?: string[];
|
|
42
|
+
/**
|
|
43
|
+
* Initial values in uncontrolled mode. Defaults to `[]`. Also the values a form reset returns
|
|
44
|
+
* to: the latest prop value is mirrored into the boxes' `defaultChecked`.
|
|
45
|
+
*/
|
|
46
|
+
defaultValue?: string[];
|
|
47
|
+
/**
|
|
48
|
+
* Runs inside the Root's transition whenever the set of checked values changes. May be sync
|
|
49
|
+
* or async (also a Server Function); rejections reach the nearest Error Boundary and roll the
|
|
50
|
+
* change back.
|
|
51
|
+
*
|
|
52
|
+
* `next` is the whole set as a fresh array in document order of the Items; treat it as a set.
|
|
53
|
+
* `details.added` / `details.removed` say what changed. When controlled and updating after
|
|
54
|
+
* your own `await`, prefer a functional update keyed by `added` / `removed` over
|
|
55
|
+
* `setValue(next)`: two overlapping actions completing out of order would otherwise land the
|
|
56
|
+
* older whole set last. A `setState` placed after your own `await` is not a Transition update;
|
|
57
|
+
* wrap it in `startTransition` (React limitation). `details.event.preventDefault()` is not a
|
|
58
|
+
* veto; use controlled mode to veto a change.
|
|
59
|
+
*/
|
|
60
|
+
valueChangeAction?: ChangeAction<string[], CheckboxGroupValueChangeDetails>;
|
|
61
|
+
/**
|
|
62
|
+
* The `name` shared by every Item (form data key: `formData.getAll(name)`). Defaults to a
|
|
63
|
+
* `useId()` value; pass a real name when the group is inside a `<form>` you submit.
|
|
64
|
+
*/
|
|
65
|
+
name?: string;
|
|
66
|
+
/** The `form` attribute, applied to the fieldset and to every Item. */
|
|
67
|
+
form?: string;
|
|
68
|
+
/**
|
|
69
|
+
* "At least one Item must be checked." Rendered as native `required` on every Item while no
|
|
70
|
+
* enabled Item is checked, and on none once one is: values with no Item and checked disabled
|
|
71
|
+
* Items (neither is submitted) do not satisfy it. Until the Items have mounted (server HTML,
|
|
72
|
+
* before hydration) any checked value satisfies it. Not exposed on the fieldset (ARIA does not
|
|
73
|
+
* allow `aria-required` on role `group`): say it in the `Label` or through `aria-describedby`.
|
|
74
|
+
*/
|
|
75
|
+
required?: boolean;
|
|
76
|
+
/** Renders `<fieldset disabled>`: every Item and Parent is disabled and unfocusable. */
|
|
77
|
+
disabled?: boolean;
|
|
78
|
+
className?: StateValue<string | undefined, CheckboxGroupRootState>;
|
|
79
|
+
style?: StateValue<CSSProperties | undefined, CheckboxGroupRootState>;
|
|
80
|
+
children?: StateValue<ReactNode, CheckboxGroupRootState>;
|
|
81
|
+
/** Replace the rendered element. Must keep a `<fieldset>`. */
|
|
82
|
+
render?: RenderProp<ComponentPropsWithRef<"fieldset">, CheckboxGroupRootState>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* `<fieldset>` that owns the group's state (a set of values), the transition, the shared `name`,
|
|
86
|
+
* the form-reset listener, the mount reconciliation and the group-level `required`
|
|
87
|
+
* (design/components/checkbox-group.md 14.3). Carries `data-pending` while `valueChangeAction`
|
|
88
|
+
* is in flight. Its implicit role is `group`; no `role` is written.
|
|
89
|
+
*
|
|
90
|
+
* Owned keys (conventions 1.2): `disabled`, `form`, `data-pending`, `data-disabled`.
|
|
91
|
+
*
|
|
92
|
+
* Unlike RadioGroup, Items may hydrate after their Root (a Suspense boundary between them): a
|
|
93
|
+
* click before an Item hydrated is reconciled when it does.
|
|
94
|
+
*/
|
|
95
|
+
export declare function CheckboxGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp, form, required, disabled, className, style, children, render, ...rest }: CheckboxGroupRootProps): import("react").JSX.Element;
|
|
96
|
+
export declare namespace CheckboxGroupRoot {
|
|
97
|
+
var displayName: string;
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
//# sourceMappingURL=checkbox-group-root.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-group-root.d.mts","names":[],"sources":["../../src/checkbox-group/checkbox-group-root.tsx"],"mappings":";;;;iBA8BiB,wCAAwC;;;;;;;WAO9C,QAAQ;;WAER;;WAEA;;iBAGM;;;;;;;;WAQN;;WAEA;;WAEA;;iBAGM,+BAA+B,KAC9C;;;;;;;;;EAkBA;;;;;EAKA;;;;;;;;;;;;;;EAcA,oBAAoB,uBAAuB;;;;;EAK3C;;EAEA;;;;;;;;EAQA;;EAEA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,mCAAmC;;;;;;;;;;;;;wBAoFzC,oBACd,OACA,cACA,mBACA,MAAM,UACN,MACA,UACA,UACA,WACA,OACA,UACA,WACG,QACF,yCAAsB,IAAA;yBAbT"}
|