@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.
Files changed (27) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +35 -3
  3. package/dist/runtime/adapter/drupal/graphqlMiddleware.js +9 -1
  4. package/dist/runtime/adapter/index.d.ts +4 -0
  5. package/dist/runtime/components/Blocks/FromLibrary/index.vue +2 -3
  6. package/dist/runtime/components/Edit/Dialog/index.vue +14 -1
  7. package/dist/runtime/components/Edit/DragInteractions/index.vue +1 -4
  8. package/dist/runtime/components/Edit/EditProvider.vue +1 -0
  9. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +33 -27
  10. package/dist/runtime/components/Edit/Features/Edit/index.vue +60 -14
  11. package/dist/runtime/components/Edit/Features/Exit/index.vue +2 -1
  12. package/dist/runtime/components/Edit/Features/Library/EditReusable/index.vue +206 -0
  13. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/index.vue +7 -8
  14. package/dist/runtime/components/Edit/Features/Library/index.vue +25 -2
  15. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +11 -10
  16. package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue +1 -1
  17. package/dist/runtime/components/Edit/Features/Publish/index.vue +4 -1
  18. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Content/index.vue +1 -1
  19. package/dist/runtime/components/Edit/Features/Translations/index.vue +26 -1
  20. package/dist/runtime/css/output.css +1 -1
  21. package/dist/runtime/helpers/broadcastProvider.d.ts +10 -2
  22. package/dist/runtime/helpers/composables/onBroadcastEvent.d.ts +2 -0
  23. package/dist/runtime/helpers/composables/onBroadcastEvent.js +10 -0
  24. package/dist/runtime/helpers/featuresProvider.d.ts +2 -2
  25. package/dist/runtime/helpers/index.js +2 -2
  26. package/dist/runtime/types/index.d.ts +12 -2
  27. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "blokkli",
3
3
  "configKey": "blokkli",
4
- "version": "1.0.0",
4
+ "version": "1.0.2",
5
5
  "compatibility": {
6
6
  "nuxt": "^3.12.0"
7
7
  },
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.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 features = featureExtractor.getFeatures().filter((v) => {
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 = typeof availableFeaturesAtBuild[number]
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 class="bk-dialog-content">
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:edit', {
245
- uuid: lastInteractedElement.uuid,
246
- bundle: block.itemBundle,
247
- })
244
+ eventBus.emit('item:doubleClick', block)
248
245
  }
249
246
  }
250
247
  }
@@ -166,6 +166,7 @@ onMounted(() => {
166
166
  setRootClasses()
167
167
  baseLogger.log('EditProvider mounted')
168
168
  dom.init()
169
+ broadcast.emit('editorLoaded', { uuid: props.entityUuid })
169
170
  })
170
171
 
171
172
  onBeforeUnmount(() => {
@@ -60,7 +60,11 @@ import {
60
60
  nextTick,
61
61
  } from '#imports'
62
62
  import { AddListItem } from '#blokkli/components'
63
- import type { Command, DraggableExistingBlock } from '#blokkli/types'
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((field) => {
354
- return field.allowedBundles.map((bundle) => {
355
- const label = types.getBlockBundleDefinition(bundle)?.label || bundle
356
- return {
357
- id: 'block_add_list:insert:' + field.name + ':' + bundle,
358
- label: $t(
359
- 'addBlockCommand.insertInField',
360
- 'Insert "@block" into "@field"',
361
- )
362
- .replace('@block', label)
363
- .replace('@field', field.label),
364
- group: 'add',
365
- bundle,
366
- callback: () =>
367
- commandCallbackInsert(
368
- bundle,
369
- field.name,
370
- field.entityType,
371
- field.uuid,
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="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 disabled = computed(() => {
31
- if (state.editMode.value !== 'editing') {
32
- return true
33
- }
31
+ const block = computed(() => {
34
32
  if (selection.blocks.value.length !== 1) {
35
- return true
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
- return definition?.editor?.disableEdit === true
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: items[0].uuid,
54
- bundle: items[0].itemBundle,
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">&nbsp;{{ 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
- return (
119
- types.getFieldConfig(
120
- props.field.hostEntityType,
121
- props.field.hostEntityBundle,
122
- props.field.name,
123
- )?.allowedBundles || []
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
  })