@blokkli/editor 1.0.4 → 1.1.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.
Files changed (78) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +345 -16
  3. package/dist/runtime/adapter/drupal/graphql/base.graphql +2 -1
  4. package/dist/runtime/adapter/drupal/graphqlMiddleware.js +4 -1
  5. package/dist/runtime/adapter/index.d.ts +12 -1
  6. package/dist/runtime/blokkliPlugins/Sidebar/Detached/index.vue +41 -39
  7. package/dist/runtime/blokkliPlugins/Sidebar/index.vue +10 -16
  8. package/dist/runtime/blokkliPlugins/ViewOption/index.vue +2 -0
  9. package/dist/runtime/components/BlokkliField.vue +75 -17
  10. package/dist/runtime/components/BlokkliItem.vue +34 -6
  11. package/dist/runtime/components/BlokkliProvider.vue +18 -1
  12. package/dist/runtime/components/Edit/BlockProxy/index.vue +102 -0
  13. package/dist/runtime/components/Edit/DragInteractions/index.vue +49 -25
  14. package/dist/runtime/components/Edit/DraggableList.vue +140 -30
  15. package/dist/runtime/components/Edit/EditProvider.vue +4 -0
  16. package/dist/runtime/components/Edit/Features/AddList/index.vue +3 -0
  17. package/dist/runtime/components/Edit/Features/Artboard/Overview/index.vue +111 -0
  18. package/dist/runtime/components/Edit/Features/Artboard/Scrollbar/index.vue +47 -0
  19. package/dist/runtime/components/Edit/Features/Artboard/index.vue +301 -9
  20. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +29 -4
  21. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +3 -4
  22. package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue +27 -0
  23. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +24 -3
  24. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/fragment.glsl +56 -24
  25. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +184 -29
  26. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/vertex.glsl +36 -16
  27. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +4 -0
  28. package/dist/runtime/components/Edit/Features/Duplicate/index.vue +1 -13
  29. package/dist/runtime/components/Edit/Features/EditableMask/index.vue +2 -2
  30. package/dist/runtime/components/Edit/Features/History/index.vue +1 -1
  31. package/dist/runtime/components/Edit/Features/Options/Form/Checkbox/index.vue +2 -2
  32. package/dist/runtime/components/Edit/Features/Options/Form/Checkboxes/index.vue +28 -25
  33. package/dist/runtime/components/Edit/Features/Options/Form/Color/index.vue +1 -1
  34. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue +67 -39
  35. package/dist/runtime/components/Edit/Features/Options/Form/Number/index.vue +6 -2
  36. package/dist/runtime/components/Edit/Features/Options/Form/Radios/index.vue +1 -1
  37. package/dist/runtime/components/Edit/Features/Options/Form/Range/index.vue +2 -2
  38. package/dist/runtime/components/Edit/Features/Options/Form/Text/index.vue +2 -1
  39. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +83 -33
  40. package/dist/runtime/components/Edit/Features/ProxyView/index.vue +38 -0
  41. package/dist/runtime/components/Edit/Features/Publish/index.vue +53 -6
  42. package/dist/runtime/components/Edit/Features/Search/Overlay/index.vue +3 -13
  43. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +1 -1
  44. package/dist/runtime/components/Edit/Features/Settings/Dialog/index.vue +2 -0
  45. package/dist/runtime/components/Edit/Features/Structure/List/Field/index.vue +3 -3
  46. package/dist/runtime/components/Edit/Features/Structure/index.vue +3 -3
  47. package/dist/runtime/components/Edit/ScrollBoundary/index.vue +24 -0
  48. package/dist/runtime/components/Edit/index.d.ts +2 -1
  49. package/dist/runtime/components/Edit/index.js +3 -1
  50. package/dist/runtime/composables/defineBlokkli.js +10 -5
  51. package/dist/runtime/constants/index.d.ts +1 -1
  52. package/dist/runtime/constants/index.js +6 -1
  53. package/dist/runtime/css/output.css +1 -1
  54. package/dist/runtime/helpers/animationProvider.js +10 -4
  55. package/dist/runtime/helpers/domProvider.d.ts +12 -4
  56. package/dist/runtime/helpers/domProvider.js +70 -26
  57. package/dist/runtime/helpers/featuresProvider.d.ts +1 -1
  58. package/dist/runtime/helpers/runtimeHelpers/index.d.ts +6 -0
  59. package/dist/runtime/helpers/runtimeHelpers/index.js +25 -0
  60. package/dist/runtime/helpers/selectionProvider.d.ts +2 -1
  61. package/dist/runtime/helpers/selectionProvider.js +7 -8
  62. package/dist/runtime/helpers/symbols.d.ts +7 -0
  63. package/dist/runtime/helpers/symbols.js +7 -0
  64. package/dist/runtime/helpers/typesProvider.d.ts +1 -1
  65. package/dist/runtime/helpers/uiProvider.d.ts +1 -0
  66. package/dist/runtime/helpers/uiProvider.js +16 -3
  67. package/dist/runtime/helpers/webgl/index.d.ts +6 -1
  68. package/dist/runtime/helpers/webgl/index.js +38 -5
  69. package/dist/runtime/icons/eye.svg +1 -0
  70. package/dist/runtime/types/generatedModuleTypes.d.ts +12 -4
  71. package/dist/runtime/types/index.d.ts +30 -1
  72. package/package.json +7 -5
  73. package/dist/runtime/components/Edit/Features/Artboard/Manager/Artboard.d.ts +0 -204
  74. package/dist/runtime/components/Edit/Features/Artboard/Manager/Artboard.js +0 -748
  75. package/dist/runtime/components/Edit/Features/Artboard/Manager/Scrollbar/index.vue +0 -176
  76. package/dist/runtime/components/Edit/Features/Artboard/Manager/index.vue +0 -317
  77. package/dist/runtime/helpers/Artboard/index.d.ts +0 -16
  78. package/dist/runtime/helpers/Artboard/index.js +0 -20
@@ -105,12 +105,13 @@ mutation pbPublish(
105
105
  $entityType: EntityType!
106
106
  $entityUuid: String!
107
107
  $langcode: String
108
+ $createNewState: Boolean
108
109
  ) {
109
110
  state: paragraphsEditMutationState(
110
111
  entityType: $entityType
111
112
  entityUuid: $entityUuid
112
113
  ) {
113
- action: publish {
114
+ action: publish(createNewState: $createNewState) {
114
115
  ...paragraphsBlokkliMutationResult
115
116
  }
116
117
  }
@@ -96,7 +96,10 @@ export default defineBlokkliEditAdapter(
96
96
  index,
97
97
  status
98
98
  }).then(mapMutation);
99
- const publish = () => useGraphqlMutation("pbPublish", ctx.value).then(mapMutation);
99
+ const publish = (options) => useGraphqlMutation("pbPublish", {
100
+ ...ctx.value,
101
+ createNewState: !options.closeAfterPublish
102
+ }).then(mapMutation);
100
103
  const importFromExisting = (e) => useGraphqlMutation("pbCopyFromExisting", {
101
104
  ...ctx.value,
102
105
  sourceUuid: e.sourceUuid,
@@ -121,6 +121,17 @@ export type BlokkliAdapterGetLibraryItemsResult = {
121
121
  total: number;
122
122
  perPage: number;
123
123
  };
124
+ export type BlokkliAdapterPublishOptions = {
125
+ /**
126
+ * Whether the editor will be closed after publishing.
127
+ *
128
+ * If false, the adapter should return an empty state again, so that the
129
+ * editor UI shows the correct state (no pending changes).
130
+ * If true, the adapter may return no state at all, since the editor will
131
+ * be closed anyway after publishing.
132
+ */
133
+ closeAfterPublish?: boolean;
134
+ };
124
135
  export interface BlokkliAdapter<T> {
125
136
  /**
126
137
  * Load the state for the given langcode.
@@ -231,7 +242,7 @@ export interface BlokkliAdapter<T> {
231
242
  /**
232
243
  * Publish all changes.
233
244
  */
234
- publish?: () => Promise<MutationResponseLike<T>>;
245
+ publish?: (options: BlokkliAdapterPublishOptions) => Promise<MutationResponseLike<T | undefined | null>>;
235
246
  /**
236
247
  * Set a specific history index.
237
248
  */
@@ -9,46 +9,48 @@
9
9
  @pointermove="onPointerMove"
10
10
  @focus.capture="onFocus"
11
11
  >
12
- <div class="bk">
13
- <div
14
- class="bk-sidebar-title"
15
- @mousedown.stop="onMouseDown($event, 'move')"
16
- >
17
- <slot name="icon">
18
- <Icon v-if="icon" :name="icon" />
19
- </slot>
20
- <span>{{ title }}</span>
21
- <button
22
- @click.prevent.stop.capture="isMinimized = !isMinimized"
23
- @mousedown.capture.stop
24
- >
25
- <Icon :name="isMinimized ? 'window-maximize' : 'window-minimize'" />
26
- </button>
27
- <button
28
- @click.prevent.stop.capture="$emit('close')"
29
- @mousedown.capture.stop
12
+ <ScrollBoundary>
13
+ <div class="bk">
14
+ <div
15
+ class="bk-sidebar-title"
16
+ @mousedown.stop="onMouseDown($event, 'move')"
30
17
  >
31
- <Icon name="close" />
32
- </button>
18
+ <slot name="icon">
19
+ <Icon v-if="icon" :name="icon" />
20
+ </slot>
21
+ <span>{{ title }}</span>
22
+ <button
23
+ @click.prevent.stop.capture="isMinimized = !isMinimized"
24
+ @mousedown.capture.stop
25
+ >
26
+ <Icon :name="isMinimized ? 'window-maximize' : 'window-minimize'" />
27
+ </button>
28
+ <button
29
+ @click.prevent.stop.capture="$emit('close')"
30
+ @mousedown.capture.stop
31
+ >
32
+ <Icon name="close" />
33
+ </button>
34
+ </div>
33
35
  </div>
34
- </div>
35
- <div class="bk-sidebar-detached-inner" :style="innerStyle">
36
- <slot :width="userWidth" :height="userHeight" />
37
- <template v-if="!size && !isMinimized">
38
- <div
39
- class="bk-sidebar-detached-handle bk-is-bottom"
40
- @mousedown.stop.prevent="onMouseDown($event, 'resize-bottom')"
41
- />
42
- <div
43
- class="bk-sidebar-detached-handle bk-is-right"
44
- @mousedown.stop.prevent="onMouseDown($event, 'resize-right')"
45
- />
46
- <div
47
- class="bk-sidebar-detached-handle bk-is-bottom-right"
48
- @mousedown.stop.prevent="onMouseDown($event, 'resize-bottom-right')"
49
- />
50
- </template>
51
- </div>
36
+ <div class="bk-sidebar-detached-inner" :style="innerStyle">
37
+ <slot :width="userWidth" :height="userHeight" />
38
+ <template v-if="!size && !isMinimized">
39
+ <div
40
+ class="bk-sidebar-detached-handle bk-is-bottom"
41
+ @mousedown.stop.prevent="onMouseDown($event, 'resize-bottom')"
42
+ />
43
+ <div
44
+ class="bk-sidebar-detached-handle bk-is-right"
45
+ @mousedown.stop.prevent="onMouseDown($event, 'resize-right')"
46
+ />
47
+ <div
48
+ class="bk-sidebar-detached-handle bk-is-bottom-right"
49
+ @mousedown.stop.prevent="onMouseDown($event, 'resize-bottom-right')"
50
+ />
51
+ </template>
52
+ </div>
53
+ </ScrollBoundary>
52
54
  </ViewportBlockingRect>
53
55
  </template>
54
56
 
@@ -61,7 +63,7 @@ import {
61
63
  watch,
62
64
  useState,
63
65
  } from '#imports'
64
- import { Icon, ViewportBlockingRect } from '#blokkli/components'
66
+ import { Icon, ViewportBlockingRect, ScrollBoundary } from '#blokkli/components'
65
67
  import type { BlokkliIcon } from '#blokkli/icons'
66
68
  import onBlokkliEvent from '#blokkli/helpers/composables/onBlokkliEvent'
67
69
 
@@ -45,7 +45,6 @@
45
45
  :size="size"
46
46
  :is-left="region === 'left'"
47
47
  class="bk-sidebar-inner"
48
- @wheel="onWheel"
49
48
  @close="onAttach"
50
49
  >
51
50
  <template #icon>
@@ -66,11 +65,10 @@
66
65
  </div>
67
66
  </template>
68
67
  </SidebarDetached>
69
- <div
68
+ <ScrollBoundary
70
69
  v-else
71
70
  v-show="activeSidebar === id"
72
71
  class="bk-sidebar-inner"
73
- @wheel="onWheel"
74
72
  >
75
73
  <div class="bk">
76
74
  <div class="bk-sidebar-title">
@@ -95,14 +93,14 @@
95
93
  />
96
94
  </div>
97
95
  </div>
98
- </div>
96
+ </ScrollBoundary>
99
97
  </Teleport>
100
98
  </template>
101
99
 
102
100
  <script setup lang="ts">
103
101
  import { computed, watch, ref, useBlokkli } from '#imports'
104
102
  import type { BlokkliIcon } from '#blokkli/icons'
105
- import { Icon, ShortcutIndicator } from '#blokkli/components'
103
+ import { Icon, ShortcutIndicator, ScrollBoundary } from '#blokkli/components'
106
104
  import SidebarDetached from './Detached/index.vue'
107
105
  import defineCommands from '#blokkli/helpers/composables/defineCommands'
108
106
  import onBlokkliEvent from '#blokkli/helpers/composables/onBlokkliEvent'
@@ -141,7 +139,7 @@ const emit = defineEmits<{
141
139
  (e: 'updated'): void
142
140
  }>()
143
141
 
144
- const { storage, state, ui, $t, keyboard } = useBlokkli()
142
+ const { storage, state, ui, $t } = useBlokkli()
145
143
 
146
144
  const tourElement = ref<HTMLElement | null>(null)
147
145
 
@@ -163,16 +161,6 @@ watch(isDisabled, (v) => {
163
161
  }
164
162
  })
165
163
 
166
- const onWheel = (e: WheelEvent) => {
167
- e.stopPropagation()
168
- if (e.ctrlKey || e.metaKey || keyboard.isPressingControl.value) {
169
- e.preventDefault()
170
- }
171
- if (isOverflowing.value) {
172
- e.stopPropagation()
173
- }
174
- }
175
-
176
164
  const onDetach = () => {
177
165
  isDetached.value = true
178
166
  activeSidebar.value = ''
@@ -264,6 +252,12 @@ onBlokkliEvent('item:dropped', () => {
264
252
  }
265
253
  })
266
254
 
255
+ onBlokkliEvent('sidebar:open', (id) => {
256
+ if (id === props.id) {
257
+ activeSidebar.value = props.id
258
+ }
259
+ })
260
+
267
261
  defineExpose({ showSidebar })
268
262
 
269
263
  defineTourItem(() => {
@@ -5,6 +5,7 @@
5
5
  ref="button"
6
6
  class="bk-toolbar-button"
7
7
  :class="{ 'bk-is-inactive': !isActive }"
8
+ :style="{ order: weight || 0 }"
8
9
  @click.prevent.stop="onClick"
9
10
  >
10
11
  <slot name="icon">
@@ -47,6 +48,7 @@ const props = defineProps<{
47
48
  icon?: BlokkliIcon
48
49
  tourText?: string
49
50
  modelValue?: boolean
51
+ weight?: number | string
50
52
  }>()
51
53
 
52
54
  const emit = defineEmits<{
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <slot :items="filteredList" />
2
+ <slot v-if="!isGlobalProxyMode" :items="filteredList" />
3
3
  <Component
4
4
  :is="DraggableList"
5
5
  v-if="DraggableList && isEditing && canEdit && !isInReusable && entity"
@@ -8,20 +8,27 @@
8
8
  :entity="entity"
9
9
  :field-key="fieldKey!"
10
10
  :allowed-fragments="allowedFragments"
11
+ :nesting-level="nestingLevel"
11
12
  :drop-alignment="dropAlignment"
12
13
  :field-list-type="fieldListType"
13
14
  :class="[attrs.class, listClass, { [nonEmptyClass]: filteredList.length }]"
14
15
  :is-nested="isNested"
15
- class="bk-field-list"
16
+ :language="providerEntity?.language"
17
+ :proxy-mode="proxyMode"
16
18
  :tag="tag"
19
+ :global-proxy-mode="!!isGlobalProxyMode"
17
20
  />
18
21
  <component
19
22
  :is="tag"
20
- v-else-if="!editOnly && (filteredList.length || isEditing || isPreview)"
23
+ v-else-if="
24
+ !editOnly &&
25
+ (filteredList.length || isEditing || isPreview) &&
26
+ !proxyMode &&
27
+ !isGlobalProxyMode
28
+ "
21
29
  :class="[
22
30
  attrs.class,
23
31
  {
24
- 'bk-field-list': canEdit && !isNested && !isPreview,
25
32
  [nonEmptyClass]: filteredList.length,
26
33
  },
27
34
  listClass,
@@ -36,12 +43,20 @@
36
43
  :index="i"
37
44
  />
38
45
  </component>
39
- <slot name="after" :items="filteredList" />
46
+ <slot v-if="!isGlobalProxyMode" name="after" :items="filteredList" />
40
47
  </template>
41
48
 
42
49
  <script lang="ts" setup>
43
- import { computed, useAttrs, inject, provide, ref } from '#imports'
50
+ import {
51
+ computed,
52
+ useAttrs,
53
+ inject,
54
+ provide,
55
+ ref,
56
+ type ComputedRef,
57
+ } from '#imports'
44
58
  import type { BlokkliFragmentName } from '#blokkli/definitions'
59
+ import { isVisibleByOptions } from '#blokkli/helpers/runtimeHelpers'
45
60
  import BlokkliItem from './BlokkliItem.vue'
46
61
 
47
62
  import type {
@@ -49,6 +64,7 @@ import type {
49
64
  MutatedField,
50
65
  EntityContext,
51
66
  ItemEditContext,
67
+ BlokkliProviderEntityContext,
52
68
  } from '#blokkli/types'
53
69
  import type {
54
70
  ValidFieldListTypes,
@@ -61,11 +77,16 @@ import {
61
77
  INJECT_IS_IN_REUSABLE,
62
78
  INJECT_IS_NESTED,
63
79
  INJECT_IS_PREVIEW,
80
+ INJECT_NESTING_LEVEL,
64
81
  INJECT_FIELD_LIST_BLOCKS,
65
82
  INJECT_PROVIDER_BLOCKS,
66
83
  INJECT_EDIT_CONTEXT,
67
84
  INJECT_MUTATED_FIELDS_MAP,
68
85
  INJECT_EDIT_FIELD_LIST_COMPONENT,
86
+ INJECT_PROVIDER_CONTEXT,
87
+ INJECT_FIELD_PROXY_MODE,
88
+ INJECT_GLOBAL_PROXY_MODE,
89
+ INJECT_FIELD_USES_PROXY,
69
90
  } from '../helpers/symbols'
70
91
  import type DraggableListComponent from './Edit/DraggableList.vue'
71
92
 
@@ -81,9 +102,14 @@ defineOptions({
81
102
  })
82
103
 
83
104
  const isEditing = inject(INJECT_IS_EDITING, false)
105
+ const isGlobalProxyMode = inject<ComputedRef<boolean> | null>(
106
+ INJECT_GLOBAL_PROXY_MODE,
107
+ null,
108
+ )
84
109
  const isInReusable = inject(INJECT_IS_IN_REUSABLE, false)
85
110
  const isPreview = inject<boolean>(INJECT_IS_PREVIEW, false)
86
111
  const isNested = inject(INJECT_IS_NESTED, false)
112
+ const nestingLevel = inject<number>(INJECT_NESTING_LEVEL, 0)
87
113
  const mutatedFields = inject<Record<string, MutatedField> | null>(
88
114
  INJECT_MUTATED_FIELDS_MAP,
89
115
  null,
@@ -95,6 +121,16 @@ if (!entity) {
95
121
  throw new Error('Missing entity context.')
96
122
  }
97
123
 
124
+ const providerEntity = inject<ComputedRef<BlokkliProviderEntityContext>>(
125
+ INJECT_PROVIDER_CONTEXT,
126
+ )!
127
+
128
+ if (!providerEntity) {
129
+ throw new Error(
130
+ 'Missing blökkli injection: ' + INJECT_PROVIDER_CONTEXT.toString(),
131
+ )
132
+ }
133
+
98
134
  const props = withDefaults(
99
135
  defineProps<{
100
136
  name: string
@@ -106,6 +142,10 @@ const props = withDefaults(
106
142
  nonEmptyClass?: string
107
143
  allowedFragments?: BlokkliFragmentName[]
108
144
  dropAlignment?: 'vertical' | 'horizontal'
145
+ /**
146
+ * Renders proxy blocks during editing.
147
+ */
148
+ proxyMode?: boolean
109
149
  }>(),
110
150
  {
111
151
  list: () => [],
@@ -130,27 +170,45 @@ const fieldKey = computed<string | undefined>(() => {
130
170
 
131
171
  const fieldListType = computed(() => props.fieldListType)
132
172
 
173
+ function filterVisible(item?: FieldListItemTyped | FieldListItem): boolean {
174
+ // The block is always rendered during editing.
175
+ if (isEditing) {
176
+ return true
177
+ }
178
+ return isVisibleByOptions(item, providerEntity.value.language)
179
+ }
180
+
133
181
  const filteredList = computed<FieldListItemTyped[]>(() => {
134
182
  if (mutatedFields && !isInReusable && editContext && fieldKey.value) {
135
- return ((mutatedFields[fieldKey.value] || {}).list || []).map((v) => {
136
- const mutatedOptions = editContext.mutatedOptions[v.uuid] || {}
137
- return {
138
- ...v,
139
- options: {
140
- ...v.options,
141
- ...mutatedOptions,
142
- },
143
- } as FieldListItemTyped
144
- })
183
+ return ((mutatedFields[fieldKey.value] || {}).list || [])
184
+ .map((v) => {
185
+ const mutatedOptions = editContext.mutatedOptions[v.uuid] || {}
186
+ return {
187
+ ...v,
188
+ options: {
189
+ ...v.options,
190
+ ...mutatedOptions,
191
+ },
192
+ } as FieldListItemTyped
193
+ })
194
+ .filter(filterVisible)
145
195
  }
196
+
146
197
  const list = Array.isArray(props.list) ? props.list : [props.list]
147
- return list.filter(Boolean) as FieldListItemTyped[]
198
+ return list.filter(filterVisible) as FieldListItemTyped[]
148
199
  })
149
200
 
150
201
  provide(INJECT_IS_NESTED, true)
202
+ provide(INJECT_NESTING_LEVEL, nestingLevel + 1)
151
203
  provide(INJECT_FIELD_LIST_TYPE, fieldListType)
152
204
  provide(INJECT_FIELD_LIST_BLOCKS, filteredList)
153
205
 
206
+ if (props.proxyMode) {
207
+ provide(INJECT_IS_EDITING, false)
208
+ provide(INJECT_FIELD_PROXY_MODE, false)
209
+ provide(INJECT_FIELD_USES_PROXY, true)
210
+ }
211
+
154
212
  if (!isNested) {
155
213
  provide(INJECT_PROVIDER_BLOCKS, filteredList)
156
214
  }
@@ -1,5 +1,19 @@
1
1
  <template>
2
- <component :is="component" v-if="component" v-bind="props" />
2
+ <Component
3
+ :is="component"
4
+ v-if="isProxyMode || isGlobalProxyMode"
5
+ :bundle="bundle"
6
+ :uuid="uuid"
7
+ :field-list-type="fieldListType"
8
+ :parent-type="parentType"
9
+ :item-props="props"
10
+ />
11
+ <Component
12
+ :is="component"
13
+ v-else-if="component"
14
+ v-bind="props"
15
+ :data-bk-in-proxy="fieldUsesProxy || undefined"
16
+ />
3
17
  <div v-else-if="isEditing">Block not implemented</div>
4
18
  </template>
5
19
 
@@ -9,6 +23,7 @@ import {
9
23
  provide,
10
24
  useRuntimeConfig,
11
25
  inject,
26
+ defineAsyncComponent,
12
27
  type ComputedRef,
13
28
  } from '#imports'
14
29
  import type { InjectedBlokkliItem } from '#blokkli/types'
@@ -17,6 +32,9 @@ import {
17
32
  INJECT_BLOCK_ITEM,
18
33
  INJECT_ENTITY_CONTEXT,
19
34
  INJECT_FIELD_LIST_TYPE,
35
+ INJECT_FIELD_PROXY_MODE,
36
+ INJECT_FIELD_USES_PROXY,
37
+ INJECT_GLOBAL_PROXY_MODE,
20
38
  } from '../helpers/symbols'
21
39
  import type {
22
40
  BlockBundleWithNested,
@@ -45,15 +63,25 @@ const componentProps = withDefaults(
45
63
  },
46
64
  )
47
65
 
66
+ const isProxyMode = inject(INJECT_FIELD_PROXY_MODE, false)
67
+ const fieldUsesProxy = inject(INJECT_FIELD_USES_PROXY, false)
68
+ const isGlobalProxyMode = inject<ComputedRef<boolean> | null>(
69
+ INJECT_GLOBAL_PROXY_MODE,
70
+ null,
71
+ )
72
+
48
73
  const fieldListType = inject<ComputedRef<ValidFieldListTypes> | undefined>(
49
74
  INJECT_FIELD_LIST_TYPE,
50
75
  )
51
76
 
52
- const component = getBlokkliItemComponent(
53
- componentProps.bundle,
54
- fieldListType?.value || 'default',
55
- componentProps.parentType,
56
- )
77
+ const component =
78
+ isProxyMode || isGlobalProxyMode?.value
79
+ ? defineAsyncComponent(() => import('./Edit/BlockProxy/index.vue'))
80
+ : getBlokkliItemComponent(
81
+ componentProps.bundle,
82
+ fieldListType?.value || 'default',
83
+ componentProps.parentType,
84
+ )
57
85
 
58
86
  const index = computed(() => componentProps.index)
59
87
  const item = computed(() => ({
@@ -68,7 +68,11 @@ import {
68
68
  ref,
69
69
  onMounted,
70
70
  } from '#imports'
71
- import { INJECT_ENTITY_CONTEXT } from '../helpers/symbols'
71
+ import {
72
+ INJECT_ENTITY_CONTEXT,
73
+ INJECT_PROVIDER_CONTEXT,
74
+ } from '../helpers/symbols'
75
+ import type { BlokkliProviderEntityContext } from '#blokkli/types'
72
76
 
73
77
  const PreviewProvider = defineAsyncComponent(
74
78
  () => import('./Edit/PreviewProvider.vue'),
@@ -141,6 +145,7 @@ const showIndicator = computed(
141
145
 
142
146
  function edit() {
143
147
  router.push({
148
+ path: route.path,
144
149
  query: {
145
150
  blokkliEditing: props.entityUuid,
146
151
  language: props.language,
@@ -148,6 +153,18 @@ function edit() {
148
153
  })
149
154
  }
150
155
 
156
+ const blokkliProviderEntityContext = computed<BlokkliProviderEntityContext>(
157
+ () => {
158
+ return {
159
+ uuid: props.entityUuid,
160
+ type: props.entityType,
161
+ bundle: props.entityBundle,
162
+ language: props.language,
163
+ }
164
+ },
165
+ )
166
+
167
+ provide(INJECT_PROVIDER_CONTEXT, blokkliProviderEntityContext)
151
168
  provide(INJECT_ENTITY_CONTEXT, {
152
169
  uuid: props.entityUuid,
153
170
  type: props.entityType,
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <div ref="root" class="bk-block-proxy">
3
+ <div class="bk-block-proxy-header">
4
+ <ItemIcon :bundle="bundle" />
5
+ {{ type?.label }}
6
+ </div>
7
+ <div v-if="proxyComponent" class="bk-block-proxy-component">
8
+ <Component :is="proxyComponent" v-bind="itemProps" />
9
+ </div>
10
+ <div v-if="fieldLayout.length" class="bk-block-proxy-fields">
11
+ <div
12
+ v-for="(row, i) in fieldLayout"
13
+ :key="i"
14
+ class="bk-block-proxy-fields-row"
15
+ :style="{
16
+ gridTemplateColumns: `repeat(${row.length}, 1fr)`,
17
+ }"
18
+ >
19
+ <div
20
+ v-for="field in row"
21
+ :key="field.name"
22
+ class="bk-block-proxy-fields-row-field"
23
+ >
24
+ <span>{{ field.label }}</span>
25
+ <BlokkliField proxy-mode :name="field.name" />
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </template>
31
+
32
+ <script setup lang="ts">
33
+ import type {
34
+ BlockBundleWithNested,
35
+ ValidFieldListTypes,
36
+ } from '#blokkli/generated-types'
37
+ import { computed, useBlokkli, onMounted, onBeforeUnmount, ref } from '#imports'
38
+ import {
39
+ getDefinition,
40
+ getBlokkliItemProxyComponent,
41
+ } from '#blokkli/definitions'
42
+
43
+ import { ItemIcon } from '#blokkli/components'
44
+ import type { FieldConfig } from '#blokkli/types'
45
+ import { falsy } from '#blokkli/helpers'
46
+
47
+ const props = defineProps<{
48
+ uuid: string
49
+ bundle: string
50
+ fieldListType: ValidFieldListTypes
51
+ parentType: BlockBundleWithNested
52
+ itemProps?: any
53
+ }>()
54
+
55
+ const { dom, types, runtimeConfig } = useBlokkli()
56
+
57
+ const root = ref<HTMLElement | null>(null)
58
+
59
+ const type = computed(() => types.getBlockBundleDefinition(props.bundle))
60
+
61
+ const proxyComponent = getBlokkliItemProxyComponent(props.bundle)
62
+
63
+ const definition = getDefinition(
64
+ props.bundle,
65
+ props.fieldListType,
66
+ props.parentType,
67
+ )
68
+
69
+ const fieldLayout = computed<FieldConfig[][]>(() => {
70
+ if (definition?.editor?.fieldLayout) {
71
+ return definition.editor.fieldLayout.map((row) => {
72
+ return row
73
+ .map((fieldName) => {
74
+ return types.fieldConfig.forName(
75
+ runtimeConfig.itemEntityType,
76
+ props.bundle,
77
+ fieldName,
78
+ )
79
+ })
80
+ .filter(falsy)
81
+ })
82
+ }
83
+
84
+ return types.fieldConfig
85
+ .forEntityTypeAndBundle(runtimeConfig.itemEntityType, props.bundle)
86
+ .map((config) => [config])
87
+ })
88
+
89
+ onMounted(() => {
90
+ dom.registerBlock(
91
+ props.uuid,
92
+ root.value,
93
+ props.bundle,
94
+ props.fieldListType,
95
+ props.parentType as BlockBundleWithNested,
96
+ )
97
+ })
98
+
99
+ onBeforeUnmount(() => {
100
+ dom.unregisterBlock(props.uuid)
101
+ })
102
+ </script>