@itwin/itwinui-react 5.0.0-alpha.10 → 5.0.0-alpha.12

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 (69) hide show
  1. package/CHANGELOG.md +134 -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 +58 -20
  6. package/dist/DEV/bricks/Field.internal.js +47 -0
  7. package/dist/DEV/bricks/Field.js +116 -85
  8. package/dist/DEV/bricks/Icon.js +144 -7
  9. package/dist/DEV/bricks/Label.js +4 -10
  10. package/dist/DEV/bricks/Radio.js +7 -14
  11. package/dist/DEV/bricks/Root.internal.js +17 -0
  12. package/dist/DEV/bricks/Root.js +73 -27
  13. package/dist/DEV/bricks/Select.js +9 -15
  14. package/dist/DEV/bricks/Spinner.js +23 -8
  15. package/dist/DEV/bricks/Switch.js +8 -15
  16. package/dist/DEV/bricks/Table.js +71 -37
  17. package/dist/DEV/bricks/Tabs.js +4 -29
  18. package/dist/DEV/bricks/TextBox.js +23 -37
  19. package/dist/DEV/bricks/Tooltip.js +1 -1
  20. package/dist/DEV/bricks/TreeItem.js +92 -10
  21. package/dist/DEV/bricks/index.js +3 -1
  22. package/dist/DEV/bricks/styles.css.js +1 -1
  23. package/dist/DEV/bricks/~hooks.js +3 -1
  24. package/dist/DEV/bricks/~utils.js +17 -0
  25. package/dist/DEV/foundations/styles.css.js +1 -1
  26. package/dist/bricks/Badge.d.ts +1 -1
  27. package/dist/bricks/Checkbox.d.ts +13 -5
  28. package/dist/bricks/Checkbox.js +7 -14
  29. package/dist/bricks/Description.d.ts +2 -6
  30. package/dist/bricks/Description.js +7 -14
  31. package/dist/bricks/DropdownMenu.d.ts +9 -9
  32. package/dist/bricks/DropdownMenu.js +57 -19
  33. package/dist/bricks/Field.d.ts +63 -27
  34. package/dist/bricks/Field.internal.d.ts +33 -0
  35. package/dist/bricks/Field.internal.js +47 -0
  36. package/dist/bricks/Field.js +111 -84
  37. package/dist/bricks/Icon.d.ts +12 -1
  38. package/dist/bricks/Icon.js +142 -7
  39. package/dist/bricks/Label.d.ts +5 -12
  40. package/dist/bricks/Label.js +4 -10
  41. package/dist/bricks/Radio.d.ts +14 -5
  42. package/dist/bricks/Radio.js +7 -14
  43. package/dist/bricks/Root.d.ts +12 -0
  44. package/dist/bricks/Root.internal.d.ts +6 -0
  45. package/dist/bricks/Root.internal.js +17 -0
  46. package/dist/bricks/Root.js +73 -27
  47. package/dist/bricks/Select.d.ts +29 -12
  48. package/dist/bricks/Select.js +9 -15
  49. package/dist/bricks/Spinner.js +23 -8
  50. package/dist/bricks/Switch.d.ts +12 -5
  51. package/dist/bricks/Switch.js +8 -15
  52. package/dist/bricks/Table.d.ts +94 -37
  53. package/dist/bricks/Table.js +69 -36
  54. package/dist/bricks/Tabs.d.ts +3 -4
  55. package/dist/bricks/Tabs.js +4 -29
  56. package/dist/bricks/TextBox.d.ts +42 -19
  57. package/dist/bricks/TextBox.js +23 -37
  58. package/dist/bricks/Tooltip.js +1 -1
  59. package/dist/bricks/TreeItem.d.ts +53 -9
  60. package/dist/bricks/TreeItem.js +81 -10
  61. package/dist/bricks/index.d.ts +2 -1
  62. package/dist/bricks/index.js +3 -1
  63. package/dist/bricks/styles.css.js +1 -1
  64. package/dist/bricks/~hooks.d.ts +8 -0
  65. package/dist/bricks/~hooks.js +3 -1
  66. package/dist/bricks/~utils.d.ts +8 -0
  67. package/dist/bricks/~utils.js +17 -0
  68. package/dist/foundations/styles.css.js +1 -1
  69. package/package.json +1 -1
@@ -24,8 +24,8 @@ interface DropdownMenuProps extends Pick<MenuProviderProps, "children" | "placem
24
24
  *
25
25
  * **Note**: `DropdownMenu` should not be used for navigation; it is only intended for actions.
26
26
  */
27
- declare function DropdownMenu(props: DropdownMenuProps): import("react/jsx-runtime").JSX.Element;
28
- declare namespace DropdownMenu {
27
+ declare function DropdownMenuRoot(props: DropdownMenuProps): import("react/jsx-runtime").JSX.Element;
28
+ declare namespace DropdownMenuRoot {
29
29
  var displayName: string;
30
30
  }
31
31
  interface DropdownMenuContentProps extends FocusableProps {
@@ -56,7 +56,7 @@ interface DropdownMenuButtonProps extends FocusableProps<"button"> {
56
56
  * ```
57
57
  */
58
58
  declare const DropdownMenuButton: React.ForwardRefExoticComponent<DropdownMenuButtonProps & React.RefAttributes<HTMLElement | HTMLButtonElement>>;
59
- interface DropdownMenuItemProps extends Omit<FocusableProps, "children">, Partial<Pick<DropdownMenuItemShortcutsProps, "shortcuts"> & Pick<DropdownMenuIconProps, "icon">> {
59
+ interface DropdownMenuItemProps extends Omit<FocusableProps<"button">, "children">, Partial<Pick<DropdownMenuItemShortcutsProps, "shortcuts"> & Pick<DropdownMenuIconProps, "icon">> {
60
60
  /** The primary text label for the menu-item. */
61
61
  label: React.ReactNode;
62
62
  }
@@ -69,8 +69,8 @@ interface DropdownMenuItemProps extends Omit<FocusableProps, "children">, Partia
69
69
  * <DropdownMenu.Item label="Edit" />
70
70
  * ```
71
71
  */
72
- declare const DropdownMenuItem: React.ForwardRefExoticComponent<DropdownMenuItemProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
73
- interface DropdownMenuItemShortcutsProps extends BaseProps {
72
+ declare const DropdownMenuItem: React.ForwardRefExoticComponent<DropdownMenuItemProps & React.RefAttributes<HTMLElement | HTMLButtonElement>>;
73
+ interface DropdownMenuItemShortcutsProps extends Omit<BaseProps<"span">, "children"> {
74
74
  /**
75
75
  * A string defining the keyboard shortcut(s) associated with the menu item.
76
76
  *
@@ -87,7 +87,7 @@ interface DropdownMenuItemShortcutsProps extends BaseProps {
87
87
  */
88
88
  shortcuts: AnyString | `${PredefinedSymbol}+${AnyString}`;
89
89
  }
90
- interface DropdownMenuIconProps extends BaseProps {
90
+ interface DropdownMenuIconProps extends BaseProps<"svg"> {
91
91
  /**
92
92
  * An optional icon displayed before the menu-item label.
93
93
  *
@@ -96,7 +96,7 @@ interface DropdownMenuIconProps extends BaseProps {
96
96
  */
97
97
  icon?: string | React.JSX.Element;
98
98
  }
99
- interface DropdownMenuCheckboxItemProps extends Omit<FocusableProps, "onChange" | "children">, Pick<MenuItemCheckboxProps, "checked" | "onChange" | "name" | "value">, Pick<DropdownMenuItemProps, "label" | "icon"> {
99
+ interface DropdownMenuCheckboxItemProps extends Omit<FocusableProps<"button">, "onChange" | "children" | "name">, Pick<MenuItemCheckboxProps, "defaultChecked" | "checked" | "onChange" | "name" | "value">, Pick<DropdownMenuItemProps, "label" | "icon"> {
100
100
  }
101
101
  /**
102
102
  * A single menu item within the dropdown menu. Should be used as a child of `DropdownMenu.Content`.
@@ -107,5 +107,5 @@ interface DropdownMenuCheckboxItemProps extends Omit<FocusableProps, "onChange"
107
107
  * <DropdownMenu.CheckboxItem name="edit" label="Edit" />
108
108
  * ```
109
109
  */
110
- declare const DropdownMenuCheckboxItem: React.ForwardRefExoticComponent<DropdownMenuCheckboxItemProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
111
- export { DropdownMenu as Root, DropdownMenuButton as Button, DropdownMenuContent as Content, DropdownMenuItem as Item, DropdownMenuCheckboxItem as CheckboxItem, };
110
+ declare const DropdownMenuCheckboxItem: React.ForwardRefExoticComponent<DropdownMenuCheckboxItemProps & React.RefAttributes<HTMLElement | HTMLButtonElement>>;
111
+ export { DropdownMenuRoot as Root, DropdownMenuButton as Button, DropdownMenuContent as Content, DropdownMenuItem as Item, DropdownMenuCheckboxItem as CheckboxItem, };
@@ -3,6 +3,7 @@ import * as React from "react";
3
3
  import cx from "classnames";
4
4
  import * as ListItem from "./~utils.ListItem.js";
5
5
  import { Button } from "./Button.js";
6
+ import { Button as ButtonAk } from "@ariakit/react/button";
6
7
  import { Kbd } from "./Kbd.js";
7
8
  import { Checkmark, DisclosureArrow, Icon } from "./Icon.js";
8
9
  import {
@@ -19,7 +20,8 @@ import {
19
20
  } from "@ariakit/react/menu";
20
21
  import { useStoreState } from "@ariakit/react/store";
21
22
  import { predefinedSymbols } from "./Kbd.internal.js";
22
- function DropdownMenu(props) {
23
+ import { usePopoverContext } from "@ariakit/react/popover";
24
+ function DropdownMenuRoot(props) {
23
25
  const {
24
26
  children,
25
27
  placement,
@@ -34,6 +36,7 @@ function DropdownMenu(props) {
34
36
  defaultOpen: defaultOpenProp,
35
37
  open: openProp,
36
38
  setOpen: setOpenProp,
39
+ popover: usePopoverContext(),
37
40
  children
38
41
  }
39
42
  );
@@ -44,7 +47,7 @@ const DropdownMenuContent = forwardRef(
44
47
  return /* @__PURE__ */ jsx(
45
48
  Menu,
46
49
  {
47
- portal: popover.portal,
50
+ portal: true,
48
51
  unmountOnHide: true,
49
52
  ...props,
50
53
  gutter: 4,
@@ -83,13 +86,23 @@ const DropdownMenuItem = forwardRef(
83
86
  MenuItem,
84
87
  {
85
88
  accessibleWhenDisabled: true,
86
- ...rest,
87
- render: /* @__PURE__ */ jsx(ListItem.Root, { render: props.render }),
88
- className: cx("\u{1F95D}-dropdown-menu-item", props.className),
89
- ref: forwardedRef,
89
+ render: /* @__PURE__ */ jsx(
90
+ ListItem.Root,
91
+ {
92
+ render: /* @__PURE__ */ jsx(
93
+ ButtonAk,
94
+ {
95
+ accessibleWhenDisabled: true,
96
+ ...rest,
97
+ className: cx("\u{1F95D}-dropdown-menu-item", props.className),
98
+ ref: forwardedRef
99
+ }
100
+ )
101
+ }
102
+ ),
90
103
  children: [
91
104
  icon ? /* @__PURE__ */ jsx(DropdownMenuIcon, { icon }) : null,
92
- /* @__PURE__ */ jsx(ListItem.Content, { children: label }),
105
+ /* @__PURE__ */ jsx(ListItem.Content, { render: /* @__PURE__ */ jsx("span", {}), children: label }),
93
106
  shortcuts ? /* @__PURE__ */ jsx(DropdownMenuItemShortcuts, { shortcuts }) : null
94
107
  ]
95
108
  }
@@ -107,6 +120,7 @@ const DropdownMenuItemShortcuts = forwardRef((props, forwardedRef) => {
107
120
  return /* @__PURE__ */ jsx(
108
121
  ListItem.Decoration,
109
122
  {
123
+ render: /* @__PURE__ */ jsx("span", {}),
110
124
  ...rest,
111
125
  className: cx("\u{1F95D}-dropdown-menu-item-shortcuts", props.className),
112
126
  ref: forwardedRef,
@@ -136,29 +150,53 @@ const DropdownMenuIcon = forwardRef(
136
150
  Icon,
137
151
  {
138
152
  href: typeof icon === "string" ? icon : void 0,
139
- render: React.isValidElement(icon) ? icon : void 0
153
+ render: React.isValidElement(icon) ? icon : void 0,
154
+ ...rest,
155
+ ref: forwardedRef
140
156
  }
141
- ),
142
- ...rest,
143
- ref: forwardedRef
157
+ )
144
158
  }
145
159
  );
146
160
  }
147
161
  );
148
162
  const DropdownMenuCheckboxItem = forwardRef((props, forwardedRef) => {
149
- const { label, icon, ...rest } = props;
163
+ const {
164
+ label,
165
+ icon,
166
+ defaultChecked,
167
+ checked,
168
+ onChange,
169
+ name,
170
+ value = defaultChecked ? "on" : void 0,
171
+ // For defaultChecked to work
172
+ ...rest
173
+ } = props;
150
174
  return /* @__PURE__ */ jsxs(
151
175
  MenuItemCheckbox,
152
176
  {
153
177
  accessibleWhenDisabled: true,
154
- value: props.defaultChecked ? "on" : void 0,
155
- ...rest,
156
- render: /* @__PURE__ */ jsx(ListItem.Root, { render: props.render }),
157
- className: cx("\u{1F95D}-dropdown-menu-item", props.className),
158
- ref: forwardedRef,
178
+ defaultChecked,
179
+ checked,
180
+ name,
181
+ value,
182
+ onChange,
183
+ render: /* @__PURE__ */ jsx(
184
+ ListItem.Root,
185
+ {
186
+ render: /* @__PURE__ */ jsx(
187
+ ButtonAk,
188
+ {
189
+ accessibleWhenDisabled: true,
190
+ ...rest,
191
+ className: cx("\u{1F95D}-dropdown-menu-item", props.className),
192
+ ref: forwardedRef
193
+ }
194
+ )
195
+ }
196
+ ),
159
197
  children: [
160
198
  icon ? /* @__PURE__ */ jsx(DropdownMenuIcon, { icon }) : null,
161
- /* @__PURE__ */ jsx(ListItem.Content, { children: label }),
199
+ /* @__PURE__ */ jsx(ListItem.Content, { render: /* @__PURE__ */ jsx("span", {}), children: label }),
162
200
  /* @__PURE__ */ jsx(
163
201
  ListItem.Decoration,
164
202
  {
@@ -174,5 +212,5 @@ export {
174
212
  DropdownMenuCheckboxItem as CheckboxItem,
175
213
  DropdownMenuContent as Content,
176
214
  DropdownMenuItem as Item,
177
- DropdownMenu as Root
215
+ DropdownMenuRoot as Root
178
216
  };
@@ -1,53 +1,89 @@
1
1
  import * as React from "react";
2
- import { useCollectionStore, type CollectionItemProps } from "@ariakit/react/collection";
2
+ import { type CollectionItemProps } from "@ariakit/react/collection";
3
3
  import { type BaseProps } from "./~utils.js";
4
- interface FieldProps extends BaseProps {
4
+ interface FieldRootProps extends BaseProps {
5
5
  /**
6
6
  * Allows overriding the default block layout for text controls.
7
7
  */
8
8
  layout?: "inline";
9
9
  }
10
10
  /**
11
- * A container for form controls. It manages ID associations provides a consistent layout and spacing.
11
+ * A container for form controls. It manages ID associations, and provides a
12
+ * consistent layout and spacing.
12
13
  *
13
14
  * Example:
14
15
  * ```tsx
15
- * <Field>
16
- * <Label>Label</Label>
17
- * <TextBox.Input />
18
- * </Field>
16
+ * <Field.Root>
17
+ * <Field.Label>Label</Field.Label>
18
+ * <Field.Control render={<TextBox.Input />} />
19
+ * </Field.Root>
19
20
  * ```
20
21
  *
21
- * Supports a `layout` prop, which can be set to `inline` to align the label and control horizontally.
22
+ * Supports a `layout` prop, which can be set to `inline` to align the label and
23
+ * control horizontally.
22
24
  *
23
- * Should contain a `Label` component paired with a form control. Supported form controls include:
25
+ * Should contain a `Field.Label` component paired with a form control.
26
+ *
27
+ * Supported form controls include:
24
28
  * - `TextBox.Input`
25
29
  * - `TextBox.Textarea`
26
30
  * - `Checkbox`
27
31
  * - `Radio`
28
32
  * - `Switch`
29
33
  */
30
- export declare const Field: React.ForwardRefExoticComponent<FieldProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
31
- type CollectionStoreItem = NonNullable<ReturnType<ReturnType<typeof useCollectionStore>["item"]>>;
32
- interface FieldCollectionStoreItem extends CollectionStoreItem {
33
- /** The type of field element being tracked */
34
- elementType: "label" | "control" | "description";
35
- /** If a control, the type of control. */
36
- controlType?: "textlike" | "checkable";
37
- }
38
- interface FieldCollectionItemControlProps extends Pick<CollectionItemProps, "render" | "id"> {
39
- type: FieldCollectionStoreItem["controlType"];
40
- }
34
+ declare const FieldRoot: React.ForwardRefExoticComponent<FieldRootProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
41
35
  /**
42
- * An element tracked as a control in the `Field`’s collection.
36
+ * A label for the field’s control element. This is automatically associated
37
+ * with the control’s `id`.
43
38
  */
44
- export declare function FieldControl(props: FieldCollectionItemControlProps): import("react/jsx-runtime").JSX.Element;
39
+ declare const FieldLabel: React.ForwardRefExoticComponent<Pick<import("@ariakit/react/role").RoleProps, "render"> & Omit<Omit<React.DetailedHTMLProps<React.LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "ref">, "render"> & React.RefAttributes<HTMLElement | HTMLDivElement>>;
45
40
  /**
46
- * An element tracked as a label in the `Field`’s collection.
41
+ * A description for the field’s control element. This is automatically
42
+ * associated with the control.
43
+ *
44
+ * Should not include content without an adequate text alternative (e.g.
45
+ * interactive elements).
47
46
  */
48
- export declare function FieldLabel(props: Pick<CollectionItemProps, "render">): import("react/jsx-runtime").JSX.Element;
47
+ declare const FieldDescription: React.ForwardRefExoticComponent<Pick<import("@ariakit/react/role").RoleProps, "render"> & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "render"> & React.RefAttributes<HTMLElement | HTMLDivElement>>;
48
+ interface FieldCollectionItemControlProps extends Pick<CollectionItemProps, "render" | "id"> {
49
+ }
49
50
  /**
50
- * An element tracked as a description in the `Field`’s collection.
51
+ * The control component for the field.
52
+ *
53
+ * If the rendered component uses a compositional API, then use a function
54
+ * within `render` to apply the `controlProps` to the correct sub-component:
55
+ *
56
+ * ```tsx
57
+ * <Field.Control
58
+ * render={(controlProps) => (
59
+ * <TextBox.Root>
60
+ * <TextBox.Icon href={placeholder} />
61
+ * <TextBox.Input {...controlProps} />
62
+ * </TextBox.Root>
63
+ * )}
64
+ * />
65
+ * ```
66
+ *
67
+ * If you need a custom `id` set for the control, set it on this component
68
+ * instead of the control component within `render`.
69
+ *
70
+ * ```tsx
71
+ * <Field.Control id="custom" render={<TextBox.Input />} />
72
+ * ```
73
+ */
74
+ declare const FieldControl: React.ForwardRefExoticComponent<FieldCollectionItemControlProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
75
+ /**
76
+ * An associated error message for a field. When used within `<Field.Root>`, the
77
+ * associated form control will be rendered with `aria-invalid="true"`.
78
+ *
79
+ * Example:
80
+ * ```tsx
81
+ * <Field.Root>
82
+ * <Field.Label>Label</Field.Label>
83
+ * <Field.Control render={<TextBox.Input />} />
84
+ * <Field.ErrorMessage>Something is wrong!</Field.ErrorMessage>
85
+ * </Field.Root>
86
+ * ```
51
87
  */
52
- export declare function FieldDescription(props: Pick<CollectionItemProps, "render" | "id">): import("react/jsx-runtime").JSX.Element;
53
- export {};
88
+ declare const FieldErrorMessage: React.ForwardRefExoticComponent<Pick<import("@ariakit/react/role").RoleProps, "render"> & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "render"> & React.RefAttributes<HTMLElement | HTMLDivElement>>;
89
+ export { FieldRoot as Root, FieldControl as Control, FieldLabel as Label, FieldDescription as Description, FieldErrorMessage as ErrorMessage, };
@@ -0,0 +1,33 @@
1
+ import * as React from "react";
2
+ import { useCollectionStore, type CollectionProps } from "@ariakit/react/collection";
3
+ /**
4
+ * Ariakit’s unexported `CollectionStoreItem` type inferred.
5
+ * @private
6
+ */
7
+ export type CollectionStoreItem = NonNullable<ReturnType<ReturnType<typeof useCollectionStore>["item"]>>;
8
+ /**
9
+ * An extension of `CollectionStoreItem` to track element and control types.
10
+ * @private
11
+ */
12
+ export interface FieldCollectionStoreItem extends CollectionStoreItem {
13
+ /** The type of field element being tracked */
14
+ elementType: "label" | "control" | "description" | "error";
15
+ /** If a control, the type of control. */
16
+ controlType?: "textlike" | "checkable";
17
+ }
18
+ /**
19
+ * A collection that tracks labels, controls, and descriptions which provides
20
+ * information about IDs, placement of labels, and control types.
21
+ * @private
22
+ */
23
+ export declare function FieldCollection(props: Pick<CollectionProps, "render">): import("react/jsx-runtime").JSX.Element;
24
+ /**
25
+ * Control type context for the field.
26
+ * @private
27
+ */
28
+ export declare const FieldControlTypeContext: React.Context<React.Dispatch<React.SetStateAction<"textlike" | "checkable" | undefined>> | undefined>;
29
+ /**
30
+ * Sets the control type for the field. Necessary for layout.
31
+ * @private
32
+ */
33
+ export declare function useFieldControlType(controlType: NonNullable<FieldCollectionStoreItem["controlType"]>): void;
@@ -0,0 +1,47 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import {
4
+ useCollectionStore,
5
+ Collection
6
+ } from "@ariakit/react/collection";
7
+ import { useStoreState } from "@ariakit/react/store";
8
+ function FieldCollection(props) {
9
+ const fieldElementCollection = useCollectionStore({
10
+ defaultItems: []
11
+ });
12
+ const renderedItems = useStoreState(fieldElementCollection, "renderedItems");
13
+ const [controlType, controlIndex] = React.useMemo(() => {
14
+ const controlIndex2 = renderedItems.findIndex(
15
+ (item) => item.elementType === "control"
16
+ );
17
+ return [renderedItems[controlIndex2]?.controlType, controlIndex2];
18
+ }, [renderedItems]);
19
+ const labelPlacement = React.useMemo(() => {
20
+ const labelIndex = renderedItems.findIndex(
21
+ (item) => item.elementType === "label"
22
+ );
23
+ if (controlIndex === -1 || labelIndex === -1) return;
24
+ return labelIndex < controlIndex ? "before" : "after";
25
+ }, [renderedItems, controlIndex]);
26
+ return /* @__PURE__ */ jsx(
27
+ Collection,
28
+ {
29
+ ...props,
30
+ store: fieldElementCollection,
31
+ "data-kiwi-label-placement": labelPlacement,
32
+ "data-kiwi-control-type": controlType
33
+ }
34
+ );
35
+ }
36
+ const FieldControlTypeContext = React.createContext(void 0);
37
+ function useFieldControlType(controlType) {
38
+ const setControlType = React.useContext(FieldControlTypeContext);
39
+ React.useEffect(() => {
40
+ setControlType?.(controlType);
41
+ }, [controlType, setControlType]);
42
+ }
43
+ export {
44
+ FieldCollection,
45
+ FieldControlTypeContext,
46
+ useFieldControlType
47
+ };
@@ -3,14 +3,18 @@ import * as React from "react";
3
3
  import cx from "classnames";
4
4
  import { Role } from "@ariakit/react/role";
5
5
  import {
6
- useCollectionStore,
7
- Collection,
8
6
  useCollectionContext,
9
7
  CollectionItem
10
8
  } from "@ariakit/react/collection";
11
9
  import { useStoreState } from "@ariakit/react/store";
12
10
  import { forwardRef } from "./~utils.js";
13
- const Field = forwardRef((props, forwardedRef) => {
11
+ import {
12
+ FieldCollection,
13
+ FieldControlTypeContext
14
+ } from "./Field.internal.js";
15
+ import { Label } from "./Label.js";
16
+ import { Description } from "./Description.js";
17
+ const FieldRoot = forwardRef((props, forwardedRef) => {
14
18
  const { layout, ...rest } = props;
15
19
  return /* @__PURE__ */ jsx(
16
20
  FieldCollection,
@@ -27,75 +31,40 @@ const Field = forwardRef((props, forwardedRef) => {
27
31
  }
28
32
  );
29
33
  });
30
- function FieldCollection(props) {
31
- const fieldElementCollection = useCollectionStore({
32
- defaultItems: []
33
- });
34
- const renderedItems = useStoreState(fieldElementCollection, "renderedItems");
35
- const [controlType, controlIndex] = React.useMemo(() => {
36
- const controlIndex2 = renderedItems.findIndex(
37
- (item) => item.elementType === "control"
34
+ const FieldLabel = forwardRef(
35
+ (props, forwardedRef) => {
36
+ const store = useCollectionContext();
37
+ const renderedItems = useStoreState(store, "renderedItems");
38
+ const fieldId = React.useMemo(
39
+ () => renderedItems?.find(
40
+ (item) => item.elementType === "control"
41
+ )?.id,
42
+ [renderedItems]
38
43
  );
39
- return [renderedItems[controlIndex2]?.controlType, controlIndex2];
40
- }, [renderedItems]);
41
- const labelPlacement = React.useMemo(() => {
42
- const labelIndex = renderedItems.findIndex(
43
- (item) => item.elementType === "label"
44
+ const getData = React.useCallback(
45
+ (data) => ({
46
+ ...data,
47
+ elementType: "label"
48
+ }),
49
+ []
44
50
  );
45
- if (controlIndex === -1 || labelIndex === -1) return;
46
- return labelIndex < controlIndex ? "before" : "after";
47
- }, [renderedItems, controlIndex]);
48
- return /* @__PURE__ */ jsx(
49
- Collection,
50
- {
51
- ...props,
52
- store: fieldElementCollection,
53
- "data-kiwi-label-placement": labelPlacement,
54
- "data-kiwi-control-type": controlType
55
- }
56
- );
57
- }
58
- function FieldControl(props) {
59
- const store = useCollectionContext();
51
+ return /* @__PURE__ */ jsx(
52
+ CollectionItem,
53
+ {
54
+ getItem: getData,
55
+ render: /* @__PURE__ */ jsx(Label, { ...props, htmlFor: fieldId }),
56
+ ref: forwardedRef
57
+ }
58
+ );
59
+ }
60
+ );
61
+ const FieldDescription = forwardRef((props, forwardedRef) => {
60
62
  const generatedId = React.useId();
61
- const { id = store ? generatedId : void 0, type, ...rest } = props;
62
- const renderedItems = useStoreState(store, "renderedItems");
63
- const describedBy = React.useMemo(() => {
64
- const idRefList = renderedItems?.filter(
65
- (item) => item.elementType === "description"
66
- )?.map((item) => item.id).join(" ");
67
- return idRefList || void 0;
68
- }, [renderedItems]);
69
- const getData = React.useCallback(
70
- (data) => ({
71
- ...data,
72
- elementType: "control",
73
- controlType: type
74
- }),
75
- [type]
76
- );
77
- return /* @__PURE__ */ jsx(
78
- CollectionItem,
79
- {
80
- id,
81
- getItem: getData,
82
- render: /* @__PURE__ */ jsx(Role, { ...rest, "aria-describedby": describedBy })
83
- }
84
- );
85
- }
86
- function FieldLabel(props) {
87
- const store = useCollectionContext();
88
- const renderedItems = useStoreState(store, "renderedItems");
89
- const fieldId = React.useMemo(
90
- () => renderedItems?.find(
91
- (item) => item.elementType === "control"
92
- )?.id,
93
- [renderedItems]
94
- );
63
+ const { id = generatedId, ...rest } = props;
95
64
  const getData = React.useCallback(
96
65
  (data) => ({
97
66
  ...data,
98
- elementType: "label"
67
+ elementType: "description"
99
68
  }),
100
69
  []
101
70
  );
@@ -103,25 +72,83 @@ function FieldLabel(props) {
103
72
  CollectionItem,
104
73
  {
105
74
  getItem: getData,
106
- render: /* @__PURE__ */ jsx(Role.label, { ...props, htmlFor: fieldId })
75
+ id,
76
+ render: /* @__PURE__ */ jsx(Description, { ...rest }),
77
+ ref: forwardedRef
107
78
  }
108
79
  );
109
- }
110
- function FieldDescription(props) {
111
- const generatedId = React.useId();
112
- const { id = generatedId, ...rest } = props;
113
- const getData = React.useCallback(
114
- (data) => ({
115
- ...data,
116
- elementType: "description"
117
- }),
118
- []
119
- );
120
- return /* @__PURE__ */ jsx(CollectionItem, { ...rest, id, getItem: getData });
121
- }
80
+ });
81
+ const FieldControl = forwardRef(
82
+ (props, forwardedRef) => {
83
+ const [controlType, setControlType] = React.useState();
84
+ const store = useCollectionContext();
85
+ const generatedId = React.useId();
86
+ const { id = store ? generatedId : void 0, ...rest } = props;
87
+ const renderedItems = useStoreState(store, "renderedItems");
88
+ const describedBy = React.useMemo(() => {
89
+ const idRefList = renderedItems?.filter(
90
+ (item) => item.elementType === "description" || item.elementType === "error"
91
+ )?.map((item) => item.id).join(" ");
92
+ return idRefList || void 0;
93
+ }, [renderedItems]);
94
+ const getData = React.useCallback(
95
+ (data) => ({
96
+ ...data,
97
+ elementType: "control",
98
+ controlType
99
+ }),
100
+ [controlType]
101
+ );
102
+ const invalid = React.useMemo(
103
+ () => renderedItems?.some(
104
+ (item) => item.elementType === "error"
105
+ ),
106
+ [renderedItems]
107
+ );
108
+ return /* @__PURE__ */ jsx(FieldControlTypeContext.Provider, { value: setControlType, children: /* @__PURE__ */ jsx(
109
+ CollectionItem,
110
+ {
111
+ id,
112
+ getItem: getData,
113
+ render: /* @__PURE__ */ jsx(
114
+ Role,
115
+ {
116
+ ...rest,
117
+ "aria-invalid": invalid ? "true" : void 0,
118
+ "aria-describedby": describedBy
119
+ }
120
+ ),
121
+ ref: forwardedRef
122
+ }
123
+ ) });
124
+ }
125
+ );
126
+ const FieldErrorMessage = forwardRef(
127
+ (props, forwardedRef) => {
128
+ const generatedId = React.useId();
129
+ const { id = generatedId, ...rest } = props;
130
+ const getData = React.useCallback(
131
+ (data) => ({
132
+ ...data,
133
+ elementType: "error"
134
+ }),
135
+ []
136
+ );
137
+ return /* @__PURE__ */ jsx(
138
+ CollectionItem,
139
+ {
140
+ id,
141
+ getItem: getData,
142
+ render: /* @__PURE__ */ jsx(Description, { ...rest, tone: "critical" }),
143
+ ref: forwardedRef
144
+ }
145
+ );
146
+ }
147
+ );
122
148
  export {
123
- Field,
124
- FieldControl,
125
- FieldDescription,
126
- FieldLabel
149
+ FieldControl as Control,
150
+ FieldDescription as Description,
151
+ FieldErrorMessage as ErrorMessage,
152
+ FieldLabel as Label,
153
+ FieldRoot as Root
127
154
  };
@@ -5,6 +5,11 @@ interface IconProps extends Omit<BaseProps<"svg">, "children"> {
5
5
  * URL of the symbol sprite.
6
6
  *
7
7
  * Should be a URL to an `.svg` file from `@itwin/itwinui-icons`.
8
+ *
9
+ * Note: The `.svg` must be an external HTTP resource for it to be processed by
10
+ * the `<use>` element. As a fallback, JS will be used to `fetch` the SVG from
11
+ * non-supported URLs; the fetched SVG content will be sanitized using the
12
+ * `unstable_htmlSanitizer` function passed to `<Root>`.
8
13
  */
9
14
  href?: string;
10
15
  /**
@@ -27,7 +32,7 @@ interface IconProps extends Omit<BaseProps<"svg">, "children"> {
27
32
  }
28
33
  /**
29
34
  * Icon component that provides fill and sizing to the SVGs from `@itwin/itwinui-icons`.
30
- * It uses an external symbol sprite to render the icon based on the specified `size`.
35
+ * It renders the correct symbol sprite based on the specified `size`.
31
36
  *
32
37
  * ```tsx
33
38
  * const arrowIcon = new URL("@itwin/itwinui-icons/arrow.svg", import.meta.url).href;
@@ -63,4 +68,10 @@ export declare const Checkmark: React.ForwardRefExoticComponent<CheckmarkProps &
63
68
  interface DismissProps extends Omit<BaseProps<"svg">, "children"> {
64
69
  }
65
70
  export declare const Dismiss: React.ForwardRefExoticComponent<DismissProps & React.RefAttributes<HTMLElement | SVGSVGElement>>;
71
+ interface StatusWarningProps extends Omit<BaseProps<"svg">, "children"> {
72
+ }
73
+ export declare const StatusWarning: React.ForwardRefExoticComponent<StatusWarningProps & React.RefAttributes<HTMLElement | SVGSVGElement>>;
74
+ interface MoreHorizontalProps extends Omit<BaseProps<"svg">, "children"> {
75
+ }
76
+ export declare const MoreHorizontal: React.ForwardRefExoticComponent<MoreHorizontalProps & React.RefAttributes<HTMLElement | SVGSVGElement>>;
66
77
  export {};