@blokkli/editor 1.0.0

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 (395) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/dist/module.cjs +5 -0
  4. package/dist/module.d.mts +129 -0
  5. package/dist/module.d.ts +129 -0
  6. package/dist/module.json +12 -0
  7. package/dist/module.mjs +5430 -0
  8. package/dist/runtime/adapter/drupal/graphql/base.graphql +906 -0
  9. package/dist/runtime/adapter/drupal/graphql/comments.graphql +56 -0
  10. package/dist/runtime/adapter/drupal/graphql/fragments.graphql +25 -0
  11. package/dist/runtime/adapter/drupal/graphql/library.graphql +66 -0
  12. package/dist/runtime/adapter/drupal/graphql/search.graphql +19 -0
  13. package/dist/runtime/adapter/drupal/graphql/transform.graphql +27 -0
  14. package/dist/runtime/adapter/drupal/graphqlMiddleware.d.ts +2 -0
  15. package/dist/runtime/adapter/drupal/graphqlMiddleware.js +643 -0
  16. package/dist/runtime/adapter/index.d.ts +352 -0
  17. package/dist/runtime/adapter/index.js +3 -0
  18. package/dist/runtime/blokkliPlugins/AddAction/index.vue +87 -0
  19. package/dist/runtime/blokkliPlugins/ContextMenu/Menu/index.vue +95 -0
  20. package/dist/runtime/blokkliPlugins/ContextMenu/index.vue +49 -0
  21. package/dist/runtime/blokkliPlugins/DebugOverlay/index.vue +34 -0
  22. package/dist/runtime/blokkliPlugins/DroppableEdit/index.vue +73 -0
  23. package/dist/runtime/blokkliPlugins/ItemAction/index.vue +132 -0
  24. package/dist/runtime/blokkliPlugins/ItemDropdown/index.vue +42 -0
  25. package/dist/runtime/blokkliPlugins/MenuButton/index.vue +74 -0
  26. package/dist/runtime/blokkliPlugins/Sidebar/Detached/index.vue +334 -0
  27. package/dist/runtime/blokkliPlugins/Sidebar/index.vue +286 -0
  28. package/dist/runtime/blokkliPlugins/ToolbarButton/index.vue +104 -0
  29. package/dist/runtime/blokkliPlugins/TourItem/index.vue +45 -0
  30. package/dist/runtime/blokkliPlugins/ViewOption/index.vue +106 -0
  31. package/dist/runtime/blokkliPlugins/index.d.ts +12 -0
  32. package/dist/runtime/blokkliPlugins/index.js +24 -0
  33. package/dist/runtime/components/Blocks/Fragment/icon.svg +1 -0
  34. package/dist/runtime/components/Blocks/Fragment/index.vue +24 -0
  35. package/dist/runtime/components/Blocks/FromLibrary/index.vue +58 -0
  36. package/dist/runtime/components/BlokkliEditable.vue +73 -0
  37. package/dist/runtime/components/BlokkliField.vue +157 -0
  38. package/dist/runtime/components/BlokkliItem.vue +79 -0
  39. package/dist/runtime/components/BlokkliProvider.vue +160 -0
  40. package/dist/runtime/components/Edit/Actions/index.vue +263 -0
  41. package/dist/runtime/components/Edit/AddListItem/index.vue +116 -0
  42. package/dist/runtime/components/Edit/AnimationCanvas/index.vue +122 -0
  43. package/dist/runtime/components/Edit/AppMenu/index.vue +60 -0
  44. package/dist/runtime/components/Edit/BlokkliErrorBoundary.vue +64 -0
  45. package/dist/runtime/components/Edit/Dialog/index.vue +163 -0
  46. package/dist/runtime/components/Edit/DragInteractions/index.vue +439 -0
  47. package/dist/runtime/components/Edit/DraggableList.vue +110 -0
  48. package/dist/runtime/components/Edit/EditIndicator.vue +82 -0
  49. package/dist/runtime/components/Edit/EditProvider.vue +213 -0
  50. package/dist/runtime/components/Edit/Features/AddList/docs.md +4 -0
  51. package/dist/runtime/components/Edit/Features/AddList/index.vue +205 -0
  52. package/dist/runtime/components/Edit/Features/Artboard/Manager/Artboard.d.ts +204 -0
  53. package/dist/runtime/components/Edit/Features/Artboard/Manager/Artboard.js +748 -0
  54. package/dist/runtime/components/Edit/Features/Artboard/Manager/Scrollbar/index.vue +176 -0
  55. package/dist/runtime/components/Edit/Features/Artboard/Manager/index.vue +317 -0
  56. package/dist/runtime/components/Edit/Features/Artboard/index.vue +45 -0
  57. package/dist/runtime/components/Edit/Features/Assistant/Overlay/ResultMarkup/index.vue +17 -0
  58. package/dist/runtime/components/Edit/Features/Assistant/Overlay/index.vue +147 -0
  59. package/dist/runtime/components/Edit/Features/Assistant/docs.md +7 -0
  60. package/dist/runtime/components/Edit/Features/Assistant/index.vue +68 -0
  61. package/dist/runtime/components/Edit/Features/BlockAddList/docs.md +15 -0
  62. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +440 -0
  63. package/dist/runtime/components/Edit/Features/Clipboard/List/Item/File.vue +68 -0
  64. package/dist/runtime/components/Edit/Features/Clipboard/List/Item/Video.vue +56 -0
  65. package/dist/runtime/components/Edit/Features/Clipboard/List/index.vue +69 -0
  66. package/dist/runtime/components/Edit/Features/Clipboard/docs.md +16 -0
  67. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +485 -0
  68. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Group/index.vue +61 -0
  69. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +280 -0
  70. package/dist/runtime/components/Edit/Features/CommandPalette/index.vue +51 -0
  71. package/dist/runtime/components/Edit/Features/Comments/AddForm/index.vue +32 -0
  72. package/dist/runtime/components/Edit/Features/Comments/Comment/index.vue +53 -0
  73. package/dist/runtime/components/Edit/Features/Comments/Overlay/Item/index.vue +100 -0
  74. package/dist/runtime/components/Edit/Features/Comments/Overlay/index.vue +133 -0
  75. package/dist/runtime/components/Edit/Features/Comments/docs.md +13 -0
  76. package/dist/runtime/components/Edit/Features/Comments/index.vue +110 -0
  77. package/dist/runtime/components/Edit/Features/Conversions/index.vue +98 -0
  78. package/dist/runtime/components/Edit/Features/Debug/Rects/index.vue +55 -0
  79. package/dist/runtime/components/Edit/Features/Debug/Viewport/index.vue +93 -0
  80. package/dist/runtime/components/Edit/Features/Debug/docs.md +3 -0
  81. package/dist/runtime/components/Edit/Features/Debug/index.vue +178 -0
  82. package/dist/runtime/components/Edit/Features/Delete/index.vue +43 -0
  83. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +420 -0
  84. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/fragment.glsl +58 -0
  85. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +808 -0
  86. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/vertex.glsl +57 -0
  87. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +410 -0
  88. package/dist/runtime/components/Edit/Features/Duplicate/index.vue +109 -0
  89. package/dist/runtime/components/Edit/Features/Edit/index.vue +63 -0
  90. package/dist/runtime/components/Edit/Features/EditForm/Frame/index.vue +73 -0
  91. package/dist/runtime/components/Edit/Features/EditForm/index.vue +217 -0
  92. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Contenteditable/index.vue +42 -0
  93. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Frame/index.vue +68 -0
  94. package/dist/runtime/components/Edit/Features/EditableField/Overlay/Plaintext/index.vue +81 -0
  95. package/dist/runtime/components/Edit/Features/EditableField/Overlay/index.vue +357 -0
  96. package/dist/runtime/components/Edit/Features/EditableField/index.vue +192 -0
  97. package/dist/runtime/components/Edit/Features/EditableMask/index.vue +64 -0
  98. package/dist/runtime/components/Edit/Features/EntityTitle/index.vue +108 -0
  99. package/dist/runtime/components/Edit/Features/Exit/index.vue +38 -0
  100. package/dist/runtime/components/Edit/Features/FieldAreas/Overlay/index.vue +33 -0
  101. package/dist/runtime/components/Edit/Features/FieldAreas/index.vue +43 -0
  102. package/dist/runtime/components/Edit/Features/Fragments/Dialog/Item/index.vue +68 -0
  103. package/dist/runtime/components/Edit/Features/Fragments/Dialog/index.vue +137 -0
  104. package/dist/runtime/components/Edit/Features/Fragments/docs.md +101 -0
  105. package/dist/runtime/components/Edit/Features/Fragments/index.vue +86 -0
  106. package/dist/runtime/components/Edit/Features/Grid/index.vue +40 -0
  107. package/dist/runtime/components/Edit/Features/Help/Shortcuts/index.vue +71 -0
  108. package/dist/runtime/components/Edit/Features/Help/index.vue +53 -0
  109. package/dist/runtime/components/Edit/Features/History/index.vue +263 -0
  110. package/dist/runtime/components/Edit/Features/ImportExisting/Dialog/index.vue +140 -0
  111. package/dist/runtime/components/Edit/Features/ImportExisting/index.vue +92 -0
  112. package/dist/runtime/components/Edit/Features/Library/EditReusable/index.vue +0 -0
  113. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/Item/index.vue +73 -0
  114. package/dist/runtime/components/Edit/Features/Library/LibraryDialog/index.vue +184 -0
  115. package/dist/runtime/components/Edit/Features/Library/ReusableDialog/index.vue +88 -0
  116. package/dist/runtime/components/Edit/Features/Library/docs.md +127 -0
  117. package/dist/runtime/components/Edit/Features/Library/index.vue +184 -0
  118. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +184 -0
  119. package/dist/runtime/components/Edit/Features/MediaLibrary/index.vue +182 -0
  120. package/dist/runtime/components/Edit/Features/MediaLibrary/types.d.ts +57 -0
  121. package/dist/runtime/components/Edit/Features/MediaLibrary/types.js +0 -0
  122. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/fragment.glsl +90 -0
  123. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/index.vue +289 -0
  124. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/vertex.glsl +182 -0
  125. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +76 -0
  126. package/dist/runtime/components/Edit/Features/Options/Form/Checkbox/index.vue +52 -0
  127. package/dist/runtime/components/Edit/Features/Options/Form/Checkboxes/index.vue +129 -0
  128. package/dist/runtime/components/Edit/Features/Options/Form/Color/index.vue +38 -0
  129. package/dist/runtime/components/Edit/Features/Options/Form/Group.vue +25 -0
  130. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue +155 -0
  131. package/dist/runtime/components/Edit/Features/Options/Form/Number/index.vue +74 -0
  132. package/dist/runtime/components/Edit/Features/Options/Form/Radios/index.vue +135 -0
  133. package/dist/runtime/components/Edit/Features/Options/Form/Range/index.vue +47 -0
  134. package/dist/runtime/components/Edit/Features/Options/Form/Text/index.vue +38 -0
  135. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +342 -0
  136. package/dist/runtime/components/Edit/Features/Options/index.vue +88 -0
  137. package/dist/runtime/components/Edit/Features/Ownership/index.vue +57 -0
  138. package/dist/runtime/components/Edit/Features/Preview/index.vue +45 -0
  139. package/dist/runtime/components/Edit/Features/PreviewGrant/QrCode/index.vue +30 -0
  140. package/dist/runtime/components/Edit/Features/PreviewGrant/index.vue +73 -0
  141. package/dist/runtime/components/Edit/Features/Publish/index.vue +50 -0
  142. package/dist/runtime/components/Edit/Features/ResponsivePreview/Frame/index.vue +81 -0
  143. package/dist/runtime/components/Edit/Features/ResponsivePreview/index.vue +217 -0
  144. package/dist/runtime/components/Edit/Features/Revert/index.vue +68 -0
  145. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Content/index.vue +165 -0
  146. package/dist/runtime/components/Edit/Features/Search/Overlay/Results/Page/index.vue +211 -0
  147. package/dist/runtime/components/Edit/Features/Search/Overlay/index.vue +214 -0
  148. package/dist/runtime/components/Edit/Features/Search/index.vue +79 -0
  149. package/dist/runtime/components/Edit/Features/Selection/Overlay/fragment.glsl +99 -0
  150. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +144 -0
  151. package/dist/runtime/components/Edit/Features/Selection/Overlay/vertex.glsl +85 -0
  152. package/dist/runtime/components/Edit/Features/Selection/OverlayFallback/index.vue +50 -0
  153. package/dist/runtime/components/Edit/Features/Selection/index.vue +295 -0
  154. package/dist/runtime/components/Edit/Features/Settings/Dialog/FeatureSetting/index.vue +141 -0
  155. package/dist/runtime/components/Edit/Features/Settings/Dialog/index.vue +138 -0
  156. package/dist/runtime/components/Edit/Features/Settings/index.vue +92 -0
  157. package/dist/runtime/components/Edit/Features/Structure/List/Field/index.vue +181 -0
  158. package/dist/runtime/components/Edit/Features/Structure/List/Item/index.vue +149 -0
  159. package/dist/runtime/components/Edit/Features/Structure/List/index.vue +55 -0
  160. package/dist/runtime/components/Edit/Features/Structure/index.vue +83 -0
  161. package/dist/runtime/components/Edit/Features/Theme/Color/index.vue +81 -0
  162. package/dist/runtime/components/Edit/Features/Theme/GeneratedCode/index.vue +24 -0
  163. package/dist/runtime/components/Edit/Features/Theme/index.vue +122 -0
  164. package/dist/runtime/components/Edit/Features/TouchActionBar/Bar/index.vue +26 -0
  165. package/dist/runtime/components/Edit/Features/TouchActionBar/index.vue +42 -0
  166. package/dist/runtime/components/Edit/Features/Tour/Overlay/index.vue +270 -0
  167. package/dist/runtime/components/Edit/Features/Tour/Popup/index.vue +36 -0
  168. package/dist/runtime/components/Edit/Features/Tour/docs.md +0 -0
  169. package/dist/runtime/components/Edit/Features/Tour/index.vue +46 -0
  170. package/dist/runtime/components/Edit/Features/Transform/docs.md +67 -0
  171. package/dist/runtime/components/Edit/Features/Transform/index.vue +177 -0
  172. package/dist/runtime/components/Edit/Features/Translations/Banner/index.vue +50 -0
  173. package/dist/runtime/components/Edit/Features/Translations/index.vue +193 -0
  174. package/dist/runtime/components/Edit/Features/Validations/Overlay/Item.vue +50 -0
  175. package/dist/runtime/components/Edit/Features/Validations/Overlay/index.vue +51 -0
  176. package/dist/runtime/components/Edit/Features/Validations/SidebarItem/index.vue +50 -0
  177. package/dist/runtime/components/Edit/Features/Validations/index.vue +70 -0
  178. package/dist/runtime/components/Edit/Features/index.vue +67 -0
  179. package/dist/runtime/components/Edit/FormOverlay/Header/index.vue +39 -0
  180. package/dist/runtime/components/Edit/FormOverlay/index.vue +52 -0
  181. package/dist/runtime/components/Edit/Highlight/index.vue +94 -0
  182. package/dist/runtime/components/Edit/Icon/index.vue +21 -0
  183. package/dist/runtime/components/Edit/ItemIcon/index.vue +27 -0
  184. package/dist/runtime/components/Edit/Loading/index.vue +19 -0
  185. package/dist/runtime/components/Edit/Messages/Item/index.vue +107 -0
  186. package/dist/runtime/components/Edit/Messages/index.vue +37 -0
  187. package/dist/runtime/components/Edit/PreviewProvider.vue +223 -0
  188. package/dist/runtime/components/Edit/RelativeTime/index.vue +37 -0
  189. package/dist/runtime/components/Edit/Resizable/index.vue +90 -0
  190. package/dist/runtime/components/Edit/ScaleToFit/index.vue +57 -0
  191. package/dist/runtime/components/Edit/ShortcutIndicator/index.vue +90 -0
  192. package/dist/runtime/components/Edit/Sortli/index.vue +92 -0
  193. package/dist/runtime/components/Edit/SystemRequirements/index.vue +91 -0
  194. package/dist/runtime/components/Edit/Toolbar/index.vue +106 -0
  195. package/dist/runtime/components/Edit/ViewportBlockingRect/index.vue +75 -0
  196. package/dist/runtime/components/Edit/index.d.ts +14 -0
  197. package/dist/runtime/components/Edit/index.js +28 -0
  198. package/dist/runtime/composables/defineBlokkli.d.ts +6 -0
  199. package/dist/runtime/composables/defineBlokkli.js +108 -0
  200. package/dist/runtime/composables/defineBlokkliFeature.d.ts +28 -0
  201. package/dist/runtime/composables/defineBlokkliFeature.js +62 -0
  202. package/dist/runtime/composables/defineBlokkliFragment.d.ts +3 -0
  203. package/dist/runtime/composables/defineBlokkliFragment.js +54 -0
  204. package/dist/runtime/composables/useBlokkli.d.ts +8 -0
  205. package/dist/runtime/composables/useBlokkli.js +5 -0
  206. package/dist/runtime/constants/index.d.ts +4 -0
  207. package/dist/runtime/constants/index.js +2 -0
  208. package/dist/runtime/css/output.css +1 -0
  209. package/dist/runtime/helpers/Artboard/index.d.ts +16 -0
  210. package/dist/runtime/helpers/Artboard/index.js +20 -0
  211. package/dist/runtime/helpers/DragStyle/index.d.ts +12 -0
  212. package/dist/runtime/helpers/DragStyle/index.js +86 -0
  213. package/dist/runtime/helpers/animationProvider.d.ts +25 -0
  214. package/dist/runtime/helpers/animationProvider.js +116 -0
  215. package/dist/runtime/helpers/broadcastProvider.d.ts +7 -0
  216. package/dist/runtime/helpers/broadcastProvider.js +26 -0
  217. package/dist/runtime/helpers/commandsProvider.d.ts +9 -0
  218. package/dist/runtime/helpers/commandsProvider.js +16 -0
  219. package/dist/runtime/helpers/composables/defineCommands.d.ts +2 -0
  220. package/dist/runtime/helpers/composables/defineCommands.js +10 -0
  221. package/dist/runtime/helpers/composables/defineDropAreas.d.ts +2 -0
  222. package/dist/runtime/helpers/composables/defineDropAreas.js +10 -0
  223. package/dist/runtime/helpers/composables/defineShortcut.d.ts +2 -0
  224. package/dist/runtime/helpers/composables/defineShortcut.js +19 -0
  225. package/dist/runtime/helpers/composables/defineTourItem.d.ts +2 -0
  226. package/dist/runtime/helpers/composables/defineTourItem.js +10 -0
  227. package/dist/runtime/helpers/composables/onBlokkliEvent.d.ts +2 -0
  228. package/dist/runtime/helpers/composables/onBlokkliEvent.js +10 -0
  229. package/dist/runtime/helpers/composables/useAnimationFrame.d.ts +1 -0
  230. package/dist/runtime/helpers/composables/useAnimationFrame.js +14 -0
  231. package/dist/runtime/helpers/composables/useDebugLogger.d.ts +2 -0
  232. package/dist/runtime/helpers/composables/useDebugLogger.js +5 -0
  233. package/dist/runtime/helpers/composables/useDelayedIntersectionObserver.d.ts +5 -0
  234. package/dist/runtime/helpers/composables/useDelayedIntersectionObserver.js +26 -0
  235. package/dist/runtime/helpers/debugProvider.d.ts +23 -0
  236. package/dist/runtime/helpers/debugProvider.js +65 -0
  237. package/dist/runtime/helpers/dom/index.d.ts +5 -0
  238. package/dist/runtime/helpers/dom/index.js +37 -0
  239. package/dist/runtime/helpers/domProvider.d.ts +46 -0
  240. package/dist/runtime/helpers/domProvider.js +446 -0
  241. package/dist/runtime/helpers/dropAreaProvider.d.ts +9 -0
  242. package/dist/runtime/helpers/dropAreaProvider.js +22 -0
  243. package/dist/runtime/helpers/easing.d.ts +3 -0
  244. package/dist/runtime/helpers/easing.js +16 -0
  245. package/dist/runtime/helpers/eventBus.d.ts +3 -0
  246. package/dist/runtime/helpers/eventBus.js +5 -0
  247. package/dist/runtime/helpers/featuresProvider.d.ts +23 -0
  248. package/dist/runtime/helpers/featuresProvider.js +16 -0
  249. package/dist/runtime/helpers/frameEventBus.d.ts +9 -0
  250. package/dist/runtime/helpers/frameEventBus.js +2 -0
  251. package/dist/runtime/helpers/index.d.ts +87 -0
  252. package/dist/runtime/helpers/index.js +467 -0
  253. package/dist/runtime/helpers/keyboardProvider.d.ts +17 -0
  254. package/dist/runtime/helpers/keyboardProvider.js +79 -0
  255. package/dist/runtime/helpers/options.d.ts +2 -0
  256. package/dist/runtime/helpers/options.js +21 -0
  257. package/dist/runtime/helpers/runtimeHelpers/index.d.ts +10 -0
  258. package/dist/runtime/helpers/runtimeHelpers/index.js +35 -0
  259. package/dist/runtime/helpers/selectionProvider.d.ts +62 -0
  260. package/dist/runtime/helpers/selectionProvider.js +149 -0
  261. package/dist/runtime/helpers/stateProvider.d.ts +35 -0
  262. package/dist/runtime/helpers/stateProvider.js +226 -0
  263. package/dist/runtime/helpers/storageProvider.d.ts +15 -0
  264. package/dist/runtime/helpers/storageProvider.js +61 -0
  265. package/dist/runtime/helpers/symbols.d.ts +16 -0
  266. package/dist/runtime/helpers/symbols.js +18 -0
  267. package/dist/runtime/helpers/textProvider.d.ts +4 -0
  268. package/dist/runtime/helpers/textProvider.js +20 -0
  269. package/dist/runtime/helpers/themeProvider.d.ts +27 -0
  270. package/dist/runtime/helpers/themeProvider.js +124 -0
  271. package/dist/runtime/helpers/tourProvider.d.ts +11 -0
  272. package/dist/runtime/helpers/tourProvider.js +19 -0
  273. package/dist/runtime/helpers/transform.d.ts +2 -0
  274. package/dist/runtime/helpers/transform.js +17 -0
  275. package/dist/runtime/helpers/typesProvider.d.ts +36 -0
  276. package/dist/runtime/helpers/typesProvider.js +138 -0
  277. package/dist/runtime/helpers/uiProvider.d.ts +36 -0
  278. package/dist/runtime/helpers/uiProvider.js +278 -0
  279. package/dist/runtime/helpers/webgl/index.d.ts +32 -0
  280. package/dist/runtime/helpers/webgl/index.js +132 -0
  281. package/dist/runtime/icons/alert.svg +6 -0
  282. package/dist/runtime/icons/area.svg +5 -0
  283. package/dist/runtime/icons/arrow-down.svg +1 -0
  284. package/dist/runtime/icons/arrow-left.svg +1 -0
  285. package/dist/runtime/icons/arrow-right.svg +1 -0
  286. package/dist/runtime/icons/arrow-up.svg +1 -0
  287. package/dist/runtime/icons/artboard-disabled.svg +9 -0
  288. package/dist/runtime/icons/artboard-enabled.svg +29 -0
  289. package/dist/runtime/icons/artboard.svg +1 -0
  290. package/dist/runtime/icons/bug.svg +1 -0
  291. package/dist/runtime/icons/button-pointer.svg +1 -0
  292. package/dist/runtime/icons/caret.svg +12 -0
  293. package/dist/runtime/icons/cellphone.svg +1 -0
  294. package/dist/runtime/icons/chat-question.svg +1 -0
  295. package/dist/runtime/icons/check.svg +1 -0
  296. package/dist/runtime/icons/checkbox.svg +5 -0
  297. package/dist/runtime/icons/checks.svg +1 -0
  298. package/dist/runtime/icons/chevron-left.svg +1 -0
  299. package/dist/runtime/icons/chevron-right.svg +1 -0
  300. package/dist/runtime/icons/clipboard.svg +5 -0
  301. package/dist/runtime/icons/close.svg +5 -0
  302. package/dist/runtime/icons/cog.svg +5 -0
  303. package/dist/runtime/icons/command.svg +1 -0
  304. package/dist/runtime/icons/comment.svg +5 -0
  305. package/dist/runtime/icons/comment_add.svg +5 -0
  306. package/dist/runtime/icons/convert.svg +1 -0
  307. package/dist/runtime/icons/cursor-move.svg +1 -0
  308. package/dist/runtime/icons/dead.svg +1 -0
  309. package/dist/runtime/icons/delete.svg +8 -0
  310. package/dist/runtime/icons/detach.svg +7 -0
  311. package/dist/runtime/icons/drag.svg +1 -0
  312. package/dist/runtime/icons/duplicate.svg +12 -0
  313. package/dist/runtime/icons/edit.svg +8 -0
  314. package/dist/runtime/icons/exit.svg +6 -0
  315. package/dist/runtime/icons/expand.svg +1 -0
  316. package/dist/runtime/icons/file.svg +1 -0
  317. package/dist/runtime/icons/form.svg +1 -0
  318. package/dist/runtime/icons/fragment.svg +1 -0
  319. package/dist/runtime/icons/grid.svg +13 -0
  320. package/dist/runtime/icons/group.svg +5 -0
  321. package/dist/runtime/icons/help.svg +1 -0
  322. package/dist/runtime/icons/history.svg +1 -0
  323. package/dist/runtime/icons/image.svg +1 -0
  324. package/dist/runtime/icons/import.svg +5 -0
  325. package/dist/runtime/icons/laptop.svg +1 -0
  326. package/dist/runtime/icons/list-view-grid.svg +1 -0
  327. package/dist/runtime/icons/list-view-horizontal.svg +1 -0
  328. package/dist/runtime/icons/loader.svg +1 -0
  329. package/dist/runtime/icons/logo.svg +5 -0
  330. package/dist/runtime/icons/magnifier.svg +5 -0
  331. package/dist/runtime/icons/menu.svg +1 -0
  332. package/dist/runtime/icons/minus.svg +1 -0
  333. package/dist/runtime/icons/monitor.svg +1 -0
  334. package/dist/runtime/icons/multi-select.svg +1 -0
  335. package/dist/runtime/icons/multimedia.svg +1 -0
  336. package/dist/runtime/icons/opacity.svg +5 -0
  337. package/dist/runtime/icons/open_in_new.svg +3 -0
  338. package/dist/runtime/icons/palette.svg +1 -0
  339. package/dist/runtime/icons/plus-box.svg +1 -0
  340. package/dist/runtime/icons/plus.svg +1 -0
  341. package/dist/runtime/icons/preview.svg +5 -0
  342. package/dist/runtime/icons/publish.svg +12 -0
  343. package/dist/runtime/icons/puzzle.svg +1 -0
  344. package/dist/runtime/icons/qrcode.svg +5 -0
  345. package/dist/runtime/icons/question.svg +5 -0
  346. package/dist/runtime/icons/redo.svg +12 -0
  347. package/dist/runtime/icons/resize.svg +1 -0
  348. package/dist/runtime/icons/reusable.svg +5 -0
  349. package/dist/runtime/icons/revert.svg +5 -0
  350. package/dist/runtime/icons/robot.svg +1 -0
  351. package/dist/runtime/icons/rotate-phone.svg +1 -0
  352. package/dist/runtime/icons/sad.svg +1 -0
  353. package/dist/runtime/icons/save.svg +1 -0
  354. package/dist/runtime/icons/script.svg +1 -0
  355. package/dist/runtime/icons/scrolltotop.svg +6 -0
  356. package/dist/runtime/icons/search.svg +1 -0
  357. package/dist/runtime/icons/selection.svg +5 -0
  358. package/dist/runtime/icons/spinner.svg +15 -0
  359. package/dist/runtime/icons/star.svg +1 -0
  360. package/dist/runtime/icons/swap-horizontal.svg +1 -0
  361. package/dist/runtime/icons/tablet.svg +1 -0
  362. package/dist/runtime/icons/textbox.svg +1 -0
  363. package/dist/runtime/icons/texturebox.svg +5 -0
  364. package/dist/runtime/icons/tiktok.svg +1 -0
  365. package/dist/runtime/icons/title.svg +1 -0
  366. package/dist/runtime/icons/tools.svg +1 -0
  367. package/dist/runtime/icons/translate.svg +5 -0
  368. package/dist/runtime/icons/tree.svg +5 -0
  369. package/dist/runtime/icons/tutor.svg +1 -0
  370. package/dist/runtime/icons/ui-list-horizontal.svg +19 -0
  371. package/dist/runtime/icons/ui-list-sidebar.svg +21 -0
  372. package/dist/runtime/icons/ui-list-vertical.svg +9 -0
  373. package/dist/runtime/icons/undo.svg +12 -0
  374. package/dist/runtime/icons/unstar.svg +1 -0
  375. package/dist/runtime/icons/upload.svg +1 -0
  376. package/dist/runtime/icons/user.svg +1 -0
  377. package/dist/runtime/icons/video-outline.svg +1 -0
  378. package/dist/runtime/icons/vimeo.svg +3 -0
  379. package/dist/runtime/icons/window-maximize.svg +1 -0
  380. package/dist/runtime/icons/window-minimize.svg +1 -0
  381. package/dist/runtime/icons/youtube.svg +3 -0
  382. package/dist/runtime/plugins/blokkliEditable.d.ts +2 -0
  383. package/dist/runtime/plugins/blokkliEditable.js +31 -0
  384. package/dist/runtime/public/Inter.var.woff2 +0 -0
  385. package/dist/runtime/types/blokkOptions.d.ts +83 -0
  386. package/dist/runtime/types/blokkOptions.js +0 -0
  387. package/dist/runtime/types/generatedModuleTypes.d.ts +41 -0
  388. package/dist/runtime/types/generatedModuleTypes.js +0 -0
  389. package/dist/runtime/types/index.d.ts +1052 -0
  390. package/dist/runtime/types/index.js +1 -0
  391. package/dist/runtime/types/theme.d.ts +33 -0
  392. package/dist/runtime/types/theme.js +0 -0
  393. package/dist/types.d.mts +1 -0
  394. package/dist/types.d.ts +1 -0
  395. package/package.json +103 -0
@@ -0,0 +1,808 @@
1
+ <template>
2
+ <Teleport to="body">
3
+ <slot :color="active?.color" :label="active?.label" />
4
+ </Teleport>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ import {
9
+ falsy,
10
+ findClosestRectangle,
11
+ intersects,
12
+ isInsideRect,
13
+ rgbaToString,
14
+ toShaderColor,
15
+ } from '#blokkli/helpers'
16
+ import onBlokkliEvent from '#blokkli/helpers/composables/onBlokkliEvent'
17
+ import type {
18
+ DropTargetEvent,
19
+ BlokkliFieldElement,
20
+ DraggableItem,
21
+ DropArea,
22
+ Rectangle,
23
+ Coord,
24
+ } from '#blokkli/types'
25
+ import { ref, computed, useBlokkli, onBeforeUnmount } from '#imports'
26
+ import {
27
+ setBuffersAndAttributes,
28
+ drawBufferInfo,
29
+ setUniforms,
30
+ type BufferInfo,
31
+ } from 'twgl.js'
32
+ import vs from './vertex.glsl?raw'
33
+ import fs from './fragment.glsl?raw'
34
+ import { RectangleBufferCollector } from '#blokkli/helpers/webgl'
35
+
36
+ const props = defineProps<{
37
+ items: DraggableItem[]
38
+ box: Rectangle
39
+ mouseX: number
40
+ mouseY: number
41
+ isTouch: boolean
42
+ }>()
43
+
44
+ enum RectRenderType {
45
+ FIELD,
46
+ DROP_AREA,
47
+ }
48
+
49
+ type Orientation = 'horizontal' | 'vertical'
50
+
51
+ type FieldRectChild = Rectangle & {
52
+ id: string
53
+ label: string
54
+ }
55
+
56
+ type FieldRect = Rectangle & {
57
+ key: string
58
+ field: BlokkliFieldElement
59
+ label: string
60
+ canAddChildren: boolean
61
+ emptyChild?: FieldRectChild
62
+ orientation: Orientation
63
+ gap: number
64
+ childrenElements: HTMLElement[]
65
+ }
66
+
67
+ type DrawnRect = Rectangle & {
68
+ id: string
69
+ type: 'field' | 'drop-area'
70
+ label: string
71
+ color: string
72
+ colorAlpha: string
73
+ field?: FieldRect
74
+ index: number
75
+ }
76
+
77
+ const dragStart = Date.now()
78
+
79
+ const cursorIsInsideClipped = () =>
80
+ isInsideRect(props.mouseX, props.mouseY, ui.visibleViewport.value) &&
81
+ !ui.viewportBlockingRects.value.some((v) =>
82
+ isInsideRect(props.mouseX, props.mouseY, v),
83
+ )
84
+
85
+ const active = ref<DrawnRect | null>(null)
86
+
87
+ defineEmits<{
88
+ (e: 'drop', data: DropTargetEvent): void
89
+ }>()
90
+
91
+ const {
92
+ dom,
93
+ ui,
94
+ theme,
95
+ dropAreas,
96
+ eventBus,
97
+ animation,
98
+ state,
99
+ runtimeConfig,
100
+ types,
101
+ } = useBlokkli()
102
+
103
+ const gl = animation.gl()
104
+ const canvas = animation.getCanvasElement()
105
+ const ctx: CanvasRenderingContext2D | null =
106
+ !gl && canvas ? canvas.getContext('2d') : null
107
+
108
+ const programInfo = gl
109
+ ? animation.registerProgram('drop_targets', gl, [vs, fs])
110
+ : null
111
+
112
+ const areas = dropAreas
113
+ .getDropAreas(props.items)
114
+ .reduce<Record<string, DropArea>>((acc, v) => {
115
+ acc[v.id] = v
116
+ return acc
117
+ }, {})
118
+
119
+ const visibleDropAreas: Set<string> = new Set()
120
+
121
+ const areasObserver = new IntersectionObserver(
122
+ (entries) => {
123
+ for (const entry of entries) {
124
+ if (entry.target instanceof HTMLElement) {
125
+ const id = entry.target.dataset.dropAreaId
126
+ if (id) {
127
+ if (entry.isIntersecting) {
128
+ visibleDropAreas.add(id)
129
+ } else {
130
+ visibleDropAreas.delete(id)
131
+ }
132
+ }
133
+ }
134
+ }
135
+ },
136
+ {
137
+ threshold: 0,
138
+ },
139
+ )
140
+
141
+ Object.values(areas).forEach((area) => {
142
+ area.element.dataset.dropAreaId = area.id
143
+ areasObserver.observe(area.element)
144
+ })
145
+
146
+ onBlokkliEvent('mouse:down', (e) => {
147
+ const coord = toCanvasSpaceCoordinates(e.x, e.y)
148
+ const match = collector.getRectAtPosition(coord)
149
+ active.value = match || null
150
+ })
151
+
152
+ onBlokkliEvent('mouse:up', (e) => {
153
+ if (!active.value) {
154
+ return
155
+ }
156
+
157
+ // On touch devices, if the distance is greater than the threshold, the user
158
+ // has likely interacted with the artboard (panning, zooming).
159
+ if (props.isTouch && e.distance > 10) {
160
+ active.value = null
161
+ return
162
+ }
163
+
164
+ // On desktop, only emit drop if the distance is greater than the threshold.
165
+ // This prevents accidentally moving a block.
166
+ if (!props.isTouch && e.distance < 7) {
167
+ return
168
+ }
169
+
170
+ emitDrop()
171
+ })
172
+
173
+ const emitDrop = async () => {
174
+ const timeDelta = Date.now() - dragStart
175
+ // Prevent accidental drops. At least 400ms should have passed between the
176
+ // time the drag was initiated and when the drop was made.
177
+ if (active.value && timeDelta > 400) {
178
+ if (active.value.type === 'field') {
179
+ const [hostUuid, fieldName, preceedingUuid] = active.value.id.split(':')
180
+
181
+ const field = dom.findField(hostUuid, fieldName)
182
+
183
+ if (!field) {
184
+ return
185
+ }
186
+
187
+ eventBus.emit('dragging:drop', {
188
+ field,
189
+ preceedingUuid,
190
+ items: [...props.items],
191
+ host: {
192
+ type: field.hostEntityType,
193
+ uuid: field.hostEntityUuid,
194
+ fieldName: field.name,
195
+ },
196
+ })
197
+ return
198
+ } else if (active.value.type === 'drop-area') {
199
+ const area = areas[active.value.id]
200
+ if (!area) {
201
+ return
202
+ }
203
+ await area.onDrop()
204
+ }
205
+ }
206
+
207
+ eventBus.emit('dragging:end')
208
+ eventBus.emit('item:dropped')
209
+ }
210
+
211
+ function getChildrenOrientation(element: HTMLElement): Orientation {
212
+ const computedStyle = window.getComputedStyle(element)
213
+
214
+ // Check for Flex layout
215
+ if (computedStyle.display.includes('flex')) {
216
+ // Flex direction row or row-reverse indicates horizontal layout
217
+ if (
218
+ computedStyle.flexDirection === 'row' ||
219
+ computedStyle.flexDirection === 'row-reverse'
220
+ ) {
221
+ return 'horizontal'
222
+ } else {
223
+ // Otherwise, it's vertical
224
+ return 'vertical'
225
+ }
226
+ }
227
+
228
+ // Check for Grid layout
229
+ if (computedStyle.display.includes('grid')) {
230
+ // We'll need to check the grid-template-columns and grid-template-rows
231
+ // This is a simple check, assuming a basic grid layout
232
+ if (computedStyle.gridTemplateColumns.split(' ').length > 1) {
233
+ return 'horizontal'
234
+ } else {
235
+ return 'vertical'
236
+ }
237
+ }
238
+
239
+ // Default to vertical for block elements and other displays
240
+ return 'vertical'
241
+ }
242
+
243
+ /**
244
+ * The bundles being dragged.
245
+ *
246
+ * In case of dragging a from_library block, the bundle of the reusable block is also returned here.
247
+ */
248
+ const draggingBundles = computed<string[]>(() =>
249
+ props.items
250
+ .flatMap((item) => {
251
+ const bundles: string[] = []
252
+ if ('itemBundle' in item && item.itemBundle) {
253
+ bundles.push(item.itemBundle)
254
+ }
255
+ if ('reusableBundle' in item && item.reusableBundle) {
256
+ bundles.push(item.reusableBundle)
257
+ }
258
+ return bundles
259
+ })
260
+ .filter(falsy),
261
+ )
262
+
263
+ const selectionUuids = computed<string[]>(() =>
264
+ props.items
265
+ .map((item) => {
266
+ if (item.itemType === 'existing') {
267
+ return item.uuid
268
+ }
269
+ })
270
+ .filter(falsy),
271
+ )
272
+
273
+ function getGapSize(orientation: Orientation, element: HTMLElement): number {
274
+ const computedStyle = window.getComputedStyle(element)
275
+
276
+ // Check for Grid or Flex layout
277
+ if (
278
+ computedStyle.display.includes('grid') ||
279
+ computedStyle.display.includes('flex')
280
+ ) {
281
+ const gap =
282
+ orientation === 'vertical'
283
+ ? computedStyle.columnGap || computedStyle.gridColumnGap
284
+ : computedStyle.rowGap || computedStyle.gridRowGap
285
+
286
+ if (gap) {
287
+ // Extract the first value.
288
+ const gapParts = gap.split(' ')
289
+ const gapValue = gapParts[0]
290
+ if (gapValue.endsWith('px')) {
291
+ return Number.parseFloat(gapValue)
292
+ }
293
+ }
294
+ }
295
+
296
+ return 30
297
+ }
298
+
299
+ const fieldChildCache: Record<string, FieldRectChild[]> = {}
300
+
301
+ const buildChildId = (
302
+ field: BlokkliFieldElement,
303
+ preceedingUuid?: string | undefined | null,
304
+ type?: string | undefined | null,
305
+ uuid?: string | undefined | null,
306
+ ) => {
307
+ return `${field.key}:${preceedingUuid || ''}:${type || ''}:${uuid || ''}`
308
+ }
309
+
310
+ const buildChildren = (
311
+ field: FieldRect,
312
+ visible: string[],
313
+ ): FieldRectChild[] => {
314
+ if (!field.canAddChildren) {
315
+ return []
316
+ }
317
+
318
+ if (field.emptyChild) {
319
+ return [field.emptyChild]
320
+ }
321
+
322
+ const children: FieldRectChild[] = []
323
+
324
+ let prevWasInSelection = false
325
+ let prevUuid: string | undefined = ''
326
+
327
+ for (let i = 0; i < field.childrenElements.length; i++) {
328
+ const childrenForUuid: FieldRectChild[] = []
329
+
330
+ const isLast = i === field.childrenElements.length - 1
331
+
332
+ const el = field.childrenElements[i]
333
+ if (!(el instanceof HTMLElement)) {
334
+ continue
335
+ }
336
+
337
+ const uuid = el.dataset.uuid
338
+ if (!uuid) {
339
+ continue
340
+ }
341
+
342
+ if (!visible.includes(uuid)) {
343
+ prevUuid = uuid
344
+ continue
345
+ }
346
+
347
+ const cached = fieldChildCache[uuid]
348
+ if (cached) {
349
+ children.push(...cached)
350
+ prevUuid = uuid
351
+ continue
352
+ }
353
+
354
+ // Skip child if it's part of the selection.
355
+ if (selectionUuids.value.includes(uuid)) {
356
+ prevWasInSelection = true
357
+ prevUuid = uuid
358
+ continue
359
+ }
360
+
361
+ // Last element.
362
+ if (isLast) {
363
+ const id = buildChildId(field.field, uuid, 'last', uuid)
364
+ if (field.orientation === 'vertical') {
365
+ childrenForUuid.push({
366
+ id,
367
+ width: field.width,
368
+ height: field.gap,
369
+ x: 0,
370
+ y: el.offsetTop + el.scrollHeight,
371
+ label: field.label,
372
+ })
373
+ } else {
374
+ childrenForUuid.push({
375
+ id,
376
+ width: field.gap,
377
+ height: el.offsetHeight,
378
+ x: el.offsetLeft + el.offsetWidth,
379
+ y: el.offsetTop,
380
+ label: field.label,
381
+ })
382
+ }
383
+ }
384
+
385
+ // If the previous element was part of the selection, don't add a child,
386
+ // because the move operation would result in the same position.
387
+ if (prevWasInSelection) {
388
+ prevWasInSelection = false
389
+ prevUuid = uuid
390
+ children.push(...childrenForUuid)
391
+ continue
392
+ }
393
+
394
+ const id = buildChildId(field.field, prevUuid, 'between', uuid)
395
+
396
+ if (field.orientation === 'vertical') {
397
+ childrenForUuid.push({
398
+ id,
399
+ width: field.width,
400
+ height: field.gap,
401
+ x: 0,
402
+ y: el.offsetTop - field.gap / 2,
403
+ label: field.label,
404
+ })
405
+ } else {
406
+ childrenForUuid.push({
407
+ id,
408
+ width: field.gap,
409
+ height: Math.max(el.offsetHeight, 30),
410
+ x: Math.max(el.offsetLeft - field.gap, -field.gap),
411
+ y: el.offsetTop,
412
+ label: field.label,
413
+ })
414
+ }
415
+
416
+ fieldChildCache[uuid] = childrenForUuid
417
+
418
+ children.push(...childrenForUuid)
419
+
420
+ prevUuid = uuid
421
+ }
422
+ return children
423
+ }
424
+
425
+ const fieldCache: Record<string, FieldRect> = {}
426
+
427
+ function getBundleLabel(field: BlokkliFieldElement): string {
428
+ if (field.hostEntityType === runtimeConfig.itemEntityType) {
429
+ return (
430
+ types.getBlockBundleDefinition(field.hostEntityBundle)?.label ||
431
+ field.hostEntityBundle
432
+ )
433
+ }
434
+
435
+ return state.entity.value.bundleLabel || field.hostEntityBundle
436
+ }
437
+
438
+ function getInsertText(field: BlokkliFieldElement): string {
439
+ const bundleLabel = getBundleLabel(field)
440
+ return `${bundleLabel} » <strong>${field.label}</strong>`
441
+ }
442
+
443
+ const determineCanAddChildren = (
444
+ field: BlokkliFieldElement,
445
+ children: HTMLElement[],
446
+ ) => {
447
+ // Check cardinality of field.
448
+ if (field.cardinality !== -1) {
449
+ // Current block count.
450
+ const count = state.getFieldBlockCount(field.key)
451
+
452
+ // Count of children that are also part of the selection.
453
+ const childrenThatAreSelection = children.filter((child) => {
454
+ const uuid = child.dataset.uuid
455
+ if (!uuid) {
456
+ return false
457
+ }
458
+ return selectionUuids.value.includes(uuid)
459
+ }).length
460
+ const countAfter = count - childrenThatAreSelection + props.items.length
461
+ if (countAfter > field.cardinality) {
462
+ return false
463
+ }
464
+ }
465
+
466
+ return (
467
+ !draggingBundles.value.length ||
468
+ draggingBundles.value.every((bundle) =>
469
+ field.allowedBundles.includes(bundle),
470
+ )
471
+ )
472
+ }
473
+
474
+ const buildEmptyChild = (
475
+ field: BlokkliFieldElement,
476
+ children: HTMLElement[],
477
+ orientation: Orientation,
478
+ fieldWidth: number,
479
+ fieldHeight: number,
480
+ ): FieldRectChild | undefined => {
481
+ if (children.length === 0) {
482
+ const id = buildChildId(field, null, 'empty')
483
+ if (orientation === 'horizontal') {
484
+ return {
485
+ id,
486
+ x: 0,
487
+ y: 0,
488
+ width: fieldWidth,
489
+ height: fieldHeight,
490
+ label: getInsertText(field),
491
+ }
492
+ } else {
493
+ return {
494
+ id,
495
+ x: 0,
496
+ y: 0,
497
+ width: fieldWidth,
498
+ height: fieldHeight > 30 ? 0 : 30,
499
+ label: getInsertText(field),
500
+ }
501
+ }
502
+ }
503
+ }
504
+
505
+ const buildFieldRect = (key: string): FieldRect | undefined => {
506
+ if (fieldCache[key]) {
507
+ return fieldCache[key]
508
+ }
509
+
510
+ const [uuid, name] = key.split(':')
511
+ const field = dom.findField(uuid, name)
512
+ if (!field) {
513
+ return
514
+ }
515
+ const childElements = [...field.element.children] as HTMLElement[]
516
+
517
+ const canAddChildren = determineCanAddChildren(field, childElements)
518
+ const orientation =
519
+ field.dropAlignment || getChildrenOrientation(field.element)
520
+
521
+ const rect = dom.getFieldRect(field.key)
522
+ if (!rect) {
523
+ throw new Error('Failed to get rect for field: ' + field.key)
524
+ }
525
+ const x = rect.x
526
+ const y = rect.y
527
+ const height = Math.max(rect.height, 30)
528
+ const width = Math.max(rect.width, 30)
529
+ const emptyChild = buildEmptyChild(
530
+ field,
531
+ childElements,
532
+ orientation,
533
+ width,
534
+ height,
535
+ )
536
+ const gap = Math.max(getGapSize(orientation, field.element), 30)
537
+
538
+ const fieldRect = {
539
+ key: field.key,
540
+ field,
541
+ width,
542
+ height,
543
+ x,
544
+ y,
545
+ label: getInsertText(field),
546
+ canAddChildren,
547
+ emptyChild,
548
+ orientation,
549
+ gap,
550
+ childrenElements: childElements,
551
+ }
552
+
553
+ fieldCache[key] = fieldRect
554
+ return fieldRect
555
+ }
556
+
557
+ const cachedDropAreaRects: Record<string, Rectangle> = {}
558
+
559
+ const buildDropAreaRect = (area: DropArea): Rectangle => {
560
+ if (cachedDropAreaRects[area.id]) {
561
+ return cachedDropAreaRects[area.id]
562
+ }
563
+
564
+ const rect = ui.getAbsoluteElementRect(area.element)
565
+
566
+ const dropAreaRect: Rectangle = {
567
+ x: rect.x,
568
+ y: rect.y,
569
+ width: Math.max(rect.width, 30),
570
+ height: Math.max(rect.height, 30),
571
+ }
572
+
573
+ cachedDropAreaRects[area.id] = dropAreaRect
574
+ return dropAreaRect
575
+ }
576
+
577
+ const colorTeal = rgbaToString(theme.teal.value.normal)
578
+ const colorTealAlpha = rgbaToString(theme.teal.value.normal, 0.7)
579
+ const colorAccent = rgbaToString(theme.accent.value[800])
580
+ const colorAccentAlpha = rgbaToString(theme.accent.value[800], 0.7)
581
+
582
+ class DropTargetRectangleBufferCollector extends RectangleBufferCollector<DrawnRect> {
583
+ getBufferInfo(): { info: BufferInfo | null; hasChanged: boolean } {
584
+ const visibleFields = dom.getVisibleFields()
585
+ const visibleBlocks = dom.getVisibleBlocks()
586
+
587
+ const lengthBefore = this.positions.length
588
+
589
+ for (let i = 0; i < visibleFields.length; i++) {
590
+ const key = visibleFields[i]
591
+ const fieldRect = buildFieldRect(key)
592
+ if (!fieldRect) {
593
+ continue
594
+ }
595
+ const children = buildChildren(fieldRect, visibleBlocks)
596
+ for (let j = 0; j < children.length; j++) {
597
+ const child = children[j]
598
+ if (this.added.has(child.id)) {
599
+ continue
600
+ }
601
+ this.addRectangle(
602
+ {
603
+ id: child.id,
604
+ type: 'field',
605
+ label: child.label,
606
+ color: colorAccent,
607
+ colorAlpha: colorAccentAlpha,
608
+ x: fieldRect.x + child.x,
609
+ y: fieldRect.y + child.y,
610
+ width: child.width,
611
+ height: child.height,
612
+ field: fieldRect,
613
+ },
614
+ RectRenderType.FIELD,
615
+ )
616
+ }
617
+ }
618
+
619
+ const visibleAreas = Array.from(visibleDropAreas)
620
+
621
+ for (let i = 0; i < visibleAreas.length; i++) {
622
+ const area = areas[visibleAreas[i]]
623
+ if (!area) {
624
+ continue
625
+ }
626
+ if (this.added.has(area.id)) {
627
+ continue
628
+ }
629
+ const areaRect = buildDropAreaRect(area)
630
+
631
+ this.addRectangle(
632
+ {
633
+ id: area.id,
634
+ type: 'drop-area',
635
+ label: area.label,
636
+ color: colorTeal,
637
+ colorAlpha: colorTealAlpha,
638
+ x: areaRect.x,
639
+ y: areaRect.y,
640
+ width: areaRect.width,
641
+ height: areaRect.height,
642
+ },
643
+ RectRenderType.DROP_AREA,
644
+ )
645
+ }
646
+
647
+ const hasChanged = lengthBefore !== this.positions.length
648
+
649
+ // Only update the buffer info if it has changed.
650
+ if (hasChanged) {
651
+ this.bufferInfo = this.createBufferInfo()
652
+ }
653
+
654
+ return { info: this.bufferInfo, hasChanged }
655
+ }
656
+
657
+ getClosestIntersectingRect(box: Rectangle, coords: Coord): DrawnRect | null {
658
+ const candidates: DrawnRect[] = []
659
+ const rects = Object.values(this.rects)
660
+ for (let i = 0; i < rects.length; i++) {
661
+ const rect = rects[i]
662
+ if (intersects(box, rect)) {
663
+ candidates.push(rect)
664
+ }
665
+ }
666
+
667
+ if (candidates.length === 0) {
668
+ return null
669
+ } else if (candidates.length === 1) {
670
+ return candidates[0]
671
+ }
672
+
673
+ return findClosestRectangle(coords.x, coords.y, candidates)
674
+ }
675
+
676
+ getRectAtPosition(coord: Coord): DrawnRect | null {
677
+ const rects = Object.values(this.rects)
678
+
679
+ for (let i = 0; i < rects.length; i++) {
680
+ const rect = rects[i]
681
+ if (isInsideRect(coord.x, coord.y, rect)) {
682
+ return rect
683
+ }
684
+ }
685
+
686
+ return null
687
+ }
688
+ }
689
+
690
+ const collector = new DropTargetRectangleBufferCollector(gl)
691
+
692
+ const uniforms = computed(() => {
693
+ const index = active.value?.index
694
+ return {
695
+ u_color_field_active: toShaderColor(theme.accent.value[700]),
696
+ u_color_field_default: toShaderColor(theme.mono.value[400]),
697
+ u_color_area_active: toShaderColor(theme.teal.value.normal),
698
+ u_color_area_default: toShaderColor(theme.teal.value.normal),
699
+ u_active_rect_id: index === undefined ? -1 : index,
700
+ }
701
+ })
702
+
703
+ const dragBox = ref<Rectangle>({
704
+ x: 0,
705
+ y: 0,
706
+ width: 0,
707
+ height: 0,
708
+ })
709
+
710
+ function toCanvasSpaceCoordinates(x: number, y: number): Coord {
711
+ const scale = ui.artboardScale.value
712
+ const offset = { ...ui.artboardOffset.value }
713
+ return {
714
+ x: (x - offset.x) / scale,
715
+ y: (y - offset.y) / scale,
716
+ }
717
+ }
718
+
719
+ onBlokkliEvent('canvas:draw', () => {
720
+ const scale = ui.artboardScale.value
721
+ const offset = { ...ui.artboardOffset.value }
722
+
723
+ dragBox.value = {
724
+ x: (props.box.x - offset.x) / scale,
725
+ y: (props.box.y - offset.y) / scale,
726
+ width: props.box.width / scale,
727
+ height: props.box.height / scale,
728
+ }
729
+
730
+ const mouseAbsolute = toCanvasSpaceCoordinates(props.mouseX, props.mouseY)
731
+
732
+ if (gl && programInfo) {
733
+ gl.useProgram(programInfo.program)
734
+ animation.setSharedUniforms(gl, programInfo)
735
+ }
736
+
737
+ const isInsideClipped = cursorIsInsideClipped()
738
+
739
+ if (!props.isTouch) {
740
+ if (isInsideClipped) {
741
+ const closest = collector.getClosestIntersectingRect(
742
+ dragBox.value,
743
+ mouseAbsolute,
744
+ )
745
+
746
+ active.value = closest || null
747
+ } else {
748
+ active.value = null
749
+ }
750
+ }
751
+
752
+ const { info, hasChanged } = collector.getBufferInfo()
753
+
754
+ // WebGL rendering.
755
+ if (programInfo && gl) {
756
+ setUniforms(programInfo, uniforms.value)
757
+
758
+ // Nothing to draw.
759
+ if (info) {
760
+ // Only update buffer and attributes when they have changed.
761
+ if (hasChanged && gl && programInfo) {
762
+ setBuffersAndAttributes(gl, programInfo, info)
763
+ }
764
+
765
+ if (gl) {
766
+ drawBufferInfo(gl, info, gl.TRIANGLES)
767
+ }
768
+ }
769
+
770
+ return
771
+ }
772
+
773
+ // Fallback rendering.
774
+ if (!ctx) {
775
+ return
776
+ }
777
+
778
+ ctx.clearRect(0, 0, canvas.width, canvas.height)
779
+
780
+ const rects = Object.values(collector.rects)
781
+
782
+ for (let i = 0; i < rects.length; i++) {
783
+ const rect = rects[i]
784
+ if (active.value?.id === rect.id) {
785
+ ctx.fillStyle = rect.color
786
+ } else {
787
+ ctx.fillStyle = rect.colorAlpha
788
+ }
789
+
790
+ ctx.fillRect(
791
+ (rect.x * scale + offset.x) * animation.dpi.value,
792
+ (rect.y * scale + offset.y) * animation.dpi.value,
793
+ rect.width * animation.dpi.value * scale,
794
+ rect.height * animation.dpi.value * scale,
795
+ )
796
+ }
797
+ })
798
+
799
+ onBeforeUnmount(() => {
800
+ if (gl) {
801
+ gl.clear(gl.COLOR_BUFFER_BIT)
802
+ }
803
+
804
+ if (ctx) {
805
+ ctx.clearRect(0, 0, canvas.width, canvas.height)
806
+ }
807
+ })
808
+ </script>