@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
@@ -1,6 +1,16 @@
1
1
  <script setup>
2
- import { computed, ref, nextTick } from "vue";
2
+ import { computed, ref, onMounted, watch, nextTick } from "vue";
3
3
  import { NodeViewWrapper } from "@tiptap/vue-3";
4
+ import AColorPalettePopover from "../../components/editor/AColorPalettePopover.vue";
5
+ import AIconPickerPopover from "../../components/editor/AIconPickerPopover.vue";
6
+ import ALocationPickerPopover from "../../components/editor/ALocationPickerPopover.vue";
7
+ import { useAbraLocale } from "../../composables/useAbraLocale";
8
+ import {
9
+ DateFormatter,
10
+ getLocalTimeZone,
11
+ Time,
12
+ parseDate
13
+ } from "@internationalized/date";
4
14
  const props = defineProps({
5
15
  decorations: { type: Array, required: true },
6
16
  selected: { type: Boolean, required: true },
@@ -14,15 +24,19 @@ const props = defineProps({
14
24
  extension: { type: Object, required: true },
15
25
  HTMLAttributes: { type: Object, required: true }
16
26
  });
27
+ const t = useAbraLocale("editor");
17
28
  function storage() {
18
29
  return props.editor.storage?.metaField;
19
30
  }
31
+ const df = new DateFormatter("en-US", { dateStyle: "medium" });
20
32
  const fieldType = computed(() => props.node.attrs.fieldType);
21
33
  const fieldLabel = computed(() => props.node.attrs.fieldLabel);
22
34
  const metaKey = computed(() => props.node.attrs.metaKey);
23
35
  const startKey = computed(() => props.node.attrs.startKey);
24
36
  const endKey = computed(() => props.node.attrs.endKey);
25
37
  const allDayKey = computed(() => props.node.attrs.allDayKey);
38
+ const latKey = computed(() => props.node.attrs.latKey);
39
+ const lngKey = computed(() => props.node.attrs.lngKey);
26
40
  const presets = computed(() => {
27
41
  try {
28
42
  return JSON.parse(props.node.attrs.presets ?? "[]");
@@ -30,6 +44,13 @@ const presets = computed(() => {
30
44
  return [];
31
45
  }
32
46
  });
47
+ const iconOptions = computed(() => {
48
+ try {
49
+ return JSON.parse(props.node.attrs.iconOptions ?? "[]");
50
+ } catch {
51
+ return [];
52
+ }
53
+ });
33
54
  const options = computed(() => {
34
55
  try {
35
56
  return JSON.parse(props.node.attrs.options ?? "[]");
@@ -46,130 +67,343 @@ function getStr(key) {
46
67
  }
47
68
  function getStrArr(key) {
48
69
  const v = storage()?.pageMeta?.[key];
49
- return Array.isArray(v) ? v : [];
70
+ if (!v || !Array.isArray(v)) return [];
71
+ return v;
50
72
  }
51
73
  function getObjArr(key) {
52
74
  const v = storage()?.pageMeta?.[key];
53
- return Array.isArray(v) ? v : [];
75
+ if (!v || !Array.isArray(v)) return [];
76
+ return v;
54
77
  }
55
78
  function getNum(key, fallback = 0) {
56
79
  return storage()?.pageMeta?.[key] ?? fallback;
57
80
  }
58
- function getBool(key) {
59
- return Boolean(storage()?.pageMeta?.[key]);
81
+ function getBool(key, fallback = false) {
82
+ const v = storage()?.pageMeta?.[key];
83
+ if (v === void 0 || v === null) return fallback;
84
+ return Boolean(v);
85
+ }
86
+ function getOptNum(key) {
87
+ const v = storage()?.pageMeta?.[key];
88
+ if (v === void 0 || v === null) return void 0;
89
+ return Number(v);
60
90
  }
61
91
  function patch(update) {
92
+ if (!props.editor?.isEditable) return;
62
93
  const s = storage();
63
94
  if (!s) return;
64
95
  if (s.pageMeta) Object.assign(s.pageMeta, update);
65
96
  s.updateMeta?.(update);
66
97
  }
67
- const labelDraft = ref("");
68
- function commitLabel() {
69
- if (labelDraft.value !== fieldLabel.value) {
70
- props.updateAttributes({ fieldLabel: labelDraft.value });
98
+ function isoToCalendarDate(s) {
99
+ if (s.length < 10) return void 0;
100
+ try {
101
+ return parseDate(s.slice(0, 10));
102
+ } catch {
103
+ return void 0;
71
104
  }
72
105
  }
73
- function deleteChip() {
74
- props.deleteNode();
106
+ function dvToIso(d) {
107
+ return d.toString().slice(0, 10);
75
108
  }
76
- const defaultPresets = ["#6366f1", "#f97316", "#22c55e", "#ef4444", "#a855f7", "#06b6d4", "#f59e0b", "#ec4899"];
77
- const allPresets = computed(() => presets.value.length ? presets.value : defaultPresets);
78
- function toggleSelect(opt) {
79
- patch({ [metaKey.value]: opt === getStr(metaKey.value) ? "" : opt });
109
+ function isoToTime(hhmm) {
110
+ const [h = 0, m = 0] = hhmm.split(":").map(Number);
111
+ return new Time(isNaN(h) ? 0 : h, isNaN(m) ? 0 : m);
80
112
  }
81
- function toggleMultiSelect(opt) {
82
- const current = getStrArr(metaKey.value);
83
- const next = current.includes(opt) ? current.filter((x) => x !== opt) : [...current, opt];
84
- patch({ [metaKey.value]: next });
113
+ function timeToHHMM(t2) {
114
+ return `${String(t2.hour).padStart(2, "0")}:${String(t2.minute).padStart(2, "0")}`;
85
115
  }
86
- function toggleTag(tag) {
87
- const current = getStrArr(metaKey.value);
88
- const next = current.includes(tag) ? current.filter((x) => x !== tag) : [...current, tag];
89
- patch({ [metaKey.value]: next });
116
+ function getDateRange(sk, ek) {
117
+ const start = isoToCalendarDate(getStr(sk));
118
+ const end = isoToCalendarDate(getStr(ek));
119
+ return start && end ? { start, end } : void 0;
90
120
  }
91
- function fmtDate(iso) {
92
- if (!iso) return "";
93
- try {
94
- return new Date(iso).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
95
- } catch {
96
- return iso;
97
- }
121
+ function formatDateRange(sk, ek) {
122
+ const startStr = getStr(sk).slice(0, 10);
123
+ const endStr = getStr(ek).slice(0, 10);
124
+ if (!startStr) return t.pickDate;
125
+ const sd = isoToCalendarDate(startStr);
126
+ if (!sd) return t.pickDate;
127
+ const startFmt = df.format(sd.toDate(getLocalTimeZone()));
128
+ if (!endStr) return startFmt;
129
+ const ed = isoToCalendarDate(endStr);
130
+ if (!ed || startStr === endStr) return startFmt;
131
+ return `${startFmt} \u2013 ${df.format(ed.toDate(getLocalTimeZone()))}`;
98
132
  }
99
- function fmtDatetime(iso) {
100
- if (!iso) return "";
101
- try {
102
- return new Date(iso).toLocaleString("en-US", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
103
- } catch {
104
- return iso;
105
- }
133
+ function onDateTimeRange(range) {
134
+ if (!range?.start || !range?.end) return;
135
+ const allDay = getBool(allDayKey.value, true);
136
+ const st = allDay ? "00:00" : getStr(startKey.value).slice(11, 16) || "00:00";
137
+ const et = allDay ? "01:00" : getStr(endKey.value).slice(11, 16) || "01:00";
138
+ patch({
139
+ [startKey.value]: `${dvToIso(range.start)}T${st}:00.000Z`,
140
+ [endKey.value]: `${dvToIso(range.end)}T${et}:00.000Z`
141
+ });
106
142
  }
107
- const displayValue = computed(() => {
108
- const t = fieldType.value;
109
- if (t === "toggle") return getBool(metaKey.value) ? "Yes" : "No";
110
- if (t === "colorPreset" || t === "colorPicker") return getStr(metaKey.value) ? "" : "None";
111
- if (t === "date") return fmtDate(getStr(metaKey.value)) || "Set";
112
- if (t === "datetime") return fmtDatetime(getStr(metaKey.value)) || "Set";
113
- if (t === "daterange") {
114
- const s = getStr(startKey.value);
115
- const e = getStr(endKey.value);
116
- return s && e ? `${fmtDate(s)} \u2013 ${fmtDate(e)}` : "Set";
117
- }
118
- if (t === "datetimerange") {
119
- const s = getStr(startKey.value);
120
- const e = getStr(endKey.value);
121
- return s && e ? `${fmtDatetime(s)} \u2013 ${fmtDatetime(e)}` : "Set";
122
- }
123
- if (t === "timerange") {
124
- const s = getStr(startKey.value);
125
- const e = getStr(endKey.value);
126
- return s && e ? `${s} \u2013 ${e}` : "Set";
127
- }
128
- if (t === "time") return getStr(metaKey.value) || "Set";
129
- if (t === "slider" || t === "number") {
130
- const v = getNum(metaKey.value, sliderMin.value);
131
- return unit.value ? `${v} ${unit.value}` : String(v);
132
- }
133
- if (t === "rating") {
134
- const v = getNum(metaKey.value);
135
- return v ? `${v}/${sliderMax.value}` : "Rate";
136
- }
137
- if (t === "url") {
138
- const v = getStr(metaKey.value);
139
- return v ? new URL(v).hostname : "Add URL";
140
- }
141
- if (t === "select") return getStr(metaKey.value) || "Select";
142
- if (t === "multiselect") {
143
- const arr = getStrArr(metaKey.value);
144
- return arr.length ? arr.join(", ") : "Select";
145
- }
146
- if (t === "tags") {
147
- const arr = getStrArr(metaKey.value);
148
- return arr.length ? arr.join(", ") : "Add tags";
143
+ function onStartTime(t2) {
144
+ if (!t2) return;
145
+ const date = getStr(startKey.value).slice(0, 10) || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
146
+ patch({ [startKey.value]: `${date}T${timeToHHMM(t2)}:00.000Z` });
147
+ }
148
+ function onEndTime(t2) {
149
+ if (!t2) return;
150
+ const date = getStr(endKey.value).slice(0, 10) || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
151
+ patch({ [endKey.value]: `${date}T${timeToHHMM(t2)}:00.000Z` });
152
+ }
153
+ function toggleAllDay() {
154
+ patch({ [allDayKey.value]: !getBool(allDayKey.value, true) });
155
+ }
156
+ function onDateRange(range) {
157
+ if (!range?.start || !range?.end) return;
158
+ patch({ [startKey.value]: dvToIso(range.start), [endKey.value]: dvToIso(range.end) });
159
+ }
160
+ function onSlider(v) {
161
+ if (v == null) return;
162
+ patch({ [metaKey.value]: Array.isArray(v) ? v[0] : v });
163
+ }
164
+ function onColor(c) {
165
+ const update = { [metaKey.value]: c };
166
+ if (metaKey.value !== "color") update.color = c;
167
+ patch(update);
168
+ colorPopoverOpen.value = false;
169
+ }
170
+ function onLatLng(key, v) {
171
+ patch({ [key]: v != null ? Number(v) : void 0 });
172
+ }
173
+ function onIcon(name) {
174
+ const update = { [metaKey.value]: name };
175
+ if (metaKey.value !== "icon") update.icon = name;
176
+ patch(update);
177
+ }
178
+ function onToggle(v) {
179
+ patch({ [metaKey.value]: v });
180
+ }
181
+ function onNumber(v) {
182
+ patch({ [metaKey.value]: v != null && v !== "" ? Number(v) : void 0 });
183
+ }
184
+ function onSelect(v) {
185
+ patch({ [metaKey.value]: v });
186
+ }
187
+ function onMultiSelect(v) {
188
+ patch({ [metaKey.value]: v });
189
+ }
190
+ function onRating(v) {
191
+ const current = getNum(metaKey.value);
192
+ const next = current === v ? 0 : v;
193
+ const update = { [metaKey.value]: next };
194
+ if (metaKey.value !== "rating") update.rating = next;
195
+ patch(update);
196
+ }
197
+ function onRatingWheel(e) {
198
+ const delta = -Math.sign(e.deltaY);
199
+ if (!delta) return;
200
+ const current = getNum(metaKey.value);
201
+ const max = sliderMax.value || 5;
202
+ const next = Math.max(0, Math.min(max, current + delta));
203
+ if (next !== current) patch({ [metaKey.value]: next });
204
+ }
205
+ function onNumberWheel(e) {
206
+ const delta = -Math.sign(e.deltaY);
207
+ if (!delta) return;
208
+ const step = (sliderStep.value || 1) * (e.shiftKey ? 10 : 1);
209
+ const current = getNum(metaKey.value);
210
+ const min = sliderMin.value;
211
+ const max = sliderMax.value;
212
+ const next = Math.max(min, Math.min(max, current + delta * step));
213
+ if (next !== current) patch({ [metaKey.value]: next });
214
+ }
215
+ function onSliderWheel(e) {
216
+ const delta = -Math.sign(e.deltaY);
217
+ if (!delta) return;
218
+ const step = (sliderStep.value || 1) * (e.shiftKey ? 10 : 1);
219
+ const current = getNum(metaKey.value);
220
+ const min = sliderMin.value;
221
+ const max = sliderMax.value;
222
+ const next = Math.max(min, Math.min(max, current + delta * step));
223
+ if (next !== current) patch({ [metaKey.value]: next });
224
+ }
225
+ function onDateWheel(e, key) {
226
+ const delta = -Math.sign(e.deltaY);
227
+ if (!delta) return;
228
+ const current = getStr(key);
229
+ const base = current ? new Date(current) : /* @__PURE__ */ new Date();
230
+ if (Number.isNaN(base.getTime())) return;
231
+ base.setUTCDate(base.getUTCDate() + delta);
232
+ if (current.length <= 10 || !current.includes("T"))
233
+ patch({ [key]: base.toISOString().slice(0, 10) });
234
+ else
235
+ patch({ [key]: base.toISOString() });
236
+ }
237
+ function onTimeWheel(e, key) {
238
+ const delta = -Math.sign(e.deltaY);
239
+ if (!delta) return;
240
+ const current = getStr(key) || "00:00";
241
+ const [hStr, mStr] = current.slice(0, 5).split(":");
242
+ const total = parseInt(hStr ?? "0", 10) * 60 + parseInt(mStr ?? "0", 10) + delta * (e.shiftKey ? 60 : 15);
243
+ const clamped = (total % (24 * 60) + 24 * 60) % (24 * 60);
244
+ const h = Math.floor(clamped / 60).toString().padStart(2, "0");
245
+ const m = (clamped % 60).toString().padStart(2, "0");
246
+ patch({ [key]: `${h}:${m}` });
247
+ }
248
+ function onSingleDate(d) {
249
+ if (!d || typeof d.toString !== "function") return;
250
+ const dv = d;
251
+ patch({ [metaKey.value]: dvToIso(dv) });
252
+ }
253
+ function onSingleDatetimeDate(d) {
254
+ if (!d) return;
255
+ const dv = d;
256
+ const date = dvToIso(dv);
257
+ const time = getStr(metaKey.value).slice(11, 16) || "00:00";
258
+ patch({ [metaKey.value]: `${date}T${time}:00.000Z` });
259
+ }
260
+ function onSingleTime(t2) {
261
+ if (!t2) return;
262
+ patch({ [metaKey.value]: timeToHHMM(t2) });
263
+ }
264
+ function onTimeRangeStart(t2) {
265
+ if (!t2) return;
266
+ patch({ [startKey.value]: timeToHHMM(t2) });
267
+ }
268
+ function onTimeRangeEnd(t2) {
269
+ if (!t2) return;
270
+ patch({ [endKey.value]: timeToHHMM(t2) });
271
+ }
272
+ function deleteField() {
273
+ if (!props.editor?.isEditable) return;
274
+ const clearPatch = {};
275
+ if (metaKey.value) clearPatch[metaKey.value] = void 0;
276
+ if (startKey.value) clearPatch[startKey.value] = void 0;
277
+ if (endKey.value) clearPatch[endKey.value] = void 0;
278
+ if (allDayKey.value) clearPatch[allDayKey.value] = void 0;
279
+ if (latKey.value) clearPatch[latKey.value] = void 0;
280
+ if (lngKey.value) clearPatch[lngKey.value] = void 0;
281
+ if (Object.keys(clearPatch).length) patch(clearPatch);
282
+ const pos = props.getPos();
283
+ if (pos !== void 0) {
284
+ props.editor.chain().deleteRange({ from: pos, to: pos + props.node.nodeSize }).run();
149
285
  }
150
- if (t === "textarea") {
151
- const v = getStr(metaKey.value);
152
- return v ? v.slice(0, 24) + (v.length > 24 ? "\u2026" : "") : "Add text";
286
+ }
287
+ const isDragging = ref(false);
288
+ function onGripPointerDown(e) {
289
+ if (!props.editor?.isEditable) return;
290
+ e.preventDefault();
291
+ e.stopPropagation();
292
+ const startX = e.clientX;
293
+ const startY = e.clientY;
294
+ let activated = false;
295
+ const ACTIVATION_PX = 4;
296
+ function targetPosFromPoint(x, y) {
297
+ const el = document.elementFromPoint(x, y);
298
+ const chip = el?.closest(".meta-field-chip");
299
+ if (!chip) return null;
300
+ try {
301
+ const view = props.editor.view;
302
+ const coords = { left: x, top: y };
303
+ const posInfo = view.posAtCoords?.(coords);
304
+ if (posInfo && typeof posInfo.pos === "number") return posInfo.pos;
305
+ } catch {
306
+ }
307
+ return null;
153
308
  }
154
- if (t === "location") {
155
- const lat = getNum(metaKey.value);
156
- return lat ? `${getNum(props.node.attrs.latKey)?.toFixed(2)}, ${getNum(props.node.attrs.lngKey)?.toFixed(2)}` : "Set";
309
+ function onMove(ev) {
310
+ const dx = ev.clientX - startX;
311
+ const dy = ev.clientY - startY;
312
+ if (!activated && Math.hypot(dx, dy) >= ACTIVATION_PX) {
313
+ activated = true;
314
+ isDragging.value = true;
315
+ document.body.style.cursor = "grabbing";
316
+ }
317
+ if (activated) ev.preventDefault();
157
318
  }
158
- if (t === "members") {
159
- const arr = getObjArr(metaKey.value);
160
- return arr.length ? arr.map((m) => m.label).join(", ") : "Add members";
319
+ function onUp(ev) {
320
+ document.removeEventListener("pointermove", onMove, true);
321
+ document.removeEventListener("pointerup", onUp, true);
322
+ document.body.style.cursor = "";
323
+ if (!activated) {
324
+ isDragging.value = false;
325
+ return;
326
+ }
327
+ isDragging.value = false;
328
+ const fromPos = props.getPos();
329
+ if (fromPos === void 0) return;
330
+ const toPos = targetPosFromPoint(ev.clientX, ev.clientY);
331
+ if (toPos === null || toPos === fromPos) return;
332
+ props.editor.commands.moveMetaField(fromPos, toPos);
161
333
  }
162
- return getStr(metaKey.value) || "\u2014";
334
+ document.addEventListener("pointermove", onMove, true);
335
+ document.addEventListener("pointerup", onUp, true);
336
+ }
337
+ const isEditable = computed(() => props.editor?.isEditable ?? false);
338
+ const isHovered = ref(false);
339
+ const colorPopoverOpen = ref(false);
340
+ const iconPopoverOpen = ref(false);
341
+ const locationPopoverOpen = ref(false);
342
+ const selectPopoverOpen = ref(false);
343
+ const multiSelectPopoverOpen = ref(false);
344
+ const membersPopoverOpen = ref(false);
345
+ const textareaPopoverOpen = ref(false);
346
+ const datePopoverOpen = ref(false);
347
+ const datetimePopoverOpen = ref(false);
348
+ const timePopoverOpen = ref(false);
349
+ const daterangePopoverOpen = ref(false);
350
+ const datetimerangePopoverOpen = ref(false);
351
+ onMounted(() => {
352
+ const s = storage();
353
+ if (!s?.pendingOpen) return;
354
+ const marker = metaKey.value || startKey.value || latKey.value;
355
+ const tag = `${fieldType.value}:${marker}`;
356
+ if (s.pendingOpen !== tag) return;
357
+ s.pendingOpen = "";
358
+ setTimeout(() => {
359
+ switch (fieldType.value) {
360
+ case "colorPreset":
361
+ case "colorPicker":
362
+ colorPopoverOpen.value = true;
363
+ break;
364
+ case "icon":
365
+ iconPopoverOpen.value = true;
366
+ break;
367
+ case "location":
368
+ locationPopoverOpen.value = true;
369
+ break;
370
+ case "select":
371
+ selectPopoverOpen.value = true;
372
+ break;
373
+ case "multiselect":
374
+ multiSelectPopoverOpen.value = true;
375
+ break;
376
+ case "members":
377
+ membersPopoverOpen.value = true;
378
+ break;
379
+ case "textarea":
380
+ textareaPopoverOpen.value = true;
381
+ break;
382
+ case "date":
383
+ datePopoverOpen.value = true;
384
+ break;
385
+ case "datetime":
386
+ datetimePopoverOpen.value = true;
387
+ break;
388
+ case "time":
389
+ timePopoverOpen.value = true;
390
+ break;
391
+ case "daterange":
392
+ daterangePopoverOpen.value = true;
393
+ break;
394
+ case "datetimerange":
395
+ datetimerangePopoverOpen.value = true;
396
+ break;
397
+ }
398
+ }, 150);
163
399
  });
164
- const chipColor = computed(() => {
165
- const t = fieldType.value;
166
- if (t === "colorPreset" || t === "colorPicker") return getStr(metaKey.value) || "";
167
- return "";
400
+ const textareaRef = ref(null);
401
+ watch(textareaPopoverOpen, async (open) => {
402
+ if (open) {
403
+ await nextTick();
404
+ textareaRef.value?.textareaRef?.focus();
405
+ }
168
406
  });
169
- const popoverOpen = ref(false);
170
- const editingText = ref(false);
171
- const textDraft = ref("");
172
- const newOption = ref("");
173
407
  const memberSearch = ref("");
174
408
  const mentionItems = computed(
175
409
  () => props.editor.storage?.metaField?.mentionItems ?? []
@@ -183,535 +417,880 @@ function onToggleMember(user) {
183
417
  const exists = current.some((m) => m.id === user.id);
184
418
  patch({ [metaKey.value]: exists ? current.filter((m) => m.id !== user.id) : [...current, { id: user.id, label: user.label }] });
185
419
  }
186
- function openEditor() {
420
+ const editingLabel = ref(false);
421
+ const labelDraft = ref("");
422
+ const labelInputEl = ref(null);
423
+ function startEditLabel() {
187
424
  labelDraft.value = fieldLabel.value;
188
- popoverOpen.value = true;
425
+ editingLabel.value = true;
426
+ nextTick(() => labelInputEl.value?.select());
427
+ }
428
+ function saveLabel() {
429
+ editingLabel.value = false;
430
+ if (labelDraft.value.trim() !== fieldLabel.value) {
431
+ props.updateAttributes({ fieldLabel: labelDraft.value.trim() });
432
+ }
189
433
  }
190
- function _startTextEdit() {
191
- textDraft.value = getStr(metaKey.value);
192
- editingText.value = true;
193
- nextTick(() => document.querySelector(".meta-text-input")?.focus());
434
+ const newOptionDraft = ref("");
435
+ function addOption(_multi) {
436
+ const val = newOptionDraft.value.trim();
437
+ if (!val || options.value.includes(val)) return;
438
+ const updated = [...options.value, val];
439
+ props.updateAttributes({ options: JSON.stringify(updated) });
440
+ newOptionDraft.value = "";
194
441
  }
195
- function _commitText() {
196
- patch({ [metaKey.value]: textDraft.value });
197
- editingText.value = false;
442
+ function removeOption(opt) {
443
+ const updated = options.value.filter((o) => o !== opt);
444
+ props.updateAttributes({ options: JSON.stringify(updated) });
198
445
  }
199
446
  </script>
200
447
 
201
448
  <template>
202
449
  <NodeViewWrapper
203
450
  as="span"
204
- class="inline-flex items-center"
451
+ class="meta-field-chip"
452
+ contenteditable="false"
453
+ :data-field-type="fieldType"
454
+ :class="{ 'pointer-events-none': !isEditable, 'meta-field-chip--dragging': isDragging }"
455
+ @mouseenter="isHovered = true"
456
+ @mouseleave="isHovered = false"
205
457
  >
206
- <!-- ── Chip wrapper ─────────────────────────────────────────────────────── -->
207
- <UPopover
208
- v-model:open="popoverOpen"
209
- :content="{ side: 'bottom', align: 'start' }"
458
+ <!-- Drag grip visible on hover, top-left -->
459
+ <span
460
+ v-if="isHovered && isEditable"
461
+ class="meta-field-grip absolute -top-2 -left-2 size-4 flex items-center justify-center rounded-full bg-(--ui-bg-elevated) border border-(--ui-border) z-10 cursor-grab active:cursor-grabbing select-none"
462
+ :title="t.dragToReorder"
463
+ @pointerdown="onGripPointerDown"
464
+ @click.stop
210
465
  >
211
- <button
212
- type="button"
213
- class="inline-flex items-center gap-1 rounded-md border border-default bg-muted px-2 py-0.5 text-xs font-medium text-default hover:bg-elevated cursor-pointer select-none mx-0.5"
214
- @mousedown.prevent
215
- @click="openEditor"
216
- >
217
- <!-- Color swatch for color fields -->
218
- <span
219
- v-if="chipColor"
220
- class="size-3 rounded-full border border-white/20 shrink-0"
221
- :style="`background: ${chipColor}`"
222
- />
223
-
224
- <!-- Label -->
225
- <span class="text-muted">{{ fieldLabel || fieldType }}</span>
226
-
227
- <span class="text-default">
228
- <!-- Toggle shows a switch icon -->
229
- <span v-if="fieldType === 'toggle'">
230
- <UIcon
231
- :name="getBool(metaKey) ? 'i-lucide-toggle-right' : 'i-lucide-toggle-left'"
232
- class="size-3.5 align-middle"
233
- />
234
- </span>
235
- <!-- Rating shows stars -->
236
- <span
237
- v-else-if="fieldType === 'rating'"
238
- class="flex gap-0.5"
466
+ <UIcon
467
+ name="i-lucide-grip-vertical"
468
+ class="size-3 text-(--ui-text-muted)"
469
+ />
470
+ </span>
471
+ <!-- ── datetimerange ─────────────────────────────────────────────────── -->
472
+ <template v-if="fieldType === 'datetimerange'">
473
+ <div class="flex items-center gap-1">
474
+ <UPopover
475
+ v-model:open="datetimerangePopoverOpen"
476
+ :content="{ align: 'start' }"
477
+ >
478
+ <UButton
479
+ size="sm"
480
+ color="neutral"
481
+ variant="ghost"
482
+ icon="i-lucide-calendar"
483
+ class="h-7 px-2.5 py-1 text-sm border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) data-[state=open]:bg-(--ui-bg-elevated)"
239
484
  >
240
- <UIcon
241
- v-for="i in sliderMax"
242
- :key="i"
243
- :name="i <= getNum(metaKey) ? 'i-lucide-star' : 'i-lucide-star'"
244
- :class="i <= getNum(metaKey) ? 'text-amber-400' : 'text-muted'"
245
- class="size-3"
246
- />
247
- </span>
248
- <!-- Everything else: text display -->
249
- <span v-else>{{ displayValue }}</span>
250
- </span>
485
+ {{ formatDateRange(startKey, endKey) }}
486
+ </UButton>
487
+ <template #content>
488
+ <div class="p-2">
489
+ <UCalendar
490
+ range
491
+ :model-value="getDateRange(startKey, endKey)"
492
+ @update:model-value="onDateTimeRange($event)"
493
+ />
494
+ <div
495
+ v-if="!getBool(allDayKey, true)"
496
+ class="flex items-center gap-2 pt-3 mt-3 border-t border-(--ui-border)"
497
+ >
498
+ <div class="flex-1">
499
+ <p class="text-xs font-medium text-(--ui-text-muted) mb-1">
500
+ {{ t.start }}
501
+ </p>
502
+ <UInputTime
503
+ size="sm"
504
+ :model-value="isoToTime(getStr(startKey).slice(11, 16) || '00:00')"
505
+ @update:model-value="onStartTime($event)"
506
+ />
507
+ </div>
508
+ <UIcon
509
+ name="i-lucide-arrow-right"
510
+ class="size-3 text-(--ui-text-dimmed) mt-4"
511
+ />
512
+ <div class="flex-1">
513
+ <p class="text-xs font-medium text-(--ui-text-muted) mb-1">
514
+ {{ t.end }}
515
+ </p>
516
+ <UInputTime
517
+ size="sm"
518
+ :model-value="isoToTime(getStr(endKey).slice(11, 16) || '01:00')"
519
+ @update:model-value="onEndTime($event)"
520
+ />
521
+ </div>
522
+ </div>
523
+ </div>
524
+ </template>
525
+ </UPopover>
251
526
 
252
- <!-- Delete button -->
253
527
  <UButton
254
- icon="i-lucide-x"
255
- size="xs"
528
+ size="sm"
529
+ :color="getBool(allDayKey, true) ? 'primary' : 'neutral'"
530
+ :variant="getBool(allDayKey, true) ? 'soft' : 'ghost'"
531
+ class="h-7 px-2.5 py-1 text-sm"
532
+ @click="toggleAllDay"
533
+ >
534
+ {{ t.allDay }}
535
+ </UButton>
536
+ </div>
537
+ </template>
538
+
539
+ <!-- ── daterange ─────────────────────────────────────────────────────── -->
540
+ <template v-else-if="fieldType === 'daterange'">
541
+ <UPopover
542
+ v-model:open="daterangePopoverOpen"
543
+ :content="{ align: 'start' }"
544
+ >
545
+ <UButton
546
+ size="sm"
256
547
  color="neutral"
257
548
  variant="ghost"
258
- class="size-3.5 p-0 opacity-50 hover:opacity-100 -mr-0.5"
259
- @click.stop="deleteChip"
260
- />
261
- </button>
262
-
263
- <!-- ── Popover content ─────────────────────────────────────────────── -->
264
- <template #content>
265
- <div class="p-2 min-w-48 max-w-xs space-y-2">
266
- <!-- Field label editor -->
267
- <div class="flex items-center gap-1 border-b border-default pb-2">
268
- <input
269
- v-model="labelDraft"
270
- :placeholder="fieldType"
271
- class="flex-1 text-xs font-medium bg-transparent border-none outline-none"
272
- @blur="commitLabel"
273
- @keydown.enter.prevent="commitLabel"
274
- >
275
- </div>
549
+ icon="i-lucide-calendar-range"
550
+ class="h-7 px-2.5 py-1 text-sm border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) data-[state=open]:bg-(--ui-bg-elevated)"
551
+ >
552
+ {{ formatDateRange(startKey, endKey) }}
553
+ </UButton>
554
+ <template #content>
555
+ <UCalendar
556
+ class="p-2"
557
+ range
558
+ :model-value="getDateRange(startKey, endKey)"
559
+ @update:model-value="onDateRange($event)"
560
+ />
561
+ </template>
562
+ </UPopover>
563
+ </template>
276
564
 
277
- <!-- ── Toggle ──────────────────────────────────────────────────── -->
278
- <div
279
- v-if="fieldType === 'toggle'"
280
- class="flex items-center justify-between"
565
+ <!-- ── slider ────────────────────────────────────────────────────────── -->
566
+ <template v-else-if="fieldType === 'slider'">
567
+ <!-- mousedown.stop prevents TipTap drag-handle from hijacking slider drags -->
568
+ <div
569
+ class="flex items-center gap-2 h-7 px-2.5 border border-(--ui-border) rounded-md text-sm"
570
+ @mousedown.stop
571
+ @touchstart.stop
572
+ @wheel.prevent="onSliderWheel"
573
+ >
574
+ <template v-if="fieldLabel">
575
+ <input
576
+ v-if="editingLabel"
577
+ ref="labelInputEl"
578
+ v-model="labelDraft"
579
+ class="text-(--ui-text-muted) shrink-0 text-xs bg-transparent border-b border-(--ui-border) outline-none w-20"
580
+ @blur="saveLabel"
581
+ @keydown.enter.prevent="saveLabel"
582
+ @keydown.escape.prevent="editingLabel = false"
583
+ @mousedown.stop
281
584
  >
282
- <span class="text-xs text-muted">{{ getBool(metaKey) ? "On" : "Off" }}</span>
283
- <USwitch
284
- :model-value="getBool(metaKey)"
285
- @update:model-value="(v) => patch({ [metaKey]: v })"
286
- />
287
- </div>
585
+ <span
586
+ v-else
587
+ class="text-(--ui-text-muted) shrink-0 text-xs cursor-text hover:text-(--ui-text)"
588
+ @click.stop="startEditLabel"
589
+ >{{ fieldLabel }}</span>
590
+ </template>
591
+ <USlider
592
+ size="sm"
593
+ class="w-24"
594
+ :min="sliderMin"
595
+ :max="sliderMax"
596
+ :model-value="getNum(metaKey)"
597
+ @update:model-value="onSlider($event)"
598
+ />
599
+ <span class="text-(--ui-text-muted) tabular-nums w-8 text-right shrink-0 text-xs">
600
+ {{ getNum(metaKey) }}%
601
+ </span>
602
+ </div>
603
+ </template>
288
604
 
289
- <!-- ── Color presets ───────────────────────────────────────────── -->
290
- <div
291
- v-else-if="fieldType === 'colorPreset'"
292
- class="flex flex-wrap gap-1.5"
293
- >
294
- <button
295
- v-for="c in allPresets"
296
- :key="c"
297
- class="size-5 rounded-full border-2 cursor-pointer"
298
- :style="`background: ${c}; border-color: ${getStr(metaKey) === c ? c : 'transparent'}`"
299
- :class="getStr(metaKey) === c ? 'ring-2 ring-offset-1 ring-current' : ''"
300
- @click="patch({ [metaKey]: getStr(metaKey) === c ? '' : c })"
301
- />
302
- <!-- Clear -->
303
- <button
304
- v-if="getStr(metaKey)"
305
- class="size-5 rounded-full border border-default flex items-center justify-center text-muted hover:bg-muted"
306
- @click="patch({ [metaKey]: '' })"
307
- >
308
- <UIcon
309
- name="i-lucide-x"
310
- class="size-3"
311
- />
312
- </button>
313
- </div>
605
+ <!-- ── colorPreset ───────────────────────────────────────────────────── -->
606
+ <template v-else-if="fieldType === 'colorPreset'">
607
+ <AColorPalettePopover
608
+ :model-value="getStr(metaKey)"
609
+ :open="colorPopoverOpen"
610
+ @update:model-value="onColor"
611
+ @update:open="colorPopoverOpen = $event"
612
+ >
613
+ <UButton
614
+ size="sm"
615
+ color="neutral"
616
+ variant="ghost"
617
+ class="h-7 px-2.5 py-1 text-sm border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) gap-1.5 data-[state=open]:bg-(--ui-bg-elevated)"
618
+ >
619
+ <span
620
+ class="size-3 rounded-full shrink-0 ring-1 ring-(--ui-border)"
621
+ :style="{ background: getStr(metaKey) || presets[0] }"
622
+ />
623
+ <span>{{ fieldLabel || t.color }}</span>
624
+ </UButton>
625
+ </AColorPalettePopover>
626
+ </template>
314
627
 
315
- <!-- ── Color picker ────────────────────────────────────────────── -->
316
- <div
317
- v-else-if="fieldType === 'colorPicker'"
318
- class="space-y-1"
628
+ <!-- ── location ──────────────────────────────────────────────────────── -->
629
+ <template v-else-if="fieldType === 'location'">
630
+ <ALocationPickerPopover
631
+ :lat-value="getOptNum(latKey)"
632
+ :lng-value="getOptNum(lngKey)"
633
+ :open="locationPopoverOpen"
634
+ @update:lat="(v) => onLatLng(latKey, v)"
635
+ @update:lng="(v) => onLatLng(lngKey, v)"
636
+ @update:open="locationPopoverOpen = $event"
637
+ @clear="() => {
638
+ onLatLng(latKey, null);
639
+ onLatLng(lngKey, null);
640
+ }"
641
+ >
642
+ <UButton
643
+ size="sm"
644
+ color="neutral"
645
+ variant="ghost"
646
+ :icon="getOptNum(latKey) !== void 0 ? 'i-lucide-map-pin' : 'i-lucide-map-pin-off'"
647
+ class="h-7 px-2.5 py-1 text-sm border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) gap-1.5 data-[state=open]:bg-(--ui-bg-elevated)"
648
+ >
649
+ <span
650
+ v-if="fieldLabel && getOptNum(latKey) === void 0"
651
+ class="text-(--ui-text-muted)"
652
+ >{{ fieldLabel }}</span>
653
+ <span
654
+ v-if="getOptNum(latKey) !== void 0"
655
+ class="tabular-nums"
319
656
  >
320
- <input
321
- type="color"
322
- :value="getStr(metaKey) || '#6366f1'"
323
- class="w-full h-8 rounded cursor-pointer"
324
- @input="(e) => patch({ [metaKey]: e.target.value })"
325
- >
326
- <UButton
327
- v-if="getStr(metaKey)"
328
- icon="i-lucide-x"
329
- size="xs"
330
- color="neutral"
331
- variant="ghost"
332
- label="Clear"
333
- class="w-full justify-start"
334
- @click="patch({ [metaKey]: '' })"
335
- />
336
- </div>
337
-
338
- <!-- ── Date ───────────────────────────────────────────────────── -->
339
- <div v-else-if="fieldType === 'date'">
340
- <input
341
- type="date"
342
- :value="getStr(metaKey)"
343
- class="w-full text-xs rounded border border-default bg-transparent px-2 py-1 outline-none"
344
- @change="(e) => patch({ [metaKey]: e.target.value })"
345
- >
346
- </div>
347
-
348
- <!-- ── Datetime ───────────────────────────────────────────────── -->
349
- <div v-else-if="fieldType === 'datetime'">
350
- <input
351
- type="datetime-local"
352
- :value="getStr(metaKey)"
353
- class="w-full text-xs rounded border border-default bg-transparent px-2 py-1 outline-none"
354
- @change="(e) => patch({ [metaKey]: e.target.value })"
355
- >
356
- </div>
657
+ {{ getOptNum(latKey).toFixed(4) }}, {{ getOptNum(lngKey).toFixed(4) }}
658
+ </span>
659
+ </UButton>
660
+ </ALocationPickerPopover>
661
+ </template>
357
662
 
358
- <!-- ── Date range ─────────────────────────────────────────────── -->
359
- <div
360
- v-else-if="fieldType === 'daterange'"
361
- class="space-y-1"
362
- >
363
- <div class="flex items-center gap-1 text-xs text-muted">
364
- <span class="w-8">Start</span><input
365
- type="date"
366
- :value="getStr(startKey)"
367
- class="flex-1 text-xs rounded border border-default bg-transparent px-2 py-1 outline-none"
368
- @change="(e) => patch({ [startKey]: e.target.value })"
369
- >
370
- </div>
371
- <div class="flex items-center gap-1 text-xs text-muted">
372
- <span class="w-8">End</span><input
373
- type="date"
374
- :value="getStr(endKey)"
375
- class="flex-1 text-xs rounded border border-default bg-transparent px-2 py-1 outline-none"
376
- @change="(e) => patch({ [endKey]: e.target.value })"
377
- >
378
- </div>
379
- </div>
663
+ <!-- ── icon ──────────────────────────────────────────────────────────── -->
664
+ <template v-else-if="fieldType === 'icon'">
665
+ <AIconPickerPopover
666
+ :model-value="getStr(metaKey)"
667
+ :open="iconPopoverOpen"
668
+ :options="iconOptions.length ? iconOptions : void 0"
669
+ @update:model-value="onIcon"
670
+ @update:open="iconPopoverOpen = $event"
671
+ >
672
+ <UButton
673
+ size="sm"
674
+ color="neutral"
675
+ variant="ghost"
676
+ class="h-7 px-2.5 py-1 text-sm border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) gap-1.5"
677
+ :icon="getStr(metaKey) ? `i-lucide-${getStr(metaKey)}` : 'i-lucide-smile'"
678
+ >
679
+ <span
680
+ v-if="fieldLabel && !getStr(metaKey)"
681
+ class="text-(--ui-text-muted)"
682
+ >{{ fieldLabel }}</span>
683
+ </UButton>
684
+ </AIconPickerPopover>
685
+ </template>
380
686
 
381
- <!-- ── Datetime range ─────────────────────────────────────────── -->
687
+ <!-- ── textarea ───────────────────────────────────────────────────────── -->
688
+ <template v-else-if="fieldType === 'textarea'">
689
+ <UPopover
690
+ v-model:open="textareaPopoverOpen"
691
+ :content="{ align: 'start' }"
692
+ >
693
+ <UButton
694
+ size="sm"
695
+ color="neutral"
696
+ variant="ghost"
697
+ icon="i-lucide-text"
698
+ class="h-7 px-2.5 py-1 text-sm border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) gap-1.5 data-[state=open]:bg-(--ui-bg-elevated)"
699
+ >
700
+ <span
701
+ v-if="fieldLabel"
702
+ class="text-(--ui-text-muted) text-xs"
703
+ >{{ fieldLabel }}</span>
704
+ <span
705
+ v-if="getStr(metaKey)"
706
+ class="max-w-48 truncate"
707
+ >{{ getStr(metaKey) }}</span>
708
+ </UButton>
709
+ <template #content>
382
710
  <div
383
- v-else-if="fieldType === 'datetimerange'"
384
- class="space-y-1"
711
+ class="w-72 p-2 flex flex-col gap-2"
712
+ @mousedown.stop
385
713
  >
386
- <div class="flex items-center gap-1 text-xs text-muted">
387
- <span class="w-8">Start</span><input
388
- type="datetime-local"
389
- :value="getStr(startKey)"
390
- class="flex-1 text-xs rounded border border-default bg-transparent px-2 py-1 outline-none"
391
- @change="(e) => patch({ [startKey]: e.target.value })"
392
- >
393
- </div>
394
- <div class="flex items-center gap-1 text-xs text-muted">
395
- <span class="w-8">End</span><input
396
- type="datetime-local"
397
- :value="getStr(endKey)"
398
- class="flex-1 text-xs rounded border border-default bg-transparent px-2 py-1 outline-none"
399
- @change="(e) => patch({ [endKey]: e.target.value })"
400
- >
401
- </div>
402
- <div class="flex items-center gap-2 text-xs">
403
- <USwitch
404
- :model-value="getBool(allDayKey)"
405
- @update:model-value="(v) => patch({ [allDayKey]: v })"
406
- /><span class="text-muted">All day</span>
407
- </div>
408
- </div>
409
-
410
- <!-- ── Time ───────────────────────────────────────────────────── -->
411
- <div v-else-if="fieldType === 'time' || fieldType === 'timerange'">
412
- <div class="space-y-1">
413
- <input
414
- type="time"
415
- :value="fieldType === 'time' ? getStr(metaKey) : getStr(startKey)"
416
- class="w-full text-xs rounded border border-default bg-transparent px-2 py-1 outline-none"
417
- @change="(e) => patch({ [fieldType === 'time' ? metaKey : startKey]: e.target.value })"
418
- >
714
+ <template v-if="fieldLabel">
419
715
  <input
420
- v-if="fieldType === 'timerange'"
421
- type="time"
422
- :value="getStr(endKey)"
423
- class="w-full text-xs rounded border border-default bg-transparent px-2 py-1 outline-none"
424
- @change="(e) => patch({ [endKey]: e.target.value })"
716
+ v-if="editingLabel"
717
+ ref="labelInputEl"
718
+ v-model="labelDraft"
719
+ class="text-xs text-(--ui-text-muted) bg-transparent border-b border-(--ui-border) outline-none w-32"
720
+ @blur="saveLabel"
721
+ @keydown.enter.prevent="saveLabel"
722
+ @keydown.escape.prevent="editingLabel = false"
723
+ @mousedown.stop
425
724
  >
426
- </div>
427
- </div>
428
-
429
- <!-- ── Slider ─────────────────────────────────────────────────── -->
430
- <div
431
- v-else-if="fieldType === 'slider'"
432
- class="space-y-1"
433
- >
434
- <div class="flex items-center gap-2">
435
- <USlider
436
- :model-value="getNum(metaKey, sliderMin)"
437
- :min="sliderMin"
438
- :max="sliderMax"
439
- :step="sliderStep"
440
- class="flex-1"
441
- @update:model-value="(v) => patch({ [metaKey]: v })"
442
- />
443
- <span class="text-xs w-10 text-right tabular-nums">{{ getNum(metaKey, sliderMin) }}</span>
444
- </div>
445
- <div class="flex justify-between text-xs text-muted">
446
- <span>{{ sliderMin }}</span><span>{{ sliderMax }}</span>
447
- </div>
448
- </div>
449
-
450
- <!-- ── Number ─────────────────────────────────────────────────── -->
451
- <div
452
- v-else-if="fieldType === 'number'"
453
- class="flex items-center gap-2"
454
- >
455
- <UInputNumber
456
- :model-value="getNum(metaKey)"
457
- :min="sliderMin"
458
- :max="sliderMax"
459
- :step="sliderStep"
460
- class="flex-1"
461
- size="xs"
725
+ <span
726
+ v-else
727
+ class="text-xs text-(--ui-text-muted) cursor-text hover:text-(--ui-text)"
728
+ @click.stop="startEditLabel"
729
+ >{{ fieldLabel }}</span>
730
+ </template>
731
+ <UTextarea
732
+ ref="textareaRef"
733
+ size="sm"
734
+ :model-value="getStr(metaKey)"
735
+ :rows="3"
736
+ class="w-full"
462
737
  @update:model-value="(v) => patch({ [metaKey]: v })"
738
+ @mousedown.stop
463
739
  />
464
- <span
465
- v-if="unit"
466
- class="text-xs text-muted"
467
- >{{ unit }}</span>
468
740
  </div>
741
+ </template>
742
+ </UPopover>
743
+ </template>
469
744
 
470
- <!-- ── Rating ─────────────────────────────────────────────────── -->
471
- <div
472
- v-else-if="fieldType === 'rating'"
473
- class="flex gap-1"
745
+ <!-- ── number ─────────────────────────────────────────────────────────── -->
746
+ <template v-else-if="fieldType === 'number'">
747
+ <div
748
+ class="flex items-center gap-1.5 h-7 px-2.5 border border-(--ui-border) rounded-md text-sm"
749
+ @mousedown.stop
750
+ @touchstart.stop
751
+ @wheel.prevent="onNumberWheel"
752
+ >
753
+ <template v-if="fieldLabel">
754
+ <input
755
+ v-if="editingLabel"
756
+ ref="labelInputEl"
757
+ v-model="labelDraft"
758
+ class="text-(--ui-text-muted) shrink-0 text-xs bg-transparent border-b border-(--ui-border) outline-none w-20"
759
+ @blur="saveLabel"
760
+ @keydown.enter.prevent="saveLabel"
761
+ @keydown.escape.prevent="editingLabel = false"
762
+ @mousedown.stop
474
763
  >
475
- <button
476
- v-for="i in sliderMax"
477
- :key="i"
478
- class="p-0.5 hover:scale-110 transition-transform"
479
- @click="patch({ [metaKey]: i === getNum(metaKey) ? 0 : i })"
480
- >
481
- <UIcon
482
- name="i-lucide-star"
483
- :class="i <= getNum(metaKey) ? 'text-amber-400' : 'text-muted'"
484
- class="size-5"
485
- />
486
- </button>
487
- </div>
764
+ <span
765
+ v-else
766
+ class="text-(--ui-text-muted) shrink-0 text-xs cursor-text hover:text-(--ui-text)"
767
+ @click.stop="startEditLabel"
768
+ >{{ fieldLabel }}</span>
769
+ </template>
770
+ <UInputNumber
771
+ size="xs"
772
+ :model-value="getOptNum(metaKey)"
773
+ :step="sliderStep"
774
+ class="max-w-32"
775
+ @update:model-value="onNumber"
776
+ />
777
+ <span
778
+ v-if="unit"
779
+ class="text-(--ui-text-muted) shrink-0 text-xs"
780
+ >{{ unit }}</span>
781
+ </div>
782
+ </template>
488
783
 
489
- <!-- ── Select ─────────────────────────────────────────────────── -->
784
+ <!-- ── toggle ─────────────────────────────────────────────────────────── -->
785
+ <template v-else-if="fieldType === 'toggle'">
786
+ <div class="flex items-center gap-2 h-7 px-2.5 border border-(--ui-border) rounded-md text-sm">
787
+ <template v-if="fieldLabel">
788
+ <input
789
+ v-if="editingLabel"
790
+ ref="labelInputEl"
791
+ v-model="labelDraft"
792
+ class="text-(--ui-text-muted) text-xs bg-transparent border-b border-(--ui-border) outline-none w-20"
793
+ @blur="saveLabel"
794
+ @keydown.enter.prevent="saveLabel"
795
+ @keydown.escape.prevent="editingLabel = false"
796
+ @mousedown.stop
797
+ >
798
+ <span
799
+ v-else
800
+ class="text-(--ui-text-muted) text-xs cursor-text hover:text-(--ui-text)"
801
+ @click.stop="startEditLabel"
802
+ >{{ fieldLabel }}</span>
803
+ </template>
804
+ <USwitch
805
+ size="sm"
806
+ :model-value="getBool(metaKey)"
807
+ @update:model-value="onToggle"
808
+ />
809
+ </div>
810
+ </template>
811
+
812
+ <!-- ── select ─────────────────────────────────────────────────────────── -->
813
+ <template v-else-if="fieldType === 'select'">
814
+ <UPopover
815
+ v-model:open="selectPopoverOpen"
816
+ :content="{ align: 'start' }"
817
+ >
818
+ <UButton
819
+ size="sm"
820
+ color="neutral"
821
+ variant="ghost"
822
+ icon="i-lucide-chevron-down"
823
+ trailing
824
+ class="h-7 px-2.5 border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) data-[state=open]:bg-(--ui-bg-elevated) min-w-28"
825
+ >
826
+ <span :class="getStr(metaKey) ? '' : 'text-(--ui-text-dimmed)'">
827
+ {{ getStr(metaKey) || fieldLabel || t.select }}
828
+ </span>
829
+ </UButton>
830
+ <template #content>
490
831
  <div
491
- v-else-if="fieldType === 'select'"
492
- class="space-y-1"
832
+ class="flex flex-col w-52"
833
+ @mousedown.stop
493
834
  >
494
- <button
835
+ <div
495
836
  v-for="opt in options"
496
837
  :key="opt"
497
- class="flex items-center gap-2 w-full px-2 py-1 rounded text-xs hover:bg-muted text-left"
498
- :class="getStr(metaKey) === opt ? 'bg-primary/10 text-primary' : ''"
499
- @click="toggleSelect(opt)"
838
+ class="flex items-center justify-between px-3 py-1.5 hover:bg-(--ui-bg-elevated) cursor-pointer group"
839
+ @click="onSelect(opt);
840
+ selectPopoverOpen = false"
500
841
  >
501
- <UIcon
502
- v-if="getStr(metaKey) === opt"
503
- name="i-lucide-check"
504
- class="size-3"
842
+ <div class="flex items-center gap-2">
843
+ <UIcon
844
+ v-if="getStr(metaKey) === opt"
845
+ name="i-lucide-check"
846
+ class="size-3.5 text-primary shrink-0"
847
+ />
848
+ <span
849
+ v-else
850
+ class="size-3.5 shrink-0"
851
+ />
852
+ <span class="text-sm">{{ opt }}</span>
853
+ </div>
854
+ <UTooltip
855
+ :text="t.removeOption"
856
+ :content="{ side: 'right' }"
857
+ >
858
+ <UButton
859
+ size="xs"
860
+ color="neutral"
861
+ variant="ghost"
862
+ icon="i-lucide-x"
863
+ class="size-5 p-0 opacity-0 group-hover:opacity-100 shrink-0"
864
+ @click.stop="removeOption(opt)"
865
+ />
866
+ </UTooltip>
867
+ </div>
868
+ <USeparator
869
+ v-if="options.length"
870
+ class="my-1"
871
+ />
872
+ <div class="px-2 py-1.5">
873
+ <UInput
874
+ v-model="newOptionDraft"
875
+ size="xs"
876
+ variant="none"
877
+ :placeholder="t.addOption"
878
+ icon="i-lucide-plus"
879
+ class="w-full"
880
+ @keydown.enter.prevent="addOption(false)"
505
881
  />
506
- <span :class="getStr(metaKey) === opt ? '' : 'ml-5'">{{ opt }}</span>
507
- </button>
508
- <div
509
- v-if="!options.length"
510
- class="text-xs text-muted px-2"
511
- >
512
- No options yet
513
882
  </div>
514
883
  </div>
884
+ </template>
885
+ </UPopover>
886
+ </template>
515
887
 
516
- <!-- ── Multi select ───────────────────────────────────────────── -->
888
+ <!-- ── multiselect ────────────────────────────────────────────────────── -->
889
+ <template v-else-if="fieldType === 'multiselect'">
890
+ <UPopover
891
+ v-model:open="multiSelectPopoverOpen"
892
+ :content="{ align: 'start' }"
893
+ >
894
+ <UButton
895
+ size="sm"
896
+ color="neutral"
897
+ variant="ghost"
898
+ icon="i-lucide-chevron-down"
899
+ trailing
900
+ class="h-7 px-2.5 border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) data-[state=open]:bg-(--ui-bg-elevated) min-w-28"
901
+ >
902
+ <span :class="getStrArr(metaKey).length ? '' : 'text-(--ui-text-dimmed)'">
903
+ {{ getStrArr(metaKey).length ? getStrArr(metaKey).join(", ") : fieldLabel || t.select }}
904
+ </span>
905
+ </UButton>
906
+ <template #content>
517
907
  <div
518
- v-else-if="fieldType === 'multiselect'"
519
- class="space-y-1"
908
+ class="flex flex-col w-52"
909
+ @mousedown.stop
520
910
  >
521
- <button
911
+ <div
522
912
  v-for="opt in options"
523
913
  :key="opt"
524
- class="flex items-center gap-2 w-full px-2 py-1 rounded text-xs hover:bg-muted text-left"
525
- :class="getStrArr(metaKey).includes(opt) ? 'bg-primary/10 text-primary' : ''"
526
- @click="toggleMultiSelect(opt)"
527
- >
528
- <UIcon
529
- :name="getStrArr(metaKey).includes(opt) ? 'i-lucide-check-square' : 'i-lucide-square'"
530
- class="size-3"
531
- />
532
- {{ opt }}
533
- </button>
534
- <div
535
- v-if="!options.length"
536
- class="text-xs text-muted px-2"
914
+ class="flex items-center justify-between px-3 py-1.5 hover:bg-(--ui-bg-elevated) cursor-pointer group"
915
+ @click="onMultiSelect(getStrArr(metaKey).includes(opt) ? getStrArr(metaKey).filter((v) => v !== opt) : [...getStrArr(metaKey), opt])"
537
916
  >
538
- No options yet
539
- </div>
540
- </div>
541
-
542
- <!-- ── Tags ───────────────────────────────────────────────────── -->
543
- <div
544
- v-else-if="fieldType === 'tags'"
545
- class="space-y-2"
546
- >
547
- <div class="flex flex-wrap gap-1">
548
- <span
549
- v-for="tag in getStrArr(metaKey)"
550
- :key="tag"
551
- class="inline-flex items-center gap-0.5 rounded-full bg-primary/10 text-primary px-2 py-0.5 text-xs"
917
+ <div class="flex items-center gap-2">
918
+ <UIcon
919
+ v-if="getStrArr(metaKey).includes(opt)"
920
+ name="i-lucide-check"
921
+ class="size-3.5 text-primary shrink-0"
922
+ />
923
+ <span
924
+ v-else
925
+ class="size-3.5 shrink-0"
926
+ />
927
+ <span class="text-sm">{{ opt }}</span>
928
+ </div>
929
+ <UTooltip
930
+ :text="t.removeOption"
931
+ :content="{ side: 'right' }"
552
932
  >
553
- {{ tag }}
554
- <button @click="toggleTag(tag)"><UIcon
555
- name="i-lucide-x"
556
- class="size-3"
557
- /></button>
558
- </span>
933
+ <UButton
934
+ size="xs"
935
+ color="neutral"
936
+ variant="ghost"
937
+ icon="i-lucide-x"
938
+ class="size-5 p-0 opacity-0 group-hover:opacity-100 shrink-0"
939
+ @click.stop="removeOption(opt)"
940
+ />
941
+ </UTooltip>
559
942
  </div>
560
- <div class="flex gap-1">
943
+ <USeparator
944
+ v-if="options.length"
945
+ class="my-1"
946
+ />
947
+ <div class="px-2 py-1.5">
561
948
  <UInput
562
- v-model="newOption"
563
- size="xs"
564
- placeholder="Add tag…"
565
- class="flex-1"
566
- @keydown.enter.prevent="() => {
567
- if (newOption.trim()) {
568
- toggleTag(newOption.trim());
569
- newOption = '';
570
- }
571
- }"
572
- />
573
- <UButton
949
+ v-model="newOptionDraft"
574
950
  size="xs"
951
+ variant="none"
952
+ :placeholder="t.addOption"
575
953
  icon="i-lucide-plus"
576
- @click="() => {
577
- if (newOption.trim()) {
578
- toggleTag(newOption.trim());
579
- newOption = '';
580
- }
581
- }"
954
+ class="w-full"
955
+ @keydown.enter.prevent="addOption(true)"
582
956
  />
583
957
  </div>
584
958
  </div>
959
+ </template>
960
+ </UPopover>
961
+ </template>
585
962
 
586
- <!-- ── URL ────────────────────────────────────────────────────── -->
587
- <div
588
- v-else-if="fieldType === 'url'"
589
- class="space-y-1"
963
+ <!-- ── url ────────────────────────────────────────────────────────────── -->
964
+ <template v-else-if="fieldType === 'url'">
965
+ <div
966
+ class="flex items-center gap-1 h-7 px-2.5 border border-(--ui-border) rounded-md text-sm"
967
+ @mousedown.stop
968
+ >
969
+ <UIcon
970
+ name="i-lucide-link"
971
+ class="size-3.5 shrink-0 text-(--ui-text-muted)"
972
+ />
973
+ <UInput
974
+ type="url"
975
+ size="xs"
976
+ variant="none"
977
+ class="flex-1 min-w-32"
978
+ :model-value="getStr(metaKey)"
979
+ :placeholder="fieldLabel || 'https://\u2026'"
980
+ @update:model-value="(v) => patch({ [metaKey]: v })"
981
+ />
982
+ </div>
983
+ </template>
984
+
985
+ <!-- ── rating ─────────────────────────────────────────────────────────── -->
986
+ <template v-else-if="fieldType === 'rating'">
987
+ <div class="inline-flex items-center gap-1.5 h-7 px-2">
988
+ <template v-if="fieldLabel">
989
+ <input
990
+ v-if="editingLabel"
991
+ ref="labelInputEl"
992
+ v-model="labelDraft"
993
+ class="text-(--ui-text-muted) text-xs bg-transparent border-b border-(--ui-border) outline-none w-20 leading-none"
994
+ @blur="saveLabel"
995
+ @keydown.enter.prevent="saveLabel"
996
+ @keydown.escape.prevent="editingLabel = false"
997
+ @mousedown.stop
590
998
  >
591
- <UInput
592
- :model-value="getStr(metaKey)"
593
- size="xs"
594
- placeholder="https://…"
595
- leading-icon="i-lucide-link"
596
- @update:model-value="(v) => patch({ [metaKey]: v })"
999
+ <span
1000
+ v-else
1001
+ class="text-(--ui-text-muted) text-xs leading-none cursor-text hover:text-(--ui-text)"
1002
+ @click.stop="startEditLabel"
1003
+ >{{ fieldLabel }}</span>
1004
+ </template>
1005
+ <div
1006
+ class="inline-flex items-center gap-0.5"
1007
+ @wheel.prevent="onRatingWheel"
1008
+ >
1009
+ <button
1010
+ v-for="i in sliderMax"
1011
+ :key="i"
1012
+ type="button"
1013
+ class="size-5 flex items-center justify-center rounded transition-colors hover:bg-(--ui-bg-elevated)"
1014
+ :class="getNum(metaKey) >= i ? 'text-amber-400' : 'text-(--ui-text-dimmed) opacity-40 hover:opacity-70'"
1015
+ @click="onRating(i)"
1016
+ >
1017
+ <UIcon
1018
+ name="i-lucide-star"
1019
+ class="size-3.5"
597
1020
  />
598
- <a
599
- v-if="getStr(metaKey)"
600
- :href="getStr(metaKey)"
601
- target="_blank"
602
- class="text-xs text-primary hover:underline flex items-center gap-1"
603
- >
604
- <UIcon
605
- name="i-lucide-external-link"
606
- class="size-3"
607
- />
608
- Open
609
- </a>
610
- </div>
1021
+ </button>
1022
+ </div>
1023
+ </div>
1024
+ </template>
611
1025
 
612
- <!-- ── Textarea ───────────────────────────────────────────────── -->
613
- <div v-else-if="fieldType === 'textarea'">
614
- <UTextarea
615
- :model-value="getStr(metaKey)"
616
- size="xs"
617
- :rows="3"
618
- placeholder="Add text…"
619
- @update:model-value="(v) => patch({ [metaKey]: v })"
1026
+ <!-- ── tags ───────────────────────────────────────────────────────────── -->
1027
+ <template v-else-if="fieldType === 'tags'">
1028
+ <UInputTags
1029
+ size="sm"
1030
+ :model-value="getStrArr(metaKey)"
1031
+ :placeholder="fieldLabel || t.addTag"
1032
+ class="min-h-7"
1033
+ @update:model-value="(v) => patch({ [metaKey]: v })"
1034
+ @mousedown.stop
1035
+ />
1036
+ </template>
1037
+
1038
+ <!-- ── colorPicker ────────────────────────────────────────────────────── -->
1039
+ <template v-else-if="fieldType === 'colorPicker'">
1040
+ <UPopover :content="{ align: 'start' }">
1041
+ <UButton
1042
+ size="sm"
1043
+ color="neutral"
1044
+ variant="ghost"
1045
+ class="h-7 px-2.5 border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) gap-1.5 data-[state=open]:bg-(--ui-bg-elevated)"
1046
+ >
1047
+ <span
1048
+ class="size-3 rounded-full shrink-0 ring-1 ring-(--ui-border)"
1049
+ :style="{ background: getStr(metaKey) || '#6366f1' }"
1050
+ />
1051
+ <span class="text-(--ui-text-muted) text-xs font-mono">{{ getStr(metaKey) || fieldLabel || t.color }}</span>
1052
+ </UButton>
1053
+ <template #content>
1054
+ <div class="p-3">
1055
+ <UColorPicker
1056
+ :model-value="getStr(metaKey) || '#6366f1'"
1057
+ format="hex"
1058
+ @update:model-value="(v) => {
1059
+ if (v) patch({ [metaKey]: v });
1060
+ }"
620
1061
  />
621
1062
  </div>
1063
+ </template>
1064
+ </UPopover>
1065
+ </template>
622
1066
 
623
- <!-- ── Location ───────────────────────────────────────────────── -->
624
- <div
625
- v-else-if="fieldType === 'location'"
626
- class="space-y-1"
627
- >
628
- <div class="flex items-center gap-1">
629
- <span class="text-xs text-muted w-7">Lat</span>
630
- <UInputNumber
631
- :model-value="getNum(props.node.attrs.latKey)"
632
- size="xs"
633
- class="flex-1"
634
- :step="1e-4"
635
- @update:model-value="(v) => patch({ [props.node.attrs.latKey]: v })"
636
- />
637
- </div>
638
- <div class="flex items-center gap-1">
639
- <span class="text-xs text-muted w-7">Lng</span>
640
- <UInputNumber
641
- :model-value="getNum(props.node.attrs.lngKey)"
642
- size="xs"
643
- class="flex-1"
644
- :step="1e-4"
645
- @update:model-value="(v) => patch({ [props.node.attrs.lngKey]: v })"
646
- />
647
- </div>
1067
+ <!-- ── datetime ───────────────────────────────────────────────────────── -->
1068
+ <template v-else-if="fieldType === 'datetime'">
1069
+ <UPopover
1070
+ v-model:open="datetimePopoverOpen"
1071
+ :content="{ align: 'start' }"
1072
+ >
1073
+ <UButton
1074
+ size="sm"
1075
+ color="neutral"
1076
+ variant="ghost"
1077
+ icon="i-lucide-calendar-clock"
1078
+ class="h-7 px-2.5 py-1 text-sm border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) data-[state=open]:bg-(--ui-bg-elevated)"
1079
+ @wheel.prevent="(e) => onDateWheel(e, metaKey)"
1080
+ >
1081
+ {{ getStr(metaKey) ? df.format(new Date(getStr(metaKey))) : fieldLabel || t.pickDatetime }}
1082
+ </UButton>
1083
+ <template #content>
1084
+ <div class="p-2 flex flex-col gap-2">
1085
+ <UCalendar
1086
+ :model-value="isoToCalendarDate(getStr(metaKey))"
1087
+ @update:model-value="onSingleDatetimeDate"
1088
+ />
1089
+ <UInputTime
1090
+ size="sm"
1091
+ :model-value="isoToTime(getStr(metaKey).slice(11, 16) || '00:00')"
1092
+ @update:model-value="(t2) => t2 && patch({ [metaKey]: `${getStr(metaKey).slice(0, 10) || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}T${timeToHHMM(t2)}:00.000Z` })"
1093
+ />
648
1094
  </div>
1095
+ </template>
1096
+ </UPopover>
1097
+ </template>
649
1098
 
650
- <!-- ── Icon ───────────────────────────────────────────────────── -->
651
- <div
652
- v-else-if="fieldType === 'icon'"
653
- class="space-y-1"
654
- >
655
- <AIconPicker
656
- :model-value="getStr(metaKey)"
657
- @update:model-value="(v) => patch({ [metaKey]: v })"
1099
+ <!-- ── date ───────────────────────────────────────────────────────────── -->
1100
+ <template v-else-if="fieldType === 'date'">
1101
+ <UPopover
1102
+ v-model:open="datePopoverOpen"
1103
+ :content="{ align: 'start' }"
1104
+ >
1105
+ <UButton
1106
+ size="sm"
1107
+ color="neutral"
1108
+ variant="ghost"
1109
+ icon="i-lucide-calendar"
1110
+ class="h-7 px-2.5 py-1 text-sm border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) data-[state=open]:bg-(--ui-bg-elevated)"
1111
+ @wheel.prevent="(e) => onDateWheel(e, metaKey)"
1112
+ >
1113
+ {{ getStr(metaKey) ? df.format(isoToCalendarDate(getStr(metaKey)).toDate(getLocalTimeZone())) : fieldLabel || t.pickDate }}
1114
+ </UButton>
1115
+ <template #content>
1116
+ <UCalendar
1117
+ class="p-2"
1118
+ :model-value="isoToCalendarDate(getStr(metaKey))"
1119
+ @update:model-value="onSingleDate"
1120
+ />
1121
+ </template>
1122
+ </UPopover>
1123
+ </template>
1124
+
1125
+ <!-- ── time ───────────────────────────────────────────────────────────── -->
1126
+ <template v-else-if="fieldType === 'time'">
1127
+ <UPopover
1128
+ v-model:open="timePopoverOpen"
1129
+ :content="{ align: 'start' }"
1130
+ >
1131
+ <UButton
1132
+ size="sm"
1133
+ color="neutral"
1134
+ variant="ghost"
1135
+ icon="i-lucide-clock"
1136
+ class="h-7 px-2.5 border border-(--ui-border) rounded-md hover:bg-(--ui-bg-elevated) data-[state=open]:bg-(--ui-bg-elevated)"
1137
+ @wheel.prevent="(e) => onTimeWheel(e, metaKey)"
1138
+ >
1139
+ {{ getStr(metaKey) || fieldLabel || t.pickTime }}
1140
+ </UButton>
1141
+ <template #content>
1142
+ <div class="p-3">
1143
+ <UInputTime
1144
+ size="sm"
1145
+ :model-value="isoToTime(getStr(metaKey) || '00:00')"
1146
+ @update:model-value="onSingleTime"
658
1147
  />
659
1148
  </div>
1149
+ </template>
1150
+ </UPopover>
1151
+ </template>
1152
+
1153
+ <!-- ── timerange ──────────────────────────────────────────────────────── -->
1154
+ <template v-else-if="fieldType === 'timerange'">
1155
+ <div
1156
+ class="flex items-center gap-2 h-7 px-2"
1157
+ @mousedown.stop
1158
+ @touchstart.stop
1159
+ >
1160
+ <template v-if="fieldLabel">
1161
+ <input
1162
+ v-if="editingLabel"
1163
+ ref="labelInputEl"
1164
+ v-model="labelDraft"
1165
+ class="text-(--ui-text-muted) text-xs shrink-0 bg-transparent border-b border-(--ui-border) outline-none w-20"
1166
+ @blur="saveLabel"
1167
+ @keydown.enter.prevent="saveLabel"
1168
+ @keydown.escape.prevent="editingLabel = false"
1169
+ @mousedown.stop
1170
+ >
1171
+ <span
1172
+ v-else
1173
+ class="text-(--ui-text-muted) text-xs shrink-0 cursor-text hover:text-(--ui-text)"
1174
+ @click.stop="startEditLabel"
1175
+ >{{ fieldLabel }}</span>
1176
+ </template>
1177
+ <UInputTime
1178
+ size="sm"
1179
+ :model-value="isoToTime(getStr(startKey) || '00:00')"
1180
+ @update:model-value="onTimeRangeStart"
1181
+ />
1182
+ <UIcon
1183
+ name="i-lucide-arrow-right"
1184
+ class="size-3 text-(--ui-text-dimmed) shrink-0"
1185
+ />
1186
+ <UInputTime
1187
+ size="sm"
1188
+ :model-value="isoToTime(getStr(endKey) || '01:00')"
1189
+ @update:model-value="onTimeRangeEnd"
1190
+ />
1191
+ </div>
1192
+ </template>
660
1193
 
661
- <!-- ── Members ──────────────────────────────────────────────── -->
1194
+ <!-- ── members ──────────────────────────────────────────────────────── -->
1195
+ <template v-else-if="fieldType === 'members'">
1196
+ <UPopover
1197
+ v-model:open="membersPopoverOpen"
1198
+ :content="{ align: 'start' }"
1199
+ >
1200
+ <div
1201
+ class="flex items-center gap-1 min-h-7 px-1.5 border border-(--ui-border) rounded-md cursor-pointer hover:bg-(--ui-bg-elevated)"
1202
+ @mousedown.stop
1203
+ >
1204
+ <template v-if="getObjArr(metaKey).length">
1205
+ <UTooltip
1206
+ v-for="m in getObjArr(metaKey)"
1207
+ :key="m.id"
1208
+ :text="m.label"
1209
+ >
1210
+ <UAvatar
1211
+ :alt="m.label"
1212
+ size="2xs"
1213
+ />
1214
+ </UTooltip>
1215
+ </template>
1216
+ <span
1217
+ v-else
1218
+ class="text-sm text-(--ui-text-dimmed) px-0.5"
1219
+ >{{ fieldLabel || t.members }}</span>
1220
+ <UIcon
1221
+ name="i-lucide-chevron-down"
1222
+ class="size-3.5 text-(--ui-text-dimmed) ml-1 shrink-0"
1223
+ />
1224
+ </div>
1225
+ <template #content>
662
1226
  <div
663
- v-else-if="fieldType === 'members'"
664
- class="space-y-1"
1227
+ class="flex flex-col w-56"
1228
+ @mousedown.stop
665
1229
  >
666
1230
  <UInput
667
1231
  v-model="memberSearch"
668
1232
  size="xs"
669
1233
  variant="none"
670
- placeholder="Search members…"
671
- leading-icon="i-lucide-search"
1234
+ :placeholder="t.searchMembers"
1235
+ icon="i-lucide-search"
1236
+ class="px-2 pt-2 pb-1"
672
1237
  />
673
- <USeparator />
674
- <div class="max-h-48 overflow-y-auto">
675
- <button
676
- v-for="user in filteredMentionItems"
677
- :key="user.id"
678
- class="flex items-center gap-2 w-full px-2 py-1.5 rounded text-xs hover:bg-muted text-left"
679
- @click="onToggleMember(user)"
680
- >
681
- <UIcon
682
- v-if="getObjArr(metaKey).some((m) => m.id === user.id)"
683
- name="i-lucide-check"
684
- class="size-3.5 text-primary shrink-0"
685
- />
686
- <span
687
- v-else
688
- class="size-3.5 shrink-0"
689
- />
690
- <UAvatar
691
- :alt="user.label"
692
- :style="user.avatar?.style"
693
- size="2xs"
694
- />
695
- <span class="truncate">{{ user.label }}</span>
696
- </button>
697
- <div
698
- v-if="!filteredMentionItems.length"
699
- class="px-2 py-2 text-xs text-muted"
700
- >
701
- No members found
702
- </div>
1238
+ <USeparator class="mb-1" />
1239
+ <div
1240
+ v-for="user in filteredMentionItems"
1241
+ :key="user.id"
1242
+ class="flex items-center gap-2 px-3 py-1.5 hover:bg-(--ui-bg-elevated) cursor-pointer"
1243
+ @click="onToggleMember(user)"
1244
+ >
1245
+ <UIcon
1246
+ v-if="getObjArr(metaKey).some((m2) => m2.id === user.id)"
1247
+ name="i-lucide-check"
1248
+ class="size-3.5 text-primary shrink-0"
1249
+ />
1250
+ <span
1251
+ v-else
1252
+ class="size-3.5 shrink-0"
1253
+ />
1254
+ <UAvatar
1255
+ :alt="user.label"
1256
+ :style="user.avatar?.style"
1257
+ size="2xs"
1258
+ />
1259
+ <span class="text-sm truncate">{{ user.label }}</span>
1260
+ </div>
1261
+ <div
1262
+ v-if="!filteredMentionItems.length"
1263
+ class="px-3 py-2 text-sm text-(--ui-text-dimmed)"
1264
+ >
1265
+ {{ t.noMembersFound }}
703
1266
  </div>
704
1267
  </div>
1268
+ </template>
1269
+ </UPopover>
1270
+ </template>
705
1271
 
706
- <!-- Fallback -->
707
- <div
708
- v-else
709
- class="text-xs text-muted"
710
- >
711
- {{ fieldType }}
712
- </div>
713
- </div>
714
- </template>
715
- </UPopover>
1272
+ <!-- ── Delete button ─────────────────────────────────────────────────── -->
1273
+ <UTooltip
1274
+ v-if="isHovered && isEditable"
1275
+ :text="t.deleteField"
1276
+ :content="{ side: 'top' }"
1277
+ >
1278
+ <UButton
1279
+ size="xs"
1280
+ color="neutral"
1281
+ variant="ghost"
1282
+ icon="i-lucide-x"
1283
+ class="absolute -top-2 -right-2 size-4 p-0 rounded-full bg-(--ui-bg-elevated) border border-(--ui-border) z-10"
1284
+ @click.stop="deleteField"
1285
+ />
1286
+ </UTooltip>
716
1287
  </NodeViewWrapper>
717
1288
  </template>
1289
+
1290
+ <style scoped>
1291
+ .meta-field-chip{align-items:center;display:inline-flex;position:relative;vertical-align:middle}.meta-field-chip--dragging{opacity:.5}
1292
+ </style>
1293
+
1294
+ <style>
1295
+ .meta-chip-flash{animation:meta-chip-flash .9s ease-out}@keyframes meta-chip-flash{0%,to{box-shadow:0 0 0 0 transparent}20%{box-shadow:0 0 0 3px var(--ui-primary,#6366f1)}}
1296
+ </style>