@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
@@ -13,25 +13,31 @@ export default function(ui) {
13
13
  let mouseY = 0;
14
14
  let iterator = 120;
15
15
  const webglSupported = ref(null);
16
- useAnimationFrame(() => {
16
+ useAnimationFrame((time) => {
17
17
  if (iterator < 1) {
18
18
  return;
19
19
  }
20
20
  iterator--;
21
- eventBus.emit("animationFrame:before");
21
+ eventBus.emit("animationFrame:before", time);
22
22
  eventBus.emit("animationFrame", {
23
23
  mouseX,
24
24
  mouseY,
25
25
  fieldAreas: []
26
26
  });
27
27
  });
28
+ function onWindowMouseMove(e) {
29
+ mouseX = e.clientX;
30
+ mouseY = e.clientY;
31
+ }
28
32
  onMounted(() => {
29
- document.addEventListener("scroll", requestDraw);
30
33
  document.body.addEventListener("wheel", requestDraw, { passive: false });
34
+ window.addEventListener("pointermove", onWindowMouseMove, { capture: true });
31
35
  });
32
36
  onBeforeUnmount(() => {
33
37
  document.body.removeEventListener("wheel", requestDraw);
34
- document.removeEventListener("scroll", requestDraw);
38
+ window.removeEventListener("pointermove", onWindowMouseMove, {
39
+ capture: true
40
+ });
35
41
  });
36
42
  const requestDraw = () => iterator = 120;
37
43
  onBlokkliEvent("select", requestDraw);
@@ -4,6 +4,11 @@ import type { DraggableExistingBlock, BlokkliFieldElement, DraggableItem, Droppa
4
4
  import type { UiProvider } from './uiProvider.js';
5
5
  import type { BlockBundleWithNested, ValidFieldListTypes } from '#blokkli/generated-types';
6
6
  import type { DebugProvider } from './debugProvider.js';
7
+ type RegisteredFieldType = {
8
+ entityType: string;
9
+ entityBundle: string;
10
+ fieldName: string;
11
+ };
7
12
  type MeasuredBlockRect = Rectangle & {
8
13
  time: number;
9
14
  };
@@ -11,17 +16,18 @@ export type DomProvider = {
11
16
  findBlock(uuid: string): DraggableExistingBlock | undefined;
12
17
  getAllBlocks(): DraggableExistingBlock[];
13
18
  findClosestBlock(el: Element | EventTarget): DraggableExistingBlock | undefined;
14
- getAllFields(): BlokkliFieldElement[];
15
19
  /**
16
20
  * Return the droppable markup for a draggable item.
17
21
  */
18
22
  getDropElementMarkup(item: DraggableItem, checkSize?: boolean): string;
19
23
  getBlockField(uuid: string): BlokkliFieldElement;
20
24
  findField(entityUuid: string, fieldName: string): BlokkliFieldElement | undefined;
21
- registerBlock: (uuid: string, instance: ComponentInternalInstance | null, bundle: string, fieldListType: ValidFieldListTypes, parentBlockBundle?: BlockBundleWithNested) => void;
25
+ registerBlock: (uuid: string, instance: ComponentInternalInstance | null | HTMLElement, bundle: string, fieldListType: ValidFieldListTypes, parentBlockBundle?: BlockBundleWithNested) => void;
22
26
  unregisterBlock: (uuid: string) => void;
23
- registerField: (uuid: string, fieldName: string, instance: HTMLElement) => void;
24
- unregisterField: (uuid: string, fieldName: string) => void;
27
+ registerField: (entity: EntityContext, fieldName: string, instance: HTMLElement) => void;
28
+ updateFieldElement: (entity: EntityContext, fieldName: string, element: HTMLElement) => void;
29
+ unregisterField: (entity: EntityContext, fieldName: string) => void;
30
+ registeredFieldTypes: ComputedRef<RegisteredFieldType[]>;
25
31
  /**
26
32
  * Get all droppable entity fields.
27
33
  */
@@ -30,11 +36,13 @@ export type DomProvider = {
30
36
  getBlockVisibilities(): Record<string, boolean>;
31
37
  getVisibleBlocks(): string[];
32
38
  getVisibleFields(): string[];
39
+ isBlockVisible(uuid: string): boolean;
33
40
  getActiveProviderElement: () => HTMLElement;
34
41
  getBlockRects: () => Record<string, MeasuredBlockRect>;
35
42
  getBlockRect: (uuid: string) => MeasuredBlockRect | undefined;
36
43
  refreshBlockRect: (uuid: string) => void;
37
44
  getFieldRect: (key: string) => Rectangle | undefined;
45
+ updateVisibleRects: () => void;
38
46
  isReady: ComputedRef<boolean>;
39
47
  init: () => void;
40
48
  /**
@@ -15,6 +15,7 @@ const buildFieldElement = (element) => {
15
15
  const name = element.dataset.fieldName;
16
16
  const label = element.dataset.fieldLabel;
17
17
  const isNested = element.dataset.fieldIsNested === "true";
18
+ const nestingLevel = Number.parseInt(element.dataset.bkNestingLevel || "0");
18
19
  const fieldListType = element.dataset.fieldListType;
19
20
  const hostEntityType = element.dataset.hostEntityType;
20
21
  const hostEntityBundle = element.dataset.hostEntityBundle;
@@ -29,6 +30,7 @@ const buildFieldElement = (element) => {
29
30
  name,
30
31
  label,
31
32
  isNested,
33
+ nestingLevel,
32
34
  hostEntityType,
33
35
  hostEntityUuid,
34
36
  hostEntityBundle,
@@ -42,6 +44,9 @@ const buildFieldElement = (element) => {
42
44
  }
43
45
  };
44
46
  const getVisibleBlockElement = (instance) => {
47
+ if (instance instanceof HTMLElement) {
48
+ return instance;
49
+ }
45
50
  if (instance.vnode.el instanceof HTMLElement) {
46
51
  return instance.vnode.el;
47
52
  } else if (instance?.vnode.el instanceof Text && instance?.vnode.el.nextElementSibling instanceof HTMLElement) {
@@ -102,7 +107,7 @@ export default function(ui, debug) {
102
107
  if (entry.target instanceof HTMLElement) {
103
108
  const uuid = entry.target.dataset.uuid || entry.target.closest("[data-uuid]")?.dataset.uuid;
104
109
  const fieldKey = entry.target.dataset.fieldKey;
105
- const rect = entry.boundingClientRect;
110
+ const rect = entry.target.getBoundingClientRect();
106
111
  if (fieldKey) {
107
112
  if (entry.isIntersecting) {
108
113
  visibleFields.add(fieldKey);
@@ -136,20 +141,53 @@ export default function(ui, debug) {
136
141
  const observer = useDelayedIntersectionObserver(intersectionCallback);
137
142
  const registeredBlocks = reactive({});
138
143
  const registeredFields = reactive({});
139
- const registerField = (uuid, fieldName, element) => {
140
- const key = `${uuid}:${fieldName}`;
141
- registeredFields[key] = element;
144
+ const registeredFieldTypes = computed(() => {
145
+ const fields = Object.values(registeredFields);
146
+ const found = /* @__PURE__ */ new Set();
147
+ const uniqueFieldTypes = [];
148
+ for (let i = 0; i < fields.length; i++) {
149
+ const field = fields[i];
150
+ if (field) {
151
+ const key = `${field.entity.type}:${field.entity.bundle}:${field.fieldName}`;
152
+ if (!found.has(key)) {
153
+ uniqueFieldTypes.push({
154
+ entityType: field.entity.type,
155
+ entityBundle: field.entity.bundle,
156
+ fieldName: field.fieldName
157
+ });
158
+ found.add(key);
159
+ }
160
+ }
161
+ }
162
+ return uniqueFieldTypes;
163
+ });
164
+ const registerField = (entity, fieldName, element) => {
165
+ const key = `${entity.uuid}:${fieldName}`;
166
+ registeredFields[key] = { element, entity, fieldName };
167
+ observer.observe(element);
168
+ };
169
+ const updateFieldElement = (entity, fieldName, element) => {
170
+ const key = `${entity.uuid}:${fieldName}`;
171
+ const existingElement = registeredFields[key]?.element;
172
+ if (existingElement) {
173
+ observer.unobserve(existingElement);
174
+ }
175
+ registeredFields[key] = { entity, fieldName, element };
142
176
  observer.observe(element);
143
177
  };
144
- const unregisterField = (uuid, fieldName) => {
145
- const key = `${uuid}:${fieldName}`;
146
- const el = registeredFields[key];
178
+ const unregisterField = (entity, fieldName) => {
179
+ const key = `${entity.uuid}:${fieldName}`;
180
+ const el = registeredFields[key]?.element;
147
181
  if (el) {
148
182
  observer.unobserve(el);
149
183
  }
184
+ visibleFields.delete(key);
150
185
  registeredFields[key] = void 0;
151
186
  };
152
187
  function getElementToObserve(el, bundle, fieldListType, parentBlockBundle) {
188
+ if (el.classList.contains("bk-block-proxy")) {
189
+ return el;
190
+ }
153
191
  const definition = getDefinition(bundle, fieldListType, parentBlockBundle);
154
192
  if (!definition) {
155
193
  throw new Error("Failed to load definition for bundle: " + bundle);
@@ -197,6 +235,7 @@ export default function(ui, debug) {
197
235
  }
198
236
  registeredBlocks[uuid] = void 0;
199
237
  delete blockRects[uuid];
238
+ visibleBlocks.delete(uuid);
200
239
  };
201
240
  const findBlock = (uuid) => {
202
241
  const cached = draggableBlockCache[uuid];
@@ -225,14 +264,6 @@ export default function(ui, debug) {
225
264
  }
226
265
  }).filter(falsy);
227
266
  };
228
- const getAllFields = () => {
229
- const elements = [...document.querySelectorAll(".bk-field-list")];
230
- return elements.map((element) => {
231
- if (element instanceof HTMLElement) {
232
- return buildFieldElement(element);
233
- }
234
- }).filter(falsy);
235
- };
236
267
  const getDropElementMarkup = (item, checkSize) => {
237
268
  const el = item.itemType === "existing" ? getDragElement(item) : item.element();
238
269
  if (!el) {
@@ -253,7 +284,7 @@ export default function(ui, debug) {
253
284
  if (!block) {
254
285
  throw new Error("Block does not exist: " + uuid);
255
286
  }
256
- const el = block.element().closest(".bk-field-list");
287
+ const el = block.element().closest(".bk-draggable-list-container");
257
288
  if (!(el instanceof HTMLElement)) {
258
289
  throw new TypeError("Failed to locate field element for block: " + uuid);
259
290
  }
@@ -272,9 +303,9 @@ export default function(ui, debug) {
272
303
  }
273
304
  return buildFieldElement(el);
274
305
  };
275
- const getAllDroppableFields = () => [...document.querySelectorAll("[data-blokkli-droppable-field]")].map(
276
- mapDroppableField
277
- );
306
+ const getAllDroppableFields = () => [...document.querySelectorAll("[data-blokkli-droppable-field]")].filter((el) => {
307
+ return !el.closest('[data-bk-in-proxy="true"]');
308
+ }).map(mapDroppableField);
278
309
  const getBlockVisibilities = () => {
279
310
  return blockVisibility;
280
311
  };
@@ -324,12 +355,19 @@ export default function(ui, debug) {
324
355
  fieldRects[key] = ui.getAbsoluteElementRect(el.getBoundingClientRect());
325
356
  }
326
357
  let stateReloadTimeout = null;
358
+ function getUuidsToUpdateRectsFor() {
359
+ const allUuids = Object.keys(registeredBlocks);
360
+ if (allUuids.length < 150) {
361
+ return allUuids;
362
+ }
363
+ return getVisibleBlocks();
364
+ }
327
365
  function updateVisibleRects() {
328
- const visible = getVisibleBlocks();
366
+ const toUpdate = getUuidsToUpdateRectsFor();
329
367
  const offset = ui.artboardOffset.value;
330
368
  const scale = ui.artboardScale.value;
331
- for (let i = 0; i < visible.length; i++) {
332
- const uuid = visible[i];
369
+ for (let i = 0; i < toUpdate.length; i++) {
370
+ const uuid = toUpdate[i];
333
371
  const el = registeredBlocks[uuid];
334
372
  if (!el) {
335
373
  continue;
@@ -362,7 +400,7 @@ export default function(ui, debug) {
362
400
  continue;
363
401
  }
364
402
  fieldRects[key] = ui.getAbsoluteElementRect(
365
- field.getBoundingClientRect(),
403
+ field.element.getBoundingClientRect(),
366
404
  scale,
367
405
  offset
368
406
  );
@@ -376,7 +414,7 @@ export default function(ui, debug) {
376
414
  stateReloadTimeout = window.setTimeout(updateVisibleRects, 300);
377
415
  });
378
416
  onBlokkliEvent("ui:resized", function() {
379
- getVisibleBlocks().forEach(refreshBlockRect);
417
+ updateVisibleRects();
380
418
  getVisibleFields().forEach(refreshFieldRect);
381
419
  logger.log("Refreshed all visible rects");
382
420
  });
@@ -417,11 +455,13 @@ export default function(ui, debug) {
417
455
  dragElementCache.set(block.uuid, el);
418
456
  return el;
419
457
  }
458
+ function isBlockVisible(uuid) {
459
+ return visibleBlocks.has(uuid);
460
+ }
420
461
  return {
421
462
  findBlock,
422
463
  getAllBlocks,
423
464
  findClosestBlock,
424
- getAllFields,
425
465
  getDropElementMarkup,
426
466
  getBlockField,
427
467
  findField,
@@ -434,13 +474,17 @@ export default function(ui, debug) {
434
474
  getVisibleFields,
435
475
  registerField,
436
476
  unregisterField,
477
+ updateFieldElement,
437
478
  getActiveProviderElement,
438
479
  getBlockRects,
439
480
  getBlockRect,
440
481
  getFieldRect,
441
482
  refreshBlockRect,
483
+ isBlockVisible,
442
484
  isReady: computed(() => mutationsReady.value && intersectionReady.value),
443
485
  init,
444
- getDragElement
486
+ getDragElement,
487
+ updateVisibleRects,
488
+ registeredFieldTypes
445
489
  };
446
490
  }
@@ -10,7 +10,7 @@ export default function (): {
10
10
  features: ComputedRef<{
11
11
  id: ValidFeatureKey;
12
12
  label?: string | undefined;
13
- icon: import("../../../playground/.nuxt/blokkli/icons").BlokkliIcon;
13
+ icon: import("../../../.nuxt/blokkli/icons").BlokkliIcon;
14
14
  description?: string | undefined;
15
15
  dependencies?: ValidFeatureKey[] | undefined;
16
16
  viewports?: import("../constants").Viewport[] | undefined;
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * This file should contain all helpers that are meant for runtime functionality, such as defineBlokkli composable or <BlokkliProvider>.
3
3
  */
4
+ import type { FieldListItemTyped } from '#blokkli/generated-types';
4
5
  import type { BlockOptionDefinition } from '#blokkli/types/blokkOptions';
6
+ import type { FieldListItem } from '#blokkli/types';
5
7
  /**
6
8
  * Map all kinds of truthy values for a checkbox.
7
9
  * Returns our "internal" value of a checkbox state.
@@ -13,3 +15,7 @@ export declare function mapCheckboxTrue(v?: unknown): '1' | '0';
13
15
  * Internally, all option values are stored as strings. This function maps the stored data to the runtime value.
14
16
  */
15
17
  export declare function getRuntimeOptionValue(definition: Pick<BlockOptionDefinition, 'type' | 'default'>, value: string | string[] | boolean | undefined | null | number): string | string[] | boolean | number;
18
+ /**
19
+ * Determines whether an item is visible.
20
+ */
21
+ export declare function isVisibleByOptions(item?: FieldListItemTyped | FieldListItem, language?: string): boolean;
@@ -1,3 +1,8 @@
1
+ import {
2
+ bundlesWithVisibleLanguage,
3
+ bundlesWithHiddenGlobally
4
+ } from "#blokkli/default-global-options";
5
+ import { BK_HIDDEN_GLOBALLY, BK_VISIBLE_LANGUAGES } from "../symbols.js";
1
6
  export function mapCheckboxTrue(v) {
2
7
  return v === true || v === "1" || v === 1 || v === "true" ? "1" : "0";
3
8
  }
@@ -31,3 +36,23 @@ export function getRuntimeOptionValue(definition, value) {
31
36
  }
32
37
  return "";
33
38
  }
39
+ export function isVisibleByOptions(item, language) {
40
+ if (!item) {
41
+ return false;
42
+ }
43
+ if (item.options) {
44
+ if (bundlesWithHiddenGlobally.includes(item.bundle) && mapCheckboxTrue(item.options[BK_HIDDEN_GLOBALLY]) === "1") {
45
+ return false;
46
+ }
47
+ if (bundlesWithVisibleLanguage.includes(item.bundle)) {
48
+ const option = item.options[BK_VISIBLE_LANGUAGES];
49
+ if (language && option && typeof option === "string") {
50
+ const languages = option.split(",");
51
+ if (languages.length && !languages.includes(language)) {
52
+ return false;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ return true;
58
+ }
@@ -9,7 +9,7 @@ export type SelectionProvider = {
9
9
  /**
10
10
  * The currently selected UUIDs as a map.
11
11
  */
12
- uuidsMap: ComputedRef<Record<string, boolean>>;
12
+ uuidsSet: ComputedRef<Set<string>>;
13
13
  /**
14
14
  * The currently selected blocks.
15
15
  */
@@ -58,5 +58,6 @@ export type SelectionProvider = {
58
58
  * The block bundles of the items being dragged.
59
59
  */
60
60
  dragItemsBundles: ComputedRef<string[]>;
61
+ isBlockSelected(uuid: string): boolean;
61
62
  };
62
63
  export default function (dom: DomProvider): SelectionProvider;
@@ -20,12 +20,7 @@ export default function(dom) {
20
20
  const dragItemsBundles = computed(
21
21
  () => dragItems.value.map((v) => v.itemBundle).filter(falsy)
22
22
  );
23
- const uuidsMap = computed(() => {
24
- return selectedUuids.value.reduce((acc, uuid) => {
25
- acc[uuid] = true;
26
- return acc;
27
- }, {});
28
- });
23
+ const uuidsSet = computed(() => new Set(selectedUuids.value));
29
24
  const isDragging = computed(() => !!draggingMode.value);
30
25
  const blocks = computed(
31
26
  () => selectedUuids.value.map((uuid) => {
@@ -130,6 +125,9 @@ export default function(dom) {
130
125
  (v) => v.itemType === "existing" || v.itemType === "existing_structure"
131
126
  );
132
127
  });
128
+ function isBlockSelected(uuid) {
129
+ return uuidsSet.value.has(uuid);
130
+ }
133
131
  return {
134
132
  uuids: selectedUuids,
135
133
  blocks,
@@ -143,7 +141,8 @@ export default function(dom) {
143
141
  draggingMode,
144
142
  interactionMode,
145
143
  dragItems,
146
- uuidsMap,
147
- dragItemsBundles
144
+ uuidsSet,
145
+ dragItemsBundles,
146
+ isBlockSelected
148
147
  };
149
148
  }
@@ -2,15 +2,22 @@ export declare const INJECT_APP: unique symbol;
2
2
  export declare const INJECT_EDIT_CONTEXT: unique symbol;
3
3
  export declare const INJECT_IS_EDITING: unique symbol;
4
4
  export declare const INJECT_IS_NESTED: unique symbol;
5
+ export declare const INJECT_NESTING_LEVEL: unique symbol;
5
6
  export declare const INJECT_IS_PREVIEW: unique symbol;
6
7
  export declare const INJECT_IS_IN_REUSABLE: unique symbol;
7
8
  export declare const INJECT_REUSABLE_OPTIONS: unique symbol;
8
9
  export declare const INJECT_FIELD_LIST_TYPE: unique symbol;
9
10
  export declare const INJECT_FIELD_LIST_BLOCKS: unique symbol;
11
+ export declare const INJECT_FIELD_PROXY_MODE: unique symbol;
12
+ export declare const INJECT_FIELD_USES_PROXY: unique symbol;
13
+ export declare const INJECT_GLOBAL_PROXY_MODE: unique symbol;
10
14
  export declare const INJECT_PROVIDER_BLOCKS: unique symbol;
11
15
  export declare const INJECT_BLOCK_ITEM: unique symbol;
12
16
  export declare const INJECT_MUTATED_FIELDS_MAP: unique symbol;
13
17
  export declare const INJECT_ENTITY_CONTEXT: unique symbol;
18
+ export declare const INJECT_PROVIDER_CONTEXT: unique symbol;
14
19
  export declare const INJECT_FRAGMENT_CONTEXT: unique symbol;
15
20
  export declare const INJECT_EDIT_FIELD_LIST_COMPONENT: unique symbol;
16
21
  export declare const INJECT_EDIT_LOGGER: unique symbol;
22
+ export declare const BK_HIDDEN_GLOBALLY = "bkHiddenGlobally";
23
+ export declare const BK_VISIBLE_LANGUAGES = "bkVisibleLanguages";
@@ -2,17 +2,24 @@ export const INJECT_APP = Symbol("blokkli_app");
2
2
  export const INJECT_EDIT_CONTEXT = Symbol("blokkli_edit_context");
3
3
  export const INJECT_IS_EDITING = Symbol("blokkli_is_editing");
4
4
  export const INJECT_IS_NESTED = Symbol("blokkli_is_nested");
5
+ export const INJECT_NESTING_LEVEL = Symbol("blokkli_nesting_level");
5
6
  export const INJECT_IS_PREVIEW = Symbol("blokkli_is_preview");
6
7
  export const INJECT_IS_IN_REUSABLE = Symbol("blokkli_is_in_reusable");
7
8
  export const INJECT_REUSABLE_OPTIONS = Symbol("blokkli_from_library_options");
8
9
  export const INJECT_FIELD_LIST_TYPE = Symbol("blokkli_field_list_type");
9
10
  export const INJECT_FIELD_LIST_BLOCKS = Symbol("blokkli_field_list_blocks");
11
+ export const INJECT_FIELD_PROXY_MODE = Symbol("blokkli_field_proxy_mode");
12
+ export const INJECT_FIELD_USES_PROXY = Symbol("blokkli_field_uses_proxy");
13
+ export const INJECT_GLOBAL_PROXY_MODE = Symbol("blokkli_global_proxy_mode");
10
14
  export const INJECT_PROVIDER_BLOCKS = Symbol("blokkli_provider_blocks");
11
15
  export const INJECT_BLOCK_ITEM = Symbol("blokkli_block_item");
12
16
  export const INJECT_MUTATED_FIELDS_MAP = Symbol("blokkli_mutated_fields_map");
13
17
  export const INJECT_ENTITY_CONTEXT = Symbol("blokkli_entity_context");
18
+ export const INJECT_PROVIDER_CONTEXT = Symbol("blokkli_provider_context");
14
19
  export const INJECT_FRAGMENT_CONTEXT = Symbol("blokkli_fragment_context");
15
20
  export const INJECT_EDIT_FIELD_LIST_COMPONENT = Symbol(
16
21
  "blokkli_edit_field_list_component"
17
22
  );
18
23
  export const INJECT_EDIT_LOGGER = Symbol("blokkli_edit_logger");
24
+ export const BK_HIDDEN_GLOBALLY = "bkHiddenGlobally";
25
+ export const BK_VISIBLE_LANGUAGES = "bkVisibleLanguages";
@@ -3,7 +3,7 @@ import type { FieldConfig, BlockBundleDefinition, EditableFieldConfig, BlockDefi
3
3
  import type { AdapterContext, BlokkliAdapter } from '../adapter.js';
4
4
  import type { SelectionProvider } from './selectionProvider.js';
5
5
  export type BlokkliBlockType = BlockBundleDefinition & {
6
- definition: BlockDefinitionInput<BlockDefinitionOptionsInput, any[]> | undefined;
6
+ definition: BlockDefinitionInput<BlockDefinitionOptionsInput, never[]> | undefined;
7
7
  };
8
8
  interface MappableConfig {
9
9
  entityType: string;
@@ -15,6 +15,7 @@ export type UiProvider = {
15
15
  isDesktop: ComputedRef<boolean>;
16
16
  isArtboard: () => boolean;
17
17
  isAnimating: Ref<boolean>;
18
+ isProxyMode: Ref<boolean>;
18
19
  useAnimations: ComputedRef<boolean>;
19
20
  lowPerformanceMode: ComputedRef<boolean>;
20
21
  toolbarHeight: ComputedRef<number>;
@@ -8,10 +8,12 @@ import {
8
8
  import { eventBus } from "./eventBus.js";
9
9
  import { falsy } from "./index.js";
10
10
  const ARTBOARD_CLASS = "bk-is-artboard";
11
+ const CLASS_PROXY_MODE = "bk-is-proxy-mode";
11
12
  export default function(storage) {
12
13
  let cachedRootElement = null;
13
14
  let cachedArtboardElement = null;
14
15
  let cachedProviderElement = null;
16
+ const isProxyMode = ref(false);
15
17
  const menuIsOpen = ref(false);
16
18
  const isAnimating = ref(false);
17
19
  const openContextMenu = ref("");
@@ -197,10 +199,18 @@ export default function(storage) {
197
199
  height: visibleViewportHeight.value - 2 * viewportPadding.value
198
200
  };
199
201
  });
202
+ function setProxyModeClass() {
203
+ document.documentElement.classList.remove(CLASS_PROXY_MODE);
204
+ if (isProxyMode.value) {
205
+ document.documentElement.classList.add(CLASS_PROXY_MODE);
206
+ }
207
+ }
208
+ watch(isProxyMode, setProxyModeClass);
200
209
  onMounted(() => {
201
210
  document.documentElement.classList.add("bk-html-root");
202
211
  document.body.classList.add("bk-body");
203
212
  document.documentElement.classList.add(ARTBOARD_CLASS);
213
+ setProxyModeClass();
204
214
  viewportWidth.value = window.innerWidth;
205
215
  viewportHeight.value = window.innerHeight;
206
216
  window.addEventListener("resize", onResize);
@@ -212,6 +222,7 @@ export default function(storage) {
212
222
  document.documentElement.classList.remove("bk-html-root");
213
223
  document.body.classList.remove("bk-body");
214
224
  document.documentElement.classList.remove(ARTBOARD_CLASS);
225
+ document.documentElement.classList.remove(CLASS_PROXY_MODE);
215
226
  clearTimeout(resizeTimeout);
216
227
  const artboard = artboardElement();
217
228
  resizeObserver.unobserve(artboard);
@@ -224,14 +235,15 @@ export default function(storage) {
224
235
  };
225
236
  });
226
237
  function getAbsoluteElementRect(v, providedScale, providedOffset) {
227
- const rect = "x" in v && "y" in v && "width" in v && "height" in v ? v : v.getBoundingClientRect();
238
+ const rect = v instanceof HTMLElement ? v.getBoundingClientRect() : v;
228
239
  const scale = providedScale || artboardScale.value;
229
240
  const offset = providedOffset || artboardOffset.value;
230
241
  return {
231
242
  x: rect.x / scale - offset.x / scale,
232
243
  y: rect.y / scale - offset.y / scale,
233
- width: rect.width / scale,
234
- height: rect.height / scale
244
+ // Force at least a size of 24.
245
+ width: Math.max(rect.width / scale, 24),
246
+ height: Math.max(rect.height / scale, 24)
235
247
  };
236
248
  }
237
249
  function getViewportRelativeRect(rect) {
@@ -268,6 +280,7 @@ export default function(storage) {
268
280
  openContextMenu,
269
281
  viewport,
270
282
  artboardSize: computed(() => artboardSize.value),
283
+ isProxyMode,
271
284
  artboardScale,
272
285
  artboardOffset,
273
286
  selectionTopLeft,
@@ -9,6 +9,9 @@ type RectangleBufferRect = Rectangle & {
9
9
  type RectangleBufferCollectorOptions = {
10
10
  padding?: number;
11
11
  };
12
+ type PlacedRectangle = Rectangle & {
13
+ originalY: number;
14
+ };
12
15
  export declare class RectangleBufferCollector<T extends RectangleBufferRect> {
13
16
  gl?: WebGLRenderingContext;
14
17
  added: Set<string>;
@@ -22,9 +25,11 @@ export declare class RectangleBufferCollector<T extends RectangleBufferRect> {
22
25
  radius: number[];
23
26
  index: number;
24
27
  bufferInfo: BufferInfo | null;
28
+ placedRects: PlacedRectangle[];
25
29
  constructor(gl?: WebGLRenderingContext, _options?: RectangleBufferCollectorOptions);
26
30
  reset(): void;
27
- addRectangle(rect: Omit<T, 'index'>, type: number): void;
31
+ getIdealPosition(x: number, y: number, width: number, height: number): Rectangle;
32
+ addRectangle(rect: Omit<T, 'index'>, type: number, checkOverlap?: boolean): void;
28
33
  getIndex(id: string): number | undefined;
29
34
  updateRectangle(): void;
30
35
  createBufferInfo(): BufferInfo | null;
@@ -1,4 +1,5 @@
1
1
  import { createBufferInfoFromArrays } from "twgl.js";
2
+ import { intersects } from "../index.js";
2
3
  export class RectangleBufferCollector {
3
4
  gl;
4
5
  added = /* @__PURE__ */ new Set();
@@ -12,6 +13,7 @@ export class RectangleBufferCollector {
12
13
  radius = [];
13
14
  index = 0;
14
15
  bufferInfo = null;
16
+ placedRects = [];
15
17
  constructor(gl, _options) {
16
18
  this.gl = gl;
17
19
  }
@@ -28,11 +30,42 @@ export class RectangleBufferCollector {
28
30
  this.index = 0;
29
31
  this.bufferInfo = null;
30
32
  }
31
- addRectangle(rect, type) {
32
- const x = rect.x;
33
- const y = rect.y;
34
- const width = rect.width;
35
- const height = rect.height;
33
+ getIdealPosition(x, y, width, height) {
34
+ const rect = {
35
+ x,
36
+ y,
37
+ width,
38
+ height,
39
+ originalY: y
40
+ };
41
+ const intersections = [];
42
+ for (let i = 0; i < this.placedRects.length; i++) {
43
+ if (intersects(rect, this.placedRects[i])) {
44
+ intersections.push(this.placedRects[i]);
45
+ }
46
+ }
47
+ if (intersections.length === 0) {
48
+ this.placedRects.push(rect);
49
+ return rect;
50
+ }
51
+ intersections.sort((a, b) => b.originalY - a.originalY);
52
+ for (let i = 0; i < intersections.length; i++) {
53
+ const existingRect = intersections[i];
54
+ let iterations = 0;
55
+ const direction = y > existingRect.originalY ? -1 : 1;
56
+ while (intersects(rect, existingRect) && iterations < 10) {
57
+ rect.y = y + direction * (10 * (iterations + 1));
58
+ iterations++;
59
+ }
60
+ if (iterations >= 10) {
61
+ rect.y = y;
62
+ }
63
+ }
64
+ this.placedRects.push(rect);
65
+ return rect;
66
+ }
67
+ addRectangle(rect, type, checkOverlap = false) {
68
+ const { x, y, width, height } = checkOverlap ? this.getIdealPosition(rect.x, rect.y, rect.width, rect.height) : rect;
36
69
  this.positions.push(
37
70
  x,
38
71
  y,
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>eye</title><path d="M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17M12,4.5C7,4.5 2.73,7.61 1,12C2.73,16.39 7,19.5 12,19.5C17,19.5 21.27,16.39 23,12C21.27,7.61 17,4.5 12,4.5Z" /></svg>
@@ -3,18 +3,22 @@ export type ModuleOptionsSettings = {
3
3
  disable?: boolean;
4
4
  default?: 'vertical' | 'horizontal' | 'sidebar';
5
5
  };
6
- 'feature:artboard:persist'?: {
6
+ 'feature:block-add-list:hideDisabledBlocks'?: {
7
7
  disable?: boolean;
8
8
  default?: boolean;
9
9
  };
10
- 'feature:artboard:scrollSpeed'?: {
10
+ 'feature:artboard:momentum'?: {
11
11
  disable?: boolean;
12
- default?: number;
12
+ default?: boolean;
13
13
  };
14
- 'feature:block-add-list:hideDisabledBlocks'?: {
14
+ 'feature:artboard:persist'?: {
15
15
  disable?: boolean;
16
16
  default?: boolean;
17
17
  };
18
+ 'feature:artboard:scrollSpeed'?: {
19
+ disable?: boolean;
20
+ default?: number;
21
+ };
18
22
  'feature:clipboard:openSidebarOnPaste'?: {
19
23
  disable?: boolean;
20
24
  default?: boolean;
@@ -27,6 +31,10 @@ export type ModuleOptionsSettings = {
27
31
  disable?: boolean;
28
32
  default?: boolean;
29
33
  };
34
+ 'feature:publish:closeAfterPublish'?: {
35
+ disable?: boolean;
36
+ default?: boolean;
37
+ };
30
38
  'feature:settings:lowPerformanceMode'?: {
31
39
  disable?: boolean;
32
40
  default?: boolean;