@blokkli/editor 1.3.3 → 1.4.0-alpha.0

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.
@@ -1,8 +1,6 @@
1
- import type { ComponentInternalInstance } from 'vue';
2
1
  import { type ComputedRef } from '#imports';
3
2
  import type { DraggableExistingBlock, BlokkliFieldElement, DraggableItem, DroppableEntityField, EntityContext, Rectangle } from '#blokkli/types';
4
3
  import type { UiProvider } from './uiProvider.js';
5
- import type { BlockBundleWithNested, ValidFieldListTypes } from '#blokkli/generated-types';
6
4
  import type { DebugProvider } from './debugProvider.js';
7
5
  type RegisteredFieldType = {
8
6
  entityType: string;
@@ -21,8 +19,6 @@ export type DomProvider = {
21
19
  */
22
20
  getDropElementMarkup(item: DraggableItem, checkSize?: boolean): string;
23
21
  findField(entityUuid: string, fieldName: string): BlokkliFieldElement | undefined;
24
- registerBlock: (uuid: string, instance: ComponentInternalInstance | null | HTMLElement, bundle: string, fieldListType: ValidFieldListTypes, parentBlockBundle?: BlockBundleWithNested) => void;
25
- unregisterBlock: (uuid: string) => void;
26
22
  registerField: (entity: EntityContext, fieldName: string, instance: HTMLElement) => void;
27
23
  updateFieldElement: (entity: EntityContext, fieldName: string, element: HTMLElement) => void;
28
24
  unregisterField: (entity: EntityContext, fieldName: string) => void;
@@ -43,16 +43,6 @@ const buildFieldElement = (element) => {
43
43
  };
44
44
  }
45
45
  };
46
- const getVisibleBlockElement = (instance) => {
47
- if (instance instanceof HTMLElement) {
48
- return instance;
49
- }
50
- if (instance.vnode.el instanceof HTMLElement) {
51
- return instance.vnode.el;
52
- } else if (instance?.vnode.el instanceof Text && instance?.vnode.el.nextElementSibling instanceof HTMLElement) {
53
- return instance.vnode.el.nextElementSibling;
54
- }
55
- };
56
46
  function rectWithTime(rect, time) {
57
47
  return {
58
48
  ...rect,
@@ -60,6 +50,7 @@ function rectWithTime(rect, time) {
60
50
  };
61
51
  }
62
52
  export default function(ui, debug) {
53
+ const artboardElement = ui.artboardElement();
63
54
  const logger = debug.createLogger("DomProvider");
64
55
  const mutationsReady = ref(true);
65
56
  const intersectionReady = ref(false);
@@ -136,7 +127,7 @@ export default function(ui, debug) {
136
127
  }
137
128
  }
138
129
  }
139
- const observer = useDelayedIntersectionObserver(intersectionCallback);
130
+ const intersectionObserver = useDelayedIntersectionObserver(intersectionCallback);
140
131
  const registeredBlocks = reactive({});
141
132
  const registeredFields = reactive({});
142
133
  const registeredFieldTypes = computed(() => {
@@ -162,22 +153,22 @@ export default function(ui, debug) {
162
153
  const registerField = (entity, fieldName, element) => {
163
154
  const key = `${entity.uuid}:${fieldName}`;
164
155
  registeredFields[key] = { element, entity, fieldName };
165
- observer.observe(element);
156
+ intersectionObserver.observe(element);
166
157
  };
167
158
  const updateFieldElement = (entity, fieldName, element) => {
168
159
  const key = `${entity.uuid}:${fieldName}`;
169
160
  const existingElement = registeredFields[key]?.element;
170
161
  if (existingElement) {
171
- observer.unobserve(existingElement);
162
+ intersectionObserver.unobserve(existingElement);
172
163
  }
173
164
  registeredFields[key] = { entity, fieldName, element };
174
- observer.observe(element);
165
+ intersectionObserver.observe(element);
175
166
  };
176
167
  const unregisterField = (entity, fieldName) => {
177
168
  const key = `${entity.uuid}:${fieldName}`;
178
169
  const el = registeredFields[key]?.element;
179
170
  if (el) {
180
- observer.unobserve(el);
171
+ intersectionObserver.unobserve(el);
181
172
  }
182
173
  visibleFields.delete(key);
183
174
  registeredFields[key] = void 0;
@@ -196,45 +187,6 @@ export default function(ui, debug) {
196
187
  }
197
188
  return el;
198
189
  }
199
- const registerBlock = (uuid, instance, bundle, fieldListType, parentBlockBundle) => {
200
- if (registeredBlocks[uuid]) {
201
- console.error(
202
- "Trying to register block with already existing UUID: " + uuid
203
- );
204
- }
205
- if (!instance) {
206
- console.error(
207
- `Failed to get component instance of block with UUID "${uuid}"`
208
- );
209
- return;
210
- }
211
- const el = getVisibleBlockElement(instance);
212
- if (!el) {
213
- console.error(
214
- `Failed to locate block component element for UUID "${uuid}". Make sure the block renders at least one root element that is always visible.`
215
- );
216
- return;
217
- }
218
- const observableElement = getElementToObserve(
219
- el,
220
- bundle,
221
- fieldListType,
222
- parentBlockBundle
223
- );
224
- observer.observe(observableElement);
225
- resizeObserver.observe(observableElement);
226
- registeredBlocks[uuid] = el;
227
- };
228
- const unregisterBlock = (uuid) => {
229
- const el = registeredBlocks[uuid];
230
- if (el) {
231
- observer.unobserve(el);
232
- resizeObserver.unobserve(el);
233
- }
234
- registeredBlocks[uuid] = void 0;
235
- delete blockRects[uuid];
236
- visibleBlocks.delete(uuid);
237
- };
238
190
  const findBlock = (uuid) => {
239
191
  const cached = draggableBlockCache[uuid];
240
192
  if (cached) {
@@ -399,26 +351,72 @@ export default function(ui, debug) {
399
351
  logger.log("Refreshed all visible rects");
400
352
  });
401
353
  function init() {
402
- observer.init();
354
+ intersectionObserver.init();
403
355
  intersectionReady.value = true;
404
356
  logger.log("IntersectionObserver initialized");
405
357
  }
406
358
  const dragElementUuidMap = /* @__PURE__ */ new WeakMap();
407
359
  const dragElementCache = /* @__PURE__ */ new Map();
408
- const callback = function(mutationsList) {
360
+ function handleNodeAdded(node) {
361
+ if (!(node instanceof HTMLElement)) {
362
+ return;
363
+ }
364
+ if (node.dataset.uuid) {
365
+ const item = buildDraggableItem(node);
366
+ if (item && item.itemType === "existing") {
367
+ const observableElement = getElementToObserve(
368
+ node,
369
+ item.itemBundle,
370
+ item.hostFieldListType,
371
+ item.hostBundle
372
+ );
373
+ intersectionObserver.observe(observableElement);
374
+ resizeObserver.observe(observableElement);
375
+ registeredBlocks[item.uuid] = node;
376
+ }
377
+ } else if (node.dataset.fieldName && node.dataset.fieldKey && node.dataset.fieldCardinality) {
378
+ const blocks = node.querySelectorAll('[data-element-type="existing"]');
379
+ for (const block of blocks) {
380
+ handleNodeAdded(block);
381
+ }
382
+ }
383
+ }
384
+ function handleNodeRemoved(node) {
385
+ if (node instanceof HTMLElement && node.dataset.uuid) {
386
+ const uuid = node.dataset.uuid;
387
+ const el = registeredBlocks[uuid];
388
+ if (el !== node) {
389
+ return;
390
+ }
391
+ if (el) {
392
+ intersectionObserver.unobserve(el);
393
+ resizeObserver.unobserve(el);
394
+ dragElementUuidMap.delete(el);
395
+ }
396
+ dragElementUuidMap.delete(node);
397
+ dragElementCache.delete(uuid);
398
+ registeredBlocks[uuid] = void 0;
399
+ delete blockRects[uuid];
400
+ visibleBlocks.delete(uuid);
401
+ }
402
+ }
403
+ const mutationObserverCallback = function(mutationsList) {
409
404
  for (const mutation of mutationsList) {
410
405
  if (mutation.type === "childList") {
411
- mutation.removedNodes.forEach((node) => {
412
- const uuid = dragElementUuidMap.get(node);
413
- dragElementUuidMap.delete(node);
414
- if (uuid) {
415
- dragElementCache.delete(uuid);
416
- }
417
- });
406
+ for (const node of mutation.removedNodes) {
407
+ handleNodeRemoved(node);
408
+ }
409
+ for (const node of mutation.addedNodes) {
410
+ handleNodeAdded(node);
411
+ }
418
412
  }
419
413
  }
420
414
  };
421
- const mutationObserver = new MutationObserver(callback);
415
+ const mutationObserver = new MutationObserver(mutationObserverCallback);
416
+ mutationObserver.observe(artboardElement, {
417
+ subtree: true,
418
+ childList: true
419
+ });
422
420
  function getDragElement(block) {
423
421
  const cached = dragElementCache.get(block.uuid);
424
422
  if (cached && document.body.contains(cached)) {
@@ -444,8 +442,6 @@ export default function(ui, debug) {
444
442
  findClosestBlock,
445
443
  getDropElementMarkup,
446
444
  findField,
447
- registerBlock,
448
- unregisterBlock,
449
445
  getAllDroppableFields,
450
446
  findClosestEntityContext,
451
447
  getVisibleBlocks,
@@ -1018,7 +1018,7 @@ export type FeatureDefinition<Methods extends AdapterMethods[] = [], T extends s
1018
1018
  /**
1019
1019
  * The unique ID of the feature.
1020
1020
  */
1021
- id: T;
1021
+ id: string;
1022
1022
  /**
1023
1023
  * The label of the feature.
1024
1024
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokkli/editor",
3
- "version": "1.3.3",
3
+ "version": "1.4.0-alpha.0",
4
4
  "description": "Interactive page building experience for Nuxt",
5
5
  "repository": "blokkli/editor",
6
6
  "type": "module",
@@ -49,7 +49,7 @@
49
49
  "license": "MIT",
50
50
  "dependencies": {
51
51
  "@nuxt/kit": "^3.13.1",
52
- "artboard-deluxe": "^0.0.1",
52
+ "artboard-deluxe": "^0.1.0",
53
53
  "estree-walker-ts": "^1.0.1",
54
54
  "fzf": "^0.5.2",
55
55
  "get-video-id": "^4.1.7",