@nextsparkjs/core 0.1.0-beta.158 → 0.1.0-beta.159
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/dashboard/block-editor/batch-action-bar.d.ts +12 -0
- package/dist/components/dashboard/block-editor/batch-action-bar.d.ts.map +1 -0
- package/dist/components/dashboard/block-editor/batch-action-bar.js +99 -0
- package/dist/components/dashboard/block-editor/block-picker.d.ts +8 -3
- package/dist/components/dashboard/block-editor/block-picker.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/block-picker.js +5 -3
- package/dist/components/dashboard/block-editor/block-preview-canvas.d.ts +7 -3
- package/dist/components/dashboard/block-editor/block-preview-canvas.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/block-preview-canvas.js +17 -8
- package/dist/components/dashboard/block-editor/block-settings-panel.d.ts +2 -1
- package/dist/components/dashboard/block-editor/block-settings-panel.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/block-settings-panel.js +10 -1
- package/dist/components/dashboard/block-editor/builder-editor-view.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/builder-editor-view.js +190 -26
- package/dist/components/dashboard/block-editor/tree-view-node.d.ts +7 -2
- package/dist/components/dashboard/block-editor/tree-view-node.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/tree-view-node.js +16 -3
- package/dist/components/dashboard/block-editor/tree-view.d.ts +7 -2
- package/dist/components/dashboard/block-editor/tree-view.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/tree-view.js +7 -4
- package/dist/lib/blocks/clipboard.d.ts +8 -1
- package/dist/lib/blocks/clipboard.d.ts.map +1 -1
- package/dist/lib/blocks/clipboard.js +30 -8
- package/dist/messages/en/admin.json +20 -1
- package/dist/messages/en/index.d.ts +19 -0
- package/dist/messages/en/index.d.ts.map +1 -1
- package/dist/messages/es/admin.json +20 -1
- package/dist/messages/es/index.d.ts +19 -0
- package/dist/messages/es/index.d.ts.map +1 -1
- package/dist/styles/classes.json +3 -2
- package/dist/styles/ui.css +1 -1
- package/package.json +2 -2
- package/scripts/build/registry/post-build/page-generator.mjs +52 -4
|
@@ -5,7 +5,13 @@ import { useRouter } from "next/navigation";
|
|
|
5
5
|
import { useTranslations } from "next-intl";
|
|
6
6
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
7
7
|
import { v4 as uuidv4 } from "uuid";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
copyBlockToClipboard,
|
|
10
|
+
getBlockFromClipboard,
|
|
11
|
+
copyBlocksToClipboard,
|
|
12
|
+
getBlocksFromClipboard,
|
|
13
|
+
getClipboardBlockCount
|
|
14
|
+
} from "../../../lib/blocks/clipboard.js";
|
|
9
15
|
import { Button } from "../../ui/button.js";
|
|
10
16
|
import { Input } from "../../ui/input.js";
|
|
11
17
|
import { Separator } from "../../ui/separator.js";
|
|
@@ -16,11 +22,13 @@ import { sel } from "../../../lib/test/index.js";
|
|
|
16
22
|
import { BlockPicker } from "./block-picker.js";
|
|
17
23
|
import { BlockPreviewCanvas } from "./block-preview-canvas.js";
|
|
18
24
|
import { BlockSettingsPanel } from "./block-settings-panel.js";
|
|
25
|
+
import { BatchActionBar } from "./batch-action-bar.js";
|
|
19
26
|
import { BlockService } from "../../../lib/services/block.service.js";
|
|
20
27
|
import { ViewportToggle } from "./viewport-toggle.js";
|
|
21
28
|
import { ConfigPanel } from "./config-panel.js";
|
|
22
29
|
import { useSidebar } from "../../../contexts/sidebar-context.js";
|
|
23
30
|
import { cn } from "../../../lib/utils/index.js";
|
|
31
|
+
import { isPatternReference } from "../../../types/pattern-reference.js";
|
|
24
32
|
function getTeamId() {
|
|
25
33
|
if (typeof window !== "undefined") {
|
|
26
34
|
return localStorage.getItem("activeTeamId");
|
|
@@ -49,7 +57,8 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
49
57
|
const queryClient = useQueryClient();
|
|
50
58
|
const { isCollapsed } = useSidebar();
|
|
51
59
|
const [blocks, setBlocks] = useState([]);
|
|
52
|
-
const [
|
|
60
|
+
const [selectedBlockIds, setSelectedBlockIds] = useState(/* @__PURE__ */ new Set());
|
|
61
|
+
const lastSelectedIdRef = useRef(null);
|
|
53
62
|
const [title, setTitle] = useState("");
|
|
54
63
|
const [slug, setSlug] = useState("");
|
|
55
64
|
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false);
|
|
@@ -234,17 +243,68 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
234
243
|
};
|
|
235
244
|
saveMutation.mutate(data);
|
|
236
245
|
}, [title, slug, blocks, pageSettings, entityFields, saveMutation, validateFields]);
|
|
246
|
+
const selectedBlockId = useMemo(() => {
|
|
247
|
+
if (selectedBlockIds.size === 1) return Array.from(selectedBlockIds)[0];
|
|
248
|
+
return null;
|
|
249
|
+
}, [selectedBlockIds]);
|
|
250
|
+
const setSelectedBlockId = useCallback((id2) => {
|
|
251
|
+
if (id2) {
|
|
252
|
+
setSelectedBlockIds(/* @__PURE__ */ new Set([id2]));
|
|
253
|
+
lastSelectedIdRef.current = id2;
|
|
254
|
+
} else {
|
|
255
|
+
setSelectedBlockIds(/* @__PURE__ */ new Set());
|
|
256
|
+
lastSelectedIdRef.current = null;
|
|
257
|
+
}
|
|
258
|
+
}, []);
|
|
259
|
+
const handleSelectBlock = useCallback((blockId, event) => {
|
|
260
|
+
if ((event == null ? void 0 : event.metaKey) || (event == null ? void 0 : event.ctrlKey)) {
|
|
261
|
+
setSelectedBlockIds((prev) => {
|
|
262
|
+
const next = new Set(prev);
|
|
263
|
+
if (next.has(blockId)) {
|
|
264
|
+
next.delete(blockId);
|
|
265
|
+
} else {
|
|
266
|
+
next.add(blockId);
|
|
267
|
+
}
|
|
268
|
+
lastSelectedIdRef.current = blockId;
|
|
269
|
+
return next;
|
|
270
|
+
});
|
|
271
|
+
} else if ((event == null ? void 0 : event.shiftKey) && lastSelectedIdRef.current) {
|
|
272
|
+
const anchorIdx = blocks.findIndex((b) => b.id === lastSelectedIdRef.current);
|
|
273
|
+
const targetIdx = blocks.findIndex((b) => b.id === blockId);
|
|
274
|
+
if (anchorIdx !== -1 && targetIdx !== -1) {
|
|
275
|
+
const start = Math.min(anchorIdx, targetIdx);
|
|
276
|
+
const end = Math.max(anchorIdx, targetIdx);
|
|
277
|
+
const rangeIds = blocks.slice(start, end + 1).map((b) => b.id);
|
|
278
|
+
setSelectedBlockIds((prev) => {
|
|
279
|
+
const next = new Set(prev);
|
|
280
|
+
rangeIds.forEach((id2) => next.add(id2));
|
|
281
|
+
return next;
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
setSelectedBlockIds(/* @__PURE__ */ new Set([blockId]));
|
|
286
|
+
lastSelectedIdRef.current = blockId;
|
|
287
|
+
}
|
|
288
|
+
}, [blocks]);
|
|
289
|
+
const handleSelectAll = useCallback(() => {
|
|
290
|
+
const nonPatternIds = blocks.filter((b) => !isPatternReference(b)).map((b) => b.id);
|
|
291
|
+
setSelectedBlockIds(new Set(nonPatternIds));
|
|
292
|
+
}, [blocks]);
|
|
293
|
+
const handleClearSelection = useCallback(() => {
|
|
294
|
+
setSelectedBlockIds(/* @__PURE__ */ new Set());
|
|
295
|
+
}, []);
|
|
296
|
+
const [clipboardCount, setClipboardCount] = useState(() => getClipboardBlockCount());
|
|
237
297
|
const handleAddBlock = useCallback((blockSlug) => {
|
|
238
298
|
const newBlock = {
|
|
239
299
|
id: uuidv4(),
|
|
240
300
|
blockSlug,
|
|
241
301
|
props: {}
|
|
242
302
|
};
|
|
243
|
-
if (
|
|
244
|
-
const
|
|
245
|
-
if (
|
|
303
|
+
if (selectedBlockIds.size > 0) {
|
|
304
|
+
const lastIdx = Math.max(...Array.from(selectedBlockIds).map((id2) => blocks.findIndex((b) => b.id === id2)));
|
|
305
|
+
if (lastIdx !== -1) {
|
|
246
306
|
const newBlocks = [...blocks];
|
|
247
|
-
newBlocks.splice(
|
|
307
|
+
newBlocks.splice(lastIdx + 1, 0, newBlock);
|
|
248
308
|
setBlocks(newBlocks);
|
|
249
309
|
setSelectedBlockId(newBlock.id);
|
|
250
310
|
return;
|
|
@@ -252,29 +312,29 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
252
312
|
}
|
|
253
313
|
setBlocks((prev) => [...prev, newBlock]);
|
|
254
314
|
setSelectedBlockId(newBlock.id);
|
|
255
|
-
}, [blocks,
|
|
315
|
+
}, [blocks, selectedBlockIds, setSelectedBlockId]);
|
|
256
316
|
const handleAddPattern = useCallback((patternId) => {
|
|
257
317
|
const patternRef = {
|
|
258
318
|
type: "pattern",
|
|
259
319
|
ref: patternId,
|
|
260
320
|
id: uuidv4()
|
|
261
|
-
// Unique instance ID
|
|
262
321
|
};
|
|
263
322
|
setBlocks((prev) => [...prev, patternRef]);
|
|
264
323
|
setSelectedBlockId(patternRef.id);
|
|
265
|
-
}, []);
|
|
324
|
+
}, [setSelectedBlockId]);
|
|
266
325
|
const handleRemoveBlock = useCallback((blockId) => {
|
|
267
326
|
setBlocks((prev) => prev.filter((b) => b.id !== blockId));
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
327
|
+
setSelectedBlockIds((prev) => {
|
|
328
|
+
const next = new Set(prev);
|
|
329
|
+
next.delete(blockId);
|
|
330
|
+
return next;
|
|
331
|
+
});
|
|
332
|
+
}, []);
|
|
273
333
|
const handleCopyBlock = useCallback((blockId) => {
|
|
274
334
|
const block = blocks.find((b) => b.id === blockId);
|
|
275
335
|
if (block) {
|
|
276
336
|
copyBlockToClipboard(block);
|
|
277
|
-
|
|
337
|
+
setClipboardCount(1);
|
|
278
338
|
toast.success(t("messages.blockCopied"));
|
|
279
339
|
}
|
|
280
340
|
}, [blocks, t]);
|
|
@@ -300,7 +360,68 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
300
360
|
setBlocks((prev) => [...prev, newBlock]);
|
|
301
361
|
setSelectedBlockId(newBlock.id);
|
|
302
362
|
toast.success(t("messages.blockPasted"));
|
|
303
|
-
}, [blocks, selectedBlockId, t]);
|
|
363
|
+
}, [blocks, selectedBlockId, t, setSelectedBlockId]);
|
|
364
|
+
const handleCopySelected = useCallback(() => {
|
|
365
|
+
const selected = blocks.filter((b) => selectedBlockIds.has(b.id) && !isPatternReference(b));
|
|
366
|
+
if (selected.length === 0) return;
|
|
367
|
+
copyBlocksToClipboard(selected, entitySlug);
|
|
368
|
+
setClipboardCount(selected.length);
|
|
369
|
+
toast.success(t("multiSelect.copied", { count: selected.length }));
|
|
370
|
+
}, [blocks, selectedBlockIds, entitySlug, t]);
|
|
371
|
+
const handleDeleteSelected = useCallback(() => {
|
|
372
|
+
const idsToDelete = selectedBlockIds;
|
|
373
|
+
setBlocks((prev) => prev.filter((b) => !idsToDelete.has(b.id)));
|
|
374
|
+
setSelectedBlockIds(/* @__PURE__ */ new Set());
|
|
375
|
+
toast.success(t("multiSelect.deleted", { count: idsToDelete.size }));
|
|
376
|
+
}, [selectedBlockIds, t]);
|
|
377
|
+
const handleDuplicateSelected = useCallback(() => {
|
|
378
|
+
const selectedOrdered = blocks.filter((b) => selectedBlockIds.has(b.id) && !isPatternReference(b));
|
|
379
|
+
if (selectedOrdered.length === 0) return;
|
|
380
|
+
const lastIdx = blocks.findIndex((b) => b.id === selectedOrdered[selectedOrdered.length - 1].id);
|
|
381
|
+
const duplicates = selectedOrdered.map((b) => ({
|
|
382
|
+
...b,
|
|
383
|
+
id: uuidv4(),
|
|
384
|
+
props: { ...b.props }
|
|
385
|
+
}));
|
|
386
|
+
const newBlocks = [...blocks];
|
|
387
|
+
newBlocks.splice(lastIdx + 1, 0, ...duplicates);
|
|
388
|
+
setBlocks(newBlocks);
|
|
389
|
+
setSelectedBlockIds(new Set(duplicates.map((d) => d.id)));
|
|
390
|
+
toast.success(t("multiSelect.duplicated", { count: duplicates.length }));
|
|
391
|
+
}, [blocks, selectedBlockIds, t]);
|
|
392
|
+
const handlePasteBlocks = useCallback(() => {
|
|
393
|
+
const clipData = getBlocksFromClipboard();
|
|
394
|
+
if (!clipData || clipData.blocks.length === 0) {
|
|
395
|
+
handlePasteBlock();
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const allowedSlugs = new Set(BlockService.getForScope(entitySlug).map((b) => b.slug));
|
|
399
|
+
const compatible = clipData.blocks.filter((b) => allowedSlugs.has(b.blockSlug));
|
|
400
|
+
const skipped = clipData.blocks.length - compatible.length;
|
|
401
|
+
if (compatible.length === 0) {
|
|
402
|
+
toast.error(t("multiSelect.clipboardEmpty"));
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const newBlocks = compatible.map((b) => ({
|
|
406
|
+
id: uuidv4(),
|
|
407
|
+
blockSlug: b.blockSlug,
|
|
408
|
+
props: { ...b.props }
|
|
409
|
+
}));
|
|
410
|
+
const insertIdx = selectedBlockIds.size > 0 ? Math.max(...Array.from(selectedBlockIds).map((id2) => blocks.findIndex((b) => b.id === id2))) : blocks.length - 1;
|
|
411
|
+
const updatedBlocks = [...blocks];
|
|
412
|
+
updatedBlocks.splice(insertIdx + 1, 0, ...newBlocks);
|
|
413
|
+
setBlocks(updatedBlocks);
|
|
414
|
+
setSelectedBlockIds(new Set(newBlocks.map((b) => b.id)));
|
|
415
|
+
if (skipped > 0) {
|
|
416
|
+
toast.warning(t("multiSelect.pastedPartial", {
|
|
417
|
+
pasted: compatible.length,
|
|
418
|
+
total: clipData.blocks.length,
|
|
419
|
+
skipped
|
|
420
|
+
}));
|
|
421
|
+
} else {
|
|
422
|
+
toast.success(t("multiSelect.pasted", { count: newBlocks.length }));
|
|
423
|
+
}
|
|
424
|
+
}, [blocks, selectedBlockIds, entitySlug, t, handlePasteBlock]);
|
|
304
425
|
const handleDuplicateBlock = useCallback((blockId) => {
|
|
305
426
|
const block = blocks.find((b) => b.id === blockId);
|
|
306
427
|
if (block) {
|
|
@@ -315,7 +436,7 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
315
436
|
setBlocks(newBlocks);
|
|
316
437
|
setSelectedBlockId(duplicated.id);
|
|
317
438
|
}
|
|
318
|
-
}, [blocks]);
|
|
439
|
+
}, [blocks, setSelectedBlockId]);
|
|
319
440
|
const handleUpdateBlockProps = useCallback((blockId, props) => {
|
|
320
441
|
setBlocks((prev) => prev.map(
|
|
321
442
|
(block) => block.id === blockId ? { ...block, props } : block
|
|
@@ -342,6 +463,35 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
342
463
|
return newBlocks;
|
|
343
464
|
});
|
|
344
465
|
}, []);
|
|
466
|
+
useEffect(() => {
|
|
467
|
+
if (viewMode !== "preview") return;
|
|
468
|
+
const handler = (e) => {
|
|
469
|
+
const target = e.target;
|
|
470
|
+
const isInputFocused = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable;
|
|
471
|
+
if (isInputFocused) return;
|
|
472
|
+
const isMod = e.metaKey || e.ctrlKey;
|
|
473
|
+
if (isMod && e.key === "a") {
|
|
474
|
+
e.preventDefault();
|
|
475
|
+
handleSelectAll();
|
|
476
|
+
} else if (e.key === "Escape") {
|
|
477
|
+
handleClearSelection();
|
|
478
|
+
} else if (isMod && e.key === "c" && selectedBlockIds.size > 0) {
|
|
479
|
+
e.preventDefault();
|
|
480
|
+
handleCopySelected();
|
|
481
|
+
} else if (isMod && e.key === "v") {
|
|
482
|
+
e.preventDefault();
|
|
483
|
+
handlePasteBlocks();
|
|
484
|
+
} else if (isMod && e.key === "d" && selectedBlockIds.size > 0) {
|
|
485
|
+
e.preventDefault();
|
|
486
|
+
handleDuplicateSelected();
|
|
487
|
+
} else if ((e.key === "Delete" || e.key === "Backspace") && selectedBlockIds.size > 0) {
|
|
488
|
+
e.preventDefault();
|
|
489
|
+
handleDeleteSelected();
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
document.addEventListener("keydown", handler);
|
|
493
|
+
return () => document.removeEventListener("keydown", handler);
|
|
494
|
+
}, [viewMode, selectedBlockIds, handleSelectAll, handleClearSelection, handleCopySelected, handlePasteBlocks, handleDuplicateSelected, handleDeleteSelected]);
|
|
345
495
|
const handleEntityFieldChange = useCallback((field, value) => {
|
|
346
496
|
setEntityFields((prev) => ({ ...prev, [field]: value }));
|
|
347
497
|
onEntityFieldChangeProp == null ? void 0 : onEntityFieldChangeProp(field, value);
|
|
@@ -356,9 +506,9 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
356
506
|
const handleViewModeChange = useCallback((mode2) => {
|
|
357
507
|
setViewMode(mode2);
|
|
358
508
|
if (mode2 === "settings") {
|
|
359
|
-
|
|
509
|
+
handleClearSelection();
|
|
360
510
|
}
|
|
361
|
-
}, []);
|
|
511
|
+
}, [handleClearSelection]);
|
|
362
512
|
const selectedBlock = selectedBlockId ? blocks.find((b) => b.id === selectedBlockId) : void 0;
|
|
363
513
|
const publicUrl = useMemo(() => {
|
|
364
514
|
var _a2, _b, _c;
|
|
@@ -613,16 +763,17 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
613
763
|
showPatternsTab,
|
|
614
764
|
pageBlocks: blocks,
|
|
615
765
|
selectedBlockId,
|
|
616
|
-
|
|
766
|
+
selectedBlockIds,
|
|
767
|
+
onSelectBlock: handleSelectBlock,
|
|
617
768
|
onReorderBlocks: handleReorderBlocks,
|
|
618
769
|
onCopyBlock: handleCopyBlock,
|
|
619
770
|
onDuplicateBlock: handleDuplicateBlock,
|
|
620
771
|
onRemoveBlock: handleRemoveBlock,
|
|
621
|
-
onPasteBlock:
|
|
622
|
-
|
|
772
|
+
onPasteBlock: handlePasteBlocks,
|
|
773
|
+
clipboardCount
|
|
623
774
|
}
|
|
624
775
|
) }),
|
|
625
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-hidden", children: [
|
|
776
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-hidden relative", children: [
|
|
626
777
|
/* @__PURE__ */ jsx(
|
|
627
778
|
"div",
|
|
628
779
|
{
|
|
@@ -644,8 +795,8 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
644
795
|
BlockPreviewCanvas,
|
|
645
796
|
{
|
|
646
797
|
blocks,
|
|
647
|
-
|
|
648
|
-
onSelectBlock:
|
|
798
|
+
selectedBlockIds,
|
|
799
|
+
onSelectBlock: handleSelectBlock,
|
|
649
800
|
onMoveUp: handleMoveBlockUp,
|
|
650
801
|
onMoveDown: handleMoveBlockDown,
|
|
651
802
|
onCopy: handleCopyBlock,
|
|
@@ -657,6 +808,18 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
657
808
|
)
|
|
658
809
|
}
|
|
659
810
|
),
|
|
811
|
+
viewMode === "preview" && selectedBlockIds.size > 1 && /* @__PURE__ */ jsx(
|
|
812
|
+
BatchActionBar,
|
|
813
|
+
{
|
|
814
|
+
selectedCount: selectedBlockIds.size,
|
|
815
|
+
onCopy: handleCopySelected,
|
|
816
|
+
onDuplicate: handleDuplicateSelected,
|
|
817
|
+
onDelete: handleDeleteSelected,
|
|
818
|
+
onClearSelection: handleClearSelection,
|
|
819
|
+
clipboardCount,
|
|
820
|
+
onPaste: handlePasteBlocks
|
|
821
|
+
}
|
|
822
|
+
),
|
|
660
823
|
/* @__PURE__ */ jsx("div", { className: cn("h-full", viewMode !== "settings" && "hidden"), children: /* @__PURE__ */ jsx(
|
|
661
824
|
ConfigPanel,
|
|
662
825
|
{
|
|
@@ -672,6 +835,7 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
672
835
|
BlockSettingsPanel,
|
|
673
836
|
{
|
|
674
837
|
block: selectedBlock,
|
|
838
|
+
selectedCount: selectedBlockIds.size,
|
|
675
839
|
onUpdateProps: (props) => {
|
|
676
840
|
if (selectedBlockId) {
|
|
677
841
|
handleUpdateBlockProps(selectedBlockId, props);
|
|
@@ -682,7 +846,7 @@ function BuilderEditorView({ entitySlug, entityConfig, id, mode, onEntityFieldCh
|
|
|
682
846
|
handleRemoveBlock(selectedBlockId);
|
|
683
847
|
}
|
|
684
848
|
},
|
|
685
|
-
onClose:
|
|
849
|
+
onClose: handleClearSelection
|
|
686
850
|
}
|
|
687
851
|
) })
|
|
688
852
|
] })
|
|
@@ -3,12 +3,17 @@ import { type PatternReference } from '../../../types/pattern-reference';
|
|
|
3
3
|
interface TreeViewNodeProps {
|
|
4
4
|
block: BlockInstance | PatternReference;
|
|
5
5
|
isSelected: boolean;
|
|
6
|
-
|
|
6
|
+
isMultiSelect?: boolean;
|
|
7
|
+
onSelect: (event?: {
|
|
8
|
+
metaKey?: boolean;
|
|
9
|
+
shiftKey?: boolean;
|
|
10
|
+
ctrlKey?: boolean;
|
|
11
|
+
}) => void;
|
|
7
12
|
onCopy?: () => void;
|
|
8
13
|
onDuplicate?: () => void;
|
|
9
14
|
onRemove?: () => void;
|
|
10
15
|
isPartOfPattern?: boolean;
|
|
11
16
|
}
|
|
12
|
-
export declare function TreeViewNode({ block, isSelected, onSelect, onCopy, onDuplicate, onRemove, isPartOfPattern }: TreeViewNodeProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare function TreeViewNode({ block, isSelected, isMultiSelect, onSelect, onCopy, onDuplicate, onRemove, isPartOfPattern }: TreeViewNodeProps): import("react/jsx-runtime").JSX.Element;
|
|
13
18
|
export {};
|
|
14
19
|
//# sourceMappingURL=tree-view-node.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-view-node.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/tree-view-node.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAE5F,UAAU,iBAAiB;IACzB,KAAK,EAAE,aAAa,GAAG,gBAAgB,CAAA;IACvC,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"tree-view-node.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/tree-view-node.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAE5F,UAAU,iBAAiB;IACzB,KAAK,EAAE,aAAa,GAAG,gBAAgB,CAAA;IACvC,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACxF,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,UAAU,EACV,aAAqB,EACrB,QAAQ,EACR,MAAM,EACN,WAAW,EACX,QAAQ,EACR,eAAuB,EACxB,EAAE,iBAAiB,2CA6InB"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useSortable } from "@dnd-kit/sortable";
|
|
4
4
|
import { CSS } from "@dnd-kit/utilities";
|
|
5
|
-
import { GripVertical, ClipboardCopy, Copy, Trash2 } from "lucide-react";
|
|
5
|
+
import { GripVertical, ClipboardCopy, Copy, Trash2, Check } from "lucide-react";
|
|
6
6
|
import { cn } from "../../../lib/utils/index.js";
|
|
7
7
|
import { sel } from "../../../lib/test/index.js";
|
|
8
8
|
import { BlockService } from "../../../lib/services/block.service.js";
|
|
@@ -11,6 +11,7 @@ import { isPatternReference } from "../../../types/pattern-reference.js";
|
|
|
11
11
|
function TreeViewNode({
|
|
12
12
|
block,
|
|
13
13
|
isSelected,
|
|
14
|
+
isMultiSelect = false,
|
|
14
15
|
onSelect,
|
|
15
16
|
onCopy,
|
|
16
17
|
onDuplicate,
|
|
@@ -46,12 +47,24 @@ function TreeViewNode({
|
|
|
46
47
|
className: cn(
|
|
47
48
|
"group flex items-center gap-2 px-2 py-1.5 rounded-md cursor-pointer transition-colors",
|
|
48
49
|
"hover:bg-muted/80",
|
|
49
|
-
isSelected && "bg-primary/10 ring-1 ring-primary",
|
|
50
|
+
isSelected && !isMultiSelect && "bg-primary/10 ring-1 ring-primary",
|
|
51
|
+
isSelected && isMultiSelect && "bg-primary/10 ring-1 ring-primary/70",
|
|
50
52
|
isPartOfPattern && "ml-4 border-l-2 border-muted-foreground/20",
|
|
51
53
|
isDragging && "z-50"
|
|
52
54
|
),
|
|
53
|
-
onClick: onSelect,
|
|
55
|
+
onClick: (e) => onSelect({ metaKey: e.metaKey, shiftKey: e.shiftKey, ctrlKey: e.ctrlKey }),
|
|
54
56
|
children: [
|
|
57
|
+
isMultiSelect && !isPartOfPattern && /* @__PURE__ */ jsx(
|
|
58
|
+
"div",
|
|
59
|
+
{
|
|
60
|
+
className: cn(
|
|
61
|
+
"flex items-center justify-center w-4 h-4 rounded border shrink-0 transition-colors",
|
|
62
|
+
isSelected ? "bg-primary border-primary text-primary-foreground" : "border-muted-foreground/30 hover:border-primary"
|
|
63
|
+
),
|
|
64
|
+
"data-cy": sel("blockEditor.treeView.nodeCheckbox", { id: block.id }),
|
|
65
|
+
children: isSelected && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" })
|
|
66
|
+
}
|
|
67
|
+
),
|
|
55
68
|
!isPartOfPattern && /* @__PURE__ */ jsx(
|
|
56
69
|
"div",
|
|
57
70
|
{
|
|
@@ -3,7 +3,12 @@ import type { BlockInstance } from '../../../types/blocks';
|
|
|
3
3
|
interface TreeViewProps {
|
|
4
4
|
blocks: (BlockInstance | PatternReference)[];
|
|
5
5
|
selectedBlockId: string | null;
|
|
6
|
-
|
|
6
|
+
selectedBlockIds?: Set<string>;
|
|
7
|
+
onSelectBlock: (id: string, event?: {
|
|
8
|
+
metaKey?: boolean;
|
|
9
|
+
shiftKey?: boolean;
|
|
10
|
+
ctrlKey?: boolean;
|
|
11
|
+
}) => void;
|
|
7
12
|
onReorder: (blocks: (BlockInstance | PatternReference)[]) => void;
|
|
8
13
|
onCopy?: (id: string) => void;
|
|
9
14
|
onDuplicate?: (id: string) => void;
|
|
@@ -15,6 +20,6 @@ interface TreeViewProps {
|
|
|
15
20
|
* Displays a tree structure of all blocks with drag & drop reordering.
|
|
16
21
|
* Clicking a block selects it and scrolls to it in the preview.
|
|
17
22
|
*/
|
|
18
|
-
export declare function TreeView({ blocks, selectedBlockId, onSelectBlock, onReorder, onCopy, onDuplicate, onRemove, emptyMessage }: TreeViewProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export declare function TreeView({ blocks, selectedBlockId, selectedBlockIds, onSelectBlock, onReorder, onCopy, onDuplicate, onRemove, emptyMessage }: TreeViewProps): import("react/jsx-runtime").JSX.Element;
|
|
19
24
|
export {};
|
|
20
25
|
//# sourceMappingURL=tree-view.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-view.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/tree-view.tsx"],"names":[],"mappings":"AAwBA,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAC5F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,UAAU,aAAa;IACrB,MAAM,EAAE,CAAC,aAAa,GAAG,gBAAgB,CAAC,EAAE,CAAA;IAC5C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"tree-view.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/block-editor/tree-view.tsx"],"names":[],"mappings":"AAwBA,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAC5F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,UAAU,aAAa;IACrB,MAAM,EAAE,CAAC,aAAa,GAAG,gBAAgB,CAAC,EAAE,CAAA;IAC5C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC9B,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACzG,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,aAAa,GAAG,gBAAgB,CAAC,EAAE,KAAK,IAAI,CAAA;IACjE,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,MAAM,EACN,WAAW,EACX,QAAQ,EACR,YAAY,EACb,EAAE,aAAa,2CAqHf"}
|
|
@@ -24,6 +24,7 @@ import { isPatternReference } from "../../../types/pattern-reference.js";
|
|
|
24
24
|
function TreeView({
|
|
25
25
|
blocks,
|
|
26
26
|
selectedBlockId,
|
|
27
|
+
selectedBlockIds,
|
|
27
28
|
onSelectBlock,
|
|
28
29
|
onReorder,
|
|
29
30
|
onCopy,
|
|
@@ -74,8 +75,9 @@ function TreeView({
|
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
}, [selectedBlockId]);
|
|
77
|
-
const
|
|
78
|
-
|
|
78
|
+
const isMultiSelect = ((selectedBlockIds == null ? void 0 : selectedBlockIds.size) ?? 0) > 1;
|
|
79
|
+
const handleSelectBlock = useCallback((blockId, event) => {
|
|
80
|
+
onSelectBlock(blockId, event);
|
|
79
81
|
}, [onSelectBlock]);
|
|
80
82
|
if (blocks.length === 0) {
|
|
81
83
|
return /* @__PURE__ */ jsxs(
|
|
@@ -110,8 +112,9 @@ function TreeView({
|
|
|
110
112
|
TreeViewNode,
|
|
111
113
|
{
|
|
112
114
|
block: item.block,
|
|
113
|
-
isSelected: selectedBlockId === item.id,
|
|
114
|
-
|
|
115
|
+
isSelected: selectedBlockIds ? selectedBlockIds.has(item.id) : selectedBlockId === item.id,
|
|
116
|
+
isMultiSelect,
|
|
117
|
+
onSelect: (event) => handleSelectBlock(item.id, event),
|
|
115
118
|
onCopy: onCopy ? () => onCopy(item.id) : void 0,
|
|
116
119
|
onDuplicate: onDuplicate ? () => onDuplicate(item.id) : void 0,
|
|
117
120
|
onRemove: onRemove ? () => onRemove(item.id) : void 0,
|
|
@@ -2,10 +2,17 @@ import type { BlockInstance } from '../../types/blocks';
|
|
|
2
2
|
export interface ClipboardBlock {
|
|
3
3
|
blockSlug: string;
|
|
4
4
|
props: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export interface ClipboardData {
|
|
7
|
+
blocks: ClipboardBlock[];
|
|
8
|
+
sourceEntitySlug?: string;
|
|
5
9
|
copiedAt: number;
|
|
6
10
|
}
|
|
11
|
+
export declare function copyBlocksToClipboard(blocks: BlockInstance[], sourceEntitySlug?: string): void;
|
|
7
12
|
export declare function copyBlockToClipboard(block: BlockInstance): void;
|
|
13
|
+
export declare function getBlocksFromClipboard(): ClipboardData | null;
|
|
8
14
|
export declare function getBlockFromClipboard(): ClipboardBlock | null;
|
|
9
|
-
export declare function
|
|
15
|
+
export declare function getClipboardBlockCount(): number;
|
|
16
|
+
export declare function hasClipboardBlocks(): boolean;
|
|
10
17
|
export declare function clearBlockClipboard(): void;
|
|
11
18
|
//# sourceMappingURL=clipboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../../src/lib/blocks/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAIvD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../../src/lib/blocks/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAIvD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAU9F;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAE/D;AAED,wBAAgB,sBAAsB,IAAI,aAAa,GAAG,IAAI,CAY7D;AAED,wBAAgB,qBAAqB,IAAI,cAAc,GAAG,IAAI,CAI7D;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -1,23 +1,42 @@
|
|
|
1
1
|
const CLIPBOARD_KEY = "nextspark:block-clipboard";
|
|
2
|
-
function
|
|
2
|
+
function copyBlocksToClipboard(blocks, sourceEntitySlug) {
|
|
3
3
|
const data = {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
blocks: blocks.map((b) => ({
|
|
5
|
+
blockSlug: b.blockSlug,
|
|
6
|
+
props: { ...b.props }
|
|
7
|
+
})),
|
|
8
|
+
sourceEntitySlug,
|
|
6
9
|
copiedAt: Date.now()
|
|
7
10
|
};
|
|
8
11
|
localStorage.setItem(CLIPBOARD_KEY, JSON.stringify(data));
|
|
9
12
|
}
|
|
10
|
-
function
|
|
13
|
+
function copyBlockToClipboard(block) {
|
|
14
|
+
copyBlocksToClipboard([block]);
|
|
15
|
+
}
|
|
16
|
+
function getBlocksFromClipboard() {
|
|
11
17
|
const raw = localStorage.getItem(CLIPBOARD_KEY);
|
|
12
18
|
if (!raw) return null;
|
|
13
19
|
try {
|
|
14
|
-
|
|
20
|
+
const data = JSON.parse(raw);
|
|
21
|
+
if (Array.isArray(data == null ? void 0 : data.blocks)) {
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
15
25
|
} catch {
|
|
16
26
|
return null;
|
|
17
27
|
}
|
|
18
28
|
}
|
|
19
|
-
function
|
|
20
|
-
|
|
29
|
+
function getBlockFromClipboard() {
|
|
30
|
+
const data = getBlocksFromClipboard();
|
|
31
|
+
if (!data || data.blocks.length === 0) return null;
|
|
32
|
+
return data.blocks[data.blocks.length - 1];
|
|
33
|
+
}
|
|
34
|
+
function getClipboardBlockCount() {
|
|
35
|
+
var _a;
|
|
36
|
+
return ((_a = getBlocksFromClipboard()) == null ? void 0 : _a.blocks.length) ?? 0;
|
|
37
|
+
}
|
|
38
|
+
function hasClipboardBlocks() {
|
|
39
|
+
return getClipboardBlockCount() > 0;
|
|
21
40
|
}
|
|
22
41
|
function clearBlockClipboard() {
|
|
23
42
|
localStorage.removeItem(CLIPBOARD_KEY);
|
|
@@ -25,6 +44,9 @@ function clearBlockClipboard() {
|
|
|
25
44
|
export {
|
|
26
45
|
clearBlockClipboard,
|
|
27
46
|
copyBlockToClipboard,
|
|
47
|
+
copyBlocksToClipboard,
|
|
28
48
|
getBlockFromClipboard,
|
|
29
|
-
|
|
49
|
+
getBlocksFromClipboard,
|
|
50
|
+
getClipboardBlockCount,
|
|
51
|
+
hasClipboardBlocks
|
|
30
52
|
};
|
|
@@ -306,13 +306,32 @@
|
|
|
306
306
|
},
|
|
307
307
|
"layout": {
|
|
308
308
|
"empty": "No blocks added yet",
|
|
309
|
-
"pasteBlock": "Paste block"
|
|
309
|
+
"pasteBlock": "Paste block",
|
|
310
|
+
"pasteBlocks": "Paste {count} blocks"
|
|
310
311
|
},
|
|
311
312
|
"messages": {
|
|
312
313
|
"saved": "Saved successfully",
|
|
313
314
|
"created": "Created successfully",
|
|
314
315
|
"blockCopied": "Block copied to clipboard",
|
|
315
316
|
"blockPasted": "Block pasted"
|
|
317
|
+
},
|
|
318
|
+
"multiSelect": {
|
|
319
|
+
"selected": "{count, plural, one {# block selected} other {# blocks selected}}",
|
|
320
|
+
"selectAll": "Select all",
|
|
321
|
+
"deselectAll": "Deselect all",
|
|
322
|
+
"copy": "Copy",
|
|
323
|
+
"copied": "{count, plural, one {Block copied} other {# blocks copied}}",
|
|
324
|
+
"paste": "Paste",
|
|
325
|
+
"pasted": "{count, plural, one {Block pasted} other {# blocks pasted}}",
|
|
326
|
+
"pastedPartial": "{pasted} of {total} blocks pasted ({skipped} incompatible)",
|
|
327
|
+
"duplicate": "Duplicate",
|
|
328
|
+
"duplicated": "{count, plural, one {Block duplicated} other {# blocks duplicated}}",
|
|
329
|
+
"delete": "Delete",
|
|
330
|
+
"deleteConfirm": "{count, plural, one {Delete this block?} other {Delete # blocks?}}",
|
|
331
|
+
"deleted": "{count, plural, one {Block deleted} other {# blocks deleted}}",
|
|
332
|
+
"patternSkipped": "Pattern references excluded from selection",
|
|
333
|
+
"clipboardEmpty": "Clipboard is empty",
|
|
334
|
+
"settingsHint": "Use the action bar to manage selected blocks"
|
|
316
335
|
}
|
|
317
336
|
},
|
|
318
337
|
"patterns": {
|
|
@@ -308,6 +308,7 @@ declare const _default: {
|
|
|
308
308
|
layout: {
|
|
309
309
|
empty: string;
|
|
310
310
|
pasteBlock: string;
|
|
311
|
+
pasteBlocks: string;
|
|
311
312
|
};
|
|
312
313
|
messages: {
|
|
313
314
|
saved: string;
|
|
@@ -315,6 +316,24 @@ declare const _default: {
|
|
|
315
316
|
blockCopied: string;
|
|
316
317
|
blockPasted: string;
|
|
317
318
|
};
|
|
319
|
+
multiSelect: {
|
|
320
|
+
selected: string;
|
|
321
|
+
selectAll: string;
|
|
322
|
+
deselectAll: string;
|
|
323
|
+
copy: string;
|
|
324
|
+
copied: string;
|
|
325
|
+
paste: string;
|
|
326
|
+
pasted: string;
|
|
327
|
+
pastedPartial: string;
|
|
328
|
+
duplicate: string;
|
|
329
|
+
duplicated: string;
|
|
330
|
+
delete: string;
|
|
331
|
+
deleteConfirm: string;
|
|
332
|
+
deleted: string;
|
|
333
|
+
patternSkipped: string;
|
|
334
|
+
clipboardEmpty: string;
|
|
335
|
+
settingsHint: string;
|
|
336
|
+
};
|
|
318
337
|
};
|
|
319
338
|
patterns: {
|
|
320
339
|
delete: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/messages/en/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/messages/en/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,wBAqBU"}
|