@asteby/metacore-runtime-react 34.1.0 → 35.1.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/CHANGELOG.md +7 -86
- package/dist/action-modal-dispatcher.d.ts +4 -0
- package/dist/action-modal-dispatcher.d.ts.map +1 -1
- package/dist/action-modal-dispatcher.js +102 -23
- package/dist/addon-loader.d.ts +1 -1
- package/dist/addon-loader.d.ts.map +1 -1
- package/dist/addon-loader.js +8 -1
- package/dist/color-picker-field.d.ts +13 -0
- package/dist/color-picker-field.d.ts.map +1 -0
- package/dist/color-picker-field.js +181 -0
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +99 -61
- package/dist/dynamic-columns.d.ts.map +1 -1
- package/dist/dynamic-columns.js +23 -8
- package/dist/dynamic-form.d.ts +1 -0
- package/dist/dynamic-form.d.ts.map +1 -1
- package/dist/dynamic-form.js +3 -1
- package/dist/dynamic-select-field.d.ts.map +1 -1
- package/dist/dynamic-select-field.js +6 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/permissions-manager.d.ts +5 -0
- package/dist/permissions-manager.d.ts.map +1 -1
- package/dist/permissions-manager.js +67 -23
- package/dist/use-print-document.d.ts +10 -1
- package/dist/use-print-document.d.ts.map +1 -1
- package/dist/use-print-document.js +28 -1
- package/package.json +1 -1
- package/src/__tests__/color-picker-field.test.tsx +18 -0
- package/src/__tests__/filename-from-disposition.test.ts +30 -0
- package/src/__tests__/prefill-scalar-from-record.test.ts +37 -0
- package/src/__tests__/record-detail-display.test.tsx +30 -0
- package/src/action-modal-dispatcher.tsx +110 -22
- package/src/addon-loader.tsx +7 -1
- package/src/color-picker-field.tsx +296 -0
- package/src/dialogs/dynamic-record.tsx +139 -65
- package/src/dynamic-columns.tsx +28 -12
- package/src/dynamic-form.tsx +9 -1
- package/src/dynamic-select-field.tsx +7 -3
- package/src/index.ts +2 -0
- package/src/permissions-manager.tsx +98 -39
- package/src/use-print-document.ts +38 -2
|
@@ -10,7 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
// flows through <ApiProvider> from runtime-react. Host-specific runtime values —
|
|
11
11
|
// the image-url resolver and the org IANA timezone — are passed as props so the
|
|
12
12
|
// SDK stays transport- and host-agnostic.
|
|
13
|
-
import { createContext, useCallback, useContext, useEffect,
|
|
13
|
+
import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
14
14
|
import { useTranslation } from 'react-i18next';
|
|
15
15
|
/** Model key of the open create/edit dialog — used to hide "+" on self-FK pickers
|
|
16
16
|
* (e.g. Customer.parent_id) so they don't nest another "Crear Cliente" modal. */
|
|
@@ -23,9 +23,7 @@ import { es } from 'date-fns/locale';
|
|
|
23
23
|
import { ExternalLink, Loader2, CalendarIcon, ChevronDown, Check, Upload, X as XIcon, ScanLine } from 'lucide-react';
|
|
24
24
|
import { BarcodeScanner } from '../barcode-scanner';
|
|
25
25
|
import { useApi } from '../api-context';
|
|
26
|
-
import { toastServerError, extractFieldErrors,
|
|
27
|
-
import { validateValues, bagHasErrors } from '../validator';
|
|
28
|
-
import { validationCatalog } from '../validation-catalog';
|
|
26
|
+
import { toastServerError, extractFieldErrors, localizeFieldIssue } from '../server-error';
|
|
29
27
|
import { DynamicSelectField, OptionLead, OptionThumb } from '../dynamic-select-field';
|
|
30
28
|
import { DynamicRelations } from '../dynamic-relations';
|
|
31
29
|
import { useOptionsResolver } from '../use-options-resolver';
|
|
@@ -169,6 +167,23 @@ function isRelationField(field) {
|
|
|
169
167
|
!!getFieldRef(field) ||
|
|
170
168
|
!!field.searchEndpoint);
|
|
171
169
|
}
|
|
170
|
+
// looksLikeForeignKey — true only for real FKs. A bare `*_id` suffix is NOT
|
|
171
|
+
// enough: columns like `external_id`, `trace_id`, or `invoice_uid` are plain
|
|
172
|
+
// text identifiers from a PAC/provider, not belongs_to relations. Treating them
|
|
173
|
+
// as relations rendered an InitialsAvatar ("6" chip next to "6a8c…") and made
|
|
174
|
+
// fiscal detail modals look broken.
|
|
175
|
+
function looksLikeForeignKey(field) {
|
|
176
|
+
if (isRelationField(field))
|
|
177
|
+
return true;
|
|
178
|
+
if (typeof field.key !== 'string' || !field.key.endsWith('_id'))
|
|
179
|
+
return false;
|
|
180
|
+
const t = String(field.type || '').toLowerCase();
|
|
181
|
+
return (t === 'uuid' ||
|
|
182
|
+
t === 'search' ||
|
|
183
|
+
t === 'relation' ||
|
|
184
|
+
t === 'dynamic_select' ||
|
|
185
|
+
t === 'belongs_to');
|
|
186
|
+
}
|
|
172
187
|
function formatDisplayValue(rawValue, field) {
|
|
173
188
|
// Unset nullable FK serialized as the nil UUID renders as empty, not zeros.
|
|
174
189
|
const value = normalizeNilUuid(rawValue);
|
|
@@ -284,19 +299,9 @@ export function stripHiddenFieldValues(values, fields, mode) {
|
|
|
284
299
|
}
|
|
285
300
|
return out;
|
|
286
301
|
}
|
|
287
|
-
function toastValidationFailed(t, lang, localized) {
|
|
288
|
-
toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }), {
|
|
289
|
-
description: Object.values(localized).filter(Boolean).join('\n'),
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
302
|
export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId, endpoint, onSaved, onCreate, onUpdate, defaults, lockedFields, schema, onDelete, onEdit, onOpenFullPage, initialRecord, getImageUrl = identityImageUrl, timeZone, currency, onChange, }) {
|
|
293
303
|
const api = useApi();
|
|
294
|
-
const { t
|
|
295
|
-
// Unique per dialog instance. The footer submit lives OUTSIDE <form>, so
|
|
296
|
-
// it binds via `form={id}`. A hardcoded id made nested create (product +
|
|
297
|
-
// "Crear categoría") submit the PARENT form — toast "Revisa los campos
|
|
298
|
-
// marcados" with no marks on the inner modal.
|
|
299
|
-
const formId = useId();
|
|
304
|
+
const { t } = useTranslation();
|
|
300
305
|
const [modalMeta, setModalMeta] = useState(schema ? schema : null);
|
|
301
306
|
const [relations, setRelations] = useState([]);
|
|
302
307
|
const [record, setRecord] = useState(null);
|
|
@@ -490,25 +495,24 @@ export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId,
|
|
|
490
495
|
const labelForKey = (key) => {
|
|
491
496
|
const f = (modalMeta?.fields ?? []).find(x => x.key === key);
|
|
492
497
|
if (f?.label)
|
|
493
|
-
return
|
|
498
|
+
return f.label;
|
|
494
499
|
return key.replace(/[._-]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
|
|
495
500
|
};
|
|
496
|
-
const lang = i18n.language;
|
|
497
501
|
// Turn a failed submit (422 `errors` map, or a bare `{errors}` body) into
|
|
498
502
|
// inline field errors + a summary toast. When there is no field map, fall
|
|
499
503
|
// back to the existing single cause-carrying toast.
|
|
500
504
|
const handleSubmitError = (err) => {
|
|
501
505
|
const map = extractFieldErrors(err);
|
|
502
506
|
if (map) {
|
|
503
|
-
const
|
|
504
|
-
for (const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
setFieldErrors(
|
|
508
|
-
|
|
507
|
+
const next = {};
|
|
508
|
+
for (const [key, issues] of Object.entries(map)) {
|
|
509
|
+
next[key] = localizeFieldIssue(issues[0], labelForKey(key), t);
|
|
510
|
+
}
|
|
511
|
+
setFieldErrors(next);
|
|
512
|
+
toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }));
|
|
509
513
|
return;
|
|
510
514
|
}
|
|
511
|
-
toastServerError(err, { t,
|
|
515
|
+
toastServerError(err, { t, fallback: t('dynamic.save_error', { defaultValue: 'No se pudo guardar' }) });
|
|
512
516
|
};
|
|
513
517
|
const handleSubmit = async (e) => {
|
|
514
518
|
e?.preventDefault();
|
|
@@ -520,15 +524,15 @@ export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId,
|
|
|
520
524
|
// fields are gated: a field hidden by its `visible_when` predicate
|
|
521
525
|
// must not block submit even when it is declared required (matching
|
|
522
526
|
// the render, which drops it via the same filter).
|
|
523
|
-
const
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
setFieldErrors(
|
|
531
|
-
|
|
527
|
+
const missing = {};
|
|
528
|
+
for (const field of filterVisibleFields(modalMeta.fields, mode, formValues)) {
|
|
529
|
+
if (field.required && !formValues[field.key] && formValues[field.key] !== 0 && formValues[field.key] !== false) {
|
|
530
|
+
missing[field.key] = localizeFieldIssue({ code: 'required' }, field.label, t);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (Object.keys(missing).length) {
|
|
534
|
+
setFieldErrors(missing);
|
|
535
|
+
toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }));
|
|
532
536
|
return;
|
|
533
537
|
}
|
|
534
538
|
}
|
|
@@ -649,21 +653,22 @@ export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId,
|
|
|
649
653
|
// then advance. Mirrors handleSubmit's required check but scoped to the step.
|
|
650
654
|
const goNextStep = () => {
|
|
651
655
|
const step = groups[clampedStep];
|
|
652
|
-
const
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
656
|
+
const missing = {};
|
|
657
|
+
for (const field of step?.fields ?? []) {
|
|
658
|
+
if (field.required && !formValues[field.key] && formValues[field.key] !== 0 && formValues[field.key] !== false) {
|
|
659
|
+
missing[field.key] = localizeFieldIssue({ code: 'required' }, field.label, t);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (Object.keys(missing).length) {
|
|
663
|
+
setFieldErrors(missing);
|
|
664
|
+
toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }));
|
|
660
665
|
return;
|
|
661
666
|
}
|
|
662
667
|
setFieldErrors({});
|
|
663
668
|
setStepIndex(Math.min(clampedStep + 1, groups.length - 1));
|
|
664
669
|
};
|
|
665
670
|
const goBackStep = () => setStepIndex(Math.max(clampedStep - 1, 0));
|
|
666
|
-
return (_jsx(RecordDialogModelContext.Provider, { value: model, children: _jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "sm:max-w-2xl max-h-[90dvh] flex flex-col p-0 gap-0 overflow-hidden", style: { maxHeight: '90dvh' }, children: [_jsxs(DialogHeader, { className: "p-6 pb-4 border-b shrink-0", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: config.description })] }), _jsx("div", { className: "flex-1 overflow-y-auto p-6", children: loading ? (_jsx(LoadingSkeleton, {})) : modalMeta ? (_jsx(ModelContext.Provider, { value: model, children: _jsx(ImageUrlContext.Provider, { value: getImageUrl, children: _jsx(TimeZoneContext.Provider, { value: timeZone, children: _jsxs(CurrencyContext.Provider, { value: currency, children: [_jsxs("form", { id:
|
|
671
|
+
return (_jsx(RecordDialogModelContext.Provider, { value: model, children: _jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "sm:max-w-2xl max-h-[90dvh] flex flex-col p-0 gap-0 overflow-hidden", style: { maxHeight: '90dvh' }, children: [_jsxs(DialogHeader, { className: "p-6 pb-4 border-b shrink-0", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: config.description })] }), _jsx("div", { className: "flex-1 overflow-y-auto p-6", children: loading ? (_jsx(LoadingSkeleton, {})) : modalMeta ? (_jsx(ModelContext.Provider, { value: model, children: _jsx(ImageUrlContext.Provider, { value: getImageUrl, children: _jsx(TimeZoneContext.Provider, { value: timeZone, children: _jsxs(CurrencyContext.Provider, { value: currency, children: [_jsxs("form", { id: "dynamic-record-form", onSubmit: handleSubmit, className: "grid gap-y-4", children: [isSteps && (_jsx(WizardProgress, { groups: groups, stepIndex: clampedStep })), (isSteps ? [groups[clampedStep]] : groups).map(group => (_jsx(FieldSection, { group: group, children: _jsx("div", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: renderFields(group.fields) }) }, group.key))), record?.external_url && (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2", children: _jsx("div", { className: "sm:col-span-2 min-w-0", children: _jsxs("a", { href: record.external_url, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1.5 text-sm text-primary hover:underline mt-1", children: [_jsx(ExternalLink, { className: "h-3.5 w-3.5" }), "Ver en ", record.external_provider ?? 'proveedor externo'] }) }) }))] }), !isCreate && record && relations.length > 0 && (_jsx("div", { className: "mt-6", children: _jsx(DynamicRelations, { record: record, relations: relations, lineSubtable: true, embedOnly: true, canCreate: mode === 'edit', canEdit: mode === 'edit', canDelete: mode === 'edit', onChange: handleChildChange }) }))] }) }) }) })) : null }), _jsxs(DialogFooter, { className: "p-4 border-t shrink-0 sm:justify-between", children: [isView && onOpenFullPage ? (_jsxs(Button, { variant: "ghost", size: "sm", className: "text-muted-foreground", onClick: () => { onOpenChange(false); onOpenFullPage(); }, children: [_jsx(ExternalLink, { className: "mr-1.5 h-3.5 w-3.5" }), "Ver p\u00E1gina completa"] })) : _jsx("span", {}), _jsxs("div", { className: "flex items-center gap-2", children: [isSteps && clampedStep > 0 ? (_jsx(Button, { variant: "outline", onClick: goBackStep, disabled: saving || deleting, children: "Anterior" })) : (_jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: saving || deleting, children: config.cancelLabel })), isView && onDelete && (_jsxs(Button, { variant: "destructive", onClick: handleDelete, disabled: deleting || loading, children: [deleting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), deleting ? 'Eliminando...' : 'Eliminar'] })), isView && onEdit && (_jsx(Button, { onClick: onEdit, disabled: deleting || loading, children: "Editar" })), isEditable && isSteps && !isLastStep && (_jsx(Button, { type: "button", onClick: goNextStep, disabled: saving || loading, children: "Siguiente" })), isEditable && (!isSteps || isLastStep) && (_jsxs(Button, { type: "submit", form: "dynamic-record-form", disabled: saving || loading, children: [saving && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), saving ? config.submittingLabel : config.submitLabel] }))] })] })] }) }) }));
|
|
667
672
|
}
|
|
668
673
|
function LoadingSkeleton() {
|
|
669
674
|
return (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-4", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Skeleton, { className: "h-3.5 w-24" }), _jsx(Skeleton, { className: "h-9 w-full" })] }, i))) }));
|
|
@@ -698,9 +703,7 @@ export function ReadonlyEditField({ field, value }) {
|
|
|
698
703
|
// ReadonlyRelationField — a locked/readonly FK field (customer_id, category_id…)
|
|
699
704
|
// resolves the record's label instead of showing the raw id, mirroring
|
|
700
705
|
// RelationViewValue's lookup but rendered as a disabled input to match the rest
|
|
701
|
-
// of ReadonlyEditField.
|
|
702
|
-
// seeding a POS-selected customer into a vehicle create modal) would show a bare
|
|
703
|
-
// UUID — the exact readability bug this dialog otherwise avoids elsewhere.
|
|
706
|
+
// of ReadonlyEditField.
|
|
704
707
|
function ReadonlyRelationField({ field, value, fieldRef, }) {
|
|
705
708
|
const rawVal = value && typeof value === 'object' ? (value.value ?? value.id) : value;
|
|
706
709
|
const needResolve = fieldRef != null || !!field.searchEndpoint;
|
|
@@ -720,7 +723,9 @@ function ReadonlyRelationField({ field, value, fieldRef, }) {
|
|
|
720
723
|
// RelationViewValue — read-only FK lead. Resolves the relation's label + image
|
|
721
724
|
// from (1) the sibling object the table served, then (2) the canonical options
|
|
722
725
|
// endpoint, and renders an OptionLead (thumbnail / icon / color dot) + label.
|
|
723
|
-
|
|
726
|
+
// When `stack` is true (`display: "image_stack"`), the landscape mark sits ON
|
|
727
|
+
// TOP of the label — wide logos (brand marks) fit without cropping.
|
|
728
|
+
function RelationViewValue({ field, value, record, stack = false, }) {
|
|
724
729
|
const getImageUrl = useContext(ImageUrlContext);
|
|
725
730
|
const sib = relationSiblingValue(field, record);
|
|
726
731
|
const sibLabel = typeof sib === 'string' ? sib : objectLabel(sib);
|
|
@@ -804,15 +809,15 @@ export function ViewValue({ field, value: rawValue, record, getImageUrl: getImag
|
|
|
804
809
|
return _jsx("p", { className: "text-sm py-1 text-muted-foreground", children: "\u2014" });
|
|
805
810
|
}
|
|
806
811
|
const value = normalizeNilUuid(rawValue);
|
|
807
|
-
// Landscape stack on a relation FK (brand marks, product cards)
|
|
808
|
-
|
|
809
|
-
|
|
812
|
+
// Landscape stack on a relation FK (brand marks, product cards): image ON
|
|
813
|
+
// TOP, label UNDERNEATH. Checked before the default relation lead so a
|
|
814
|
+
// `display: "image_stack"` FK does not fall through to the side-by-side chip.
|
|
815
|
+
if (renderAs === 'image_stack' && looksLikeForeignKey(field)) {
|
|
810
816
|
return _jsx(RelationViewValue, { field: field, value: value, record: record, stack: true });
|
|
811
817
|
}
|
|
812
|
-
// Relation (search / dynamic_select / ref /
|
|
813
|
-
// label.
|
|
814
|
-
|
|
815
|
-
if (isRelationField(field) || (typeof field.key === 'string' && field.key.endsWith('_id'))) {
|
|
818
|
+
// Relation (search / dynamic_select / ref / uuid *_id FK) → resolved
|
|
819
|
+
// thumbnail + label. Plain text `*_id` columns (external_id, …) stay text.
|
|
820
|
+
if (looksLikeForeignKey(field)) {
|
|
816
821
|
return _jsx(RelationViewValue, { field: field, value: value, record: record });
|
|
817
822
|
}
|
|
818
823
|
// The value is itself a resolved object the backend served inline — render
|
|
@@ -827,16 +832,24 @@ export function ViewValue({ field, value: rawValue, record, getImageUrl: getImag
|
|
|
827
832
|
if (field.type === 'color') {
|
|
828
833
|
return value ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-5 w-5 rounded-full border shadow-sm", style: { backgroundColor: value } }), _jsx("span", { className: "text-sm", children: value })] })) : (_jsx("p", { className: "text-sm py-1 text-muted-foreground", children: "-" }));
|
|
829
834
|
}
|
|
830
|
-
// Landscape stack for image/logo URL columns
|
|
835
|
+
// Landscape stack for image/logo URL columns (and `type: image` with
|
|
836
|
+
// `cellStyle: image_stack`). Wide marks sit above an optional caption.
|
|
831
837
|
if (renderAs === 'image_stack') {
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
+
if (value && isLucideIconName(value)) {
|
|
839
|
+
return _jsx(IconNameViewValue, { name: value });
|
|
840
|
+
}
|
|
841
|
+
const labelField = (field.styleConfig &&
|
|
842
|
+
field.styleConfig.label_field) ||
|
|
843
|
+
(field.styleConfig && field.styleConfig.labelField);
|
|
844
|
+
let caption;
|
|
845
|
+
if (labelField && record && typeof record === 'object') {
|
|
846
|
+
const raw = record[labelField];
|
|
847
|
+
if (raw != null && String(raw) !== '')
|
|
848
|
+
caption = String(raw);
|
|
849
|
+
}
|
|
850
|
+
return value || caption ? (_jsx("div", { className: "py-1", children: _jsx(ImageStack, { src: value ? String(value) : undefined, label: caption, getImageUrl: getImageUrl, size: "lg" }) })) : (_jsx("p", { className: "text-sm py-1 text-muted-foreground", children: "Sin imagen" }));
|
|
838
851
|
}
|
|
839
|
-
if (field.type === 'image') {
|
|
852
|
+
if (field.type === 'image' || renderAs === 'image') {
|
|
840
853
|
if (isLucideIconName(value)) {
|
|
841
854
|
return _jsx(IconNameViewValue, { name: value });
|
|
842
855
|
}
|
|
@@ -1007,8 +1020,33 @@ function StructuredViewValue({ value, field, locale, t, }) {
|
|
|
1007
1020
|
if (isEmpty) {
|
|
1008
1021
|
return _jsx("p", { className: "text-sm py-1 text-muted-foreground", children: "\u2014" });
|
|
1009
1022
|
}
|
|
1023
|
+
// Line-items arrays with a declared itemFields schema → mini-table.
|
|
1024
|
+
// Plain objects (PAC provider_data, fiscal_data bags) → readable key/value
|
|
1025
|
+
// list; nested objects/arrays render as pretty JSON instead of `key: {…}`
|
|
1026
|
+
// stubs that looked broken in fiscal detail modals.
|
|
1027
|
+
const hasItemFields = !!(field?.itemFields ?? field?.item_fields);
|
|
1028
|
+
if (!hasItemFields &&
|
|
1029
|
+
value !== null &&
|
|
1030
|
+
typeof value === 'object' &&
|
|
1031
|
+
!Array.isArray(value)) {
|
|
1032
|
+
return _jsx(JsonObjectViewValue, { value: value });
|
|
1033
|
+
}
|
|
1010
1034
|
return (_jsx("div", { className: "text-sm py-1", children: _jsx(CollectionCell, { value: value, itemFields: field?.itemFields ?? field?.item_fields, variant: "inline", locale: locale, t: t, getImageUrl: getImageUrl }) }));
|
|
1011
1035
|
}
|
|
1036
|
+
/** Flatten a jsonb/object bag into labeled rows; nest as pretty JSON. */
|
|
1037
|
+
function JsonObjectViewValue({ value }) {
|
|
1038
|
+
const entries = Object.entries(value).filter(([, v]) => v !== undefined);
|
|
1039
|
+
if (entries.length === 0) {
|
|
1040
|
+
return _jsx("p", { className: "text-sm py-1 text-muted-foreground", children: "\u2014" });
|
|
1041
|
+
}
|
|
1042
|
+
return (_jsx("dl", { className: "grid gap-2 py-1 text-sm", children: entries.map(([key, raw]) => {
|
|
1043
|
+
const label = humanizeToken(key);
|
|
1044
|
+
const isNest = raw !== null &&
|
|
1045
|
+
typeof raw === 'object' &&
|
|
1046
|
+
!(raw instanceof Date);
|
|
1047
|
+
return (_jsxs("div", { className: "min-w-0", children: [_jsx("dt", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: label }), _jsx("dd", { className: "mt-0.5 break-words text-foreground", children: isNest ? (_jsx("pre", { className: "max-h-48 overflow-auto rounded-md bg-muted/40 p-2 text-[11px] leading-relaxed whitespace-pre-wrap", children: JSON.stringify(raw, null, 2) })) : raw === null || raw === '' ? (_jsx("span", { className: "text-muted-foreground", children: "\u2014" })) : (String(raw)) })] }, key));
|
|
1048
|
+
}) }));
|
|
1049
|
+
}
|
|
1012
1050
|
export function EditField({ field, value, onChange, record }) {
|
|
1013
1051
|
const { t, i18n } = useTranslation();
|
|
1014
1052
|
const editFieldImageUrl = useContext(ImageUrlContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"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"}
|
package/dist/dynamic-columns.js
CHANGED
|
@@ -23,7 +23,7 @@ import { generateBadgeStyles, getInitials, relationChipStyles, } from '@asteby/m
|
|
|
23
23
|
import { Progress } from './dialogs/_primitives';
|
|
24
24
|
import { humanizeToken } from './dynamic-columns-helpers';
|
|
25
25
|
import { objectLabel } from './dynamic-relation-helpers';
|
|
26
|
-
import {
|
|
26
|
+
import { OptionBadge, RelationThumbnail, ImageStack, statusColorFor, useIsDarkTheme, } from './display-value';
|
|
27
27
|
import { MediaValue } from './rich-url';
|
|
28
28
|
import { OptionsContext } from './options-context';
|
|
29
29
|
import { DynamicIcon, isLucideIconName } from './dynamic-icon';
|
|
@@ -468,6 +468,10 @@ export const resolveRelationSubtitle = (col, row) => {
|
|
|
468
468
|
* carries an `image`. Falls back to the raw id when no sibling was resolved, and
|
|
469
469
|
* to an empty marker when there is no value at all. Domain-agnostic: works for
|
|
470
470
|
* every `belongs_to` column (category, supplier, brand, …) without per-addon code.
|
|
471
|
+
*
|
|
472
|
+
* When `stack` is true (column `display: "image_stack"`), the landscape mark
|
|
473
|
+
* sits ON TOP of the label — wide logos fit without cropping and the cell
|
|
474
|
+
* stays readable in dense tables.
|
|
471
475
|
*/
|
|
472
476
|
const RelationCell = ({ col, row, getImageUrl, stack = false }) => {
|
|
473
477
|
const display = resolveRelationLabel(col, row);
|
|
@@ -658,7 +662,15 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
|
|
|
658
662
|
return _jsx(ReferenceCell, { col: col, row: row.original });
|
|
659
663
|
}
|
|
660
664
|
// Landscape stack: wide image ON TOP, label UNDERNEATH.
|
|
665
|
+
// Declared via `display: "image_stack"` on an image column
|
|
666
|
+
// or on a belongs_to FK whose sibling carries a logo/photo
|
|
667
|
+
// (brand marks, product cards). Fits logos that are wider
|
|
668
|
+
// than tall without cropping into a square thumb.
|
|
661
669
|
if (renderAs === 'image_stack') {
|
|
670
|
+
// FK relation (brand_id → brands) OR any column that
|
|
671
|
+
// already resolved a sibling with an image — stack it.
|
|
672
|
+
// Don't require `col.ref` alone: enrichment sometimes
|
|
673
|
+
// leaves type=text while cellStyle carries image_stack.
|
|
662
674
|
const looksRelation = !!col.ref ||
|
|
663
675
|
(typeof col.key === 'string' &&
|
|
664
676
|
col.key.endsWith('_id') &&
|
|
@@ -872,13 +884,6 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
|
|
|
872
884
|
: 'FileText', className: "h-4 w-4" }) }, i));
|
|
873
885
|
}), remaining > 0 && (_jsxs("div", { className: "flex h-8 w-8 items-center justify-center rounded-full bg-muted text-xs font-medium ring-2 ring-background", children: ["+", remaining] }))] }));
|
|
874
886
|
}
|
|
875
|
-
case 'image_stack': {
|
|
876
|
-
const imageValue = value ||
|
|
877
|
-
(Array.isArray(row.original.media)
|
|
878
|
-
? row.original.media.find((m) => m.type === 'image')?.url
|
|
879
|
-
: null);
|
|
880
|
-
return (_jsx(ImageCell, { value: imageValue, getImageUrl: getImageUrl, stack: true }));
|
|
881
|
-
}
|
|
882
887
|
case 'image': {
|
|
883
888
|
const imageValue = value ||
|
|
884
889
|
(Array.isArray(row.original.media)
|
|
@@ -886,6 +891,16 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
|
|
|
886
891
|
: null);
|
|
887
892
|
return _jsx(ImageCell, { value: imageValue, getImageUrl: getImageUrl });
|
|
888
893
|
}
|
|
894
|
+
case 'image_stack': {
|
|
895
|
+
// Defensive: normally handled above before the
|
|
896
|
+
// switch; kept so a late `type: image_stack` without
|
|
897
|
+
// cellStyle still stacks.
|
|
898
|
+
const labelField = styleCfg(col, 'label_field', 'labelField');
|
|
899
|
+
const caption = labelField
|
|
900
|
+
? String(getNestedValue(row.original, labelField) ?? '')
|
|
901
|
+
: undefined;
|
|
902
|
+
return (_jsx(ImageCell, { value: value, getImageUrl: getImageUrl, label: caption || undefined, stack: true }));
|
|
903
|
+
}
|
|
889
904
|
default: {
|
|
890
905
|
if (typeof value === 'object' && value !== null) {
|
|
891
906
|
return (_jsx(CollectionCell, { value: value, locale: currentLanguage, t: t, itemFields: col.itemFields ?? col.item_fields, getImageUrl: getImageUrl }));
|
package/dist/dynamic-form.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { DynamicSelectField } from './dynamic-select-field';
|
|
|
7
7
|
export { DynamicDateField } from './dynamic-date-field';
|
|
8
8
|
export { UploadField } from './upload-field';
|
|
9
9
|
export { IconPickerField } from './icon-picker-field';
|
|
10
|
+
export { ColorPickerField, DEFAULT_ROLE_COLOR, normalizeHex } from './color-picker-field';
|
|
10
11
|
export interface DynamicFormProps {
|
|
11
12
|
fields: ActionFieldDef[];
|
|
12
13
|
initialValues?: Record<string, any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-form.d.ts","sourceRoot":"","sources":["../src/dynamic-form.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAcrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EACH,cAAc,EACd,aAAa,EAOhB,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-form.d.ts","sourceRoot":"","sources":["../src/dynamic-form.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAcrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EACH,cAAc,EACd,aAAa,EAOhB,MAAM,uBAAuB,CAAA;AAW9B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEzF,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,CAAA;CAC1B;AAED,wBAAgB,WAAW,CAAC,EACxB,MAAM,EACN,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,WAAuB,EACvB,WAAwB,EACxB,QAAgB,EAChB,UAAU,GACb,EAAE,gBAAgB,+BA8LlB"}
|
package/dist/dynamic-form.js
CHANGED
|
@@ -15,12 +15,14 @@ import { DynamicSelectField } from './dynamic-select-field';
|
|
|
15
15
|
import { DynamicDateField } from './dynamic-date-field';
|
|
16
16
|
import { UploadField } from './upload-field';
|
|
17
17
|
import { IconPickerField } from './icon-picker-field';
|
|
18
|
+
import { ColorPickerField } from './color-picker-field';
|
|
18
19
|
export { buildZodSchema, resolveWidget };
|
|
19
20
|
export { DynamicLineItems } from './dynamic-line-items';
|
|
20
21
|
export { DynamicSelectField } from './dynamic-select-field';
|
|
21
22
|
export { DynamicDateField } from './dynamic-date-field';
|
|
22
23
|
export { UploadField } from './upload-field';
|
|
23
24
|
export { IconPickerField } from './icon-picker-field';
|
|
25
|
+
export { ColorPickerField, DEFAULT_ROLE_COLOR, normalizeHex } from './color-picker-field';
|
|
24
26
|
export function DynamicForm({ fields, initialValues, onSubmit, onCancel, submitLabel = 'Guardar', cancelLabel = 'Cancelar', disabled = false, formLayout, }) {
|
|
25
27
|
const [values, setValues] = useState({});
|
|
26
28
|
const [errors, setErrors] = useState({});
|
|
@@ -230,7 +232,7 @@ function FieldRenderer({ field, value, onChange, initialValues, effectiveOptions
|
|
|
230
232
|
// / future MDX editor pick it up without breaking the contract.
|
|
231
233
|
return _jsx(Textarea, { id: field.key, "data-widget": "richtext", value: value || '', onChange: (e) => onChange(e.target.value), placeholder: field.placeholder });
|
|
232
234
|
case 'color':
|
|
233
|
-
return _jsx(
|
|
235
|
+
return (_jsx(ColorPickerField, { "aria-label": field.label || field.key, value: typeof value === 'string' ? value : '', onChange: onChange }));
|
|
234
236
|
case 'select':
|
|
235
237
|
return (_jsxs(Select, { value: value || '', onValueChange: onChange, children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, { placeholder: field.placeholder || 'Seleccionar...' }) }), _jsx(SelectContent, { children: (effectiveOptions ?? field.options)?.map((opt) => _jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })] }));
|
|
236
238
|
case 'switch':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dynamic-select-field.d.ts","sourceRoot":"","sources":["../src/dynamic-select-field.tsx"],"names":[],"mappings":"AA4CA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,gDAAgD,CAAA;AAEjF;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EACxB,KAAK,EACL,IAAI,EACJ,IAAS,GACZ,EAAE;IACC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,+BA4BA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EACvB,MAAM,EACN,IAAS,GACZ,EAAE;IACC,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,CAAA;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,sCA4BA;AAMD,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,CAAA;IACV,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;IAC1B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAA;IAClC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAAA;IAChD;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,kBAAkB,CAAC,EAC/B,KAAK,EACL,KAAK,EACL,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAgB,EAChB,aAAoB,EACpB,kBAA0B,EAC1B,UAAkB,GACrB,EAAE,uBAAuB,+BAiTzB;AAED,eAAe,kBAAkB,CAAA"}
|
|
@@ -23,6 +23,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
23
23
|
// value). A dedicated `?ids=` lookup is a follow-up; create flows — the common
|
|
24
24
|
// case — start empty and never hit this.
|
|
25
25
|
import { useEffect, useRef, useState } from 'react';
|
|
26
|
+
import { useTranslation } from 'react-i18next';
|
|
26
27
|
import { Badge, Button, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Popover, PopoverContent, PopoverTrigger, InitialsAvatar, } from '@asteby/metacore-ui/primitives';
|
|
27
28
|
import { Check, ChevronsUpDown, Loader2, Plus, ScanLine } from 'lucide-react';
|
|
28
29
|
import { resolveColorCss } from '@asteby/metacore-ui/lib';
|
|
@@ -88,6 +89,8 @@ function useDebounced(value, ms) {
|
|
|
88
89
|
return useDebouncedValue(value, ms);
|
|
89
90
|
}
|
|
90
91
|
export function DynamicSelectField({ field, value, onChange, seedOption, dependsValue, dependsHint, readonly = false, staticOptions = null, descriptionAsBadge = false, hideCreate = false, }) {
|
|
92
|
+
const { t } = useTranslation();
|
|
93
|
+
const ph = (fallback) => field.placeholder ? t(field.placeholder, { defaultValue: field.placeholder }) : fallback;
|
|
91
94
|
const [open, setOpen] = useState(false);
|
|
92
95
|
const [search, setSearch] = useState('');
|
|
93
96
|
const [scanOpen, setScanOpen] = useState(false);
|
|
@@ -206,7 +209,7 @@ export function DynamicSelectField({ field, value, onChange, seedOption, depends
|
|
|
206
209
|
// the eager fetch is in flight the label falls back to the seed/raw value,
|
|
207
210
|
// then snaps to the name once options arrive.
|
|
208
211
|
if (readonly) {
|
|
209
|
-
return (_jsx(Button, { type: "button", variant: "outline", role: "combobox", id: field.key, disabled: true, "aria-readonly": "true", className: "w-full min-w-0 cursor-default justify-start font-normal opacity-100", children: _jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [selectedOption ? _jsx(OptionLead, { option: selectedOption, size: 20 }) : null, _jsx("span", { className: 'min-w-0 flex-1 truncate ' + (selectedOption ? '' : 'text-muted-foreground'), children: selectedOption?.label ?? (loading ? 'Cargando…' :
|
|
212
|
+
return (_jsx(Button, { type: "button", variant: "outline", role: "combobox", id: field.key, disabled: true, "aria-readonly": "true", className: "w-full min-w-0 cursor-default justify-start font-normal opacity-100", children: _jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [selectedOption ? _jsx(OptionLead, { option: selectedOption, size: 20 }) : null, _jsx("span", { className: 'min-w-0 flex-1 truncate ' + (selectedOption ? '' : 'text-muted-foreground'), children: selectedOption?.label ?? (loading ? 'Cargando…' : ph('—')) })] }) }));
|
|
210
213
|
}
|
|
211
214
|
// w-full + min-w-0: as a grid cell child, the row must be allowed to shrink
|
|
212
215
|
// to the cell. Without min-w-0 the combobox+button row sizes to its content
|
|
@@ -215,10 +218,10 @@ export function DynamicSelectField({ field, value, onChange, seedOption, depends
|
|
|
215
218
|
return (_jsxs("div", { className: "flex w-full min-w-0 items-center gap-1.5", children: [_jsxs(Popover, { open: open && !blockedByDependency, onOpenChange: (o) => { if (!blockedByDependency)
|
|
216
219
|
setOpen(o); }, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", role: "combobox", "aria-expanded": open, id: field.key, disabled: blockedByDependency, className: "min-w-0 flex-1 justify-between font-normal", "data-empty": !value, "data-depends-blocked": blockedByDependency ? '' : undefined, children: [_jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [value && selectedOption ? (_jsx(OptionLead, { option: selectedOption, size: 20 })) : null, _jsx("span", { className: 'min-w-0 flex-1 truncate ' + (selectedLabel ? '' : 'text-muted-foreground'), children: blockedByDependency
|
|
217
220
|
? (dependsHint || DEFAULT_DEPENDS_HINT)
|
|
218
|
-
: selectedLabel ||
|
|
221
|
+
: selectedLabel || ph('Buscar…') }), descriptionAsBadge && selectedOption?.description ? (_jsx(Badge, { variant: "secondary", className: "shrink-0 font-normal tabular-nums", children: selectedOption.description })) : null] }), _jsx(ChevronsUpDown, { className: "ml-2 size-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "p-0", align: "start",
|
|
219
222
|
// Match the trigger width without an arbitrary Tailwind class
|
|
220
223
|
// (those don't always survive a consuming app's Tailwind scan).
|
|
221
|
-
style: { width: 'var(--radix-popover-trigger-width)' }, children: _jsxs(Command, { shouldFilter: false, children: [_jsx(CommandInput, { placeholder:
|
|
224
|
+
style: { width: 'var(--radix-popover-trigger-width)' }, children: _jsxs(Command, { shouldFilter: false, children: [_jsx(CommandInput, { placeholder: ph('Buscar…'), value: search, onValueChange: setSearch }), _jsxs(CommandList, { children: [loading && (_jsxs("div", { className: "text-muted-foreground flex items-center justify-center gap-2 py-6 text-sm", children: [_jsx(Loader2, { className: "size-4 animate-spin" }), "Buscando\u2026"] })), !loading && options.length === 0 && (_jsx(CommandEmpty, { children: useStatic
|
|
222
225
|
? debounced
|
|
223
226
|
? 'Sin resultados'
|
|
224
227
|
: 'Sin opciones'
|
package/dist/index.d.ts
CHANGED
|
@@ -28,7 +28,8 @@ export * from './slot';
|
|
|
28
28
|
export * from './capability-gate';
|
|
29
29
|
export { PermissionsProvider, useCan, usePermissionsActive, makeCan, capabilityForActionKey, modelCapability, gateTableMetadata, resolveRowActions, type CanFn, type PermissionsProviderProps, } from './permissions-context';
|
|
30
30
|
export { useDynamicRowActions, type UseDynamicRowActionsParams, type DynamicRowActions, } from './dynamic-row-actions';
|
|
31
|
-
export {
|
|
31
|
+
export { ColorPickerField, DEFAULT_ROLE_COLOR, normalizeHex } from './color-picker-field';
|
|
32
|
+
export { PermissionsManager, moduleActionCapability, moduleCapabilities, grantedCountForModule, capabilitySetsEqual, defaultActionIcon, suggestRoleIcon, normalizeCatalogGroups, flattenGroups, filterModuleGroups, groupModuleActions, type PermissionsManagerProps, type PermissionsCatalog, type GroupedPermissionsCatalog, type FlatPermissionsCatalog, type ModuleGroup, type PermissionModuleDef, type PermissionActionDef, type GeneralPermissionDef, type RoleDef, type RoleInput, } from './permissions-manager';
|
|
32
33
|
export * from './org-runtime-context';
|
|
33
34
|
export * from './org-runtime-provider';
|
|
34
35
|
export * from './navigation-builder';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,8 @@ export * from './slot';
|
|
|
33
33
|
export * from './capability-gate';
|
|
34
34
|
export { PermissionsProvider, useCan, usePermissionsActive, makeCan, capabilityForActionKey, modelCapability, gateTableMetadata, resolveRowActions, } from './permissions-context';
|
|
35
35
|
export { useDynamicRowActions, } from './dynamic-row-actions';
|
|
36
|
-
export {
|
|
36
|
+
export { ColorPickerField, DEFAULT_ROLE_COLOR, normalizeHex } from './color-picker-field';
|
|
37
|
+
export { PermissionsManager, moduleActionCapability, moduleCapabilities, grantedCountForModule, capabilitySetsEqual, defaultActionIcon, suggestRoleIcon, normalizeCatalogGroups, flattenGroups, filterModuleGroups, groupModuleActions, } from './permissions-manager';
|
|
37
38
|
export * from './org-runtime-context';
|
|
38
39
|
export * from './org-runtime-provider';
|
|
39
40
|
export * from './navigation-builder';
|
|
@@ -91,11 +91,14 @@ export interface RoleDef {
|
|
|
91
91
|
label?: string;
|
|
92
92
|
/** Accent color (hex) for the role chip. */
|
|
93
93
|
color?: string;
|
|
94
|
+
/** Lucide PascalCase name (or image path) for the role chip. */
|
|
95
|
+
icon?: string;
|
|
94
96
|
}
|
|
95
97
|
export interface RoleInput {
|
|
96
98
|
name: string;
|
|
97
99
|
label?: string;
|
|
98
100
|
color?: string;
|
|
101
|
+
icon?: string;
|
|
99
102
|
}
|
|
100
103
|
export interface PermissionsManagerProps {
|
|
101
104
|
/** Loads the module×action universe + general flags (grouped or flat). */
|
|
@@ -136,6 +139,8 @@ export declare function grantedCountForModule(granted: ReadonlySet<string>, modu
|
|
|
136
139
|
export declare function capabilitySetsEqual(a: ReadonlySet<string>, b: ReadonlySet<string>): boolean;
|
|
137
140
|
/** Default lucide icon when the manifest action doesn't declare one. */
|
|
138
141
|
export declare function defaultActionIcon(actionKey: string, kind?: string): string;
|
|
142
|
+
/** Suggest a Lucide icon from the role label (create-dialog default). */
|
|
143
|
+
export declare function suggestRoleIcon(label: string): string;
|
|
139
144
|
/**
|
|
140
145
|
* Normalize whatever `loadModules` returned into the canonical grouped shape.
|
|
141
146
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions-manager.d.ts","sourceRoot":"","sources":["../src/permissions-manager.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"permissions-manager.d.ts","sourceRoot":"","sources":["../src/permissions-manager.tsx"],"names":[],"mappings":"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"}
|