@abraca/nuxt 0.2.0 → 1.5.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 (559) hide show
  1. package/dist/module.d.mts +72 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +139 -3
  4. package/dist/runtime/assets/editor.css +1 -0
  5. package/dist/runtime/components/AAccountSwitcherModal.d.vue.ts +10 -0
  6. package/dist/runtime/components/AAccountSwitcherModal.vue +158 -0
  7. package/dist/runtime/components/AAccountSwitcherModal.vue.d.ts +10 -0
  8. package/dist/runtime/components/AClaimAccountModal.d.vue.ts +10 -0
  9. package/dist/runtime/components/AClaimAccountModal.vue +230 -0
  10. package/dist/runtime/components/AClaimAccountModal.vue.d.ts +10 -0
  11. package/dist/runtime/components/ACollaborationUsers.vue +1 -0
  12. package/dist/runtime/components/AColorPicker.vue +4 -2
  13. package/dist/runtime/components/ACommandPalette.vue +8 -3
  14. package/dist/runtime/components/AConnectServerModal.d.vue.ts +12 -0
  15. package/dist/runtime/components/AConnectServerModal.vue +200 -0
  16. package/dist/runtime/components/AConnectServerModal.vue.d.ts +12 -0
  17. package/dist/runtime/components/AConnectionStatus.vue +1 -0
  18. package/dist/runtime/components/ADocPickModal.d.vue.ts +13 -0
  19. package/dist/runtime/components/ADocPickModal.vue +71 -0
  20. package/dist/runtime/components/ADocPickModal.vue.d.ts +13 -0
  21. package/dist/runtime/components/ADocRenderer.d.vue.ts +29 -0
  22. package/dist/runtime/components/ADocRenderer.vue +105 -0
  23. package/dist/runtime/components/ADocRenderer.vue.d.ts +29 -0
  24. package/dist/runtime/components/ADocTypeSelect.vue +8 -4
  25. package/dist/runtime/components/ADocumentTree.d.vue.ts +3 -3
  26. package/dist/runtime/components/ADocumentTree.vue +196 -29
  27. package/dist/runtime/components/ADocumentTree.vue.d.ts +3 -3
  28. package/dist/runtime/components/AEditor.d.vue.ts +9 -4
  29. package/dist/runtime/components/AEditor.vue +118 -8
  30. package/dist/runtime/components/AEditor.vue.d.ts +9 -4
  31. package/dist/runtime/components/AFloatingWindow.d.vue.ts +54 -2
  32. package/dist/runtime/components/AFloatingWindow.vue +15 -14
  33. package/dist/runtime/components/AFloatingWindow.vue.d.ts +54 -2
  34. package/dist/runtime/components/AIconPicker.vue +10 -2
  35. package/dist/runtime/components/AInviteRedeemModal.d.vue.ts +10 -0
  36. package/dist/runtime/components/AInviteRedeemModal.vue +122 -0
  37. package/dist/runtime/components/AInviteRedeemModal.vue.d.ts +10 -0
  38. package/dist/runtime/components/ANodePanel.vue +109 -62
  39. package/dist/runtime/components/ANotifications.vue +37 -8
  40. package/dist/runtime/components/APermissionGuard.vue +4 -1
  41. package/dist/runtime/components/APresence.vue +15 -3
  42. package/dist/runtime/components/AProvider.d.vue.ts +0 -1
  43. package/dist/runtime/components/AProvider.vue +24 -5
  44. package/dist/runtime/components/AProvider.vue.d.ts +0 -1
  45. package/dist/runtime/components/ARoleBadge.vue +1 -0
  46. package/dist/runtime/components/ASpaceFormModal.d.vue.ts +16 -0
  47. package/dist/runtime/components/ASpaceFormModal.vue +182 -0
  48. package/dist/runtime/components/ASpaceFormModal.vue.d.ts +16 -0
  49. package/dist/runtime/components/AVoiceBar.vue +60 -16
  50. package/dist/runtime/components/AVoiceTile.vue +5 -1
  51. package/dist/runtime/components/AWindowLayer.vue +1 -0
  52. package/dist/runtime/components/aware/AArea.d.vue.ts +1 -1
  53. package/dist/runtime/components/aware/AArea.vue +3 -2
  54. package/dist/runtime/components/aware/AArea.vue.d.ts +1 -1
  55. package/dist/runtime/components/aware/AAvatar.vue +87 -16
  56. package/dist/runtime/components/aware/AButton.vue +7 -2
  57. package/dist/runtime/components/aware/ACursorLabel.vue +6 -1
  58. package/dist/runtime/components/aware/ADocBadge.vue +6 -1
  59. package/dist/runtime/components/aware/AFacepile.vue +15 -3
  60. package/dist/runtime/components/aware/AInput.vue +8 -3
  61. package/dist/runtime/components/aware/ASelect.vue +3 -2
  62. package/dist/runtime/components/aware/ATextarea.vue +8 -3
  63. package/dist/runtime/components/aware/AUserList.vue +10 -2
  64. package/dist/runtime/components/chat/AChatAgentStatus.d.vue.ts +15 -0
  65. package/dist/runtime/components/chat/AChatAgentStatus.vue +95 -0
  66. package/dist/runtime/components/chat/AChatAgentStatus.vue.d.ts +15 -0
  67. package/dist/runtime/components/chat/AChatDocLink.d.vue.ts +18 -0
  68. package/dist/runtime/components/chat/AChatDocLink.vue +29 -0
  69. package/dist/runtime/components/chat/AChatDocLink.vue.d.ts +18 -0
  70. package/dist/runtime/components/chat/AChatDocQuote.d.vue.ts +26 -0
  71. package/dist/runtime/components/chat/AChatDocQuote.vue +47 -0
  72. package/dist/runtime/components/chat/AChatDocQuote.vue.d.ts +26 -0
  73. package/dist/runtime/components/chat/AChatInput.d.vue.ts +45 -0
  74. package/dist/runtime/components/chat/AChatInput.vue +219 -0
  75. package/dist/runtime/components/chat/AChatInput.vue.d.ts +45 -0
  76. package/dist/runtime/components/chat/AChatList.d.vue.ts +59 -0
  77. package/dist/runtime/components/chat/AChatList.vue +184 -0
  78. package/dist/runtime/components/chat/AChatList.vue.d.ts +59 -0
  79. package/dist/runtime/components/chat/AChatMemberList.d.vue.ts +24 -0
  80. package/dist/runtime/components/chat/AChatMemberList.vue +97 -0
  81. package/dist/runtime/components/chat/AChatMemberList.vue.d.ts +24 -0
  82. package/dist/runtime/components/chat/AChatMessages.d.vue.ts +31 -0
  83. package/dist/runtime/components/chat/AChatMessages.vue +161 -0
  84. package/dist/runtime/components/chat/AChatMessages.vue.d.ts +31 -0
  85. package/dist/runtime/components/chat/AChatPanel.d.vue.ts +84 -0
  86. package/dist/runtime/components/chat/AChatPanel.vue +89 -0
  87. package/dist/runtime/components/chat/AChatPanel.vue.d.ts +84 -0
  88. package/dist/runtime/components/chat/AChatTypingIndicator.d.vue.ts +11 -0
  89. package/dist/runtime/components/chat/AChatTypingIndicator.vue +58 -0
  90. package/dist/runtime/components/chat/AChatTypingIndicator.vue.d.ts +11 -0
  91. package/dist/runtime/components/editor/AColorPalettePopover.d.vue.ts +23 -0
  92. package/dist/runtime/components/editor/AColorPalettePopover.vue +71 -0
  93. package/dist/runtime/components/editor/AColorPalettePopover.vue.d.ts +23 -0
  94. package/dist/runtime/components/editor/ADocLinkPopover.d.vue.ts +7 -0
  95. package/dist/runtime/components/editor/ADocLinkPopover.vue +74 -0
  96. package/dist/runtime/components/editor/ADocLinkPopover.vue.d.ts +7 -0
  97. package/dist/runtime/components/editor/AFileAudioPlayer.d.vue.ts +10 -0
  98. package/dist/runtime/components/editor/AFileAudioPlayer.vue +353 -0
  99. package/dist/runtime/components/editor/AFileAudioPlayer.vue.d.ts +10 -0
  100. package/dist/runtime/components/editor/AFileGlbViewer.d.vue.ts +13 -0
  101. package/dist/runtime/components/editor/AFileGlbViewer.vue +187 -0
  102. package/dist/runtime/components/editor/AFileGlbViewer.vue.d.ts +13 -0
  103. package/dist/runtime/components/editor/AFileVideoPlayer.d.vue.ts +7 -0
  104. package/dist/runtime/components/editor/AFileVideoPlayer.vue +62 -0
  105. package/dist/runtime/components/editor/AFileVideoPlayer.vue.d.ts +7 -0
  106. package/dist/runtime/components/editor/ALinkPopover.d.vue.ts +8 -0
  107. package/dist/runtime/components/editor/ALinkPopover.vue +149 -0
  108. package/dist/runtime/components/editor/ALinkPopover.vue.d.ts +8 -0
  109. package/dist/runtime/components/editor/ALocationPickerPopover.d.vue.ts +28 -0
  110. package/dist/runtime/components/editor/ALocationPickerPopover.vue +232 -0
  111. package/dist/runtime/components/editor/ALocationPickerPopover.vue.d.ts +28 -0
  112. package/dist/runtime/components/renderers/ACalendarRenderer.d.vue.ts +14 -1
  113. package/dist/runtime/components/renderers/ACalendarRenderer.vue +279 -125
  114. package/dist/runtime/components/renderers/ACalendarRenderer.vue.d.ts +14 -1
  115. package/dist/runtime/components/renderers/ACallRenderer.d.vue.ts +13 -0
  116. package/dist/runtime/components/renderers/ACallRenderer.vue +172 -0
  117. package/dist/runtime/components/renderers/ACallRenderer.vue.d.ts +13 -0
  118. package/dist/runtime/components/renderers/AChecklistRenderer.d.vue.ts +19 -0
  119. package/dist/runtime/components/renderers/AChecklistRenderer.vue +582 -0
  120. package/dist/runtime/components/renderers/AChecklistRenderer.vue.d.ts +19 -0
  121. package/dist/runtime/components/renderers/ADashboardRenderer.d.vue.ts +19 -0
  122. package/dist/runtime/components/renderers/ADashboardRenderer.vue +1374 -0
  123. package/dist/runtime/components/renderers/ADashboardRenderer.vue.d.ts +19 -0
  124. package/dist/runtime/components/renderers/AGalleryCoverImage.d.vue.ts +8 -0
  125. package/dist/runtime/components/renderers/AGalleryCoverImage.vue +60 -0
  126. package/dist/runtime/components/renderers/AGalleryCoverImage.vue.d.ts +8 -0
  127. package/dist/runtime/components/renderers/AGalleryRenderer.d.vue.ts +12 -1
  128. package/dist/runtime/components/renderers/AGalleryRenderer.vue +327 -53
  129. package/dist/runtime/components/renderers/AGalleryRenderer.vue.d.ts +12 -1
  130. package/dist/runtime/components/renderers/AGraphRenderer.d.vue.ts +19 -0
  131. package/dist/runtime/components/renderers/AGraphRenderer.vue +1030 -0
  132. package/dist/runtime/components/renderers/AGraphRenderer.vue.d.ts +19 -0
  133. package/dist/runtime/components/renderers/AKanbanRenderer.d.vue.ts +13 -1
  134. package/dist/runtime/components/renderers/AKanbanRenderer.vue +490 -140
  135. package/dist/runtime/components/renderers/AKanbanRenderer.vue.d.ts +13 -1
  136. package/dist/runtime/components/renderers/AMapRenderer.d.vue.ts +19 -0
  137. package/dist/runtime/components/renderers/AMapRenderer.vue +1624 -0
  138. package/dist/runtime/components/renderers/AMapRenderer.vue.d.ts +19 -0
  139. package/dist/runtime/components/renderers/AMediaRenderer.d.vue.ts +19 -0
  140. package/dist/runtime/components/renderers/AMediaRenderer.vue +224 -0
  141. package/dist/runtime/components/renderers/AMediaRenderer.vue.d.ts +19 -0
  142. package/dist/runtime/components/renderers/AOutlineRenderer.d.vue.ts +12 -1
  143. package/dist/runtime/components/renderers/AOutlineRenderer.vue +295 -134
  144. package/dist/runtime/components/renderers/AOutlineRenderer.vue.d.ts +12 -1
  145. package/dist/runtime/components/renderers/ASpatialRenderer.d.vue.ts +19 -0
  146. package/dist/runtime/components/renderers/ASpatialRenderer.vue +436 -0
  147. package/dist/runtime/components/renderers/ASpatialRenderer.vue.d.ts +19 -0
  148. package/dist/runtime/components/renderers/ATableRenderer.d.vue.ts +12 -1
  149. package/dist/runtime/components/renderers/ATableRenderer.vue +459 -147
  150. package/dist/runtime/components/renderers/ATableRenderer.vue.d.ts +12 -1
  151. package/dist/runtime/components/renderers/ATimelineRenderer.d.vue.ts +19 -0
  152. package/dist/runtime/components/renderers/ATimelineRenderer.vue +468 -0
  153. package/dist/runtime/components/renderers/ATimelineRenderer.vue.d.ts +19 -0
  154. package/dist/runtime/components/renderers/calendar/ACalendarDayCell.d.vue.ts +41 -0
  155. package/dist/runtime/components/renderers/calendar/ACalendarDayCell.vue +109 -0
  156. package/dist/runtime/components/renderers/calendar/ACalendarDayCell.vue.d.ts +41 -0
  157. package/dist/runtime/components/renderers/calendar/ACalendarDayView.d.vue.ts +49 -0
  158. package/dist/runtime/components/renderers/calendar/ACalendarDayView.vue +152 -0
  159. package/dist/runtime/components/renderers/calendar/ACalendarDayView.vue.d.ts +49 -0
  160. package/dist/runtime/components/renderers/calendar/ACalendarEventChip.d.vue.ts +39 -0
  161. package/dist/runtime/components/renderers/calendar/ACalendarEventChip.vue +101 -0
  162. package/dist/runtime/components/renderers/calendar/ACalendarEventChip.vue.d.ts +39 -0
  163. package/dist/runtime/components/renderers/calendar/ACalendarMonthView.d.vue.ts +43 -0
  164. package/dist/runtime/components/renderers/calendar/ACalendarMonthView.vue +87 -0
  165. package/dist/runtime/components/renderers/calendar/ACalendarMonthView.vue.d.ts +43 -0
  166. package/dist/runtime/components/renderers/calendar/ACalendarToolbar.d.vue.ts +38 -0
  167. package/dist/runtime/components/renderers/calendar/ACalendarToolbar.vue +206 -0
  168. package/dist/runtime/components/renderers/calendar/ACalendarToolbar.vue.d.ts +38 -0
  169. package/dist/runtime/components/renderers/calendar/ACalendarUnscheduled.d.vue.ts +28 -0
  170. package/dist/runtime/components/renderers/calendar/ACalendarUnscheduled.vue +33 -0
  171. package/dist/runtime/components/renderers/calendar/ACalendarUnscheduled.vue.d.ts +28 -0
  172. package/dist/runtime/components/renderers/calendar/ACalendarWeekView.d.vue.ts +50 -0
  173. package/dist/runtime/components/renderers/calendar/ACalendarWeekView.vue +188 -0
  174. package/dist/runtime/components/renderers/calendar/ACalendarWeekView.vue.d.ts +50 -0
  175. package/dist/runtime/components/renderers/media/MediaPlaylist.d.vue.ts +25 -0
  176. package/dist/runtime/components/renderers/media/MediaPlaylist.vue +115 -0
  177. package/dist/runtime/components/renderers/media/MediaPlaylist.vue.d.ts +25 -0
  178. package/dist/runtime/components/renderers/media/MediaSyncBar.d.vue.ts +21 -0
  179. package/dist/runtime/components/renderers/media/MediaSyncBar.vue +61 -0
  180. package/dist/runtime/components/renderers/media/MediaSyncBar.vue.d.ts +21 -0
  181. package/dist/runtime/components/renderers/media/MediaTransportBar.d.vue.ts +22 -0
  182. package/dist/runtime/components/renderers/media/MediaTransportBar.vue +98 -0
  183. package/dist/runtime/components/renderers/media/MediaTransportBar.vue.d.ts +22 -0
  184. package/dist/runtime/components/renderers/spatial/SpatialGround.d.vue.ts +20 -0
  185. package/dist/runtime/components/renderers/spatial/SpatialGround.vue +26 -0
  186. package/dist/runtime/components/renderers/spatial/SpatialGround.vue.d.ts +20 -0
  187. package/dist/runtime/components/renderers/spatial/SpatialObject.d.vue.ts +17 -0
  188. package/dist/runtime/components/renderers/spatial/SpatialObject.vue +257 -0
  189. package/dist/runtime/components/renderers/spatial/SpatialObject.vue.d.ts +17 -0
  190. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.d.vue.ts +15 -0
  191. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.vue +18 -0
  192. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.vue.d.ts +15 -0
  193. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.d.vue.ts +8 -0
  194. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.vue +53 -0
  195. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.vue.d.ts +8 -0
  196. package/dist/runtime/components/renderers/table/ATableColumnHeader.d.vue.ts +25 -0
  197. package/dist/runtime/components/renderers/table/ATableColumnHeader.vue +129 -0
  198. package/dist/runtime/components/renderers/table/ATableColumnHeader.vue.d.ts +25 -0
  199. package/dist/runtime/components/renderers/table/ATableFlatMode.d.vue.ts +21 -0
  200. package/dist/runtime/components/renderers/table/ATableFlatMode.vue +370 -0
  201. package/dist/runtime/components/renderers/table/ATableFlatMode.vue.d.ts +21 -0
  202. package/dist/runtime/components/renderers/table/ATableToolbar.d.vue.ts +22 -0
  203. package/dist/runtime/components/renderers/table/ATableToolbar.vue +106 -0
  204. package/dist/runtime/components/renderers/table/ATableToolbar.vue.d.ts +22 -0
  205. package/dist/runtime/components/renderers/table/cells/ATableCell.d.vue.ts +18 -0
  206. package/dist/runtime/components/renderers/table/cells/ATableCell.vue +54 -0
  207. package/dist/runtime/components/renderers/table/cells/ATableCell.vue.d.ts +18 -0
  208. package/dist/runtime/components/renderers/table/cells/ATableCellColor.d.vue.ts +14 -0
  209. package/dist/runtime/components/renderers/table/cells/ATableCellColor.vue +67 -0
  210. package/dist/runtime/components/renderers/table/cells/ATableCellColor.vue.d.ts +14 -0
  211. package/dist/runtime/components/renderers/table/cells/ATableCellDate.d.vue.ts +16 -0
  212. package/dist/runtime/components/renderers/table/cells/ATableCellDate.vue +91 -0
  213. package/dist/runtime/components/renderers/table/cells/ATableCellDate.vue.d.ts +16 -0
  214. package/dist/runtime/components/renderers/table/cells/ATableCellMembers.d.vue.ts +6 -0
  215. package/dist/runtime/components/renderers/table/cells/ATableCellMembers.vue +30 -0
  216. package/dist/runtime/components/renderers/table/cells/ATableCellMembers.vue.d.ts +6 -0
  217. package/dist/runtime/components/renderers/table/cells/ATableCellMultiSelect.d.vue.ts +17 -0
  218. package/dist/runtime/components/renderers/table/cells/ATableCellMultiSelect.vue +76 -0
  219. package/dist/runtime/components/renderers/table/cells/ATableCellMultiSelect.vue.d.ts +17 -0
  220. package/dist/runtime/components/renderers/table/cells/ATableCellNumber.d.vue.ts +17 -0
  221. package/dist/runtime/components/renderers/table/cells/ATableCellNumber.vue +54 -0
  222. package/dist/runtime/components/renderers/table/cells/ATableCellNumber.vue.d.ts +17 -0
  223. package/dist/runtime/components/renderers/table/cells/ATableCellRating.d.vue.ts +16 -0
  224. package/dist/runtime/components/renderers/table/cells/ATableCellRating.vue +35 -0
  225. package/dist/runtime/components/renderers/table/cells/ATableCellRating.vue.d.ts +16 -0
  226. package/dist/runtime/components/renderers/table/cells/ATableCellSelect.d.vue.ts +18 -0
  227. package/dist/runtime/components/renderers/table/cells/ATableCellSelect.vue +111 -0
  228. package/dist/runtime/components/renderers/table/cells/ATableCellSelect.vue.d.ts +18 -0
  229. package/dist/runtime/components/renderers/table/cells/ATableCellSlider.d.vue.ts +16 -0
  230. package/dist/runtime/components/renderers/table/cells/ATableCellSlider.vue +35 -0
  231. package/dist/runtime/components/renderers/table/cells/ATableCellSlider.vue.d.ts +16 -0
  232. package/dist/runtime/components/renderers/table/cells/ATableCellTags.d.vue.ts +15 -0
  233. package/dist/runtime/components/renderers/table/cells/ATableCellTags.vue +92 -0
  234. package/dist/runtime/components/renderers/table/cells/ATableCellTags.vue.d.ts +15 -0
  235. package/dist/runtime/components/renderers/table/cells/ATableCellText.d.vue.ts +15 -0
  236. package/dist/runtime/components/renderers/table/cells/ATableCellText.vue +44 -0
  237. package/dist/runtime/components/renderers/table/cells/ATableCellText.vue.d.ts +15 -0
  238. package/dist/runtime/components/renderers/table/cells/ATableCellToggle.d.vue.ts +14 -0
  239. package/dist/runtime/components/renderers/table/cells/ATableCellToggle.vue +31 -0
  240. package/dist/runtime/components/renderers/table/cells/ATableCellToggle.vue.d.ts +14 -0
  241. package/dist/runtime/components/renderers/table/cells/ATableCellUrl.d.vue.ts +15 -0
  242. package/dist/runtime/components/renderers/table/cells/ATableCellUrl.vue +63 -0
  243. package/dist/runtime/components/renderers/table/cells/ATableCellUrl.vue.d.ts +15 -0
  244. package/dist/runtime/components/renderers/timeline/ATimelineAxis.d.vue.ts +9 -0
  245. package/dist/runtime/components/renderers/timeline/ATimelineAxis.vue +53 -0
  246. package/dist/runtime/components/renderers/timeline/ATimelineAxis.vue.d.ts +9 -0
  247. package/dist/runtime/components/renderers/timeline/ATimelineBar.d.vue.ts +26 -0
  248. package/dist/runtime/components/renderers/timeline/ATimelineBar.vue +59 -0
  249. package/dist/runtime/components/renderers/timeline/ATimelineBar.vue.d.ts +26 -0
  250. package/dist/runtime/components/renderers/timeline/ATimelineBarArea.d.vue.ts +28 -0
  251. package/dist/runtime/components/renderers/timeline/ATimelineBarArea.vue +109 -0
  252. package/dist/runtime/components/renderers/timeline/ATimelineBarArea.vue.d.ts +28 -0
  253. package/dist/runtime/components/renderers/timeline/ATimelineLabelPanel.d.vue.ts +43 -0
  254. package/dist/runtime/components/renderers/timeline/ATimelineLabelPanel.vue +168 -0
  255. package/dist/runtime/components/renderers/timeline/ATimelineLabelPanel.vue.d.ts +43 -0
  256. package/dist/runtime/components/renderers/timeline/ATimelineMilestone.d.vue.ts +24 -0
  257. package/dist/runtime/components/renderers/timeline/ATimelineMilestone.vue +46 -0
  258. package/dist/runtime/components/renderers/timeline/ATimelineMilestone.vue.d.ts +24 -0
  259. package/dist/runtime/components/renderers/timeline/ATimelineToolbar.d.vue.ts +34 -0
  260. package/dist/runtime/components/renderers/timeline/ATimelineToolbar.vue +193 -0
  261. package/dist/runtime/components/renderers/timeline/ATimelineToolbar.vue.d.ts +34 -0
  262. package/dist/runtime/components/settings/ASettingsAdminPanel.d.vue.ts +3 -0
  263. package/dist/runtime/components/settings/ASettingsAdminPanel.vue +159 -0
  264. package/dist/runtime/components/settings/ASettingsAdminPanel.vue.d.ts +3 -0
  265. package/dist/runtime/components/settings/ASettingsConnectionPanel.d.vue.ts +3 -0
  266. package/dist/runtime/components/settings/ASettingsConnectionPanel.vue +146 -0
  267. package/dist/runtime/components/settings/ASettingsConnectionPanel.vue.d.ts +3 -0
  268. package/dist/runtime/components/settings/ASettingsInvitesPanel.d.vue.ts +3 -0
  269. package/dist/runtime/components/settings/ASettingsInvitesPanel.vue +157 -0
  270. package/dist/runtime/components/settings/ASettingsInvitesPanel.vue.d.ts +3 -0
  271. package/dist/runtime/components/settings/ASettingsMembersPanel.d.vue.ts +3 -0
  272. package/dist/runtime/components/settings/ASettingsMembersPanel.vue +134 -0
  273. package/dist/runtime/components/settings/ASettingsMembersPanel.vue.d.ts +3 -0
  274. package/dist/runtime/components/settings/ASettingsModal.d.vue.ts +3 -0
  275. package/dist/runtime/components/settings/ASettingsModal.vue +176 -0
  276. package/dist/runtime/components/settings/ASettingsModal.vue.d.ts +3 -0
  277. package/dist/runtime/components/settings/ASettingsOfflinePanel.d.vue.ts +3 -0
  278. package/dist/runtime/components/settings/ASettingsOfflinePanel.vue +170 -0
  279. package/dist/runtime/components/settings/ASettingsOfflinePanel.vue.d.ts +3 -0
  280. package/dist/runtime/components/settings/ASettingsPluginsPanel.d.vue.ts +3 -0
  281. package/dist/runtime/components/settings/ASettingsPluginsPanel.vue +96 -0
  282. package/dist/runtime/components/settings/ASettingsPluginsPanel.vue.d.ts +3 -0
  283. package/dist/runtime/components/settings/ASettingsProfilePanel.d.vue.ts +3 -0
  284. package/dist/runtime/components/settings/ASettingsProfilePanel.vue +223 -0
  285. package/dist/runtime/components/settings/ASettingsProfilePanel.vue.d.ts +3 -0
  286. package/dist/runtime/components/settings/ASettingsSecurityPanel.d.vue.ts +3 -0
  287. package/dist/runtime/components/settings/ASettingsSecurityPanel.vue +312 -0
  288. package/dist/runtime/components/settings/ASettingsSecurityPanel.vue.d.ts +3 -0
  289. package/dist/runtime/components/settings/ASettingsSpacesPanel.d.vue.ts +3 -0
  290. package/dist/runtime/components/settings/ASettingsSpacesPanel.vue +195 -0
  291. package/dist/runtime/components/settings/ASettingsSpacesPanel.vue.d.ts +3 -0
  292. package/dist/runtime/components/settings/ASettingsTrashPanel.d.vue.ts +3 -0
  293. package/dist/runtime/components/settings/ASettingsTrashPanel.vue +135 -0
  294. package/dist/runtime/components/settings/ASettingsTrashPanel.vue.d.ts +3 -0
  295. package/dist/runtime/components/shell/AChildContextMenu.d.vue.ts +30 -0
  296. package/dist/runtime/components/shell/AChildContextMenu.vue +48 -0
  297. package/dist/runtime/components/shell/AChildContextMenu.vue.d.ts +30 -0
  298. package/dist/runtime/components/shell/ACursorOverlay.d.vue.ts +11 -0
  299. package/dist/runtime/components/shell/ACursorOverlay.vue +55 -0
  300. package/dist/runtime/components/shell/ACursorOverlay.vue.d.ts +11 -0
  301. package/dist/runtime/components/shell/ADocDragGhost.d.vue.ts +3 -0
  302. package/dist/runtime/components/shell/ADocDragGhost.vue +58 -0
  303. package/dist/runtime/components/shell/ADocDragGhost.vue.d.ts +3 -0
  304. package/dist/runtime/components/shell/ADocPanelSettings.d.vue.ts +111 -0
  305. package/dist/runtime/components/shell/ADocPanelSettings.vue +621 -0
  306. package/dist/runtime/components/shell/ADocPanelSettings.vue.d.ts +111 -0
  307. package/dist/runtime/components/shell/AFavoritesList.d.vue.ts +27 -0
  308. package/dist/runtime/components/shell/AFavoritesList.vue +83 -0
  309. package/dist/runtime/components/shell/AFavoritesList.vue.d.ts +27 -0
  310. package/dist/runtime/components/shell/ANodeContextMenu.d.vue.ts +17 -0
  311. package/dist/runtime/components/shell/ANodeContextMenu.vue +14 -0
  312. package/dist/runtime/components/shell/ANodeContextMenu.vue.d.ts +17 -0
  313. package/dist/runtime/components/shell/ASidebar.d.vue.ts +54 -0
  314. package/dist/runtime/components/shell/ASidebar.vue +92 -0
  315. package/dist/runtime/components/shell/ASidebar.vue.d.ts +54 -0
  316. package/dist/runtime/components/shell/ASidebarToggle.d.vue.ts +7 -0
  317. package/dist/runtime/components/shell/ASidebarToggle.vue +23 -0
  318. package/dist/runtime/components/shell/ASidebarToggle.vue.d.ts +7 -0
  319. package/dist/runtime/components/shell/ASpaceSwitcher.d.vue.ts +32 -0
  320. package/dist/runtime/components/shell/ASpaceSwitcher.vue +63 -0
  321. package/dist/runtime/components/shell/ASpaceSwitcher.vue.d.ts +32 -0
  322. package/dist/runtime/components/shell/ASyncStatus.d.vue.ts +25 -0
  323. package/dist/runtime/components/shell/ASyncStatus.vue +96 -0
  324. package/dist/runtime/components/shell/ASyncStatus.vue.d.ts +25 -0
  325. package/dist/runtime/components/shell/AUserMenu.d.vue.ts +28 -0
  326. package/dist/runtime/components/shell/AUserMenu.vue +79 -0
  327. package/dist/runtime/components/shell/AUserMenu.vue.d.ts +28 -0
  328. package/dist/runtime/components/shell/AUserProfilePopover.d.vue.ts +54 -0
  329. package/dist/runtime/components/shell/AUserProfilePopover.vue +176 -0
  330. package/dist/runtime/components/shell/AUserProfilePopover.vue.d.ts +54 -0
  331. package/dist/runtime/components/shell/AWelcomeScreen.d.vue.ts +96 -0
  332. package/dist/runtime/components/shell/AWelcomeScreen.vue +422 -0
  333. package/dist/runtime/components/shell/AWelcomeScreen.vue.d.ts +96 -0
  334. package/dist/runtime/composables/useAAField.js +2 -0
  335. package/dist/runtime/composables/useAbraLocale.js +1 -0
  336. package/dist/runtime/composables/useAbracadabra.js +1 -0
  337. package/dist/runtime/composables/useAbracadabraAuth.d.ts +3 -4
  338. package/dist/runtime/composables/useAbracadabraAuth.js +4 -0
  339. package/dist/runtime/composables/useAwareness.js +6 -0
  340. package/dist/runtime/composables/useAwarenessPeers.js +1 -0
  341. package/dist/runtime/composables/useBackgroundSync.d.ts +5 -0
  342. package/dist/runtime/composables/useBackgroundSync.js +24 -3
  343. package/dist/runtime/composables/useBroadcastSync.d.ts +18 -0
  344. package/dist/runtime/composables/useBroadcastSync.js +26 -0
  345. package/dist/runtime/composables/useCalendarView.d.ts +86 -0
  346. package/dist/runtime/composables/useCalendarView.js +316 -0
  347. package/dist/runtime/composables/useChat.d.ts +2 -1
  348. package/dist/runtime/composables/useChat.js +21 -12
  349. package/dist/runtime/composables/useChatUsers.js +3 -1
  350. package/dist/runtime/composables/useChildTree.d.ts +4 -2
  351. package/dist/runtime/composables/useChildTree.js +31 -21
  352. package/dist/runtime/composables/useCommandPalette.js +77 -19
  353. package/dist/runtime/composables/useConnectionStatus.d.ts +1 -1
  354. package/dist/runtime/composables/useConnectionStatus.js +8 -1
  355. package/dist/runtime/composables/useCrossWindowSync.d.ts +11 -0
  356. package/dist/runtime/composables/useCrossWindowSync.js +38 -0
  357. package/dist/runtime/composables/useDashboard.js +17 -9
  358. package/dist/runtime/composables/useDevicePairing.d.ts +58 -0
  359. package/dist/runtime/composables/useDevicePairing.js +110 -0
  360. package/dist/runtime/composables/useDocDragBus.d.ts +28 -0
  361. package/dist/runtime/composables/useDocDragBus.js +22 -0
  362. package/dist/runtime/composables/useDocDropZone.d.ts +51 -0
  363. package/dist/runtime/composables/useDocDropZone.js +84 -0
  364. package/dist/runtime/composables/useDocExport.d.ts +5 -0
  365. package/dist/runtime/composables/useDocExport.js +4 -2
  366. package/dist/runtime/composables/useDocImport.js +5 -3
  367. package/dist/runtime/composables/useDocLabels.d.ts +22 -0
  368. package/dist/runtime/composables/useDocLabels.js +11 -0
  369. package/dist/runtime/composables/useDocLinkPick.d.ts +18 -0
  370. package/dist/runtime/composables/useDocLinkPick.js +22 -0
  371. package/dist/runtime/composables/useDocSeo.d.ts +20 -0
  372. package/dist/runtime/composables/useDocSeo.js +45 -0
  373. package/dist/runtime/composables/useDocSlugs.d.ts +7 -0
  374. package/dist/runtime/composables/useDocSlugs.js +23 -0
  375. package/dist/runtime/composables/useDocTree.d.ts +35 -0
  376. package/dist/runtime/composables/useDocTree.js +39 -0
  377. package/dist/runtime/composables/useEditor.js +1 -0
  378. package/dist/runtime/composables/useEditorDragHandle.js +4 -1
  379. package/dist/runtime/composables/useEditorEmojis.d.ts +22 -0
  380. package/dist/runtime/composables/useEditorEmojis.js +57 -0
  381. package/dist/runtime/composables/useEditorMentions.d.ts +10 -3
  382. package/dist/runtime/composables/useEditorMentions.js +35 -5
  383. package/dist/runtime/composables/useEditorSuggestions.d.ts +2 -1
  384. package/dist/runtime/composables/useEditorSuggestions.js +36 -21
  385. package/dist/runtime/composables/useEditorToolbar.d.ts +1 -1
  386. package/dist/runtime/composables/useEditorToolbar.js +5 -1
  387. package/dist/runtime/composables/useFavorites.d.ts +13 -0
  388. package/dist/runtime/composables/useFavorites.js +42 -0
  389. package/dist/runtime/composables/useFileIndex.js +4 -1
  390. package/dist/runtime/composables/useFileTransfer.d.ts +112 -0
  391. package/dist/runtime/composables/useFileTransfer.js +183 -0
  392. package/dist/runtime/composables/useFollowUser.js +4 -1
  393. package/dist/runtime/composables/useIdentityDoc.d.ts +89 -0
  394. package/dist/runtime/composables/useIdentityDoc.js +349 -0
  395. package/dist/runtime/composables/useInstalledPlugins.d.ts +31 -0
  396. package/dist/runtime/composables/useInstalledPlugins.js +58 -0
  397. package/dist/runtime/composables/useInvites.d.ts +56 -0
  398. package/dist/runtime/composables/useInvites.js +78 -0
  399. package/dist/runtime/composables/useJoinLink.d.ts +25 -0
  400. package/dist/runtime/composables/useJoinLink.js +58 -0
  401. package/dist/runtime/composables/useMediaExtractor.d.ts +31 -0
  402. package/dist/runtime/composables/useMediaExtractor.js +46 -0
  403. package/dist/runtime/composables/useMediaPlayback.d.ts +43 -0
  404. package/dist/runtime/composables/useMediaPlayback.js +465 -0
  405. package/dist/runtime/composables/useNodeContextMenu.d.ts +26 -0
  406. package/dist/runtime/composables/useNodeContextMenu.js +99 -0
  407. package/dist/runtime/composables/useNodePanel.d.ts +20 -0
  408. package/dist/runtime/composables/useNodePanel.js +89 -0
  409. package/dist/runtime/composables/useNodePanelFollow.d.ts +2 -0
  410. package/dist/runtime/composables/useNodePanelFollow.js +37 -0
  411. package/dist/runtime/composables/useNotifications.d.ts +1 -0
  412. package/dist/runtime/composables/useNotifications.js +9 -2
  413. package/dist/runtime/composables/usePasskeyAccounts.js +4 -2
  414. package/dist/runtime/composables/usePluginRegistry.js +1 -0
  415. package/dist/runtime/composables/useRendererBase.d.ts +16 -1
  416. package/dist/runtime/composables/useRendererBase.js +10 -1
  417. package/dist/runtime/composables/useSearchIndex.d.ts +1 -0
  418. package/dist/runtime/composables/useSearchIndex.js +15 -5
  419. package/dist/runtime/composables/useServerInfo.d.ts +31 -0
  420. package/dist/runtime/composables/useServerInfo.js +80 -0
  421. package/dist/runtime/composables/useSettingsModal.d.ts +18 -0
  422. package/dist/runtime/composables/useSettingsModal.js +30 -0
  423. package/dist/runtime/composables/useSlideoverSwipe.d.ts +39 -0
  424. package/dist/runtime/composables/useSlideoverSwipe.js +48 -0
  425. package/dist/runtime/composables/useSlugRoute.d.ts +6 -0
  426. package/dist/runtime/composables/useSlugRoute.js +21 -0
  427. package/dist/runtime/composables/useSpaces.d.ts +37 -0
  428. package/dist/runtime/composables/useSpaces.js +85 -0
  429. package/dist/runtime/composables/useSpatialCamera.d.ts +16 -0
  430. package/dist/runtime/composables/useSpatialCamera.js +175 -0
  431. package/dist/runtime/composables/useSpatialDrag.d.ts +14 -0
  432. package/dist/runtime/composables/useSpatialDrag.js +137 -0
  433. package/dist/runtime/composables/useTableView.d.ts +29 -0
  434. package/dist/runtime/composables/useTableView.js +184 -0
  435. package/dist/runtime/composables/useTimelineView.d.ts +55 -0
  436. package/dist/runtime/composables/useTimelineView.js +434 -0
  437. package/dist/runtime/composables/useTiptapDragState.d.ts +8 -0
  438. package/dist/runtime/composables/useTiptapDragState.js +5 -0
  439. package/dist/runtime/composables/useTouchDrag.d.ts +36 -0
  440. package/dist/runtime/composables/useTouchDrag.js +194 -0
  441. package/dist/runtime/composables/useTrash.d.ts +5 -1
  442. package/dist/runtime/composables/useTrash.js +12 -6
  443. package/dist/runtime/composables/useTreeUndoManager.d.ts +22 -0
  444. package/dist/runtime/composables/useTreeUndoManager.js +45 -0
  445. package/dist/runtime/composables/useUndoRedo.d.ts +37 -0
  446. package/dist/runtime/composables/useUndoRedo.js +115 -0
  447. package/dist/runtime/composables/useVoice.js +2 -0
  448. package/dist/runtime/composables/useWebRTC.d.ts +50 -0
  449. package/dist/runtime/composables/useWebRTC.js +179 -0
  450. package/dist/runtime/composables/useWindowManager.d.ts +2 -0
  451. package/dist/runtime/composables/useWindowManager.js +63 -1
  452. package/dist/runtime/extensions/code-preview.d.ts +2 -0
  453. package/dist/runtime/extensions/code-preview.js +17 -0
  454. package/dist/runtime/extensions/code-tree.d.ts +2 -0
  455. package/dist/runtime/extensions/code-tree.js +33 -0
  456. package/dist/runtime/extensions/doc-embed.d.ts +12 -0
  457. package/dist/runtime/extensions/doc-embed.js +63 -0
  458. package/dist/runtime/extensions/doc-link-drop.d.ts +3 -0
  459. package/dist/runtime/extensions/doc-link-drop.js +63 -0
  460. package/dist/runtime/extensions/document-header.js +1 -1
  461. package/dist/runtime/extensions/field.d.ts +3 -0
  462. package/dist/runtime/extensions/field.js +53 -0
  463. package/dist/runtime/extensions/mention-drop.d.ts +8 -0
  464. package/dist/runtime/extensions/mention-drop.js +47 -0
  465. package/dist/runtime/extensions/meta-field.d.ts +4 -1
  466. package/dist/runtime/extensions/meta-field.js +2 -0
  467. package/dist/runtime/extensions/selection-drag.d.ts +13 -0
  468. package/dist/runtime/extensions/selection-drag.js +126 -0
  469. package/dist/runtime/extensions/steps.js +1 -1
  470. package/dist/runtime/extensions/views/AccordionItemView.vue +14 -3
  471. package/dist/runtime/extensions/views/AccordionView.vue +4 -1
  472. package/dist/runtime/extensions/views/BadgeView.vue +12 -2
  473. package/dist/runtime/extensions/views/CalloutView.vue +4 -1
  474. package/dist/runtime/extensions/views/CardGroupView.vue +4 -1
  475. package/dist/runtime/extensions/views/CardView.vue +18 -3
  476. package/dist/runtime/extensions/views/CodeCollapseView.vue +1 -0
  477. package/dist/runtime/extensions/views/CodeGroupView.vue +5 -1
  478. package/dist/runtime/extensions/views/CodePreviewView.d.vue.ts +4 -0
  479. package/dist/runtime/extensions/views/CodePreviewView.vue +48 -0
  480. package/dist/runtime/extensions/views/CodePreviewView.vue.d.ts +4 -0
  481. package/dist/runtime/extensions/views/CodeTreeView.d.vue.ts +4 -0
  482. package/dist/runtime/extensions/views/CodeTreeView.vue +88 -0
  483. package/dist/runtime/extensions/views/CodeTreeView.vue.d.ts +4 -0
  484. package/dist/runtime/extensions/views/CollapsibleView.vue +9 -2
  485. package/dist/runtime/extensions/views/DocEmbedView.d.vue.ts +4 -0
  486. package/dist/runtime/extensions/views/DocEmbedView.vue +198 -0
  487. package/dist/runtime/extensions/views/DocEmbedView.vue.d.ts +4 -0
  488. package/dist/runtime/extensions/views/FieldGroupView.d.vue.ts +4 -0
  489. package/dist/runtime/extensions/views/FieldGroupView.vue +25 -0
  490. package/dist/runtime/extensions/views/FieldGroupView.vue.d.ts +4 -0
  491. package/dist/runtime/extensions/views/FieldView.d.vue.ts +4 -0
  492. package/dist/runtime/extensions/views/FieldView.vue +53 -0
  493. package/dist/runtime/extensions/views/FieldView.vue.d.ts +4 -0
  494. package/dist/runtime/extensions/views/FileNodeView.vue +34 -8
  495. package/dist/runtime/extensions/views/KbdView.vue +9 -2
  496. package/dist/runtime/extensions/views/MetaFieldView.vue +276 -48
  497. package/dist/runtime/extensions/views/ProseIconView.vue +9 -2
  498. package/dist/runtime/extensions/views/StepsView.vue +1 -0
  499. package/dist/runtime/extensions/views/TabsView.vue +18 -4
  500. package/dist/runtime/locale.d.ts +136 -0
  501. package/dist/runtime/locale.js +137 -1
  502. package/dist/runtime/middleware/abracadabra-auth.d.ts +1 -10
  503. package/dist/runtime/middleware/abracadabra-auth.js +2 -0
  504. package/dist/runtime/plugin-abracadabra.client.d.ts +1 -1
  505. package/dist/runtime/plugin-abracadabra.client.js +127 -55
  506. package/dist/runtime/plugin-abracadabra.server.d.ts +1 -1
  507. package/dist/runtime/plugin-abracadabra.server.js +4 -0
  508. package/dist/runtime/plugin-shared-globals.client.d.ts +1 -1
  509. package/dist/runtime/plugin-shared-globals.client.js +1 -0
  510. package/dist/runtime/plugins/core.plugin.js +40 -4
  511. package/dist/runtime/server/api/_abracadabra/render/[docId].get.d.ts +19 -17
  512. package/dist/runtime/server/api/_abracadabra/render/[docId].get.js +33 -4
  513. package/dist/runtime/server/api/_abracadabra/resolve/[...slug].get.d.ts +12 -0
  514. package/dist/runtime/server/api/_abracadabra/resolve/[...slug].get.js +44 -0
  515. package/dist/runtime/server/api/_abracadabra/slugs.get.d.ts +2 -0
  516. package/dist/runtime/server/api/_abracadabra/slugs.get.js +8 -0
  517. package/dist/runtime/server/api/_abracadabra/spaces.get.d.ts +1 -10
  518. package/dist/runtime/server/api/_abracadabra/spaces.get.js +3 -0
  519. package/dist/runtime/server/plugins/abracadabra-service.js +29 -12
  520. package/dist/runtime/server/runners/doc-tree-cache.js +4 -0
  521. package/dist/runtime/server/utils/docCache.d.ts +8 -6
  522. package/dist/runtime/server/utils/docCache.js +3 -3
  523. package/dist/runtime/server/utils/serverPluginLoader.d.ts +20 -0
  524. package/dist/runtime/server/utils/serverPluginLoader.js +42 -0
  525. package/dist/runtime/server/utils/serverRunner.d.ts +11 -2
  526. package/dist/runtime/server/utils/serverRunner.js +21 -10
  527. package/dist/runtime/server/utils/slugMap.d.ts +32 -0
  528. package/dist/runtime/server/utils/slugMap.js +58 -0
  529. package/dist/runtime/server/utils/spaceManager.d.ts +25 -0
  530. package/dist/runtime/server/utils/spaceManager.js +188 -0
  531. package/dist/runtime/types.d.ts +129 -30
  532. package/dist/runtime/types.js +17 -17
  533. package/dist/runtime/utils/chatContent.d.ts +41 -0
  534. package/dist/runtime/utils/chatContent.js +65 -0
  535. package/dist/runtime/utils/colorPalettes.js +12 -6
  536. package/dist/runtime/utils/coverCache.d.ts +12 -0
  537. package/dist/runtime/utils/coverCache.js +14 -0
  538. package/dist/runtime/utils/docReferenceEdges.d.ts +26 -0
  539. package/dist/runtime/utils/docReferenceEdges.js +122 -0
  540. package/dist/runtime/utils/docTypes.d.ts +34 -1
  541. package/dist/runtime/utils/docTypes.js +129 -1
  542. package/dist/runtime/utils/duplicateDocContent.d.ts +19 -0
  543. package/dist/runtime/utils/duplicateDocContent.js +68 -0
  544. package/dist/runtime/utils/extractFileMetadata.d.ts +13 -0
  545. package/dist/runtime/utils/extractFileMetadata.js +94 -0
  546. package/dist/runtime/utils/getMetaColor.d.ts +6 -0
  547. package/dist/runtime/utils/getMetaColor.js +12 -0
  548. package/dist/runtime/utils/htmlToYjs.d.ts +19 -0
  549. package/dist/runtime/utils/htmlToYjs.js +235 -0
  550. package/dist/runtime/utils/markdownToYjs.js +5 -5
  551. package/dist/runtime/utils/metaFieldDefinitions.js +9 -0
  552. package/dist/runtime/utils/notificationRenderers.d.ts +13 -0
  553. package/dist/runtime/utils/notificationRenderers.js +41 -0
  554. package/dist/runtime/utils/sdkRef.d.ts +12 -0
  555. package/dist/runtime/utils/sdkRef.js +7 -0
  556. package/dist/runtime/utils/slugify.d.ts +40 -0
  557. package/dist/runtime/utils/slugify.js +36 -0
  558. package/dist/types.d.mts +18 -0
  559. package/package.json +44 -32
@@ -0,0 +1,1624 @@
1
+ <script setup>
2
+ import { ref, computed, watch, shallowRef, onMounted, onBeforeUnmount, onUnmounted, defineAsyncComponent } from "vue";
3
+ import { useRuntimeConfig, useColorMode } from "#imports";
4
+ import { useAbracadabra } from "../../composables/useAbracadabra";
5
+ import { useRendererBase } from "../../composables/useRendererBase";
6
+ import { useNodePanel } from "../../composables/useNodePanel";
7
+ import { DEFAULT_LOCALE } from "../../locale";
8
+ const AEditor = defineAsyncComponent(
9
+ () => import("../AEditor.vue")
10
+ );
11
+ const props = defineProps({
12
+ docId: { type: String, required: true },
13
+ childProvider: { type: null, required: true },
14
+ docLabel: { type: String, required: true },
15
+ pageTypes: { type: Array, required: false },
16
+ labels: { type: Object, required: false },
17
+ editable: { type: Boolean, required: false, default: true }
18
+ });
19
+ const config = useRuntimeConfig();
20
+ const locale = computed(() => ({
21
+ ...DEFAULT_LOCALE.renderers.map,
22
+ ...config.public?.abracadabra?.locale?.renderers?.map ?? {},
23
+ ...props.labels ?? {}
24
+ }));
25
+ const { childProviderRef, tree, connectedUsers, states, setLocalState } = useRendererBase(props);
26
+ const { userName, userColor: userColorName } = useAbracadabra();
27
+ const localClientId = computed(
28
+ () => childProviderRef.value?.awareness?.clientID ?? 0
29
+ );
30
+ const {
31
+ openNodeId,
32
+ openNodeLabel,
33
+ openNodeProvider,
34
+ isLoading: _nodePanelLoading,
35
+ openNode,
36
+ closePanel
37
+ } = useNodePanel(childProviderRef);
38
+ let mapboxgl = null;
39
+ const mapboxLoaded = ref(false);
40
+ const mapboxError = ref(null);
41
+ const allEntries = computed(() => tree.childrenOf(null));
42
+ function getEntryLocation(entry) {
43
+ if (entry.meta?.geoLat !== void 0 && entry.meta?.geoLng !== void 0) {
44
+ return { lat: entry.meta.geoLat, lng: entry.meta.geoLng };
45
+ }
46
+ const meta = entry.meta;
47
+ if (meta) {
48
+ for (const key of Object.keys(meta)) {
49
+ if (key.startsWith("_lat_")) {
50
+ const lat = meta[key];
51
+ const lng = meta["_lng_" + key.slice(5)];
52
+ if (typeof lat === "number" && typeof lng === "number") {
53
+ return { lat, lng };
54
+ }
55
+ }
56
+ }
57
+ }
58
+ return null;
59
+ }
60
+ const markers = computed(
61
+ () => allEntries.value.filter((e) => {
62
+ if (e.meta?.geoType === "line" || e.meta?.geoType === "measure")
63
+ return false;
64
+ return e.meta?.geoType === "marker" || getEntryLocation(e) !== null;
65
+ })
66
+ );
67
+ const lines = computed(
68
+ () => allEntries.value.filter((e) => e.meta?.geoType === "line")
69
+ );
70
+ const measures = computed(
71
+ () => allEntries.value.filter((e) => e.meta?.geoType === "measure")
72
+ );
73
+ const markerInstances = /* @__PURE__ */ new Map();
74
+ const linePointInstances = /* @__PURE__ */ new Map();
75
+ function entryToMarkerData(entry) {
76
+ const loc = getEntryLocation(entry);
77
+ return {
78
+ lng: loc?.lng ?? 0,
79
+ lat: loc?.lat ?? 0,
80
+ label: entry.label,
81
+ icon: entry.meta?.icon ?? "map-pin",
82
+ color: entry.meta?.color ?? "#3b82f6",
83
+ addedByName: "",
84
+ createdAt: entry.order
85
+ };
86
+ }
87
+ const MARKER_ICON_SVG = {
88
+ "map-pin": `<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/>`,
89
+ "star": `<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>`,
90
+ "flag": `<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/>`,
91
+ "home": `<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/>`,
92
+ "building-2": `<path d="M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z"/><path d="M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2"/><path d="M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2"/><path d="M10 6h4"/><path d="M10 10h4"/><path d="M10 14h4"/><path d="M10 18h4"/>`,
93
+ "coffee": `<path d="M17 8h1a4 4 0 1 1 0 8h-1"/><path d="M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4Z"/><line x1="6" y1="2" x2="6" y2="4"/><line x1="10" y1="2" x2="10" y2="4"/><line x1="14" y1="2" x2="14" y2="4"/>`,
94
+ "utensils": `<path d="M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2"/><path d="M7 2v20"/><path d="M21 15V2a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7"/>`,
95
+ "camera": `<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/>`,
96
+ "heart": `<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>`,
97
+ "zap": `<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>`,
98
+ "triangle-alert": `<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>`,
99
+ "car": `<path d="M19 17H5a2 2 0 0 1-2-2V9l2-4h14l2 4v6a2 2 0 0 1-2 2Z"/><path d="M9 17v2"/><path d="M15 17v2"/><circle cx="7.5" cy="13.5" r="1.5"/><circle cx="16.5" cy="13.5" r="1.5"/>`,
100
+ "plane": `<path d="M17.8 19.2 16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.5-.1 1 .3 1.3L9 12l-2 3H4l-1 1 3 2 2 3 1-1v-3l3-2 3.5 5.3c.3.4.8.5 1.3.3l.5-.2c.4-.3.6-.7.5-1.2z"/>`,
101
+ "anchor": `<circle cx="12" cy="5" r="3"/><line x1="12" y1="22" x2="12" y2="8"/><path d="M5 12H2a10 10 0 0 0 20 0h-3"/>`,
102
+ "tree-pine": `<path d="m17 14 3 3.3a1 1 0 0 1-.7 1.7H4.7a1 1 0 0 1-.7-1.7L7 14"/><path d="m14 10 3 3.3a1 1 0 0 1-.7 1.7H7.7a1 1 0 0 1-.7-1.7L10 10"/><path d="M12 2 7 7.7a1 1 0 0 0 .7 1.7h8.6a1 1 0 0 0 .7-1.7L12 2Z"/><path d="M12 22v-3"/>`,
103
+ "mountain": `<path d="m8 3 4 8 5-5 5 15H2L8 3z"/>`,
104
+ "waves": `<path d="M2 6c.6.5 1.2 1 2.5 1C7 7 7 5 9.5 5c2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/><path d="M2 12c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/><path d="M2 18c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/>`,
105
+ "shield": `<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>`,
106
+ "crosshair": `<circle cx="12" cy="12" r="10"/><line x1="22" y1="12" x2="18" y2="12"/><line x1="6" y1="12" x2="2" y2="12"/><line x1="12" y1="6" x2="12" y2="2"/><line x1="12" y1="22" x2="12" y2="18"/>`,
107
+ "circle-dot": `<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="1"/>`,
108
+ "bookmark": `<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/>`,
109
+ "gem": `<path d="M6 3h12l4 6-10 13L2 9Z"/><path d="M11 3 8 9l4 13 4-13-3-6"/><path d="M2 9h20"/>`,
110
+ "radio": `<circle cx="12" cy="12" r="2"/><path d="M4.93 4.93a10 10 0 0 0 0 14.14"/><path d="M7.76 7.76a6 6 0 0 0 0 8.48"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M16.24 7.76a6 6 0 0 1 0 8.48"/>`,
111
+ "compass": `<circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/>`
112
+ };
113
+ const MARKER_COLORS = [
114
+ { key: "blue", hex: "#3b82f6", border: "#1d4ed8" },
115
+ { key: "orange", hex: "#f97316", border: "#c2410c" },
116
+ { key: "green", hex: "#22c55e", border: "#15803d" },
117
+ { key: "red", hex: "#ef4444", border: "#b91c1c" },
118
+ { key: "purple", hex: "#a855f7", border: "#7e22ce" }
119
+ ];
120
+ const COLOR_HEX = {
121
+ primary: "#6366f1",
122
+ blue: "#3b82f6",
123
+ sky: "#0ea5e9",
124
+ indigo: "#6366f1",
125
+ cyan: "#06b6d4",
126
+ green: "#22c55e",
127
+ emerald: "#10b981",
128
+ teal: "#14b8a6",
129
+ orange: "#f97316",
130
+ amber: "#f59e0b",
131
+ yellow: "#eab308",
132
+ red: "#ef4444",
133
+ rose: "#f43f5e",
134
+ pink: "#ec4899",
135
+ purple: "#a855f7",
136
+ violet: "#8b5cf6",
137
+ neutral: "#6b7280",
138
+ slate: "#64748b"
139
+ };
140
+ const mapContainer = ref();
141
+ let map = null;
142
+ let mapResizeObserver = null;
143
+ const mapReady = ref(false);
144
+ const mapFadedIn = ref(false);
145
+ const colorMode = useColorMode();
146
+ const isDark = computed(() => colorMode.value === "dark");
147
+ const activeMode = ref("pan");
148
+ const showLabels = ref(true);
149
+ const popupProvider = shallowRef(null);
150
+ const popupDocId = ref(null);
151
+ const popupDocLabel = ref("");
152
+ async function loadPopupProvider(nodeId, label) {
153
+ popupProvider.value = null;
154
+ popupDocId.value = nodeId;
155
+ popupDocLabel.value = label;
156
+ if (!childProviderRef.value) return;
157
+ try {
158
+ const childProv = await childProviderRef.value.loadChild(nodeId);
159
+ if (!childProv.isSynced) {
160
+ await new Promise((resolve) => {
161
+ const done = () => {
162
+ childProv.off("synced", done);
163
+ resolve();
164
+ };
165
+ childProv.on("synced", done);
166
+ setTimeout(resolve, 4e3);
167
+ });
168
+ }
169
+ const doc = childProv.document;
170
+ const frag = doc.getXmlFragment("default");
171
+ if (!frag._item) {
172
+ doc.transact(() => {
173
+ void frag.length;
174
+ });
175
+ }
176
+ if (popupDocId.value === nodeId) {
177
+ popupProvider.value = childProv;
178
+ }
179
+ } catch (e) {
180
+ console.error("Failed to load popup provider:", e);
181
+ }
182
+ }
183
+ function clearPopupProvider() {
184
+ popupProvider.value = null;
185
+ popupDocId.value = null;
186
+ popupDocLabel.value = "";
187
+ }
188
+ const selectedMarkerKey = ref(null);
189
+ const markerPopupScreenPos = ref({ x: 0, y: 0 });
190
+ const selectedMarker = computed(
191
+ () => selectedMarkerKey.value ? markers.value.find((e) => e.id === selectedMarkerKey.value) ?? null : null
192
+ );
193
+ const selectedLineKey = ref(null);
194
+ const linePopupScreenPos = ref({ x: 0, y: 0 });
195
+ const linePopupGeoPos = ref(null);
196
+ const selectedLine = computed(
197
+ () => selectedLineKey.value ? lines.value.find((e) => e.id === selectedLineKey.value) ?? null : null
198
+ );
199
+ watch([selectedMarkerKey, selectedLineKey], ([mk, lk]) => {
200
+ if (!mk && !lk) clearPopupProvider();
201
+ });
202
+ const selectedMeasureKey = ref(null);
203
+ const measurePopupScreenPos = ref({ x: 0, y: 0 });
204
+ const measurePopupGeoPos = ref(null);
205
+ const selectedMeasureInfo = computed(() => {
206
+ if (!selectedMeasureKey.value) return null;
207
+ const entry = measures.value.find((e) => e.id === selectedMeasureKey.value);
208
+ if (!entry) return null;
209
+ const pts = tree.childrenOf(entry.id).filter(
210
+ (p) => p.meta?.geoLat !== void 0 && p.meta?.geoLng !== void 0
211
+ );
212
+ if (pts.length < 2) return null;
213
+ let dist = 0;
214
+ for (let i = 1; i < pts.length; i++) {
215
+ dist += haversine(
216
+ [pts[i - 1].meta.geoLng, pts[i - 1].meta.geoLat],
217
+ [pts[i].meta.geoLng, pts[i].meta.geoLat]
218
+ );
219
+ }
220
+ return { entry, dist };
221
+ });
222
+ const drawPoints = ref([]);
223
+ const drawMouseLngLat = ref(null);
224
+ const measurePoints = ref([]);
225
+ const measurePreviewScreenPos = ref({ x: 0, y: 0 });
226
+ const measurePreviewTotal = computed(() => {
227
+ let d = 0;
228
+ for (let i = 1; i < measurePoints.value.length; i++)
229
+ d += haversine(measurePoints.value[i - 1], measurePoints.value[i]);
230
+ return d;
231
+ });
232
+ function haversine(a, b) {
233
+ const R = 6371e3;
234
+ const \u03C61 = a[1] * Math.PI / 180, \u03C62 = b[1] * Math.PI / 180;
235
+ const \u0394\u03C6 = (b[1] - a[1]) * Math.PI / 180, \u0394\u03BB = (b[0] - a[0]) * Math.PI / 180;
236
+ const x = Math.sin(\u0394\u03C6 / 2) ** 2 + Math.cos(\u03C61) * Math.cos(\u03C62) * Math.sin(\u0394\u03BB / 2) ** 2;
237
+ return R * 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1 - x));
238
+ }
239
+ function formatDist(m) {
240
+ return m >= 1e3 ? `${(m / 1e3).toFixed(1)} km` : `${Math.round(m)} m`;
241
+ }
242
+ const pingElements = /* @__PURE__ */ new Map();
243
+ const measureLabelEls = /* @__PURE__ */ new Map();
244
+ const followingClientId = ref(null);
245
+ let lastAppliedFollowTime = 0;
246
+ let followEaseInProgress = false;
247
+ let rafId = 0;
248
+ let broadcastFrame = 0;
249
+ const CURSOR_LERP = 0.25;
250
+ const CAMERA_LERP = 0.08;
251
+ const myColorHex = computed(() => COLOR_HEX[userColorName.value] ?? "#6366f1");
252
+ const mapCursorClass = computed(
253
+ () => activeMode.value !== "pan" && followingClientId.value === null ? "cursor-crosshair" : ""
254
+ );
255
+ const modeHint = computed(() => {
256
+ switch (activeMode.value) {
257
+ case "marker":
258
+ return locale.value.hintMarker ?? "Click to place marker";
259
+ case "ping":
260
+ return locale.value.hintPing ?? "Click to send ping";
261
+ case "line":
262
+ return drawPoints.value.length >= 2 ? `${drawPoints.value.length} ${locale.value.points ?? "points"}` : locale.value.hintLine ?? "Click to start drawing a line";
263
+ case "measure":
264
+ return measurePoints.value.length >= 1 ? measurePoints.value.length >= 2 ? `${formatDist(measurePreviewTotal.value)}` : locale.value.hintMeasureAdd ?? "Click to add points" : locale.value.hintMeasure ?? "Click to start measuring";
265
+ default:
266
+ return null;
267
+ }
268
+ });
269
+ const modeHintIcon = computed(() => {
270
+ switch (activeMode.value) {
271
+ case "marker":
272
+ return "i-lucide-map-pin";
273
+ case "ping":
274
+ return "i-lucide-radio";
275
+ case "line":
276
+ return "i-lucide-route";
277
+ case "measure":
278
+ return "i-lucide-ruler";
279
+ default:
280
+ return "i-lucide-hand";
281
+ }
282
+ });
283
+ function toolBtn(mode) {
284
+ const active = activeMode.value === mode;
285
+ return {
286
+ color: active ? "primary" : "neutral",
287
+ variant: active ? "solid" : "ghost",
288
+ size: "sm"
289
+ };
290
+ }
291
+ function setMode(mode) {
292
+ if (!props.editable) return;
293
+ if (activeMode.value === mode) {
294
+ activeMode.value = "pan";
295
+ return;
296
+ }
297
+ activeMode.value = mode;
298
+ if (mode !== "line") {
299
+ drawPoints.value = [];
300
+ drawMouseLngLat.value = null;
301
+ updateDrawPreview();
302
+ }
303
+ if (mode !== "measure") {
304
+ measurePoints.value = [];
305
+ clearMeasurePreview();
306
+ }
307
+ selectedMarkerKey.value = null;
308
+ selectedLineKey.value = null;
309
+ selectedMeasureKey.value = null;
310
+ }
311
+ const remoteUsers = computed(
312
+ () => states.value.filter((s) => s.clientId !== localClientId.value).map((s) => ({
313
+ clientId: s.clientId,
314
+ name: s.user?.name ?? "User",
315
+ color: s.user?.color ?? "blue",
316
+ colorHex: s.user?.color || "#6366f1",
317
+ camera: s.mapCamera,
318
+ cursor: s.mapCursor,
319
+ mapPing: s.mapPing
320
+ }))
321
+ );
322
+ const allPingStates = computed(
323
+ () => states.value.map((s) => ({
324
+ clientId: s.clientId,
325
+ colorHex: s.user?.color || "#6366f1",
326
+ mapPing: s.mapPing
327
+ })).filter((s) => s.mapPing && Date.now() - s.mapPing.t < 3e3)
328
+ );
329
+ const followingUser = computed(
330
+ () => remoteUsers.value.find((u) => u.clientId === followingClientId.value) ?? null
331
+ );
332
+ const getLightPreset = () => isDark.value ? "night" : "day";
333
+ function broadcastCamera() {
334
+ if (!map || followingClientId.value !== null) return;
335
+ const c = map.getCenter();
336
+ setLocalState({
337
+ mapCamera: {
338
+ center: [c.lng, c.lat],
339
+ zoom: map.getZoom(),
340
+ pitch: map.getPitch(),
341
+ bearing: map.getBearing(),
342
+ t: Date.now()
343
+ }
344
+ });
345
+ }
346
+ function breakFollow() {
347
+ if (followEaseInProgress) return;
348
+ if (followingClientId.value !== null) followingClientId.value = null;
349
+ }
350
+ function followUser(clientId) {
351
+ if (clientId === localClientId.value) return;
352
+ followingClientId.value = clientId;
353
+ lastAppliedFollowTime = 0;
354
+ }
355
+ function emptyFC() {
356
+ return { type: "FeatureCollection", features: [] };
357
+ }
358
+ const presenceLerpMap = /* @__PURE__ */ new Map();
359
+ function createPresenceEl(name, colorHex) {
360
+ const el = document.createElement("div");
361
+ el.className = "presence-marker";
362
+ const initials = name.split(" ").map((w) => w[0] ?? "").join("").substring(0, 2).toUpperCase();
363
+ el.innerHTML = `<div class="presence-avatar" style="background:${colorHex}">${initials}</div><div class="presence-label">${name}</div>`;
364
+ return el;
365
+ }
366
+ function tickPresenceMarkers() {
367
+ if (!map || !mapReady.value || !mapboxgl) return;
368
+ const seen = /* @__PURE__ */ new Set();
369
+ for (const user of remoteUsers.value) {
370
+ if (!user.camera) continue;
371
+ seen.add(user.clientId);
372
+ const [tLng, tLat] = user.camera.center;
373
+ const p = presenceLerpMap.get(user.clientId);
374
+ if (p) {
375
+ p.tgtLng = tLng;
376
+ p.tgtLat = tLat;
377
+ p.curLng += (p.tgtLng - p.curLng) * CAMERA_LERP;
378
+ p.curLat += (p.tgtLat - p.curLat) * CAMERA_LERP;
379
+ p.marker.setLngLat([p.curLng, p.curLat]);
380
+ } else {
381
+ const m = new mapboxgl.Marker({
382
+ element: createPresenceEl(user.name, user.colorHex),
383
+ anchor: "bottom"
384
+ }).setLngLat([tLng, tLat]).addTo(map);
385
+ presenceLerpMap.set(user.clientId, {
386
+ marker: m,
387
+ curLng: tLng,
388
+ curLat: tLat,
389
+ tgtLng: tLng,
390
+ tgtLat: tLat
391
+ });
392
+ }
393
+ }
394
+ for (const [id, p] of presenceLerpMap) {
395
+ if (!seen.has(id)) {
396
+ p.marker.remove();
397
+ presenceLerpMap.delete(id);
398
+ }
399
+ }
400
+ }
401
+ const cursorLerpMap = /* @__PURE__ */ new Map();
402
+ function createCursorEl(name, colorHex) {
403
+ const el = document.createElement("div");
404
+ el.className = "map-cursor-el";
405
+ el.innerHTML = `
406
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" style="display:block">
407
+ <path d="M2 2L7 14L9 9L14 7L2 2Z" fill="${colorHex}" stroke="rgba(0,0,0,.25)" stroke-width="1" stroke-linejoin="round"/>
408
+ </svg>
409
+ <span class="map-cursor-name" style="background:${colorHex}">${name}</span>
410
+ `;
411
+ return el;
412
+ }
413
+ function tickCursors() {
414
+ if (!map || !mapContainer.value) return;
415
+ const seen = /* @__PURE__ */ new Set();
416
+ for (const user of remoteUsers.value) {
417
+ if (!user.cursor) continue;
418
+ seen.add(user.clientId);
419
+ const proj = map.project([user.cursor.lng, user.cursor.lat]);
420
+ const c = cursorLerpMap.get(user.clientId);
421
+ if (c) {
422
+ c.screenX += (proj.x - c.screenX) * CURSOR_LERP;
423
+ c.screenY += (proj.y - c.screenY) * CURSOR_LERP;
424
+ c.el.style.transform = `translate(${c.screenX}px,${c.screenY}px)`;
425
+ } else {
426
+ const el = createCursorEl(user.name, user.colorHex);
427
+ mapContainer.value.appendChild(el);
428
+ el.style.transform = `translate(${proj.x}px,${proj.y}px)`;
429
+ cursorLerpMap.set(user.clientId, {
430
+ el,
431
+ screenX: proj.x,
432
+ screenY: proj.y
433
+ });
434
+ }
435
+ }
436
+ for (const [id, c] of cursorLerpMap) {
437
+ if (!seen.has(id)) {
438
+ c.el.remove();
439
+ cursorLerpMap.delete(id);
440
+ }
441
+ }
442
+ }
443
+ let cursorBroadcastFrame = 0;
444
+ function onMapPointerMove(e) {
445
+ if (!map || !mapContainer.value) return;
446
+ cursorBroadcastFrame++;
447
+ if (cursorBroadcastFrame % 2 !== 0) return;
448
+ const rect = mapContainer.value.getBoundingClientRect();
449
+ const x = e.clientX - rect.left, y = e.clientY - rect.top;
450
+ try {
451
+ const { lng, lat } = map.unproject([x, y]);
452
+ setLocalState({ mapCursor: { lng, lat } });
453
+ if (activeMode.value === "line" && drawPoints.value.length > 0) {
454
+ drawMouseLngLat.value = [lng, lat];
455
+ updateDrawPreview();
456
+ }
457
+ } catch {
458
+ }
459
+ }
460
+ function onMapPointerLeave() {
461
+ setLocalState({ mapCursor: null });
462
+ drawMouseLngLat.value = null;
463
+ if (activeMode.value === "line") updateDrawPreview();
464
+ }
465
+ function getIconSVG(name) {
466
+ if (MARKER_ICON_SVG[name]) return MARKER_ICON_SVG[name];
467
+ return MARKER_ICON_SVG["map-pin"];
468
+ }
469
+ function buildPinHTML(data) {
470
+ const colorEntry = MARKER_COLORS.find((c) => c.hex === data.color);
471
+ const hex = data.color || "#3b82f6";
472
+ const border = colorEntry?.border ?? "#333";
473
+ const svg = getIconSVG(data.icon ?? "map-pin");
474
+ return { hex, border, svg };
475
+ }
476
+ function createMarkerEl(data, key) {
477
+ const { hex, border, svg } = buildPinHTML(data);
478
+ const container = document.createElement("div");
479
+ container.className = "collab-marker-container";
480
+ const pin = document.createElement("div");
481
+ pin.className = "collab-marker-pin";
482
+ pin.style.cssText = `background:${hex};box-shadow:0 2px 8px rgba(0,0,0,.4),0 0 0 2px ${border};`;
483
+ pin.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="13" height="13">${svg}</svg>`;
484
+ const labelEl = document.createElement("div");
485
+ labelEl.className = "collab-marker-label";
486
+ labelEl.textContent = data.label;
487
+ pin.addEventListener("click", (ev) => {
488
+ ev.stopPropagation();
489
+ openMarkerPopup(key);
490
+ });
491
+ if (props.editable) {
492
+ container.addEventListener("contextmenu", (ev) => {
493
+ ev.preventDefault();
494
+ ev.stopPropagation();
495
+ if (selectedMarkerKey.value === key) closeMarkerPopup();
496
+ tree.deleteEntry(key);
497
+ });
498
+ }
499
+ container.appendChild(pin);
500
+ container.appendChild(labelEl);
501
+ return container;
502
+ }
503
+ function updateMarkerEl(el, data) {
504
+ const pin = el.querySelector(".collab-marker-pin");
505
+ const label = el.querySelector(".collab-marker-label");
506
+ if (pin) {
507
+ const { hex, border, svg } = buildPinHTML(data);
508
+ pin.style.cssText = `background:${hex};box-shadow:0 2px 8px rgba(0,0,0,.4),0 0 0 2px ${border};`;
509
+ pin.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="13" height="13">${svg}</svg>`;
510
+ }
511
+ if (label) label.textContent = data.label;
512
+ }
513
+ function syncMarkers() {
514
+ if (!map || !mapReady.value || !mapboxgl) return;
515
+ const currentKeys = new Set(markers.value.map((e) => e.id));
516
+ for (const [key, m] of markerInstances) {
517
+ if (!currentKeys.has(key)) {
518
+ m.remove();
519
+ markerInstances.delete(key);
520
+ }
521
+ }
522
+ for (const entry of markers.value) {
523
+ const data = entryToMarkerData(entry);
524
+ if (markerInstances.has(entry.id)) {
525
+ updateMarkerEl(markerInstances.get(entry.id).getElement(), data);
526
+ } else {
527
+ const el = createMarkerEl(data, entry.id);
528
+ const m = new mapboxgl.Marker({ element: el, anchor: "bottom", draggable: props.editable }).setLngLat([data.lng, data.lat]).addTo(map);
529
+ if (props.editable) {
530
+ m.on("dragend", () => {
531
+ const lngLat = m.getLngLat();
532
+ tree.updateMeta(entry.id, { geoLng: lngLat.lng, geoLat: lngLat.lat });
533
+ });
534
+ }
535
+ markerInstances.set(entry.id, m);
536
+ }
537
+ const inst = markerInstances.get(entry.id);
538
+ const cur = inst.getLngLat();
539
+ if (cur.lng !== data.lng || cur.lat !== data.lat) {
540
+ inst.setLngLat([data.lng, data.lat]);
541
+ }
542
+ }
543
+ }
544
+ watch(markers, () => syncMarkers(), { deep: true });
545
+ watch(
546
+ () => tree.treeMap.yMap.value,
547
+ (ymap, oldYmap) => {
548
+ if (oldYmap) oldYmap.unobserve(onTreeYMapChange);
549
+ if (ymap) ymap.observe(onTreeYMapChange);
550
+ },
551
+ { immediate: true }
552
+ );
553
+ function onTreeYMapChange() {
554
+ syncMarkers();
555
+ syncLineSource();
556
+ syncLinePoints();
557
+ }
558
+ onBeforeUnmount(() => {
559
+ tree.treeMap.yMap.value?.unobserve(onTreeYMapChange);
560
+ });
561
+ function openMarkerPopup(key) {
562
+ const entry = markers.value.find((e) => e.id === key);
563
+ if (!entry) return;
564
+ selectedMarkerKey.value = key;
565
+ selectedLineKey.value = null;
566
+ selectedMeasureKey.value = null;
567
+ updateAllPopupPositions();
568
+ loadPopupProvider(key, entry.label);
569
+ }
570
+ function closeMarkerPopup() {
571
+ selectedMarkerKey.value = null;
572
+ }
573
+ function deleteSelectedMarker() {
574
+ if (!selectedMarkerKey.value || !props.editable) return;
575
+ tree.deleteEntry(selectedMarkerKey.value);
576
+ closeMarkerPopup();
577
+ }
578
+ function openLinePopup(key, geoPos) {
579
+ selectedLineKey.value = key;
580
+ linePopupGeoPos.value = geoPos;
581
+ selectedMarkerKey.value = null;
582
+ selectedMeasureKey.value = null;
583
+ updateAllPopupPositions();
584
+ const entry = lines.value.find((e) => e.id === key);
585
+ if (entry) loadPopupProvider(key, entry.label);
586
+ }
587
+ function deleteSelectedLine() {
588
+ if (!selectedLineKey.value || !props.editable) return;
589
+ tree.deleteEntry(selectedLineKey.value);
590
+ selectedLineKey.value = null;
591
+ }
592
+ function openMeasurePopup(key, geoPos) {
593
+ selectedMeasureKey.value = key;
594
+ measurePopupGeoPos.value = geoPos;
595
+ selectedMarkerKey.value = null;
596
+ selectedLineKey.value = null;
597
+ updateAllPopupPositions();
598
+ }
599
+ function deleteSelectedMeasure() {
600
+ if (!selectedMeasureKey.value || !props.editable) return;
601
+ tree.deleteEntry(selectedMeasureKey.value);
602
+ selectedMeasureKey.value = null;
603
+ }
604
+ function sendPing(lng, lat) {
605
+ setLocalState({ mapPing: { lng, lat, t: Date.now() } });
606
+ setTimeout(() => setLocalState({ mapPing: null }), 3500);
607
+ }
608
+ function createPingEl(colorHex) {
609
+ const root = document.createElement("div");
610
+ root.className = "map-ping-root";
611
+ root.style.setProperty("--ping-color", colorHex);
612
+ root.innerHTML = `
613
+ <div class="map-ping-ring" style="animation-delay:0s"></div>
614
+ <div class="map-ping-ring" style="animation-delay:0.5s"></div>
615
+ <div class="map-ping-ring" style="animation-delay:1s"></div>
616
+ <div class="map-ping-dot"></div>
617
+ `;
618
+ return root;
619
+ }
620
+ function tickPings() {
621
+ if (!map || !mapContainer.value) return;
622
+ const seenIds = /* @__PURE__ */ new Set();
623
+ for (const ps of allPingStates.value) {
624
+ if (!ps.mapPing) continue;
625
+ if (Date.now() - ps.mapPing.t >= 3e3) continue;
626
+ seenIds.add(ps.clientId);
627
+ const proj = map.project([ps.mapPing.lng, ps.mapPing.lat]);
628
+ let el = pingElements.get(ps.clientId);
629
+ if (!el) {
630
+ el = createPingEl(ps.colorHex);
631
+ mapContainer.value.appendChild(el);
632
+ pingElements.set(ps.clientId, el);
633
+ }
634
+ el.style.left = `${proj.x}px`;
635
+ el.style.top = `${proj.y}px`;
636
+ }
637
+ for (const [id, el] of pingElements) {
638
+ if (!seenIds.has(id)) {
639
+ el.remove();
640
+ pingElements.delete(id);
641
+ }
642
+ }
643
+ }
644
+ function updateDrawPreview() {
645
+ if (!map || !map.getSource("draw-preview")) return;
646
+ const pts = drawPoints.value;
647
+ const mouse = drawMouseLngLat.value;
648
+ const coords = mouse && pts.length > 0 ? [...pts, mouse] : [...pts];
649
+ map.getSource("draw-preview")?.setData({
650
+ type: "FeatureCollection",
651
+ features: coords.length >= 2 ? [
652
+ {
653
+ type: "Feature",
654
+ geometry: { type: "LineString", coordinates: coords },
655
+ properties: {}
656
+ }
657
+ ] : []
658
+ });
659
+ map.getSource("draw-points")?.setData({
660
+ type: "FeatureCollection",
661
+ features: pts.map((p) => ({
662
+ type: "Feature",
663
+ geometry: { type: "Point", coordinates: p },
664
+ properties: {}
665
+ }))
666
+ });
667
+ }
668
+ function finishLine() {
669
+ if (drawPoints.value.length < 2 || !props.editable) return;
670
+ const lineId = tree.createChild(null, "Line");
671
+ tree.updateMeta(lineId, { geoType: "line", color: myColorHex.value });
672
+ drawPoints.value.forEach((pt, i) => {
673
+ const ptId = tree.createChild(lineId, `Point ${i + 1}`);
674
+ tree.updateMeta(ptId, { geoType: "marker", geoLng: pt[0], geoLat: pt[1] });
675
+ });
676
+ drawPoints.value = [];
677
+ drawMouseLngLat.value = null;
678
+ activeMode.value = "pan";
679
+ updateDrawPreview();
680
+ }
681
+ function cancelDrawing() {
682
+ drawPoints.value = [];
683
+ drawMouseLngLat.value = null;
684
+ updateDrawPreview();
685
+ }
686
+ function syncLineSource() {
687
+ if (!map || !map.getSource("collab-lines")) return;
688
+ const features = lines.value.map((line) => {
689
+ const pts = tree.childrenOf(line.id).filter(
690
+ (p) => p.meta?.geoLat !== void 0 && p.meta?.geoLng !== void 0
691
+ );
692
+ const coords = pts.map(
693
+ (p) => [p.meta.geoLng, p.meta.geoLat]
694
+ );
695
+ return {
696
+ type: "Feature",
697
+ geometry: { type: "LineString", coordinates: coords },
698
+ properties: {
699
+ color: line.meta?.color ?? "#3b82f6",
700
+ label: line.label ?? "",
701
+ key: line.id
702
+ }
703
+ };
704
+ });
705
+ map.getSource("collab-lines")?.setData({
706
+ type: "FeatureCollection",
707
+ features
708
+ });
709
+ }
710
+ function createLinePointEl() {
711
+ const el = document.createElement("div");
712
+ el.className = "collab-line-point";
713
+ return el;
714
+ }
715
+ function syncLinePoints() {
716
+ if (!map || !mapboxgl) return;
717
+ const activePointKeys = /* @__PURE__ */ new Set();
718
+ for (const line of lines.value) {
719
+ const lineColor = line.meta?.color ?? "#3b82f6";
720
+ const pts = tree.childrenOf(line.id).filter(
721
+ (p) => p.meta?.geoLat !== void 0 && p.meta?.geoLng !== void 0
722
+ );
723
+ for (const pt of pts) {
724
+ activePointKeys.add(pt.id);
725
+ const lng = pt.meta.geoLng;
726
+ const lat = pt.meta.geoLat;
727
+ if (linePointInstances.has(pt.id)) {
728
+ const inst = linePointInstances.get(pt.id);
729
+ const cur = inst.getLngLat();
730
+ if (cur.lng !== lng || cur.lat !== lat) inst.setLngLat([lng, lat]);
731
+ const el = inst.getElement();
732
+ el.style.background = lineColor;
733
+ } else {
734
+ const el = createLinePointEl();
735
+ el.style.background = lineColor;
736
+ el.addEventListener("click", (ev) => {
737
+ ev.stopPropagation();
738
+ openNode(pt.id, pt.label);
739
+ });
740
+ const m = new mapboxgl.Marker({ element: el, anchor: "center", draggable: props.editable }).setLngLat([lng, lat]).addTo(map);
741
+ if (props.editable) {
742
+ m.on("dragend", () => {
743
+ const lngLat = m.getLngLat();
744
+ tree.updateMeta(pt.id, { geoLng: lngLat.lng, geoLat: lngLat.lat });
745
+ });
746
+ }
747
+ linePointInstances.set(pt.id, m);
748
+ }
749
+ }
750
+ }
751
+ for (const [key, m] of linePointInstances) {
752
+ if (!activePointKeys.has(key)) {
753
+ m.remove();
754
+ linePointInstances.delete(key);
755
+ }
756
+ }
757
+ }
758
+ watch(
759
+ tree.entries,
760
+ () => {
761
+ if (selectedLineKey.value && !lines.value.find((e) => e.id === selectedLineKey.value))
762
+ selectedLineKey.value = null;
763
+ syncMeasureSource();
764
+ if (selectedMeasureKey.value && !measures.value.find((e) => e.id === selectedMeasureKey.value))
765
+ selectedMeasureKey.value = null;
766
+ },
767
+ { deep: true }
768
+ );
769
+ function updateMeasurePreview() {
770
+ if (!map || !map.getSource("measure-preview-lines")) return;
771
+ const pts = measurePoints.value;
772
+ map.getSource("measure-preview-lines")?.setData({
773
+ type: "FeatureCollection",
774
+ features: pts.length >= 2 ? [
775
+ {
776
+ type: "Feature",
777
+ geometry: { type: "LineString", coordinates: pts },
778
+ properties: {}
779
+ }
780
+ ] : []
781
+ });
782
+ map.getSource("measure-preview-points")?.setData({
783
+ type: "FeatureCollection",
784
+ features: pts.map((p) => ({
785
+ type: "Feature",
786
+ geometry: { type: "Point", coordinates: p },
787
+ properties: {}
788
+ }))
789
+ });
790
+ if (pts.length >= 1 && map) {
791
+ const last = pts[pts.length - 1];
792
+ const proj = map.project(last);
793
+ measurePreviewScreenPos.value = { x: proj.x + 10, y: proj.y - 10 };
794
+ }
795
+ }
796
+ function clearMeasurePreview() {
797
+ if (!map) return;
798
+ map.getSource("measure-preview-lines")?.setData(emptyFC());
799
+ map.getSource("measure-preview-points")?.setData(emptyFC());
800
+ }
801
+ function finishMeasure() {
802
+ if (measurePoints.value.length < 2 || !props.editable) return;
803
+ const measureId = tree.createChild(null, "Measure");
804
+ tree.updateMeta(measureId, { geoType: "measure" });
805
+ measurePoints.value.forEach((pt, i) => {
806
+ const ptId = tree.createChild(measureId, `Point ${i + 1}`);
807
+ tree.updateMeta(ptId, { geoType: "marker", geoLng: pt[0], geoLat: pt[1] });
808
+ });
809
+ measurePoints.value = [];
810
+ clearMeasurePreview();
811
+ }
812
+ function syncMeasureSource() {
813
+ if (!map || !map.getSource("measure-collab-lines")) return;
814
+ const lineFeatures = measures.value.map((entry) => {
815
+ const pts = tree.childrenOf(entry.id).filter((p) => p.meta?.geoLat !== void 0);
816
+ const coords = pts.map(
817
+ (p) => [p.meta.geoLng, p.meta.geoLat]
818
+ );
819
+ return {
820
+ type: "Feature",
821
+ geometry: { type: "LineString", coordinates: coords },
822
+ properties: { key: entry.id }
823
+ };
824
+ });
825
+ map.getSource("measure-collab-lines")?.setData({
826
+ type: "FeatureCollection",
827
+ features: lineFeatures
828
+ });
829
+ const pointFeatures = measures.value.flatMap(
830
+ (entry) => tree.childrenOf(entry.id).filter((p) => p.meta?.geoLat !== void 0).map((p, i) => ({
831
+ type: "Feature",
832
+ id: `${entry.id}-${i}`,
833
+ geometry: {
834
+ type: "Point",
835
+ coordinates: [p.meta.geoLng, p.meta.geoLat]
836
+ },
837
+ properties: { measureId: entry.id }
838
+ }))
839
+ );
840
+ map.getSource("measure-collab-points")?.setData({
841
+ type: "FeatureCollection",
842
+ features: pointFeatures
843
+ });
844
+ }
845
+ function tickMeasureLabels() {
846
+ if (!map || !mapContainer.value || !mapReady.value) return;
847
+ const seen = /* @__PURE__ */ new Set();
848
+ for (const entry of measures.value) {
849
+ const pts = tree.childrenOf(entry.id).filter((p) => p.meta?.geoLat !== void 0);
850
+ if (pts.length < 2) continue;
851
+ seen.add(entry.id);
852
+ const midPt = pts[Math.floor((pts.length - 1) / 2)];
853
+ const proj = map.project([midPt.meta.geoLng, midPt.meta.geoLat]);
854
+ let dist = 0;
855
+ for (let i = 1; i < pts.length; i++) {
856
+ dist += haversine(
857
+ [pts[i - 1].meta.geoLng, pts[i - 1].meta.geoLat],
858
+ [pts[i].meta.geoLng, pts[i].meta.geoLat]
859
+ );
860
+ }
861
+ let el = measureLabelEls.get(entry.id);
862
+ if (!el) {
863
+ el = document.createElement("div");
864
+ el.className = "measure-label-el";
865
+ mapContainer.value.appendChild(el);
866
+ measureLabelEls.set(entry.id, el);
867
+ }
868
+ el.textContent = formatDist(dist);
869
+ el.style.left = `${proj.x}px`;
870
+ el.style.top = `${proj.y}px`;
871
+ }
872
+ for (const [id, el] of measureLabelEls) {
873
+ if (!seen.has(id)) {
874
+ el.remove();
875
+ measureLabelEls.delete(id);
876
+ }
877
+ }
878
+ }
879
+ function updateAllPopupPositions() {
880
+ if (!map) return;
881
+ if (selectedMarkerKey.value) {
882
+ const entry = markers.value.find((e) => e.id === selectedMarkerKey.value);
883
+ if (entry) {
884
+ const loc = getEntryLocation(entry);
885
+ const pt = map.project([loc?.lng ?? 0, loc?.lat ?? 0]);
886
+ markerPopupScreenPos.value = { x: pt.x + 16, y: pt.y - 80 };
887
+ }
888
+ }
889
+ if (linePopupGeoPos.value) {
890
+ const pt = map.project(linePopupGeoPos.value);
891
+ linePopupScreenPos.value = { x: pt.x + 8, y: pt.y - 50 };
892
+ }
893
+ if (measurePopupGeoPos.value) {
894
+ const pt = map.project(measurePopupGeoPos.value);
895
+ measurePopupScreenPos.value = { x: pt.x + 8, y: pt.y - 50 };
896
+ }
897
+ if (measurePoints.value.length >= 1) {
898
+ const last = measurePoints.value[measurePoints.value.length - 1];
899
+ const proj = map.project(last);
900
+ measurePreviewScreenPos.value = { x: proj.x + 10, y: proj.y - 10 };
901
+ }
902
+ }
903
+ function handleMapClick(e) {
904
+ if (followingClientId.value !== null) return;
905
+ const target = e.originalEvent.target;
906
+ if (target.closest(".collab-marker-pin") || target.closest(".collab-line-point")) return;
907
+ if (selectedMarkerKey.value) {
908
+ closeMarkerPopup();
909
+ return;
910
+ }
911
+ switch (activeMode.value) {
912
+ case "pan": {
913
+ const bbox = [
914
+ [e.point.x - 8, e.point.y - 8],
915
+ [e.point.x + 8, e.point.y + 8]
916
+ ];
917
+ const lineFeats = map.queryRenderedFeatures(bbox, {
918
+ layers: ["collab-lines-layer"]
919
+ });
920
+ if (lineFeats.length > 0) {
921
+ const id = lineFeats[0].properties?.key;
922
+ if (id && lines.value.find((e2) => e2.id === id)) {
923
+ openLinePopup(id, [e.lngLat.lng, e.lngLat.lat]);
924
+ return;
925
+ }
926
+ }
927
+ const measureFeats = map.queryRenderedFeatures(bbox, {
928
+ layers: ["measure-collab-lines-layer"]
929
+ });
930
+ if (measureFeats.length > 0) {
931
+ const id = measureFeats[0].properties?.key;
932
+ if (id && measures.value.find((e2) => e2.id === id)) {
933
+ openMeasurePopup(id, [e.lngLat.lng, e.lngLat.lat]);
934
+ return;
935
+ }
936
+ }
937
+ selectedLineKey.value = null;
938
+ selectedMeasureKey.value = null;
939
+ break;
940
+ }
941
+ case "marker":
942
+ if (!props.editable) break;
943
+ if (target.closest(".map-ping-root,.presence-marker,.map-cursor-el"))
944
+ return;
945
+ {
946
+ const id = tree.createChild(null, userName.value);
947
+ tree.updateMeta(id, {
948
+ geoType: "marker",
949
+ geoLat: e.lngLat.lat,
950
+ geoLng: e.lngLat.lng,
951
+ icon: "map-pin",
952
+ color: myColorHex.value
953
+ });
954
+ }
955
+ break;
956
+ case "ping":
957
+ sendPing(e.lngLat.lng, e.lngLat.lat);
958
+ activeMode.value = "pan";
959
+ break;
960
+ case "line":
961
+ if (!props.editable) break;
962
+ drawPoints.value.push([e.lngLat.lng, e.lngLat.lat]);
963
+ updateDrawPreview();
964
+ break;
965
+ case "measure": {
966
+ if (!props.editable) break;
967
+ if (measurePoints.value.length >= 2) {
968
+ const last = measurePoints.value[measurePoints.value.length - 1];
969
+ const proj = map.project(last);
970
+ const dx = e.point.x - proj.x, dy = e.point.y - proj.y;
971
+ if (Math.sqrt(dx * dx + dy * dy) < 15) {
972
+ finishMeasure();
973
+ break;
974
+ }
975
+ }
976
+ measurePoints.value.push([e.lngLat.lng, e.lngLat.lat]);
977
+ updateMeasurePreview();
978
+ break;
979
+ }
980
+ }
981
+ }
982
+ function handleMapDblClick(e) {
983
+ if (activeMode.value === "line" && drawPoints.value.length >= 2) {
984
+ e.preventDefault();
985
+ finishLine();
986
+ }
987
+ }
988
+ function handleMapContextMenu(e) {
989
+ if (!map || !props.editable) return;
990
+ e.originalEvent.preventDefault();
991
+ const bbox = [
992
+ [e.point.x - 8, e.point.y - 8],
993
+ [e.point.x + 8, e.point.y + 8]
994
+ ];
995
+ const lineFeats = map.queryRenderedFeatures(bbox, {
996
+ layers: ["collab-lines-layer"]
997
+ });
998
+ if (lineFeats.length > 0) {
999
+ const id = lineFeats[0].properties?.key;
1000
+ if (id) {
1001
+ tree.deleteEntry(id);
1002
+ if (selectedLineKey.value === id) selectedLineKey.value = null;
1003
+ }
1004
+ return;
1005
+ }
1006
+ const measureFeats = map.queryRenderedFeatures(bbox, {
1007
+ layers: ["measure-collab-lines-layer"]
1008
+ });
1009
+ if (measureFeats.length > 0) {
1010
+ const id = measureFeats[0].properties?.key;
1011
+ if (id) {
1012
+ tree.deleteEntry(id);
1013
+ if (selectedMeasureKey.value === id) selectedMeasureKey.value = null;
1014
+ }
1015
+ return;
1016
+ }
1017
+ }
1018
+ function onKeyDown(e) {
1019
+ if (e.key === "Escape") {
1020
+ if (activeMode.value === "line") cancelDrawing();
1021
+ if (activeMode.value === "measure") {
1022
+ measurePoints.value = [];
1023
+ clearMeasurePreview();
1024
+ }
1025
+ closeMarkerPopup();
1026
+ selectedLineKey.value = null;
1027
+ selectedMeasureKey.value = null;
1028
+ activeMode.value = "pan";
1029
+ }
1030
+ }
1031
+ function applyFollowCamera() {
1032
+ const user = followingUser.value;
1033
+ if (!user?.camera || !map) return;
1034
+ if (user.camera.t <= lastAppliedFollowTime) return;
1035
+ lastAppliedFollowTime = user.camera.t;
1036
+ followEaseInProgress = true;
1037
+ map.easeTo({
1038
+ center: user.camera.center,
1039
+ zoom: user.camera.zoom,
1040
+ pitch: user.camera.pitch,
1041
+ bearing: user.camera.bearing,
1042
+ duration: 200,
1043
+ easing: (t) => t
1044
+ });
1045
+ setTimeout(() => {
1046
+ followEaseInProgress = false;
1047
+ }, 250);
1048
+ }
1049
+ function startLoop() {
1050
+ const loop = () => {
1051
+ broadcastFrame++;
1052
+ if (followingClientId.value !== null) applyFollowCamera();
1053
+ if (mapReady.value) {
1054
+ tickCursors();
1055
+ tickPings();
1056
+ tickMeasureLabels();
1057
+ updateAllPopupPositions();
1058
+ }
1059
+ if (broadcastFrame % 2 === 0 && mapReady.value) tickPresenceMarkers();
1060
+ if (followingClientId.value === null && broadcastFrame % 4 === 0 && map)
1061
+ broadcastCamera();
1062
+ rafId = requestAnimationFrame(loop);
1063
+ };
1064
+ rafId = requestAnimationFrame(loop);
1065
+ }
1066
+ function applyLabels() {
1067
+ if (!map?.isStyleLoaded()) return;
1068
+ const v = showLabels.value;
1069
+ map.setConfigProperty("basemap", "showPlaceLabels", v);
1070
+ map.setConfigProperty("basemap", "showPointOfInterestLabels", v);
1071
+ map.setConfigProperty("basemap", "showRoadLabels", v);
1072
+ map.setConfigProperty("basemap", "showTransitLabels", v);
1073
+ }
1074
+ watch(showLabels, applyLabels);
1075
+ watch(activeMode, (mode) => {
1076
+ if (!map) return;
1077
+ if (mode === "line") map.doubleClickZoom.disable();
1078
+ else map.doubleClickZoom.enable();
1079
+ });
1080
+ onMounted(async () => {
1081
+ try {
1082
+ const mod = await import("mapbox-gl");
1083
+ mapboxgl = mod.default || mod;
1084
+ await import("mapbox-gl/dist/mapbox-gl.css");
1085
+ mapboxLoaded.value = true;
1086
+ } catch {
1087
+ mapboxError.value = "Map renderer requires mapbox-gl. Install it with: pnpm add mapbox-gl";
1088
+ return;
1089
+ }
1090
+ if (!mapContainer.value) return;
1091
+ window.addEventListener("keydown", onKeyDown);
1092
+ const token = config.public?.abracadabra?.mapboxToken;
1093
+ if (!token) {
1094
+ mapboxError.value = "Mapbox access token not configured. Set abracadabra.mapboxToken in runtimeConfig.public.";
1095
+ return;
1096
+ }
1097
+ mapboxgl.accessToken = token;
1098
+ map = new mapboxgl.Map({
1099
+ container: mapContainer.value,
1100
+ style: "mapbox://styles/mapbox/standard",
1101
+ projection: "globe",
1102
+ center: [0, 20],
1103
+ zoom: 2,
1104
+ pitch: 0,
1105
+ bearing: 0,
1106
+ antialias: true,
1107
+ attributionControl: false
1108
+ });
1109
+ map.on("style.load", () => {
1110
+ map.setConfigProperty("basemap", "lightPreset", getLightPreset());
1111
+ applyLabels();
1112
+ });
1113
+ map.on("load", () => {
1114
+ try {
1115
+ map.addSource("mapbox-dem", {
1116
+ type: "raster-dem",
1117
+ url: "mapbox://mapbox.mapbox-terrain-dem-v1",
1118
+ tileSize: 512,
1119
+ maxzoom: 14
1120
+ });
1121
+ map.setTerrain({ source: "mapbox-dem", exaggeration: 1 });
1122
+ } catch {
1123
+ }
1124
+ map.addControl(
1125
+ new mapboxgl.AttributionControl({ compact: true }),
1126
+ "bottom-right"
1127
+ );
1128
+ map.addSource("collab-lines", { type: "geojson", data: emptyFC() });
1129
+ map.addLayer({
1130
+ id: "collab-lines-layer",
1131
+ type: "line",
1132
+ source: "collab-lines",
1133
+ paint: {
1134
+ "line-color": ["get", "color"],
1135
+ "line-width": 4,
1136
+ "line-opacity": 0.85
1137
+ }
1138
+ });
1139
+ map.addSource("draw-preview", { type: "geojson", data: emptyFC() });
1140
+ map.addLayer({
1141
+ id: "draw-preview-layer",
1142
+ type: "line",
1143
+ source: "draw-preview",
1144
+ paint: {
1145
+ "line-color": myColorHex.value,
1146
+ "line-width": 2,
1147
+ "line-dasharray": [4, 3],
1148
+ "line-opacity": 0.7
1149
+ }
1150
+ });
1151
+ map.addSource("draw-points", { type: "geojson", data: emptyFC() });
1152
+ map.addLayer({
1153
+ id: "draw-points-layer",
1154
+ type: "circle",
1155
+ source: "draw-points",
1156
+ paint: {
1157
+ "circle-radius": 5,
1158
+ "circle-color": myColorHex.value,
1159
+ "circle-stroke-color": "white",
1160
+ "circle-stroke-width": 2
1161
+ }
1162
+ });
1163
+ map.addSource("measure-preview-lines", {
1164
+ type: "geojson",
1165
+ data: emptyFC()
1166
+ });
1167
+ map.addLayer({
1168
+ id: "measure-preview-lines-layer",
1169
+ type: "line",
1170
+ source: "measure-preview-lines",
1171
+ paint: {
1172
+ "line-color": "#facc15",
1173
+ "line-width": 2,
1174
+ "line-dasharray": [3, 2]
1175
+ }
1176
+ });
1177
+ map.addSource("measure-preview-points", {
1178
+ type: "geojson",
1179
+ data: emptyFC()
1180
+ });
1181
+ map.addLayer({
1182
+ id: "measure-preview-points-layer",
1183
+ type: "circle",
1184
+ source: "measure-preview-points",
1185
+ paint: {
1186
+ "circle-radius": 6,
1187
+ "circle-color": "#facc15",
1188
+ "circle-stroke-color": "white",
1189
+ "circle-stroke-width": 2
1190
+ }
1191
+ });
1192
+ map.addSource("measure-collab-lines", {
1193
+ type: "geojson",
1194
+ data: emptyFC()
1195
+ });
1196
+ map.addLayer({
1197
+ id: "measure-collab-lines-layer",
1198
+ type: "line",
1199
+ source: "measure-collab-lines",
1200
+ paint: {
1201
+ "line-color": "#facc15",
1202
+ "line-width": 3,
1203
+ "line-dasharray": [3, 2],
1204
+ "line-opacity": 0.85
1205
+ }
1206
+ });
1207
+ map.addSource("measure-collab-points", {
1208
+ type: "geojson",
1209
+ data: emptyFC()
1210
+ });
1211
+ map.addLayer({
1212
+ id: "measure-collab-points-layer",
1213
+ type: "circle",
1214
+ source: "measure-collab-points",
1215
+ paint: {
1216
+ "circle-radius": 4,
1217
+ "circle-color": "#facc15",
1218
+ "circle-stroke-color": "white",
1219
+ "circle-stroke-width": 1.5,
1220
+ "circle-opacity": 0.85
1221
+ }
1222
+ });
1223
+ mapReady.value = true;
1224
+ setTimeout(() => mapFadedIn.value = true, 100);
1225
+ map.on("moveend", () => {
1226
+ if (followingClientId.value === null) broadcastCamera();
1227
+ });
1228
+ for (const ev of ["dragstart", "zoomstart", "pitchstart", "rotatestart"]) {
1229
+ map.on(ev, breakFollow);
1230
+ }
1231
+ map.on("click", handleMapClick);
1232
+ map.on("dblclick", handleMapDblClick);
1233
+ map.on("contextmenu", handleMapContextMenu);
1234
+ syncMarkers();
1235
+ syncLineSource();
1236
+ syncLinePoints();
1237
+ syncMeasureSource();
1238
+ startLoop();
1239
+ broadcastCamera();
1240
+ });
1241
+ map.on("error", (e) => console.warn("Map error:", e));
1242
+ const ro = new ResizeObserver(() => map?.resize());
1243
+ ro.observe(mapContainer.value);
1244
+ mapResizeObserver = ro;
1245
+ });
1246
+ watch(isDark, () => {
1247
+ if (map?.isStyleLoaded())
1248
+ map.setConfigProperty("basemap", "lightPreset", getLightPreset());
1249
+ });
1250
+ onUnmounted(() => {
1251
+ mapResizeObserver?.disconnect();
1252
+ mapResizeObserver = null;
1253
+ window.removeEventListener("keydown", onKeyDown);
1254
+ cancelAnimationFrame(rafId);
1255
+ setLocalState({ mapCamera: void 0, mapCursor: null, mapPing: null });
1256
+ for (const m of markerInstances.values()) m.remove();
1257
+ for (const m of linePointInstances.values()) m.remove();
1258
+ for (const p of presenceLerpMap.values()) p.marker.remove();
1259
+ for (const c of cursorLerpMap.values()) c.el.remove();
1260
+ for (const e of pingElements.values()) e.remove();
1261
+ for (const e of measureLabelEls.values()) e.remove();
1262
+ markerInstances.clear();
1263
+ linePointInstances.clear();
1264
+ presenceLerpMap.clear();
1265
+ cursorLerpMap.clear();
1266
+ pingElements.clear();
1267
+ measureLabelEls.clear();
1268
+ map?.remove();
1269
+ map = null;
1270
+ });
1271
+ function userInitials(name) {
1272
+ return name.split(" ").map((w) => w[0] ?? "").join("").substring(0, 2).toUpperCase();
1273
+ }
1274
+ defineExpose({ connectedUsers });
1275
+ </script>
1276
+
1277
+ <template>
1278
+ <div class="a-map-renderer-root">
1279
+ <!-- Mapbox not installed fallback -->
1280
+ <div
1281
+ v-if="mapboxError"
1282
+ class="flex flex-col items-center justify-center flex-1 gap-3"
1283
+ >
1284
+ <UIcon
1285
+ name="i-lucide-map"
1286
+ class="size-12 text-(--ui-text-dimmed)"
1287
+ />
1288
+ <p class="text-sm text-(--ui-text-muted) text-center max-w-xs">
1289
+ {{ mapboxError }}
1290
+ </p>
1291
+ </div>
1292
+
1293
+ <template v-else>
1294
+ <!-- Map canvas -->
1295
+ <div
1296
+ ref="mapContainer"
1297
+ class="absolute inset-0 transition-opacity duration-1000"
1298
+ :class="[mapFadedIn ? 'opacity-100' : 'opacity-0', mapCursorClass]"
1299
+ @pointermove="onMapPointerMove"
1300
+ @pointerleave="onMapPointerLeave"
1301
+ />
1302
+
1303
+ <!-- Toolbar (bottom-center) -->
1304
+ <div
1305
+ v-if="editable"
1306
+ class="a-map-toolbar-bar"
1307
+ >
1308
+ <div class="toolbar-group">
1309
+ <UButton
1310
+ icon="i-lucide-hand"
1311
+ v-bind="toolBtn('pan')"
1312
+ :title="locale.pan"
1313
+ @click="setMode('pan')"
1314
+ />
1315
+ <UButton
1316
+ icon="i-lucide-map-pin"
1317
+ v-bind="toolBtn('marker')"
1318
+ :title="locale.addMarker"
1319
+ @click="setMode('marker')"
1320
+ />
1321
+ <UButton
1322
+ icon="i-lucide-radio"
1323
+ v-bind="toolBtn('ping')"
1324
+ :title="locale.ping"
1325
+ @click="setMode('ping')"
1326
+ />
1327
+ <UButton
1328
+ icon="i-lucide-route"
1329
+ v-bind="toolBtn('line')"
1330
+ :title="locale.addLine"
1331
+ @click="setMode('line')"
1332
+ />
1333
+ <UButton
1334
+ icon="i-lucide-ruler"
1335
+ v-bind="toolBtn('measure')"
1336
+ :title="locale.addMeasure"
1337
+ @click="setMode('measure')"
1338
+ />
1339
+ </div>
1340
+ <div class="toolbar-divider" />
1341
+ <UButton
1342
+ icon="i-lucide-type"
1343
+ size="sm"
1344
+ :color="showLabels ? 'primary' : 'neutral'"
1345
+ :variant="showLabels ? 'soft' : 'ghost'"
1346
+ :title="showLabels ? locale.hideLabels : locale.showLabels"
1347
+ :class="{ 'opacity-40': !showLabels }"
1348
+ @click="showLabels = !showLabels"
1349
+ />
1350
+ </div>
1351
+
1352
+ <!-- Follow badge -->
1353
+ <Transition name="badge-fade">
1354
+ <div
1355
+ v-if="followingUser"
1356
+ class="follow-badge"
1357
+ >
1358
+ <UIcon
1359
+ name="i-lucide-eye"
1360
+ class="badge-icon"
1361
+ />
1362
+ <span>{{ locale.following }} {{ followingUser.name }}</span>
1363
+ <button
1364
+ class="badge-close"
1365
+ @click="followingClientId = null"
1366
+ >
1367
+ <UIcon name="i-lucide-x" />
1368
+ </button>
1369
+ </div>
1370
+ </Transition>
1371
+
1372
+ <!-- Mode hint bar -->
1373
+ <Transition name="badge-fade">
1374
+ <div
1375
+ v-if="modeHint"
1376
+ class="place-hint"
1377
+ >
1378
+ <UIcon :name="modeHintIcon" />
1379
+ <span>{{ modeHint }}</span>
1380
+ <template v-if="activeMode === 'line' && drawPoints.length >= 2">
1381
+ <span class="ml-1 opacity-50">&middot;</span>
1382
+ <button
1383
+ class="underline opacity-80 ml-1 pointer-events-auto"
1384
+ @click="finishLine"
1385
+ >
1386
+ {{ locale.finish }}
1387
+ </button>
1388
+ </template>
1389
+ <template v-if="activeMode === 'measure' && measurePoints.length >= 2">
1390
+ <span class="ml-1 opacity-50">&middot;</span>
1391
+ <button
1392
+ class="underline opacity-80 ml-1 pointer-events-auto"
1393
+ @click="finishMeasure"
1394
+ >
1395
+ {{ locale.save }}
1396
+ </button>
1397
+ </template>
1398
+ </div>
1399
+ </Transition>
1400
+
1401
+ <!-- In-progress measure distance badge -->
1402
+ <Transition name="badge-fade">
1403
+ <div
1404
+ v-if="activeMode === 'measure' && measurePoints.length >= 2"
1405
+ class="measure-preview-badge"
1406
+ :style="{
1407
+ left: measurePreviewScreenPos.x + 'px',
1408
+ top: measurePreviewScreenPos.y + 'px'
1409
+ }"
1410
+ >
1411
+ {{ formatDist(measurePreviewTotal) }}
1412
+ </div>
1413
+ </Transition>
1414
+
1415
+ <!-- Marker popup overlay -->
1416
+ <Transition name="popup-fade">
1417
+ <div
1418
+ v-if="selectedMarker"
1419
+ class="map-popup-overlay map-popup-editor"
1420
+ :style="{
1421
+ left: markerPopupScreenPos.x + 'px',
1422
+ top: markerPopupScreenPos.y + 'px'
1423
+ }"
1424
+ >
1425
+ <div class="popup-row popup-header">
1426
+ <UIcon
1427
+ :name="`i-lucide-${selectedMarker.meta?.icon ?? 'map-pin'}`"
1428
+ class="popup-icon"
1429
+ />
1430
+ <span class="popup-label">{{ selectedMarker.label }}</span>
1431
+ <UButton
1432
+ icon="i-lucide-external-link"
1433
+ size="xs"
1434
+ color="neutral"
1435
+ variant="ghost"
1436
+ :title="locale.openInPanel"
1437
+ @click="openNode(selectedMarkerKey, selectedMarker.label);
1438
+ closeMarkerPopup()"
1439
+ />
1440
+ <UButton
1441
+ v-if="editable"
1442
+ icon="i-lucide-trash-2"
1443
+ size="xs"
1444
+ color="error"
1445
+ variant="ghost"
1446
+ @click="deleteSelectedMarker"
1447
+ />
1448
+ <UButton
1449
+ icon="i-lucide-x"
1450
+ size="xs"
1451
+ color="neutral"
1452
+ variant="ghost"
1453
+ @click="closeMarkerPopup"
1454
+ />
1455
+ </div>
1456
+ <div class="popup-editor-body">
1457
+ <div
1458
+ v-if="!popupProvider"
1459
+ class="popup-editor-loading"
1460
+ >
1461
+ <UIcon
1462
+ name="i-lucide-loader-circle"
1463
+ class="size-4 animate-spin text-(--ui-text-dimmed)"
1464
+ />
1465
+ </div>
1466
+ <AEditor
1467
+ v-else
1468
+ :doc-id="selectedMarkerKey"
1469
+ :child-provider="popupProvider"
1470
+ :doc-label="selectedMarker.label"
1471
+ />
1472
+ </div>
1473
+ </div>
1474
+ </Transition>
1475
+
1476
+ <!-- Line selection popup -->
1477
+ <Transition name="popup-fade">
1478
+ <div
1479
+ v-if="selectedLine"
1480
+ class="map-popup-overlay map-popup-editor"
1481
+ :style="{
1482
+ left: linePopupScreenPos.x + 'px',
1483
+ top: linePopupScreenPos.y + 'px'
1484
+ }"
1485
+ >
1486
+ <div class="popup-row popup-header">
1487
+ <UIcon
1488
+ name="i-lucide-route"
1489
+ class="popup-icon"
1490
+ />
1491
+ <span class="popup-label">{{ selectedLine.label }}</span>
1492
+ <UButton
1493
+ icon="i-lucide-external-link"
1494
+ size="xs"
1495
+ color="neutral"
1496
+ variant="ghost"
1497
+ :title="locale.openInPanel"
1498
+ @click="openNode(selectedLineKey, selectedLine.label);
1499
+ selectedLineKey = null"
1500
+ />
1501
+ <UButton
1502
+ v-if="editable"
1503
+ icon="i-lucide-trash-2"
1504
+ size="xs"
1505
+ color="error"
1506
+ variant="ghost"
1507
+ @click="deleteSelectedLine"
1508
+ />
1509
+ <UButton
1510
+ icon="i-lucide-x"
1511
+ size="xs"
1512
+ color="neutral"
1513
+ variant="ghost"
1514
+ @click="selectedLineKey = null"
1515
+ />
1516
+ </div>
1517
+ <div class="popup-editor-body">
1518
+ <div
1519
+ v-if="!popupProvider"
1520
+ class="popup-editor-loading"
1521
+ >
1522
+ <UIcon
1523
+ name="i-lucide-loader-circle"
1524
+ class="size-4 animate-spin text-(--ui-text-dimmed)"
1525
+ />
1526
+ </div>
1527
+ <AEditor
1528
+ v-else
1529
+ :doc-id="selectedLineKey"
1530
+ :child-provider="popupProvider"
1531
+ :doc-label="selectedLine.label"
1532
+ />
1533
+ </div>
1534
+ </div>
1535
+ </Transition>
1536
+
1537
+ <!-- Measure selection popup -->
1538
+ <Transition name="popup-fade">
1539
+ <div
1540
+ v-if="selectedMeasureInfo"
1541
+ class="map-popup-overlay"
1542
+ :style="{
1543
+ left: measurePopupScreenPos.x + 'px',
1544
+ top: measurePopupScreenPos.y + 'px'
1545
+ }"
1546
+ >
1547
+ <div class="popup-row">
1548
+ <UIcon
1549
+ name="i-lucide-ruler"
1550
+ class="popup-icon"
1551
+ />
1552
+ <span class="popup-dist">{{
1553
+ formatDist(selectedMeasureInfo.dist)
1554
+ }}</span>
1555
+ <UButton
1556
+ icon="i-lucide-x"
1557
+ size="xs"
1558
+ color="neutral"
1559
+ variant="ghost"
1560
+ @click="selectedMeasureKey = null"
1561
+ />
1562
+ </div>
1563
+ <div class="popup-row popup-meta">
1564
+ <UButton
1565
+ v-if="editable"
1566
+ icon="i-lucide-trash-2"
1567
+ size="xs"
1568
+ color="error"
1569
+ variant="ghost"
1570
+ @click="deleteSelectedMeasure"
1571
+ />
1572
+ </div>
1573
+ </div>
1574
+ </Transition>
1575
+
1576
+ <!-- Presence HUD -->
1577
+ <div
1578
+ v-if="remoteUsers.length > 0"
1579
+ class="presence-hud"
1580
+ >
1581
+ <div
1582
+ v-for="user in remoteUsers"
1583
+ :key="user.clientId"
1584
+ class="presence-pill"
1585
+ :class="{ 'is-following': followingClientId === user.clientId }"
1586
+ :title="
1587
+ followingClientId === user.clientId ? `${locale.unfollow} ${user.name}` : `${locale.follow} ${user.name}`
1588
+ "
1589
+ @click="
1590
+ followingClientId === user.clientId ? followingClientId = null : followUser(user.clientId)
1591
+ "
1592
+ >
1593
+ <div
1594
+ class="hud-avatar"
1595
+ :style="{ background: user.colorHex }"
1596
+ >
1597
+ {{ userInitials(user.name) }}
1598
+ </div>
1599
+ <span class="hud-name">{{ user.name }}</span>
1600
+ <UIcon
1601
+ v-if="followingClientId === user.clientId"
1602
+ name="i-lucide-eye"
1603
+ class="hud-follow-icon"
1604
+ />
1605
+ </div>
1606
+ </div>
1607
+ </template>
1608
+
1609
+ <ANodePanel
1610
+ :node-id="openNodeId"
1611
+ :node-label="openNodeLabel"
1612
+ :child-provider="openNodeProvider"
1613
+ @close="closePanel"
1614
+ />
1615
+ </div>
1616
+ </template>
1617
+
1618
+ <style scoped>
1619
+ .a-map-renderer-root{display:flex;flex:1;flex-direction:column;height:100%;min-height:0;overflow:hidden;position:relative}.a-map-toolbar-bar{align-items:center;backdrop-filter:blur(8px);background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:10px;bottom:2rem;display:flex;gap:3px;left:50%;padding:3px;position:absolute;transform:translateX(-50%);z-index:20}.toolbar-group{align-items:center;display:flex;gap:1px}.toolbar-divider{background:var(--ui-border);flex-shrink:0;height:20px;margin:0 2px;width:1px}.follow-badge{align-items:center;backdrop-filter:blur(8px);background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:999px;color:var(--ui-text);display:flex;font-family:ui-monospace,SF Mono,monospace;font-size:.72rem;gap:.375rem;left:50%;padding:.3rem .5rem .3rem .75rem;position:absolute;top:1rem;transform:translateX(-50%);white-space:nowrap;z-index:20}.badge-icon{color:var(--ui-primary);font-size:.8rem}.badge-close{align-items:center;background:var(--ui-bg-elevated);border:none;border-radius:50%;color:var(--ui-text-dimmed);cursor:pointer;display:flex;font-size:.65rem;height:1.2rem;justify-content:center;margin-left:.2rem;transition:background .15s;width:1.2rem}.badge-close:hover{background:var(--ui-bg-accented);color:var(--ui-text)}.place-hint{align-items:center;backdrop-filter:blur(8px);background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:999px;bottom:5.5rem;color:var(--ui-text);display:flex;font-family:ui-monospace,SF Mono,monospace;font-size:.7rem;gap:.375rem;left:50%;padding:.3rem .75rem;pointer-events:none;position:absolute;transform:translateX(-50%);white-space:nowrap;z-index:20}.place-hint button{pointer-events:auto}.measure-preview-badge{background:rgba(250,204,21,.9);border-radius:4px;color:#000;font-size:.65rem;font-weight:700;padding:2px 6px;pointer-events:none;position:absolute;white-space:nowrap;z-index:35}.map-popup-overlay{background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:7px;box-shadow:0 4px 20px rgba(0,0,0,.45);display:flex;flex-direction:column;gap:4px;max-width:240px;min-width:180px;padding:5px;pointer-events:auto;position:absolute;z-index:40}.popup-row{align-items:center;display:flex;gap:4px}.popup-meta{justify-content:space-between;padding:0 2px}.popup-meta>span{color:var(--ui-text-muted);font-size:.65rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.popup-icon{color:var(--ui-text-muted);flex-shrink:0;font-size:.8rem}.popup-dist{flex:1;font-size:.8rem;font-weight:700}.popup-label{color:var(--ui-text);flex:1;font-size:.75rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.map-popup-editor{display:flex;flex-direction:column;max-height:400px;max-width:480px;min-width:400px}.popup-header{border-bottom:1px solid var(--ui-border);flex-shrink:0;padding-bottom:4px}.popup-editor-body{flex:1;max-height:340px;min-height:0;overflow-y:auto}.popup-editor-body :deep(.tiptap){font-size:.8rem;min-height:60px;padding:4px 8px}.popup-editor-body :deep(h1.document-header){font-size:.9rem;padding-top:4px}.popup-editor-body :deep([data-type=document-meta]){font-size:.75rem;padding:0 8px}.popup-editor-loading{align-items:center;display:flex;justify-content:center;padding:20px}.presence-hud{display:flex;flex-direction:column;gap:.375rem;position:absolute;right:.75rem;top:.75rem;z-index:20}.presence-pill{align-items:center;backdrop-filter:blur(8px);background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:999px;cursor:pointer;display:flex;gap:.5rem;padding:.25rem .6rem .25rem .25rem;transition:background .15s,border-color .15s}.presence-pill:hover{background:var(--ui-bg-elevated)}.presence-pill.is-following{background:var(--ui-bg-accented);border-color:var(--ui-primary)}.hud-avatar{align-items:center;border:1.5px solid var(--ui-border);border-radius:50%;color:#fff;display:flex;flex-shrink:0;font-size:.6rem;font-weight:700;height:1.5rem;justify-content:center;width:1.5rem}.hud-name{color:var(--ui-text);font-family:ui-monospace,SF Mono,monospace;font-size:.72rem;white-space:nowrap}.hud-follow-icon{color:var(--ui-primary);flex-shrink:0;font-size:.7rem}.badge-fade-enter-active,.badge-fade-leave-active{transition:opacity .25s ease}.badge-fade-enter-from,.badge-fade-leave-to{opacity:0}.popup-fade-enter-active,.popup-fade-leave-active{transition:opacity .15s ease,transform .15s ease}.popup-fade-enter-from,.popup-fade-leave-to{opacity:0;transform:scale(.95) translateY(4px)}
1620
+ </style>
1621
+
1622
+ <style>
1623
+ .mapboxgl-map{height:100%!important;width:100%!important}.collab-marker-container{align-items:center;cursor:pointer;display:flex;flex-direction:column}.collab-marker-pin{align-items:center;border-radius:50%;display:flex;height:28px;justify-content:center;transition:transform .2s ease;width:28px;z-index:30}.collab-marker-pin:hover{transform:scale(1.15)}.collab-marker-label{background:rgba(0,0,0,.5);border-radius:3px;color:#fff;font-size:11px;font-weight:700;margin-top:3px;padding:1px 5px;pointer-events:none;text-shadow:0 1px 4px rgba(0,0,0,.7);white-space:nowrap}.collab-line-point{border:2px solid #fff;border-radius:50%;box-shadow:0 1px 4px rgba(0,0,0,.4);cursor:grab;height:10px;width:10px}.collab-line-point:hover{height:14px;width:14px}.presence-marker{align-items:center;display:flex;flex-direction:column;gap:2px;pointer-events:none}.presence-avatar{align-items:center;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 8px rgba(0,0,0,.4);color:#fff;display:flex;font-size:.65rem;font-weight:700;height:1.75rem;justify-content:center;width:1.75rem}.presence-label{color:#fff;font-size:.6rem;font-weight:700;text-shadow:0 1px 4px rgba(0,0,0,.8);white-space:nowrap}.map-cursor-el{left:0;pointer-events:none;position:absolute;top:0;will-change:transform;z-index:50}.map-cursor-name{font-size:.6rem;font-weight:600;left:14px;top:8px}.map-cursor-name,.measure-label-el{border-radius:3px;color:#000;padding:1px 5px;position:absolute;white-space:nowrap}.measure-label-el{background:rgba(250,204,21,.92);box-shadow:0 1px 4px rgba(0,0,0,.3);font-size:.62rem;font-weight:700;left:0;pointer-events:none;top:0;transform:translate(-50%,calc(-100% - 5px));z-index:35}@keyframes ping-ring{0%{opacity:1;transform:scale(0)}to{opacity:0;transform:scale(3)}}.map-ping-root{height:12px;left:0;pointer-events:none;position:absolute;top:0;transform:translate(-50%,-50%);width:12px;z-index:45}.map-ping-ring{animation:ping-ring 1.5s ease-out forwards;border:3px solid var(--ping-color);border-radius:50%;inset:-16px;position:absolute}.map-ping-dot{background:var(--ping-color);border:2px solid #fff;border-radius:50%;height:12px;left:0;position:absolute;top:0;width:12px}
1624
+ </style>