@blokkli/editor 1.0.0 → 1.0.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/dist/module.json +1 -1
- package/dist/module.mjs +35 -3
- package/dist/runtime/adapter/drupal/graphqlMiddleware.js +9 -1
- package/dist/runtime/adapter/index.d.ts +4 -0
- package/dist/runtime/components/Blocks/FromLibrary/index.vue +2 -3
- package/dist/runtime/components/Edit/Dialog/index.vue +14 -1
- package/dist/runtime/components/Edit/DragInteractions/index.vue +1 -4
- package/dist/runtime/components/Edit/EditProvider.vue +1 -0
- package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +33 -27
- package/dist/runtime/components/Edit/Features/Edit/index.vue +60 -14
- package/dist/runtime/components/Edit/Features/Exit/index.vue +2 -1
- package/dist/runtime/components/Edit/Features/Library/EditReusable/index.vue +206 -0
- package/dist/runtime/components/Edit/Features/Library/LibraryDialog/index.vue +7 -8
- package/dist/runtime/components/Edit/Features/Library/index.vue +25 -2
- package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +11 -10
- package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue +1 -1
- package/dist/runtime/components/Edit/Features/Publish/index.vue +4 -1
- package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Content/index.vue +1 -1
- package/dist/runtime/components/Edit/Features/Translations/index.vue +26 -1
- package/dist/runtime/css/output.css +1 -1
- package/dist/runtime/helpers/broadcastProvider.d.ts +10 -2
- package/dist/runtime/helpers/composables/onBroadcastEvent.d.ts +2 -0
- package/dist/runtime/helpers/composables/onBroadcastEvent.js +10 -0
- package/dist/runtime/helpers/featuresProvider.d.ts +2 -2
- package/dist/runtime/helpers/index.js +2 -2
- package/dist/runtime/types/index.d.ts +12 -2
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { createUnplugin } from 'unplugin';
|
|
|
6
6
|
import MagicString from 'magic-string';
|
|
7
7
|
import { walk } from 'estree-walker-ts';
|
|
8
8
|
|
|
9
|
-
const version = "1.0.
|
|
9
|
+
const version = "1.0.2";
|
|
10
10
|
|
|
11
11
|
function sortObjectKeys(obj) {
|
|
12
12
|
const sortedKeys = Object.keys(obj).sort();
|
|
@@ -1155,6 +1155,14 @@ const libraryError$2 = {
|
|
|
1155
1155
|
source: "Failed to add block to library.",
|
|
1156
1156
|
translation: "Das Element konnte nicht wiederverwendbar gemacht werden."
|
|
1157
1157
|
};
|
|
1158
|
+
const libraryItemEditOverlayBack$2 = {
|
|
1159
|
+
source: "Back to page",
|
|
1160
|
+
translation: "Zurück zur Seite"
|
|
1161
|
+
};
|
|
1162
|
+
const libraryItemEditOverlayTitle$2 = {
|
|
1163
|
+
source: "Edit reusable block",
|
|
1164
|
+
translation: "Wiederverwendbaren Block bearbeiten"
|
|
1165
|
+
};
|
|
1158
1166
|
const libraryPlaceBundleSelectLabel$2 = {
|
|
1159
1167
|
source: "Bundle",
|
|
1160
1168
|
translation: "Typ"
|
|
@@ -1692,6 +1700,8 @@ const de = {
|
|
|
1692
1700
|
libraryDialogTitle: libraryDialogTitle$2,
|
|
1693
1701
|
libraryDialogTitleInputPlaceholder: libraryDialogTitleInputPlaceholder$2,
|
|
1694
1702
|
libraryError: libraryError$2,
|
|
1703
|
+
libraryItemEditOverlayBack: libraryItemEditOverlayBack$2,
|
|
1704
|
+
libraryItemEditOverlayTitle: libraryItemEditOverlayTitle$2,
|
|
1695
1705
|
libraryPlaceBundleSelectLabel: libraryPlaceBundleSelectLabel$2,
|
|
1696
1706
|
libraryPlaceDialogLead: libraryPlaceDialogLead$2,
|
|
1697
1707
|
libraryPlaceDialogSubmit: libraryPlaceDialogSubmit$2,
|
|
@@ -2298,6 +2308,14 @@ const libraryError$1 = {
|
|
|
2298
2308
|
source: "Failed to add block to library.",
|
|
2299
2309
|
translation: "L'élément n’a pas pu être rendu réutilisable."
|
|
2300
2310
|
};
|
|
2311
|
+
const libraryItemEditOverlayBack$1 = {
|
|
2312
|
+
source: "Back to page",
|
|
2313
|
+
translation: ""
|
|
2314
|
+
};
|
|
2315
|
+
const libraryItemEditOverlayTitle$1 = {
|
|
2316
|
+
source: "Edit reusable block",
|
|
2317
|
+
translation: ""
|
|
2318
|
+
};
|
|
2301
2319
|
const libraryPlaceBundleSelectLabel$1 = {
|
|
2302
2320
|
source: "Bundle",
|
|
2303
2321
|
translation: ""
|
|
@@ -2835,6 +2853,8 @@ const fr = {
|
|
|
2835
2853
|
libraryDialogTitle: libraryDialogTitle$1,
|
|
2836
2854
|
libraryDialogTitleInputPlaceholder: libraryDialogTitleInputPlaceholder$1,
|
|
2837
2855
|
libraryError: libraryError$1,
|
|
2856
|
+
libraryItemEditOverlayBack: libraryItemEditOverlayBack$1,
|
|
2857
|
+
libraryItemEditOverlayTitle: libraryItemEditOverlayTitle$1,
|
|
2838
2858
|
libraryPlaceBundleSelectLabel: libraryPlaceBundleSelectLabel$1,
|
|
2839
2859
|
libraryPlaceDialogLead: libraryPlaceDialogLead$1,
|
|
2840
2860
|
libraryPlaceDialogSubmit: libraryPlaceDialogSubmit$1,
|
|
@@ -3441,6 +3461,14 @@ const libraryError = {
|
|
|
3441
3461
|
source: "Failed to add block to library.",
|
|
3442
3462
|
translation: "L'elemento non può essere reso riutilizzabile."
|
|
3443
3463
|
};
|
|
3464
|
+
const libraryItemEditOverlayBack = {
|
|
3465
|
+
source: "Back to page",
|
|
3466
|
+
translation: ""
|
|
3467
|
+
};
|
|
3468
|
+
const libraryItemEditOverlayTitle = {
|
|
3469
|
+
source: "Edit reusable block",
|
|
3470
|
+
translation: ""
|
|
3471
|
+
};
|
|
3444
3472
|
const libraryPlaceBundleSelectLabel = {
|
|
3445
3473
|
source: "Bundle",
|
|
3446
3474
|
translation: ""
|
|
@@ -3978,6 +4006,8 @@ const it = {
|
|
|
3978
4006
|
libraryDialogTitle: libraryDialogTitle,
|
|
3979
4007
|
libraryDialogTitleInputPlaceholder: libraryDialogTitleInputPlaceholder,
|
|
3980
4008
|
libraryError: libraryError,
|
|
4009
|
+
libraryItemEditOverlayBack: libraryItemEditOverlayBack,
|
|
4010
|
+
libraryItemEditOverlayTitle: libraryItemEditOverlayTitle,
|
|
3981
4011
|
libraryPlaceBundleSelectLabel: libraryPlaceBundleSelectLabel,
|
|
3982
4012
|
libraryPlaceDialogLead: libraryPlaceDialogLead,
|
|
3983
4013
|
libraryPlaceDialogSubmit: libraryPlaceDialogSubmit,
|
|
@@ -4972,12 +5002,14 @@ const module = defineNuxtModule({
|
|
|
4972
5002
|
followSymbolicLinks: false
|
|
4973
5003
|
}) : [];
|
|
4974
5004
|
await featureExtractor.addFiles([...builtinFeatures, ...customFeatures]);
|
|
4975
|
-
const
|
|
5005
|
+
const extractedFeatures = featureExtractor.getFeatures();
|
|
5006
|
+
const features = extractedFeatures.filter((v) => {
|
|
4976
5007
|
return v.id !== "theme" || moduleOptions.enableThemeEditor;
|
|
4977
5008
|
});
|
|
4978
5009
|
const featuresContext = {
|
|
4979
5010
|
features
|
|
4980
5011
|
};
|
|
5012
|
+
const allFeatureIds = extractedFeatures.map((v) => v.id);
|
|
4981
5013
|
if (moduleOptions.alterFeatures) {
|
|
4982
5014
|
featuresContext.features = await Promise.resolve(
|
|
4983
5015
|
moduleOptions.alterFeatures(featuresContext)
|
|
@@ -5023,7 +5055,7 @@ export const availableFeaturesAtBuild = ${JSON.stringify(
|
|
|
5023
5055
|
availableFeaturesAtBuild
|
|
5024
5056
|
)} as const
|
|
5025
5057
|
|
|
5026
|
-
export type ValidFeatureKey =
|
|
5058
|
+
export type ValidFeatureKey = ${allFeatureIds.map((v) => '"' + v + '"').join(" | ")}
|
|
5027
5059
|
|
|
5028
5060
|
type FeatureComponent = {
|
|
5029
5061
|
id: string
|
|
@@ -339,6 +339,13 @@ export default defineBlokkliEditAdapter(
|
|
|
339
339
|
const url = typeof parts === "string" ? parts : "/" + parts.join("/");
|
|
340
340
|
return { url: prefix + url + `?paragraphsBlokkli=true` };
|
|
341
341
|
};
|
|
342
|
+
const getLibraryItemEditUrl = (uuid) => {
|
|
343
|
+
const url = buildFormUrl(
|
|
344
|
+
["blokkli", "library-item", uuid],
|
|
345
|
+
ctx.value.language
|
|
346
|
+
).url;
|
|
347
|
+
return `${url}&blokkliEditing=${uuid}&language=${ctx.value.language}`;
|
|
348
|
+
};
|
|
342
349
|
const formFrameBuilder = (e) => {
|
|
343
350
|
const entityType = ctx.value.entityType.toLowerCase();
|
|
344
351
|
if (e.id === "block:add") {
|
|
@@ -637,7 +644,8 @@ export default defineBlokkliEditAdapter(
|
|
|
637
644
|
addContentSearchItem,
|
|
638
645
|
clipboardMapBundle,
|
|
639
646
|
addBlockFromClipboardItem,
|
|
640
|
-
changeLanguage
|
|
647
|
+
changeLanguage,
|
|
648
|
+
getLibraryItemEditUrl
|
|
641
649
|
};
|
|
642
650
|
}
|
|
643
651
|
);
|
|
@@ -197,6 +197,10 @@ export interface BlokkliAdapter<T> {
|
|
|
197
197
|
* Add a reusable item.
|
|
198
198
|
*/
|
|
199
199
|
addLibraryItem?: (e: AddReusableItemEvent) => Promise<MutationResponseLike<T>>;
|
|
200
|
+
/**
|
|
201
|
+
* Build the URL to edit a library item.
|
|
202
|
+
*/
|
|
203
|
+
getLibraryItemEditUrl?: (uuid: string) => string;
|
|
200
204
|
/**
|
|
201
205
|
* Delete multiple items.
|
|
202
206
|
*/
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
:data-reusable-bundle="item.bundle"
|
|
8
8
|
:data-reusable-uuid="item.uuid"
|
|
9
9
|
:data-bk-library-label="libraryItem?.label"
|
|
10
|
+
:data-bk-library-item-uuid="libraryItem?.uuid"
|
|
10
11
|
data-blokkli-is-reusable="true"
|
|
11
12
|
:parent-type="parentType"
|
|
12
13
|
/>
|
|
@@ -23,6 +24,7 @@ import type { FieldListItem } from '#blokkli/types'
|
|
|
23
24
|
interface LibraryItem {
|
|
24
25
|
block?: FieldListItem
|
|
25
26
|
label?: string
|
|
27
|
+
uuid?: string
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
const props = defineProps<{
|
|
@@ -31,9 +33,6 @@ const props = defineProps<{
|
|
|
31
33
|
|
|
32
34
|
const { index, options, parentType } = defineBlokkli({
|
|
33
35
|
bundle: 'from_library',
|
|
34
|
-
editor: {
|
|
35
|
-
disableEdit: true,
|
|
36
|
-
},
|
|
37
36
|
})
|
|
38
37
|
|
|
39
38
|
// Reusable items inherit the options from this wrapper paragraph.
|
|
@@ -19,7 +19,12 @@
|
|
|
19
19
|
</button>
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
|
-
<div
|
|
22
|
+
<div
|
|
23
|
+
class="bk-dialog-content"
|
|
24
|
+
:class="{
|
|
25
|
+
'bk-is-fullscreen': fullScreen,
|
|
26
|
+
}"
|
|
27
|
+
>
|
|
23
28
|
<div class="bk-dialog-content-inner">
|
|
24
29
|
<div v-if="lead" class="bk bk-dialog-lead">
|
|
25
30
|
{{ lead }}
|
|
@@ -67,6 +72,7 @@ const props = withDefaults(
|
|
|
67
72
|
isLoading?: boolean
|
|
68
73
|
hideButtons?: boolean
|
|
69
74
|
icon?: BlokkliIcon
|
|
75
|
+
fullScreen?: boolean
|
|
70
76
|
}>(),
|
|
71
77
|
{
|
|
72
78
|
width: 600,
|
|
@@ -82,6 +88,13 @@ const style = computed(() => {
|
|
|
82
88
|
return {}
|
|
83
89
|
}
|
|
84
90
|
|
|
91
|
+
if (props.fullScreen) {
|
|
92
|
+
return {
|
|
93
|
+
maxWidth: '100vw',
|
|
94
|
+
height: '100vh',
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
85
98
|
if (typeof props.width === 'number') {
|
|
86
99
|
return {
|
|
87
100
|
maxWidth: props.width + 'px',
|
|
@@ -241,10 +241,7 @@ function onPointerUp(e: PointerEvent) {
|
|
|
241
241
|
if (!block) {
|
|
242
242
|
return
|
|
243
243
|
}
|
|
244
|
-
eventBus.emit('item:
|
|
245
|
-
uuid: lastInteractedElement.uuid,
|
|
246
|
-
bundle: block.itemBundle,
|
|
247
|
-
})
|
|
244
|
+
eventBus.emit('item:doubleClick', block)
|
|
248
245
|
}
|
|
249
246
|
}
|
|
250
247
|
}
|
|
@@ -60,7 +60,11 @@ import {
|
|
|
60
60
|
nextTick,
|
|
61
61
|
} from '#imports'
|
|
62
62
|
import { AddListItem } from '#blokkli/components'
|
|
63
|
-
import type {
|
|
63
|
+
import type {
|
|
64
|
+
Command,
|
|
65
|
+
DraggableExistingBlock,
|
|
66
|
+
FieldConfig,
|
|
67
|
+
} from '#blokkli/types'
|
|
64
68
|
import { getDefaultDefinition } from '#blokkli/definitions'
|
|
65
69
|
import defineCommands from '#blokkli/helpers/composables/defineCommands'
|
|
66
70
|
import onBlokkliEvent from '#blokkli/helpers/composables/onBlokkliEvent'
|
|
@@ -225,7 +229,7 @@ const getBundlesForAppendCommands = () => {
|
|
|
225
229
|
}
|
|
226
230
|
|
|
227
231
|
const block = selection.blocks.value[0]
|
|
228
|
-
const field = types.getFieldConfig(
|
|
232
|
+
const field: FieldConfig | undefined = types.getFieldConfig(
|
|
229
233
|
block.hostType,
|
|
230
234
|
block.hostBundle,
|
|
231
235
|
block.hostFieldName,
|
|
@@ -256,7 +260,7 @@ const getAppendEndCommands = (): Command[] => {
|
|
|
256
260
|
context.value.entityType,
|
|
257
261
|
context.value.entityBundle,
|
|
258
262
|
)
|
|
259
|
-
.flatMap((field) => {
|
|
263
|
+
.flatMap((field: FieldConfig) => {
|
|
260
264
|
if (field.cardinality !== -1) {
|
|
261
265
|
const key = getFieldKey(context.value.entityUuid, field.name)
|
|
262
266
|
const count = state.getFieldBlockCount(key)
|
|
@@ -267,7 +271,7 @@ const getAppendEndCommands = (): Command[] => {
|
|
|
267
271
|
}
|
|
268
272
|
return field.allowedBundles
|
|
269
273
|
.filter((v) => !reservedBundles.includes(v))
|
|
270
|
-
.map((bundle) => {
|
|
274
|
+
.map((bundle: string) => {
|
|
271
275
|
const definition = types.getBlockBundleDefinition(bundle)
|
|
272
276
|
return {
|
|
273
277
|
id: 'block_add_list:append_end:' + bundle + field.name,
|
|
@@ -350,29 +354,31 @@ const getInsertCommands = (
|
|
|
350
354
|
}
|
|
351
355
|
})
|
|
352
356
|
|
|
353
|
-
const commands: Command[] = nestedFields.flatMap(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
357
|
+
const commands: Command[] = nestedFields.flatMap(
|
|
358
|
+
(field: FieldConfig & { uuid: string }) => {
|
|
359
|
+
return field.allowedBundles.map((bundle: string) => {
|
|
360
|
+
const label = types.getBlockBundleDefinition(bundle)?.label || bundle
|
|
361
|
+
return {
|
|
362
|
+
id: 'block_add_list:insert:' + field.name + ':' + bundle,
|
|
363
|
+
label: $t(
|
|
364
|
+
'addBlockCommand.insertInField',
|
|
365
|
+
'Insert "@block" into "@field"',
|
|
366
|
+
)
|
|
367
|
+
.replace('@block', label)
|
|
368
|
+
.replace('@field', field.label),
|
|
369
|
+
group: 'add',
|
|
370
|
+
bundle,
|
|
371
|
+
callback: () =>
|
|
372
|
+
commandCallbackInsert(
|
|
373
|
+
bundle,
|
|
374
|
+
field.name,
|
|
375
|
+
field.entityType,
|
|
376
|
+
field.uuid,
|
|
377
|
+
),
|
|
378
|
+
}
|
|
379
|
+
})
|
|
380
|
+
},
|
|
381
|
+
)
|
|
376
382
|
|
|
377
383
|
if (block.hostType === runtimeConfig.itemEntityType) {
|
|
378
384
|
const parentBlock = dom.findBlock(block.hostUuid)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<PluginItemAction
|
|
3
3
|
id="edit"
|
|
4
4
|
:title="$t('edit', 'Edit')"
|
|
5
|
-
:disabled="
|
|
5
|
+
:disabled="!canEdit"
|
|
6
6
|
meta
|
|
7
7
|
key-code="E"
|
|
8
8
|
icon="edit"
|
|
@@ -16,6 +16,7 @@ import { computed, useBlokkli, defineBlokkliFeature } from '#imports'
|
|
|
16
16
|
import type { DraggableExistingBlock } from '#blokkli/types'
|
|
17
17
|
import { PluginItemAction } from '#blokkli/plugins'
|
|
18
18
|
import { getDefinition } from '#blokkli/definitions'
|
|
19
|
+
import onBlokkliEvent from '#blokkli/helpers/composables/onBlokkliEvent'
|
|
19
20
|
|
|
20
21
|
defineBlokkliFeature({
|
|
21
22
|
id: 'edit',
|
|
@@ -25,23 +26,45 @@ defineBlokkliFeature({
|
|
|
25
26
|
requiredAdapterMethods: ['formFrameBuilder'],
|
|
26
27
|
})
|
|
27
28
|
|
|
28
|
-
const { eventBus, selection, state, $t } = useBlokkli()
|
|
29
|
+
const { eventBus, selection, state, $t, adapter } = useBlokkli()
|
|
29
30
|
|
|
30
|
-
const
|
|
31
|
-
if (state.editMode.value !== 'editing') {
|
|
32
|
-
return true
|
|
33
|
-
}
|
|
31
|
+
const block = computed(() => {
|
|
34
32
|
if (selection.blocks.value.length !== 1) {
|
|
35
|
-
return
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return selection.blocks.value[0]
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const canEdit = computed(() => {
|
|
40
|
+
// Editing is only possible when a single block is selected.
|
|
41
|
+
if (!block.value) {
|
|
42
|
+
return false
|
|
36
43
|
}
|
|
37
44
|
|
|
38
|
-
const block = selection.blocks.value[0]
|
|
39
45
|
const definition = getDefinition(
|
|
40
|
-
block.itemBundle,
|
|
41
|
-
block.hostFieldListType,
|
|
42
|
-
block.parentBlockBundle,
|
|
46
|
+
block.value.itemBundle,
|
|
47
|
+
block.value.hostFieldListType,
|
|
48
|
+
block.value.parentBlockBundle,
|
|
43
49
|
)
|
|
44
|
-
|
|
50
|
+
|
|
51
|
+
// Editing is explicitly disabled via the definition.
|
|
52
|
+
if (definition?.editor?.disableEdit) {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// For reusable blocks, editing is only possible if the adapter implements
|
|
57
|
+
// the getLibraryItemEditUrl method.
|
|
58
|
+
if (block.value.libraryItemUuid) {
|
|
59
|
+
return (
|
|
60
|
+
!!adapter.getLibraryItemEditUrl &&
|
|
61
|
+
(state.editMode.value === 'editing' ||
|
|
62
|
+
state.editMode.value === 'translating') &&
|
|
63
|
+
!block.value.isNew
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return state.editMode.value === 'editing'
|
|
45
68
|
})
|
|
46
69
|
|
|
47
70
|
function onClick(items: DraggableExistingBlock[]) {
|
|
@@ -49,11 +72,34 @@ function onClick(items: DraggableExistingBlock[]) {
|
|
|
49
72
|
return
|
|
50
73
|
}
|
|
51
74
|
|
|
75
|
+
if (!canEdit.value) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const item = items[0]
|
|
80
|
+
|
|
81
|
+
// Because editing library items inside the current context is not (yet)
|
|
82
|
+
// supported, editing has to happen in a separate window where the host
|
|
83
|
+
// context is the library item entity.
|
|
84
|
+
if (item.libraryItemUuid && adapter.getLibraryItemEditUrl) {
|
|
85
|
+
const url = adapter.getLibraryItemEditUrl(item.libraryItemUuid)
|
|
86
|
+
eventBus.emit('library:edit-item', {
|
|
87
|
+
url,
|
|
88
|
+
label: item.editTitle,
|
|
89
|
+
uuid: item.libraryItemUuid,
|
|
90
|
+
})
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
52
94
|
eventBus.emit('item:edit', {
|
|
53
|
-
uuid:
|
|
54
|
-
bundle:
|
|
95
|
+
uuid: item.uuid,
|
|
96
|
+
bundle: item.itemBundle,
|
|
55
97
|
})
|
|
56
98
|
}
|
|
99
|
+
|
|
100
|
+
onBlokkliEvent('item:doubleClick', function (block) {
|
|
101
|
+
onClick([block])
|
|
102
|
+
})
|
|
57
103
|
</script>
|
|
58
104
|
|
|
59
105
|
<script lang="ts">
|
|
@@ -20,12 +20,13 @@ defineBlokkliFeature({
|
|
|
20
20
|
description: 'Provides a menu button to exit the editor without saving.',
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
const { $t } = useBlokkli()
|
|
23
|
+
const { $t, broadcast, context } = useBlokkli()
|
|
24
24
|
|
|
25
25
|
const route = useRoute()
|
|
26
26
|
|
|
27
27
|
function onClick() {
|
|
28
28
|
nextTick(() => {
|
|
29
|
+
broadcast.emit('closeEditor', { uuid: context.value.entityUuid })
|
|
29
30
|
window.location.href = route.path
|
|
30
31
|
})
|
|
31
32
|
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Teleport to="body">
|
|
3
|
+
<Loading v-if="isLoading" />
|
|
4
|
+
<Transition name="bk-library-edit-header">
|
|
5
|
+
<header v-show="isLoaded" class="bk bk-library-edit-overlay-header">
|
|
6
|
+
<h2>
|
|
7
|
+
<span>{{
|
|
8
|
+
$t('libraryItemEditOverlayTitle', 'Edit reusable block')
|
|
9
|
+
}}</span>
|
|
10
|
+
<span v-if="label"> {{ label }}</span>
|
|
11
|
+
</h2>
|
|
12
|
+
<button @click.prevent="closeOverlay">
|
|
13
|
+
<Icon name="arrow-left" />
|
|
14
|
+
<span>{{ $t('libraryItemEditOverlayBack', 'Back to page') }}</span>
|
|
15
|
+
</button>
|
|
16
|
+
</header>
|
|
17
|
+
</Transition>
|
|
18
|
+
<Transition
|
|
19
|
+
:css="false"
|
|
20
|
+
@enter="onEnter"
|
|
21
|
+
@after-enter="onAfter"
|
|
22
|
+
@enter-cancelled="onAfter"
|
|
23
|
+
@leave="onLeave"
|
|
24
|
+
@after-leave="onAfterLeave"
|
|
25
|
+
@leave-cancelled="onAfterLeave"
|
|
26
|
+
>
|
|
27
|
+
<div v-show="isLoaded" class="bk bk-library-edit-overlay">
|
|
28
|
+
<iframe
|
|
29
|
+
ref="iframe"
|
|
30
|
+
:src="url"
|
|
31
|
+
style="width: 100%; height: 100%"
|
|
32
|
+
@load="onLoad"
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
</Transition>
|
|
36
|
+
</Teleport>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script lang="ts" setup>
|
|
40
|
+
import onBroadcastEvent from '#blokkli/helpers/composables/onBroadcastEvent'
|
|
41
|
+
import { ref, useBlokkli } from '#imports'
|
|
42
|
+
import { Icon } from '#blokkli/components'
|
|
43
|
+
import Loading from './../../../Loading/index.vue'
|
|
44
|
+
|
|
45
|
+
const props = defineProps<{
|
|
46
|
+
url: string
|
|
47
|
+
uuid: string
|
|
48
|
+
label?: string
|
|
49
|
+
}>()
|
|
50
|
+
|
|
51
|
+
const DURATION = 530
|
|
52
|
+
const emit = defineEmits(['submit', 'close'])
|
|
53
|
+
|
|
54
|
+
function getOriginatingElement(): HTMLElement | null {
|
|
55
|
+
const el = document.querySelector(
|
|
56
|
+
`[data-bk-library-item-uuid="${props.uuid}"]`,
|
|
57
|
+
)
|
|
58
|
+
if (el instanceof HTMLElement) {
|
|
59
|
+
return el
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// called one frame after the element is inserted.
|
|
66
|
+
// use this to start the entering animation.
|
|
67
|
+
function onEnter(el: Element, done: () => void) {
|
|
68
|
+
if (el instanceof HTMLElement) {
|
|
69
|
+
const originating = getOriginatingElement()
|
|
70
|
+
if (!originating) {
|
|
71
|
+
done()
|
|
72
|
+
isLoading.value = false
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const originatingRect = originating.getBoundingClientRect()
|
|
77
|
+
const overlayRect = el.getBoundingClientRect()
|
|
78
|
+
|
|
79
|
+
const offsetX =
|
|
80
|
+
originatingRect.x - overlayRect.x + originatingRect.width / 2
|
|
81
|
+
const offsetY =
|
|
82
|
+
originatingRect.y - overlayRect.y + originatingRect.height / 2
|
|
83
|
+
|
|
84
|
+
el.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(0, 0)`
|
|
85
|
+
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
el.style.transitionDuration = DURATION + 'ms'
|
|
88
|
+
el.style.transitionTimingFunction = 'cubic-bezier(0.56, 0.04, 0.25, 1)'
|
|
89
|
+
el.style.transitionProperty = 'transform'
|
|
90
|
+
el.style.transformOrigin = '0px 0px'
|
|
91
|
+
el.style.transform = 'translate(0px, 0px)'
|
|
92
|
+
}, 10)
|
|
93
|
+
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
done()
|
|
96
|
+
isLoading.value = false
|
|
97
|
+
}, DURATION)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// called when the enter transition has finished.
|
|
102
|
+
function onAfter(el: Element) {
|
|
103
|
+
if (el instanceof HTMLElement) {
|
|
104
|
+
el.style.transform = ''
|
|
105
|
+
el.style.transitionDuration = ''
|
|
106
|
+
el.style.opacity = ''
|
|
107
|
+
el.style.transitionProperty = ''
|
|
108
|
+
el.style.transitionTimingFunction = ''
|
|
109
|
+
el.style.transformOrigin = ''
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// called when the leave transition starts.
|
|
114
|
+
// use this to start the leaving animation.
|
|
115
|
+
function onLeave(el: Element, done: () => void) {
|
|
116
|
+
if (el instanceof HTMLElement) {
|
|
117
|
+
const originating = getOriginatingElement()
|
|
118
|
+
if (!originating) {
|
|
119
|
+
done()
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const originatingRect = originating.getBoundingClientRect()
|
|
124
|
+
const overlayRect = el.getBoundingClientRect()
|
|
125
|
+
|
|
126
|
+
const offsetX =
|
|
127
|
+
originatingRect.x - overlayRect.x + originatingRect.width / 2
|
|
128
|
+
const offsetY =
|
|
129
|
+
originatingRect.y - overlayRect.y + originatingRect.height / 2
|
|
130
|
+
|
|
131
|
+
el.style.transform = 'translate(0px, 0px)'
|
|
132
|
+
|
|
133
|
+
setTimeout(() => {
|
|
134
|
+
el.style.transitionDuration = DURATION + 'ms'
|
|
135
|
+
el.style.transitionTimingFunction = 'cubic-bezier(0.56, 0.04, 0.25, 1)'
|
|
136
|
+
el.style.transitionProperty = 'transform'
|
|
137
|
+
el.style.transformOrigin = '0px 0px'
|
|
138
|
+
el.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(0, 0)`
|
|
139
|
+
}, 10)
|
|
140
|
+
|
|
141
|
+
setTimeout(() => {
|
|
142
|
+
done()
|
|
143
|
+
}, DURATION)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function onAfterLeave(el: Element) {
|
|
148
|
+
onAfter(el)
|
|
149
|
+
if (hasPublished.value) {
|
|
150
|
+
emit('submit')
|
|
151
|
+
} else {
|
|
152
|
+
emit('close')
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const { $t } = useBlokkli()
|
|
157
|
+
|
|
158
|
+
const iframe = ref<HTMLIFrameElement | null>(null)
|
|
159
|
+
const isLoaded = ref(false)
|
|
160
|
+
const isLoading = ref(true)
|
|
161
|
+
const hasPublished = ref(false)
|
|
162
|
+
let timeout: any = null
|
|
163
|
+
|
|
164
|
+
function onLibraryItemPublished({ uuid }: { uuid: string }) {
|
|
165
|
+
if (props.uuid === uuid) {
|
|
166
|
+
hasPublished.value = true
|
|
167
|
+
isLoaded.value = false
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function onLoad() {
|
|
172
|
+
clearTimeout(timeout)
|
|
173
|
+
|
|
174
|
+
timeout = window.setTimeout(() => {
|
|
175
|
+
isLoaded.value = true
|
|
176
|
+
}, 3000)
|
|
177
|
+
if (!iframe.value) {
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
iframe.value.focus()
|
|
182
|
+
|
|
183
|
+
iframe.value.contentWindow?.focus()
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function closeOverlay() {
|
|
187
|
+
hasPublished.value = false
|
|
188
|
+
isLoaded.value = false
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function onLibraryItemClose({ uuid }: { uuid: string }) {
|
|
192
|
+
if (props.uuid === uuid) {
|
|
193
|
+
closeOverlay()
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function onEditorLoaded({ uuid }: { uuid: string }) {
|
|
198
|
+
if (props.uuid === uuid) {
|
|
199
|
+
isLoaded.value = true
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
onBroadcastEvent('published', onLibraryItemPublished)
|
|
204
|
+
onBroadcastEvent('closeEditor', onLibraryItemClose)
|
|
205
|
+
onBroadcastEvent('editorLoaded', onEditorLoaded)
|
|
206
|
+
</script>
|
|
@@ -93,7 +93,7 @@ import type {
|
|
|
93
93
|
} from '#blokkli/adapter'
|
|
94
94
|
import { FormOverlay, Icon } from '#blokkli/components'
|
|
95
95
|
import Loading from './../../../Loading/index.vue'
|
|
96
|
-
import type { BlokkliFieldElement } from '#blokkli/types'
|
|
96
|
+
import type { BlokkliFieldElement, FieldConfig } from '#blokkli/types'
|
|
97
97
|
import { ref, useBlokkli, useAsyncData, computed, watch } from '#imports'
|
|
98
98
|
import LibraryListItem from './Item/index.vue'
|
|
99
99
|
|
|
@@ -115,13 +115,12 @@ const selectedItem = ref('')
|
|
|
115
115
|
const page = ref(0)
|
|
116
116
|
|
|
117
117
|
const allowedBundles = computed<string[]>(() => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
).filter((v) => {
|
|
118
|
+
const fieldConfig: FieldConfig | undefined = types.getFieldConfig(
|
|
119
|
+
props.field.hostEntityType,
|
|
120
|
+
props.field.hostEntityBundle,
|
|
121
|
+
props.field.name,
|
|
122
|
+
)
|
|
123
|
+
return (fieldConfig?.allowedBundles || []).filter((v) => {
|
|
125
124
|
return types.getBlockBundleDefinition(v)?.allowReusable
|
|
126
125
|
})
|
|
127
126
|
})
|