@toaster-builder/site-runtime 0.1.0 → 0.1.2
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/README.md
CHANGED
|
@@ -36,3 +36,57 @@ export default defineNuxtConfig({
|
|
|
36
36
|
modules: ['@toaster-builder/site-runtime'],
|
|
37
37
|
})
|
|
38
38
|
```
|
|
39
|
+
|
|
40
|
+
## Граница блока в Builder
|
|
41
|
+
|
|
42
|
+
В dev-режиме Runtime автоматически добавляет корневому DOM-элементу обычного
|
|
43
|
+
Block атрибуты `data-toaster-editor-root="auto"` и
|
|
44
|
+
`data-toaster-placement-id`. Рамка
|
|
45
|
+
Builder строится по фактическому `getBoundingClientRect()` этого элемента, поэтому
|
|
46
|
+
работает для элементов с `position: fixed`, `sticky` и `absolute`.
|
|
47
|
+
|
|
48
|
+
Block с несколькими корнями или `Teleport` должен явно отметить визуальный
|
|
49
|
+
элемент, который Builder будет считать его границей. Явная граница имеет
|
|
50
|
+
приоритет над автоматически найденным корнем:
|
|
51
|
+
|
|
52
|
+
```vue
|
|
53
|
+
<script setup lang="ts">
|
|
54
|
+
import { inject, ref } from 'vue'
|
|
55
|
+
import { blockPlacementIdKey } from '#toaster-site-runtime/utils/block-placement'
|
|
56
|
+
|
|
57
|
+
const placementId = inject(blockPlacementIdKey, ref(''))
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<template>
|
|
61
|
+
<Teleport to="body">
|
|
62
|
+
<div
|
|
63
|
+
data-toaster-editor-root
|
|
64
|
+
:data-toaster-placement-id="placementId"
|
|
65
|
+
>
|
|
66
|
+
<!-- Содержимое модального окна -->
|
|
67
|
+
</div>
|
|
68
|
+
</Teleport>
|
|
69
|
+
</template>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Для модального Block атрибут ставится на само окно, а не на backdrop.
|
|
73
|
+
|
|
74
|
+
## Действия блока в Builder
|
|
75
|
+
|
|
76
|
+
По умолчанию Builder показывает полный набор действий. Block может ограничить
|
|
77
|
+
его атрибутом `data-toaster-editor-actions` на том же элементе, который отмечен
|
|
78
|
+
как `data-toaster-editor-root`:
|
|
79
|
+
|
|
80
|
+
```vue
|
|
81
|
+
<div
|
|
82
|
+
data-toaster-editor-root
|
|
83
|
+
data-toaster-editor-actions="version settings assistant add add-ai"
|
|
84
|
+
:data-toaster-placement-id="placementId"
|
|
85
|
+
>
|
|
86
|
+
<!-- Содержимое блока -->
|
|
87
|
+
</div>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Доступные значения: `version`, `move`, `copy`, `settings`, `assistant`,
|
|
91
|
+
`visibility`, `delete`, `add`, `add-ai`. Если атрибут отсутствует, доступны все
|
|
92
|
+
действия. Пустой атрибут скрывает все элементы управления.
|
package/dist/module.json
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
computed,
|
|
4
|
+
nextTick,
|
|
5
|
+
onBeforeUnmount,
|
|
6
|
+
onMounted,
|
|
7
|
+
ref,
|
|
8
|
+
shallowRef
|
|
9
|
+
} from "vue";
|
|
3
10
|
import addBlockIcon from "../assets/editor/add-block.svg";
|
|
4
11
|
import aiAssistantIcon from "../assets/editor/ai-assistant.svg";
|
|
5
12
|
import blockSettingsCenterIcon from "../assets/editor/block-settings-center.svg";
|
|
@@ -12,6 +19,10 @@ import moveBlockUpIcon from "../assets/editor/move-block-up.svg";
|
|
|
12
19
|
import showBlockIcon from "../assets/editor/show-block.svg";
|
|
13
20
|
import BlockPlacementProvider from "#toaster-site-runtime/components/BlockPlacementProvider.vue";
|
|
14
21
|
import { useBuilderEventService } from "#toaster-site-runtime/composables/useBuilderEventService";
|
|
22
|
+
import {
|
|
23
|
+
blockEditorActions,
|
|
24
|
+
parseBlockEditorActions
|
|
25
|
+
} from "#toaster-site-runtime/utils/block-editor-actions";
|
|
15
26
|
const props = defineProps({
|
|
16
27
|
blockComponent: { type: null, required: true },
|
|
17
28
|
blockId: { type: String, required: true },
|
|
@@ -24,6 +35,22 @@ const props = defineProps({
|
|
|
24
35
|
region: { type: null, required: true }
|
|
25
36
|
});
|
|
26
37
|
const builderEvents = useBuilderEventService();
|
|
38
|
+
const contentElement = ref(null);
|
|
39
|
+
const editorTarget = shallowRef(null);
|
|
40
|
+
const overlayElement = ref(null);
|
|
41
|
+
const overlayHovered = ref(false);
|
|
42
|
+
const overlayFocused = ref(false);
|
|
43
|
+
const overlayStyle = ref({});
|
|
44
|
+
const overlayVisible = ref(false);
|
|
45
|
+
const enabledEditorActions = shallowRef(
|
|
46
|
+
new Set(blockEditorActions)
|
|
47
|
+
);
|
|
48
|
+
const targetHovered = ref(false);
|
|
49
|
+
const targetFocused = ref(false);
|
|
50
|
+
const overlayActive = computed(() => overlayHovered.value || overlayFocused.value || targetHovered.value || targetFocused.value);
|
|
51
|
+
let boundsFrame = null;
|
|
52
|
+
let mutationObserver = null;
|
|
53
|
+
let resizeObserver = null;
|
|
27
54
|
const blockVersionLabel = computed(() => {
|
|
28
55
|
const [name, variant = ""] = props.blockId.split("/");
|
|
29
56
|
const formattedVariant = /^v\d+$/i.test(variant) ? variant.toUpperCase() : variant;
|
|
@@ -36,6 +63,123 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
36
63
|
region: props.region
|
|
37
64
|
}, payload);
|
|
38
65
|
}
|
|
66
|
+
function updateOverlayBounds() {
|
|
67
|
+
boundsFrame = null;
|
|
68
|
+
const target = editorTarget.value;
|
|
69
|
+
if (!target) {
|
|
70
|
+
overlayVisible.value = false;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const bounds = target.getBoundingClientRect();
|
|
74
|
+
overlayVisible.value = bounds.width > 0 && bounds.height > 0;
|
|
75
|
+
overlayStyle.value = {
|
|
76
|
+
top: `${bounds.top}px`,
|
|
77
|
+
left: `${bounds.left}px`,
|
|
78
|
+
width: `${bounds.width}px`,
|
|
79
|
+
height: `${bounds.height}px`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function scheduleOverlayBoundsUpdate() {
|
|
83
|
+
if (boundsFrame !== null) return;
|
|
84
|
+
boundsFrame = window.requestAnimationFrame(updateOverlayBounds);
|
|
85
|
+
}
|
|
86
|
+
function handleTargetPointerEnter() {
|
|
87
|
+
targetHovered.value = true;
|
|
88
|
+
}
|
|
89
|
+
function handleTargetPointerLeave() {
|
|
90
|
+
targetHovered.value = false;
|
|
91
|
+
}
|
|
92
|
+
function handleTargetFocusIn() {
|
|
93
|
+
targetFocused.value = true;
|
|
94
|
+
}
|
|
95
|
+
function handleTargetFocusOut() {
|
|
96
|
+
window.requestAnimationFrame(() => {
|
|
97
|
+
targetFocused.value = editorTarget.value?.contains(document.activeElement) ?? false;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function unbindEditorTarget() {
|
|
101
|
+
const target = editorTarget.value;
|
|
102
|
+
if (target) {
|
|
103
|
+
target.removeEventListener("pointerenter", handleTargetPointerEnter);
|
|
104
|
+
target.removeEventListener("pointerleave", handleTargetPointerLeave);
|
|
105
|
+
target.removeEventListener("focusin", handleTargetFocusIn);
|
|
106
|
+
target.removeEventListener("focusout", handleTargetFocusOut);
|
|
107
|
+
}
|
|
108
|
+
resizeObserver?.disconnect();
|
|
109
|
+
resizeObserver = null;
|
|
110
|
+
targetHovered.value = false;
|
|
111
|
+
targetFocused.value = false;
|
|
112
|
+
}
|
|
113
|
+
function bindEditorTarget(target) {
|
|
114
|
+
enabledEditorActions.value = parseBlockEditorActions(
|
|
115
|
+
target?.dataset.toasterEditorActions
|
|
116
|
+
);
|
|
117
|
+
if (editorTarget.value === target) {
|
|
118
|
+
scheduleOverlayBoundsUpdate();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
unbindEditorTarget();
|
|
122
|
+
editorTarget.value = target;
|
|
123
|
+
if (!target) {
|
|
124
|
+
overlayVisible.value = false;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
target.addEventListener("pointerenter", handleTargetPointerEnter);
|
|
128
|
+
target.addEventListener("pointerleave", handleTargetPointerLeave);
|
|
129
|
+
target.addEventListener("focusin", handleTargetFocusIn);
|
|
130
|
+
target.addEventListener("focusout", handleTargetFocusOut);
|
|
131
|
+
resizeObserver = new ResizeObserver(scheduleOverlayBoundsUpdate);
|
|
132
|
+
resizeObserver.observe(target);
|
|
133
|
+
scheduleOverlayBoundsUpdate();
|
|
134
|
+
}
|
|
135
|
+
function hasEditorAction(action) {
|
|
136
|
+
return enabledEditorActions.value.has(action);
|
|
137
|
+
}
|
|
138
|
+
function findPlacementTargets(root) {
|
|
139
|
+
return Array.from(root.querySelectorAll("[data-toaster-editor-root]")).filter((element) => element.dataset.toasterPlacementId === props.placementId);
|
|
140
|
+
}
|
|
141
|
+
function resolveEditorTarget() {
|
|
142
|
+
const documentTargets = findPlacementTargets(document);
|
|
143
|
+
const explicitTarget = documentTargets.find(
|
|
144
|
+
(element) => element.dataset.toasterEditorRoot !== "auto"
|
|
145
|
+
);
|
|
146
|
+
const automaticTarget = contentElement.value ? findPlacementTargets(contentElement.value).find(
|
|
147
|
+
(element) => element.dataset.toasterEditorRoot === "auto"
|
|
148
|
+
) : documentTargets.find((element) => element.dataset.toasterEditorRoot === "auto");
|
|
149
|
+
bindEditorTarget(explicitTarget ?? automaticTarget ?? null);
|
|
150
|
+
}
|
|
151
|
+
function handleOverlayFocusOut() {
|
|
152
|
+
window.requestAnimationFrame(() => {
|
|
153
|
+
overlayFocused.value = overlayElement.value?.contains(document.activeElement) ?? false;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
onMounted(() => {
|
|
157
|
+
document.addEventListener("scroll", scheduleOverlayBoundsUpdate, true);
|
|
158
|
+
window.addEventListener("resize", scheduleOverlayBoundsUpdate);
|
|
159
|
+
mutationObserver = new MutationObserver(resolveEditorTarget);
|
|
160
|
+
mutationObserver.observe(document.body, {
|
|
161
|
+
attributes: true,
|
|
162
|
+
attributeFilter: [
|
|
163
|
+
"data-toaster-editor-actions",
|
|
164
|
+
"data-toaster-editor-root",
|
|
165
|
+
"data-toaster-placement-id"
|
|
166
|
+
],
|
|
167
|
+
childList: true,
|
|
168
|
+
subtree: true
|
|
169
|
+
});
|
|
170
|
+
void nextTick(resolveEditorTarget);
|
|
171
|
+
});
|
|
172
|
+
onBeforeUnmount(() => {
|
|
173
|
+
document.removeEventListener("scroll", scheduleOverlayBoundsUpdate, true);
|
|
174
|
+
window.removeEventListener("resize", scheduleOverlayBoundsUpdate);
|
|
175
|
+
mutationObserver?.disconnect();
|
|
176
|
+
mutationObserver = null;
|
|
177
|
+
unbindEditorTarget();
|
|
178
|
+
if (boundsFrame !== null) {
|
|
179
|
+
window.cancelAnimationFrame(boundsFrame);
|
|
180
|
+
boundsFrame = null;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
39
183
|
</script>
|
|
40
184
|
|
|
41
185
|
<template>
|
|
@@ -49,18 +193,38 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
49
193
|
:data-toaster-placement-id="placementId"
|
|
50
194
|
:data-toaster-region="region"
|
|
51
195
|
>
|
|
52
|
-
<div
|
|
196
|
+
<div
|
|
197
|
+
ref="contentElement"
|
|
198
|
+
class="block-editor-frame__content"
|
|
199
|
+
>
|
|
53
200
|
<BlockPlacementProvider :placement-id="placementId">
|
|
54
201
|
<component
|
|
55
202
|
:is="blockComponent"
|
|
203
|
+
data-toaster-editor-root="auto"
|
|
204
|
+
:data-toaster-placement-id="placementId"
|
|
56
205
|
:options="options"
|
|
57
206
|
/>
|
|
58
207
|
</BlockPlacementProvider>
|
|
59
208
|
</div>
|
|
60
209
|
|
|
61
|
-
<
|
|
210
|
+
<div
|
|
211
|
+
v-if="builderReady"
|
|
212
|
+
v-show="overlayVisible"
|
|
213
|
+
ref="overlayElement"
|
|
214
|
+
class="block-editor-frame__overlay"
|
|
215
|
+
:class="{ 'block-editor-frame__overlay--active': overlayActive }"
|
|
216
|
+
data-toaster-editor-overlay
|
|
217
|
+
:data-toaster-editor-actions="[...enabledEditorActions].join(' ')"
|
|
218
|
+
:data-toaster-placement-id="placementId"
|
|
219
|
+
:style="overlayStyle"
|
|
220
|
+
@pointerenter="overlayHovered = true"
|
|
221
|
+
@pointerleave="overlayHovered = false"
|
|
222
|
+
@focusin="overlayFocused = true"
|
|
223
|
+
@focusout="handleOverlayFocusOut"
|
|
224
|
+
>
|
|
62
225
|
<div class="block-editor-frame__toolbar">
|
|
63
226
|
<button
|
|
227
|
+
v-if="hasEditorAction('version')"
|
|
64
228
|
class="block-editor-frame__control block-editor-frame__version"
|
|
65
229
|
type="button"
|
|
66
230
|
:aria-label="`\u0421\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0435\u0440\u0441\u0438\u044E \u0431\u043B\u043E\u043A\u0430 ${blockVersionLabel}`"
|
|
@@ -71,6 +235,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
71
235
|
</button>
|
|
72
236
|
|
|
73
237
|
<button
|
|
238
|
+
v-if="hasEditorAction('move')"
|
|
74
239
|
class="block-editor-frame__control block-editor-frame__icon-button"
|
|
75
240
|
type="button"
|
|
76
241
|
:aria-label="`\u041F\u0435\u0440\u0435\u043D\u0435\u0441\u0442\u0438 \u0432\u0432\u0435\u0440\u0445 \u0431\u043B\u043E\u043A ${blockVersionLabel}`"
|
|
@@ -86,6 +251,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
86
251
|
</button>
|
|
87
252
|
|
|
88
253
|
<button
|
|
254
|
+
v-if="hasEditorAction('move')"
|
|
89
255
|
class="block-editor-frame__control block-editor-frame__icon-button"
|
|
90
256
|
type="button"
|
|
91
257
|
:aria-label="`\u041F\u0435\u0440\u0435\u043D\u0435\u0441\u0442\u0438 \u0432\u043D\u0438\u0437 \u0431\u043B\u043E\u043A ${blockVersionLabel}`"
|
|
@@ -101,6 +267,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
101
267
|
</button>
|
|
102
268
|
|
|
103
269
|
<button
|
|
270
|
+
v-if="hasEditorAction('copy')"
|
|
104
271
|
class="block-editor-frame__control block-editor-frame__icon-button"
|
|
105
272
|
type="button"
|
|
106
273
|
:aria-label="`\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0431\u043B\u043E\u043A ${blockVersionLabel}`"
|
|
@@ -115,6 +282,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
115
282
|
</button>
|
|
116
283
|
|
|
117
284
|
<button
|
|
285
|
+
v-if="hasEditorAction('settings')"
|
|
118
286
|
class="block-editor-frame__control block-editor-frame__icon-button"
|
|
119
287
|
type="button"
|
|
120
288
|
:aria-label="`\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0431\u043B\u043E\u043A\u0430 ${blockVersionLabel}`"
|
|
@@ -139,6 +307,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
139
307
|
</button>
|
|
140
308
|
|
|
141
309
|
<button
|
|
310
|
+
v-if="hasEditorAction('assistant')"
|
|
142
311
|
class="block-editor-frame__control block-editor-frame__icon-button"
|
|
143
312
|
type="button"
|
|
144
313
|
:aria-label="`\u041E\u0442\u043A\u0440\u044B\u0442\u044C AI-\u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442\u0430 \u0434\u043B\u044F \u0431\u043B\u043E\u043A\u0430 ${blockVersionLabel}`"
|
|
@@ -153,6 +322,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
153
322
|
</button>
|
|
154
323
|
|
|
155
324
|
<button
|
|
325
|
+
v-if="hasEditorAction('visibility')"
|
|
156
326
|
class="block-editor-frame__control block-editor-frame__icon-button"
|
|
157
327
|
type="button"
|
|
158
328
|
:aria-label="enabled ? `\u0412\u0440\u0435\u043C\u0435\u043D\u043D\u043E \u0441\u043A\u0440\u044B\u0442\u044C \u0431\u043B\u043E\u043A ${blockVersionLabel}` : `\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0431\u043B\u043E\u043A ${blockVersionLabel}`"
|
|
@@ -167,6 +337,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
167
337
|
</button>
|
|
168
338
|
|
|
169
339
|
<button
|
|
340
|
+
v-if="hasEditorAction('delete')"
|
|
170
341
|
class="block-editor-frame__control block-editor-frame__icon-button"
|
|
171
342
|
type="button"
|
|
172
343
|
:aria-label="`\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0431\u043B\u043E\u043A ${blockVersionLabel}`"
|
|
@@ -182,6 +353,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
182
353
|
</div>
|
|
183
354
|
|
|
184
355
|
<button
|
|
356
|
+
v-if="hasEditorAction('add')"
|
|
185
357
|
class="block-editor-frame__control block-editor-frame__add block-editor-frame__add--after"
|
|
186
358
|
type="button"
|
|
187
359
|
aria-label="Добавить блок снизу"
|
|
@@ -196,6 +368,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
196
368
|
</button>
|
|
197
369
|
|
|
198
370
|
<button
|
|
371
|
+
v-if="hasEditorAction('add-ai')"
|
|
199
372
|
class="block-editor-frame__control block-editor-frame__add-ai"
|
|
200
373
|
type="button"
|
|
201
374
|
:aria-label="`\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0431\u043B\u043E\u043A \u0447\u0435\u0440\u0435\u0437 AI \u043F\u043E\u0441\u043B\u0435 \u0431\u043B\u043E\u043A\u0430 ${blockVersionLabel}`"
|
|
@@ -208,7 +381,7 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
208
381
|
aria-hidden="true"
|
|
209
382
|
>
|
|
210
383
|
</button>
|
|
211
|
-
</
|
|
384
|
+
</div>
|
|
212
385
|
</div>
|
|
213
386
|
</template>
|
|
214
387
|
|
|
@@ -216,16 +389,16 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
216
389
|
.block-editor-frame {
|
|
217
390
|
position: relative;
|
|
218
391
|
}
|
|
219
|
-
|
|
220
|
-
|
|
392
|
+
|
|
393
|
+
.block-editor-frame__overlay {
|
|
394
|
+
position: fixed;
|
|
221
395
|
z-index: 2147483645;
|
|
396
|
+
box-sizing: border-box;
|
|
222
397
|
border: 1px dashed transparent;
|
|
223
|
-
content: "";
|
|
224
|
-
inset: 0;
|
|
225
398
|
pointer-events: none;
|
|
226
399
|
transition: border-color 120ms ease;
|
|
227
400
|
}
|
|
228
|
-
.block-editor-
|
|
401
|
+
.block-editor-frame__overlay--active {
|
|
229
402
|
border-color: #ff0099;
|
|
230
403
|
}
|
|
231
404
|
|
|
@@ -389,24 +562,19 @@ function postBuilderEvent(event, payload = {}) {
|
|
|
389
562
|
transform: translateX(-50%);
|
|
390
563
|
}
|
|
391
564
|
|
|
392
|
-
.block-editor-
|
|
393
|
-
.block-editor-
|
|
394
|
-
.block-editor-
|
|
395
|
-
.block-editor-frame--builder-ready:focus-within .block-editor-frame__add,
|
|
396
|
-
.block-editor-frame--builder-ready:hover .block-editor-frame__add-ai,
|
|
397
|
-
.block-editor-frame--builder-ready:focus-within .block-editor-frame__add-ai {
|
|
565
|
+
.block-editor-frame__overlay--active .block-editor-frame__toolbar,
|
|
566
|
+
.block-editor-frame__overlay--active .block-editor-frame__add,
|
|
567
|
+
.block-editor-frame__overlay--active .block-editor-frame__add-ai {
|
|
398
568
|
opacity: 1;
|
|
399
569
|
pointer-events: auto;
|
|
400
570
|
}
|
|
401
571
|
|
|
402
|
-
.block-editor-
|
|
403
|
-
.block-editor-frame--builder-ready:focus-within .block-editor-frame__toolbar {
|
|
572
|
+
.block-editor-frame__overlay--active .block-editor-frame__toolbar {
|
|
404
573
|
transform: translateY(0);
|
|
405
574
|
}
|
|
406
575
|
|
|
407
576
|
@media (max-width: 499px) {
|
|
408
|
-
.block-editor-
|
|
409
|
-
.block-editor-frame--builder-ready:focus-within::after {
|
|
577
|
+
.block-editor-frame__overlay--active {
|
|
410
578
|
border-color: transparent;
|
|
411
579
|
}
|
|
412
580
|
.block-editor-frame__toolbar,
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const blockEditorActions: readonly ["version", "move", "copy", "settings", "assistant", "visibility", "delete", "add", "add-ai"];
|
|
2
|
+
export type BlockEditorAction = (typeof blockEditorActions)[number];
|
|
3
|
+
export declare function parseBlockEditorActions(value: string | undefined): ReadonlySet<BlockEditorAction>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const blockEditorActions = [
|
|
2
|
+
"version",
|
|
3
|
+
"move",
|
|
4
|
+
"copy",
|
|
5
|
+
"settings",
|
|
6
|
+
"assistant",
|
|
7
|
+
"visibility",
|
|
8
|
+
"delete",
|
|
9
|
+
"add",
|
|
10
|
+
"add-ai"
|
|
11
|
+
];
|
|
12
|
+
const knownActions = new Set(blockEditorActions);
|
|
13
|
+
export function parseBlockEditorActions(value) {
|
|
14
|
+
if (value === void 0) return new Set(blockEditorActions);
|
|
15
|
+
return new Set(
|
|
16
|
+
value.split(/\s+/).filter((action) => knownActions.has(action))
|
|
17
|
+
);
|
|
18
|
+
}
|