@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.
Files changed (207) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +2 -1
  3. package/src/AccessibleIcon/AccessibleIcon.tsx +6 -2
  4. package/src/AccessibleIcon/__tests__/AccessibleIcon.test.tsx +1 -1
  5. package/src/AccessibleIcon/types.ts +4 -0
  6. package/src/Accordion/Accordion.tsx +34 -12
  7. package/src/Accordion/AccordionContext.ts +1 -1
  8. package/src/Accordion/__tests__/Accordion.reading-direction.test.tsx +1 -1
  9. package/src/Accordion/hooks/useAccordionItem.ts +1 -1
  10. package/src/Accordion/hooks/useAccordionRoot.ts +1 -1
  11. package/src/Accordion/hooks/useAccordionTrigger.ts +2 -2
  12. package/src/Accordion/index.ts +2 -1
  13. package/src/Accordion/types.ts +55 -13
  14. package/src/Alert/Alert.tsx +9 -2
  15. package/src/Alert/__tests__/Alert.test.tsx +1 -1
  16. package/src/Alert/types.ts +1 -0
  17. package/src/Avatar/Avatar.tsx +20 -7
  18. package/src/Avatar/AvatarContext.ts +12 -6
  19. package/src/Breadcrumb/Breadcrumb.tsx +32 -10
  20. package/src/Button/Button.tsx +5 -2
  21. package/src/Button/types.ts +4 -0
  22. package/src/Carousel/Carousel.tsx +30 -14
  23. package/src/Carousel/CarouselContext.ts +7 -3
  24. package/src/Carousel/__tests__/Carousel.asChild.test.tsx +1 -1
  25. package/src/Carousel/__tests__/Carousel.auto-play.test.tsx +1 -1
  26. package/src/Carousel/__tests__/Carousel.basic-rendering.test.tsx +1 -1
  27. package/src/Carousel/__tests__/Carousel.controlled-state.test.tsx +1 -1
  28. package/src/Carousel/__tests__/Carousel.error-handling.test.tsx +1 -1
  29. package/src/Carousel/__tests__/Carousel.ids.test.tsx +1 -1
  30. package/src/Carousel/__tests__/Carousel.imperative-api.test.tsx +2 -2
  31. package/src/Carousel/__tests__/Carousel.indicators.test.tsx +1 -1
  32. package/src/Carousel/__tests__/Carousel.intersection-observer.test.tsx +2 -2
  33. package/src/Carousel/__tests__/Carousel.keyboard-navigation.test.tsx +1 -1
  34. package/src/Carousel/__tests__/Carousel.play-pause.test.tsx +1 -1
  35. package/src/Carousel/__tests__/Carousel.prev-next.test.tsx +1 -1
  36. package/src/Carousel/__tests__/Carousel.reduced-motion.test.tsx +1 -1
  37. package/src/Carousel/__tests__/Carousel.refresh-progress.test.tsx +2 -2
  38. package/src/Carousel/__tests__/Carousel.scroll-snap-change.test.tsx +1 -1
  39. package/src/Carousel/__tests__/Carousel.scroll-sync.test.tsx +1 -1
  40. package/src/Carousel/__tests__/Carousel.slides-per-move.test.tsx +1 -1
  41. package/src/Carousel/__tests__/Carousel.slides-per-page.test.tsx +1 -1
  42. package/src/Carousel/__tests__/Carousel.touch-interaction.test.tsx +1 -1
  43. package/src/Carousel/__tests__/Carousel.transition-modes.test.tsx +1 -1
  44. package/src/Carousel/__tests__/Carousel.translations.test.tsx +1 -1
  45. package/src/Carousel/__tests__/Carousel.uncontrolled-state.test.tsx +1 -1
  46. package/src/Carousel/types.ts +8 -0
  47. package/src/Checkbox/Checkbox.tsx +11 -6
  48. package/src/Checkbox/CheckboxContext.ts +1 -1
  49. package/src/Checkbox/hooks/useCheckboxRoot.ts +1 -1
  50. package/src/Checkbox/index.ts +1 -0
  51. package/src/Checkbox/types.ts +30 -3
  52. package/src/CheckboxCard/CheckboxCard.tsx +13 -11
  53. package/src/CheckboxCard/CheckboxCardContext.ts +19 -6
  54. package/src/CheckboxCard/hooks/useCheckboxCardRoot.ts +2 -2
  55. package/src/CheckboxCard/types.ts +21 -5
  56. package/src/Collapsible/Collapsible.tsx +37 -21
  57. package/src/Collapsible/CollapsibleContext.ts +1 -1
  58. package/src/Collapsible/hooks/useCollapsibleRoot.ts +1 -1
  59. package/src/Collapsible/hooks/useCollapsibleTrigger.ts +1 -1
  60. package/src/Collapsible/index.ts +1 -0
  61. package/src/Collapsible/types.ts +45 -12
  62. package/src/ContextMenu/ContextMenu.tsx +60 -34
  63. package/src/ContextMenu/ContextMenuContext.ts +2 -2
  64. package/src/ContextMenu/ContextMenuSubContext.ts +1 -1
  65. package/src/ContextMenu/__tests__/ContextMenu.reading-direction.test.tsx +1 -1
  66. package/src/ContextMenu/index.ts +2 -1
  67. package/src/ContextMenu/types.ts +160 -17
  68. package/src/DirectionProvider/DirectionProvider.tsx +7 -1
  69. package/src/DirectionProvider/__tests__/DirectionProvider.test.tsx +1 -1
  70. package/src/DirectionProvider/types.ts +1 -0
  71. package/src/Divider/Divider.tsx +4 -1
  72. package/src/Divider/__tests__/Divider.test.tsx +1 -1
  73. package/src/Divider/index.ts +2 -1
  74. package/src/Divider/types.ts +5 -0
  75. package/src/Dropdown/Dropdown.tsx +60 -34
  76. package/src/Dropdown/DropdownContext.ts +2 -2
  77. package/src/Dropdown/DropdownSubContext.ts +1 -1
  78. package/src/Dropdown/__tests__/Dropdown.reading-direction.test.tsx +1 -1
  79. package/src/Dropdown/hooks/useDropdownContent.ts +1 -1
  80. package/src/Dropdown/hooks/useDropdownItem.ts +1 -1
  81. package/src/Dropdown/hooks/useDropdownRoot.ts +2 -2
  82. package/src/Dropdown/hooks/useDropdownTrigger.ts +1 -1
  83. package/src/Dropdown/index.ts +2 -1
  84. package/src/Dropdown/types.ts +153 -25
  85. package/src/EmptyState/EmptyState.tsx +34 -20
  86. package/src/EmptyState/__tests__/EmptyState.Actions.test.tsx +1 -1
  87. package/src/EmptyState/__tests__/EmptyState.Description.test.tsx +1 -1
  88. package/src/EmptyState/__tests__/EmptyState.Media.test.tsx +1 -1
  89. package/src/EmptyState/__tests__/EmptyState.Root.test.tsx +1 -1
  90. package/src/EmptyState/__tests__/EmptyState.Title.test.tsx +1 -1
  91. package/src/EmptyState/types.ts +2 -1
  92. package/src/Field/Field.tsx +24 -10
  93. package/src/Field/FieldContext.ts +1 -1
  94. package/src/Field/types.ts +4 -0
  95. package/src/Fieldset/Fieldset.tsx +26 -10
  96. package/src/Fieldset/types.ts +2 -0
  97. package/src/Input/Input.tsx +6 -3
  98. package/src/Input/__tests__/Input.field-integration.test.tsx +1 -1
  99. package/src/Input/types.ts +4 -0
  100. package/src/InputGroup/InputGroup.tsx +15 -8
  101. package/src/InputGroup/types.ts +9 -0
  102. package/src/MillerColumns/MillerColumns.tsx +28 -8
  103. package/src/MillerColumns/MillerColumnsContext.ts +1 -1
  104. package/src/MillerColumns/hooks/useMillerColumnsItem.ts +2 -2
  105. package/src/MillerColumns/hooks/useMillerColumnsRoot.ts +0 -0
  106. package/src/MillerColumns/index.ts +1 -1
  107. package/src/MillerColumns/types.ts +67 -14
  108. package/src/MillerColumns/useMillerColumnsSelection.ts +1 -1
  109. package/src/Modal/Modal.tsx +25 -11
  110. package/src/Modal/ModalContext.ts +14 -7
  111. package/src/Modal/hooks/useModalRoot.ts +1 -1
  112. package/src/Modal/hooks/useModalTrigger.ts +2 -2
  113. package/src/Modal/types.ts +51 -2
  114. package/src/Portal/Portal.tsx +3 -1
  115. package/src/Portal/types.ts +4 -0
  116. package/src/Progress/Progress.tsx +12 -7
  117. package/src/Progress/ProgressContext.ts +18 -6
  118. package/src/RadioCard/RadioCard.tsx +17 -11
  119. package/src/RadioCard/RadioCardContext.ts +17 -5
  120. package/src/RadioCard/RadioCardItemContext.ts +18 -5
  121. package/src/RadioCard/__tests__/RadioCard.reading-direction.test.tsx +1 -1
  122. package/src/RadioCard/hooks/useRadioCardRoot.ts +1 -1
  123. package/src/RadioCard/types.ts +24 -3
  124. package/src/RadioGroup/RadioGroup.tsx +17 -11
  125. package/src/RadioGroup/RadioGroupContext.ts +1 -1
  126. package/src/RadioGroup/RadioGroupItemContext.ts +1 -1
  127. package/src/RadioGroup/__tests__/RadioGroup.reading-direction.test.tsx +1 -1
  128. package/src/RadioGroup/hooks/useRadioGroupRoot.ts +1 -1
  129. package/src/RadioGroup/index.ts +1 -0
  130. package/src/RadioGroup/types.ts +34 -3
  131. package/src/Select/Select.tsx +23 -8
  132. package/src/Select/__tests__/Select.field-integration.test.tsx +1 -1
  133. package/src/Select/index.ts +1 -1
  134. package/src/Select/types.ts +18 -3
  135. package/src/SkipNav/SkipNav.tsx +7 -2
  136. package/src/SkipNav/__tests__/SkipNav.ids.test.tsx +1 -1
  137. package/src/Slider/Slider.tsx +26 -11
  138. package/src/Slider/SliderContext.ts +13 -6
  139. package/src/Slider/__tests__/Slider.reading-direction.test.tsx +1 -1
  140. package/src/Slider/hooks/useSliderRoot.ts +1 -1
  141. package/src/Slider/types.ts +12 -3
  142. package/src/Status/Status.tsx +9 -2
  143. package/src/Status/__tests__/Status.test.tsx +1 -1
  144. package/src/Status/types.ts +4 -0
  145. package/src/Switch/Switch.tsx +16 -6
  146. package/src/Switch/SwitchContext.ts +13 -5
  147. package/src/Switch/hooks/useSwitchRoot.ts +1 -1
  148. package/src/Switch/types.ts +24 -3
  149. package/src/Table/Table.tsx +51 -25
  150. package/src/Table/__tests__/Table.Body.test.tsx +1 -1
  151. package/src/Table/__tests__/Table.Caption.test.tsx +1 -1
  152. package/src/Table/__tests__/Table.Cell.test.tsx +1 -1
  153. package/src/Table/__tests__/Table.Footer.test.tsx +1 -1
  154. package/src/Table/__tests__/Table.Head.test.tsx +1 -1
  155. package/src/Table/__tests__/Table.Header.test.tsx +1 -1
  156. package/src/Table/__tests__/Table.Root.test.tsx +1 -1
  157. package/src/Table/__tests__/Table.Row.test.tsx +1 -1
  158. package/src/Table/__tests__/Table.ScrollArea.test.tsx +1 -1
  159. package/src/Table/index.ts +2 -1
  160. package/src/Tabs/Tabs.tsx +30 -10
  161. package/src/Tabs/TabsContext.ts +15 -7
  162. package/src/Tabs/__tests__/Tabs.asChild.test.tsx +1 -1
  163. package/src/Tabs/__tests__/Tabs.basic-rendering.test.tsx +1 -1
  164. package/src/Tabs/__tests__/Tabs.change-event-callbacks.test.tsx +1 -1
  165. package/src/Tabs/__tests__/Tabs.controlled-state.test.tsx +1 -1
  166. package/src/Tabs/__tests__/Tabs.error-handling.test.tsx +1 -1
  167. package/src/Tabs/__tests__/Tabs.imperative-api.test.tsx +1 -1
  168. package/src/Tabs/__tests__/Tabs.keyboard-interaction.test.tsx +1 -1
  169. package/src/Tabs/__tests__/Tabs.lazy-mount.test.tsx +1 -1
  170. package/src/Tabs/__tests__/Tabs.mouse-interaction.test.tsx +1 -1
  171. package/src/Tabs/__tests__/Tabs.reading-direction.test.tsx +1 -1
  172. package/src/Tabs/__tests__/Tabs.uncontrolled-state.test.tsx +1 -1
  173. package/src/Tabs/hooks/useTabsContent.ts +1 -1
  174. package/src/Tabs/hooks/useTabsRoot.ts +1 -1
  175. package/src/Tabs/hooks/useTabsTrigger.ts +1 -1
  176. package/src/Tabs/types.ts +35 -1
  177. package/src/Tabs/utils.ts +1 -1
  178. package/src/Textarea/Textarea.tsx +6 -3
  179. package/src/Textarea/__tests__/Textarea.field-integration.test.tsx +1 -1
  180. package/src/Textarea/types.ts +4 -0
  181. package/src/Toggle/Toggle.tsx +11 -4
  182. package/src/Toggle/types.ts +7 -3
  183. package/src/ToggleGroup/ToggleGroup.tsx +23 -13
  184. package/src/ToggleGroup/ToggleGroupContext.ts +1 -1
  185. package/src/ToggleGroup/__tests__/ToggleGroup.reading-direction.test.tsx +1 -1
  186. package/src/ToggleGroup/hooks/useToggleGroupRoot.ts +1 -1
  187. package/src/ToggleGroup/types.ts +45 -5
  188. package/src/Tooltip/Tooltip.tsx +46 -15
  189. package/src/Tooltip/TooltipContext.ts +1 -1
  190. package/src/Tooltip/hooks/useTooltipContent.ts +1 -1
  191. package/src/Tooltip/hooks/useTooltipRoot.ts +1 -1
  192. package/src/Tooltip/hooks/useTooltipTrigger.ts +1 -1
  193. package/src/Tooltip/index.ts +1 -0
  194. package/src/Tooltip/types.ts +50 -2
  195. package/src/Tree/Tree.tsx +58 -12
  196. package/src/Tree/TreeContext.ts +1 -1
  197. package/src/Tree/__tests__/Tree.selection-path.test.tsx +2 -2
  198. package/src/Tree/hooks/useTreeItemKeyboard.ts +1 -1
  199. package/src/Tree/hooks/useTreeRoot.ts +1 -1
  200. package/src/Tree/index.ts +1 -1
  201. package/src/Tree/types.ts +39 -7
  202. package/src/VisuallyHidden/VisuallyHidden.tsx +4 -2
  203. package/src/VisuallyHidden/__tests__/VisuallyHidden.test.tsx +1 -1
  204. package/src/VisuallyHidden/types.ts +4 -0
  205. package/src/index.ts +39 -38
  206. package/src/types.ts +1 -0
  207. package/src/utils/createStrictContext.ts +9 -5
@@ -1,5 +1,10 @@
1
1
  import { ComponentProps, ReactNode } from "react";
2
2
 
3
+ /**
4
+ * Context published by {@link Tooltip.Provider} — the shared open / skip
5
+ * delays and the group-wide open coordination callbacks used to suppress
6
+ * the open delay while another tooltip in the group is already showing.
7
+ */
3
8
  export type TooltipProviderContextValue = {
4
9
  delayDuration: number;
5
10
  skipDelayDuration: number;
@@ -8,6 +13,11 @@ export type TooltipProviderContextValue = {
8
13
  onCloseGlobally: () => void;
9
14
  };
10
15
 
16
+ /**
17
+ * Context published by {@link Tooltip.Root} to its descendants — the live
18
+ * `open` state, the content `id` for ARIA wiring, and the timing callbacks
19
+ * the trigger and content use to open / close with the correct delays.
20
+ */
11
21
  export type TooltipContextValue = {
12
22
  open: boolean;
13
23
  contentId: string;
@@ -19,46 +29,84 @@ export type TooltipContextValue = {
19
29
  cancelGrace: () => void;
20
30
  };
21
31
 
32
+ /**
33
+ * Props for {@link Tooltip.Provider} — sets the `delayDuration` and
34
+ * `skipDelayDuration` shared by every tooltip in the subtree.
35
+ */
22
36
  export type TooltipProviderProps = {
23
37
  children?: ReactNode;
24
38
  delayDuration?: number;
25
39
  skipDelayDuration?: number;
26
40
  };
27
41
 
28
- type UncontrolledTooltipRootProps = {
42
+ /**
43
+ * Uncontrolled variant of {@link TooltipRootProps}: the component owns the
44
+ * open state. Pass `defaultOpen` (or omit it); `onOpenChange` is optional
45
+ * and `open` is forbidden.
46
+ */
47
+ export type UncontrolledTooltipRootProps = {
29
48
  defaultOpen?: boolean;
30
49
  open?: never;
31
50
  onOpenChange?: (open: boolean) => void;
32
51
  };
33
52
 
34
- type ControlledTooltipRootProps = {
53
+ /**
54
+ * Controlled variant of {@link TooltipRootProps}: the parent owns the open
55
+ * state. Pass `open` (with an optional `onOpenChange`); `defaultOpen` is
56
+ * forbidden.
57
+ */
58
+ export type ControlledTooltipRootProps = {
35
59
  open: boolean;
36
60
  onOpenChange?: (open: boolean) => void;
37
61
  defaultOpen?: never;
38
62
  };
39
63
 
64
+ /**
65
+ * Props for {@link Tooltip.Root}. Combines the per-tooltip timing /
66
+ * hoverable-content options with one of the two state modes
67
+ * ({@link UncontrolledTooltipRootProps} | {@link ControlledTooltipRootProps}),
68
+ * so TypeScript accepts exactly one mode.
69
+ */
40
70
  export type TooltipRootProps = {
41
71
  children?: ReactNode;
42
72
  delayDuration?: number;
43
73
  disableHoverableContent?: boolean;
44
74
  } & (UncontrolledTooltipRootProps | ControlledTooltipRootProps);
45
75
 
76
+ /**
77
+ * Props for {@link Tooltip.Trigger} — all native `<button>` attributes plus
78
+ * the `asChild` escape hatch.
79
+ */
46
80
  export type TooltipTriggerProps = ComponentProps<"button"> & {
47
81
  asChild?: boolean;
48
82
  };
49
83
 
84
+ /**
85
+ * Props for {@link Tooltip.Portal} — the `container` to render the content
86
+ * into (defaults to `document.body`) and `forceMount` to keep the content
87
+ * in the DOM while closed for exit animations.
88
+ */
50
89
  export type TooltipPortalProps = {
51
90
  children?: ReactNode;
52
91
  container?: HTMLElement;
53
92
  forceMount?: boolean;
54
93
  };
55
94
 
95
+ /**
96
+ * Props for {@link Tooltip.Content} — all native `<div>` attributes plus
97
+ * `forceMount` and the dismissal callbacks fired on Escape
98
+ * (`onEscapeKeyDown`) and outside pointer-down (`onPointerDownOutside`).
99
+ */
56
100
  export type TooltipContentProps = ComponentProps<"div"> & {
57
101
  forceMount?: boolean;
58
102
  onEscapeKeyDown?: (event: KeyboardEvent) => void;
59
103
  onPointerDownOutside?: (event: PointerEvent) => void;
60
104
  };
61
105
 
106
+ /**
107
+ * Props for {@link Tooltip.Arrow} — all native `<span>` attributes plus the
108
+ * `asChild` escape hatch.
109
+ */
62
110
  export type TooltipArrowProps = ComponentProps<"span"> & {
63
111
  asChild?: boolean;
64
112
  };
package/src/Tree/Tree.tsx CHANGED
@@ -1,8 +1,9 @@
1
1
  import { Fragment, useLayoutEffect, useRef } from "react";
2
+ import type { ReactElement } from "react";
2
3
 
3
- import { Breadcrumb } from "../Breadcrumb";
4
- import { Slot, composeEventHandlers } from "../Slot";
5
- import { deriveId } from "../utils";
4
+ import { Breadcrumb } from "../Breadcrumb/index.ts";
5
+ import { Slot, composeEventHandlers } from "../Slot/index.ts";
6
+ import { deriveId } from "../utils/index.ts";
6
7
 
7
8
  import {
8
9
  TreeContext,
@@ -16,7 +17,7 @@ import {
16
17
  useTreeItemKeyboard,
17
18
  useTreeRoot,
18
19
  useTreeSelectionPaths,
19
- } from "./hooks";
20
+ } from "./hooks/index.ts";
20
21
  import { partitionBranchChildren } from "./utils";
21
22
 
22
23
  import type {
@@ -63,7 +64,7 @@ import type {
63
64
  * </Tree.Root>
64
65
  * ```
65
66
  */
66
- export function TreeRoot(props: TreeRootProps) {
67
+ export function TreeRoot(props: TreeRootProps): ReactElement {
67
68
  const {
68
69
  children,
69
70
  expandedValues,
@@ -115,6 +116,7 @@ export function TreeRoot(props: TreeRootProps) {
115
116
  );
116
117
  }
117
118
 
119
+ /** @internal */
118
120
  TreeRoot.displayName = "TreeRoot";
119
121
 
120
122
  /**
@@ -141,7 +143,7 @@ export function TreeItem({
141
143
  onFocus,
142
144
  onKeyDown,
143
145
  ...rest
144
- }: TreeItemProps) {
146
+ }: TreeItemProps): ReactElement {
145
147
  const { depth, parentValue } = useTreeLevelContext();
146
148
  const { isSelected, select, registerNode, tabStop, setActiveValue } =
147
149
  useTreeContext();
@@ -200,6 +202,7 @@ export function TreeItem({
200
202
  );
201
203
  }
202
204
 
205
+ /** @internal */
203
206
  TreeItem.displayName = "TreeItem";
204
207
 
205
208
  /**
@@ -235,7 +238,7 @@ export function TreeBranch({
235
238
  onFocus,
236
239
  onKeyDown,
237
240
  ...rest
238
- }: TreeBranchProps) {
241
+ }: TreeBranchProps): ReactElement {
239
242
  const { depth, parentValue } = useTreeLevelContext();
240
243
  const {
241
244
  rootId,
@@ -300,6 +303,7 @@ export function TreeBranch({
300
303
  );
301
304
  }
302
305
 
306
+ /** @internal */
303
307
  TreeBranch.displayName = "TreeBranch";
304
308
 
305
309
  /**
@@ -321,7 +325,7 @@ export function TreeBranchControl({
321
325
  children,
322
326
  onClick,
323
327
  ...rest
324
- }: TreeBranchControlProps) {
328
+ }: TreeBranchControlProps): ReactElement {
325
329
  const { value, disabled, controlId } = useTreeItemContext();
326
330
  const { toggleExpanded, select } = useTreeContext();
327
331
 
@@ -348,6 +352,7 @@ export function TreeBranchControl({
348
352
  );
349
353
  }
350
354
 
355
+ /** @internal */
351
356
  TreeBranchControl.displayName = "TreeBranchControl";
352
357
 
353
358
  /**
@@ -363,7 +368,7 @@ export function TreeBranchContent({
363
368
  children,
364
369
  forceMount = false,
365
370
  ...rest
366
- }: TreeBranchContentProps) {
371
+ }: TreeBranchContentProps): ReactElement {
367
372
  const { depth } = useTreeLevelContext();
368
373
  const { value: branchValue, expanded } = useTreeItemContext();
369
374
 
@@ -384,6 +389,7 @@ export function TreeBranchContent({
384
389
  );
385
390
  }
386
391
 
392
+ /** @internal */
387
393
  TreeBranchContent.displayName = "TreeBranchContent";
388
394
 
389
395
  /**
@@ -413,7 +419,7 @@ export function TreeBranchIndicator({
413
419
  children,
414
420
  asChild = false,
415
421
  ...rest
416
- }: TreeBranchIndicatorProps) {
422
+ }: TreeBranchIndicatorProps): ReactElement {
417
423
  const { expanded } = useTreeItemContext();
418
424
 
419
425
  const indicatorProps = {
@@ -429,6 +435,7 @@ export function TreeBranchIndicator({
429
435
  );
430
436
  }
431
437
 
438
+ /** @internal */
432
439
  TreeBranchIndicator.displayName = "TreeBranchIndicator";
433
440
 
434
441
  /**
@@ -483,7 +490,7 @@ export function TreeSelectionPath({
483
490
  children,
484
491
  separator,
485
492
  ...rest
486
- }: TreeSelectionPathProps) {
493
+ }: TreeSelectionPathProps): ReactElement {
487
494
  const paths = useTreeSelectionPaths();
488
495
  const empty = paths.length === 0;
489
496
 
@@ -544,9 +551,14 @@ export function TreeSelectionPath({
544
551
  );
545
552
  }
546
553
 
554
+ /** @internal */
547
555
  TreeSelectionPath.displayName = "TreeSelectionPath";
548
556
 
549
- type TreeCompound = typeof TreeRoot & {
557
+ /**
558
+ * The shape of the exported `Tree` value — callable as `Tree.Root` and
559
+ * carrying every sub-component as a static property.
560
+ */
561
+ export type TreeCompound = typeof TreeRoot & {
550
562
  Root: typeof TreeRoot;
551
563
  Item: typeof TreeItem;
552
564
  Branch: typeof TreeBranch;
@@ -556,6 +568,39 @@ type TreeCompound = typeof TreeRoot & {
556
568
  SelectionPath: typeof TreeSelectionPath;
557
569
  };
558
570
 
571
+ /**
572
+ * Headless, accessible **Tree** — a compound component implementing the
573
+ * WAI-ARIA tree view pattern (`role="tree"` / `treeitem` / `group`) with
574
+ * roving tabindex, single or multiple selection, and expandable branches,
575
+ * with zero styles.
576
+ *
577
+ * `Tree` is both callable (an alias of {@link TreeRoot | `Tree.Root`}) and
578
+ * carries its sub-components as static properties:
579
+ *
580
+ * - {@link TreeRoot | `Tree.Root`} — state owner, context provider, `role="tree"`.
581
+ * - {@link TreeItem | `Tree.Item`} — a leaf `role="treeitem"`.
582
+ * - {@link TreeBranch | `Tree.Branch`} — an expandable `role="treeitem"` with children.
583
+ * - {@link TreeBranchControl | `Tree.BranchControl`} — the branch's selectable / toggling control.
584
+ * - {@link TreeBranchContent | `Tree.BranchContent`} — the collapsible `role="group"` of child nodes.
585
+ * - {@link TreeBranchIndicator | `Tree.BranchIndicator`} — expand/collapse affordance.
586
+ * - {@link TreeSelectionPath | `Tree.SelectionPath`} — breadcrumb of the selected node's ancestry.
587
+ *
588
+ * @example
589
+ * ```tsx
590
+ * import { Tree } from "@primitiv-ui/react";
591
+ *
592
+ * <Tree.Root>
593
+ * <Tree.Branch value="src">
594
+ * <Tree.BranchControl>
595
+ * src <Tree.BranchIndicator />
596
+ * </Tree.BranchControl>
597
+ * <Tree.BranchContent>
598
+ * <Tree.Item value="index">index.ts</Tree.Item>
599
+ * </Tree.BranchContent>
600
+ * </Tree.Branch>
601
+ * </Tree.Root>;
602
+ * ```
603
+ */
559
604
  const TreeCompound: TreeCompound = Object.assign(TreeRoot, {
560
605
  Root: TreeRoot,
561
606
  Item: TreeItem,
@@ -566,6 +611,7 @@ const TreeCompound: TreeCompound = Object.assign(TreeRoot, {
566
611
  SelectionPath: TreeSelectionPath,
567
612
  });
568
613
 
614
+ /** @internal */
569
615
  TreeCompound.displayName = "Tree";
570
616
 
571
617
  export { TreeCompound as Tree };
@@ -1,4 +1,4 @@
1
- import { createStrictContext } from "../utils";
1
+ import { createStrictContext } from "../utils/index.ts";
2
2
 
3
3
  import type {
4
4
  TreeContextValue,
@@ -3,8 +3,8 @@ import { useState } from "react";
3
3
  import { render, screen, within } from "@testing-library/react";
4
4
  import userEvent from "@testing-library/user-event";
5
5
 
6
- import { Tree, useTreePath, useTreeSelectionPaths } from "../../Tree";
7
- import type { TreePathSegment } from "../../Tree";
6
+ import { Tree, useTreePath, useTreeSelectionPaths } from "../../Tree/index.ts";
7
+ import type { TreePathSegment } from "../../Tree/index.ts";
8
8
 
9
9
  function PathProbe({ value }: { value: string }) {
10
10
  const path = useTreePath(value);
@@ -1,6 +1,6 @@
1
1
  import type { KeyboardEvent } from "react";
2
2
 
3
- import { useRovingTabindex } from "../../hooks";
3
+ import { useRovingTabindex } from "../../hooks/index.ts";
4
4
  import { useTreeContext } from "../TreeContext";
5
5
 
6
6
  type TreeItemKeyboardOptions = {
@@ -1,6 +1,6 @@
1
1
  import { useCallback, useId, useRef, useState } from "react";
2
2
 
3
- import { useCollection, useControllableState } from "../../hooks";
3
+ import { useCollection, useControllableState } from "../../hooks/index.ts";
4
4
 
5
5
  import type {
6
6
  SelectionMode,
package/src/Tree/index.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from "./Tree";
2
+ export * from "./types";
2
3
  export { useTreePath, useTreeSelectionPaths } from "./hooks/useTreePath";
3
- export type { TreePathSegment } from "./types";
package/src/Tree/types.ts CHANGED
@@ -1,24 +1,28 @@
1
1
  import type { ComponentProps, ReactNode } from "react";
2
2
 
3
- type TreeRootBaseProps = ComponentProps<"div"> & {
3
+ /** Mode-independent props shared by every `Tree.Root` variant. */
4
+ export type TreeRootBaseProps = ComponentProps<"div"> & {
4
5
  children: ReactNode;
5
6
  };
6
7
 
7
- type TreeRootUncontrolledExpansionProps = {
8
+ /** Uncontrolled expansion — initial expanded branches via `defaultExpandedValues`. */
9
+ export type TreeRootUncontrolledExpansionProps = {
8
10
  /** Branch values expanded on first render when uncontrolled. */
9
11
  defaultExpandedValues?: string[];
10
12
  expandedValues?: never;
11
13
  onExpandedChange?: (values: string[]) => void;
12
14
  };
13
15
 
14
- type TreeRootControlledExpansionProps = {
16
+ /** Controlled expansion — the expanded set is owned by the consumer. */
17
+ export type TreeRootControlledExpansionProps = {
15
18
  defaultExpandedValues?: never;
16
19
  /** The set of expanded branch values, owned by the consumer. */
17
20
  expandedValues: string[];
18
21
  onExpandedChange: (values: string[]) => void;
19
22
  };
20
23
 
21
- type TreeRootSingleUncontrolledSelectionProps = {
24
+ /** Single-selection mode, uncontrolled — initial value via `defaultSelectedValue`. */
25
+ export type TreeRootSingleUncontrolledSelectionProps = {
22
26
  selectionMode?: "single";
23
27
  /** The value selected on first render when uncontrolled. */
24
28
  defaultSelectedValue?: string | null;
@@ -29,7 +33,8 @@ type TreeRootSingleUncontrolledSelectionProps = {
29
33
  onSelectedValuesChange?: never;
30
34
  };
31
35
 
32
- type TreeRootSingleControlledSelectionProps = {
36
+ /** Single-selection mode, controlled — the selected value is owned by the consumer. */
37
+ export type TreeRootSingleControlledSelectionProps = {
33
38
  selectionMode?: "single";
34
39
  defaultSelectedValue?: never;
35
40
  /** The selected value, owned by the consumer. */
@@ -40,7 +45,8 @@ type TreeRootSingleControlledSelectionProps = {
40
45
  onSelectedValuesChange?: never;
41
46
  };
42
47
 
43
- type TreeRootMultipleUncontrolledSelectionProps = {
48
+ /** Multiple-selection mode, uncontrolled — initial values via `defaultSelectedValues`. */
49
+ export type TreeRootMultipleUncontrolledSelectionProps = {
44
50
  selectionMode: "multiple";
45
51
  /** The values selected on first render when uncontrolled. */
46
52
  defaultSelectedValues?: string[];
@@ -51,7 +57,8 @@ type TreeRootMultipleUncontrolledSelectionProps = {
51
57
  onSelectedValueChange?: never;
52
58
  };
53
59
 
54
- type TreeRootMultipleControlledSelectionProps = {
60
+ /** Multiple-selection mode, controlled — the selected values are owned by the consumer. */
61
+ export type TreeRootMultipleControlledSelectionProps = {
55
62
  selectionMode: "multiple";
56
63
  defaultSelectedValues?: never;
57
64
  /** The selected values, owned by the consumer. */
@@ -62,6 +69,12 @@ type TreeRootMultipleControlledSelectionProps = {
62
69
  onSelectedValueChange?: never;
63
70
  };
64
71
 
72
+ /**
73
+ * Props for `Tree.Root`. Combines the shared {@link TreeRootBaseProps} with
74
+ * one expansion arm (controlled / uncontrolled) and one selection arm
75
+ * (single / multiple, controlled / uncontrolled), so the relevant
76
+ * `value` / `defaultValue` / `onChange` shape is enforced per mode.
77
+ */
65
78
  export type TreeRootProps = TreeRootBaseProps &
66
79
  (TreeRootUncontrolledExpansionProps | TreeRootControlledExpansionProps) &
67
80
  (
@@ -71,6 +84,7 @@ export type TreeRootProps = TreeRootBaseProps &
71
84
  | TreeRootMultipleControlledSelectionProps
72
85
  );
73
86
 
87
+ /** Props for `Tree.Item` — a selectable, focusable leaf treeitem. */
74
88
  export type TreeItemProps = ComponentProps<"div"> & {
75
89
  /** Stable identifier for this item, unique within the tree. */
76
90
  value: string;
@@ -88,6 +102,7 @@ export type TreeItemProps = ComponentProps<"div"> & {
88
102
  children: ReactNode;
89
103
  };
90
104
 
105
+ /** Props for `Tree.Branch` — an expandable treeitem with nested children. */
91
106
  export type TreeBranchProps = Omit<ComponentProps<"div">, "ref"> & {
92
107
  /** Stable identifier for this branch, unique within the tree. */
93
108
  value: string;
@@ -106,12 +121,14 @@ export type TreeBranchProps = Omit<ComponentProps<"div">, "ref"> & {
106
121
  children: ReactNode;
107
122
  };
108
123
 
124
+ /** Props for `Tree.BranchControl` — the branch's selectable, toggling control row. */
109
125
  export type TreeBranchControlProps = ComponentProps<"div"> & {
110
126
  /** Render the control as the supplied child element instead of `<div>`. */
111
127
  asChild?: boolean;
112
128
  children: ReactNode;
113
129
  };
114
130
 
131
+ /** Props for `Tree.BranchContent` — the collapsible group of a branch's child nodes. */
115
132
  export type TreeBranchContentProps = ComponentProps<"div"> & {
116
133
  children: ReactNode;
117
134
  /**
@@ -122,6 +139,7 @@ export type TreeBranchContentProps = ComponentProps<"div"> & {
122
139
  forceMount?: boolean;
123
140
  };
124
141
 
142
+ /** Props for `Tree.BranchIndicator` — the expand/collapse affordance. */
125
143
  export type TreeBranchIndicatorProps = ComponentProps<"span"> & {
126
144
  /** Render as the supplied child element instead of `<span>`. */
127
145
  asChild?: boolean;
@@ -133,6 +151,10 @@ export type TreeSelectionPathRenderProps = {
133
151
  paths: TreePathSegment[][];
134
152
  };
135
153
 
154
+ /**
155
+ * Props for `Tree.SelectionPath` — a breadcrumb of the selected node's
156
+ * root-to-leaf ancestry, with an optional render-prop for custom layout.
157
+ */
136
158
  export type TreeSelectionPathProps = Omit<ComponentProps<"div">, "children"> & {
137
159
  /**
138
160
  * Either standard React children (ignored — the subcomponent does its
@@ -147,6 +169,7 @@ export type TreeSelectionPathProps = Omit<ComponentProps<"div">, "children"> & {
147
169
  separator?: ReactNode;
148
170
  };
149
171
 
172
+ /** Per-level context — the nesting depth and enclosing branch value, shared down each subtree. */
150
173
  export type TreeLevelContextValue = {
151
174
  /** Zero-based nesting depth — `0` for items directly inside `Tree.Root`. */
152
175
  depth: number;
@@ -154,6 +177,7 @@ export type TreeLevelContextValue = {
154
177
  parentValue: string | null;
155
178
  };
156
179
 
180
+ /** Registry entry for one tree node — its value, element, and structural metadata. */
157
181
  export type TreeNodeMeta = {
158
182
  value: string;
159
183
  element: HTMLElement;
@@ -177,14 +201,21 @@ export type TreePathSegment = {
177
201
  depth: number;
178
202
  };
179
203
 
204
+ /** Whether the tree allows one selected node (`"single"`) or many (`"multiple"`). */
180
205
  export type SelectionMode = "single" | "multiple";
181
206
 
207
+ /** Keyboard/pointer modifiers that influence a selection gesture. */
182
208
  export type TreeSelectModifiers = {
183
209
  meta: boolean;
184
210
  ctrl: boolean;
185
211
  shift: boolean;
186
212
  };
187
213
 
214
+ /**
215
+ * Context shared from `Tree.Root` to every descendant — selection and
216
+ * expansion state, the node registry, roving-tabindex bookkeeping, and the
217
+ * path resolver.
218
+ */
188
219
  export type TreeContextValue = {
189
220
  /** Stable id shared across the tree, used to derive ARIA wiring ids. */
190
221
  rootId: string;
@@ -215,6 +246,7 @@ export type TreeContextValue = {
215
246
  selectedOrder: readonly string[];
216
247
  };
217
248
 
249
+ /** Context a branch shares with its own control and content — its value, expanded/disabled state, and control id. */
218
250
  export type TreeItemContextValue = {
219
251
  value: string;
220
252
  expanded: boolean;
@@ -1,5 +1,6 @@
1
1
  import { CSSProperties } from "react";
2
- import { Slot } from "../Slot";
2
+ import type { ReactElement } from "react";
3
+ import { Slot } from "../Slot/index.ts";
3
4
  import { VisuallyHiddenProps } from "./types";
4
5
 
5
6
  const visuallyHiddenStyle: CSSProperties = {
@@ -51,7 +52,7 @@ export function VisuallyHidden({
51
52
  children,
52
53
  style,
53
54
  ...rest
54
- }: VisuallyHiddenProps) {
55
+ }: VisuallyHiddenProps): ReactElement {
55
56
  const rootProps = {
56
57
  ...rest,
57
58
  style: { ...visuallyHiddenStyle, ...style },
@@ -64,4 +65,5 @@ export function VisuallyHidden({
64
65
  return <span {...rootProps}>{children}</span>;
65
66
  }
66
67
 
68
+ /** @internal */
67
69
  VisuallyHidden.displayName = "VisuallyHidden";
@@ -1,4 +1,4 @@
1
- import { VisuallyHidden } from "..";
1
+ import { VisuallyHidden } from "../index.ts";
2
2
  import { render, screen } from "@testing-library/react";
3
3
 
4
4
  describe("VisuallyHidden component", () => {
@@ -1,5 +1,9 @@
1
1
  import { ComponentProps } from "react";
2
2
 
3
+ /**
4
+ * Props for {@link VisuallyHidden} — all native `<span>` attributes plus
5
+ * the `asChild` escape hatch.
6
+ */
3
7
  export type VisuallyHiddenProps = ComponentProps<"span"> & {
4
8
  asChild?: boolean;
5
9
  };
package/src/index.ts CHANGED
@@ -1,38 +1,39 @@
1
- export * from "./AccessibleIcon";
2
- export * from "./Accordion";
3
- export * from "./Alert";
4
- export * from "./Avatar";
5
- export * from "./Breadcrumb";
6
- export * from "./Button";
7
- export * from "./Carousel";
8
- export * from "./Checkbox";
9
- export * from "./CheckboxCard";
10
- export * from "./Collapsible";
11
- export * from "./ContextMenu";
12
- export * from "./DirectionProvider";
13
- export * from "./Divider";
14
- export * from "./Dropdown";
15
- export * from "./EmptyState";
16
- export * from "./Field";
17
- export * from "./Fieldset";
18
- export * from "./Input";
19
- export * from "./InputGroup";
20
- export * from "./MillerColumns";
21
- export * from "./Modal";
22
- export * from "./Portal";
23
- export * from "./Progress";
24
- export * from "./RadioCard";
25
- export * from "./RadioGroup";
26
- export * from "./Select";
27
- export * from "./SkipNav";
28
- export * from "./Slider";
29
- export * from "./Status";
30
- export * from "./Switch";
31
- export * from "./Table";
32
- export * from "./Tabs";
33
- export * from "./Textarea";
34
- export * from "./Toggle";
35
- export * from "./ToggleGroup";
36
- export * from "./Tooltip";
37
- export * from "./Tree";
38
- export * from "./VisuallyHidden";
1
+ export * from "./AccessibleIcon/index.ts";
2
+ export * from "./Accordion/index.ts";
3
+ export * from "./Alert/index.ts";
4
+ export * from "./Avatar/index.ts";
5
+ export * from "./Breadcrumb/index.ts";
6
+ export * from "./Button/index.ts";
7
+ export * from "./Carousel/index.ts";
8
+ export * from "./Checkbox/index.ts";
9
+ export * from "./CheckboxCard/index.ts";
10
+ export * from "./Collapsible/index.ts";
11
+ export * from "./ContextMenu/index.ts";
12
+ export * from "./DirectionProvider/index.ts";
13
+ export * from "./Divider/index.ts";
14
+ export * from "./Dropdown/index.ts";
15
+ export * from "./EmptyState/index.ts";
16
+ export * from "./Field/index.ts";
17
+ export * from "./Fieldset/index.ts";
18
+ export * from "./Input/index.ts";
19
+ export * from "./InputGroup/index.ts";
20
+ export * from "./MillerColumns/index.ts";
21
+ export * from "./Modal/index.ts";
22
+ export * from "./Portal/index.ts";
23
+ export * from "./Progress/index.ts";
24
+ export * from "./RadioCard/index.ts";
25
+ export * from "./RadioGroup/index.ts";
26
+ export * from "./Select/index.ts";
27
+ export * from "./SkipNav/index.ts";
28
+ export * from "./Slider/index.ts";
29
+ export * from "./Status/index.ts";
30
+ export * from "./Switch/index.ts";
31
+ export * from "./Table/index.ts";
32
+ export * from "./Tabs/index.ts";
33
+ export * from "./Textarea/index.ts";
34
+ export * from "./Toggle/index.ts";
35
+ export * from "./ToggleGroup/index.ts";
36
+ export * from "./Tooltip/index.ts";
37
+ export * from "./Tree/index.ts";
38
+ export * from "./VisuallyHidden/index.ts";
39
+ export type { HeadingLevel } from "./types.ts";
package/src/types.ts CHANGED
@@ -8,6 +8,7 @@ export type PossibleRef<T> = Ref<T> | undefined;
8
8
 
9
9
  export type AnyProps = Record<string, unknown>;
10
10
 
11
+ /** A heading level, `1`–`6`, mapped to an `<h1>`–`<h6>` element. */
11
12
  export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
12
13
 
13
14
  export type HeadingTag = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
@@ -20,11 +20,15 @@ import { createContext, useContext, type Context } from "react";
20
20
  * ```ts
21
21
  * type FooContextValue = { count: number };
22
22
  *
23
- * export const [FooContext, useFooContext] =
24
- * createStrictContext<FooContextValue>(
25
- * "Foo sub-components must be rendered inside <Foo.Root>.",
26
- * "FooContext",
27
- * );
23
+ * // JSR rejects array-destructured exports as a "slow type", so bind the
24
+ * // pair locally and re-export each half with an explicit type:
25
+ * const fooContext = createStrictContext<FooContextValue>(
26
+ * "Foo sub-components must be rendered inside <Foo.Root>.",
27
+ * "FooContext",
28
+ * );
29
+ *
30
+ * export const FooContext: Context<FooContextValue | null> = fooContext[0];
31
+ * export const useFooContext: () => FooContextValue = fooContext[1];
28
32
  * ```
29
33
  */
30
34
  export function createStrictContext<T>(