@primitiv-ui/react 0.1.0 → 0.1.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.
- package/LICENSE +21 -0
- package/package.json +2 -1
- package/src/AccessibleIcon/AccessibleIcon.tsx +6 -2
- package/src/AccessibleIcon/__tests__/AccessibleIcon.test.tsx +1 -1
- package/src/AccessibleIcon/types.ts +4 -0
- package/src/Accordion/Accordion.tsx +34 -12
- package/src/Accordion/AccordionContext.ts +1 -1
- package/src/Accordion/__tests__/Accordion.reading-direction.test.tsx +1 -1
- package/src/Accordion/hooks/useAccordionItem.ts +1 -1
- package/src/Accordion/hooks/useAccordionRoot.ts +1 -1
- package/src/Accordion/hooks/useAccordionTrigger.ts +2 -2
- package/src/Accordion/index.ts +2 -1
- package/src/Accordion/types.ts +55 -13
- package/src/Alert/Alert.tsx +9 -2
- package/src/Alert/__tests__/Alert.test.tsx +1 -1
- package/src/Alert/types.ts +1 -0
- package/src/Avatar/Avatar.tsx +20 -7
- package/src/Avatar/AvatarContext.ts +12 -6
- package/src/Breadcrumb/Breadcrumb.tsx +32 -10
- package/src/Button/Button.tsx +5 -2
- package/src/Button/types.ts +4 -0
- package/src/Carousel/Carousel.tsx +30 -14
- package/src/Carousel/CarouselContext.ts +7 -3
- package/src/Carousel/__tests__/Carousel.asChild.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.auto-play.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.basic-rendering.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.controlled-state.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.error-handling.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.ids.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.imperative-api.test.tsx +2 -2
- package/src/Carousel/__tests__/Carousel.indicators.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.intersection-observer.test.tsx +2 -2
- package/src/Carousel/__tests__/Carousel.keyboard-navigation.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.play-pause.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.prev-next.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.reduced-motion.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.refresh-progress.test.tsx +2 -2
- package/src/Carousel/__tests__/Carousel.scroll-snap-change.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.scroll-sync.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.slides-per-move.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.slides-per-page.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.touch-interaction.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.transition-modes.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.translations.test.tsx +1 -1
- package/src/Carousel/__tests__/Carousel.uncontrolled-state.test.tsx +1 -1
- package/src/Carousel/types.ts +8 -0
- package/src/Checkbox/Checkbox.tsx +11 -6
- package/src/Checkbox/CheckboxContext.ts +1 -1
- package/src/Checkbox/hooks/useCheckboxRoot.ts +1 -1
- package/src/Checkbox/index.ts +1 -0
- package/src/Checkbox/types.ts +30 -3
- package/src/CheckboxCard/CheckboxCard.tsx +13 -11
- package/src/CheckboxCard/CheckboxCardContext.ts +19 -6
- package/src/CheckboxCard/hooks/useCheckboxCardRoot.ts +2 -2
- package/src/CheckboxCard/types.ts +21 -5
- package/src/Collapsible/Collapsible.tsx +37 -21
- package/src/Collapsible/CollapsibleContext.ts +1 -1
- package/src/Collapsible/hooks/useCollapsibleRoot.ts +1 -1
- package/src/Collapsible/hooks/useCollapsibleTrigger.ts +1 -1
- package/src/Collapsible/index.ts +1 -0
- package/src/Collapsible/types.ts +45 -12
- package/src/ContextMenu/ContextMenu.tsx +60 -34
- package/src/ContextMenu/ContextMenuContext.ts +2 -2
- package/src/ContextMenu/ContextMenuSubContext.ts +1 -1
- package/src/ContextMenu/__tests__/ContextMenu.reading-direction.test.tsx +1 -1
- package/src/ContextMenu/index.ts +2 -1
- package/src/ContextMenu/types.ts +160 -17
- package/src/DirectionProvider/DirectionProvider.tsx +7 -1
- package/src/DirectionProvider/__tests__/DirectionProvider.test.tsx +1 -1
- package/src/DirectionProvider/types.ts +1 -0
- package/src/Divider/Divider.tsx +4 -1
- package/src/Divider/__tests__/Divider.test.tsx +1 -1
- package/src/Divider/index.ts +2 -1
- package/src/Divider/types.ts +5 -0
- package/src/Dropdown/Dropdown.tsx +60 -34
- package/src/Dropdown/DropdownContext.ts +2 -2
- package/src/Dropdown/DropdownSubContext.ts +1 -1
- package/src/Dropdown/__tests__/Dropdown.reading-direction.test.tsx +1 -1
- package/src/Dropdown/hooks/useDropdownContent.ts +1 -1
- package/src/Dropdown/hooks/useDropdownItem.ts +1 -1
- package/src/Dropdown/hooks/useDropdownRoot.ts +2 -2
- package/src/Dropdown/hooks/useDropdownTrigger.ts +1 -1
- package/src/Dropdown/index.ts +2 -1
- package/src/Dropdown/types.ts +153 -25
- package/src/EmptyState/EmptyState.tsx +34 -20
- package/src/EmptyState/__tests__/EmptyState.Actions.test.tsx +1 -1
- package/src/EmptyState/__tests__/EmptyState.Description.test.tsx +1 -1
- package/src/EmptyState/__tests__/EmptyState.Media.test.tsx +1 -1
- package/src/EmptyState/__tests__/EmptyState.Root.test.tsx +1 -1
- package/src/EmptyState/__tests__/EmptyState.Title.test.tsx +1 -1
- package/src/EmptyState/types.ts +2 -1
- package/src/Field/Field.tsx +24 -10
- package/src/Field/FieldContext.ts +1 -1
- package/src/Field/types.ts +4 -0
- package/src/Fieldset/Fieldset.tsx +26 -10
- package/src/Fieldset/types.ts +2 -0
- package/src/Input/Input.tsx +6 -3
- package/src/Input/__tests__/Input.field-integration.test.tsx +1 -1
- package/src/Input/types.ts +4 -0
- package/src/InputGroup/InputGroup.tsx +15 -8
- package/src/InputGroup/types.ts +9 -0
- package/src/MillerColumns/MillerColumns.tsx +28 -8
- package/src/MillerColumns/MillerColumnsContext.ts +1 -1
- package/src/MillerColumns/hooks/useMillerColumnsItem.ts +2 -2
- package/src/MillerColumns/hooks/useMillerColumnsRoot.ts +0 -0
- package/src/MillerColumns/index.ts +1 -1
- package/src/MillerColumns/types.ts +67 -14
- package/src/MillerColumns/useMillerColumnsSelection.ts +1 -1
- package/src/Modal/Modal.tsx +25 -11
- package/src/Modal/ModalContext.ts +14 -7
- package/src/Modal/hooks/useModalRoot.ts +1 -1
- package/src/Modal/hooks/useModalTrigger.ts +2 -2
- package/src/Modal/types.ts +51 -2
- package/src/Portal/Portal.tsx +3 -1
- package/src/Portal/types.ts +4 -0
- package/src/Progress/Progress.tsx +12 -7
- package/src/Progress/ProgressContext.ts +18 -6
- package/src/RadioCard/RadioCard.tsx +17 -11
- package/src/RadioCard/RadioCardContext.ts +17 -5
- package/src/RadioCard/RadioCardItemContext.ts +18 -5
- package/src/RadioCard/__tests__/RadioCard.reading-direction.test.tsx +1 -1
- package/src/RadioCard/hooks/useRadioCardRoot.ts +1 -1
- package/src/RadioCard/types.ts +24 -3
- package/src/RadioGroup/RadioGroup.tsx +17 -11
- package/src/RadioGroup/RadioGroupContext.ts +1 -1
- package/src/RadioGroup/RadioGroupItemContext.ts +1 -1
- package/src/RadioGroup/__tests__/RadioGroup.reading-direction.test.tsx +1 -1
- package/src/RadioGroup/hooks/useRadioGroupRoot.ts +1 -1
- package/src/RadioGroup/index.ts +1 -0
- package/src/RadioGroup/types.ts +34 -3
- package/src/Select/Select.tsx +23 -8
- package/src/Select/__tests__/Select.field-integration.test.tsx +1 -1
- package/src/Select/index.ts +1 -1
- package/src/Select/types.ts +18 -3
- package/src/SkipNav/SkipNav.tsx +7 -2
- package/src/SkipNav/__tests__/SkipNav.ids.test.tsx +1 -1
- package/src/Slider/Slider.tsx +26 -11
- package/src/Slider/SliderContext.ts +13 -6
- package/src/Slider/__tests__/Slider.reading-direction.test.tsx +1 -1
- package/src/Slider/hooks/useSliderRoot.ts +1 -1
- package/src/Slider/types.ts +12 -3
- package/src/Status/Status.tsx +9 -2
- package/src/Status/__tests__/Status.test.tsx +1 -1
- package/src/Status/types.ts +4 -0
- package/src/Switch/Switch.tsx +16 -6
- package/src/Switch/SwitchContext.ts +13 -5
- package/src/Switch/hooks/useSwitchRoot.ts +1 -1
- package/src/Switch/types.ts +24 -3
- package/src/Table/Table.tsx +51 -25
- package/src/Table/__tests__/Table.Body.test.tsx +1 -1
- package/src/Table/__tests__/Table.Caption.test.tsx +1 -1
- package/src/Table/__tests__/Table.Cell.test.tsx +1 -1
- package/src/Table/__tests__/Table.Footer.test.tsx +1 -1
- package/src/Table/__tests__/Table.Head.test.tsx +1 -1
- package/src/Table/__tests__/Table.Header.test.tsx +1 -1
- package/src/Table/__tests__/Table.Root.test.tsx +1 -1
- package/src/Table/__tests__/Table.Row.test.tsx +1 -1
- package/src/Table/__tests__/Table.ScrollArea.test.tsx +1 -1
- package/src/Table/index.ts +2 -1
- package/src/Tabs/Tabs.tsx +30 -10
- package/src/Tabs/TabsContext.ts +15 -7
- package/src/Tabs/__tests__/Tabs.asChild.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.basic-rendering.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.change-event-callbacks.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.controlled-state.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.error-handling.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.imperative-api.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.keyboard-interaction.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.lazy-mount.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.mouse-interaction.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.reading-direction.test.tsx +1 -1
- package/src/Tabs/__tests__/Tabs.uncontrolled-state.test.tsx +1 -1
- package/src/Tabs/hooks/useTabsContent.ts +1 -1
- package/src/Tabs/hooks/useTabsRoot.ts +1 -1
- package/src/Tabs/hooks/useTabsTrigger.ts +1 -1
- package/src/Tabs/types.ts +35 -1
- package/src/Tabs/utils.ts +1 -1
- package/src/Textarea/Textarea.tsx +6 -3
- package/src/Textarea/__tests__/Textarea.field-integration.test.tsx +1 -1
- package/src/Textarea/types.ts +4 -0
- package/src/Toggle/Toggle.tsx +11 -4
- package/src/Toggle/types.ts +7 -3
- package/src/ToggleGroup/ToggleGroup.tsx +23 -13
- package/src/ToggleGroup/ToggleGroupContext.ts +1 -1
- package/src/ToggleGroup/__tests__/ToggleGroup.reading-direction.test.tsx +1 -1
- package/src/ToggleGroup/hooks/useToggleGroupRoot.ts +1 -1
- package/src/ToggleGroup/types.ts +45 -5
- package/src/Tooltip/Tooltip.tsx +46 -15
- package/src/Tooltip/TooltipContext.ts +1 -1
- package/src/Tooltip/hooks/useTooltipContent.ts +1 -1
- package/src/Tooltip/hooks/useTooltipRoot.ts +1 -1
- package/src/Tooltip/hooks/useTooltipTrigger.ts +1 -1
- package/src/Tooltip/index.ts +1 -0
- package/src/Tooltip/types.ts +50 -2
- package/src/Tree/Tree.tsx +58 -12
- package/src/Tree/TreeContext.ts +1 -1
- package/src/Tree/__tests__/Tree.selection-path.test.tsx +2 -2
- package/src/Tree/hooks/useTreeItemKeyboard.ts +1 -1
- package/src/Tree/hooks/useTreeRoot.ts +1 -1
- package/src/Tree/index.ts +1 -1
- package/src/Tree/types.ts +39 -7
- package/src/VisuallyHidden/VisuallyHidden.tsx +4 -2
- package/src/VisuallyHidden/__tests__/VisuallyHidden.test.tsx +1 -1
- package/src/VisuallyHidden/types.ts +4 -0
- package/src/index.ts +39 -38
- package/src/types.ts +1 -0
- package/src/utils/createStrictContext.ts +9 -5
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
|
+
import type { ReactElement } from "react";
|
|
2
3
|
|
|
3
|
-
import { Slot, composeEventHandlers } from "../Slot";
|
|
4
|
+
import { Slot, composeEventHandlers } from "../Slot/index.ts";
|
|
4
5
|
|
|
5
6
|
import { CheckboxContext } from "./CheckboxContext";
|
|
6
|
-
import { useCheckboxContext, useCheckboxRoot } from "./hooks";
|
|
7
|
+
import { useCheckboxContext, useCheckboxRoot } from "./hooks/index.ts";
|
|
7
8
|
import {
|
|
8
9
|
CheckboxIndicatorProps,
|
|
9
10
|
CheckboxRootProps,
|
|
@@ -76,7 +77,7 @@ function dataStateOf(checked: CheckedState) {
|
|
|
76
77
|
* </Checkbox.Root>
|
|
77
78
|
* ```
|
|
78
79
|
*/
|
|
79
|
-
function CheckboxRoot(props: CheckboxRootProps) {
|
|
80
|
+
export function CheckboxRoot(props: CheckboxRootProps): ReactElement {
|
|
80
81
|
const {
|
|
81
82
|
defaultChecked,
|
|
82
83
|
checked,
|
|
@@ -118,6 +119,7 @@ function CheckboxRoot(props: CheckboxRootProps) {
|
|
|
118
119
|
);
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
/** @internal */
|
|
121
123
|
CheckboxRoot.displayName = "CheckboxRoot";
|
|
122
124
|
|
|
123
125
|
/**
|
|
@@ -164,12 +166,12 @@ CheckboxRoot.displayName = "CheckboxRoot";
|
|
|
164
166
|
*
|
|
165
167
|
* @throws if rendered outside a `Checkbox.Root`.
|
|
166
168
|
*/
|
|
167
|
-
function CheckboxIndicator({
|
|
169
|
+
export function CheckboxIndicator({
|
|
168
170
|
children,
|
|
169
171
|
forceMount,
|
|
170
172
|
asChild = false,
|
|
171
173
|
...rest
|
|
172
|
-
}: CheckboxIndicatorProps) {
|
|
174
|
+
}: CheckboxIndicatorProps): ReactElement | null {
|
|
173
175
|
const { checked } = useCheckboxContext();
|
|
174
176
|
const isVisible = checked !== false;
|
|
175
177
|
if (!isVisible && !forceMount) return null;
|
|
@@ -184,9 +186,11 @@ function CheckboxIndicator({
|
|
|
184
186
|
return <span {...indicatorProps}>{children}</span>;
|
|
185
187
|
}
|
|
186
188
|
|
|
189
|
+
/** @internal */
|
|
187
190
|
CheckboxIndicator.displayName = "CheckboxIndicator";
|
|
188
191
|
|
|
189
|
-
|
|
192
|
+
/** Type of the {@link Checkbox} compound: the root callable plus its attached sub-components. */
|
|
193
|
+
export type TCheckboxCompound = typeof CheckboxRoot & {
|
|
190
194
|
Root: typeof CheckboxRoot;
|
|
191
195
|
Indicator: typeof CheckboxIndicator;
|
|
192
196
|
};
|
|
@@ -223,6 +227,7 @@ const CheckboxCompound: TCheckboxCompound = Object.assign(CheckboxRoot, {
|
|
|
223
227
|
Indicator: CheckboxIndicator,
|
|
224
228
|
});
|
|
225
229
|
|
|
230
|
+
/** @internal */
|
|
226
231
|
CheckboxCompound.displayName = "Checkbox";
|
|
227
232
|
|
|
228
233
|
export { CheckboxCompound as Checkbox };
|
package/src/Checkbox/index.ts
CHANGED
package/src/Checkbox/types.ts
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import { ComponentProps, ReactNode, Ref } from "react";
|
|
2
2
|
|
|
3
|
+
/** The checked value of a checkbox — `true`, `false`, or `"indeterminate"` (the tri-state). */
|
|
3
4
|
export type CheckedState = boolean | "indeterminate";
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Props for {@link Checkbox.Indicator} — all `<span>` attributes plus
|
|
8
|
+
* `forceMount` (keep mounted while unchecked for exit animations) and the
|
|
9
|
+
* `asChild` escape hatch.
|
|
10
|
+
*/
|
|
5
11
|
export type CheckboxIndicatorProps = ComponentProps<"span"> & {
|
|
6
12
|
children?: ReactNode;
|
|
7
13
|
forceMount?: boolean;
|
|
8
14
|
asChild?: boolean;
|
|
9
15
|
};
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Shared base for both {@link CheckboxRootProps} variants — the native
|
|
19
|
+
* `<button>` attributes (minus the ones the component owns) plus the
|
|
20
|
+
* `asChild` escape hatch and a typed `ref`.
|
|
21
|
+
*/
|
|
22
|
+
export type CheckboxRootBaseProps = Omit<
|
|
12
23
|
ComponentProps<"button">,
|
|
13
24
|
"type" | "role" | "aria-checked" | "defaultChecked"
|
|
14
25
|
> & {
|
|
@@ -16,18 +27,34 @@ type CheckboxRootBaseProps = Omit<
|
|
|
16
27
|
ref?: Ref<HTMLButtonElement>;
|
|
17
28
|
};
|
|
18
29
|
|
|
19
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Uncontrolled variant of {@link CheckboxRootProps}: the component owns the
|
|
32
|
+
* checked value. Pass `defaultChecked` (or omit it); `onCheckedChange` is
|
|
33
|
+
* optional and `checked` is forbidden.
|
|
34
|
+
*/
|
|
35
|
+
export type CheckboxRootUncontrolledProps = CheckboxRootBaseProps & {
|
|
20
36
|
defaultChecked?: CheckedState;
|
|
21
37
|
checked?: never;
|
|
22
38
|
onCheckedChange?: (checked: boolean) => void;
|
|
23
39
|
};
|
|
24
40
|
|
|
25
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Controlled variant of {@link CheckboxRootProps}: the parent owns the
|
|
43
|
+
* checked value. Pass `checked` and `onCheckedChange` together;
|
|
44
|
+
* `defaultChecked` is forbidden.
|
|
45
|
+
*/
|
|
46
|
+
export type CheckboxRootControlledProps = CheckboxRootBaseProps & {
|
|
26
47
|
defaultChecked?: never;
|
|
27
48
|
checked: CheckedState;
|
|
28
49
|
onCheckedChange: (checked: boolean) => void;
|
|
29
50
|
};
|
|
30
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Props for {@link Checkbox.Root}. A discriminated union of
|
|
54
|
+
* {@link CheckboxRootUncontrolledProps} and
|
|
55
|
+
* {@link CheckboxRootControlledProps}, so TypeScript accepts exactly one
|
|
56
|
+
* state mode.
|
|
57
|
+
*/
|
|
31
58
|
export type CheckboxRootProps =
|
|
32
59
|
| CheckboxRootUncontrolledProps
|
|
33
60
|
| CheckboxRootControlledProps;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
|
+
import type { ReactElement } from "react";
|
|
2
3
|
|
|
3
|
-
import { Slot, composeEventHandlers } from "../Slot";
|
|
4
|
+
import { Slot, composeEventHandlers } from "../Slot/index.ts";
|
|
4
5
|
|
|
5
6
|
import { CheckboxCardContext } from "./CheckboxCardContext";
|
|
6
|
-
import { useCheckboxCardContext, useCheckboxCardRoot } from "./hooks";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
CheckboxCardRootProps,
|
|
10
|
-
CheckedState,
|
|
11
|
-
} from "./types";
|
|
7
|
+
import { useCheckboxCardContext, useCheckboxCardRoot } from "./hooks/index.ts";
|
|
8
|
+
import { CheckboxCardIndicatorProps, CheckboxCardRootProps } from "./types";
|
|
9
|
+
import type { CheckedState } from "../Checkbox/types";
|
|
12
10
|
|
|
13
11
|
function dataStateOf(checked: CheckedState) {
|
|
14
12
|
if (checked === "indeterminate") return "indeterminate" as const;
|
|
@@ -66,7 +64,7 @@ function dataStateOf(checked: CheckedState) {
|
|
|
66
64
|
* </CheckboxCard.Root>
|
|
67
65
|
* ```
|
|
68
66
|
*/
|
|
69
|
-
function CheckboxCardRoot(props: CheckboxCardRootProps) {
|
|
67
|
+
export function CheckboxCardRoot(props: CheckboxCardRootProps): ReactElement {
|
|
70
68
|
const {
|
|
71
69
|
defaultChecked,
|
|
72
70
|
checked,
|
|
@@ -108,6 +106,7 @@ function CheckboxCardRoot(props: CheckboxCardRootProps) {
|
|
|
108
106
|
);
|
|
109
107
|
}
|
|
110
108
|
|
|
109
|
+
/** @internal */
|
|
111
110
|
CheckboxCardRoot.displayName = "CheckboxCardRoot";
|
|
112
111
|
|
|
113
112
|
/**
|
|
@@ -136,12 +135,12 @@ CheckboxCardRoot.displayName = "CheckboxCardRoot";
|
|
|
136
135
|
*
|
|
137
136
|
* @throws if rendered outside a `CheckboxCard.Root`.
|
|
138
137
|
*/
|
|
139
|
-
function CheckboxCardIndicator({
|
|
138
|
+
export function CheckboxCardIndicator({
|
|
140
139
|
children,
|
|
141
140
|
forceMount,
|
|
142
141
|
asChild = false,
|
|
143
142
|
...rest
|
|
144
|
-
}: CheckboxCardIndicatorProps) {
|
|
143
|
+
}: CheckboxCardIndicatorProps): ReactElement | null {
|
|
145
144
|
const { checked } = useCheckboxCardContext();
|
|
146
145
|
const isVisible = checked !== false;
|
|
147
146
|
if (!isVisible && !forceMount) return null;
|
|
@@ -156,9 +155,12 @@ function CheckboxCardIndicator({
|
|
|
156
155
|
return <span {...indicatorProps}>{children}</span>;
|
|
157
156
|
}
|
|
158
157
|
|
|
158
|
+
/** @internal */
|
|
159
159
|
CheckboxCardIndicator.displayName = "CheckboxCardIndicator";
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
/** Type of the {@link CheckboxCard} compound: the callable `CheckboxCard.Root`
|
|
162
|
+
* component augmented with its sub-components as static properties. */
|
|
163
|
+
export type TCheckboxCardCompound = typeof CheckboxCardRoot & {
|
|
162
164
|
Root: typeof CheckboxCardRoot;
|
|
163
165
|
Indicator: typeof CheckboxCardIndicator;
|
|
164
166
|
};
|
|
@@ -1,12 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Context } from "react";
|
|
2
|
+
import { createStrictContext } from "../utils/index.ts";
|
|
2
3
|
|
|
3
|
-
import { CheckedState } from "
|
|
4
|
+
import type { CheckedState } from "../Checkbox/types";
|
|
4
5
|
|
|
6
|
+
/** The value shared by `CheckboxCard.Root` with its `CheckboxCard.Indicator`,
|
|
7
|
+
* exposing the current checked state. */
|
|
5
8
|
export type CheckboxCardContextValue = {
|
|
9
|
+
/** Current checked state of the card. */
|
|
6
10
|
checked: CheckedState;
|
|
7
11
|
};
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const checkboxCardContextPair = createStrictContext<CheckboxCardContextValue>(
|
|
14
|
+
"CheckboxCard sub-components must be rendered inside a <CheckboxCard.Root>.",
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
/** Strict React context carrying the {@link CheckboxCardContextValue} from
|
|
18
|
+
* `CheckboxCard.Root` to its indicator. `null` when read outside a
|
|
19
|
+
* `CheckboxCard.Root`. */
|
|
20
|
+
export const CheckboxCardContext: Context<CheckboxCardContextValue | null> =
|
|
21
|
+
checkboxCardContextPair[0];
|
|
22
|
+
/** Reads the {@link CheckboxCardContextValue}; throws when used outside a
|
|
23
|
+
* `CheckboxCard.Root`. */
|
|
24
|
+
export const useCheckboxCardContext: () => CheckboxCardContextValue =
|
|
25
|
+
checkboxCardContextPair[1];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useCallback } from "react";
|
|
2
2
|
|
|
3
|
-
import { useControllableState } from "../../hooks";
|
|
3
|
+
import { useControllableState } from "../../hooks/index.ts";
|
|
4
4
|
|
|
5
|
-
import { CheckedState } from "
|
|
5
|
+
import type { CheckedState } from "../../Checkbox/types";
|
|
6
6
|
|
|
7
7
|
type UseCheckboxCardRootArgs = {
|
|
8
8
|
defaultChecked?: CheckedState;
|
|
@@ -1,33 +1,49 @@
|
|
|
1
1
|
import { ComponentProps, ReactNode, Ref } from "react";
|
|
2
|
+
import type { CheckedState } from "../Checkbox/types";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
/** Props for `CheckboxCard.Indicator` — the visual marker shown when the card
|
|
5
|
+
* is checked. By default it renders only while checked; set `forceMount` to
|
|
6
|
+
* keep it mounted for exit transitions. */
|
|
5
7
|
export type CheckboxCardIndicatorProps = ComponentProps<"span"> & {
|
|
6
8
|
children?: ReactNode;
|
|
7
9
|
forceMount?: boolean;
|
|
8
10
|
asChild?: boolean;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
/** Props shared by both controlled and uncontrolled `CheckboxCard.Root` usage.
|
|
14
|
+
* Extends the native `<button>` props (minus the checkbox-managed ones). */
|
|
15
|
+
export type CheckboxCardRootBaseProps = Omit<
|
|
12
16
|
ComponentProps<"button">,
|
|
13
17
|
"type" | "role" | "aria-checked" | "defaultChecked"
|
|
14
18
|
> & {
|
|
19
|
+
/** Render the child element instead of the default `<button>`. */
|
|
15
20
|
asChild?: boolean;
|
|
21
|
+
/** Ref to the rendered element. */
|
|
16
22
|
ref?: Ref<HTMLButtonElement>;
|
|
17
23
|
};
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
/** Uncontrolled `CheckboxCard.Root` props: the component owns the checked
|
|
26
|
+
* state, seeded by an optional `defaultChecked`. */
|
|
27
|
+
export type CheckboxCardRootUncontrolledProps = CheckboxCardRootBaseProps & {
|
|
28
|
+
/** Checked state on first render. */
|
|
20
29
|
defaultChecked?: CheckedState;
|
|
21
30
|
checked?: never;
|
|
31
|
+
/** Called with the new boolean checked state when it changes. */
|
|
22
32
|
onCheckedChange?: (checked: boolean) => void;
|
|
23
33
|
};
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
/** Controlled `CheckboxCard.Root` props: the caller owns the checked state via
|
|
36
|
+
* `checked` and is notified through the required `onCheckedChange`. */
|
|
37
|
+
export type CheckboxCardRootControlledProps = CheckboxCardRootBaseProps & {
|
|
26
38
|
defaultChecked?: never;
|
|
39
|
+
/** Current checked state. */
|
|
27
40
|
checked: CheckedState;
|
|
41
|
+
/** Called with the new boolean checked state when the user toggles. */
|
|
28
42
|
onCheckedChange: (checked: boolean) => void;
|
|
29
43
|
};
|
|
30
44
|
|
|
45
|
+
/** Props for `CheckboxCard.Root` — resolves to either the controlled or
|
|
46
|
+
* uncontrolled prop shape. */
|
|
31
47
|
export type CheckboxCardRootProps =
|
|
32
48
|
| CheckboxCardRootUncontrolledProps
|
|
33
49
|
| CheckboxCardRootControlledProps;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { Ref } from "react";
|
|
2
|
+
import type { ReactElement } from "react";
|
|
2
3
|
|
|
3
|
-
import { Slot } from "../Slot";
|
|
4
|
+
import { Slot } from "../Slot/index.ts";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
6
|
+
import {
|
|
7
|
+
CollapsibleContext,
|
|
8
|
+
useCollapsibleContext,
|
|
9
|
+
} from "./CollapsibleContext";
|
|
10
|
+
import { useCollapsibleRoot, useCollapsibleTrigger } from "./hooks/index.ts";
|
|
7
11
|
|
|
8
12
|
import type {
|
|
9
13
|
CollapsibleRootProps,
|
|
@@ -63,7 +67,7 @@ export function CollapsibleRoot({
|
|
|
63
67
|
onOpenChange,
|
|
64
68
|
disabled = false,
|
|
65
69
|
...rest
|
|
66
|
-
}: CollapsibleRootProps) {
|
|
70
|
+
}: CollapsibleRootProps): ReactElement {
|
|
67
71
|
const { contextValue } = useCollapsibleRoot(
|
|
68
72
|
controlledOpen,
|
|
69
73
|
defaultOpen,
|
|
@@ -84,6 +88,7 @@ export function CollapsibleRoot({
|
|
|
84
88
|
);
|
|
85
89
|
}
|
|
86
90
|
|
|
91
|
+
/** @internal */
|
|
87
92
|
CollapsibleRoot.displayName = "CollapsibleRoot";
|
|
88
93
|
|
|
89
94
|
/**
|
|
@@ -140,16 +145,14 @@ CollapsibleRoot.displayName = "CollapsibleRoot";
|
|
|
140
145
|
* </Collapsible.Trigger>
|
|
141
146
|
* ```
|
|
142
147
|
*/
|
|
143
|
-
export function CollapsibleTrigger<
|
|
144
|
-
T extends HTMLElement = HTMLButtonElement,
|
|
145
|
-
>({
|
|
148
|
+
export function CollapsibleTrigger<T extends HTMLElement = HTMLButtonElement>({
|
|
146
149
|
ref,
|
|
147
150
|
children,
|
|
148
151
|
onClick,
|
|
149
152
|
onKeyDown,
|
|
150
153
|
asChild = false,
|
|
151
154
|
...rest
|
|
152
|
-
}: CollapsibleTriggerProps<T>) {
|
|
155
|
+
}: CollapsibleTriggerProps<T>): ReactElement {
|
|
153
156
|
const { triggerProps } = useCollapsibleTrigger({
|
|
154
157
|
ref: ref as Ref<HTMLButtonElement>,
|
|
155
158
|
onClick,
|
|
@@ -169,6 +172,7 @@ export function CollapsibleTrigger<
|
|
|
169
172
|
);
|
|
170
173
|
}
|
|
171
174
|
|
|
175
|
+
/** @internal */
|
|
172
176
|
CollapsibleTrigger.displayName = "CollapsibleTrigger";
|
|
173
177
|
|
|
174
178
|
/**
|
|
@@ -222,7 +226,7 @@ export function CollapsibleContent({
|
|
|
222
226
|
children,
|
|
223
227
|
forceMount = false,
|
|
224
228
|
...rest
|
|
225
|
-
}: CollapsibleContentProps) {
|
|
229
|
+
}: CollapsibleContentProps): ReactElement {
|
|
226
230
|
const { open, disabled, contentId } = useCollapsibleContext();
|
|
227
231
|
|
|
228
232
|
return (
|
|
@@ -239,6 +243,7 @@ export function CollapsibleContent({
|
|
|
239
243
|
);
|
|
240
244
|
}
|
|
241
245
|
|
|
246
|
+
/** @internal */
|
|
242
247
|
CollapsibleContent.displayName = "CollapsibleContent";
|
|
243
248
|
|
|
244
249
|
/**
|
|
@@ -281,35 +286,46 @@ CollapsibleContent.displayName = "CollapsibleContent";
|
|
|
281
286
|
export function CollapsibleTriggerIcon({
|
|
282
287
|
children,
|
|
283
288
|
...rest
|
|
284
|
-
}: CollapsibleTriggerIconProps) {
|
|
289
|
+
}: CollapsibleTriggerIconProps): ReactElement {
|
|
285
290
|
const { open } = useCollapsibleContext();
|
|
286
291
|
|
|
287
292
|
return (
|
|
288
|
-
<span
|
|
289
|
-
aria-hidden="true"
|
|
290
|
-
data-state={open ? "open" : "closed"}
|
|
291
|
-
{...rest}
|
|
292
|
-
>
|
|
293
|
+
<span aria-hidden="true" data-state={open ? "open" : "closed"} {...rest}>
|
|
293
294
|
{children}
|
|
294
295
|
</span>
|
|
295
296
|
);
|
|
296
297
|
}
|
|
297
298
|
|
|
299
|
+
/** @internal */
|
|
298
300
|
CollapsibleTriggerIcon.displayName = "CollapsibleTriggerIcon";
|
|
299
301
|
|
|
302
|
+
/** Type of the {@link Collapsible} compound — the Root callable plus its sub-components. */
|
|
300
303
|
type CollapsibleCompound = typeof CollapsibleRoot & {
|
|
304
|
+
/** The root, owning open/closed state and context. */
|
|
301
305
|
Root: typeof CollapsibleRoot;
|
|
306
|
+
/** The button that toggles the panel. */
|
|
302
307
|
Trigger: typeof CollapsibleTrigger;
|
|
308
|
+
/** The collapsible panel. */
|
|
303
309
|
Content: typeof CollapsibleContent;
|
|
310
|
+
/** An aria-hidden icon wrapper with an open/closed `data-state` hook. */
|
|
304
311
|
TriggerIcon: typeof CollapsibleTriggerIcon;
|
|
305
312
|
};
|
|
306
313
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
314
|
+
/**
|
|
315
|
+
* Collapsible — a single disclosure widget pairing a trigger with a panel
|
|
316
|
+
* that expands and collapses. Use as a namespace (`Collapsible.Root`,
|
|
317
|
+
* `Collapsible.Trigger`, `Collapsible.Content`, `Collapsible.TriggerIcon`);
|
|
318
|
+
* the default export is also callable as the Root.
|
|
319
|
+
*/
|
|
320
|
+
const CollapsibleCompound: CollapsibleCompound = Object.assign(
|
|
321
|
+
CollapsibleRoot,
|
|
322
|
+
{
|
|
323
|
+
Root: CollapsibleRoot,
|
|
324
|
+
Trigger: CollapsibleTrigger,
|
|
325
|
+
Content: CollapsibleContent,
|
|
326
|
+
TriggerIcon: CollapsibleTriggerIcon,
|
|
327
|
+
},
|
|
328
|
+
);
|
|
313
329
|
|
|
314
330
|
CollapsibleCompound.displayName = "Collapsible";
|
|
315
331
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useRef, MouseEvent, KeyboardEvent } from "react";
|
|
2
2
|
|
|
3
|
-
import { composeRefs } from "../../Slot";
|
|
3
|
+
import { composeRefs } from "../../Slot/index.ts";
|
|
4
4
|
|
|
5
5
|
import { CollapsibleTriggerProps } from "../types";
|
|
6
6
|
import { useCollapsibleContext } from "../CollapsibleContext";
|
package/src/Collapsible/index.ts
CHANGED
package/src/Collapsible/types.ts
CHANGED
|
@@ -1,48 +1,81 @@
|
|
|
1
1
|
import { ComponentProps, ReactNode, Ref } from "react";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/** Props common to both controlled and uncontrolled `Collapsible.Root` modes. */
|
|
4
|
+
export type CollapsibleRootBaseProps = Omit<
|
|
5
|
+
ComponentProps<"div">,
|
|
6
|
+
"onChange"
|
|
7
|
+
> & {
|
|
8
|
+
/** When `true`, disables the widget and short-circuits trigger activation. */
|
|
4
9
|
disabled?: boolean;
|
|
5
10
|
};
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Props for `Collapsible.Root` in uncontrolled mode — the component owns the
|
|
14
|
+
* open state. Pass `defaultOpen` to set the initial value; `open` is forbidden.
|
|
15
|
+
*/
|
|
16
|
+
export type CollapsibleRootUncontrolledProps = CollapsibleRootBaseProps & {
|
|
17
|
+
/** Initial open state when uncontrolled. Defaults to `false`. */
|
|
8
18
|
defaultOpen?: boolean;
|
|
19
|
+
/** Forbidden in uncontrolled mode. */
|
|
9
20
|
open?: never;
|
|
21
|
+
/** Called whenever the open state changes. */
|
|
10
22
|
onOpenChange?: (open: boolean) => void;
|
|
11
23
|
};
|
|
12
24
|
|
|
13
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Props for `Collapsible.Root` in controlled mode — the parent owns the open
|
|
27
|
+
* value. Pass `open` and `onOpenChange` together; `defaultOpen` is forbidden.
|
|
28
|
+
*/
|
|
29
|
+
export type CollapsibleRootControlledProps = CollapsibleRootBaseProps & {
|
|
30
|
+
/** The controlled open state. */
|
|
14
31
|
open: boolean;
|
|
32
|
+
/** Called whenever the component requests an open-state change. */
|
|
15
33
|
onOpenChange: (open: boolean) => void;
|
|
34
|
+
/** Forbidden in controlled mode. */
|
|
16
35
|
defaultOpen?: never;
|
|
17
36
|
};
|
|
18
37
|
|
|
38
|
+
/** Props for `Collapsible.Root` — discriminated controlled/uncontrolled union. */
|
|
19
39
|
export type CollapsibleRootProps =
|
|
20
40
|
| CollapsibleRootUncontrolledProps
|
|
21
41
|
| CollapsibleRootControlledProps;
|
|
22
42
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
/** Props for `Collapsible.Trigger`, the button that toggles the panel. */
|
|
44
|
+
export type CollapsibleTriggerProps<T extends HTMLElement = HTMLButtonElement> =
|
|
45
|
+
Omit<ComponentProps<"button">, "ref"> & {
|
|
46
|
+
/** Trigger content (label, icon, etc.). */
|
|
47
|
+
children: ReactNode;
|
|
48
|
+
/** Render the child element instead of the default `<button>`. */
|
|
49
|
+
asChild?: boolean;
|
|
50
|
+
/** Ref to the rendered element. Defaults to `HTMLButtonElement`; when using
|
|
51
|
+
* `asChild`, specify the child's element type (e.g. `HTMLAnchorElement`). */
|
|
52
|
+
ref?: Ref<T>;
|
|
53
|
+
};
|
|
32
54
|
|
|
55
|
+
/** Props for `Collapsible.Content`, the panel revealed when open. */
|
|
33
56
|
export type CollapsibleContentProps = ComponentProps<"div"> & {
|
|
57
|
+
/** Panel content. */
|
|
34
58
|
children: ReactNode;
|
|
59
|
+
/** Keep the panel mounted when closed so transitions can be CSS-driven. */
|
|
35
60
|
forceMount?: boolean;
|
|
36
61
|
};
|
|
37
62
|
|
|
63
|
+
/** Props for `Collapsible.TriggerIcon`, the aria-hidden icon wrapper. */
|
|
38
64
|
export type CollapsibleTriggerIconProps = ComponentProps<"span"> & {
|
|
65
|
+
/** The icon to render (inline SVG or icon component). */
|
|
39
66
|
children: ReactNode;
|
|
40
67
|
};
|
|
41
68
|
|
|
69
|
+
/** Value shared through Collapsible context to all sub-components. */
|
|
42
70
|
export type CollapsibleContextValue = {
|
|
71
|
+
/** Whether the panel is currently open. */
|
|
43
72
|
open: boolean;
|
|
73
|
+
/** Whether the widget is disabled. */
|
|
44
74
|
disabled: boolean;
|
|
75
|
+
/** Toggle the open state. */
|
|
45
76
|
toggle: () => void;
|
|
77
|
+
/** Generated id linking trigger to content. */
|
|
46
78
|
triggerId: string;
|
|
79
|
+
/** Generated id of the content panel. */
|
|
47
80
|
contentId: string;
|
|
48
81
|
};
|