@asteby/metacore-runtime-react 34.0.1 → 34.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 +12 -0
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +19 -2
- package/dist/dialogs/import.d.ts.map +1 -1
- package/dist/dialogs/import.js +6 -10
- package/dist/display-value.d.ts +23 -0
- package/dist/display-value.d.ts.map +1 -1
- package/dist/display-value.js +34 -1
- package/dist/dynamic-columns.d.ts +3 -0
- package/dist/dynamic-columns.d.ts.map +1 -1
- package/dist/dynamic-columns.js +36 -6
- package/dist/dynamic-select-field.d.ts.map +1 -1
- package/dist/dynamic-select-field.js +2 -6
- package/dist/dynamic-table.d.ts.map +1 -1
- package/dist/dynamic-table.js +10 -7
- package/dist/file-pick-button.d.ts +21 -0
- package/dist/file-pick-button.d.ts.map +1 -0
- package/dist/file-pick-button.js +39 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/metadata-cache.d.ts.map +1 -1
- package/dist/metadata-cache.js +8 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/upload-field.d.ts.map +1 -1
- package/dist/upload-field.js +27 -32
- package/dist/use-debounced-value.d.ts +8 -0
- package/dist/use-debounced-value.d.ts.map +1 -0
- package/dist/use-debounced-value.js +15 -0
- package/dist/use-dynamic-filters.d.ts.map +1 -1
- package/dist/use-dynamic-filters.js +6 -4
- package/package.json +1 -1
- package/src/__tests__/image-stack.test.tsx +52 -0
- package/src/__tests__/use-debounced-value.test.ts +56 -0
- package/src/dialogs/dynamic-record.tsx +43 -1
- package/src/dialogs/import.tsx +9 -15
- package/src/display-value.tsx +82 -4
- package/src/dynamic-columns.tsx +79 -6
- package/src/dynamic-select-field.tsx +2 -6
- package/src/dynamic-table.tsx +9 -6
- package/src/file-pick-button.tsx +125 -0
- package/src/index.ts +11 -0
- package/src/metadata-cache.ts +8 -1
- package/src/types.ts +2 -0
- package/src/upload-field.tsx +41 -71
- package/src/use-debounced-value.ts +17 -0
- package/src/use-dynamic-filters.ts +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 34.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b08ffb0: Add `image_stack` cell/modal display (logo above label, no muted plate) and debounce DynamicTable / kanban free-text search (~350ms) so typing on large catalogs is less abrupt.
|
|
8
|
+
|
|
9
|
+
## 34.0.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 7bff072: Locale-aware FilePickButton: hide native file chrome so labels follow app language (es/en). UploadField and ImportDialog use it.
|
|
14
|
+
|
|
3
15
|
## 34.0.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AA+C1C,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAEjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"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"}
|
|
@@ -39,7 +39,7 @@ import { DynamicIcon, isLucideIconName } from '../dynamic-icon';
|
|
|
39
39
|
import { IconPickerField } from '../icon-picker-field';
|
|
40
40
|
import { humanizeToken } from '../dynamic-columns-helpers';
|
|
41
41
|
import { formatDateCell } from '../dynamic-columns';
|
|
42
|
-
import { OptionBadge, statusColorFor, useIsDarkTheme, } from '../display-value';
|
|
42
|
+
import { ImageStack, OptionBadge, statusColorFor, useIsDarkTheme, } from '../display-value';
|
|
43
43
|
import { MediaValue, RichText } from '../rich-url';
|
|
44
44
|
import { generateBadgeStyles } from '@asteby/metacore-ui/lib';
|
|
45
45
|
import { CollectionCell } from '../collection-cell';
|
|
@@ -720,7 +720,7 @@ function ReadonlyRelationField({ field, value, fieldRef, }) {
|
|
|
720
720
|
// RelationViewValue — read-only FK lead. Resolves the relation's label + image
|
|
721
721
|
// from (1) the sibling object the table served, then (2) the canonical options
|
|
722
722
|
// endpoint, and renders an OptionLead (thumbnail / icon / color dot) + label.
|
|
723
|
-
function RelationViewValue({ field, value, record }) {
|
|
723
|
+
function RelationViewValue({ field, value, record, stack = false }) {
|
|
724
724
|
const getImageUrl = useContext(ImageUrlContext);
|
|
725
725
|
const sib = relationSiblingValue(field, record);
|
|
726
726
|
const sibLabel = typeof sib === 'string' ? sib : objectLabel(sib);
|
|
@@ -750,6 +750,9 @@ function RelationViewValue({ field, value, record }) {
|
|
|
750
750
|
if (!label && !image) {
|
|
751
751
|
return _jsx("p", { className: "text-sm py-1 text-muted-foreground", children: "\u2014" });
|
|
752
752
|
}
|
|
753
|
+
if (stack) {
|
|
754
|
+
return (_jsx("div", { className: "py-1", children: _jsx(ImageStack, { src: image || undefined, label: label, getImageUrl: getImageUrl, size: "lg" }) }));
|
|
755
|
+
}
|
|
753
756
|
const lead = {
|
|
754
757
|
image: image ? getImageUrl(image) : null,
|
|
755
758
|
color: resolved?.color ?? null,
|
|
@@ -801,6 +804,11 @@ export function ViewValue({ field, value: rawValue, record, getImageUrl: getImag
|
|
|
801
804
|
return _jsx("p", { className: "text-sm py-1 text-muted-foreground", children: "\u2014" });
|
|
802
805
|
}
|
|
803
806
|
const value = normalizeNilUuid(rawValue);
|
|
807
|
+
// Landscape stack on a relation FK (brand marks, product cards).
|
|
808
|
+
if (renderAs === 'image_stack' &&
|
|
809
|
+
(isRelationField(field) || (typeof field.key === 'string' && field.key.endsWith('_id')))) {
|
|
810
|
+
return _jsx(RelationViewValue, { field: field, value: value, record: record, stack: true });
|
|
811
|
+
}
|
|
804
812
|
// Relation (search / dynamic_select / ref / any *_id) → resolved thumbnail +
|
|
805
813
|
// label. The *_id catch-all covers plain-typed FK columns not tagged as a
|
|
806
814
|
// relation field.
|
|
@@ -819,6 +827,15 @@ export function ViewValue({ field, value: rawValue, record, getImageUrl: getImag
|
|
|
819
827
|
if (field.type === 'color') {
|
|
820
828
|
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: "-" }));
|
|
821
829
|
}
|
|
830
|
+
// Landscape stack for image/logo URL columns.
|
|
831
|
+
if (renderAs === 'image_stack') {
|
|
832
|
+
const caption = (typeof field.styleConfig?.label_field === 'string' &&
|
|
833
|
+
record?.[field.styleConfig.label_field]) ||
|
|
834
|
+
(typeof field.styleConfig?.labelField === 'string' &&
|
|
835
|
+
record?.[field.styleConfig.labelField]) ||
|
|
836
|
+
undefined;
|
|
837
|
+
return (_jsx("div", { className: "py-1", children: _jsx(ImageStack, { src: value ? String(value) : undefined, label: caption ? String(caption) : field.label, getImageUrl: getImageUrl, size: "lg" }) }));
|
|
838
|
+
}
|
|
822
839
|
if (field.type === 'image') {
|
|
823
840
|
if (isLucideIconName(value)) {
|
|
824
841
|
return _jsx(IconNameViewValue, { name: value });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/dialogs/import.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/dialogs/import.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAI7C,UAAU,iBAAiB;IACvB,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,aAAa,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;CAC1B;AAqCD,wBAAgB,YAAY,CAAC,EACzB,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,UAAU,GACb,EAAE,iBAAiB,+BAyXnB"}
|
package/dist/dialogs/import.js
CHANGED
|
@@ -4,12 +4,14 @@ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-run
|
|
|
4
4
|
// the validation rules all come from the model's ImportSpec served by the
|
|
5
5
|
// kernel, so this dialog carries no per-model knowledge. Axios-like client is
|
|
6
6
|
// provided by <ApiProvider>.
|
|
7
|
-
import { useState, useEffect
|
|
8
|
-
import {
|
|
7
|
+
import { useState, useEffect } from 'react';
|
|
8
|
+
import { useTranslation } from 'react-i18next';
|
|
9
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, Button, Label, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@asteby/metacore-ui/primitives';
|
|
9
10
|
import { Progress } from './_primitives';
|
|
10
11
|
import { toast } from 'sonner';
|
|
11
12
|
import { FileDown, Loader2, Check, AlertCircle } from 'lucide-react';
|
|
12
13
|
import { useApi } from '../api-context';
|
|
14
|
+
import { FilePickButton } from '../file-pick-button';
|
|
13
15
|
function errorColumn(e) {
|
|
14
16
|
return e.column ?? e.field ?? '';
|
|
15
17
|
}
|
|
@@ -18,6 +20,7 @@ function errorMessage(e) {
|
|
|
18
20
|
}
|
|
19
21
|
export function ImportDialog({ open, onOpenChange, model, metadata, onImported, }) {
|
|
20
22
|
const api = useApi();
|
|
23
|
+
const { t } = useTranslation();
|
|
21
24
|
const [step, setStep] = useState('upload');
|
|
22
25
|
const [file, setFile] = useState(null);
|
|
23
26
|
const [validating, setValidating] = useState(false);
|
|
@@ -25,7 +28,6 @@ export function ImportDialog({ open, onOpenChange, model, metadata, onImported,
|
|
|
25
28
|
const [validationResult, setValidationResult] = useState(null);
|
|
26
29
|
const [importResult, setImportResult] = useState(null);
|
|
27
30
|
const [progress, setProgress] = useState(0);
|
|
28
|
-
const fileInputRef = useRef(null);
|
|
29
31
|
useEffect(() => {
|
|
30
32
|
if (open) {
|
|
31
33
|
setStep('upload');
|
|
@@ -35,14 +37,8 @@ export function ImportDialog({ open, onOpenChange, model, metadata, onImported,
|
|
|
35
37
|
setValidationResult(null);
|
|
36
38
|
setImportResult(null);
|
|
37
39
|
setProgress(0);
|
|
38
|
-
if (fileInputRef.current)
|
|
39
|
-
fileInputRef.current.value = '';
|
|
40
40
|
}
|
|
41
41
|
}, [open]);
|
|
42
|
-
const handleFileChange = (e) => {
|
|
43
|
-
const selectedFile = e.target.files?.[0] ?? null;
|
|
44
|
-
setFile(selectedFile);
|
|
45
|
-
};
|
|
46
42
|
const handleDownloadTemplate = async () => {
|
|
47
43
|
try {
|
|
48
44
|
const response = await api.get(`/dynamic/${model}/export/template`, {
|
|
@@ -167,6 +163,6 @@ export function ImportDialog({ open, onOpenChange, model, metadata, onImported,
|
|
|
167
163
|
validation: 'Validacion',
|
|
168
164
|
results: 'Resultados',
|
|
169
165
|
};
|
|
170
|
-
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "sm:max-w-lg max-h-[90vh] flex flex-col p-0 gap-0 overflow-hidden", children: [_jsxs(DialogHeader, { className: "p-6 pb-4 border-b shrink-0", children: [_jsxs(DialogTitle, { children: ["Importar ", metadata.title] }), _jsx(DialogDescription, { children: stepTitle[step] })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-6", children: [step === 'upload' && (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { children: [_jsxs(Button, { variant: "link", className: "px-0 h-auto text-sm", onClick: handleDownloadTemplate, children: [_jsx(FileDown, { className: "h-4 w-4 mr-1" }), "Descargar plantilla"] }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "La plantilla trae las columnas, un ejemplo y las instrucciones. Borra la fila de ejemplo antes de subir." })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "import-file", className: "text-sm font-medium", children:
|
|
166
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "sm:max-w-lg max-h-[90vh] flex flex-col p-0 gap-0 overflow-hidden", children: [_jsxs(DialogHeader, { className: "p-6 pb-4 border-b shrink-0", children: [_jsxs(DialogTitle, { children: ["Importar ", metadata.title] }), _jsx(DialogDescription, { children: stepTitle[step] })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-6", children: [step === 'upload' && (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { children: [_jsxs(Button, { variant: "link", className: "px-0 h-auto text-sm", onClick: handleDownloadTemplate, children: [_jsx(FileDown, { className: "h-4 w-4 mr-1" }), "Descargar plantilla"] }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "La plantilla trae las columnas, un ejemplo y las instrucciones. Borra la fila de ejemplo antes de subir." })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "import-file", className: "text-sm font-medium", children: t('common.upload.choose', { defaultValue: 'Choose file' }) }), _jsx(FilePickButton, { id: "import-file", accept: ".xlsx,.xls,.csv,.json", hasFile: Boolean(file), fileName: file?.name, onFile: setFile }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Formatos aceptados: Excel, CSV, JSON" })] })] })), step === 'validation' && validationResult && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Check, { className: "h-4 w-4 text-green-600" }), _jsxs("span", { children: [_jsx("strong", { children: validationResult.valid }), " valido(s)"] })] }), validationResult.errors.length > 0 && (_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-destructive" }), _jsxs("span", { children: [_jsx("strong", { children: validationResult.errors.length }), " error(es)"] })] }))] }), validationResult.skipped > 0 && (_jsxs("p", { className: "text-xs text-muted-foreground", children: ["Se ignoraron ", validationResult.skipped, " fila(s) de ejemplo de la plantilla."] })), validationResult.errors.length > 0 && (_jsx("div", { className: "border rounded-md max-h-60 overflow-auto", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-16", children: "Fila" }), _jsx(TableHead, { children: "Campo" }), _jsx(TableHead, { children: "Error" })] }) }), _jsx(TableBody, { children: validationResult.errors.map((error, idx) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-mono text-xs", children: error.row }), _jsx(TableCell, { className: "text-sm", children: errorColumn(error) }), _jsx(TableCell, { className: "text-sm text-destructive", children: errorMessage(error) })] }, idx))) })] }) })), importing && (_jsxs("div", { className: "space-y-2", children: [_jsx(Progress, { value: progress }), _jsxs("p", { className: "text-xs text-muted-foreground text-center", children: ["Importando... ", progress > 0 ? `${progress}%` : ''] })] }))] })), step === 'results' && importResult && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center gap-4", children: [importResult.created > 0 && (_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Check, { className: "h-4 w-4 text-green-600" }), _jsxs("span", { children: [_jsx("strong", { children: importResult.created }), " creado(s)"] })] })), importResult.errors.length > 0 && (_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-destructive" }), _jsxs("span", { children: [_jsx("strong", { children: importResult.errors.length }), " error(es)"] })] }))] }), importResult.created > 0 && importResult.errors.length === 0 && (_jsxs("div", { className: "flex items-center gap-2 rounded-md bg-green-50 dark:bg-green-950/20 p-3 text-sm text-green-700 dark:text-green-400", children: [_jsx(Check, { className: "h-4 w-4 shrink-0" }), "Todos los registros fueron importados correctamente."] })), importResult.errors.length > 0 && (_jsx("div", { className: "border rounded-md max-h-60 overflow-auto", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-16", children: "Fila" }), _jsx(TableHead, { children: "Campo" }), _jsx(TableHead, { children: "Error" })] }) }), _jsx(TableBody, { children: importResult.errors.map((error, idx) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-mono text-xs", children: error.row }), _jsx(TableCell, { className: "text-sm", children: errorColumn(error) }), _jsx(TableCell, { className: "text-sm text-destructive", children: errorMessage(error) })] }, idx))) })] }) }))] }))] }), _jsxs(DialogFooter, { className: "p-4 border-t shrink-0", children: [step === 'upload' && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: handleClose, children: "Cancelar" }), _jsxs(Button, { onClick: handleValidate, disabled: !file || validating, children: [validating && (_jsx(Loader2, { className: "h-4 w-4 mr-1 animate-spin" })), validating ? 'Validando...' : 'Validar'] })] })), step === 'validation' && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: () => setStep('upload'), disabled: importing, children: "Atras" }), _jsxs(Button, { onClick: handleImport, disabled: importing ||
|
|
171
167
|
(validationResult !== null && validationResult.valid === 0), children: [importing && (_jsx(Loader2, { className: "h-4 w-4 mr-1 animate-spin" })), importing ? 'Importando...' : 'Importar'] })] })), step === 'results' && (_jsx(Button, { onClick: handleClose, children: "Cerrar" }))] })] }) }));
|
|
172
168
|
}
|
package/dist/display-value.d.ts
CHANGED
|
@@ -33,6 +33,29 @@ export declare const RelationThumbnail: React.FC<{
|
|
|
33
33
|
getImageUrl?: (path: string) => string;
|
|
34
34
|
size?: number;
|
|
35
35
|
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Landscape-friendly identity block: wide image ON TOP, label (and optional
|
|
38
|
+
* subtitle) UNDERNEATH. Use for brand logos, product photos and any mark that
|
|
39
|
+
* is wider than it is tall — a square thumb next to text crops logos and
|
|
40
|
+
* wastes the cell. Declared via `display: "image_stack"` on a column (image
|
|
41
|
+
* URL or FK relation with a logo/photo sibling).
|
|
42
|
+
*
|
|
43
|
+
* No padded card / muted plate behind the mark — that ate table row height.
|
|
44
|
+
* The image is sized with max-width/max-height and `object-contain` only.
|
|
45
|
+
*
|
|
46
|
+
* Sizes (CSS, not Tailwind arbitrary — host safelists vary):
|
|
47
|
+
* sm — compact table (~88×32)
|
|
48
|
+
* md — default table (~112×40)
|
|
49
|
+
* lg — detail/modal (~180×72)
|
|
50
|
+
*/
|
|
51
|
+
export declare const ImageStack: React.FC<{
|
|
52
|
+
src?: string | null;
|
|
53
|
+
label?: string | null;
|
|
54
|
+
subtitle?: string | null;
|
|
55
|
+
getImageUrl?: (path: string) => string;
|
|
56
|
+
size?: 'sm' | 'md' | 'lg';
|
|
57
|
+
className?: string;
|
|
58
|
+
}>;
|
|
36
59
|
export interface DisplayOption {
|
|
37
60
|
value: string;
|
|
38
61
|
label: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display-value.d.ts","sourceRoot":"","sources":["../src/display-value.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAmBxC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAepD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,
|
|
1
|
+
{"version":3,"file":"display-value.d.ts","sourceRoot":"","sources":["../src/display-value.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAmBxC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAepD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC,IAAI,CAAC,EAAE,MAAM,CAAA;CAChB,CAiBA,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB,CAuDA,CAAA;AAED,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC;IAC/B,MAAM,EAAE,aAAa,CAAA;IACrB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB,CA8BA,CAAA"}
|
package/dist/display-value.js
CHANGED
|
@@ -58,7 +58,40 @@ export function statusColorFor(value) {
|
|
|
58
58
|
* an addon-arbitrary Tailwind class never gets dropped by a consuming app's
|
|
59
59
|
* class scan). Rendered inline alongside a label — never alone.
|
|
60
60
|
*/
|
|
61
|
-
export const RelationThumbnail = ({ src, alt, getImageUrl, size = 20 }) => (_jsxs(Avatar, { className: "shrink-0 rounded-md
|
|
61
|
+
export const RelationThumbnail = ({ src, alt, getImageUrl, size = 20 }) => (_jsxs(Avatar, { className: "shrink-0 rounded-md", style: { width: size, height: size }, children: [_jsx(AvatarImage, { src: getImageUrl ? getImageUrl(src) : src, alt: alt, className: "object-contain" }), _jsx(AvatarFallback, { className: "rounded-md bg-transparent text-[8px] font-bold text-muted-foreground", children: getInitials(alt) })] }));
|
|
62
|
+
/**
|
|
63
|
+
* Landscape-friendly identity block: wide image ON TOP, label (and optional
|
|
64
|
+
* subtitle) UNDERNEATH. Use for brand logos, product photos and any mark that
|
|
65
|
+
* is wider than it is tall — a square thumb next to text crops logos and
|
|
66
|
+
* wastes the cell. Declared via `display: "image_stack"` on a column (image
|
|
67
|
+
* URL or FK relation with a logo/photo sibling).
|
|
68
|
+
*
|
|
69
|
+
* No padded card / muted plate behind the mark — that ate table row height.
|
|
70
|
+
* The image is sized with max-width/max-height and `object-contain` only.
|
|
71
|
+
*
|
|
72
|
+
* Sizes (CSS, not Tailwind arbitrary — host safelists vary):
|
|
73
|
+
* sm — compact table (~88×32)
|
|
74
|
+
* md — default table (~112×40)
|
|
75
|
+
* lg — detail/modal (~180×72)
|
|
76
|
+
*/
|
|
77
|
+
export const ImageStack = ({ src, label, subtitle, getImageUrl, size = 'md', className }) => {
|
|
78
|
+
const dims = size === 'lg'
|
|
79
|
+
? { w: 180, h: 72, text: 'text-sm' }
|
|
80
|
+
: size === 'sm'
|
|
81
|
+
? { w: 88, h: 32, text: 'text-[11px]' }
|
|
82
|
+
: { w: 112, h: 40, text: 'text-xs' };
|
|
83
|
+
const alt = label || '';
|
|
84
|
+
const resolved = src
|
|
85
|
+
? getImageUrl
|
|
86
|
+
? getImageUrl(src)
|
|
87
|
+
: src
|
|
88
|
+
: undefined;
|
|
89
|
+
const [broken, setBroken] = React.useState(false);
|
|
90
|
+
React.useEffect(() => {
|
|
91
|
+
setBroken(false);
|
|
92
|
+
}, [resolved]);
|
|
93
|
+
return (_jsxs("span", { className: `inline-flex max-w-[220px] flex-col items-start gap-0.5 ${className ?? ''}`, title: subtitle ? `${alt} · ${subtitle}` : alt || undefined, children: [resolved && !broken ? (_jsx("img", { src: resolved, alt: alt, className: "block object-contain", style: { maxWidth: dims.w, maxHeight: dims.h, width: 'auto', height: 'auto' }, onError: () => setBroken(true) })) : (_jsx("span", { className: "flex items-center text-[10px] font-semibold tracking-wide text-muted-foreground", style: { minHeight: Math.round(dims.h * 0.55) }, children: getInitials(alt || '?') })), (label || subtitle) && (_jsxs("span", { className: `flex w-full min-w-0 flex-col items-start leading-tight ${dims.text}`, children: [label ? (_jsx("span", { className: "w-full truncate text-left font-medium text-foreground/90", children: label })) : null, subtitle ? (_jsx("span", { className: "w-full truncate text-left text-[0.7em] text-muted-foreground", children: subtitle })) : null] }))] }));
|
|
94
|
+
};
|
|
62
95
|
/**
|
|
63
96
|
* Colored option badge — the canonical "pro" pill for a select/status/badge
|
|
64
97
|
* value. Explicit backend `color` wins; otherwise a stable, cohesive color is
|
|
@@ -173,6 +173,9 @@ export declare const resolveRelationSubtitle: (col: ColumnDefinition, row: any)
|
|
|
173
173
|
export declare const ImageCell: React.FC<{
|
|
174
174
|
value: unknown;
|
|
175
175
|
getImageUrl: (path: string) => string;
|
|
176
|
+
/** Optional caption under the image (display: image_stack). */
|
|
177
|
+
label?: string;
|
|
178
|
+
stack?: boolean;
|
|
176
179
|
}>;
|
|
177
180
|
export declare function makeDefaultGetDynamicColumns(helpers?: DynamicColumnsHelpers): GetDynamicColumns;
|
|
178
181
|
/**
|
|
@@ -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;AAyC9C,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE9D,OAAO,KAAK,EAER,iBAAiB,EACpB,MAAM,wBAAwB,CAAA;AAE/B,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AA0BD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,gBAAgB,EAAE,cAAc,MAAM,KAAG,MACzB,CAAA;AAQrD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,gBAAgB,KAAG,MAAM,GAAG,SAG5D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC7B,KAAK,gBAAgB,EACrB,OAAO,OAAO,EACd,WAAW,MAAM,EACjB,SAAS,MAAM,KAChB,MAyBF,CAAA;AAsDD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OAMlE,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OAkC5D,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OACqB,CAAA;AAwFhF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,KAAG,MAGnE,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,eAAe,2DAA4D,CAAA;AAExF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC1B,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAClB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA6C5C;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,gBAAgB,EAAE,KAAK,GAAG,KAAG,MAWtE,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,gBAAgB,EAAE,KAAK,GAAG,KAAG,MAOtE,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACpC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,GACjE,MAAM,CAcR;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOxE;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,GACzB,KAAK,gBAAgB,EACrB,KAAK,GAAG,EACR,OAAO,GAAG,EACV,mBAAe,KAChB,MAAM,GAAG,SAcX,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAAI,KAAK,gBAAgB,EAAE,KAAK,GAAG,KAAG,MAOzE,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 { OptionBadge, RelationThumbnail, statusColorFor, useIsDarkTheme, } from './display-value';
|
|
26
|
+
import { ImageStack, OptionBadge, RelationThumbnail, 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';
|
|
@@ -369,7 +369,7 @@ export const resolveRelationLabel = (col, row) => {
|
|
|
369
369
|
export const resolveRelationImage = (col, row) => {
|
|
370
370
|
const sibling = getNestedValue(row, relationKeyFor(col));
|
|
371
371
|
if (sibling && typeof sibling === 'object') {
|
|
372
|
-
const img = sibling.image ?? sibling.avatar ?? sibling.photo;
|
|
372
|
+
const img = sibling.image ?? sibling.avatar ?? sibling.photo ?? sibling.logo ?? sibling.thumbnail;
|
|
373
373
|
if (img !== undefined && img !== null && img !== '')
|
|
374
374
|
return String(img);
|
|
375
375
|
}
|
|
@@ -469,12 +469,15 @@ export const resolveRelationSubtitle = (col, row) => {
|
|
|
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
471
|
*/
|
|
472
|
-
const RelationCell = ({ col, row, getImageUrl }) => {
|
|
472
|
+
const RelationCell = ({ col, row, getImageUrl, stack = false }) => {
|
|
473
473
|
const display = resolveRelationLabel(col, row);
|
|
474
474
|
if (!display)
|
|
475
475
|
return _jsx(EmptyCell, {});
|
|
476
476
|
const image = resolveRelationImage(col, row);
|
|
477
477
|
const subtitle = resolveRelationSubtitle(col, row);
|
|
478
|
+
if (stack) {
|
|
479
|
+
return (_jsx(ImageStack, { src: image || undefined, label: display, subtitle: subtitle || undefined, getImageUrl: getImageUrl, size: "md" }));
|
|
480
|
+
}
|
|
478
481
|
// FLAT reference cell: no tinted capsule around the pair. A reference is
|
|
479
482
|
// data, not a status — the pill treatment (and its per-label tint) made a
|
|
480
483
|
// products/warehouses listing read as a wall of badges. What identifies the
|
|
@@ -537,12 +540,17 @@ const AvatarCell = ({ name, desc, avatarSrc, getImageUrl }) => (_jsxs("div", { c
|
|
|
537
540
|
* form widget stores — renders the glyph instead of an <img> that would 404
|
|
538
541
|
* into an empty grey box. Exported for tests.
|
|
539
542
|
*/
|
|
540
|
-
export const ImageCell = ({ value, getImageUrl }) => {
|
|
541
|
-
if (!value)
|
|
543
|
+
export const ImageCell = ({ value, getImageUrl, label, stack = false }) => {
|
|
544
|
+
if (!value && !label)
|
|
542
545
|
return _jsx("span", { className: "text-muted-foreground", children: "-" });
|
|
543
|
-
if (isLucideIconName(value)) {
|
|
546
|
+
if (value && isLucideIconName(value)) {
|
|
544
547
|
return (_jsx("div", { className: "h-10 w-10 flex items-center justify-center rounded bg-muted", children: _jsx(DynamicIcon, { name: value, className: "h-5 w-5" }) }));
|
|
545
548
|
}
|
|
549
|
+
if (stack) {
|
|
550
|
+
return (_jsx(ImageStack, { src: value ? String(value) : undefined, label: label, getImageUrl: getImageUrl, size: "md" }));
|
|
551
|
+
}
|
|
552
|
+
if (!value)
|
|
553
|
+
return _jsx("span", { className: "text-muted-foreground", children: "-" });
|
|
546
554
|
return (_jsx("div", { className: "h-10 w-10 relative rounded overflow-hidden bg-muted flex items-center justify-center", children: _jsx("img", { src: getImageUrl(String(value)), alt: "Thumbnail", className: "h-full w-full object-contain", onError: (e) => {
|
|
547
555
|
;
|
|
548
556
|
e.currentTarget.style.display = 'none';
|
|
@@ -649,6 +657,21 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
|
|
|
649
657
|
if (renderAs === 'reference') {
|
|
650
658
|
return _jsx(ReferenceCell, { col: col, row: row.original });
|
|
651
659
|
}
|
|
660
|
+
// Landscape stack: wide image ON TOP, label UNDERNEATH.
|
|
661
|
+
if (renderAs === 'image_stack') {
|
|
662
|
+
const looksRelation = !!col.ref ||
|
|
663
|
+
(typeof col.key === 'string' &&
|
|
664
|
+
col.key.endsWith('_id') &&
|
|
665
|
+
resolveRelationLabel(col, row.original) != null);
|
|
666
|
+
if (looksRelation) {
|
|
667
|
+
return (_jsx(RelationCell, { col: col, row: row.original, getImageUrl: getImageUrl, stack: true }));
|
|
668
|
+
}
|
|
669
|
+
const labelField = styleCfg(col, 'label_field', 'labelField');
|
|
670
|
+
const caption = labelField
|
|
671
|
+
? String(getNestedValue(row.original, labelField) ?? '')
|
|
672
|
+
: undefined;
|
|
673
|
+
return (_jsx(ImageCell, { value: value, getImageUrl: getImageUrl, label: caption || undefined, stack: true }));
|
|
674
|
+
}
|
|
652
675
|
// Resolved FK relation chip. Triggers on an explicit
|
|
653
676
|
// `cellStyle: 'relation'` or on any column carrying a `ref`
|
|
654
677
|
// (a belongs_to FK) that isn't being rendered as an
|
|
@@ -849,6 +872,13 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
|
|
|
849
872
|
: 'FileText', className: "h-4 w-4" }) }, i));
|
|
850
873
|
}), 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] }))] }));
|
|
851
874
|
}
|
|
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
|
+
}
|
|
852
882
|
case 'image': {
|
|
853
883
|
const imageValue = value ||
|
|
854
884
|
(Array.isArray(row.original.media)
|
|
@@ -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":"AA2CA,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,+BA8SzB;AAED,eAAe,kBAAkB,CAAA"}
|
|
@@ -28,6 +28,7 @@ import { Check, ChevronsUpDown, Loader2, Plus, ScanLine } from 'lucide-react';
|
|
|
28
28
|
import { resolveColorCss } from '@asteby/metacore-ui/lib';
|
|
29
29
|
import { BarcodeScanner } from './barcode-scanner';
|
|
30
30
|
import { DynamicIcon, isLucideIconName } from './dynamic-icon';
|
|
31
|
+
import { useDebouncedValue } from './use-debounced-value';
|
|
31
32
|
import { useOptionsResolver } from './use-options-resolver';
|
|
32
33
|
import { getDependsOn, getFieldRef, resolveOptionsSource } from './dynamic-form-schema';
|
|
33
34
|
/**
|
|
@@ -84,12 +85,7 @@ export function OptionLead({ option, size = 20, }) {
|
|
|
84
85
|
return null;
|
|
85
86
|
}
|
|
86
87
|
function useDebounced(value, ms) {
|
|
87
|
-
|
|
88
|
-
useEffect(() => {
|
|
89
|
-
const t = setTimeout(() => setDebounced(value), ms);
|
|
90
|
-
return () => clearTimeout(t);
|
|
91
|
-
}, [value, ms]);
|
|
92
|
-
return debounced;
|
|
88
|
+
return useDebouncedValue(value, ms);
|
|
93
89
|
}
|
|
94
90
|
export function DynamicSelectField({ field, value, onChange, seedOption, dependsValue, dependsHint, readonly = false, staticOptions = null, descriptionAsBadge = false, hideCreate = false, }) {
|
|
95
91
|
const [open, setOpen] = useState(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AAgC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AAgC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AA4FnF,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/B,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAkB,EAClB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,EAC5C,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,kBAA0B,GAC7C,EAAE,iBAAiB,+BAkvCnB"}
|
package/dist/dynamic-table.js
CHANGED
|
@@ -29,6 +29,7 @@ import { translateOptionLabels } from './filter-chips';
|
|
|
29
29
|
import { dedupeById, useInfiniteScrollSentinel } from './use-infinite-scroll';
|
|
30
30
|
import { OptionsContext } from './options-context';
|
|
31
31
|
import { getSearchableColumnKeys } from './column-visibility';
|
|
32
|
+
import { useDebouncedValue } from './use-debounced-value';
|
|
32
33
|
import { useCan, usePermissionsActive, gateTableMetadata } from './permissions-context';
|
|
33
34
|
import { useDynamicRowActions } from './dynamic-row-actions';
|
|
34
35
|
import { ExportDialog } from './dialogs/export';
|
|
@@ -165,6 +166,8 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
165
166
|
pageSize: storedPageSizeRef.current ?? 10,
|
|
166
167
|
});
|
|
167
168
|
const [globalFilter, setGlobalFilter] = useState('');
|
|
169
|
+
// Debounce search → URL + fetch so each keystroke does not thrash the server.
|
|
170
|
+
const debouncedGlobalFilter = useDebouncedValue(globalFilter);
|
|
168
171
|
const [rowCount, setRowCount] = useState(bootData?.rowCount ?? 0);
|
|
169
172
|
const [dateRange, setDateRange] = useState(undefined);
|
|
170
173
|
const [dynamicFilters, setDynamicFilters] = useState({});
|
|
@@ -322,8 +325,8 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
322
325
|
params.set('sortBy', sorting[0].id);
|
|
323
326
|
params.set('order', sorting[0].desc ? 'desc' : 'asc');
|
|
324
327
|
}
|
|
325
|
-
if (
|
|
326
|
-
params.set('search',
|
|
328
|
+
if (debouncedGlobalFilter)
|
|
329
|
+
params.set('search', debouncedGlobalFilter);
|
|
327
330
|
Object.entries(dynamicFilters).forEach(([key, values]) => {
|
|
328
331
|
if (values.length === 0)
|
|
329
332
|
return;
|
|
@@ -348,7 +351,7 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
348
351
|
const newUrl = search ? `${window.location.pathname}?${search}` : window.location.pathname;
|
|
349
352
|
lastSelfSearch.current = search ? `?${search}` : '';
|
|
350
353
|
window.history.replaceState(null, '', newUrl);
|
|
351
|
-
}, [enableUrlSync, urlSynced, pagination, sorting,
|
|
354
|
+
}, [enableUrlSync, urlSynced, pagination, sorting, debouncedGlobalFilter, dynamicFilters, defaultFilters]);
|
|
352
355
|
// The host router can rewrite the query string WITHOUT remounting the
|
|
353
356
|
// table — e.g. sidebar sibling entries deep-link different `f_` filters
|
|
354
357
|
// into the same model route. The mount-time init above never re-runs, so
|
|
@@ -532,12 +535,12 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
532
535
|
params.sortBy = sorting[0].id;
|
|
533
536
|
params.order = sorting[0].desc ? 'desc' : 'asc';
|
|
534
537
|
}
|
|
535
|
-
if (
|
|
538
|
+
if (debouncedGlobalFilter) {
|
|
536
539
|
if (searchableKeys === null) {
|
|
537
|
-
params.search =
|
|
540
|
+
params.search = debouncedGlobalFilter;
|
|
538
541
|
}
|
|
539
542
|
else if (searchableKeys.length > 0) {
|
|
540
|
-
params.search =
|
|
543
|
+
params.search = debouncedGlobalFilter;
|
|
541
544
|
params.search_columns = searchableKeys.join(',');
|
|
542
545
|
}
|
|
543
546
|
// searchableKeys === [] → drop the search request entirely
|
|
@@ -567,7 +570,7 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
567
570
|
params['f_created_at'] = `${startDate}_${endDate}`;
|
|
568
571
|
}
|
|
569
572
|
return params;
|
|
570
|
-
}, [sorting,
|
|
573
|
+
}, [sorting, debouncedGlobalFilter, columnFilters, defaultFilters, dynamicFilters, dateRange, searchableKeys]);
|
|
571
574
|
const hasActiveFilters = useMemo(() => {
|
|
572
575
|
if (globalFilter)
|
|
573
576
|
return true;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface FilePickButtonProps {
|
|
2
|
+
/** Called with the picked File, or null when cleared. */
|
|
3
|
+
onFile: (file: File | null) => void;
|
|
4
|
+
accept?: string;
|
|
5
|
+
/** HTML capture attribute (e.g. "environment" for rear camera). */
|
|
6
|
+
capture?: boolean | 'user' | 'environment';
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
/** When true, shows replace + clear affordances. */
|
|
10
|
+
hasFile?: boolean;
|
|
11
|
+
/** Optional display name next to the button when hasFile. */
|
|
12
|
+
fileName?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
/** Override the empty-state pick label (still falls back to i18n). */
|
|
15
|
+
pickLabel?: string;
|
|
16
|
+
replaceLabel?: string;
|
|
17
|
+
clearLabel?: string;
|
|
18
|
+
id?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function FilePickButton({ onFile, accept, capture, disabled, loading, hasFile, fileName, className, pickLabel, replaceLabel, clearLabel, id: idProp, }: FilePickButtonProps): import("react").JSX.Element;
|
|
21
|
+
//# sourceMappingURL=file-pick-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-pick-button.d.ts","sourceRoot":"","sources":["../src/file-pick-button.tsx"],"names":[],"mappings":"AAUA,MAAM,WAAW,mBAAmB;IAChC,yDAAyD;IACzD,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,aAAa,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,EAAE,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,cAAc,CAAC,EAC3B,MAAM,EACN,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,SAAS,EACT,YAAY,EACZ,UAAU,EACV,EAAE,EAAE,MAAM,GACb,EAAE,mBAAmB,+BAiFrB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// FilePickButton — locale-aware file picker. Native <input type="file"> always
|
|
3
|
+
// paints the browser/OS chrome ("Choose File" / "No file chosen") in the
|
|
4
|
+
// *browser* language, not the app language — so Spanish UIs on an English
|
|
5
|
+
// Chrome show English. Hide the native control and drive it from a Button
|
|
6
|
+
// whose labels come from i18n (common.upload.*).
|
|
7
|
+
import { useCallback, useId, useRef } from 'react';
|
|
8
|
+
import { useTranslation } from 'react-i18next';
|
|
9
|
+
import { Button } from '@asteby/metacore-ui/primitives';
|
|
10
|
+
import { Loader2, Paperclip, X } from 'lucide-react';
|
|
11
|
+
export function FilePickButton({ onFile, accept, capture, disabled, loading, hasFile, fileName, className, pickLabel, replaceLabel, clearLabel, id: idProp, }) {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
const autoId = useId();
|
|
14
|
+
const id = idProp || autoId;
|
|
15
|
+
const inputRef = useRef(null);
|
|
16
|
+
const busy = Boolean(disabled || loading);
|
|
17
|
+
const pick = useCallback(() => {
|
|
18
|
+
if (busy)
|
|
19
|
+
return;
|
|
20
|
+
inputRef.current?.click();
|
|
21
|
+
}, [busy]);
|
|
22
|
+
const onChange = useCallback((e) => {
|
|
23
|
+
const file = e.target.files?.[0] ?? null;
|
|
24
|
+
if (inputRef.current)
|
|
25
|
+
inputRef.current.value = '';
|
|
26
|
+
if (file)
|
|
27
|
+
onFile(file);
|
|
28
|
+
}, [onFile]);
|
|
29
|
+
const onClear = useCallback(() => {
|
|
30
|
+
if (busy)
|
|
31
|
+
return;
|
|
32
|
+
onFile(null);
|
|
33
|
+
}, [busy, onFile]);
|
|
34
|
+
const emptyLabel = pickLabel || t('common.upload.choose', { defaultValue: 'Choose file' });
|
|
35
|
+
const filledLabel = replaceLabel || t('common.upload.replace', { defaultValue: 'Replace' });
|
|
36
|
+
const removeLabel = clearLabel || t('common.upload.remove', { defaultValue: 'Remove file' });
|
|
37
|
+
const emptyHint = t('common.upload.none', { defaultValue: 'No file chosen' });
|
|
38
|
+
return (_jsxs("div", { className: className ? `grid gap-1.5 ${className}` : 'grid gap-1.5', "data-widget": "file-pick", children: [_jsx("input", { ref: inputRef, id: id, type: "file", accept: accept, ...(capture !== undefined ? { capture } : {}), className: "sr-only", onChange: onChange, tabIndex: -1, "aria-hidden": "true" }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: pick, disabled: busy, children: [loading ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : (_jsx(Paperclip, { className: "mr-2 h-4 w-4" })), hasFile ? filledLabel : emptyLabel] }), hasFile ? (_jsxs("div", { className: "flex min-w-0 items-center gap-1 text-sm text-muted-foreground", children: [fileName ? (_jsx("span", { className: "truncate", title: fileName, children: fileName })) : null, _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-6 w-6 p-0", onClick: onClear, disabled: busy, "aria-label": removeLabel, children: _jsx(X, { className: "h-3.5 w-3.5" }) })] })) : (_jsx("span", { className: "text-xs text-muted-foreground", children: emptyHint }))] })] }));
|
|
39
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,9 @@ export { useStageLayout, type StageLayout, type UseStageLayoutResult, } from './
|
|
|
12
12
|
export { useStageOverrides, type StageOverridePatch, type UseStageOverridesResult, } from './stage-overrides';
|
|
13
13
|
export { DynamicView, resolveViewRenderer, readViewFromSearch, resolveActiveView, type DynamicViewProps, } from './dynamic-view';
|
|
14
14
|
export { useDynamicFilters, type UseDynamicFiltersOptions, type UseDynamicFiltersResult, } from './use-dynamic-filters';
|
|
15
|
+
export { useDebouncedValue, SEARCH_DEBOUNCE_MS } from './use-debounced-value';
|
|
15
16
|
export * from './dynamic-form';
|
|
17
|
+
export { FilePickButton, type FilePickButtonProps, } from './file-pick-button';
|
|
16
18
|
export * from './barcode-scanner';
|
|
17
19
|
export * from './form-layout';
|
|
18
20
|
export * from './form-layout-ui';
|
|
@@ -45,6 +47,7 @@ export type { ColumnFilterConfig, FilterOption as DynamicColumnFilterOption, Get
|
|
|
45
47
|
export { defaultGetDynamicColumns, makeDefaultGetDynamicColumns, relationKeyFor, resolveAvatarSrc, resolveMissingActorLabel, resolveActorDisplayName, resolveRelationLabel, type DynamicColumnsHelpers, } from './dynamic-columns';
|
|
46
48
|
export { humanizeToken } from './dynamic-columns-helpers';
|
|
47
49
|
export { UrlChip, FileChip, ImageThumbnail, MediaValue, RichText, linkifyText, classifyUrl, isImageUrl, isFileUrl, ensureHref, smartUrlLabel, fileNameFromUrl, splitTrailingPunct, type UrlKind, type LinkifyOptions, } from './rich-url';
|
|
50
|
+
export { ImageStack, OptionBadge, statusColorFor, useIsDarkTheme, } from './display-value';
|
|
48
51
|
export { CollectionCell, formatScalar, prettifyKey, countLabel, type CollectionCellProps, type Translate as CollectionCellTranslate, } from './collection-cell';
|
|
49
52
|
export { NIL_UUID, isNilUuid, normalizeNilUuid } from './nil-uuid';
|
|
50
53
|
export { DynamicRecordDialog, ViewValue } from './dialogs/dynamic-record';
|
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":"AAKA,cAAc,SAAS,CAAA;AACvB,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,WAAW,CAAA;AAClB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,UAAU,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,KAAK,cAAc,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AACnG,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,EACvB,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,GACnC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,GAC9B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,oBAAoB,GAC5B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,GAC/B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,gBAAgB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC/B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC7E,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,cAAc,EACd,KAAK,mBAAmB,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EACH,qBAAqB,EACrB,KAAK,gBAAgB,GACxB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,KAAK,uBAAuB,EAC5B,KAAK,eAAe,GACvB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACtB,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,mBAAmB,EACnB,MAAM,EACN,oBAAoB,EACpB,OAAO,EACP,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,KAAK,EACV,KAAK,wBAAwB,GAChC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,GACzB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,OAAO,EACZ,KAAK,SAAS,GACjB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,8BAA8B,GACtC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,WAAW,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC9B,MAAM,yBAAyB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,YAAY,EACR,kBAAkB,EAClB,YAAY,IAAI,yBAAyB,EACzC,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,qBAAqB,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EACH,OAAO,EACP,QAAQ,EACR,cAAc,EACd,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,UAAU,EACV,WAAW,EACX,cAAc,EACd,cAAc,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,YAAY,EACZ,WAAW,EACX,UAAU,EACV,KAAK,mBAAmB,EACxB,KAAK,SAAS,IAAI,uBAAuB,GAC5C,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC5G,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,YAAY,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC9B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GAC3B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACH,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,GACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,qBAAqB,EACrB,KAAK,0BAA0B,GAClC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,GAC1B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,gBAAgB,EAChB,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,aAAa,EACb,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC/D,YAAY,EACR,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,UAAU,EACV,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,cAAc,EACd,KAAK,iBAAiB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,cAAc,EACd,cAAc,EACd,SAAS,EACT,UAAU,EACV,KAAK,mBAAmB,GAC3B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,UAAU,EACV,SAAS,EACT,WAAW,EACX,WAAW,EACX,KAAK,eAAe,GACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,aAAa,EACb,YAAY,EACZ,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA"}
|