@qeetrix/react 0.0.1 → 0.0.4
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 +288 -0
- package/README.md +240 -4
- package/dist/accordion/accordion.d.ts +42 -0
- package/dist/accordion/accordion.js +72 -0
- package/dist/accordion/index.d.ts +2 -0
- package/dist/accordion/index.js +1 -0
- package/dist/avatar/avatar.d.ts +21 -0
- package/dist/avatar/avatar.js +43 -0
- package/dist/avatar/index.d.ts +2 -0
- package/dist/avatar/index.js +1 -0
- package/dist/badge/badge.d.ts +14 -0
- package/dist/badge/badge.js +25 -0
- package/dist/badge/index.d.ts +2 -0
- package/dist/badge/index.js +1 -0
- package/dist/box/box.d.ts +27 -0
- package/dist/box/box.js +21 -0
- package/dist/box/index.d.ts +2 -0
- package/dist/box/index.js +1 -0
- package/dist/button/button.d.ts +50 -0
- package/dist/button/button.js +78 -0
- package/dist/button/index.d.ts +2 -0
- package/dist/button/index.js +1 -0
- package/dist/card/card.d.ts +30 -0
- package/dist/card/card.js +56 -0
- package/dist/card/index.d.ts +2 -0
- package/dist/card/index.js +1 -0
- package/dist/checkbox/checkbox.d.ts +33 -0
- package/dist/checkbox/checkbox.js +61 -0
- package/dist/checkbox/index.d.ts +2 -0
- package/dist/checkbox/index.js +1 -0
- package/dist/css/accordion.css +73 -0
- package/dist/css/avatar.css +50 -0
- package/dist/css/badge.css +59 -0
- package/dist/css/box.css +163 -0
- package/dist/css/button.css +243 -0
- package/dist/css/card.css +75 -0
- package/dist/css/checkbox.css +67 -0
- package/dist/css/dialog.css +128 -0
- package/dist/css/drawer.css +129 -0
- package/dist/css/experimental/alert.css +89 -0
- package/dist/css/experimental/app-shell.css +258 -0
- package/dist/css/experimental/breadcrumb.css +67 -0
- package/dist/css/experimental/copy-button.css +13 -0
- package/dist/css/experimental/empty-state.css +63 -0
- package/dist/css/experimental/otp-input.css +84 -0
- package/dist/css/experimental/page-header.css +110 -0
- package/dist/css/experimental/password-input.css +21 -0
- package/dist/css/experimental/sidebar.css +234 -0
- package/dist/css/experimental/stat.css +115 -0
- package/dist/css/experimental/top-bar.css +299 -0
- package/dist/css/field.css +121 -0
- package/dist/css/fieldset.css +37 -0
- package/dist/css/grid.css +86 -0
- package/dist/css/heading.css +93 -0
- package/dist/css/inline.css +85 -0
- package/dist/css/input.css +108 -0
- package/dist/css/link.css +45 -0
- package/dist/css/menu.css +166 -0
- package/dist/css/popover.css +72 -0
- package/dist/css/progress.css +102 -0
- package/dist/css/radio.css +54 -0
- package/dist/css/scroll-area.css +70 -0
- package/dist/css/select.css +189 -0
- package/dist/css/separator.css +35 -0
- package/dist/css/skeleton.css +39 -0
- package/dist/css/skip-link.css +33 -0
- package/dist/css/slider.css +108 -0
- package/dist/css/spinner.css +55 -0
- package/dist/css/stack.css +76 -0
- package/dist/css/switch.css +112 -0
- package/dist/css/table.css +68 -0
- package/dist/css/tabs.css +123 -0
- package/dist/css/text-field.css +4 -0
- package/dist/css/text.css +106 -0
- package/dist/css/toast.css +115 -0
- package/dist/css/toggle.css +125 -0
- package/dist/css/tooltip.css +47 -0
- package/dist/css/visually-hidden.css +15 -0
- package/dist/dialog/dialog.d.ts +54 -0
- package/dist/dialog/dialog.js +121 -0
- package/dist/dialog/index.d.ts +2 -0
- package/dist/dialog/index.js +1 -0
- package/dist/drawer/drawer.d.ts +49 -0
- package/dist/drawer/drawer.js +102 -0
- package/dist/drawer/index.d.ts +2 -0
- package/dist/drawer/index.js +1 -0
- package/dist/experimental/alert/alert.d.ts +29 -0
- package/dist/experimental/alert/alert.js +72 -0
- package/dist/experimental/alert/index.d.ts +2 -0
- package/dist/experimental/app-shell/app-shell.d.ts +60 -0
- package/dist/experimental/app-shell/app-shell.js +224 -0
- package/dist/experimental/app-shell/index.d.ts +2 -0
- package/dist/experimental/breadcrumb/breadcrumb.d.ts +27 -0
- package/dist/experimental/breadcrumb/breadcrumb.js +48 -0
- package/dist/experimental/breadcrumb/index.d.ts +2 -0
- package/dist/experimental/copy-button/copy-button.d.ts +27 -0
- package/dist/experimental/copy-button/copy-button.js +61 -0
- package/dist/experimental/copy-button/index.d.ts +2 -0
- package/dist/experimental/empty-state/data-state.d.ts +23 -0
- package/dist/experimental/empty-state/data-state.js +40 -0
- package/dist/experimental/empty-state/empty-state.d.ts +26 -0
- package/dist/experimental/empty-state/empty-state.js +46 -0
- package/dist/experimental/empty-state/index.d.ts +3 -0
- package/dist/experimental/index.d.ts +24 -0
- package/dist/experimental/index.js +13 -0
- package/dist/experimental/otp-input/index.d.ts +2 -0
- package/dist/experimental/otp-input/otp-input.d.ts +27 -0
- package/dist/experimental/otp-input/otp-input.js +39 -0
- package/dist/experimental/page-header/index.d.ts +2 -0
- package/dist/experimental/page-header/page-header.d.ts +32 -0
- package/dist/experimental/page-header/page-header.js +73 -0
- package/dist/experimental/password-input/index.d.ts +2 -0
- package/dist/experimental/password-input/password-input.d.ts +26 -0
- package/dist/experimental/password-input/password-input.js +103 -0
- package/dist/experimental/sidebar/index.d.ts +2 -0
- package/dist/experimental/sidebar/sidebar.d.ts +64 -0
- package/dist/experimental/sidebar/sidebar.js +200 -0
- package/dist/experimental/stat/index.d.ts +2 -0
- package/dist/experimental/stat/stat.d.ts +31 -0
- package/dist/experimental/stat/stat.js +90 -0
- package/dist/experimental/top-bar/index.d.ts +2 -0
- package/dist/experimental/top-bar/top-bar.d.ts +60 -0
- package/dist/experimental/top-bar/top-bar.js +162 -0
- package/dist/field/choice.d.ts +21 -0
- package/dist/field/choice.js +67 -0
- package/dist/field/field.d.ts +31 -0
- package/dist/field/field.js +78 -0
- package/dist/field/index.d.ts +3 -0
- package/dist/field/index.js +1 -0
- package/dist/fieldset/fieldset.d.ts +19 -0
- package/dist/fieldset/fieldset.js +29 -0
- package/dist/fieldset/index.d.ts +2 -0
- package/dist/fieldset/index.js +1 -0
- package/dist/format/format.d.ts +12 -0
- package/dist/format/format.js +50 -0
- package/dist/format/index.d.ts +2 -0
- package/dist/format/index.js +1 -0
- package/dist/grid/grid.d.ts +30 -0
- package/dist/grid/grid.js +36 -0
- package/dist/grid/index.d.ts +2 -0
- package/dist/grid/index.js +1 -0
- package/dist/heading/heading.d.ts +23 -0
- package/dist/heading/heading.js +30 -0
- package/dist/heading/index.d.ts +2 -0
- package/dist/heading/index.js +1 -0
- package/dist/index.d.ts +84 -1
- package/dist/index.js +40 -0
- package/dist/inline/index.d.ts +2 -0
- package/dist/inline/index.js +1 -0
- package/dist/inline/inline.d.ts +19 -0
- package/dist/inline/inline.js +16 -0
- package/dist/input/index.d.ts +2 -0
- package/dist/input/index.js +1 -0
- package/dist/input/input.d.ts +37 -0
- package/dist/input/input.js +63 -0
- package/dist/internal/control.d.ts +9 -0
- package/dist/internal/control.js +4 -0
- package/dist/internal/cx.js +7 -0
- package/dist/internal/media.js +15 -0
- package/dist/internal/messages.d.ts +75 -0
- package/dist/internal/messages.js +61 -0
- package/dist/internal/refs.js +23 -0
- package/dist/internal/render.d.ts +6 -0
- package/dist/internal/render.js +22 -0
- package/dist/internal/space.d.ts +9 -0
- package/dist/internal/text.d.ts +5 -0
- package/dist/internal/text.js +18 -0
- package/dist/link/index.d.ts +2 -0
- package/dist/link/index.js +1 -0
- package/dist/link/link.d.ts +19 -0
- package/dist/link/link.js +32 -0
- package/dist/locales/hi.d.ts +8 -0
- package/dist/locales/hi.js +60 -0
- package/dist/menu/index.d.ts +2 -0
- package/dist/menu/index.js +1 -0
- package/dist/menu/menu.d.ts +76 -0
- package/dist/menu/menu.js +172 -0
- package/dist/popover/index.d.ts +2 -0
- package/dist/popover/index.js +1 -0
- package/dist/popover/popover.d.ts +33 -0
- package/dist/popover/popover.js +48 -0
- package/dist/progress/index.d.ts +2 -0
- package/dist/progress/index.js +1 -0
- package/dist/progress/progress.d.ts +26 -0
- package/dist/progress/progress.js +62 -0
- package/dist/provider/index.d.ts +3 -0
- package/dist/provider/index.js +1 -0
- package/dist/provider/provider.d.ts +46 -0
- package/dist/provider/provider.js +90 -0
- package/dist/radio/index.d.ts +2 -0
- package/dist/radio/index.js +1 -0
- package/dist/radio/radio.d.ts +31 -0
- package/dist/radio/radio.js +47 -0
- package/dist/scroll-area/index.d.ts +2 -0
- package/dist/scroll-area/index.js +1 -0
- package/dist/scroll-area/scroll-area.d.ts +18 -0
- package/dist/scroll-area/scroll-area.js +39 -0
- package/dist/select/index.d.ts +2 -0
- package/dist/select/index.js +1 -0
- package/dist/select/select.d.ts +36 -0
- package/dist/select/select.js +82 -0
- package/dist/separator/index.d.ts +2 -0
- package/dist/separator/index.js +1 -0
- package/dist/separator/separator.d.ts +16 -0
- package/dist/separator/separator.js +16 -0
- package/dist/skeleton/index.d.ts +2 -0
- package/dist/skeleton/index.js +1 -0
- package/dist/skeleton/skeleton.d.ts +12 -0
- package/dist/skeleton/skeleton.js +18 -0
- package/dist/skip-link/index.d.ts +2 -0
- package/dist/skip-link/index.js +1 -0
- package/dist/skip-link/skip-link.d.ts +13 -0
- package/dist/skip-link/skip-link.js +18 -0
- package/dist/slider/index.d.ts +2 -0
- package/dist/slider/index.js +1 -0
- package/dist/slider/slider.d.ts +20 -0
- package/dist/slider/slider.js +58 -0
- package/dist/spinner/index.d.ts +2 -0
- package/dist/spinner/index.js +1 -0
- package/dist/spinner/spinner.d.ts +15 -0
- package/dist/spinner/spinner.js +19 -0
- package/dist/stack/index.d.ts +2 -0
- package/dist/stack/index.js +1 -0
- package/dist/stack/stack.d.ts +17 -0
- package/dist/stack/stack.js +15 -0
- package/dist/styles.css +4548 -0
- package/dist/switch/index.d.ts +2 -0
- package/dist/switch/index.js +1 -0
- package/dist/switch/switch.d.ts +18 -0
- package/dist/switch/switch.js +31 -0
- package/dist/table/index.d.ts +2 -0
- package/dist/table/index.js +1 -0
- package/dist/table/table.d.ts +36 -0
- package/dist/table/table.js +69 -0
- package/dist/tabs/index.d.ts +2 -0
- package/dist/tabs/index.js +1 -0
- package/dist/tabs/tabs.d.ts +43 -0
- package/dist/tabs/tabs.js +66 -0
- package/dist/text/index.d.ts +3 -0
- package/dist/text/index.js +1 -0
- package/dist/text/text.d.ts +24 -0
- package/dist/text/text.js +24 -0
- package/dist/text-field/index.d.ts +2 -0
- package/dist/text-field/index.js +1 -0
- package/dist/text-field/text-field.d.ts +15 -0
- package/dist/text-field/text-field.js +43 -0
- package/dist/toast/index.d.ts +2 -0
- package/dist/toast/index.js +1 -0
- package/dist/toast/toast.d.ts +57 -0
- package/dist/toast/toast.js +124 -0
- package/dist/toggle/index.d.ts +2 -0
- package/dist/toggle/index.js +1 -0
- package/dist/toggle/toggle.d.ts +48 -0
- package/dist/toggle/toggle.js +54 -0
- package/dist/tooltip/index.d.ts +2 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/tooltip/tooltip.d.ts +26 -0
- package/dist/tooltip/tooltip.js +39 -0
- package/dist/visually-hidden/index.d.ts +2 -0
- package/dist/visually-hidden/index.js +1 -0
- package/dist/visually-hidden/visually-hidden.d.ts +8 -0
- package/dist/visually-hidden/visually-hidden.js +12 -0
- package/package.json +170 -2
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { DEFAULT_LOCALE, messages } from "../internal/messages.js";
|
|
3
|
+
import { useMediaQuery } from "../internal/media.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { createContext, use, useEffect, useState } from "react";
|
|
6
|
+
import { DirectionProvider } from "@base-ui/react/direction-provider";
|
|
7
|
+
// src/provider/provider.tsx
|
|
8
|
+
const SettingsContext = createContext({
|
|
9
|
+
locale: DEFAULT_LOCALE,
|
|
10
|
+
messages: {}
|
|
11
|
+
});
|
|
12
|
+
const ColorSchemeContext = createContext({
|
|
13
|
+
colorScheme: "light",
|
|
14
|
+
resolvedColorScheme: "light",
|
|
15
|
+
setColorScheme: () => {}
|
|
16
|
+
});
|
|
17
|
+
function ColorSchemeRoot({ colorScheme, defaultColorScheme, onColorSchemeChange, children }) {
|
|
18
|
+
const [own, setOwn] = useState(defaultColorScheme ?? "system");
|
|
19
|
+
const scheme = colorScheme ?? own;
|
|
20
|
+
const prefersDark = useMediaQuery("(prefers-color-scheme: dark)", false);
|
|
21
|
+
const resolved = scheme === "system" ? prefersDark ? "dark" : "light" : scheme;
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
document.documentElement.dataset.qxColorScheme = resolved;
|
|
24
|
+
}, [resolved]);
|
|
25
|
+
const setColorScheme = (next) => {
|
|
26
|
+
if (colorScheme === void 0) setOwn(next);
|
|
27
|
+
onColorSchemeChange?.(next);
|
|
28
|
+
};
|
|
29
|
+
return /* @__PURE__ */ jsx(ColorSchemeContext, {
|
|
30
|
+
value: {
|
|
31
|
+
colorScheme: scheme,
|
|
32
|
+
resolvedColorScheme: resolved,
|
|
33
|
+
setColorScheme
|
|
34
|
+
},
|
|
35
|
+
children
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function merge(outer, inner) {
|
|
39
|
+
const out = { ...outer };
|
|
40
|
+
for (const [group, strings] of Object.entries(inner)) out[group] = {
|
|
41
|
+
...out[group],
|
|
42
|
+
...strings
|
|
43
|
+
};
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* App-wide settings for Qeetrix components: locale, direction and strings. Nest one to change a
|
|
48
|
+
* section; it inherits whatever it doesn't set.
|
|
49
|
+
*/
|
|
50
|
+
function QeetrixProvider({ locale, direction, messages: strings, colorScheme, defaultColorScheme, onColorSchemeChange, children }) {
|
|
51
|
+
const outer = use(SettingsContext);
|
|
52
|
+
const settings = {
|
|
53
|
+
locale: locale ?? outer.locale,
|
|
54
|
+
messages: strings ? merge(outer.messages, strings) : outer.messages
|
|
55
|
+
};
|
|
56
|
+
const directed = direction ? /* @__PURE__ */ jsx(DirectionProvider, {
|
|
57
|
+
direction,
|
|
58
|
+
children
|
|
59
|
+
}) : children;
|
|
60
|
+
return /* @__PURE__ */ jsx(SettingsContext, {
|
|
61
|
+
value: settings,
|
|
62
|
+
children: colorScheme !== void 0 || defaultColorScheme !== void 0 ? /* @__PURE__ */ jsx(ColorSchemeRoot, {
|
|
63
|
+
colorScheme,
|
|
64
|
+
defaultColorScheme,
|
|
65
|
+
onColorSchemeChange,
|
|
66
|
+
children: directed
|
|
67
|
+
}) : directed
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The colour scheme, and a way to change it, from the QeetrixProvider that manages it (one with
|
|
72
|
+
* `colorScheme` or `defaultColorScheme`).
|
|
73
|
+
*/
|
|
74
|
+
function useColorScheme() {
|
|
75
|
+
return use(ColorSchemeContext);
|
|
76
|
+
}
|
|
77
|
+
/** The locale set by the nearest QeetrixProvider; `en-IN` without one. */
|
|
78
|
+
function useLocale() {
|
|
79
|
+
return use(SettingsContext).locale;
|
|
80
|
+
}
|
|
81
|
+
/** A component's strings: its own prop, then the provider, then the English defaults. */
|
|
82
|
+
function useMessages(group, own) {
|
|
83
|
+
const provided = use(SettingsContext).messages[group];
|
|
84
|
+
return {
|
|
85
|
+
...messages[group],
|
|
86
|
+
...provided,
|
|
87
|
+
...own
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export { QeetrixProvider, useColorScheme, useLocale, useMessages };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Radio, RadioGroup } from "./radio.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { FieldMessageProps } from "../field/field.js";
|
|
2
|
+
import { ChoiceLabelProps, ChoiceOrientation } from "../field/choice.js";
|
|
3
|
+
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
4
|
+
import { Radio } from "@base-ui/react/radio";
|
|
5
|
+
import { RadioGroup } from "@base-ui/react/radio-group";
|
|
6
|
+
interface RadioOwnProps<Value> extends Omit<Radio.Root.Props<Value>, "className" | "style" | "children"> {
|
|
7
|
+
/** A line under the label. */
|
|
8
|
+
description?: ReactNode;
|
|
9
|
+
/** Placement of the row (or of the control alone, with no label) only. */
|
|
10
|
+
className?: string;
|
|
11
|
+
style?: CSSProperties;
|
|
12
|
+
}
|
|
13
|
+
/** Radio props: Base UI's (`value` required), plus `label` — or a required `aria-label`. */
|
|
14
|
+
export type RadioProps<Value = string> = RadioOwnProps<Value> & ChoiceLabelProps;
|
|
15
|
+
/** One option of a RadioGroup (06-component-specs.md §3). The 5px Ember ring is its border. */
|
|
16
|
+
declare function Radio$1<Value = string>({ label, description, className, style, ...props }: RadioProps<Value>): ReactElement;
|
|
17
|
+
export interface RadioGroupProps<Value = string> extends Omit<RadioGroup.Props<Value>, "className" | "style" | "render">, FieldMessageProps {
|
|
18
|
+
/** The question, shown as the group's legend. */
|
|
19
|
+
label: ReactNode;
|
|
20
|
+
/** `vertical` (default) or `horizontal` for short options. */
|
|
21
|
+
orientation?: ChoiceOrientation;
|
|
22
|
+
/** Placement only (margin, width, grid placement). */
|
|
23
|
+
className?: string;
|
|
24
|
+
style?: CSSProperties;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* One choice from a set, always answered: arrow keys move and select, and the group is one tab
|
|
28
|
+
* stop. Generic over the value: `RadioGroup<"monthly" | "yearly">`.
|
|
29
|
+
*/
|
|
30
|
+
declare function RadioGroup$1<Value = string>({ label, description, error, name, disabled, orientation, className, style, children, ...props }: RadioGroupProps<Value>): ReactElement;
|
|
31
|
+
export { Radio$1 as Radio, RadioGroup$1 as RadioGroup };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { ChoiceGroup, ChoiceRow } from "../field/choice.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { Radio } from "@base-ui/react/radio";
|
|
6
|
+
import { RadioGroup } from "@base-ui/react/radio-group";
|
|
7
|
+
// src/radio/radio.tsx
|
|
8
|
+
/** One option of a RadioGroup (06-component-specs.md §3). The 5px Ember ring is its border. */
|
|
9
|
+
function Radio$1({ label, description, className, style, ...props }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(ChoiceRow, {
|
|
11
|
+
kind: "radio",
|
|
12
|
+
label,
|
|
13
|
+
description,
|
|
14
|
+
disabled: props.disabled,
|
|
15
|
+
className,
|
|
16
|
+
style,
|
|
17
|
+
children: /* @__PURE__ */ jsx(Radio.Root, {
|
|
18
|
+
...props,
|
|
19
|
+
className: cx("qx-radio", label == null ? className : void 0),
|
|
20
|
+
style: label == null ? style : void 0,
|
|
21
|
+
"data-slot": "radio-indicator"
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* One choice from a set, always answered: arrow keys move and select, and the group is one tab
|
|
27
|
+
* stop. Generic over the value: `RadioGroup<"monthly" | "yearly">`.
|
|
28
|
+
*/
|
|
29
|
+
function RadioGroup$1({ label, description, error, name, disabled, orientation = "vertical", className, style, children, ...props }) {
|
|
30
|
+
return /* @__PURE__ */ jsx(ChoiceGroup, {
|
|
31
|
+
kind: "radio",
|
|
32
|
+
label,
|
|
33
|
+
description,
|
|
34
|
+
error,
|
|
35
|
+
name,
|
|
36
|
+
disabled,
|
|
37
|
+
orientation,
|
|
38
|
+
className,
|
|
39
|
+
style,
|
|
40
|
+
group: /* @__PURE__ */ jsx(RadioGroup, {
|
|
41
|
+
...props,
|
|
42
|
+
disabled
|
|
43
|
+
}),
|
|
44
|
+
children
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
export { Radio$1 as Radio, RadioGroup$1 as RadioGroup };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ScrollArea } from "./scroll-area.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { ScrollArea } from "@base-ui/react/scroll-area";
|
|
3
|
+
export type ScrollAreaOrientation = "vertical" | "horizontal" | "both";
|
|
4
|
+
export interface ScrollAreaProps extends Omit<ScrollArea.Root.Props, "className" | "style" | "children"> {
|
|
5
|
+
/** Which way it scrolls. Default `vertical`. */
|
|
6
|
+
orientation?: ScrollAreaOrientation;
|
|
7
|
+
/** Its size, e.g. a height (`style={{ blockSize: 320 }}`), and its placement. */
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A scrolling region with Qeetrix scrollbars that show on hover, while scrolling and on keyboard
|
|
14
|
+
* focus (06-component-specs.md, increment 5). When its content overflows, the region takes keyboard
|
|
15
|
+
* focus, so it can be scrolled without a pointer.
|
|
16
|
+
*/
|
|
17
|
+
declare function ScrollArea$1({ orientation, className, children, ...props }: ScrollAreaProps): ReactElement;
|
|
18
|
+
export { ScrollArea$1 as ScrollArea };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { ScrollArea } from "@base-ui/react/scroll-area";
|
|
5
|
+
// src/scroll-area/scroll-area.tsx
|
|
6
|
+
/**
|
|
7
|
+
* A scrolling region with Qeetrix scrollbars that show on hover, while scrolling and on keyboard
|
|
8
|
+
* focus (06-component-specs.md, increment 5). When its content overflows, the region takes keyboard
|
|
9
|
+
* focus, so it can be scrolled without a pointer.
|
|
10
|
+
*/
|
|
11
|
+
function ScrollArea$1({ orientation = "vertical", className, children, ...props }) {
|
|
12
|
+
return /* @__PURE__ */ jsxs(ScrollArea.Root, {
|
|
13
|
+
...props,
|
|
14
|
+
className: cx("qx-scroll-area", className),
|
|
15
|
+
"data-slot": "scroll-area",
|
|
16
|
+
children: [
|
|
17
|
+
/* @__PURE__ */ jsx(ScrollArea.Viewport, {
|
|
18
|
+
className: "qx-scroll-area-viewport",
|
|
19
|
+
"data-slot": "scroll-area-viewport",
|
|
20
|
+
children: /* @__PURE__ */ jsx(ScrollArea.Content, {
|
|
21
|
+
className: "qx-scroll-area-content",
|
|
22
|
+
children
|
|
23
|
+
})
|
|
24
|
+
}),
|
|
25
|
+
orientation !== "horizontal" && /* @__PURE__ */ jsx(ScrollArea.Scrollbar, {
|
|
26
|
+
orientation: "vertical",
|
|
27
|
+
className: "qx-scroll-area-scrollbar",
|
|
28
|
+
children: /* @__PURE__ */ jsx(ScrollArea.Thumb, { className: "qx-scroll-area-thumb" })
|
|
29
|
+
}),
|
|
30
|
+
orientation !== "vertical" && /* @__PURE__ */ jsx(ScrollArea.Scrollbar, {
|
|
31
|
+
orientation: "horizontal",
|
|
32
|
+
className: "qx-scroll-area-scrollbar",
|
|
33
|
+
children: /* @__PURE__ */ jsx(ScrollArea.Thumb, { className: "qx-scroll-area-thumb" })
|
|
34
|
+
}),
|
|
35
|
+
orientation === "both" && /* @__PURE__ */ jsx(ScrollArea.Corner, {})
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export { ScrollArea$1 as ScrollArea };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Select } from "./select.js";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CSSProperties, ReactElement, ReactNode, Ref } from "react";
|
|
2
|
+
import { Select } from "@base-ui/react/select";
|
|
3
|
+
/** One option. */
|
|
4
|
+
export interface SelectItem<Value> {
|
|
5
|
+
value: Value;
|
|
6
|
+
label: ReactNode;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Options under a group label. */
|
|
10
|
+
export interface SelectItemGroup<Value> {
|
|
11
|
+
label: ReactNode;
|
|
12
|
+
items: ReadonlyArray<SelectItem<Value>>;
|
|
13
|
+
}
|
|
14
|
+
export interface SelectProps<Value, Multiple extends boolean | undefined = false> extends Omit<Select.Root.Props<Value, Multiple>, "items" | "children" | "id"> {
|
|
15
|
+
/** The options, flat or in groups. */
|
|
16
|
+
items: ReadonlyArray<SelectItem<Value> | SelectItemGroup<Value>>;
|
|
17
|
+
/** Shown while nothing is chosen. An example, never an instruction ("e.g. Monthly"). */
|
|
18
|
+
placeholder?: ReactNode;
|
|
19
|
+
/** The trigger's id. */
|
|
20
|
+
id?: string;
|
|
21
|
+
/** The trigger, which a Field labels. */
|
|
22
|
+
ref?: Ref<HTMLButtonElement>;
|
|
23
|
+
/** Without a Field: the trigger's accessible name. */
|
|
24
|
+
"aria-label"?: string;
|
|
25
|
+
"aria-labelledby"?: string;
|
|
26
|
+
"aria-describedby"?: string;
|
|
27
|
+
/** Placement of the trigger only. */
|
|
28
|
+
className?: string;
|
|
29
|
+
style?: CSSProperties;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Pick one option, or several with `multiple`, from up to about 15 (06-component-specs.md §4). It
|
|
33
|
+
* looks like a field and opens its list below, like a menu. Wrap it in a Field for its label.
|
|
34
|
+
*/
|
|
35
|
+
declare function Select$1<Value, Multiple extends boolean | undefined = false>({ items, placeholder, id, ref, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, className, style, ...props }: SelectProps<Value, Multiple>): ReactElement;
|
|
36
|
+
export { Select$1 as Select };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { ChevronDownIcon } from "@qeetrix/icons/icons/chevron-down";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { CheckIcon } from "@qeetrix/icons/icons/check";
|
|
6
|
+
import { Select } from "@base-ui/react/select";
|
|
7
|
+
// src/select/select.tsx
|
|
8
|
+
const isGroup = (entry) => "items" in entry;
|
|
9
|
+
function Option({ item }) {
|
|
10
|
+
return /* @__PURE__ */ jsxs(Select.Item, {
|
|
11
|
+
value: item.value,
|
|
12
|
+
disabled: item.disabled,
|
|
13
|
+
className: "qx-select-option",
|
|
14
|
+
"data-slot": "select-option",
|
|
15
|
+
children: [/* @__PURE__ */ jsx(Select.ItemText, {
|
|
16
|
+
className: "qx-select-option-text",
|
|
17
|
+
children: item.label
|
|
18
|
+
}), /* @__PURE__ */ jsx(Select.ItemIndicator, {
|
|
19
|
+
className: "qx-select-option-check",
|
|
20
|
+
children: /* @__PURE__ */ jsx(CheckIcon, {
|
|
21
|
+
shape: "sharp",
|
|
22
|
+
size: 16,
|
|
23
|
+
"aria-hidden": true
|
|
24
|
+
})
|
|
25
|
+
})]
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Pick one option, or several with `multiple`, from up to about 15 (06-component-specs.md §4). It
|
|
30
|
+
* looks like a field and opens its list below, like a menu. Wrap it in a Field for its label.
|
|
31
|
+
*/
|
|
32
|
+
function Select$1({ items, placeholder, id, ref, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, className, style, ...props }) {
|
|
33
|
+
const flat = items.flatMap((entry) => isGroup(entry) ? entry.items : [entry]);
|
|
34
|
+
const labelOf = (value) => flat.find((item) => Object.is(item.value, value))?.label;
|
|
35
|
+
return /* @__PURE__ */ jsxs(Select.Root, {
|
|
36
|
+
...props,
|
|
37
|
+
id,
|
|
38
|
+
items: flat,
|
|
39
|
+
children: [/* @__PURE__ */ jsxs(Select.Trigger, {
|
|
40
|
+
ref,
|
|
41
|
+
"aria-label": ariaLabel,
|
|
42
|
+
"aria-labelledby": ariaLabelledBy,
|
|
43
|
+
"aria-describedby": ariaDescribedBy,
|
|
44
|
+
className: cx("qx-select-trigger", className),
|
|
45
|
+
style,
|
|
46
|
+
"data-slot": "select-trigger",
|
|
47
|
+
children: [/* @__PURE__ */ jsx(Select.Value, {
|
|
48
|
+
className: "qx-select-value",
|
|
49
|
+
"data-slot": "select-value",
|
|
50
|
+
placeholder,
|
|
51
|
+
children: (value) => Array.isArray(value) ? value.length > 0 ? value.map(labelOf).filter((label) => label != null).join(", ") : placeholder : labelOf(value) ?? placeholder
|
|
52
|
+
}), /* @__PURE__ */ jsx(Select.Icon, {
|
|
53
|
+
className: "qx-select-icon",
|
|
54
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
55
|
+
shape: "sharp",
|
|
56
|
+
size: 16,
|
|
57
|
+
"aria-hidden": true
|
|
58
|
+
})
|
|
59
|
+
})]
|
|
60
|
+
}), /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsx(Select.Positioner, {
|
|
61
|
+
alignItemWithTrigger: false,
|
|
62
|
+
sideOffset: 4,
|
|
63
|
+
className: "qx-select-positioner",
|
|
64
|
+
children: /* @__PURE__ */ jsx(Select.Popup, {
|
|
65
|
+
className: "qx-select-popup",
|
|
66
|
+
"data-slot": "select-popup",
|
|
67
|
+
children: /* @__PURE__ */ jsx(Select.List, {
|
|
68
|
+
className: "qx-select-list",
|
|
69
|
+
children: items.map((entry, index) => isGroup(entry) ? /* @__PURE__ */ jsxs(Select.Group, {
|
|
70
|
+
className: "qx-select-group",
|
|
71
|
+
children: [/* @__PURE__ */ jsx(Select.GroupLabel, {
|
|
72
|
+
className: "qx-select-group-label",
|
|
73
|
+
"data-slot": "select-group-label",
|
|
74
|
+
children: entry.label
|
|
75
|
+
}), entry.items.map((item) => /* @__PURE__ */ jsx(Option, { item }, String(item.value)))]
|
|
76
|
+
}, index) : /* @__PURE__ */ jsx(Option, { item: entry }, String(entry.value)))
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
}) })]
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
export { Select$1 as Select };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Separator } from "./separator.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RenderProp } from "../internal/render.js";
|
|
2
|
+
import { ComponentProps, ReactElement } from "react";
|
|
3
|
+
export type SeparatorOrientation = "horizontal" | "vertical";
|
|
4
|
+
export type SeparatorTone = "subtle" | "default" | "strong";
|
|
5
|
+
export interface SeparatorProps extends ComponentProps<"div"> {
|
|
6
|
+
/** Default `horizontal`. A vertical separator stretches to its row. */
|
|
7
|
+
orientation?: SeparatorOrientation;
|
|
8
|
+
/** Line colour from the border tokens. Default `subtle`. */
|
|
9
|
+
tone?: SeparatorTone;
|
|
10
|
+
/** Purely visual: hidden from assistive technology (`role="none"`). */
|
|
11
|
+
decorative?: boolean;
|
|
12
|
+
/** Render a different element. */
|
|
13
|
+
render?: RenderProp;
|
|
14
|
+
}
|
|
15
|
+
/** A 1px line between groups of content. */
|
|
16
|
+
export declare function Separator({ orientation, tone, decorative, render, className, ...props }: SeparatorProps): ReactElement;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { cx } from "../internal/cx.js";
|
|
2
|
+
import { renderElement } from "../internal/render.js";
|
|
3
|
+
// src/separator/separator.tsx
|
|
4
|
+
/** A 1px line between groups of content. */
|
|
5
|
+
function Separator({ orientation = "horizontal", tone, decorative, render, className, ...props }) {
|
|
6
|
+
return renderElement("div", render, {
|
|
7
|
+
role: decorative ? "none" : "separator",
|
|
8
|
+
"aria-orientation": decorative || orientation === "horizontal" ? void 0 : orientation,
|
|
9
|
+
...props,
|
|
10
|
+
className: cx("qx-separator", className),
|
|
11
|
+
"data-slot": "separator",
|
|
12
|
+
"data-orientation": orientation,
|
|
13
|
+
"data-tone": tone
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export { Separator };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Skeleton } from "./skeleton.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ComponentProps, ReactElement } from "react";
|
|
2
|
+
export type SkeletonVariant = "text" | "block" | "circle";
|
|
3
|
+
export interface SkeletonProps extends ComponentProps<"span"> {
|
|
4
|
+
/** `text` (one line), `block` (a card or image) or `circle` (an avatar). Default `text`. */
|
|
5
|
+
variant?: SkeletonVariant;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A placeholder shaped like the content that is loading (06-component-specs.md, increment 6). Size
|
|
9
|
+
* it with `style` or `className`. It is hidden from assistive technology: set `aria-busy` on the
|
|
10
|
+
* loading region and announce the wait with a Spinner or text. Server-safe.
|
|
11
|
+
*/
|
|
12
|
+
export declare function Skeleton({ variant, className, ...props }: SkeletonProps): ReactElement;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { cx } from "../internal/cx.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
// src/skeleton/skeleton.tsx
|
|
4
|
+
/**
|
|
5
|
+
* A placeholder shaped like the content that is loading (06-component-specs.md, increment 6). Size
|
|
6
|
+
* it with `style` or `className`. It is hidden from assistive technology: set `aria-busy` on the
|
|
7
|
+
* loading region and announce the wait with a Spinner or text. Server-safe.
|
|
8
|
+
*/
|
|
9
|
+
function Skeleton({ variant = "text", className, ...props }) {
|
|
10
|
+
return /* @__PURE__ */ jsx("span", {
|
|
11
|
+
...props,
|
|
12
|
+
"aria-hidden": true,
|
|
13
|
+
className: cx("qx-skeleton", className),
|
|
14
|
+
"data-slot": "skeleton",
|
|
15
|
+
"data-variant": variant
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export { Skeleton };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SkipLink } from "./skip-link.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RenderProp } from "../internal/render.js";
|
|
2
|
+
import { ComponentProps, ReactElement } from "react";
|
|
3
|
+
export interface SkipLinkProps extends ComponentProps<"a"> {
|
|
4
|
+
/** Where the link jumps to. Default `#main`. */
|
|
5
|
+
href?: string;
|
|
6
|
+
/** Render a different element, e.g. a router link. */
|
|
7
|
+
render?: RenderProp;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The first focusable element on a page: it jumps past the navigation to the main content
|
|
11
|
+
* (WCAG 2.4.1 Bypass Blocks). Hidden until focused.
|
|
12
|
+
*/
|
|
13
|
+
export declare function SkipLink({ href, children, render, className, ...props }: SkipLinkProps): ReactElement;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { cx } from "../internal/cx.js";
|
|
2
|
+
import { renderElement } from "../internal/render.js";
|
|
3
|
+
import { messages } from "../internal/messages.js";
|
|
4
|
+
// src/skip-link/skip-link.tsx
|
|
5
|
+
/**
|
|
6
|
+
* The first focusable element on a page: it jumps past the navigation to the main content
|
|
7
|
+
* (WCAG 2.4.1 Bypass Blocks). Hidden until focused.
|
|
8
|
+
*/
|
|
9
|
+
function SkipLink({ href = "#main", children = messages.skipLink.label, render, className, ...props }) {
|
|
10
|
+
return renderElement("a", render, {
|
|
11
|
+
...props,
|
|
12
|
+
href,
|
|
13
|
+
children,
|
|
14
|
+
className: cx("qx-skip-link", className),
|
|
15
|
+
"data-slot": "skip-link"
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export { SkipLink };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Slider } from "./slider.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { QeetrixMessages } from "../internal/messages.js";
|
|
2
|
+
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
3
|
+
import { Slider } from "@base-ui/react/slider";
|
|
4
|
+
export interface SliderProps<Value extends number | readonly number[] = number> extends Omit<Slider.Root.Props<Value>, "className" | "style" | "children"> {
|
|
5
|
+
/** The visible label. Without one, give the slider an `aria-label`. */
|
|
6
|
+
label?: ReactNode;
|
|
7
|
+
/** Show the formatted value at the end of the header, in `locale` (default: QeetrixProvider's). */
|
|
8
|
+
showValue?: boolean;
|
|
9
|
+
/** A range's thumb names, over QeetrixProvider's and the English defaults. */
|
|
10
|
+
messages?: Partial<QeetrixMessages["slider"]>;
|
|
11
|
+
/** Placement only. */
|
|
12
|
+
className?: string;
|
|
13
|
+
style?: CSSProperties;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A number, or a range, on a continuous scale (06-component-specs.md, increment 5). An array value
|
|
17
|
+
* renders one thumb per value. Arrow keys step, Page Up and Down take `largeStep`, Home and End jump.
|
|
18
|
+
*/
|
|
19
|
+
declare function Slider$1<Value extends number | readonly number[] = number>({ label, showValue, messages, "aria-label": ariaLabel, locale, className, value, defaultValue, ...props }: SliderProps<Value>): ReactElement;
|
|
20
|
+
export { Slider$1 as Slider };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { useLocale, useMessages } from "../provider/provider.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { Slider } from "@base-ui/react/slider";
|
|
6
|
+
// src/slider/slider.tsx
|
|
7
|
+
/**
|
|
8
|
+
* A number, or a range, on a continuous scale (06-component-specs.md, increment 5). An array value
|
|
9
|
+
* renders one thumb per value. Arrow keys step, Page Up and Down take `largeStep`, Home and End jump.
|
|
10
|
+
*/
|
|
11
|
+
function Slider$1({ label, showValue, messages, "aria-label": ariaLabel, locale, className, value, defaultValue, ...props }) {
|
|
12
|
+
const strings = useMessages("slider", messages);
|
|
13
|
+
const providerLocale = useLocale();
|
|
14
|
+
const initial = value ?? defaultValue;
|
|
15
|
+
const thumbs = Array.isArray(initial) ? initial.length : 1;
|
|
16
|
+
const range = thumbs > 1;
|
|
17
|
+
return /* @__PURE__ */ jsxs(Slider.Root, {
|
|
18
|
+
...props,
|
|
19
|
+
"aria-label": ariaLabel,
|
|
20
|
+
value,
|
|
21
|
+
defaultValue,
|
|
22
|
+
locale: locale ?? providerLocale,
|
|
23
|
+
className: cx("qx-slider", className),
|
|
24
|
+
"data-slot": "slider",
|
|
25
|
+
children: [(label != null || showValue) && /* @__PURE__ */ jsxs("div", {
|
|
26
|
+
className: "qx-slider-header",
|
|
27
|
+
"data-slot": "slider-header",
|
|
28
|
+
children: [label != null && /* @__PURE__ */ jsx(Slider.Label, {
|
|
29
|
+
className: "qx-slider-label",
|
|
30
|
+
"data-slot": "slider-label",
|
|
31
|
+
children: label
|
|
32
|
+
}), showValue && /* @__PURE__ */ jsx(Slider.Value, {
|
|
33
|
+
className: "qx-slider-value",
|
|
34
|
+
"data-slot": "slider-value"
|
|
35
|
+
})]
|
|
36
|
+
}), /* @__PURE__ */ jsx(Slider.Control, {
|
|
37
|
+
className: "qx-slider-control",
|
|
38
|
+
"data-slot": "slider-control",
|
|
39
|
+
children: /* @__PURE__ */ jsxs(Slider.Track, {
|
|
40
|
+
className: "qx-slider-track",
|
|
41
|
+
"data-slot": "slider-track",
|
|
42
|
+
children: [/* @__PURE__ */ jsx(Slider.Indicator, {
|
|
43
|
+
className: "qx-slider-indicator",
|
|
44
|
+
"data-slot": "slider-indicator"
|
|
45
|
+
}), Array.from({ length: thumbs }, (_, index) => /* @__PURE__ */ jsx(Slider.Thumb, {
|
|
46
|
+
index,
|
|
47
|
+
getAriaLabel: range ? (i) => {
|
|
48
|
+
const bound = i === 0 ? strings.minimum : strings.maximum;
|
|
49
|
+
return ariaLabel ? `${ariaLabel}, ${bound}` : bound;
|
|
50
|
+
} : ariaLabel ? () => ariaLabel : null,
|
|
51
|
+
className: "qx-slider-thumb",
|
|
52
|
+
"data-slot": "slider-thumb"
|
|
53
|
+
}, index))]
|
|
54
|
+
})
|
|
55
|
+
})]
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export { Slider$1 as Slider };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Spinner } from "./spinner.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ComponentProps, ReactElement } from "react";
|
|
2
|
+
export type SpinnerSize = "sm" | "md" | "lg" | "xl";
|
|
3
|
+
export type SpinnerTone = "default" | "brand";
|
|
4
|
+
export interface SpinnerProps extends Omit<ComponentProps<"span">, "children"> {
|
|
5
|
+
/** `sm` 14px, `md` 16px (default), `lg` 20px, `xl` 24px. */
|
|
6
|
+
size?: SpinnerSize;
|
|
7
|
+
/** `default` follows the text colour; `brand` is Ember. */
|
|
8
|
+
tone?: SpinnerTone;
|
|
9
|
+
/** The accessible name. Default "Loading". */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** Hidden from assistive technology, when something else announces the wait (a busy Button). */
|
|
12
|
+
decorative?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** An indeterminate wait: a 2px ring that turns, or fades under reduced motion. */
|
|
15
|
+
export declare function Spinner({ size, tone, label, decorative, className, ...props }: SpinnerProps): ReactElement;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { cx } from "../internal/cx.js";
|
|
2
|
+
import { messages } from "../internal/messages.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
// src/spinner/spinner.tsx
|
|
5
|
+
/** An indeterminate wait: a 2px ring that turns, or fades under reduced motion. */
|
|
6
|
+
function Spinner({ size, tone, label = messages.spinner.label, decorative, className, ...props }) {
|
|
7
|
+
return /* @__PURE__ */ jsx("span", {
|
|
8
|
+
...decorative ? { "aria-hidden": true } : {
|
|
9
|
+
role: "status",
|
|
10
|
+
"aria-label": label
|
|
11
|
+
},
|
|
12
|
+
...props,
|
|
13
|
+
className: cx("qx-spinner", className),
|
|
14
|
+
"data-slot": "spinner",
|
|
15
|
+
"data-size": size,
|
|
16
|
+
"data-tone": tone
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export { Spinner };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Stack } from "./stack.js";
|