@abraca/nuxt 1.9.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (434) hide show
  1. package/dist/module.d.mts +4 -3
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +9 -1
  4. package/dist/runtime/components/ADocumentTree.vue +1 -1
  5. package/dist/runtime/components/AEditor.d.vue.ts +26 -1
  6. package/dist/runtime/components/AEditor.vue +153 -4
  7. package/dist/runtime/components/AEditor.vue.d.ts +26 -1
  8. package/dist/runtime/components/AIdentityModal.d.vue.ts +46 -0
  9. package/dist/runtime/components/AIdentityModal.vue +157 -0
  10. package/dist/runtime/components/AIdentityModal.vue.d.ts +46 -0
  11. package/dist/runtime/components/AMnemonicLoginModal.d.vue.ts +35 -0
  12. package/dist/runtime/components/AMnemonicLoginModal.vue +173 -0
  13. package/dist/runtime/components/AMnemonicLoginModal.vue.d.ts +35 -0
  14. package/dist/runtime/components/ANodePanel.d.vue.ts +29 -2
  15. package/dist/runtime/components/ANodePanel.vue +148 -27
  16. package/dist/runtime/components/ANodePanel.vue.d.ts +29 -2
  17. package/dist/runtime/components/ANodePanelHeader.d.vue.ts +64 -0
  18. package/dist/runtime/components/ANodePanelHeader.vue +105 -0
  19. package/dist/runtime/components/ANodePanelHeader.vue.d.ts +64 -0
  20. package/dist/runtime/components/ANodeSettingsPanel.d.vue.ts +49 -0
  21. package/dist/runtime/components/ANodeSettingsPanel.vue +59 -0
  22. package/dist/runtime/components/ANodeSettingsPanel.vue.d.ts +49 -0
  23. package/dist/runtime/components/ANotificationBell.d.vue.ts +26 -0
  24. package/dist/runtime/components/ANotificationBell.vue +55 -0
  25. package/dist/runtime/components/ANotificationBell.vue.d.ts +26 -0
  26. package/dist/runtime/components/AOfflineSync.d.vue.ts +11 -0
  27. package/dist/runtime/components/AOfflineSync.vue +217 -0
  28. package/dist/runtime/components/AOfflineSync.vue.d.ts +11 -0
  29. package/dist/runtime/components/ARecoveryPhraseDisplay.d.vue.ts +26 -0
  30. package/dist/runtime/components/ARecoveryPhraseDisplay.vue +94 -0
  31. package/dist/runtime/components/ARecoveryPhraseDisplay.vue.d.ts +26 -0
  32. package/dist/runtime/components/AServerInfoModal.d.vue.ts +43 -0
  33. package/dist/runtime/components/AServerInfoModal.vue +150 -0
  34. package/dist/runtime/components/AServerInfoModal.vue.d.ts +43 -0
  35. package/dist/runtime/components/ASpaceFormModal.vue +1 -1
  36. package/dist/runtime/components/aware/AAccordion.d.vue.ts +25 -0
  37. package/dist/runtime/components/aware/AAccordion.vue +107 -0
  38. package/dist/runtime/components/aware/AAccordion.vue.d.ts +25 -0
  39. package/dist/runtime/components/aware/AArea.vue +24 -11
  40. package/dist/runtime/components/aware/AAvatar.d.vue.ts +6 -0
  41. package/dist/runtime/components/aware/AAvatar.vue +33 -3
  42. package/dist/runtime/components/aware/AAvatar.vue.d.ts +6 -0
  43. package/dist/runtime/components/aware/AAvatarGroup.d.vue.ts +10 -0
  44. package/dist/runtime/components/aware/AAvatarGroup.vue +30 -0
  45. package/dist/runtime/components/aware/AAvatarGroup.vue.d.ts +10 -0
  46. package/dist/runtime/components/aware/AButton.d.vue.ts +4 -2
  47. package/dist/runtime/components/aware/AButton.vue +46 -14
  48. package/dist/runtime/components/aware/AButton.vue.d.ts +4 -2
  49. package/dist/runtime/components/aware/ACalendar.d.vue.ts +17 -0
  50. package/dist/runtime/components/aware/ACalendar.vue +145 -0
  51. package/dist/runtime/components/aware/ACalendar.vue.d.ts +17 -0
  52. package/dist/runtime/components/aware/ACarousel.d.vue.ts +25 -0
  53. package/dist/runtime/components/aware/ACarousel.vue +39 -0
  54. package/dist/runtime/components/aware/ACarousel.vue.d.ts +25 -0
  55. package/dist/runtime/components/aware/ACheckbox.d.vue.ts +11 -0
  56. package/dist/runtime/components/aware/ACheckbox.vue +74 -0
  57. package/dist/runtime/components/aware/ACheckbox.vue.d.ts +11 -0
  58. package/dist/runtime/components/aware/ACheckboxGroup.d.vue.ts +27 -0
  59. package/dist/runtime/components/aware/ACheckboxGroup.vue +79 -0
  60. package/dist/runtime/components/aware/ACheckboxGroup.vue.d.ts +27 -0
  61. package/dist/runtime/components/aware/ACollapsible.d.vue.ts +25 -0
  62. package/dist/runtime/components/aware/ACollapsible.vue +45 -0
  63. package/dist/runtime/components/aware/ACollapsible.vue.d.ts +25 -0
  64. package/dist/runtime/components/aware/AColorPicker.d.vue.ts +15 -0
  65. package/dist/runtime/components/aware/AColorPicker.vue +48 -0
  66. package/dist/runtime/components/aware/AColorPicker.vue.d.ts +15 -0
  67. package/dist/runtime/components/aware/ACommandPalette.d.vue.ts +33 -0
  68. package/dist/runtime/components/aware/ACommandPalette.vue +123 -0
  69. package/dist/runtime/components/aware/ACommandPalette.vue.d.ts +33 -0
  70. package/dist/runtime/components/aware/AContextMenu.d.vue.ts +25 -0
  71. package/dist/runtime/components/aware/AContextMenu.vue +63 -0
  72. package/dist/runtime/components/aware/AContextMenu.vue.d.ts +25 -0
  73. package/dist/runtime/components/aware/ADrawer.d.vue.ts +25 -0
  74. package/dist/runtime/components/aware/ADrawer.vue +57 -0
  75. package/dist/runtime/components/aware/ADrawer.vue.d.ts +25 -0
  76. package/dist/runtime/components/aware/ADropdownMenu.d.vue.ts +25 -0
  77. package/dist/runtime/components/aware/ADropdownMenu.vue +63 -0
  78. package/dist/runtime/components/aware/ADropdownMenu.vue.d.ts +25 -0
  79. package/dist/runtime/components/aware/AFileUpload.d.vue.ts +27 -0
  80. package/dist/runtime/components/aware/AFileUpload.vue +67 -0
  81. package/dist/runtime/components/aware/AFileUpload.vue.d.ts +27 -0
  82. package/dist/runtime/components/aware/AFollowBar.d.vue.ts +21 -0
  83. package/dist/runtime/components/aware/AFollowBar.vue +62 -0
  84. package/dist/runtime/components/aware/AFollowBar.vue.d.ts +21 -0
  85. package/dist/runtime/components/aware/AFollowScroll.d.vue.ts +7 -0
  86. package/dist/runtime/components/aware/AFollowScroll.vue +17 -0
  87. package/dist/runtime/components/aware/AFollowScroll.vue.d.ts +7 -0
  88. package/dist/runtime/components/aware/AFormSync.d.vue.ts +21 -0
  89. package/dist/runtime/components/aware/AFormSync.vue +52 -0
  90. package/dist/runtime/components/aware/AFormSync.vue.d.ts +21 -0
  91. package/dist/runtime/components/aware/AGlobalFocusLayer.d.vue.ts +3 -0
  92. package/dist/runtime/components/aware/AGlobalFocusLayer.vue +90 -0
  93. package/dist/runtime/components/aware/AGlobalFocusLayer.vue.d.ts +3 -0
  94. package/dist/runtime/components/aware/AHoverItem.d.vue.ts +27 -0
  95. package/dist/runtime/components/aware/AHoverItem.vue +124 -0
  96. package/dist/runtime/components/aware/AHoverItem.vue.d.ts +27 -0
  97. package/dist/runtime/components/aware/AInput.d.vue.ts +12 -2
  98. package/dist/runtime/components/aware/AInput.vue +72 -19
  99. package/dist/runtime/components/aware/AInput.vue.d.ts +12 -2
  100. package/dist/runtime/components/aware/AInputMenu.d.vue.ts +17 -0
  101. package/dist/runtime/components/aware/AInputMenu.vue +138 -0
  102. package/dist/runtime/components/aware/AInputMenu.vue.d.ts +17 -0
  103. package/dist/runtime/components/aware/AInputNumber.d.vue.ts +15 -0
  104. package/dist/runtime/components/aware/AInputNumber.vue +67 -0
  105. package/dist/runtime/components/aware/AInputNumber.vue.d.ts +15 -0
  106. package/dist/runtime/components/aware/AInputTags.d.vue.ts +15 -0
  107. package/dist/runtime/components/aware/AInputTags.vue +67 -0
  108. package/dist/runtime/components/aware/AInputTags.vue.d.ts +15 -0
  109. package/dist/runtime/components/aware/AKeyHint.d.vue.ts +3 -0
  110. package/dist/runtime/components/aware/AKeyHint.vue +23 -0
  111. package/dist/runtime/components/aware/AKeyHint.vue.d.ts +3 -0
  112. package/dist/runtime/components/aware/AMedia.d.vue.ts +19 -0
  113. package/dist/runtime/components/aware/AMedia.vue +85 -0
  114. package/dist/runtime/components/aware/AMedia.vue.d.ts +19 -0
  115. package/dist/runtime/components/aware/AModal.d.vue.ts +33 -0
  116. package/dist/runtime/components/aware/AModal.vue +110 -0
  117. package/dist/runtime/components/aware/AModal.vue.d.ts +33 -0
  118. package/dist/runtime/components/aware/ANavigationMenu.d.vue.ts +25 -0
  119. package/dist/runtime/components/aware/ANavigationMenu.vue +82 -0
  120. package/dist/runtime/components/aware/ANavigationMenu.vue.d.ts +25 -0
  121. package/dist/runtime/components/aware/APagination.d.vue.ts +13 -0
  122. package/dist/runtime/components/aware/APagination.vue +53 -0
  123. package/dist/runtime/components/aware/APagination.vue.d.ts +13 -0
  124. package/dist/runtime/components/aware/APeerCaretLayer.d.vue.ts +10 -0
  125. package/dist/runtime/components/aware/APeerCaretLayer.vue +133 -0
  126. package/dist/runtime/components/aware/APeerCaretLayer.vue.d.ts +10 -0
  127. package/dist/runtime/components/aware/APinInput.d.vue.ts +15 -0
  128. package/dist/runtime/components/aware/APinInput.vue +48 -0
  129. package/dist/runtime/components/aware/APinInput.vue.d.ts +15 -0
  130. package/dist/runtime/components/aware/APopover.d.vue.ts +25 -0
  131. package/dist/runtime/components/aware/APopover.vue +57 -0
  132. package/dist/runtime/components/aware/APopover.vue.d.ts +25 -0
  133. package/dist/runtime/components/aware/APresenceBlobs.d.vue.ts +3 -0
  134. package/dist/runtime/components/aware/APresenceBlobs.vue +69 -0
  135. package/dist/runtime/components/aware/APresenceBlobs.vue.d.ts +3 -0
  136. package/dist/runtime/components/aware/APresenceCursors.d.vue.ts +20 -0
  137. package/dist/runtime/components/aware/APresenceCursors.vue +47 -0
  138. package/dist/runtime/components/aware/APresenceCursors.vue.d.ts +20 -0
  139. package/dist/runtime/components/aware/ARadioGroup.d.vue.ts +27 -0
  140. package/dist/runtime/components/aware/ARadioGroup.vue +86 -0
  141. package/dist/runtime/components/aware/ARadioGroup.vue.d.ts +27 -0
  142. package/dist/runtime/components/aware/AScroll.d.vue.ts +25 -0
  143. package/dist/runtime/components/aware/AScroll.vue +87 -0
  144. package/dist/runtime/components/aware/AScroll.vue.d.ts +25 -0
  145. package/dist/runtime/components/aware/ASelect.d.vue.ts +12 -2
  146. package/dist/runtime/components/aware/ASelect.vue +146 -22
  147. package/dist/runtime/components/aware/ASelect.vue.d.ts +12 -2
  148. package/dist/runtime/components/aware/ASelectMenu.d.vue.ts +17 -0
  149. package/dist/runtime/components/aware/ASelectMenu.vue +139 -0
  150. package/dist/runtime/components/aware/ASelectMenu.vue.d.ts +17 -0
  151. package/dist/runtime/components/aware/ASlideover.d.vue.ts +33 -0
  152. package/dist/runtime/components/aware/ASlideover.vue +110 -0
  153. package/dist/runtime/components/aware/ASlideover.vue.d.ts +33 -0
  154. package/dist/runtime/components/aware/ASlider.d.vue.ts +19 -0
  155. package/dist/runtime/components/aware/ASlider.vue +77 -0
  156. package/dist/runtime/components/aware/ASlider.vue.d.ts +19 -0
  157. package/dist/runtime/components/aware/AStepper.d.vue.ts +25 -0
  158. package/dist/runtime/components/aware/AStepper.vue +82 -0
  159. package/dist/runtime/components/aware/AStepper.vue.d.ts +25 -0
  160. package/dist/runtime/components/aware/ASwitch.d.vue.ts +11 -0
  161. package/dist/runtime/components/aware/ASwitch.vue +75 -0
  162. package/dist/runtime/components/aware/ASwitch.vue.d.ts +11 -0
  163. package/dist/runtime/components/aware/ATable.d.vue.ts +23 -0
  164. package/dist/runtime/components/aware/ATable.vue +97 -0
  165. package/dist/runtime/components/aware/ATable.vue.d.ts +23 -0
  166. package/dist/runtime/components/aware/ATabs.d.vue.ts +27 -0
  167. package/dist/runtime/components/aware/ATabs.vue +128 -0
  168. package/dist/runtime/components/aware/ATabs.vue.d.ts +27 -0
  169. package/dist/runtime/components/aware/ATextarea.d.vue.ts +12 -2
  170. package/dist/runtime/components/aware/ATextarea.vue +72 -19
  171. package/dist/runtime/components/aware/ATextarea.vue.d.ts +12 -2
  172. package/dist/runtime/components/aware/AToggleGroup.d.vue.ts +27 -0
  173. package/dist/runtime/components/aware/AToggleGroup.vue +79 -0
  174. package/dist/runtime/components/aware/AToggleGroup.vue.d.ts +27 -0
  175. package/dist/runtime/components/aware/ATree.d.vue.ts +27 -0
  176. package/dist/runtime/components/aware/ATree.vue +111 -0
  177. package/dist/runtime/components/aware/ATree.vue.d.ts +27 -0
  178. package/dist/runtime/components/chat/AChatPanel.d.vue.ts +6 -6
  179. package/dist/runtime/components/chat/AChatPanel.vue.d.ts +6 -6
  180. package/dist/runtime/components/chat/ANodeChatPanel.d.vue.ts +42 -0
  181. package/dist/runtime/components/chat/ANodeChatPanel.vue +53 -0
  182. package/dist/runtime/components/chat/ANodeChatPanel.vue.d.ts +42 -0
  183. package/dist/runtime/components/docs/ADocsSearch.d.vue.ts +2 -2
  184. package/dist/runtime/components/docs/ADocsSearch.vue.d.ts +2 -2
  185. package/dist/runtime/components/docs/ADocsSearchButton.d.vue.ts +3 -3
  186. package/dist/runtime/components/docs/ADocsSearchButton.vue.d.ts +3 -3
  187. package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +26 -0
  188. package/dist/runtime/components/editor/AEditorRedoButton.vue +38 -0
  189. package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +26 -0
  190. package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +26 -0
  191. package/dist/runtime/components/editor/AEditorUndoButton.vue +38 -0
  192. package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +26 -0
  193. package/dist/runtime/components/editor/AIconPickerPopover.d.vue.ts +24 -0
  194. package/dist/runtime/components/editor/AIconPickerPopover.vue +113 -0
  195. package/dist/runtime/components/editor/AIconPickerPopover.vue.d.ts +24 -0
  196. package/dist/runtime/components/editor/ANodeInlineLabel.d.vue.ts +24 -0
  197. package/dist/runtime/components/editor/ANodeInlineLabel.vue +101 -0
  198. package/dist/runtime/components/editor/ANodeInlineLabel.vue.d.ts +24 -0
  199. package/dist/runtime/components/renderers/ADocLoadError.d.vue.ts +3 -0
  200. package/dist/runtime/components/renderers/ADocLoadError.vue +11 -0
  201. package/dist/runtime/components/renderers/ADocLoadError.vue.d.ts +3 -0
  202. package/dist/runtime/components/renderers/ADocLoadingSkeleton.d.vue.ts +3 -0
  203. package/dist/runtime/components/renderers/ADocLoadingSkeleton.vue +5 -0
  204. package/dist/runtime/components/renderers/ADocLoadingSkeleton.vue.d.ts +3 -0
  205. package/dist/runtime/components/renderers/AOverviewRenderer.d.vue.ts +22 -0
  206. package/dist/runtime/components/renderers/AOverviewRenderer.vue +1041 -0
  207. package/dist/runtime/components/renderers/AOverviewRenderer.vue.d.ts +22 -0
  208. package/dist/runtime/components/renderers/AProseRenderer.d.vue.ts +23 -0
  209. package/dist/runtime/components/renderers/AProseRenderer.vue +31 -0
  210. package/dist/runtime/components/renderers/AProseRenderer.vue.d.ts +23 -0
  211. package/dist/runtime/components/renderers/ASheetsRenderer.client.d.vue.ts +19 -0
  212. package/dist/runtime/components/renderers/ASheetsRenderer.client.vue +865 -0
  213. package/dist/runtime/components/renderers/ASheetsRenderer.client.vue.d.ts +19 -0
  214. package/dist/runtime/components/renderers/calendar/ACalendarDayCell.d.vue.ts +14 -0
  215. package/dist/runtime/components/renderers/calendar/ACalendarDayCell.vue +45 -15
  216. package/dist/runtime/components/renderers/calendar/ACalendarDayCell.vue.d.ts +14 -0
  217. package/dist/runtime/components/renderers/calendar/ACalendarDayView.d.vue.ts +15 -0
  218. package/dist/runtime/components/renderers/calendar/ACalendarDayView.vue +93 -20
  219. package/dist/runtime/components/renderers/calendar/ACalendarDayView.vue.d.ts +15 -0
  220. package/dist/runtime/components/renderers/calendar/ACalendarEventChip.d.vue.ts +9 -0
  221. package/dist/runtime/components/renderers/calendar/ACalendarEventChip.vue +31 -2
  222. package/dist/runtime/components/renderers/calendar/ACalendarEventChip.vue.d.ts +9 -0
  223. package/dist/runtime/components/renderers/calendar/ACalendarToolbar.d.vue.ts +4 -4
  224. package/dist/runtime/components/renderers/calendar/ACalendarToolbar.vue.d.ts +4 -4
  225. package/dist/runtime/components/renderers/calendar/ACalendarWeekView.d.vue.ts +15 -0
  226. package/dist/runtime/components/renderers/calendar/ACalendarWeekView.vue +94 -21
  227. package/dist/runtime/components/renderers/calendar/ACalendarWeekView.vue.d.ts +15 -0
  228. package/dist/runtime/components/renderers/media/MediaTransportBar.d.vue.ts +2 -2
  229. package/dist/runtime/components/renderers/media/MediaTransportBar.vue.d.ts +2 -2
  230. package/dist/runtime/components/renderers/sheets/ASheetsCell.d.vue.ts +45 -0
  231. package/dist/runtime/components/renderers/sheets/ASheetsCell.vue +123 -0
  232. package/dist/runtime/components/renderers/sheets/ASheetsCell.vue.d.ts +45 -0
  233. package/dist/runtime/components/renderers/sheets/ASheetsGrid.d.vue.ts +111 -0
  234. package/dist/runtime/components/renderers/sheets/ASheetsGrid.vue +737 -0
  235. package/dist/runtime/components/renderers/sheets/ASheetsGrid.vue.d.ts +111 -0
  236. package/dist/runtime/components/renderers/sheets/ASheetsMobileActionBar.d.vue.ts +26 -0
  237. package/dist/runtime/components/renderers/sheets/ASheetsMobileActionBar.vue +100 -0
  238. package/dist/runtime/components/renderers/sheets/ASheetsMobileActionBar.vue.d.ts +26 -0
  239. package/dist/runtime/components/renderers/sheets/ASheetsToolbar.d.vue.ts +48 -0
  240. package/dist/runtime/components/renderers/sheets/ASheetsToolbar.vue +243 -0
  241. package/dist/runtime/components/renderers/sheets/ASheetsToolbar.vue.d.ts +48 -0
  242. package/dist/runtime/components/renderers/table/cells/ATableCellColor.d.vue.ts +1 -0
  243. package/dist/runtime/components/renderers/table/cells/ATableCellColor.vue +13 -32
  244. package/dist/runtime/components/renderers/table/cells/ATableCellColor.vue.d.ts +1 -0
  245. package/dist/runtime/components/renderers/timeline/ATimelineBar.d.vue.ts +6 -0
  246. package/dist/runtime/components/renderers/timeline/ATimelineBar.vue +34 -4
  247. package/dist/runtime/components/renderers/timeline/ATimelineBar.vue.d.ts +6 -0
  248. package/dist/runtime/components/renderers/timeline/ATimelineBarArea.d.vue.ts +16 -0
  249. package/dist/runtime/components/renderers/timeline/ATimelineBarArea.vue +14 -3
  250. package/dist/runtime/components/renderers/timeline/ATimelineBarArea.vue.d.ts +16 -0
  251. package/dist/runtime/components/renderers/timeline/ATimelineLabelPanel.d.vue.ts +13 -1
  252. package/dist/runtime/components/renderers/timeline/ATimelineLabelPanel.vue +114 -47
  253. package/dist/runtime/components/renderers/timeline/ATimelineLabelPanel.vue.d.ts +13 -1
  254. package/dist/runtime/components/renderers/timeline/ATimelineMilestone.d.vue.ts +4 -0
  255. package/dist/runtime/components/renderers/timeline/ATimelineMilestone.vue +21 -4
  256. package/dist/runtime/components/renderers/timeline/ATimelineMilestone.vue.d.ts +4 -0
  257. package/dist/runtime/components/renderers/timeline/ATimelineToolbar.d.vue.ts +2 -2
  258. package/dist/runtime/components/renderers/timeline/ATimelineToolbar.vue.d.ts +2 -2
  259. package/dist/runtime/components/settings/ASettingsSpacesPanel.vue +7 -25
  260. package/dist/runtime/components/shell/ADocPanelSettings.d.vue.ts +3 -3
  261. package/dist/runtime/components/shell/ADocPanelSettings.vue.d.ts +3 -3
  262. package/dist/runtime/components/shell/ASyncStatus.d.vue.ts +1 -1
  263. package/dist/runtime/components/shell/ASyncStatus.vue.d.ts +1 -1
  264. package/dist/runtime/components/shell/AUserMenu.d.vue.ts +2 -2
  265. package/dist/runtime/components/shell/AUserMenu.vue.d.ts +2 -2
  266. package/dist/runtime/components/shell/AWelcomeScreen.d.vue.ts +1 -1
  267. package/dist/runtime/components/shell/AWelcomeScreen.vue.d.ts +1 -1
  268. package/dist/runtime/composables/useAACaret.d.ts +29 -0
  269. package/dist/runtime/composables/useAACaret.js +64 -0
  270. package/dist/runtime/composables/useAAEphemeral.d.ts +32 -0
  271. package/dist/runtime/composables/useAAEphemeral.js +33 -0
  272. package/dist/runtime/composables/useAAField.d.ts +10 -2
  273. package/dist/runtime/composables/useAAField.js +31 -2
  274. package/dist/runtime/composables/useAAFieldValue.d.ts +26 -0
  275. package/dist/runtime/composables/useAAFieldValue.js +32 -0
  276. package/dist/runtime/composables/useAAFocus.d.ts +68 -0
  277. package/dist/runtime/composables/useAAFocus.js +174 -0
  278. package/dist/runtime/composables/useAAFollowAnchor.d.ts +25 -0
  279. package/dist/runtime/composables/useAAFollowAnchor.js +69 -0
  280. package/dist/runtime/composables/useAAFollowPeer.d.ts +29 -0
  281. package/dist/runtime/composables/useAAFollowPeer.js +75 -0
  282. package/dist/runtime/composables/useAAKey.d.ts +22 -0
  283. package/dist/runtime/composables/useAAKey.js +24 -0
  284. package/dist/runtime/composables/useAAPointer.d.ts +30 -0
  285. package/dist/runtime/composables/useAAPointer.js +53 -0
  286. package/dist/runtime/composables/useAAUIState.d.ts +29 -0
  287. package/dist/runtime/composables/useAAUIState.js +28 -0
  288. package/dist/runtime/composables/useAAViewport.d.ts +22 -0
  289. package/dist/runtime/composables/useAAViewport.js +50 -0
  290. package/dist/runtime/composables/useAbraAdmin.d.ts +54 -0
  291. package/dist/runtime/composables/useAbraAdmin.js +115 -0
  292. package/dist/runtime/composables/useAbracadabraAuth.d.ts +8 -0
  293. package/dist/runtime/composables/useAbracadabraAuth.js +8 -0
  294. package/dist/runtime/composables/useAggregatedPresence.d.ts +23 -0
  295. package/dist/runtime/composables/useAggregatedPresence.js +140 -0
  296. package/dist/runtime/composables/useChat.d.ts +16 -2
  297. package/dist/runtime/composables/useChat.js +257 -66
  298. package/dist/runtime/composables/useChatUsers.d.ts +2 -0
  299. package/dist/runtime/composables/useChatUsers.js +2 -1
  300. package/dist/runtime/composables/useDocLookup.d.ts +4 -0
  301. package/dist/runtime/composables/useDocLookup.js +25 -0
  302. package/dist/runtime/composables/useDocSnapshots.d.ts +79 -0
  303. package/dist/runtime/composables/useDocSnapshots.js +234 -0
  304. package/dist/runtime/composables/useEditorDragHandle.d.ts +7 -0
  305. package/dist/runtime/composables/useEditorDragHandle.js +19 -1
  306. package/dist/runtime/composables/useEditorSuggestions.js +26 -1
  307. package/dist/runtime/composables/useEditorToolbar.js +9 -1
  308. package/dist/runtime/composables/useEmailVerification.d.ts +33 -0
  309. package/dist/runtime/composables/useEmailVerification.js +58 -0
  310. package/dist/runtime/composables/useIdentityDoc.js +0 -3
  311. package/dist/runtime/composables/useItemPresence.d.ts +47 -0
  312. package/dist/runtime/composables/useItemPresence.js +73 -0
  313. package/dist/runtime/composables/useResizableWidth.d.ts +24 -0
  314. package/dist/runtime/composables/useResizableWidth.js +87 -0
  315. package/dist/runtime/composables/useServerInfo.d.ts +17 -2
  316. package/dist/runtime/composables/useServerInfo.js +30 -6
  317. package/dist/runtime/composables/useServerSearch.d.ts +36 -0
  318. package/dist/runtime/composables/useServerSearch.js +91 -0
  319. package/dist/runtime/composables/useServerTrash.d.ts +67 -0
  320. package/dist/runtime/composables/useServerTrash.js +128 -0
  321. package/dist/runtime/composables/useSheetsClipboard.d.ts +42 -0
  322. package/dist/runtime/composables/useSheetsClipboard.js +109 -0
  323. package/dist/runtime/composables/useSheetsFormulas.d.ts +38 -0
  324. package/dist/runtime/composables/useSheetsFormulas.js +725 -0
  325. package/dist/runtime/composables/useSheetsSelection.d.ts +68 -0
  326. package/dist/runtime/composables/useSheetsSelection.js +390 -0
  327. package/dist/runtime/composables/useSheetsView.d.ts +31 -0
  328. package/dist/runtime/composables/useSheetsView.js +77 -0
  329. package/dist/runtime/composables/useSpaceConnections.d.ts +43 -0
  330. package/dist/runtime/composables/useSpaceConnections.js +72 -0
  331. package/dist/runtime/composables/useSpaces.d.ts +1 -3
  332. package/dist/runtime/composables/useSpaces.js +2 -5
  333. package/dist/runtime/composables/useTiptapHistory.d.ts +22 -0
  334. package/dist/runtime/composables/useTiptapHistory.js +12 -0
  335. package/dist/runtime/composables/useTreeExpansion.d.ts +28 -0
  336. package/dist/runtime/composables/useTreeExpansion.js +94 -0
  337. package/dist/runtime/composables/useYDoc.js +12 -1
  338. package/dist/runtime/extensions/button.d.ts +3 -0
  339. package/dist/runtime/extensions/button.js +62 -0
  340. package/dist/runtime/extensions/color-swatch.d.ts +2 -0
  341. package/dist/runtime/extensions/color-swatch.js +34 -0
  342. package/dist/runtime/extensions/diff.d.ts +2 -0
  343. package/dist/runtime/extensions/diff.js +40 -0
  344. package/dist/runtime/extensions/divider.d.ts +2 -0
  345. package/dist/runtime/extensions/divider.js +33 -0
  346. package/dist/runtime/extensions/embed.d.ts +2 -0
  347. package/dist/runtime/extensions/embed.js +40 -0
  348. package/dist/runtime/extensions/figure.d.ts +2 -0
  349. package/dist/runtime/extensions/figure.js +49 -0
  350. package/dist/runtime/extensions/math.d.ts +15 -0
  351. package/dist/runtime/extensions/math.js +66 -0
  352. package/dist/runtime/extensions/progress.d.ts +2 -0
  353. package/dist/runtime/extensions/progress.js +43 -0
  354. package/dist/runtime/extensions/quote.d.ts +2 -0
  355. package/dist/runtime/extensions/quote.js +39 -0
  356. package/dist/runtime/extensions/spoiler.d.ts +2 -0
  357. package/dist/runtime/extensions/spoiler.js +36 -0
  358. package/dist/runtime/extensions/stat.d.ts +3 -0
  359. package/dist/runtime/extensions/stat.js +58 -0
  360. package/dist/runtime/extensions/video.d.ts +2 -0
  361. package/dist/runtime/extensions/video.js +40 -0
  362. package/dist/runtime/extensions/views/ButtonGroupView.d.vue.ts +4 -0
  363. package/dist/runtime/extensions/views/ButtonGroupView.vue +25 -0
  364. package/dist/runtime/extensions/views/ButtonGroupView.vue.d.ts +4 -0
  365. package/dist/runtime/extensions/views/ButtonView.d.vue.ts +4 -0
  366. package/dist/runtime/extensions/views/ButtonView.vue +171 -0
  367. package/dist/runtime/extensions/views/ButtonView.vue.d.ts +4 -0
  368. package/dist/runtime/extensions/views/ColorSwatchView.d.vue.ts +4 -0
  369. package/dist/runtime/extensions/views/ColorSwatchView.vue +134 -0
  370. package/dist/runtime/extensions/views/ColorSwatchView.vue.d.ts +4 -0
  371. package/dist/runtime/extensions/views/DiffView.d.vue.ts +4 -0
  372. package/dist/runtime/extensions/views/DiffView.vue +163 -0
  373. package/dist/runtime/extensions/views/DiffView.vue.d.ts +4 -0
  374. package/dist/runtime/extensions/views/DividerView.d.vue.ts +4 -0
  375. package/dist/runtime/extensions/views/DividerView.vue +40 -0
  376. package/dist/runtime/extensions/views/DividerView.vue.d.ts +4 -0
  377. package/dist/runtime/extensions/views/EmbedView.d.vue.ts +4 -0
  378. package/dist/runtime/extensions/views/EmbedView.vue +166 -0
  379. package/dist/runtime/extensions/views/EmbedView.vue.d.ts +4 -0
  380. package/dist/runtime/extensions/views/FigureView.d.vue.ts +4 -0
  381. package/dist/runtime/extensions/views/FigureView.vue +122 -0
  382. package/dist/runtime/extensions/views/FigureView.vue.d.ts +4 -0
  383. package/dist/runtime/extensions/views/FileNodeView.vue +21 -24
  384. package/dist/runtime/extensions/views/MathBlockView.d.vue.ts +4 -0
  385. package/dist/runtime/extensions/views/MathBlockView.vue +151 -0
  386. package/dist/runtime/extensions/views/MathBlockView.vue.d.ts +4 -0
  387. package/dist/runtime/extensions/views/MathInlineView.d.vue.ts +4 -0
  388. package/dist/runtime/extensions/views/MathInlineView.vue +149 -0
  389. package/dist/runtime/extensions/views/MathInlineView.vue.d.ts +4 -0
  390. package/dist/runtime/extensions/views/MetaFieldView.vue +1129 -550
  391. package/dist/runtime/extensions/views/ProgressView.d.vue.ts +4 -0
  392. package/dist/runtime/extensions/views/ProgressView.vue +156 -0
  393. package/dist/runtime/extensions/views/ProgressView.vue.d.ts +4 -0
  394. package/dist/runtime/extensions/views/QuoteView.d.vue.ts +4 -0
  395. package/dist/runtime/extensions/views/QuoteView.vue +128 -0
  396. package/dist/runtime/extensions/views/QuoteView.vue.d.ts +4 -0
  397. package/dist/runtime/extensions/views/SpoilerView.d.vue.ts +4 -0
  398. package/dist/runtime/extensions/views/SpoilerView.vue +62 -0
  399. package/dist/runtime/extensions/views/SpoilerView.vue.d.ts +4 -0
  400. package/dist/runtime/extensions/views/StatGroupView.d.vue.ts +4 -0
  401. package/dist/runtime/extensions/views/StatGroupView.vue +25 -0
  402. package/dist/runtime/extensions/views/StatGroupView.vue.d.ts +4 -0
  403. package/dist/runtime/extensions/views/StatView.d.vue.ts +4 -0
  404. package/dist/runtime/extensions/views/StatView.vue +89 -0
  405. package/dist/runtime/extensions/views/StatView.vue.d.ts +4 -0
  406. package/dist/runtime/extensions/views/VideoView.d.vue.ts +4 -0
  407. package/dist/runtime/extensions/views/VideoView.vue +190 -0
  408. package/dist/runtime/extensions/views/VideoView.vue.d.ts +4 -0
  409. package/dist/runtime/locale.d.ts +133 -0
  410. package/dist/runtime/locale.js +121 -2
  411. package/dist/runtime/plugin-abracadabra.client.js +233 -36
  412. package/dist/runtime/plugin-abracadabra.server.js +0 -1
  413. package/dist/runtime/plugins/core.plugin.js +73 -4
  414. package/dist/runtime/server/plugins/abracadabra-service.js +1 -1
  415. package/dist/runtime/server/utils/rpcHandler.d.ts +74 -0
  416. package/dist/runtime/server/utils/rpcHandler.js +74 -0
  417. package/dist/runtime/server/utils/spaceManager.js +10 -9
  418. package/dist/runtime/types.d.ts +63 -10
  419. package/dist/runtime/utils/awareRingStyle.d.ts +22 -0
  420. package/dist/runtime/utils/awareRingStyle.js +16 -0
  421. package/dist/runtime/utils/caretCoordinates.d.ts +41 -0
  422. package/dist/runtime/utils/caretCoordinates.js +126 -0
  423. package/dist/runtime/utils/content.d.ts +1 -1
  424. package/dist/runtime/utils/docTypes.js +44 -13
  425. package/dist/runtime/utils/domPath.d.ts +42 -0
  426. package/dist/runtime/utils/domPath.js +89 -0
  427. package/dist/runtime/utils/loadKatex.d.ts +1 -0
  428. package/dist/runtime/utils/loadKatex.js +29 -0
  429. package/dist/runtime/utils/lucideIcons.d.ts +16 -0
  430. package/dist/runtime/utils/lucideIcons.js +451 -0
  431. package/dist/runtime/utils/time.d.ts +15 -0
  432. package/dist/runtime/utils/time.js +5 -0
  433. package/dist/types.d.mts +4 -0
  434. package/package.json +27 -16
@@ -0,0 +1,1041 @@
1
+ <script setup>
2
+ import { ref, computed, onBeforeUnmount } from "vue";
3
+ import { useRouter, useRuntimeConfig, useAppConfig } from "#imports";
4
+ import { useVirtualizer } from "@tanstack/vue-virtual";
5
+ import { DEFAULT_LOCALE } from "../../locale";
6
+ import { useAbracadabra } from "../../composables/useAbracadabra";
7
+ import { useRendererBase } from "../../composables/useRendererBase";
8
+ import { useNodePanel } from "../../composables/useNodePanel";
9
+ import { useNodePanelFollow } from "../../composables/useNodePanelFollow";
10
+ import { useDocDropZone } from "../../composables/useDocDropZone";
11
+ import { useDocDragBus } from "../../composables/useDocDragBus";
12
+ import { useTouchDrag } from "../../composables/useTouchDrag";
13
+ import { useItemPresence, useViewingBroadcast } from "../../composables/useItemPresence";
14
+ import { useTreeExpansion } from "../../composables/useTreeExpansion";
15
+ import { useChatUsers } from "../../composables/useChatUsers";
16
+ import { useFavorites } from "../../composables/useFavorites";
17
+ import { useVoice } from "../../composables/useVoice";
18
+ import { useCommandPalette } from "../../composables/useCommandPalette";
19
+ import { useDocumentPermissions } from "../../composables/useDocumentPermissions";
20
+ import { resolveDocType, getAvailableDocTypes } from "../../utils/docTypes";
21
+ import { avatarBorderStyle } from "../../utils/avatarStyle";
22
+ import { DOC_DRAG_MIME, isDescendantInMap } from "../../utils/docDragDrop";
23
+ const props = defineProps({
24
+ docId: { type: String, required: true },
25
+ childProvider: { type: null, required: true },
26
+ docLabel: { type: String, required: true },
27
+ pageTypes: { type: Array, required: false },
28
+ followingUser: { type: [String, null], required: false, default: null },
29
+ isSpaceRoot: { type: Boolean, required: false, default: true },
30
+ labels: { type: Object, required: false, default: () => ({}) }
31
+ });
32
+ const config = useRuntimeConfig();
33
+ const locale = computed(() => ({
34
+ ...DEFAULT_LOCALE.renderers.overview,
35
+ ...config.public?.abracadabra?.locale?.renderers?.overview ?? {},
36
+ ...props.labels ?? {}
37
+ }));
38
+ const {
39
+ childProviderRef,
40
+ rootDoc,
41
+ tree,
42
+ connectedUsers,
43
+ states,
44
+ setLocalState
45
+ } = useRendererBase(props);
46
+ const abra = useAbracadabra();
47
+ const { canWrite } = useDocumentPermissions(abra.effectiveRole);
48
+ const {
49
+ openNodeId,
50
+ openNodeLabel,
51
+ openNodeProvider,
52
+ openNode,
53
+ closePanel
54
+ } = useNodePanel(childProviderRef);
55
+ useNodePanelFollow(
56
+ openNodeId,
57
+ openNodeLabel,
58
+ openNode,
59
+ closePanel,
60
+ () => props.followingUser,
61
+ states,
62
+ setLocalState
63
+ );
64
+ useViewingBroadcast(() => props.docId, openNodeId);
65
+ const { getViewers: getDocViewers } = useItemPresence();
66
+ const { favorites, isFavorite, toggleFavorite, moveFavorite } = useFavorites(rootDoc);
67
+ const { voiceRoomId, voiceStatus, peerCount: voicePeerCount, joinRoom: _joinRoom } = useVoice();
68
+ const router = useRouter();
69
+ const { isOpen: searchOpen, searchTerm } = useCommandPalette();
70
+ const appConfig = useAppConfig();
71
+ const neutral = computed(() => appConfig.ui?.colors?.neutral ?? "zinc");
72
+ const { onlineUsers } = useChatUsers();
73
+ const allEntries = computed(() => tree.entries.value);
74
+ const spaceStats = computed(() => {
75
+ const entries = allEntries.value;
76
+ const now = Date.now();
77
+ const tagMap = /* @__PURE__ */ new Map();
78
+ const callDocs = /* @__PURE__ */ new Map();
79
+ let taskTotal = 0;
80
+ let taskDone = 0;
81
+ let taskOverdue = 0;
82
+ const pendingTasks = [];
83
+ const upcomingList = [];
84
+ const recentList = [];
85
+ for (const e of entries) {
86
+ const type = e.type || "doc";
87
+ if (type === "call") callDocs.set(e.id, e);
88
+ if (e.meta?.tags) {
89
+ for (const tag of e.meta.tags) {
90
+ tagMap.set(tag, (tagMap.get(tag) || 0) + 1);
91
+ }
92
+ }
93
+ if (e.meta?.checked !== void 0) {
94
+ taskTotal++;
95
+ if (e.meta.checked) {
96
+ taskDone++;
97
+ } else {
98
+ if (pendingTasks.length < 5) pendingTasks.push(e);
99
+ const due = e.meta.dateEnd;
100
+ if (due && new Date(due).getTime() < now) taskOverdue++;
101
+ }
102
+ }
103
+ const d = e.meta?.datetimeStart ?? e.meta?.dateStart;
104
+ if (d) {
105
+ const ts = new Date(d).getTime();
106
+ if (ts >= now) upcomingList.push({ entry: e, ts });
107
+ }
108
+ if (e.updatedAt) recentList.push(e);
109
+ }
110
+ upcomingList.sort((a, b) => a.ts - b.ts);
111
+ const upcoming = upcomingList.slice(0, 8).map((u) => u.entry);
112
+ recentList.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
113
+ const recentActivity = recentList.slice(0, 20);
114
+ const tagCounts = [...tagMap.entries()].sort((a, b) => b[1] - a[1]).slice(0, 20);
115
+ const taskPct = taskTotal ? Math.round(taskDone / taskTotal * 100) : 0;
116
+ return { tagCounts, callDocs, taskTotal, taskDone, taskOverdue, taskPct, pendingTasks, upcoming, recentActivity };
117
+ });
118
+ const usersWithContext = computed(
119
+ () => onlineUsers.value.filter((u) => u.publicKey !== abra.publicKeyB64.value).map((u) => ({
120
+ ...u,
121
+ docLabel: u.docId ? tree.treeMap.data[u.docId]?.label : void 0
122
+ }))
123
+ );
124
+ const activeCallRooms = computed(() => {
125
+ const { callDocs } = spaceStats.value;
126
+ const roomUsers = /* @__PURE__ */ new Map();
127
+ for (const u of usersWithContext.value) {
128
+ if (u.docId && callDocs.has(u.docId)) {
129
+ const list = roomUsers.get(u.docId) || [];
130
+ list.push(u);
131
+ roomUsers.set(u.docId, list);
132
+ }
133
+ }
134
+ if (voiceRoomId.value && voiceStatus.value === "connected" && callDocs.has(voiceRoomId.value)) {
135
+ if (!roomUsers.has(voiceRoomId.value)) roomUsers.set(voiceRoomId.value, []);
136
+ }
137
+ return [...roomUsers.entries()].map(([docId, users]) => ({
138
+ entry: callDocs.get(docId),
139
+ users,
140
+ isMyRoom: voiceRoomId.value === docId,
141
+ peerCount: voiceRoomId.value === docId ? voicePeerCount.value + 1 : users.length
142
+ }));
143
+ });
144
+ const favoriteEntries = computed(() => {
145
+ const treeData = tree.treeMap.data;
146
+ return favorites.value.map((id) => {
147
+ const raw = treeData[id];
148
+ return raw ? { ...raw, id } : void 0;
149
+ }).filter((e) => !!e);
150
+ });
151
+ const quickCreateTypes = computed(
152
+ () => ["doc", "prose", "kanban", "calendar", "checklist", "call"].map((k) => resolveDocType(k, abra.registry))
153
+ );
154
+ const directChildren = computed(() => tree.childrenOf(null));
155
+ const { expandedIds, toggle: toggleExpand, flatItems } = useTreeExpansion({
156
+ storageKey: `overview:expand:${props.docId}`,
157
+ childrenOf: (parentId) => tree.childrenOf(parentId)
158
+ });
159
+ const viewersByItem = computed(() => {
160
+ const m = /* @__PURE__ */ new Map();
161
+ for (const item of flatItems.value) {
162
+ const v = getDocViewers(item.id);
163
+ if (v.length) m.set(item.id, v);
164
+ }
165
+ for (const e of spaceStats.value.recentActivity) {
166
+ if (!m.has(e.id)) {
167
+ const v = getDocViewers(e.id);
168
+ if (v.length) m.set(e.id, v);
169
+ }
170
+ }
171
+ return m;
172
+ });
173
+ function itemViewers(itemId) {
174
+ return viewersByItem.value.get(itemId) ?? [];
175
+ }
176
+ const pagesScrollRef = ref(null);
177
+ const ROW_HEIGHT = 40;
178
+ const virtualizer = useVirtualizer(
179
+ computed(() => ({
180
+ count: flatItems.value.length,
181
+ getScrollElement: () => pagesScrollRef.value,
182
+ estimateSize: () => ROW_HEIGHT,
183
+ overscan: 8
184
+ }))
185
+ );
186
+ const virtualPageRows = computed(() => {
187
+ const rows = virtualizer.value.getVirtualItems();
188
+ const flat = flatItems.value;
189
+ return rows.map((vRow) => ({ vRow, item: flat[vRow.index] }));
190
+ });
191
+ function handleNavigate(entry) {
192
+ router.push(`/doc/${entry.id}`);
193
+ }
194
+ function handleJoinCall(docId) {
195
+ router.push(`/doc/${docId}`);
196
+ }
197
+ function createTypedPage(type) {
198
+ const label = locale.value.untitled;
199
+ const id = tree.createChild(null, label);
200
+ if (id) {
201
+ const entry = tree.treeMap.get(id);
202
+ if (entry) tree.treeMap.set(id, { ...entry, type });
203
+ router.push(`/doc/${id}`);
204
+ }
205
+ }
206
+ async function duplicateDoc(id) {
207
+ const provider = abra.provider.value;
208
+ if (!provider) return;
209
+ const { duplicateDocTree } = await import("../../utils/duplicateDocContent");
210
+ await duplicateDocTree(
211
+ provider,
212
+ id,
213
+ tree.treeMap.data,
214
+ (newId, entry) => tree.treeMap.set(newId, entry)
215
+ );
216
+ }
217
+ function changeDocType(id, type) {
218
+ const entry = tree.treeMap.get(id);
219
+ if (entry) tree.treeMap.set(id, { ...entry, type });
220
+ }
221
+ const renameId = ref(null);
222
+ const renameValue = ref("");
223
+ let renameCooldown = false;
224
+ function startRename(id) {
225
+ const entry = tree.treeMap.get(id);
226
+ if (!entry) return;
227
+ renameId.value = id;
228
+ renameValue.value = entry.label;
229
+ renameCooldown = true;
230
+ setTimeout(() => {
231
+ renameCooldown = false;
232
+ }, 200);
233
+ }
234
+ function commitRename() {
235
+ if (renameCooldown) return;
236
+ if (renameId.value && renameValue.value.trim()) {
237
+ tree.renameEntry(renameId.value, renameValue.value.trim());
238
+ }
239
+ renameId.value = null;
240
+ }
241
+ async function openAsWindow(id, label) {
242
+ const { useWindowManager } = await import("../../composables/useWindowManager");
243
+ const wm = useWindowManager();
244
+ if (wm.windows.has(id)) {
245
+ wm.focusWindow(id);
246
+ return;
247
+ }
248
+ const childProv = await childProviderRef.value?.loadChild(id);
249
+ if (!childProv) return;
250
+ if (!childProv.isSynced) {
251
+ await new Promise((resolve) => {
252
+ const done = () => {
253
+ childProv.off("synced", done);
254
+ resolve();
255
+ };
256
+ childProv.on("synced", done);
257
+ setTimeout(resolve, 6e3);
258
+ });
259
+ }
260
+ const entry = tree.entries.value.find((e) => e.id === id);
261
+ wm.openWindow({
262
+ id,
263
+ title: label,
264
+ docId: id,
265
+ docType: entry?.type,
266
+ provider: childProv,
267
+ initialTab: "editor"
268
+ });
269
+ }
270
+ function pageMenuItems(page) {
271
+ const l = locale.value;
272
+ return [
273
+ [
274
+ { label: l.open, icon: "i-lucide-external-link", onSelect: () => router.push(`/doc/${page.id}`) },
275
+ { label: l.openAsSlideover, icon: "i-lucide-panel-right", onSelect: () => openNode(page.id, page.label) },
276
+ { label: l.openAsWindow, icon: "i-lucide-picture-in-picture-2", onSelect: () => openAsWindow(page.id, page.label) },
277
+ { label: l.rename, icon: "i-lucide-pencil", onSelect: () => startRename(page.id) },
278
+ { label: l.duplicate, icon: "i-lucide-copy", onSelect: () => duplicateDoc(page.id) },
279
+ {
280
+ label: isFavorite(page.id) ? l.removeFromFavorites : l.addToFavorites,
281
+ icon: isFavorite(page.id) ? "i-lucide-star-off" : "i-lucide-star",
282
+ onSelect: () => toggleFavorite(page.id)
283
+ }
284
+ ],
285
+ [
286
+ {
287
+ label: l.changeType,
288
+ icon: "i-lucide-layers",
289
+ children: getAvailableDocTypes(abra.registry).map((typeDef) => ({
290
+ label: typeDef.label,
291
+ icon: typeDef.icon,
292
+ type: "checkbox",
293
+ checked: page.type === typeDef.key,
294
+ onSelect: (e) => {
295
+ e.preventDefault();
296
+ changeDocType(page.id, typeDef.key);
297
+ }
298
+ }))
299
+ }
300
+ ],
301
+ [
302
+ {
303
+ label: l.moveToTrash,
304
+ icon: "i-lucide-trash-2",
305
+ color: "error",
306
+ onSelect: () => tree.deleteEntry(page.id)
307
+ }
308
+ ]
309
+ ];
310
+ }
311
+ function readOnlyMenuItems(page) {
312
+ const l = locale.value;
313
+ return [
314
+ [
315
+ { label: l.open, icon: "i-lucide-external-link", onSelect: () => router.push(`/doc/${page.id}`) },
316
+ { label: l.openAsSlideover, icon: "i-lucide-panel-right", onSelect: () => openNode(page.id, page.label) },
317
+ { label: l.openAsWindow, icon: "i-lucide-picture-in-picture-2", onSelect: () => openAsWindow(page.id, page.label) },
318
+ {
319
+ label: isFavorite(page.id) ? l.removeFromFavorites : l.addToFavorites,
320
+ icon: isFavorite(page.id) ? "i-lucide-star-off" : "i-lucide-star",
321
+ onSelect: () => toggleFavorite(page.id)
322
+ }
323
+ ]
324
+ ];
325
+ }
326
+ const dragId = ref(null);
327
+ const dropIndicator = ref(null);
328
+ const docDragBus = useDocDragBus();
329
+ function siblingsOf(parentId) {
330
+ return tree.childrenOf(parentId);
331
+ }
332
+ function computeOrder(targetId, position, parentId, excludeId) {
333
+ const exclude = excludeId ?? dragId.value;
334
+ const siblings = siblingsOf(parentId).filter((p) => p.id !== exclude);
335
+ const idx = siblings.findIndex((p) => p.id === targetId);
336
+ if (idx < 0) return Date.now();
337
+ const target = siblings[idx];
338
+ if (position === "before") {
339
+ const prev = siblings[idx - 1];
340
+ return prev ? (prev.order + target.order) / 2 : target.order - 1e3;
341
+ } else {
342
+ const next = siblings[idx + 1];
343
+ return next ? (target.order + next.order) / 2 : target.order + 1e3;
344
+ }
345
+ }
346
+ function onDragStart(e, page) {
347
+ if (!canWrite.value) return;
348
+ dragId.value = page.id;
349
+ if (e.dataTransfer) {
350
+ e.dataTransfer.effectAllowed = "move";
351
+ e.dataTransfer.setData("text/plain", page.id);
352
+ e.dataTransfer.setData(DOC_DRAG_MIME, JSON.stringify({ id: page.id, label: page.label }));
353
+ }
354
+ docDragBus.startDrag({
355
+ docIds: [page.id],
356
+ labels: [page.label],
357
+ source: "renderer",
358
+ sourceDocId: props.docId,
359
+ pointer: { x: e.clientX, y: e.clientY }
360
+ });
361
+ }
362
+ function onDragOver(e, page) {
363
+ if (!canWrite.value) return;
364
+ e.preventDefault();
365
+ if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
366
+ if (page.id === dragId.value) return;
367
+ if (dragId.value && isDescendantInMap(tree.treeMap.data, dragId.value, page.id)) return;
368
+ const rect = e.currentTarget.getBoundingClientRect();
369
+ const y = e.clientY - rect.top;
370
+ const h = rect.height;
371
+ let position;
372
+ if (y < h * 0.25) position = "before";
373
+ else if (y > h * 0.75) position = "after";
374
+ else position = "inside";
375
+ dropIndicator.value = { targetId: page.id, position };
376
+ }
377
+ function onDrop(e) {
378
+ e.preventDefault();
379
+ if (!dropIndicator.value || !canWrite.value || !dragId.value) {
380
+ cleanupDrag();
381
+ return;
382
+ }
383
+ const { targetId, position } = dropIndicator.value;
384
+ const targetEntry = tree.treeMap.get(targetId);
385
+ if (!targetEntry) {
386
+ cleanupDrag();
387
+ return;
388
+ }
389
+ const targetParent = targetEntry.parentId ?? null;
390
+ const rootParent = props.docId;
391
+ if (position === "inside") {
392
+ tree.moveEntry(dragId.value, targetId, Date.now());
393
+ if (!expandedIds.value.has(targetId)) toggleExpand(targetId);
394
+ } else {
395
+ const parentForReorder = targetParent === rootParent ? null : targetParent;
396
+ const newOrder = computeOrder(targetId, position, parentForReorder);
397
+ tree.moveEntry(dragId.value, parentForReorder, newOrder);
398
+ }
399
+ cleanupDrag();
400
+ }
401
+ function onDragEnd() {
402
+ cleanupDrag();
403
+ docDragBus.endDrag();
404
+ }
405
+ function cleanupDrag() {
406
+ dragId.value = null;
407
+ dropIndicator.value = null;
408
+ }
409
+ const { containerRef: overviewDropRef, isDropTarget } = useDocDropZone({
410
+ parentDocId: props.docId,
411
+ tree,
412
+ resolveDropPosition: (pointer, el) => {
413
+ const items = el.querySelectorAll("[data-overview-child]");
414
+ for (let i = 0; i < items.length; i++) {
415
+ const node = items[i];
416
+ const rect = node.getBoundingClientRect();
417
+ if (pointer.y < rect.top + rect.height / 2) {
418
+ const targetId = node.getAttribute("data-overview-child-id") || void 0;
419
+ const entry = targetId ? tree.treeMap.get(targetId) : void 0;
420
+ const parentId = entry?.parentId ?? null;
421
+ const parentForReorder = parentId === props.docId ? null : parentId;
422
+ const siblings = siblingsOf(parentForReorder);
423
+ const idx = siblings.findIndex((s) => s.id === targetId);
424
+ const target = idx >= 0 ? siblings[idx] : void 0;
425
+ const prev = idx > 0 ? siblings[idx - 1] : void 0;
426
+ return {
427
+ parentDocId: parentForReorder ?? props.docId,
428
+ targetItemId: targetId,
429
+ position: "before",
430
+ order: target ? prev ? (prev.order + target.order) / 2 : target.order - 1e3 : Date.now()
431
+ };
432
+ }
433
+ }
434
+ const roots = directChildren.value;
435
+ const last = roots[roots.length - 1];
436
+ return {
437
+ parentDocId: props.docId,
438
+ order: last ? last.order + 1e3 : Date.now()
439
+ };
440
+ }
441
+ });
442
+ const myClientId = computed(
443
+ () => props.childProvider?.awareness?.clientID ?? 0
444
+ );
445
+ function onItemPointerEnter(itemId) {
446
+ if (dragId.value) return;
447
+ setLocalState({ "overview:hovering": itemId });
448
+ }
449
+ function onItemPointerLeave() {
450
+ if (dragId.value) return;
451
+ setLocalState({ "overview:hovering": null });
452
+ }
453
+ const remoteHoversByItem = computed(() => {
454
+ const m = /* @__PURE__ */ new Map();
455
+ const me = myClientId.value;
456
+ for (const s of states.value) {
457
+ if (s.clientId === me) continue;
458
+ const hovering = s["overview:hovering"];
459
+ if (!hovering || !s.user) continue;
460
+ const list = m.get(hovering);
461
+ const u = { name: s.user.name ?? "", color: s.user.color ?? "#888" };
462
+ if (list) list.push(u);
463
+ else m.set(hovering, [u]);
464
+ }
465
+ return m;
466
+ });
467
+ function remoteHovers(itemId) {
468
+ return remoteHoversByItem.value.get(itemId) ?? [];
469
+ }
470
+ onBeforeUnmount(() => {
471
+ setLocalState({ "overview:hovering": null });
472
+ });
473
+ const pinnedDrag = useTouchDrag({
474
+ idAttr: "data-pinned-id",
475
+ onDrop(dragId2, targetId) {
476
+ if (!canWrite.value) return;
477
+ const fromIdx = favorites.value.indexOf(dragId2);
478
+ const toIdx = favorites.value.indexOf(targetId);
479
+ if (fromIdx >= 0 && toIdx >= 0 && fromIdx !== toIdx) {
480
+ moveFavorite(fromIdx, toIdx);
481
+ }
482
+ }
483
+ });
484
+ function searchTag(tag) {
485
+ searchTerm.value = tag;
486
+ searchOpen.value = true;
487
+ }
488
+ function timeAgo(ts) {
489
+ if (!ts) return "";
490
+ const diff = Math.max(0, Date.now() - ts);
491
+ const sec = Math.floor(diff / 1e3);
492
+ if (sec < 5) return "just now";
493
+ if (sec < 60) return `${sec}s ago`;
494
+ const min = Math.floor(sec / 60);
495
+ if (min < 60) return `${min}m ago`;
496
+ const hr = Math.floor(min / 60);
497
+ if (hr < 24) return `${hr}h ago`;
498
+ const day = Math.floor(hr / 24);
499
+ if (day < 30) return `${day}d ago`;
500
+ const mon = Math.floor(day / 30);
501
+ if (mon < 12) return `${mon}mo ago`;
502
+ const yr = Math.floor(day / 365);
503
+ return `${yr}y ago`;
504
+ }
505
+ function getTypeIcon(entry) {
506
+ return resolveDocType(entry.type, abra.registry).icon;
507
+ }
508
+ function formatEventDate(entry) {
509
+ const d = entry.meta?.datetimeStart ?? entry.meta?.dateStart;
510
+ if (!d) return "";
511
+ const date = new Date(d);
512
+ const now = /* @__PURE__ */ new Date();
513
+ const diff = date.getTime() - now.getTime();
514
+ const days = Math.ceil(diff / 864e5);
515
+ if (days === 0) return locale.value.eventToday;
516
+ if (days === 1) return locale.value.eventTomorrow;
517
+ if (days < 7) return locale.value.eventInDays(days);
518
+ return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
519
+ }
520
+ defineExpose({ connectedUsers });
521
+ </script>
522
+
523
+ <template>
524
+ <div class="flex-1 overflow-y-auto">
525
+ <div
526
+ ref="overviewDropRef"
527
+ class="max-w-6xl mx-auto p-4 sm:p-6 lg:p-8 pb-32 space-y-6"
528
+ :class="isDropTarget ? 'ring-2 ring-inset ring-(--ui-primary)/30 rounded-(--ui-radius) bg-(--ui-primary)/3' : ''"
529
+ >
530
+ <!-- ═══ Compact stat line ═══ -->
531
+ <div class="flex items-center gap-4 text-xs text-(--ui-text-dimmed) flex-wrap">
532
+ <span class="flex items-center gap-1.5">
533
+ <UIcon name="i-lucide-file-text" class="size-3.5" />
534
+ {{ locale.documentsCount(allEntries.length) }}
535
+ </span>
536
+ <span class="flex items-center gap-1.5">
537
+ <span class="size-1.5 rounded-full bg-success animate-pulse" />
538
+ {{ locale.onlineCount(usersWithContext.length + 1) }}
539
+ </span>
540
+ <span v-if="spaceStats.taskTotal" class="flex items-center gap-1.5">
541
+ <UIcon name="i-lucide-check-square" class="size-3.5" />
542
+ {{ spaceStats.taskPct }}% {{ locale.tasksComplete }}
543
+ </span>
544
+ <span v-if="spaceStats.upcoming.length" class="flex items-center gap-1.5">
545
+ <UIcon name="i-lucide-calendar-clock" class="size-3.5" />
546
+ {{ locale.upcomingCount(spaceStats.upcoming.length) }}
547
+ </span>
548
+ <span v-if="spaceStats.taskOverdue" class="flex items-center gap-1.5 text-warning">
549
+ <UIcon name="i-lucide-clock" class="size-3.5" />
550
+ {{ locale.overdueCount(spaceStats.taskOverdue) }}
551
+ </span>
552
+ <span v-if="activeCallRooms.length" class="flex items-center gap-1.5 text-success">
553
+ <UIcon name="i-lucide-phone" class="size-3.5" />
554
+ {{ locale.activeCalls(activeCallRooms.length) }}
555
+ </span>
556
+ </div>
557
+
558
+ <!-- ═══ Pinned — favorite documents (space root only) ═══ -->
559
+ <section v-if="isSpaceRoot && favoriteEntries.length" class="space-y-3">
560
+ <h2 class="text-sm font-semibold text-(--ui-text-highlighted) uppercase tracking-wide flex items-center gap-2">
561
+ <UIcon name="i-lucide-pin" class="size-4" />
562
+ {{ locale.pinned }}
563
+ </h2>
564
+ <TransitionGroup
565
+ name="pinned-item"
566
+ tag="div"
567
+ class="flex items-center gap-2 flex-wrap"
568
+ :class="{ 'is-pinned-dragging': pinnedDrag.isDragging.value }"
569
+ >
570
+ <div v-for="entry in favoriteEntries" :key="entry.id" class="pinned-item">
571
+ <ANodeContextMenu :items="canWrite ? pageMenuItems(entry) : readOnlyMenuItems(entry)">
572
+ <button
573
+ :data-pinned-id="entry.id"
574
+ class="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-(--ui-bg-elevated)/40 border border-(--ui-border-muted) hover:border-(--ui-border) hover:bg-(--ui-bg-elevated) transition-colors cursor-pointer text-left select-none"
575
+ :class="[
576
+ pinnedDrag.dragId.value === entry.id ? 'opacity-30' : '',
577
+ pinnedDrag.dragOverId.value === entry.id && pinnedDrag.dragId.value !== entry.id ? 'border-(--ui-primary)' : ''
578
+ ]"
579
+ @click="handleNavigate(entry)"
580
+ @pointerdown="pinnedDrag.handlePointerDown($event, entry.id)"
581
+ >
582
+ <UIcon
583
+ :name="resolveDocType(entry.type, abra.registry).icon"
584
+ class="size-3.5 text-(--ui-text-muted) shrink-0"
585
+ />
586
+ <span class="text-sm text-(--ui-text) truncate max-w-40">{{ entry.label || locale.untitled }}</span>
587
+ <UBadge
588
+ v-if="entry.type && entry.type !== 'doc'"
589
+ variant="subtle"
590
+ color="neutral"
591
+ size="xs"
592
+ :label="resolveDocType(entry.type, abra.registry).label"
593
+ class="shrink-0"
594
+ />
595
+ </button>
596
+ </ANodeContextMenu>
597
+ </div>
598
+ </TransitionGroup>
599
+ </section>
600
+
601
+ <!-- ═══ Active Calls ═══ -->
602
+ <section v-if="activeCallRooms.length" class="space-y-3">
603
+ <h2 class="text-sm font-semibold text-(--ui-text-highlighted) uppercase tracking-wide flex items-center gap-2">
604
+ <UIcon name="i-lucide-phone" class="size-4 text-success" />
605
+ {{ locale.activeCalls(activeCallRooms.length) }}
606
+ </h2>
607
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
608
+ <button
609
+ v-for="room in activeCallRooms"
610
+ :key="room.entry.id"
611
+ class="flex items-center gap-3 p-3 rounded-lg bg-(--ui-bg-elevated)/40 border border-(--ui-border-muted) hover:border-(--ui-border) hover:bg-(--ui-bg-elevated) transition-all cursor-pointer text-left group"
612
+ @click="handleJoinCall(room.entry.id)"
613
+ >
614
+ <div class="relative shrink-0">
615
+ <UIcon name="i-lucide-phone" class="size-5 text-success" />
616
+ <span class="absolute -top-1 -right-1 size-2 rounded-full bg-success animate-pulse" />
617
+ </div>
618
+ <div class="flex flex-col min-w-0 flex-1">
619
+ <span class="text-sm font-medium text-(--ui-text) truncate">{{ room.entry.label || locale.untitled }}</span>
620
+ <span class="text-xs text-(--ui-text-dimmed)">
621
+ {{ locale.callParticipants(room.peerCount) }}
622
+ </span>
623
+ </div>
624
+ <div class="flex -space-x-1.5 shrink-0">
625
+ <UAvatar
626
+ v-for="user in room.users.slice(0, 3)"
627
+ :key="user.publicKey"
628
+ :alt="user.name"
629
+ size="2xs"
630
+ :style="avatarBorderStyle(user.color, neutral)"
631
+ />
632
+ <span
633
+ v-if="room.users.length > 3"
634
+ class="flex items-center justify-center size-5 rounded-full bg-(--ui-bg-elevated) border border-(--ui-border-muted) text-[10px] text-(--ui-text-dimmed)"
635
+ >
636
+ +{{ room.users.length - 3 }}
637
+ </span>
638
+ </div>
639
+ <UBadge
640
+ v-if="room.isMyRoom"
641
+ variant="subtle"
642
+ color="success"
643
+ size="xs"
644
+ :label="locale.inCall"
645
+ class="shrink-0"
646
+ />
647
+ <UIcon
648
+ v-else
649
+ name="i-lucide-arrow-right"
650
+ class="size-3.5 text-(--ui-text-dimmed) opacity-0 group-hover:opacity-100 transition-opacity shrink-0"
651
+ />
652
+ </button>
653
+ </div>
654
+ </section>
655
+
656
+ <!-- ═══ Pages — direct children with full interactivity ═══ -->
657
+ <section class="space-y-3">
658
+ <div class="flex items-center justify-between gap-2 min-w-0">
659
+ <h2 class="text-sm font-semibold text-(--ui-text-highlighted) uppercase tracking-wide flex items-center gap-2 shrink-0">
660
+ <UIcon name="i-lucide-files" class="size-4" />
661
+ {{ locale.pages }}
662
+ </h2>
663
+ <div v-if="canWrite" class="flex items-center gap-1 overflow-x-auto shrink min-w-0" style="scrollbar-width: none;">
664
+ <UButton
665
+ v-for="typeDef in quickCreateTypes"
666
+ :key="typeDef.key"
667
+ :icon="typeDef.icon"
668
+ size="xs"
669
+ variant="ghost"
670
+ color="neutral"
671
+ class="shrink-0"
672
+ @click="createTypedPage(typeDef.key)"
673
+ >
674
+ <span class="hidden sm:inline">{{ typeDef.label }}</span>
675
+ </UButton>
676
+ </div>
677
+ </div>
678
+
679
+ <!-- Virtualized tree -->
680
+ <div
681
+ v-if="flatItems.length > 0"
682
+ ref="pagesScrollRef"
683
+ class="overflow-y-auto rounded-(--ui-radius)"
684
+ :class="{ 'is-dragging': dragId }"
685
+ style="max-height: 60vh"
686
+ >
687
+ <div
688
+ :style="{
689
+ height: `${virtualizer.getTotalSize()}px`,
690
+ position: 'relative',
691
+ width: '100%'
692
+ }"
693
+ >
694
+ <div
695
+ v-for="{ vRow, item } in virtualPageRows"
696
+ :key="item.id"
697
+ data-overview-child
698
+ :data-overview-child-id="item.id"
699
+ class="overview-item absolute left-0 right-0"
700
+ :class="{ 'opacity-30': dragId === item.id }"
701
+ :style="{
702
+ transform: `translateY(${vRow.start}px)`,
703
+ height: `${vRow.size}px`,
704
+ paddingLeft: `${item.depth * 16}px`
705
+ }"
706
+ @dragover="onDragOver($event, item.entry)"
707
+ @drop.stop="onDrop"
708
+ @pointerenter="onItemPointerEnter(item.id)"
709
+ @pointerleave="onItemPointerLeave()"
710
+ >
711
+ <div
712
+ v-if="dropIndicator?.targetId === item.id && dropIndicator.position === 'before'"
713
+ class="drop-line drop-line-before"
714
+ >
715
+ <div class="drop-line-dot" />
716
+ </div>
717
+
718
+ <div
719
+ v-if="dropIndicator?.targetId === item.id && dropIndicator.position === 'inside'"
720
+ class="drop-inside"
721
+ />
722
+
723
+ <div
724
+ v-if="dropIndicator?.targetId === item.id && dropIndicator.position === 'after'"
725
+ class="drop-line drop-line-after"
726
+ >
727
+ <div class="drop-line-dot" />
728
+ </div>
729
+
730
+ <ANodeContextMenu :items="canWrite ? pageMenuItems(item.entry) : readOnlyMenuItems(item.entry)">
731
+ <button
732
+ type="button"
733
+ class="flex items-center gap-1.5 pr-3 py-2 rounded-lg hover:bg-(--ui-bg-elevated) transition-colors text-sm text-(--ui-text) w-full select-none cursor-pointer relative"
734
+ :class="[
735
+ itemViewers(item.id).length ? 'ring-2 ring-inset' : remoteHovers(item.id).length ? 'ring-1 ring-inset' : ''
736
+ ]"
737
+ :style="itemViewers(item.id).length ? {
738
+ '--tw-ring-color': itemViewers(item.id)[0].color,
739
+ backgroundColor: itemViewers(item.id)[0].color + '14'
740
+ } : remoteHovers(item.id).length ? { '--tw-ring-color': remoteHovers(item.id)[0].color } : {}"
741
+ :draggable="canWrite"
742
+ @dragstart="onDragStart($event, item.entry)"
743
+ @dragend="onDragEnd"
744
+ @click="handleNavigate(item.entry)"
745
+ @dblclick.prevent="canWrite && startRename(item.id)"
746
+ >
747
+ <span
748
+ v-if="item.hasChildren"
749
+ class="flex items-center justify-center size-5 shrink-0 rounded hover:bg-(--ui-bg-accented)"
750
+ @click.stop="toggleExpand(item.id)"
751
+ >
752
+ <UIcon
753
+ :name="item.expanded ? 'i-lucide-chevron-down' : 'i-lucide-chevron-right'"
754
+ class="size-3.5 text-(--ui-text-dimmed)"
755
+ />
756
+ </span>
757
+ <span v-else class="size-5 shrink-0" />
758
+
759
+ <UIcon
760
+ :name="resolveDocType(item.entry.type, abra.registry).icon"
761
+ class="size-4 shrink-0 text-(--ui-text-muted)"
762
+ />
763
+
764
+ <UInput
765
+ v-if="canWrite && renameId === item.id"
766
+ v-model="renameValue"
767
+ size="xs"
768
+ variant="none"
769
+ class="flex-1"
770
+ autofocus
771
+ @blur="commitRename"
772
+ @keydown.enter.prevent="commitRename"
773
+ @keydown.escape.prevent="renameId = null"
774
+ @click.stop
775
+ @dblclick.stop
776
+ />
777
+ <span v-else class="truncate flex-1 text-left">{{ item.entry.label || locale.untitled }}</span>
778
+
779
+ <UBadge
780
+ v-if="item.entry.type && item.entry.type !== 'doc'"
781
+ variant="subtle"
782
+ color="neutral"
783
+ size="xs"
784
+ :label="resolveDocType(item.entry.type, abra.registry).label"
785
+ class="shrink-0"
786
+ />
787
+
788
+ <div
789
+ v-if="itemViewers(item.id).length"
790
+ class="flex -space-x-1 shrink-0"
791
+ >
792
+ <UAvatar
793
+ v-for="(u, i) in itemViewers(item.id).slice(0, 3)"
794
+ :key="`v-${i}`"
795
+ size="2xs"
796
+ :alt="u.name"
797
+ :title="u.name"
798
+ :style="avatarBorderStyle(u.color, neutral)"
799
+ />
800
+ </div>
801
+
802
+ <template v-else>
803
+ <template v-for="hover in remoteHovers(item.id).slice(0, 2)" :key="hover.name">
804
+ <UBadge
805
+ variant="subtle"
806
+ size="xs"
807
+ :label="hover.name"
808
+ :style="{ color: hover.color, borderColor: hover.color }"
809
+ class="shrink-0"
810
+ />
811
+ </template>
812
+ </template>
813
+
814
+ <div class="overview-row-actions flex items-center gap-0.5 shrink-0">
815
+ <UButton
816
+ v-if="canWrite"
817
+ icon="i-lucide-plus"
818
+ size="xs"
819
+ variant="ghost"
820
+ color="neutral"
821
+ @click.stop="() => {
822
+ const id = tree.createChild(item.id, locale.untitled);
823
+ if (id) {
824
+ if (!expandedIds.has(item.id)) toggleExpand(item.id);
825
+ openNode(id, locale.untitled);
826
+ }
827
+ }"
828
+ />
829
+ </div>
830
+ </button>
831
+ </ANodeContextMenu>
832
+ </div>
833
+ </div>
834
+ </div>
835
+
836
+ <div v-if="flatItems.length === 0 && canWrite" class="flex flex-col items-center justify-center py-8 text-(--ui-text-dimmed)">
837
+ <UIcon name="i-lucide-files" class="size-8 mb-2 opacity-30" />
838
+ <p class="text-sm mb-3">
839
+ {{ locale.emptyWelcome }}
840
+ </p>
841
+ <div class="flex items-center gap-2 flex-wrap justify-center">
842
+ <UButton
843
+ v-for="typeDef in quickCreateTypes"
844
+ :key="typeDef.key"
845
+ :icon="typeDef.icon"
846
+ size="sm"
847
+ variant="soft"
848
+ color="neutral"
849
+ :label="typeDef.label"
850
+ @click="createTypedPage(typeDef.key)"
851
+ />
852
+ </div>
853
+ </div>
854
+
855
+ <div v-else-if="flatItems.length === 0" class="flex flex-col items-center justify-center py-8 text-(--ui-text-dimmed)">
856
+ <UIcon name="i-lucide-files" class="size-8 mb-2 opacity-30" />
857
+ <p class="text-sm">
858
+ {{ locale.noPages }}
859
+ </p>
860
+ </div>
861
+ </section>
862
+
863
+ <!-- ═══ Main grid: Activity + Sidebar ═══ -->
864
+ <div class="grid grid-cols-1 lg:grid-cols-5 gap-6">
865
+ <!-- Activity feed (3 cols) -->
866
+ <section class="lg:col-span-3 space-y-3">
867
+ <h2 class="text-sm font-semibold text-(--ui-text-highlighted) uppercase tracking-wide flex items-center gap-2">
868
+ <UIcon name="i-lucide-activity" class="size-4" />
869
+ {{ locale.activity }}
870
+ </h2>
871
+
872
+ <div v-if="spaceStats.recentActivity.length" class="space-y-1">
873
+ <ANodeContextMenu
874
+ v-for="entry in spaceStats.recentActivity"
875
+ :key="entry.id"
876
+ :items="canWrite ? pageMenuItems(entry) : readOnlyMenuItems(entry)"
877
+ >
878
+ <button
879
+ class="w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-(--ui-bg-elevated) transition-colors cursor-pointer text-left group"
880
+ :class="remoteHovers(entry.id).length ? 'ring-1 ring-inset' : ''"
881
+ :style="remoteHovers(entry.id).length ? { '--tw-ring-color': remoteHovers(entry.id)[0].color } : {}"
882
+ @click="handleNavigate(entry)"
883
+ @pointerenter="onItemPointerEnter(entry.id)"
884
+ @pointerleave="onItemPointerLeave()"
885
+ >
886
+ <UIcon :name="getTypeIcon(entry)" class="size-4 text-(--ui-text-dimmed) shrink-0" />
887
+ <span class="text-sm text-(--ui-text) truncate flex-1">{{ entry.label }}</span>
888
+ <template v-for="hover in remoteHovers(entry.id).slice(0, 1)" :key="hover.name">
889
+ <UBadge
890
+ variant="subtle"
891
+ size="xs"
892
+ :label="hover.name"
893
+ :style="{ color: hover.color, borderColor: hover.color }"
894
+ class="shrink-0"
895
+ />
896
+ </template>
897
+ <span class="text-xs text-(--ui-text-dimmed) shrink-0 opacity-60 group-hover:opacity-100 transition-opacity">
898
+ {{ timeAgo(entry.updatedAt) }}
899
+ </span>
900
+ </button>
901
+ </ANodeContextMenu>
902
+ </div>
903
+
904
+ <div v-else class="flex flex-col items-center justify-center py-12 text-(--ui-text-dimmed)">
905
+ <UIcon name="i-lucide-inbox" class="size-8 mb-2 opacity-30" />
906
+ <p class="text-sm">
907
+ {{ locale.noActivity }}
908
+ </p>
909
+ <p class="text-xs mt-1 opacity-60">
910
+ {{ locale.emptyActivityHint }}
911
+ </p>
912
+ </div>
913
+ </section>
914
+
915
+ <!-- Sidebar (2 cols) -->
916
+ <aside class="lg:col-span-2 space-y-6">
917
+ <!-- Tasks progress -->
918
+ <section v-if="spaceStats.taskTotal" class="space-y-3">
919
+ <h2 class="text-sm font-semibold text-(--ui-text-highlighted) uppercase tracking-wide flex items-center gap-2">
920
+ <UIcon name="i-lucide-check-square" class="size-4" />
921
+ {{ locale.tasks }}
922
+ </h2>
923
+
924
+ <div class="p-4 rounded-lg bg-(--ui-bg-elevated)/40 border border-(--ui-border-muted) space-y-3">
925
+ <div class="flex items-end justify-between">
926
+ <div>
927
+ <span class="text-3xl font-bold text-(--ui-text-highlighted)">{{ spaceStats.taskDone }}</span>
928
+ <span class="text-sm text-(--ui-text-dimmed)"> / {{ spaceStats.taskTotal }}</span>
929
+ </div>
930
+ <span class="text-sm font-medium" :class="spaceStats.taskPct === 100 ? 'text-success' : 'text-(--ui-text-muted)'">
931
+ {{ spaceStats.taskPct }}%
932
+ </span>
933
+ </div>
934
+
935
+ <div class="h-1.5 w-full rounded-full bg-(--ui-bg-accented) overflow-hidden">
936
+ <div
937
+ class="h-full rounded-full"
938
+ :class="spaceStats.taskPct === 100 ? 'bg-success' : 'bg-(--ui-primary)'"
939
+ :style="{ width: `${spaceStats.taskPct}%` }"
940
+ />
941
+ </div>
942
+
943
+ <div v-if="spaceStats.taskOverdue" class="flex items-center gap-2 text-xs text-warning">
944
+ <UIcon name="i-lucide-clock" class="size-3.5" />
945
+ {{ locale.overdueCount(spaceStats.taskOverdue) }}
946
+ </div>
947
+
948
+ <div v-if="spaceStats.pendingTasks.length" class="pt-2 border-t border-(--ui-border-muted) space-y-1">
949
+ <ANodeContextMenu
950
+ v-for="task in spaceStats.pendingTasks"
951
+ :key="task.id"
952
+ :items="canWrite ? pageMenuItems(task) : readOnlyMenuItems(task)"
953
+ >
954
+ <button
955
+ class="w-full flex items-center gap-2 text-sm text-(--ui-text-muted) hover:text-(--ui-text) cursor-pointer truncate text-left py-0.5"
956
+ @click="handleNavigate(task)"
957
+ @pointerenter="onItemPointerEnter(task.id)"
958
+ @pointerleave="onItemPointerLeave()"
959
+ >
960
+ <UIcon name="i-lucide-circle" class="size-3 shrink-0" />
961
+ <span class="truncate">{{ task.label }}</span>
962
+ </button>
963
+ </ANodeContextMenu>
964
+ </div>
965
+ </div>
966
+ </section>
967
+
968
+ <!-- Upcoming events -->
969
+ <section v-if="spaceStats.upcoming.length" class="space-y-3">
970
+ <h2 class="text-sm font-semibold text-(--ui-text-highlighted) uppercase tracking-wide flex items-center gap-2">
971
+ <UIcon name="i-lucide-calendar-clock" class="size-4" />
972
+ {{ locale.upcoming }}
973
+ </h2>
974
+
975
+ <div class="space-y-1">
976
+ <ANodeContextMenu
977
+ v-for="entry in spaceStats.upcoming"
978
+ :key="entry.id"
979
+ :items="canWrite ? pageMenuItems(entry) : readOnlyMenuItems(entry)"
980
+ >
981
+ <button
982
+ class="w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-(--ui-bg-elevated) transition-colors cursor-pointer text-left"
983
+ @click="handleNavigate(entry)"
984
+ @pointerenter="onItemPointerEnter(entry.id)"
985
+ @pointerleave="onItemPointerLeave()"
986
+ >
987
+ <div
988
+ class="size-2 rounded-full shrink-0"
989
+ :style="{ background: entry.meta?.color || 'var(--ui-primary)' }"
990
+ />
991
+ <span class="text-sm text-(--ui-text) truncate flex-1">{{ entry.label }}</span>
992
+ <UBadge
993
+ variant="subtle"
994
+ color="neutral"
995
+ size="xs"
996
+ :label="formatEventDate(entry)"
997
+ />
998
+ </button>
999
+ </ANodeContextMenu>
1000
+ </div>
1001
+ </section>
1002
+
1003
+ <!-- Tags -->
1004
+ <section v-if="spaceStats.tagCounts.length" class="space-y-3">
1005
+ <h2 class="text-sm font-semibold text-(--ui-text-highlighted) uppercase tracking-wide flex items-center gap-2">
1006
+ <UIcon name="i-lucide-tags" class="size-4" />
1007
+ {{ locale.tags }}
1008
+ </h2>
1009
+
1010
+ <div class="flex flex-wrap gap-1.5">
1011
+ <UBadge
1012
+ v-for="[tag, count] in spaceStats.tagCounts"
1013
+ :key="tag"
1014
+ variant="subtle"
1015
+ color="neutral"
1016
+ size="sm"
1017
+ class="cursor-pointer"
1018
+ @click="searchTag(tag)"
1019
+ >
1020
+ {{ tag }}
1021
+ <span class="text-(--ui-text-dimmed) ml-1 opacity-60">{{ count }}</span>
1022
+ </UBadge>
1023
+ </div>
1024
+ </section>
1025
+ </aside>
1026
+ </div>
1027
+
1028
+ <!-- ═══ Node panel ═══ -->
1029
+ <ANodePanel
1030
+ :node-id="openNodeId"
1031
+ :node-label="openNodeLabel"
1032
+ :child-provider="openNodeProvider"
1033
+ @close="closePanel"
1034
+ />
1035
+ </div>
1036
+ </div>
1037
+ </template>
1038
+
1039
+ <style scoped>
1040
+ .pinned-item-move{transition:transform .2s ease-out}.is-pinned-dragging .pinned-item-move{transition:none}.pinned-item-enter-active{transition:all .15s ease-out}.pinned-item-leave-active{position:absolute;transition:all .1s ease-in}.pinned-item-enter-from,.pinned-item-leave-to{opacity:0;transform:scale(.9)}.overview-row-actions{opacity:0;pointer-events:none;transition:opacity .1s ease}@media (hover:hover) and (pointer:fine){.overview-item:hover .overview-row-actions,.overview-row-actions:has([data-state=open]){opacity:1;pointer-events:auto}}.overview-row-actions:has([data-state=open]){opacity:1;pointer-events:auto}.drop-line{background:var(--ui-primary);border-radius:1px;height:2px;left:12px;pointer-events:none;position:absolute;right:4px;z-index:20}.drop-line-before{top:0}.drop-line-after{bottom:0}.drop-line-dot{background:var(--ui-bg);border:2px solid var(--ui-primary);border-radius:50%;height:8px;left:-3px;position:absolute;top:-3px;width:8px}.drop-inside{background:color-mix(in srgb,var(--ui-primary) 8%,transparent);border:2px solid color-mix(in srgb,var(--ui-primary) 50%,transparent);border-radius:var(--ui-radius);inset:1px 4px;pointer-events:none;position:absolute;z-index:10}
1041
+ </style>