camox 0.76.0 → 0.76.1
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/core/editing/createEditableBlock.js +1077 -1681
- package/dist/core/editing/fieldSlot.js +251 -0
- package/dist/core/editing/useFieldSlot.js +159 -0
- package/dist/core/layoutContext.d.ts +2 -0
- package/dist/core/layoutContext.js +27 -1
- package/dist/features/canvas/CanvasPageFrame.js +2 -2
- package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -1
- package/dist/features/canvas/canvasCameraController.js +595 -0
- package/dist/features/canvas/useCanvasCamera.js +141 -587
- package/dist/features/canvas/useCanvasFrame.js +1 -1
- package/dist/features/page/DerivedPageContent.js +4 -8
- package/dist/features/preview/components/AssetLightbox.js +6 -65
- package/dist/features/preview/components/CanvasPreview.js +2 -2
- package/dist/features/preview/components/Frame.js +3 -3
- package/dist/features/preview/components/ItemFieldsEditor.js +376 -460
- package/dist/features/preview/components/Overlays.js +4 -9
- package/dist/features/preview/components/PreviewPanel.js +3 -3
- package/dist/features/preview/components/RemovedBlockPlaceholder.js +2 -2
- package/dist/features/preview/components/SelectionEditor.js +285 -339
- package/dist/features/preview/components/ZoomableImage.js +105 -0
- package/dist/features/preview/components/contentFieldSchema.js +3 -1
- package/dist/features/preview/components/useFieldWriter.js +30 -51
- package/dist/features/preview/components/useRecordView.js +3 -3
- package/dist/features/preview/overlayMessages.js +20 -58
- package/dist/features/preview/previewStore.js +6 -123
- package/dist/features/preview/repeatableItemPath.js +47 -0
- package/dist/features/renderer/RendererApp.js +6 -6
- package/dist/features/renderer/RendererFrames.js +2 -2
- package/dist/features/renderer/rendererHost.js +1 -1
- package/dist/features/routes/pageRuntime.d.ts +2 -8
- package/dist/features/routes/pageRuntime.js +21 -105
- package/dist/features/runtime/pageApp.js +1 -1
- package/dist/features/runtime/pageRead.js +105 -0
- package/dist/features/runtime/reader.d.ts +25 -0
- package/dist/features/runtime/reader.js +142 -0
- package/dist/features/runtime/runtime.d.ts +9 -3
- package/dist/features/runtime/runtime.js +608 -776
- package/dist/features/sdkBundle/buildSdkBundle.d.ts +5 -0
- package/dist/features/sdkBundle/buildSdkBundle.js +9 -3
- package/dist/features/studio/components/DraftsSheet.js +124 -65
- package/dist/features/studio/components/ThreadMessages.js +5 -9
- package/dist/features/studio/showInCanvas.js +9 -19
- package/dist/features/studio/useEditorSelection.js +8 -19
- package/dist/package.js +1 -1
- package/dist/studio.css +1 -1
- package/package.json +4 -4
- package/dist/core/hooks/useFieldSelection.js +0 -67
- package/dist/core/hooks/useIsEditable.js +0 -21
- package/dist/core/hooks/useOverlayMessage.js +0 -70
|
@@ -15,6 +15,11 @@ export interface BuiltSdkBundle {
|
|
|
15
15
|
name: string;
|
|
16
16
|
/** Its files, every one at the root: entries, chunks and assets. */
|
|
17
17
|
dir: string;
|
|
18
|
+
/**
|
|
19
|
+
* The modules a page loads at first paint, by id, for the browser bundle as just built: what
|
|
20
|
+
* every visitor downloads, before anything loads lazily.
|
|
21
|
+
*/
|
|
22
|
+
firstPaint?: string[];
|
|
18
23
|
}
|
|
19
24
|
export type SdkBundleBuild = Record<SdkBundleTarget, BuiltSdkBundle>;
|
|
20
25
|
/** The lockfile a website installed from, and the website's importer in it. */
|
|
@@ -62,7 +62,7 @@ async function buildSdkBundle({ root, outDir, settings }) {
|
|
|
62
62
|
importer,
|
|
63
63
|
target
|
|
64
64
|
});
|
|
65
|
-
const entries = await buildTarget({
|
|
65
|
+
const { entries, firstPaint } = await buildTarget({
|
|
66
66
|
root: resolve(root),
|
|
67
67
|
dir,
|
|
68
68
|
target,
|
|
@@ -79,7 +79,8 @@ async function buildSdkBundle({ root, outDir, settings }) {
|
|
|
79
79
|
await writeFile(join(dir, SDK_BUNDLE_MANIFEST), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
80
80
|
result[target] = {
|
|
81
81
|
name: names[target],
|
|
82
|
-
dir
|
|
82
|
+
dir,
|
|
83
|
+
...firstPaint ? { firstPaint } : {}
|
|
83
84
|
};
|
|
84
85
|
}
|
|
85
86
|
return result;
|
|
@@ -164,9 +165,11 @@ async function buildTarget({ root, dir, target, specifiers, names, settings }) {
|
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
};
|
|
168
|
+
let firstPaint;
|
|
167
169
|
if (!workerd) {
|
|
168
170
|
const input = config.build.rolldownOptions.input;
|
|
169
171
|
const pageModules = await modulesLoadedStatically(config, Object.fromEntries(specifiers.filter(loadsAtFirstPaint).map((specifier) => [entryName(specifier), input[entryName(specifier)]])));
|
|
172
|
+
firstPaint = [...pageModules];
|
|
170
173
|
const output = config.build.rolldownOptions.output;
|
|
171
174
|
output.codeSplitting = { groups: [{
|
|
172
175
|
name: "react",
|
|
@@ -179,7 +182,10 @@ async function buildTarget({ root, dir, target, specifiers, names, settings }) {
|
|
|
179
182
|
}] };
|
|
180
183
|
}
|
|
181
184
|
await build(config);
|
|
182
|
-
return
|
|
185
|
+
return {
|
|
186
|
+
entries: Object.fromEntries(specifiers.map((specifier) => [specifier, sdkBundleEntryFile(specifier)])),
|
|
187
|
+
...firstPaint ? { firstPaint } : {}
|
|
188
|
+
};
|
|
183
189
|
}
|
|
184
190
|
/**
|
|
185
191
|
* The chunks a page loads at first paint, beside the entry files it imports: its code, React, and
|
|
@@ -18,101 +18,160 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@camox/ui/tabs";
|
|
|
18
18
|
* restore or delete (ADR 0046), and a tab of Publications, to read why Live changed (ADR 0045).
|
|
19
19
|
*/
|
|
20
20
|
function DraftsSheet(t0) {
|
|
21
|
-
const $ = c(
|
|
21
|
+
const $ = c(36);
|
|
22
22
|
const { projectId, open, onOpenChange } = t0;
|
|
23
23
|
let t1;
|
|
24
|
-
if ($[0]
|
|
25
|
-
t1 =
|
|
24
|
+
if ($[0] !== projectId) {
|
|
25
|
+
t1 = reads.archivedDrafts({ projectId });
|
|
26
|
+
$[0] = projectId;
|
|
27
|
+
$[1] = t1;
|
|
28
|
+
} else t1 = $[1];
|
|
29
|
+
let t2;
|
|
30
|
+
if ($[2] !== open) {
|
|
31
|
+
t2 = { enabled: open };
|
|
32
|
+
$[2] = open;
|
|
33
|
+
$[3] = t2;
|
|
34
|
+
} else t2 = $[3];
|
|
35
|
+
const archived = useReadQuery(t1, t2);
|
|
36
|
+
let t3;
|
|
37
|
+
if ($[4] !== projectId) {
|
|
38
|
+
t3 = reads.publications({ projectId });
|
|
39
|
+
$[4] = projectId;
|
|
40
|
+
$[5] = t3;
|
|
41
|
+
} else t3 = $[5];
|
|
42
|
+
let t4;
|
|
43
|
+
if ($[6] !== open) {
|
|
44
|
+
t4 = { enabled: open };
|
|
45
|
+
$[6] = open;
|
|
46
|
+
$[7] = t4;
|
|
47
|
+
} else t4 = $[7];
|
|
48
|
+
const publications = useReadQuery(t3, t4);
|
|
49
|
+
let t5;
|
|
50
|
+
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
|
51
|
+
t5 = /* @__PURE__ */ jsxs(SheetHeader, {
|
|
26
52
|
className: "border-b",
|
|
27
53
|
children: [/* @__PURE__ */ jsx(SheetTitle, { children: "Drafts" }), /* @__PURE__ */ jsx(SheetDescription, { children: "Drafts set aside, to bring back or delete, and what was published." })]
|
|
28
54
|
});
|
|
29
|
-
$[
|
|
30
|
-
} else
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
55
|
+
$[8] = t5;
|
|
56
|
+
} else t5 = $[8];
|
|
57
|
+
const t6 = archived.data?.length;
|
|
58
|
+
let t7;
|
|
59
|
+
if ($[9] !== t6) {
|
|
60
|
+
t7 = /* @__PURE__ */ jsxs(TabsTrigger, {
|
|
34
61
|
value: "archived",
|
|
35
|
-
children: "Archived"
|
|
36
|
-
})
|
|
62
|
+
children: ["Archived ", /* @__PURE__ */ jsx(TabCount, { count: t6 })]
|
|
63
|
+
});
|
|
64
|
+
$[9] = t6;
|
|
65
|
+
$[10] = t7;
|
|
66
|
+
} else t7 = $[10];
|
|
67
|
+
const t8 = publications.data?.length;
|
|
68
|
+
let t9;
|
|
69
|
+
if ($[11] !== t8) {
|
|
70
|
+
t9 = /* @__PURE__ */ jsxs(TabsTrigger, {
|
|
37
71
|
value: "published",
|
|
38
|
-
children: "Published"
|
|
39
|
-
})
|
|
40
|
-
$[
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
72
|
+
children: ["Published ", /* @__PURE__ */ jsx(TabCount, { count: t8 })]
|
|
73
|
+
});
|
|
74
|
+
$[11] = t8;
|
|
75
|
+
$[12] = t9;
|
|
76
|
+
} else t9 = $[12];
|
|
77
|
+
let t10;
|
|
78
|
+
if ($[13] !== t7 || $[14] !== t9) {
|
|
79
|
+
t10 = /* @__PURE__ */ jsxs(TabsList, { children: [t7, t9] });
|
|
80
|
+
$[13] = t7;
|
|
81
|
+
$[14] = t9;
|
|
82
|
+
$[15] = t10;
|
|
83
|
+
} else t10 = $[15];
|
|
84
|
+
let t11;
|
|
85
|
+
if ($[16] !== onOpenChange || $[17] !== open || $[18] !== projectId) {
|
|
86
|
+
t11 = open && /* @__PURE__ */ jsx(ArchivedDrafts, {
|
|
45
87
|
projectId,
|
|
46
88
|
onRestored: () => onOpenChange(false)
|
|
47
89
|
});
|
|
48
|
-
$[
|
|
49
|
-
$[
|
|
50
|
-
$[
|
|
51
|
-
$[
|
|
52
|
-
} else
|
|
53
|
-
let
|
|
54
|
-
if ($[
|
|
55
|
-
|
|
90
|
+
$[16] = onOpenChange;
|
|
91
|
+
$[17] = open;
|
|
92
|
+
$[18] = projectId;
|
|
93
|
+
$[19] = t11;
|
|
94
|
+
} else t11 = $[19];
|
|
95
|
+
let t12;
|
|
96
|
+
if ($[20] !== t11) {
|
|
97
|
+
t12 = /* @__PURE__ */ jsx(TabsContent, {
|
|
56
98
|
value: "archived",
|
|
57
99
|
className: "overflow-y-auto",
|
|
58
|
-
children:
|
|
100
|
+
children: t11
|
|
59
101
|
});
|
|
60
|
-
$[
|
|
61
|
-
$[
|
|
62
|
-
} else
|
|
63
|
-
let
|
|
64
|
-
if ($[
|
|
65
|
-
|
|
102
|
+
$[20] = t11;
|
|
103
|
+
$[21] = t12;
|
|
104
|
+
} else t12 = $[21];
|
|
105
|
+
let t13;
|
|
106
|
+
if ($[22] !== onOpenChange || $[23] !== open || $[24] !== projectId) {
|
|
107
|
+
t13 = open && /* @__PURE__ */ jsx(PublishedTab, {
|
|
66
108
|
projectId,
|
|
67
109
|
onEntered: () => onOpenChange(false)
|
|
68
110
|
});
|
|
69
|
-
$[
|
|
70
|
-
$[
|
|
71
|
-
$[
|
|
72
|
-
$[
|
|
73
|
-
} else
|
|
74
|
-
let
|
|
75
|
-
if ($[
|
|
76
|
-
|
|
111
|
+
$[22] = onOpenChange;
|
|
112
|
+
$[23] = open;
|
|
113
|
+
$[24] = projectId;
|
|
114
|
+
$[25] = t13;
|
|
115
|
+
} else t13 = $[25];
|
|
116
|
+
let t14;
|
|
117
|
+
if ($[26] !== t13) {
|
|
118
|
+
t14 = /* @__PURE__ */ jsx(TabsContent, {
|
|
77
119
|
value: "published",
|
|
78
120
|
className: "overflow-y-auto",
|
|
79
|
-
children:
|
|
121
|
+
children: t13
|
|
80
122
|
});
|
|
81
|
-
$[
|
|
82
|
-
$[
|
|
83
|
-
} else
|
|
84
|
-
let
|
|
85
|
-
if ($[
|
|
86
|
-
|
|
123
|
+
$[26] = t13;
|
|
124
|
+
$[27] = t14;
|
|
125
|
+
} else t14 = $[27];
|
|
126
|
+
let t15;
|
|
127
|
+
if ($[28] !== t10 || $[29] !== t12 || $[30] !== t14) {
|
|
128
|
+
t15 = /* @__PURE__ */ jsxs(SheetContent, {
|
|
87
129
|
side: "right",
|
|
88
130
|
className: "gap-0 data-[side=right]:sm:max-w-3xl",
|
|
89
|
-
children: [
|
|
131
|
+
children: [t5, /* @__PURE__ */ jsxs(Tabs, {
|
|
90
132
|
defaultValue: "archived",
|
|
91
133
|
className: "flex-1 overflow-hidden p-4",
|
|
92
134
|
children: [
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
135
|
+
t10,
|
|
136
|
+
t12,
|
|
137
|
+
t14
|
|
96
138
|
]
|
|
97
139
|
})]
|
|
98
140
|
});
|
|
99
|
-
$[
|
|
100
|
-
$[
|
|
101
|
-
$[
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
141
|
+
$[28] = t10;
|
|
142
|
+
$[29] = t12;
|
|
143
|
+
$[30] = t14;
|
|
144
|
+
$[31] = t15;
|
|
145
|
+
} else t15 = $[31];
|
|
146
|
+
let t16;
|
|
147
|
+
if ($[32] !== onOpenChange || $[33] !== open || $[34] !== t15) {
|
|
148
|
+
t16 = /* @__PURE__ */ jsx(Sheet, {
|
|
106
149
|
open,
|
|
107
150
|
onOpenChange,
|
|
108
|
-
children:
|
|
151
|
+
children: t15
|
|
152
|
+
});
|
|
153
|
+
$[32] = onOpenChange;
|
|
154
|
+
$[33] = open;
|
|
155
|
+
$[34] = t15;
|
|
156
|
+
$[35] = t16;
|
|
157
|
+
} else t16 = $[35];
|
|
158
|
+
return t16;
|
|
159
|
+
}
|
|
160
|
+
/** How many items a tab holds, once they've loaded. */
|
|
161
|
+
function TabCount(t0) {
|
|
162
|
+
const $ = c(2);
|
|
163
|
+
const { count } = t0;
|
|
164
|
+
if (count === void 0) return null;
|
|
165
|
+
let t1;
|
|
166
|
+
if ($[0] !== count) {
|
|
167
|
+
t1 = /* @__PURE__ */ jsx("span", {
|
|
168
|
+
className: "text-muted-foreground tabular-nums",
|
|
169
|
+
children: count
|
|
109
170
|
});
|
|
110
|
-
$[
|
|
111
|
-
$[
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
} else t8 = $[20];
|
|
115
|
-
return t8;
|
|
171
|
+
$[0] = count;
|
|
172
|
+
$[1] = t1;
|
|
173
|
+
} else t1 = $[1];
|
|
174
|
+
return t1;
|
|
116
175
|
}
|
|
117
176
|
/** The archived drafts, each with Restore and Delete. */
|
|
118
177
|
function ArchivedDrafts(t0) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
|
+
import { ZoomableImage } from "../../preview/components/ZoomableImage.js";
|
|
2
3
|
import { Squareling } from "./Squareling.js";
|
|
3
4
|
import { ThreadMarkdown } from "./ThreadMarkdown.js";
|
|
4
5
|
import { c } from "react/compiler-runtime";
|
|
@@ -706,15 +707,10 @@ function AttachmentThumbnails(t0) {
|
|
|
706
707
|
} else t7 = $[8];
|
|
707
708
|
let t8;
|
|
708
709
|
if ($[9] !== opened) {
|
|
709
|
-
t8 = opened && /* @__PURE__ */ jsx(
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
alt: opened.filename,
|
|
714
|
-
className: "max-h-full max-w-full object-contain shadow-lg",
|
|
715
|
-
draggable: false
|
|
716
|
-
})
|
|
717
|
-
});
|
|
710
|
+
t8 = opened && /* @__PURE__ */ jsx(ZoomableImage, {
|
|
711
|
+
src: opened.url,
|
|
712
|
+
alt: opened.filename
|
|
713
|
+
}, opened.url);
|
|
718
714
|
$[9] = opened;
|
|
719
715
|
$[10] = t8;
|
|
720
716
|
} else t8 = $[10];
|
|
@@ -3,6 +3,7 @@ import { useViewLocale } from "../../lib/view-locale-context.js";
|
|
|
3
3
|
import { useLocation, useNavigate } from "../navigation/navigation.js";
|
|
4
4
|
import { useProjectUuid } from "../../lib/auth.js";
|
|
5
5
|
import { reads, useStudioCache } from "../../lib/studio-reads.js";
|
|
6
|
+
import { fieldOwner, ownerSelection, slotSelection } from "../../core/editing/fieldSlot.js";
|
|
6
7
|
import { previewStore, sameEditingOwner } from "../preview/previewStore.js";
|
|
7
8
|
import { fieldTypesDictionary } from "../../core/lib/fieldTypes.js";
|
|
8
9
|
import { c } from "react/compiler-runtime";
|
|
@@ -18,27 +19,16 @@ const isFieldType = (kind) => !!kind && Object.hasOwn(fieldTypesDictionary, kind
|
|
|
18
19
|
/** What to select on the target's page: its field, else its item or block, else nothing. */
|
|
19
20
|
function selectionOf({ blockId, itemId, field }) {
|
|
20
21
|
if (!blockId) return null;
|
|
21
|
-
const
|
|
22
|
-
if (itemId) return field && fieldType ? {
|
|
23
|
-
type: "item-field",
|
|
24
|
-
blockId,
|
|
25
|
-
itemId,
|
|
26
|
-
fieldName: field.name,
|
|
27
|
-
fieldType
|
|
28
|
-
} : {
|
|
29
|
-
type: "item",
|
|
22
|
+
const owner = fieldOwner({
|
|
30
23
|
blockId,
|
|
31
24
|
itemId
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
type: "block",
|
|
40
|
-
blockId
|
|
41
|
-
};
|
|
25
|
+
});
|
|
26
|
+
if (!field || !isFieldType(field.kind)) return ownerSelection(owner);
|
|
27
|
+
return slotSelection({
|
|
28
|
+
owner,
|
|
29
|
+
name: field.name,
|
|
30
|
+
type: field.kind
|
|
31
|
+
});
|
|
42
32
|
}
|
|
43
33
|
/** Stops selecting what was last shown in the Canvas. */
|
|
44
34
|
let stopSelecting = null;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { placedRecords } from "../../lib/normalized-data.js";
|
|
2
2
|
import { reads, useReadQuery } from "../../lib/studio-reads.js";
|
|
3
3
|
import { useBlockDefinition, useCollectionDefinition } from "../../lib/studio-definitions.js";
|
|
4
|
-
import { isBlockPlacement,
|
|
4
|
+
import { isBlockPlacement, slotOf } from "../../core/editing/fieldSlot.js";
|
|
5
|
+
import { previewStore, selectionBlockId, selectionForOwner, selectionItemId } from "../preview/previewStore.js";
|
|
5
6
|
import { entityName } from "../preview/entityName.js";
|
|
6
|
-
import {
|
|
7
|
-
import { formatFieldName } from "../preview/components/
|
|
8
|
-
import { getSchemaForItem } from "../preview/components/SelectionEditor.js";
|
|
7
|
+
import { itemContentSchema, itemPath } from "../preview/repeatableItemPath.js";
|
|
8
|
+
import { contentFieldSchema, formatFieldName } from "../preview/components/contentFieldSchema.js";
|
|
9
9
|
import { c } from "react/compiler-runtime";
|
|
10
10
|
import { useSelector } from "@xstate/store-react";
|
|
11
11
|
|
|
@@ -32,14 +32,8 @@ function editorSelectionOf({ selection, block, items, schema, records, recordSch
|
|
|
32
32
|
for (const item of items) path.push(entityName(item, "Item"));
|
|
33
33
|
const recordSelected = selection.type === "record" || selection.type === "record-field";
|
|
34
34
|
if (recordSelected) path.push(...records.length > 0 ? records.map((record) => record.title || "Record") : ["Record"]);
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
fieldName = selection.fieldName;
|
|
38
|
-
path.push(fieldLabel(schema, fieldName));
|
|
39
|
-
} else if (selection.type === "record-field") {
|
|
40
|
-
fieldName = selection.recordFieldName;
|
|
41
|
-
path.push(fieldLabel(recordSchema, fieldName));
|
|
42
|
-
}
|
|
35
|
+
const fieldName = slotOf(selection)?.name;
|
|
36
|
+
if (fieldName) path.push(fieldLabel(recordSelected ? recordSchema : schema, fieldName));
|
|
43
37
|
const itemId = selectionItemId(selection) ?? void 0;
|
|
44
38
|
const recordId = recordSelected ? selection.nested?.recordId ?? selection.recordId : void 0;
|
|
45
39
|
return {
|
|
@@ -94,13 +88,8 @@ function useEditorSelection(where) {
|
|
|
94
88
|
$[8] = t4;
|
|
95
89
|
$[9] = t5;
|
|
96
90
|
} else t5 = $[9];
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
for (let item_0 = itemId ? itemsMap.get(itemId) : void 0; item_0;) {
|
|
100
|
-
items.unshift(item_0);
|
|
101
|
-
item_0 = item_0.parentItemId ? itemsMap.get(item_0.parentItemId) : void 0;
|
|
102
|
-
}
|
|
103
|
-
const schema = blockDef && itemId ? getSchemaForItem(blockDef.contentSchema, itemId, itemsMap) : blockDef?.contentSchema;
|
|
91
|
+
const items = itemPath(itemId, t5);
|
|
92
|
+
const schema = blockDef && itemContentSchema(blockDef.contentSchema, items);
|
|
104
93
|
const records = [];
|
|
105
94
|
if ((selection?.type === "record" || selection?.type === "record-field") && isBlockPlacement(selection)) {
|
|
106
95
|
const placer = itemId ? items.at(-1) : bundle?.block;
|
package/dist/package.js
CHANGED