@itwin/itwinui-react 5.0.0-alpha.11 → 5.0.0-alpha.13

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 (65) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +13 -2
  3. package/dist/DEV/bricks/Checkbox.js +7 -14
  4. package/dist/DEV/bricks/Description.js +7 -14
  5. package/dist/DEV/bricks/DropdownMenu.js +68 -21
  6. package/dist/DEV/bricks/ErrorRegion.js +137 -0
  7. package/dist/DEV/bricks/Field.internal.js +47 -0
  8. package/dist/DEV/bricks/Field.js +120 -85
  9. package/dist/DEV/bricks/Icon.js +57 -0
  10. package/dist/DEV/bricks/IconButton.js +2 -5
  11. package/dist/DEV/bricks/Label.js +4 -10
  12. package/dist/DEV/bricks/Radio.js +7 -14
  13. package/dist/DEV/bricks/Select.js +9 -15
  14. package/dist/DEV/bricks/Switch.js +8 -15
  15. package/dist/DEV/bricks/Table.js +71 -37
  16. package/dist/DEV/bricks/Tabs.js +4 -29
  17. package/dist/DEV/bricks/TextBox.js +23 -37
  18. package/dist/DEV/bricks/Toolbar.js +25 -0
  19. package/dist/DEV/bricks/TreeItem.js +114 -42
  20. package/dist/DEV/bricks/index.js +9 -3
  21. package/dist/DEV/bricks/styles.css.js +1 -1
  22. package/dist/DEV/bricks/~utils.Dot.js +22 -0
  23. package/dist/DEV/foundations/styles.css.js +1 -1
  24. package/dist/bricks/Checkbox.d.ts +13 -5
  25. package/dist/bricks/Checkbox.js +7 -14
  26. package/dist/bricks/Description.d.ts +2 -6
  27. package/dist/bricks/Description.js +7 -14
  28. package/dist/bricks/DropdownMenu.d.ts +11 -9
  29. package/dist/bricks/DropdownMenu.js +67 -20
  30. package/dist/bricks/ErrorRegion.d.ts +88 -0
  31. package/dist/bricks/ErrorRegion.js +135 -0
  32. package/dist/bricks/Field.d.ts +69 -27
  33. package/dist/bricks/Field.internal.d.ts +33 -0
  34. package/dist/bricks/Field.internal.js +47 -0
  35. package/dist/bricks/Field.js +115 -84
  36. package/dist/bricks/Icon.d.ts +6 -0
  37. package/dist/bricks/Icon.js +55 -0
  38. package/dist/bricks/IconButton.js +2 -5
  39. package/dist/bricks/Label.d.ts +5 -12
  40. package/dist/bricks/Label.js +4 -10
  41. package/dist/bricks/ProgressBar.d.ts +7 -1
  42. package/dist/bricks/Radio.d.ts +14 -5
  43. package/dist/bricks/Radio.js +7 -14
  44. package/dist/bricks/Select.d.ts +29 -12
  45. package/dist/bricks/Select.js +9 -15
  46. package/dist/bricks/Switch.d.ts +12 -5
  47. package/dist/bricks/Switch.js +8 -15
  48. package/dist/bricks/Table.d.ts +94 -37
  49. package/dist/bricks/Table.js +69 -36
  50. package/dist/bricks/Tabs.d.ts +3 -4
  51. package/dist/bricks/Tabs.js +4 -29
  52. package/dist/bricks/TextBox.d.ts +42 -19
  53. package/dist/bricks/TextBox.js +23 -37
  54. package/dist/bricks/Toolbar.d.ts +35 -0
  55. package/dist/bricks/Toolbar.js +23 -0
  56. package/dist/bricks/TreeItem.d.ts +63 -9
  57. package/dist/bricks/TreeItem.js +103 -41
  58. package/dist/bricks/index.d.ts +5 -2
  59. package/dist/bricks/index.js +9 -3
  60. package/dist/bricks/styles.css.js +1 -1
  61. package/dist/bricks/~hooks.d.ts +1 -1
  62. package/dist/bricks/~utils.Dot.d.ts +11 -0
  63. package/dist/bricks/~utils.Dot.js +21 -0
  64. package/dist/foundations/styles.css.js +1 -1
  65. package/package.json +1 -1
@@ -1,41 +1,21 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import * as React from "react";
3
- import * as ReactDOM from "react-dom";
4
2
  import cx from "classnames";
5
3
  import * as AkTab from "@ariakit/react/tab";
6
- import { useControlledState } from "./~hooks.js";
7
4
  import { forwardRef } from "./~utils.js";
8
5
  function Tabs(props) {
9
6
  const {
10
7
  defaultSelectedId,
11
- selectedId: selectedIdProp,
12
- setSelectedId: setSelectedIdProp,
8
+ selectedId,
9
+ setSelectedId,
13
10
  selectOnMove,
14
11
  children
15
12
  } = props;
16
- const [selectedId, setSelectedId] = useControlledState(
17
- defaultSelectedId,
18
- selectedIdProp,
19
- setSelectedIdProp
20
- );
21
13
  return /* @__PURE__ */ jsx(
22
14
  AkTab.TabProvider,
23
15
  {
16
+ defaultSelectedId,
24
17
  selectedId,
25
- setSelectedId: React.useCallback(
26
- (id) => {
27
- if (document.startViewTransition) {
28
- document.startViewTransition(() => {
29
- ReactDOM.flushSync(() => {
30
- setSelectedId(id);
31
- });
32
- });
33
- } else {
34
- setSelectedId(id);
35
- }
36
- },
37
- [setSelectedId]
38
- ),
18
+ setSelectedId,
39
19
  selectOnMove,
40
20
  children
41
21
  }
@@ -44,17 +24,12 @@ function Tabs(props) {
44
24
  DEV: Tabs.displayName = "Tabs.Root";
45
25
  const TabList = forwardRef((props, forwardedRef) => {
46
26
  const { tone = "neutral", ...rest } = props;
47
- const viewTransitionName = `\u{1F95D}active-stripe-${React.useId().replaceAll(":", "_")}`;
48
27
  return /* @__PURE__ */ jsx(
49
28
  AkTab.TabList,
50
29
  {
51
30
  ...rest,
52
31
  "data-kiwi-tone": tone,
53
32
  className: cx("\u{1F95D}-tab-list", props.className),
54
- style: {
55
- "--\u{1F95D}tab-active-stripe-view-transition-name": viewTransitionName,
56
- ...props.style
57
- },
58
33
  ref: forwardedRef
59
34
  }
60
35
  );
@@ -3,40 +3,33 @@ import * as React from "react";
3
3
  import { Role } from "@ariakit/react/role";
4
4
  import { Focusable } from "@ariakit/react/focusable";
5
5
  import cx from "classnames";
6
- import { FieldControl } from "./Field.js";
7
6
  import { Icon } from "./Icon.js";
8
7
  import { useMergedRefs } from "./~hooks.js";
9
8
  import { forwardRef } from "./~utils.js";
9
+ import { useFieldControlType } from "./Field.internal.js";
10
10
  const TextBoxInput = forwardRef(
11
11
  (props, forwardedRef) => {
12
- const { id, ...rest } = props;
12
+ useFieldControlType("textlike");
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
- FieldControl,
19
+ Role.input,
20
20
  {
21
- type: "textlike",
22
- id,
21
+ readOnly: props.disabled,
22
+ ...props,
23
+ className: cx({ "\u{1F95D}-text-box": !rootContext }, props.className),
24
+ placeholder: props.placeholder ?? " ",
23
25
  render: /* @__PURE__ */ jsx(
24
- Role.input,
26
+ Focusable,
25
27
  {
26
- readOnly: props.disabled,
27
- ...rest,
28
- className: cx({ "\u{1F95D}-text-box": !rootContext }, props.className),
29
- placeholder: props.placeholder ?? " ",
30
- render: /* @__PURE__ */ jsx(
31
- Focusable,
32
- {
33
- accessibleWhenDisabled: true,
34
- render: props.render || /* @__PURE__ */ jsx("input", {})
35
- }
36
- ),
37
- ref: useMergedRefs(rootContext?.inputRef, forwardedRef)
28
+ accessibleWhenDisabled: true,
29
+ render: props.render || /* @__PURE__ */ jsx("input", {})
38
30
  }
39
- )
31
+ ),
32
+ ref: useMergedRefs(rootContext?.inputRef, forwardedRef)
40
33
  }
41
34
  );
42
35
  }
@@ -44,29 +37,22 @@ const TextBoxInput = forwardRef(
44
37
  DEV: TextBoxInput.displayName = "TextBox.Input";
45
38
  const TextBoxTextarea = forwardRef(
46
39
  (props, forwardedRef) => {
47
- const { id, ...rest } = props;
40
+ useFieldControlType("textlike");
48
41
  return /* @__PURE__ */ jsx(
49
- FieldControl,
42
+ Role.textarea,
50
43
  {
51
- type: "textlike",
52
- id,
44
+ readOnly: props.disabled,
45
+ ...props,
46
+ className: cx("\u{1F95D}-text-box", props.className),
47
+ placeholder: props.placeholder ?? " ",
53
48
  render: /* @__PURE__ */ jsx(
54
- Role.textarea,
49
+ Focusable,
55
50
  {
56
- readOnly: props.disabled,
57
- ...rest,
58
- className: cx("\u{1F95D}-text-box", props.className),
59
- placeholder: props.placeholder ?? " ",
60
- render: /* @__PURE__ */ jsx(
61
- Focusable,
62
- {
63
- accessibleWhenDisabled: true,
64
- render: props.render || /* @__PURE__ */ jsx("textarea", {})
65
- }
66
- ),
67
- ref: forwardedRef
51
+ accessibleWhenDisabled: true,
52
+ render: props.render || /* @__PURE__ */ jsx("textarea", {})
68
53
  }
69
- )
54
+ ),
55
+ ref: forwardedRef
70
56
  }
71
57
  );
72
58
  }
@@ -0,0 +1,25 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import cx from "classnames";
3
+ import * as Toolbar from "@ariakit/react/toolbar";
4
+ import { forwardRef } from "./~utils.js";
5
+ const ToolbarGroup = forwardRef((props, forwardedRef) => {
6
+ return /* @__PURE__ */ jsx(
7
+ Toolbar.Toolbar,
8
+ {
9
+ ...props,
10
+ className: cx("\u{1F95D}-toolbar", props.className),
11
+ ref: forwardedRef
12
+ }
13
+ );
14
+ });
15
+ DEV: ToolbarGroup.displayName = "Toolbar.Group";
16
+ const ToolbarItem = forwardRef(
17
+ (props, forwardedRef) => {
18
+ return /* @__PURE__ */ jsx(Toolbar.ToolbarItem, { ...props, ref: forwardedRef });
19
+ }
20
+ );
21
+ DEV: ToolbarItem.displayName = "Toolbar.Item";
22
+ export {
23
+ ToolbarGroup as Group,
24
+ ToolbarItem as Item
25
+ };
@@ -2,15 +2,17 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import cx from "classnames";
4
4
  import { Role } from "@ariakit/react/role";
5
+ import { PopoverProvider } from "@ariakit/react/popover";
5
6
  import {
6
7
  CompositeItem
7
8
  } from "@ariakit/react/composite";
8
- import { Toolbar } from "@ariakit/react/toolbar";
9
+ import { Toolbar, ToolbarItem } from "@ariakit/react/toolbar";
9
10
  import * as ListItem from "./~utils.ListItem.js";
10
11
  import { IconButton } from "./IconButton.js";
11
- import { Icon, StatusWarning } from "./Icon.js";
12
+ import * as DropdownMenu from "./DropdownMenu.js";
13
+ import { ChevronDown, Icon, StatusWarning, MoreHorizontal } from "./Icon.js";
12
14
  import { forwardRef } from "./~utils.js";
13
- import { useEventHandlers } from "./~hooks.js";
15
+ import { useEventHandlers, useSafeContext } from "./~hooks.js";
14
16
  import { GhostAligner, useGhostAlignment } from "./~utils.GhostAligner.js";
15
17
  const TreeItemContext = React.createContext(void 0);
16
18
  const TreeItemRoot = forwardRef(
@@ -49,13 +51,22 @@ const TreeItemRoot = forwardRef(
49
51
  const labelId = React.useId();
50
52
  const descriptionId = React.useId();
51
53
  const decorationId = React.useId();
54
+ const errorId = typeof error === "string" ? error : void 0;
52
55
  const icon = error ? /* @__PURE__ */ jsx(StatusWarning, {}) : iconProp;
53
56
  const describedBy = React.useMemo(() => {
54
57
  const idRefs = [];
55
58
  if (description) idRefs.push(descriptionId);
56
59
  if (unstable_decorations || icon) idRefs.push(decorationId);
60
+ if (errorId) idRefs.push(errorId);
57
61
  return idRefs.length > 0 ? idRefs.join(" ") : void 0;
58
- }, [unstable_decorations, icon, decorationId, description, descriptionId]);
62
+ }, [
63
+ unstable_decorations,
64
+ icon,
65
+ decorationId,
66
+ description,
67
+ descriptionId,
68
+ errorId
69
+ ]);
59
70
  return /* @__PURE__ */ jsx(
60
71
  TreeItemContext.Provider,
61
72
  {
@@ -63,9 +74,10 @@ const TreeItemRoot = forwardRef(
63
74
  () => ({
64
75
  level,
65
76
  expanded,
66
- selected
77
+ selected,
78
+ error
67
79
  }),
68
- [level, expanded, selected]
80
+ [level, expanded, selected, error]
69
81
  ),
70
82
  children: /* @__PURE__ */ jsx(
71
83
  CompositeItem,
@@ -143,31 +155,115 @@ const TreeItemRoot = forwardRef(
143
155
  );
144
156
  DEV: TreeItemRoot.displayName = "TreeItem.Root";
145
157
  const TreeItemActions = forwardRef((props, forwardedRef) => {
146
- return /* @__PURE__ */ jsx(
158
+ const { children, ...rest } = props;
159
+ const actions = React.Children.toArray(children).filter(Boolean);
160
+ const { error } = useSafeContext(TreeItemContext);
161
+ const limit = error ? 2 : 3;
162
+ return /* @__PURE__ */ jsxs(
147
163
  Toolbar,
148
164
  {
149
- ...props,
165
+ ...rest,
150
166
  onClick: useEventHandlers(props.onClick, (e) => e.stopPropagation()),
151
167
  onKeyDown: useEventHandlers(props.onKeyDown, (e) => e.stopPropagation()),
152
168
  className: cx("\u{1F95D}-tree-item-actions-container", props.className),
169
+ focusLoop: false,
153
170
  ref: forwardedRef,
154
- children: props.children
171
+ children: [
172
+ actions.slice(0, limit - 1),
173
+ actions.length === limit ? actions[limit - 1] : null,
174
+ actions.length > limit ? /* @__PURE__ */ jsx(TreeItemActionsOverflowMenu, { children: actions.slice(limit - 1) }) : null
175
+ ]
155
176
  }
156
177
  );
157
178
  });
158
179
  DEV: TreeItemActions.displayName = "TreeItemActions";
180
+ const arrowKeys = ["ArrowDown", "ArrowUp", "ArrowLeft", "ArrowRight"];
181
+ const TreeItemActionsOverflowMenuContext = React.createContext(false);
182
+ function TreeItemActionsOverflowMenu({ children }) {
183
+ const [open, setOpen] = React.useState(false);
184
+ const isArrowKeyPressed = React.useRef(false);
185
+ return /* @__PURE__ */ jsx(PopoverProvider, { placement: "right-start", children: /* @__PURE__ */ jsxs(
186
+ DropdownMenu.Root,
187
+ {
188
+ open,
189
+ setOpen: React.useCallback((value) => {
190
+ if (value && !isArrowKeyPressed.current) {
191
+ setOpen(true);
192
+ } else {
193
+ setOpen(false);
194
+ }
195
+ }, []),
196
+ children: [
197
+ /* @__PURE__ */ jsx(
198
+ DropdownMenu.Button,
199
+ {
200
+ onKeyDown: (e) => {
201
+ if (arrowKeys.includes(e.key)) {
202
+ isArrowKeyPressed.current = true;
203
+ }
204
+ queueMicrotask(() => {
205
+ isArrowKeyPressed.current = false;
206
+ });
207
+ },
208
+ render: /* @__PURE__ */ jsx(TreeItemAction, { label: "More", icon: /* @__PURE__ */ jsx(MoreHorizontal, {}) })
209
+ }
210
+ ),
211
+ /* @__PURE__ */ jsx(TreeItemActionsOverflowMenuContext.Provider, { value: true, children: /* @__PURE__ */ jsx(DropdownMenu.Content, { children }) })
212
+ ]
213
+ }
214
+ ) });
215
+ }
216
+ DEV: TreeItemActionsOverflowMenu.displayName = "TreeItemActionsOverflowMenu";
159
217
  const TreeItemAction = forwardRef(
160
218
  (props, forwardedRef) => {
161
- const { visible, ...rest } = props;
219
+ const { error } = useSafeContext(TreeItemContext);
220
+ const {
221
+ visible = error ? true : void 0,
222
+ // visible by default during error state
223
+ label,
224
+ icon,
225
+ dot,
226
+ ...rest
227
+ } = props;
228
+ if (React.useContext(TreeItemActionsOverflowMenuContext)) {
229
+ DEV: {
230
+ if (visible !== void 0)
231
+ console.warn("overflowing actions should not use `visible` prop");
232
+ }
233
+ return /* @__PURE__ */ jsx(
234
+ DropdownMenu.Item,
235
+ {
236
+ ...rest,
237
+ label,
238
+ icon,
239
+ unstable_dot: dot,
240
+ ref: forwardedRef
241
+ }
242
+ );
243
+ }
244
+ DEV: {
245
+ if (!icon)
246
+ throw new Error(
247
+ "`icon` prop is required when the action is displayed as a button"
248
+ );
249
+ }
162
250
  return /* @__PURE__ */ jsx(
163
- IconButton,
251
+ ToolbarItem,
164
252
  {
165
- inert: visible === false ? true : void 0,
166
- ...rest,
167
- variant: "ghost",
168
- className: cx("\u{1F95D}-tree-item-action", props.className),
169
- "data-kiwi-visible": visible,
170
- ref: forwardedRef
253
+ render: /* @__PURE__ */ jsx(
254
+ IconButton,
255
+ {
256
+ label,
257
+ icon,
258
+ inert: visible === false ? true : void 0,
259
+ ...rest,
260
+ dot,
261
+ variant: "ghost",
262
+ className: cx("\u{1F95D}-tree-item-action", props.className),
263
+ "data-kiwi-visible": visible,
264
+ ref: forwardedRef
265
+ }
266
+ )
171
267
  }
172
268
  );
173
269
  }
@@ -191,36 +287,12 @@ const TreeItemExpander = forwardRef(
191
287
  "data-kiwi-variant": "ghost",
192
288
  "data-kiwi-ghost-align": useGhostAlignment(),
193
289
  ref: forwardedRef,
194
- children: /* @__PURE__ */ jsx(TreeChevron, {})
290
+ children: /* @__PURE__ */ jsx(ChevronDown, {})
195
291
  }
196
292
  );
197
293
  }
198
294
  );
199
295
  DEV: TreeItemExpander.displayName = "TreeItemExpander";
200
- const TreeChevron = forwardRef(
201
- (props, forwardedRef) => {
202
- return /* @__PURE__ */ jsx(
203
- Icon,
204
- {
205
- ...props,
206
- render: /* @__PURE__ */ jsx(
207
- Role.svg,
208
- {
209
- width: "16",
210
- height: "16",
211
- fill: "currentColor",
212
- viewBox: "0 0 16 16",
213
- render: props.render,
214
- children: /* @__PURE__ */ jsx("path", { d: "M4.146 6.146a.5.5 0 0 1 .708 0L8 9.293l3.146-3.147a.5.5 0 0 1 .708.708l-3.5 3.5a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 0 1 0-.708Z" })
215
- }
216
- ),
217
- className: cx("\u{1F95D}-tree-chevron", props.className),
218
- ref: forwardedRef
219
- }
220
- );
221
- }
222
- );
223
- DEV: TreeChevron.displayName = "TreeChevron";
224
296
  export {
225
297
  TreeItemAction as Action,
226
298
  TreeItemRoot as Root
@@ -8,10 +8,11 @@ import { Checkbox } from "./Checkbox.js";
8
8
  import { Chip } from "./Chip.js";
9
9
  import { Description } from "./Description.js";
10
10
  import * as DropdownMenu from "./DropdownMenu.js";
11
+ import * as unstable_ErrorRegion from "./ErrorRegion.js";
11
12
  import { Divider } from "./Divider.js";
12
13
  import { Icon } from "./Icon.js";
13
14
  import { IconButton } from "./IconButton.js";
14
- import { Field } from "./Field.js";
15
+ import * as Field from "./Field.js";
15
16
  import { Kbd } from "./Kbd.js";
16
17
  import { Label } from "./Label.js";
17
18
  import { ProgressBar } from "./ProgressBar.js";
@@ -20,11 +21,13 @@ import * as Select from "./Select.js";
20
21
  import { Spinner } from "./Spinner.js";
21
22
  import { Skeleton } from "./Skeleton.js";
22
23
  import { Switch } from "./Switch.js";
24
+ import * as Table from "./Table.js";
23
25
  import * as Tabs from "./Tabs.js";
24
26
  import { Text } from "./Text.js";
25
27
  import * as TextBox from "./TextBox.js";
26
- import * as Tree from "./Tree.js";
28
+ import * as unstable_Toolbar from "./Toolbar.js";
27
29
  import { Tooltip } from "./Tooltip.js";
30
+ import * as Tree from "./Tree.js";
28
31
  import { VisuallyHidden } from "./VisuallyHidden.js";
29
32
  export {
30
33
  Anchor,
@@ -48,10 +51,13 @@ export {
48
51
  Skeleton,
49
52
  Spinner,
50
53
  Switch,
54
+ Table,
51
55
  Tabs,
52
56
  Text,
53
57
  TextBox,
54
58
  Tooltip,
55
59
  Tree,
56
- VisuallyHidden
60
+ VisuallyHidden,
61
+ unstable_ErrorRegion,
62
+ unstable_Toolbar
57
63
  };