@blokkli/editor 2.0.0-alpha.13 → 2.0.0-alpha.15

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 (289) hide show
  1. package/dist/module.d.mts +1 -1
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +4873 -1167
  4. package/dist/modules/drupal/graphql/base/fragment.ParagraphsBlokkliConfigInput.graphql +31 -0
  5. package/dist/modules/drupal/graphql/base/fragment.blokkliProps.graphql +1 -0
  6. package/dist/modules/drupal/graphql/base/fragment.paragraphsBlokkliEditState.graphql +5 -0
  7. package/dist/modules/drupal/graphql/base/query.pbEntityConfig.graphql +5 -0
  8. package/dist/modules/drupal/graphql/features/publishNew.graphql +1 -4
  9. package/dist/modules/drupal/graphql/features/scheduler.graphql +31 -0
  10. package/dist/modules/drupal/graphql/features/transform.graphql +9 -1
  11. package/dist/modules/drupal/graphql/features/transform_host.graphql +38 -0
  12. package/dist/modules/drupal/graphql/mutations/update_host_options.graphql +15 -0
  13. package/dist/modules/drupal/index.d.mts +1 -1
  14. package/dist/modules/drupal/index.mjs +37 -7
  15. package/dist/modules/drupal/runtime/adapter/index.js +140 -5
  16. package/dist/runtime/adapter/index.d.ts +90 -1
  17. package/dist/runtime/blokkliPlugins/AddAction/index.vue +27 -3
  18. package/dist/runtime/blokkliPlugins/BlockIndicator/index.vue +65 -0
  19. package/dist/runtime/blokkliPlugins/BlockIndicator/index.vue.d.ts +26 -0
  20. package/dist/runtime/blokkliPlugins/ContextMenu/Menu/index.vue +3 -0
  21. package/dist/runtime/blokkliPlugins/ContextMenu/index.vue +3 -2
  22. package/dist/runtime/blokkliPlugins/DroppableEdit/index.vue +3 -3
  23. package/dist/runtime/blokkliPlugins/ItemDropdown/index.vue +49 -11
  24. package/dist/runtime/blokkliPlugins/ItemDropdown/index.vue.d.ts +29 -15
  25. package/dist/runtime/blokkliPlugins/MenuButton/index.vue.d.ts +2 -2
  26. package/dist/runtime/blokkliPlugins/Sidebar/Detached/index.vue +6 -7
  27. package/dist/runtime/blokkliPlugins/Sidebar/index.vue +2 -9
  28. package/dist/runtime/blokkliPlugins/Sidebar/index.vue.d.ts +1 -1
  29. package/dist/runtime/blokkliPlugins/ViewOption/index.vue +6 -3
  30. package/dist/runtime/blokkliPlugins/index.d.ts +8 -7
  31. package/dist/runtime/blokkliPlugins/index.js +15 -13
  32. package/dist/runtime/components/Blocks/Fragment/icon.svg +1 -1
  33. package/dist/runtime/components/BlokkliProvider.vue +1 -0
  34. package/dist/runtime/components/BlokkliProvider.vue.d.ts +1 -0
  35. package/dist/runtime/components/Edit/Actions/index.vue +39 -67
  36. package/dist/runtime/components/Edit/AddListItem/index.vue +2 -5
  37. package/dist/runtime/components/Edit/AddListItem/index.vue.d.ts +1 -1
  38. package/dist/runtime/components/Edit/AddListItemIcon/index.vue +19 -0
  39. package/dist/runtime/components/Edit/AddListItemIcon/index.vue.d.ts +15 -0
  40. package/dist/runtime/components/Edit/AppMenu/index.vue +5 -5
  41. package/dist/runtime/components/Edit/Dialog/index.vue +5 -1
  42. package/dist/runtime/components/Edit/Dialog/index.vue.d.ts +1 -1
  43. package/dist/runtime/components/Edit/DiffViewer/State.vue +276 -0
  44. package/dist/runtime/components/Edit/DiffViewer/State.vue.d.ts +16 -0
  45. package/dist/runtime/components/Edit/DragInteractions/index.vue +35 -6
  46. package/dist/runtime/components/Edit/EditProvider.vue +46 -35
  47. package/dist/runtime/components/Edit/Features/AddList/index.vue +15 -25
  48. package/dist/runtime/components/Edit/Features/Analyze/Overlay/fragment.glsl +58 -0
  49. package/dist/runtime/components/Edit/Features/Analyze/Overlay/index.vue +168 -0
  50. package/dist/runtime/components/Edit/Features/Analyze/Overlay/index.vue.d.ts +9 -0
  51. package/dist/runtime/components/Edit/Features/Analyze/Overlay/vertex.glsl +72 -0
  52. package/dist/runtime/components/Edit/Features/Analyze/Renderer.vue +159 -0
  53. package/dist/runtime/components/Edit/Features/Analyze/Renderer.vue.d.ts +7 -0
  54. package/dist/runtime/components/Edit/Features/Analyze/Results/Results.vue +100 -0
  55. package/dist/runtime/components/Edit/Features/Analyze/Results/Results.vue.d.ts +6 -0
  56. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItem.vue +56 -0
  57. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItem.vue.d.ts +3 -0
  58. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItemNodes.vue +87 -0
  59. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItemNodes.vue.d.ts +7 -0
  60. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItemNodesTarget.vue +101 -0
  61. package/dist/runtime/components/Edit/Features/Analyze/Results/ResultsItemNodesTarget.vue.d.ts +8 -0
  62. package/dist/runtime/components/Edit/Features/Analyze/Results/Status.vue +18 -0
  63. package/dist/runtime/components/Edit/Features/Analyze/Results/Status.vue.d.ts +8 -0
  64. package/dist/runtime/components/Edit/Features/Analyze/Summary/Chart.vue +92 -0
  65. package/dist/runtime/components/Edit/Features/Analyze/Summary/Chart.vue.d.ts +17 -0
  66. package/dist/runtime/components/Edit/Features/Analyze/Summary/index.vue +77 -0
  67. package/dist/runtime/components/Edit/Features/Analyze/Summary/index.vue.d.ts +6 -0
  68. package/dist/runtime/components/Edit/Features/Analyze/analyzers/axe.d.ts +12 -0
  69. package/dist/runtime/components/Edit/Features/Analyze/analyzers/axe.js +75 -0
  70. package/dist/runtime/components/Edit/Features/Analyze/analyzers/defineAnalyzer.d.ts +4 -0
  71. package/dist/runtime/components/Edit/Features/Analyze/analyzers/defineAnalyzer.js +5 -0
  72. package/dist/runtime/components/Edit/Features/Analyze/analyzers/helpers/Context.d.ts +32 -0
  73. package/dist/runtime/components/Edit/Features/Analyze/analyzers/helpers/Context.js +45 -0
  74. package/dist/runtime/components/Edit/Features/Analyze/analyzers/helpers/collectTextElements.d.ts +5 -0
  75. package/dist/runtime/components/Edit/Features/Analyze/analyzers/helpers/collectTextElements.js +95 -0
  76. package/dist/runtime/components/Edit/Features/Analyze/analyzers/helpers/normalizeArray.d.ts +3 -0
  77. package/dist/runtime/components/Edit/Features/Analyze/analyzers/helpers/normalizeArray.js +13 -0
  78. package/dist/runtime/components/Edit/Features/Analyze/analyzers/index.d.ts +2 -0
  79. package/dist/runtime/components/Edit/Features/Analyze/analyzers/index.js +2 -0
  80. package/dist/runtime/components/Edit/Features/Analyze/analyzers/readability.d.ts +2 -0
  81. package/dist/runtime/components/Edit/Features/Analyze/analyzers/readability.js +165 -0
  82. package/dist/runtime/components/Edit/Features/Analyze/analyzers/types.d.ts +44 -0
  83. package/dist/runtime/components/Edit/Features/Analyze/analyzers/types.js +0 -0
  84. package/dist/runtime/components/Edit/Features/Analyze/helper.d.ts +5 -0
  85. package/dist/runtime/components/Edit/Features/Analyze/helper.js +28 -0
  86. package/dist/runtime/components/Edit/Features/Analyze/index.vue +44 -0
  87. package/dist/runtime/components/Edit/Features/Anchors/Renderer.vue +136 -0
  88. package/dist/runtime/components/Edit/Features/Anchors/index.vue +32 -0
  89. package/dist/runtime/components/Edit/Features/Anchors/index.vue.d.ts +2 -0
  90. package/dist/runtime/components/Edit/Features/Artboard/Overview/index.vue +25 -13
  91. package/dist/runtime/components/Edit/Features/Artboard/Renderer.vue +296 -0
  92. package/dist/runtime/components/Edit/Features/Artboard/Renderer.vue.d.ts +7 -0
  93. package/dist/runtime/components/Edit/Features/Artboard/index.vue +10 -245
  94. package/dist/runtime/components/Edit/Features/Assistant/index.vue +3 -2
  95. package/dist/runtime/components/Edit/Features/BlockAddList/index.vue +4 -4
  96. package/dist/runtime/components/Edit/Features/Clipboard/index.vue +161 -28
  97. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Group/index.vue +16 -4
  98. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/Group/index.vue.d.ts +0 -1
  99. package/dist/runtime/components/Edit/Features/CommandPalette/Palette/index.vue +4 -53
  100. package/dist/runtime/components/Edit/Features/CommandPalette/index.vue +3 -2
  101. package/dist/runtime/components/Edit/Features/Conversions/index.vue +12 -14
  102. package/dist/runtime/components/Edit/Features/Debug/Viewport/index.vue +14 -0
  103. package/dist/runtime/components/Edit/Features/Debug/index.vue +27 -24
  104. package/dist/runtime/components/Edit/Features/Diff/DiffView/index.vue +13 -190
  105. package/dist/runtime/components/Edit/Features/Diff/index.vue +2 -2
  106. package/dist/runtime/components/Edit/Features/DraggingOverlay/DragItems/index.vue +4 -4
  107. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/fragment.glsl +1 -1
  108. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/index.vue +35 -71
  109. package/dist/runtime/components/Edit/Features/DraggingOverlay/DropTargets/vertex.glsl +1 -1
  110. package/dist/runtime/components/Edit/Features/DraggingOverlay/index.vue +62 -48
  111. package/dist/runtime/components/Edit/Features/EditForm/Frame/index.vue +3 -3
  112. package/dist/runtime/components/Edit/Features/EditForm/index.vue +3 -3
  113. package/dist/runtime/components/Edit/Features/EditableField/index.vue +6 -2
  114. package/dist/runtime/components/Edit/Features/EditableMask/index.vue +3 -20
  115. package/dist/runtime/components/Edit/Features/EntityTitle/index.vue +33 -1
  116. package/dist/runtime/components/Edit/Features/Fragments/index.vue +3 -2
  117. package/dist/runtime/components/Edit/Features/History/index.vue +35 -12
  118. package/dist/runtime/components/Edit/Features/ImportExisting/Dialog/index.vue +6 -2
  119. package/dist/runtime/components/Edit/Features/ImportExisting/index.vue +3 -2
  120. package/dist/runtime/components/Edit/Features/Library/index.vue +11 -9
  121. package/dist/runtime/components/Edit/Features/MediaLibrary/Library/index.vue +5 -8
  122. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/fragment.glsl +1 -1
  123. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/index.vue +9 -4
  124. package/dist/runtime/components/Edit/Features/MultiSelect/Overlay/vertex.glsl +1 -1
  125. package/dist/runtime/components/Edit/Features/MultiSelect/index.vue +8 -14
  126. package/dist/runtime/components/Edit/Features/Options/Form/Checkbox/index.vue +3 -2
  127. package/dist/runtime/components/Edit/Features/Options/Form/Checkbox/index.vue.d.ts +2 -0
  128. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue +9 -3
  129. package/dist/runtime/components/Edit/Features/Options/Form/Item.vue.d.ts +0 -1
  130. package/dist/runtime/components/Edit/Features/Options/Form/Radios/index.vue +37 -19
  131. package/dist/runtime/components/Edit/Features/Options/Form/Radios/index.vue.d.ts +8 -2
  132. package/dist/runtime/components/Edit/Features/Options/Form/index.vue +81 -37
  133. package/dist/runtime/components/Edit/Features/Options/Form/index.vue.d.ts +5 -5
  134. package/dist/runtime/components/Edit/Features/Options/index.vue +30 -6
  135. package/dist/runtime/components/Edit/Features/PreviewGrant/index.vue +3 -3
  136. package/dist/runtime/components/Edit/Features/Publish/Dialog/Item.vue +41 -14
  137. package/dist/runtime/components/Edit/Features/Publish/Dialog/Item.vue.d.ts +2 -0
  138. package/dist/runtime/components/Edit/Features/Publish/Dialog/PublishOption.vue +47 -0
  139. package/dist/runtime/components/Edit/Features/Publish/Dialog/PublishOption.vue.d.ts +19 -0
  140. package/dist/runtime/components/Edit/Features/Publish/Dialog/ScheduleDate.vue +183 -0
  141. package/dist/runtime/components/Edit/Features/Publish/Dialog/ScheduleDate.vue.d.ts +13 -0
  142. package/dist/runtime/components/Edit/Features/Publish/Dialog/Summary.vue +83 -0
  143. package/dist/runtime/components/Edit/Features/Publish/Dialog/Summary.vue.d.ts +9 -0
  144. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue +381 -128
  145. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue.d.ts +3 -14
  146. package/dist/runtime/components/Edit/Features/Publish/index.vue +37 -22
  147. package/dist/runtime/components/Edit/Features/Revert/index.vue +3 -3
  148. package/dist/runtime/components/Edit/Features/Search/index.vue +3 -2
  149. package/dist/runtime/components/Edit/Features/Selection/AddButtons/AddButtonsField.vue +54 -0
  150. package/dist/runtime/components/Edit/Features/Selection/AddButtons/AddButtonsField.vue.d.ts +14 -0
  151. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue +120 -0
  152. package/dist/runtime/components/Edit/Features/Selection/AddButtons/Overlay/index.vue.d.ts +15 -0
  153. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue +459 -0
  154. package/dist/runtime/components/Edit/Features/Selection/AddButtons/index.vue.d.ts +6 -0
  155. package/dist/runtime/components/Edit/Features/Selection/Overlay/fragment.glsl +14 -9
  156. package/dist/runtime/components/Edit/Features/Selection/Overlay/index.vue +32 -11
  157. package/dist/runtime/components/Edit/Features/Selection/Overlay/vertex.glsl +1 -1
  158. package/dist/runtime/components/Edit/Features/Selection/index.vue +76 -7
  159. package/dist/runtime/components/Edit/Features/Settings/Dialog/FeatureSetting/index.vue +12 -17
  160. package/dist/runtime/components/Edit/Features/Settings/index.vue +11 -25
  161. package/dist/runtime/components/Edit/Features/Theme/Color/index.vue +5 -1
  162. package/dist/runtime/components/Edit/Features/Theme/index.vue +2 -1
  163. package/dist/runtime/components/Edit/Features/TouchActionBar/index.vue +3 -2
  164. package/dist/runtime/components/Edit/Features/Transform/Dialog/index.vue +198 -0
  165. package/dist/runtime/components/Edit/Features/Transform/Dialog/index.vue.d.ts +13 -0
  166. package/dist/runtime/components/Edit/Features/Transform/index.vue +155 -44
  167. package/dist/runtime/components/Edit/Form/Datepicker/index.vue +198 -0
  168. package/dist/runtime/components/Edit/Form/Datepicker/index.vue.d.ts +15 -0
  169. package/dist/runtime/components/Edit/Form/Radio/index.vue +33 -0
  170. package/dist/runtime/components/Edit/Form/Radio/index.vue.d.ts +20 -0
  171. package/dist/runtime/components/Edit/Form/RadioTabs/index.vue +37 -0
  172. package/dist/runtime/components/Edit/Form/RadioTabs/index.vue.d.ts +22 -0
  173. package/dist/runtime/components/Edit/Form/Select/index.vue +29 -0
  174. package/dist/runtime/components/Edit/Form/Select/index.vue.d.ts +20 -0
  175. package/dist/runtime/components/Edit/Form/Text/index.vue +33 -0
  176. package/dist/runtime/components/Edit/Form/Text/index.vue.d.ts +19 -0
  177. package/dist/runtime/components/Edit/Form/Textarea/index.vue +13 -6
  178. package/dist/runtime/components/Edit/Form/Textarea/index.vue.d.ts +4 -0
  179. package/dist/runtime/components/Edit/FormOverlay/index.vue +1 -1
  180. package/dist/runtime/components/Edit/Indicators/index.vue +123 -0
  181. package/dist/runtime/components/Edit/Indicators/index.vue.d.ts +2 -0
  182. package/dist/runtime/components/Edit/ItemIcon/index.vue +2 -1
  183. package/dist/runtime/components/Edit/Konami/Game/PixelGrid.vue +66 -0
  184. package/dist/runtime/components/Edit/Konami/Game/PixelGrid.vue.d.ts +7 -0
  185. package/dist/runtime/components/Edit/Konami/Game/blokkli.png +0 -0
  186. package/dist/runtime/components/Edit/Konami/Game/charmap.d.ts +2 -0
  187. package/dist/runtime/components/Edit/Konami/Game/charmap.js +168 -0
  188. package/dist/runtime/components/Edit/Konami/Game/index.vue +752 -0
  189. package/dist/runtime/components/Edit/Konami/Game/index.vue.d.ts +6 -0
  190. package/dist/runtime/components/Edit/Konami/Game/textRendering.d.ts +8 -0
  191. package/dist/runtime/components/Edit/Konami/Game/textRendering.js +138 -0
  192. package/dist/runtime/components/Edit/Konami/Game/useIconRendering.d.ts +9 -0
  193. package/dist/runtime/components/Edit/Konami/Game/useIconRendering.js +130 -0
  194. package/dist/runtime/components/Edit/Konami/index.vue +44 -0
  195. package/dist/runtime/components/Edit/Konami/index.vue.d.ts +2 -0
  196. package/dist/runtime/components/Edit/Loading/index.vue +6 -2
  197. package/dist/runtime/components/Edit/Loading/index.vue.d.ts +2 -0
  198. package/dist/runtime/components/Edit/Messages/index.vue +8 -3
  199. package/dist/runtime/components/Edit/PluginConfigForm/Checkbox/index.vue +17 -0
  200. package/dist/runtime/components/Edit/PluginConfigForm/Checkbox/index.vue.d.ts +11 -0
  201. package/dist/runtime/components/Edit/PluginConfigForm/Options/index.vue +37 -0
  202. package/dist/runtime/components/Edit/PluginConfigForm/Options/index.vue.d.ts +11 -0
  203. package/dist/runtime/components/Edit/PluginConfigForm/Text/index.vue +43 -0
  204. package/dist/runtime/components/Edit/PluginConfigForm/Text/index.vue.d.ts +11 -0
  205. package/dist/runtime/components/Edit/PluginConfigForm/index.vue +57 -0
  206. package/dist/runtime/components/Edit/PluginConfigForm/index.vue.d.ts +16 -0
  207. package/dist/runtime/components/Edit/PreviewProvider.vue +3 -4
  208. package/dist/runtime/components/Edit/RelativeTime/index.vue +3 -2
  209. package/dist/runtime/components/Edit/ShortcutIndicator/index.vue +8 -3
  210. package/dist/runtime/components/Edit/SystemRequirements/index.vue +3 -3
  211. package/dist/runtime/components/Edit/Toolbar/index.vue +3 -2
  212. package/dist/runtime/components/Edit/Transition/index.vue +41 -0
  213. package/dist/runtime/components/Edit/Transition/index.vue.d.ts +19 -0
  214. package/dist/runtime/components/Edit/index.d.ts +24 -15
  215. package/dist/runtime/components/Edit/index.js +46 -28
  216. package/dist/runtime/composables/defineBlokkli.js +7 -3
  217. package/dist/runtime/composables/defineBlokkliFeature.d.ts +4 -7
  218. package/dist/runtime/composables/defineBlokkliProvider.d.ts +11 -0
  219. package/dist/runtime/composables/defineBlokkliProvider.js +46 -0
  220. package/dist/runtime/composables/useBlokkliHelper.js +1 -1
  221. package/dist/runtime/constants/index.d.ts +3 -0
  222. package/dist/runtime/constants/index.js +3 -0
  223. package/dist/runtime/css/output.css +1 -1
  224. package/dist/runtime/helpers/addElementClasses.d.ts +2 -0
  225. package/dist/runtime/helpers/addElementClasses.js +24 -0
  226. package/dist/runtime/helpers/animationProvider.d.ts +4 -2
  227. package/dist/runtime/helpers/animationProvider.js +7 -2
  228. package/dist/runtime/helpers/bundles/index.d.ts +1 -0
  229. package/dist/runtime/helpers/bundles/index.js +4 -0
  230. package/dist/runtime/helpers/composables/useStickyToolbar.d.ts +20 -0
  231. package/dist/runtime/helpers/composables/useStickyToolbar.js +215 -0
  232. package/dist/runtime/helpers/definitionProvider.d.ts +2 -1
  233. package/dist/runtime/helpers/definitionProvider.js +17 -0
  234. package/dist/runtime/helpers/domProvider.d.ts +2 -1
  235. package/dist/runtime/helpers/domProvider.js +89 -43
  236. package/dist/runtime/helpers/dropTargets/index.d.ts +6 -0
  237. package/dist/runtime/helpers/dropTargets/index.js +49 -0
  238. package/dist/runtime/helpers/eventBus.d.ts +1 -1
  239. package/dist/runtime/helpers/eventBus.js +2 -2
  240. package/dist/runtime/helpers/index.d.ts +10 -1
  241. package/dist/runtime/helpers/index.js +57 -0
  242. package/dist/runtime/helpers/indicatorsProvider.d.ts +10 -0
  243. package/dist/runtime/helpers/indicatorsProvider.js +23 -0
  244. package/dist/runtime/helpers/keyboardProvider.d.ts +2 -0
  245. package/dist/runtime/helpers/keyboardProvider.js +17 -1
  246. package/dist/runtime/helpers/pluginProvider.d.ts +10 -0
  247. package/dist/runtime/helpers/pluginProvider.js +33 -0
  248. package/dist/runtime/helpers/renderCycle.d.ts +1 -0
  249. package/dist/runtime/helpers/renderCycle.js +10 -0
  250. package/dist/runtime/helpers/runtimeHelpers/index.js +14 -11
  251. package/dist/runtime/helpers/selectionProvider.d.ts +16 -0
  252. package/dist/runtime/helpers/selectionProvider.js +47 -35
  253. package/dist/runtime/helpers/stateProvider.d.ts +7 -2
  254. package/dist/runtime/helpers/stateProvider.js +89 -14
  255. package/dist/runtime/helpers/storageProvider.d.ts +4 -3
  256. package/dist/runtime/helpers/storageProvider.js +56 -3
  257. package/dist/runtime/helpers/symbols.d.ts +1 -0
  258. package/dist/runtime/helpers/symbols.js +1 -0
  259. package/dist/runtime/helpers/textProvider.js +6 -0
  260. package/dist/runtime/helpers/themeProvider.d.ts +2 -0
  261. package/dist/runtime/helpers/themeProvider.js +4 -1
  262. package/dist/runtime/helpers/transform.js +1 -3
  263. package/dist/runtime/helpers/uiProvider.d.ts +9 -2
  264. package/dist/runtime/helpers/uiProvider.js +72 -47
  265. package/dist/runtime/helpers/useTransitionedValue.d.ts +18 -0
  266. package/dist/runtime/helpers/useTransitionedValue.js +57 -0
  267. package/dist/runtime/icons/anchor.svg +1 -0
  268. package/dist/runtime/icons/arrow-left.svg +1 -1
  269. package/dist/runtime/icons/arrow-right.svg +1 -1
  270. package/dist/runtime/icons/arrow-top-right.svg +1 -0
  271. package/dist/runtime/icons/calendar-clock.svg +1 -0
  272. package/dist/runtime/icons/chart.svg +1 -0
  273. package/dist/runtime/icons/copy.svg +1 -0
  274. package/dist/runtime/icons/cursor-move.svg +1 -1
  275. package/dist/runtime/icons/diff.svg +1 -1
  276. package/dist/runtime/icons/eye-off.svg +1 -0
  277. package/dist/runtime/icons/eye.svg +1 -1
  278. package/dist/runtime/icons/info.svg +1 -1
  279. package/dist/runtime/icons/link.svg +1 -0
  280. package/dist/runtime/icons/speedometer.svg +1 -0
  281. package/dist/runtime/types/blokkOptions.d.ts +8 -0
  282. package/dist/runtime/types/index.d.ts +172 -6
  283. package/dist/runtime/types/theme.d.ts +2 -1
  284. package/dist/shared/{editor.gz_ac6uT.d.mts → editor.CKsrTpc1.d.mts} +1 -1
  285. package/package.json +20 -5
  286. package/dist/runtime/components/Edit/Features/FieldAreas/Overlay/index.vue +0 -22
  287. package/dist/runtime/components/Edit/Features/FieldAreas/index.vue +0 -41
  288. /package/dist/runtime/components/Edit/Features/{FieldAreas/Overlay → Analyze}/index.vue.d.ts +0 -0
  289. /package/dist/runtime/components/Edit/Features/{FieldAreas/index.vue.d.ts → Anchors/Renderer.vue.d.ts} +0 -0
@@ -0,0 +1,752 @@
1
+ <template>
2
+ <div
3
+ class="bk bk-konami"
4
+ :style="{
5
+ '--bk-bg': background
6
+ }"
7
+ >
8
+ <div class="bk-dialog-background" />
9
+ <div class="bk-konami-game bk-slide-up-inner">
10
+ <div class="bk-konami-game-canvas">
11
+ <canvas
12
+ ref="canvasDisplay"
13
+ :style="canvasStyle"
14
+ :width="canvasWidth"
15
+ :height="canvasHeight"
16
+ class="bk-is-display"
17
+ />
18
+ <Pixelgrid
19
+ :canvas-scale
20
+ :canvas-height
21
+ :canvas-width
22
+ :style="canvasStyle"
23
+ />
24
+ </div>
25
+ </div>
26
+ <div v-if="DEBUG_ICONS" class="bk-konami-debug-canvas">
27
+ <canvas
28
+ ref="debugCanvas"
29
+ :width="debugCanvasWidth"
30
+ :height="debugCanvasHeight"
31
+ :style="{
32
+ width: debugCanvasWidth * 6 + 'px',
33
+ height: debugCanvasHeight * 6 + 'px'
34
+ }"
35
+ />
36
+ </div>
37
+ </div>
38
+ </template>
39
+
40
+ <script setup>
41
+ import onBlokkliEvent from "#blokkli/helpers/composables/onBlokkliEvent";
42
+ import {
43
+ computed,
44
+ useTemplateRef,
45
+ useBlokkli,
46
+ ref,
47
+ onMounted,
48
+ onUnmounted
49
+ } from "#imports";
50
+ import Pixelgrid from "./PixelGrid.vue";
51
+ import { useTextRendering } from "./textRendering";
52
+ import { useIconRendering } from "./useIconRendering";
53
+ import logoUrl from "./blokkli.png";
54
+ const emit = defineEmits(["close"]);
55
+ const DEBUG_ICONS = false;
56
+ const DEBUG_GAME = false;
57
+ const INIT_EATEN = 0;
58
+ const largeIconSize = 32;
59
+ const blackColor = "black";
60
+ const worldWidth = 7 * 3;
61
+ const worldHeight = 4 * 3 - 1;
62
+ const scoreAreaHeight = 1;
63
+ const cellSize = 12;
64
+ const gameWorldBorder = 1;
65
+ const gameWorldPadding = 1;
66
+ let isLoaded = false;
67
+ const { keyboard, ui } = useBlokkli();
68
+ const { drawTextPixels, getTextWidth, drawText } = useTextRendering();
69
+ const { initIcons, getIconCount, drawIcon } = useIconRendering(
70
+ cellSize,
71
+ largeIconSize
72
+ );
73
+ const iconCount = getIconCount();
74
+ const canvasWidth = computed(() => {
75
+ return worldWidth * cellSize + (gameWorldBorder + gameWorldPadding) * 2;
76
+ });
77
+ const canvasHeight = computed(() => {
78
+ return scoreAreaHeight * cellSize + (gameWorldBorder + gameWorldPadding) * 2 + worldHeight * cellSize;
79
+ });
80
+ const canvasScale = computed(() => {
81
+ const availableWidth = ui.viewport.value.width * 0.8;
82
+ const availableHeight = ui.viewport.value.height * 0.8;
83
+ const maxScaleWidth = Math.floor(availableWidth / canvasWidth.value);
84
+ const maxScaleHeight = Math.floor(availableHeight / canvasHeight.value);
85
+ return Math.max(1, Math.min(maxScaleWidth, maxScaleHeight));
86
+ });
87
+ const canvasStyle = computed(() => {
88
+ return {
89
+ width: canvasWidth.value * canvasScale.value + "px",
90
+ height: canvasHeight.value * canvasScale.value + "px"
91
+ };
92
+ });
93
+ const snake = ref([
94
+ { x: Math.floor(worldWidth / 2), y: Math.floor(worldHeight / 2) }
95
+ ]);
96
+ const direction = ref("right");
97
+ const nextDirection = ref("right");
98
+ const food = ref({ x: 10, y: 10 });
99
+ const gameOver = ref(false);
100
+ const gameStarted = ref(false);
101
+ const score = ref(0);
102
+ const blocksEaten = ref(0);
103
+ const removedTail = ref(null);
104
+ let lastCellUpdate = 0;
105
+ let gameOverTime = 0;
106
+ const currentBlockIndex = ref(0);
107
+ let movesSinceFoodSpawn = 0;
108
+ let optimalPathLength = 0;
109
+ const canvasDisplay = useTemplateRef("canvasDisplay");
110
+ const debugCanvas = useTemplateRef("debugCanvas");
111
+ const debugCanvasWidth = computed(() => {
112
+ if (!DEBUG_ICONS) return 0;
113
+ const iconsPerRow = 7;
114
+ return Math.min(iconCount, iconsPerRow) * (largeIconSize + 10);
115
+ });
116
+ const debugCanvasHeight = computed(() => {
117
+ if (!DEBUG_ICONS) return 0;
118
+ const iconsPerRow = 7;
119
+ const smallRows = Math.ceil(iconCount / iconsPerRow);
120
+ const largeRows = Math.ceil(iconCount / iconsPerRow);
121
+ return smallRows * (cellSize + 10) + largeRows * (largeIconSize + 10) + 20;
122
+ });
123
+ let scoreCanvas = null;
124
+ let snakeCanvas = null;
125
+ let logoCanvas = null;
126
+ let lastScore = -1;
127
+ let lastBlocksEaten = -1;
128
+ const cellMoveDuration = 250;
129
+ function generateFood() {
130
+ let newFood;
131
+ do {
132
+ newFood = {
133
+ x: Math.floor(Math.random() * worldWidth),
134
+ y: Math.floor(Math.random() * worldHeight)
135
+ };
136
+ } while (snake.value.some(
137
+ (segment) => segment.x === newFood.x && segment.y === newFood.y
138
+ ));
139
+ food.value = newFood;
140
+ currentBlockIndex.value = (currentBlockIndex.value + 1) % iconCount;
141
+ movesSinceFoodSpawn = 0;
142
+ const head = snake.value[0];
143
+ optimalPathLength = Math.abs(head.x - newFood.x) + Math.abs(head.y - newFood.y);
144
+ }
145
+ function getAIDirection() {
146
+ const head = snake.value[0];
147
+ const target = food.value;
148
+ const isSafe = (pos) => {
149
+ if (pos.x < 0 || pos.x >= worldWidth || pos.y < 0 || pos.y >= worldHeight) {
150
+ return false;
151
+ }
152
+ for (let i = 0; i < snake.value.length - 1; i++) {
153
+ const segment = snake.value[i];
154
+ if (segment.x === pos.x && segment.y === pos.y) {
155
+ return false;
156
+ }
157
+ }
158
+ return true;
159
+ };
160
+ const moves = [];
161
+ const directions = ["up", "down", "left", "right"];
162
+ for (const dir of directions) {
163
+ if (dir === "up" && direction.value === "down" || dir === "down" && direction.value === "up" || dir === "left" && direction.value === "right" || dir === "right" && direction.value === "left") {
164
+ continue;
165
+ }
166
+ const newPos = { ...head };
167
+ switch (dir) {
168
+ case "up":
169
+ newPos.y -= 1;
170
+ break;
171
+ case "down":
172
+ newPos.y += 1;
173
+ break;
174
+ case "left":
175
+ newPos.x -= 1;
176
+ break;
177
+ case "right":
178
+ newPos.x += 1;
179
+ break;
180
+ }
181
+ if (isSafe(newPos)) {
182
+ const distance = Math.abs(newPos.x - target.x) + Math.abs(newPos.y - target.y);
183
+ moves.push({ dir, pos: newPos, priority: -distance });
184
+ }
185
+ }
186
+ moves.sort((a, b) => b.priority - a.priority);
187
+ return moves.length > 0 ? moves[0].dir : direction.value;
188
+ }
189
+ function resetGame() {
190
+ const startPos = {
191
+ x: Math.floor(worldWidth / 2),
192
+ y: Math.floor(worldHeight / 2)
193
+ };
194
+ snake.value = [startPos];
195
+ direction.value = "right";
196
+ nextDirection.value = "right";
197
+ gameOver.value = false;
198
+ gameStarted.value = false;
199
+ score.value = 0;
200
+ blocksEaten.value = 0;
201
+ removedTail.value = null;
202
+ lastCellUpdate = 0;
203
+ gameOverTime = 0;
204
+ movesSinceFoodSpawn = 0;
205
+ optimalPathLength = 0;
206
+ if (DEBUG_GAME) {
207
+ for (let i = 0; i < 10; i++) {
208
+ const head = snake.value[0];
209
+ snake.value.push({ x: head.x - i - 1, y: head.y });
210
+ }
211
+ blocksEaten.value = 10;
212
+ score.value = 10 * 100;
213
+ gameStarted.value = true;
214
+ }
215
+ if (INIT_EATEN) {
216
+ for (let i = 0; i < INIT_EATEN; i++) {
217
+ const head = snake.value[0];
218
+ snake.value.push({ x: head.x - i - 1, y: head.y });
219
+ }
220
+ }
221
+ generateFood();
222
+ }
223
+ function update(currentTime) {
224
+ if (gameOver.value || !gameStarted.value) return;
225
+ if (lastCellUpdate === 0) {
226
+ lastCellUpdate = currentTime;
227
+ return;
228
+ }
229
+ const timeSinceLastUpdate = currentTime - lastCellUpdate;
230
+ if (timeSinceLastUpdate >= cellMoveDuration) {
231
+ if (DEBUG_GAME) {
232
+ nextDirection.value = getAIDirection();
233
+ }
234
+ direction.value = nextDirection.value;
235
+ const head = snake.value[0];
236
+ const newHead = { ...head };
237
+ switch (direction.value) {
238
+ case "up":
239
+ newHead.y -= 1;
240
+ break;
241
+ case "down":
242
+ newHead.y += 1;
243
+ break;
244
+ case "left":
245
+ newHead.x -= 1;
246
+ break;
247
+ case "right":
248
+ newHead.x += 1;
249
+ break;
250
+ }
251
+ if (newHead.x < 0 || newHead.x >= worldWidth || newHead.y < 0 || newHead.y >= worldHeight) {
252
+ gameOver.value = true;
253
+ gameOverTime = lastCellUpdate + cellMoveDuration;
254
+ return;
255
+ }
256
+ if (snake.value.some(
257
+ (segment) => segment.x === newHead.x && segment.y === newHead.y
258
+ )) {
259
+ gameOver.value = true;
260
+ gameOverTime = lastCellUpdate + cellMoveDuration;
261
+ return;
262
+ }
263
+ lastCellUpdate = currentTime;
264
+ snake.value.unshift(newHead);
265
+ movesSinceFoodSpawn++;
266
+ if (newHead.x === food.value.x && newHead.y === food.value.y) {
267
+ const pathDifference = movesSinceFoodSpawn - optimalPathLength;
268
+ const cappedDifference = Math.min(pathDifference, 9);
269
+ const points = 100 - cappedDifference * 10;
270
+ score.value += points;
271
+ blocksEaten.value += 1;
272
+ generateFood();
273
+ removedTail.value = null;
274
+ } else {
275
+ const tail = snake.value.pop();
276
+ removedTail.value = tail ? { ...tail } : null;
277
+ }
278
+ }
279
+ }
280
+ const background = computed(() => {
281
+ return "rgba(133, 144, 24, 1)";
282
+ });
283
+ function initOffscreenCanvases() {
284
+ scoreCanvas = document.createElement("canvas");
285
+ scoreCanvas.width = canvasWidth.value;
286
+ scoreCanvas.height = cellSize;
287
+ const gameAreaWidth = worldWidth * cellSize + (gameWorldBorder + gameWorldPadding) * 2;
288
+ const gameAreaHeight = scoreAreaHeight * cellSize + (gameWorldBorder + gameWorldPadding) * 2 + worldHeight * cellSize;
289
+ snakeCanvas = new OffscreenCanvas(gameAreaWidth, gameAreaHeight);
290
+ }
291
+ async function initLogo() {
292
+ return new Promise((resolve) => {
293
+ const img = new Image();
294
+ img.onload = () => {
295
+ logoCanvas = new OffscreenCanvas(img.width, img.height);
296
+ const ctx = logoCanvas.getContext("2d", { willReadFrequently: true });
297
+ if (!ctx) {
298
+ resolve();
299
+ return;
300
+ }
301
+ ctx.drawImage(img, 0, 0);
302
+ const imageData = ctx.getImageData(0, 0, img.width, img.height);
303
+ const data = imageData.data;
304
+ const bgColor = background.value;
305
+ const match = bgColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
306
+ const bgR = match ? Number.parseInt(match[1]) : 0;
307
+ const bgG = match ? Number.parseInt(match[2]) : 0;
308
+ const bgB = match ? Number.parseInt(match[3]) : 0;
309
+ for (let i = 0; i < data.length; i += 4) {
310
+ const r = data[i];
311
+ const g = data[i + 1];
312
+ const b = data[i + 2];
313
+ const a = data[i + 3];
314
+ const brightness = (r + g + b) / 3;
315
+ if (a > 0 && brightness > 200) {
316
+ data[i] = bgR;
317
+ data[i + 1] = bgG;
318
+ data[i + 2] = bgB;
319
+ data[i + 3] = 255;
320
+ }
321
+ }
322
+ ctx.putImageData(imageData, 0, 0);
323
+ resolve();
324
+ };
325
+ img.src = logoUrl;
326
+ });
327
+ }
328
+ function drawScoreArea() {
329
+ if (!scoreCanvas) return;
330
+ const ctx = scoreCanvas.getContext("2d");
331
+ if (!ctx) return;
332
+ ctx.fillStyle = background.value;
333
+ ctx.fillRect(0, 0, scoreCanvas.width, scoreCanvas.height);
334
+ const scoreText = "Score: " + score.value.toString();
335
+ drawTextPixels(ctx, scoreText, 0, 2, blackColor, "left");
336
+ const blocksText = blocksEaten.value.toString();
337
+ const rightAlignX = worldWidth * cellSize + 4;
338
+ drawTextPixels(ctx, blocksText, rightAlignX, 2, blackColor, "right");
339
+ lastScore = score.value;
340
+ lastBlocksEaten = blocksEaten.value;
341
+ }
342
+ function drawStartScreen(ctx, currentTime) {
343
+ ctx.imageSmoothingEnabled = false;
344
+ const offset = gameWorldBorder + gameWorldPadding;
345
+ const totalWidth = worldWidth * cellSize;
346
+ const largeIconSize2 = 32;
347
+ const gameAreaY = scoreAreaHeight * cellSize + offset;
348
+ const numColumns = 6;
349
+ const columnWidth = totalWidth / numColumns;
350
+ const rowHeight = largeIconSize2 + 24;
351
+ const numRows = 8;
352
+ const speed = 25;
353
+ const wrapHeight = numRows * rowHeight;
354
+ let positionIndex = 0;
355
+ for (let row = 0; row < numRows; row++) {
356
+ for (let col = 0; col < numColumns; col++) {
357
+ if ((row + col) % 2 === 0) {
358
+ const iconIndex = positionIndex % iconCount;
359
+ const xBase = offset + col * columnWidth + (columnWidth - largeIconSize2) / 2;
360
+ const sineFrequency = 1e-3;
361
+ const sinePhase = positionIndex * 0.6;
362
+ const xOffset = Math.cos(currentTime * sineFrequency + sinePhase) * 24;
363
+ const x = xBase + xOffset;
364
+ const baseY = row * rowHeight;
365
+ const yProgress = currentTime / 1e3 * speed;
366
+ const wrappedY = (baseY + yProgress) % wrapHeight;
367
+ const y = wrappedY + gameAreaY - largeIconSize2 * 2;
368
+ drawIcon(ctx, iconIndex, x, y, true);
369
+ positionIndex++;
370
+ }
371
+ }
372
+ }
373
+ if (logoCanvas) {
374
+ ctx.drawImage(logoCanvas, 0, 0);
375
+ }
376
+ const line1 = "Use arrow keys to move";
377
+ const line1Width = getTextWidth(line1);
378
+ const line1X = Math.floor((totalWidth - line1Width) / 2) + offset;
379
+ const line2 = "Press ESC to exit";
380
+ const line2Width = getTextWidth(line2);
381
+ const line2X = Math.floor((totalWidth - line2Width) / 2) + offset;
382
+ ctx.beginPath();
383
+ ctx.rect((canvasWidth.value - (line1Width + 10)) / 2, 88, line1Width + 10, 21);
384
+ ctx.fill();
385
+ ctx.lineWidth = 2;
386
+ ctx.stroke();
387
+ drawText(ctx, line1, line1X, 90, blackColor);
388
+ drawText(ctx, line2, line2X, 100, blackColor);
389
+ const blinkOn = currentTime % 1e3 < 500;
390
+ if (blinkOn) {
391
+ const spaceText = "Press SPACE to start";
392
+ const spaceTextWidth = Math.round(getTextWidth(spaceText));
393
+ const spaceTextX = Math.round((canvasWidth.value - spaceTextWidth) / 2);
394
+ ctx.fillStyle = background.value;
395
+ ctx.strokeStyle = blackColor;
396
+ ctx.lineWidth = 2;
397
+ ctx.beginPath();
398
+ ctx.rect(spaceTextX - 3, 117, spaceTextWidth + 6, 13);
399
+ ctx.fill();
400
+ ctx.stroke();
401
+ drawTextPixels(
402
+ ctx,
403
+ spaceText,
404
+ canvasWidth.value / 2,
405
+ 120,
406
+ blackColor,
407
+ "center"
408
+ );
409
+ }
410
+ }
411
+ function draw(currentTime) {
412
+ const ctx = canvasDisplay.value?.getContext("2d");
413
+ if (!ctx) return;
414
+ if (!gameStarted.value) {
415
+ ctx.fillStyle = background.value;
416
+ ctx.fillRect(0, 0, canvasWidth.value, canvasHeight.value);
417
+ drawStartScreen(ctx, currentTime);
418
+ return;
419
+ }
420
+ let movementProgress = 0;
421
+ if (lastCellUpdate > 0) {
422
+ const timeToUse = gameOver.value && gameOverTime > 0 ? gameOverTime : currentTime;
423
+ const timeSinceLastUpdate = timeToUse - lastCellUpdate;
424
+ movementProgress = Math.min(timeSinceLastUpdate / cellMoveDuration, 1);
425
+ }
426
+ if (score.value !== lastScore || blocksEaten.value !== lastBlocksEaten) {
427
+ drawScoreArea();
428
+ }
429
+ const offset = gameWorldBorder + gameWorldPadding;
430
+ const gameAreaY = scoreAreaHeight * cellSize;
431
+ const gameAreaHeight = canvasHeight.value - gameAreaY;
432
+ ctx.fillStyle = background.value;
433
+ ctx.fillRect(0, gameAreaY, canvasWidth.value, gameAreaHeight);
434
+ if (gameWorldBorder > 0) {
435
+ ctx.fillStyle = blackColor;
436
+ const borderX = 0;
437
+ const borderY = scoreAreaHeight * cellSize;
438
+ const borderWidth = worldWidth * cellSize + (gameWorldBorder + gameWorldPadding) * 2;
439
+ const borderHeight = worldHeight * cellSize + (gameWorldBorder + gameWorldPadding) * 2;
440
+ ctx.fillRect(borderX, borderY, borderWidth, gameWorldBorder);
441
+ ctx.fillRect(
442
+ borderX,
443
+ borderY + borderHeight - gameWorldBorder,
444
+ borderWidth,
445
+ gameWorldBorder
446
+ );
447
+ ctx.fillRect(borderX, borderY, gameWorldBorder, borderHeight);
448
+ ctx.fillRect(
449
+ borderX + borderWidth - gameWorldBorder,
450
+ borderY,
451
+ gameWorldBorder,
452
+ borderHeight
453
+ );
454
+ }
455
+ const renderPositions = [];
456
+ if (removedTail.value) {
457
+ const currentTail = snake.value[snake.value.length - 1];
458
+ if (currentTail) {
459
+ const dx = currentTail.x - removedTail.value.x;
460
+ const dy = currentTail.y - removedTail.value.y;
461
+ const renderX = removedTail.value.x + dx * movementProgress;
462
+ const renderY = removedTail.value.y + dy * movementProgress;
463
+ renderPositions.push({ x: renderX, y: renderY });
464
+ }
465
+ }
466
+ for (let i = snake.value.length - 1; i >= 0; i--) {
467
+ const segment = snake.value[i];
468
+ let renderX = segment.x;
469
+ let renderY = segment.y;
470
+ if (i === 0) {
471
+ const dx = direction.value === "left" ? 1 : direction.value === "right" ? -1 : 0;
472
+ const dy = direction.value === "up" ? 1 : direction.value === "down" ? -1 : 0;
473
+ renderX = segment.x + dx * (1 - movementProgress);
474
+ renderY = segment.y + dy * (1 - movementProgress);
475
+ }
476
+ renderPositions.push({ x: renderX, y: renderY });
477
+ }
478
+ const SNAKE_DEBUG = false;
479
+ if (snakeCanvas) {
480
+ const snakeCtx = SNAKE_DEBUG ? ctx : snakeCanvas.getContext("2d", {
481
+ willReadFrequently: true
482
+ });
483
+ if (snakeCtx) {
484
+ snakeCtx.clearRect(0, 0, snakeCanvas.width, snakeCanvas.height);
485
+ snakeCtx.strokeStyle = blackColor;
486
+ snakeCtx.lineCap = "round";
487
+ snakeCtx.lineJoin = "round";
488
+ snakeCtx.beginPath();
489
+ if (renderPositions.length > 0) {
490
+ const offset2 = gameWorldBorder + gameWorldPadding;
491
+ const firstPos = renderPositions[0];
492
+ const startX = Math.round(firstPos.x * cellSize + cellSize / 2 + offset2);
493
+ const startY = Math.round(
494
+ (firstPos.y + scoreAreaHeight) * cellSize + cellSize / 2 + offset2
495
+ );
496
+ snakeCtx.moveTo(startX, startY);
497
+ for (let i = 1; i < renderPositions.length; i++) {
498
+ const pos = renderPositions[i];
499
+ const x = Math.round(pos.x * cellSize + cellSize / 2 + offset2);
500
+ const y = Math.round(
501
+ (pos.y + scoreAreaHeight) * cellSize + cellSize / 2 + offset2
502
+ );
503
+ snakeCtx.lineTo(x, y);
504
+ }
505
+ snakeCtx.lineCap = "round";
506
+ snakeCtx.lineJoin = "round";
507
+ snakeCtx.lineDashOffset = 0;
508
+ snakeCtx.lineWidth = 12;
509
+ snakeCtx.setLineDash([4e5]);
510
+ snakeCtx.stroke();
511
+ snakeCtx.strokeStyle = "white";
512
+ snakeCtx.lineDashOffset = 0;
513
+ snakeCtx.lineWidth = 10;
514
+ snakeCtx.stroke();
515
+ snakeCtx.lineWidth = 6;
516
+ snakeCtx.strokeStyle = "black";
517
+ snakeCtx.lineDashOffset = -0;
518
+ snakeCtx.setLineDash([4, 8]);
519
+ snakeCtx.stroke();
520
+ snakeCtx.lineWidth = 2;
521
+ snakeCtx.strokeStyle = "black";
522
+ snakeCtx.lineDashOffset = -0;
523
+ snakeCtx.setLineDash([]);
524
+ snakeCtx.stroke();
525
+ const headPos = renderPositions[renderPositions.length - 1];
526
+ const headX = Math.round(headPos.x * cellSize + cellSize / 2 + offset2);
527
+ const headY = Math.round(
528
+ (headPos.y + scoreAreaHeight) * cellSize + cellSize / 2 + offset2
529
+ );
530
+ const headRadius = cellSize / 2;
531
+ snakeCtx.setLineDash([]);
532
+ snakeCtx.fillStyle = blackColor;
533
+ const mouthCycle = currentTime % 600 / 600;
534
+ const mouthOpen = Math.sin(mouthCycle * Math.PI * 2) * 0.5 + 0.5;
535
+ const maxMouthAngle = Math.PI / 3;
536
+ const mouthAngle = mouthOpen * maxMouthAngle;
537
+ snakeCtx.fillStyle = "white";
538
+ snakeCtx.beginPath();
539
+ snakeCtx.arc(headX, headY, cellSize / 2 - 2, 0, Math.PI * 2);
540
+ snakeCtx.fill();
541
+ let rotation = 0;
542
+ switch (direction.value) {
543
+ case "right":
544
+ rotation = 0;
545
+ break;
546
+ case "down":
547
+ rotation = Math.PI / 2;
548
+ break;
549
+ case "left":
550
+ rotation = Math.PI;
551
+ break;
552
+ case "up":
553
+ rotation = -Math.PI / 2;
554
+ break;
555
+ }
556
+ const jawLength = headRadius + 2;
557
+ const mouthOffset = -1;
558
+ const mouthCenterX = headX + Math.cos(rotation) * mouthOffset;
559
+ const mouthCenterY = headY + Math.sin(rotation) * mouthOffset;
560
+ const upperJawX = mouthCenterX + Math.cos(rotation - mouthAngle / 2) * jawLength;
561
+ const upperJawY = mouthCenterY + Math.sin(rotation - mouthAngle / 2) * jawLength;
562
+ const lowerJawX = mouthCenterX + Math.cos(rotation + mouthAngle / 2) * jawLength;
563
+ const lowerJawY = mouthCenterY + Math.sin(rotation + mouthAngle / 2) * jawLength;
564
+ snakeCtx.fillStyle = "white";
565
+ snakeCtx.beginPath();
566
+ snakeCtx.moveTo(mouthCenterX, mouthCenterY);
567
+ snakeCtx.lineTo(upperJawX, upperJawY);
568
+ snakeCtx.lineTo(lowerJawX, lowerJawY);
569
+ snakeCtx.closePath();
570
+ snakeCtx.fill();
571
+ snakeCtx.strokeStyle = blackColor;
572
+ snakeCtx.lineWidth = 1;
573
+ snakeCtx.lineCap = "round";
574
+ snakeCtx.beginPath();
575
+ snakeCtx.moveTo(mouthCenterX, mouthCenterY);
576
+ snakeCtx.lineTo(upperJawX, upperJawY);
577
+ snakeCtx.stroke();
578
+ snakeCtx.beginPath();
579
+ snakeCtx.moveTo(mouthCenterX, mouthCenterY);
580
+ snakeCtx.lineTo(lowerJawX, lowerJawY);
581
+ snakeCtx.stroke();
582
+ }
583
+ if (!SNAKE_DEBUG) {
584
+ const imageData = snakeCtx.getImageData(
585
+ 0,
586
+ 0,
587
+ snakeCanvas.width,
588
+ snakeCanvas.height
589
+ );
590
+ const data = imageData.data;
591
+ const THRESHOLD = 100;
592
+ for (let i = 0; i < data.length; i += 4) {
593
+ const r = data[i];
594
+ const g = data[i + 1];
595
+ const b = data[i + 2];
596
+ const a = data[i + 3];
597
+ const brightness = (r + g + b) / 3;
598
+ if (a > THRESHOLD && brightness < THRESHOLD) {
599
+ data[i] = 0;
600
+ data[i + 1] = 0;
601
+ data[i + 2] = 0;
602
+ data[i + 3] = 255;
603
+ } else {
604
+ data[i] = 0;
605
+ data[i + 1] = 0;
606
+ data[i + 2] = 0;
607
+ data[i + 3] = 0;
608
+ }
609
+ }
610
+ snakeCtx.putImageData(imageData, 0, 0);
611
+ ctx.drawImage(
612
+ snakeCanvas,
613
+ 0,
614
+ 0,
615
+ // source x, y
616
+ snakeCanvas.width,
617
+ snakeCanvas.height,
618
+ // source width, height
619
+ 0,
620
+ 0,
621
+ // destination x, y
622
+ snakeCanvas.width,
623
+ snakeCanvas.height
624
+ // destination width, height
625
+ );
626
+ }
627
+ }
628
+ }
629
+ const foodX = food.value.x * cellSize + offset;
630
+ const foodY = (food.value.y + scoreAreaHeight) * cellSize + offset;
631
+ drawIcon(ctx, currentBlockIndex.value, foodX, foodY);
632
+ if (scoreCanvas) {
633
+ ctx.drawImage(scoreCanvas, 0, 0);
634
+ }
635
+ if (gameOver.value) {
636
+ const totalWidth = worldWidth * cellSize;
637
+ const gameOverText = "GAME OVER";
638
+ const gameOverWidth = getTextWidth(gameOverText) * 3;
639
+ const gameOverX = Math.floor((totalWidth - gameOverWidth) / 2) + offset;
640
+ drawText(
641
+ ctx,
642
+ gameOverText,
643
+ gameOverX,
644
+ 3 * cellSize,
645
+ blackColor,
646
+ background.value,
647
+ 1,
648
+ 2,
649
+ 3
650
+ );
651
+ const retryText = "Press SPACE to try again";
652
+ const retryWidth = getTextWidth(retryText);
653
+ const retryX = Math.floor((totalWidth - retryWidth) / 2) + offset;
654
+ drawText(
655
+ ctx,
656
+ retryText,
657
+ retryX,
658
+ 8 * cellSize,
659
+ blackColor,
660
+ background.value,
661
+ 1,
662
+ 2
663
+ );
664
+ }
665
+ }
666
+ function handleKeyPress(e) {
667
+ e.stopPropagation();
668
+ const key = e.key;
669
+ if ((key === "r" || key === "R") && (e.metaKey || e.ctrlKey)) {
670
+ return;
671
+ }
672
+ if (key === "Escape") {
673
+ e.preventDefault();
674
+ emit("close");
675
+ return;
676
+ }
677
+ if (key === " " && gameOver.value) {
678
+ e.preventDefault();
679
+ resetGame();
680
+ gameStarted.value = true;
681
+ return;
682
+ }
683
+ if (!gameStarted.value && (key === " " || key === "ArrowUp" || key === "ArrowDown" || key === "ArrowLeft" || key === "ArrowRight")) {
684
+ e.preventDefault();
685
+ gameStarted.value = true;
686
+ return;
687
+ }
688
+ if (key === "ArrowUp" && direction.value !== "down") {
689
+ e.preventDefault();
690
+ nextDirection.value = "up";
691
+ } else if (key === "ArrowDown" && direction.value !== "up") {
692
+ e.preventDefault();
693
+ nextDirection.value = "down";
694
+ } else if (key === "ArrowLeft" && direction.value !== "right") {
695
+ e.preventDefault();
696
+ nextDirection.value = "left";
697
+ } else if (key === "ArrowRight" && direction.value !== "left") {
698
+ e.preventDefault();
699
+ nextDirection.value = "right";
700
+ }
701
+ }
702
+ onMounted(async () => {
703
+ keyboard.lockKeyboardEvents("konami");
704
+ document.addEventListener("keydown", handleKeyPress, { capture: true });
705
+ console.log(
706
+ "Virtual screen resolution:",
707
+ canvasWidth.value,
708
+ "x",
709
+ canvasHeight.value
710
+ );
711
+ await initIcons();
712
+ await initLogo();
713
+ initOffscreenCanvases();
714
+ resetGame();
715
+ drawScoreArea();
716
+ if (DEBUG_ICONS && debugCanvas.value) {
717
+ const ctx = debugCanvas.value.getContext("2d");
718
+ if (ctx) {
719
+ ctx.fillStyle = "white";
720
+ ctx.fillRect(0, 0, debugCanvas.value.width, debugCanvas.value.height);
721
+ const iconsPerRow = 7;
722
+ for (let i = 0; i < iconCount; i++) {
723
+ const row = Math.floor(i / iconsPerRow);
724
+ const col = i % iconsPerRow;
725
+ const x = col * (largeIconSize + 10) + 5;
726
+ const y = row * (cellSize + 10) + 5;
727
+ drawIcon(ctx, i, x, y, false);
728
+ }
729
+ const smallRows = Math.ceil(iconCount / iconsPerRow);
730
+ const largeIconsStartY = smallRows * (cellSize + 10) + 10;
731
+ for (let i = 0; i < iconCount; i++) {
732
+ const row = Math.floor(i / iconsPerRow);
733
+ const col = i % iconsPerRow;
734
+ const x = col * (largeIconSize + 10) + 5;
735
+ const y = largeIconsStartY + row * (largeIconSize + 10);
736
+ drawIcon(ctx, i, x, y, true);
737
+ }
738
+ }
739
+ }
740
+ isLoaded = true;
741
+ });
742
+ onUnmounted(() => {
743
+ keyboard.unlockKeyboardEvents("konami");
744
+ document.removeEventListener("keydown", handleKeyPress, { capture: true });
745
+ });
746
+ onBlokkliEvent("canvas:draw", (e) => {
747
+ if (!isLoaded) return;
748
+ const time = e.time;
749
+ update(time);
750
+ draw(time);
751
+ });
752
+ </script>