@vertebr/react 0.11.0 → 0.13.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/dist/components/admin/AdminContent.d.ts.map +1 -1
- package/dist/components/admin/AdminContent.js +7 -10
- package/dist/components/admin/VertebrAdmin.d.ts.map +1 -1
- package/dist/components/admin/VertebrAdmin.js +6 -4
- package/dist/components/config/DescriptionInput.d.ts +3 -1
- package/dist/components/config/DescriptionInput.d.ts.map +1 -1
- package/dist/components/config/DescriptionInput.js +2 -2
- package/dist/components/config/DocumentAttachmentField.d.ts +17 -0
- package/dist/components/config/DocumentAttachmentField.d.ts.map +1 -0
- package/dist/components/config/DocumentAttachmentField.js +32 -0
- package/dist/components/config/ImagePickerModal.d.ts +12 -1
- package/dist/components/config/ImagePickerModal.d.ts.map +1 -1
- package/dist/components/config/ImagePickerModal.js +52 -23
- package/dist/components/config/MarkdownDocumentModal.d.ts +19 -0
- package/dist/components/config/MarkdownDocumentModal.d.ts.map +1 -0
- package/dist/components/config/MarkdownDocumentModal.js +34 -0
- package/dist/components/config/form/ConfigField.d.ts.map +1 -1
- package/dist/components/config/form/ConfigField.js +129 -15
- package/dist/components/config/form/RecordConfigForm.d.ts.map +1 -1
- package/dist/components/config/form/RecordConfigForm.js +24 -10
- package/dist/components/fonts/FontLibraryBoard.d.ts.map +1 -1
- package/dist/components/fonts/FontLibraryBoard.js +1 -1
- package/dist/components/gallery/GalleryBoard.d.ts.map +1 -1
- package/dist/components/gallery/GalleryBoard.js +37 -5
- package/dist/components/resources/ImageUploadControl.d.ts +3 -1
- package/dist/components/resources/ImageUploadControl.d.ts.map +1 -1
- package/dist/components/resources/ImageUploadControl.js +5 -3
- package/dist/lib/documents.d.ts +14 -0
- package/dist/lib/documents.d.ts.map +1 -0
- package/dist/lib/documents.js +42 -0
- package/dist/styles/form.css +28 -0
- package/dist/styles/gallery.css +237 -0
- package/dist/styles/modal.css +2 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminContent.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminContent.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"AdminContent.d.ts","sourceRoot":"","sources":["../../../src/components/admin/AdminContent.tsx"],"names":[],"mappings":"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"}
|
|
@@ -85,11 +85,8 @@ export function AdminContent({ client, catalog, selection, onSelectionChange, au
|
|
|
85
85
|
: "Unable to load catalog." }) }) }));
|
|
86
86
|
}
|
|
87
87
|
return (_jsx("div", { className: "vertebr-content", children: _jsxs("section", { className: "vertebr-panel", children: [selection?.kind === "overview" ? (_jsx(MetricsBoard, { label: metricsData?.label ?? catalog.metrics?.label, windowLabel: metricsData?.windowLabel, compareLabel: metricsData?.compareLabel, metrics: metricsData?.metrics ?? [], charts: metricsData?.charts ?? [], range: metricsRange, onRangeChange: onMetricsRangeChange, loading: metricsLoading, onRefresh: () => void onRefreshMetrics() })) : null, selection?.kind === "audit" ? (_jsx(AuditBoard, { client: client, label: catalog.audit?.label })) : null, selection?.kind === "sync" ? (_jsx(AdminSyncPage, { client: client, catalog: catalog })) : null, selection?.kind === "gallery" && galleryData ? (_jsx(GalleryBoard, { label: galleryData.label, items: galleryData.items, accept: galleryData.accept, maxBytes: galleryData.maxBytes, canDelete: galleryData.canDelete, loading: galleryLoading, onRefresh: () => void onRefreshGallery(), onUpload: async (files) => {
|
|
88
|
-
|
|
89
|
-
await client.uploadGalleryFile(
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
await client.uploadGalleryFiles(files);
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
await client.uploadGalleryFile(file);
|
|
93
90
|
}
|
|
94
91
|
await onRefreshGallery();
|
|
95
92
|
}, onDelete: galleryData.canDelete
|
|
@@ -192,12 +189,12 @@ export function AdminContent({ client, catalog, selection, onSelectionChange, au
|
|
|
192
189
|
}
|
|
193
190
|
: undefined, onUpload: resourceData.uploads
|
|
194
191
|
? async (field, files) => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
192
|
+
const uploaded = [];
|
|
193
|
+
for (const file of files) {
|
|
194
|
+
const result = await client.uploadResourceFile(resourceData.id, field, file);
|
|
195
|
+
uploaded.push({ url: result.url, name: result.name });
|
|
198
196
|
}
|
|
199
|
-
|
|
200
|
-
return result.files;
|
|
197
|
+
return uploaded;
|
|
201
198
|
}
|
|
202
199
|
: undefined, ...galleryPicker })) : null, selection?.kind === "addons" ? (_jsx(AddonOverview, { client: client, catalog: catalog, onSelectAddon: (id) => onSelectionChange?.({ kind: "addon", id }) })) : null, selection?.kind === "config" && configData ? (_jsx(ConfigEditor, { client: client, catalog: catalog, configData: configData, isPageSelection: isPageSelection, previewPath: catalog.configs.find((item) => item.id === configData.id)
|
|
203
200
|
?.previewPath, relatedAddons: catalog.configs.find((item) => item.id === configData.id)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VertebrAdmin.d.ts","sourceRoot":"","sources":["../../../src/components/admin/VertebrAdmin.tsx"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,wBAAgB,YAAY,CAAC,EAC3B,OAAsB,EACtB,QAAQ,EAAE,YAAY,EACtB,KAAuB,EACvB,aAA6B,EAC7B,eAAiC,EACjC,eAAiC,EACjC,sBAAgD,EAChD,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE,iBAAiB,+
|
|
1
|
+
{"version":3,"file":"VertebrAdmin.d.ts","sourceRoot":"","sources":["../../../src/components/admin/VertebrAdmin.tsx"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,wBAAgB,YAAY,CAAC,EAC3B,OAAsB,EACtB,QAAQ,EAAE,YAAY,EACtB,KAAuB,EACvB,aAA6B,EAC7B,eAAiC,EACjC,eAAiC,EACjC,sBAAgD,EAChD,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE,iBAAiB,+BAkuBnB"}
|
|
@@ -380,11 +380,13 @@ export function VertebrAdmin({ apiBase = "/admin/api", basePath: basePathProp, t
|
|
|
380
380
|
return data.items;
|
|
381
381
|
}, [client]);
|
|
382
382
|
const uploadGallery = useCallback(async (files) => {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
383
|
+
// Upload one file per request — base64 bulk payloads easily exceed the
|
|
384
|
+
// host HTTP body limit when several product photos are selected.
|
|
385
|
+
const items = [];
|
|
386
|
+
for (const file of files) {
|
|
387
|
+
const { item } = await client.uploadGalleryFile(file);
|
|
388
|
+
items.push(item);
|
|
386
389
|
}
|
|
387
|
-
const { items } = await client.uploadGalleryFiles(files);
|
|
388
390
|
return items;
|
|
389
391
|
}, [client]);
|
|
390
392
|
const galleryPicker = catalog?.gallery
|
|
@@ -13,6 +13,8 @@ export type DescriptionInputProps = {
|
|
|
13
13
|
onBlur?: () => void;
|
|
14
14
|
onChange: (next: string) => void;
|
|
15
15
|
inputRef?: React.Ref<HTMLElement>;
|
|
16
|
+
/** Opens a document-style modal for focused policy editing. */
|
|
17
|
+
onOpenDocumentView?: () => void;
|
|
16
18
|
};
|
|
17
|
-
export declare function DescriptionInput({ id, name, value, readOnly, placeholder, recordImages, galleryUpload, onListGallery, onUploadGallery, onBlur, onChange, inputRef, }: DescriptionInputProps): import("react").JSX.Element;
|
|
19
|
+
export declare function DescriptionInput({ id, name, value, readOnly, placeholder, recordImages, galleryUpload, onListGallery, onUploadGallery, onBlur, onChange, inputRef, onOpenDocumentView, }: DescriptionInputProps): import("react").JSX.Element;
|
|
18
20
|
//# sourceMappingURL=DescriptionInput.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DescriptionInput.d.ts","sourceRoot":"","sources":["../../../src/components/config/DescriptionInput.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"DescriptionInput.d.ts","sourceRoot":"","sources":["../../../src/components/config/DescriptionInput.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAClC,+DAA+D;IAC/D,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;CACjC,CAAC;AAoCF,wBAAgB,gBAAgB,CAAC,EAC/B,EAAE,EACF,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,WAAoC,EACpC,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,kBAAkB,GACnB,EAAE,qBAAqB,+BAqTvB"}
|
|
@@ -19,7 +19,7 @@ function assignRef(ref, node) {
|
|
|
19
19
|
function ToolbarButton({ active, disabled, title, onClick, children, }) {
|
|
20
20
|
return (_jsx("button", { type: "button", className: "vertebr-md-btn", "data-active": active || undefined, disabled: disabled, title: title, onMouseDown: (event) => event.preventDefault(), onClick: onClick, children: children }));
|
|
21
21
|
}
|
|
22
|
-
export function DescriptionInput({ id, name, value, readOnly, placeholder = "Write a description…", recordImages, galleryUpload, onListGallery, onUploadGallery, onBlur, onChange, inputRef, }) {
|
|
22
|
+
export function DescriptionInput({ id, name, value, readOnly, placeholder = "Write a description…", recordImages, galleryUpload, onListGallery, onUploadGallery, onBlur, onChange, inputRef, onOpenDocumentView, }) {
|
|
23
23
|
const text = typeof value === "string" ? value : "";
|
|
24
24
|
const onChangeRef = useRef(onChange);
|
|
25
25
|
const onBlurRef = useRef(onBlur);
|
|
@@ -148,5 +148,5 @@ export function DescriptionInput({ id, name, value, readOnly, placeholder = "Wri
|
|
|
148
148
|
rows: 3,
|
|
149
149
|
cols: 3,
|
|
150
150
|
withHeaderRow: true,
|
|
151
|
-
}).run(), children: "Table" }), marks?.table ? (_jsxs(_Fragment, { children: [_jsx(ToolbarButton, { disabled: locked, title: "Add column", onClick: () => editor?.chain().focus().addColumnAfter().run(), children: "+Col" }), _jsx(ToolbarButton, { disabled: locked, title: "Add row", onClick: () => editor?.chain().focus().addRowAfter().run(), children: "+Row" }), _jsx(ToolbarButton, { disabled: locked, title: "Delete table", onClick: () => editor?.chain().focus().deleteTable().run(), children: "Del" })] })) : null, _jsx(ToolbarButton, { active: marks?.link, disabled: locked, title: "Link", onClick: setLink, children: "Link" }), _jsx(ToolbarButton, { disabled: locked, title: "Insert images", onClick: () => setPickerOpen(true), children: "Image" })] }), _jsx(EditorContent, { editor: editor }), _jsxs("p", { className: "vertebr-field-prose-meta", children: ["Markdown", _jsx("span", { "aria-hidden": "true", children: " \u00B7 " }), stats.words, " ", stats.words === 1 ? "word" : "words", _jsx("span", { "aria-hidden": "true", children: " \u00B7 " }), stats.characters, " ", stats.characters === 1 ? "character" : "characters"] }), pickerOpen ? (_jsx(ImagePickerModal, { recordImages: recordImages, galleryUpload: galleryUpload, onListGallery: onListGallery, onUploadGallery: onUploadGallery, onClose: () => setPickerOpen(false), onInsert: insertImages })) : null] }));
|
|
151
|
+
}).run(), children: "Table" }), marks?.table ? (_jsxs(_Fragment, { children: [_jsx(ToolbarButton, { disabled: locked, title: "Add column", onClick: () => editor?.chain().focus().addColumnAfter().run(), children: "+Col" }), _jsx(ToolbarButton, { disabled: locked, title: "Add row", onClick: () => editor?.chain().focus().addRowAfter().run(), children: "+Row" }), _jsx(ToolbarButton, { disabled: locked, title: "Delete table", onClick: () => editor?.chain().focus().deleteTable().run(), children: "Del" })] })) : null, _jsx(ToolbarButton, { active: marks?.link, disabled: locked, title: "Link", onClick: setLink, children: "Link" }), _jsx(ToolbarButton, { disabled: locked, title: "Insert images", onClick: () => setPickerOpen(true), children: "Image" }), onOpenDocumentView ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "vertebr-md-sep", "aria-hidden": "true" }), _jsx(ToolbarButton, { disabled: false, title: "Open document view", onClick: onOpenDocumentView, children: "Doc" })] })) : null] }), _jsx(EditorContent, { editor: editor }), _jsxs("p", { className: "vertebr-field-prose-meta", children: ["Markdown", _jsx("span", { "aria-hidden": "true", children: " \u00B7 " }), stats.words, " ", stats.words === 1 ? "word" : "words", _jsx("span", { "aria-hidden": "true", children: " \u00B7 " }), stats.characters, " ", stats.characters === 1 ? "character" : "characters", onOpenDocumentView ? (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": "true", children: " \u00B7 " }), _jsx("button", { type: "button", className: "vertebr-md-doc-link", onClick: onOpenDocumentView, children: "Open in document view" })] })) : null] }), pickerOpen ? (_jsx(ImagePickerModal, { recordImages: recordImages, galleryUpload: galleryUpload, onListGallery: onListGallery, onUploadGallery: onUploadGallery, onClose: () => setPickerOpen(false), onInsert: insertImages })) : null] }));
|
|
152
152
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type DocumentAttachmentFieldProps = {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
readOnly?: boolean;
|
|
6
|
+
description?: string;
|
|
7
|
+
/** Sibling markdown body available for document-view editing. */
|
|
8
|
+
markdownBody?: string;
|
|
9
|
+
canPickFiles?: boolean;
|
|
10
|
+
canUpload?: boolean;
|
|
11
|
+
onChangeUrl: (next: string) => void;
|
|
12
|
+
onOpenPicker?: () => void;
|
|
13
|
+
onUploadFiles?: (files: File[]) => Promise<void>;
|
|
14
|
+
onEditMarkdown?: () => void;
|
|
15
|
+
};
|
|
16
|
+
export declare function DocumentAttachmentField({ id, label, value, readOnly, description, markdownBody, canPickFiles, canUpload, onChangeUrl, onOpenPicker, onUploadFiles, onEditMarkdown, }: DocumentAttachmentFieldProps): import("react").JSX.Element;
|
|
17
|
+
//# sourceMappingURL=DocumentAttachmentField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocumentAttachmentField.d.ts","sourceRoot":"","sources":["../../../src/components/config/DocumentAttachmentField.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,4BAA4B,GAAG;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,EACtC,EAAE,EACF,KAAK,EACL,KAAK,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,WAAW,EACX,YAAY,EACZ,aAAa,EACb,cAAc,GACf,EAAE,4BAA4B,+BAqI9B"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
import { pdfFileName } from "../../lib/documents";
|
|
4
|
+
export function DocumentAttachmentField({ id, label, value, readOnly, description, markdownBody, canPickFiles, canUpload, onChangeUrl, onOpenPicker, onUploadFiles, onEditMarkdown, }) {
|
|
5
|
+
const inputRef = useRef(null);
|
|
6
|
+
const [busy, setBusy] = useState(false);
|
|
7
|
+
const [showUrl, setShowUrl] = useState(() => Boolean(value.trim()));
|
|
8
|
+
const url = value.trim();
|
|
9
|
+
const hasPdf = Boolean(url);
|
|
10
|
+
const canEditMd = Boolean(onEditMarkdown && markdownBody !== undefined);
|
|
11
|
+
const handleFiles = async (files) => {
|
|
12
|
+
if (!files?.length || !onUploadFiles || readOnly)
|
|
13
|
+
return;
|
|
14
|
+
setBusy(true);
|
|
15
|
+
try {
|
|
16
|
+
await onUploadFiles([...files]);
|
|
17
|
+
setShowUrl(true);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
setBusy(false);
|
|
21
|
+
if (inputRef.current)
|
|
22
|
+
inputRef.current.value = "";
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
return (_jsxs("div", { className: "vertebr-doc-attach", children: [_jsxs("div", { className: "vertebr-doc-attach-card", "data-has-file": hasPdf || undefined, children: [_jsxs("div", { className: "vertebr-doc-attach-main", children: [_jsx("div", { className: "vertebr-doc-attach-icon", "aria-hidden": "true", children: "PDF" }), _jsxs("div", { className: "vertebr-doc-attach-copy", children: [_jsx("p", { className: "vertebr-doc-attach-title", children: hasPdf ? pdfFileName(url) : "No PDF attached" }), _jsx("p", { className: "vertebr-doc-attach-hint", children: hasPdf
|
|
26
|
+
? "Optional download for shoppers. Markdown remains the live policy."
|
|
27
|
+
: description?.trim() ||
|
|
28
|
+
"Optional PDF download. Markdown remains the live policy." })] })] }), _jsxs("div", { className: "vertebr-doc-attach-actions", children: [canEditMd ? (_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-primary", onClick: onEditMarkdown, children: "Edit document" })) : null, canPickFiles && !readOnly ? (_jsx("button", { type: "button", className: "vertebr-btn", onClick: onOpenPicker, disabled: busy, children: "Choose PDF" })) : null, canUpload && !readOnly ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "vertebr-btn", disabled: busy, onClick: () => inputRef.current?.click(), children: busy ? "Uploading…" : "Upload" }), _jsx("input", { ref: inputRef, type: "file", accept: "application/pdf,.pdf", hidden: true, onChange: (event) => void handleFiles(event.target.files) })] })) : null, hasPdf ? (_jsx("a", { className: "vertebr-btn", href: url, target: "_blank", rel: "noreferrer", children: "Open" })) : null, hasPdf && !readOnly ? (_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet", onClick: () => {
|
|
29
|
+
onChangeUrl("");
|
|
30
|
+
setShowUrl(false);
|
|
31
|
+
}, children: "Remove" })) : null] })] }), !readOnly ? (showUrl ? (_jsxs("label", { className: "vertebr-doc-attach-url", htmlFor: id, children: [_jsxs("span", { children: [label, " URL"] }), _jsx("input", { id: id, type: "url", placeholder: "https://\u2026/policy.pdf", value: value, onChange: (event) => onChangeUrl(event.target.value) })] })) : (_jsx("button", { type: "button", className: "vertebr-doc-attach-url-toggle", onClick: () => setShowUrl(true), children: "Paste PDF URL" }))) : hasPdf ? (_jsxs("label", { className: "vertebr-doc-attach-url", htmlFor: id, children: [_jsxs("span", { children: [label, " URL"] }), _jsx("input", { id: id, type: "url", readOnly: true, value: value })] })) : null] }));
|
|
32
|
+
}
|
|
@@ -6,6 +6,8 @@ export type PickerImage = {
|
|
|
6
6
|
name: string;
|
|
7
7
|
source: "record" | "gallery" | "url";
|
|
8
8
|
};
|
|
9
|
+
type Tab = "record" | "gallery";
|
|
10
|
+
type AssetKind = "image" | "document" | "any";
|
|
9
11
|
export type ImagePickerModalProps = {
|
|
10
12
|
recordImages?: RecordImage[];
|
|
11
13
|
galleryUpload?: Pick<ResourceUploadMeta, "accept" | "maxBytes">;
|
|
@@ -13,6 +15,15 @@ export type ImagePickerModalProps = {
|
|
|
13
15
|
onUploadGallery?: (files: File[]) => Promise<GalleryItem[]>;
|
|
14
16
|
onClose: () => void;
|
|
15
17
|
onInsert: (images: PickerImage[]) => void;
|
|
18
|
+
/** Dialog heading. @default "Choose images" */
|
|
19
|
+
title?: string;
|
|
20
|
+
/** Primary action label prefix. @default "Use" */
|
|
21
|
+
confirmLabel?: string;
|
|
22
|
+
/** Prefer Files tab when both product photos and gallery exist. */
|
|
23
|
+
defaultTab?: Tab;
|
|
24
|
+
/** Limit Files library to images or PDFs. @default "image" */
|
|
25
|
+
assetKind?: AssetKind;
|
|
16
26
|
};
|
|
17
|
-
export declare function ImagePickerModal({ recordImages, galleryUpload, onListGallery, onUploadGallery, onClose, onInsert, }: ImagePickerModalProps): import("react").
|
|
27
|
+
export declare function ImagePickerModal({ recordImages, galleryUpload, onListGallery, onUploadGallery, onClose, onInsert, title, confirmLabel, defaultTab, assetKind, }: ImagePickerModalProps): import("react").ReactPortal;
|
|
28
|
+
export {};
|
|
18
29
|
//# sourceMappingURL=ImagePickerModal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImagePickerModal.d.ts","sourceRoot":"","sources":["../../../src/components/config/ImagePickerModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ImagePickerModal.d.ts","sourceRoot":"","sources":["../../../src/components/config/ImagePickerModal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;CACtC,CAAC;AAEF,KAAK,GAAG,GAAG,QAAQ,GAAG,SAAS,CAAC;AAChC,KAAK,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC;AAE9C,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAC1C,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAC/B,YAAiB,EACjB,aAAa,EACb,aAAa,EACb,eAAe,EACf,OAAO,EACP,QAAQ,EACR,KAAuB,EACvB,YAAoB,EACpB,UAAU,EACV,SAAmB,GACpB,EAAE,qBAAqB,+BAqSvB"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
import { filterGalleryByKind, isPdfAsset } from "../../lib/documents";
|
|
3
5
|
import { ImageUploadControl } from "../resources/ImageUploadControl";
|
|
4
|
-
export function ImagePickerModal({ recordImages = [], galleryUpload, onListGallery, onUploadGallery, onClose, onInsert, }) {
|
|
6
|
+
export function ImagePickerModal({ recordImages = [], galleryUpload, onListGallery, onUploadGallery, onClose, onInsert, title = "Choose images", confirmLabel = "Use", defaultTab, assetKind = "image", }) {
|
|
5
7
|
const hasGallery = Boolean(onListGallery);
|
|
6
|
-
const
|
|
8
|
+
const docsOnly = assetKind === "document";
|
|
9
|
+
const [tab, setTab] = useState(() => {
|
|
10
|
+
if (defaultTab)
|
|
11
|
+
return defaultTab;
|
|
12
|
+
if (!docsOnly && recordImages.length)
|
|
13
|
+
return "record";
|
|
14
|
+
return "gallery";
|
|
15
|
+
});
|
|
7
16
|
const [gallery, setGallery] = useState([]);
|
|
8
17
|
const [loading, setLoading] = useState(false);
|
|
9
18
|
const [error, setError] = useState(null);
|
|
@@ -31,7 +40,7 @@ export function ImagePickerModal({ recordImages = [], galleryUpload, onListGalle
|
|
|
31
40
|
void onListGallery()
|
|
32
41
|
.then((items) => {
|
|
33
42
|
if (!cancelled)
|
|
34
|
-
setGallery(items);
|
|
43
|
+
setGallery(filterGalleryByKind(items, assetKind));
|
|
35
44
|
})
|
|
36
45
|
.catch((err) => {
|
|
37
46
|
if (!cancelled) {
|
|
@@ -45,13 +54,15 @@ export function ImagePickerModal({ recordImages = [], galleryUpload, onListGalle
|
|
|
45
54
|
return () => {
|
|
46
55
|
cancelled = true;
|
|
47
56
|
};
|
|
48
|
-
}, [hasGallery, onListGallery]);
|
|
49
|
-
const recordTiles = useMemo(() =>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
}, [hasGallery, onListGallery, assetKind]);
|
|
58
|
+
const recordTiles = useMemo(() => docsOnly
|
|
59
|
+
? []
|
|
60
|
+
: recordImages.map((image) => ({
|
|
61
|
+
id: `record:${image.id}`,
|
|
62
|
+
url: image.url,
|
|
63
|
+
name: image.name,
|
|
64
|
+
source: "record",
|
|
65
|
+
})), [recordImages, docsOnly]);
|
|
55
66
|
const galleryTiles = useMemo(() => gallery.map((item) => ({
|
|
56
67
|
id: `gallery:${item.id}`,
|
|
57
68
|
url: item.url,
|
|
@@ -61,6 +72,8 @@ export function ImagePickerModal({ recordImages = [], galleryUpload, onListGalle
|
|
|
61
72
|
const tiles = tab === "record" ? recordTiles : galleryTiles;
|
|
62
73
|
const picked = Object.values(selected);
|
|
63
74
|
const canGalleryUpload = Boolean(galleryUpload && onUploadGallery);
|
|
75
|
+
const unit = docsOnly ? "document" : "image";
|
|
76
|
+
const units = docsOnly ? "documents" : "images";
|
|
64
77
|
const toggle = (image) => {
|
|
65
78
|
setSelected((current) => {
|
|
66
79
|
const next = { ...current };
|
|
@@ -78,22 +91,33 @@ export function ImagePickerModal({ recordImages = [], galleryUpload, onListGalle
|
|
|
78
91
|
const image = {
|
|
79
92
|
id: `url:${href}`,
|
|
80
93
|
url: href,
|
|
81
|
-
name: "Image",
|
|
94
|
+
name: docsOnly ? "Document" : "Image",
|
|
82
95
|
source: "url",
|
|
83
96
|
};
|
|
84
97
|
setSelected((current) => ({ ...current, [image.id]: image }));
|
|
85
98
|
setUrl("");
|
|
86
99
|
};
|
|
87
|
-
|
|
100
|
+
const galleryAccept = docsOnly && galleryUpload
|
|
101
|
+
? {
|
|
102
|
+
...galleryUpload,
|
|
103
|
+
accept: galleryUpload.accept.some((entry) => /pdf/i.test(entry))
|
|
104
|
+
? galleryUpload.accept
|
|
105
|
+
: [...galleryUpload.accept, "application/pdf"],
|
|
106
|
+
}
|
|
107
|
+
: galleryUpload;
|
|
108
|
+
return createPortal(_jsx("div", { className: "vertebr-modal-backdrop", role: "presentation", onClick: onClose, children: _jsxs("div", { className: "vertebr-modal", role: "dialog", "aria-modal": "true", "aria-label": title, onClick: (event) => event.stopPropagation(), children: [_jsxs("header", { className: "vertebr-modal-head", children: [_jsxs("div", { className: "vertebr-modal-heading", children: [_jsx("p", { className: "vertebr-modal-eyebrow", children: docsOnly ? "Documents" : "Media" }), _jsx("h2", { children: title })] }), _jsx("button", { type: "button", className: "vertebr-btn", onClick: onClose, children: "Close" })] }), _jsxs("div", { className: "vertebr-modal-body vertebr-picker-body", children: [!docsOnly && recordImages.length > 0 && hasGallery ? (_jsxs("div", { className: "vertebr-picker-tabs", role: "tablist", children: [_jsxs("button", { type: "button", role: "tab", "aria-selected": tab === "record", "data-active": tab === "record" || undefined, onClick: () => setTab("record"), children: ["Product photos", _jsx("span", { children: recordTiles.length })] }), _jsxs("button", { type: "button", role: "tab", "aria-selected": tab === "gallery", "data-active": tab === "gallery" || undefined, onClick: () => setTab("gallery"), children: ["Files", _jsx("span", { children: loading ? "…" : galleryTiles.length })] })] })) : null, tab === "gallery" && canGalleryUpload && galleryAccept ? (_jsx(ImageUploadControl, { meta: {
|
|
88
109
|
field: "gallery",
|
|
89
|
-
accept:
|
|
90
|
-
maxBytes:
|
|
91
|
-
}, multiple: true,
|
|
110
|
+
accept: galleryAccept.accept,
|
|
111
|
+
maxBytes: galleryAccept.maxBytes,
|
|
112
|
+
}, multiple: true, showOptimizeHint: !docsOnly, label: docsOnly
|
|
113
|
+
? "Drop PDFs to add them to Files"
|
|
114
|
+
: "Drop images to add them to Files", onUpload: async (files) => {
|
|
92
115
|
const items = await onUploadGallery(files);
|
|
93
|
-
|
|
116
|
+
const kept = filterGalleryByKind(items, assetKind);
|
|
117
|
+
setGallery((current) => [...kept, ...current]);
|
|
94
118
|
setSelected((current) => {
|
|
95
119
|
const next = { ...current };
|
|
96
|
-
for (const item of
|
|
120
|
+
for (const item of kept) {
|
|
97
121
|
const image = {
|
|
98
122
|
id: `gallery:${item.id}`,
|
|
99
123
|
url: item.url,
|
|
@@ -104,17 +128,22 @@ export function ImagePickerModal({ recordImages = [], galleryUpload, onListGalle
|
|
|
104
128
|
}
|
|
105
129
|
return next;
|
|
106
130
|
});
|
|
107
|
-
} })) : null, _jsxs("label", { className: "vertebr-field", children: [
|
|
131
|
+
} })) : null, _jsxs("label", { className: "vertebr-field", children: [_jsxs("span", { children: ["Or paste a ", docsOnly ? "PDF" : "image", " URL"] }), _jsxs("div", { className: "vertebr-picker-url", children: [_jsx("input", { type: "url", value: url, placeholder: "https://", onChange: (event) => setUrl(event.target.value), onKeyDown: (event) => {
|
|
108
132
|
if (event.key === "Enter") {
|
|
109
133
|
event.preventDefault();
|
|
110
134
|
addUrl();
|
|
111
135
|
}
|
|
112
|
-
} }), _jsx("button", { type: "button", className: "vertebr-btn", disabled: !url.trim(), onClick: addUrl, children: "Add" })] })] }), error ? (_jsx("p", { className: "vertebr-status", "data-tone": "danger", children: error })) : null, loading && tab === "gallery" ? (_jsx("div", { className: "vertebr-empty", children: "Loading
|
|
136
|
+
} }), _jsx("button", { type: "button", className: "vertebr-btn", disabled: !url.trim(), onClick: addUrl, children: "Add" })] })] }), error ? (_jsx("p", { className: "vertebr-status", "data-tone": "danger", children: error })) : null, loading && tab === "gallery" ? (_jsx("div", { className: "vertebr-empty", children: "Loading Files\u2026" })) : tiles.length === 0 ? (_jsx("div", { className: "vertebr-empty", children: tab === "record"
|
|
113
137
|
? "No product photos on this record yet."
|
|
114
138
|
: hasGallery
|
|
115
|
-
?
|
|
116
|
-
|
|
139
|
+
? docsOnly
|
|
140
|
+
? "No PDFs in Files yet."
|
|
141
|
+
: "No images in Files yet."
|
|
142
|
+
: "No Files library is configured. Paste a URL instead." })) : (_jsx("div", { className: "vertebr-picker-grid", children: tiles.map((image) => {
|
|
117
143
|
const active = Boolean(selected[image.id]);
|
|
118
|
-
|
|
119
|
-
|
|
144
|
+
const pdf = docsOnly || isPdfAsset(image);
|
|
145
|
+
return (_jsxs("button", { type: "button", className: "vertebr-picker-tile", "data-selected": active || undefined, onClick: () => toggle(image), children: [_jsx("span", { className: pdf
|
|
146
|
+
? "vertebr-picker-thumb vertebr-gallery-thumb-file"
|
|
147
|
+
: "vertebr-picker-thumb", children: pdf ? (_jsx("span", { className: "vertebr-gallery-file-badge", children: "PDF" })) : (_jsx("img", { src: image.url, alt: "" })) }), _jsx("span", { className: "vertebr-picker-name", children: image.name })] }, image.id));
|
|
148
|
+
}) }))] }), _jsxs("footer", { className: "vertebr-picker-foot", children: [_jsxs("span", { className: "vertebr-picker-count", children: [picked.length, " selected"] }), _jsxs("button", { type: "button", className: "vertebr-btn vertebr-btn-primary", disabled: picked.length === 0, onClick: () => onInsert(picked), children: [confirmLabel, " ", picked.length || "", picked.length === 1 ? ` ${unit}` : ` ${units}`] })] })] }) }), document.body);
|
|
120
149
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GalleryItem, ResourceUploadMeta } from "@vertebr/client";
|
|
2
|
+
import type { RecordImage } from "../../lib/images";
|
|
3
|
+
export type MarkdownDocumentModalProps = {
|
|
4
|
+
title?: string;
|
|
5
|
+
value: string;
|
|
6
|
+
readOnly?: boolean;
|
|
7
|
+
recordImages?: RecordImage[];
|
|
8
|
+
galleryUpload?: Pick<ResourceUploadMeta, "accept" | "maxBytes">;
|
|
9
|
+
onListGallery?: () => Promise<GalleryItem[]>;
|
|
10
|
+
onUploadGallery?: (files: File[]) => Promise<GalleryItem[]>;
|
|
11
|
+
onChange: (next: string) => void;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Full-page document chrome for editing policy markdown
|
|
16
|
+
* (PDF-like page, not a binary PDF editor).
|
|
17
|
+
*/
|
|
18
|
+
export declare function MarkdownDocumentModal({ title, value, readOnly, recordImages, galleryUpload, onListGallery, onUploadGallery, onChange, onClose, }: MarkdownDocumentModalProps): import("react").ReactPortal;
|
|
19
|
+
//# sourceMappingURL=MarkdownDocumentModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownDocumentModal.d.ts","sourceRoot":"","sources":["../../../src/components/config/MarkdownDocumentModal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,KAAyB,EACzB,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,QAAQ,EACR,OAAO,GACR,EAAE,0BAA0B,+BAkF5B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
import { descriptionStats } from "../../lib/description";
|
|
5
|
+
import { DescriptionInput } from "./DescriptionInput";
|
|
6
|
+
/**
|
|
7
|
+
* Full-page document chrome for editing policy markdown
|
|
8
|
+
* (PDF-like page, not a binary PDF editor).
|
|
9
|
+
*/
|
|
10
|
+
export function MarkdownDocumentModal({ title = "Policy document", value, readOnly, recordImages, galleryUpload, onListGallery, onUploadGallery, onChange, onClose, }) {
|
|
11
|
+
const [draft, setDraft] = useState(value);
|
|
12
|
+
const stats = descriptionStats(draft);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setDraft(value);
|
|
15
|
+
}, [value]);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const onKeyDown = (event) => {
|
|
18
|
+
if (event.key === "Escape")
|
|
19
|
+
onClose();
|
|
20
|
+
};
|
|
21
|
+
window.addEventListener("keydown", onKeyDown);
|
|
22
|
+
const previous = document.body.style.overflow;
|
|
23
|
+
document.body.style.overflow = "hidden";
|
|
24
|
+
return () => {
|
|
25
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
26
|
+
document.body.style.overflow = previous;
|
|
27
|
+
};
|
|
28
|
+
}, [onClose]);
|
|
29
|
+
const saveAndClose = () => {
|
|
30
|
+
onChange(draft);
|
|
31
|
+
onClose();
|
|
32
|
+
};
|
|
33
|
+
return createPortal(_jsx("div", { className: "vertebr-modal-backdrop vertebr-doc-modal-backdrop", role: "presentation", onClick: onClose, children: _jsxs("div", { className: "vertebr-modal vertebr-doc-modal", role: "dialog", "aria-modal": "true", "aria-label": title, onClick: (event) => event.stopPropagation(), children: [_jsxs("header", { className: "vertebr-modal-head", children: [_jsxs("div", { className: "vertebr-modal-heading", children: [_jsx("p", { className: "vertebr-modal-eyebrow", children: "Document" }), _jsx("h2", { children: title })] }), _jsxs("div", { className: "vertebr-doc-modal-actions", children: [_jsxs("span", { className: "vertebr-doc-modal-stats", children: [stats.words, " words \u00B7 ", stats.characters, " characters"] }), !readOnly ? (_jsx("button", { type: "button", className: "vertebr-btn vertebr-btn-primary", onClick: saveAndClose, children: "Done" })) : null, _jsx("button", { type: "button", className: "vertebr-btn", onClick: onClose, children: "Close" })] })] }), _jsx("div", { className: "vertebr-modal-body vertebr-doc-modal-body", children: _jsx("div", { className: "vertebr-doc-page", children: _jsx(DescriptionInput, { id: "vertebr-doc-modal-editor", value: draft, readOnly: readOnly, placeholder: "Write the policy\u2026", recordImages: recordImages, galleryUpload: galleryUpload, onListGallery: onListGallery, onUploadGallery: onUploadGallery, onChange: setDraft }) }) })] }) }), document.body);
|
|
34
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigField.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/ConfigField.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ConfigField.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/ConfigField.tsx"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIjE,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA2BtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAmBvF,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAC5C,mBAAmB,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,EAAE,KACV,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACpD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,KAAK,EACL,UAAU,EACV,OAAO,EACP,MAAM,EACN,OAAO,EACP,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,aAAa,EACb,aAAa,EACb,eAAe,EACf,KAAK,EACL,YAAY,EACZ,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,WAAW,EACX,MAAM,GACP,EAAE,gBAAgB,+BA4elB"}
|