@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
@@ -6,16 +6,16 @@
6
6
  import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
7
7
  import defineRenderer from "#blokkli/helpers/composables/defineRenderer";
8
8
  import { useBlokkli, computed, ref, watch } from "#imports";
9
- import { setBuffersAndAttributes, drawBufferInfo, setUniforms } from "twgl.js";
9
+ import {
10
+ setBuffersAndAttributes,
11
+ drawBufferInfo,
12
+ setUniforms
13
+ } from "twgl.js";
10
14
  import vs from "./vertex.glsl?raw";
11
15
  import fs from "./fragment.glsl?raw";
12
16
  import { RectangleBufferCollector } from "#blokkli/helpers/webgl";
13
17
  import { toShaderColor, isInsideRect } from "#blokkli/helpers";
14
- const props = defineProps({
15
- gl: { type: null, required: true }
16
- });
17
18
  const { animation, theme, dom, selection, state, ui, directive, blocks } = useBlokkli();
18
- const programInfo = animation.registerProgram("hover", props.gl, [vs, fs]);
19
19
  const MAX_RECTS = 11;
20
20
  function getDeepestUuid(uuids) {
21
21
  if (uuids.length === 0) {
@@ -48,22 +48,13 @@ let previousEditableFieldRect = null;
48
48
  const isHoveringEditableField = ref(false);
49
49
  const isHoveringSelectedBlock = ref(false);
50
50
  class HoverRectangleBufferCollector extends RectangleBufferCollector {
51
+ getBufferInfo(gl) {
52
+ if (!this.bufferInfo) {
53
+ this.bufferInfo = this.createBufferInfo(gl);
54
+ }
55
+ return this.bufferInfo;
56
+ }
51
57
  }
52
- const collector = new HoverRectangleBufferCollector(props.gl);
53
- for (let i = 0; i < MAX_RECTS; i++) {
54
- collector.addRectangle(
55
- {
56
- id: `hover-rect-${i}`,
57
- x: 0,
58
- y: 0,
59
- width: 100,
60
- height: 100,
61
- radius: [0, 0, 0, 0]
62
- },
63
- 0
64
- );
65
- }
66
- const bufferInfo = collector.createBufferInfo();
67
58
  function resetHoverState() {
68
59
  previousHoveredUuids = [];
69
60
  previousDeepestUuid = null;
@@ -201,11 +192,11 @@ function updateHoverState(mouseX, mouseY, offset, scale, artboardSize) {
201
192
  }
202
193
  const uniforms = computed(() => {
203
194
  return {
204
- u_color_mono: toShaderColor(theme.mono.value[300]),
205
- u_color_accent: toShaderColor(theme.accent.value[600]),
206
- u_color_teal: toShaderColor(theme.teal.value.normal),
207
- u_color_white: toShaderColor([255, 255, 255]),
208
- u_color_lime: toShaderColor(theme.lime.value.normal)
195
+ u_color_mono: theme.mono.value[300],
196
+ u_color_accent: theme.accent.value[600],
197
+ u_color_teal: theme.teal.value.normal,
198
+ u_color_white: [255, 255, 255],
199
+ u_color_lime: theme.lime.value.normal
209
200
  };
210
201
  });
211
202
  onBlokkliEvent("state:reloaded", () => {
@@ -214,9 +205,26 @@ onBlokkliEvent("state:reloaded", () => {
214
205
  onBlokkliEvent("ui:resized", () => {
215
206
  resetHoverState();
216
207
  });
217
- defineRenderer("hover-overlay", {
208
+ const { collector } = defineRenderer("hover-overlay", {
218
209
  zIndex: 200,
219
- enabled: () => !selection.isChangingOptions.value,
210
+ collector: () => {
211
+ const c = new HoverRectangleBufferCollector();
212
+ for (let i = 0; i < MAX_RECTS; i++) {
213
+ c.addRectangle(
214
+ {
215
+ id: `hover-rect-${i}`,
216
+ x: 0,
217
+ y: 0,
218
+ width: 100,
219
+ height: 100,
220
+ radius: [0, 0, 0, 0]
221
+ },
222
+ 0
223
+ );
224
+ }
225
+ return c;
226
+ },
227
+ program: () => ({ shaders: [vs, fs] }),
220
228
  cursor: () => {
221
229
  if (isHoveringEditableField.value && state.editMode.value !== "readonly") {
222
230
  return "text";
@@ -226,10 +234,8 @@ defineRenderer("hover-overlay", {
226
234
  }
227
235
  return null;
228
236
  },
229
- render: (ctx) => {
230
- if (!bufferInfo) {
231
- return;
232
- }
237
+ render: (ctx, gl, program) => {
238
+ const bufferInfo = collector.getBufferInfo(gl);
233
239
  if (!ui.openTooltip.value) {
234
240
  updateHoverState(
235
241
  ctx.mouseX,
@@ -239,17 +245,198 @@ defineRenderer("hover-overlay", {
239
245
  ctx.artboardSize
240
246
  );
241
247
  }
242
- props.gl.useProgram(programInfo.program);
243
- setUniforms(programInfo, uniforms.value);
244
- setUniforms(programInfo, {
248
+ gl.useProgram(program.program);
249
+ setUniforms(program, {
250
+ u_color_mono: toShaderColor(uniforms.value.u_color_mono),
251
+ u_color_accent: toShaderColor(uniforms.value.u_color_accent),
252
+ u_color_teal: toShaderColor(uniforms.value.u_color_teal),
253
+ u_color_white: toShaderColor(uniforms.value.u_color_white),
254
+ u_color_lime: toShaderColor(uniforms.value.u_color_lime),
245
255
  u_hover_positions: hoverState.positions,
246
256
  u_hover_radii: hoverState.radii,
247
257
  u_hover_types: hoverState.types,
248
- u_hover_visible: hoverState.visible
258
+ u_hover_visible: hoverState.visible,
259
+ u_opacity: ctx.changeOptionsTransition
249
260
  });
250
- animation.setSharedUniforms(props.gl, programInfo);
251
- setBuffersAndAttributes(props.gl, programInfo, bufferInfo);
252
- drawBufferInfo(props.gl, bufferInfo, props.gl.TRIANGLES);
261
+ animation.setSharedUniforms(gl, program);
262
+ setBuffersAndAttributes(gl, program, bufferInfo);
263
+ drawBufferInfo(gl, bufferInfo, gl.TRIANGLES);
264
+ },
265
+ renderFallback: (ctx, ctx2d) => {
266
+ if (!ui.openTooltip.value) {
267
+ updateHoverState(
268
+ ctx.mouseX,
269
+ ctx.mouseY,
270
+ ctx.artboardOffset,
271
+ ctx.artboardScale,
272
+ ctx.artboardSize
273
+ );
274
+ }
275
+ const rgbToCss = (rgb) => {
276
+ return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
277
+ };
278
+ const rgbaToCss = (rgb, alpha) => {
279
+ return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${alpha})`;
280
+ };
281
+ const colors = uniforms.value;
282
+ const borderThickness = 1.5 * ctx.dpi;
283
+ const dashLength = 7 * ctx.dpi;
284
+ ctx2d.globalAlpha = ctx.changeOptionsTransition;
285
+ for (let i = 0; i < MAX_RECTS; i++) {
286
+ if (hoverState.visible[i] !== 1) {
287
+ continue;
288
+ }
289
+ const x = hoverState.positions[i * 4 + 0];
290
+ const y = hoverState.positions[i * 4 + 1];
291
+ const width = hoverState.positions[i * 4 + 2];
292
+ const height = hoverState.positions[i * 4 + 3];
293
+ const radiusTopLeft = hoverState.radii[i * 4 + 0];
294
+ const radiusTopRight = hoverState.radii[i * 4 + 1];
295
+ const radiusBottomRight = hoverState.radii[i * 4 + 2];
296
+ const radiusBottomLeft = hoverState.radii[i * 4 + 3];
297
+ const viewportX = (x * ctx.artboardScale + ctx.artboardOffset.x) * ctx.dpi;
298
+ const viewportY = (y * ctx.artboardScale + ctx.artboardOffset.y) * ctx.dpi;
299
+ const viewportWidth = width * ctx.artboardScale * ctx.dpi;
300
+ const viewportHeight = height * ctx.artboardScale * ctx.dpi;
301
+ const type = hoverState.types[i];
302
+ if (type === 2) {
303
+ ctx2d.fillStyle = rgbaToCss(colors.u_color_teal, 0.2);
304
+ const maxRadius = Math.min(viewportWidth, viewportHeight) / 2;
305
+ const rtl = Math.min(
306
+ radiusTopLeft * ctx.artboardScale * ctx.dpi,
307
+ maxRadius
308
+ );
309
+ const rtr = Math.min(
310
+ radiusTopRight * ctx.artboardScale * ctx.dpi,
311
+ maxRadius
312
+ );
313
+ const rbr = Math.min(
314
+ radiusBottomRight * ctx.artboardScale * ctx.dpi,
315
+ maxRadius
316
+ );
317
+ const rbl = Math.min(
318
+ radiusBottomLeft * ctx.artboardScale * ctx.dpi,
319
+ maxRadius
320
+ );
321
+ ctx2d.beginPath();
322
+ ctx2d.moveTo(viewportX + rtl, viewportY);
323
+ ctx2d.lineTo(viewportX + viewportWidth - rtr, viewportY);
324
+ if (rtr > 0) {
325
+ ctx2d.arcTo(
326
+ viewportX + viewportWidth,
327
+ viewportY,
328
+ viewportX + viewportWidth,
329
+ viewportY + rtr,
330
+ rtr
331
+ );
332
+ }
333
+ ctx2d.lineTo(
334
+ viewportX + viewportWidth,
335
+ viewportY + viewportHeight - rbr
336
+ );
337
+ if (rbr > 0) {
338
+ ctx2d.arcTo(
339
+ viewportX + viewportWidth,
340
+ viewportY + viewportHeight,
341
+ viewportX + viewportWidth - rbr,
342
+ viewportY + viewportHeight,
343
+ rbr
344
+ );
345
+ }
346
+ ctx2d.lineTo(viewportX + rbl, viewportY + viewportHeight);
347
+ if (rbl > 0) {
348
+ ctx2d.arcTo(
349
+ viewportX,
350
+ viewportY + viewportHeight,
351
+ viewportX,
352
+ viewportY + viewportHeight - rbl,
353
+ rbl
354
+ );
355
+ }
356
+ ctx2d.lineTo(viewportX, viewportY + rtl);
357
+ if (rtl > 0) {
358
+ ctx2d.arcTo(viewportX, viewportY, viewportX + rtl, viewportY, rtl);
359
+ }
360
+ ctx2d.closePath();
361
+ ctx2d.fill();
362
+ ctx2d.strokeStyle = rgbToCss(colors.u_color_teal);
363
+ ctx2d.lineWidth = borderThickness;
364
+ ctx2d.setLineDash([]);
365
+ ctx2d.stroke();
366
+ } else {
367
+ let strokeColor = colors.u_color_mono;
368
+ if (type === 4) {
369
+ strokeColor = colors.u_color_lime;
370
+ } else if (type === 3) {
371
+ strokeColor = colors.u_color_white;
372
+ } else if (type === 1) {
373
+ strokeColor = colors.u_color_accent;
374
+ }
375
+ ctx2d.strokeStyle = rgbToCss(strokeColor);
376
+ ctx2d.lineWidth = borderThickness;
377
+ ctx2d.setLineDash([dashLength, dashLength]);
378
+ const maxRadius = Math.min(viewportWidth, viewportHeight) / 2;
379
+ const rtl = Math.min(
380
+ radiusTopLeft * ctx.artboardScale * ctx.dpi,
381
+ maxRadius
382
+ );
383
+ const rtr = Math.min(
384
+ radiusTopRight * ctx.artboardScale * ctx.dpi,
385
+ maxRadius
386
+ );
387
+ const rbr = Math.min(
388
+ radiusBottomRight * ctx.artboardScale * ctx.dpi,
389
+ maxRadius
390
+ );
391
+ const rbl = Math.min(
392
+ radiusBottomLeft * ctx.artboardScale * ctx.dpi,
393
+ maxRadius
394
+ );
395
+ ctx2d.beginPath();
396
+ ctx2d.moveTo(viewportX + rtl, viewportY);
397
+ ctx2d.lineTo(viewportX + viewportWidth - rtr, viewportY);
398
+ if (rtr > 0) {
399
+ ctx2d.arcTo(
400
+ viewportX + viewportWidth,
401
+ viewportY,
402
+ viewportX + viewportWidth,
403
+ viewportY + rtr,
404
+ rtr
405
+ );
406
+ }
407
+ ctx2d.lineTo(
408
+ viewportX + viewportWidth,
409
+ viewportY + viewportHeight - rbr
410
+ );
411
+ if (rbr > 0) {
412
+ ctx2d.arcTo(
413
+ viewportX + viewportWidth,
414
+ viewportY + viewportHeight,
415
+ viewportX + viewportWidth - rbr,
416
+ viewportY + viewportHeight,
417
+ rbr
418
+ );
419
+ }
420
+ ctx2d.lineTo(viewportX + rbl, viewportY + viewportHeight);
421
+ if (rbl > 0) {
422
+ ctx2d.arcTo(
423
+ viewportX,
424
+ viewportY + viewportHeight,
425
+ viewportX,
426
+ viewportY + viewportHeight - rbl,
427
+ rbl
428
+ );
429
+ }
430
+ ctx2d.lineTo(viewportX, viewportY + rtl);
431
+ if (rtl > 0) {
432
+ ctx2d.arcTo(viewportX, viewportY, viewportX + rtl, viewportY, rtl);
433
+ }
434
+ ctx2d.closePath();
435
+ ctx2d.stroke();
436
+ }
437
+ ctx2d.setLineDash([]);
438
+ }
439
+ ctx2d.globalAlpha = 1;
253
440
  }
254
441
  });
255
442
  </script>
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -1,12 +1,14 @@
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
- attribute float a_rect_type;
9
- attribute vec4 a_rect_radius;
8
+ in vec4 a_quad;
9
+ in float a_rect_id;
10
+ in float a_rect_type;
11
+ in vec4 a_rect_radius;
10
12
 
11
13
  // The global scaling applied to all quads.
12
14
  uniform float u_scale;
@@ -23,13 +25,27 @@ uniform vec4 u_hover_radii[11]; // topLeft, topRight, bottomRight, bottomLeft
23
25
  uniform float u_hover_types[11]; // 0=mono, 1=accent, 2=teal fill
24
26
  uniform float u_hover_visible[11]; // 0=hidden, 1=visible
25
27
 
28
+ // Color uniforms
29
+ uniform vec3 u_color_mono;
30
+ uniform vec3 u_color_accent;
31
+ uniform vec3 u_color_teal;
32
+ uniform vec3 u_color_white;
33
+ uniform vec3 u_color_lime;
34
+
26
35
  // The transformed quad for the fragment shader.
27
- varying vec4 v_quad;
28
- varying vec4 v_rect_radius;
29
- varying vec2 v_rect_size;
30
- varying vec2 v_rect_center;
31
- varying float v_rect_type;
32
- varying vec2 v_quad_artboard_pos;
36
+ out vec4 v_quad;
37
+ out vec4 v_rect_radius;
38
+ out vec2 v_rect_size;
39
+ out vec2 v_rect_center;
40
+ out float v_rect_type;
41
+ out vec2 v_quad_artboard_pos;
42
+ // Optimized varyings to reduce fragment shader calculations
43
+ out vec4 v_corner_radii;
44
+ out float v_border_thickness;
45
+ out vec2 v_half_size;
46
+ out vec3 v_color;
47
+ out float v_dash_cycle;
48
+ out vec2 v_rect_size_artboard;
33
49
 
34
50
  void main() {
35
51
  int rectIndex = int(a_rect_id);
@@ -114,4 +130,26 @@ void main() {
114
130
  v_rect_type = hoverType;
115
131
  // Pass the original artboard-space quad position for stable dash pattern
116
132
  v_quad_artboard_pos = vec2(hoverPos.x, hoverPos.y);
133
+
134
+ // Calculate optimized values once per vertex instead of per fragment
135
+ // Corner radii clamped to max radius
136
+ v_corner_radii = min(v_rect_radius, min(v_rect_size.x, v_rect_size.y) / 2.0);
137
+
138
+ v_border_thickness = 1.5 * u_dpi;
139
+ v_half_size = v_rect_size / 2.0;
140
+ v_dash_cycle = 14.0 - u_scale * 1.0;
141
+ v_rect_size_artboard = vec2(hoverPos.z, hoverPos.w);
142
+
143
+ // Select color based on type: 0 = mono, 1 = accent, 2 = teal, 3 = white (inverted), 4 = lime (library)
144
+ if (hoverType > 3.5) {
145
+ v_color = u_color_lime;
146
+ } else if (hoverType > 2.5) {
147
+ v_color = u_color_white;
148
+ } else if (hoverType > 1.5) {
149
+ v_color = u_color_teal;
150
+ } else if (hoverType > 0.5) {
151
+ v_color = u_color_accent;
152
+ } else {
153
+ v_color = u_color_mono;
154
+ }
117
155
  }
@@ -1,20 +1,23 @@
1
1
  <template>
2
- <Overlay v-if="isVisible && gl && animation.webglEnabled.value" :gl="gl" />
2
+ <ErrorBoundary v-model="isLocked" :label="$t('feature_hover_label', 'Hover')">
3
+ <Renderer v-if="isVisible" :key="animation.renderKey.value" />
4
+ </ErrorBoundary>
3
5
  </template>
4
6
 
5
7
  <script setup>
6
- import Overlay from "./Overlay/index.vue";
7
- import { computed, useBlokkli, defineBlokkliFeature } from "#imports";
8
+ import Renderer from "./Renderer/index.vue";
9
+ import { computed, useBlokkli, defineBlokkliFeature, ref } from "#imports";
10
+ import { ErrorBoundary } from "#blokkli/components";
8
11
  defineBlokkliFeature({
9
12
  id: "hover",
10
13
  icon: "selection",
11
14
  label: "Hover",
12
15
  description: "Renders a border around blocks that are currently being hovered."
13
16
  });
14
- const { selection, ui, animation, dom } = useBlokkli();
15
- const gl = animation.gl();
17
+ const { selection, ui, dom, animation, $t } = useBlokkli();
18
+ const isLocked = ref(false);
16
19
  const isVisible = computed(
17
- () => dom.isReady.value && !selection.isMultiSelecting.value && !selection.editableActive.value && !selection.isDragging.value && !ui.hasTransformOverlayOpen.value && !ui.hasDialogOpen.value && !ui.isAnimating.value
20
+ () => !isLocked.value && dom.isReady.value && !selection.isMultiSelecting.value && !selection.editableActive.value && !selection.isDragging.value && !ui.hasTransformOverlayOpen.value && !ui.hasDialogOpen.value && !ui.isAnimating.value
18
21
  );
19
22
  </script>
20
23
 
@@ -21,11 +21,7 @@
21
21
  :class="backgroundClass"
22
22
  >
23
23
  <ScaleToFit :width="previewWidth" :max-height="400">
24
- <BlokkliItem
25
- v-bind="item"
26
- parent-type="nested"
27
- class="bk-drop-element"
28
- />
24
+ <BlokkliItem v-bind="item" parent-type="nested" />
29
25
  </ScaleToFit>
30
26
  </div>
31
27
  </div>
@@ -88,16 +88,27 @@ const { adapter } = defineBlokkliFeature({
88
88
  });
89
89
  const { selection, state, types, $t, eventBus, definitions } = useBlokkli();
90
90
  const showReusableDialog = ref(false);
91
+ async function selectNewlyAdded(cb) {
92
+ const uuidsBefore = state.getAllUuids();
93
+ await cb();
94
+ const uuidsAfter = state.getAllUuids();
95
+ const newUuid = uuidsAfter.find((uuid) => !uuidsBefore.includes(uuid));
96
+ if (!newUuid) {
97
+ return;
98
+ }
99
+ eventBus.emit("select", newUuid);
100
+ }
91
101
  const onDetach = async () => {
92
102
  if (!adapter.detachReusableBlock || !selection.uuids.value.length) {
93
103
  return;
94
104
  }
95
- await state.mutateWithLoadingState(
96
- () => adapter.detachReusableBlock({
97
- uuids: selection.uuids.value
98
- })
105
+ await selectNewlyAdded(
106
+ () => state.mutateWithLoadingState(
107
+ () => adapter.detachReusableBlock({
108
+ uuids: selection.uuids.value
109
+ })
110
+ )
99
111
  );
100
- eventBus.emit("select:end");
101
112
  };
102
113
  const placedAction = ref(null);
103
114
  const onAddLibraryItem = async (uuid) => {
@@ -140,14 +151,15 @@ async function onMakeReusable(label) {
140
151
  if (!item) {
141
152
  return;
142
153
  }
143
- await state.mutateWithLoadingState(
144
- () => adapter.makeBlockReusable({
145
- label,
146
- uuid: item.uuid
147
- }),
148
- $t("libraryError", "Failed to add block to library.")
154
+ await selectNewlyAdded(
155
+ () => state.mutateWithLoadingState(
156
+ () => adapter.makeBlockReusable({
157
+ label,
158
+ uuid: item.uuid
159
+ }),
160
+ $t("libraryError", "Failed to add block to library.")
161
+ )
149
162
  );
150
- eventBus.emit("select:end");
151
163
  }
152
164
  const isSupportedOnEntity = computed(
153
165
  () => types.generallyAvailableBundles.find((v) => v.id === BUNDLE_FROM_LIBRARY)
@@ -3,7 +3,7 @@
3
3
  :key="mediaId"
4
4
  class="bk-media-library-items-item"
5
5
  :class="{ 'bk-is-selected': isSelected }"
6
- :data-sortli-id="'media_library_' + mediaId"
6
+ :data-sortli-id="mediaId"
7
7
  data-element-type="media_library"
8
8
  :data-item-bundle="targetBundles[0]"
9
9
  :data-media-id="mediaId"
@@ -45,20 +45,17 @@
45
45
  <div
46
46
  ref="listEl"
47
47
  class="bk-media-library-items bk-scrollbar-light"
48
- :class="[{ 'bk-is-sortli': isSortli }, 'bk-is-' + listView]"
48
+ :class="'bk-is-' + listView"
49
49
  >
50
- <Sortli v-if="isSortli" no-transition :get-drag-items="getDragItems">
50
+ <Sortli no-transition :get-drag-items="getDragItems" :build-item>
51
51
  <Item
52
52
  v-for="item in items"
53
53
  :key="item.mediaId"
54
54
  v-bind="item"
55
55
  v-model="selected"
56
+ :class="'bk-is-' + listView"
56
57
  />
57
58
  </Sortli>
58
-
59
- <div v-else>
60
- <Item v-for="item in items" :key="item.mediaId" v-bind="item" />
61
- </div>
62
59
  </div>
63
60
 
64
61
  <div v-if="selected.length" class="bk-media-library-cancel">
@@ -82,10 +79,9 @@ import {
82
79
  } from "#imports";
83
80
  import { Sortli, Icon, Pagination, FormToggle } from "#blokkli/components";
84
81
  import Item from "./Item.vue";
85
- import { buildDraggableItem, falsy } from "#blokkli/helpers";
82
+ import { falsy } from "#blokkli/helpers";
86
83
  import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
87
84
  defineProps({
88
- isSortli: { type: Boolean, required: false },
89
85
  modelValue: { type: String, required: false }
90
86
  });
91
87
  const { adapter, storage, $t, element } = useBlokkli();
@@ -102,17 +98,17 @@ function getDragItems(activeItem) {
102
98
  const items2 = selected.value.map((id) => {
103
99
  const el = element.query(
104
100
  listElement,
105
- `[data-sortli-id="media_library_${id}"]`,
101
+ `[data-sortli-id="${id}"]`,
106
102
  "Find media library drag item."
107
103
  );
108
104
  if (!(el instanceof HTMLElement)) {
109
105
  return null;
110
106
  }
111
- const item = buildDraggableItem(el);
112
- if (item?.itemType === "media_library") {
113
- return item;
107
+ const item = buildItem(el);
108
+ if (!item) {
109
+ return null;
114
110
  }
115
- return null;
111
+ return item;
116
112
  }).filter(falsy);
117
113
  if (!activeId) {
118
114
  return items2;
@@ -167,6 +163,23 @@ const perPage = computed(() => data.value?.perPage || 0);
167
163
  const totalPages = computed(() => {
168
164
  return Math.ceil(total.value / perPage.value);
169
165
  });
166
+ function buildItem(element2) {
167
+ const id = element2.dataset.sortliId;
168
+ if (!id) {
169
+ return null;
170
+ }
171
+ const item = items.value.find((v) => v.mediaId === id);
172
+ if (!item) {
173
+ return null;
174
+ }
175
+ return {
176
+ itemType: "media_library",
177
+ mediaId: item.mediaId,
178
+ mediaBundle: item.mediaBundle ?? "",
179
+ itemBundle: item.targetBundles[0] ?? "",
180
+ element: () => element2
181
+ };
182
+ }
170
183
  onBlokkliEvent("item:dropped", function() {
171
184
  selected.value = [];
172
185
  });
@@ -1,5 +1,4 @@
1
1
  type __VLS_Props = {
2
- isSortli?: boolean;
3
2
  modelValue?: string;
4
3
  };
5
4
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -14,21 +14,11 @@
14
14
  >
15
15
  <Library is-sortli />
16
16
  </PluginSidebar>
17
-
18
- <PluginDroppableEdit
19
- id="media-replace"
20
- title="Replace media"
21
- icon="image"
22
- entity-type="media"
23
- @save="onDroppableEditSave"
24
- >
25
- <Library v-model="selected" />
26
- </PluginDroppableEdit>
27
17
  </template>
28
18
 
29
19
  <script setup>
30
- import { useBlokkli, defineBlokkliFeature, ref } from "#imports";
31
- import { PluginSidebar, PluginDroppableEdit } from "#blokkli/plugins";
20
+ import { useBlokkli, defineBlokkliFeature } from "#imports";
21
+ import { PluginSidebar } from "#blokkli/plugins";
32
22
  import Library from "./Library/index.vue";
33
23
  import defineDropAreas from "#blokkli/helpers/composables/defineDropAreas";
34
24
  import { falsy } from "#blokkli/helpers";
@@ -40,45 +30,11 @@ defineBlokkliFeature({
40
30
  description: "Implements a media library to easily drag and drop media like images or videos.",
41
31
  requiredAdapterMethods: ["mediaLibraryGetResults", "mediaLibraryAddBlock"]
42
32
  });
43
- const { $t, adapter, state, runtimeConfig, types, directive } = useBlokkli();
44
- const selected = ref("");
33
+ const { $t, adapter, state, types, directive } = useBlokkli();
45
34
  const ERROR_MESSAGE = $t(
46
35
  "mediaLibraryReplaceFailed",
47
36
  "Failed to replace media."
48
37
  );
49
- const onDroppableEditSave = async (e) => {
50
- if (!selected.value) {
51
- return;
52
- }
53
- if ("itemType" in e.host && adapter.mediaLibraryReplaceMedia) {
54
- const host = e.host;
55
- await state.mutateWithLoadingState(
56
- () => adapter.mediaLibraryReplaceMedia({
57
- host: {
58
- uuid: host.block.uuid,
59
- type: runtimeConfig.itemEntityType,
60
- fieldName: e.fieldName
61
- },
62
- mediaId: selected.value
63
- }),
64
- ERROR_MESSAGE
65
- );
66
- } else if ("type" in e.host && adapter.mediaLibraryReplaceEntityMedia) {
67
- const host = e.host;
68
- const type = host.type;
69
- await state.mutateWithLoadingState(
70
- () => adapter.mediaLibraryReplaceEntityMedia({
71
- host: {
72
- uuid: host.uuid,
73
- type,
74
- fieldName: e.fieldName
75
- },
76
- mediaId: selected.value
77
- }),
78
- ERROR_MESSAGE
79
- );
80
- }
81
- };
82
38
  defineDropAreas((dragItems) => {
83
39
  if (!adapter.mediaLibraryReplaceMedia) {
84
40
  return;