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

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 ADDED
@@ -0,0 +1,116 @@
1
+ # Changelog
2
+
3
+ ## 5.0.0-alpha.11
4
+
5
+ - Added `error` prop to `<Tree.Item>`.
6
+ - Implemented fallback strategy for `<Icon>`, so that non-HTTP URLs are fetched at runtime.
7
+ - Added `unstable_htmlSanitizer` prop to `<Root>`.
8
+ - Added `tone="accent"` support to `<Badge>`.
9
+ - Adjusted `DropdownMenu` and `Tooltip` to be portaled by default.
10
+ - Styling changes:
11
+ - Added shimmer animation to `<Skeleton>`.
12
+ - Updated `<Spinner>` visuals and animation to match `<ProgressBar>`.
13
+ - Bug fixes:
14
+ - Fixed styles not unloading when `<Root>` is unmounted.
15
+ - Fixed `<Anchor>` underline not showing when rendered as a `<button>`.
16
+ - Fixed `<Tree.ItemAction visible>` affecting the visibility of all actions.
17
+ - Fixed vertical centering in `<Tab.TabList>`.
18
+ - Fixed `Tab` active stripe positioning and animation.
19
+ - Fixed `<Button variant="solid" tone="accent">` icon fill in pressed state.
20
+
21
+ ## 5.0.0-alpha.10
22
+
23
+ - Added initial `<Skeleton>` component.
24
+ - Added initial `<ProgressBar>` component.
25
+ - Fixed various UX and accessibility issues related to `<Tree.Item>` actions visibility.
26
+ - Actions no longer get stuck.
27
+ - Tooltips can now be hovered.
28
+ - Focus correctly returns to actions after menu closes.
29
+ - Keyboard events no longer affect the main treeitem.
30
+ - Reduced `<Field>` spacing.
31
+ - Experimental changes in `<Icon>` component's `href` handling.
32
+
33
+ ## 5.0.0-alpha.9
34
+
35
+ - Added `dot` prop to `<IconButton>` for showing a small "dot" next to the icon.
36
+ - Added `unstable_decorations` prop to `<Tree.Item>` for showing multiple decorations (e.g. icons).
37
+ - **breaking**: Replaced `<DropdownMenu.Item>` children with new `label` prop (see [#423](https://github.com/iTwin/design-system/pull/423)).
38
+ - Added `icon` prop to `<DropdownMenu.Item>` and `<DropdownMenu.CheckboxItem>`.
39
+ - Updated the `shortcuts` prop of `<DropdownMenu.Item>` to recognize predefined "symbols" (e.g. modifier keys).
40
+ - Updated `<Anchor>` and `<Badge>` visuals to match the latest design.
41
+ - Fixed forced-colors mode styling for `DropdownMenu`.
42
+
43
+ ## 5.0.0-alpha.8
44
+
45
+ - Added `description` prop to `<Tree.Item>` component for showing "sublabels".
46
+ - **breaking**: Updated `<Text>` component to require `variant` prop.
47
+ - (soft breaking) Removed `children` from `<Tree.Item>` prop types.
48
+ - Updated `DropdownMenu` padding.
49
+
50
+ ## 5.0.0-alpha.7
51
+
52
+ - Added new `<Avatar>` component.
53
+ - Added new `<Badge>` component.
54
+ - Added `alt` prop to `<Icon>` component.
55
+ - Fixed all color tokens to use the correct `oklch` values.
56
+ - Fixed an issue where `<Tree.Item>` was not respecting its `style` prop.
57
+
58
+ ## 5.0.0-alpha.6
59
+
60
+ - **breaking**: All CSS variables have been renamed to use the `--ids` prefix. See [#369](https://github.com/iTwin/kiwi/pull/369).
61
+ - **breaking**: Some CSS variables were renamed further. See [#368](https://github.com/iTwin/kiwi/pull/368).
62
+ - Notably, the "surface" backgrounds have been split into two different "page" and "elevation" scales.
63
+ - Background colors have been updated to match the latest design.
64
+ - All styles are now loaded into `@layer itwinui`. The one exception is the CSS reset which remains in `@layer reset`.
65
+ - `<Field>` now respects the order of `<Description>`s when creating associations.
66
+
67
+ ## 5.0.0-alpha.5
68
+
69
+ - **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`.
70
+ - **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)).
71
+ - **breaking**: Replaced `<Chip>` children with new `label` prop (see [#349](https://github.com/iTwin/kiwi/pull/349)).
72
+ - Added `<Tree.ItemAction>` component with `visible` prop for more granular control over action visibility.
73
+ - Updated the layout of `<Field>` so that `<Description>` is placed in the best spot according on the label position and control type.
74
+ - `<Field>` now considers the presence of explicit control `id`s when creating associations.
75
+
76
+ ## 5.0.0-alpha.4
77
+
78
+ - Added `onDismiss` prop and dismiss button to `<Chip>`.
79
+ - Fixed a rare issue where `TextBox` was still editable when `disabled`.
80
+ - Fixed "forced colors" mode styling for `<Button>` and `<IconButton>`.
81
+ - Explicitly set typography styles on `<Root>` to improve compatibility with iTwinUI theme bridge.
82
+ - Updated `DropdownMenu` visuals.
83
+
84
+ ## 5.0.0-alpha.3
85
+
86
+ - Added `<DropdownMenu.CheckboxItem>` component for rendering menu items with a checkable state.
87
+ - Added `variant` prop to `<Select.HtmlSelect>` component for displaying different visual variants of the component.
88
+ - Updated event handling of `Tree` components to avoid firing `onClick` event of the `<Tree.Item>` component when the expander or one of the actions is clicked.
89
+ - Updated `Tree` components to implement a tree view pattern instead of the previously used nested list approach.
90
+ - Updated size and spacing of `<Tree.Item>`, `<DropdownMenu.Item>` and `<Select>` components.
91
+ - Fixed `<Label>` component alignment with `TextBox` components.
92
+ - Fixed action rendering of `<Tree.Item>` component.
93
+ - Fixed `<Checkbox>` component styling, which caused the mixed checkbox to be displayed as unchecked in the light theme.
94
+
95
+ ## 5.0.0-alpha.2
96
+
97
+ - Added initial `Tree` component, exposed as `<Tree.Root>` and `<Tree.Item>` subcomponents.
98
+ - Added initial `<Spinner>` component for indicating quick, indeterminate progress.
99
+ - Added `<Description>` component to be used within a `<Field>`.
100
+ - Added initial `<Chip>` component.
101
+ - Added `symbol` prop to `<Kbd>` for displaying predefined symbols.
102
+ - Added `focusable` prop to `<Tabs.TabPanel>` component.
103
+ - Fixed a visual issue where light color-scheme was using dark shadows.
104
+
105
+ ## 5.0.0-alpha.1
106
+
107
+ - Added `<Text>` component with a `variant` prop to support all text styles from Figma.
108
+ - Added `Select` component built on top of the HTML `<select>` element. Exposed as `<Select.Root>` and `<Select.HtmlSelect>`.
109
+ - Added `shortcuts` prop to `<DropdownMenu.Item>`.
110
+ - Added JSDoc comments to all components for inline IDE hints.
111
+ - Fixed `<Kbd>` component using the wrong font.
112
+ - Fixed some visual issues.
113
+
114
+ ## 5.0.0-alpha.0
115
+
116
+ Initial release 🥳
@@ -45,7 +45,7 @@ const DropdownMenuContent = forwardRef(
45
45
  return /* @__PURE__ */ jsx(
46
46
  Menu,
47
47
  {
48
- portal: popover.portal,
48
+ portal: true,
49
49
  unmountOnHide: true,
50
50
  ...props,
51
51
  gutter: 4,
@@ -2,10 +2,21 @@ import { jsx } 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 { forwardRef } from "./~utils.js";
5
+ import {
6
+ forwardRef,
7
+ getOwnerDocument,
8
+ parseDOM
9
+ } from "./~utils.js";
10
+ import {
11
+ HtmlSanitizerContext,
12
+ spriteSheetId,
13
+ useRootNode
14
+ } from "./Root.internal.js";
15
+ import { useLatestRef, useSafeContext } from "./~hooks.js";
6
16
  const Icon = forwardRef((props, forwardedRef) => {
7
- const { href, size, alt, ...rest } = props;
17
+ const { href: hrefProp, size, alt, ...rest } = props;
8
18
  const isDecorative = !alt;
19
+ const hrefBase = useNormalizedHrefBase(hrefProp);
9
20
  return /* @__PURE__ */ jsx(
10
21
  Role.svg,
11
22
  {
@@ -16,20 +27,82 @@ const Icon = forwardRef((props, forwardedRef) => {
16
27
  "data-kiwi-size": size,
17
28
  className: cx("\u{1F95D}-icon", props.className),
18
29
  ref: forwardedRef,
19
- children: href ? /* @__PURE__ */ jsx("use", { href: toIconHref(href, size) }) : null
30
+ children: hrefBase ? /* @__PURE__ */ jsx("use", { href: toIconHref(hrefBase, size) }) : null
20
31
  }
21
32
  );
22
33
  });
23
34
  DEV: Icon.displayName = "Icon";
24
- function toIconHref(href, size) {
25
- const separator = href.includes("#") ? "--" : "#";
35
+ function toIconHref(hrefBase, size) {
36
+ const separator = hrefBase.includes("#") ? "--" : "#";
26
37
  const suffix = toIconId(size);
27
- return `${href}${separator}${suffix}`;
38
+ return `${hrefBase}${separator}${suffix}`;
28
39
  }
29
40
  function toIconId(size) {
30
41
  if (size === "large") return "icon-large";
31
42
  return "icon";
32
43
  }
44
+ function useNormalizedHrefBase(rawHref) {
45
+ const generatedId = React.useId();
46
+ const sanitizeHtml = useLatestRef(useSafeContext(HtmlSanitizerContext));
47
+ const rootNode = useRootNode();
48
+ const inlineHref = React.useRef(void 0);
49
+ const getClientSnapshot = () => {
50
+ const ownerDocument = getOwnerDocument(rootNode);
51
+ if (!rawHref || !ownerDocument) return void 0;
52
+ if (isHttpProtocol(rawHref, ownerDocument)) return rawHref;
53
+ return inlineHref.current;
54
+ };
55
+ const subscribe = React.useCallback(
56
+ (notify) => {
57
+ const ownerDocument = getOwnerDocument(rootNode);
58
+ const spriteSheet = ownerDocument?.getElementById(spriteSheetId);
59
+ if (!rawHref || !ownerDocument || !spriteSheet) return () => {
60
+ };
61
+ if (isHttpProtocol(rawHref, ownerDocument)) return () => {
62
+ };
63
+ const cache = spriteSheet[Symbol.for("\u{1F95D}")]?.icons;
64
+ if (!cache) return () => {
65
+ };
66
+ const prefix = `\u{1F95D}${generatedId}`;
67
+ if (cache.has(rawHref)) {
68
+ inlineHref.current = cache.get(rawHref);
69
+ notify();
70
+ return () => {
71
+ };
72
+ }
73
+ const abortController = new AbortController();
74
+ const { signal } = abortController;
75
+ (async () => {
76
+ const response = await fetch(rawHref, { signal });
77
+ if (!response.ok) throw new Error(`Failed to fetch ${rawHref}`);
78
+ const fetchedSvgString = sanitizeHtml.current(await response.text());
79
+ const parsedSvgContent = parseDOM(fetchedSvgString, {
80
+ ownerDocument
81
+ });
82
+ const symbols = parsedSvgContent.querySelectorAll("symbol");
83
+ for (const symbol of symbols) {
84
+ symbol.id = `${prefix}--${symbol.id}`;
85
+ if (ownerDocument.getElementById(symbol.id)) continue;
86
+ spriteSheet.appendChild(symbol.cloneNode(true));
87
+ }
88
+ inlineHref.current = `#${prefix}`;
89
+ cache.set(rawHref, inlineHref.current);
90
+ if (!signal.aborted) notify();
91
+ })();
92
+ return () => abortController.abort();
93
+ },
94
+ [rawHref, rootNode, sanitizeHtml, generatedId]
95
+ );
96
+ return React.useSyncExternalStore(
97
+ subscribe,
98
+ getClientSnapshot,
99
+ () => rawHref
100
+ );
101
+ }
102
+ function isHttpProtocol(url, ownerDocument) {
103
+ const { protocol } = new URL(url, ownerDocument.baseURI);
104
+ return ["http:", "https:"].includes(protocol);
105
+ }
33
106
  const DisclosureArrow = forwardRef(
34
107
  (props, forwardedRef) => {
35
108
  const { direction = "down", ...rest } = props;
@@ -116,9 +189,41 @@ const Dismiss = forwardRef(
116
189
  }
117
190
  );
118
191
  DEV: Dismiss.displayName = "Dismiss";
192
+ const StatusWarning = forwardRef(
193
+ (props, forwardedRef) => {
194
+ return /* @__PURE__ */ jsx(
195
+ Icon,
196
+ {
197
+ ...props,
198
+ render: /* @__PURE__ */ jsx(
199
+ Role.svg,
200
+ {
201
+ width: "16",
202
+ height: "16",
203
+ fill: "currentColor",
204
+ viewBox: "0 0 16 16",
205
+ render: props.render,
206
+ children: /* @__PURE__ */ jsx(
207
+ "path",
208
+ {
209
+ fill: "currentColor",
210
+ fillRule: "evenodd",
211
+ d: "M8.354 2.06a.5.5 0 0 0-.708 0L2.061 7.647a.5.5 0 0 0 0 .707l5.585 5.586a.5.5 0 0 0 .708 0l5.585-5.586a.5.5 0 0 0 0-.707L8.354 2.061Zm-1.415-.707a1.5 1.5 0 0 1 2.122 0l5.585 5.586a1.5 1.5 0 0 1 0 2.122l-5.585 5.585a1.5 1.5 0 0 1-2.122 0L1.354 9.061a1.5 1.5 0 0 1 0-2.122l5.585-5.586ZM8.75 10.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM8.5 8.5v-3a.5.5 0 0 0-1 0v3a.5.5 0 0 0 1 0Z",
212
+ clipRule: "evenodd"
213
+ }
214
+ )
215
+ }
216
+ ),
217
+ ref: forwardedRef
218
+ }
219
+ );
220
+ }
221
+ );
222
+ DEV: StatusWarning.displayName = "StatusWarning";
119
223
  export {
120
224
  Checkmark,
121
225
  DisclosureArrow,
122
226
  Dismiss,
123
- Icon
227
+ Icon,
228
+ StatusWarning
124
229
  };
@@ -0,0 +1,17 @@
1
+ import * as React from "react";
2
+ import { useIsClient } from "./~hooks.js";
3
+ const RootNodeContext = React.createContext(null);
4
+ function useRootNode() {
5
+ const maybeRootNode = React.useContext(RootNodeContext);
6
+ const isClient = useIsClient();
7
+ if (!isClient) return void 0;
8
+ return maybeRootNode;
9
+ }
10
+ const spriteSheetId = "\u{1F95D}-inline-sprites";
11
+ const HtmlSanitizerContext = React.createContext(void 0);
12
+ export {
13
+ HtmlSanitizerContext,
14
+ RootNodeContext,
15
+ spriteSheetId,
16
+ useRootNode
17
+ };
@@ -6,15 +6,33 @@ import { PortalContext } from "@ariakit/react/portal";
6
6
  import cx from "classnames";
7
7
  import foundationsCss from "../foundations/styles.css.js";
8
8
  import bricksCss from "./styles.css.js";
9
- import { forwardRef, isBrowser } from "./~utils.js";
10
- import { useIsClient, useMergedRefs } from "./~hooks.js";
9
+ import {
10
+ forwardRef,
11
+ getOwnerDocument,
12
+ identity,
13
+ isBrowser,
14
+ isDocument
15
+ } from "./~utils.js";
16
+ import { useLayoutEffect, useMergedRefs } from "./~hooks.js";
17
+ import {
18
+ HtmlSanitizerContext,
19
+ RootNodeContext,
20
+ spriteSheetId,
21
+ useRootNode
22
+ } from "./Root.internal.js";
11
23
  const css = foundationsCss + bricksCss;
12
24
  const Root = forwardRef((props, forwardedRef) => {
13
- const { children, synchronizeColorScheme = false, ...rest } = props;
25
+ const {
26
+ children,
27
+ synchronizeColorScheme = false,
28
+ unstable_htmlSanitizer = identity,
29
+ ...rest
30
+ } = props;
14
31
  const [portalContainer, setPortalContainer] = React.useState(null);
15
32
  return /* @__PURE__ */ jsxs(RootInternal, { ...rest, ref: forwardedRef, children: [
16
33
  /* @__PURE__ */ jsx(Styles, {}),
17
34
  /* @__PURE__ */ jsx(Fonts, {}),
35
+ /* @__PURE__ */ jsx(InlineSpriteSheet, {}),
18
36
  synchronizeColorScheme ? /* @__PURE__ */ jsx(SynchronizeColorScheme, { colorScheme: props.colorScheme }) : null,
19
37
  /* @__PURE__ */ jsx(
20
38
  PortalContainer,
@@ -24,14 +42,10 @@ const Root = forwardRef((props, forwardedRef) => {
24
42
  ref: setPortalContainer
25
43
  }
26
44
  ),
27
- /* @__PURE__ */ jsx(PortalContext.Provider, { value: portalContainer, children })
45
+ /* @__PURE__ */ jsx(PortalContext.Provider, { value: portalContainer, children: /* @__PURE__ */ jsx(HtmlSanitizerContext.Provider, { value: unstable_htmlSanitizer, children }) })
28
46
  ] });
29
47
  });
30
48
  DEV: Root.displayName = "Root";
31
- const RootNodeContext = React.createContext(null);
32
- function useRootNode() {
33
- return React.useContext(RootNodeContext);
34
- }
35
49
  const RootInternal = forwardRef(
36
50
  (props, forwardedRef) => {
37
51
  const { children, colorScheme, density, ...rest } = props;
@@ -72,10 +86,9 @@ function SynchronizeColorScheme({
72
86
  return null;
73
87
  }
74
88
  const PortalContainer = forwardRef((props, forwardedRef) => {
75
- const isClient = useIsClient();
76
89
  const rootNode = useRootNode();
77
- if (!isClient) return null;
78
- const destination = rootNode && isDocument(rootNode) ? rootNode.body : rootNode;
90
+ if (!rootNode) return null;
91
+ const destination = isDocument(rootNode) ? rootNode.body : rootNode;
79
92
  if (!destination) return null;
80
93
  return ReactDOM.createPortal(
81
94
  /* @__PURE__ */ jsx(
@@ -95,35 +108,46 @@ function Styles() {
95
108
  const rootNode = useRootNode();
96
109
  useLayoutEffect(() => {
97
110
  if (!rootNode) return;
98
- loadStyles(rootNode, { css });
111
+ const { cleanup } = loadStyles(rootNode, { css });
112
+ return cleanup;
99
113
  }, [rootNode]);
100
114
  return null;
101
115
  }
102
- const styleSheets = /* @__PURE__ */ new WeakMap();
103
- function loadStyles(rootNode, { css: css2 }) {
116
+ const styleSheets = new Map(
117
+ Object.entries({ default: /* @__PURE__ */ new WeakMap() })
118
+ );
119
+ function loadStyles(rootNode, { css: css2, key = "default" }) {
120
+ let cleanup = () => {
121
+ };
104
122
  const loaded = (() => {
105
123
  if (!isBrowser) return false;
106
124
  const ownerDocument = getOwnerDocument(rootNode);
107
125
  const _window = getWindow(rootNode);
108
126
  if (!ownerDocument || !_window) return false;
109
- if (!supportsAdoptedStylesheets && !rootNode.querySelector("style[data-kiwi]")) {
127
+ if (!supportsAdoptedStylesheets && !rootNode.querySelector(`style[data-kiwi="${key}"]`)) {
110
128
  const styleElement = ownerDocument.createElement("style");
111
- styleElement.dataset.kiwi = "true";
129
+ styleElement.dataset.kiwi = key;
112
130
  styleElement.textContent = css2;
113
131
  (rootNode.head || rootNode).appendChild(styleElement);
132
+ cleanup = () => styleElement.remove();
114
133
  return true;
115
134
  }
116
- const styleSheet = styleSheets.get(_window) || new _window.CSSStyleSheet();
117
- if (!styleSheets.has(_window)) {
118
- styleSheets.set(_window, styleSheet);
135
+ const styleSheet = styleSheets.get(key)?.get(_window) || new _window.CSSStyleSheet();
136
+ if (!styleSheets.get(key)?.has(_window)) {
137
+ styleSheets.get(key)?.set(_window, styleSheet);
119
138
  }
120
139
  styleSheet.replaceSync(css2);
121
140
  if (!rootNode.adoptedStyleSheets.includes(styleSheet)) {
122
141
  rootNode.adoptedStyleSheets.push(styleSheet);
142
+ cleanup = () => {
143
+ rootNode.adoptedStyleSheets = rootNode.adoptedStyleSheets.filter(
144
+ (sheet) => sheet !== styleSheet
145
+ );
146
+ };
123
147
  }
124
148
  return true;
125
149
  })();
126
- return { loaded };
150
+ return { loaded, cleanup };
127
151
  }
128
152
  function Fonts() {
129
153
  const rootNode = useRootNode();
@@ -133,6 +157,35 @@ function Fonts() {
133
157
  }, [rootNode]);
134
158
  return null;
135
159
  }
160
+ function InlineSpriteSheet() {
161
+ const rootNode = useRootNode();
162
+ React.useEffect(
163
+ function maybeCreateSpriteSheet() {
164
+ const ownerDocument = getOwnerDocument(rootNode);
165
+ if (!ownerDocument) return;
166
+ const spriteSheet = ownerDocument?.getElementById(spriteSheetId);
167
+ if (spriteSheet) return;
168
+ const svg = ownerDocument.createElementNS(
169
+ "http://www.w3.org/2000/svg",
170
+ "svg"
171
+ );
172
+ svg.id = spriteSheetId;
173
+ svg.style.display = "none";
174
+ Object.defineProperty(svg, Symbol.for("\u{1F95D}"), {
175
+ value: { icons: /* @__PURE__ */ new Map() }
176
+ // Map of icon URLs that have already been inlined.
177
+ });
178
+ ownerDocument.body.appendChild(svg);
179
+ return () => {
180
+ if (svg.isConnected) {
181
+ ownerDocument.body.removeChild(svg);
182
+ }
183
+ };
184
+ },
185
+ [rootNode]
186
+ );
187
+ return null;
188
+ }
136
189
  function loadFonts(rootNode) {
137
190
  const ownerWindow = getWindow(rootNode);
138
191
  if (!ownerWindow || Array.from(ownerWindow.document.fonts).some(
@@ -161,17 +214,10 @@ const supportsAdoptedStylesheets = isBrowser && "adoptedStyleSheets" in Document
161
214
  function isShadow(node) {
162
215
  return node instanceof ShadowRoot || node?.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !!node?.host;
163
216
  }
164
- function isDocument(node) {
165
- return node?.nodeType === Node.DOCUMENT_NODE;
166
- }
167
- function getOwnerDocument(node) {
168
- return (isDocument(node) ? node : node.ownerDocument) || null;
169
- }
170
217
  function getWindow(node) {
171
218
  const ownerDocument = getOwnerDocument(node);
172
219
  return ownerDocument?.defaultView || null;
173
220
  }
174
- const useLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
175
221
  export {
176
222
  Root
177
223
  };
@@ -17,17 +17,32 @@ const Spinner = forwardRef(
17
17
  ...rest,
18
18
  "data-kiwi-size": size,
19
19
  "data-kiwi-tone": tone,
20
+ "data-kiwi-variant": "indeterminate",
20
21
  className: cx("\u{1F95D}-spinner", props.className),
21
22
  ref: forwardedRef,
22
23
  children: [
23
- /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", className: "\u{1F95D}-spinner-svg", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx(
24
- "path",
25
- {
26
- stroke: "currentColor",
27
- strokeLinecap: "round",
28
- d: "M9.5 1.674a6.503 6.503 0 0 1 0 12.652m-3-12.652a6.503 6.503 0 0 0 0 12.652"
29
- }
30
- ) }),
24
+ /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", className: "\u{1F95D}-spinner-svg", viewBox: "0 0 16 16", children: [
25
+ /* @__PURE__ */ jsx(
26
+ "circle",
27
+ {
28
+ pathLength: "100",
29
+ className: "\u{1F95D}-spinner-svg-track",
30
+ cx: "8",
31
+ cy: "8",
32
+ r: "6.5"
33
+ }
34
+ ),
35
+ /* @__PURE__ */ jsx(
36
+ "circle",
37
+ {
38
+ pathLength: "100",
39
+ className: "\u{1F95D}-spinner-svg-fill",
40
+ cx: "8",
41
+ cy: "8",
42
+ r: "6.5"
43
+ }
44
+ )
45
+ ] }),
31
46
  /* @__PURE__ */ jsx(VisuallyHidden, { children: alt })
32
47
  ]
33
48
  }
@@ -43,6 +43,7 @@ const Tooltip = forwardRef(
43
43
  AkTooltip.Tooltip,
44
44
  {
45
45
  "aria-hidden": "true",
46
+ portal: true,
46
47
  ...rest,
47
48
  unmountOnHide,
48
49
  className: cx("\u{1F95D}-tooltip", props.className),
@@ -53,7 +54,6 @@ const Tooltip = forwardRef(
53
54
  ...props.style
54
55
  },
55
56
  wrapperProps: popover.wrapperProps,
56
- portal: popover.portal,
57
57
  children: content
58
58
  }
59
59
  )
@@ -8,7 +8,7 @@ import {
8
8
  import { Toolbar } from "@ariakit/react/toolbar";
9
9
  import * as ListItem from "./~utils.ListItem.js";
10
10
  import { IconButton } from "./IconButton.js";
11
- import { Icon } from "./Icon.js";
11
+ import { Icon, StatusWarning } from "./Icon.js";
12
12
  import { forwardRef } from "./~utils.js";
13
13
  import { useEventHandlers } from "./~hooks.js";
14
14
  import { GhostAligner, useGhostAlignment } from "./~utils.GhostAligner.js";
@@ -19,11 +19,12 @@ const TreeItemRoot = forwardRef(
19
19
  "aria-level": level,
20
20
  selected,
21
21
  expanded,
22
- icon,
22
+ icon: iconProp,
23
23
  unstable_decorations,
24
24
  label,
25
25
  description,
26
26
  actions,
27
+ error,
27
28
  onSelectedChange,
28
29
  onExpandedChange,
29
30
  onClick: onClickProp,
@@ -48,6 +49,7 @@ const TreeItemRoot = forwardRef(
48
49
  const labelId = React.useId();
49
50
  const descriptionId = React.useId();
50
51
  const decorationId = React.useId();
52
+ const icon = error ? /* @__PURE__ */ jsx(StatusWarning, {}) : iconProp;
51
53
  const describedBy = React.useMemo(() => {
52
54
  const idRefs = [];
53
55
  if (description) idRefs.push(descriptionId);
@@ -90,6 +92,7 @@ const TreeItemRoot = forwardRef(
90
92
  {
91
93
  "data-kiwi-expanded": expanded,
92
94
  "data-kiwi-selected": selected,
95
+ "data-kiwi-error": error ? true : void 0,
93
96
  className: "\u{1F95D}-tree-item-node",
94
97
  style: { "--\u{1F95D}tree-item-level": level },
95
98
  role: void 0,
@@ -146,7 +149,7 @@ const TreeItemActions = forwardRef((props, forwardedRef) => {
146
149
  ...props,
147
150
  onClick: useEventHandlers(props.onClick, (e) => e.stopPropagation()),
148
151
  onKeyDown: useEventHandlers(props.onKeyDown, (e) => e.stopPropagation()),
149
- className: cx("\u{1F95D}-tree-item-actions", props.className),
152
+ className: cx("\u{1F95D}-tree-item-actions-container", props.className),
150
153
  ref: forwardedRef,
151
154
  children: props.children
152
155
  }