@pilotiq/pilotiq 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +8 -0
- package/CLAUDE.md +1 -1
- package/dist/actions/Action.d.ts +25 -0
- package/dist/actions/Action.d.ts.map +1 -1
- package/dist/actions/Action.js +25 -0
- package/dist/actions/Action.js.map +1 -1
- package/dist/elements/dispatchForm.d.ts +0 -14
- package/dist/elements/dispatchForm.d.ts.map +1 -1
- package/dist/elements/dispatchForm.js +28 -0
- package/dist/elements/dispatchForm.js.map +1 -1
- package/dist/fields/BuilderField.d.ts +27 -1
- package/dist/fields/BuilderField.d.ts.map +1 -1
- package/dist/fields/BuilderField.js +36 -1
- package/dist/fields/BuilderField.js.map +1 -1
- package/dist/fields/FileUploadField.d.ts +65 -0
- package/dist/fields/FileUploadField.d.ts.map +1 -1
- package/dist/fields/FileUploadField.js +72 -0
- package/dist/fields/FileUploadField.js.map +1 -1
- package/dist/fields/RepeaterField.d.ts +34 -1
- package/dist/fields/RepeaterField.d.ts.map +1 -1
- package/dist/fields/RepeaterField.js +43 -1
- package/dist/fields/RepeaterField.js.map +1 -1
- package/dist/fields/RowButton.d.ts +9 -2
- package/dist/fields/RowButton.d.ts.map +1 -1
- package/dist/fields/TextField.d.ts +106 -0
- package/dist/fields/TextField.d.ts.map +1 -1
- package/dist/fields/TextField.js +115 -0
- package/dist/fields/TextField.js.map +1 -1
- package/dist/filters/queryBuilder/Constraint.d.ts +1 -1
- package/dist/filters/queryBuilder/Constraint.d.ts.map +1 -1
- package/dist/filters/queryBuilder/TextConstraint.d.ts.map +1 -1
- package/dist/filters/queryBuilder/TextConstraint.js +2 -3
- package/dist/filters/queryBuilder/TextConstraint.js.map +1 -1
- package/dist/orm/modelDefaults.d.ts +1 -1
- package/dist/orm/modelDefaults.d.ts.map +1 -1
- package/dist/react/SchemaRenderer.d.ts.map +1 -1
- package/dist/react/SchemaRenderer.js +108 -7
- package/dist/react/SchemaRenderer.js.map +1 -1
- package/dist/react/fields/BuilderInput.d.ts.map +1 -1
- package/dist/react/fields/BuilderInput.js +32 -3
- package/dist/react/fields/BuilderInput.js.map +1 -1
- package/dist/react/fields/FieldShell.d.ts +9 -1
- package/dist/react/fields/FieldShell.d.ts.map +1 -1
- package/dist/react/fields/FieldShell.js +4 -3
- package/dist/react/fields/FieldShell.js.map +1 -1
- package/dist/react/fields/FileUploadInput.d.ts +17 -4
- package/dist/react/fields/FileUploadInput.d.ts.map +1 -1
- package/dist/react/fields/FileUploadInput.js +204 -25
- package/dist/react/fields/FileUploadInput.js.map +1 -1
- package/dist/react/fields/RepeaterInput.d.ts.map +1 -1
- package/dist/react/fields/RepeaterInput.js +33 -2
- package/dist/react/fields/RepeaterInput.js.map +1 -1
- package/dist/react/fields/TextLikeInput.d.ts +5 -1
- package/dist/react/fields/TextLikeInput.d.ts.map +1 -1
- package/dist/react/fields/TextLikeInput.js +17 -2
- package/dist/react/fields/TextLikeInput.js.map +1 -1
- package/dist/react/fields/rowChromeButton.d.ts +24 -5
- package/dist/react/fields/rowChromeButton.d.ts.map +1 -1
- package/dist/react/fields/rowChromeButton.js +51 -8
- package/dist/react/fields/rowChromeButton.js.map +1 -1
- package/dist/react/fields/textInputControls.d.ts +47 -0
- package/dist/react/fields/textInputControls.d.ts.map +1 -0
- package/dist/react/fields/textInputControls.js +134 -0
- package/dist/react/fields/textInputControls.js.map +1 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +21 -1
- package/dist/routes.js.map +1 -1
- package/dist/schema/Alert.d.ts +58 -0
- package/dist/schema/Alert.d.ts.map +1 -1
- package/dist/schema/Alert.js +68 -1
- package/dist/schema/Alert.js.map +1 -1
- package/dist/schema/resolveSchema.d.ts.map +1 -1
- package/dist/schema/resolveSchema.js +32 -0
- package/dist/schema/resolveSchema.js.map +1 -1
- package/package.json +2 -1
- package/src/actions/Action.test.ts +47 -0
- package/src/actions/Action.ts +35 -0
- package/src/elements/dispatchForm.ts +28 -0
- package/src/fields/BuilderField.ts +38 -1
- package/src/fields/FileUploadField.test.ts +46 -0
- package/src/fields/FileUploadField.ts +90 -2
- package/src/fields/RepeaterField.ts +45 -1
- package/src/fields/RowButton.test.ts +70 -0
- package/src/fields/RowButton.ts +11 -1
- package/src/fields/TextField.test.ts +168 -0
- package/src/fields/TextField.ts +141 -1
- package/src/filters/QueryBuilderFilter.test.ts +18 -0
- package/src/filters/queryBuilder/Constraint.ts +1 -1
- package/src/filters/queryBuilder/TextConstraint.ts +5 -6
- package/src/orm/modelDefaults.ts +1 -1
- package/src/react/SchemaRenderer.tsx +222 -14
- package/src/react/fields/BuilderInput.tsx +37 -0
- package/src/react/fields/FieldShell.tsx +13 -2
- package/src/react/fields/FileUploadInput.tsx +516 -85
- package/src/react/fields/RepeaterInput.tsx +39 -0
- package/src/react/fields/TextLikeInput.tsx +22 -2
- package/src/react/fields/rowChromeButton.tsx +102 -6
- package/src/react/fields/textInputControls.tsx +238 -0
- package/src/routes.ts +21 -1
- package/src/schema/Alert.test.ts +46 -0
- package/src/schema/Alert.ts +90 -8
- package/src/schema/resolveSchema.ts +32 -0
|
@@ -7,6 +7,7 @@ import { Input } from './ui/input.js';
|
|
|
7
7
|
import { Popover, PopoverTrigger, PopoverContent } from './ui/popover.js';
|
|
8
8
|
import { FieldShell } from './fields/FieldShell.js';
|
|
9
9
|
import { TextLikeInput } from './fields/TextLikeInput.js';
|
|
10
|
+
import { useTextInputControls } from './fields/textInputControls.js';
|
|
10
11
|
import { SelectFieldInput } from './fields/SelectFieldInput.js';
|
|
11
12
|
import { ToggleFieldInput } from './fields/ToggleFieldInput.js';
|
|
12
13
|
import { DateFieldInput } from './fields/DateFieldInput.js';
|
|
@@ -30,7 +31,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '
|
|
|
30
31
|
import { Table as DataTable, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from './ui/table.js';
|
|
31
32
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from './ui/dropdown-menu.js';
|
|
32
33
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from './ui/tooltip.js';
|
|
33
|
-
import { FilterIcon, CircleIcon, InboxIcon, GripVerticalIcon, ChevronDownIcon, CopyIcon, CheckIcon, XIcon, } from 'lucide-react';
|
|
34
|
+
import { FilterIcon, CircleIcon, InboxIcon, GripVerticalIcon, ChevronDownIcon, CopyIcon, CheckIcon, XIcon, InfoIcon, TriangleAlertIcon, CircleCheckIcon, CircleAlertIcon, } from 'lucide-react';
|
|
34
35
|
import { useNavigate } from './navigate.js';
|
|
35
36
|
import { parseDateRangeValue, encodeDateRangeValue, } from '../filters/DateRangeFilter.js';
|
|
36
37
|
import { parseMultiSelectValue, encodeMultiSelectValue, } from '../filters/MultiSelectFilter.js';
|
|
@@ -106,9 +107,39 @@ function renderField(el, index) {
|
|
|
106
107
|
if (Custom) {
|
|
107
108
|
return (_jsx(FieldShell, { el: el, name: name, label: label, required: required, children: _jsx(Custom, { el: el, name: name, defaultValue: defaultValue, required: required, disabled: disabled, placeholder: placeholder }) }, index));
|
|
108
109
|
}
|
|
110
|
+
// TextField (and slug) rich affordances live in a dedicated shell so
|
|
111
|
+
// `useTextInputControls` can hold reveal-toggle / mask state via React
|
|
112
|
+
// hooks (renderField itself is a plain function, hooks would violate
|
|
113
|
+
// rules-of-hooks here).
|
|
114
|
+
if (fieldType === 'text' || fieldType === 'slug') {
|
|
115
|
+
return (_jsx(TextFieldShell, { el: el, name: name, label: label, required: required, common: common }, index));
|
|
116
|
+
}
|
|
109
117
|
const input = renderFieldInput(fieldType, el, name, defaultValue, defaultStr, common, disabled, required, placeholder);
|
|
110
118
|
return (_jsx(FieldShell, { el: el, name: name, label: label, required: required, children: input }, index));
|
|
111
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Component-shape TextField renderer — wraps the input shell so we can
|
|
122
|
+
* use `useTextInputControls()` (which holds the eye-toggle / mask state).
|
|
123
|
+
* Keeps `renderField` itself hook-free.
|
|
124
|
+
*/
|
|
125
|
+
function TextFieldShell({ el, name, label, required, common, }) {
|
|
126
|
+
const controls = useTextInputControls(el, name, (m) => renderElement(m, 0));
|
|
127
|
+
// Build the input with all the new HTML attrs (inputMode /
|
|
128
|
+
// autocapitalize / list / maxLength + the password/text type from
|
|
129
|
+
// the controls hook).
|
|
130
|
+
const textExtra = {};
|
|
131
|
+
if (el['maxLength'] !== undefined)
|
|
132
|
+
textExtra['maxLength'] = Number(el['maxLength']);
|
|
133
|
+
if (el['inputMode'] !== undefined)
|
|
134
|
+
textExtra['inputMode'] = String(el['inputMode']);
|
|
135
|
+
if (el['autocapitalize'] !== undefined)
|
|
136
|
+
textExtra['autoCapitalize'] = String(el['autocapitalize']);
|
|
137
|
+
if (Array.isArray(el['datalist']))
|
|
138
|
+
textExtra['list'] = `${name}__datalist`;
|
|
139
|
+
const datalist = Array.isArray(el['datalist']) ? el['datalist'] : undefined;
|
|
140
|
+
const input = (_jsxs(_Fragment, { children: [_jsx(TextLikeInput, { el: el, name: name, common: common, type: controls.type, extraProps: textExtra, multiline: false, applyMask: controls.applyMask }), datalist && (_jsx("datalist", { id: `${name}__datalist`, children: datalist.map((v, i) => _jsx("option", { value: v }, i)) }))] }));
|
|
141
|
+
return (_jsx(FieldShell, { el: el, name: name, label: label, required: required, before: controls.before, after: controls.after, children: input }));
|
|
142
|
+
}
|
|
112
143
|
function renderFieldInput(fieldType, el, name, defaultValue, defaultStr, common, disabled, required, placeholder) {
|
|
113
144
|
switch (fieldType) {
|
|
114
145
|
case 'textarea': {
|
|
@@ -178,7 +209,13 @@ function renderFieldInput(fieldType, el, name, defaultValue, defaultStr, common,
|
|
|
178
209
|
return (_jsx(TagsInput, { name: name, defaultValue: defaultValue, disabled: disabled, placeholder: placeholder, suggestions: suggestions, separator: separator, splitKeys: splitKeys, maxTags: maxTags, reorderable: reorderable }));
|
|
179
210
|
}
|
|
180
211
|
case 'fileUpload': {
|
|
181
|
-
return (_jsx(FileUploadInput, { name: name, defaultValue: defaultValue, disabled: disabled, accept: el['accept'], maxSize: typeof el['maxSize'] === 'number' ? el['maxSize'] : undefined, multiple: Boolean(el['multiple']), preview: el['preview'] !== false, directory: typeof el['directory'] === 'string' ? el['directory'] : undefined, uploadUrl: typeof el['uploadUrl'] === 'string' ? el['uploadUrl'] : undefined
|
|
212
|
+
return (_jsx(FileUploadInput, { name: name, defaultValue: defaultValue, disabled: disabled, accept: el['accept'], maxSize: typeof el['maxSize'] === 'number' ? el['maxSize'] : undefined, multiple: Boolean(el['multiple']), preview: el['preview'] !== false, directory: typeof el['directory'] === 'string' ? el['directory'] : undefined, uploadUrl: typeof el['uploadUrl'] === 'string' ? el['uploadUrl'] : undefined, downloadable: Boolean(el['downloadable']), openable: Boolean(el['openable']), reorderable: Boolean(el['reorderable']), appendFiles: Boolean(el['appendFiles']), panelLayout: el['panelLayout'] === 'grid' ? 'grid'
|
|
213
|
+
: el['panelLayout'] === 'integrated' ? 'integrated'
|
|
214
|
+
: 'list', ...(el['automaticallyResize'] && typeof el['automaticallyResize'] === 'object'
|
|
215
|
+
? { automaticallyResize: el['automaticallyResize'] }
|
|
216
|
+
: {}), imageEditor: Boolean(el['imageEditor']), circleCropper: Boolean(el['circleCropper']), automaticallyCropImagesToAspectRatio: Boolean(el['automaticallyCropImagesToAspectRatio']), ...(Array.isArray(el['imageEditorAspectRatioOptions'])
|
|
217
|
+
? { imageEditorAspectRatioOptions: el['imageEditorAspectRatioOptions'] }
|
|
218
|
+
: {}) }));
|
|
182
219
|
}
|
|
183
220
|
case 'markdown': {
|
|
184
221
|
const toolbarButtons = el['toolbarButtons'] ?? [];
|
|
@@ -403,6 +440,9 @@ function ActionModalDialog({ trigger, meta, ids, initialValues = {}, open: contr
|
|
|
403
440
|
const dispatchUrl = meta['dispatchUrl'];
|
|
404
441
|
const fields = (meta.children ?? []);
|
|
405
442
|
const hasForm = fields.length > 0;
|
|
443
|
+
// Filament v5 — auxiliary Elements stamped by the resolver between
|
|
444
|
+
// the body and the footer (Alert / Text / Heading / Action / …).
|
|
445
|
+
const contentFooter = (meta['modalContentFooter'] ?? []);
|
|
406
446
|
const heading = modal?.heading ?? confirm?.title ?? (hasForm ? String(meta['label'] ?? 'Submit') : 'Are you sure?');
|
|
407
447
|
const description = modal?.description ?? confirm?.message;
|
|
408
448
|
const submitLabel = modal?.submitLabel ?? (destructive ? 'Delete' : (hasForm ? 'Submit' : 'Confirm'));
|
|
@@ -534,7 +574,7 @@ function ActionModalDialog({ trigger, meta, ids, initialValues = {}, open: contr
|
|
|
534
574
|
if (!o)
|
|
535
575
|
reset();
|
|
536
576
|
setOpen(o);
|
|
537
|
-
}, children: _jsxs(DialogContent, { className: popupClass, children: [showCloseButton && (_jsx("button", { type: "button", "aria-label": "Close", onClick: () => setOpen(false), className: "absolute top-3 right-3 z-20 inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground", children: _jsx(XIcon, { className: "size-4" }) })), _jsxs("form", { ref: formRef, onSubmit: onSubmit, className: formCls, children: [_jsxs(DialogHeader, { className: headerCls, children: [_jsxs(DialogTitle, { className: modal?.icon ? 'flex items-center gap-2' : undefined, children: [HeaderIcon && (_jsx(HeaderIcon, { "aria-hidden": true, className: `size-5 shrink-0 ${iconColorClass ?? ''}`.trim() })), _jsx("span", { children: heading })] }), description && _jsx(DialogDescription, { children: description })] }), hasForm && (
|
|
577
|
+
}, children: _jsxs(DialogContent, { className: popupClass, children: [showCloseButton && (_jsx("button", { type: "button", "aria-label": "Close", onClick: () => setOpen(false), className: "absolute top-3 right-3 z-20 inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground", children: _jsx(XIcon, { className: "size-4" }) })), _jsxs("form", { ref: formRef, onSubmit: onSubmit, className: formCls, children: [_jsxs(DialogHeader, { className: headerCls, children: [_jsxs(DialogTitle, { className: modal?.icon ? 'flex items-center gap-2' : undefined, children: [HeaderIcon && (_jsx(HeaderIcon, { "aria-hidden": true, className: `size-5 shrink-0 ${iconColorClass ?? ''}`.trim() })), _jsx("span", { children: heading })] }), description && _jsx(DialogDescription, { children: description })] }), (hasForm || contentFooter.length > 0) && (_jsxs("div", { className: `flex flex-col gap-3 py-2 ${bodyCls}`.trim(), children: [fields.map((f, i) => renderFormChild(f, i, initialValues, errors)), contentFooter.map((c, i) => renderElement(c, fields.length + i))] })), !hasForm && contentFooter.length === 0 && stickyMode && _jsx("div", { className: bodyCls }), serverError && (_jsx("p", { className: `py-2 text-sm text-destructive ${stickyMode ? 'px-6' : ''}`.trim(), children: serverError })), _jsxs(DialogFooter, { className: footerCls, children: [_jsx("button", { type: "button", onClick: () => setOpen(false), className: cancelClass, children: cancelLabel }), _jsx("button", { type: "submit", disabled: submitting, autoFocus: submitAutofocus, className: confirmClass, children: submitting ? 'Working…' : submitLabel })] })] })] }) })] }));
|
|
538
578
|
}
|
|
539
579
|
/**
|
|
540
580
|
* Confirm-style dialog wrapping an action's button. The trigger button is
|
|
@@ -1460,6 +1500,70 @@ function EntryCopyButton({ text, label }) {
|
|
|
1460
1500
|
};
|
|
1461
1501
|
return (_jsx("button", { type: "button", onClick: handleClick, "aria-label": label, title: label, className: "inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-muted", children: copied ? _jsx(CheckIcon, { className: "size-3.5" }) : _jsx(CopyIcon, { className: "size-3.5" }) }));
|
|
1462
1502
|
}
|
|
1503
|
+
// ─── Alert renderer ─────────────────────────────────────────
|
|
1504
|
+
//
|
|
1505
|
+
// Owns dismissal state (per-mount + optional localStorage persistence)
|
|
1506
|
+
// + icon dispatch + footer-actions alignment. Lifted out of the inline
|
|
1507
|
+
// `case 'alert'` branch when Alert gained `dismissible() / iconColor() /
|
|
1508
|
+
// footerActionsAlignment()` setters — those need component-local state
|
|
1509
|
+
// (the dismiss button, the persisted-dismissal hydration on mount), and
|
|
1510
|
+
// inlining the hooks under a switch arm is fragile.
|
|
1511
|
+
const ALERT_TYPE_ICONS = {
|
|
1512
|
+
info: InfoIcon,
|
|
1513
|
+
warning: TriangleAlertIcon,
|
|
1514
|
+
success: CircleCheckIcon,
|
|
1515
|
+
danger: CircleAlertIcon,
|
|
1516
|
+
};
|
|
1517
|
+
const ALERT_TYPE_DEFAULT_ICON_COLOR = {
|
|
1518
|
+
info: 'info',
|
|
1519
|
+
warning: 'warning',
|
|
1520
|
+
success: 'success',
|
|
1521
|
+
danger: 'destructive',
|
|
1522
|
+
};
|
|
1523
|
+
const ALERT_ACTIONS_ALIGNMENT = {
|
|
1524
|
+
start: 'justify-start',
|
|
1525
|
+
center: 'justify-center',
|
|
1526
|
+
end: 'justify-end',
|
|
1527
|
+
};
|
|
1528
|
+
function alertPersistKey(persistKey) {
|
|
1529
|
+
return `pilotiq.alert.${persistKey}`;
|
|
1530
|
+
}
|
|
1531
|
+
function AlertRenderer(props) {
|
|
1532
|
+
const { alertType, content, title, dismissible, persistDismissal, iconColor, actionsAlignment, footer, } = props;
|
|
1533
|
+
const [dismissed, setDismissed] = useState(false);
|
|
1534
|
+
// Hydrate persisted-dismissal on first paint. `useState(false)` keeps
|
|
1535
|
+
// SSR + first client paint identical (Hydration safe); the effect
|
|
1536
|
+
// flips to dismissed if localStorage has the flag set.
|
|
1537
|
+
useEffect(() => {
|
|
1538
|
+
if (!persistDismissal)
|
|
1539
|
+
return;
|
|
1540
|
+
if (typeof window === 'undefined')
|
|
1541
|
+
return;
|
|
1542
|
+
try {
|
|
1543
|
+
if (window.localStorage.getItem(alertPersistKey(persistDismissal)) === '1') {
|
|
1544
|
+
setDismissed(true);
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
catch { /* localStorage blocked (Safari ITP / SSR) — render visible */ }
|
|
1548
|
+
}, [persistDismissal]);
|
|
1549
|
+
if (dismissed)
|
|
1550
|
+
return null;
|
|
1551
|
+
const styles = alertStyles[alertType] ?? alertStyles['info'];
|
|
1552
|
+
const Icon = ALERT_TYPE_ICONS[alertType] ?? InfoIcon;
|
|
1553
|
+
const iconColorKey = iconColor ?? ALERT_TYPE_DEFAULT_ICON_COLOR[alertType] ?? 'info';
|
|
1554
|
+
const iconColorCls = TEXT_COLOR_CLASSES[iconColorKey] ?? '';
|
|
1555
|
+
const alignCls = ALERT_ACTIONS_ALIGNMENT[actionsAlignment ?? 'start'] ?? 'justify-start';
|
|
1556
|
+
const handleDismiss = () => {
|
|
1557
|
+
setDismissed(true);
|
|
1558
|
+
if (persistDismissal && typeof window !== 'undefined') {
|
|
1559
|
+
try {
|
|
1560
|
+
window.localStorage.setItem(alertPersistKey(persistDismissal), '1');
|
|
1561
|
+
}
|
|
1562
|
+
catch { /* localStorage blocked — dismiss is per-mount only */ }
|
|
1563
|
+
}
|
|
1564
|
+
};
|
|
1565
|
+
return (_jsxs("div", { className: `relative rounded-lg border p-4 ${styles} ${dismissible ? 'pr-9' : ''}`, children: [_jsxs("div", { className: "flex gap-3", children: [_jsx(Icon, { className: `size-5 shrink-0 mt-0.5 ${iconColorCls}`, "aria-hidden": "true" }), _jsxs("div", { className: "flex-1 min-w-0", children: [title !== undefined && _jsx("p", { className: "font-medium mb-1", children: title }), _jsx("p", { className: "text-sm", children: content }), footer.length > 0 && (_jsx("div", { className: `flex items-center gap-2 mt-3 ${alignCls}`, children: footer }))] })] }), dismissible && (_jsx("button", { type: "button", onClick: handleDismiss, "aria-label": "Dismiss", title: "Dismiss", className: "absolute top-3 right-3 inline-flex h-6 w-6 items-center justify-center rounded opacity-70 hover:opacity-100 transition-opacity", children: _jsx(XIcon, { className: "size-4", "aria-hidden": "true" }) }))] }));
|
|
1566
|
+
}
|
|
1463
1567
|
function renderElement(el, index) {
|
|
1464
1568
|
switch (el.type) {
|
|
1465
1569
|
case 'text':
|
|
@@ -1508,11 +1612,8 @@ function renderElement(el, index) {
|
|
|
1508
1612
|
return (_jsxs("div", { className: "flex items-start justify-between gap-4", children: [titleBlock, _jsx("div", { className: "flex items-center gap-2 shrink-0", children: headerActions.map((a, i) => renderActionLike(a, i)) })] }, index));
|
|
1509
1613
|
}
|
|
1510
1614
|
case 'alert': {
|
|
1511
|
-
const alertType = String(el['alertType'] ?? 'info');
|
|
1512
|
-
const styles = alertStyles[alertType] ?? alertStyles['info'];
|
|
1513
|
-
const title = el['title'] ? String(el['title']) : undefined;
|
|
1514
1615
|
const footer = (el.children ?? []).filter(c => c.type === 'action' || c.type === 'actionGroup');
|
|
1515
|
-
return (
|
|
1616
|
+
return (_jsx(AlertRenderer, { alertType: String(el['alertType'] ?? 'info'), content: String(el['content'] ?? ''), ...(el['title'] !== undefined ? { title: String(el['title']) } : {}), ...(el['dismissible'] ? { dismissible: Boolean(el['dismissible']) } : {}), ...(el['persistDismissal'] !== undefined ? { persistDismissal: String(el['persistDismissal']) } : {}), ...(el['iconColor'] !== undefined ? { iconColor: String(el['iconColor']) } : {}), ...(el['actionsAlignment'] !== undefined ? { actionsAlignment: String(el['actionsAlignment']) } : {}), footer: footer.map((a, i) => renderActionLike(a, i)) }, index));
|
|
1516
1617
|
}
|
|
1517
1618
|
case 'emptyState': {
|
|
1518
1619
|
const heading = String(el['heading'] ?? '');
|