@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.
- package/CHANGELOG.md +134 -0
- package/README.md +13 -2
- package/dist/DEV/bricks/Checkbox.js +7 -14
- package/dist/DEV/bricks/Description.js +7 -14
- package/dist/DEV/bricks/DropdownMenu.js +58 -20
- package/dist/DEV/bricks/Field.internal.js +47 -0
- package/dist/DEV/bricks/Field.js +116 -85
- package/dist/DEV/bricks/Icon.js +144 -7
- package/dist/DEV/bricks/Label.js +4 -10
- package/dist/DEV/bricks/Radio.js +7 -14
- package/dist/DEV/bricks/Root.internal.js +17 -0
- package/dist/DEV/bricks/Root.js +73 -27
- package/dist/DEV/bricks/Select.js +9 -15
- package/dist/DEV/bricks/Spinner.js +23 -8
- package/dist/DEV/bricks/Switch.js +8 -15
- package/dist/DEV/bricks/Table.js +71 -37
- package/dist/DEV/bricks/Tabs.js +4 -29
- package/dist/DEV/bricks/TextBox.js +23 -37
- package/dist/DEV/bricks/Tooltip.js +1 -1
- package/dist/DEV/bricks/TreeItem.js +92 -10
- package/dist/DEV/bricks/index.js +3 -1
- package/dist/DEV/bricks/styles.css.js +1 -1
- package/dist/DEV/bricks/~hooks.js +3 -1
- package/dist/DEV/bricks/~utils.js +17 -0
- package/dist/DEV/foundations/styles.css.js +1 -1
- package/dist/bricks/Badge.d.ts +1 -1
- package/dist/bricks/Checkbox.d.ts +13 -5
- package/dist/bricks/Checkbox.js +7 -14
- package/dist/bricks/Description.d.ts +2 -6
- package/dist/bricks/Description.js +7 -14
- package/dist/bricks/DropdownMenu.d.ts +9 -9
- package/dist/bricks/DropdownMenu.js +57 -19
- package/dist/bricks/Field.d.ts +63 -27
- package/dist/bricks/Field.internal.d.ts +33 -0
- package/dist/bricks/Field.internal.js +47 -0
- package/dist/bricks/Field.js +111 -84
- package/dist/bricks/Icon.d.ts +12 -1
- package/dist/bricks/Icon.js +142 -7
- package/dist/bricks/Label.d.ts +5 -12
- package/dist/bricks/Label.js +4 -10
- package/dist/bricks/Radio.d.ts +14 -5
- package/dist/bricks/Radio.js +7 -14
- package/dist/bricks/Root.d.ts +12 -0
- package/dist/bricks/Root.internal.d.ts +6 -0
- package/dist/bricks/Root.internal.js +17 -0
- package/dist/bricks/Root.js +73 -27
- package/dist/bricks/Select.d.ts +29 -12
- package/dist/bricks/Select.js +9 -15
- package/dist/bricks/Spinner.js +23 -8
- package/dist/bricks/Switch.d.ts +12 -5
- package/dist/bricks/Switch.js +8 -15
- package/dist/bricks/Table.d.ts +94 -37
- package/dist/bricks/Table.js +69 -36
- package/dist/bricks/Tabs.d.ts +3 -4
- package/dist/bricks/Tabs.js +4 -29
- package/dist/bricks/TextBox.d.ts +42 -19
- package/dist/bricks/TextBox.js +23 -37
- package/dist/bricks/Tooltip.js +1 -1
- package/dist/bricks/TreeItem.d.ts +53 -9
- package/dist/bricks/TreeItem.js +81 -10
- package/dist/bricks/index.d.ts +2 -1
- package/dist/bricks/index.js +3 -1
- package/dist/bricks/styles.css.js +1 -1
- package/dist/bricks/~hooks.d.ts +8 -0
- package/dist/bricks/~hooks.js +3 -1
- package/dist/bricks/~utils.d.ts +8 -0
- package/dist/bricks/~utils.js +17 -0
- package/dist/foundations/styles.css.js +1 -1
- package/package.json +1 -1
package/dist/bricks/Icon.js
CHANGED
|
@@ -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 {
|
|
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,19 +27,81 @@ 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:
|
|
30
|
+
children: hrefBase ? /* @__PURE__ */ jsx("use", { href: toIconHref(hrefBase, size) }) : null
|
|
20
31
|
}
|
|
21
32
|
);
|
|
22
33
|
});
|
|
23
|
-
function toIconHref(
|
|
24
|
-
const separator =
|
|
34
|
+
function toIconHref(hrefBase, size) {
|
|
35
|
+
const separator = hrefBase.includes("#") ? "--" : "#";
|
|
25
36
|
const suffix = toIconId(size);
|
|
26
|
-
return `${
|
|
37
|
+
return `${hrefBase}${separator}${suffix}`;
|
|
27
38
|
}
|
|
28
39
|
function toIconId(size) {
|
|
29
40
|
if (size === "large") return "icon-large";
|
|
30
41
|
return "icon";
|
|
31
42
|
}
|
|
43
|
+
function useNormalizedHrefBase(rawHref) {
|
|
44
|
+
const generatedId = React.useId();
|
|
45
|
+
const sanitizeHtml = useLatestRef(useSafeContext(HtmlSanitizerContext));
|
|
46
|
+
const rootNode = useRootNode();
|
|
47
|
+
const inlineHref = React.useRef(void 0);
|
|
48
|
+
const getClientSnapshot = () => {
|
|
49
|
+
const ownerDocument = getOwnerDocument(rootNode);
|
|
50
|
+
if (!rawHref || !ownerDocument) return void 0;
|
|
51
|
+
if (isHttpProtocol(rawHref, ownerDocument)) return rawHref;
|
|
52
|
+
return inlineHref.current;
|
|
53
|
+
};
|
|
54
|
+
const subscribe = React.useCallback(
|
|
55
|
+
(notify) => {
|
|
56
|
+
const ownerDocument = getOwnerDocument(rootNode);
|
|
57
|
+
const spriteSheet = ownerDocument?.getElementById(spriteSheetId);
|
|
58
|
+
if (!rawHref || !ownerDocument || !spriteSheet) return () => {
|
|
59
|
+
};
|
|
60
|
+
if (isHttpProtocol(rawHref, ownerDocument)) return () => {
|
|
61
|
+
};
|
|
62
|
+
const cache = spriteSheet[Symbol.for("\u{1F95D}")]?.icons;
|
|
63
|
+
if (!cache) return () => {
|
|
64
|
+
};
|
|
65
|
+
const prefix = `\u{1F95D}${generatedId}`;
|
|
66
|
+
if (cache.has(rawHref)) {
|
|
67
|
+
inlineHref.current = cache.get(rawHref);
|
|
68
|
+
notify();
|
|
69
|
+
return () => {
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const abortController = new AbortController();
|
|
73
|
+
const { signal } = abortController;
|
|
74
|
+
(async () => {
|
|
75
|
+
const response = await fetch(rawHref, { signal });
|
|
76
|
+
if (!response.ok) throw new Error(`Failed to fetch ${rawHref}`);
|
|
77
|
+
const fetchedSvgString = sanitizeHtml.current(await response.text());
|
|
78
|
+
const parsedSvgContent = parseDOM(fetchedSvgString, {
|
|
79
|
+
ownerDocument
|
|
80
|
+
});
|
|
81
|
+
const symbols = parsedSvgContent.querySelectorAll("symbol");
|
|
82
|
+
for (const symbol of symbols) {
|
|
83
|
+
symbol.id = `${prefix}--${symbol.id}`;
|
|
84
|
+
if (ownerDocument.getElementById(symbol.id)) continue;
|
|
85
|
+
spriteSheet.appendChild(symbol.cloneNode(true));
|
|
86
|
+
}
|
|
87
|
+
inlineHref.current = `#${prefix}`;
|
|
88
|
+
cache.set(rawHref, inlineHref.current);
|
|
89
|
+
if (!signal.aborted) notify();
|
|
90
|
+
})();
|
|
91
|
+
return () => abortController.abort();
|
|
92
|
+
},
|
|
93
|
+
[rawHref, rootNode, sanitizeHtml, generatedId]
|
|
94
|
+
);
|
|
95
|
+
return React.useSyncExternalStore(
|
|
96
|
+
subscribe,
|
|
97
|
+
getClientSnapshot,
|
|
98
|
+
() => rawHref
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
function isHttpProtocol(url, ownerDocument) {
|
|
102
|
+
const { protocol } = new URL(url, ownerDocument.baseURI);
|
|
103
|
+
return ["http:", "https:"].includes(protocol);
|
|
104
|
+
}
|
|
32
105
|
const DisclosureArrow = forwardRef(
|
|
33
106
|
(props, forwardedRef) => {
|
|
34
107
|
const { direction = "down", ...rest } = props;
|
|
@@ -112,9 +185,71 @@ const Dismiss = forwardRef(
|
|
|
112
185
|
);
|
|
113
186
|
}
|
|
114
187
|
);
|
|
188
|
+
const StatusWarning = forwardRef(
|
|
189
|
+
(props, forwardedRef) => {
|
|
190
|
+
return /* @__PURE__ */ jsx(
|
|
191
|
+
Icon,
|
|
192
|
+
{
|
|
193
|
+
...props,
|
|
194
|
+
render: /* @__PURE__ */ jsx(
|
|
195
|
+
Role.svg,
|
|
196
|
+
{
|
|
197
|
+
width: "16",
|
|
198
|
+
height: "16",
|
|
199
|
+
fill: "currentColor",
|
|
200
|
+
viewBox: "0 0 16 16",
|
|
201
|
+
render: props.render,
|
|
202
|
+
children: /* @__PURE__ */ jsx(
|
|
203
|
+
"path",
|
|
204
|
+
{
|
|
205
|
+
fill: "currentColor",
|
|
206
|
+
fillRule: "evenodd",
|
|
207
|
+
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",
|
|
208
|
+
clipRule: "evenodd"
|
|
209
|
+
}
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
),
|
|
213
|
+
ref: forwardedRef
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
const MoreHorizontal = forwardRef(
|
|
219
|
+
(props, forwardedRef) => {
|
|
220
|
+
return /* @__PURE__ */ jsx(
|
|
221
|
+
Icon,
|
|
222
|
+
{
|
|
223
|
+
...props,
|
|
224
|
+
render: /* @__PURE__ */ jsx(
|
|
225
|
+
Role.svg,
|
|
226
|
+
{
|
|
227
|
+
width: "16",
|
|
228
|
+
height: "16",
|
|
229
|
+
viewBox: "0 0 16 16",
|
|
230
|
+
fill: "none",
|
|
231
|
+
render: props.render,
|
|
232
|
+
children: /* @__PURE__ */ jsx(
|
|
233
|
+
"path",
|
|
234
|
+
{
|
|
235
|
+
fill: "currentColor",
|
|
236
|
+
fillRule: "evenodd",
|
|
237
|
+
d: "M3 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2Zm6-1a1 1 0 1 1-2 0 1 1 0 0 1 2 0Zm5 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z",
|
|
238
|
+
clipRule: "evenodd"
|
|
239
|
+
}
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
),
|
|
243
|
+
ref: forwardedRef
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
);
|
|
115
248
|
export {
|
|
116
249
|
Checkmark,
|
|
117
250
|
DisclosureArrow,
|
|
118
251
|
Dismiss,
|
|
119
|
-
Icon
|
|
252
|
+
Icon,
|
|
253
|
+
MoreHorizontal,
|
|
254
|
+
StatusWarning
|
|
120
255
|
};
|
package/dist/bricks/Label.d.ts
CHANGED
|
@@ -2,24 +2,17 @@ import { type BaseProps } from "./~utils.js";
|
|
|
2
2
|
interface LabelProps extends BaseProps<"label"> {
|
|
3
3
|
}
|
|
4
4
|
/**
|
|
5
|
-
* A styled wrapper over the HTML `<label>` element, used for labelling form
|
|
5
|
+
* A styled wrapper over the HTML `<label>` element, used for labelling form
|
|
6
|
+
* controls.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
|
|
8
|
+
* Example usage:
|
|
9
9
|
* ```tsx
|
|
10
10
|
* <Label htmlFor="my-input">Label</Label>
|
|
11
11
|
* <TextBox.Input id="my-input" />
|
|
12
12
|
* ```
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* ```tsx
|
|
17
|
-
* <Field>
|
|
18
|
-
* <Label>Label</Label>
|
|
19
|
-
* <TextBox.Input />
|
|
20
|
-
* </Field>
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
14
|
+
* See `Field.Label` for convenient usage with form controls (e.g. automatic
|
|
15
|
+
* association with adjacent form control).
|
|
23
16
|
*/
|
|
24
17
|
export declare const Label: import("react").ForwardRefExoticComponent<LabelProps & import("react").RefAttributes<HTMLElement | HTMLLabelElement>>;
|
|
25
18
|
export {};
|
package/dist/bricks/Label.js
CHANGED
|
@@ -2,19 +2,13 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import cx from "classnames";
|
|
3
3
|
import { Role } from "@ariakit/react/role";
|
|
4
4
|
import { forwardRef } from "./~utils.js";
|
|
5
|
-
import { FieldLabel } from "./Field.js";
|
|
6
5
|
const Label = forwardRef((props, forwardedRef) => {
|
|
7
6
|
return /* @__PURE__ */ jsx(
|
|
8
|
-
|
|
7
|
+
Role.label,
|
|
9
8
|
{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
...props,
|
|
14
|
-
className: cx("\u{1F95D}-label", props.className),
|
|
15
|
-
ref: forwardedRef
|
|
16
|
-
}
|
|
17
|
-
)
|
|
9
|
+
...props,
|
|
10
|
+
className: cx("\u{1F95D}-label", props.className),
|
|
11
|
+
ref: forwardedRef
|
|
18
12
|
}
|
|
19
13
|
);
|
|
20
14
|
});
|
package/dist/bricks/Radio.d.ts
CHANGED
|
@@ -7,13 +7,22 @@ interface RadioProps extends InputBaseProps, RadioOwnProps {
|
|
|
7
7
|
/**
|
|
8
8
|
* A styled radio input element, typically used for selecting a single option from a list.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* Use with the `Field` components to automatically handle ID associations for
|
|
11
|
+
* labels and descriptions:
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Field.Root>
|
|
14
|
+
* <Field.Label>Choose one</Field.Label>
|
|
15
|
+
* <Field.Control render={<Radio />} />
|
|
16
|
+
* </Field.Root>
|
|
17
|
+
* ```
|
|
11
18
|
*
|
|
19
|
+
* Without the `Field` components you will need to manually associate labels,
|
|
20
|
+
* descriptions, etc.:
|
|
12
21
|
* ```tsx
|
|
13
|
-
* <
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* </
|
|
22
|
+
* <Radio id="editor-vim" name="editor" value="vim" />
|
|
23
|
+
* <Label htmlFor="editor-vim">Vim</Label>
|
|
24
|
+
* <Radio id="editor-emacs" name="editor" value="emacs" />
|
|
25
|
+
* <Label htmlFor="editor-emacs">Emacs</Label>
|
|
17
26
|
* ```
|
|
18
27
|
*
|
|
19
28
|
* Underneath, it's an HTML radio input, i.e. `<input type="radio">`, so it supports the same props,
|
package/dist/bricks/Radio.js
CHANGED
|
@@ -3,24 +3,17 @@ import cx from "classnames";
|
|
|
3
3
|
import {
|
|
4
4
|
Radio as AkRadio
|
|
5
5
|
} from "@ariakit/react/radio";
|
|
6
|
-
import { FieldControl } from "./Field.js";
|
|
7
6
|
import { forwardRef } from "./~utils.js";
|
|
7
|
+
import { useFieldControlType } from "./Field.internal.js";
|
|
8
8
|
const Radio = forwardRef((props, forwardedRef) => {
|
|
9
|
-
|
|
9
|
+
useFieldControlType("checkable");
|
|
10
10
|
return /* @__PURE__ */ jsx(
|
|
11
|
-
|
|
11
|
+
AkRadio,
|
|
12
12
|
{
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
{
|
|
18
|
-
accessibleWhenDisabled: true,
|
|
19
|
-
...rest,
|
|
20
|
-
className: cx("\u{1F95D}-checkbox", "\u{1F95D}-radio", props.className),
|
|
21
|
-
ref: forwardedRef
|
|
22
|
-
}
|
|
23
|
-
)
|
|
13
|
+
accessibleWhenDisabled: true,
|
|
14
|
+
...props,
|
|
15
|
+
className: cx("\u{1F95D}-checkbox", "\u{1F95D}-radio", props.className),
|
|
16
|
+
ref: forwardedRef
|
|
24
17
|
}
|
|
25
18
|
);
|
|
26
19
|
});
|
package/dist/bricks/Root.d.ts
CHANGED
|
@@ -17,6 +17,18 @@ interface RootProps extends BaseProps {
|
|
|
17
17
|
* The density to use for all components under the Root.
|
|
18
18
|
*/
|
|
19
19
|
density: "dense";
|
|
20
|
+
/**
|
|
21
|
+
* An HTML sanitizer function that will be used across all components wherever DOM elements
|
|
22
|
+
* are created from HTML strings.
|
|
23
|
+
*
|
|
24
|
+
* When this prop is not passed, sanitization will be skipped.
|
|
25
|
+
*
|
|
26
|
+
* Example:
|
|
27
|
+
* ```tsx
|
|
28
|
+
* unstablized_htmlSanitizer={DOMPurify.sanitize}
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
unstable_htmlSanitizer?: (html: string) => string;
|
|
20
32
|
}
|
|
21
33
|
/**
|
|
22
34
|
* Component to be used at the root of your application. It ensures that kiwi styles and fonts are loaded
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export declare const RootNodeContext: React.Context<Document | ShadowRoot | null>;
|
|
3
|
+
/** Returns the closest [rootNode](https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode). */
|
|
4
|
+
export declare function useRootNode(): Document | ShadowRoot | null | undefined;
|
|
5
|
+
export declare const spriteSheetId = "\uD83E\uDD5D-inline-sprites";
|
|
6
|
+
export declare const HtmlSanitizerContext: React.Context<((html: string) => string) | undefined>;
|
|
@@ -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
|
+
};
|
package/dist/bricks/Root.js
CHANGED
|
@@ -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 {
|
|
10
|
-
|
|
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 {
|
|
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,13 +42,9 @@ 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
|
-
const RootNodeContext = React.createContext(null);
|
|
31
|
-
function useRootNode() {
|
|
32
|
-
return React.useContext(RootNodeContext);
|
|
33
|
-
}
|
|
34
48
|
const RootInternal = forwardRef(
|
|
35
49
|
(props, forwardedRef) => {
|
|
36
50
|
const { children, colorScheme, density, ...rest } = props;
|
|
@@ -71,10 +85,9 @@ function SynchronizeColorScheme({
|
|
|
71
85
|
return null;
|
|
72
86
|
}
|
|
73
87
|
const PortalContainer = forwardRef((props, forwardedRef) => {
|
|
74
|
-
const isClient = useIsClient();
|
|
75
88
|
const rootNode = useRootNode();
|
|
76
|
-
if (!
|
|
77
|
-
const destination =
|
|
89
|
+
if (!rootNode) return null;
|
|
90
|
+
const destination = isDocument(rootNode) ? rootNode.body : rootNode;
|
|
78
91
|
if (!destination) return null;
|
|
79
92
|
return ReactDOM.createPortal(
|
|
80
93
|
/* @__PURE__ */ jsx(
|
|
@@ -94,35 +107,46 @@ function Styles() {
|
|
|
94
107
|
const rootNode = useRootNode();
|
|
95
108
|
useLayoutEffect(() => {
|
|
96
109
|
if (!rootNode) return;
|
|
97
|
-
loadStyles(rootNode, { css });
|
|
110
|
+
const { cleanup } = loadStyles(rootNode, { css });
|
|
111
|
+
return cleanup;
|
|
98
112
|
}, [rootNode]);
|
|
99
113
|
return null;
|
|
100
114
|
}
|
|
101
|
-
const styleSheets =
|
|
102
|
-
|
|
115
|
+
const styleSheets = new Map(
|
|
116
|
+
Object.entries({ default: /* @__PURE__ */ new WeakMap() })
|
|
117
|
+
);
|
|
118
|
+
function loadStyles(rootNode, { css: css2, key = "default" }) {
|
|
119
|
+
let cleanup = () => {
|
|
120
|
+
};
|
|
103
121
|
const loaded = (() => {
|
|
104
122
|
if (!isBrowser) return false;
|
|
105
123
|
const ownerDocument = getOwnerDocument(rootNode);
|
|
106
124
|
const _window = getWindow(rootNode);
|
|
107
125
|
if (!ownerDocument || !_window) return false;
|
|
108
|
-
if (!supportsAdoptedStylesheets && !rootNode.querySelector(
|
|
126
|
+
if (!supportsAdoptedStylesheets && !rootNode.querySelector(`style[data-kiwi="${key}"]`)) {
|
|
109
127
|
const styleElement = ownerDocument.createElement("style");
|
|
110
|
-
styleElement.dataset.kiwi =
|
|
128
|
+
styleElement.dataset.kiwi = key;
|
|
111
129
|
styleElement.textContent = css2;
|
|
112
130
|
(rootNode.head || rootNode).appendChild(styleElement);
|
|
131
|
+
cleanup = () => styleElement.remove();
|
|
113
132
|
return true;
|
|
114
133
|
}
|
|
115
|
-
const styleSheet = styleSheets.get(_window) || new _window.CSSStyleSheet();
|
|
116
|
-
if (!styleSheets.has(_window)) {
|
|
117
|
-
styleSheets.set(_window, styleSheet);
|
|
134
|
+
const styleSheet = styleSheets.get(key)?.get(_window) || new _window.CSSStyleSheet();
|
|
135
|
+
if (!styleSheets.get(key)?.has(_window)) {
|
|
136
|
+
styleSheets.get(key)?.set(_window, styleSheet);
|
|
118
137
|
}
|
|
119
138
|
styleSheet.replaceSync(css2);
|
|
120
139
|
if (!rootNode.adoptedStyleSheets.includes(styleSheet)) {
|
|
121
140
|
rootNode.adoptedStyleSheets.push(styleSheet);
|
|
141
|
+
cleanup = () => {
|
|
142
|
+
rootNode.adoptedStyleSheets = rootNode.adoptedStyleSheets.filter(
|
|
143
|
+
(sheet) => sheet !== styleSheet
|
|
144
|
+
);
|
|
145
|
+
};
|
|
122
146
|
}
|
|
123
147
|
return true;
|
|
124
148
|
})();
|
|
125
|
-
return { loaded };
|
|
149
|
+
return { loaded, cleanup };
|
|
126
150
|
}
|
|
127
151
|
function Fonts() {
|
|
128
152
|
const rootNode = useRootNode();
|
|
@@ -132,6 +156,35 @@ function Fonts() {
|
|
|
132
156
|
}, [rootNode]);
|
|
133
157
|
return null;
|
|
134
158
|
}
|
|
159
|
+
function InlineSpriteSheet() {
|
|
160
|
+
const rootNode = useRootNode();
|
|
161
|
+
React.useEffect(
|
|
162
|
+
function maybeCreateSpriteSheet() {
|
|
163
|
+
const ownerDocument = getOwnerDocument(rootNode);
|
|
164
|
+
if (!ownerDocument) return;
|
|
165
|
+
const spriteSheet = ownerDocument?.getElementById(spriteSheetId);
|
|
166
|
+
if (spriteSheet) return;
|
|
167
|
+
const svg = ownerDocument.createElementNS(
|
|
168
|
+
"http://www.w3.org/2000/svg",
|
|
169
|
+
"svg"
|
|
170
|
+
);
|
|
171
|
+
svg.id = spriteSheetId;
|
|
172
|
+
svg.style.display = "none";
|
|
173
|
+
Object.defineProperty(svg, Symbol.for("\u{1F95D}"), {
|
|
174
|
+
value: { icons: /* @__PURE__ */ new Map() }
|
|
175
|
+
// Map of icon URLs that have already been inlined.
|
|
176
|
+
});
|
|
177
|
+
ownerDocument.body.appendChild(svg);
|
|
178
|
+
return () => {
|
|
179
|
+
if (svg.isConnected) {
|
|
180
|
+
ownerDocument.body.removeChild(svg);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
},
|
|
184
|
+
[rootNode]
|
|
185
|
+
);
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
135
188
|
function loadFonts(rootNode) {
|
|
136
189
|
const ownerWindow = getWindow(rootNode);
|
|
137
190
|
if (!ownerWindow || Array.from(ownerWindow.document.fonts).some(
|
|
@@ -160,17 +213,10 @@ const supportsAdoptedStylesheets = isBrowser && "adoptedStyleSheets" in Document
|
|
|
160
213
|
function isShadow(node) {
|
|
161
214
|
return node instanceof ShadowRoot || node?.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !!node?.host;
|
|
162
215
|
}
|
|
163
|
-
function isDocument(node) {
|
|
164
|
-
return node?.nodeType === Node.DOCUMENT_NODE;
|
|
165
|
-
}
|
|
166
|
-
function getOwnerDocument(node) {
|
|
167
|
-
return (isDocument(node) ? node : node.ownerDocument) || null;
|
|
168
|
-
}
|
|
169
216
|
function getWindow(node) {
|
|
170
217
|
const ownerDocument = getOwnerDocument(node);
|
|
171
218
|
return ownerDocument?.defaultView || null;
|
|
172
219
|
}
|
|
173
|
-
const useLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect;
|
|
174
220
|
export {
|
|
175
221
|
Root
|
|
176
222
|
};
|
package/dist/bricks/Select.d.ts
CHANGED
|
@@ -3,20 +3,37 @@ import { type FocusableProps } from "./~utils.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Compound component for a select element, which allows the user to select a value from a list of options.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Use with the `Field` components to automatically handle ID associations for
|
|
7
|
+
* labels and descriptions:
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Field.Root>
|
|
10
|
+
* <Field.Label>Fruit</Field.Label>
|
|
11
|
+
* <Field.Control
|
|
12
|
+
* render={(controlProps) => (
|
|
13
|
+
* <Select.Root>
|
|
14
|
+
* <Select.HtmlSelect name="fruit" {...controlProps}>
|
|
15
|
+
* <option value="kiwi">Kiwi</option>
|
|
16
|
+
* <option value="mango">Mango</option>
|
|
17
|
+
* <option value="papaya">Papaya</option>
|
|
18
|
+
* </Select.HtmlSelect>
|
|
19
|
+
* </Select.Root>
|
|
20
|
+
* )}
|
|
21
|
+
* />
|
|
22
|
+
* </Field.Root>
|
|
23
|
+
* ```
|
|
7
24
|
*
|
|
8
|
-
*
|
|
25
|
+
* Without the `Field` components you will need to manually associate labels,
|
|
26
|
+
* descriptions, etc.:
|
|
9
27
|
* ```tsx
|
|
10
|
-
* <
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* </Field>
|
|
28
|
+
* <Label htmlFor="fruit">Fruit</Label>
|
|
29
|
+
* <Description id="fruit-description">Something to include in a fruit salad.</Description>
|
|
30
|
+
* <Select.Root>
|
|
31
|
+
* <Select.HtmlSelect id="fruit" aria-labelledby="fruit-description">
|
|
32
|
+
* <option value="kiwi">Kiwi</option>
|
|
33
|
+
* <option value="mango">Mango</option>
|
|
34
|
+
* <option value="papaya">Papaya</option>
|
|
35
|
+
* </Select.HtmlSelect>
|
|
36
|
+
* </Select.Root>
|
|
20
37
|
* ```
|
|
21
38
|
*/
|
|
22
39
|
declare const SelectRoot: React.ForwardRefExoticComponent<Pick<import("@ariakit/react/role").RoleProps, "render"> & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "render"> & React.RefAttributes<HTMLElement | HTMLDivElement>>;
|
package/dist/bricks/Select.js
CHANGED
|
@@ -7,11 +7,12 @@ import {
|
|
|
7
7
|
isBrowser
|
|
8
8
|
} from "./~utils.js";
|
|
9
9
|
import { DisclosureArrow } from "./Icon.js";
|
|
10
|
-
import {
|
|
10
|
+
import { useFieldControlType } from "./Field.internal.js";
|
|
11
11
|
const supportsHas = isBrowser && CSS?.supports?.("selector(:has(+ *))");
|
|
12
12
|
const HtmlSelectContext = React.createContext(() => {
|
|
13
13
|
});
|
|
14
14
|
const SelectRoot = forwardRef((props, forwardedRef) => {
|
|
15
|
+
useFieldControlType("textlike");
|
|
15
16
|
const [isHtmlSelect, setIsHtmlSelect] = React.useState(false);
|
|
16
17
|
return /* @__PURE__ */ jsx(HtmlSelectContext.Provider, { value: setIsHtmlSelect, children: /* @__PURE__ */ jsx(
|
|
17
18
|
Role.div,
|
|
@@ -25,7 +26,7 @@ const SelectRoot = forwardRef((props, forwardedRef) => {
|
|
|
25
26
|
});
|
|
26
27
|
const HtmlSelect = forwardRef(
|
|
27
28
|
(props, forwardedRef) => {
|
|
28
|
-
const {
|
|
29
|
+
const { variant = "solid", ...rest } = props;
|
|
29
30
|
const setIsHtmlSelect = React.useContext(HtmlSelectContext);
|
|
30
31
|
React.useEffect(
|
|
31
32
|
function updateContext() {
|
|
@@ -35,20 +36,13 @@ const HtmlSelect = forwardRef(
|
|
|
35
36
|
);
|
|
36
37
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37
38
|
/* @__PURE__ */ jsx(
|
|
38
|
-
|
|
39
|
+
Role.select,
|
|
39
40
|
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
...rest,
|
|
46
|
-
className: cx("\u{1F95D}-button", "\u{1F95D}-select", props.className),
|
|
47
|
-
"data-kiwi-tone": "neutral",
|
|
48
|
-
"data-kiwi-variant": variant,
|
|
49
|
-
ref: forwardedRef
|
|
50
|
-
}
|
|
51
|
-
)
|
|
41
|
+
...rest,
|
|
42
|
+
className: cx("\u{1F95D}-button", "\u{1F95D}-select", props.className),
|
|
43
|
+
"data-kiwi-tone": "neutral",
|
|
44
|
+
"data-kiwi-variant": variant,
|
|
45
|
+
ref: forwardedRef
|
|
52
46
|
}
|
|
53
47
|
),
|
|
54
48
|
/* @__PURE__ */ jsx(DisclosureArrow, { className: "\u{1F95D}-select-arrow" })
|
package/dist/bricks/Spinner.js
CHANGED
|
@@ -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__ */
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
}
|