@blokkli/editor 2.0.0-alpha.21 → 2.0.0-alpha.23

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 (154) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +97 -169
  3. package/dist/runtime/blokkliPlugins/MenuButton/index.vue +3 -1
  4. package/dist/runtime/blokkliPlugins/Sidebar/Detached/index.vue +20 -14
  5. package/dist/runtime/blokkliPlugins/Sidebar/Detached/index.vue.d.ts +8 -4
  6. package/dist/runtime/blokkliPlugins/Sidebar/index.vue +55 -25
  7. package/dist/runtime/blokkliPlugins/Sidebar/index.vue.d.ts +4 -3
  8. package/dist/runtime/blokkliPlugins/ToolbarButton/index.vue +4 -1
  9. package/dist/runtime/blokkliPlugins/ViewOption/index.vue +3 -1
  10. package/dist/runtime/blokkliPlugins/index.d.ts +1 -3
  11. package/dist/runtime/blokkliPlugins/index.js +0 -4
  12. package/dist/runtime/components/Blocks/FromLibrary/index.vue +0 -5
  13. package/dist/runtime/components/BlokkliEditable.vue +6 -1
  14. package/dist/runtime/components/BlokkliField.vue +1 -1
  15. package/dist/runtime/components/BlokkliProvider.vue +4 -4
  16. package/dist/runtime/components/Edit/Actions/ItemDropdown.vue +66 -0
  17. package/dist/runtime/components/Edit/Actions/ItemDropdown.vue.d.ts +6 -0
  18. package/dist/runtime/components/Edit/Actions/index.vue +7 -49
  19. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +23 -68
  20. package/dist/runtime/components/Edit/BlockProxy/index.vue +2 -8
  21. package/dist/runtime/components/Edit/BlokkliErrorBoundary.vue +33 -49
  22. package/dist/runtime/components/Edit/BlokkliErrorBoundary.vue.d.ts +14 -1
  23. package/dist/runtime/components/Edit/BlokkliRootErrorBoundary.vue +93 -0
  24. package/dist/runtime/components/Edit/BlokkliRootErrorBoundary.vue.d.ts +12 -0
  25. package/dist/runtime/components/Edit/DraggableList.vue +5 -25
  26. package/dist/runtime/components/Edit/EditProvider.vue +24 -11
  27. package/dist/runtime/components/Edit/Features/{BlockAddList → AddList/Blocks}/index.vue +26 -62
  28. package/dist/runtime/components/Edit/Features/{Hover/Overlay → AddList/Blocks}/index.vue.d.ts +2 -2
  29. package/dist/runtime/components/Edit/Features/AddList/index.vue +29 -8
  30. package/dist/runtime/components/Edit/Features/Analyze/{Renderer.vue → Main.vue} +4 -8
  31. package/dist/runtime/components/Edit/Features/Analyze/{Overlay → Renderer}/fragment.glsl +10 -6
  32. package/dist/runtime/components/Edit/Features/Analyze/{Overlay → Renderer}/index.vue +43 -15
  33. package/dist/runtime/components/Edit/Features/Analyze/{Overlay → Renderer}/index.vue.d.ts +0 -2
  34. package/dist/runtime/components/Edit/Features/Analyze/{Overlay → Renderer}/vertex.glsl +11 -9
  35. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItemNodesTarget.vue +15 -3
  36. package/dist/runtime/components/Edit/Features/Analyze/analyzers/helpers/collectTextElements.js +3 -0
  37. package/dist/runtime/components/Edit/Features/Analyze/index.vue +7 -3
  38. package/dist/runtime/components/Edit/Features/Anchors/index.vue +2 -2
  39. package/dist/runtime/components/Edit/Features/Clipboard/List/index.vue +21 -10
  40. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +18 -11
  41. package/dist/runtime/components/Edit/Features/Conversions/index.vue +16 -9
  42. package/dist/runtime/components/Edit/Features/Debug/DebugSection.vue +24 -0
  43. package/dist/runtime/components/Edit/Features/Debug/DebugSection.vue.d.ts +16 -0
  44. package/dist/runtime/components/Edit/Features/Debug/Main.vue +80 -0
  45. package/dist/runtime/components/Edit/Features/Debug/Section/Features.vue +34 -0
  46. package/dist/runtime/components/Edit/Features/Debug/Section/Icons.vue +15 -0
  47. package/dist/runtime/components/Edit/Features/Debug/Section/Icons.vue.d.ts +2 -0
  48. package/dist/runtime/components/Edit/Features/Debug/Section/Keyboard.vue +17 -0
  49. package/dist/runtime/components/Edit/Features/Debug/Section/Keyboard.vue.d.ts +2 -0
  50. package/dist/runtime/components/Edit/Features/Debug/Section/Logging.vue +66 -0
  51. package/dist/runtime/components/Edit/Features/{Selection/OverlayFallback/index.vue.d.ts → Debug/Section/Logging.vue.d.ts} +2 -1
  52. package/dist/runtime/components/Edit/Features/Debug/Section/Rendering.vue +96 -0
  53. package/dist/runtime/components/Edit/Features/Debug/Section/Rendering.vue.d.ts +2 -0
  54. package/dist/runtime/components/Edit/Features/Debug/Section/Selection.vue +25 -0
  55. package/dist/runtime/components/Edit/Features/Debug/Section/Selection.vue.d.ts +2 -0
  56. package/dist/runtime/components/Edit/Features/Debug/index.vue +2 -2
  57. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +20 -27
  58. package/dist/runtime/components/Edit/Features/DraggingOverlay/Renderer/fragment.glsl +80 -0
  59. package/dist/runtime/components/Edit/Features/DraggingOverlay/{DropTargets → Renderer}/index.vue +100 -87
  60. package/dist/runtime/components/Edit/Features/DraggingOverlay/{DropTargets → Renderer}/vertex.glsl +51 -8
  61. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +3 -3
  62. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue +0 -6
  63. package/dist/runtime/components/Edit/Features/EditableField/index.vue +6 -2
  64. package/dist/runtime/components/Edit/Features/Fragments/Dialog/Item/index.vue +1 -5
  65. package/dist/runtime/components/Edit/Features/Hover/Renderer/fragment.glsl +141 -0
  66. package/dist/runtime/components/Edit/Features/Hover/{Overlay → Renderer}/index.vue +225 -38
  67. package/dist/runtime/components/Edit/Features/Hover/Renderer/index.vue.d.ts +2 -0
  68. package/dist/runtime/components/Edit/Features/Hover/{Overlay → Renderer}/vertex.glsl +49 -11
  69. package/dist/runtime/components/Edit/Features/Hover/index.vue +9 -6
  70. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/Item/index.vue +1 -5
  71. package/dist/runtime/components/Edit/Features/Library/index.vue +24 -12
  72. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/Item.vue +1 -1
  73. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +26 -13
  74. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue.d.ts +0 -1
  75. package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue +3 -47
  76. package/dist/runtime/components/Edit/Features/MultiSelect/{Overlay → Renderer}/fragment.glsl +13 -26
  77. package/dist/runtime/components/Edit/Features/MultiSelect/{Overlay → Renderer}/index.vue +130 -72
  78. package/dist/runtime/components/Edit/Features/MultiSelect/{Overlay → Renderer}/index.vue.d.ts +0 -1
  79. package/dist/runtime/components/Edit/Features/MultiSelect/{Overlay → Renderer}/vertex.glsl +27 -2
  80. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +25 -12
  81. package/dist/runtime/components/Edit/Features/Ownership/index.vue +2 -2
  82. package/dist/runtime/components/Edit/Features/ResponsivePreview/index.vue +1 -1
  83. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Content/index.vue +23 -6
  84. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue.d.ts +2 -2
  85. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/fragment.glsl +19 -17
  86. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/index.vue +242 -131
  87. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/vertex.glsl +29 -12
  88. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue +12 -4
  89. package/dist/runtime/components/Edit/Features/Selection/{Overlay → Renderer}/fragment.glsl +23 -14
  90. package/dist/runtime/components/Edit/Features/Selection/{Overlay → Renderer}/index.vue +121 -28
  91. package/dist/runtime/components/Edit/Features/Selection/{Overlay → Renderer}/index.vue.d.ts +0 -2
  92. package/dist/runtime/components/Edit/Features/Selection/{Overlay → Renderer}/vertex.glsl +23 -14
  93. package/dist/runtime/components/Edit/Features/Selection/index.vue +46 -59
  94. package/dist/runtime/components/Edit/Features/Transform/Dialog/index.vue +5 -5
  95. package/dist/runtime/components/Edit/Features/Transform/index.vue +29 -22
  96. package/dist/runtime/components/Edit/Form/Checkboxes/index.vue +43 -0
  97. package/dist/runtime/components/Edit/Form/Checkboxes/index.vue.d.ts +20 -0
  98. package/dist/runtime/components/Edit/Messages/Item/index.vue.d.ts +1 -1
  99. package/dist/runtime/components/Edit/PreviewProvider.vue +1 -1
  100. package/dist/runtime/components/Edit/Sortli/index.vue +5 -8
  101. package/dist/runtime/components/Edit/Sortli/index.vue.d.ts +2 -0
  102. package/dist/runtime/components/Edit/Toolbar/index.vue +1 -4
  103. package/dist/runtime/components/Edit/ViewportBlockingRect/index.vue +9 -2
  104. package/dist/runtime/components/Edit/ViewportBlockingRect/index.vue.d.ts +4 -1
  105. package/dist/runtime/components/Edit/index.d.ts +6 -4
  106. package/dist/runtime/components/Edit/index.js +11 -7
  107. package/dist/runtime/css/output.css +1 -1
  108. package/dist/runtime/helpers/animationProvider.d.ts +58 -9
  109. package/dist/runtime/helpers/animationProvider.js +318 -75
  110. package/dist/runtime/helpers/composables/defineItemDropdownAction.d.ts +2 -0
  111. package/dist/runtime/helpers/composables/defineItemDropdownAction.js +10 -0
  112. package/dist/runtime/helpers/composables/defineRenderer.d.ts +5 -2
  113. package/dist/runtime/helpers/composables/defineRenderer.js +3 -2
  114. package/dist/runtime/helpers/composables/useGlobalBlokkliObject.d.ts +16 -0
  115. package/dist/runtime/helpers/composables/useGlobalBlokkliObject.js +36 -0
  116. package/dist/runtime/helpers/debugProvider.d.ts +13 -3
  117. package/dist/runtime/helpers/debugProvider.js +80 -12
  118. package/dist/runtime/helpers/domProvider.js +46 -32
  119. package/dist/runtime/helpers/dropTargets/index.js +1 -1
  120. package/dist/runtime/helpers/eventBus.d.ts +1 -1
  121. package/dist/runtime/helpers/index.d.ts +1 -6
  122. package/dist/runtime/helpers/index.js +0 -81
  123. package/dist/runtime/helpers/pluginProvider.d.ts +16 -0
  124. package/dist/runtime/helpers/pluginProvider.js +30 -1
  125. package/dist/runtime/helpers/providers/directive.d.ts +4 -1
  126. package/dist/runtime/helpers/providers/directive.js +9 -2
  127. package/dist/runtime/helpers/stateProvider.js +1 -0
  128. package/dist/runtime/helpers/uiProvider.d.ts +5 -1
  129. package/dist/runtime/helpers/uiProvider.js +41 -7
  130. package/dist/runtime/helpers/webgl/index.d.ts +2 -3
  131. package/dist/runtime/helpers/webgl/index.js +9 -14
  132. package/dist/runtime/icons/dock-left.svg +1 -0
  133. package/dist/runtime/icons/dock-right.svg +1 -0
  134. package/dist/runtime/icons/dock-window.svg +1 -0
  135. package/dist/runtime/plugins/blokkliDirectives.js +1 -1
  136. package/dist/runtime/types/index.d.ts +4 -21
  137. package/package.json +1 -1
  138. package/dist/runtime/blokkliPlugins/DroppableEdit/index.vue +0 -56
  139. package/dist/runtime/blokkliPlugins/DroppableEdit/index.vue.d.ts +0 -24
  140. package/dist/runtime/blokkliPlugins/ItemDropdown/index.vue +0 -76
  141. package/dist/runtime/blokkliPlugins/ItemDropdown/index.vue.d.ts +0 -31
  142. package/dist/runtime/components/Edit/Features/BlockAddList/docs.md +0 -15
  143. package/dist/runtime/components/Edit/Features/Debug/Renderer.vue +0 -240
  144. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/fragment.glsl +0 -96
  145. package/dist/runtime/components/Edit/Features/Hover/Overlay/fragment.glsl +0 -139
  146. package/dist/runtime/components/Edit/Features/Selection/OverlayFallback/index.vue +0 -42
  147. /package/dist/runtime/components/Edit/Features/Analyze/{Renderer.vue.d.ts → Main.vue.d.ts} +0 -0
  148. /package/dist/runtime/components/Edit/Features/Anchors/{Renderer.vue → Overlay/index.vue} +0 -0
  149. /package/dist/runtime/components/Edit/Features/{BlockAddList → Anchors/Overlay}/index.vue.d.ts +0 -0
  150. /package/dist/runtime/components/Edit/Features/Debug/{Renderer.vue.d.ts → Main.vue.d.ts} +0 -0
  151. /package/dist/runtime/components/Edit/Features/{Anchors/Renderer.vue.d.ts → Debug/Section/Features.vue.d.ts} +0 -0
  152. /package/dist/runtime/components/Edit/Features/DraggingOverlay/{DropTargets → Renderer}/index.vue.d.ts +0 -0
  153. /package/dist/runtime/components/Edit/Features/Ownership/{Renderer.vue → Banner/index.vue} +0 -0
  154. /package/dist/runtime/components/Edit/Features/Ownership/{Renderer.vue.d.ts → Banner/index.vue.d.ts} +0 -0
@@ -20,7 +20,11 @@
20
20
  import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
21
21
  import defineRenderer from "#blokkli/helpers/composables/defineRenderer";
22
22
  import { useBlokkli, computed, ref } from "#imports";
23
- import { setBuffersAndAttributes, drawBufferInfo, setUniforms } from "twgl.js";
23
+ import {
24
+ setBuffersAndAttributes,
25
+ drawBufferInfo,
26
+ setUniforms
27
+ } from "twgl.js";
24
28
  import vs from "./vertex.glsl?raw";
25
29
  import fs from "./fragment.glsl?raw";
26
30
  import { RectangleBufferCollector } from "#blokkli/helpers/webgl";
@@ -113,44 +117,26 @@ const tooltipData = computed(() => {
113
117
  return { x: screenX, y: screenY, transform, position, text, isField };
114
118
  });
115
119
  const emit = defineEmits(["toggle", "toggleField"]);
116
- const gl = animation.gl();
117
- const programInfo = gl ? animation.registerProgram("add-buttons", gl, [vs, fs]) : null;
118
120
  const MAX_CIRCLES = 10;
119
121
  const BUTTON_RADIUS = 12;
120
122
  const TOOLTIP_MARGIN = 20;
121
- let bufferInfo = null;
122
- if (gl) {
123
- class CircleBufferCollector extends RectangleBufferCollector {
124
- }
125
- const collector = new CircleBufferCollector(gl);
126
- for (let i = 0; i < MAX_CIRCLES; i++) {
127
- collector.addRectangle(
128
- {
129
- id: `circle-${i}`,
130
- x: 0,
131
- y: 0,
132
- width: 40,
133
- height: 40
134
- },
135
- i
136
- );
137
- }
138
- bufferInfo = collector.createBufferInfo();
123
+ class CircleBufferCollector extends RectangleBufferCollector {
139
124
  }
125
+ let bufferInfoCache = null;
140
126
  const circlePositions = new Float32Array(MAX_CIRCLES * 2);
141
127
  const circleVisible = new Float32Array(MAX_CIRCLES);
142
128
  const hoveredCircle = ref(-1);
143
129
  const color = computed(() => {
144
- return toShaderColor(theme.accent.value[600]);
130
+ return theme.accent.value[600];
145
131
  });
146
132
  const colorHover = computed(() => {
147
- return toShaderColor(theme.accent.value[500]);
133
+ return theme.accent.value[500];
148
134
  });
149
135
  const colorField = computed(() => {
150
- return toShaderColor(theme.accent.value[400]);
136
+ return theme.accent.value[400];
151
137
  });
152
138
  const colorFieldHover = computed(() => {
153
- return toShaderColor(theme.accent.value[300]);
139
+ return theme.accent.value[300];
154
140
  });
155
141
  const orientationCache = /* @__PURE__ */ new Map();
156
142
  const currentOrientation = ref("horizontal");
@@ -310,127 +296,252 @@ function getCircleAtPoint(x, y) {
310
296
  }
311
297
  return -1;
312
298
  }
313
- if (gl && programInfo && bufferInfo) {
314
- defineRenderer("add-buttons", {
315
- zIndex: 1e3,
316
- enabled: () => {
317
- if (selection.uuids.value.length !== 1) {
318
- return false;
319
- }
320
- if (ui.openTooltip.value && ui.openTooltip.value !== "add-buttons") {
321
- return false;
322
- }
323
- if (ui.hasTransformOverlayOpen.value) {
324
- return false;
299
+ const { collector } = defineRenderer("add-buttons", {
300
+ zIndex: 1e3,
301
+ collector: () => {
302
+ const c = new CircleBufferCollector();
303
+ for (let i = 0; i < MAX_CIRCLES; i++) {
304
+ c.addRectangle(
305
+ {
306
+ id: `circle-${i}`,
307
+ x: 0,
308
+ y: 0,
309
+ width: 40,
310
+ height: 40
311
+ },
312
+ i
313
+ );
314
+ }
315
+ return c;
316
+ },
317
+ program: () => ({ shaders: [vs, fs] }),
318
+ enabled: () => {
319
+ if (selection.uuids.value.length !== 1) {
320
+ return false;
321
+ }
322
+ if (ui.openTooltip.value && ui.openTooltip.value !== "add-buttons") {
323
+ return false;
324
+ }
325
+ if (ui.hasTransformOverlayOpen.value) {
326
+ return false;
327
+ }
328
+ return true;
329
+ },
330
+ cursor: () => hoveredCircle.value >= 0 ? "pointer" : null,
331
+ onClick: ({ mouseArtboard }) => {
332
+ if (selection.uuids.value.length !== 1) {
333
+ return false;
334
+ }
335
+ const clickedCircle = getCircleAtPoint(mouseArtboard.x, mouseArtboard.y);
336
+ if (clickedCircle >= 0) {
337
+ const cx = circlePositions[clickedCircle * 2];
338
+ const cy = circlePositions[clickedCircle * 2 + 1];
339
+ if (clickedCircle === 0 || clickedCircle === 1) {
340
+ const position = clickedCircle === 0 ? "before" : "after";
341
+ emit("toggle", {
342
+ position,
343
+ coordinates: { x: cx, y: cy }
344
+ });
345
+ } else {
346
+ const fieldIndex = clickedCircle - 2;
347
+ emit("toggleField", {
348
+ index: fieldIndex,
349
+ coordinates: { x: cx, y: cy }
350
+ });
325
351
  }
326
352
  return true;
327
- },
328
- cursor: () => hoveredCircle.value >= 0 ? "pointer" : null,
329
- onClick: ({ mouseArtboard }) => {
330
- if (selection.uuids.value.length !== 1) {
331
- return false;
353
+ }
354
+ return false;
355
+ },
356
+ render: (ctx, gl, program) => {
357
+ if (!bufferInfoCache) {
358
+ bufferInfoCache = collector.createBufferInfo(gl);
359
+ }
360
+ if (!bufferInfoCache) {
361
+ return;
362
+ }
363
+ circleVisible.fill(0);
364
+ if (ctx.selectedUuids.length !== 1) {
365
+ return;
366
+ }
367
+ const uuid = ctx.selectedUuids[0];
368
+ if (!uuid) {
369
+ return;
370
+ }
371
+ const blockState = getBlockState(uuid);
372
+ if (blockState.canShowBeforeAfter) {
373
+ const blockRect = dom.getBlockRect(uuid);
374
+ if (!blockRect || blockRect.width === 0) {
375
+ return;
332
376
  }
333
- const clickedCircle = getCircleAtPoint(mouseArtboard.x, mouseArtboard.y);
334
- if (clickedCircle >= 0) {
335
- const cx = circlePositions[clickedCircle * 2];
336
- const cy = circlePositions[clickedCircle * 2 + 1];
337
- if (clickedCircle === 0 || clickedCircle === 1) {
338
- const position = clickedCircle === 0 ? "before" : "after";
339
- emit("toggle", {
340
- position,
341
- coordinates: { x: cx, y: cy }
342
- });
343
- } else {
344
- const fieldIndex = clickedCircle - 2;
345
- emit("toggleField", {
346
- index: fieldIndex,
347
- coordinates: { x: cx, y: cy }
348
- });
349
- }
350
- return true;
377
+ const orientation = getOrientationForUuid(uuid);
378
+ currentOrientation.value = orientation;
379
+ const BUTTON_SHIFT = 2 / ctx.artboardScale;
380
+ if (orientation === "horizontal") {
381
+ circlePositions[0] = blockRect.x - BUTTON_SHIFT;
382
+ circlePositions[1] = blockRect.y + blockRect.height / 2;
383
+ circleVisible[0] = 1;
384
+ circlePositions[2] = blockRect.x + blockRect.width + BUTTON_SHIFT;
385
+ circlePositions[3] = blockRect.y + blockRect.height / 2;
386
+ circleVisible[1] = 1;
387
+ } else {
388
+ circlePositions[0] = blockRect.x + blockRect.width / 2;
389
+ circlePositions[1] = blockRect.y - BUTTON_SHIFT;
390
+ circleVisible[0] = 1;
391
+ circlePositions[2] = blockRect.x + blockRect.width / 2;
392
+ circlePositions[3] = blockRect.y + blockRect.height + BUTTON_SHIFT;
393
+ circleVisible[1] = 1;
351
394
  }
352
- return false;
353
- },
354
- render: (ctx) => {
355
- if (selection.isChangingOptions.value) {
356
- return;
395
+ }
396
+ currentUuid.value = uuid;
397
+ currentBundleLabel.value = blockState.bundleLabel;
398
+ currentSingleAllowedBundleLabel.value = blockState.singleAllowedBundleLabel;
399
+ if (blockState.emptyFieldKeys.length > 0) {
400
+ emptyFieldTooltips.value = blockState.emptyFieldTooltips;
401
+ for (let i = 0; i < blockState.emptyFieldKeys.length && i < 8; i++) {
402
+ const fieldKey = blockState.emptyFieldKeys[i];
403
+ if (!fieldKey) {
404
+ continue;
405
+ }
406
+ const fieldRect = dom.getFieldRect(fieldKey);
407
+ if (!fieldRect) {
408
+ continue;
409
+ }
410
+ const circleIndex = i + 2;
411
+ circlePositions[circleIndex * 2] = fieldRect.x + fieldRect.width / 2;
412
+ circlePositions[circleIndex * 2 + 1] = fieldRect.y + fieldRect.height / 2;
413
+ circleVisible[circleIndex] = 1;
357
414
  }
358
- circleVisible.fill(0);
359
- if (ctx.selectedUuids.length !== 1) {
415
+ } else {
416
+ emptyFieldTooltips.value = [];
417
+ }
418
+ hoveredCircle.value = getCircleAtPoint(
419
+ ctx.mouseArtboard.x,
420
+ ctx.mouseArtboard.y
421
+ );
422
+ gl.useProgram(program.program);
423
+ setUniforms(program, {
424
+ u_circle_positions: circlePositions,
425
+ u_circle_visible: circleVisible,
426
+ u_color: toShaderColor(color.value),
427
+ u_color_hover: toShaderColor(colorHover.value),
428
+ u_color_field: toShaderColor(colorField.value),
429
+ u_color_field_hover: toShaderColor(colorFieldHover.value),
430
+ u_hovered_circle: hoveredCircle.value,
431
+ u_radius: BUTTON_RADIUS,
432
+ u_scale_transition: ctx.changeOptionsTransition
433
+ });
434
+ animation.setSharedUniforms(gl, program);
435
+ setBuffersAndAttributes(gl, program, bufferInfoCache);
436
+ drawBufferInfo(gl, bufferInfoCache, gl.TRIANGLES);
437
+ },
438
+ renderFallback: (ctx, ctx2d) => {
439
+ circleVisible.fill(0);
440
+ if (ctx.selectedUuids.length !== 1) {
441
+ return;
442
+ }
443
+ const uuid = ctx.selectedUuids[0];
444
+ if (!uuid) {
445
+ return;
446
+ }
447
+ const blockState = getBlockState(uuid);
448
+ if (blockState.canShowBeforeAfter) {
449
+ const blockRect = dom.getBlockRect(uuid);
450
+ if (!blockRect || blockRect.width === 0) {
360
451
  return;
361
452
  }
362
- const uuid = ctx.selectedUuids[0];
363
- if (!uuid) {
364
- return;
453
+ const orientation = getOrientationForUuid(uuid);
454
+ currentOrientation.value = orientation;
455
+ const BUTTON_SHIFT = 2 / ctx.artboardScale;
456
+ if (orientation === "horizontal") {
457
+ circlePositions[0] = blockRect.x - BUTTON_SHIFT;
458
+ circlePositions[1] = blockRect.y + blockRect.height / 2;
459
+ circleVisible[0] = 1;
460
+ circlePositions[2] = blockRect.x + blockRect.width + BUTTON_SHIFT;
461
+ circlePositions[3] = blockRect.y + blockRect.height / 2;
462
+ circleVisible[1] = 1;
463
+ } else {
464
+ circlePositions[0] = blockRect.x + blockRect.width / 2;
465
+ circlePositions[1] = blockRect.y - BUTTON_SHIFT;
466
+ circleVisible[0] = 1;
467
+ circlePositions[2] = blockRect.x + blockRect.width / 2;
468
+ circlePositions[3] = blockRect.y + blockRect.height + BUTTON_SHIFT;
469
+ circleVisible[1] = 1;
365
470
  }
366
- const blockState = getBlockState(uuid);
367
- if (blockState.canShowBeforeAfter) {
368
- const blockRect = dom.getBlockRect(uuid);
369
- if (!blockRect || blockRect.width === 0) {
370
- return;
471
+ }
472
+ currentUuid.value = uuid;
473
+ currentBundleLabel.value = blockState.bundleLabel;
474
+ currentSingleAllowedBundleLabel.value = blockState.singleAllowedBundleLabel;
475
+ if (blockState.emptyFieldKeys.length > 0) {
476
+ emptyFieldTooltips.value = blockState.emptyFieldTooltips;
477
+ for (let i = 0; i < blockState.emptyFieldKeys.length && i < 8; i++) {
478
+ const fieldKey = blockState.emptyFieldKeys[i];
479
+ if (!fieldKey) {
480
+ continue;
371
481
  }
372
- const orientation = getOrientationForUuid(uuid);
373
- currentOrientation.value = orientation;
374
- const BUTTON_SHIFT = 2 / ctx.artboardScale;
375
- if (orientation === "horizontal") {
376
- circlePositions[0] = blockRect.x - BUTTON_SHIFT;
377
- circlePositions[1] = blockRect.y + blockRect.height / 2;
378
- circleVisible[0] = 1;
379
- circlePositions[2] = blockRect.x + blockRect.width + BUTTON_SHIFT;
380
- circlePositions[3] = blockRect.y + blockRect.height / 2;
381
- circleVisible[1] = 1;
382
- } else {
383
- circlePositions[0] = blockRect.x + blockRect.width / 2;
384
- circlePositions[1] = blockRect.y - BUTTON_SHIFT;
385
- circleVisible[0] = 1;
386
- circlePositions[2] = blockRect.x + blockRect.width / 2;
387
- circlePositions[3] = blockRect.y + blockRect.height + BUTTON_SHIFT;
388
- circleVisible[1] = 1;
482
+ const fieldRect = dom.getFieldRect(fieldKey);
483
+ if (!fieldRect) {
484
+ continue;
389
485
  }
486
+ const circleIndex = i + 2;
487
+ circlePositions[circleIndex * 2] = fieldRect.x + fieldRect.width / 2;
488
+ circlePositions[circleIndex * 2 + 1] = fieldRect.y + fieldRect.height / 2;
489
+ circleVisible[circleIndex] = 1;
390
490
  }
391
- currentUuid.value = uuid;
392
- currentBundleLabel.value = blockState.bundleLabel;
393
- currentSingleAllowedBundleLabel.value = blockState.singleAllowedBundleLabel;
394
- if (blockState.emptyFieldKeys.length > 0) {
395
- emptyFieldTooltips.value = blockState.emptyFieldTooltips;
396
- for (let i = 0; i < blockState.emptyFieldKeys.length && i < 8; i++) {
397
- const fieldKey = blockState.emptyFieldKeys[i];
398
- if (!fieldKey) {
399
- continue;
400
- }
401
- const fieldRect = dom.getFieldRect(fieldKey);
402
- if (!fieldRect) {
403
- continue;
404
- }
405
- const circleIndex = i + 2;
406
- circlePositions[circleIndex * 2] = fieldRect.x + fieldRect.width / 2;
407
- circlePositions[circleIndex * 2 + 1] = fieldRect.y + fieldRect.height / 2;
408
- circleVisible[circleIndex] = 1;
409
- }
491
+ } else {
492
+ emptyFieldTooltips.value = [];
493
+ }
494
+ hoveredCircle.value = getCircleAtPoint(
495
+ ctx.mouseArtboard.x,
496
+ ctx.mouseArtboard.y
497
+ );
498
+ const rgbToCss = (rgb) => {
499
+ return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
500
+ };
501
+ const borderWidth = 2 * ctx.dpi;
502
+ const radius = BUTTON_RADIUS * ctx.dpi * ctx.changeOptionsTransition;
503
+ const innerRadius = radius - borderWidth;
504
+ for (let i = 0; i < MAX_CIRCLES; i++) {
505
+ if (circleVisible[i] <= 0) {
506
+ continue;
507
+ }
508
+ const artboardX = circlePositions[i * 2];
509
+ const artboardY = circlePositions[i * 2 + 1];
510
+ const viewportX = (artboardX * ctx.artboardScale + ctx.artboardOffset.x) * ctx.dpi;
511
+ const viewportY = (artboardY * ctx.artboardScale + ctx.artboardOffset.y) * ctx.dpi;
512
+ const isFieldButton = i >= 2;
513
+ const isHovered = hoveredCircle.value === i;
514
+ let fillColor;
515
+ if (isFieldButton) {
516
+ fillColor = isHovered ? colorFieldHover.value : colorField.value;
410
517
  } else {
411
- emptyFieldTooltips.value = [];
518
+ fillColor = isHovered ? colorHover.value : color.value;
412
519
  }
413
- hoveredCircle.value = getCircleAtPoint(
414
- ctx.mouseArtboard.x,
415
- ctx.mouseArtboard.y
520
+ ctx2d.fillStyle = rgbToCss(fillColor);
521
+ ctx2d.strokeStyle = "rgb(255, 255, 255)";
522
+ ctx2d.lineWidth = borderWidth;
523
+ ctx2d.beginPath();
524
+ ctx2d.arc(viewportX, viewportY, radius, 0, Math.PI * 2);
525
+ ctx2d.fill();
526
+ ctx2d.stroke();
527
+ const plusThickness = (ctx.dpi <= 0.5 ? 1.25 : 1.5) * ctx.dpi;
528
+ const plusLength = innerRadius * 0.5;
529
+ ctx2d.fillStyle = "rgb(255, 255, 255)";
530
+ ctx2d.fillRect(
531
+ viewportX - plusLength,
532
+ viewportY - plusThickness,
533
+ plusLength * 2,
534
+ plusThickness * 2
535
+ );
536
+ ctx2d.fillRect(
537
+ viewportX - plusThickness,
538
+ viewportY - plusLength,
539
+ plusThickness * 2,
540
+ plusLength * 2
416
541
  );
417
- gl.useProgram(programInfo.program);
418
- setUniforms(programInfo, {
419
- u_circle_positions: circlePositions,
420
- u_circle_visible: circleVisible,
421
- u_color: color.value,
422
- u_color_hover: colorHover.value,
423
- u_color_field: colorField.value,
424
- u_color_field_hover: colorFieldHover.value,
425
- u_hovered_circle: hoveredCircle.value,
426
- u_radius: BUTTON_RADIUS
427
- });
428
- animation.setSharedUniforms(gl, programInfo);
429
- setBuffersAndAttributes(gl, programInfo, bufferInfo);
430
- drawBufferInfo(gl, bufferInfo, gl.TRIANGLES);
431
542
  }
432
- });
433
- }
543
+ }
544
+ });
434
545
  </script>
435
546
 
436
547
  <script>
@@ -1,10 +1,12 @@
1
+ #version 300 es
2
+
1
3
  precision highp float;
2
4
 
3
5
  // [x, y] position.
4
- attribute vec2 a_position;
6
+ in vec2 a_position;
5
7
  // The [x,y,width, height] of the quad the vertex belongs to.
6
- attribute vec4 a_quad;
7
- attribute float a_rect_id;
8
+ in vec4 a_quad;
9
+ in float a_rect_id;
8
10
 
9
11
  // The global scaling applied to all quads.
10
12
  uniform float u_scale;
@@ -14,6 +16,8 @@ uniform float u_offset_x;
14
16
  // The amount of pixels to offset on the y axis.
15
17
  uniform float u_offset_y;
16
18
  uniform vec2 u_resolution;
19
+ // Scale transition for change options animation
20
+ uniform float u_scale_transition;
17
21
 
18
22
  // Circle positions (10 vec2s = 20 floats)
19
23
  uniform vec2 u_circle_positions[10];
@@ -25,12 +29,15 @@ uniform float u_hovered_circle;
25
29
  uniform float u_radius;
26
30
 
27
31
  // The transformed quad for the fragment shader.
28
- varying vec4 v_quad;
29
- varying vec2 v_circle_center;
30
- varying float v_visible;
31
- varying float v_is_hovered;
32
- varying float v_scale_fade;
33
- varying float v_rect_id;
32
+ out vec4 v_quad;
33
+ out vec2 v_circle_center;
34
+ out float v_visible;
35
+ out float v_is_hovered;
36
+ out float v_scale_fade;
37
+ out float v_rect_id;
38
+ out float v_radius;
39
+ out float v_inner_radius;
40
+ out float v_scale_factor;
34
41
 
35
42
  void main() {
36
43
  int rectId = int(a_rect_id);
@@ -49,13 +56,23 @@ void main() {
49
56
  v_scale_fade = clamp(v_scale_fade, 0.0, 1.0);
50
57
  }
51
58
 
59
+ // Combined scale factor for fragment shader
60
+ v_scale_factor = v_scale_fade * u_scale_transition;
61
+
52
62
  // Border width in pixels (must match fragment shader)
53
- float borderWidth = 4.0;
63
+ float borderWidth = 2.0;
54
64
 
55
65
  // Circle radius in artboard space - apply inverse scaling to keep constant size
56
- // Then multiply by fade factor
66
+ // Then multiply by fade factor and scale transition
57
67
  // Add border width to the radius so the border renders outside
58
- float radius = (u_radius + borderWidth) / u_scale * v_scale_fade;
68
+ float radius =
69
+ (u_radius + borderWidth) / u_scale * v_scale_fade * u_scale_transition;
70
+ float innerRadius =
71
+ (u_radius - borderWidth) / u_scale * v_scale_fade * u_scale_transition;
72
+
73
+ // Pass scaled radii to fragment shader (in viewport pixels)
74
+ v_radius = radius * u_scale * u_dpi;
75
+ v_inner_radius = innerRadius * u_scale * u_dpi;
59
76
 
60
77
  // Calculate quad bounds centered on circle position
61
78
  float left = circlePos.x - radius;
@@ -15,13 +15,20 @@
15
15
  </BlokkliTransition>
16
16
  </Teleport>
17
17
 
18
- <Renderer @toggle="onRendererToggle" @toggle-field="onRendererToggleField" />
18
+ <ErrorBoundary v-model="isLocked" label="Add Buttons">
19
+ <Renderer
20
+ v-if="!isLocked"
21
+ :key="animation.renderKey.value"
22
+ @toggle="onRendererToggle"
23
+ @toggle-field="onRendererToggleField"
24
+ />
25
+ </ErrorBoundary>
19
26
  </template>
20
27
 
21
28
  <script setup>
22
29
  import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
23
30
  import { computed, useBlokkli, ref, watch } from "#imports";
24
- import { BlokkliTransition } from "#blokkli/components";
31
+ import { BlokkliTransition, ErrorBoundary } from "#blokkli/components";
25
32
  import {
26
33
  getChildrenOrientation,
27
34
  getGapSize,
@@ -37,7 +44,8 @@ import { itemEntityType } from "#blokkli-build/config";
37
44
  const props = defineProps({
38
45
  items: { type: Array, required: true }
39
46
  });
40
- const { dom, state, eventBus, types, $t, blocks, fields } = useBlokkli();
47
+ const { dom, state, eventBus, types, $t, blocks, fields, animation } = useBlokkli();
48
+ const isLocked = ref(false);
41
49
  const shouldRender = computed(() => {
42
50
  return props.items.length === 1;
43
51
  });
@@ -322,7 +330,7 @@ function getPreceedingUuidBefore(uuid2, field) {
322
330
  if (!child) {
323
331
  continue;
324
332
  }
325
- const childUuid = child.dataset.uuid;
333
+ const childUuid = child.dataset.bkUuid;
326
334
  if (childUuid === uuid2) {
327
335
  return prevUuid;
328
336
  }
@@ -1,19 +1,27 @@
1
+ #version 300 es
2
+
1
3
  precision highp float;
2
4
 
3
- varying vec4 v_quad;
4
- varying vec3 v_color;
5
- varying vec4 v_rect_radius;
6
- varying float v_thickness;
7
- varying float v_rect_id;
8
- varying vec2 v_rect_size;
9
- varying vec2 v_rect_center;
10
- varying float v_rect_width;
11
-
12
- varying float v_transition;
13
- uniform float u_scale;
5
+ in vec4 v_quad;
6
+ in vec3 v_color;
7
+ in vec4 v_rect_radius;
8
+ in float v_thickness;
9
+ in float v_rect_id;
10
+ in vec2 v_rect_size;
11
+ in vec2 v_rect_center;
12
+ in float v_rect_width;
13
+
14
+ in float v_transition;
15
+ // Optimized varyings calculated in vertex shader
16
+ in float v_stripe_distance;
17
+ in vec4 v_base_scaled_radius;
18
+
19
+ out vec4 fragColor;
20
+
14
21
  uniform float u_dpi;
15
22
  uniform float u_time;
16
23
  uniform float u_is_transforming;
24
+ uniform float u_opacity;
17
25
  uniform vec2 u_resolution;
18
26
 
19
27
  #define PI 3.141592653589793
@@ -60,7 +68,7 @@ float exponentialIn(float t) {
60
68
  }
61
69
 
62
70
  float getStripePattern(vec2 quadRelativePos, float time) {
63
- float d = 300.0 * u_scale;
71
+ float d = v_stripe_distance;
64
72
 
65
73
  float t = mod(u_time + v_rect_id * 1000.0, 1200.0) / 1200.0;
66
74
 
@@ -87,7 +95,7 @@ vec4 drawBox(float thickness, vec4 bg, vec4 fill, vec4 border, float offset) {
87
95
 
88
96
  vec2 size = v_rect_size + borderThickness * 2.0 * v_transition;
89
97
  float u_edgeSoftness = 1.0 + v_transition;
90
- vec4 radius = v_rect_radius * u_scale + vec4(borderThickness);
98
+ vec4 radius = v_base_scaled_radius + vec4(borderThickness);
91
99
  vec4 u_cornerRadii = min(radius, min(size.x, size.y) / 2.0) * v_transition;
92
100
  float u_borderSoftness = 1.0 + v_transition;
93
101
 
@@ -134,5 +142,6 @@ void main() {
134
142
  );
135
143
 
136
144
  vec4 finalColor = mix(borderBottom, borderTop, borderTop.a);
137
- gl_FragColor = finalColor;
145
+ finalColor.a *= u_opacity;
146
+ fragColor = finalColor;
138
147
  }