@itwin/itwinui-react 5.0.0-alpha.3 → 5.0.0-alpha.5

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.
@@ -4,17 +4,21 @@ import * as Ariakit from "@ariakit/react";
4
4
  import cx from "classnames";
5
5
  import { forwardRef } from "./~utils.js";
6
6
  const Field = forwardRef((props, forwardedRef) => {
7
- const fieldId = React.useId();
8
7
  const { layout, ...rest } = props;
9
- return /* @__PURE__ */ jsx(FieldIdContext.Provider, { value: fieldId, children: /* @__PURE__ */ jsx(FieldDescribedByProvider, { children: /* @__PURE__ */ jsx(
10
- Ariakit.Role,
8
+ return /* @__PURE__ */ jsx(FieldDescribedByProvider, { children: /* @__PURE__ */ jsx(
9
+ FieldCollection,
11
10
  {
12
- ...rest,
13
- className: cx("\u{1F95D}-field", props.className),
14
- "data-kiwi-layout": layout,
15
- ref: forwardedRef
11
+ render: /* @__PURE__ */ jsx(
12
+ Ariakit.Role.div,
13
+ {
14
+ ...rest,
15
+ className: cx("\u{1F95D}-field", props.className),
16
+ "data-kiwi-layout": layout,
17
+ ref: forwardedRef
18
+ }
19
+ )
16
20
  }
17
- ) }) });
21
+ ) });
18
22
  });
19
23
  const FieldDescribedByContext = React.createContext(void 0);
20
24
  function FieldDescribedByProvider(props) {
@@ -65,13 +69,78 @@ function useFieldRegisterDescribedBy(id) {
65
69
  return () => unregister(id);
66
70
  }, [id, register, unregister]);
67
71
  }
68
- const FieldIdContext = React.createContext(void 0);
69
- function useFieldId() {
70
- return React.useContext(FieldIdContext);
72
+ function FieldCollection(props) {
73
+ const fieldElementCollection = Ariakit.useCollectionStore({
74
+ defaultItems: []
75
+ });
76
+ const renderedItems = Ariakit.useStoreState(
77
+ fieldElementCollection,
78
+ "renderedItems"
79
+ );
80
+ const [controlType, controlIndex] = React.useMemo(() => {
81
+ const controlIndex2 = renderedItems.findIndex(
82
+ (item) => item.elementType === "control"
83
+ );
84
+ return [renderedItems[controlIndex2]?.controlType, controlIndex2];
85
+ }, [renderedItems]);
86
+ const labelPlacement = React.useMemo(() => {
87
+ const labelIndex = renderedItems.findIndex(
88
+ (item) => item.elementType === "label"
89
+ );
90
+ if (controlIndex === -1 || labelIndex === -1) return;
91
+ return labelIndex < controlIndex ? "before" : "after";
92
+ }, [renderedItems, controlIndex]);
93
+ return /* @__PURE__ */ jsx(
94
+ Ariakit.Collection,
95
+ {
96
+ ...props,
97
+ store: fieldElementCollection,
98
+ "data-kiwi-label-placement": labelPlacement,
99
+ "data-kiwi-control-type": controlType
100
+ }
101
+ );
102
+ }
103
+ function FieldControl(props) {
104
+ const generatedId = React.useId();
105
+ const { id = generatedId, type, ...rest } = props;
106
+ const getData = React.useCallback(
107
+ (data) => ({
108
+ ...data,
109
+ elementType: "control",
110
+ controlType: type
111
+ }),
112
+ [type]
113
+ );
114
+ return /* @__PURE__ */ jsx(Ariakit.CollectionItem, { ...rest, id, getItem: getData });
115
+ }
116
+ function FieldLabel(props) {
117
+ const store = Ariakit.useCollectionContext();
118
+ const renderedItems = Ariakit.useStoreState(store, "renderedItems");
119
+ const fieldId = React.useMemo(
120
+ () => renderedItems?.find(
121
+ (item) => item.elementType === "control"
122
+ )?.id,
123
+ [renderedItems]
124
+ );
125
+ const getData = React.useCallback(
126
+ (data) => ({
127
+ ...data,
128
+ elementType: "label"
129
+ }),
130
+ []
131
+ );
132
+ return /* @__PURE__ */ jsx(
133
+ Ariakit.CollectionItem,
134
+ {
135
+ getItem: getData,
136
+ render: /* @__PURE__ */ jsx(Ariakit.Role.label, { ...props, htmlFor: fieldId })
137
+ }
138
+ );
71
139
  }
72
140
  export {
73
141
  Field,
142
+ FieldControl,
143
+ FieldLabel,
74
144
  useFieldDescribedBy,
75
- useFieldId,
76
145
  useFieldRegisterDescribedBy
77
146
  };
@@ -35,4 +35,7 @@ export declare const DisclosureArrow: React.ForwardRefExoticComponent<Disclosure
35
35
  interface CheckmarkProps extends Omit<BaseProps<"svg">, "children"> {
36
36
  }
37
37
  export declare const Checkmark: React.ForwardRefExoticComponent<CheckmarkProps & React.RefAttributes<HTMLElement | SVGSVGElement>>;
38
+ interface DismissProps extends Omit<BaseProps<"svg">, "children"> {
39
+ }
40
+ export declare const Dismiss: React.ForwardRefExoticComponent<DismissProps & React.RefAttributes<HTMLElement | SVGSVGElement>>;
38
41
  export {};
@@ -83,8 +83,31 @@ const Checkmark = forwardRef(
83
83
  );
84
84
  }
85
85
  );
86
+ const Dismiss = forwardRef(
87
+ (props, forwardedRef) => {
88
+ return /* @__PURE__ */ jsx(
89
+ Icon,
90
+ {
91
+ ...props,
92
+ render: /* @__PURE__ */ jsx(
93
+ Ariakit.Role.svg,
94
+ {
95
+ width: "16",
96
+ height: "16",
97
+ viewBox: "0 0 16 16",
98
+ fill: "currentColor",
99
+ render: props.render,
100
+ children: /* @__PURE__ */ jsx("path", { d: "M4.853 4.146a.5.5 0 1 0-.707.708L7.293 8l-3.147 3.146a.5.5 0 0 0 .707.708L8 8.707l3.146 3.147a.5.5 0 0 0 .707-.708L8.707 8l3.146-3.146a.5.5 0 1 0-.707-.708L8 7.293 4.853 4.146Z" })
101
+ }
102
+ ),
103
+ ref: forwardedRef
104
+ }
105
+ );
106
+ }
107
+ );
86
108
  export {
87
109
  Checkmark,
88
110
  DisclosureArrow,
111
+ Dismiss,
89
112
  Icon
90
113
  };
@@ -1,17 +1,20 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import cx from "classnames";
3
3
  import * as Ariakit from "@ariakit/react";
4
- import { useFieldId } from "./Field.js";
5
4
  import { forwardRef } from "./~utils.js";
5
+ import { FieldLabel } from "./Field.js";
6
6
  const Label = forwardRef((props, forwardedRef) => {
7
- const fieldId = useFieldId();
8
7
  return /* @__PURE__ */ jsx(
9
- Ariakit.Role.label,
8
+ FieldLabel,
10
9
  {
11
- htmlFor: fieldId,
12
- ...props,
13
- className: cx("\u{1F95D}-label", props.className),
14
- ref: forwardedRef
10
+ render: /* @__PURE__ */ jsx(
11
+ Ariakit.Role.label,
12
+ {
13
+ ...props,
14
+ className: cx("\u{1F95D}-label", props.className),
15
+ ref: forwardedRef
16
+ }
17
+ )
15
18
  }
16
19
  );
17
20
  });
@@ -1,20 +1,26 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import cx from "classnames";
3
3
  import * as Ariakit from "@ariakit/react";
4
- import { useFieldDescribedBy, useFieldId } from "./Field.js";
4
+ import { FieldControl, useFieldDescribedBy } from "./Field.js";
5
5
  import { forwardRef } from "./~utils.js";
6
6
  const Radio = forwardRef((props, forwardedRef) => {
7
- const fieldId = useFieldId();
7
+ const { id, ...rest } = props;
8
8
  const describedBy = useFieldDescribedBy(props["aria-describedby"]);
9
9
  return /* @__PURE__ */ jsx(
10
- Ariakit.Radio,
10
+ FieldControl,
11
11
  {
12
- accessibleWhenDisabled: true,
13
- id: fieldId,
14
- ...props,
15
- className: cx("\u{1F95D}-checkbox", "\u{1F95D}-radio", props.className),
16
- "aria-describedby": describedBy,
17
- ref: forwardedRef
12
+ type: "checkable",
13
+ id,
14
+ render: /* @__PURE__ */ jsx(
15
+ Ariakit.Radio,
16
+ {
17
+ accessibleWhenDisabled: true,
18
+ ...rest,
19
+ className: cx("\u{1F95D}-checkbox", "\u{1F95D}-radio", props.className),
20
+ "aria-describedby": describedBy,
21
+ ref: forwardedRef
22
+ }
23
+ )
18
24
  }
19
25
  );
20
26
  });
@@ -7,7 +7,7 @@ import {
7
7
  isBrowser
8
8
  } from "./~utils.js";
9
9
  import { DisclosureArrow } from "./Icon.js";
10
- import { useFieldDescribedBy, useFieldId } from "./Field.js";
10
+ import { FieldControl, useFieldDescribedBy } from "./Field.js";
11
11
  const supportsHas = isBrowser && CSS?.supports?.("selector(:has(+ *))");
12
12
  const HtmlSelectContext = React.createContext(() => {
13
13
  });
@@ -25,9 +25,8 @@ const SelectRoot = forwardRef((props, forwardedRef) => {
25
25
  });
26
26
  const HtmlSelect = forwardRef(
27
27
  (props, forwardedRef) => {
28
- const { variant = "solid", ...rest } = props;
28
+ const { id, variant = "solid", ...rest } = props;
29
29
  const setIsHtmlSelect = React.useContext(HtmlSelectContext);
30
- const fieldId = useFieldId();
31
30
  const describedBy = useFieldDescribedBy(props["aria-describedby"]);
32
31
  React.useEffect(
33
32
  function updateContext() {
@@ -37,15 +36,21 @@ const HtmlSelect = forwardRef(
37
36
  );
38
37
  return /* @__PURE__ */ jsxs(Fragment, { children: [
39
38
  /* @__PURE__ */ jsx(
40
- Ariakit.Role.select,
39
+ FieldControl,
41
40
  {
42
- id: fieldId,
43
- ...rest,
44
- className: cx("\u{1F95D}-button", "\u{1F95D}-select", props.className),
45
- "aria-describedby": describedBy,
46
- "data-kiwi-tone": "neutral",
47
- "data-kiwi-variant": variant,
48
- ref: forwardedRef
41
+ type: "textlike",
42
+ id,
43
+ render: /* @__PURE__ */ jsx(
44
+ Ariakit.Role.select,
45
+ {
46
+ ...rest,
47
+ className: cx("\u{1F95D}-button", "\u{1F95D}-select", props.className),
48
+ "aria-describedby": describedBy,
49
+ "data-kiwi-tone": "neutral",
50
+ "data-kiwi-variant": variant,
51
+ ref: forwardedRef
52
+ }
53
+ )
49
54
  }
50
55
  ),
51
56
  /* @__PURE__ */ jsx(DisclosureArrow, { className: "\u{1F95D}-select-arrow" })
@@ -1,22 +1,28 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import cx from "classnames";
3
3
  import * as Ariakit from "@ariakit/react";
4
- import { useFieldDescribedBy, useFieldId } from "./Field.js";
4
+ import { FieldControl, useFieldDescribedBy } from "./Field.js";
5
5
  import { forwardRef } from "./~utils.js";
6
6
  const Switch = forwardRef(
7
7
  (props, forwardedRef) => {
8
- const fieldId = useFieldId();
8
+ const { id, ...rest } = props;
9
9
  const describedBy = useFieldDescribedBy(props["aria-describedby"]);
10
10
  return /* @__PURE__ */ jsx(
11
- Ariakit.Checkbox,
11
+ FieldControl,
12
12
  {
13
- accessibleWhenDisabled: true,
14
- id: fieldId,
15
- ...props,
16
- className: cx("\u{1F95D}-switch", props.className),
17
- "aria-describedby": describedBy,
18
- role: "switch",
19
- ref: forwardedRef
13
+ type: "checkable",
14
+ id,
15
+ render: /* @__PURE__ */ jsx(
16
+ Ariakit.Checkbox,
17
+ {
18
+ accessibleWhenDisabled: true,
19
+ ...rest,
20
+ className: cx("\u{1F95D}-switch", props.className),
21
+ "aria-describedby": describedBy,
22
+ role: "switch",
23
+ ref: forwardedRef
24
+ }
25
+ )
20
26
  }
21
27
  );
22
28
  }
@@ -2,59 +2,73 @@ import { jsx } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import * as Ariakit from "@ariakit/react";
4
4
  import cx from "classnames";
5
- import { useFieldDescribedBy, useFieldId } from "./Field.js";
5
+ import { FieldControl, useFieldDescribedBy } from "./Field.js";
6
6
  import { Icon } from "./Icon.js";
7
7
  import { useMergedRefs } from "./~hooks.js";
8
8
  import { forwardRef } from "./~utils.js";
9
9
  const TextBoxInput = forwardRef(
10
10
  (props, forwardedRef) => {
11
+ const { id, ...rest } = props;
11
12
  const describedBy = useFieldDescribedBy(props["aria-describedby"]);
12
- const fieldId = useFieldId();
13
13
  const rootContext = React.useContext(TextBoxRootContext);
14
14
  const setDisabled = rootContext?.setDisabled;
15
15
  React.useEffect(() => {
16
16
  setDisabled?.(props.disabled);
17
17
  }, [setDisabled, props.disabled]);
18
18
  return /* @__PURE__ */ jsx(
19
- Ariakit.Role.input,
19
+ FieldControl,
20
20
  {
21
- id: fieldId,
22
- ...props,
23
- "aria-describedby": describedBy,
24
- className: cx({ "\u{1F95D}-text-box": !rootContext }, props.className),
25
- placeholder: props.placeholder ?? " ",
21
+ type: "textlike",
22
+ id,
26
23
  render: /* @__PURE__ */ jsx(
27
- Ariakit.Focusable,
24
+ Ariakit.Role.input,
28
25
  {
29
- accessibleWhenDisabled: true,
30
- render: props.render || /* @__PURE__ */ jsx("input", {})
26
+ readOnly: props.disabled,
27
+ ...rest,
28
+ "aria-describedby": describedBy,
29
+ className: cx({ "\u{1F95D}-text-box": !rootContext }, props.className),
30
+ placeholder: props.placeholder ?? " ",
31
+ render: /* @__PURE__ */ jsx(
32
+ Ariakit.Focusable,
33
+ {
34
+ accessibleWhenDisabled: true,
35
+ render: props.render || /* @__PURE__ */ jsx("input", {})
36
+ }
37
+ ),
38
+ ref: useMergedRefs(rootContext?.inputRef, forwardedRef)
31
39
  }
32
- ),
33
- ref: useMergedRefs(rootContext?.inputRef, forwardedRef)
40
+ )
34
41
  }
35
42
  );
36
43
  }
37
44
  );
38
45
  const TextBoxTextarea = forwardRef(
39
46
  (props, forwardedRef) => {
40
- const fieldId = useFieldId();
47
+ const { id, ...rest } = props;
41
48
  const describedBy = useFieldDescribedBy(props["aria-describedby"]);
42
49
  return /* @__PURE__ */ jsx(
43
- Ariakit.Role.textarea,
50
+ FieldControl,
44
51
  {
45
- id: fieldId,
46
- ...props,
47
- className: cx("\u{1F95D}-text-box", props.className),
48
- "aria-describedby": describedBy,
49
- placeholder: props.placeholder ?? " ",
52
+ type: "textlike",
53
+ id,
50
54
  render: /* @__PURE__ */ jsx(
51
- Ariakit.Focusable,
55
+ Ariakit.Role.textarea,
52
56
  {
53
- accessibleWhenDisabled: true,
54
- render: props.render || /* @__PURE__ */ jsx("textarea", {})
57
+ readOnly: props.disabled,
58
+ ...rest,
59
+ className: cx("\u{1F95D}-text-box", props.className),
60
+ "aria-describedby": describedBy,
61
+ placeholder: props.placeholder ?? " ",
62
+ render: /* @__PURE__ */ jsx(
63
+ Ariakit.Focusable,
64
+ {
65
+ accessibleWhenDisabled: true,
66
+ render: props.render || /* @__PURE__ */ jsx("textarea", {})
67
+ }
68
+ ),
69
+ ref: forwardedRef
55
70
  }
56
- ),
57
- ref: forwardedRef
71
+ )
58
72
  }
59
73
  );
60
74
  }
@@ -1,27 +1,32 @@
1
1
  import * as React from "react";
2
+ import { IconButton } from "./IconButton.js";
2
3
  import { type BaseProps } from "./~utils.js";
3
4
  interface TreeProps extends BaseProps {
4
5
  }
5
6
  /**
6
7
  * A tree is a hierarchical list of items that can be expanded or collapsed, or optionally selected.
7
8
  *
8
- * `Tree.Root` is the root component for a tree. `Tree.Item`s can be nested inside a `Tree.Root` to create a hierarchical tree structure.
9
+ * `Tree.Root` is the root component for a tree. `Tree.Item`s are rendered as a flat list in the `Tree.Root` component to create a hierarchical tree structure.
9
10
  *
10
11
  * Example:
11
12
  * ```tsx
12
13
  * <Tree.Root>
13
- * <Tree.Item label="Parent 1">
14
- * <Tree.Item label="Child 1.1" />
15
- * <Tree.Item label="Child 1.2" />
16
- * </Tree.Item>
17
- * <Tree.Item label="Parent 2">
18
- * <Tree.Item label="Child 2.1" />
19
- * </Tree.Item>
14
+ * <Tree.Item label="Parent 1" aria-level={1} aria-posinset={1} aria-setsize={2} />
15
+ * <Tree.Item label="Child 1.1" aria-level={2} aria-posinset={1} aria-setsize={2} />
16
+ * <Tree.Item label="Child 1.2" aria-level={2} aria-posinset={2} aria-setsize={2} />
17
+ * <Tree.Item label="Parent 2" aria-level={1} aria-posinset={2} aria-setsize={2} />
18
+ * <Tree.Item label="Child 2.1" aria-level={2} aria-posinset={1} aria-setsize={1} />
20
19
  * </Tree.Root>
21
20
  * ```
22
21
  */
23
22
  declare const Tree: React.ForwardRefExoticComponent<TreeProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
24
23
  interface TreeItemProps extends Omit<BaseProps, "content"> {
24
+ /** Specifies the nesting level of the tree item. Nesting levels start at 1. */
25
+ "aria-level": number;
26
+ /** Defines tree item position in the current level of tree items. Integer greater than or equal to 1. */
27
+ "aria-posinset": number;
28
+ /** Defines tree item set size of the current level. */
29
+ "aria-setsize": number;
25
30
  /**
26
31
  * Specifies if the tree item is selected.
27
32
  *
@@ -56,31 +61,67 @@ interface TreeItemProps extends Omit<BaseProps, "content"> {
56
61
  * Can be a URL of an SVG from the `kiwi-icons` package, or a JSX element.
57
62
  */
58
63
  icon?: string | React.JSX.Element;
59
- /** The label to display for the tree item. */
64
+ /**
65
+ * The primary label that identifies the tree item and is displayed inside it.
66
+ */
60
67
  label?: React.ReactNode;
61
- /** The actions available for the tree item. */
62
- actions?: React.ReactNode;
68
+ /**
69
+ * The actions available for the tree item. Must be a list of `Tree.ItemAction` components.
70
+ *
71
+ * Example:
72
+ * ```tsx
73
+ * actions={[
74
+ * <Tree.ItemAction key={…} icon={…} label={…} />,
75
+ * <Tree.ItemAction key={…} icon={…} label={…} />,
76
+ * ]}
77
+ * ```
78
+ */
79
+ actions?: React.ReactNode[];
63
80
  }
64
81
  /**
65
82
  * A treeitem is a node in a tree structure that may be expanded or collapsed to reveal or hide its descendants.
66
83
  *
67
- * `Tree.Item`s can be nested as JSX elements inside a `Tree.Root` to create a hierarchical tree structure.
84
+ * `Tree.Item`s can be rendered inside a `Tree.Root`. Additional properties are specified to the `Tree.Item`s to create a hierarchical tree structure.
68
85
  *
69
86
  * Example:
70
87
  * ```tsx
71
88
  * <Tree.Root>
72
- * <Tree.Item label="Parent">
73
- * <Tree.Item label="Child 1" />
74
- * <Tree.Item label="Child 2" />
75
- * </Tree.Item>
89
+ * <Tree.Item label="Parent" aria-level={1} aria-posinset={1} aria-setsize={1} />
90
+ * <Tree.Item label="Child 1" aria-level={2} aria-posinset={1} aria-setsize={2} />
91
+ * <Tree.Item label="Child 2" aria-level={2} aria-posinset={2} aria-setsize={2} />
76
92
  * </Tree.Root>
77
93
  * ```
78
94
  *
79
- * The `label` and `icon` props can be used to specify the treeitem's own content. `children` is only used for nested items.
95
+ * The `label` and `icon` props can be used to specify the treeitem's own content.
96
+ *
97
+ * The `aria-level` prop is used to specify the nesting level of the treeitem. Nesting levels start at 1.
98
+ *
99
+ * The `aria-posinset` and `aria-setsize` props are used to define the treeitem's position in the current level of tree items.
80
100
  *
81
101
  * The `expanded` and `onExpandedChange` props can be used to control the expansion state of a treeitem.
82
102
  *
83
103
  * The `selected` and `onSelectedChange` props can be used to control the selection state of a treeitem.
104
+ *
105
+ * Secondary actions can be passed into the `actions` prop.
84
106
  */
85
107
  declare const TreeItem: React.ForwardRefExoticComponent<TreeItemProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
86
- export { Tree as Root, TreeItem as Item };
108
+ type IconButtonProps = React.ComponentProps<typeof IconButton>;
109
+ interface TreeItemActionProps extends BaseProps<"button">, Pick<IconButtonProps, "label" | "icon"> {
110
+ /**
111
+ * Controls the visibility of the action.
112
+ *
113
+ * If `true`, the action is always visible.
114
+ * If `false`, the action is hidden and becomes inaccessible, but still occupies space.
115
+ *
116
+ * By default, the action is shown only when the treeitem receives hover/focus.
117
+ */
118
+ visible?: boolean;
119
+ }
120
+ /**
121
+ * A secondary action for `<Tree.Item>`, to be passed into the `actions` prop. The action is typically
122
+ * displayed as an icon-button on the right end of the treeitem.
123
+ *
124
+ * By default, the action appears only on hover/focus. This can be controlled by the `visible` prop.
125
+ */
126
+ declare const TreeItemAction: React.ForwardRefExoticComponent<TreeItemActionProps & React.RefAttributes<HTMLElement | HTMLButtonElement>>;
127
+ export { Tree as Root, TreeItem as Item, TreeItemAction as ItemAction };
@@ -23,6 +23,7 @@ const Tree = forwardRef((props, forwardedRef) => {
23
23
  });
24
24
  const TreeItem = forwardRef((props, forwardedRef) => {
25
25
  const {
26
+ "aria-level": level,
26
27
  selected,
27
28
  children,
28
29
  expanded,
@@ -36,8 +37,6 @@ const TreeItem = forwardRef((props, forwardedRef) => {
36
37
  onKeyDown: onKeyDownProp,
37
38
  ...rest
38
39
  } = props;
39
- const parentContext = React.useContext(TreeItemContext);
40
- const level = parentContext ? parentContext.level + 1 : 1;
41
40
  const handleClick = (event) => {
42
41
  if (selected === void 0) return;
43
42
  event.stopPropagation();
@@ -66,7 +65,7 @@ const TreeItem = forwardRef((props, forwardedRef) => {
66
65
  }),
67
66
  [level, expanded, selected, contentId]
68
67
  ),
69
- children: /* @__PURE__ */ jsxs(
68
+ children: /* @__PURE__ */ jsx(
70
69
  Ariakit.CompositeItem,
71
70
  {
72
71
  render: /* @__PURE__ */ jsx(Ariakit.Role, { ...rest }),
@@ -82,35 +81,33 @@ const TreeItem = forwardRef((props, forwardedRef) => {
82
81
  "aria-expanded": expanded,
83
82
  "aria-selected": selected,
84
83
  "aria-labelledby": contentId,
84
+ "aria-level": level,
85
85
  className: cx("\u{1F95D}-tree-item", props.className),
86
86
  ref: forwardedRef,
87
- children: [
88
- /* @__PURE__ */ jsxs(
89
- ListItem.Root,
90
- {
91
- "data-kiwi-expanded": expanded,
92
- "data-kiwi-selected": selected,
93
- className: "\u{1F95D}-tree-item-node",
94
- style: { "--\u{1F95D}tree-item-level": level },
95
- role: void 0,
96
- children: [
97
- /* @__PURE__ */ jsx(
98
- TreeItemExpander,
99
- {
100
- onClick: () => {
101
- if (expanded === void 0) return;
102
- onExpandedChange?.(!expanded);
103
- }
87
+ children: /* @__PURE__ */ jsxs(
88
+ ListItem.Root,
89
+ {
90
+ "data-kiwi-expanded": expanded,
91
+ "data-kiwi-selected": selected,
92
+ className: "\u{1F95D}-tree-item-node",
93
+ style: { "--\u{1F95D}tree-item-level": level },
94
+ role: void 0,
95
+ children: [
96
+ /* @__PURE__ */ jsx(
97
+ TreeItemExpander,
98
+ {
99
+ onClick: () => {
100
+ if (expanded === void 0) return;
101
+ onExpandedChange?.(!expanded);
104
102
  }
105
- ),
106
- typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { href: icon }) : icon,
107
- /* @__PURE__ */ jsx(TreeItemContent, { label }),
108
- /* @__PURE__ */ jsx(TreeItemActions, { children: actions })
109
- ]
110
- }
111
- ),
112
- children && /* @__PURE__ */ jsx("div", { role: "group", children })
113
- ]
103
+ }
104
+ ),
105
+ typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { href: icon }) : icon,
106
+ /* @__PURE__ */ jsx(TreeItemContent, { label }),
107
+ /* @__PURE__ */ jsx(TreeItemActions, { children: actions })
108
+ ]
109
+ }
110
+ )
114
111
  }
115
112
  )
116
113
  }
@@ -132,18 +129,30 @@ const TreeItemContent = forwardRef(
132
129
  );
133
130
  }
134
131
  );
135
- const TreeItemActions = forwardRef(
132
+ const TreeItemActions = forwardRef((props, forwardedRef) => {
133
+ return /* @__PURE__ */ jsx(
134
+ Ariakit.Toolbar,
135
+ {
136
+ ...props,
137
+ onClick: useEventHandlers(props.onClick, (e) => e.stopPropagation()),
138
+ className: cx("\u{1F95D}-tree-item-actions", props.className),
139
+ ref: forwardedRef,
140
+ children: props.children
141
+ }
142
+ );
143
+ });
144
+ const TreeItemAction = forwardRef(
136
145
  (props, forwardedRef) => {
137
146
  const { visible, ...rest } = props;
138
147
  return /* @__PURE__ */ jsx(
139
- Ariakit.Toolbar,
148
+ IconButton,
140
149
  {
150
+ inert: visible === false ? true : void 0,
141
151
  ...rest,
142
- onClick: useEventHandlers(props.onClick, (e) => e.stopPropagation()),
143
- className: cx("\u{1F95D}-tree-item-actions", props.className),
152
+ variant: "ghost",
153
+ className: cx("\u{1F95D}-tree-item-action", props.className),
144
154
  "data-kiwi-visible": visible,
145
- ref: forwardedRef,
146
- children: props.children
155
+ ref: forwardedRef
147
156
  }
148
157
  );
149
158
  }
@@ -193,5 +202,6 @@ const TreeChevron = forwardRef(
193
202
  const TreeItemContext = React.createContext(void 0);
194
203
  export {
195
204
  TreeItem as Item,
205
+ TreeItemAction as ItemAction,
196
206
  Tree as Root
197
207
  };