@rojaostudio/ds 2.0.0-next.3 → 2.0.0-next.31
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/README.md +42 -2
- package/THIRD_PARTY_NOTICES.md +66 -0
- package/dist/components/avatar.d.ts +20 -12
- package/dist/components/avatar.js +8 -6
- package/dist/components/badge.d.ts +7 -6
- package/dist/components/badge.js +2 -1
- package/dist/components/breadcrumb.d.ts +4 -4
- package/dist/components/breadcrumb.js +1 -1
- package/dist/components/bubble.d.ts +26 -11
- package/dist/components/bubble.js +3 -3
- package/dist/components/button.d.ts +1 -1
- package/dist/components/card.d.ts +28 -12
- package/dist/components/card.js +4 -2
- package/dist/components/chart.d.ts +18 -8
- package/dist/components/chart.js +89 -25
- package/dist/components/choice-carousel.d.ts +1 -1
- package/dist/components/choice-carousel.js +2 -4
- package/dist/components/choice-list.d.ts +40 -0
- package/dist/components/choice-list.js +122 -0
- package/dist/components/choice-preview-card.d.ts +1 -7
- package/dist/components/color-input.d.ts +1 -1
- package/dist/components/context-menu.d.ts +5 -2
- package/dist/components/currency-input.d.ts +0 -2
- package/dist/components/data-table-header.d.ts +55 -18
- package/dist/components/data-table-header.js +148 -101
- package/dist/components/date-picker.d.ts +1 -1
- package/dist/components/dialog.d.ts +6 -3
- package/dist/components/dialog.js +2 -2
- package/dist/components/dropdown-menu.d.ts +5 -2
- package/dist/components/dropzone.d.ts +2 -2
- package/dist/components/dropzone.js +1 -1
- package/dist/components/file-input.d.ts +13 -8
- package/dist/components/file-input.js +24 -21
- package/dist/components/filter-chip.d.ts +11 -5
- package/dist/components/filter-chip.js +15 -6
- package/dist/components/floating-stepper.d.ts +11 -28
- package/dist/components/floating-stepper.js +2 -30
- package/dist/components/form-actions.d.ts +45 -15
- package/dist/components/form-actions.js +33 -12
- package/dist/components/heading.d.ts +42 -0
- package/dist/components/heading.js +25 -0
- package/dist/components/icon-button.d.ts +1 -1
- package/dist/components/image-crop-dialog.d.ts +60 -0
- package/dist/components/image-crop-dialog.js +240 -0
- package/dist/components/image-crop-modal.d.ts +12 -55
- package/dist/components/image-crop-modal.js +2 -249
- package/dist/components/image-upload.d.ts +8 -17
- package/dist/components/image-upload.js +3 -3
- package/dist/components/index.d.ts +15 -10
- package/dist/components/index.js +10 -0
- package/dist/components/internal/bottom-bar.d.ts +33 -0
- package/dist/components/internal/bottom-bar.js +64 -0
- package/dist/components/internal/button.d.ts +1 -1
- package/dist/components/internal/icons.d.ts +11 -1
- package/dist/components/internal/icons.js +23 -0
- package/dist/components/internal/menu.d.ts +3 -2
- package/dist/components/internal/menu.js +1 -1
- package/dist/components/internal/modal.js +9 -0
- package/dist/components/internal/toggle.d.ts +1 -1
- package/dist/components/internal/use-on-screen-keyboard.d.ts +12 -0
- package/dist/components/internal/use-on-screen-keyboard.js +49 -0
- package/dist/components/item.d.ts +14 -7
- package/dist/components/item.js +5 -2
- package/dist/components/loading-overlay.d.ts +43 -0
- package/dist/components/loading-overlay.js +81 -0
- package/dist/components/marker.d.ts +11 -3
- package/dist/components/marker.js +4 -3
- package/dist/components/number-input.d.ts +1 -1
- package/dist/components/progress.d.ts +3 -3
- package/dist/components/progress.js +2 -2
- package/dist/components/row-actions.d.ts +3 -0
- package/dist/components/row-actions.js +8 -4
- package/dist/components/saving-bar.d.ts +38 -10
- package/dist/components/saving-bar.js +30 -7
- package/dist/components/section-header.d.ts +4 -3
- package/dist/components/selectable-card.d.ts +2 -10
- package/dist/components/sidebar.d.ts +8 -11
- package/dist/components/sidebar.js +4 -5
- package/dist/components/spinner.d.ts +9 -6
- package/dist/components/spinner.js +3 -3
- package/dist/components/star-rating.d.ts +3 -3
- package/dist/components/star-rating.js +2 -2
- package/dist/components/stat.d.ts +18 -6
- package/dist/components/stat.js +9 -3
- package/dist/components/status.d.ts +4 -4
- package/dist/components/status.js +2 -2
- package/dist/components/stepper.d.ts +33 -0
- package/dist/components/stepper.js +36 -0
- package/dist/components/summary-bar.d.ts +3 -2
- package/dist/components/summary-bar.js +10 -1
- package/dist/components/tile.d.ts +5 -5
- package/dist/components/tile.js +2 -2
- package/dist/components/time-picker.d.ts +1 -1
- package/dist/components/toast.d.ts +21 -8
- package/dist/components/toast.js +5 -3
- package/dist/components/toggle-card-compact.d.ts +6 -25
- package/dist/components/toggle-card-compact.js +8 -35
- package/dist/components/toggle-card.d.ts +23 -9
- package/dist/components/toggle-card.js +38 -2
- package/dist/components/toggle.d.ts +1 -1
- package/dist/components/typing-indicator.d.ts +2 -2
- package/dist/components/typing-indicator.js +1 -1
- package/package.json +4 -4
- package/styles/base.css +13 -1
- package/styles/rds/components-styles.css +799 -266
- package/styles/rds/components.css +57 -31
- package/styles/rds/foundation.css +1 -1
- package/styles/rds/theme.css +40 -29
- package/styles/rds.css +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
__objRest,
|
|
4
|
+
__spreadProps,
|
|
5
|
+
__spreadValues
|
|
6
|
+
} from "../../chunk-ORMEWXMH.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { useEffect, useRef } from "react";
|
|
9
|
+
import { useOnScreenKeyboard } from "./use-on-screen-keyboard.js";
|
|
10
|
+
const TOAST_OFFSET = "--toast-offset-bottom";
|
|
11
|
+
const onScreen = /* @__PURE__ */ new Map();
|
|
12
|
+
function footprint(el) {
|
|
13
|
+
const bottom = Number.parseFloat(getComputedStyle(el).bottom);
|
|
14
|
+
return el.getBoundingClientRect().height + (Number.isFinite(bottom) ? bottom : 0);
|
|
15
|
+
}
|
|
16
|
+
function publishToastOffset() {
|
|
17
|
+
const root = document.documentElement;
|
|
18
|
+
if (!onScreen.size) {
|
|
19
|
+
root.style.removeProperty(TOAST_OFFSET);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const taken = Math.max(...onScreen.values());
|
|
23
|
+
root.style.setProperty(TOAST_OFFSET, `calc(${taken}px + var(--space-16))`);
|
|
24
|
+
}
|
|
25
|
+
function useToastOffset(ref, visible) {
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const el = ref.current;
|
|
28
|
+
if (!el || !visible) return;
|
|
29
|
+
const measure = () => {
|
|
30
|
+
onScreen.set(el, footprint(el));
|
|
31
|
+
publishToastOffset();
|
|
32
|
+
};
|
|
33
|
+
measure();
|
|
34
|
+
const observer = typeof ResizeObserver === "function" ? new ResizeObserver(measure) : null;
|
|
35
|
+
observer == null ? void 0 : observer.observe(el);
|
|
36
|
+
window.addEventListener("resize", measure);
|
|
37
|
+
return () => {
|
|
38
|
+
observer == null ? void 0 : observer.disconnect();
|
|
39
|
+
window.removeEventListener("resize", measure);
|
|
40
|
+
onScreen.delete(el);
|
|
41
|
+
publishToastOffset();
|
|
42
|
+
};
|
|
43
|
+
}, [ref, visible]);
|
|
44
|
+
}
|
|
45
|
+
function BottomBar(_a) {
|
|
46
|
+
var _b = _a, { placement = "docked", leading, className, children } = _b, rest = __objRest(_b, ["placement", "leading", "className", "children"]);
|
|
47
|
+
const keyboard = useOnScreenKeyboard();
|
|
48
|
+
const ref = useRef(null);
|
|
49
|
+
useToastOffset(ref, !keyboard);
|
|
50
|
+
return /* @__PURE__ */ jsxs(
|
|
51
|
+
"div",
|
|
52
|
+
__spreadProps(__spreadValues({}, rest), {
|
|
53
|
+
ref,
|
|
54
|
+
className: ["rds-bottom-bar", `rds-bottom-bar--${placement}`, keyboard && "rds-bottom-bar--keyboard", className].filter(Boolean).join(" "),
|
|
55
|
+
children: [
|
|
56
|
+
leading !== void 0 && /* @__PURE__ */ jsx("div", { className: "rds-bottom-bar__leading", children: leading }),
|
|
57
|
+
children
|
|
58
|
+
]
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
BottomBar
|
|
64
|
+
};
|
|
@@ -2,7 +2,7 @@ import * as react from 'react';
|
|
|
2
2
|
import { MouseEventHandler, MouseEvent } from 'react';
|
|
3
3
|
|
|
4
4
|
type ButtonTone = 'action' | 'neutral' | 'danger' | 'inverse';
|
|
5
|
-
/**
|
|
5
|
+
/** The emphasis (Figma: `variant`): fill, outline or ghost. */
|
|
6
6
|
type ButtonVariant = 'fill' | 'outline' | 'ghost';
|
|
7
7
|
/**
|
|
8
8
|
* The height: sm 36, md 44 (the default), lg 52. The touch target is 44 in every size: on sm, an invisible layer
|
|
@@ -62,6 +62,8 @@ declare function ImageIcon(): react.JSX.Element;
|
|
|
62
62
|
declare function ImageOffIcon(): react.JSX.Element;
|
|
63
63
|
/** A circular arrow: try again. */
|
|
64
64
|
declare function RotateCcwIcon(): react.JSX.Element;
|
|
65
|
+
/** An arrow bending back (Lucide undo-2): undo, discard the changes. */
|
|
66
|
+
declare function Undo2Icon(): react.JSX.Element;
|
|
65
67
|
/** Sparkles: the assistant. */
|
|
66
68
|
declare function SparklesIcon(): react.JSX.Element;
|
|
67
69
|
/** A thumb up: a reaction. */
|
|
@@ -104,5 +106,13 @@ declare function CopyIcon(): react.JSX.Element;
|
|
|
104
106
|
declare function PencilIcon(): react.JSX.Element;
|
|
105
107
|
/** Three sliders: the filters of a list. */
|
|
106
108
|
declare function SlidersIcon(): react.JSX.Element;
|
|
109
|
+
/** A square: the 1:1 crop. */
|
|
110
|
+
declare function SquareIcon(): react.JSX.Element;
|
|
111
|
+
/** A standing rectangle: a portrait crop (4:5). */
|
|
112
|
+
declare function RectangleVerticalIcon(): react.JSX.Element;
|
|
113
|
+
/** A lying rectangle: a landscape crop (16:9). */
|
|
114
|
+
declare function RectangleHorizontalIcon(): react.JSX.Element;
|
|
115
|
+
/** A dashed square: a free crop, no fixed aspect. */
|
|
116
|
+
declare function SquareDashedIcon(): react.JSX.Element;
|
|
107
117
|
|
|
108
|
-
export { AlertIcon, ArrowDownIcon, ArrowLeftIcon, ArrowUpDownIcon, ArrowUpIcon, BadgeCheckIcon, BuildingIcon, CalendarIcon, CameraIcon, CheckCheckIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, CircleCheckIcon, ClockIcon, CloseIcon, CopyIcon, ExternalLinkIcon, EyeIcon, EyeOffIcon, FileTextIcon, ImageIcon, ImageOffIcon, ImagePlusIcon, InfoIcon, LockIcon, MapPinIcon, MegaphoneIcon, MenuIcon, MicIcon, MinusIcon, MoreVerticalIcon, PaperclipIcon, PencilIcon, PhoneIcon, PlusIcon, QuoteIcon, ReplyIcon, RotateCcwIcon, SearchIcon, SearchXIcon, SlidersIcon, SmileIcon, SparklesIcon, StarFilledIcon, StarIcon, TableIcon, ThumbsUpIcon, TriangleAlertIcon, UploadIcon, UserIcon };
|
|
118
|
+
export { AlertIcon, ArrowDownIcon, ArrowLeftIcon, ArrowUpDownIcon, ArrowUpIcon, BadgeCheckIcon, BuildingIcon, CalendarIcon, CameraIcon, CheckCheckIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, CircleCheckIcon, ClockIcon, CloseIcon, CopyIcon, ExternalLinkIcon, EyeIcon, EyeOffIcon, FileTextIcon, ImageIcon, ImageOffIcon, ImagePlusIcon, InfoIcon, LockIcon, MapPinIcon, MegaphoneIcon, MenuIcon, MicIcon, MinusIcon, MoreVerticalIcon, PaperclipIcon, PencilIcon, PhoneIcon, PlusIcon, QuoteIcon, RectangleHorizontalIcon, RectangleVerticalIcon, ReplyIcon, RotateCcwIcon, SearchIcon, SearchXIcon, SlidersIcon, SmileIcon, SparklesIcon, SquareDashedIcon, SquareIcon, StarFilledIcon, StarIcon, TableIcon, ThumbsUpIcon, TriangleAlertIcon, Undo2Icon, UploadIcon, UserIcon };
|
|
@@ -150,6 +150,12 @@ function RotateCcwIcon() {
|
|
|
150
150
|
/* @__PURE__ */ jsx("path", { d: "M3 3v5h5" })
|
|
151
151
|
] });
|
|
152
152
|
}
|
|
153
|
+
function Undo2Icon() {
|
|
154
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
155
|
+
/* @__PURE__ */ jsx("path", { d: "M9 14 4 9l5-5" }),
|
|
156
|
+
/* @__PURE__ */ jsx("path", { d: "M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11" })
|
|
157
|
+
] });
|
|
158
|
+
}
|
|
153
159
|
function SparklesIcon() {
|
|
154
160
|
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
155
161
|
/* @__PURE__ */ jsx("path", { d: "M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z" }),
|
|
@@ -260,6 +266,18 @@ function PencilIcon() {
|
|
|
260
266
|
function SlidersIcon() {
|
|
261
267
|
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M21 4h-7M10 4H3M21 12h-9M8 12H3M21 20h-5M12 20H3M14 2v4M8 10v4M16 18v4" }) });
|
|
262
268
|
}
|
|
269
|
+
function SquareIcon() {
|
|
270
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }) });
|
|
271
|
+
}
|
|
272
|
+
function RectangleVerticalIcon() {
|
|
273
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("rect", { width: "12", height: "20", x: "6", y: "2", rx: "2" }) });
|
|
274
|
+
}
|
|
275
|
+
function RectangleHorizontalIcon() {
|
|
276
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("rect", { width: "20", height: "12", x: "2", y: "6", rx: "2" }) });
|
|
277
|
+
}
|
|
278
|
+
function SquareDashedIcon() {
|
|
279
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M5 3a2 2 0 0 0-2 2M19 3a2 2 0 0 1 2 2M21 19a2 2 0 0 1-2 2M5 21a2 2 0 0 1-2-2M9 3h1M9 21h1M14 3h1M14 21h1M3 9v1M21 9v1M3 14v1M21 14v1" }) });
|
|
280
|
+
}
|
|
263
281
|
export {
|
|
264
282
|
AlertIcon,
|
|
265
283
|
ArrowDownIcon,
|
|
@@ -299,6 +317,8 @@ export {
|
|
|
299
317
|
PhoneIcon,
|
|
300
318
|
PlusIcon,
|
|
301
319
|
QuoteIcon,
|
|
320
|
+
RectangleHorizontalIcon,
|
|
321
|
+
RectangleVerticalIcon,
|
|
302
322
|
ReplyIcon,
|
|
303
323
|
RotateCcwIcon,
|
|
304
324
|
SearchIcon,
|
|
@@ -306,11 +326,14 @@ export {
|
|
|
306
326
|
SlidersIcon,
|
|
307
327
|
SmileIcon,
|
|
308
328
|
SparklesIcon,
|
|
329
|
+
SquareDashedIcon,
|
|
330
|
+
SquareIcon,
|
|
309
331
|
StarFilledIcon,
|
|
310
332
|
StarIcon,
|
|
311
333
|
TableIcon,
|
|
312
334
|
ThumbsUpIcon,
|
|
313
335
|
TriangleAlertIcon,
|
|
336
|
+
Undo2Icon,
|
|
314
337
|
UploadIcon,
|
|
315
338
|
UserIcon
|
|
316
339
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/** neutral (default) or danger (Figma: `tone`). */
|
|
5
|
+
type MenuItemTone = 'neutral' | 'danger';
|
|
5
6
|
interface MenuItemContentProps {
|
|
6
7
|
/** The action, a verb ("Duplicar") (Figma: `label`). */
|
|
7
8
|
children: ReactNode;
|
|
@@ -10,7 +11,7 @@ interface MenuItemContentProps {
|
|
|
10
11
|
/** A keyboard shortcut shown on the right (Figma: `showShortcut`), such as "Ctrl D". Not announced. */
|
|
11
12
|
shortcut?: ReactNode;
|
|
12
13
|
}
|
|
13
|
-
declare const menuItemClassName: (tone?: MenuItemTone, extra?: string) => string;
|
|
14
|
+
declare const menuItemClassName: (tone?: MenuItemTone | "default", extra?: string) => string;
|
|
14
15
|
declare function MenuItemContent({ children, icon, shortcut }: MenuItemContentProps): react.JSX.Element;
|
|
15
16
|
|
|
16
17
|
export { MenuItemContent, type MenuItemContentProps, type MenuItemTone, menuItemClassName };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../../chunk-ORMEWXMH.js";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
const menuItemClassName = (tone = "
|
|
3
|
+
const menuItemClassName = (tone = "neutral", extra) => ["rds-menu__item", tone === "danger" && "rds-menu__item--danger", extra].filter(Boolean).join(" ");
|
|
4
4
|
function MenuItemContent({ children, icon, shortcut }) {
|
|
5
5
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6
6
|
icon && /* @__PURE__ */ jsx("span", { className: "rds-menu__icon", "aria-hidden": "true", children: icon }),
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
__spreadValues
|
|
5
5
|
} from "../../chunk-ORMEWXMH.js";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { useRef } from "react";
|
|
7
8
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
8
9
|
import { Button } from "../button.js";
|
|
9
10
|
import { IconButton } from "../icon-button.js";
|
|
@@ -32,6 +33,7 @@ function ModalShell({
|
|
|
32
33
|
container,
|
|
33
34
|
className
|
|
34
35
|
}) {
|
|
36
|
+
const opener = useRef(null);
|
|
35
37
|
const cancel = /* @__PURE__ */ jsx(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { tone: "neutral", variant: "outline", children: cancelLabel }) }, "cancel");
|
|
36
38
|
const confirm = /* @__PURE__ */ jsx(Button, { onClick: onConfirm, children: confirmLabel }, "confirm");
|
|
37
39
|
const actions = footer != null ? footer : confirmLabel ? stackedFooter ? [confirm, cancel] : [cancel, confirm] : null;
|
|
@@ -51,6 +53,7 @@ function ModalShell({
|
|
|
51
53
|
className: ["rds-modal", prefix, ...modifiers, className].filter(Boolean).join(" "),
|
|
52
54
|
style: boxStyle,
|
|
53
55
|
onOpenAutoFocus: (event) => {
|
|
56
|
+
opener.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
54
57
|
const box = event.currentTarget;
|
|
55
58
|
const first = box.querySelector(
|
|
56
59
|
'.rds-modal__body :is(input, textarea, select, button, a[href], [tabindex]:not([tabindex="-1"])):not(:disabled)'
|
|
@@ -59,6 +62,12 @@ function ModalShell({
|
|
|
59
62
|
event.preventDefault();
|
|
60
63
|
first.focus();
|
|
61
64
|
}
|
|
65
|
+
},
|
|
66
|
+
onCloseAutoFocus: (event) => {
|
|
67
|
+
var _a;
|
|
68
|
+
if (trigger || !((_a = opener.current) == null ? void 0 : _a.isConnected)) return;
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
opener.current.focus();
|
|
62
71
|
}
|
|
63
72
|
}, description ? {} : { "aria-describedby": void 0 }), {
|
|
64
73
|
children: [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** The emphasis (Figma: `variant`): ghost in a toolbar, outline when it stands alone. */
|
|
2
2
|
type ToggleVariant = 'ghost' | 'outline';
|
|
3
3
|
declare function toggleClassName(variant: ToggleVariant, extra?: string): string;
|
|
4
4
|
/** A toggle without visible text needs a name, or a screen reader only says "toggle button". */
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Whether focusing this element brings up the on-screen keyboard: a text field, a text area or contenteditable. */
|
|
2
|
+
declare function isEditable(el: Element | null): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Whether the phone's on-screen keyboard is open: compact screen (below 1024), an editable field focused, and the
|
|
5
|
+
* visible area (visualViewport, scaled back from a pinch zoom) well short of the layout viewport. For the bars at the
|
|
6
|
+
* foot of the screen (FormActions, SavingBar), which leave while it is open so they do not cover the field being
|
|
7
|
+
* typed in. Without visualViewport (old browsers) or on the server it is always false: the bar stays.
|
|
8
|
+
* `enabled` false skips the listeners (a layout that does not sit at the foot).
|
|
9
|
+
*/
|
|
10
|
+
declare function useOnScreenKeyboard(enabled?: boolean): boolean;
|
|
11
|
+
|
|
12
|
+
export { isEditable, useOnScreenKeyboard };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../../chunk-ORMEWXMH.js";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
const COMPACT = "(max-width: 1023px)";
|
|
5
|
+
const KEYBOARD_RATIO = 0.75;
|
|
6
|
+
const NO_KEYBOARD = /* @__PURE__ */ new Set(["button", "checkbox", "color", "file", "hidden", "image", "radio", "range", "reset", "submit"]);
|
|
7
|
+
function isEditable(el) {
|
|
8
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
9
|
+
if (el.isContentEditable) return true;
|
|
10
|
+
if (el instanceof HTMLTextAreaElement) return !el.readOnly && !el.disabled;
|
|
11
|
+
if (el instanceof HTMLInputElement) return !NO_KEYBOARD.has(el.type) && !el.readOnly && !el.disabled;
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
function useOnScreenKeyboard(enabled = true) {
|
|
15
|
+
const [open, setOpen] = useState(false);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const viewport = window.visualViewport;
|
|
18
|
+
if (!enabled || !viewport || typeof window.matchMedia !== "function") {
|
|
19
|
+
setOpen(false);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const compact = window.matchMedia(COMPACT);
|
|
23
|
+
let frame = 0;
|
|
24
|
+
const measure = () => compact.matches && isEditable(document.activeElement) && viewport.height * viewport.scale < window.innerHeight * KEYBOARD_RATIO;
|
|
25
|
+
const check = () => {
|
|
26
|
+
cancelAnimationFrame(frame);
|
|
27
|
+
frame = requestAnimationFrame(() => setOpen(measure()));
|
|
28
|
+
};
|
|
29
|
+
check();
|
|
30
|
+
viewport.addEventListener("resize", check);
|
|
31
|
+
window.addEventListener("resize", check);
|
|
32
|
+
document.addEventListener("focusin", check);
|
|
33
|
+
document.addEventListener("focusout", check);
|
|
34
|
+
compact.addEventListener("change", check);
|
|
35
|
+
return () => {
|
|
36
|
+
cancelAnimationFrame(frame);
|
|
37
|
+
viewport.removeEventListener("resize", check);
|
|
38
|
+
window.removeEventListener("resize", check);
|
|
39
|
+
document.removeEventListener("focusin", check);
|
|
40
|
+
document.removeEventListener("focusout", check);
|
|
41
|
+
compact.removeEventListener("change", check);
|
|
42
|
+
};
|
|
43
|
+
}, [enabled]);
|
|
44
|
+
return enabled && open;
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
isEditable,
|
|
48
|
+
useOnScreenKeyboard
|
|
49
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
type
|
|
4
|
+
/** The emphasis (Figma: `variant`). */
|
|
5
|
+
type ItemVariant = 'ghost' | 'outline' | 'soft';
|
|
6
|
+
type ItemSize = 'md' | 'sm';
|
|
6
7
|
interface ItemProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
7
8
|
/** The thing's name (Figma: `title`). */
|
|
8
9
|
title: ReactNode;
|
|
@@ -12,10 +13,16 @@ interface ItemProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
|
12
13
|
media?: ReactNode;
|
|
13
14
|
/** One action or control on the right (Figma: `showAction` + `action`): a ghost Button, an IconButton, a Switch. */
|
|
14
15
|
action?: ReactNode;
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
/**
|
|
17
|
+
* ghost (default): loose in the list, a line between rows; outline: each row a block; soft: a background, no
|
|
18
|
+
* border (Figma: `variant`). `'default'` and `'muted'` are deprecated (2.0.0-next): they are ghost and soft.
|
|
19
|
+
*/
|
|
20
|
+
variant?: ItemVariant | 'default' | 'muted';
|
|
21
|
+
/**
|
|
22
|
+
* md (default) or sm for dense lists: 14 and 12 text, 8 12 padding (Figma: `size`). `'default'` is deprecated
|
|
23
|
+
* (2.0.0-next): it is `'md'`.
|
|
24
|
+
*/
|
|
25
|
+
size?: ItemSize | 'default';
|
|
19
26
|
}
|
|
20
27
|
/**
|
|
21
28
|
* Item — Figma [RDS] Content/Item. One row of a list: media, title, description and one action. Inside an ItemGroup
|
|
@@ -26,7 +33,7 @@ interface ItemGroupProps extends HTMLAttributes<HTMLUListElement> {
|
|
|
26
33
|
/** The Items. One variant for the whole list. */
|
|
27
34
|
children: ReactNode;
|
|
28
35
|
}
|
|
29
|
-
/** The list the Items go in (<ul>).
|
|
36
|
+
/** The list the Items go in (<ul>). ghost rows get a line between them; outline and soft rows a gap of 8. */
|
|
30
37
|
declare function ItemGroup({ className, children, ...rest }: ItemGroupProps): react.JSX.Element;
|
|
31
38
|
|
|
32
39
|
export { Item, ItemGroup, type ItemGroupProps, type ItemProps, type ItemSize, type ItemVariant };
|
package/dist/components/item.js
CHANGED
|
@@ -6,14 +6,17 @@ import {
|
|
|
6
6
|
} from "../chunk-ORMEWXMH.js";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { createContext, useContext } from "react";
|
|
9
|
+
const LEGACY_VARIANT = { default: "ghost", muted: "soft" };
|
|
9
10
|
const InGroup = createContext(false);
|
|
10
11
|
function Item(_a) {
|
|
11
|
-
var _b = _a, { title, description, media, action, variant = "
|
|
12
|
+
var _b = _a, { title, description, media, action, variant = "ghost", size = "md", className } = _b, rest = __objRest(_b, ["title", "description", "media", "action", "variant", "size", "className"]);
|
|
13
|
+
var _a2;
|
|
12
14
|
const Root = useContext(InGroup) ? "li" : "div";
|
|
15
|
+
const look = (_a2 = LEGACY_VARIANT[variant]) != null ? _a2 : variant;
|
|
13
16
|
return /* @__PURE__ */ jsxs(
|
|
14
17
|
Root,
|
|
15
18
|
__spreadProps(__spreadValues({}, rest), {
|
|
16
|
-
className: ["rds-item", `rds-item--${
|
|
19
|
+
className: ["rds-item", `rds-item--${look}`, size === "sm" && "rds-item--sm", className].filter(Boolean).join(" "),
|
|
17
20
|
children: [
|
|
18
21
|
media && /* @__PURE__ */ jsx("span", { className: "rds-item__media", children: media }),
|
|
19
22
|
/* @__PURE__ */ jsxs("span", { className: "rds-item__content", children: [
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
interface LoadingOverlayProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
5
|
+
/**
|
|
6
|
+
* The action is running (Figma: `open`, code only). The overlay shows only if it is still true after `delay`:
|
|
7
|
+
* if the next page opens first, it never shows.
|
|
8
|
+
*/
|
|
9
|
+
open: boolean;
|
|
10
|
+
/** What is happening, in the gerund with its object: "Criando o produto…" (Figma: `label`). It is the dialog's name and is said once (aria-live="polite"). */
|
|
11
|
+
label?: string;
|
|
12
|
+
/**
|
|
13
|
+
* How long (ms) `open` has to stay true before the overlay shows. Up to it, the wait is the main button in
|
|
14
|
+
* loading (`<Button loading>`, or the SavingBar in `status="saving"`); past it, the overlay comes in and stays
|
|
15
|
+
* until the other page opens. 400 by default; 0 shows it at once.
|
|
16
|
+
*/
|
|
17
|
+
delay?: number;
|
|
18
|
+
/** Where the portal goes (default: document.body). Inside a `.ds-plate`, for example, to read the brand mode. */
|
|
19
|
+
container?: HTMLElement | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* LoadingOverlay — Figma [RDS] Overlays/LoadingOverlay. The long wait of an action that leads to another page
|
|
23
|
+
* (create the product and land on its editing). A veil over the whole screen (loading-overlay/scrim) and, in the
|
|
24
|
+
* middle, a panel (loading-overlay/background, radius/container, elevation/modal) with the Spinner lg and one line
|
|
25
|
+
* saying what is happening. Styles: loading-overlay.css.
|
|
26
|
+
*
|
|
27
|
+
* Time: up to `delay` (~400 ms) only the main button is in loading ("Criando…", aria-busy on the button); past it,
|
|
28
|
+
* the overlay shows, and it stays until the other page opens. If the navigation comes first, it never shows. Do not
|
|
29
|
+
* use it for short waits (it only flashes), to load a page or a list (PageSkeleton), for a measured wait (Progress),
|
|
30
|
+
* or to save without changing page (the SavingBar in `status="saving"`). Never two indicators: with the overlay,
|
|
31
|
+
* the SavingBar keeps only its button in loading.
|
|
32
|
+
*
|
|
33
|
+
* Error: the app sets `open={false}` (the overlay leaves and the focus goes back to where it was, the main button)
|
|
34
|
+
* and returns the error to the SavingBar in `status="error"`, with the form untouched.
|
|
35
|
+
*
|
|
36
|
+
* Accessibility: role="dialog" aria-modal="true" named by `label`; the focus goes to the panel (tabindex=-1) and
|
|
37
|
+
* stays there; Escape does not close it (the action is running). While it is shown, the rest of the page is
|
|
38
|
+
* `inert` and `aria-busy="true"` (put back on close). The label is in an aria-live="polite" region. With
|
|
39
|
+
* prefers-reduced-motion: reduce, no fade, and the Spinner turns slowly (3 s a turn).
|
|
40
|
+
*/
|
|
41
|
+
declare function LoadingOverlay({ open, label, delay, container, className, ...rest }: LoadingOverlayProps): react.ReactPortal | null;
|
|
42
|
+
|
|
43
|
+
export { LoadingOverlay, type LoadingOverlayProps };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
__objRest,
|
|
4
|
+
__spreadProps,
|
|
5
|
+
__spreadValues
|
|
6
|
+
} from "../chunk-ORMEWXMH.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
9
|
+
import { createPortal } from "react-dom";
|
|
10
|
+
import { Spinner } from "./spinner.js";
|
|
11
|
+
function isolate(keep) {
|
|
12
|
+
const marked = [];
|
|
13
|
+
for (let node = keep; node && node !== document.body && node.parentElement; node = node.parentElement) {
|
|
14
|
+
for (const sibling of node.parentElement.children) {
|
|
15
|
+
if (sibling === node || sibling.hasAttribute("inert") || /^(SCRIPT|STYLE|LINK|TEMPLATE)$/.test(sibling.tagName)) continue;
|
|
16
|
+
marked.push({ el: sibling, inert: sibling.getAttribute("inert"), busy: sibling.getAttribute("aria-busy") });
|
|
17
|
+
sibling.setAttribute("inert", "");
|
|
18
|
+
sibling.setAttribute("aria-busy", "true");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return marked;
|
|
22
|
+
}
|
|
23
|
+
function restore(marked) {
|
|
24
|
+
for (const { el, inert, busy } of marked) {
|
|
25
|
+
if (inert === null) el.removeAttribute("inert");
|
|
26
|
+
else el.setAttribute("inert", inert);
|
|
27
|
+
if (busy === null) el.removeAttribute("aria-busy");
|
|
28
|
+
else el.setAttribute("aria-busy", busy);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function LoadingOverlay(_a) {
|
|
32
|
+
var _b = _a, { open, label = "Carregando\u2026", delay = 400, container, className } = _b, rest = __objRest(_b, ["open", "label", "delay", "container", "className"]);
|
|
33
|
+
const [shown, setShown] = useState(false);
|
|
34
|
+
const veil = useRef(null);
|
|
35
|
+
const panel = useRef(null);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (!open) {
|
|
38
|
+
setShown(false);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (delay <= 0) {
|
|
42
|
+
setShown(true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const timer = setTimeout(() => setShown(true), delay);
|
|
46
|
+
return () => clearTimeout(timer);
|
|
47
|
+
}, [open, delay]);
|
|
48
|
+
useLayoutEffect(() => {
|
|
49
|
+
if (!shown || !veil.current || !panel.current) return;
|
|
50
|
+
const previous = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
51
|
+
const marked = isolate(veil.current);
|
|
52
|
+
const box = panel.current;
|
|
53
|
+
box.focus({ preventScroll: true });
|
|
54
|
+
const keep = (event) => {
|
|
55
|
+
if (!box.contains(event.target)) box.focus({ preventScroll: true });
|
|
56
|
+
};
|
|
57
|
+
document.addEventListener("focusin", keep);
|
|
58
|
+
return () => {
|
|
59
|
+
document.removeEventListener("focusin", keep);
|
|
60
|
+
restore(marked);
|
|
61
|
+
if (previous == null ? void 0 : previous.isConnected) previous.focus({ preventScroll: true });
|
|
62
|
+
};
|
|
63
|
+
}, [shown]);
|
|
64
|
+
if (!shown || typeof document === "undefined") return null;
|
|
65
|
+
const onKeyDown = (event) => {
|
|
66
|
+
if (event.key === "Escape" || event.key === "Tab") {
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
event.stopPropagation();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return createPortal(
|
|
72
|
+
/* @__PURE__ */ jsx("div", __spreadProps(__spreadValues({}, rest), { ref: veil, className: ["rds-loading-overlay", className].filter(Boolean).join(" "), onKeyDown, children: /* @__PURE__ */ jsxs("div", { ref: panel, className: "rds-loading-overlay__panel", role: "dialog", "aria-modal": "true", "aria-label": label, tabIndex: -1, children: [
|
|
73
|
+
/* @__PURE__ */ jsx(Spinner, { size: "lg", tone: "neutral", "aria-hidden": "true" }),
|
|
74
|
+
/* @__PURE__ */ jsx("p", { className: "rds-loading-overlay__label", "aria-live": "polite", children: label })
|
|
75
|
+
] }) })),
|
|
76
|
+
container != null ? container : document.body
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
LoadingOverlay
|
|
81
|
+
};
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
+
/** The marker's shape (Figma: `kind`): it is the form, not the emphasis, so it is not a `variant`. */
|
|
5
|
+
type MarkerKind = 'inline' | 'border' | 'separator';
|
|
6
|
+
/** @deprecated Use MarkerKind (2.0.0-next: `variant` is `kind`, and default is inline). */
|
|
4
7
|
type MarkerVariant = 'default' | 'border' | 'separator';
|
|
5
8
|
interface MarkerProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* inline (default): icon and text; border: with a line under it, to split rows; separator: the text between two
|
|
11
|
+
* lines (Figma: `kind`).
|
|
12
|
+
*/
|
|
13
|
+
kind?: MarkerKind;
|
|
14
|
+
/** @deprecated Use `kind` (2.0.0-next): default → inline, border and separator stay. */
|
|
7
15
|
variant?: MarkerVariant;
|
|
8
16
|
/** The assistant's status, a system note or a date (Figma: `text`). */
|
|
9
17
|
children: ReactNode;
|
|
@@ -19,6 +27,6 @@ interface MarkerProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
19
27
|
* Marker — Figma [RDS] Chat/Marker. A line inside the conversation that is not a message: the assistant's status
|
|
20
28
|
* ("Buscando…"), a system note or a date between two lines. Styles: marker.css.
|
|
21
29
|
*/
|
|
22
|
-
declare function Marker({ variant, children, icon, loading, className, ...rest }: MarkerProps): react.JSX.Element;
|
|
30
|
+
declare function Marker({ kind: kindProp, variant, children, icon, loading, className, ...rest }: MarkerProps): react.JSX.Element;
|
|
23
31
|
|
|
24
|
-
export { Marker, type MarkerProps, type MarkerVariant };
|
|
32
|
+
export { Marker, type MarkerKind, type MarkerProps, type MarkerVariant };
|
|
@@ -7,10 +7,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
import { SparklesIcon } from "./internal/icons.js";
|
|
8
8
|
import { Spinner } from "./spinner.js";
|
|
9
9
|
function Marker(_a) {
|
|
10
|
-
var _b = _a, {
|
|
11
|
-
const
|
|
10
|
+
var _b = _a, { kind: kindProp, variant, children, icon = /* @__PURE__ */ jsx(SparklesIcon, {}), loading, className } = _b, rest = __objRest(_b, ["kind", "variant", "children", "icon", "loading", "className"]);
|
|
11
|
+
const kind = kindProp != null ? kindProp : variant === "default" || variant === void 0 ? "inline" : variant;
|
|
12
|
+
const classes = ["rds-marker", `rds-marker--${kind}`, className].filter(Boolean).join(" ");
|
|
12
13
|
const role = loading ? "status" : void 0;
|
|
13
|
-
if (
|
|
14
|
+
if (kind === "separator") {
|
|
14
15
|
return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({ role }, rest), { className: classes, children: [
|
|
15
16
|
/* @__PURE__ */ jsx("span", { className: "rds-marker__line", "aria-hidden": "true" }),
|
|
16
17
|
/* @__PURE__ */ jsx("span", { className: "rds-marker__text", children }),
|
|
@@ -53,7 +53,7 @@ interface NumberInputProps extends Omit<FieldTextProps, 'labelPosition'> {
|
|
|
53
53
|
* booking, instalments). The number in the middle is typed; the field is a spinbutton, so the arrows move it (Page
|
|
54
54
|
* Up/Down by ten steps, Home/End to the limits) and − and + stay out of the Tab order. At a limit its button turns
|
|
55
55
|
* off. A price, a CPF or a CEP is the Input; a continuous range, the Slider; the steps of a flow, the
|
|
56
|
-
*
|
|
56
|
+
* Stepper. Styles: number-input.css and internal/field.css.
|
|
57
57
|
*/
|
|
58
58
|
declare function NumberInput({ label, hint, error, errorMessage, required, value, defaultValue, onChange, min, max, step, unit, steps, stepsLabel, debounce, decrementLabel, incrementLabel, name, placeholder, disabled, id, className, style, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, }: NumberInputProps): react.JSX.Element;
|
|
59
59
|
|
|
@@ -3,7 +3,7 @@ import { HTMLAttributes, ReactNode } from 'react';
|
|
|
3
3
|
|
|
4
4
|
/** task: something moving to the end (upload, import). measure: a value inside a known range (quota used). */
|
|
5
5
|
type ProgressKind = 'task' | 'measure';
|
|
6
|
-
type ProgressSize = '
|
|
6
|
+
type ProgressSize = 'md' | 'sm';
|
|
7
7
|
interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
8
8
|
/** 0 to `max` (Figma: `value`, 0 to 100 in steps of 5; the code takes any value). */
|
|
9
9
|
value: number;
|
|
@@ -18,8 +18,8 @@ interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'>
|
|
|
18
18
|
valueText?: ReactNode;
|
|
19
19
|
/** task → role="progressbar"; measure → role="meter". */
|
|
20
20
|
kind?: ProgressKind;
|
|
21
|
-
/**
|
|
22
|
-
size?: ProgressSize;
|
|
21
|
+
/** md: 8px bar (default); sm: 4px, for dense lists (Figma: `size`). `'default'` is deprecated (2.0.0-next): it is `'md'`. */
|
|
22
|
+
size?: ProgressSize | 'default';
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Progress — Figma [RDS] Indicators/Progress. A bar with a value: the track is the brand tint, the fill the first
|
|
@@ -15,7 +15,7 @@ function Progress(_a) {
|
|
|
15
15
|
showValue = true,
|
|
16
16
|
valueText,
|
|
17
17
|
kind = "task",
|
|
18
|
-
size = "
|
|
18
|
+
size = "md",
|
|
19
19
|
className
|
|
20
20
|
} = _b, rest = __objRest(_b, [
|
|
21
21
|
"value",
|
|
@@ -32,7 +32,7 @@ function Progress(_a) {
|
|
|
32
32
|
const clamped = Math.min(Math.max(value, 0), max);
|
|
33
33
|
const percent = max > 0 ? clamped / max * 100 : 0;
|
|
34
34
|
const text = valueText != null ? valueText : `${Math.round(percent)}%`;
|
|
35
|
-
return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({}, rest), { className: ["rds-progress", `rds-progress--${size}`, className].filter(Boolean).join(" "), children: [
|
|
35
|
+
return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({}, rest), { className: ["rds-progress", `rds-progress--${size === "default" ? "md" : size}`, className].filter(Boolean).join(" "), children: [
|
|
36
36
|
(showLabel || showValue) && /* @__PURE__ */ jsxs("div", { className: "rds-progress__row", children: [
|
|
37
37
|
showLabel && /* @__PURE__ */ jsx("span", { id: labelId, className: "rds-progress__label", children: label }),
|
|
38
38
|
showValue && /* @__PURE__ */ jsx("span", { className: "rds-progress__value", "aria-hidden": "true", children: text })
|
|
@@ -4,6 +4,9 @@ import { ReactNode } from 'react';
|
|
|
4
4
|
interface RowActionItem {
|
|
5
5
|
label: string;
|
|
6
6
|
icon?: ReactNode;
|
|
7
|
+
/** neutral (default) or danger: danger items go last, after a separator. */
|
|
8
|
+
tone?: 'neutral' | 'danger';
|
|
9
|
+
/** @deprecated Use `tone` (2.0.0-next): default → neutral, danger stays. */
|
|
7
10
|
variant?: 'default' | 'danger';
|
|
8
11
|
disabled?: boolean;
|
|
9
12
|
onClick: () => void;
|
|
@@ -13,10 +13,14 @@ function RowActions({
|
|
|
13
13
|
items = [],
|
|
14
14
|
dangerSeparator
|
|
15
15
|
}) {
|
|
16
|
-
const
|
|
16
|
+
const isDanger = (i) => {
|
|
17
|
+
var _a;
|
|
18
|
+
return ((_a = i.tone) != null ? _a : i.variant) === "danger";
|
|
19
|
+
};
|
|
20
|
+
const hasDanger = items.some(isDanger);
|
|
17
21
|
const showSep = dangerSeparator != null ? dangerSeparator : hasDanger;
|
|
18
|
-
const normalItems = showSep ? items.filter((i) => i
|
|
19
|
-
const dangerItems = showSep ? items.filter(
|
|
22
|
+
const normalItems = showSep ? items.filter((i) => !isDanger(i)) : items;
|
|
23
|
+
const dangerItems = showSep ? items.filter(isDanger) : [];
|
|
20
24
|
return /* @__PURE__ */ jsxs("div", { className: "rds-row-actions", children: [
|
|
21
25
|
primaryHref ? /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", tone: "neutral", children: /* @__PURE__ */ jsx("a", { href: primaryHref, onClick: (e) => e.stopPropagation(), children: primaryLabel }) }) : primaryOnClick ? /* @__PURE__ */ jsx(
|
|
22
26
|
Button,
|
|
@@ -48,7 +52,7 @@ function RowActions({
|
|
|
48
52
|
DropdownMenuItem,
|
|
49
53
|
{
|
|
50
54
|
icon: item.icon,
|
|
51
|
-
tone: item
|
|
55
|
+
tone: isDanger(item) ? "danger" : "neutral",
|
|
52
56
|
disabled: item.disabled,
|
|
53
57
|
onSelect: item.onClick,
|
|
54
58
|
children: item.label
|