@-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
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useId, useState } from "react";
|
|
3
|
+
import { resolveColor } from "../style/resolveColor.js";
|
|
4
|
+
import { tabsCss } from "../style/tabsCss.js";
|
|
5
|
+
import { useStyle } from "../style/useStyle.js";
|
|
6
|
+
const TabsContext = createContext(null);
|
|
7
|
+
function useTabsContext(part) {
|
|
8
|
+
const ctx = useContext(TabsContext);
|
|
9
|
+
if (!ctx)
|
|
10
|
+
throw new Error(`Tabs.${part} must be used within Tabs`);
|
|
11
|
+
return ctx;
|
|
12
|
+
}
|
|
13
|
+
// Values are free strings: whitespace is not allowed in ids.
|
|
14
|
+
const idPart = (value) => value.replace(/\s/g, "_");
|
|
15
|
+
const tabId = (baseId, value) => `${baseId}-tab-${idPart(value)}`;
|
|
16
|
+
const panelId = (baseId, value) => `${baseId}-panel-${idPart(value)}`;
|
|
17
|
+
export function Tabs({ value: controlledValue, defaultValue, onChange, variant = "underline", orientation = "horizontal", color = "--color-primary", keepMounted = false, className, style, children, }) {
|
|
18
|
+
useStyle("tabs", tabsCss);
|
|
19
|
+
const baseId = useId();
|
|
20
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
21
|
+
const controlled = controlledValue !== undefined;
|
|
22
|
+
const value = controlled ? controlledValue : uncontrolledValue;
|
|
23
|
+
const select = (next) => {
|
|
24
|
+
if (next === value)
|
|
25
|
+
return;
|
|
26
|
+
if (!controlled)
|
|
27
|
+
setUncontrolledValue(next);
|
|
28
|
+
onChange?.(next);
|
|
29
|
+
};
|
|
30
|
+
return (_jsx(TabsContext.Provider, { value: { value, select, baseId, variant, orientation, color, keepMounted }, children: _jsx("div", { className: className, style: style, children: children }) }));
|
|
31
|
+
}
|
|
32
|
+
const NEXT_KEY = { horizontal: "ArrowRight", vertical: "ArrowDown" };
|
|
33
|
+
const PREV_KEY = { horizontal: "ArrowLeft", vertical: "ArrowUp" };
|
|
34
|
+
/** The tab list (`role="tablist"`, class `rui-tabs`). Arrow keys, Home and End move and activate. */
|
|
35
|
+
function List({ className, style, onKeyDown, ...props }) {
|
|
36
|
+
const { select, variant, orientation, color } = useTabsContext("List");
|
|
37
|
+
const handleKeyDown = (event) => {
|
|
38
|
+
onKeyDown?.(event);
|
|
39
|
+
const tabs = Array.from(event.currentTarget.querySelectorAll(':scope > [role="tab"]:not(:disabled)'));
|
|
40
|
+
const current = tabs.indexOf(event.target);
|
|
41
|
+
if (current === -1)
|
|
42
|
+
return;
|
|
43
|
+
let next;
|
|
44
|
+
if (event.key === NEXT_KEY[orientation])
|
|
45
|
+
next = (current + 1) % tabs.length;
|
|
46
|
+
else if (event.key === PREV_KEY[orientation])
|
|
47
|
+
next = (current - 1 + tabs.length) % tabs.length;
|
|
48
|
+
else if (event.key === "Home")
|
|
49
|
+
next = 0;
|
|
50
|
+
else if (event.key === "End")
|
|
51
|
+
next = tabs.length - 1;
|
|
52
|
+
else
|
|
53
|
+
return;
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
tabs[next].focus();
|
|
56
|
+
const nextValue = tabs[next].dataset.value;
|
|
57
|
+
if (nextValue !== undefined)
|
|
58
|
+
select(nextValue);
|
|
59
|
+
};
|
|
60
|
+
return (_jsx("div", { role: "tablist", "aria-orientation": orientation, ...props, className: className ? `rui-tabs ${className}` : "rui-tabs", "data-variant": variant, style: { "--rui-tabs-color": resolveColor(color), ...style }, onKeyDown: handleKeyDown }));
|
|
61
|
+
}
|
|
62
|
+
function Tab({ value, disabled, onClick, ...props }) {
|
|
63
|
+
const ctx = useTabsContext("Tab");
|
|
64
|
+
const selected = ctx.value === value;
|
|
65
|
+
return (_jsx("button", { type: "button", role: "tab", id: tabId(ctx.baseId, value), "aria-controls": panelId(ctx.baseId, value), "aria-selected": selected,
|
|
66
|
+
// Roving tabIndex: only the active tab is in the Tab order (every tab while none is active).
|
|
67
|
+
tabIndex: selected || ctx.value === undefined ? 0 : -1, disabled: disabled, "data-value": value, ...props, onClick: event => {
|
|
68
|
+
onClick?.(event);
|
|
69
|
+
if (!event.defaultPrevented)
|
|
70
|
+
ctx.select(value);
|
|
71
|
+
} }));
|
|
72
|
+
}
|
|
73
|
+
function Panel({ value, ...props }) {
|
|
74
|
+
const ctx = useTabsContext("Panel");
|
|
75
|
+
const selected = ctx.value === value;
|
|
76
|
+
if (!selected && !ctx.keepMounted)
|
|
77
|
+
return null;
|
|
78
|
+
return (_jsx("div", { role: "tabpanel", id: panelId(ctx.baseId, value), "aria-labelledby": tabId(ctx.baseId, value), tabIndex: 0, hidden: !selected, ...props }));
|
|
79
|
+
}
|
|
80
|
+
Tabs.List = List;
|
|
81
|
+
Tabs.Tab = Tab;
|
|
82
|
+
Tabs.Panel = Panel;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BadgeProps } from "./Badge.js";
|
|
2
|
+
type TagProps = BadgeProps & {
|
|
3
|
+
/** Shows a × button calling this. */
|
|
4
|
+
onRemove?: () => void;
|
|
5
|
+
/** Accessible name of the × button. Defaults to `"Remove"`. */
|
|
6
|
+
removeLabel?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function Tag({ variant, color, size, onRemove, removeLabel, className, style, children, ...props }: TagProps): import("react").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=Tag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tag.d.ts","sourceRoot":"","sources":["../../src/components/Tag.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,KAAK,QAAQ,GAAG,UAAU,GAAG;IAC3B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,GAAG,CAAC,EAClB,OAAiB,EACjB,KAAyB,EACzB,IAAI,EACJ,QAAQ,EACR,WAAsB,EACtB,SAAS,EACT,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,QAAQ,+BAiBV"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { badgeCss, badgeVars } from "../style/badgeCss.js";
|
|
3
|
+
import { useStyle } from "../style/useStyle.js";
|
|
4
|
+
export function Tag({ variant = "solid", color = "--color-primary", size, onRemove, removeLabel = "Remove", className, style, children, ...props }) {
|
|
5
|
+
useStyle("badge", badgeCss);
|
|
6
|
+
return (_jsxs("span", { ...props, className: className ? `rui-tag ${className}` : "rui-tag", "data-variant": variant, style: { ...badgeVars(color, size), ...style }, children: [children, onRemove && (_jsx("button", { type: "button", className: "rui-tag-remove", "aria-label": removeLabel, onClick: onRemove, children: "\u00D7" }))] }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { TooltipPlacement } from "../tooltip/tooltipEngine.js";
|
|
3
|
+
type TooltipProps = {
|
|
4
|
+
/** Not interactive: the bubble never receives pointer events or focus. */
|
|
5
|
+
content: ReactNode;
|
|
6
|
+
/** Flips and shifts by itself when there is no room. Defaults to `"top"`. */
|
|
7
|
+
placement?: TooltipPlacement;
|
|
8
|
+
/** Hover delay in ms before opening; keyboard focus opens right away. Defaults to 300. */
|
|
9
|
+
delay?: number;
|
|
10
|
+
/** Background. `"--color-x"` reads the theme variable; anything else is a raw CSS color. Defaults to `--color-text`. */
|
|
11
|
+
color?: string;
|
|
12
|
+
/** Defaults to `--color-bg`. */
|
|
13
|
+
textColor?: string;
|
|
14
|
+
/** Numbers are pixels. Defaults to 240. */
|
|
15
|
+
maxWidth?: string | number;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
/** A single element that accepts a ref (DOM element or forwardRef component). */
|
|
18
|
+
children: ReactElement;
|
|
19
|
+
};
|
|
20
|
+
export declare function Tooltip({ content, placement, delay, color, textColor, maxWidth, disabled, children, }: TooltipProps): import("react").JSX.Element;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=Tooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../src/components/Tooltip.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA4C,YAAY,EAAE,SAAS,EAAO,MAAM,OAAO,CAAA;AAKnG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AASnE,KAAK,YAAY,GAAG;IAClB,0EAA0E;IAC1E,OAAO,EAAE,SAAS,CAAA;IAClB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wHAAwH;IACxH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,iFAAiF;IACjF,QAAQ,EAAE,YAAY,CAAA;CACvB,CAAA;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,SAAiB,EACjB,KAAW,EACX,KAAK,EACL,SAAS,EACT,QAAQ,EACR,QAAgB,EAChB,QAAQ,GACT,EAAE,YAAY,+BA+Ed"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Children, cloneElement, useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
import { tooltipCss } from "../style/tooltipCss.js";
|
|
5
|
+
import { useStyle } from "../style/useStyle.js";
|
|
6
|
+
import { TooltipEngine } from "../tooltip/tooltipEngine.js";
|
|
7
|
+
import { assignRef, getElementRef } from "../utils/childRef.js";
|
|
8
|
+
import { isDev } from "../utils/isDev.js";
|
|
9
|
+
const INTERACTIVE = "a[href], button, input, select, textarea, [tabindex]";
|
|
10
|
+
export function Tooltip({ content, placement = "top", delay = 300, color, textColor, maxWidth, disabled = false, children, }) {
|
|
11
|
+
useStyle("tooltip", tooltipCss);
|
|
12
|
+
const [open, setOpen] = useState(false);
|
|
13
|
+
const [engine] = useState(() => new TooltipEngine(setOpen));
|
|
14
|
+
const anchorRef = useRef(null);
|
|
15
|
+
const child = Children.only(children);
|
|
16
|
+
const childProps = child.props;
|
|
17
|
+
const childRef = getElementRef(child);
|
|
18
|
+
const setAnchor = useCallback((node) => {
|
|
19
|
+
anchorRef.current = node;
|
|
20
|
+
assignRef(childRef, node);
|
|
21
|
+
}, [childRef]);
|
|
22
|
+
useLayoutEffect(() => {
|
|
23
|
+
engine.setLook({ placement, color, textColor, maxWidth });
|
|
24
|
+
}, [engine, placement, color, textColor, maxWidth]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (disabled)
|
|
27
|
+
engine.hide();
|
|
28
|
+
}, [engine, disabled]);
|
|
29
|
+
useEffect(() => () => engine.hide(), [engine]);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (isDev() && !anchorRef.current) {
|
|
32
|
+
console.warn("Tooltip: the child did not receive the ref (use a DOM element or a forwardRef component).");
|
|
33
|
+
}
|
|
34
|
+
}, []);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (open && isDev() && engine.content.querySelector(INTERACTIVE)) {
|
|
37
|
+
console.warn("Tooltip: the content holds an interactive element, which can never be reached.");
|
|
38
|
+
}
|
|
39
|
+
}, [engine, open, content]);
|
|
40
|
+
const onPointerEnter = (event) => {
|
|
41
|
+
childProps.onPointerEnter?.(event);
|
|
42
|
+
if (!disabled && event.pointerType !== "touch")
|
|
43
|
+
engine.scheduleShow(event.currentTarget, delay);
|
|
44
|
+
};
|
|
45
|
+
const onPointerLeave = (event) => {
|
|
46
|
+
childProps.onPointerLeave?.(event);
|
|
47
|
+
if (event.pointerType !== "touch")
|
|
48
|
+
engine.hide();
|
|
49
|
+
};
|
|
50
|
+
const onPointerDown = (event) => {
|
|
51
|
+
childProps.onPointerDown?.(event);
|
|
52
|
+
if (!disabled && event.pointerType === "touch")
|
|
53
|
+
engine.showForTouch(event.currentTarget);
|
|
54
|
+
};
|
|
55
|
+
const onFocus = (event) => {
|
|
56
|
+
childProps.onFocus?.(event);
|
|
57
|
+
if (!disabled)
|
|
58
|
+
engine.show(event.currentTarget);
|
|
59
|
+
};
|
|
60
|
+
const onBlur = (event) => {
|
|
61
|
+
childProps.onBlur?.(event);
|
|
62
|
+
engine.hide();
|
|
63
|
+
};
|
|
64
|
+
const describedBy = open
|
|
65
|
+
? [childProps["aria-describedby"], engine.id].filter(Boolean).join(" ")
|
|
66
|
+
: childProps["aria-describedby"];
|
|
67
|
+
return (_jsxs(_Fragment, { children: [cloneElement(child, {
|
|
68
|
+
ref: setAnchor,
|
|
69
|
+
"aria-describedby": describedBy,
|
|
70
|
+
onPointerEnter,
|
|
71
|
+
onPointerLeave,
|
|
72
|
+
onPointerDown,
|
|
73
|
+
onFocus,
|
|
74
|
+
onBlur,
|
|
75
|
+
}), createPortal(content, engine.content)] }));
|
|
76
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function openDrawer(id: string): void;
|
|
2
|
+
export declare function closeDrawer(id: string): void;
|
|
3
|
+
export declare function toggleDrawer(id: string): void;
|
|
4
|
+
/** Reads whether drawer `id` is open by call, with bound `open` / `close` / `toggle`. */
|
|
5
|
+
export declare function useDrawer(id: string): {
|
|
6
|
+
isOpen: boolean;
|
|
7
|
+
open: () => void;
|
|
8
|
+
close: () => void;
|
|
9
|
+
toggle: () => void;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=drawerStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drawerStore.d.ts","sourceRoot":"","sources":["../../src/components/drawerStore.ts"],"names":[],"mappings":"AAqBA,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAAE,CAYlH"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useCallback, useMemo, useSyncExternalStore } from "react";
|
|
2
|
+
// Drawers opened by call, by id. Kept apart from Drawer.tsx so the component file
|
|
3
|
+
// only exports components (react-refresh rule).
|
|
4
|
+
const openIds = new Set();
|
|
5
|
+
const listeners = new Set();
|
|
6
|
+
function subscribe(listener) {
|
|
7
|
+
listeners.add(listener);
|
|
8
|
+
return () => {
|
|
9
|
+
listeners.delete(listener);
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function setDrawerOpen(id, open) {
|
|
13
|
+
if (openIds.has(id) === open)
|
|
14
|
+
return;
|
|
15
|
+
if (open)
|
|
16
|
+
openIds.add(id);
|
|
17
|
+
else
|
|
18
|
+
openIds.delete(id);
|
|
19
|
+
listeners.forEach(listener => listener());
|
|
20
|
+
}
|
|
21
|
+
export function openDrawer(id) {
|
|
22
|
+
setDrawerOpen(id, true);
|
|
23
|
+
}
|
|
24
|
+
export function closeDrawer(id) {
|
|
25
|
+
setDrawerOpen(id, false);
|
|
26
|
+
}
|
|
27
|
+
export function toggleDrawer(id) {
|
|
28
|
+
setDrawerOpen(id, !openIds.has(id));
|
|
29
|
+
}
|
|
30
|
+
/** Reads whether drawer `id` is open by call, with bound `open` / `close` / `toggle`. */
|
|
31
|
+
export function useDrawer(id) {
|
|
32
|
+
const getSnapshot = useCallback(() => openIds.has(id), [id]);
|
|
33
|
+
const isOpen = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
34
|
+
return useMemo(() => ({
|
|
35
|
+
isOpen,
|
|
36
|
+
open: () => openDrawer(id),
|
|
37
|
+
close: () => closeDrawer(id),
|
|
38
|
+
toggle: () => toggleDrawer(id),
|
|
39
|
+
}), [id, isOpen]);
|
|
40
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type PaginationItem = {
|
|
2
|
+
type: "page";
|
|
3
|
+
page: number;
|
|
4
|
+
current: boolean;
|
|
5
|
+
} | {
|
|
6
|
+
type: "first" | "previous" | "next" | "last";
|
|
7
|
+
page: number;
|
|
8
|
+
disabled: boolean;
|
|
9
|
+
} | {
|
|
10
|
+
type: "ellipsis";
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Items to render for `page` of `total` (1-based): edges, previous / next, the first and
|
|
14
|
+
* last pages, `siblings` pages around the current one, and ellipses for the gaps.
|
|
15
|
+
* A gap of a single page shows that page instead of an ellipsis.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getPaginationItems(page: number, total: number, siblings: number, showEdges: boolean): PaginationItem[];
|
|
18
|
+
//# sourceMappingURL=paginationItems.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginationItems.d.ts","sourceRoot":"","sources":["../../src/components/paginationItems.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACjF;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAA;AAExB;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,cAAc,EAAE,CAyBtH"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Items to render for `page` of `total` (1-based): edges, previous / next, the first and
|
|
3
|
+
* last pages, `siblings` pages around the current one, and ellipses for the gaps.
|
|
4
|
+
* A gap of a single page shows that page instead of an ellipsis.
|
|
5
|
+
*/
|
|
6
|
+
export function getPaginationItems(page, total, siblings, showEdges) {
|
|
7
|
+
const last = Math.max(1, total);
|
|
8
|
+
const current = Math.min(Math.max(1, page), last);
|
|
9
|
+
const shown = new Set([1, last]);
|
|
10
|
+
for (let p = current - siblings; p <= current + siblings; p++) {
|
|
11
|
+
if (p >= 1 && p <= last)
|
|
12
|
+
shown.add(p);
|
|
13
|
+
}
|
|
14
|
+
const pages = [...shown].sort((a, b) => a - b);
|
|
15
|
+
const items = [];
|
|
16
|
+
if (showEdges)
|
|
17
|
+
items.push({ type: "first", page: 1, disabled: current === 1 });
|
|
18
|
+
items.push({ type: "previous", page: current - 1, disabled: current === 1 });
|
|
19
|
+
let previous = 0;
|
|
20
|
+
for (const p of pages) {
|
|
21
|
+
if (p - previous === 2)
|
|
22
|
+
items.push({ type: "page", page: p - 1, current: false });
|
|
23
|
+
else if (p - previous > 2)
|
|
24
|
+
items.push({ type: "ellipsis" });
|
|
25
|
+
items.push({ type: "page", page: p, current: p === current });
|
|
26
|
+
previous = p;
|
|
27
|
+
}
|
|
28
|
+
items.push({ type: "next", page: current + 1, disabled: current === last });
|
|
29
|
+
if (showEdges)
|
|
30
|
+
items.push({ type: "last", page: last, disabled: current === last });
|
|
31
|
+
return items;
|
|
32
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,21 +2,37 @@ export { default as Modal, openModal, closeModal } from "./components/Modal.js";
|
|
|
2
2
|
export { default as ColorPicker } from "./components/ColorPicker.js";
|
|
3
3
|
export { default as ConfirmDeleteButton } from "./components/ConfirmDeleteButton.js";
|
|
4
4
|
export { ColorField } from "./components/ColorField.js";
|
|
5
|
-
export { Button, type ButtonVariant } from "./components/Button.js";
|
|
6
|
-
export { NavBar
|
|
7
|
-
export {
|
|
5
|
+
export { Button, type ButtonVariant, type ThemeColorVar } from "./components/Button.js";
|
|
6
|
+
export { NavBar } from "./components/NavBar.js";
|
|
7
|
+
export { Spinner } from "./components/Spinner.js";
|
|
8
|
+
export { Skeleton } from "./components/Skeleton.js";
|
|
9
|
+
export { Card } from "./components/Card.js";
|
|
10
|
+
export { Stack } from "./components/Stack.js";
|
|
11
|
+
export { Badge, type BadgeVariant } from "./components/Badge.js";
|
|
12
|
+
export { Tag } from "./components/Tag.js";
|
|
13
|
+
export { Tabs } from "./components/Tabs.js";
|
|
14
|
+
export { Tooltip } from "./components/Tooltip.js";
|
|
15
|
+
export { DropdownMenu } from "./components/DropdownMenu.js";
|
|
16
|
+
export { Table, type TableColumn, type SortState } from "./components/Table.js";
|
|
17
|
+
export type { TooltipPlacement } from "./tooltip/tooltipEngine.js";
|
|
18
|
+
export { Drawer, type DrawerSide, type DrawerMode } from "./components/Drawer.js";
|
|
19
|
+
export { openDrawer, closeDrawer, toggleDrawer, useDrawer } from "./components/drawerStore.js";
|
|
20
|
+
export { PageStatus } from "./components/PageStatus.js";
|
|
21
|
+
export { Pagination } from "./components/Pagination.js";
|
|
22
|
+
export { Accordion } from "./components/Accordion.js";
|
|
23
|
+
export type { PaginationItem } from "./components/paginationItems.js";
|
|
8
24
|
export { ThemeProvider, useTheme } from "./theme/ThemeProvider.js";
|
|
9
25
|
export { ThemeSelect } from "./theme/ThemeSelect.js";
|
|
10
26
|
export { defaultPalette } from "./theme/palette.js";
|
|
11
27
|
export { createLocalThemeStore, createHttpThemeStore, type ThemeStore } from "./theme/store.js";
|
|
12
28
|
export { serializeColors, parseColors, isHexColor, randomHex } from "./theme/clipboard.js";
|
|
13
29
|
export type { ThemeColors, ThemeDefinition, ThemeCatalog, ThemeDraft } from "./theme/types.js";
|
|
14
|
-
export { PopupProvider, type InterceptFetchMode } from "./popup/PopupProvider.js";
|
|
15
|
-
export { usePopup, type PopupApi } from "./popup/usePopup.js";
|
|
16
|
-
export { PopupHost } from "./popup/PopupHost.js";
|
|
30
|
+
export { PopupProvider, type InterceptFetchMode, type ToastGroupConfig } from "./popup/PopupProvider.js";
|
|
31
|
+
export { usePopup, type PopupApi, type PushOptions } from "./popup/usePopup.js";
|
|
32
|
+
export { PopupHost, type ToastBox } from "./popup/PopupHost.js";
|
|
17
33
|
export { createInterceptedFetch, type InterceptorHandlers } from "./popup/fetchInterceptor.js";
|
|
18
34
|
export { createErrorRules, createGraphqlErrorRules, defaultMessages, type ErrorRules, type ErrorRulesOptions, type GraphqlError, type GraphqlErrorRulesOptions, type PopupMessages, type FetchErrorReport, } from "./popup/errorRules.js";
|
|
19
35
|
export { fetchJson } from "./net/fetchJson.js";
|
|
20
|
-
export { useDocumentTitle, useAsync, useElementSize, useClickOutside, useEscapeKey } from "@-reddacted-/react-hooks";
|
|
36
|
+
export { useDocumentTitle, useAsync, useElementSize, useClickOutside, useEscapeKey, useFocusTrap, useScrollLock, useOverlayStack, } from "@-reddacted-/react-hooks";
|
|
21
37
|
export type { AsyncStatus, AsyncStatus as LoadStatus, AsyncResult, ElementSize } from "@-reddacted-/react-hooks";
|
|
22
38
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAC/E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACpE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,21 @@ export { default as ConfirmDeleteButton } from "./components/ConfirmDeleteButton
|
|
|
4
4
|
export { ColorField } from "./components/ColorField.js";
|
|
5
5
|
export { Button } from "./components/Button.js";
|
|
6
6
|
export { NavBar } from "./components/NavBar.js";
|
|
7
|
-
export {
|
|
7
|
+
export { Spinner } from "./components/Spinner.js";
|
|
8
|
+
export { Skeleton } from "./components/Skeleton.js";
|
|
9
|
+
export { Card } from "./components/Card.js";
|
|
10
|
+
export { Stack } from "./components/Stack.js";
|
|
11
|
+
export { Badge } from "./components/Badge.js";
|
|
12
|
+
export { Tag } from "./components/Tag.js";
|
|
13
|
+
export { Tabs } from "./components/Tabs.js";
|
|
14
|
+
export { Tooltip } from "./components/Tooltip.js";
|
|
15
|
+
export { DropdownMenu } from "./components/DropdownMenu.js";
|
|
16
|
+
export { Table } from "./components/Table.js";
|
|
17
|
+
export { Drawer } from "./components/Drawer.js";
|
|
18
|
+
export { openDrawer, closeDrawer, toggleDrawer, useDrawer } from "./components/drawerStore.js";
|
|
19
|
+
export { PageStatus } from "./components/PageStatus.js";
|
|
20
|
+
export { Pagination } from "./components/Pagination.js";
|
|
21
|
+
export { Accordion } from "./components/Accordion.js";
|
|
8
22
|
export { ThemeProvider, useTheme } from "./theme/ThemeProvider.js";
|
|
9
23
|
export { ThemeSelect } from "./theme/ThemeSelect.js";
|
|
10
24
|
export { defaultPalette } from "./theme/palette.js";
|
|
@@ -17,4 +31,4 @@ export { createInterceptedFetch } from "./popup/fetchInterceptor.js";
|
|
|
17
31
|
export { createErrorRules, createGraphqlErrorRules, defaultMessages, } from "./popup/errorRules.js";
|
|
18
32
|
export { fetchJson } from "./net/fetchJson.js";
|
|
19
33
|
// Réexportés depuis react-hooks : les appelants n'ont pas à connaître le découpage.
|
|
20
|
-
export { useDocumentTitle, useAsync, useElementSize, useClickOutside, useEscapeKey } from "@-reddacted-/react-hooks";
|
|
34
|
+
export { useDocumentTitle, useAsync, useElementSize, useClickOutside, useEscapeKey, useFocusTrap, useScrollLock, useOverlayStack, } from "@-reddacted-/react-hooks";
|
|
@@ -1,8 +1,24 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
/** One group's box: every message of the group, stacked. */
|
|
3
|
+
export type ToastBox = {
|
|
4
|
+
group: string;
|
|
5
|
+
/** `"--color-x"` reads the theme variable; anything else is a raw CSS color. */
|
|
6
|
+
color: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
items: {
|
|
9
|
+
id: number | string;
|
|
10
|
+
content: ReactNode;
|
|
11
|
+
}[];
|
|
12
|
+
};
|
|
1
13
|
type PopupHostProps = {
|
|
2
|
-
|
|
3
|
-
|
|
14
|
+
boxes: ToastBox[];
|
|
15
|
+
/** Called with the group of the box whose × was clicked. */
|
|
16
|
+
onDismiss: (group: string) => void;
|
|
4
17
|
closeLabel?: string;
|
|
18
|
+
/** Set on the `.rui-toasts` container. */
|
|
19
|
+
className?: string;
|
|
20
|
+
style?: CSSProperties;
|
|
5
21
|
};
|
|
6
|
-
export declare function PopupHost({
|
|
22
|
+
export declare function PopupHost({ boxes, onDismiss, closeLabel, className, style }: PopupHostProps): import("react").JSX.Element | null;
|
|
7
23
|
export {};
|
|
8
24
|
//# sourceMappingURL=PopupHost.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopupHost.d.ts","sourceRoot":"","sources":["../../src/popup/PopupHost.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PopupHost.d.ts","sourceRoot":"","sources":["../../src/popup/PopupHost.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAIrD,4DAA4D;AAC5D,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,EAAE,SAAS,CAAA;KAAE,EAAE,CAAA;CACrD,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAA;IACjB,4DAA4D;IAC5D,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,aAAa,CAAA;CACtB,CAAA;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,UAAoB,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,cAAc,sCA6BrG"}
|
package/dist/popup/PopupHost.js
CHANGED
|
@@ -1,46 +1,67 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { resolveColor } from "../style/resolveColor.js";
|
|
3
|
+
import { useStyle } from "../style/useStyle.js";
|
|
4
|
+
export function PopupHost({ boxes, onDismiss, closeLabel = "Close", className, style }) {
|
|
5
|
+
useStyle("toast", toastCss);
|
|
6
|
+
if (boxes.length === 0)
|
|
4
7
|
return null;
|
|
5
|
-
return (_jsxs("div", { role: "alert", "aria-live": "assertive", style:
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
8
|
+
return (_jsx("div", { className: className ? `rui-toasts ${className}` : "rui-toasts", style: style, children: boxes.map(box => (_jsxs("div", { role: "alert", "aria-live": "assertive", className: box.className ? `rui-toast ${box.className}` : "rui-toast", "data-group": box.group || undefined, style: { "--rui-toast-color": resolveColor(box.color) }, children: [_jsx("div", { className: "rui-toast-body", children: box.items.map(item => (_jsx("div", { className: "rui-toast-message", children: item.content }, item.id))) }), _jsx("button", { type: "button", className: "rui-toast-close", "aria-label": closeLabel, onClick: () => onDismiss(box.group), children: "\u00D7" })] }, box.group))) }));
|
|
9
|
+
}
|
|
10
|
+
// Every selector is wrapped in :where() so it has zero specificity:
|
|
11
|
+
// any class or style set by the consuming project wins without !important.
|
|
12
|
+
// Above the overlay stack (modals start at 1000) so errors stay visible over a modal.
|
|
13
|
+
const toastCss = `
|
|
14
|
+
:where(.rui-toasts) {
|
|
15
|
+
position: fixed;
|
|
16
|
+
top: 1rem;
|
|
17
|
+
left: 50%;
|
|
18
|
+
transform: translateX(-50%);
|
|
19
|
+
z-index: 2000;
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
gap: 0.5rem;
|
|
23
|
+
width: max-content;
|
|
24
|
+
max-width: min(32rem, calc(100vw - 2rem));
|
|
25
|
+
}
|
|
26
|
+
:where(.rui-toast) {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: flex-start;
|
|
29
|
+
gap: 0.75rem;
|
|
30
|
+
padding: 0.75rem 0.75rem 0.75rem 1rem;
|
|
31
|
+
border: 1px solid var(--rui-toast-color);
|
|
32
|
+
border-radius: 8px;
|
|
33
|
+
background-color: color-mix(in srgb, var(--rui-toast-color) 12%, var(--color-surface));
|
|
34
|
+
box-shadow: 0 4px 16px color-mix(in srgb, var(--color-text) 15%, transparent);
|
|
35
|
+
}
|
|
36
|
+
:where(.rui-toast-body) {
|
|
37
|
+
flex: 1;
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
gap: 0.25rem;
|
|
41
|
+
}
|
|
42
|
+
:where(.rui-toast-message) {
|
|
43
|
+
font-size: 0.875rem;
|
|
44
|
+
line-height: 1.4;
|
|
45
|
+
color: var(--color-text);
|
|
46
|
+
}
|
|
47
|
+
:where(.rui-toast-close) {
|
|
48
|
+
flex-shrink: 0;
|
|
49
|
+
width: 1.5rem;
|
|
50
|
+
height: 1.5rem;
|
|
51
|
+
padding: 0;
|
|
52
|
+
border: none;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
background-color: transparent;
|
|
55
|
+
color: var(--rui-toast-color);
|
|
56
|
+
font-size: 1.125rem;
|
|
57
|
+
line-height: 1;
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
}
|
|
60
|
+
:where(.rui-toast-close:hover) {
|
|
61
|
+
background-color: color-mix(in srgb, var(--rui-toast-color) 12%, transparent);
|
|
62
|
+
}
|
|
63
|
+
:where(.rui-toast-close:focus-visible) {
|
|
64
|
+
outline: 2px solid var(--rui-toast-color);
|
|
65
|
+
outline-offset: 1px;
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
@@ -1,19 +1,36 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
2
|
import type { FetchErrorReport, GraphqlErrorRulesOptions } from "./errorRules.js";
|
|
3
3
|
/** Which `window.fetch` failures raise a popup on their own; `false` leaves fetch untouched. */
|
|
4
4
|
export type InterceptFetchMode = false | "rest" | "graphql";
|
|
5
|
+
export type ToastGroupConfig = {
|
|
6
|
+
/** `"--color-x"` reads the theme variable; anything else is a raw CSS color. Defaults to the provider's `color`. */
|
|
7
|
+
color?: string;
|
|
8
|
+
/** Closes the group's box this many ms after its last message. Absent or 0: stays until closed. */
|
|
9
|
+
duration?: number;
|
|
10
|
+
/** Added to the group's `.rui-toast` box. */
|
|
11
|
+
className?: string;
|
|
12
|
+
};
|
|
5
13
|
type PopupProviderProps = GraphqlErrorRulesOptions & {
|
|
6
14
|
children: ReactNode;
|
|
7
15
|
closeLabel?: string;
|
|
16
|
+
/** Groups the project uses, by name. Undeclared groups are accepted with the defaults. */
|
|
17
|
+
groups?: Record<string, ToastGroupConfig>;
|
|
18
|
+
/** Default color of every box. `"--color-x"` reads the theme variable. Defaults to `"--color-primary"`. */
|
|
19
|
+
color?: string;
|
|
8
20
|
/**
|
|
9
21
|
* Installs a `window.fetch` interceptor that raises popups by itself: `"rest"` reads HTTP
|
|
10
22
|
* statuses, `"graphql"` also reads the `errors` array on `graphqlPaths`. Off by default.
|
|
11
23
|
* Intercepted messages clear as soon as the next request starts; pushed ones stay.
|
|
12
24
|
*/
|
|
13
25
|
interceptFetch?: InterceptFetchMode;
|
|
26
|
+
/** Group of intercepted fetch failures. Omitted: the anonymous default group. */
|
|
27
|
+
fetchGroup?: string;
|
|
14
28
|
/** Called for every intercepted failure, with the method, URL and status behind it. */
|
|
15
29
|
onReport?: (report: FetchErrorReport) => void;
|
|
30
|
+
/** Set on the `.rui-toasts` container, e.g. to move it. */
|
|
31
|
+
className?: string;
|
|
32
|
+
style?: CSSProperties;
|
|
16
33
|
};
|
|
17
|
-
export declare function PopupProvider({ children, closeLabel, interceptFetch, onReport, ...ruleOptions }: PopupProviderProps): import("react").JSX.Element;
|
|
34
|
+
export declare function PopupProvider({ children, closeLabel, groups: groupConfigs, color, interceptFetch, fetchGroup, onReport, className, style, ...ruleOptions }: PopupProviderProps): import("react").JSX.Element;
|
|
18
35
|
export {};
|
|
19
36
|
//# sourceMappingURL=PopupProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopupProvider.d.ts","sourceRoot":"","sources":["../../src/popup/PopupProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"PopupProvider.d.ts","sourceRoot":"","sources":["../../src/popup/PopupProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AASjF,gGAAgG;AAChG,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;AAE3D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,oHAAoH;IACpH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mGAAmG;IACnG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,kBAAkB,GAAG,wBAAwB,GAAG;IACnD,QAAQ,EAAE,SAAS,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACzC,2GAA2G;IAC3G,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,cAAc,CAAC,EAAE,kBAAkB,CAAA;IACnC,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC7C,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,aAAa,CAAA;CACtB,CAAA;AAwBD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,UAAU,EACV,MAAM,EAAE,YAAY,EACpB,KAAyB,EACzB,cAAsB,EACtB,UAA0B,EAC1B,QAAQ,EACR,SAAS,EACT,KAAK,EACL,GAAG,WAAW,EACf,EAAE,kBAAkB,+BA0GpB"}
|