@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
@@ -9,6 +9,13 @@ in vec3 v_color_default;
9
9
  in vec3 v_color_active;
10
10
  in float v_rect_id;
11
11
 
12
+ // Optimized inputs - values computed once per vertex instead of per pixel
13
+ in vec2 v_size;
14
+ in vec2 v_location;
15
+ in float v_thickness;
16
+ in float v_edge_softness;
17
+ in float v_radius;
18
+
12
19
  out vec4 fragColor;
13
20
 
14
21
  uniform float u_time;
@@ -45,32 +52,11 @@ void main() {
45
52
  return;
46
53
  }
47
54
 
48
- // Selectable blocks.
49
- float radius_base = 2.0 * u_scale;
50
- float thickness = max(min(1.0 * u_scale, 3.0), 0.5);
51
- float inset = max(min(2.0 * u_scale, 1.0), 2.0) * thickness;
52
-
53
- float u_rect_x = v_quad.x + inset;
54
- float u_rect_y = v_quad.y + inset;
55
- float u_rectWidth = v_quad.z - 2.0 * inset;
56
- float u_rectHeight = v_quad.w - 2.0 * inset;
57
-
58
- vec2 size = vec2(u_rectWidth, u_rectHeight);
59
-
60
- float x = u_rect_x;
61
- float y = u_rect_y;
62
- vec2 offsetPosition = vec2(x + size.x / 2.0, y + size.y / 2.0);
63
-
64
- vec2 location = vec2(offsetPosition);
65
-
66
- float edgeSoftness = 1.0 * u_dpi;
67
- float radius =
68
- min(radius_base * u_dpi, min(size.x, size.y) / 2.0) + thickness * 2.0;
69
-
55
+ // Selectable blocks - using pre-computed values from vertex shader
70
56
  float distance = roundedBoxSDF(
71
- location - gl_FragCoord.xy,
72
- size / 2.0,
73
- radius
57
+ v_location - gl_FragCoord.xy,
58
+ v_size / 2.0,
59
+ v_radius
74
60
  );
75
61
 
76
62
  bool is_intersecting = v_intersecting >= 0.5;
@@ -79,7 +65,8 @@ void main() {
79
65
  float mixedDistance = is_intersecting ? distance : abs(distance);
80
66
 
81
67
  float smoothedAlpha =
82
- 1.0 - smoothstep(-edgeSoftness, edgeSoftness, mixedDistance - thickness);
68
+ 1.0 -
69
+ smoothstep(-v_edge_softness, v_edge_softness, mixedDistance - v_thickness);
83
70
 
84
71
  fragColor = vec4(
85
72
  color,
@@ -22,13 +22,15 @@ const logger = useDebugLogger();
22
22
  const props = defineProps({
23
23
  startX: { type: Number, required: true },
24
24
  startY: { type: Number, required: true },
25
- isPressingControl: { type: Boolean, required: true },
26
- gl: { type: null, required: true }
25
+ isPressingControl: { type: Boolean, required: true }
27
26
  });
28
27
  const startTimestamp = Date.now();
29
28
  defineEmits(["select"]);
30
29
  class MultiSelectRectangleBufferCollector extends RectangleBufferCollector {
31
- getBufferInfo(offset, scale) {
30
+ getBufferInfo(gl, offset, scale) {
31
+ if (!offset || !scale) {
32
+ return { info: this.bufferInfo, hasChanged: false };
33
+ }
32
34
  const visibleBlocks = dom.getVisibleBlocks();
33
35
  const lengthBefore = this.positions.length;
34
36
  for (let i = 0; i < visibleBlocks.length; i++) {
@@ -63,8 +65,8 @@ class MultiSelectRectangleBufferCollector extends RectangleBufferCollector {
63
65
  );
64
66
  }
65
67
  const hasChanged = lengthBefore !== this.positions.length;
66
- if (hasChanged) {
67
- this.bufferInfo = this.createBufferInfo();
68
+ if (hasChanged && gl) {
69
+ this.bufferInfo = this.createBufferInfo(gl);
68
70
  }
69
71
  return { info: this.bufferInfo, hasChanged };
70
72
  }
@@ -95,68 +97,11 @@ class MultiSelectRectangleBufferCollector extends RectangleBufferCollector {
95
97
  return false;
96
98
  }
97
99
  }
98
- const collector = new MultiSelectRectangleBufferCollector(props.gl);
99
- const thick = 300;
100
- collector.addRectangle(
101
- {
102
- width: 1e3,
103
- height: thick,
104
- x: 100,
105
- y: 100,
106
- id: "select-rect-top",
107
- isNested: false,
108
- radius: [0, 0, 0, 0]
109
- },
110
- 0
111
- );
112
- collector.addRectangle(
113
- {
114
- width: thick,
115
- height: 1e3,
116
- x: 1e3 + thick,
117
- y: thick,
118
- id: "select-rect-right",
119
- isNested: false,
120
- radius: [0, 0, 0, 0]
121
- },
122
- 0
123
- );
124
- collector.addRectangle(
125
- {
126
- width: 1e3,
127
- height: thick,
128
- x: 100 + thick,
129
- y: 1e3 + thick,
130
- id: "select-rect-bottom",
131
- isNested: false,
132
- radius: [0, 0, 0, 0]
133
- },
134
- 0
135
- );
136
- collector.addRectangle(
137
- {
138
- width: thick,
139
- height: 1e3,
140
- x: 100,
141
- y: 100 + thick,
142
- id: "select-rect-left",
143
- isNested: false,
144
- radius: [0, 0, 0, 0]
145
- },
146
- 0
147
- );
148
100
  const artboardOffsetStart = { ...ui.artboardOffset.value };
149
101
  const artboardScaleStart = ui.artboardScale.value;
150
- const programInfo = animation.registerProgram(
151
- "multi_select_overlay",
152
- props.gl,
153
- [vs, fs]
154
- );
155
102
  const uniforms = {
156
- u_color_field_active: toShaderColor(theme.accent.value[700]),
157
- u_color_field_default: toShaderColor(theme.mono.value[400]),
158
- u_color_area_active: toShaderColor(theme.teal.value.normal),
159
- u_color_area_default: toShaderColor(theme.teal.value.normal)
103
+ u_color_field_active: theme.accent.value[700],
104
+ u_color_field_default: theme.mono.value[400]
160
105
  };
161
106
  let mouseX = 0;
162
107
  let mouseY = 0;
@@ -181,11 +126,65 @@ function getSelectRect(offset, scale) {
181
126
  };
182
127
  return { shader, check };
183
128
  }
184
- defineRenderer("multiselect-overlay", {
129
+ const { collector } = defineRenderer("multiselect-overlay", {
185
130
  zIndex: 450,
186
131
  only: true,
132
+ collector: () => {
133
+ const c = new MultiSelectRectangleBufferCollector();
134
+ const thick = 300;
135
+ c.addRectangle(
136
+ {
137
+ width: 1e3,
138
+ height: thick,
139
+ x: 100,
140
+ y: 100,
141
+ id: "select-rect-top",
142
+ isNested: false,
143
+ radius: [0, 0, 0, 0]
144
+ },
145
+ 0
146
+ );
147
+ c.addRectangle(
148
+ {
149
+ width: thick,
150
+ height: 1e3,
151
+ x: 1e3 + thick,
152
+ y: thick,
153
+ id: "select-rect-right",
154
+ isNested: false,
155
+ radius: [0, 0, 0, 0]
156
+ },
157
+ 0
158
+ );
159
+ c.addRectangle(
160
+ {
161
+ width: 1e3,
162
+ height: thick,
163
+ x: 100 + thick,
164
+ y: 1e3 + thick,
165
+ id: "select-rect-bottom",
166
+ isNested: false,
167
+ radius: [0, 0, 0, 0]
168
+ },
169
+ 0
170
+ );
171
+ c.addRectangle(
172
+ {
173
+ width: thick,
174
+ height: 1e3,
175
+ x: 100,
176
+ y: 100 + thick,
177
+ id: "select-rect-left",
178
+ isNested: false,
179
+ radius: [0, 0, 0, 0]
180
+ },
181
+ 0
182
+ );
183
+ return c;
184
+ },
185
+ program: () => ({ shaders: [vs, fs] }),
187
186
  cursor: () => "crosshair",
188
- render: (ctx) => {
187
+ render: (ctx, gl, program) => {
189
188
  mouseX = ctx.mouseX;
190
189
  mouseY = ctx.mouseY;
191
190
  const { shader, check } = getSelectRect(
@@ -194,16 +193,20 @@ defineRenderer("multiselect-overlay", {
194
193
  );
195
194
  const { nested } = collector.getSelectedUuids(check);
196
195
  const shouldSelectAll = props.isPressingControl || !nested.length;
197
- ctx.gl.useProgram(programInfo.program);
196
+ gl.useProgram(program.program);
198
197
  const time = (Date.now() - startTimestamp) / 1e3;
199
- setUniforms(programInfo, uniforms);
200
- setUniforms(programInfo, {
198
+ setUniforms(program, {
199
+ u_color_field_active: toShaderColor(uniforms.u_color_field_active),
200
+ u_color_field_default: toShaderColor(uniforms.u_color_field_default)
201
+ });
202
+ setUniforms(program, {
201
203
  u_select_all: shouldSelectAll ? 1 : 0,
202
204
  u_select_rect: [shader.x, shader.y, shader.width, shader.height],
203
205
  u_time: time
204
206
  });
205
- animation.setSharedUniforms(ctx.gl, programInfo);
207
+ animation.setSharedUniforms(gl, program);
206
208
  const { info, hasChanged } = collector.getBufferInfo(
209
+ gl,
207
210
  ctx.artboardOffset,
208
211
  ctx.artboardScale
209
212
  );
@@ -211,9 +214,64 @@ defineRenderer("multiselect-overlay", {
211
214
  return;
212
215
  }
213
216
  if (hasChanged) {
214
- setBuffersAndAttributes(ctx.gl, programInfo, info);
217
+ setBuffersAndAttributes(gl, program, info);
218
+ }
219
+ drawBufferInfo(gl, info, gl.TRIANGLES);
220
+ },
221
+ renderFallback: (ctx, ctx2d) => {
222
+ mouseX = ctx.mouseX;
223
+ mouseY = ctx.mouseY;
224
+ const { shader, check } = getSelectRect(
225
+ ctx.artboardOffset,
226
+ ctx.artboardScale
227
+ );
228
+ const { nested } = collector.getSelectedUuids(check);
229
+ const shouldSelectAll = props.isPressingControl || !nested.length;
230
+ collector.getBufferInfo(void 0, ctx.artboardOffset, ctx.artboardScale);
231
+ const rects = Object.values(collector.rects);
232
+ const colorFieldActive = `rgba(${uniforms.u_color_field_active[0]}, ${uniforms.u_color_field_active[1]}, ${uniforms.u_color_field_active[2]}, 0.3)`;
233
+ for (let i = 0; i < rects.length; i++) {
234
+ const rect = rects[i];
235
+ if (rect.id.startsWith("select-rect-")) {
236
+ continue;
237
+ }
238
+ if (!intersects(rect, check)) {
239
+ continue;
240
+ }
241
+ if (!rect.isNested && !shouldSelectAll) {
242
+ continue;
243
+ }
244
+ ctx2d.fillStyle = colorFieldActive;
245
+ ctx2d.fillRect(
246
+ (rect.x * ctx.artboardScale + ctx.artboardOffset.x) * ctx.dpi,
247
+ (rect.y * ctx.artboardScale + ctx.artboardOffset.y) * ctx.dpi,
248
+ rect.width * ctx.artboardScale * ctx.dpi,
249
+ rect.height * ctx.artboardScale * ctx.dpi
250
+ );
215
251
  }
216
- drawBufferInfo(ctx.gl, info, ctx.gl.TRIANGLES);
252
+ const time = (Date.now() - startTimestamp) / 1e3;
253
+ const speed = 100 * ctx.dpi;
254
+ const dashLength = 8 * ctx.dpi;
255
+ const phase = time * speed * -1;
256
+ ctx2d.lineWidth = 2 * ctx.dpi;
257
+ ctx2d.setLineDash([dashLength, dashLength]);
258
+ ctx2d.strokeStyle = "rgba(255, 255, 255, 0.8)";
259
+ ctx2d.lineDashOffset = phase % (dashLength * 2);
260
+ ctx2d.strokeRect(
261
+ shader.x * ctx.dpi,
262
+ shader.y * ctx.dpi,
263
+ shader.width * ctx.dpi,
264
+ shader.height * ctx.dpi
265
+ );
266
+ ctx2d.strokeStyle = "rgba(0, 0, 0, 0.8)";
267
+ ctx2d.lineDashOffset = (phase + dashLength) % (dashLength * 2);
268
+ ctx2d.strokeRect(
269
+ shader.x * ctx.dpi,
270
+ shader.y * ctx.dpi,
271
+ shader.width * ctx.dpi,
272
+ shader.height * ctx.dpi
273
+ );
274
+ ctx2d.setLineDash([]);
217
275
  }
218
276
  });
219
277
  function getUuidsToSelect() {
@@ -2,7 +2,6 @@ type __VLS_Props = {
2
2
  startX: number;
3
3
  startY: number;
4
4
  isPressingControl: boolean;
5
- gl: WebGLRenderingContext;
6
5
  };
7
6
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
8
7
  select: (uuids: string[]) => any;
@@ -17,8 +17,6 @@ uniform float u_select_all;
17
17
  uniform vec2 u_resolution;
18
18
  uniform vec3 u_color_field_default;
19
19
  uniform vec3 u_color_field_active;
20
- uniform vec3 u_color_area_default;
21
- uniform vec3 u_color_area_active;
22
20
  uniform vec4 u_select_rect;
23
21
 
24
22
  out vec4 v_quad;
@@ -28,6 +26,13 @@ out vec3 v_color_default;
28
26
  out vec3 v_color_active;
29
27
  out float v_rect_id;
30
28
 
29
+ // Optimized outputs - values computed once per vertex instead of per pixel
30
+ out vec2 v_size;
31
+ out vec2 v_location;
32
+ out float v_thickness;
33
+ out float v_edge_softness;
34
+ out float v_radius;
35
+
31
36
  bool isIntersecting(vec4 a, vec4 b) {
32
37
  return a.x < b.x + b.z &&
33
38
  a.x + a.z > b.x &&
@@ -179,4 +184,24 @@ void main() {
179
184
 
180
185
  v_color_default = u_color_field_default;
181
186
  v_color_active = u_color_field_active;
187
+
188
+ // Compute values that are constant per quad (optimization)
189
+ float radius_base = 2.0 * u_scale;
190
+ v_thickness = max(min(1.0 * u_scale, 3.0), 0.5);
191
+ float inset = max(min(2.0 * u_scale, 1.0), 2.0) * v_thickness;
192
+
193
+ float u_rect_x = transformed_quad.x + inset;
194
+ float u_rect_y = transformed_quad.y + inset;
195
+ float u_rectWidth = transformed_quad.z - 2.0 * inset;
196
+ float u_rectHeight = transformed_quad.w - 2.0 * inset;
197
+
198
+ v_size = vec2(u_rectWidth, u_rectHeight);
199
+
200
+ float x = u_rect_x;
201
+ float y = u_rect_y;
202
+ v_location = vec2(x + v_size.x / 2.0, y + v_size.y / 2.0);
203
+
204
+ v_edge_softness = 1.0 * u_dpi;
205
+ v_radius =
206
+ min(radius_base * u_dpi, min(v_size.x, v_size.y) / 2.0) + v_thickness * 2.0;
182
207
  }
@@ -1,18 +1,25 @@
1
1
  <template>
2
- <Overlay
3
- v-if="shouldRender && gl"
4
- :start-x="downX"
5
- :start-y="downY"
6
- :is-pressing-control="keyboard.isPressingControl.value"
7
- :gl="gl"
8
- @select="onSelect"
9
- />
2
+ <ErrorBoundary
3
+ v-model="isLocked"
4
+ :label="$t('feature_multi-select_label', 'Multiselect')"
5
+ @error="onError"
6
+ >
7
+ <Renderer
8
+ v-if="shouldRender"
9
+ :key="animation.renderKey.value"
10
+ :start-x="downX"
11
+ :start-y="downY"
12
+ :is-pressing-control="keyboard.isPressingControl.value"
13
+ @select="onSelect"
14
+ />
15
+ </ErrorBoundary>
10
16
  </template>
11
17
 
12
18
  <script setup>
13
19
  import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
14
20
  import { ref, useBlokkli, defineBlokkliFeature, computed } from "#imports";
15
- import Overlay from "./Overlay/index.vue";
21
+ import { ErrorBoundary } from "#blokkli/components";
22
+ import Renderer from "./Renderer/index.vue";
16
23
  defineBlokkliFeature({
17
24
  id: "multi-select",
18
25
  label: "Multiselect",
@@ -20,12 +27,18 @@ defineBlokkliFeature({
20
27
  description: "Implements support for selecting multiple blocks using a select rectangle.",
21
28
  viewports: ["desktop"]
22
29
  });
23
- const { keyboard, eventBus, selection, animation } = useBlokkli();
24
- const gl = animation.gl();
25
- const enabled = computed(() => !selection.editableActive.value && gl);
30
+ const { keyboard, eventBus, selection, animation, $t } = useBlokkli();
31
+ const isLocked = ref(false);
32
+ const enabled = computed(
33
+ () => !selection.editableActive.value && !isLocked.value
34
+ );
26
35
  const shouldRender = ref(false);
27
36
  const downX = ref(0);
28
37
  const downY = ref(0);
38
+ function onError() {
39
+ eventBus.emit("select:end");
40
+ shouldRender.value = false;
41
+ }
29
42
  const onSelect = (uuids) => {
30
43
  shouldRender.value = false;
31
44
  eventBus.emit("select:end", uuids);
@@ -1,12 +1,12 @@
1
1
  <template>
2
2
  <Teleport to="#bk-banner-list">
3
- <Renderer v-if="shouldRender" @submit="takeOwnership" />
3
+ <OwnershipBanner v-if="shouldRender" @submit="takeOwnership" />
4
4
  </Teleport>
5
5
  </template>
6
6
 
7
7
  <script setup>
8
8
  import { useBlokkli, defineBlokkliFeature, computed } from "#imports";
9
- import Renderer from "./Renderer.vue";
9
+ import OwnershipBanner from "./Banner/index.vue";
10
10
  const { adapter } = defineBlokkliFeature({
11
11
  id: "ownership",
12
12
  icon: "user",
@@ -37,7 +37,7 @@
37
37
  </div>
38
38
  <Icon name="caret" />
39
39
  </button>
40
- <div v-show="dropdownOpen" class="bk-dropdown-content">
40
+ <div v-if="dropdownOpen" class="bk-dropdown-content">
41
41
  <label v-for="option in viewportOptions" :key="option.id">
42
42
  <input
43
43
  v-model="selectedViewportId"
@@ -4,16 +4,14 @@
4
4
  <Icon name="spinner" />
5
5
  </div>
6
6
  <div :class="{ 'bk-search-is-loading': isLoading }">
7
- <Sortli no-transition>
7
+ <Sortli :build-item>
8
8
  <button
9
9
  v-for="(item, i) in items"
10
10
  :key="tab + item.id"
11
11
  ref="listItems"
12
- data-element-type="search_content"
13
12
  class="bk bk-search-item bk-is-content"
14
13
  :class="{ 'bk-is-active': i === index }"
15
- :data-sortli-id="'search_' + tab + i"
16
- :data-search-item="JSON.stringify(item)"
14
+ :data-sortli-id="i"
17
15
  @mouseenter="index = i"
18
16
  >
19
17
  <div
@@ -56,7 +54,7 @@
56
54
  <script setup>
57
55
  import { watch, ref, useBlokkli, onMounted } from "#imports";
58
56
  import { ItemIcon, Icon, Sortli } from "#blokkli/components";
59
- import { buildDraggableItem, modulo } from "#blokkli/helpers";
57
+ import { modulo } from "#blokkli/helpers";
60
58
  const listItems = ref([]);
61
59
  const props = defineProps({
62
60
  visible: { type: Boolean, required: true },
@@ -101,6 +99,25 @@ const goToFirst = () => setIndex(0);
101
99
  const select = () => clickItem();
102
100
  const isActive = () => props.visible;
103
101
  defineExpose({ prev, next, select, isActive, goToFirst });
102
+ function buildItem(element) {
103
+ if (!element.dataset.sortliId) {
104
+ return;
105
+ }
106
+ const index2 = Number.parseInt(element.dataset.sortliId);
107
+ if (Number.isNaN(index2) || !Number.isFinite(index2)) {
108
+ return;
109
+ }
110
+ const item = items.value[index2];
111
+ if (!item) {
112
+ return;
113
+ }
114
+ return {
115
+ itemType: "search_content",
116
+ element: () => element,
117
+ itemBundle: item.targetBundles[0] ?? "",
118
+ searchItem: item
119
+ };
120
+ }
104
121
  const setIndex = (newIndex) => {
105
122
  index.value = modulo(newIndex, items.value.length);
106
123
  scrollItemIntoView();
@@ -110,7 +127,7 @@ const clickItem = () => {
110
127
  if (!element) {
111
128
  return;
112
129
  }
113
- const item = buildDraggableItem(element);
130
+ const item = buildItem(element);
114
131
  if (!item) {
115
132
  return;
116
133
  }
@@ -6,12 +6,12 @@ type __VLS_Props = {
6
6
  label: string;
7
7
  };
8
8
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
- action: (id: string) => void;
10
9
  select: (id: string) => void;
10
+ action: (id: string) => void;
11
11
  close: () => void;
12
12
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
13
- onAction?: ((id: string) => any) | undefined;
14
13
  onSelect?: ((id: string) => any) | undefined;
15
14
  onClose?: (() => any) | undefined;
15
+ onAction?: ((id: string) => any) | undefined;
16
16
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
17
  export default _default;
@@ -1,11 +1,18 @@
1
+ #version 300 es
2
+
1
3
  precision highp float;
2
4
 
3
- varying vec4 v_quad;
4
- varying vec2 v_circle_center;
5
- varying float v_visible;
6
- varying float v_is_hovered;
7
- varying float v_scale_fade;
8
- varying float v_rect_id;
5
+ in vec4 v_quad;
6
+ in vec2 v_circle_center;
7
+ in float v_visible;
8
+ in float v_is_hovered;
9
+ in float v_scale_fade;
10
+ in float v_rect_id;
11
+ in float v_radius;
12
+ in float v_inner_radius;
13
+ in float v_scale_factor;
14
+
15
+ out vec4 fragColor;
9
16
 
10
17
  uniform float u_dpi;
11
18
  uniform vec3 u_color;
@@ -23,14 +30,9 @@ void main() {
23
30
  vec2 pixelPos = gl_FragCoord.xy;
24
31
  float dist = distance(pixelPos, v_circle_center);
25
32
 
26
- // Circle radius (includes border)
27
- float radius = v_quad.z / 2.0;
28
-
29
- // Border width in pixels (must match vertex shader) - scaled by DPI
30
- float borderWidth = 4.0 * u_dpi;
31
-
32
- // Inner circle radius (without border)
33
- float innerRadius = radius - borderWidth;
33
+ // Circle radii passed from vertex shader (in viewport pixels)
34
+ float radius = v_radius;
35
+ float innerRadius = v_inner_radius;
34
36
 
35
37
  // Anti-aliased circle
36
38
  float edgeSoftness = 1.0 * u_dpi;
@@ -46,9 +48,9 @@ void main() {
46
48
  // Plus dimensions relative to inner circle radius
47
49
  // Reduce thickness at low DPI (zoomed out)
48
50
  float plusThicknessBase = u_dpi <= 0.5 ? 1.25 : 1.5;
49
- float plusThickness = plusThicknessBase * u_dpi;
51
+ float plusThickness = plusThicknessBase * u_dpi * v_scale_factor;
50
52
  float plusLength = innerRadius * 0.5; // 50% of inner radius
51
- float plusSoftness = 0.25 * u_dpi;
53
+ float plusSoftness = 0.25 * u_dpi * v_scale_factor;
52
54
 
53
55
  // Calculate soft plus factor (0 = not plus, 1 = fully plus)
54
56
  float horizontalDist = max(abs(offset.y) - plusThickness, 0.0);
@@ -102,5 +104,5 @@ void main() {
102
104
  }
103
105
 
104
106
  // Apply scale fade to alpha
105
- gl_FragColor = vec4(finalColor, alpha);
107
+ fragColor = vec4(finalColor, alpha);
106
108
  }