@-reddacted-/react-ui 0.3.0 → 0.4.0
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/dist/components/Accordion.d.ts +27 -0
- package/dist/components/Accordion.d.ts.map +1 -0
- package/dist/components/Accordion.js +35 -0
- package/dist/components/Badge.d.ts +15 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/Badge.js +7 -0
- package/dist/components/Button.d.ts +15 -2
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js +76 -44
- package/dist/components/Card.d.ts +21 -0
- package/dist/components/Card.d.ts.map +1 -0
- package/dist/components/Card.js +17 -0
- package/dist/components/ColorField.d.ts.map +1 -1
- package/dist/components/ColorField.js +1 -1
- package/dist/components/ConfirmDeleteButton.d.ts +4 -1
- package/dist/components/ConfirmDeleteButton.d.ts.map +1 -1
- package/dist/components/ConfirmDeleteButton.js +6 -7
- package/dist/components/Drawer.d.ts +33 -0
- package/dist/components/Drawer.d.ts.map +1 -0
- package/dist/components/Drawer.js +123 -0
- package/dist/components/DropdownMenu.d.ts +61 -0
- package/dist/components/DropdownMenu.d.ts.map +1 -0
- package/dist/components/DropdownMenu.js +302 -0
- package/dist/components/Modal.d.ts.map +1 -1
- package/dist/components/Modal.js +102 -134
- package/dist/components/NavBar.d.ts +11 -14
- package/dist/components/NavBar.d.ts.map +1 -1
- package/dist/components/NavBar.js +53 -31
- package/dist/components/PageStatus.d.ts +12 -12
- package/dist/components/PageStatus.d.ts.map +1 -1
- package/dist/components/PageStatus.js +9 -29
- package/dist/components/Pagination.d.ts +44 -0
- package/dist/components/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination.js +57 -0
- package/dist/components/Skeleton.d.ts +13 -0
- package/dist/components/Skeleton.d.ts.map +1 -0
- package/dist/components/Skeleton.js +15 -0
- package/dist/components/Spinner.d.ts +14 -0
- package/dist/components/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner.js +14 -0
- package/dist/components/Stack.d.ts +13 -0
- package/dist/components/Stack.d.ts.map +1 -0
- package/dist/components/Stack.js +15 -0
- package/dist/components/Table.d.ts +54 -0
- package/dist/components/Table.d.ts.map +1 -0
- package/dist/components/Table.js +101 -0
- package/dist/components/Tabs.d.ts +34 -0
- package/dist/components/Tabs.d.ts.map +1 -0
- package/dist/components/Tabs.js +82 -0
- package/dist/components/Tag.d.ts +10 -0
- package/dist/components/Tag.d.ts.map +1 -0
- package/dist/components/Tag.js +7 -0
- package/dist/components/Tooltip.d.ts +22 -0
- package/dist/components/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip.js +76 -0
- package/dist/components/drawerStore.d.ts +11 -0
- package/dist/components/drawerStore.d.ts.map +1 -0
- package/dist/components/drawerStore.js +40 -0
- package/dist/components/paginationItems.d.ts +18 -0
- package/dist/components/paginationItems.d.ts.map +1 -0
- package/dist/components/paginationItems.js +32 -0
- package/dist/index.d.ts +23 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -2
- package/dist/popup/PopupHost.d.ts +19 -3
- package/dist/popup/PopupHost.d.ts.map +1 -1
- package/dist/popup/PopupHost.js +65 -44
- package/dist/popup/PopupProvider.d.ts +19 -2
- package/dist/popup/PopupProvider.d.ts.map +1 -1
- package/dist/popup/PopupProvider.js +69 -17
- package/dist/popup/usePopup.d.ts +11 -4
- package/dist/popup/usePopup.d.ts.map +1 -1
- package/dist/style/accordionCss.d.ts +2 -0
- package/dist/style/accordionCss.d.ts.map +1 -0
- package/dist/style/accordionCss.js +101 -0
- package/dist/style/badgeCss.d.ts +5 -0
- package/dist/style/badgeCss.d.ts.map +1 -0
- package/dist/style/badgeCss.js +68 -0
- package/dist/style/breadcrumbCss.d.ts +2 -0
- package/dist/style/breadcrumbCss.d.ts.map +1 -0
- package/dist/style/breadcrumbCss.js +53 -0
- package/dist/style/cardCss.d.ts +2 -0
- package/dist/style/cardCss.d.ts.map +1 -0
- package/dist/style/cardCss.js +49 -0
- package/dist/style/inputCss.d.ts +2 -0
- package/dist/style/inputCss.d.ts.map +1 -0
- package/dist/style/inputCss.js +107 -0
- package/dist/style/loaderCss.d.ts +2 -0
- package/dist/style/loaderCss.d.ts.map +1 -0
- package/dist/style/loaderCss.js +39 -0
- package/dist/style/menuCss.d.ts +2 -0
- package/dist/style/menuCss.d.ts.map +1 -0
- package/dist/style/menuCss.js +71 -0
- package/dist/style/paginationCss.d.ts +2 -0
- package/dist/style/paginationCss.d.ts.map +1 -0
- package/dist/style/paginationCss.js +57 -0
- package/dist/style/resolveColor.d.ts +8 -0
- package/dist/style/resolveColor.d.ts.map +1 -0
- package/dist/style/resolveColor.js +13 -0
- package/dist/style/stackCss.d.ts +2 -0
- package/dist/style/stackCss.d.ts.map +1 -0
- package/dist/style/stackCss.js +21 -0
- package/dist/style/statusCss.d.ts +2 -0
- package/dist/style/statusCss.d.ts.map +1 -0
- package/dist/style/statusCss.js +38 -0
- package/dist/style/tableCss.d.ts +2 -0
- package/dist/style/tableCss.d.ts.map +1 -0
- package/dist/style/tableCss.js +92 -0
- package/dist/style/tabsCss.d.ts +2 -0
- package/dist/style/tabsCss.d.ts.map +1 -0
- package/dist/style/tabsCss.js +72 -0
- package/dist/style/toLength.d.ts +4 -0
- package/dist/style/toLength.d.ts.map +1 -0
- package/dist/style/toLength.js +3 -0
- package/dist/style/tooltipCss.d.ts +2 -0
- package/dist/style/tooltipCss.d.ts.map +1 -0
- package/dist/style/tooltipCss.js +44 -0
- package/dist/style/useStyle.d.ts +7 -0
- package/dist/style/useStyle.d.ts.map +1 -0
- package/dist/style/useStyle.js +16 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -1
- package/dist/theme/ThemeProvider.js +32 -0
- package/dist/theme/palette.d.ts.map +1 -1
- package/dist/theme/palette.js +0 -2
- package/dist/tooltip/attributeTooltips.d.ts +7 -0
- package/dist/tooltip/attributeTooltips.d.ts.map +1 -0
- package/dist/tooltip/attributeTooltips.js +76 -0
- package/dist/tooltip/tooltipEngine.d.ts +41 -0
- package/dist/tooltip/tooltipEngine.d.ts.map +1 -0
- package/dist/tooltip/tooltipEngine.js +128 -0
- package/dist/utils/childRef.d.ts +5 -0
- package/dist/utils/childRef.d.ts.map +1 -0
- package/dist/utils/childRef.js +14 -0
- package/dist/utils/isDev.d.ts +3 -0
- package/dist/utils/isDev.d.ts.map +1 -0
- package/dist/utils/isDev.js +4 -0
- package/package.json +5 -4
|
@@ -4,18 +4,63 @@ import { createErrorRules, createGraphqlErrorRules } from "./errorRules.js";
|
|
|
4
4
|
import { createInterceptedFetch } from "./fetchInterceptor.js";
|
|
5
5
|
import { PopupHost } from "./PopupHost.js";
|
|
6
6
|
import { PopupContext } from "./usePopup.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
// Anonymous group used by push() without `group` and by fetch without `fetchGroup`.
|
|
8
|
+
const DEFAULT_GROUP = "";
|
|
9
|
+
let nextItemId = 0;
|
|
10
|
+
function addItem(groups, name, item) {
|
|
11
|
+
const group = groups.find(g => g.name === name);
|
|
12
|
+
if (!group)
|
|
13
|
+
return [...groups, { name, items: [item] }];
|
|
14
|
+
if (item.dedupKey !== null && group.items.some(i => i.dedupKey === item.dedupKey))
|
|
15
|
+
return groups;
|
|
16
|
+
return groups.map(g => (g === group ? { name, items: [...g.items, item] } : g));
|
|
17
|
+
}
|
|
18
|
+
function removeFetchItems(groups) {
|
|
19
|
+
if (!groups.some(g => g.items.some(i => i.fromFetch)))
|
|
20
|
+
return groups;
|
|
21
|
+
return groups
|
|
22
|
+
.map(g => ({ name: g.name, items: g.items.filter(i => !i.fromFetch) }))
|
|
23
|
+
.filter(g => g.items.length > 0);
|
|
24
|
+
}
|
|
25
|
+
export function PopupProvider({ children, closeLabel, groups: groupConfigs, color = "--color-primary", interceptFetch = false, fetchGroup = DEFAULT_GROUP, onReport, className, style, ...ruleOptions }) {
|
|
26
|
+
const [groups, setGroups] = useState([]);
|
|
11
27
|
// L'interception ne s'installe qu'une fois : le callback, lui, peut changer d'un rendu à
|
|
12
28
|
// l'autre sans avoir à la réinstaller.
|
|
13
29
|
const reportRef = useRef(onReport);
|
|
14
30
|
reportRef.current = onReport;
|
|
15
|
-
// Options arrive as literals: reading them through
|
|
16
|
-
// reinstalled on every parent render.
|
|
31
|
+
// Options arrive as literals: reading them through refs keeps the interceptor from being
|
|
32
|
+
// reinstalled, and push() stable, on every parent render.
|
|
17
33
|
const ruleOptionsRef = useRef(ruleOptions);
|
|
18
34
|
ruleOptionsRef.current = ruleOptions;
|
|
35
|
+
const groupConfigsRef = useRef(groupConfigs);
|
|
36
|
+
groupConfigsRef.current = groupConfigs;
|
|
37
|
+
const fetchGroupRef = useRef(fetchGroup);
|
|
38
|
+
fetchGroupRef.current = fetchGroup;
|
|
39
|
+
const timers = useRef(new Map());
|
|
40
|
+
const dismiss = useCallback((group) => {
|
|
41
|
+
if (group === undefined) {
|
|
42
|
+
timers.current.forEach(clearTimeout);
|
|
43
|
+
timers.current.clear();
|
|
44
|
+
setGroups([]);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
clearTimeout(timers.current.get(group));
|
|
48
|
+
timers.current.delete(group);
|
|
49
|
+
setGroups(current => (current.some(g => g.name === group) ? current.filter(g => g.name !== group) : current));
|
|
50
|
+
}, []);
|
|
51
|
+
const add = useCallback((group, content, dedupKey, fromFetch) => {
|
|
52
|
+
setGroups(current => addItem(current, group, { id: nextItemId++, dedupKey, content, fromFetch }));
|
|
53
|
+
// The group's timer restarts with every message.
|
|
54
|
+
const duration = groupConfigsRef.current?.[group]?.duration;
|
|
55
|
+
if (duration) {
|
|
56
|
+
clearTimeout(timers.current.get(group));
|
|
57
|
+
timers.current.set(group, setTimeout(() => dismiss(group), duration));
|
|
58
|
+
}
|
|
59
|
+
}, [dismiss]);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
const pending = timers.current;
|
|
62
|
+
return () => pending.forEach(clearTimeout);
|
|
63
|
+
}, []);
|
|
19
64
|
useEffect(() => {
|
|
20
65
|
if (!interceptFetch)
|
|
21
66
|
return;
|
|
@@ -26,8 +71,8 @@ export function PopupProvider({ children, closeLabel, interceptFetch = false, on
|
|
|
26
71
|
? createGraphqlErrorRules(ruleOptionsRef.current)
|
|
27
72
|
: createErrorRules(ruleOptionsRef.current);
|
|
28
73
|
const intercepted = createInterceptedFetch(original, {
|
|
29
|
-
onRequestStart: () =>
|
|
30
|
-
onError: message =>
|
|
74
|
+
onRequestStart: () => setGroups(removeFetchItems),
|
|
75
|
+
onError: message => add(fetchGroupRef.current, message, message, true),
|
|
31
76
|
onReport: report => reportRef.current?.(report),
|
|
32
77
|
}, rules);
|
|
33
78
|
intercepted.__popupIntercepted = true;
|
|
@@ -35,13 +80,20 @@ export function PopupProvider({ children, closeLabel, interceptFetch = false, on
|
|
|
35
80
|
return () => {
|
|
36
81
|
window.fetch = original;
|
|
37
82
|
};
|
|
38
|
-
}, [interceptFetch]);
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}, []);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
83
|
+
}, [interceptFetch, add]);
|
|
84
|
+
const push = useCallback((content, options) => {
|
|
85
|
+
const dedupKey = options?.id ?? (typeof content === "string" ? content : null);
|
|
86
|
+
add(options?.group ?? DEFAULT_GROUP, content, dedupKey, false);
|
|
87
|
+
}, [add]);
|
|
88
|
+
const api = useMemo(() => ({ push, dismiss }), [push, dismiss]);
|
|
89
|
+
const boxes = groups.map(group => {
|
|
90
|
+
const config = groupConfigs?.[group.name];
|
|
91
|
+
return {
|
|
92
|
+
group: group.name,
|
|
93
|
+
color: config?.color ?? color,
|
|
94
|
+
className: config?.className,
|
|
95
|
+
items: group.items.map(item => ({ id: item.id, content: item.content })),
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
return (_jsxs(PopupContext.Provider, { value: api, children: [children, _jsx(PopupHost, { boxes: boxes, onDismiss: dismiss, closeLabel: closeLabel, className: className, style: style })] }));
|
|
47
99
|
}
|
package/dist/popup/usePopup.d.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type PushOptions = {
|
|
3
|
+
/** Group whose box shows the message. Omitted: the anonymous default group. */
|
|
4
|
+
group?: string;
|
|
5
|
+
/** Dedup key within the group. Strings dedup by value; other content only through `id`. */
|
|
6
|
+
id?: string;
|
|
7
|
+
};
|
|
1
8
|
export type PopupApi = {
|
|
2
|
-
/** Shows
|
|
3
|
-
|
|
4
|
-
/** Closes
|
|
5
|
-
dismiss: () => void;
|
|
9
|
+
/** Shows `content` in its group's box until closed (× or the group's `duration`). */
|
|
10
|
+
push: (content: ReactNode, options?: PushOptions) => void;
|
|
11
|
+
/** Closes one group's box, or every box when called without a group. */
|
|
12
|
+
dismiss: (group?: string) => void;
|
|
6
13
|
};
|
|
7
14
|
export declare const PopupContext: import("react").Context<PopupApi | null>;
|
|
8
15
|
export declare function usePopup(): PopupApi;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePopup.d.ts","sourceRoot":"","sources":["../../src/popup/usePopup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePopup.d.ts","sourceRoot":"","sources":["../../src/popup/usePopup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,WAAW,GAAG;IACxB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2FAA2F;IAC3F,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,qFAAqF;IACrF,IAAI,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;IACzD,wEAAwE;IACxE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC,CAAA;AAED,eAAO,MAAM,YAAY,0CAAuC,CAAA;AAEhE,wBAAgB,QAAQ,IAAI,QAAQ,CAInC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const accordionCss = "\n:where(.rui-accordion:not([data-variant=\"separated\"])) {\n border: 1px solid var(--rui-accordion-border, var(--color-border));\n border-radius: 12px;\n background-color: var(--rui-accordion-bg, var(--color-surface));\n overflow: hidden;\n}\n:where(.rui-accordion:not([data-variant=\"separated\"])) > :where(details + details) {\n border-top: 1px solid var(--rui-accordion-border, var(--color-border));\n}\n:where(.rui-accordion[data-variant=\"separated\"]) {\n display: flex;\n flex-direction: column;\n gap: var(--rui-accordion-gap, 0.5rem);\n}\n:where(.rui-accordion[data-variant=\"separated\"]) > :where(details) {\n border: 1px solid var(--rui-accordion-border, var(--color-border));\n border-radius: 12px;\n background-color: var(--rui-accordion-bg, var(--color-surface));\n overflow: hidden;\n}\n\n:where(.rui-accordion) :where(summary) {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: var(--rui-accordion-padding, 0.875rem 1rem);\n color: var(--color-text);\n font-weight: 500;\n list-style: none;\n cursor: pointer;\n}\n:where(.rui-accordion) :where(summary)::-webkit-details-marker {\n display: none;\n}\n:where(.rui-accordion) :where(summary:hover) {\n background-color: color-mix(in srgb, var(--color-text) 4%, transparent);\n}\n:where(.rui-accordion) :where(summary:focus-visible) {\n outline: 2px solid var(--color-primary);\n outline-offset: -2px;\n}\n:where(.rui-accordion) :where(details) > :where(:not(summary)) {\n padding: var(--rui-accordion-padding, 0.875rem 1rem);\n color: var(--color-text);\n}\n\n:where(.rui-accordion:not([data-chevron=\"start\"], [data-chevron=\"none\"])) :where(summary)::after {\n \n content: \"\";\n flex-shrink: 0;\n width: 0.45em;\n height: 0.45em;\n border-right: 2px solid var(--color-text-muted);\n border-bottom: 2px solid var(--color-text-muted);\n transform: translateY(-25%) rotate(45deg);\n transition: transform 150ms ease-out;\n\n margin-left: auto;\n}\n:where(.rui-accordion:not([data-chevron=\"start\"], [data-chevron=\"none\"])) :where(details[open] > summary)::after {\n transform: translateY(25%) rotate(-135deg);\n}\n:where(.rui-accordion[data-chevron=\"start\"]) :where(summary)::before {\n \n content: \"\";\n flex-shrink: 0;\n width: 0.45em;\n height: 0.45em;\n border-right: 2px solid var(--color-text-muted);\n border-bottom: 2px solid var(--color-text-muted);\n transform: translateY(-25%) rotate(45deg);\n transition: transform 150ms ease-out;\n\n}\n:where(.rui-accordion[data-chevron=\"start\"]) :where(details[open] > summary)::before {\n transform: translateY(25%) rotate(-135deg);\n}\n\n/* Progressive enhancement: animated where the browser can transition to height: auto. */\n@supports (interpolate-size: allow-keywords) {\n :where(.rui-accordion) {\n interpolate-size: allow-keywords;\n }\n :where(.rui-accordion details)::details-content {\n height: 0;\n overflow: hidden;\n transition: height 200ms ease-out, content-visibility 200ms allow-discrete;\n }\n :where(.rui-accordion details[open])::details-content {\n height: auto;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n :where(.rui-accordion) :where(summary)::before,\n :where(.rui-accordion) :where(summary)::after,\n :where(.rui-accordion details)::details-content {\n transition: none;\n }\n}\n";
|
|
2
|
+
//# sourceMappingURL=accordionCss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordionCss.d.ts","sourceRoot":"","sources":["../../src/style/accordionCss.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,YAAY,6wGAkFxB,CAAA"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Accordion on native <details> / <summary>: `rui-accordion` on the container,
|
|
2
|
+
// `data-variant="separated|joined"` (default joined), `data-chevron="start|end|none"` (default end).
|
|
3
|
+
// Every selector is wrapped in :where() so it has zero specificity:
|
|
4
|
+
// any class or style set by the consuming project wins without !important.
|
|
5
|
+
const border = "1px solid var(--rui-accordion-border, var(--color-border))";
|
|
6
|
+
const bg = "var(--rui-accordion-bg, var(--color-surface))";
|
|
7
|
+
const padding = "var(--rui-accordion-padding, 0.875rem 1rem)";
|
|
8
|
+
const chevron = `
|
|
9
|
+
content: "";
|
|
10
|
+
flex-shrink: 0;
|
|
11
|
+
width: 0.45em;
|
|
12
|
+
height: 0.45em;
|
|
13
|
+
border-right: 2px solid var(--color-text-muted);
|
|
14
|
+
border-bottom: 2px solid var(--color-text-muted);
|
|
15
|
+
transform: translateY(-25%) rotate(45deg);
|
|
16
|
+
transition: transform 150ms ease-out;
|
|
17
|
+
`;
|
|
18
|
+
const chevronOpen = "transform: translateY(25%) rotate(-135deg);";
|
|
19
|
+
export const accordionCss = `
|
|
20
|
+
:where(.rui-accordion:not([data-variant="separated"])) {
|
|
21
|
+
border: ${border};
|
|
22
|
+
border-radius: 12px;
|
|
23
|
+
background-color: ${bg};
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
}
|
|
26
|
+
:where(.rui-accordion:not([data-variant="separated"])) > :where(details + details) {
|
|
27
|
+
border-top: ${border};
|
|
28
|
+
}
|
|
29
|
+
:where(.rui-accordion[data-variant="separated"]) {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
gap: var(--rui-accordion-gap, 0.5rem);
|
|
33
|
+
}
|
|
34
|
+
:where(.rui-accordion[data-variant="separated"]) > :where(details) {
|
|
35
|
+
border: ${border};
|
|
36
|
+
border-radius: 12px;
|
|
37
|
+
background-color: ${bg};
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
:where(.rui-accordion) :where(summary) {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 0.75rem;
|
|
45
|
+
padding: ${padding};
|
|
46
|
+
color: var(--color-text);
|
|
47
|
+
font-weight: 500;
|
|
48
|
+
list-style: none;
|
|
49
|
+
cursor: pointer;
|
|
50
|
+
}
|
|
51
|
+
:where(.rui-accordion) :where(summary)::-webkit-details-marker {
|
|
52
|
+
display: none;
|
|
53
|
+
}
|
|
54
|
+
:where(.rui-accordion) :where(summary:hover) {
|
|
55
|
+
background-color: color-mix(in srgb, var(--color-text) 4%, transparent);
|
|
56
|
+
}
|
|
57
|
+
:where(.rui-accordion) :where(summary:focus-visible) {
|
|
58
|
+
outline: 2px solid var(--color-primary);
|
|
59
|
+
outline-offset: -2px;
|
|
60
|
+
}
|
|
61
|
+
:where(.rui-accordion) :where(details) > :where(:not(summary)) {
|
|
62
|
+
padding: ${padding};
|
|
63
|
+
color: var(--color-text);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
:where(.rui-accordion:not([data-chevron="start"], [data-chevron="none"])) :where(summary)::after {
|
|
67
|
+
${chevron}
|
|
68
|
+
margin-left: auto;
|
|
69
|
+
}
|
|
70
|
+
:where(.rui-accordion:not([data-chevron="start"], [data-chevron="none"])) :where(details[open] > summary)::after {
|
|
71
|
+
${chevronOpen}
|
|
72
|
+
}
|
|
73
|
+
:where(.rui-accordion[data-chevron="start"]) :where(summary)::before {
|
|
74
|
+
${chevron}
|
|
75
|
+
}
|
|
76
|
+
:where(.rui-accordion[data-chevron="start"]) :where(details[open] > summary)::before {
|
|
77
|
+
${chevronOpen}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Progressive enhancement: animated where the browser can transition to height: auto. */
|
|
81
|
+
@supports (interpolate-size: allow-keywords) {
|
|
82
|
+
:where(.rui-accordion) {
|
|
83
|
+
interpolate-size: allow-keywords;
|
|
84
|
+
}
|
|
85
|
+
:where(.rui-accordion details)::details-content {
|
|
86
|
+
height: 0;
|
|
87
|
+
overflow: hidden;
|
|
88
|
+
transition: height 200ms ease-out, content-visibility 200ms allow-discrete;
|
|
89
|
+
}
|
|
90
|
+
:where(.rui-accordion details[open])::details-content {
|
|
91
|
+
height: auto;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
@media (prefers-reduced-motion: reduce) {
|
|
95
|
+
:where(.rui-accordion) :where(summary)::before,
|
|
96
|
+
:where(.rui-accordion) :where(summary)::after,
|
|
97
|
+
:where(.rui-accordion details)::details-content {
|
|
98
|
+
transition: none;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
/** CSS variables shared by Badge and Tag. */
|
|
3
|
+
export declare function badgeVars(color: string, size: string | number | undefined): CSSProperties;
|
|
4
|
+
export declare const badgeCss = "\n:where(.rui-badge, .rui-tag) {\n display: inline-flex;\n align-items: center;\n gap: 0.35em;\n box-sizing: border-box;\n padding: 0.2em 0.6em;\n border: 1px solid var(--rui-badge-color, var(--color-primary));\n border-radius: 999px;\n background-color: var(--rui-badge-color, var(--color-primary));\n color: var(--rui-badge-on, var(--color-bg));\n font-size: var(--rui-badge-size, 0.75em);\n font-weight: 500;\n line-height: 1.2;\n white-space: nowrap;\n vertical-align: middle;\n}\n:where(.rui-badge[data-variant=\"outline\"], .rui-tag[data-variant=\"outline\"]) {\n background-color: transparent;\n color: var(--rui-badge-color, var(--color-primary));\n}\n:where(.rui-badge[data-variant=\"soft\"], .rui-tag[data-variant=\"soft\"]) {\n border-color: transparent;\n background-color: color-mix(in srgb, var(--rui-badge-color, var(--color-primary)) 15%, transparent);\n color: var(--rui-badge-color, var(--color-primary));\n}\n:where(.rui-tag-remove) {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.2em;\n height: 1.2em;\n margin-right: -0.3em;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: none;\n color: inherit;\n font: inherit;\n line-height: 1;\n cursor: pointer;\n opacity: 0.75;\n}\n:where(.rui-tag-remove:hover) {\n opacity: 1;\n background-color: color-mix(in srgb, currentColor 20%, transparent);\n}\n:where(.rui-tag-remove:focus-visible) {\n opacity: 1;\n outline: 2px solid currentColor;\n outline-offset: 1px;\n}\n";
|
|
5
|
+
//# sourceMappingURL=badgeCss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badgeCss.d.ts","sourceRoot":"","sources":["../../src/style/badgeCss.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAI1C,6CAA6C;AAC7C,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAMzF;AAOD,eAAO,MAAM,QAAQ,2/CAoDpB,CAAA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { resolveColor, resolveOnColor } from "./resolveColor.js";
|
|
2
|
+
import { toLength } from "./toLength.js";
|
|
3
|
+
/** CSS variables shared by Badge and Tag. */
|
|
4
|
+
export function badgeVars(color, size) {
|
|
5
|
+
return {
|
|
6
|
+
"--rui-badge-color": resolveColor(color),
|
|
7
|
+
"--rui-badge-on": resolveOnColor(color),
|
|
8
|
+
"--rui-badge-size": toLength(size),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
// Badge and Tag labels, usable as bare classes (`rui-badge`, `rui-tag` + `rui-tag-remove`)
|
|
12
|
+
// or through the Badge / Tag components. Variant through `data-variant="outline|soft"`.
|
|
13
|
+
// Every selector is wrapped in :where() so it has zero specificity:
|
|
14
|
+
// any class or style set by the consuming project wins without !important.
|
|
15
|
+
// Sizes are in em: padding and radius follow the font size.
|
|
16
|
+
export const badgeCss = `
|
|
17
|
+
:where(.rui-badge, .rui-tag) {
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
gap: 0.35em;
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
padding: 0.2em 0.6em;
|
|
23
|
+
border: 1px solid var(--rui-badge-color, var(--color-primary));
|
|
24
|
+
border-radius: 999px;
|
|
25
|
+
background-color: var(--rui-badge-color, var(--color-primary));
|
|
26
|
+
color: var(--rui-badge-on, var(--color-bg));
|
|
27
|
+
font-size: var(--rui-badge-size, 0.75em);
|
|
28
|
+
font-weight: 500;
|
|
29
|
+
line-height: 1.2;
|
|
30
|
+
white-space: nowrap;
|
|
31
|
+
vertical-align: middle;
|
|
32
|
+
}
|
|
33
|
+
:where(.rui-badge[data-variant="outline"], .rui-tag[data-variant="outline"]) {
|
|
34
|
+
background-color: transparent;
|
|
35
|
+
color: var(--rui-badge-color, var(--color-primary));
|
|
36
|
+
}
|
|
37
|
+
:where(.rui-badge[data-variant="soft"], .rui-tag[data-variant="soft"]) {
|
|
38
|
+
border-color: transparent;
|
|
39
|
+
background-color: color-mix(in srgb, var(--rui-badge-color, var(--color-primary)) 15%, transparent);
|
|
40
|
+
color: var(--rui-badge-color, var(--color-primary));
|
|
41
|
+
}
|
|
42
|
+
:where(.rui-tag-remove) {
|
|
43
|
+
display: inline-flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
width: 1.2em;
|
|
47
|
+
height: 1.2em;
|
|
48
|
+
margin-right: -0.3em;
|
|
49
|
+
padding: 0;
|
|
50
|
+
border: none;
|
|
51
|
+
border-radius: 50%;
|
|
52
|
+
background: none;
|
|
53
|
+
color: inherit;
|
|
54
|
+
font: inherit;
|
|
55
|
+
line-height: 1;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
opacity: 0.75;
|
|
58
|
+
}
|
|
59
|
+
:where(.rui-tag-remove:hover) {
|
|
60
|
+
opacity: 1;
|
|
61
|
+
background-color: color-mix(in srgb, currentColor 20%, transparent);
|
|
62
|
+
}
|
|
63
|
+
:where(.rui-tag-remove:focus-visible) {
|
|
64
|
+
opacity: 1;
|
|
65
|
+
outline: 2px solid currentColor;
|
|
66
|
+
outline-offset: 1px;
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const breadcrumbCss = "\n:where(.rui-breadcrumb) :where(ol) {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--rui-breadcrumb-gap, 0.5rem);\n margin: 0;\n padding: 0;\n list-style: none;\n font-size: 0.875rem;\n}\n:where(.rui-breadcrumb) :where(li) {\n display: inline-flex;\n align-items: center;\n gap: var(--rui-breadcrumb-gap, 0.5rem);\n color: var(--color-text-muted);\n}\n:where(.rui-breadcrumb) :where(li + li)::before {\n content: var(--rui-breadcrumb-separator, \"/\");\n color: var(--color-text-muted);\n}\n:where(.rui-breadcrumb) :where(a) {\n color: var(--color-text-muted);\n text-decoration: none;\n}\n:where(.rui-breadcrumb) :where(a:hover) {\n color: var(--color-text);\n}\n:where(.rui-breadcrumb) :where(a:focus-visible) {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n border-radius: 2px;\n}\n:where(.rui-breadcrumb) :where([aria-current=\"page\"]) {\n color: var(--color-text);\n text-decoration: none;\n}\n:where(.rui-breadcrumb) :where(ol[data-collapse] > li:not(:first-child, :nth-last-child(-n + 2))) {\n display: none;\n}\n/* Items were hidden (4 or more): mark the gap after the first one. */\n:where(.rui-breadcrumb) :where(ol[data-collapse] > li:first-child:not(:nth-last-child(-n + 3)))::after {\n content: var(--rui-breadcrumb-separator, \"/\") \" \u2026\";\n color: var(--color-text-muted);\n}\n";
|
|
2
|
+
//# sourceMappingURL=breadcrumbCss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breadcrumbCss.d.ts","sourceRoot":"","sources":["../../src/style/breadcrumbCss.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,aAAa,g2CA6CzB,CAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Breadcrumb, class only: `<nav class="rui-breadcrumb" aria-label="…"><ol><li>…</li></ol></nav>`,
|
|
2
|
+
// the last item with `aria-current="page"`. `data-collapse` on the <ol> keeps the first and
|
|
3
|
+
// the last two items, replacing the others with "…" (hidden items are not reachable).
|
|
4
|
+
// `--rui-breadcrumb-separator` is a CSS string, e.g. `"›"`.
|
|
5
|
+
// Every selector is wrapped in :where() so it has zero specificity:
|
|
6
|
+
// any class or style set by the consuming project wins without !important.
|
|
7
|
+
const separator = `var(--rui-breadcrumb-separator, "/")`;
|
|
8
|
+
export const breadcrumbCss = `
|
|
9
|
+
:where(.rui-breadcrumb) :where(ol) {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-wrap: wrap;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: var(--rui-breadcrumb-gap, 0.5rem);
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: 0;
|
|
16
|
+
list-style: none;
|
|
17
|
+
font-size: 0.875rem;
|
|
18
|
+
}
|
|
19
|
+
:where(.rui-breadcrumb) :where(li) {
|
|
20
|
+
display: inline-flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
gap: var(--rui-breadcrumb-gap, 0.5rem);
|
|
23
|
+
color: var(--color-text-muted);
|
|
24
|
+
}
|
|
25
|
+
:where(.rui-breadcrumb) :where(li + li)::before {
|
|
26
|
+
content: ${separator};
|
|
27
|
+
color: var(--color-text-muted);
|
|
28
|
+
}
|
|
29
|
+
:where(.rui-breadcrumb) :where(a) {
|
|
30
|
+
color: var(--color-text-muted);
|
|
31
|
+
text-decoration: none;
|
|
32
|
+
}
|
|
33
|
+
:where(.rui-breadcrumb) :where(a:hover) {
|
|
34
|
+
color: var(--color-text);
|
|
35
|
+
}
|
|
36
|
+
:where(.rui-breadcrumb) :where(a:focus-visible) {
|
|
37
|
+
outline: 2px solid var(--color-primary);
|
|
38
|
+
outline-offset: 2px;
|
|
39
|
+
border-radius: 2px;
|
|
40
|
+
}
|
|
41
|
+
:where(.rui-breadcrumb) :where([aria-current="page"]) {
|
|
42
|
+
color: var(--color-text);
|
|
43
|
+
text-decoration: none;
|
|
44
|
+
}
|
|
45
|
+
:where(.rui-breadcrumb) :where(ol[data-collapse] > li:not(:first-child, :nth-last-child(-n + 2))) {
|
|
46
|
+
display: none;
|
|
47
|
+
}
|
|
48
|
+
/* Items were hidden (4 or more): mark the gap after the first one. */
|
|
49
|
+
:where(.rui-breadcrumb) :where(ol[data-collapse] > li:first-child:not(:nth-last-child(-n + 3)))::after {
|
|
50
|
+
content: ${separator} " …";
|
|
51
|
+
color: var(--color-text-muted);
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const cardCss = "\n:where(.rui-card) {\n display: block;\n box-sizing: border-box;\n padding: var(--rui-card-padding, 1.25rem);\n border: 1px solid var(--rui-card-border, var(--color-border));\n border-radius: var(--rui-card-radius, 12px);\n background-color: var(--rui-card-bg, var(--color-surface));\n box-shadow: var(--rui-card-shadow, none);\n color: var(--color-text);\n}\n/* Custom properties inherit: a nested card must not take its parent's settings. */\n:where(.rui-card) > * {\n --rui-card-bg: initial;\n --rui-card-border: initial;\n --rui-card-shadow: initial;\n --rui-card-padding: initial;\n --rui-card-radius: initial;\n --rui-card-accent: initial;\n}\n:where(button.rui-card) {\n font: inherit;\n text-align: left;\n}\n:where(a.rui-card) {\n color: inherit;\n text-decoration: none;\n}\n:where(a.rui-card, button.rui-card, .rui-card[data-interactive]) {\n cursor: pointer;\n transition: border-color 120ms, box-shadow 120ms;\n}\n:where(a.rui-card, button.rui-card, .rui-card[data-interactive]):where(:hover) {\n border-color: color-mix(in srgb, var(--rui-card-border, var(--color-border)) 70%, var(--color-text));\n box-shadow: 0 4px 12px color-mix(in srgb, var(--color-text) 10%, transparent);\n}\n:where(a.rui-card, button.rui-card, .rui-card[data-interactive]):where(:focus-visible) {\n outline: 2px solid var(--rui-card-accent, var(--color-primary));\n outline-offset: 2px;\n}\n@media (prefers-reduced-motion: reduce) {\n :where(.rui-card) {\n transition: none;\n }\n}\n";
|
|
2
|
+
//# sourceMappingURL=cardCss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cardCss.d.ts","sourceRoot":"","sources":["../../src/style/cardCss.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,m+CA6CnB,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Card surface, usable as a bare class (`rui-card`) or through the Card component.
|
|
2
|
+
// Every selector is wrapped in :where() so it has zero specificity:
|
|
3
|
+
// any class or style set by the consuming project wins without !important.
|
|
4
|
+
export const cardCss = `
|
|
5
|
+
:where(.rui-card) {
|
|
6
|
+
display: block;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
padding: var(--rui-card-padding, 1.25rem);
|
|
9
|
+
border: 1px solid var(--rui-card-border, var(--color-border));
|
|
10
|
+
border-radius: var(--rui-card-radius, 12px);
|
|
11
|
+
background-color: var(--rui-card-bg, var(--color-surface));
|
|
12
|
+
box-shadow: var(--rui-card-shadow, none);
|
|
13
|
+
color: var(--color-text);
|
|
14
|
+
}
|
|
15
|
+
/* Custom properties inherit: a nested card must not take its parent's settings. */
|
|
16
|
+
:where(.rui-card) > * {
|
|
17
|
+
--rui-card-bg: initial;
|
|
18
|
+
--rui-card-border: initial;
|
|
19
|
+
--rui-card-shadow: initial;
|
|
20
|
+
--rui-card-padding: initial;
|
|
21
|
+
--rui-card-radius: initial;
|
|
22
|
+
--rui-card-accent: initial;
|
|
23
|
+
}
|
|
24
|
+
:where(button.rui-card) {
|
|
25
|
+
font: inherit;
|
|
26
|
+
text-align: left;
|
|
27
|
+
}
|
|
28
|
+
:where(a.rui-card) {
|
|
29
|
+
color: inherit;
|
|
30
|
+
text-decoration: none;
|
|
31
|
+
}
|
|
32
|
+
:where(a.rui-card, button.rui-card, .rui-card[data-interactive]) {
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
transition: border-color 120ms, box-shadow 120ms;
|
|
35
|
+
}
|
|
36
|
+
:where(a.rui-card, button.rui-card, .rui-card[data-interactive]):where(:hover) {
|
|
37
|
+
border-color: color-mix(in srgb, var(--rui-card-border, var(--color-border)) 70%, var(--color-text));
|
|
38
|
+
box-shadow: 0 4px 12px color-mix(in srgb, var(--color-text) 10%, transparent);
|
|
39
|
+
}
|
|
40
|
+
:where(a.rui-card, button.rui-card, .rui-card[data-interactive]):where(:focus-visible) {
|
|
41
|
+
outline: 2px solid var(--rui-card-accent, var(--color-primary));
|
|
42
|
+
outline-offset: 2px;
|
|
43
|
+
}
|
|
44
|
+
@media (prefers-reduced-motion: reduce) {
|
|
45
|
+
:where(.rui-card) {
|
|
46
|
+
transition: none;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const inputCss = "\n:where(.rui-input) {\n --rui-input-accent-color: var(--rui-input-accent, var(--color-primary));\n --rui-input-invalid-color: var(--rui-input-invalid, var(--color-text));\n}\n\n:where(.rui-input:not([type=\"checkbox\"], [type=\"radio\"])) {\n box-sizing: border-box;\n width: 100%;\n padding: 0.5rem 0.75rem;\n border: 1px solid var(--color-border);\n border-radius: 6px;\n background-color: var(--color-bg);\n color: var(--color-text);\n font: inherit;\n font-size: 0.875rem;\n line-height: 1;\n transition: border-color 120ms, box-shadow 120ms;\n}\n:where(.rui-input:not([type=\"checkbox\"], [type=\"radio\"]))::placeholder {\n color: var(--color-text-muted);\n opacity: 1;\n}\n:where(.rui-input:not([type=\"checkbox\"], [type=\"radio\"]):hover:not(:disabled)) {\n border-color: color-mix(in srgb, var(--color-border) 70%, var(--color-text));\n}\n:where(.rui-input:not([type=\"checkbox\"], [type=\"radio\"]):focus-visible) {\n outline: none;\n border-color: var(--rui-input-accent-color);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--rui-input-accent-color) 25%, transparent);\n}\n:where(.rui-input.rui-invalid:not([type=\"checkbox\"], [type=\"radio\"])) {\n border-color: var(--rui-input-invalid-color);\n}\n:where(.rui-input.rui-invalid:not([type=\"checkbox\"], [type=\"radio\"]):focus-visible) {\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--rui-input-invalid-color) 25%, transparent);\n}\n:where(textarea.rui-input) {\n min-height: calc(1em + 1rem + 2px);\n line-height: 1.4;\n resize: vertical;\n}\n:where(select.rui-input) option {\n background-color: var(--color-bg);\n color: var(--color-text);\n}\n:where(.rui-input:disabled) {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n:where(input.rui-input[type=\"checkbox\"], input.rui-input[type=\"radio\"]) {\n accent-color: var(--rui-input-accent-color);\n}\n\n:where(input.rui-input[type=\"checkbox\"][role=\"switch\"]) {\n appearance: none;\n position: relative;\n box-sizing: border-box;\n width: 2.25rem;\n height: 1.25rem;\n margin: 0;\n border: none;\n border-radius: 999px;\n background-color: var(--color-border);\n vertical-align: middle;\n cursor: pointer;\n transition: background-color 120ms;\n}\n:where(input.rui-input[type=\"checkbox\"][role=\"switch\"])::before {\n content: \"\";\n position: absolute;\n top: 2px;\n left: 2px;\n width: calc(1.25rem - 4px);\n height: calc(1.25rem - 4px);\n border-radius: 50%;\n background-color: var(--color-surface);\n box-shadow: 0 1px 2px color-mix(in srgb, var(--color-text) 25%, transparent);\n transition: transform 120ms;\n}\n:where(input.rui-input[type=\"checkbox\"][role=\"switch\"]:checked) {\n background-color: var(--rui-input-accent-color);\n}\n:where(input.rui-input[type=\"checkbox\"][role=\"switch\"]:checked)::before {\n transform: translateX(1rem);\n}\n:where(input.rui-input[type=\"checkbox\"][role=\"switch\"]:focus-visible) {\n outline: 2px solid var(--rui-input-accent-color);\n outline-offset: 2px;\n}\n:where(input.rui-input[type=\"checkbox\"][role=\"switch\"]:disabled) {\n cursor: not-allowed;\n}\n\n@media (prefers-reduced-motion: reduce) {\n :where(.rui-input),\n :where(input.rui-input[type=\"checkbox\"][role=\"switch\"])::before {\n transition: none;\n }\n}\n";
|
|
2
|
+
//# sourceMappingURL=inputCss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputCss.d.ts","sourceRoot":"","sources":["../../src/style/inputCss.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,QAAQ,qsGAqGpB,CAAA"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Themed look for native fields: the project puts `rui-input` on its own elements
|
|
2
|
+
// (`rui-input rui-invalid` for the error state). Injected by ThemeProvider.
|
|
3
|
+
// Every selector is wrapped in :where() so it has zero specificity:
|
|
4
|
+
// any class or style set by the consuming project wins without !important.
|
|
5
|
+
// Text fields match Button: same vertical padding, font size, line height, border and radius.
|
|
6
|
+
export const inputCss = `
|
|
7
|
+
:where(.rui-input) {
|
|
8
|
+
--rui-input-accent-color: var(--rui-input-accent, var(--color-primary));
|
|
9
|
+
--rui-input-invalid-color: var(--rui-input-invalid, var(--color-text));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:where(.rui-input:not([type="checkbox"], [type="radio"])) {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
width: 100%;
|
|
15
|
+
padding: 0.5rem 0.75rem;
|
|
16
|
+
border: 1px solid var(--color-border);
|
|
17
|
+
border-radius: 6px;
|
|
18
|
+
background-color: var(--color-bg);
|
|
19
|
+
color: var(--color-text);
|
|
20
|
+
font: inherit;
|
|
21
|
+
font-size: 0.875rem;
|
|
22
|
+
line-height: 1;
|
|
23
|
+
transition: border-color 120ms, box-shadow 120ms;
|
|
24
|
+
}
|
|
25
|
+
:where(.rui-input:not([type="checkbox"], [type="radio"]))::placeholder {
|
|
26
|
+
color: var(--color-text-muted);
|
|
27
|
+
opacity: 1;
|
|
28
|
+
}
|
|
29
|
+
:where(.rui-input:not([type="checkbox"], [type="radio"]):hover:not(:disabled)) {
|
|
30
|
+
border-color: color-mix(in srgb, var(--color-border) 70%, var(--color-text));
|
|
31
|
+
}
|
|
32
|
+
:where(.rui-input:not([type="checkbox"], [type="radio"]):focus-visible) {
|
|
33
|
+
outline: none;
|
|
34
|
+
border-color: var(--rui-input-accent-color);
|
|
35
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--rui-input-accent-color) 25%, transparent);
|
|
36
|
+
}
|
|
37
|
+
:where(.rui-input.rui-invalid:not([type="checkbox"], [type="radio"])) {
|
|
38
|
+
border-color: var(--rui-input-invalid-color);
|
|
39
|
+
}
|
|
40
|
+
:where(.rui-input.rui-invalid:not([type="checkbox"], [type="radio"]):focus-visible) {
|
|
41
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--rui-input-invalid-color) 25%, transparent);
|
|
42
|
+
}
|
|
43
|
+
:where(textarea.rui-input) {
|
|
44
|
+
min-height: calc(1em + 1rem + 2px);
|
|
45
|
+
line-height: 1.4;
|
|
46
|
+
resize: vertical;
|
|
47
|
+
}
|
|
48
|
+
:where(select.rui-input) option {
|
|
49
|
+
background-color: var(--color-bg);
|
|
50
|
+
color: var(--color-text);
|
|
51
|
+
}
|
|
52
|
+
:where(.rui-input:disabled) {
|
|
53
|
+
opacity: 0.4;
|
|
54
|
+
cursor: not-allowed;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
:where(input.rui-input[type="checkbox"], input.rui-input[type="radio"]) {
|
|
58
|
+
accent-color: var(--rui-input-accent-color);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
:where(input.rui-input[type="checkbox"][role="switch"]) {
|
|
62
|
+
appearance: none;
|
|
63
|
+
position: relative;
|
|
64
|
+
box-sizing: border-box;
|
|
65
|
+
width: 2.25rem;
|
|
66
|
+
height: 1.25rem;
|
|
67
|
+
margin: 0;
|
|
68
|
+
border: none;
|
|
69
|
+
border-radius: 999px;
|
|
70
|
+
background-color: var(--color-border);
|
|
71
|
+
vertical-align: middle;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
transition: background-color 120ms;
|
|
74
|
+
}
|
|
75
|
+
:where(input.rui-input[type="checkbox"][role="switch"])::before {
|
|
76
|
+
content: "";
|
|
77
|
+
position: absolute;
|
|
78
|
+
top: 2px;
|
|
79
|
+
left: 2px;
|
|
80
|
+
width: calc(1.25rem - 4px);
|
|
81
|
+
height: calc(1.25rem - 4px);
|
|
82
|
+
border-radius: 50%;
|
|
83
|
+
background-color: var(--color-surface);
|
|
84
|
+
box-shadow: 0 1px 2px color-mix(in srgb, var(--color-text) 25%, transparent);
|
|
85
|
+
transition: transform 120ms;
|
|
86
|
+
}
|
|
87
|
+
:where(input.rui-input[type="checkbox"][role="switch"]:checked) {
|
|
88
|
+
background-color: var(--rui-input-accent-color);
|
|
89
|
+
}
|
|
90
|
+
:where(input.rui-input[type="checkbox"][role="switch"]:checked)::before {
|
|
91
|
+
transform: translateX(1rem);
|
|
92
|
+
}
|
|
93
|
+
:where(input.rui-input[type="checkbox"][role="switch"]:focus-visible) {
|
|
94
|
+
outline: 2px solid var(--rui-input-accent-color);
|
|
95
|
+
outline-offset: 2px;
|
|
96
|
+
}
|
|
97
|
+
:where(input.rui-input[type="checkbox"][role="switch"]:disabled) {
|
|
98
|
+
cursor: not-allowed;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@media (prefers-reduced-motion: reduce) {
|
|
102
|
+
:where(.rui-input),
|
|
103
|
+
:where(input.rui-input[type="checkbox"][role="switch"])::before {
|
|
104
|
+
transition: none;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const loaderCss = "\n:where(.rui-spinner) {\n display: inline-block;\n box-sizing: border-box;\n flex-shrink: 0;\n width: var(--rui-spinner-size, 1em);\n height: var(--rui-spinner-size, 1em);\n border: var(--rui-spinner-thickness, 0.15em) solid var(--rui-spinner-color, currentColor);\n border-top-color: transparent;\n border-radius: 50%;\n vertical-align: middle;\n animation: rui-spin 0.8s linear infinite;\n}\n:where(.rui-skeleton) {\n display: block;\n border-radius: 4px;\n background-color: var(--rui-skeleton-color, var(--color-border));\n animation: rui-pulse 1.5s ease-in-out infinite;\n}\n@media (prefers-reduced-motion: reduce) {\n /* The spinner is the only loading signal: slowed down, not stopped. */\n :where(.rui-spinner) {\n animation-duration: 2s;\n }\n :where(.rui-skeleton) {\n animation: none;\n }\n}\n@keyframes rui-spin {\n to { transform: rotate(360deg); }\n}\n@keyframes rui-pulse {\n 50% { opacity: 0.5; }\n}\n";
|
|
2
|
+
//# sourceMappingURL=loaderCss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loaderCss.d.ts","sourceRoot":"","sources":["../../src/style/loaderCss.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,SAAS,s7BAkCrB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Loading indicators, usable as bare classes (`rui-spinner`, `rui-skeleton`) or through
|
|
2
|
+
// the Spinner / Skeleton components. Injected by ThemeProvider and by the components.
|
|
3
|
+
// Every selector is wrapped in :where() so it has zero specificity:
|
|
4
|
+
// any class or style set by the consuming project wins without !important.
|
|
5
|
+
export const loaderCss = `
|
|
6
|
+
:where(.rui-spinner) {
|
|
7
|
+
display: inline-block;
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
flex-shrink: 0;
|
|
10
|
+
width: var(--rui-spinner-size, 1em);
|
|
11
|
+
height: var(--rui-spinner-size, 1em);
|
|
12
|
+
border: var(--rui-spinner-thickness, 0.15em) solid var(--rui-spinner-color, currentColor);
|
|
13
|
+
border-top-color: transparent;
|
|
14
|
+
border-radius: 50%;
|
|
15
|
+
vertical-align: middle;
|
|
16
|
+
animation: rui-spin 0.8s linear infinite;
|
|
17
|
+
}
|
|
18
|
+
:where(.rui-skeleton) {
|
|
19
|
+
display: block;
|
|
20
|
+
border-radius: 4px;
|
|
21
|
+
background-color: var(--rui-skeleton-color, var(--color-border));
|
|
22
|
+
animation: rui-pulse 1.5s ease-in-out infinite;
|
|
23
|
+
}
|
|
24
|
+
@media (prefers-reduced-motion: reduce) {
|
|
25
|
+
/* The spinner is the only loading signal: slowed down, not stopped. */
|
|
26
|
+
:where(.rui-spinner) {
|
|
27
|
+
animation-duration: 2s;
|
|
28
|
+
}
|
|
29
|
+
:where(.rui-skeleton) {
|
|
30
|
+
animation: none;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
@keyframes rui-spin {
|
|
34
|
+
to { transform: rotate(360deg); }
|
|
35
|
+
}
|
|
36
|
+
@keyframes rui-pulse {
|
|
37
|
+
50% { opacity: 0.5; }
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const menuCss = "\n:where(.rui-menu) {\n position: fixed;\n top: 0;\n left: 0;\n box-sizing: border-box;\n min-width: 8rem;\n padding: 0.25rem;\n border: 1px solid var(--rui-menu-border, var(--color-border));\n border-radius: 8px;\n background-color: var(--rui-menu-bg, var(--color-surface));\n box-shadow: var(--rui-menu-shadow, 0 4px 16px color-mix(in srgb, var(--color-text) 15%, transparent));\n color: var(--color-text);\n font-size: 0.875rem;\n outline: none;\n animation: rui-menu-in 120ms ease-out;\n}\n/* Not positioned yet: invisible but focusable, so the first item can take the focus. */\n:where(.rui-menu:not([data-placement])) {\n opacity: 0;\n animation: none;\n}\n:where(.rui-menu-item) {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.375rem 0.625rem;\n border-radius: 4px;\n color: inherit;\n text-decoration: none;\n cursor: pointer;\n outline: none;\n user-select: none;\n}\n:where(.rui-menu-item:not([aria-disabled=\"true\"]):hover, .rui-menu-item:not([aria-disabled=\"true\"]):focus) {\n background-color: color-mix(in srgb, var(--rui-menu-accent, var(--color-primary)) 12%, transparent);\n}\n:where(.rui-menu-item[aria-disabled=\"true\"]) {\n opacity: 0.4;\n cursor: not-allowed;\n}\n:where(.rui-menu-indicator) {\n display: inline-flex;\n justify-content: center;\n width: 1em;\n color: var(--rui-menu-accent, var(--color-primary));\n}\n:where(.rui-menu-label) {\n padding: 0.375rem 0.625rem 0.25rem;\n color: var(--color-text-muted);\n font-size: 0.75rem;\n font-weight: 600;\n}\n:where(.rui-menu-separator) {\n height: 1px;\n margin: 0.25rem 0;\n background-color: var(--color-border);\n}\n@media (prefers-reduced-motion: reduce) {\n :where(.rui-menu) {\n animation: none;\n }\n}\n@keyframes rui-menu-in {\n from { opacity: 0; transform: translateY(-2px); }\n}\n";
|
|
2
|
+
//# sourceMappingURL=menuCss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menuCss.d.ts","sourceRoot":"","sources":["../../src/style/menuCss.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,OAAO,mzDAkEnB,CAAA"}
|