@neasg/design-system 0.4.121 → 0.4.132
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/alert.js +3 -1
- package/dist/button.d.ts +3 -1
- package/dist/button.js +4 -3
- package/dist/checkbox.js +2 -2
- package/dist/checklist.js +4 -2
- package/dist/dialog.d.ts +4 -2
- package/dist/dialog.js +4 -4
- package/dist/dropdown-button.js +1 -0
- package/dist/file-upload-status-row.js +3 -1
- package/dist/file-upload-status-toast.d.ts +3 -1
- package/dist/file-upload-status-toast.js +2 -2
- package/dist/file-upload.d.ts +3 -1
- package/dist/file-upload.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/inline.d.ts +3 -0
- package/dist/inline.js +5 -0
- package/dist/rich-text-editor.js +3 -3
- package/dist/routing-action-panel.d.ts +3 -1
- package/dist/routing-action-panel.js +5 -3
- package/dist/routing-timeline.js +1 -1
- package/dist/table.d.ts +3 -0
- package/dist/table.js +3 -2
- package/dist/typography.d.ts +1 -1
- package/dist/typography.js +5 -3
- package/package.json +1 -1
package/dist/alert.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import { CircleAlert } from "lucide-react";
|
|
3
4
|
import { cva } from "class-variance-authority";
|
|
4
5
|
import { Button } from "./button";
|
|
5
6
|
import { Checkbox } from "./checkbox";
|
|
@@ -20,7 +21,8 @@ const alertVariants = cva("relative flex w-full items-start gap-2 rounded-surfac
|
|
|
20
21
|
});
|
|
21
22
|
const AlertAction = React.forwardRef(({ className, type = "button", ...props }, ref) => (_jsx(Button, { ref: ref, type: type, variant: "link", size: "compact", className: cn("h-auto min-h-6 px-0 text-inherit hover:text-inherit", className), ...props })));
|
|
22
23
|
AlertAction.displayName = "AlertAction";
|
|
23
|
-
const Alert = React.forwardRef(({ variant, title, description, icon
|
|
24
|
+
const Alert = React.forwardRef(({ variant, title, description, icon, action, className, children, role = "alert", ...props }, ref) => {
|
|
25
|
+
const Icon = icon !== null && icon !== void 0 ? icon : (variant === "destructive" ? CircleAlert : undefined);
|
|
24
26
|
const body = description !== null && description !== void 0 ? description : children;
|
|
25
27
|
const hasStackedContent = Boolean(title);
|
|
26
28
|
return (_jsxs("div", { ref: ref, role: role, className: cn(alertVariants({ variant }), !hasStackedContent && "items-center", className), ...props, children: [Icon ? (_jsx(Icon, { className: cn("h-4 w-4 shrink-0", hasStackedContent && "mt-0.5") })) : null, _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [title ? (_jsx(Typography, { as: "p", variant: "bodySm", color: "inherit", className: "font-bold", children: title })) : null, body ? (_jsx(Typography, { as: "div", variant: "caption", color: "inherit", className: "opacity-95", children: body })) : null] }), action ? (_jsx("div", { className: cn("shrink-0 text-inherit [&_a]:text-inherit [&_button]:text-inherit [&_button:hover]:text-inherit", hasStackedContent ? "self-start" : "self-center"), children: action })) : null] }));
|
package/dist/button.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
|
-
variant?: "link" | "default" | "warning" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
4
|
+
variant?: "link" | "default" | "warning" | "destructive" | "outline" | "secondary" | "ghost" | "destructiveGhost" | null | undefined;
|
|
5
5
|
size?: "default" | "sm" | "compact" | "comfortable" | "icon" | "compactIcon" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
7
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -12,6 +12,8 @@ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElemen
|
|
|
12
12
|
asChild?: boolean;
|
|
13
13
|
/** Allow the label to wrap within its container and the button to grow in height. */
|
|
14
14
|
wrap?: boolean;
|
|
15
|
+
/** Align the button content within its available width. */
|
|
16
|
+
contentAlign?: "center" | "start";
|
|
15
17
|
/**
|
|
16
18
|
* Shows a loading indicator, disables interaction, and sets `aria-busy`.
|
|
17
19
|
* When used with `asChild`, the component also prevents click handling and sets `aria-disabled`.
|
package/dist/button.js
CHANGED
|
@@ -12,6 +12,7 @@ const buttonVariants = cva("inline-flex cursor-pointer items-center justify-cent
|
|
|
12
12
|
outline: "border border-[hsl(var(--button-outline-border))] bg-[hsl(var(--button-outline-background))] text-foreground hover:bg-[hsl(var(--button-outline-hover-background))] hover:text-accent-foreground",
|
|
13
13
|
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
14
14
|
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
15
|
+
destructiveGhost: "text-destructive hover:bg-destructive/10 hover:text-destructive focus-visible:ring-destructive",
|
|
15
16
|
link: "text-interactive underline-offset-4 hover:text-interactive hover:underline",
|
|
16
17
|
},
|
|
17
18
|
size: {
|
|
@@ -102,7 +103,7 @@ function attachAnimatedIconRefs(node, refs) {
|
|
|
102
103
|
}
|
|
103
104
|
return node;
|
|
104
105
|
}
|
|
105
|
-
const Button = React.forwardRef(({ className, variant, size, asChild = false, wrap = false, loading = false, loadingText, loadingIndicator, disabled, children, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, tabIndex, ...props }, ref) => {
|
|
106
|
+
const Button = React.forwardRef(({ className, variant, size, asChild = false, wrap = false, contentAlign = "center", loading = false, loadingText, loadingIndicator, disabled, children, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, tabIndex, ...props }, ref) => {
|
|
106
107
|
const Comp = asChild ? Slot : "button";
|
|
107
108
|
const isDisabled = disabled || loading;
|
|
108
109
|
const loadingLabel = loadingText !== null && loadingText !== void 0 ? loadingText : children;
|
|
@@ -112,7 +113,7 @@ const Button = React.forwardRef(({ className, variant, size, asChild = false, wr
|
|
|
112
113
|
hasTextLikeContent(children)) {
|
|
113
114
|
throw new Error('NEA Button `size="icon"` and `size="compactIcon"` only accepts icon components or SVG content. Do not pass text or emoji.');
|
|
114
115
|
}
|
|
115
|
-
const content = loading ? (loadingLabel ? (_jsxs("span", { className: "inline-flex items-center gap-2", children: [loadingIndicator !== null && loadingIndicator !== void 0 ? loadingIndicator : _jsx(DefaultLoadingIndicator, {}), _jsx("span", { children: attachAnimatedIconRefs(loadingLabel, animatedIconRefs) })] })) : (loadingIndicator !== null && loadingIndicator !== void 0 ? loadingIndicator : _jsx(DefaultLoadingIndicator, {}))) : (attachAnimatedIconRefs(children, animatedIconRefs));
|
|
116
|
+
const content = loading ? (loadingLabel ? (_jsxs("span", { className: "inline-flex items-center gap-2", children: [loadingIndicator !== null && loadingIndicator !== void 0 ? loadingIndicator : _jsx(DefaultLoadingIndicator, {}), _jsx("span", { className: "inline-flex items-center gap-2", children: attachAnimatedIconRefs(loadingLabel, animatedIconRefs) })] })) : (loadingIndicator !== null && loadingIndicator !== void 0 ? loadingIndicator : _jsx(DefaultLoadingIndicator, {}))) : (attachAnimatedIconRefs(children, animatedIconRefs));
|
|
116
117
|
const startAnimatedIcons = () => {
|
|
117
118
|
animatedIconRefs.current.forEach((icon) => { var _a; return (_a = icon.startAnimation) === null || _a === void 0 ? void 0 : _a.call(icon); });
|
|
118
119
|
};
|
|
@@ -149,7 +150,7 @@ const Button = React.forwardRef(({ className, variant, size, asChild = false, wr
|
|
|
149
150
|
};
|
|
150
151
|
return (_jsx(Comp, { "data-slot": "button", className: cn(buttonVariants({ variant, size }), wrap && "h-auto max-w-full whitespace-normal break-words py-1.5", wrap && (size === "sm" || size === "compact" || size === "compactIcon"
|
|
151
152
|
? "min-h-8"
|
|
152
|
-
: size === "comfortable" ? "min-h-[46px]" : "min-h-control"), className), ref: ref, "aria-busy": loading || undefined, "aria-disabled": isDisabled || undefined, "data-loading": loading ? "" : undefined, "data-disabled": isDisabled ? "" : undefined, onClick: handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, tabIndex: isDisabled && asChild ? -1 : tabIndex, disabled: !asChild ? isDisabled : undefined, ...props, children: content }));
|
|
153
|
+
: size === "comfortable" ? "min-h-[46px]" : "min-h-control"), contentAlign === "start" && "justify-start text-left", className), ref: ref, "aria-busy": loading || undefined, "aria-disabled": isDisabled || undefined, "data-loading": loading ? "" : undefined, "data-disabled": isDisabled ? "" : undefined, onClick: handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, tabIndex: isDisabled && asChild ? -1 : tabIndex, disabled: !asChild ? isDisabled : undefined, ...props, children: content }));
|
|
153
154
|
});
|
|
154
155
|
Button.displayName = "Button";
|
|
155
156
|
export { Button, buttonVariants };
|
package/dist/checkbox.js
CHANGED
|
@@ -24,9 +24,9 @@ const Checkbox = React.forwardRef(({ className, indeterminate = false, size = "m
|
|
|
24
24
|
innerRef.current.indeterminate = indeterminate;
|
|
25
25
|
}
|
|
26
26
|
}, [indeterminate]);
|
|
27
|
-
const box = (_jsxs("span", { className: cn("relative inline-
|
|
27
|
+
const box = (_jsxs("span", { className: cn("relative inline-flex shrink-0 items-center justify-center rounded-sm border bg-background align-middle text-primary-foreground transition-colors", sizeClasses[size], (checked || indeterminate) && !disabled
|
|
28
28
|
? "border-primary bg-primary"
|
|
29
|
-
: "border-input", disabled && "cursor-not-allowed opacity-50", label && alignToStart && startAlignedOffsetClasses[size], !label && className), children: [_jsx("input", { ref: innerRef, type: "checkbox", id: inputId, checked: checked, disabled: disabled, className: "absolute inset-0 h-full w-full cursor-pointer appearance-none opacity-0 disabled:cursor-not-allowed", ...props }), indeterminate ? (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", className: "pointer-events-none
|
|
29
|
+
: "border-input", disabled && "cursor-not-allowed opacity-50", label && alignToStart && startAlignedOffsetClasses[size], !label && className), children: [_jsx("input", { ref: innerRef, type: "checkbox", id: inputId, checked: checked, disabled: disabled, className: "absolute inset-0 h-full w-full cursor-pointer appearance-none opacity-0 disabled:cursor-not-allowed", ...props }), indeterminate ? (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", className: "pointer-events-none h-3 w-3", "aria-hidden": "true", children: _jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) })) : checked ? (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", className: "pointer-events-none h-3 w-3", "aria-hidden": "true", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) })) : null] }));
|
|
30
30
|
if (!label)
|
|
31
31
|
return box;
|
|
32
32
|
return (_jsxs("label", { htmlFor: inputId, className: cn("inline-flex cursor-pointer gap-2 text-sm", alignToStart ? "items-start" : "items-center", disabled && "cursor-not-allowed opacity-50", className), children: [box, _jsxs("div", { className: "flex min-w-0 flex-col gap-0.5 select-none", children: [_jsx(Typography, { as: "span", variant: "bodySm", children: label }), description ? (_jsx(Typography, { as: "p", variant: "caption", color: "muted", children: description })) : null] })] }));
|
package/dist/checklist.js
CHANGED
|
@@ -16,15 +16,17 @@ export function ChecklistSection({ title, progress, action, children, defaultOpe
|
|
|
16
16
|
}
|
|
17
17
|
export function ChecklistSelection({ title, description, typeOptions, subtypeOptions, type, subtype, onTypeChange, onSubtypeChange, disabled, loading, action }) {
|
|
18
18
|
const Icon = loading ? LoaderCircle : ClipboardList;
|
|
19
|
-
return _jsxs("div", { "data-slot": "checklist-selection", "aria-busy": loading, className: "flex flex-col items-center gap-4 rounded-lg bg-muted/30 p-6 text-center", children: [_jsx(Icon, { "aria-hidden": "true", className: cn("size-8", loading && "animate-spin") }), _jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-sm font-medium", children: title }), _jsx("p", { className: "text-sm text-muted-foreground", children: description })] }), _jsxs("div", { className: "
|
|
19
|
+
return _jsxs("div", { "data-slot": "checklist-selection", "aria-busy": loading, className: "flex flex-col items-center gap-4 rounded-lg bg-muted/30 p-6 text-center", children: [_jsx(Icon, { "aria-hidden": "true", className: cn("size-8", loading && "animate-spin") }), _jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-sm font-medium", children: title }), _jsx("p", { className: "text-sm text-muted-foreground", children: description })] }), _jsxs("div", { className: "grid w-full max-w-md grid-cols-1 gap-[var(--layout-page-control-gap)] sm:grid-cols-2", children: [_jsx(Select, { label: "Type", hideLabel: true, placeholder: "Type", options: typeOptions, value: type, onValueChange: onTypeChange, disabled: disabled || loading }), _jsx(Select, { label: "Sub-Type", hideLabel: true, placeholder: "Sub-Type", options: subtypeOptions, value: subtype, onValueChange: onSubtypeChange, disabled: disabled || loading || !type })] }), action] });
|
|
20
20
|
}
|
|
21
21
|
export function ChecklistQuestion({ label, options, value, onValueChange, disabled, remarks, onRemarksChange, remarksLimit = 500, remarksMaxLength, remarksRequired = false, evidence, evidenceCount = 0 }) {
|
|
22
22
|
const name = React.useId();
|
|
23
23
|
const [showRemarks, setShowRemarks] = React.useState(false);
|
|
24
24
|
const [showEvidence, setShowEvidence] = React.useState(false);
|
|
25
|
+
const remarksVisible = disabled ? Boolean(remarks.trim()) : showRemarks;
|
|
26
|
+
const evidenceVisible = disabled ? evidenceCount > 0 : showEvidence;
|
|
25
27
|
const remarksToggleLabel = showRemarks ? "Hide remarks" : "Show remarks";
|
|
26
28
|
const evidenceToggleLabel = showEvidence ? "Hide photos" : "Show photos";
|
|
27
|
-
return _jsxs("div", { "data-slot": "checklist-question", className: "space-y-4 rounded-xl border border-border bg-card p-4 shadow-xs", children: [_jsx("p", { id: `${name}-label`, className: "text-sm font-medium", children: label }), _jsxs("div", { className: "flex flex-wrap items-center gap-6", children: [_jsx("fieldset", { disabled: disabled, "aria-labelledby": `${name}-label`, className: cn("flex min-w-0 border-0 p-0", disabled && "opacity-50"), children: options.map((option, index) => _jsxs("label", { className: cn("relative cursor-pointer border border-input px-2.5 py-2 text-sm font-medium focus-within:z-10 focus-within:ring-2 focus-within:ring-ring", index > 0 && "-ml-px", index === 0 && "rounded-l-md", index === options.length - 1 && "rounded-r-md", disabled && "cursor-not-allowed", value === option.value ? option.tone === "negative" ? "bg-destructive/20" : option.tone === "positive" ? "bg-primary/20" : "bg-muted" : "bg-background"), children: [_jsx("input", { className: "absolute inset-0 size-full cursor-inherit opacity-0", type: "radio", name: name, value: option.value, checked: value === option.value, onChange: () => onValueChange(option.value) }), option.label] }, option.value)) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tooltip, { content: remarksToggleLabel, children: _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", "aria-label": remarksToggleLabel, "aria-expanded": showRemarks, "aria-controls": `${name}-remarks`, onClick: () => setShowRemarks((open) => !open), children: _jsx(MessageSquareText, { "aria-hidden": "true", size: 16 }) }) }), evidence ? _jsx(Tooltip, { content: `${evidenceToggleLabel}${evidenceCount > 0 ? ` (${evidenceCount})` : ""}`, children: _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", "aria-label": evidenceToggleLabel, "aria-expanded": showEvidence, "aria-controls": `${name}-evidence`, onClick: () => setShowEvidence((open) => !open), children: _jsx(Camera, { "aria-hidden": "true", size: 16 }) }) }) : null] })] }),
|
|
29
|
+
return _jsxs("div", { "data-slot": "checklist-question", className: "space-y-4 rounded-xl border border-border bg-card p-4 shadow-xs", children: [_jsx("p", { id: `${name}-label`, className: "text-sm font-medium", children: label }), _jsxs("div", { className: "flex flex-wrap items-center gap-6", children: [_jsx("fieldset", { disabled: disabled, "aria-labelledby": `${name}-label`, className: cn("flex min-w-0 border-0 p-0", disabled && "opacity-50"), children: options.map((option, index) => _jsxs("label", { className: cn("relative cursor-pointer border border-input px-2.5 py-2 text-sm font-medium focus-within:z-10 focus-within:ring-2 focus-within:ring-ring", index > 0 && "-ml-px", index === 0 && "rounded-l-md", index === options.length - 1 && "rounded-r-md", disabled && "cursor-not-allowed", value === option.value ? option.tone === "negative" ? "bg-destructive/20" : option.tone === "positive" ? "bg-primary/20" : "bg-muted" : "bg-background"), children: [_jsx("input", { className: "absolute inset-0 size-full cursor-inherit opacity-0", type: "radio", name: name, value: option.value, checked: value === option.value, onChange: () => onValueChange(option.value) }), option.label] }, option.value)) }), !disabled ? _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tooltip, { content: remarksToggleLabel, children: _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", "aria-label": remarksToggleLabel, "aria-expanded": showRemarks, "aria-controls": `${name}-remarks`, onClick: () => setShowRemarks((open) => !open), children: _jsx(MessageSquareText, { "aria-hidden": "true", size: 16 }) }) }), evidence ? _jsx(Tooltip, { content: `${evidenceToggleLabel}${evidenceCount > 0 ? ` (${evidenceCount})` : ""}`, children: _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", "aria-label": evidenceToggleLabel, "aria-expanded": showEvidence, "aria-controls": `${name}-evidence`, onClick: () => setShowEvidence((open) => !open), children: _jsx(Camera, { "aria-hidden": "true", size: 16 }) }) }) : null] }) : null] }), evidenceVisible && evidence ? _jsx("div", { id: `${name}-evidence`, children: evidence }) : null, remarksVisible ? _jsx("div", { id: `${name}-remarks`, children: disabled ? _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium", children: "Remarks" }), _jsx("p", { className: "whitespace-pre-wrap text-sm text-muted-foreground", children: remarks })] }) : _jsx(Textarea, { label: "Remarks", hideLabel: true, placeholder: "Type...", value: remarks, "aria-required": remarksRequired, rows: 5, onChange: (event) => onRemarksChange(event.target.value), maxWords: remarksMaxLength === undefined ? remarksLimit : undefined, maxLength: remarksMaxLength, showCount: remarksMaxLength !== undefined }) }) : null] });
|
|
28
30
|
}
|
|
29
31
|
export function ChecklistAttachments({ items, onRemove }) {
|
|
30
32
|
return _jsx("div", { className: "flex flex-wrap gap-2", children: items.map((item) => _jsxs("div", { className: "relative", children: [_jsx("a", { href: item.url, target: "_blank", rel: "noreferrer", children: _jsx("img", { src: item.url, alt: item.name, className: "size-20 rounded-md border border-border object-cover" }) }), onRemove ? _jsx(Button, { variant: "outline", size: "compactIcon", "aria-label": `Remove ${item.name}`, onClick: () => onRemove(item.key), children: _jsx(Trash2, { "aria-hidden": "true", size: 16 }) }) : null] }, item.key)) });
|
package/dist/dialog.d.ts
CHANGED
|
@@ -10,8 +10,10 @@ export interface DialogAction extends Omit<ButtonProps, "children"> {
|
|
|
10
10
|
type DialogRenderable = React.ReactNode | ((helpers: DialogRenderHelpers) => React.ReactNode);
|
|
11
11
|
export interface DialogProps {
|
|
12
12
|
variant?: "default" | "confirmation" | "routingConfirmation";
|
|
13
|
-
/** Standard dialogs are
|
|
13
|
+
/** Standard dialogs are 512px wide; larger sizes are for complex editors. */
|
|
14
14
|
size?: "standard" | "large" | "extraLarge" | "full";
|
|
15
|
+
/** Optional minimum height for dialogs whose content changes between steps. */
|
|
16
|
+
minHeight?: React.CSSProperties["minHeight"];
|
|
15
17
|
open?: boolean;
|
|
16
18
|
defaultOpen?: boolean;
|
|
17
19
|
onOpenChange?: (open: boolean) => void;
|
|
@@ -29,5 +31,5 @@ export interface DialogProps {
|
|
|
29
31
|
/** Whether a pointer interaction outside the dialog closes it. */
|
|
30
32
|
closeOnOutsideClick?: boolean;
|
|
31
33
|
}
|
|
32
|
-
declare function Dialog({ variant, size, open, defaultOpen, onOpenChange, modal, trigger, title, description, children, footer, primaryAction, secondaryAction, contentClassName, bodyClassName, hideCloseButton, closeOnOutsideClick, }: DialogProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
declare function Dialog({ variant, size, minHeight, open, defaultOpen, onOpenChange, modal, trigger, title, description, children, footer, primaryAction, secondaryAction, contentClassName, bodyClassName, hideCloseButton, closeOnOutsideClick, }: DialogProps): import("react/jsx-runtime").JSX.Element;
|
|
33
35
|
export { Dialog };
|
package/dist/dialog.js
CHANGED
|
@@ -32,7 +32,7 @@ function renderDialogAction({ action, close, defaultVariant, }) {
|
|
|
32
32
|
}
|
|
33
33
|
}, children: label }));
|
|
34
34
|
}
|
|
35
|
-
function Dialog({ variant = "default", size = "standard", open, defaultOpen, onOpenChange, modal, trigger, title, description, children, footer, primaryAction, secondaryAction, contentClassName, bodyClassName, hideCloseButton = false, closeOnOutsideClick = false, }) {
|
|
35
|
+
function Dialog({ variant = "default", size = "standard", minHeight, open, defaultOpen, onOpenChange, modal, trigger, title, description, children, footer, primaryAction, secondaryAction, contentClassName, bodyClassName, hideCloseButton = false, closeOnOutsideClick = false, }) {
|
|
36
36
|
const [isOpen, setIsOpen] = useControllableOpen({
|
|
37
37
|
open,
|
|
38
38
|
defaultOpen,
|
|
@@ -46,14 +46,14 @@ function Dialog({ variant = "default", size = "standard", open, defaultOpen, onO
|
|
|
46
46
|
const hasFooter = Boolean(customFooter || primaryAction || secondaryAction);
|
|
47
47
|
const isCompactConfirmation = variant === "confirmation";
|
|
48
48
|
const isRoutingConfirmation = variant === "routingConfirmation";
|
|
49
|
-
return (_jsxs(DialogRoot, { open: isOpen, onOpenChange: setIsOpen, modal: modal, children: [trigger ? _jsx(DialogTrigger, { asChild: true, children: trigger }) : null, _jsxs(DialogSurface, { ...(!description ? { "aria-describedby": undefined } : {}), className: cn(isCompactConfirmation &&
|
|
49
|
+
return (_jsxs(DialogRoot, { open: isOpen, onOpenChange: setIsOpen, modal: modal, children: [trigger ? _jsx(DialogTrigger, { asChild: true, children: trigger }) : null, _jsxs(DialogSurface, { ...(!description ? { "aria-describedby": undefined } : {}), style: minHeight !== undefined ? { minHeight } : undefined, className: cn(isCompactConfirmation &&
|
|
50
50
|
"gap-0 overflow-hidden rounded-xl p-0", isRoutingConfirmation &&
|
|
51
|
-
"gap-0 rounded-overlay p-[var(--space-8)]", "w-[calc(100vw-
|
|
51
|
+
"gap-0 rounded-overlay p-[var(--space-8)]", minHeight !== undefined && "flex flex-col", "w-[calc(100vw-32px)]", { standard: "max-w-[512px]", large: "max-w-3xl", extraLarge: "max-w-5xl", full: "max-w-[96rem]" }[size], contentClassName), hideCloseButton: hideCloseButton || isCompactConfirmation || isRoutingConfirmation, onPointerDownOutside: (event) => {
|
|
52
52
|
if (!closeOnOutsideClick) {
|
|
53
53
|
event.preventDefault();
|
|
54
54
|
}
|
|
55
55
|
}, children: [_jsxs("div", { className: cn(isCompactConfirmation && "flex items-start gap-4 p-4"), children: [isCompactConfirmation ? (_jsx("div", { className: "rounded-lg bg-muted p-2", children: _jsx(CircleAlert, { "aria-hidden": "true", className: "size-6" }) })) : null, _jsxs(DialogHeader, { className: cn(isRoutingConfirmation && "gap-3 space-y-0"), children: [_jsx(DialogTitle, { className: cn(isRoutingConfirmation && "text-2xl leading-8"), children: title }), description ? (_jsx(DialogDescription, { className: cn(isRoutingConfirmation &&
|
|
56
|
-
"text-base leading-6 text-foreground"), children: description })) : null] })] }), body ? (_jsx("div", { className: cn("grid gap-4", isRoutingConfirmation && "mt-3 gap-[var(--space-8)]", bodyClassName), children: body })) : null, hasFooter ? (_jsx(DialogFooter, { className: cn(isCompactConfirmation && "border-t bg-muted/30 p-4", isRoutingConfirmation && "mt-[var(--space-8)] gap-3"), children: customFooter !== null && customFooter !== void 0 ? customFooter : (_jsxs(_Fragment, { children: [secondaryAction
|
|
56
|
+
"text-base leading-6 text-foreground"), children: description })) : null] })] }), body ? (_jsx("div", { className: cn("grid gap-4", minHeight !== undefined && "flex-1", isRoutingConfirmation && "mt-3 gap-[var(--space-8)]", bodyClassName), children: body })) : null, hasFooter ? (_jsx(DialogFooter, { className: cn(isCompactConfirmation && "border-t bg-muted/30 p-4", isRoutingConfirmation && "mt-[var(--space-8)] gap-3", minHeight !== undefined && "mt-auto"), children: customFooter !== null && customFooter !== void 0 ? customFooter : (_jsxs(_Fragment, { children: [secondaryAction
|
|
57
57
|
? renderDialogAction({
|
|
58
58
|
action: secondaryAction,
|
|
59
59
|
close: helpers.close,
|
package/dist/dropdown-button.js
CHANGED
|
@@ -12,6 +12,7 @@ const splitButtonDividerClassNames = {
|
|
|
12
12
|
outline: "before:bg-[hsl(var(--button-outline-border))]",
|
|
13
13
|
secondary: "before:bg-secondary-foreground/20",
|
|
14
14
|
ghost: "before:bg-border",
|
|
15
|
+
destructiveGhost: "before:bg-destructive/30",
|
|
15
16
|
link: "before:bg-interactive/25",
|
|
16
17
|
};
|
|
17
18
|
function DropdownButton({ label, leadingIcon, children, className, contentClassName, dropdownAriaLabel, menuWidth = "trigger", align = "end", alignOffset, avoidCollisions, collisionPadding, defaultOpen, disabled, hideWhenDetached, loading, loadingIndicator, loadingText, modal, onClick, onOpenChange, open, side, sideOffset = 4, split: splitProp, sticky, type = "button", variant, size, ...buttonProps }) {
|
|
@@ -37,7 +37,9 @@ export function FileUploadStatusRow({ file, onCancel, onRemove, disabled = false
|
|
|
37
37
|
const canCancel = (isUploading || isPending) && onCancel;
|
|
38
38
|
const canRemove = !isUploading && onRemove;
|
|
39
39
|
const action = canCancel ? "cancel" : canRemove ? "remove" : null;
|
|
40
|
-
return (_jsxs("li", { className: cn("rounded-control border bg-background px-2.5 py-2", isError && "border-destructive/80 bg-destructive/5"), children: [_jsxs("div", { className: "grid
|
|
40
|
+
return (_jsxs("li", { className: cn("rounded-control border bg-background px-2.5 py-2", isError && "border-destructive/80 bg-destructive/5"), children: [_jsxs("div", { className: cn("grid min-h-7 items-start gap-x-2", action
|
|
41
|
+
? "grid-cols-[1.5rem_minmax(0,1fr)_auto_1.75rem]"
|
|
42
|
+
: "grid-cols-[1.5rem_minmax(0,1fr)_auto]"), children: [_jsx("span", { className: "flex h-7 w-6 shrink-0 items-center justify-center", children: getStatusIcon(file.status, file.type) }), _jsxs("div", { className: "flex min-w-0 flex-col gap-1 py-1", children: [_jsx(Typography, { as: "p", variant: "label", className: cn("truncate", isComplete && "text-[hsl(var(--status-success-foreground))]"), title: file.name, children: file.name }), isError ? (_jsx(Typography, { as: "p", variant: "caption", className: "break-words text-xs leading-4 text-destructive", children: (_a = file.error) !== null && _a !== void 0 ? _a : "Upload failed" })) : null] }), sizeLabel ? (_jsx(Typography, { as: "span", variant: "bodySm", className: "col-start-3 mt-1.5 whitespace-nowrap text-xs leading-4 text-muted-foreground", children: sizeLabel })) : null, action ? (_jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", className: "col-start-4 h-7 w-7 shrink-0", disabled: disabled, onClick: (event) => {
|
|
41
43
|
event.stopPropagation();
|
|
42
44
|
if (action === "cancel") {
|
|
43
45
|
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
|
|
@@ -17,6 +17,8 @@ export interface FileUploadStatusToastProps {
|
|
|
17
17
|
className?: string;
|
|
18
18
|
onCancel?: (file: FileUploadStatusToastFile) => void;
|
|
19
19
|
onRemove?: (file: FileUploadStatusToastFile) => void;
|
|
20
|
+
/** Show remove actions when onRemove is provided. Does not hide cancel. */
|
|
21
|
+
showRemoveButton?: boolean;
|
|
20
22
|
onDismiss?: () => void;
|
|
21
23
|
}
|
|
22
24
|
export interface ShowFileUploadStatusToastOptions extends FileUploadStatusToastProps {
|
|
@@ -24,5 +26,5 @@ export interface ShowFileUploadStatusToastOptions extends FileUploadStatusToastP
|
|
|
24
26
|
duration?: number;
|
|
25
27
|
dismissible?: boolean;
|
|
26
28
|
}
|
|
27
|
-
export declare function FileUploadStatusToast({ files, uploadProgress, title, description, className, onCancel, onRemove, onDismiss, }: FileUploadStatusToastProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export declare function FileUploadStatusToast({ files, uploadProgress, title, description, className, onCancel, onRemove, showRemoveButton, onDismiss, }: FileUploadStatusToastProps): import("react/jsx-runtime").JSX.Element;
|
|
28
30
|
export declare function showFileUploadStatusToast({ id, duration, dismissible, onDismiss, ...props }: ShowFileUploadStatusToastOptions): string | number;
|
|
@@ -61,13 +61,13 @@ function getDefaultDescription(files) {
|
|
|
61
61
|
].filter(Boolean);
|
|
62
62
|
return parts.length > 0 ? parts.join(" / ") : undefined;
|
|
63
63
|
}
|
|
64
|
-
export function FileUploadStatusToast({ files, uploadProgress, title, description, className, onCancel, onRemove, onDismiss, }) {
|
|
64
|
+
export function FileUploadStatusToast({ files, uploadProgress, title, description, className, onCancel, onRemove, showRemoveButton = true, onDismiss, }) {
|
|
65
65
|
const normalizedFiles = normalizeFiles({ files, uploadProgress });
|
|
66
66
|
const resolvedTitle = title !== null && title !== void 0 ? title : getDefaultTitle(normalizedFiles);
|
|
67
67
|
const resolvedDescription = description !== null && description !== void 0 ? description : getDefaultDescription(normalizedFiles);
|
|
68
68
|
return (_jsxs("section", { className: cn("w-[min(40rem,calc(100vw-2rem))] overflow-hidden rounded-overlay border border-border bg-background text-foreground shadow-overlay", className), "aria-label": "File upload status", children: [_jsxs("div", { className: "flex items-start gap-3 border-b px-3 py-2.5", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(Typography, { as: "p", variant: "label", className: "truncate", children: resolvedTitle }), resolvedDescription ? (_jsx(Typography, { as: "p", variant: "caption", className: "mt-0.5 text-xs leading-4", children: resolvedDescription })) : null] }), onDismiss ? (_jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", className: "h-7 w-7 shrink-0", onClick: onDismiss, "aria-label": "Dismiss file upload status", children: _jsx(X, { "aria-hidden": "true" }) })) : null] }), _jsx("ul", { className: "max-h-80 space-y-2 overflow-y-auto p-2.5", children: normalizedFiles.map((file, index) => {
|
|
69
69
|
var _a;
|
|
70
|
-
return (_jsx(FileUploadStatusRow, { file: file, onCancel: onCancel ? () => onCancel(file) : undefined, onRemove: onRemove && (file.status === "complete" || file.status === "error")
|
|
70
|
+
return (_jsx(FileUploadStatusRow, { file: file, onCancel: onCancel ? () => onCancel(file) : undefined, onRemove: showRemoveButton && onRemove && (file.status === "complete" || file.status === "error")
|
|
71
71
|
? () => onRemove(file)
|
|
72
72
|
: undefined }, `${file.name}-${(_a = file.size) !== null && _a !== void 0 ? _a : "unknown"}-${index}`));
|
|
73
73
|
}) })] }));
|
package/dist/file-upload.d.ts
CHANGED
|
@@ -6,7 +6,9 @@ export interface FileUploadProps {
|
|
|
6
6
|
onFilesChange: (files: File[]) => void;
|
|
7
7
|
value?: File[];
|
|
8
8
|
disabled?: boolean;
|
|
9
|
+
/** Show the remove action on file rows. */
|
|
10
|
+
showRemoveButton?: boolean;
|
|
9
11
|
className?: string;
|
|
10
12
|
uploadProgress?: Map<string, FileUploadProgress>;
|
|
11
13
|
}
|
|
12
|
-
export declare function FileUpload({ accept, maxSize, maxFiles, onFilesChange, value, disabled, className, uploadProgress, }: FileUploadProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export declare function FileUpload({ accept, maxSize, maxFiles, onFilesChange, value, disabled, showRemoveButton, className, uploadProgress, }: FileUploadProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/file-upload.js
CHANGED
|
@@ -15,7 +15,7 @@ function formatFileSize(bytes) {
|
|
|
15
15
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
16
16
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i];
|
|
17
17
|
}
|
|
18
|
-
export function FileUpload({ accept, maxSize = DEFAULT_MAX_FILE_SIZE, maxFiles = 10, onFilesChange, value = [], disabled = false, className, uploadProgress, }) {
|
|
18
|
+
export function FileUpload({ accept, maxSize = DEFAULT_MAX_FILE_SIZE, maxFiles = 10, onFilesChange, value = [], disabled = false, showRemoveButton = true, className, uploadProgress, }) {
|
|
19
19
|
const [isDragOver, setIsDragOver] = useState(false);
|
|
20
20
|
const [error, setError] = useState(null);
|
|
21
21
|
const inputRef = React.useRef(null);
|
|
@@ -87,6 +87,6 @@ export function FileUpload({ accept, maxSize = DEFAULT_MAX_FILE_SIZE, maxFiles =
|
|
|
87
87
|
status: progress === null || progress === void 0 ? void 0 : progress.status,
|
|
88
88
|
progress: progress === null || progress === void 0 ? void 0 : progress.progress,
|
|
89
89
|
error: progress === null || progress === void 0 ? void 0 : progress.error,
|
|
90
|
-
}, disabled: disabled, onRemove: () => removeFile(index) }, `${file.name}-${file.size}-${index}`));
|
|
90
|
+
}, disabled: disabled, onRemove: showRemoveButton ? () => removeFile(index) : undefined }, `${file.name}-${file.size}-${index}`));
|
|
91
91
|
}) })) : null] }));
|
|
92
92
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export type { AvatarProps, AvatarSize, AvatarProfileProps, AvatarRootProps, } fr
|
|
|
3
3
|
export { AvatarProfilePopover, AvatarProfilePopoverContent, AvatarProfilePopoverHeader, AvatarProfilePopoverSection, AvatarProfilePopoverFooter, AvatarProfilePopoverFooterAction, } from "./avatar-profile-popover";
|
|
4
4
|
export type { AvatarProfilePopoverProps, AvatarProfilePopoverContentProps, AvatarProfilePopoverHeaderProps, AvatarProfilePopoverSectionProps, AvatarProfilePopoverFooterProps, AvatarProfilePopoverFooterActionProps, } from "./avatar-profile-popover";
|
|
5
5
|
export * from "./animated-icons";
|
|
6
|
+
export { Inline } from "./inline";
|
|
6
7
|
export { Alert, AlertAction, AlertConsent, alertVariants, } from "./alert";
|
|
7
8
|
export type { AlertActionProps, AlertConsentProps, AlertProps, } from "./alert";
|
|
8
9
|
export { AlertStack } from "./alert-stack";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { Avatar, AvatarProfile, AvatarRoot, AvatarImage, } from "./avatar";
|
|
2
2
|
export { AvatarProfilePopover, AvatarProfilePopoverContent, AvatarProfilePopoverHeader, AvatarProfilePopoverSection, AvatarProfilePopoverFooter, AvatarProfilePopoverFooterAction, } from "./avatar-profile-popover";
|
|
3
3
|
export * from "./animated-icons";
|
|
4
|
+
export { Inline } from "./inline";
|
|
4
5
|
export { Alert, AlertAction, AlertConsent, alertVariants, } from "./alert";
|
|
5
6
|
export { AlertStack } from "./alert-stack";
|
|
6
7
|
export { ActivityCard, ActivityCardActor, ActivityCardContent, } from "./activity-card";
|
package/dist/inline.d.ts
ADDED
package/dist/inline.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/** A compact horizontal group with design-system spacing. */
|
|
3
|
+
export function Inline({ children, ...props }) {
|
|
4
|
+
return _jsx("div", { ...props, "data-slot": "inline", className: "flex items-center gap-[var(--space-2)]", children: children });
|
|
5
|
+
}
|
package/dist/rich-text-editor.js
CHANGED
|
@@ -122,7 +122,7 @@ export function replaceTemplateVariables(content, context) {
|
|
|
122
122
|
return result;
|
|
123
123
|
}
|
|
124
124
|
function ToolbarIconButton({ active, label, onClick, children, }) {
|
|
125
|
-
return (_jsx(Button, { type: "button", variant: "ghost", size: "
|
|
125
|
+
return (_jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", className: cn(active && "bg-muted"), onClick: onClick, "aria-label": label, title: label, children: children }));
|
|
126
126
|
}
|
|
127
127
|
function getTemplateCategory(template) {
|
|
128
128
|
return template.category || DEFAULT_TEMPLATE_CATEGORY;
|
|
@@ -359,7 +359,7 @@ export function RichTextEditor({ variant = "default", placeholder = "Type messag
|
|
|
359
359
|
void handleSend();
|
|
360
360
|
}, children: [_jsx(SendIcon, { size: 16 }), isSending ? sendingLabel : sendLabel] }));
|
|
361
361
|
if (variant === "message") {
|
|
362
|
-
return (_jsxs("div", { "data-slot": "message-composer", ref: dropZoneRef, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, className: cn("box-border flex min-h-[
|
|
362
|
+
return (_jsxs("div", { "data-slot": "message-composer", ref: dropZoneRef, onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, className: cn("box-border flex min-h-[148px] flex-col overflow-hidden rounded-[8px] border border-input bg-background transition-all focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50", !isExpanded && attachments.length === 0 && "h-[148px]", isDragging && "border-2 border-primary bg-primary/5", className), children: [header ? (_jsx("div", { "data-slot": "message-composer-header", className: "flex min-h-[32px] items-center px-[10px] py-[4px] text-muted-foreground", children: _jsxs("div", { className: "flex min-w-0 items-center gap-[8px]", children: [_jsx(Reply, { "aria-hidden": "true", className: "size-[16px] shrink-0" }), _jsx(Typography, { as: "span", variant: "caption", className: "min-w-0 truncate font-medium text-muted-foreground", "data-slot": "message-composer-header-label", children: header })] }) })) : null, _jsx("div", { "data-slot": "message-composer-editor", className: cn("min-h-[64px]", isExpanded && "min-h-[200px]"), children: _jsx(EditorContent, { editor: editor, className: cn("min-h-[64px] text-sm", isExpanded && "min-h-[200px]", "[&_.ProseMirror]:min-h-[64px] [&_.ProseMirror]:outline-none", isExpanded && "[&_.ProseMirror]:min-h-[200px]", "[&_.ProseMirror_p.is-editor-empty:first-child::before]:float-left", "[&_.ProseMirror_p.is-editor-empty:first-child::before]:h-0", "[&_.ProseMirror_p.is-editor-empty:first-child::before]:pointer-events-none", "[&_.ProseMirror_p.is-editor-empty:first-child::before]:text-muted-foreground", "[&_.ProseMirror_p.is-editor-empty:first-child::before]:content-[attr(data-placeholder)]") }) }), attachments.length > 0 ? (_jsx("div", { className: "space-y-[8px] px-[10px] pb-[8px]", children: attachments.map((attachment, index) => (_jsxs("div", { className: "flex w-full items-center gap-[8px] rounded-md border bg-muted px-[12px] py-[8px] text-sm", children: [_jsx(PaperclipIcon, { size: 14, className: "shrink-0 text-muted-foreground" }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: attachment.name }), _jsx("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatFileSize(attachment.size) }), _jsx("button", { type: "button", onClick: () => removeAttachment(index), className: "shrink-0 text-muted-foreground hover:text-foreground", "aria-label": `Remove ${attachment.name}`, children: _jsx(XIcon, { size: 14 }) })] }, `${attachment.name}-${attachment.size}-${index}`))) })) : null, _jsx("input", { ref: fileInputRef, type: "file", accept: acceptedFileTypes, multiple: true, onChange: handleFileSelect, className: "hidden" }), linkPopoverOpen &&
|
|
363
363
|
linkMenuPosition &&
|
|
364
364
|
typeof document !== "undefined" &&
|
|
365
365
|
createPortal(_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-[99]", onClick: () => {
|
|
@@ -370,7 +370,7 @@ export function RichTextEditor({ variant = "default", placeholder = "Type messag
|
|
|
370
370
|
} }), _jsx("div", { ref: linkMenuRef, className: "fixed z-[100] w-80 animate-in fade-in-0 zoom-in-95 rounded-md border bg-popover p-3 shadow-md", style: {
|
|
371
371
|
top: linkMenuPosition.top,
|
|
372
372
|
left: linkMenuPosition.left,
|
|
373
|
-
}, children: _jsxs("div", { className: "flex items-end gap-2", children: [_jsx(Input, { ref: linkInputRef, label: "URL", id: "message-link-url", type: "url", placeholder: "https://example.com", value: linkUrl, onChange: (event) => setLinkUrl(event.target.value), onKeyDown: handleLinkKeyDown, inputClassName: "h-8 text-sm", autoFocus: true }), _jsx(Button, { type: "button", className: "h-8 px-3", onClick: handleLinkSubmit, disabled: !linkUrl.trim(), children: "Add" })] }) })] }), document.body), isFormattingOpen ? (_jsxs("div", { className: "flex flex-wrap items-center gap-[4px] border-t border-border px-[10px] py-[8px]", children: [_jsx(ToolbarIconButton, { label: "Bold", active: editor === null || editor === void 0 ? void 0 : editor.isActive("bold"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleBold().run(), children: _jsx(BoldIcon, { size: 14 }) }), _jsx(ToolbarIconButton, { label: "Italic", active: editor === null || editor === void 0 ? void 0 : editor.isActive("italic"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleItalic().run(), children: _jsx(ItalicIcon, { size: 14 }) }), _jsx(ToolbarIconButton, { label: "Underline", active: editor === null || editor === void 0 ? void 0 : editor.isActive("underline"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleUnderline().run(), children: _jsx(UnderlineIcon, { size: 14 }) }), _jsx(ToolbarIconButton, { label: "Bullet list", active: editor === null || editor === void 0 ? void 0 : editor.isActive("bulletList"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleBulletList().run(), children: _jsx(ListIcon, { size: 14 }) }), _jsx(ToolbarIconButton, { label: "Ordered list", active: editor === null || editor === void 0 ? void 0 : editor.isActive("orderedList"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleOrderedList().run(), children: _jsx(ListOrderedIcon, { size: 14 }) })] })) : null, _jsxs("div", { "data-slot": "message-composer-toolbar", className: "flex min-h-[52px] items-center justify-between px-[10px] py-[8px]", children: [_jsxs("div", { className: "flex items-center gap-[8px]", children: [_jsx(Tooltip, { content: `Attach files (max ${maxFileSizeLabel}) - ${acceptedFileTypesLabel}`, side: "top", contentClassName: "max-w-[240px] text-center", children: _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon",
|
|
373
|
+
}, children: _jsxs("div", { className: "flex items-end gap-2", children: [_jsx(Input, { ref: linkInputRef, label: "URL", id: "message-link-url", type: "url", placeholder: "https://example.com", value: linkUrl, onChange: (event) => setLinkUrl(event.target.value), onKeyDown: handleLinkKeyDown, inputClassName: "h-8 text-sm", autoFocus: true }), _jsx(Button, { type: "button", className: "h-8 px-3", onClick: handleLinkSubmit, disabled: !linkUrl.trim(), children: "Add" })] }) })] }), document.body), isFormattingOpen ? (_jsxs("div", { className: "flex flex-wrap items-center gap-[4px] border-t border-border px-[10px] py-[8px]", children: [_jsx(ToolbarIconButton, { label: "Bold", active: editor === null || editor === void 0 ? void 0 : editor.isActive("bold"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleBold().run(), children: _jsx(BoldIcon, { size: 14 }) }), _jsx(ToolbarIconButton, { label: "Italic", active: editor === null || editor === void 0 ? void 0 : editor.isActive("italic"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleItalic().run(), children: _jsx(ItalicIcon, { size: 14 }) }), _jsx(ToolbarIconButton, { label: "Underline", active: editor === null || editor === void 0 ? void 0 : editor.isActive("underline"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleUnderline().run(), children: _jsx(UnderlineIcon, { size: 14 }) }), _jsx(ToolbarIconButton, { label: "Bullet list", active: editor === null || editor === void 0 ? void 0 : editor.isActive("bulletList"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleBulletList().run(), children: _jsx(ListIcon, { size: 14 }) }), _jsx(ToolbarIconButton, { label: "Ordered list", active: editor === null || editor === void 0 ? void 0 : editor.isActive("orderedList"), onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleOrderedList().run(), children: _jsx(ListOrderedIcon, { size: 14 }) })] })) : null, _jsxs("div", { "data-slot": "message-composer-toolbar", className: "flex min-h-[52px] items-center justify-between px-[10px] py-[8px]", children: [_jsxs("div", { className: "flex items-center gap-[8px]", children: [_jsx(Tooltip, { content: `Attach files (max ${maxFileSizeLabel}) - ${acceptedFileTypesLabel}`, side: "top", contentClassName: "max-w-[240px] text-center", children: _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, "aria-label": "Attach files", children: _jsx(PaperclipIcon, { size: 16 }) }) }), _jsxs("div", { className: "inline-flex h-[32px] overflow-hidden rounded-control border border-input bg-background", children: [_jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", className: "rounded-none border-r border-input", onClick: () => editor === null || editor === void 0 ? void 0 : editor.chain().focus().toggleBold().run(), "aria-pressed": (_a = editor === null || editor === void 0 ? void 0 : editor.isActive("bold")) !== null && _a !== void 0 ? _a : false, "aria-label": "Bold", children: _jsx(BoldIcon, { size: 16 }) }), _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", className: "rounded-none border-r border-input", onClick: openLinkMenu, "aria-label": "Add link", children: _jsx(LinkIcon, { size: 16 }) }), _jsx(Button, { type: "button", variant: "ghost", size: "compactIcon", className: "rounded-none", onClick: () => setIsFormattingOpen((open) => !open), "aria-expanded": isFormattingOpen, "aria-label": "Formatting options", children: _jsx(Baseline, { "aria-hidden": "true", className: "size-[16px]" }) })] })] }), _jsxs("div", { className: "flex items-center gap-[8px]", children: [showTemplates && (templates.length > 0 || templateCreateHref) ? (_jsxs(Popover, { open: templatePopoverOpen, onOpenChange: setTemplatePopoverOpen, align: "end", contentClassName: "w-96 p-0", trigger: _jsxs(Button, { type: "button", variant: "outline", size: "sm", children: ["Templates", _jsx(ChevronDownIcon, { size: 16 })] }), children: [_jsx("div", { className: "max-h-80 overflow-y-auto", children: templatesByCategory.map(({ category, templates }) => {
|
|
374
374
|
var _a;
|
|
375
375
|
return (_jsxs("div", { children: [_jsx("div", { className: "sticky top-0 bg-muted px-3 py-2 text-sm font-semibold text-foreground", children: (_a = templateCategoryLabels[category]) !== null && _a !== void 0 ? _a : category }), templates.map((template) => (_jsxs("button", { type: "button", className: "w-full border-b border-border/50 px-3 py-2 text-left text-sm transition-colors last:border-0 hover:bg-muted", onClick: () => applyTemplate(template), children: [_jsx("div", { className: "truncate font-medium", children: template.name }), template.description ? (_jsx("div", { className: "mt-0.5 truncate text-xs text-muted-foreground", children: template.description })) : null] }, template.id)))] }, category));
|
|
376
376
|
}) }), templateCreateHref ? (_jsx("div", { className: "border-t p-2", children: _jsxs("a", { href: templateCreateHref, target: "_blank", rel: "noopener noreferrer", className: "flex w-full items-center justify-center gap-1.5 rounded-md px-3 py-2 text-sm text-interactive transition-colors hover:bg-muted", children: [_jsx(PlusIcon, { size: 16 }), templateCreateLabel] }) })) : null] })) : null, renderSendAction({ compact: true })] })] })] }));
|
|
@@ -16,6 +16,8 @@ export interface RoutingActionPanelProps extends Omit<DashboardActionPanelProps,
|
|
|
16
16
|
onRouteValueChange?: (value: string) => void;
|
|
17
17
|
/** Workflow-specific fields rendered before the route target. */
|
|
18
18
|
supplementaryFields?: React.ReactNode;
|
|
19
|
+
/** Read-only review context in the scrollable body, above routing activity. */
|
|
20
|
+
context?: React.ReactNode;
|
|
19
21
|
remarks: string;
|
|
20
22
|
remarksDescription?: React.ReactNode;
|
|
21
23
|
remarksPlaceholder?: string;
|
|
@@ -34,5 +36,5 @@ export interface RoutingActionPanelProps extends Omit<DashboardActionPanelProps,
|
|
|
34
36
|
* Consumers provide workflow data and actions; the component owns the complete
|
|
35
37
|
* visual composition so different records render routing consistently.
|
|
36
38
|
*/
|
|
37
|
-
declare function RoutingActionPanel({ items, isLoading, loadingLabel, emptyMessage, emptyDescription, routeOptions, routeValue, routePlaceholder, routeDescription, routeDisabled, onRouteValueChange, supplementaryFields, remarks, remarksDescription, remarksPlaceholder, remarksRequired, remarksRows, validationMessages, onRemarksChange, submitLabel, submitDisabled, submitLoading, onSubmit, ...panelProps }: RoutingActionPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
declare function RoutingActionPanel({ items, isLoading, loadingLabel, emptyMessage, emptyDescription, routeOptions, routeValue, routePlaceholder, routeDescription, routeDisabled, onRouteValueChange, supplementaryFields, context, remarks, remarksDescription, remarksPlaceholder, remarksRequired, remarksRows, validationMessages, onRemarksChange, submitLabel, submitDisabled, submitLoading, onSubmit, ...panelProps }: RoutingActionPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
38
40
|
export { RoutingActionPanel };
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Route } from "lucide-react";
|
|
4
4
|
import { Button } from "./button";
|
|
5
|
+
import { EmptyState } from "./empty-state";
|
|
5
6
|
import { DashboardActionPanel, DashboardActionPanelEmptyState, DashboardRightPanelBody, } from "./layout";
|
|
6
7
|
import { RoutingTimeline, } from "./routing-timeline";
|
|
7
8
|
import { Select } from "./select";
|
|
@@ -12,8 +13,9 @@ import { Textarea } from "./textarea";
|
|
|
12
13
|
* Consumers provide workflow data and actions; the component owns the complete
|
|
13
14
|
* visual composition so different records render routing consistently.
|
|
14
15
|
*/
|
|
15
|
-
function RoutingActionPanel({ items, isLoading = false, loadingLabel = "Loading routing activity", emptyMessage = "No routing activity yet", emptyDescription = "Workflow routes will appear here.", routeOptions, routeValue, routePlaceholder = "Select Officer Role", routeDescription, routeDisabled = false, onRouteValueChange, supplementaryFields, remarks, remarksDescription, remarksPlaceholder = "Type remarks", remarksRequired = false, remarksRows = 2, validationMessages = [], onRemarksChange, submitLabel = "Route", submitDisabled = false, submitLoading = false, onSubmit, ...panelProps }) {
|
|
16
|
-
const
|
|
17
|
-
|
|
16
|
+
function RoutingActionPanel({ items, isLoading = false, loadingLabel = "Loading routing activity", emptyMessage = "No routing activity yet", emptyDescription = "Workflow routes will appear here.", routeOptions, routeValue, routePlaceholder = "Select Officer Role", routeDescription, routeDisabled = false, onRouteValueChange, supplementaryFields, context, remarks, remarksDescription, remarksPlaceholder = "Type remarks", remarksRequired = false, remarksRows = 2, validationMessages = [], onRemarksChange, submitLabel = "Route", submitDisabled = false, submitLoading = false, onSubmit, ...panelProps }) {
|
|
17
|
+
const RoutingEmptyState = context ? EmptyState : DashboardActionPanelEmptyState;
|
|
18
|
+
const footer = (_jsxs("div", { "data-slot": "routing-action-panel-form", className: "grid gap-[var(--space-4)]", children: [supplementaryFields, _jsx(Select, { label: "Route To", options: routeOptions, value: routeValue, placeholder: routePlaceholder, disabled: routeDisabled || submitLoading, description: routeDescription, onValueChange: onRouteValueChange }), _jsx(Textarea, { label: "Remarks", value: remarks, onChange: (event) => onRemarksChange(event.target.value), placeholder: remarksPlaceholder, description: remarksDescription, disabled: routeDisabled || submitLoading, required: remarksRequired, rows: remarksRows }), validationMessages.length > 0 ? (_jsxs("details", { className: "text-sm text-muted-foreground", children: [_jsxs("summary", { className: "cursor-pointer font-medium text-foreground", children: [validationMessages.length, " required ", validationMessages.length === 1 ? "item" : "items", " remaining \u2014 view details"] }), _jsx("ul", { className: "mt-2 max-h-40 list-disc space-y-1 overflow-y-auto pl-5", children: validationMessages.map((message, index) => _jsx("li", { children: message }, index)) })] })) : null, _jsx("div", { className: "flex justify-end", children: _jsxs(Button, { type: "button", size: "default", disabled: routeDisabled || submitDisabled || validationMessages.length > 0, loading: submitLoading, loadingText: submitLabel, onClick: onSubmit, children: [_jsx(Route, { "aria-hidden": "true", className: "size-4" }), submitLabel] }) })] }));
|
|
19
|
+
return (_jsx(DashboardActionPanel, { headerSpacing: "comfortable", ...panelProps, children: _jsxs(DashboardRightPanelBody, { spacing: "comfortable", topInset: "none", footerVariant: "separated", footer: footer, children: [context ? (_jsx("div", { "data-slot": "routing-action-panel-context", className: "mb-[var(--space-4)] grid min-w-0 gap-[var(--space-3)] whitespace-pre-wrap [overflow-wrap:anywhere]", children: context })) : null, isLoading ? (_jsx("div", { "data-slot": "routing-action-panel-loading", className: context ? "flex items-center justify-center py-[var(--space-4)]" : "absolute inset-0 flex items-center justify-center", children: _jsx(Spinner, { size: "md", label: loadingLabel }) })) : items.length === 0 ? (_jsx(RoutingEmptyState, { icon: Route, message: emptyMessage, description: emptyDescription })) : (_jsx(RoutingTimeline, { density: "compact", items: items }))] }) }));
|
|
18
20
|
}
|
|
19
21
|
export { RoutingActionPanel };
|
package/dist/routing-timeline.js
CHANGED
|
@@ -87,7 +87,7 @@ function RoutingTimeline({ items, emptyMessage = "No routing activity yet.", den
|
|
|
87
87
|
? "gap-[var(--space-3)]"
|
|
88
88
|
: "gap-[24px]"), children: [item.from ? (_jsx(RoutingTimelineHandoffEndpoint, { value: item.from, label: item.fromLabel })) : null, item.from && item.to ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "sr-only", children: "to" }), _jsx(ArrowRight, { "aria-hidden": "true", "data-slot": "routing-timeline-handoff-arrow", className: cn("shrink-0 text-foreground", density === "compact" ? "size-4" : "size-6") })] })) : null, item.to ? (_jsx(RoutingTimelineHandoffEndpoint, { value: item.to, label: item.toLabel })) : null] })) : null, remark ? (_jsxs("div", { "data-slot": "routing-timeline-remark", className: cn("bg-muted", density === "compact"
|
|
89
89
|
? "rounded-control p-[var(--space-2)]"
|
|
90
|
-
: "rounded-md p-[12px]"), children: [detailLabel ? (_jsx(Typography, { as: "p", variant: "bodySm", className: "font-semibold text-instructional", children: detailLabel })) : null, _jsx(Typography, { as: "div", variant: "bodySm", className: cn(detailLabel &&
|
|
90
|
+
: "rounded-md p-[12px]"), children: [detailLabel ? (_jsx(Typography, { as: "p", variant: "bodySm", className: "font-semibold text-instructional", children: detailLabel })) : null, _jsx(Typography, { as: "div", variant: "bodySm", className: cn("whitespace-pre-wrap [overflow-wrap:anywhere]", detailLabel &&
|
|
91
91
|
(density === "compact"
|
|
92
92
|
? "mt-[var(--space-1)]"
|
|
93
93
|
: "mt-[4px]")), children: remark })] })) : null] })) : null }) }, item.id));
|
package/dist/table.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<
|
|
|
29
29
|
wrap?: boolean;
|
|
30
30
|
treatWidthAsMinWidth?: boolean;
|
|
31
31
|
containOverflow?: boolean;
|
|
32
|
+
preserveButtonPadding?: boolean;
|
|
32
33
|
} & React.RefAttributes<HTMLTableCellElement>>;
|
|
33
34
|
declare const TableRowHeader: React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & {
|
|
34
35
|
width?: string;
|
|
@@ -93,6 +94,8 @@ export interface TableColumn<Row> {
|
|
|
93
94
|
skeleton?: TableSkeletonConfig;
|
|
94
95
|
headerClassName?: string;
|
|
95
96
|
cellClassName?: string;
|
|
97
|
+
/** Keeps each design-system button's own horizontal padding in body cells. */
|
|
98
|
+
preserveButtonPadding?: boolean;
|
|
96
99
|
/** Renders this column's body cells as semantic row headers. */
|
|
97
100
|
rowHeader?: boolean;
|
|
98
101
|
/** Pins the column to the left or right edge while the table scrolls horizontally. */
|
package/dist/table.js
CHANGED
|
@@ -171,7 +171,8 @@ const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidt
|
|
|
171
171
|
treatWidthAsMinWidth,
|
|
172
172
|
}), ...props })));
|
|
173
173
|
TableHead.displayName = "TableHead";
|
|
174
|
-
const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("td", { ref: ref, className: cn("h-12 px-4 py-[4px] align-middle text-card-foreground [&:has([role=checkbox])]:pr-0
|
|
174
|
+
const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, preserveButtonPadding = false, ...props }, ref) => (_jsx("td", { ref: ref, className: cn("h-12 px-4 py-[4px] align-middle text-card-foreground [&:has([role=checkbox])]:pr-0", !preserveButtonPadding &&
|
|
175
|
+
"[&:not([data-slot=table-empty-cell])_[data-slot=button]]:px-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
|
|
175
176
|
style,
|
|
176
177
|
width,
|
|
177
178
|
minWidth,
|
|
@@ -742,7 +743,7 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(T
|
|
|
742
743
|
const Cell = column.rowHeader
|
|
743
744
|
? TableRowHeader
|
|
744
745
|
: TableCell;
|
|
745
|
-
return (_jsx(Cell, { width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), wrap: column.wrap, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn(alignClassName(column.align), stickyClassName(column.sticky, "cell", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.cellClassName), children: value }, column.key));
|
|
746
|
+
return (_jsx(Cell, { width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), wrap: column.wrap, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, preserveButtonPadding: column.preserveButtonPadding, className: cn(alignClassName(column.align), stickyClassName(column.sticky, "cell", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.cellClassName), children: value }, column.key));
|
|
746
747
|
})] }), isExpanded ? (_jsx(TableRow, { id: expandedContentId, "data-slot": "table-expanded-row", className: "bg-[hsl(var(--table-row-striped-background))] hover:bg-[hsl(var(--table-row-striped-background))]", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
|
|
747
748
|
(hasRowIndicatorColumn ? 1 : 0) +
|
|
748
749
|
(hasExpansionColumn ? 1 : 0), 1), className: "h-auto whitespace-normal p-4", children: rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.renderExpandedContent(row, rowIndex) }) })) : null] }, rowKey));
|
package/dist/typography.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface TypographyProps extends React.HTMLAttributes<HTMLElement>, Vari
|
|
|
7
7
|
as?: keyof React.JSX.IntrinsicElements;
|
|
8
8
|
asChild?: boolean;
|
|
9
9
|
/** Override the built-in text colour. Use "inherit" to inherit from a parent container. */
|
|
10
|
-
color?: "inherit" | "foreground" | "muted";
|
|
10
|
+
color?: "inherit" | "foreground" | "muted" | "primary";
|
|
11
11
|
}
|
|
12
12
|
declare const Typography: React.ForwardRefExoticComponent<TypographyProps & React.RefAttributes<HTMLElement>>;
|
|
13
13
|
export { Typography, typographyVariants };
|
package/dist/typography.js
CHANGED
|
@@ -39,9 +39,11 @@ const Typography = React.forwardRef(({ as, asChild = false, className, variant,
|
|
|
39
39
|
? "text-inherit"
|
|
40
40
|
: color === "foreground"
|
|
41
41
|
? "text-foreground"
|
|
42
|
-
: color === "
|
|
43
|
-
? "text-
|
|
44
|
-
:
|
|
42
|
+
: color === "primary"
|
|
43
|
+
? "text-primary"
|
|
44
|
+
: color === "muted"
|
|
45
|
+
? "text-instructional"
|
|
46
|
+
: undefined;
|
|
45
47
|
return (_jsx(Comp, { ref: ref, className: cn(typographyVariants({ variant: resolvedVariant }), colorClass, className), ...props }));
|
|
46
48
|
});
|
|
47
49
|
Typography.displayName = "Typography";
|