@blokkli/editor 2.0.0-alpha.16 → 2.0.0-alpha.18

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 (194) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +640 -137
  3. package/dist/modules/drupal/graphql/base/fragment.blokkliProps.graphql +1 -1
  4. package/dist/modules/drupal/graphql/base/fragment.paragraphsFieldItem.graphql +3 -1
  5. package/dist/modules/drupal/graphql/base/query.pbConfig.graphql +1 -10
  6. package/dist/modules/drupal/graphql/features/comments.graphql +11 -8
  7. package/dist/modules/drupal/graphql/mutations/set_paragraph_schedule.graphql +15 -0
  8. package/dist/modules/drupal/index.mjs +33 -0
  9. package/dist/modules/drupal/runtime/adapter/index.js +12 -4
  10. package/dist/runtime/adapter/index.d.ts +21 -0
  11. package/dist/runtime/blokkliPlugins/ContextMenu/Menu/index.vue +3 -0
  12. package/dist/runtime/blokkliPlugins/ItemAction/index.vue +23 -15
  13. package/dist/runtime/blokkliPlugins/ItemAction/index.vue.d.ts +20 -44
  14. package/dist/runtime/blokkliPlugins/TourItem/index.vue +10 -5
  15. package/dist/runtime/components/Blocks/FromLibrary/index.vue +4 -2
  16. package/dist/runtime/components/BlokkliEditable.vue +32 -14
  17. package/dist/runtime/components/BlokkliField.vue +3 -0
  18. package/dist/runtime/components/BlokkliField.vue.d.ts +3 -3
  19. package/dist/runtime/components/BlokkliItem.vue +1 -1
  20. package/dist/runtime/components/BlokkliItem.vue.d.ts +4 -2
  21. package/dist/runtime/components/BlokkliProvider.vue +41 -28
  22. package/dist/runtime/components/BlokkliProvider.vue.d.ts +2 -1
  23. package/dist/runtime/components/Edit/Actions/index.vue +36 -20
  24. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +436 -25
  25. package/dist/runtime/components/Edit/ArtboardTooltip/index.vue +83 -0
  26. package/dist/runtime/components/Edit/ArtboardTooltip/index.vue.d.ts +32 -0
  27. package/dist/runtime/components/Edit/Banner/index.vue +51 -0
  28. package/dist/runtime/components/Edit/Banner/index.vue.d.ts +18 -0
  29. package/dist/runtime/components/Edit/Dialog/index.vue +6 -4
  30. package/dist/runtime/components/Edit/DraggableList.vue +15 -7
  31. package/dist/runtime/components/Edit/DraggableList.vue.d.ts +5 -5
  32. package/dist/runtime/components/Edit/EditIndicator.vue +118 -44
  33. package/dist/runtime/components/Edit/EditIndicator.vue.d.ts +3 -0
  34. package/dist/runtime/components/Edit/EditProvider.vue +101 -31
  35. package/dist/runtime/components/Edit/EditProvider.vue.d.ts +3 -0
  36. package/dist/runtime/components/Edit/Features/AddList/index.vue +9 -11
  37. package/dist/runtime/components/Edit/Features/Analyze/Overlay/index.vue +28 -26
  38. package/dist/runtime/components/Edit/Features/Analyze/Renderer.vue +1 -1
  39. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItemNodesTarget.vue +15 -11
  40. package/dist/runtime/components/Edit/Features/Anchors/Renderer.vue +19 -102
  41. package/dist/runtime/components/Edit/Features/Artboard/Renderer.vue +3 -0
  42. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +29 -53
  43. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/ScheduleSection.vue +154 -0
  44. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/ScheduleSection.vue.d.ts +27 -0
  45. package/dist/runtime/components/Edit/Features/BlockScheduler/Dialog/index.vue +222 -0
  46. package/dist/runtime/components/Edit/Features/{Selection/AddButtons/AddButtonsField.vue.d.ts → BlockScheduler/Dialog/index.vue.d.ts} +6 -9
  47. package/dist/runtime/components/Edit/Features/BlockScheduler/index.vue +96 -0
  48. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +15 -16
  49. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Item/index.vue +51 -0
  50. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/{Group → Item}/index.vue.d.ts +9 -13
  51. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +46 -66
  52. package/dist/runtime/components/Edit/Features/CommandPalette/index.vue +2 -0
  53. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue +35 -20
  54. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue.d.ts +5 -3
  55. package/dist/runtime/components/Edit/Features/Comments/CommentInput/index.vue +29 -0
  56. package/dist/runtime/components/Edit/Features/{Publish/Dialog/ScheduleDate.vue.d.ts → Comments/CommentInput/index.vue.d.ts} +2 -2
  57. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue +22 -16
  58. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue.d.ts +1 -0
  59. package/dist/runtime/components/Edit/Features/Comments/Overlay/index.vue +15 -6
  60. package/dist/runtime/components/Edit/Features/Comments/index.vue +21 -9
  61. package/dist/runtime/components/Edit/Features/Conversions/index.vue +4 -7
  62. package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue +26 -35
  63. package/dist/runtime/components/Edit/Features/Debug/Renderer.vue +240 -0
  64. package/dist/runtime/components/Edit/Features/Debug/Renderer.vue.d.ts +6 -0
  65. package/dist/runtime/components/Edit/Features/Debug/index.vue +7 -165
  66. package/dist/runtime/components/Edit/Features/Delete/index.vue +1 -1
  67. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +14 -6
  68. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +55 -48
  69. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +30 -18
  70. package/dist/runtime/components/Edit/Features/Duplicate/index.vue +6 -8
  71. package/dist/runtime/components/Edit/Features/Edit/index.vue +16 -22
  72. package/dist/runtime/components/Edit/Features/EditForm/index.vue +7 -6
  73. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue +69 -4
  74. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue.d.ts +2 -2
  75. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Plaintext/index.vue +13 -9
  76. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue +45 -87
  77. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue.d.ts +2 -2
  78. package/dist/runtime/components/Edit/Features/EditableField/index.vue +41 -43
  79. package/dist/runtime/components/Edit/Features/Fragments/Dialog/index.vue +11 -9
  80. package/dist/runtime/components/Edit/Features/Fragments/index.vue +3 -3
  81. package/dist/runtime/components/Edit/Features/History/index.vue +5 -2
  82. package/dist/runtime/components/Edit/Features/Hover/Overlay/fragment.glsl +139 -0
  83. package/dist/runtime/components/Edit/Features/Hover/Overlay/index.vue +261 -0
  84. package/dist/runtime/components/Edit/Features/Hover/Overlay/index.vue.d.ts +6 -0
  85. package/dist/runtime/components/Edit/Features/Hover/Overlay/vertex.glsl +117 -0
  86. package/dist/runtime/components/Edit/Features/Hover/index.vue +25 -0
  87. package/dist/runtime/components/Edit/Features/Hover/index.vue.d.ts +2 -0
  88. package/dist/runtime/components/Edit/Features/Library/EditReusable/index.vue +5 -7
  89. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/index.vue +19 -27
  90. package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue +32 -28
  91. package/dist/runtime/components/Edit/Features/Library/index.vue +28 -23
  92. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +6 -3
  93. package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue +15 -12
  94. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/index.vue +36 -29
  95. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +2 -4
  96. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue +6 -1
  97. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +8 -6
  98. package/dist/runtime/components/Edit/Features/Options/index.vue +6 -6
  99. package/dist/runtime/components/Edit/Features/Ownership/Renderer.vue +35 -0
  100. package/dist/runtime/components/Edit/Features/Ownership/Renderer.vue.d.ts +6 -0
  101. package/dist/runtime/components/Edit/Features/Ownership/index.vue +7 -25
  102. package/dist/runtime/components/Edit/Features/ProxyView/index.vue +5 -1
  103. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue +68 -15
  104. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Page/index.vue +15 -15
  105. package/dist/runtime/components/Edit/Features/Search/index.vue +4 -1
  106. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue +39 -74
  107. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue.d.ts +7 -5
  108. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/fragment.glsl +106 -0
  109. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/index.vue +440 -0
  110. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/index.vue.d.ts +32 -0
  111. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Renderer/vertex.glsl +102 -0
  112. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue +53 -125
  113. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue.d.ts +2 -2
  114. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +88 -29
  115. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue.d.ts +5 -3
  116. package/dist/runtime/components/Edit/Features/Selection/Overlay/vertex.glsl +11 -2
  117. package/dist/runtime/components/Edit/Features/Selection/OverlayFallback/index.vue +2 -2
  118. package/dist/runtime/components/Edit/Features/Selection/index.vue +66 -39
  119. package/dist/runtime/components/Edit/Features/Structure/List/Field/index.vue +2 -2
  120. package/dist/runtime/components/Edit/Features/Structure/List/Item/index.vue +13 -6
  121. package/dist/runtime/components/Edit/Features/Tour/Overlay/index.vue +3 -0
  122. package/dist/runtime/components/Edit/Features/Transform/index.vue +2 -27
  123. package/dist/runtime/components/Edit/Features/Translations/Banner/index.vue +17 -11
  124. package/dist/runtime/components/Edit/Features/Translations/index.vue +20 -23
  125. package/dist/runtime/components/Edit/Features/Validations/SidebarItem/index.vue +5 -5
  126. package/dist/runtime/components/Edit/Features/index.vue +17 -7
  127. package/dist/runtime/components/Edit/Form/Text/index.vue +2 -1
  128. package/dist/runtime/components/Edit/Form/Text/index.vue.d.ts +1 -0
  129. package/dist/runtime/components/Edit/Form/Toggle/index.vue +4 -3
  130. package/dist/runtime/components/Edit/Form/Toggle/index.vue.d.ts +12 -2
  131. package/dist/runtime/components/Edit/Indicators/index.vue +1 -1
  132. package/dist/runtime/components/Edit/InfoBox/index.vue +6 -2
  133. package/dist/runtime/components/Edit/InfoBox/index.vue.d.ts +12 -2
  134. package/dist/runtime/components/Edit/Konami/Game/index.vue +5 -5
  135. package/dist/runtime/components/Edit/{Features/Publish/Dialog/ScheduleDate.vue → ScheduleDate/index.vue} +6 -58
  136. package/dist/runtime/components/Edit/ScheduleDate/index.vue.d.ts +23 -0
  137. package/dist/runtime/components/Edit/ShortcutIndicator/index.vue +3 -0
  138. package/dist/runtime/components/Edit/Transition/Height.vue +95 -0
  139. package/dist/runtime/components/Edit/Transition/Height.vue.d.ts +36 -0
  140. package/dist/runtime/components/Edit/index.d.ts +7 -3
  141. package/dist/runtime/components/Edit/index.js +12 -4
  142. package/dist/runtime/composables/defineBlokkli.js +4 -2
  143. package/dist/runtime/css/output.css +1 -1
  144. package/dist/runtime/helpers/animationProvider.d.ts +35 -1
  145. package/dist/runtime/helpers/animationProvider.js +179 -48
  146. package/dist/runtime/helpers/composables/defineRenderer.d.ts +8 -0
  147. package/dist/runtime/helpers/composables/defineRenderer.js +8 -0
  148. package/dist/runtime/helpers/composables/useStateBasedCache.d.ts +4 -0
  149. package/dist/runtime/helpers/composables/useStateBasedCache.js +13 -0
  150. package/dist/runtime/helpers/composables/useStickyToolbar.d.ts +4 -1
  151. package/dist/runtime/helpers/composables/useStickyToolbar.js +53 -35
  152. package/dist/runtime/helpers/definitionProvider.d.ts +1 -1
  153. package/dist/runtime/helpers/dom/index.d.ts +1 -0
  154. package/dist/runtime/helpers/domProvider.d.ts +54 -14
  155. package/dist/runtime/helpers/domProvider.js +168 -134
  156. package/dist/runtime/helpers/index.d.ts +1 -8
  157. package/dist/runtime/helpers/index.js +1 -84
  158. package/dist/runtime/helpers/providers/blocks.d.ts +10 -0
  159. package/dist/runtime/helpers/providers/blocks.js +91 -0
  160. package/dist/runtime/helpers/providers/directive.d.ts +24 -0
  161. package/dist/runtime/helpers/providers/directive.js +205 -0
  162. package/dist/runtime/helpers/providers/element.d.ts +6 -0
  163. package/dist/runtime/helpers/providers/element.js +35 -0
  164. package/dist/runtime/helpers/providers/fields.d.ts +8 -0
  165. package/dist/runtime/helpers/providers/fields.js +47 -0
  166. package/dist/runtime/helpers/selectionProvider.d.ts +11 -11
  167. package/dist/runtime/helpers/selectionProvider.js +38 -45
  168. package/dist/runtime/helpers/stateProvider.d.ts +7 -2
  169. package/dist/runtime/helpers/stateProvider.js +83 -14
  170. package/dist/runtime/helpers/storageProvider.d.ts +3 -2
  171. package/dist/runtime/helpers/storageProvider.js +6 -2
  172. package/dist/runtime/helpers/symbols.d.ts +1 -0
  173. package/dist/runtime/helpers/symbols.js +1 -0
  174. package/dist/runtime/helpers/themeProvider.d.ts +2 -1
  175. package/dist/runtime/helpers/themeProvider.js +24 -14
  176. package/dist/runtime/helpers/typesProvider.js +10 -26
  177. package/dist/runtime/helpers/uiProvider.d.ts +11 -3
  178. package/dist/runtime/helpers/uiProvider.js +45 -17
  179. package/dist/runtime/icons/calendar.svg +1 -0
  180. package/dist/runtime/icons/clock.svg +1 -0
  181. package/dist/runtime/icons/comment_add.svg +1 -5
  182. package/dist/runtime/icons/delete.svg +1 -8
  183. package/dist/runtime/icons/duplicate.svg +1 -12
  184. package/dist/runtime/icons/edit.svg +1 -8
  185. package/dist/runtime/icons/reusable.svg +1 -5
  186. package/dist/runtime/plugins/blokkliDirectives.js +96 -0
  187. package/dist/runtime/types/index.d.ts +66 -35
  188. package/package.json +1 -1
  189. package/dist/runtime/components/Edit/DragInteractions/index.vue +0 -401
  190. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Group/index.vue +0 -63
  191. package/dist/runtime/components/Edit/Features/Selection/AddButtons/AddButtonsField.vue +0 -54
  192. package/dist/runtime/plugins/blokkliEditable.js +0 -31
  193. /package/dist/runtime/components/Edit/{DragInteractions → Features/BlockScheduler}/index.vue.d.ts +0 -0
  194. /package/dist/runtime/plugins/{blokkliEditable.d.ts → blokkliDirectives.d.ts} +0 -0
@@ -2,6 +2,25 @@ import { type ComputedRef, type WritableComputedRef } from '#imports';
2
2
  import type { UiProvider } from './uiProvider.js';
3
3
  import { type ProgramInfo } from 'twgl.js';
4
4
  import type { StorageProvider } from './storageProvider.js';
5
+ import type { CursorKeyword } from './dom/index.js';
6
+ import type { CanvasDrawEvent, Coord } from '#blokkli/types';
7
+ import type { SelectionProvider } from './selectionProvider.js';
8
+ import type { ElementProvider } from './providers/element.js';
9
+ export type RenderContext = CanvasDrawEvent & {
10
+ gl: WebGLRenderingContext;
11
+ };
12
+ export type Renderer = {
13
+ id: string;
14
+ zIndex: number;
15
+ enabled?: () => boolean;
16
+ only?: boolean | (() => boolean);
17
+ cursor?: () => CursorKeyword | undefined | null;
18
+ onClick?: (coord: {
19
+ mouse: Coord;
20
+ mouseArtboard: Coord;
21
+ }) => boolean | undefined;
22
+ render: (ctx: RenderContext) => void;
23
+ };
5
24
  export type AnimationProvider = {
6
25
  /**
7
26
  * Request an animation loop. Should be called when UI state changes.
@@ -23,5 +42,20 @@ export type AnimationProvider = {
23
42
  */
24
43
  registerProgram: (id: string, gl: WebGLRenderingContext, shaders: string[]) => ProgramInfo;
25
44
  setMouseCoords: (x: number, y: number) => void;
45
+ cursor: ComputedRef<CursorKeyword>;
46
+ /**
47
+ * Handle a click event by calling onClick handlers on renderers.
48
+ * Returns true if any renderer claimed the click, false otherwise.
49
+ */
50
+ handleClick: (x: number, y: number) => boolean;
51
+ /**
52
+ * Register a WebGL renderer with a specific zIndex.
53
+ * Returns an unregister function.
54
+ */
55
+ registerRenderer: (id: string, config: Omit<Renderer, 'id'>) => () => void;
56
+ /**
57
+ * Unregister a WebGL renderer.
58
+ */
59
+ unregisterRenderer: (id: string) => void;
26
60
  };
27
- export default function (ui: UiProvider, storage: StorageProvider): AnimationProvider;
61
+ export default function (ui: UiProvider, storage: StorageProvider, selection: SelectionProvider, element: ElementProvider): AnimationProvider;
@@ -8,13 +8,85 @@ import {
8
8
  } from "#imports";
9
9
  import { eventBus } from "#blokkli/helpers/eventBus";
10
10
  import { createProgramInfo } from "twgl.js";
11
- export default function(ui, storage) {
11
+ export default function(ui, storage, selection, element) {
12
12
  const webglEnabled = storage.use("webglEnabled", true);
13
+ const currentCursor = ref("default");
14
+ const cursor = computed(() => currentCursor.value);
15
+ const renderers = /* @__PURE__ */ new Map();
16
+ function registerRenderer(id, config) {
17
+ renderers.set(id, { id, ...config });
18
+ return () => unregisterRenderer(id);
19
+ }
20
+ function unregisterRenderer(id) {
21
+ renderers.delete(id);
22
+ }
23
+ function handleClick(x, y) {
24
+ const sortedRenderers = Array.from(renderers.values()).filter((renderer) => !renderer.enabled || renderer.enabled()).sort((a, b) => b.zIndex - a.zIndex);
25
+ const artboardOffset = ui.artboardOffset.value;
26
+ const artboardScale = ui.artboardScale.value;
27
+ const mouseArtboard = {
28
+ x: (x - artboardOffset.x) / artboardScale,
29
+ y: (y - artboardOffset.y) / artboardScale
30
+ };
31
+ for (const renderer of sortedRenderers) {
32
+ if (renderer.onClick) {
33
+ const claimed = renderer.onClick({
34
+ mouse: { x, y },
35
+ mouseArtboard
36
+ });
37
+ if (claimed === true) {
38
+ return true;
39
+ }
40
+ }
41
+ }
42
+ return false;
43
+ }
13
44
  let mouseX = 0;
14
45
  let mouseY = 0;
15
46
  let iterator = 120;
16
47
  const webglSupported = ref(null);
48
+ const maxCanvasWidth = ref(16384);
49
+ const maxCanvasHeight = ref(16384);
50
+ let webglLimitsQueried = false;
51
+ function getCanvasElement() {
52
+ const el = element.query(
53
+ document.documentElement,
54
+ "#bk-animation-canvas-webgl",
55
+ "Find animation canvas element."
56
+ );
57
+ if (!(el instanceof HTMLCanvasElement)) {
58
+ throw new TypeError("Failed to locate WebGL canvas.");
59
+ }
60
+ return el;
61
+ }
62
+ function gl() {
63
+ if (!webglEnabled.value) {
64
+ return;
65
+ }
66
+ if (webglSupported.value === false) {
67
+ return;
68
+ }
69
+ const canvas = getCanvasElement();
70
+ const glContext = canvas.getContext("webgl2", {
71
+ premultipliedAlpha: true
72
+ });
73
+ if (!glContext) {
74
+ webglSupported.value = false;
75
+ return;
76
+ }
77
+ webglSupported.value = true;
78
+ if (!webglLimitsQueried) {
79
+ const maxViewportDims = glContext.getParameter(
80
+ glContext.MAX_VIEWPORT_DIMS
81
+ );
82
+ maxCanvasWidth.value = maxViewportDims[0] || 16384;
83
+ maxCanvasHeight.value = maxViewportDims[1] || 16384;
84
+ webglLimitsQueried = true;
85
+ }
86
+ return glContext;
87
+ }
17
88
  useAnimationFrame((time) => {
89
+ const selectedUuids = [...selection.uuids.value];
18
90
  if (iterator < 1) {
19
91
  return;
20
92
  }
@@ -26,10 +98,79 @@ export default function(ui, storage) {
26
98
  fieldAreas: [],
27
99
  time
28
100
  });
101
+ const glContext = gl();
102
+ if (glContext) {
103
+ glContext.enable(glContext.BLEND);
104
+ glContext.blendFunc(glContext.SRC_ALPHA_SATURATE, glContext.ONE);
105
+ glContext.blendEquation(glContext.FUNC_ADD);
106
+ glContext.clearColor(0, 0, 0, 0);
107
+ glContext.clear(glContext.COLOR_BUFFER_BIT);
108
+ }
109
+ const sortedRenderers = Array.from(renderers.values()).sort(
110
+ (a, b) => a.zIndex - b.zIndex
111
+ );
112
+ let onlyRenderer = null;
113
+ for (const renderer of sortedRenderers) {
114
+ if (!renderer.enabled || renderer.enabled()) {
115
+ const onlyValue = typeof renderer.only === "function" ? renderer.only() : renderer.only;
116
+ if (onlyValue) {
117
+ onlyRenderer = renderer;
118
+ break;
119
+ }
120
+ }
121
+ }
122
+ const artboardOffset = ui.artboardOffset.value;
123
+ const artboardScale = ui.artboardScale.value;
124
+ const artboardSize = ui.artboardSize.value;
125
+ const mouseArtboard = {
126
+ x: (mouseX - artboardOffset.x) / artboardScale,
127
+ y: (mouseY - artboardOffset.y) / artboardScale
128
+ };
129
+ const ctx = {
130
+ gl: glContext,
131
+ time,
132
+ mouseX,
133
+ mouseY,
134
+ mouseArtboard,
135
+ artboardOffset,
136
+ artboardScale,
137
+ artboardSize,
138
+ selectedUuids
139
+ };
140
+ if (onlyRenderer) {
141
+ const glContext2 = gl();
142
+ if (glContext2) {
143
+ onlyRenderer.render(ctx);
144
+ }
145
+ } else {
146
+ for (let i = sortedRenderers.length - 1; i >= 0; i--) {
147
+ const renderer = sortedRenderers[i];
148
+ if (!renderer.enabled || renderer.enabled()) {
149
+ const glContext2 = gl();
150
+ if (glContext2) {
151
+ renderer.render(ctx);
152
+ }
153
+ }
154
+ }
155
+ }
156
+ let newCursor = "default";
157
+ for (let i = sortedRenderers.length - 1; i >= 0; i--) {
158
+ const renderer = sortedRenderers[i];
159
+ if (renderer.cursor && (!renderer.enabled || renderer.enabled())) {
160
+ const cursorValue = renderer.cursor();
161
+ if (cursorValue) {
162
+ newCursor = cursorValue;
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ currentCursor.value = newCursor;
168
+ eventBus.emit("canvas:draw", ctx);
169
+ eventBus.emit("animationFrame:after");
29
170
  });
30
171
  function onWindowMouseMove(e) {
31
- mouseX = e.clientX;
32
- mouseY = e.clientY;
172
+ mouseX = e.pageX;
173
+ mouseY = e.pageY;
33
174
  }
34
175
  onMounted(() => {
35
176
  document.body.addEventListener("wheel", requestDraw, { passive: false });
@@ -49,39 +190,49 @@ export default function(ui, storage) {
49
190
  onBlokkliEvent("option:update", requestDraw);
50
191
  onBlokkliEvent("state:reloaded", requestDraw);
51
192
  const dpi = computed(() => {
52
- if (ui.lowPerformanceMode.value) {
53
- return 0.5;
54
- }
55
- if (ui.isMobile.value) {
56
- return window.devicePixelRatio;
57
- }
58
- return Math.min(window.devicePixelRatio, 2.5);
193
+ const viewportWidth = ui.viewport.value.width;
194
+ const viewportHeight = ui.viewport.value.height;
195
+ const deviceRatio = window.devicePixelRatio;
196
+ const maxDpiByWidth = maxCanvasWidth.value / viewportWidth;
197
+ const maxDpiByHeight = maxCanvasHeight.value / viewportHeight;
198
+ const MAX_PIXELS = 16e6;
199
+ const maxDpiByPixels = Math.sqrt(
200
+ MAX_PIXELS / (viewportWidth * viewportHeight)
201
+ );
202
+ const maxDpi = ui.lowPerformanceMode.value ? 0.5 : 2;
203
+ return Math.min(
204
+ deviceRatio,
205
+ maxDpiByWidth,
206
+ maxDpiByHeight,
207
+ maxDpiByPixels,
208
+ maxDpi
209
+ );
59
210
  });
60
- function setSharedUniforms(gl, programInfo) {
211
+ function setSharedUniforms(gl2, programInfo) {
61
212
  const resolution = [ui.viewport.value.width, ui.viewport.value.height];
62
- gl.uniform2fv(
63
- gl.getUniformLocation(programInfo.program, "u_resolution"),
213
+ gl2.uniform2fv(
214
+ gl2.getUniformLocation(programInfo.program, "u_resolution"),
64
215
  resolution
65
216
  );
66
217
  const offset = ui.artboardOffset.value;
67
- gl.uniform1f(
68
- gl.getUniformLocation(programInfo.program, "u_offset_x"),
218
+ gl2.uniform1f(
219
+ gl2.getUniformLocation(programInfo.program, "u_offset_x"),
69
220
  offset.x
70
221
  );
71
- gl.uniform1f(
72
- gl.getUniformLocation(programInfo.program, "u_offset_y"),
222
+ gl2.uniform1f(
223
+ gl2.getUniformLocation(programInfo.program, "u_offset_y"),
73
224
  offset.y
74
225
  );
75
- gl.uniform1f(
76
- gl.getUniformLocation(programInfo.program, "u_scale"),
226
+ gl2.uniform1f(
227
+ gl2.getUniformLocation(programInfo.program, "u_scale"),
77
228
  ui.artboardScale.value
78
229
  );
79
- gl.uniform1f(gl.getUniformLocation(programInfo.program, "u_dpi"), dpi.value);
230
+ gl2.uniform1f(gl2.getUniformLocation(programInfo.program, "u_dpi"), dpi.value);
80
231
  }
81
232
  const registeredPrograms = {};
82
- function registerProgram(id, gl, shaders) {
233
+ function registerProgram(id, gl2, shaders) {
83
234
  if (!registeredPrograms[id]) {
84
- registeredPrograms[id] = createProgramInfo(gl, shaders);
235
+ registeredPrograms[id] = createProgramInfo(gl2, shaders);
85
236
  }
86
237
  return registeredPrograms[id];
87
238
  }
@@ -90,39 +241,19 @@ export default function(ui, storage) {
90
241
  mouseY = y;
91
242
  iterator = 120;
92
243
  }
93
- function getCanvasElement() {
94
- const el = document.querySelector("#bk-animation-canvas-webgl");
95
- if (!(el instanceof HTMLCanvasElement)) {
96
- throw new TypeError("Failed to locate WebGL canvas.");
97
- }
98
- return el;
99
- }
100
244
  return {
101
245
  requestDraw,
102
- gl: function() {
103
- if (!webglEnabled.value) {
104
- return;
105
- }
106
- if (webglSupported.value === false) {
107
- return;
108
- }
109
- const canvas = getCanvasElement();
110
- const gl = canvas.getContext("webgl2", {
111
- premultipliedAlpha: true
112
- });
113
- if (!gl) {
114
- webglSupported.value = false;
115
- return;
116
- }
117
- webglSupported.value = true;
118
- return gl;
119
- },
246
+ gl,
120
247
  setSharedUniforms,
121
248
  dpi,
122
249
  registerProgram,
123
250
  setMouseCoords,
124
251
  webglSupported: computed(() => webglSupported.value && webglEnabled.value),
125
252
  webglEnabled,
126
- getCanvasElement
253
+ getCanvasElement,
254
+ cursor,
255
+ handleClick,
256
+ registerRenderer,
257
+ unregisterRenderer
127
258
  };
128
259
  }
@@ -0,0 +1,8 @@
1
+ import type { Renderer } from '../animationProvider.js';
2
+ /**
3
+ * Register a WebGL renderer with automatic cleanup on unmount.
4
+ *
5
+ * @param id - Unique identifier for the renderer
6
+ * @param config - Renderer configuration (zIndex, enabled, render)
7
+ */
8
+ export default function defineRenderer(id: string, config: Omit<Renderer, 'id'>): void;
@@ -0,0 +1,8 @@
1
+ import { onBeforeUnmount, useBlokkli } from "#imports";
2
+ export default function defineRenderer(id, config) {
3
+ const { animation } = useBlokkli();
4
+ const unregisterRenderer = animation.registerRenderer(id, config);
5
+ onBeforeUnmount(() => {
6
+ unregisterRenderer();
7
+ });
8
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Caches the result of the given callback for the duration of the current state.
3
+ */
4
+ export default function <T>(cb: () => T): () => T;
@@ -0,0 +1,13 @@
1
+ import onBlokkliEvent from "./onBlokkliEvent.js";
2
+ export default function(cb) {
3
+ let cached = null;
4
+ onBlokkliEvent("state:reloaded", () => {
5
+ cached = null;
6
+ });
7
+ return () => {
8
+ if (!cached) {
9
+ cached = cb();
10
+ }
11
+ return cached;
12
+ };
13
+ }
@@ -1,5 +1,6 @@
1
1
  import type { ComputedRef, ShallowRef } from 'vue';
2
- type PlacementVertical = 'top' | 'bottom' | 'auto';
2
+ import type { Coord } from '#blokkli/types';
3
+ export type PlacementVertical = 'top' | 'bottom' | 'auto';
3
4
  type PlacementHorizontal = 'left' | 'center';
4
5
  type UseStickyToolbarOptions = {
5
6
  getPlacementY?: () => PlacementVertical;
@@ -9,7 +10,9 @@ type UseStickyToolbarOptions = {
9
10
  getHeight?: () => number;
10
11
  getMargin?: () => number;
11
12
  getAnchorElement?: () => HTMLElement | null;
13
+ getAnchorCoordinates?: () => Coord | null;
12
14
  getCaretWidth?: () => number;
15
+ allowHorizontalOverflow?: boolean;
13
16
  };
14
17
  type UseStickyToolbar = {
15
18
  shouldRender: ComputedRef<boolean>;
@@ -39,26 +39,33 @@ export default function(el, options) {
39
39
  let minY = 0;
40
40
  let maxY = 0;
41
41
  let hasRects = false;
42
- if (options && options.getAnchorElement) {
43
- const anchorElement = options.getAnchorElement();
44
- if (anchorElement) {
45
- anchorRect ||= ui.getAbsoluteElementRect(
46
- anchorElement.getBoundingClientRect(),
47
- scale,
48
- offset
49
- );
50
- const rectX = (anchorRect.x + offset.x / scale) * scale;
51
- const rectY = (anchorRect.y + offset.y / scale) * scale;
52
- const rectRight = rectX + anchorRect.width * scale;
53
- const rectBottom = rectY + anchorRect.height * scale;
54
- minX = rectX;
55
- maxX = rectRight;
56
- minY = rectY;
57
- maxY = rectBottom;
58
- hasRects = true;
59
- }
42
+ const anchorElement = options && options.getAnchorElement ? options.getAnchorElement() : null;
43
+ const anchorCoordinates = options && options.getAnchorCoordinates ? options.getAnchorCoordinates() : null;
44
+ if (anchorCoordinates) {
45
+ const rectX = (anchorCoordinates.x + offset.x / scale) * scale;
46
+ const rectY = (anchorCoordinates.y + offset.y / scale) * scale;
47
+ minX = rectX;
48
+ maxX = rectX + 1;
49
+ minY = rectY;
50
+ maxY = rectY + 1;
51
+ hasRects = true;
52
+ } else if (anchorElement) {
53
+ anchorRect ||= ui.getAbsoluteElementRect(
54
+ anchorElement.getBoundingClientRect(),
55
+ scale,
56
+ offset
57
+ );
58
+ const rectX = (anchorRect.x + offset.x / scale) * scale;
59
+ const rectY = (anchorRect.y + offset.y / scale) * scale;
60
+ const rectRight = rectX + anchorRect.width * scale;
61
+ const rectBottom = rectY + anchorRect.height * scale;
62
+ minX = rectX;
63
+ maxX = rectRight;
64
+ minY = rectY;
65
+ maxY = rectBottom;
66
+ hasRects = true;
60
67
  } else {
61
- const rects = selection.blocks.value.map((block) => dom.getBlockRect(block.uuid)).filter(falsy).filter((rect2) => rect2.height || rect2.width);
68
+ const rects = selection.uuids.value.map((uuid) => dom.getBlockRect(uuid)).filter(falsy).filter((rect) => rect.height || rect.width);
62
69
  hasRects = !!rects.length;
63
70
  if (hasRects) {
64
71
  for (let i = 0; i < rects.length; i++) {
@@ -114,22 +121,33 @@ export default function(el, options) {
114
121
  } else {
115
122
  x = minX - xSubtract;
116
123
  }
117
- const rect = limitPlacedRect(
118
- {
119
- x,
120
- y,
121
- width,
122
- height
123
- },
124
- padding
125
- );
126
- const idealPosition = findIdealRectPosition(
127
- ui.viewportBlockingRects.value,
128
- rect,
129
- padding
130
- );
131
- if (!idealPosition) {
132
- return void 0;
124
+ const shouldAllowOverflow = options?.allowHorizontalOverflow && width > padding.width;
125
+ let idealPosition;
126
+ if (shouldAllowOverflow) {
127
+ const limitedY = Math.min(
128
+ Math.max(padding.y, y),
129
+ padding.height + padding.y - height
130
+ );
131
+ idealPosition = { x, y: limitedY };
132
+ } else {
133
+ const rect = limitPlacedRect(
134
+ {
135
+ x,
136
+ y,
137
+ width,
138
+ height
139
+ },
140
+ padding
141
+ );
142
+ const position = findIdealRectPosition(
143
+ ui.viewportBlockingRects.value,
144
+ rect,
145
+ padding
146
+ );
147
+ if (!position) {
148
+ return void 0;
149
+ }
150
+ idealPosition = position;
133
151
  }
134
152
  const caretWidth = getCaretWidth();
135
153
  const caretHalfWidth = caretWidth / 2;
@@ -5,7 +5,7 @@ import type { DeepReadonly } from 'vue';
5
5
  import type { BlockDefinitionOptionsInput } from '../types/index.js';
6
6
  import { type RuntimeBlockOptionArray } from '#blokkli-build/runtime-options';
7
7
  export type DefinitionProvider = {
8
- getBlockDefinition: (bundle: string, fieldListType: ValidFieldListTypes, parentBundle?: BlockBundleWithNested) => BlockDefinition | undefined;
8
+ getBlockDefinition: (bundle: string, fieldListType: ValidFieldListTypes, parentBundle?: BlockBundleWithNested | null) => BlockDefinition | undefined;
9
9
  getDefaultDefinition: (bundle: string) => BlockDefinition | undefined;
10
10
  getFragmentDefinition: (name: string) => FragmentDefinition | undefined;
11
11
  getProviderDefinition: (entityType: string, entityBundle: string) => ProviderDefinition | undefined;
@@ -62,3 +62,4 @@ export declare const MOUSE_BUTTON: Readonly<{
62
62
  */
63
63
  FIFTH: 4;
64
64
  }>;
65
+ export type CursorKeyword = 'alias' | 'all-scroll' | 'auto' | 'cell' | 'col-resize' | 'context-menu' | 'copy' | 'crosshair' | 'default' | 'e-resize' | 'ew-resize' | 'grab' | 'grabbing' | 'help' | 'move' | 'n-resize' | 'ne-resize' | 'nesw-resize' | 'no-drop' | 'none' | 'not-allowed' | 'ns-resize' | 'nw-resize' | 'nwse-resize' | 'pointer' | 'progress' | 'row-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'text' | 'vertical-text' | 'w-resize' | 'wait' | 'zoom-in' | 'zoom-out';
@@ -1,8 +1,10 @@
1
1
  import { type ComputedRef } from '#imports';
2
- import type { DraggableExistingBlock, BlokkliFieldElement, DraggableItem, DroppableEntityField, EntityContext, Rectangle } from '#blokkli/types';
2
+ import type { DraggableExistingBlock, DraggableItem, EntityContext, Rectangle, RenderedFieldListItem, RegisteredField, RegisterFieldData } from '#blokkli/types';
3
3
  import type { UiProvider } from './uiProvider.js';
4
4
  import type { DebugProvider } from './debugProvider.js';
5
5
  import type { DefinitionProvider } from './definitionProvider.js';
6
+ import type { StateProvider } from './stateProvider.js';
7
+ import type { ElementProvider } from './providers/element.js';
6
8
  type RegisteredFieldType = {
7
9
  entityType: string;
8
10
  entityBundle: string;
@@ -12,41 +14,79 @@ type MeasuredBlockRect = Rectangle & {
12
14
  time: number;
13
15
  };
14
16
  export type DomProvider = {
15
- findBlock(uuid: string): DraggableExistingBlock | undefined;
16
- getAllBlocks(): DraggableExistingBlock[];
17
17
  findClosestBlock(el: Element | EventTarget): DraggableExistingBlock | undefined;
18
18
  /**
19
19
  * Return the droppable markup for a draggable item.
20
20
  */
21
- getDropElementMarkup(item: DraggableItem, checkSize?: boolean): string;
22
- findField(entityUuid: string, fieldName: string): BlokkliFieldElement | undefined;
21
+ getDropElementMarkup(item: DraggableItem | RenderedFieldListItem, checkSize?: boolean): string;
23
22
  registerBlock: (key: string, uuid: string, el: HTMLElement | null) => void;
24
23
  unregisterBlock: (key: string, uuid: string) => void;
25
- registerField: (entity: EntityContext, fieldName: string, instance: HTMLElement) => void;
26
- updateFieldElement: (entity: EntityContext, fieldName: string, element: HTMLElement) => void;
24
+ registerField: (entity: EntityContext, fieldName: string, instance: HTMLElement, data: RegisterFieldData) => void;
25
+ updateFieldElement: (entity: EntityContext, fieldName: string, element: HTMLElement, data: RegisterFieldData) => void;
27
26
  unregisterField: (entity: EntityContext, fieldName: string) => void;
27
+ getRegisteredField: (uuid: string, fieldName: string) => RegisteredField | undefined;
28
28
  registeredFieldTypes: ComputedRef<RegisteredFieldType[]>;
29
29
  registeredBlockUuids: ComputedRef<string[]>;
30
- /**
31
- * Get all droppable entity fields.
32
- */
33
- getAllDroppableFields(): DroppableEntityField[];
34
30
  findClosestEntityContext(el: HTMLElement): EntityContext | undefined;
35
31
  getVisibleBlocks(): string[];
36
32
  getVisibleFields(): string[];
37
33
  isBlockVisible(uuid: string): boolean;
38
- getActiveProviderElement: () => HTMLElement;
39
34
  getBlockRects: () => Record<string, MeasuredBlockRect>;
40
35
  getBlockRect: (uuid: string, refresh?: boolean) => MeasuredBlockRect | undefined;
41
36
  refreshBlockRect: (uuid: string) => void;
42
37
  getFieldRect: (key: string) => Rectangle | undefined;
38
+ registeredBlocks: ComputedRef<Record<string, HTMLElement | undefined>>;
43
39
  updateVisibleRects: () => void;
44
40
  isReady: ComputedRef<boolean>;
45
41
  init: () => void;
46
42
  /**
47
43
  * Get the drag element for a block.
48
44
  */
49
- getDragElement: (block: DraggableExistingBlock) => HTMLElement | undefined;
45
+ getDragElement: (block: DraggableExistingBlock | RenderedFieldListItem) => HTMLElement | undefined;
46
+ /**
47
+ * Get debug data for troubleshooting.
48
+ */
49
+ getDebugData: () => {
50
+ registeredBlocks: Array<{
51
+ uuid: string;
52
+ hasElement: boolean;
53
+ hasObservedElement: boolean;
54
+ hasRect: boolean;
55
+ hasCurrentKey: boolean;
56
+ isVisible: boolean;
57
+ elementInfo?: {
58
+ tagName: string;
59
+ bundle?: string;
60
+ hostBundle?: string;
61
+ fieldListType?: string;
62
+ };
63
+ }>;
64
+ fields: Array<{
65
+ key: string;
66
+ isVisible: boolean;
67
+ hasRect: boolean;
68
+ entityType: string;
69
+ entityBundle: string;
70
+ fieldName: string;
71
+ }>;
72
+ summary: {
73
+ totalRegisteredBlocks: number;
74
+ totalBlocksWithElements: number;
75
+ totalObservedElements: number;
76
+ totalBlockRects: number;
77
+ totalVisibleBlocks: number;
78
+ totalRegisteredFields: number;
79
+ totalVisibleFields: number;
80
+ totalFieldRects: number;
81
+ isInitializing: boolean;
82
+ isReady: boolean;
83
+ };
84
+ orphanedData: {
85
+ rectsWithoutRegistration: string[];
86
+ observedElementsWithoutRegistration: string[];
87
+ keysWithoutRegistration: string[];
88
+ };
89
+ };
50
90
  };
51
- export default function (ui: UiProvider, debug: DebugProvider, definitions: DefinitionProvider): DomProvider;
91
+ export default function (ui: UiProvider, debug: DebugProvider, definitions: DefinitionProvider, state: StateProvider, element: ElementProvider): DomProvider;
52
92
  export {};