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

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 (110) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +6 -6
  3. package/dist/DEV/bricks/Anchor.js +5 -10
  4. package/dist/DEV/bricks/Avatar.js +24 -0
  5. package/dist/DEV/bricks/Badge.js +22 -0
  6. package/dist/DEV/bricks/Button.js +11 -4
  7. package/dist/DEV/bricks/Checkbox.js +17 -9
  8. package/dist/DEV/bricks/Chip.js +42 -0
  9. package/dist/DEV/bricks/Description.js +29 -0
  10. package/dist/DEV/bricks/Divider.js +3 -2
  11. package/dist/DEV/bricks/DropdownMenu.js +109 -30
  12. package/dist/DEV/bricks/Field.js +115 -14
  13. package/dist/DEV/bricks/Icon.js +70 -8
  14. package/dist/DEV/bricks/IconButton.js +14 -3
  15. package/dist/DEV/bricks/Kbd.internal.js +19 -0
  16. package/dist/DEV/bricks/Kbd.js +23 -6
  17. package/dist/DEV/bricks/Label.js +11 -8
  18. package/dist/DEV/bricks/ProgressBar.js +25 -0
  19. package/dist/DEV/bricks/Radio.js +17 -9
  20. package/dist/DEV/bricks/Root.js +35 -4
  21. package/dist/DEV/bricks/Select.js +17 -11
  22. package/dist/DEV/bricks/Skeleton.js +24 -0
  23. package/dist/DEV/bricks/Spinner.js +40 -0
  24. package/dist/DEV/bricks/Switch.js +18 -10
  25. package/dist/DEV/bricks/Table.js +114 -0
  26. package/dist/DEV/bricks/Tabs.js +6 -6
  27. package/dist/DEV/bricks/Text.js +2 -2
  28. package/dist/DEV/bricks/TextBox.js +54 -16
  29. package/dist/DEV/bricks/Tooltip.js +17 -25
  30. package/dist/DEV/bricks/Tree.js +15 -107
  31. package/dist/DEV/bricks/TreeItem.js +224 -0
  32. package/dist/DEV/bricks/VisuallyHidden.js +2 -2
  33. package/dist/DEV/bricks/index.js +16 -0
  34. package/dist/DEV/bricks/styles.css.js +2 -2
  35. package/dist/DEV/bricks/~hooks.js +55 -3
  36. package/dist/DEV/bricks/~utils.GhostAligner.js +13 -0
  37. package/dist/DEV/bricks/{ListItem.js → ~utils.ListItem.js} +19 -3
  38. package/dist/DEV/foundations/styles.css.js +2 -2
  39. package/dist/bricks/Anchor.js +5 -10
  40. package/dist/bricks/Avatar.d.ts +47 -0
  41. package/dist/bricks/Avatar.js +23 -0
  42. package/dist/bricks/Badge.d.ts +28 -0
  43. package/dist/bricks/Badge.js +21 -0
  44. package/dist/bricks/Button.js +11 -4
  45. package/dist/bricks/Checkbox.d.ts +2 -2
  46. package/dist/bricks/Checkbox.js +17 -9
  47. package/dist/bricks/Chip.d.ts +31 -0
  48. package/dist/bricks/Chip.js +41 -0
  49. package/dist/bricks/Description.d.ts +19 -0
  50. package/dist/bricks/Description.js +29 -0
  51. package/dist/bricks/Divider.d.ts +2 -2
  52. package/dist/bricks/Divider.js +3 -2
  53. package/dist/bricks/DropdownMenu.d.ts +41 -14
  54. package/dist/bricks/DropdownMenu.js +106 -30
  55. package/dist/bricks/Field.d.ts +23 -1
  56. package/dist/bricks/Field.js +115 -14
  57. package/dist/bricks/Icon.d.ts +34 -3
  58. package/dist/bricks/Icon.js +68 -8
  59. package/dist/bricks/IconButton.d.ts +20 -4
  60. package/dist/bricks/IconButton.js +14 -3
  61. package/dist/bricks/Kbd.d.ts +15 -0
  62. package/dist/bricks/Kbd.internal.d.ts +17 -0
  63. package/dist/bricks/Kbd.internal.js +19 -0
  64. package/dist/bricks/Kbd.js +16 -6
  65. package/dist/bricks/Label.js +11 -8
  66. package/dist/bricks/ProgressBar.d.ts +31 -0
  67. package/dist/bricks/ProgressBar.js +24 -0
  68. package/dist/bricks/Radio.d.ts +2 -2
  69. package/dist/bricks/Radio.js +17 -9
  70. package/dist/bricks/Root.js +35 -4
  71. package/dist/bricks/Select.d.ts +9 -3
  72. package/dist/bricks/Select.js +17 -11
  73. package/dist/bricks/Skeleton.d.ts +25 -0
  74. package/dist/bricks/Skeleton.js +23 -0
  75. package/dist/bricks/Spinner.d.ts +31 -0
  76. package/dist/bricks/Spinner.js +39 -0
  77. package/dist/bricks/Switch.d.ts +2 -2
  78. package/dist/bricks/Switch.js +18 -10
  79. package/dist/bricks/Table.d.ts +115 -0
  80. package/dist/bricks/Table.js +108 -0
  81. package/dist/bricks/Tabs.d.ts +4 -4
  82. package/dist/bricks/Tabs.js +6 -6
  83. package/dist/bricks/Text.d.ts +1 -1
  84. package/dist/bricks/Text.js +2 -2
  85. package/dist/bricks/TextBox.d.ts +23 -2
  86. package/dist/bricks/TextBox.js +53 -16
  87. package/dist/bricks/Tooltip.d.ts +2 -2
  88. package/dist/bricks/Tooltip.js +17 -25
  89. package/dist/bricks/Tree.d.ts +19 -20
  90. package/dist/bricks/Tree.js +14 -102
  91. package/dist/bricks/TreeItem.d.ts +123 -0
  92. package/dist/bricks/TreeItem.js +219 -0
  93. package/dist/bricks/VisuallyHidden.js +2 -2
  94. package/dist/bricks/index.d.ts +8 -0
  95. package/dist/bricks/index.js +16 -0
  96. package/dist/bricks/styles.css.js +2 -2
  97. package/dist/bricks/~hooks.d.ts +55 -0
  98. package/dist/bricks/~hooks.js +55 -3
  99. package/dist/bricks/~utils.GhostAligner.d.ts +22 -0
  100. package/dist/bricks/~utils.GhostAligner.js +13 -0
  101. package/dist/bricks/~utils.ListItem.d.ts +14 -0
  102. package/dist/bricks/{ListItem.js → ~utils.ListItem.js} +18 -3
  103. package/dist/bricks/~utils.d.ts +6 -3
  104. package/dist/foundations/styles.css.js +2 -2
  105. package/package.json +14 -13
  106. package/CHANGELOG.md +0 -14
  107. package/dist/DEV/bricks/Textarea.js +0 -30
  108. package/dist/bricks/ListItem.d.ts +0 -10
  109. package/dist/bricks/Textarea.d.ts +0 -24
  110. package/dist/bricks/Textarea.js +0 -29
@@ -0,0 +1,28 @@
1
+ import { type BaseProps } from "./~utils.js";
2
+ interface BadgeProps extends Omit<BaseProps<"span">, "children"> {
3
+ /**
4
+ * The label displayed inside the badge.
5
+ */
6
+ label: string;
7
+ /**
8
+ * The tone of the badge.
9
+ * @default "neutral"
10
+ */
11
+ tone?: "neutral" | "info" | "positive" | "attention" | "critical";
12
+ /**
13
+ * The variant style of the badge.
14
+ * @default "solid"
15
+ */
16
+ variant?: "solid" | "muted" | "outline";
17
+ }
18
+ /**
19
+ * A badge component, typically used to designate the status of an item.
20
+ *
21
+ * Example:
22
+ * ```tsx
23
+ * <Badge label="Value" />
24
+ * <Badge label="Value" tone="info" variant="outline" />
25
+ * ```
26
+ */
27
+ export declare const Badge: import("react").ForwardRefExoticComponent<BadgeProps & import("react").RefAttributes<HTMLElement | HTMLSpanElement>>;
28
+ export {};
@@ -0,0 +1,21 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import cx from "classnames";
3
+ import { Role } from "@ariakit/react/role";
4
+ import { forwardRef } from "./~utils.js";
5
+ const Badge = forwardRef((props, forwardedRef) => {
6
+ const { tone = "neutral", variant = "solid", label, ...rest } = props;
7
+ return /* @__PURE__ */ jsx(
8
+ Role.span,
9
+ {
10
+ ...rest,
11
+ "data-kiwi-tone": tone,
12
+ "data-kiwi-variant": variant,
13
+ className: cx("\u{1F95D}-badge", props.className),
14
+ ref: forwardedRef,
15
+ children: label
16
+ }
17
+ );
18
+ });
19
+ export {
20
+ Badge
21
+ };
@@ -1,18 +1,25 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import cx from "classnames";
3
- import * as Ariakit from "@ariakit/react";
3
+ import { Button as AkButton } from "@ariakit/react/button";
4
4
  import { forwardRef } from "./~utils.js";
5
+ import { useGhostAlignment } from "./~utils.GhostAligner.js";
5
6
  const Button = forwardRef(
6
7
  (props, forwardedRef) => {
7
8
  const { variant = "solid", tone = "neutral", ...rest } = props;
9
+ const ghostAlignment = useGhostAlignment();
8
10
  return /* @__PURE__ */ jsx(
9
- Ariakit.Button,
11
+ AkButton,
10
12
  {
11
13
  accessibleWhenDisabled: true,
14
+ ...rest,
12
15
  "data-kiwi-variant": variant,
13
16
  "data-kiwi-tone": tone,
14
- ...rest,
15
- className: cx("\u{1F95D}-button", props.className),
17
+ "data-kiwi-ghost-align": variant === "ghost" ? ghostAlignment : void 0,
18
+ className: cx(
19
+ "\u{1F95D}-button",
20
+ { "\u{1F95D}-ghost-aligner": variant === "ghost" },
21
+ props.className
22
+ ),
16
23
  ref: forwardedRef
17
24
  }
18
25
  );
@@ -1,7 +1,7 @@
1
- import * as Ariakit from "@ariakit/react";
1
+ import { type CheckboxProps as AkCheckboxProps } from "@ariakit/react/checkbox";
2
2
  import { type FocusableProps } from "./~utils.js";
3
3
  type InputBaseProps = Omit<FocusableProps<"input">, "defaultValue" | "checked" | "defaultChecked">;
4
- type CheckboxOwnProps = Pick<Ariakit.CheckboxProps, "value" | "defaultChecked" | "checked" | "onChange">;
4
+ type CheckboxOwnProps = Pick<AkCheckboxProps, "value" | "defaultChecked" | "checked" | "onChange">;
5
5
  interface CheckboxProps extends InputBaseProps, CheckboxOwnProps {
6
6
  }
7
7
  /**
@@ -1,19 +1,27 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import cx from "classnames";
3
- import * as Ariakit from "@ariakit/react";
4
- import { useFieldId } from "./Field.js";
3
+ import {
4
+ Checkbox as AkCheckbox
5
+ } from "@ariakit/react/checkbox";
6
+ import { FieldControl } from "./Field.js";
5
7
  import { forwardRef } from "./~utils.js";
6
8
  const Checkbox = forwardRef(
7
9
  (props, forwardedRef) => {
8
- const fieldId = useFieldId();
10
+ const { id, ...rest } = props;
9
11
  return /* @__PURE__ */ jsx(
10
- Ariakit.Checkbox,
12
+ FieldControl,
11
13
  {
12
- accessibleWhenDisabled: true,
13
- id: fieldId,
14
- ...props,
15
- className: cx("\u{1F95D}-checkbox", props.className),
16
- ref: forwardedRef
14
+ type: "checkable",
15
+ id,
16
+ render: /* @__PURE__ */ jsx(
17
+ AkCheckbox,
18
+ {
19
+ accessibleWhenDisabled: true,
20
+ ...rest,
21
+ className: cx("\u{1F95D}-checkbox", props.className),
22
+ ref: forwardedRef
23
+ }
24
+ )
17
25
  }
18
26
  );
19
27
  }
@@ -0,0 +1,31 @@
1
+ import * as React from "react";
2
+ import { type BaseProps } from "./~utils.js";
3
+ interface ChipProps extends Omit<BaseProps<"div">, "children"> {
4
+ /**
5
+ * The label displayed inside the chip.
6
+ */
7
+ label: string;
8
+ /**
9
+ * The variant style of the Chip.
10
+ * Use "solid" for primary states and "outline" for less prominent states.
11
+ *
12
+ * @default "solid"
13
+ */
14
+ variant?: "solid" | "outline";
15
+ /**
16
+ * Callback invoked when the dismiss ("❌") button is clicked.
17
+ */
18
+ onDismiss?: () => void;
19
+ }
20
+ /**
21
+ * Chip is a UI component used to represent an item, attribute, or action in a compact visual style.
22
+ * It supports two visual variants: `solid` for primary emphasis and `outline` for less prominent states.
23
+ *
24
+ * Example:
25
+ * ```tsx
26
+ * <Chip label="Value" />
27
+ * <Chip label="Value" variant="outline" />
28
+ * ```
29
+ */
30
+ export declare const Chip: React.ForwardRefExoticComponent<ChipProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
31
+ export {};
@@ -0,0 +1,41 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import cx from "classnames";
3
+ import * as React from "react";
4
+ import { Role } from "@ariakit/react/role";
5
+ import { forwardRef } from "./~utils.js";
6
+ import { IconButton } from "./IconButton.js";
7
+ import { Dismiss } from "./Icon.js";
8
+ const Chip = forwardRef((props, forwardedRef) => {
9
+ const { variant = "solid", onDismiss, label, ...rest } = props;
10
+ const baseId = React.useId();
11
+ const labelId = `${baseId}-label`;
12
+ const dismissIconId = `${baseId}-dismiss`;
13
+ return /* @__PURE__ */ jsxs(
14
+ Role.div,
15
+ {
16
+ "data-kiwi-variant": variant,
17
+ ...rest,
18
+ className: cx("\u{1F95D}-chip", props.className),
19
+ ref: forwardedRef,
20
+ children: [
21
+ /* @__PURE__ */ jsx("span", { id: labelId, children: label }),
22
+ onDismiss && /* @__PURE__ */ jsx(
23
+ IconButton,
24
+ {
25
+ id: dismissIconId,
26
+ className: "\u{1F95D}-chip-dismiss-button",
27
+ variant: "ghost",
28
+ "aria-labelledby": `${dismissIconId} ${labelId}`,
29
+ label: "Dismiss",
30
+ labelVariant: "visually-hidden",
31
+ icon: /* @__PURE__ */ jsx(Dismiss, {}),
32
+ onClick: onDismiss
33
+ }
34
+ )
35
+ ]
36
+ }
37
+ );
38
+ });
39
+ export {
40
+ Chip
41
+ };
@@ -0,0 +1,19 @@
1
+ import { type BaseProps } from "./~utils.js";
2
+ interface DescriptionProps extends BaseProps {
3
+ /**
4
+ * The tone of the description.
5
+ * @default "neutral"
6
+ */
7
+ tone?: "neutral" | "critical";
8
+ }
9
+ /**
10
+ * An additional description for a form control.
11
+ *
12
+ * Should not include content without an adequate text alternative.
13
+ *
14
+ * Either give this component an `id` and manually associate with a form control
15
+ * using `aria-describedby` on said control or use the `<Field>` component
16
+ * (WIP).
17
+ */
18
+ export declare const Description: import("react").ForwardRefExoticComponent<DescriptionProps & import("react").RefAttributes<HTMLElement | HTMLDivElement>>;
19
+ export {};
@@ -0,0 +1,29 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "./~utils.js";
3
+ import cx from "classnames";
4
+ import { Text } from "./Text.js";
5
+ import { FieldDescription } from "./Field.js";
6
+ const Description = forwardRef(
7
+ (props, forwardedRef) => {
8
+ const { id, tone, ...rest } = props;
9
+ return /* @__PURE__ */ jsx(
10
+ FieldDescription,
11
+ {
12
+ id,
13
+ render: /* @__PURE__ */ jsx(
14
+ Text,
15
+ {
16
+ ...rest,
17
+ variant: "caption-md",
18
+ "data-kiwi-tone": tone ?? "neutral",
19
+ className: cx("\u{1F95D}-description", props.className),
20
+ ref: forwardedRef
21
+ }
22
+ )
23
+ }
24
+ );
25
+ }
26
+ );
27
+ export {
28
+ Description
29
+ };
@@ -1,6 +1,6 @@
1
- import * as Ariakit from "@ariakit/react";
1
+ import { type SeparatorProps } from "@ariakit/react/separator";
2
2
  import { type BaseProps } from "./~utils.js";
3
- interface DividerProps extends BaseProps<"hr">, Pick<Ariakit.SeparatorProps, "orientation"> {
3
+ interface DividerProps extends BaseProps<"hr">, Pick<SeparatorProps, "orientation"> {
4
4
  /**
5
5
  * If true, the divider will be purely presentational and will not have any associated semantics.
6
6
  *
@@ -1,10 +1,11 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import cx from "classnames";
3
- import * as Ariakit from "@ariakit/react";
3
+ import { Role } from "@ariakit/react/role";
4
+ import { Separator } from "@ariakit/react/separator";
4
5
  import { forwardRef } from "./~utils.js";
5
6
  const Divider = forwardRef((props, forwardedRef) => {
6
7
  const { presentational, ...rest } = props;
7
- const Comp = presentational ? Ariakit.Role : Ariakit.Separator;
8
+ const Comp = presentational ? Role : Separator;
8
9
  return /* @__PURE__ */ jsx(
9
10
  Comp,
10
11
  {
@@ -1,7 +1,8 @@
1
1
  import * as React from "react";
2
- import * as Ariakit from "@ariakit/react";
3
- import { type FocusableProps } from "./~utils.js";
4
- interface DropdownMenuProps extends Pick<Ariakit.MenuProviderProps, "children" | "placement" | "open" | "setOpen" | "defaultOpen"> {
2
+ import { type AnyString, type BaseProps, type FocusableProps } from "./~utils.js";
3
+ import { type MenuItemCheckboxProps, type MenuProviderProps } from "@ariakit/react/menu";
4
+ import { type PredefinedSymbol } from "./Kbd.internal.js";
5
+ interface DropdownMenuProps extends Pick<MenuProviderProps, "children" | "placement" | "open" | "setOpen" | "defaultOpen"> {
5
6
  }
6
7
  /**
7
8
  * A dropdown menu displays a list of actions or commands when the menu button is clicked.
@@ -14,9 +15,9 @@ interface DropdownMenuProps extends Pick<Ariakit.MenuProviderProps, "children" |
14
15
  * <DropdownMenu.Button>Actions</DropdownMenu.Button>
15
16
  *
16
17
  * <DropdownMenu.Content>
17
- * <DropdownMenu.Item>Add</DropdownMenu.Item>
18
- * <DropdownMenu.Item>Edit</DropdownMenu.Item>
19
- * <DropdownMenu.Item>Delete</DropdownMenu.Item>
18
+ * <DropdownMenu.Item label="Add" />
19
+ * <DropdownMenu.Item label="Edit" />
20
+ * <DropdownMenu.Item label="Delete" />
20
21
  * </DropdownMenu.Content>
21
22
  * </DropdownMenu.Root>
22
23
  * ```
@@ -55,7 +56,21 @@ interface DropdownMenuButtonProps extends FocusableProps<"button"> {
55
56
  * ```
56
57
  */
57
58
  declare const DropdownMenuButton: React.ForwardRefExoticComponent<DropdownMenuButtonProps & React.RefAttributes<HTMLElement | HTMLButtonElement>>;
58
- interface DropdownMenuItemProps extends FocusableProps {
59
+ interface DropdownMenuItemProps extends Omit<FocusableProps, "children">, Partial<Pick<DropdownMenuItemShortcutsProps, "shortcuts"> & Pick<DropdownMenuIconProps, "icon">> {
60
+ /** The primary text label for the menu-item. */
61
+ label: React.ReactNode;
62
+ }
63
+ /**
64
+ * A single menu item within the dropdown menu. Should be used as a child of `DropdownMenu.Content`.
65
+ *
66
+ * Example:
67
+ * ```tsx
68
+ * <DropdownMenu.Item label="Add" />
69
+ * <DropdownMenu.Item label="Edit" />
70
+ * ```
71
+ */
72
+ declare const DropdownMenuItem: React.ForwardRefExoticComponent<DropdownMenuItemProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
73
+ interface DropdownMenuItemShortcutsProps extends BaseProps {
59
74
  /**
60
75
  * A string defining the keyboard shortcut(s) associated with the menu item.
61
76
  *
@@ -63,22 +78,34 @@ interface DropdownMenuItemProps extends FocusableProps {
63
78
  * shortcuts="S" // A single key shortcut
64
79
  * ```
65
80
  *
66
- * Multiple keys should be separated by the '+' character.
81
+ * Multiple keys should be separated by the `+` character. If one of the keys is
82
+ * recognized as a symbol name or a modifier key, it will be displayed as a symbol.
67
83
  *
68
84
  * ```tsx
69
- * shortcuts="Ctrl+Shift+S" // A multi-key combination
85
+ * shortcuts="Control+Enter" // A multi-key shortcut, displayed as "Ctrl ⏎"
70
86
  * ```
71
87
  */
72
- shortcuts?: string;
88
+ shortcuts: AnyString | `${PredefinedSymbol}+${AnyString}`;
89
+ }
90
+ interface DropdownMenuIconProps extends BaseProps {
91
+ /**
92
+ * An optional icon displayed before the menu-item label.
93
+ *
94
+ * Can be a URL of an SVG from the `@itwin/itwinui-icons` package,
95
+ * or a custom JSX icon.
96
+ */
97
+ icon?: string | React.JSX.Element;
98
+ }
99
+ interface DropdownMenuCheckboxItemProps extends Omit<FocusableProps, "onChange" | "children">, Pick<MenuItemCheckboxProps, "checked" | "onChange" | "name" | "value">, Pick<DropdownMenuItemProps, "label" | "icon"> {
73
100
  }
74
101
  /**
75
102
  * A single menu item within the dropdown menu. Should be used as a child of `DropdownMenu.Content`.
76
103
  *
77
104
  * Example:
78
105
  * ```tsx
79
- * <DropdownMenu.Item>Add</DropdownMenu.Item>
80
- * <DropdownMenu.Item>Edit</DropdownMenu.Item>
106
+ * <DropdownMenu.CheckboxItem name="add" label="Add" />
107
+ * <DropdownMenu.CheckboxItem name="edit" label="Edit" />
81
108
  * ```
82
109
  */
83
- declare const DropdownMenuItem: React.ForwardRefExoticComponent<DropdownMenuItemProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
84
- export { DropdownMenu as Root, DropdownMenuButton as Button, DropdownMenuContent as Content, DropdownMenuItem as Item, };
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, };
@@ -1,12 +1,24 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import cx from "classnames";
4
- import * as Ariakit from "@ariakit/react";
5
- import * as ListItem from "./ListItem.js";
4
+ import * as ListItem from "./~utils.ListItem.js";
6
5
  import { Button } from "./Button.js";
7
6
  import { Kbd } from "./Kbd.js";
8
- import { DisclosureArrow } from "./Icon.js";
9
- import { forwardRef, supportsPopover } from "./~utils.js";
7
+ import { Checkmark, DisclosureArrow, Icon } from "./Icon.js";
8
+ import {
9
+ forwardRef
10
+ } from "./~utils.js";
11
+ import { usePopoverApi } from "./~hooks.js";
12
+ import {
13
+ MenuProvider,
14
+ useMenuContext,
15
+ Menu,
16
+ MenuButton,
17
+ MenuItem,
18
+ MenuItemCheckbox
19
+ } from "@ariakit/react/menu";
20
+ import { useStoreState } from "@ariakit/react/store";
21
+ import { predefinedSymbols } from "./Kbd.internal.js";
10
22
  function DropdownMenu(props) {
11
23
  const {
12
24
  children,
@@ -15,21 +27,9 @@ function DropdownMenu(props) {
15
27
  setOpen: setOpenProp,
16
28
  defaultOpen: defaultOpenProp
17
29
  } = props;
18
- const store = Ariakit.useMenuStore();
19
- const open = Ariakit.useStoreState(store, (state) => state.open);
20
- const popover = Ariakit.useStoreState(store, (state) => state.popoverElement);
21
- React.useEffect(
22
- function syncPopoverWithOpenState() {
23
- if (popover?.isConnected) {
24
- popover?.togglePopover?.(open);
25
- }
26
- },
27
- [open, popover]
28
- );
29
30
  return /* @__PURE__ */ jsx(
30
- Ariakit.MenuProvider,
31
+ MenuProvider,
31
32
  {
32
- store,
33
33
  placement,
34
34
  defaultOpen: defaultOpenProp,
35
35
  open: openProp,
@@ -40,14 +40,16 @@ function DropdownMenu(props) {
40
40
  }
41
41
  const DropdownMenuContent = forwardRef(
42
42
  (props, forwardedRef) => {
43
+ const popover = usePopoverApi(useMenuContext());
43
44
  return /* @__PURE__ */ jsx(
44
- Ariakit.Menu,
45
+ Menu,
45
46
  {
46
- portal: !supportsPopover,
47
+ portal: popover.portal,
47
48
  unmountOnHide: true,
48
49
  ...props,
49
- style: { zIndex: supportsPopover ? void 0 : 9999, ...props.style },
50
- wrapperProps: { popover: "manual" },
50
+ gutter: 4,
51
+ style: { ...popover.style, ...props.style },
52
+ wrapperProps: popover.wrapperProps,
51
53
  className: cx("\u{1F95D}-dropdown-menu", props.className),
52
54
  ref: forwardedRef
53
55
  }
@@ -57,8 +59,9 @@ const DropdownMenuContent = forwardRef(
57
59
  const DropdownMenuButton = forwardRef(
58
60
  (props, forwardedRef) => {
59
61
  const { accessibleWhenDisabled = true, children, ...rest } = props;
62
+ const open = useStoreState(useMenuContext(), (state) => state?.open);
60
63
  return /* @__PURE__ */ jsx(
61
- Ariakit.MenuButton,
64
+ MenuButton,
62
65
  {
63
66
  accessibleWhenDisabled: true,
64
67
  render: /* @__PURE__ */ jsxs(Button, { accessibleWhenDisabled, children: [
@@ -67,6 +70,7 @@ const DropdownMenuButton = forwardRef(
67
70
  ] }),
68
71
  ...rest,
69
72
  className: cx("\u{1F95D}-dropdown-menu-button", props.className),
73
+ "data-has-popover-open": open || void 0,
70
74
  ref: forwardedRef
71
75
  }
72
76
  );
@@ -74,28 +78,100 @@ const DropdownMenuButton = forwardRef(
74
78
  );
75
79
  const DropdownMenuItem = forwardRef(
76
80
  (props, forwardedRef) => {
77
- const { shortcuts, ...rest } = props;
78
- const shortcutKeys = React.useMemo(() => {
79
- return typeof shortcuts === "string" ? shortcuts.split("+").map((key) => key.trim()) : [];
80
- }, [shortcuts]);
81
- const hasShortcuts = shortcutKeys.length > 0;
81
+ const { label, shortcuts, icon, ...rest } = props;
82
82
  return /* @__PURE__ */ jsxs(
83
- Ariakit.MenuItem,
83
+ MenuItem,
84
84
  {
85
85
  accessibleWhenDisabled: true,
86
86
  ...rest,
87
87
  render: /* @__PURE__ */ jsx(ListItem.Root, { render: props.render }),
88
+ className: cx("\u{1F95D}-dropdown-menu-item", props.className),
88
89
  ref: forwardedRef,
89
90
  children: [
90
- /* @__PURE__ */ jsx(ListItem.Content, { children: props.children }),
91
- hasShortcuts && /* @__PURE__ */ jsx("span", { className: "\u{1F95D}-dropdown-menu-item-shortcuts", children: shortcutKeys.map((key, index) => /* @__PURE__ */ jsx(Kbd, { variant: "ghost", children: key }, `${key + index}`)) })
91
+ icon ? /* @__PURE__ */ jsx(DropdownMenuIcon, { icon }) : null,
92
+ /* @__PURE__ */ jsx(ListItem.Content, { children: label }),
93
+ shortcuts ? /* @__PURE__ */ jsx(DropdownMenuItemShortcuts, { shortcuts }) : null
92
94
  ]
93
95
  }
94
96
  );
95
97
  }
96
98
  );
99
+ const DropdownMenuItemShortcuts = forwardRef((props, forwardedRef) => {
100
+ const { shortcuts, ...rest } = props;
101
+ const shortcutKeys = React.useMemo(() => {
102
+ return shortcuts.split("+").map((key) => ({
103
+ key: key.trim(),
104
+ isSymbol: key in predefinedSymbols
105
+ }));
106
+ }, [shortcuts]);
107
+ return /* @__PURE__ */ jsx(
108
+ ListItem.Decoration,
109
+ {
110
+ ...rest,
111
+ className: cx("\u{1F95D}-dropdown-menu-item-shortcuts", props.className),
112
+ ref: forwardedRef,
113
+ children: shortcutKeys.map(({ key, isSymbol }, index) => {
114
+ if (isSymbol) {
115
+ return /* @__PURE__ */ jsx(
116
+ Kbd,
117
+ {
118
+ variant: "ghost",
119
+ symbol: key
120
+ },
121
+ `${key + index}`
122
+ );
123
+ }
124
+ return /* @__PURE__ */ jsx(Kbd, { variant: "ghost", children: key }, `${key + index}`);
125
+ })
126
+ }
127
+ );
128
+ });
129
+ const DropdownMenuIcon = forwardRef(
130
+ (props, forwardedRef) => {
131
+ const { icon, ...rest } = props;
132
+ return /* @__PURE__ */ jsx(
133
+ ListItem.Decoration,
134
+ {
135
+ render: /* @__PURE__ */ jsx(
136
+ Icon,
137
+ {
138
+ href: typeof icon === "string" ? icon : void 0,
139
+ render: React.isValidElement(icon) ? icon : void 0
140
+ }
141
+ ),
142
+ ...rest,
143
+ ref: forwardedRef
144
+ }
145
+ );
146
+ }
147
+ );
148
+ const DropdownMenuCheckboxItem = forwardRef((props, forwardedRef) => {
149
+ const { label, icon, ...rest } = props;
150
+ return /* @__PURE__ */ jsxs(
151
+ MenuItemCheckbox,
152
+ {
153
+ 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,
159
+ children: [
160
+ icon ? /* @__PURE__ */ jsx(DropdownMenuIcon, { icon }) : null,
161
+ /* @__PURE__ */ jsx(ListItem.Content, { children: label }),
162
+ /* @__PURE__ */ jsx(
163
+ ListItem.Decoration,
164
+ {
165
+ render: /* @__PURE__ */ jsx(Checkmark, { className: "\u{1F95D}-dropdown-menu-checkmark" })
166
+ }
167
+ )
168
+ ]
169
+ }
170
+ );
171
+ });
97
172
  export {
98
173
  DropdownMenuButton as Button,
174
+ DropdownMenuCheckboxItem as CheckboxItem,
99
175
  DropdownMenuContent as Content,
100
176
  DropdownMenuItem as Item,
101
177
  DropdownMenu as Root
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import { useCollectionStore, type CollectionItemProps } from "@ariakit/react/collection";
2
3
  import { type BaseProps } from "./~utils.js";
3
4
  interface FieldProps extends BaseProps {
4
5
  /**
@@ -27,5 +28,26 @@ interface FieldProps extends BaseProps {
27
28
  * - `Switch`
28
29
  */
29
30
  export declare const Field: React.ForwardRefExoticComponent<FieldProps & React.RefAttributes<HTMLElement | HTMLDivElement>>;
30
- export declare function useFieldId(): string | undefined;
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
+ }
41
+ /**
42
+ * An element tracked as a control in the `Field`’s collection.
43
+ */
44
+ export declare function FieldControl(props: FieldCollectionItemControlProps): import("react/jsx-runtime").JSX.Element;
45
+ /**
46
+ * An element tracked as a label in the `Field`’s collection.
47
+ */
48
+ export declare function FieldLabel(props: Pick<CollectionItemProps, "render">): import("react/jsx-runtime").JSX.Element;
49
+ /**
50
+ * An element tracked as a description in the `Field`’s collection.
51
+ */
52
+ export declare function FieldDescription(props: Pick<CollectionItemProps, "render" | "id">): import("react/jsx-runtime").JSX.Element;
31
53
  export {};