@itwin/itwinui-react 5.0.0-alpha.4 → 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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.0.0-alpha.5
4
+
5
+ - **breaking**: `Tree` API has changed to require flat structure, with explicit ARIA props (see [#300](https://github.com/iTwin/kiwi/pull/300)). `<Tree.Item>` no longer allows passing `children`.
6
+ - **breaking**: `Tree.Item`s `action` prop now requires a list of `<Tree.ItemAction>` components (see [#355](https://github.com/iTwin/kiwi/pull/355) and [#362](https://github.com/iTwin/kiwi/pull/362)).
7
+ - **breaking**: Replaced `<Chip>` children with new `label` prop (see [#349](https://github.com/iTwin/kiwi/pull/349)).
8
+ - Added `<Tree.ItemAction>` component with `visible` prop for more granular control over action visibility.
9
+ - Updated the layout of `<Field>` so that `<Description>` is placed in the best spot according on the label position and control type.
10
+ - `<Field>` now considers the presence of explicit control `id`s when creating associations.
11
+
3
12
  ## 5.0.0-alpha.4
4
13
 
5
14
  - Added `onDismiss` prop and dismiss button to `<Chip>`.
@@ -1,21 +1,27 @@
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 Checkbox = 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}-checkbox", props.className),
17
- "aria-describedby": describedBy,
18
- 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}-checkbox", props.className),
21
+ "aria-describedby": describedBy,
22
+ ref: forwardedRef
23
+ }
24
+ )
19
25
  }
20
26
  );
21
27
  }
@@ -6,7 +6,7 @@ import { forwardRef } from "./~utils.js";
6
6
  import { IconButton } from "./IconButton.js";
7
7
  import { Dismiss } from "./Icon.js";
8
8
  const Chip = forwardRef((props, forwardedRef) => {
9
- const { variant = "solid", onDismiss, children, ...rest } = props;
9
+ const { variant = "solid", onDismiss, label, ...rest } = props;
10
10
  const baseId = React.useId();
11
11
  const labelId = `${baseId}-label`;
12
12
  const dismissIconId = `${baseId}-dismiss`;
@@ -18,7 +18,7 @@ const Chip = forwardRef((props, forwardedRef) => {
18
18
  className: cx("\u{1F95D}-chip", props.className),
19
19
  ref: forwardedRef,
20
20
  children: [
21
- /* @__PURE__ */ jsx("span", { id: labelId, children }),
21
+ /* @__PURE__ */ jsx("span", { id: labelId, children: label }),
22
22
  onDismiss && /* @__PURE__ */ jsx(
23
23
  IconButton,
24
24
  {
@@ -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
  DEV: Field.displayName = "Field";
20
24
  const FieldDescribedByContext = React.createContext(void 0);
@@ -66,13 +70,78 @@ function useFieldRegisterDescribedBy(id) {
66
70
  return () => unregister(id);
67
71
  }, [id, register, unregister]);
68
72
  }
69
- const FieldIdContext = React.createContext(void 0);
70
- function useFieldId() {
71
- return React.useContext(FieldIdContext);
73
+ function FieldCollection(props) {
74
+ const fieldElementCollection = Ariakit.useCollectionStore({
75
+ defaultItems: []
76
+ });
77
+ const renderedItems = Ariakit.useStoreState(
78
+ fieldElementCollection,
79
+ "renderedItems"
80
+ );
81
+ const [controlType, controlIndex] = React.useMemo(() => {
82
+ const controlIndex2 = renderedItems.findIndex(
83
+ (item) => item.elementType === "control"
84
+ );
85
+ return [renderedItems[controlIndex2]?.controlType, controlIndex2];
86
+ }, [renderedItems]);
87
+ const labelPlacement = React.useMemo(() => {
88
+ const labelIndex = renderedItems.findIndex(
89
+ (item) => item.elementType === "label"
90
+ );
91
+ if (controlIndex === -1 || labelIndex === -1) return;
92
+ return labelIndex < controlIndex ? "before" : "after";
93
+ }, [renderedItems, controlIndex]);
94
+ return /* @__PURE__ */ jsx(
95
+ Ariakit.Collection,
96
+ {
97
+ ...props,
98
+ store: fieldElementCollection,
99
+ "data-kiwi-label-placement": labelPlacement,
100
+ "data-kiwi-control-type": controlType
101
+ }
102
+ );
103
+ }
104
+ function FieldControl(props) {
105
+ const generatedId = React.useId();
106
+ const { id = generatedId, type, ...rest } = props;
107
+ const getData = React.useCallback(
108
+ (data) => ({
109
+ ...data,
110
+ elementType: "control",
111
+ controlType: type
112
+ }),
113
+ [type]
114
+ );
115
+ return /* @__PURE__ */ jsx(Ariakit.CollectionItem, { ...rest, id, getItem: getData });
116
+ }
117
+ function FieldLabel(props) {
118
+ const store = Ariakit.useCollectionContext();
119
+ const renderedItems = Ariakit.useStoreState(store, "renderedItems");
120
+ const fieldId = React.useMemo(
121
+ () => renderedItems?.find(
122
+ (item) => item.elementType === "control"
123
+ )?.id,
124
+ [renderedItems]
125
+ );
126
+ const getData = React.useCallback(
127
+ (data) => ({
128
+ ...data,
129
+ elementType: "label"
130
+ }),
131
+ []
132
+ );
133
+ return /* @__PURE__ */ jsx(
134
+ Ariakit.CollectionItem,
135
+ {
136
+ getItem: getData,
137
+ render: /* @__PURE__ */ jsx(Ariakit.Role.label, { ...props, htmlFor: fieldId })
138
+ }
139
+ );
72
140
  }
73
141
  export {
74
142
  Field,
143
+ FieldControl,
144
+ FieldLabel,
75
145
  useFieldDescribedBy,
76
- useFieldId,
77
146
  useFieldRegisterDescribedBy
78
147
  };
@@ -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,36 +2,42 @@ 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
- readOnly: props.disabled,
23
- ...props,
24
- "aria-describedby": describedBy,
25
- className: cx({ "\u{1F95D}-text-box": !rootContext }, props.className),
26
- placeholder: props.placeholder ?? " ",
21
+ type: "textlike",
22
+ id,
27
23
  render: /* @__PURE__ */ jsx(
28
- Ariakit.Focusable,
24
+ Ariakit.Role.input,
29
25
  {
30
- accessibleWhenDisabled: true,
31
- 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)
32
39
  }
33
- ),
34
- ref: useMergedRefs(rootContext?.inputRef, forwardedRef)
40
+ )
35
41
  }
36
42
  );
37
43
  }
@@ -39,25 +45,31 @@ const TextBoxInput = forwardRef(
39
45
  DEV: TextBoxInput.displayName = "TextBox.Input";
40
46
  const TextBoxTextarea = forwardRef(
41
47
  (props, forwardedRef) => {
42
- const fieldId = useFieldId();
48
+ const { id, ...rest } = props;
43
49
  const describedBy = useFieldDescribedBy(props["aria-describedby"]);
44
50
  return /* @__PURE__ */ jsx(
45
- Ariakit.Role.textarea,
51
+ FieldControl,
46
52
  {
47
- id: fieldId,
48
- readOnly: props.disabled,
49
- ...props,
50
- className: cx("\u{1F95D}-text-box", props.className),
51
- "aria-describedby": describedBy,
52
- placeholder: props.placeholder ?? " ",
53
+ type: "textlike",
54
+ id,
53
55
  render: /* @__PURE__ */ jsx(
54
- Ariakit.Focusable,
56
+ Ariakit.Role.textarea,
55
57
  {
56
- accessibleWhenDisabled: true,
57
- render: props.render || /* @__PURE__ */ jsx("textarea", {})
58
+ readOnly: props.disabled,
59
+ ...rest,
60
+ className: cx("\u{1F95D}-text-box", props.className),
61
+ "aria-describedby": describedBy,
62
+ placeholder: props.placeholder ?? " ",
63
+ render: /* @__PURE__ */ jsx(
64
+ Ariakit.Focusable,
65
+ {
66
+ accessibleWhenDisabled: true,
67
+ render: props.render || /* @__PURE__ */ jsx("textarea", {})
68
+ }
69
+ ),
70
+ ref: forwardedRef
58
71
  }
59
- ),
60
- ref: forwardedRef
72
+ )
61
73
  }
62
74
  );
63
75
  }
@@ -24,6 +24,7 @@ const Tree = forwardRef((props, forwardedRef) => {
24
24
  DEV: Tree.displayName = "Tree.Root";
25
25
  const TreeItem = forwardRef((props, forwardedRef) => {
26
26
  const {
27
+ "aria-level": level,
27
28
  selected,
28
29
  children,
29
30
  expanded,
@@ -37,8 +38,6 @@ const TreeItem = forwardRef((props, forwardedRef) => {
37
38
  onKeyDown: onKeyDownProp,
38
39
  ...rest
39
40
  } = props;
40
- const parentContext = React.useContext(TreeItemContext);
41
- const level = parentContext ? parentContext.level + 1 : 1;
42
41
  const handleClick = (event) => {
43
42
  if (selected === void 0) return;
44
43
  event.stopPropagation();
@@ -67,7 +66,7 @@ const TreeItem = forwardRef((props, forwardedRef) => {
67
66
  }),
68
67
  [level, expanded, selected, contentId]
69
68
  ),
70
- children: /* @__PURE__ */ jsxs(
69
+ children: /* @__PURE__ */ jsx(
71
70
  Ariakit.CompositeItem,
72
71
  {
73
72
  render: /* @__PURE__ */ jsx(Ariakit.Role, { ...rest }),
@@ -83,35 +82,33 @@ const TreeItem = forwardRef((props, forwardedRef) => {
83
82
  "aria-expanded": expanded,
84
83
  "aria-selected": selected,
85
84
  "aria-labelledby": contentId,
85
+ "aria-level": level,
86
86
  className: cx("\u{1F95D}-tree-item", props.className),
87
87
  ref: forwardedRef,
88
- children: [
89
- /* @__PURE__ */ jsxs(
90
- ListItem.Root,
91
- {
92
- "data-kiwi-expanded": expanded,
93
- "data-kiwi-selected": selected,
94
- className: "\u{1F95D}-tree-item-node",
95
- style: { "--\u{1F95D}tree-item-level": level },
96
- role: void 0,
97
- children: [
98
- /* @__PURE__ */ jsx(
99
- TreeItemExpander,
100
- {
101
- onClick: () => {
102
- if (expanded === void 0) return;
103
- onExpandedChange?.(!expanded);
104
- }
88
+ children: /* @__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);
105
103
  }
106
- ),
107
- typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { href: icon }) : icon,
108
- /* @__PURE__ */ jsx(TreeItemContent, { label }),
109
- /* @__PURE__ */ jsx(TreeItemActions, { children: actions })
110
- ]
111
- }
112
- ),
113
- children && /* @__PURE__ */ jsx("div", { role: "group", children })
114
- ]
104
+ }
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
+ )
115
112
  }
116
113
  )
117
114
  }
@@ -135,23 +132,36 @@ const TreeItemContent = forwardRef(
135
132
  }
136
133
  );
137
134
  DEV: TreeItemContent.displayName = "TreeItemContent";
138
- const TreeItemActions = forwardRef(
135
+ const TreeItemActions = forwardRef((props, forwardedRef) => {
136
+ return /* @__PURE__ */ jsx(
137
+ Ariakit.Toolbar,
138
+ {
139
+ ...props,
140
+ onClick: useEventHandlers(props.onClick, (e) => e.stopPropagation()),
141
+ className: cx("\u{1F95D}-tree-item-actions", props.className),
142
+ ref: forwardedRef,
143
+ children: props.children
144
+ }
145
+ );
146
+ });
147
+ DEV: TreeItemActions.displayName = "TreeItemActions";
148
+ const TreeItemAction = forwardRef(
139
149
  (props, forwardedRef) => {
140
150
  const { visible, ...rest } = props;
141
151
  return /* @__PURE__ */ jsx(
142
- Ariakit.Toolbar,
152
+ IconButton,
143
153
  {
154
+ inert: visible === false ? true : void 0,
144
155
  ...rest,
145
- onClick: useEventHandlers(props.onClick, (e) => e.stopPropagation()),
146
- className: cx("\u{1F95D}-tree-item-actions", props.className),
156
+ variant: "ghost",
157
+ className: cx("\u{1F95D}-tree-item-action", props.className),
147
158
  "data-kiwi-visible": visible,
148
- ref: forwardedRef,
149
- children: props.children
159
+ ref: forwardedRef
150
160
  }
151
161
  );
152
162
  }
153
163
  );
154
- DEV: TreeItemActions.displayName = "TreeItemActions";
164
+ DEV: TreeItemAction.displayName = "Tree.ItemAction";
155
165
  const TreeItemExpander = forwardRef(
156
166
  (props, forwardedRef) => {
157
167
  return /* @__PURE__ */ jsx(
@@ -199,5 +209,6 @@ DEV: TreeChevron.displayName = "TreeChevron";
199
209
  const TreeItemContext = React.createContext(void 0);
200
210
  export {
201
211
  TreeItem as Item,
212
+ TreeItemAction as ItemAction,
202
213
  Tree as Root
203
214
  };