@rovula/ui 0.1.15 → 0.1.18
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/cjs/bundle.css +6 -0
- package/dist/cjs/bundle.js +1545 -1545
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/index.d.ts +2 -0
- package/dist/cjs/types/patterns/confirm-dialog/ConfirmDialog.d.ts +3 -0
- package/dist/cjs/types/patterns/confirm-dialog/ConfirmDialog.stories.d.ts +3 -0
- package/dist/cjs/types/patterns/form-dialog/FormDialog.d.ts +2 -0
- package/dist/cjs/types/patterns/form-dialog/FormDialog.stories.d.ts +1 -0
- package/dist/components/AlertDialog/AlertDialog.js +2 -2
- package/dist/esm/bundle.css +6 -0
- package/dist/esm/bundle.js +1545 -1545
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/index.d.ts +2 -0
- package/dist/esm/types/patterns/confirm-dialog/ConfirmDialog.d.ts +3 -0
- package/dist/esm/types/patterns/confirm-dialog/ConfirmDialog.stories.d.ts +3 -0
- package/dist/esm/types/patterns/form-dialog/FormDialog.d.ts +2 -0
- package/dist/esm/types/patterns/form-dialog/FormDialog.stories.d.ts +1 -0
- package/dist/index.d.ts +69 -1
- package/dist/index.js +3 -0
- package/dist/patterns/confirm-dialog/ConfirmDialog.js +4 -3
- package/dist/patterns/form-dialog/FormDialog.js +2 -2
- package/dist/src/theme/global.css +8 -0
- package/package.json +1 -1
- package/src/components/AlertDialog/AlertDialog.tsx +2 -2
- package/src/index.ts +4 -0
- package/src/patterns/confirm-dialog/ConfirmDialog.tsx +21 -4
- package/src/patterns/form-dialog/FormDialog.tsx +15 -4
|
@@ -44,6 +44,8 @@ export * from "./components/Tree";
|
|
|
44
44
|
export * from "./components/FocusedScrollView/FocusedScrollView";
|
|
45
45
|
export * from "./components/RadioGroup/RadioGroup";
|
|
46
46
|
export * from "./components/Form";
|
|
47
|
+
export * from "./patterns/confirm-dialog/ConfirmDialog";
|
|
48
|
+
export * from "./patterns/form-dialog/FormDialog";
|
|
47
49
|
export type { ButtonProps } from "./components/Button/Button";
|
|
48
50
|
export type { InputProps } from "./components/TextInput/TextInput";
|
|
49
51
|
export type { PasswordInputProps } from "./components/PasswordInput/PasswordInput";
|
|
@@ -20,5 +20,8 @@ export type ConfirmDialogProps = {
|
|
|
20
20
|
* When true, hides the cancel button — useful for info/error alerts that only need one action.
|
|
21
21
|
*/
|
|
22
22
|
hideCancelButton?: boolean;
|
|
23
|
+
testId?: string;
|
|
24
|
+
cancelClassName?: string;
|
|
25
|
+
confirmClassName?: string;
|
|
23
26
|
};
|
|
24
27
|
export declare const ConfirmDialog: React.FC<ConfirmDialogProps>;
|
|
@@ -21,6 +21,9 @@ declare const meta: {
|
|
|
21
21
|
trigger?: React.ReactNode;
|
|
22
22
|
typeToConfirm?: string | undefined;
|
|
23
23
|
hideCancelButton?: boolean | undefined;
|
|
24
|
+
testId?: string | undefined;
|
|
25
|
+
cancelClassName?: string | undefined;
|
|
26
|
+
confirmClassName?: string | undefined;
|
|
24
27
|
}>) => import("react/jsx-runtime").JSX.Element)[];
|
|
25
28
|
argTypes: {
|
|
26
29
|
open: {
|
|
@@ -8,6 +8,7 @@ export type FormDialogAction = {
|
|
|
8
8
|
disabled?: boolean;
|
|
9
9
|
isLoading?: boolean;
|
|
10
10
|
type?: "button" | "submit" | "reset";
|
|
11
|
+
className?: string;
|
|
11
12
|
};
|
|
12
13
|
export type FormDialogProps = {
|
|
13
14
|
open?: boolean;
|
|
@@ -35,5 +36,6 @@ export type FormDialogProps = {
|
|
|
35
36
|
* Use together with a <Form id={formId} .../> inside children.
|
|
36
37
|
*/
|
|
37
38
|
formId?: string;
|
|
39
|
+
testId?: string;
|
|
38
40
|
};
|
|
39
41
|
export declare const FormDialog: React.FC<FormDialogProps>;
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { ToastProviderProps } from '@radix-ui/react-toast';
|
|
|
19
19
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
20
20
|
import { FieldValues, UseFormReturn, DefaultValues, SubmitHandler, SubmitErrorHandler, Resolver, Mode, FieldPath, RegisterOptions, FieldPathValue } from 'react-hook-form';
|
|
21
21
|
import * as yup from 'yup';
|
|
22
|
+
import Button$1 from '@/components/Button/Button';
|
|
22
23
|
import { ClassValue } from 'clsx';
|
|
23
24
|
|
|
24
25
|
type ButtonProps = {
|
|
@@ -1281,6 +1282,73 @@ declare const useOptionBridge: <TValue extends OptionValue = string, TOption ext
|
|
|
1281
1282
|
optionsByValue: Map<TValue, TOption>;
|
|
1282
1283
|
};
|
|
1283
1284
|
|
|
1285
|
+
type ConfirmDialogProps = {
|
|
1286
|
+
open?: boolean;
|
|
1287
|
+
onOpenChange?: (open: boolean) => void;
|
|
1288
|
+
title: string;
|
|
1289
|
+
description?: string;
|
|
1290
|
+
confirmLabel?: string;
|
|
1291
|
+
cancelLabel?: string;
|
|
1292
|
+
onConfirm?: () => void;
|
|
1293
|
+
onCancel?: () => void;
|
|
1294
|
+
/** Fires whenever the dialog closes, regardless of how (cancel button, overlay, Escape). */
|
|
1295
|
+
onClose?: () => void;
|
|
1296
|
+
trigger?: React.ReactNode;
|
|
1297
|
+
/**
|
|
1298
|
+
* When provided, the user must type this exact text before the confirm button is enabled.
|
|
1299
|
+
* e.g. typeToConfirm="confirm" or typeToConfirm="delete"
|
|
1300
|
+
*/
|
|
1301
|
+
typeToConfirm?: string;
|
|
1302
|
+
/**
|
|
1303
|
+
* When true, hides the cancel button — useful for info/error alerts that only need one action.
|
|
1304
|
+
*/
|
|
1305
|
+
hideCancelButton?: boolean;
|
|
1306
|
+
testId?: string;
|
|
1307
|
+
cancelClassName?: string;
|
|
1308
|
+
confirmClassName?: string;
|
|
1309
|
+
};
|
|
1310
|
+
declare const ConfirmDialog: React.FC<ConfirmDialogProps>;
|
|
1311
|
+
|
|
1312
|
+
type FormDialogAction = {
|
|
1313
|
+
label: string;
|
|
1314
|
+
onClick?: () => void;
|
|
1315
|
+
variant?: React.ComponentProps<typeof Button$1>["variant"];
|
|
1316
|
+
color?: React.ComponentProps<typeof Button$1>["color"];
|
|
1317
|
+
disabled?: boolean;
|
|
1318
|
+
isLoading?: boolean;
|
|
1319
|
+
type?: "button" | "submit" | "reset";
|
|
1320
|
+
className?: string;
|
|
1321
|
+
};
|
|
1322
|
+
type FormDialogProps = {
|
|
1323
|
+
open?: boolean;
|
|
1324
|
+
onOpenChange?: (open: boolean) => void;
|
|
1325
|
+
title: string;
|
|
1326
|
+
description?: string;
|
|
1327
|
+
children?: React.ReactNode;
|
|
1328
|
+
trigger?: React.ReactNode;
|
|
1329
|
+
/**
|
|
1330
|
+
* Primary action (right side of footer).
|
|
1331
|
+
*/
|
|
1332
|
+
confirmAction?: FormDialogAction;
|
|
1333
|
+
/**
|
|
1334
|
+
* Secondary cancel action (right side of footer, outline style).
|
|
1335
|
+
*/
|
|
1336
|
+
cancelAction?: FormDialogAction;
|
|
1337
|
+
/**
|
|
1338
|
+
* Optional extra action placed on the left side of the footer.
|
|
1339
|
+
*/
|
|
1340
|
+
extraAction?: FormDialogAction;
|
|
1341
|
+
scrollable?: boolean;
|
|
1342
|
+
className?: string;
|
|
1343
|
+
/**
|
|
1344
|
+
* When provided, the confirm button becomes type="submit" and is linked to this form id.
|
|
1345
|
+
* Use together with a <Form id={formId} .../> inside children.
|
|
1346
|
+
*/
|
|
1347
|
+
formId?: string;
|
|
1348
|
+
testId?: string;
|
|
1349
|
+
};
|
|
1350
|
+
declare const FormDialog: React.FC<FormDialogProps>;
|
|
1351
|
+
|
|
1284
1352
|
declare const resloveTimestamp: (timestamp: number) => number;
|
|
1285
1353
|
declare const getStartDateOfDay: (date: Date) => Date;
|
|
1286
1354
|
declare const getEndDateOfDay: (date: Date) => Date;
|
|
@@ -1720,4 +1788,4 @@ declare const srgbToHex: (color: string) => string;
|
|
|
1720
1788
|
*/
|
|
1721
1789
|
declare function getLucideIconNames(): Promise<string[]>;
|
|
1722
1790
|
|
|
1723
|
-
export { ActionButton, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Button, type ButtonProps, Calendar, Checkbox, Collapsible, type ControlledFormFactoryOptions, type CustomSliderProps, DataTable, type DataTableProps, DatePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Dropdown, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type DropdownProps, Field, FieldMessage, type FieldMessageProps, type FieldProps, FocusedScrollView, Footer, type FooterProps, type FooterVariant, Form, type FormController, type FormProps, Icon, Input, InputFilter, type InputFilterProps, type InputProps, Label, Loading, type MaskRule, MaskedTextInput, type MaskedTextInputProps, Menu, MenuItem, type MenuItemType, MenuLabel, type MenuOption, type MenuProps, MenuSeparator, Navbar, type NavbarProps, type NavbarVariant, NumberInput, type NumberInputProps, type OptionLike, type Options$1 as Options, OtpInput, OtpInputGroup, type OtpInputGroupProps, type OtpInputProps, PasswordInput, type PasswordInputProps, Popover, PopoverContent, PopoverTrigger, ProgressBar, RadioGroup, RadioGroupItem, Search, type SearchProps, Slider, type SliderProps, Switch, THEME_COLOR_KEYS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, Text, TextArea, type TextAreaProps, TextInput, type ThemeColorKey, Toast$1 as Toast, ToastAction, type ToastActionElement, ToastClose, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipSimple, TooltipTrigger, Tree, type TreeData, TreeItem, type TreeItemProps, type TreeProps, type UseControlledFormOptions, type UseOptionBridgeOptions, ValidationHintList, type ValidationHintListProps, type ValidationHintMode, type ValidationHintRule, type ValidationHintState, cn, createControlledForm, createYupResolver, getEndDateOfDay, getLucideIconNames, getStartDateOfDay, getStartEndTimestampOfDay, getThemeColor, getThemeColors, getTimestampUTC, reducer, resloveTimestamp, srgbToHex, toast, useControlledForm, useOptionBridge, usePrevious, useToast };
|
|
1791
|
+
export { ActionButton, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Button, type ButtonProps, Calendar, Checkbox, Collapsible, ConfirmDialog, type ConfirmDialogProps, type ControlledFormFactoryOptions, type CustomSliderProps, DataTable, type DataTableProps, DatePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Dropdown, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type DropdownProps, Field, FieldMessage, type FieldMessageProps, type FieldProps, FocusedScrollView, Footer, type FooterProps, type FooterVariant, Form, type FormController, FormDialog, type FormDialogAction, type FormDialogProps, type FormProps, Icon, Input, InputFilter, type InputFilterProps, type InputProps, Label, Loading, type MaskRule, MaskedTextInput, type MaskedTextInputProps, Menu, MenuItem, type MenuItemType, MenuLabel, type MenuOption, type MenuProps, MenuSeparator, Navbar, type NavbarProps, type NavbarVariant, NumberInput, type NumberInputProps, type OptionLike, type Options$1 as Options, OtpInput, OtpInputGroup, type OtpInputGroupProps, type OtpInputProps, PasswordInput, type PasswordInputProps, Popover, PopoverContent, PopoverTrigger, ProgressBar, RadioGroup, RadioGroupItem, Search, type SearchProps, Slider, type SliderProps, Switch, THEME_COLOR_KEYS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, Text, TextArea, type TextAreaProps, TextInput, type ThemeColorKey, Toast$1 as Toast, ToastAction, type ToastActionElement, ToastClose, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipSimple, TooltipTrigger, Tree, type TreeData, TreeItem, type TreeItemProps, type TreeProps, type UseControlledFormOptions, type UseOptionBridgeOptions, ValidationHintList, type ValidationHintListProps, type ValidationHintMode, type ValidationHintRule, type ValidationHintState, cn, createControlledForm, createYupResolver, getEndDateOfDay, getLucideIconNames, getStartDateOfDay, getStartEndTimestampOfDay, getThemeColor, getThemeColors, getTimestampUTC, reducer, resloveTimestamp, srgbToHex, toast, useControlledForm, useOptionBridge, usePrevious, useToast };
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,9 @@ export * from "./components/Tree";
|
|
|
46
46
|
export * from "./components/FocusedScrollView/FocusedScrollView";
|
|
47
47
|
export * from "./components/RadioGroup/RadioGroup";
|
|
48
48
|
export * from "./components/Form";
|
|
49
|
+
// Patterns
|
|
50
|
+
export * from "./patterns/confirm-dialog/ConfirmDialog";
|
|
51
|
+
export * from "./patterns/form-dialog/FormDialog";
|
|
49
52
|
// UTILS
|
|
50
53
|
export { resloveTimestamp, getStartDateOfDay, getEndDateOfDay, getStartEndTimestampOfDay, getTimestampUTC, } from "./utils/datetime";
|
|
51
54
|
// Hooks
|
|
@@ -5,7 +5,7 @@ import * as yup from "yup";
|
|
|
5
5
|
import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogAction, AlertDialogCancel, AlertDialogTrigger, } from "@/components/AlertDialog/AlertDialog";
|
|
6
6
|
import { useControlledForm, Field } from "@/components/Form";
|
|
7
7
|
import { TextInput } from "@/components/TextInput/TextInput";
|
|
8
|
-
export const ConfirmDialog = ({ open, onOpenChange, title, description, confirmLabel = "Confirm", cancelLabel = "Cancel", onConfirm, onCancel, onClose, trigger, typeToConfirm, hideCancelButton = false, }) => {
|
|
8
|
+
export const ConfirmDialog = ({ open, onOpenChange, title, description, confirmLabel = "Confirm", cancelLabel = "Cancel", onConfirm, onCancel, onClose, trigger, typeToConfirm, hideCancelButton = false, testId, cancelClassName, confirmClassName, }) => {
|
|
9
9
|
const formId = React.useId();
|
|
10
10
|
const requiresInput = !!typeToConfirm;
|
|
11
11
|
const validationSchema = React.useMemo(() => yup.object({
|
|
@@ -33,12 +33,13 @@ export const ConfirmDialog = ({ open, onOpenChange, title, description, confirmL
|
|
|
33
33
|
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
|
|
34
34
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
35
35
|
};
|
|
36
|
-
return (_jsxs(AlertDialog, { open: open, onOpenChange: handleOpenChange, children: [trigger && _jsx(AlertDialogTrigger, { asChild: true, children: trigger }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: title }), description && (_jsx(AlertDialogDescription, { children: description }))] }), requiresInput && (_jsxs(FormRoot, { id: formId, className: "flex flex-col gap-4 w-full", onSubmit: () => onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm(), children: [_jsxs("p", { className: "typography-small1 text-text-contrast-max", children: ["Type \u201C", typeToConfirm, "\u201D to proceed."] }), _jsx(Field, { name: "confirmInput", component: TextInput, componentProps: {
|
|
36
|
+
return (_jsxs(AlertDialog, { open: open, onOpenChange: handleOpenChange, children: [trigger && _jsx(AlertDialogTrigger, { asChild: true, children: trigger }), _jsxs(AlertDialogContent, { "data-testid": testId, children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { "data-testid": testId && `${testId}-title`, children: title }), description && (_jsx(AlertDialogDescription, { "data-testid": testId && `${testId}-description`, children: description }))] }), requiresInput && (_jsxs(FormRoot, { id: formId, className: "flex flex-col gap-4 w-full", onSubmit: () => onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm(), children: [_jsxs("p", { className: "typography-small1 text-text-contrast-max", children: ["Type \u201C", typeToConfirm, "\u201D to proceed."] }), _jsx(Field, { name: "confirmInput", component: TextInput, componentProps: {
|
|
37
37
|
label: "Type to confirm",
|
|
38
38
|
required: true,
|
|
39
39
|
hasClearIcon: true,
|
|
40
40
|
keepFooterSpace: true,
|
|
41
41
|
fullwidth: true,
|
|
42
|
-
|
|
42
|
+
testId: testId && `${testId}-type-to-confirm-input`,
|
|
43
|
+
} })] })), _jsxs(AlertDialogFooter, { children: [!hideCancelButton && (_jsx(AlertDialogCancel, { className: cancelClassName, "data-testid": testId && `${testId}-cancel-button`, onClick: handleCancel, children: cancelLabel })), _jsx(AlertDialogAction, { type: "submit", form: requiresInput ? formId : undefined, disabled: requiresInput && !isFormValid, onClick: requiresInput ? undefined : () => onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm(), className: confirmClassName, "data-testid": testId && `${testId}-confirm-button`, children: confirmLabel })] })] })] }));
|
|
43
44
|
};
|
|
44
45
|
ConfirmDialog.displayName = "ConfirmDialog";
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogBody, DialogFooter, DialogTrigger, } from "@/components/Dialog/Dialog";
|
|
4
4
|
import Button from "@/components/Button/Button";
|
|
5
|
-
export const FormDialog = ({ open, onOpenChange, title, description, children, trigger, confirmAction, cancelAction, extraAction, scrollable = false, className, formId, }) => {
|
|
5
|
+
export const FormDialog = ({ open, onOpenChange, title, description, children, trigger, confirmAction, cancelAction, extraAction, scrollable = false, className, formId, testId, }) => {
|
|
6
6
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
7
7
|
const hasFooter = confirmAction || cancelAction || extraAction;
|
|
8
|
-
return (_jsxs(Dialog, { open: open, onOpenChange: onOpenChange, children: [trigger && _jsx(DialogTrigger, { asChild: true, children: trigger }), _jsxs(DialogContent, { className: className, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: title }), description && (_jsx(DialogDescription, { children: description }))] }), children && (_jsx(DialogBody, { scrollable: scrollable, children: children })), hasFooter && (_jsxs(DialogFooter, { className: extraAction ? "justify-between" : undefined, children: [extraAction && (_jsx(Button, { type: (_a = extraAction.type) !== null && _a !== void 0 ? _a : "button", variant: (_b = extraAction.variant) !== null && _b !== void 0 ? _b : "outline", color: (_c = extraAction.color) !== null && _c !== void 0 ? _c : "secondary", fullwidth: false, disabled: extraAction.disabled, isLoading: extraAction.isLoading, onClick: extraAction.onClick, children: extraAction.label })), _jsxs("div", { className: "flex items-center gap-4", children: [cancelAction && (_jsx(Button, { type: (_d = cancelAction.type) !== null && _d !== void 0 ? _d : "button", variant: (_e = cancelAction.variant) !== null && _e !== void 0 ? _e : "outline", color: (_f = cancelAction.color) !== null && _f !== void 0 ? _f : "primary", fullwidth: false, disabled: cancelAction.disabled, isLoading: cancelAction.isLoading, onClick: cancelAction.onClick, children: cancelAction.label })), confirmAction && (_jsx(Button, { type: formId ? "submit" : (
|
|
8
|
+
return (_jsxs(Dialog, { open: open, onOpenChange: onOpenChange, children: [trigger && _jsx(DialogTrigger, { asChild: true, children: trigger }), _jsxs(DialogContent, { className: className, "data-testid": testId, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { "data-testid": testId && `${testId}-title`, children: title }), description && (_jsx(DialogDescription, { "data-testid": testId && `${testId}-description`, children: description }))] }), children && (_jsx(DialogBody, { scrollable: scrollable, children: children })), hasFooter && (_jsxs(DialogFooter, { className: extraAction ? "justify-between" : undefined, children: [extraAction && (_jsx(Button, { type: (_a = extraAction.type) !== null && _a !== void 0 ? _a : "button", variant: (_b = extraAction.variant) !== null && _b !== void 0 ? _b : "outline", color: (_c = extraAction.color) !== null && _c !== void 0 ? _c : "secondary", fullwidth: false, disabled: extraAction.disabled, isLoading: extraAction.isLoading, onClick: extraAction.onClick, className: extraAction.className, "data-testid": testId && `${testId}-extra-button`, children: extraAction.label })), _jsxs("div", { className: "flex items-center gap-4", children: [cancelAction && (_jsx(Button, { type: (_d = cancelAction.type) !== null && _d !== void 0 ? _d : "button", variant: (_e = cancelAction.variant) !== null && _e !== void 0 ? _e : "outline", color: (_f = cancelAction.color) !== null && _f !== void 0 ? _f : "primary", fullwidth: false, disabled: cancelAction.disabled, isLoading: cancelAction.isLoading, onClick: cancelAction.onClick, className: cancelAction.className, "data-testid": testId && `${testId}-cancel-button`, children: cancelAction.label })), confirmAction && (_jsx(Button, { type: formId ? "submit" : (_g = confirmAction.type) !== null && _g !== void 0 ? _g : "button", form: formId, variant: (_h = confirmAction.variant) !== null && _h !== void 0 ? _h : "solid", color: (_j = confirmAction.color) !== null && _j !== void 0 ? _j : "primary", fullwidth: false, disabled: confirmAction.disabled, isLoading: confirmAction.isLoading, onClick: confirmAction.onClick, className: confirmAction.className, "data-testid": testId && `${testId}-confirm-button`, children: confirmAction.label }))] })] }))] })] }));
|
|
9
9
|
};
|
|
10
10
|
FormDialog.displayName = "FormDialog";
|
|
@@ -4259,6 +4259,10 @@ input[type=number] {
|
|
|
4259
4259
|
min-width: 18rem;
|
|
4260
4260
|
}
|
|
4261
4261
|
|
|
4262
|
+
.min-w-\[100px\] {
|
|
4263
|
+
min-width: 100px;
|
|
4264
|
+
}
|
|
4265
|
+
|
|
4262
4266
|
.min-w-\[154px\] {
|
|
4263
4267
|
min-width: 154px;
|
|
4264
4268
|
}
|
|
@@ -4641,6 +4645,10 @@ input[type=number] {
|
|
|
4641
4645
|
white-space: nowrap;
|
|
4642
4646
|
}
|
|
4643
4647
|
|
|
4648
|
+
.whitespace-pre-line {
|
|
4649
|
+
white-space: pre-line;
|
|
4650
|
+
}
|
|
4651
|
+
|
|
4644
4652
|
.break-all {
|
|
4645
4653
|
word-break: break-all;
|
|
4646
4654
|
}
|
package/package.json
CHANGED
|
@@ -101,7 +101,7 @@ const AlertDialogAction = React.forwardRef<
|
|
|
101
101
|
ref={ref}
|
|
102
102
|
className={cn(
|
|
103
103
|
buttonVariants({ fullwidth: false }),
|
|
104
|
-
"w-[100px] justify-center",
|
|
104
|
+
"min-w-[100px] justify-center",
|
|
105
105
|
className,
|
|
106
106
|
)}
|
|
107
107
|
{...props}
|
|
@@ -117,7 +117,7 @@ const AlertDialogCancel = React.forwardRef<
|
|
|
117
117
|
ref={ref}
|
|
118
118
|
className={cn(
|
|
119
119
|
buttonVariants({ fullwidth: false, variant: "outline" }),
|
|
120
|
-
"w-[100px] justify-center",
|
|
120
|
+
"min-w-[100px] justify-center whitespace-pre-line",
|
|
121
121
|
className,
|
|
122
122
|
)}
|
|
123
123
|
{...props}
|
package/src/index.ts
CHANGED
|
@@ -52,6 +52,10 @@ export * from "./components/FocusedScrollView/FocusedScrollView";
|
|
|
52
52
|
export * from "./components/RadioGroup/RadioGroup";
|
|
53
53
|
export * from "./components/Form";
|
|
54
54
|
|
|
55
|
+
// Patterns
|
|
56
|
+
export * from "./patterns/confirm-dialog/ConfirmDialog";
|
|
57
|
+
export * from "./patterns/form-dialog/FormDialog";
|
|
58
|
+
|
|
55
59
|
// Export component types
|
|
56
60
|
export type { ButtonProps } from "./components/Button/Button";
|
|
57
61
|
export type { InputProps } from "./components/TextInput/TextInput";
|
|
@@ -37,6 +37,9 @@ export type ConfirmDialogProps = {
|
|
|
37
37
|
* When true, hides the cancel button — useful for info/error alerts that only need one action.
|
|
38
38
|
*/
|
|
39
39
|
hideCancelButton?: boolean;
|
|
40
|
+
testId?: string;
|
|
41
|
+
cancelClassName?: string;
|
|
42
|
+
confirmClassName?: string;
|
|
40
43
|
};
|
|
41
44
|
|
|
42
45
|
type ConfirmFormValues = { confirmInput: string };
|
|
@@ -54,6 +57,9 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
54
57
|
trigger,
|
|
55
58
|
typeToConfirm,
|
|
56
59
|
hideCancelButton = false,
|
|
60
|
+
testId,
|
|
61
|
+
cancelClassName,
|
|
62
|
+
confirmClassName,
|
|
57
63
|
}) => {
|
|
58
64
|
const formId = React.useId();
|
|
59
65
|
const requiresInput = !!typeToConfirm;
|
|
@@ -99,11 +105,15 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
99
105
|
return (
|
|
100
106
|
<AlertDialog open={open} onOpenChange={handleOpenChange}>
|
|
101
107
|
{trigger && <AlertDialogTrigger asChild>{trigger}</AlertDialogTrigger>}
|
|
102
|
-
<AlertDialogContent>
|
|
108
|
+
<AlertDialogContent data-testid={testId}>
|
|
103
109
|
<AlertDialogHeader>
|
|
104
|
-
<AlertDialogTitle
|
|
110
|
+
<AlertDialogTitle data-testid={testId && `${testId}-title`}>
|
|
111
|
+
{title}
|
|
112
|
+
</AlertDialogTitle>
|
|
105
113
|
{description && (
|
|
106
|
-
<AlertDialogDescription
|
|
114
|
+
<AlertDialogDescription data-testid={testId && `${testId}-description`}>
|
|
115
|
+
{description}
|
|
116
|
+
</AlertDialogDescription>
|
|
107
117
|
)}
|
|
108
118
|
</AlertDialogHeader>
|
|
109
119
|
|
|
@@ -125,6 +135,7 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
125
135
|
hasClearIcon: true,
|
|
126
136
|
keepFooterSpace: true,
|
|
127
137
|
fullwidth: true,
|
|
138
|
+
testId: testId && `${testId}-type-to-confirm-input`,
|
|
128
139
|
}}
|
|
129
140
|
/>
|
|
130
141
|
</FormRoot>
|
|
@@ -132,7 +143,11 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
132
143
|
|
|
133
144
|
<AlertDialogFooter>
|
|
134
145
|
{!hideCancelButton && (
|
|
135
|
-
<AlertDialogCancel
|
|
146
|
+
<AlertDialogCancel
|
|
147
|
+
className={cancelClassName}
|
|
148
|
+
data-testid={testId && `${testId}-cancel-button`}
|
|
149
|
+
onClick={handleCancel}
|
|
150
|
+
>
|
|
136
151
|
{cancelLabel}
|
|
137
152
|
</AlertDialogCancel>
|
|
138
153
|
)}
|
|
@@ -141,6 +156,8 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
141
156
|
form={requiresInput ? formId : undefined}
|
|
142
157
|
disabled={requiresInput && !isFormValid}
|
|
143
158
|
onClick={requiresInput ? undefined : () => onConfirm?.()}
|
|
159
|
+
className={confirmClassName}
|
|
160
|
+
data-testid={testId && `${testId}-confirm-button`}
|
|
144
161
|
>
|
|
145
162
|
{confirmLabel}
|
|
146
163
|
</AlertDialogAction>
|
|
@@ -22,6 +22,7 @@ export type FormDialogAction = {
|
|
|
22
22
|
disabled?: boolean;
|
|
23
23
|
isLoading?: boolean;
|
|
24
24
|
type?: "button" | "submit" | "reset";
|
|
25
|
+
className?: string;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
export type FormDialogProps = {
|
|
@@ -50,6 +51,7 @@ export type FormDialogProps = {
|
|
|
50
51
|
* Use together with a <Form id={formId} .../> inside children.
|
|
51
52
|
*/
|
|
52
53
|
formId?: string;
|
|
54
|
+
testId?: string;
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
export const FormDialog: React.FC<FormDialogProps> = ({
|
|
@@ -65,17 +67,20 @@ export const FormDialog: React.FC<FormDialogProps> = ({
|
|
|
65
67
|
scrollable = false,
|
|
66
68
|
className,
|
|
67
69
|
formId,
|
|
70
|
+
testId,
|
|
68
71
|
}) => {
|
|
69
72
|
const hasFooter = confirmAction || cancelAction || extraAction;
|
|
70
73
|
|
|
71
74
|
return (
|
|
72
75
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
73
76
|
{trigger && <DialogTrigger asChild>{trigger}</DialogTrigger>}
|
|
74
|
-
<DialogContent className={className}>
|
|
77
|
+
<DialogContent className={className} data-testid={testId}>
|
|
75
78
|
<DialogHeader>
|
|
76
|
-
<DialogTitle>{title}</DialogTitle>
|
|
79
|
+
<DialogTitle data-testid={testId && `${testId}-title`}>{title}</DialogTitle>
|
|
77
80
|
{description && (
|
|
78
|
-
<DialogDescription
|
|
81
|
+
<DialogDescription data-testid={testId && `${testId}-description`}>
|
|
82
|
+
{description}
|
|
83
|
+
</DialogDescription>
|
|
79
84
|
)}
|
|
80
85
|
</DialogHeader>
|
|
81
86
|
|
|
@@ -94,6 +99,8 @@ export const FormDialog: React.FC<FormDialogProps> = ({
|
|
|
94
99
|
disabled={extraAction.disabled}
|
|
95
100
|
isLoading={extraAction.isLoading}
|
|
96
101
|
onClick={extraAction.onClick}
|
|
102
|
+
className={extraAction.className}
|
|
103
|
+
data-testid={testId && `${testId}-extra-button`}
|
|
97
104
|
>
|
|
98
105
|
{extraAction.label}
|
|
99
106
|
</Button>
|
|
@@ -108,13 +115,15 @@ export const FormDialog: React.FC<FormDialogProps> = ({
|
|
|
108
115
|
disabled={cancelAction.disabled}
|
|
109
116
|
isLoading={cancelAction.isLoading}
|
|
110
117
|
onClick={cancelAction.onClick}
|
|
118
|
+
className={cancelAction.className}
|
|
119
|
+
data-testid={testId && `${testId}-cancel-button`}
|
|
111
120
|
>
|
|
112
121
|
{cancelAction.label}
|
|
113
122
|
</Button>
|
|
114
123
|
)}
|
|
115
124
|
{confirmAction && (
|
|
116
125
|
<Button
|
|
117
|
-
type={formId ? "submit" :
|
|
126
|
+
type={formId ? "submit" : confirmAction.type ?? "button"}
|
|
118
127
|
form={formId}
|
|
119
128
|
variant={confirmAction.variant ?? "solid"}
|
|
120
129
|
color={confirmAction.color ?? "primary"}
|
|
@@ -122,6 +131,8 @@ export const FormDialog: React.FC<FormDialogProps> = ({
|
|
|
122
131
|
disabled={confirmAction.disabled}
|
|
123
132
|
isLoading={confirmAction.isLoading}
|
|
124
133
|
onClick={confirmAction.onClick}
|
|
134
|
+
className={confirmAction.className}
|
|
135
|
+
data-testid={testId && `${testId}-confirm-button`}
|
|
125
136
|
>
|
|
126
137
|
{confirmAction.label}
|
|
127
138
|
</Button>
|