frappe-ui 1.0.0-beta.2 → 1.0.0-beta.21

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 (692) hide show
  1. package/experimental/FloatingWindow/FloatingWindow.cy.ts +328 -0
  2. package/experimental/FloatingWindow/FloatingWindow.vue +303 -0
  3. package/experimental/FloatingWindow/index.ts +8 -0
  4. package/experimental/FloatingWindow/types.ts +31 -0
  5. package/experimental/FloatingWindow/useFloatingWindow.ts +236 -0
  6. package/experimental/MultiEmailInput/MultiEmailInput.cy.ts +155 -0
  7. package/experimental/MultiEmailInput/MultiEmailInput.vue +472 -0
  8. package/experimental/MultiEmailInput/index.ts +17 -0
  9. package/experimental/MultiEmailInput/stories/AsyncSuggestions.vue +54 -0
  10. package/experimental/MultiEmailInput/stories/Basic.vue +18 -0
  11. package/experimental/MultiEmailInput/stories/CustomChip.vue +39 -0
  12. package/experimental/MultiEmailInput/stories/Labeling.vue +28 -0
  13. package/experimental/MultiEmailInput/types.ts +138 -0
  14. package/experimental/MultiEmailInput/utils.ts +60 -0
  15. package/experimental.ts +12 -0
  16. package/frappe/Billing/SignupBanner.vue +1 -1
  17. package/frappe/Billing/TrialBanner.vue +1 -1
  18. package/frappe/DataImport/DataImport.vue +1 -1
  19. package/frappe/DataImport/DataImportList.vue +1 -1
  20. package/frappe/DataImport/ImportSteps.vue +6 -6
  21. package/frappe/DataImport/MappingStep.vue +1 -1
  22. package/frappe/DataImport/PreviewStep.vue +9 -9
  23. package/frappe/DataImport/TemplateModal.vue +1 -1
  24. package/frappe/DataImport/UploadStep.vue +5 -5
  25. package/frappe/Filter/Filter.vue +1 -1
  26. package/frappe/Help/HelpModal.vue +1 -1
  27. package/frappe/Link/stories/Suffix.vue +2 -2
  28. package/frappe/Onboarding/GettingStartedBanner.vue +1 -1
  29. package/frappe/drive/components/AppSwitcher.vue +1 -1
  30. package/frappe/drive/components/InfoDialog.vue +3 -3
  31. package/frappe/drive/components/MoveDialog.vue +2 -2
  32. package/frappe/drive/components/Select/Select.vue +2 -2
  33. package/frappe/drive/components/ShareDialog.vue +1 -1
  34. package/frappe/telemetry/index.ts +88 -14
  35. package/frappe/telemetry/pulse.ts +78 -164
  36. package/frappe/telemetry/telemetry.test.ts +13 -79
  37. package/icons/IconPicker.vue +1 -1
  38. package/package.json +104 -34
  39. package/src/components/Alert/Alert.md +4 -0
  40. package/src/components/Alert/Alert.vue +4 -4
  41. package/src/components/Autocomplete/Autocomplete.vue +6 -6
  42. package/src/components/Avatar/Avatar.md +4 -0
  43. package/src/components/Avatar/Avatar.vue +23 -4
  44. package/src/components/Badge/Badge.api.md +1 -1
  45. package/src/components/Badge/Badge.cy.ts +34 -16
  46. package/src/components/Badge/Badge.md +20 -4
  47. package/src/components/Badge/Badge.vue +60 -45
  48. package/src/components/Badge/stories/CallMeta.vue +35 -0
  49. package/src/components/Badge/stories/EventStatus.vue +16 -0
  50. package/src/components/Badge/stories/ListStatus.vue +91 -0
  51. package/src/components/Badge/stories/Reactions.vue +33 -0
  52. package/src/components/Badge/stories/RowTags.vue +39 -0
  53. package/src/components/Badge/types.ts +1 -2
  54. package/src/components/BottomSheet/BottomSheet.api.md +57 -0
  55. package/src/components/BottomSheet/BottomSheet.vue +232 -0
  56. package/src/components/BottomSheet/index.ts +6 -0
  57. package/src/components/BottomSheet/types.ts +23 -0
  58. package/src/components/Breadcrumbs/Breadcrumbs.md +4 -0
  59. package/src/components/Breadcrumbs/Breadcrumbs.vue +3 -3
  60. package/src/components/Button/Button.api.md +37 -32
  61. package/src/components/Button/Button.cy.ts +18 -2
  62. package/src/components/Button/Button.md +20 -8
  63. package/src/components/Button/Button.vue +304 -284
  64. package/src/components/Button/stories/InlineActions.vue +10 -0
  65. package/src/components/Button/stories/LiveClassCard.vue +34 -0
  66. package/src/components/Button/stories/SectionAction.vue +17 -0
  67. package/src/components/Button/stories/SectionControls.vue +28 -0
  68. package/src/components/Button/stories/SelectionToolbar.vue +20 -0
  69. package/src/components/Button/stories/StackedActions.vue +10 -0
  70. package/src/components/Button/types.ts +38 -32
  71. package/src/components/Calendar/Calendar.api.md +16 -16
  72. package/src/components/Calendar/Calendar.vue +100 -73
  73. package/src/components/Calendar/CalendarDaily.vue +21 -20
  74. package/src/components/Calendar/CalendarMonthEvent.vue +30 -9
  75. package/src/components/Calendar/CalendarMonthly.vue +60 -39
  76. package/src/components/Calendar/CalendarTimeMarker.vue +9 -8
  77. package/src/components/Calendar/CalendarWeekDayEvent.vue +98 -42
  78. package/src/components/Calendar/CalendarWeekly.vue +77 -41
  79. package/src/components/Calendar/EventModalContent.vue +32 -16
  80. package/src/components/Calendar/NewEventModal.vue +19 -16
  81. package/src/components/Calendar/ShowMoreCalendarEvent.vue +11 -17
  82. package/src/components/Calendar/{calendarUtils.js → calendarUtils.ts} +76 -52
  83. package/src/components/Calendar/composables/{useCalendarData.js → useCalendarData.ts} +23 -11
  84. package/src/components/Calendar/composables/{useEventModal.js → useEventModal.ts} +16 -12
  85. package/src/components/Calendar/index.ts +12 -2
  86. package/src/components/Calendar/stories/CustomHeader.vue +1 -1
  87. package/src/components/Calendar/types.ts +106 -0
  88. package/src/components/Calendar/{useEventBase.js → useEventBase.ts} +40 -26
  89. package/src/components/Card.vue +2 -2
  90. package/src/components/Charts/ECharts.vue +1 -1
  91. package/src/components/Charts/NumberChart.vue +7 -7
  92. package/src/components/Charts/eChartOptions.ts +28 -13
  93. package/src/components/Checkbox/Checkbox.api.md +6 -0
  94. package/src/components/Checkbox/Checkbox.cy.ts +10 -2
  95. package/src/components/Checkbox/Checkbox.md +28 -0
  96. package/src/components/Checkbox/Checkbox.vue +9 -22
  97. package/src/components/Checkbox/stories/Group.vue +27 -0
  98. package/src/components/Checkbox/stories/HorizontalGroup.vue +24 -0
  99. package/src/components/Checkbox/stories/SettingRow.vue +23 -0
  100. package/src/components/Checkbox/stories/WithDescription.vue +27 -0
  101. package/src/components/Checkbox/types.ts +7 -0
  102. package/src/components/CodeEditor/CodeEditor.api.md +139 -0
  103. package/src/components/CodeEditor/CodeEditor.cy.ts +160 -0
  104. package/src/components/CodeEditor/CodeEditor.md +104 -0
  105. package/src/components/CodeEditor/CodeEditor.vue +556 -0
  106. package/src/components/CodeEditor/CodePreview.test.ts +49 -0
  107. package/src/components/CodeEditor/CodePreview.vue +45 -0
  108. package/src/components/CodeEditor/index.ts +17 -0
  109. package/src/components/CodeEditor/languages.ts +63 -0
  110. package/src/components/CodeEditor/stories/Default.vue +16 -0
  111. package/src/components/CodeEditor/stories/Labeling.vue +25 -0
  112. package/src/components/CodeEditor/stories/MaxHeight.vue +24 -0
  113. package/src/components/CodeEditor/stories/Preview.vue +36 -0
  114. package/src/components/CodeEditor/stories/Sizes.vue +15 -0
  115. package/src/components/CodeEditor/stories/Variants.vue +13 -0
  116. package/src/components/CodeEditor/theme.ts +272 -0
  117. package/src/components/CodeEditor/types.ts +69 -0
  118. package/src/components/Combobox/Combobox.api.md +19 -20
  119. package/src/components/Combobox/Combobox.cy.ts +54 -14
  120. package/src/components/Combobox/Combobox.md +4 -0
  121. package/src/components/Combobox/Combobox.vue +233 -247
  122. package/src/components/Combobox/ComboboxResults.vue +1 -1
  123. package/src/components/Combobox/stories/Clearable.vue +2 -2
  124. package/src/components/Combobox/stories/CreateNew.vue +1 -1
  125. package/src/components/Combobox/stories/Footer.vue +10 -2
  126. package/src/components/Combobox/stories/InDialog.vue +1 -1
  127. package/src/components/Combobox/types.ts +8 -29
  128. package/src/components/CommandPalette/CommandPaletteItem.vue +1 -1
  129. package/src/components/ContextMenu/ContextMenu.api.md +52 -0
  130. package/src/components/ContextMenu/ContextMenu.cy.ts +191 -0
  131. package/src/components/ContextMenu/ContextMenu.md +25 -0
  132. package/src/components/ContextMenu/ContextMenu.vue +106 -0
  133. package/src/components/ContextMenu/index.ts +2 -0
  134. package/src/components/ContextMenu/stories/FileList.vue +105 -0
  135. package/src/components/ContextMenu/stories/Groups.vue +95 -0
  136. package/src/components/ContextMenu/stories/Simple.vue +72 -0
  137. package/src/components/ContextMenu/types.ts +39 -0
  138. package/src/components/DatePicker/CalendarPanel.vue +128 -86
  139. package/src/components/DatePicker/DatePicker.vue +3 -9
  140. package/src/components/DatePicker/DateRangePicker.vue +4 -8
  141. package/src/components/DatePicker/DateTimePicker.cy.ts +4 -2
  142. package/src/components/DatePicker/DateTimePicker.vue +3 -9
  143. package/src/components/DatePicker/composables.ts +15 -37
  144. package/src/components/DatePicker/stories/Range.vue +1 -1
  145. package/src/components/DatePicker/types.ts +1 -1
  146. package/src/components/DesktopShell/DesktopShell.api.md +40 -0
  147. package/src/components/DesktopShell/DesktopShell.cy.ts +39 -0
  148. package/src/components/DesktopShell/DesktopShell.md +31 -0
  149. package/src/components/DesktopShell/DesktopShell.vue +81 -0
  150. package/src/components/DesktopShell/index.ts +3 -0
  151. package/src/components/DesktopShell/stories/Default.vue +97 -0
  152. package/src/components/DesktopShell/types.ts +2 -0
  153. package/src/components/Dialog/Dialog.api.md +7 -8
  154. package/src/components/Dialog/Dialog.md +4 -0
  155. package/src/components/Dialog/Dialog.vue +8 -7
  156. package/src/components/Dialog/stories/CommandPalette.vue +1 -1
  157. package/src/components/Dialog/stories/Wizard.vue +1 -1
  158. package/src/components/Dialogs.vue +11 -9
  159. package/src/components/Divider/Divider.api.md +1 -1
  160. package/src/components/Divider/Divider.md +4 -0
  161. package/src/components/Dropdown/Dropdown.api.md +10 -35
  162. package/src/components/Dropdown/Dropdown.md +10 -6
  163. package/src/components/Dropdown/Dropdown.vue +33 -47
  164. package/src/components/Dropdown/stories/{05_KebabMenu.vue → KebabMenu.vue} +3 -1
  165. package/src/components/Dropdown/stories/{06_UserMenu.vue → UserMenu.vue} +1 -1
  166. package/src/components/Dropdown/types.ts +25 -189
  167. package/src/components/Duration/Duration.api.md +92 -0
  168. package/src/components/Duration/Duration.cy.ts +183 -0
  169. package/src/components/Duration/Duration.md +98 -0
  170. package/src/components/Duration/Duration.vue +114 -0
  171. package/src/components/Duration/duration.ts +185 -0
  172. package/src/components/Duration/index.ts +8 -0
  173. package/src/components/Duration/stories/Default.vue +10 -0
  174. package/src/components/Duration/stories/Formats.vue +16 -0
  175. package/src/components/Duration/stories/RealWorld.vue +50 -0
  176. package/src/components/Duration/stories/Sizes.vue +15 -0
  177. package/src/components/Duration/stories/States.vue +21 -0
  178. package/src/components/Duration/types.ts +52 -0
  179. package/src/components/ErrorMessage/ErrorMessage.cy.ts +1 -1
  180. package/src/components/ErrorMessage/ErrorMessage.md +4 -0
  181. package/src/components/ErrorMessage/ErrorMessage.vue +1 -1
  182. package/src/components/FileUploader/FileUploader.api.md +36 -11
  183. package/src/components/FileUploader/FileUploader.cy.ts +66 -0
  184. package/src/components/FileUploader/FileUploader.md +4 -1
  185. package/src/components/FileUploader/FileUploader.vue +147 -106
  186. package/src/components/FileUploader/index.ts +6 -0
  187. package/src/components/FileUploader/types.ts +43 -0
  188. package/src/components/FormControl/FormControl.api.md +3 -4
  189. package/src/components/FormControl/FormControl.md +4 -0
  190. package/src/components/FormControl/stories/RealForm.vue +3 -3
  191. package/src/components/FormLabel.vue +5 -8
  192. package/src/components/HoverCard/HoverCard.api.md +100 -0
  193. package/src/components/HoverCard/HoverCard.cy.ts +103 -0
  194. package/src/components/HoverCard/HoverCard.md +52 -0
  195. package/src/components/HoverCard/HoverCard.vue +91 -0
  196. package/src/components/HoverCard/index.ts +2 -0
  197. package/src/components/HoverCard/stories/Arrow.vue +28 -0
  198. package/src/components/HoverCard/stories/Delays.vue +16 -0
  199. package/src/components/HoverCard/stories/Example.vue +28 -0
  200. package/src/components/HoverCard/types.ts +47 -0
  201. package/src/components/Icon/Icon.cy.ts +78 -0
  202. package/src/components/Icon/Icon.vue +50 -0
  203. package/src/components/Icon/index.ts +1 -0
  204. package/src/components/InputLabeling/InputDescription.vue +1 -1
  205. package/src/components/InputLabeling/InputError.vue +1 -1
  206. package/src/components/InputLabeling/InputLabel.vue +21 -7
  207. package/src/components/InputLabeling/RequiredIndicator.vue +1 -1
  208. package/src/components/ItemListRow/ItemListRow.vue +1 -1
  209. package/src/components/ItemListRow/stories/RowStates.vue +1 -1
  210. package/src/components/KeyboardShortcut.vue +4 -8
  211. package/src/components/KeyboardShortcutsModal/KeyboardShortcutsModal.api.md +22 -14
  212. package/src/components/KeyboardShortcutsModal/KeyboardShortcutsModal.vue +2 -2
  213. package/src/components/ListFilter/ListFilter.api.md +5 -6
  214. package/src/components/ListFilter/ListFilter.vue +161 -57
  215. package/src/components/ListFilter/NestedPopover.vue +17 -10
  216. package/src/components/ListFilter/SearchComplete.vue +31 -38
  217. package/src/components/ListItem.vue +1 -1
  218. package/src/components/ListView/ListEmptyState.vue +1 -1
  219. package/src/components/ListView/ListGroupHeader.vue +2 -2
  220. package/src/components/ListView/ListRow.vue +1 -1
  221. package/src/components/ListView/ListSelectBanner.vue +1 -1
  222. package/src/components/ListView/ListView.api.md +322 -6
  223. package/src/components/ListView/index.ts +25 -0
  224. package/src/components/ListView/stories/CustomList.vue +1 -1
  225. package/src/components/ListView/stories/GroupedRows.vue +1 -1
  226. package/src/components/LoadingIndicator.vue +13 -22
  227. package/src/components/LoadingText.vue +3 -13
  228. package/src/components/{Dropdown/DropdownMenuList.vue → Menu/Menu.vue} +110 -75
  229. package/src/components/{Dropdown/DropdownMenuItemContent.vue → Menu/MenuItemContent.vue} +23 -33
  230. package/src/components/{Dropdown/DropdownRenderContent.vue → Menu/MenuRenderContent.vue} +1 -1
  231. package/src/components/Menu/types.ts +225 -0
  232. package/src/components/{Dropdown → Menu}/utils.ts +36 -40
  233. package/src/components/MobileNav/MobileNav.api.md +70 -0
  234. package/src/components/MobileNav/MobileNav.cy.ts +89 -0
  235. package/src/components/MobileNav/MobileNav.md +34 -0
  236. package/src/components/MobileNav/MobileNav.vue +15 -0
  237. package/src/components/MobileNav/MobileNavItem.vue +125 -0
  238. package/src/components/MobileNav/index.ts +4 -0
  239. package/src/components/MobileNav/stories/Default.vue +40 -0
  240. package/src/components/MobileNav/types.ts +33 -0
  241. package/src/components/MobileShell/MobileShell.api.md +23 -0
  242. package/src/components/MobileShell/MobileShell.cy.ts +25 -0
  243. package/src/components/MobileShell/MobileShell.md +24 -0
  244. package/src/components/MobileShell/MobileShell.vue +41 -0
  245. package/src/components/MobileShell/index.ts +3 -0
  246. package/src/components/MobileShell/stories/Default.vue +75 -0
  247. package/src/components/MobileShell/types.ts +7 -0
  248. package/src/components/MonthPicker/MonthPicker.cy.ts +16 -0
  249. package/src/components/MonthPicker/MonthPicker.vue +19 -8
  250. package/src/components/MultiSelect/MultiSelect.api.md +3 -4
  251. package/src/components/MultiSelect/MultiSelect.md +42 -10
  252. package/src/components/MultiSelect/MultiSelect.vue +199 -227
  253. package/src/components/MultiSelect/MultiSelectResults.vue +1 -1
  254. package/src/components/MultiSelect/stories/Members.vue +1 -1
  255. package/src/components/MultiSelect/stories/TagsTrigger.vue +3 -3
  256. package/src/components/MultiSelect/types.ts +3 -3
  257. package/src/components/PageHeader/PageHeader.api.md +112 -0
  258. package/src/components/PageHeader/PageHeader.cy.ts +68 -0
  259. package/src/components/PageHeader/PageHeader.md +25 -0
  260. package/src/components/PageHeader/PageHeader.vue +13 -0
  261. package/src/components/PageHeader/PageHeaderBackButton.vue +29 -0
  262. package/src/components/PageHeader/PageHeaderBase.vue +51 -0
  263. package/src/components/PageHeader/PageHeaderMobile.vue +68 -0
  264. package/src/components/PageHeader/PageHeaderMobileTitle.vue +16 -0
  265. package/src/components/PageHeader/PageHeaderTarget.vue +13 -0
  266. package/src/components/PageHeader/PageHeaderTitle.vue +12 -0
  267. package/src/components/PageHeader/index.ts +7 -0
  268. package/src/components/PageHeader/stories/Default.vue +19 -0
  269. package/src/components/PageHeader/stories/Mobile.vue +24 -0
  270. package/src/components/PageHeader/target.ts +19 -0
  271. package/src/components/PageHeader/types.ts +19 -0
  272. package/src/components/Password/Password.md +4 -0
  273. package/src/components/Password/Password.vue +2 -2
  274. package/src/components/Popover/Popover.api.md +126 -42
  275. package/src/components/Popover/Popover.cy.ts +425 -41
  276. package/src/components/Popover/Popover.md +99 -4
  277. package/src/components/Popover/Popover.vue +288 -215
  278. package/src/components/Popover/index.ts +8 -1
  279. package/src/components/Popover/stories/Arrow.vue +16 -0
  280. package/src/components/Popover/stories/Bare.vue +20 -0
  281. package/src/components/Popover/stories/Click.vue +7 -4
  282. package/src/components/Popover/stories/Controlled.vue +22 -0
  283. package/src/components/Popover/stories/Dismissible.vue +19 -0
  284. package/src/components/Popover/stories/MatchTriggerWidth.vue +16 -0
  285. package/src/components/Popover/stories/SideAlign.vue +17 -0
  286. package/src/components/Popover/types.ts +101 -23
  287. package/src/components/Progress/Progress.cy.ts +2 -2
  288. package/src/components/Progress/Progress.md +4 -0
  289. package/src/components/Progress/Progress.vue +4 -4
  290. package/src/components/Rail/Rail.api.md +91 -0
  291. package/src/components/Rail/Rail.cy.ts +84 -0
  292. package/src/components/Rail/Rail.md +30 -0
  293. package/src/components/Rail/Rail.vue +16 -0
  294. package/src/components/Rail/RailItem.vue +134 -0
  295. package/src/components/Rail/RailItemBadge.vue +64 -0
  296. package/src/components/Rail/index.ts +2 -0
  297. package/src/components/Rail/stories/Default.vue +44 -0
  298. package/src/components/Rail/types.ts +37 -0
  299. package/src/components/Rating/Rating.md +4 -0
  300. package/src/components/Rating/Rating.vue +5 -8
  301. package/src/components/Rating/stories/CustomSlot.vue +2 -2
  302. package/src/components/ScrollArea/ScrollArea.api.md +59 -0
  303. package/src/components/ScrollArea/ScrollArea.vue +46 -0
  304. package/src/components/ScrollArea/ScrollBar.vue +101 -0
  305. package/src/components/ScrollArea/index.ts +2 -0
  306. package/src/components/Select/Select.cy.ts +16 -15
  307. package/src/components/Select/Select.md +4 -0
  308. package/src/components/Select/Select.vue +217 -203
  309. package/src/components/Select/stories/Example.vue +4 -3
  310. package/src/components/Select/stories/States.vue +1 -1
  311. package/src/components/Select/stories/TriggerSlots.vue +2 -2
  312. package/src/components/Select/utils.ts +4 -3
  313. package/src/components/SettingsDialog/SettingsBody.vue +23 -0
  314. package/src/components/SettingsDialog/SettingsContent.vue +7 -0
  315. package/src/components/SettingsDialog/SettingsDialog.api.md +273 -0
  316. package/src/components/SettingsDialog/SettingsDialog.cy.ts +126 -0
  317. package/src/components/SettingsDialog/SettingsDialog.md +43 -0
  318. package/src/components/SettingsDialog/SettingsDialog.vue +76 -0
  319. package/src/components/SettingsDialog/SettingsHeader.vue +36 -0
  320. package/src/components/SettingsDialog/SettingsNavGroup.vue +20 -0
  321. package/src/components/SettingsDialog/SettingsNavItem.vue +33 -0
  322. package/src/components/SettingsDialog/SettingsPanel.cy.ts +77 -0
  323. package/src/components/SettingsDialog/SettingsPanel.vue +26 -0
  324. package/src/components/SettingsDialog/SettingsRow.vue +52 -0
  325. package/src/components/SettingsDialog/SettingsSidebar.vue +16 -0
  326. package/src/components/SettingsDialog/index.ts +10 -0
  327. package/src/components/SettingsDialog/stories/Default.vue +99 -0
  328. package/src/components/SettingsDialog/stories/PanelBasic.vue +52 -0
  329. package/src/components/SettingsDialog/stories/panels/NotificationsPanel.vue +57 -0
  330. package/src/components/SettingsDialog/stories/panels/PreferencesPanel.vue +57 -0
  331. package/src/components/SettingsDialog/stories/panels/ProfilePanel.vue +38 -0
  332. package/src/components/SettingsDialog/stories/panels/UsersPanel.vue +83 -0
  333. package/src/components/SettingsDialog/types.ts +21 -0
  334. package/src/components/Sidebar/Sidebar.api.md +124 -65
  335. package/src/components/Sidebar/Sidebar.cy.ts +127 -76
  336. package/src/components/Sidebar/Sidebar.md +47 -3
  337. package/src/components/Sidebar/Sidebar.vue +64 -56
  338. package/src/components/Sidebar/SidebarCollapseToggle.vue +23 -0
  339. package/src/components/Sidebar/SidebarHeader.vue +76 -52
  340. package/src/components/Sidebar/SidebarItem.vue +159 -95
  341. package/src/components/Sidebar/SidebarItemIcon.vue +25 -0
  342. package/src/components/Sidebar/SidebarLabel.vue +34 -0
  343. package/src/components/Sidebar/SidebarSection.vue +29 -14
  344. package/src/components/Sidebar/index.ts +13 -2
  345. package/src/components/Sidebar/stories/Collapsed.vue +40 -0
  346. package/src/components/Sidebar/stories/Default.vue +153 -0
  347. package/src/components/Sidebar/stories/Legacy.vue +36 -0
  348. package/src/components/Sidebar/types.ts +105 -20
  349. package/src/components/Skeleton/Skeleton.cy.ts +21 -0
  350. package/src/components/Skeleton/Skeleton.md +21 -0
  351. package/src/components/Skeleton/Skeleton.vue +6 -0
  352. package/src/components/Skeleton/index.ts +1 -0
  353. package/src/components/Skeleton/stories/Card.vue +12 -0
  354. package/src/components/Skeleton/stories/List.vue +15 -0
  355. package/src/components/Skeleton/stories/Text.vue +11 -0
  356. package/src/components/Slider/Slider.api.md +1 -1
  357. package/src/components/Slider/Slider.cy.ts +29 -0
  358. package/src/components/Slider/Slider.md +10 -0
  359. package/src/components/Slider/Slider.vue +37 -9
  360. package/src/components/Slider/stories/NegativeValues.vue +12 -0
  361. package/src/components/Slider/types.ts +1 -1
  362. package/src/components/Spinner/Spinner.api.md +32 -0
  363. package/src/components/Spinner/Spinner.cy.ts +87 -0
  364. package/src/components/Spinner/Spinner.md +21 -0
  365. package/src/components/Spinner/Spinner.vue +168 -0
  366. package/src/components/Spinner/index.ts +2 -0
  367. package/src/components/Spinner/stories/InContext.vue +49 -0
  368. package/src/components/Spinner/stories/Sizes.vue +12 -0
  369. package/src/components/Spinner/stories/Themes.vue +10 -0
  370. package/src/components/Spinner/stories/Track.vue +12 -0
  371. package/src/components/Spinner/types.ts +14 -0
  372. package/src/components/Switch/Switch.md +4 -0
  373. package/src/components/Switch/Switch.vue +6 -23
  374. package/src/components/TabButtons/Pill.vue +161 -0
  375. package/src/components/TabButtons/TabButtons.api.md +52 -2
  376. package/src/components/TabButtons/TabButtons.cy.ts +18 -5
  377. package/src/components/TabButtons/TabButtons.md +49 -0
  378. package/src/components/TabButtons/TabButtons.vue +207 -109
  379. package/src/components/TabButtons/index.ts +11 -1
  380. package/src/components/TabButtons/pillTypes.ts +43 -0
  381. package/src/components/TabButtons/stories/PrefixSuffix.vue +65 -0
  382. package/src/components/TabButtons/stories/Sizes.vue +26 -0
  383. package/src/components/TabButtons/stories/Variants.vue +40 -0
  384. package/src/components/TabButtons/stories/Vertical.vue +64 -0
  385. package/src/components/TabButtons/types.ts +49 -0
  386. package/src/components/Tabs/Tabs.md +4 -0
  387. package/src/components/Tabs/Tabs.vue +1 -1
  388. package/src/components/TextEditor/TextEditor.cy.ts +1 -1
  389. package/src/components/TextEditor/TextEditor.md +3 -0
  390. package/src/components/TextEditor/TextEditor.vue +7 -4
  391. package/src/components/TextEditor/components/CodeBlockComponent.vue +4 -194
  392. package/src/components/TextEditor/components/FontColor.vue +1 -1
  393. package/src/components/TextEditor/components/LinkPopup.vue +1 -1
  394. package/src/components/TextEditor/components/MediaNodeView.vue +17 -17
  395. package/src/components/TextEditor/components/MentionList.vue +1 -1
  396. package/src/components/TextEditor/components/TextEditorBubbleMenu.vue +14 -5
  397. package/src/components/TextEditor/components/TextEditorFixedMenu.vue +3 -3
  398. package/src/components/TextEditor/components/{Menu.vue → TextEditorMenu.vue} +3 -3
  399. package/src/components/TextEditor/extensions/iframe/InsertIframe.vue +2 -2
  400. package/src/components/TextEditor/extensions/iframe/iframe-extension.ts +62 -19
  401. package/src/components/TextEditor/extensions/image-group/ImageGroupNodeView.vue +1 -1
  402. package/src/components/TextEditor/extensions/image-group/ImageGroupUploadDialog.vue +4 -4
  403. package/src/components/TextEditor/extensions/suggestion/SuggestionList.vue +1 -1
  404. package/src/components/TextEditor/extensions/toc-node/TocNodeView.vue +1 -1
  405. package/src/components/TextEditor/hljs-github.css +197 -0
  406. package/src/components/TextEditor/index.ts +13 -0
  407. package/src/components/TextInput/TextInput.cy.ts +8 -3
  408. package/src/components/TextInput/TextInput.md +4 -0
  409. package/src/components/TextInput/TextInput.vue +11 -15
  410. package/src/components/TextInput/stories/Slots.vue +1 -1
  411. package/src/components/Textarea/Textarea.cy.ts +1 -1
  412. package/src/components/Textarea/Textarea.md +4 -0
  413. package/src/components/Textarea/Textarea.vue +11 -15
  414. package/src/components/ThemeSwitcher/ThemePreview.vue +74 -0
  415. package/src/components/ThemeSwitcher/ThemeSwitcher.api.md +82 -0
  416. package/src/components/ThemeSwitcher/ThemeSwitcher.cy.ts +101 -0
  417. package/src/components/ThemeSwitcher/ThemeSwitcher.md +70 -0
  418. package/src/components/ThemeSwitcher/ThemeSwitcher.vue +145 -0
  419. package/src/components/ThemeSwitcher/index.ts +2 -0
  420. package/src/components/ThemeSwitcher/previews/PreviewWindow.vue +74 -0
  421. package/src/components/ThemeSwitcher/stories/Branded.vue +12 -0
  422. package/src/components/ThemeSwitcher/stories/Default.vue +7 -0
  423. package/src/components/ThemeSwitcher/stories/Menu.vue +53 -0
  424. package/src/components/ThemeSwitcher/stories/Toggle.vue +25 -0
  425. package/src/components/ThemeSwitcher/types.ts +35 -0
  426. package/src/components/TimePicker/TimePicker.api.md +67 -15
  427. package/src/components/TimePicker/TimePicker.cy.ts +130 -14
  428. package/src/components/TimePicker/TimePicker.md +6 -0
  429. package/src/components/TimePicker/TimePicker.vue +74 -19
  430. package/src/components/TimePicker/stories/Labeling.vue +21 -0
  431. package/src/components/TimePicker/stories/Range.vue +1 -1
  432. package/src/components/TimePicker/stories/SizesAndVariants.vue +23 -0
  433. package/src/components/TimePicker/stories/TwentyFour.vue +1 -1
  434. package/src/components/TimePicker/types.ts +15 -3
  435. package/src/components/TimePicker/utils.ts +82 -21
  436. package/src/components/Toast/Toast.md +1 -1
  437. package/src/components/Toast/Toast.sanitize.test.ts +50 -0
  438. package/src/components/Toast/Toast.test.ts +5 -0
  439. package/src/components/Toast/Toast.vue +7 -7
  440. package/src/components/Toast/ToastProvider.vue +18 -9
  441. package/src/components/Toast/stories/CustomIcon.vue +1 -1
  442. package/src/components/Toast/toast.ts +32 -8
  443. package/src/components/Tooltip/Tooltip.api.md +43 -5
  444. package/src/components/Tooltip/Tooltip.cy.ts +48 -0
  445. package/src/components/Tooltip/Tooltip.md +10 -0
  446. package/src/components/Tooltip/Tooltip.vue +20 -5
  447. package/src/components/Tooltip/TooltipBubble.vue +2 -2
  448. package/src/components/Tooltip/TooltipProvider.vue +53 -0
  449. package/src/components/Tooltip/index.ts +1 -0
  450. package/src/components/Tooltip/stories/Group.vue +22 -0
  451. package/src/components/Tooltip/stories/Slots.vue +2 -2
  452. package/src/components/Tooltip/types.ts +1 -1
  453. package/src/components/Tree/Tree.api.md +76 -18
  454. package/src/components/Tree/Tree.md +144 -2
  455. package/src/components/Tree/Tree.vue +276 -97
  456. package/src/components/Tree/TreeItem.vue +263 -0
  457. package/src/components/Tree/index.ts +9 -1
  458. package/src/components/Tree/stories/DragDrop.vue +94 -0
  459. package/src/components/Tree/stories/Example.vue +11 -34
  460. package/src/components/Tree/stories/ExpandAll.vue +48 -0
  461. package/src/components/Tree/stories/Guides.vue +49 -0
  462. package/src/components/Tree/stories/ListView.vue +74 -0
  463. package/src/components/Tree/tree.cy.ts +218 -90
  464. package/src/components/Tree/types.ts +114 -24
  465. package/src/components/Tree/useTreeDragDrop.ts +203 -0
  466. package/src/components/Tree/useTreeKeyboard.ts +109 -0
  467. package/src/components/VueGridLayout/Layout.vue +1 -1
  468. package/src/components/shared/picker/PickerShell.vue +20 -15
  469. package/src/components/shared/popover/PopoverPanel.vue +67 -0
  470. package/src/components/shared/popover/popoverPanel.css +102 -0
  471. package/src/components/shared/selection/utils.ts +6 -6
  472. package/src/composables/useAutofocusOnOpen.ts +2 -0
  473. package/src/composables/useScreenSize.ts +46 -0
  474. package/src/composables/useScrollContainer.ts +108 -0
  475. package/src/composables/useShortcut.ts +3 -0
  476. package/src/data-fetching/docStore.test.ts +74 -0
  477. package/src/data-fetching/docStore.ts +18 -7
  478. package/src/data-fetching/useCall/types.ts +1 -0
  479. package/src/data-fetching/useCall/useCall.test.ts +43 -0
  480. package/src/data-fetching/useCall/useCall.ts +17 -4
  481. package/src/data-fetching/useDoc/useDoc.test.ts +61 -2
  482. package/src/data-fetching/useDoc/useDoc.ts +35 -15
  483. package/src/data-fetching/useDoctype/useDoctype.ts +6 -5
  484. package/src/data-fetching/useFrappeFetch.ts +17 -4
  485. package/src/data-fetching/useList/types.ts +1 -0
  486. package/src/data-fetching/useList/useList.test.ts +40 -0
  487. package/src/data-fetching/useList/useList.ts +20 -13
  488. package/src/data-fetching/useNewDoc/useNewDoc.ts +9 -5
  489. package/src/directives/focus.ts +3 -3
  490. package/src/index.ts +105 -74
  491. package/src/mocks/handlers.ts +8 -0
  492. package/src/molecules/editor/Editor.cy.ts +6 -1
  493. package/src/molecules/editor/EditorBubbleMenu.vue +1 -1
  494. package/src/molecules/editor/EditorContent.vue +50 -9
  495. package/src/molecules/editor/EditorFixedMenu.vue +2 -1
  496. package/src/molecules/editor/EditorFloatingMenu.vue +1 -1
  497. package/src/molecules/editor/EditorTableMenu.vue +303 -0
  498. package/src/molecules/editor/MenuItems.vue +81 -69
  499. package/src/molecules/editor/commands.ts +10 -2
  500. package/src/molecules/editor/components/AttachmentNodeView.vue +115 -0
  501. package/src/molecules/editor/components/EditorDropZone.vue +105 -0
  502. package/src/molecules/editor/components/EditorPopover.vue +89 -0
  503. package/src/molecules/editor/components/MediaNodeView.vue +156 -49
  504. package/src/molecules/editor/components/MediaResizeHandles.vue +38 -0
  505. package/src/molecules/editor/components/MediaToolbar.vue +108 -54
  506. package/src/molecules/editor/components/TableContextMenu.vue +144 -0
  507. package/src/molecules/editor/components/UploadProgressIndicator.vue +33 -0
  508. package/src/molecules/editor/components/VideoControls.vue +208 -0
  509. package/src/molecules/editor/components/font-color/ColorSwatchGrid.vue +3 -5
  510. package/src/molecules/editor/components/font-color/fontColorController.ts +28 -23
  511. package/src/molecules/editor/components/font-color/swatches.ts +1 -1
  512. package/src/molecules/editor/components/media-node-view-controller.ts +4 -4
  513. package/src/molecules/editor/components/media-node-view-utils.test.ts +0 -13
  514. package/src/molecules/editor/components/media-node-view-utils.ts +0 -10
  515. package/src/molecules/editor/components/table-color/tableCellColorController.ts +80 -0
  516. package/src/molecules/editor/components/table-size-picker/TableSizePicker.vue +92 -0
  517. package/src/molecules/editor/components/table-size-picker/tableSizePickerController.ts +40 -0
  518. package/src/molecules/editor/composables/useEditorFileDrop.ts +117 -0
  519. package/src/molecules/editor/composables/useFloatingPopup.ts +46 -2
  520. package/src/molecules/editor/composables/useNodeViewResize.test.ts +60 -11
  521. package/src/molecules/editor/composables/useNodeViewResize.ts +80 -21
  522. package/src/molecules/editor/composables/useTableCellColorState.ts +78 -0
  523. package/src/molecules/editor/composables/useWindowFileDragging.ts +68 -0
  524. package/src/molecules/editor/extensions/attachment/attachment-engine.ts +250 -0
  525. package/src/molecules/editor/extensions/attachment/attachment-extension.ts +248 -0
  526. package/src/molecules/editor/extensions/attachment/attachment.flow.test.ts +80 -0
  527. package/src/molecules/editor/extensions/attachment/attachment.roundtrip.test.ts +50 -0
  528. package/src/molecules/editor/extensions/attachment/index.ts +5 -0
  529. package/src/molecules/editor/extensions/code-block/CodeBlockComponent.css +16 -26
  530. package/src/molecules/editor/extensions/code-block/CodeBlockComponent.vue +107 -22
  531. package/src/molecules/editor/extensions/content-paste/content-paste-extension.ts +5 -3
  532. package/src/molecules/editor/extensions/iframe/IframeInsertDialog.vue +34 -7
  533. package/src/molecules/editor/extensions/iframe/IframeNodeView.vue +54 -48
  534. package/src/molecules/editor/extensions/iframe/iframe-allowlist.ts +33 -4
  535. package/src/molecules/editor/extensions/iframe/iframe-commands.ts +49 -5
  536. package/src/molecules/editor/extensions/iframe/iframe-embed-utils.ts +30 -0
  537. package/src/molecules/editor/extensions/iframe/iframe-extension.ts +4 -4
  538. package/src/molecules/editor/extensions/iframe/iframeInsertDialogController.ts +12 -1
  539. package/src/molecules/editor/extensions/iframe/index.ts +4 -4
  540. package/src/molecules/editor/extensions/iframe/useIframeDialog.ts +25 -13
  541. package/src/molecules/editor/extensions/image/image-extension.ts +29 -11
  542. package/src/molecules/editor/extensions/image-group/ImageGroupGrid.vue +27 -11
  543. package/src/molecules/editor/extensions/image-group/ImageGroupGridCell.vue +55 -11
  544. package/src/molecules/editor/extensions/image-group/ImageGroupNodeView.vue +64 -31
  545. package/src/molecules/editor/extensions/image-group/ImageGroupUploadDialog.vue +84 -40
  546. package/src/molecules/editor/extensions/image-group/image-group-extension.ts +4 -3
  547. package/src/molecules/editor/extensions/image-group/useImageGroupDialog.ts +116 -17
  548. package/src/molecules/editor/extensions/link/LinkEditorPopup.vue +214 -71
  549. package/src/molecules/editor/extensions/link/link-click-plugin.ts +10 -15
  550. package/src/molecules/editor/extensions/link/link-commands.ts +24 -3
  551. package/src/molecules/editor/extensions/link/link-extension.ts +11 -2
  552. package/src/molecules/editor/extensions/link/link-popup-controller.test.ts +49 -0
  553. package/src/molecules/editor/extensions/link/link-popup-controller.ts +67 -2
  554. package/src/molecules/editor/extensions/link/link-shortcut-plugin.ts +7 -2
  555. package/src/molecules/editor/extensions/media-drop/media-drop-extension.ts +177 -0
  556. package/src/molecules/editor/extensions/shared/media-dimensions.ts +36 -3
  557. package/src/molecules/editor/extensions/shared/media-node-ops.ts +17 -0
  558. package/src/molecules/editor/extensions/shared/media-plugin.test.ts +60 -0
  559. package/src/molecules/editor/extensions/shared/media-plugin.ts +7 -37
  560. package/src/molecules/editor/extensions/shared/media-upload-engine.test.ts +39 -2
  561. package/src/molecules/editor/extensions/shared/media-upload-engine.ts +104 -10
  562. package/src/molecules/editor/extensions/shared/media-upload-state.ts +55 -0
  563. package/src/molecules/editor/extensions/shared/media-upload-types.ts +52 -1
  564. package/src/molecules/editor/extensions/shared/suggestion-helpers.ts +20 -0
  565. package/src/molecules/editor/extensions/shared/suggestion-types.ts +7 -0
  566. package/src/molecules/editor/extensions/shared/upload-types.ts +1 -0
  567. package/src/molecules/editor/extensions/slash-commands/slash-commands-extension.test.ts +38 -0
  568. package/src/molecules/editor/extensions/slash-commands/slash-commands-extension.ts +119 -55
  569. package/src/molecules/editor/extensions/suggestion/SuggestionList.vue +62 -22
  570. package/src/molecules/editor/extensions/suggestion/SuggestionListItem.vue +1 -1
  571. package/src/molecules/editor/extensions/suggestion/createSuggestionExtension.ts +4 -0
  572. package/src/molecules/editor/extensions/table/drag-scroll.ts +154 -0
  573. package/src/molecules/editor/extensions/table/table-cell-color.ts +188 -0
  574. package/src/molecules/editor/extensions/table/table-navigation.ts +560 -0
  575. package/src/molecules/editor/extensions/table/table-selection-overlay.ts +137 -0
  576. package/src/molecules/editor/extensions/toc-node/TocNodeView.vue +1 -1
  577. package/src/molecules/editor/extensions/toc-node/toc-render.ts +7 -3
  578. package/src/molecules/editor/extensions/video/video-extension.ts +72 -5
  579. package/src/molecules/editor/extensions.ts +176 -8
  580. package/src/molecules/editor/index.ts +9 -4
  581. package/src/molecules/editor/kits.test.ts +21 -1
  582. package/src/molecules/editor/kits.ts +56 -33
  583. package/src/molecules/editor/menu.test.ts +3 -1
  584. package/src/molecules/editor/menu.ts +180 -18
  585. package/src/molecules/editor/stories/Comment.vue +4 -4
  586. package/src/molecules/editor/stories/Inline.vue +1 -1
  587. package/src/molecules/editor/stories/Primitives.vue +1 -1
  588. package/src/molecules/editor/stories/RichText.vue +1 -1
  589. package/src/molecules/editor/style.css +80 -3
  590. package/src/molecules/editor/useEditor.test.ts +4 -0
  591. package/src/molecules/editor/useEditor.ts +7 -3
  592. package/src/molecules/list/List.cy.ts +626 -0
  593. package/src/molecules/list/List.vue +93 -0
  594. package/src/molecules/list/ListCell.vue +15 -0
  595. package/src/molecules/list/ListGroup.vue +40 -0
  596. package/src/molecules/list/ListHeader.vue +62 -0
  597. package/src/molecules/list/ListHeaderCell.vue +26 -0
  598. package/src/molecules/list/ListHeaderCellSort.vue +106 -0
  599. package/src/molecules/list/ListRow.vue +55 -0
  600. package/src/molecules/list/ListRowBase.vue +103 -0
  601. package/src/molecules/list/ListRows.vue +120 -0
  602. package/src/molecules/list/index.ts +24 -0
  603. package/src/molecules/list/list-context.ts +44 -0
  604. package/src/molecules/list/list.api.md +276 -0
  605. package/src/molecules/list/list.md +119 -0
  606. package/src/molecules/list/stories/Columns.vue +103 -0
  607. package/src/molecules/list/stories/Feed.vue +105 -0
  608. package/src/molecules/list/stories/Virtual.vue +31 -0
  609. package/src/molecules/list/style.css +173 -0
  610. package/src/molecules/list/types.ts +82 -0
  611. package/src/molecules/list/useVirtualRows.ts +80 -0
  612. package/src/resources/documentResource.d.ts +28 -0
  613. package/src/resources/documentResource.js +32 -4
  614. package/src/resources/documentResource.test.ts +111 -0
  615. package/src/resources/listResource.d.ts +33 -0
  616. package/src/resources/plugin.d.ts +7 -0
  617. package/src/resources/resources.d.ts +35 -0
  618. package/src/utils/{call.js → call.ts} +50 -9
  619. package/src/utils/config.ts +16 -1
  620. package/src/utils/confirmDialog.d.ts +17 -0
  621. package/src/utils/debounce.ts +6 -7
  622. package/src/utils/dialog.cy.ts +9 -9
  623. package/src/utils/fileSize.ts +36 -0
  624. package/src/utils/fileUploadHandler.ts +46 -6
  625. package/src/utils/frappeRequest.test.ts +79 -0
  626. package/src/utils/{frappeRequest.js → frappeRequest.ts} +76 -13
  627. package/src/utils/pageMeta.ts +1 -1
  628. package/src/utils/plugin.ts +58 -0
  629. package/src/utils/{request.js → request.ts} +28 -3
  630. package/src/utils/{socketio.js → socketio.ts} +11 -1
  631. package/src/utils/theme.ts +48 -57
  632. package/src/utils/useFileUpload.ts +80 -23
  633. package/tailwind/audit-token-drift.cjs +176 -0
  634. package/tailwind/colorPalette.js +69 -8
  635. package/tailwind/colors.json +1115 -397
  636. package/tailwind/figma-tokens-to-theme.js +364 -0
  637. package/tailwind/generated/colors.json +1217 -0
  638. package/tailwind/generated/effects.json +41 -0
  639. package/tailwind/generated/radius.json +20 -0
  640. package/tailwind/generated/typography.json +479 -0
  641. package/tailwind/migrate-tokens-v2.js +453 -0
  642. package/tailwind/migrate-tokens-v2.test.js +55 -0
  643. package/tailwind/plugin.js +220 -15
  644. package/tailwind/preset.js +15 -0
  645. package/tailwind/tokens.js +35 -37
  646. package/tsconfig.base.json +2 -2
  647. package/vitepress/components/Docs/CommandPalette.vue +214 -0
  648. package/vitepress/components/Docs/Demo.vue +60 -0
  649. package/vitepress/components/Docs/EmitsTable.vue +99 -0
  650. package/vitepress/components/Docs/MobileNavSheet.vue +148 -0
  651. package/vitepress/components/Docs/OnThisPage.vue +74 -0
  652. package/vitepress/components/Docs/PrevNextBtns.vue +58 -0
  653. package/vitepress/components/Docs/PropsTable.vue +185 -0
  654. package/vitepress/components/Docs/Search.vue +34 -0
  655. package/vitepress/components/Docs/Sidebar.vue +91 -0
  656. package/vitepress/components/Docs/SlotsTable.vue +99 -0
  657. package/vitepress/components/Docs/index.ts +13 -0
  658. package/vitepress/components/Docs/sidebarList.ts +33 -0
  659. package/vitepress/components/Layout.vue +58 -0
  660. package/vitepress/components/Navbar.vue +126 -0
  661. package/vitepress/components/index.ts +3 -0
  662. package/vitepress/composables/index.ts +3 -0
  663. package/vitepress/composables/useTheme.ts +39 -0
  664. package/vitepress/css/fonts/Inter-Italic.var.woff2 +0 -0
  665. package/vitepress/css/fonts/Inter.var.woff2 +0 -0
  666. package/vitepress/css/style.css +198 -0
  667. package/vitepress/index.d.ts +23 -0
  668. package/vitepress/index.node.ts +175 -0
  669. package/vitepress/index.ts +17 -0
  670. package/vitepress/plugins/colocatedComponentDocs.ts +164 -0
  671. package/vitepress/plugins/componentTransformer.ts +286 -0
  672. package/vitepress/plugins/index.ts +12 -0
  673. package/vitepress/state.ts +10 -0
  674. package/vitepress/theme/index.ts +21 -0
  675. package/frappe/telemetry/utils.ts +0 -15
  676. package/src/components/Badge/stories/Themes.vue +0 -10
  677. package/src/components/Badge/stories/Variants.vue +0 -10
  678. package/src/components/Button/stories/Icons.vue +0 -27
  679. package/src/components/Button/stories/Sizes.vue +0 -11
  680. package/src/components/Button/stories/Themes.vue +0 -10
  681. package/src/components/Button/stories/Variants.vue +0 -10
  682. package/src/components/Popover/stories/Hover.vue +0 -14
  683. package/src/components/Resource.vue +0 -21
  684. package/src/components/Sidebar/stories/Example.vue +0 -76
  685. package/src/components/Spinner.vue +0 -3
  686. package/src/components/TabButtons/TabButtons.story.vue +0 -22
  687. package/src/utils/plugin.js +0 -24
  688. /package/src/components/Dropdown/stories/{02_Shortcuts.vue → Shortcuts.vue} +0 -0
  689. /package/src/components/Dropdown/stories/{01_Simple.vue → Simple.vue} +0 -0
  690. /package/src/components/Dropdown/stories/{03_Submenus.vue → Submenus.vue} +0 -0
  691. /package/src/components/Dropdown/stories/{04_Switches.vue → Switches.vue} +0 -0
  692. /package/src/components/{Dropdown/DropdownRenderContentAsChild.vue → Menu/MenuRenderContentAsChild.vue} +0 -0
@@ -1,5 +1,5 @@
1
1
  import Link from '@tiptap/extension-link'
2
- import { buildOpenLinkEditor } from './link-commands'
2
+ import { buildOpenLinkEditor, type OpenLinkEditorOptions } from './link-commands'
3
3
  import { linkPastePlugin } from './link-paste-plugin'
4
4
  import { clearLinkOnBoundaryPlugin } from './clear-link-on-boundary-plugin'
5
5
  import { linkClickPlugin } from './link-click-plugin'
@@ -9,7 +9,7 @@ declare module '@tiptap/core' {
9
9
  interface Commands<ReturnType> {
10
10
  linkEditor: {
11
11
  /** Opens the link editor bubble menu. */
12
- openLinkEditor: () => ReturnType
12
+ openLinkEditor: (options?: OpenLinkEditorOptions) => ReturnType
13
13
  }
14
14
  }
15
15
  }
@@ -33,6 +33,15 @@ export const LinkExtension = Link.extend({
33
33
  autolink: true,
34
34
  defaultProtocol: 'https',
35
35
  linkOnPaste: false,
36
+ // Don't auto-link bare dotted identifiers like `data.doc.name` (`.name` is a
37
+ // real TLD, so linkify matches them). Only auto-link inputs that carry an
38
+ // explicit scheme (`http://`, `mailto:`, …) or a `www.` prefix — i.e. things
39
+ // a user actually means as a URL. `url` here is the raw matched text.
40
+ shouldAutoLink: (url: string): boolean => {
41
+ const hasScheme = /^[a-z][a-z0-9+.-]*:/i.test(url)
42
+ const hasWww = /^www\./i.test(url)
43
+ return hasScheme || hasWww
44
+ },
36
45
  }
37
46
  },
38
47
 
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import { describe, it, expect } from 'vitest'
6
+ import { lockScroll } from './link-popup-controller'
7
+
8
+ describe('lockScroll', () => {
9
+ // Regression: opening the link popup over a scrolled editor used to drop the
10
+ // container's `overflow-y` on close, so long content overflowed its box and
11
+ // painted over the toolbar/Submit. The lock must restore the exact prior
12
+ // overflow, even when it was authored as the `overflow-y` longhand.
13
+ it('restores an `overflow-y` longhand after lock/unlock', () => {
14
+ const el = document.createElement('div')
15
+ el.style.overflowY = 'auto'
16
+
17
+ const unlock = lockScroll(el)
18
+ expect(el.style.overflowY).toBe('hidden')
19
+ expect(el.style.overflowX).toBe('hidden')
20
+
21
+ unlock()
22
+ expect(el.style.overflowY).toBe('auto')
23
+ })
24
+
25
+ it('restores each axis independently after lock/unlock', () => {
26
+ const el = document.createElement('div')
27
+ el.style.overflowX = 'hidden'
28
+ el.style.overflowY = 'auto'
29
+
30
+ lockScroll(el)()
31
+
32
+ expect(el.style.overflowX).toBe('hidden')
33
+ expect(el.style.overflowY).toBe('auto')
34
+ })
35
+
36
+ it('leaves no inline overflow when the element had none', () => {
37
+ const el = document.createElement('div')
38
+
39
+ lockScroll(el)()
40
+
41
+ expect(el.style.overflowX).toBe('')
42
+ expect(el.style.overflowY).toBe('')
43
+ expect(el.getAttribute('style')).toBeFalsy()
44
+ })
45
+
46
+ it('is a no-op for a null scroll parent', () => {
47
+ expect(() => lockScroll(null)()).not.toThrow()
48
+ })
49
+ })
@@ -10,10 +10,17 @@ import LinkEditorPopup from './LinkEditorPopup.vue'
10
10
  export interface OpenLinkPopupOptions {
11
11
  /** Existing href to seed the editor with (`null` when creating a new link). */
12
12
  href: string | null
13
+ /** Open straight into edit mode (vs. the read-only view). */
14
+ startInEdit?: boolean
13
15
  /** Anchor element used for popup ownership and outside-click containment. */
14
16
  anchor: HTMLElement
15
17
  /** Optional positioning reference. Defaults to the editor selection. */
16
18
  virtualReference?: VirtualReference
19
+ /**
20
+ * Called when the user dismisses the popup with Escape (not on apply or
21
+ * click-outside). Used to return focus to the editor.
22
+ */
23
+ onEscape?: () => void
17
24
  }
18
25
 
19
26
  /**
@@ -35,6 +42,11 @@ export function openLinkPopup(
35
42
  ): Promise<string | null> {
36
43
  const { href, anchor } = options
37
44
 
45
+ // Lock the page's scroll container while the popup is open so the anchored
46
+ // editor can't scroll away underneath it. The app scrolls an inner
47
+ // overflow-auto element (not <body>), so we lock the nearest such ancestor.
48
+ const unlockScroll = lockScroll(getScrollParent(anchor))
49
+
38
50
  return new Promise<string | null>((resolve) => {
39
51
  let settled = false
40
52
  const settle = (value: string | null) => {
@@ -47,16 +59,21 @@ export function openLinkPopup(
47
59
  anchor,
48
60
  component: LinkEditorPopup,
49
61
  closeOnAnchorPointerDown: true,
62
+ // The popup owns Escape: in view mode it closes; in edit mode the first
63
+ // Escape steps back to view mode and only a second one closes.
64
+ closeOnEscape: false,
50
65
  virtualReference: options.virtualReference ?? {
51
66
  getBoundingClientRect: () => selectionRect(anchor),
52
67
  },
53
68
  floatingOptions: { placement: 'top' },
54
69
  props: {
55
70
  href: href ?? '',
71
+ startInEdit: options.startInEdit ?? !href,
56
72
  onClose: () => {
57
- // Cancel: resolve null, then tear down.
73
+ // Cancel via Escape: resolve null, tear down, then hand focus back.
58
74
  settle(null)
59
75
  popup.destroy()
76
+ options.onEscape?.()
60
77
  },
61
78
  onUpdateHref: (newHref: string) => {
62
79
  settle(newHref)
@@ -69,14 +86,62 @@ export function openLinkPopup(
69
86
  // else settled the promise by the time the popup is gone.
70
87
  const originalDestroy = popup.destroy
71
88
  popup.destroy = () => {
89
+ unlockScroll()
72
90
  settle(null)
73
91
  originalDestroy()
74
92
  }
75
93
 
76
- if (!popup.floating) settle(null)
94
+ if (!popup.floating) {
95
+ unlockScroll()
96
+ settle(null)
97
+ }
77
98
  })
78
99
  }
79
100
 
101
+ /**
102
+ * Lock vertical+horizontal scrolling on `el` and return a function that
103
+ * restores it.
104
+ *
105
+ * Save/restore the `overflow-x`/`overflow-y` *longhands* — never the `overflow`
106
+ * shorthand. A scroll container's value usually lives in a longhand (e.g.
107
+ * EditorContent sets `overflow-y: auto` inline); reading `.style.overflow`
108
+ * returns '' whenever the two axes differ, so locking via the shorthand and
109
+ * later clearing it would drop the original `overflow-y` and leave the editor
110
+ * overflowing its box — content then paints over the toolbar (the link-edit
111
+ * overflow bug). The longhand getters reflect the value regardless of how it
112
+ * was originally authored, so restoring them reproduces the prior state exactly.
113
+ *
114
+ * No-op (returns a no-op restore) when `el` is `null`.
115
+ */
116
+ export function lockScroll(el: HTMLElement | null): () => void {
117
+ if (!el) return () => {}
118
+ const previous = { x: el.style.overflowX, y: el.style.overflowY }
119
+ el.style.overflowX = 'hidden'
120
+ el.style.overflowY = 'hidden'
121
+ return () => {
122
+ el.style.overflowX = previous.x
123
+ el.style.overflowY = previous.y
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Nearest scrollable ancestor of `el` (the element that actually scrolls), used
129
+ * to lock scrolling while editing. The app's scroll container is an inner
130
+ * `overflow-auto` div, not `document.body`, so locking the body is a no-op —
131
+ * we must lock this element instead. Returns `null` if nothing scrolls.
132
+ */
133
+ function getScrollParent(el: HTMLElement | null): HTMLElement | null {
134
+ let node: HTMLElement | null = el
135
+ while (node && node !== document.body) {
136
+ const { overflowY } = getComputedStyle(node)
137
+ if (/(auto|scroll|overlay)/.test(overflowY) && node.scrollHeight > node.clientHeight) {
138
+ return node
139
+ }
140
+ node = node.parentElement
141
+ }
142
+ return null
143
+ }
144
+
80
145
  /**
81
146
  * Build a live `DOMRect` from the current selection (collapsed → caret rect,
82
147
  * expanded → selection rect). Falls back to the anchor's own rect when there
@@ -24,7 +24,7 @@ export function linkShortcutPlugin(options: LinkShortcutPluginOptions): Plugin {
24
24
  return new Plugin({
25
25
  key: new PluginKey('linkShortcut'),
26
26
  props: {
27
- handleKeyDown: (_view, event): boolean => {
27
+ handleKeyDown: (view, event): boolean => {
28
28
  const isModK =
29
29
  (event.metaKey || event.ctrlKey) &&
30
30
  !event.shiftKey &&
@@ -34,7 +34,12 @@ export function linkShortcutPlugin(options: LinkShortcutPluginOptions): Plugin {
34
34
 
35
35
  event.preventDefault()
36
36
  event.stopPropagation()
37
- editor.commands.openLinkEditor()
37
+ // An explicit selection (e.g. selecting a link) → edit its URL straight
38
+ // away; a bare cursor in a link → the default read-only view.
39
+ const hasSelection = !view.state.selection.empty
40
+ editor.commands.openLinkEditor(
41
+ hasSelection ? { startInEdit: true } : undefined,
42
+ )
38
43
  return true
39
44
  },
40
45
  },
@@ -0,0 +1,177 @@
1
+ import { Extension } from '@tiptap/core'
2
+ import { Plugin, Selection } from '@tiptap/pm/state'
3
+ import type { EditorView } from '@tiptap/pm/view'
4
+ import { openImageGroupUploadDialog } from '#molecules/editor/extensions/image-group/imageGroupDialogController'
5
+
6
+ /**
7
+ * The single drop pipeline.
8
+ *
9
+ * One place decides what a set of dropped files becomes, so every entry point
10
+ * behaves identically: the precise in-prose drop (this extension's ProseMirror
11
+ * plugin, which drops at the cursor) and the generous editor-area drop zone
12
+ * (`EditorDropZone`, which calls `dropFiles` directly).
13
+ *
14
+ * Routing by type/count:
15
+ * - exactly one image -> insert it inline (`uploadImage`)
16
+ * - several images -> open the image group dialog (matches the toolbar's
17
+ * multi-image pick, instead of stacking them inline)
18
+ * - any video(s) -> upload inline (`uploadVideoFiles`)
19
+ * - anything else -> upload inline as attachments (`uploadAttachmentFiles`)
20
+ *
21
+ * Type routing is feature-detected via the editor's commands, so a kit without
22
+ * the image, video, or attachment extension simply skips that branch.
23
+ *
24
+ * Drop is handled under `handleDOMEvents.drop`; a file paste of non-image,
25
+ * non-video files is handled under `props.handlePaste` (image/video pastes keep
26
+ * flowing to their own extensions' paste handlers).
27
+ */
28
+
29
+ const IMAGE_RE = /^image\//i
30
+ const VIDEO_RE = /^video\//i
31
+
32
+ /** Pull every `File` out of a drag `DataTransfer`, regardless of MIME. */
33
+ function collectFiles(dataTransfer: DataTransfer | null | undefined): File[] {
34
+ const items = dataTransfer?.items
35
+ if (!items || items.length === 0) return []
36
+ const files: File[] = []
37
+ for (let i = 0; i < items.length; i++) {
38
+ if (items[i].kind === 'file') {
39
+ const file = items[i].getAsFile()
40
+ if (file) files.push(file)
41
+ }
42
+ }
43
+ return files
44
+ }
45
+
46
+ declare module '@tiptap/core' {
47
+ interface Commands<ReturnType> {
48
+ mediaDrop: {
49
+ /**
50
+ * Route dropped/provided files by type and count (the single drop
51
+ * pipeline). Inserts at the current selection — callers that want a
52
+ * precise position should move the selection first.
53
+ */
54
+ dropFiles: (files: File[]) => ReturnType
55
+ }
56
+ }
57
+ }
58
+
59
+ export const MediaDrop = Extension.create({
60
+ name: 'mediaDrop',
61
+
62
+ addCommands() {
63
+ return {
64
+ dropFiles:
65
+ (files: File[]) =>
66
+ ({ editor }) => {
67
+ if (files.length === 0) return false
68
+
69
+ const images = files.filter((f) => IMAGE_RE.test(f.type))
70
+ const videos = files.filter((f) => VIDEO_RE.test(f.type))
71
+ // Everything that is neither image nor video becomes an attachment.
72
+ const others = files.filter(
73
+ (f) => !IMAGE_RE.test(f.type) && !VIDEO_RE.test(f.type),
74
+ )
75
+
76
+ const can = (name: string): boolean =>
77
+ typeof (editor.commands as Record<string, unknown>)[name] ===
78
+ 'function'
79
+
80
+ let handled = false
81
+
82
+ if (images.length === 1 && can('uploadImage')) {
83
+ editor.commands.uploadImage(images[0])
84
+ handled = true
85
+ } else if (images.length > 1 && can('uploadImage')) {
86
+ openImageGroupUploadDialog({ editor, files: images })
87
+ handled = true
88
+ }
89
+
90
+ if (videos.length > 0 && can('uploadVideoFiles')) {
91
+ editor.commands.uploadVideoFiles(videos)
92
+ handled = true
93
+ }
94
+
95
+ if (others.length > 0 && can('uploadAttachmentFiles')) {
96
+ editor.commands.uploadAttachmentFiles(others)
97
+ handled = true
98
+ }
99
+
100
+ return handled
101
+ },
102
+ }
103
+ },
104
+
105
+ addProseMirrorPlugins() {
106
+ const editor = this.editor
107
+
108
+ /** Whether a kit exposes a given routing command. */
109
+ const can = (name: string): boolean =>
110
+ typeof (editor.commands as Record<string, unknown>)[name] === 'function'
111
+
112
+ return [
113
+ new Plugin({
114
+ props: {
115
+ handleDOMEvents: {
116
+ drop: (view: EditorView, event: DragEvent): boolean => {
117
+ const files = collectFiles(event.dataTransfer)
118
+ if (files.length === 0) return false
119
+ // Only claim drops we can actually route; let ProseMirror handle
120
+ // the rest. Non-media files route to attachments when available.
121
+ const hasMedia = files.some(
122
+ (f) => IMAGE_RE.test(f.type) || VIDEO_RE.test(f.type),
123
+ )
124
+ const hasOther = files.some(
125
+ (f) => !IMAGE_RE.test(f.type) && !VIDEO_RE.test(f.type),
126
+ )
127
+ const routable =
128
+ hasMedia || (hasOther && can('uploadAttachmentFiles'))
129
+ if (!routable) return false
130
+
131
+ event.preventDefault()
132
+ event.stopPropagation()
133
+
134
+ // Drop at the cursor: move the selection to the drop point so the
135
+ // single-image insert lands where the file was released.
136
+ const coords = view.posAtCoords({
137
+ left: event.clientX,
138
+ top: event.clientY,
139
+ })
140
+ if (coords) {
141
+ view.dispatch(
142
+ view.state.tr.setSelection(
143
+ Selection.near(view.state.doc.resolve(coords.pos)),
144
+ ),
145
+ )
146
+ }
147
+
148
+ editor.commands.dropFiles(files)
149
+ return true
150
+ },
151
+ },
152
+
153
+ // Paste of non-image, non-video files (image/video pastes keep
154
+ // flowing to their own extensions' paste handlers, so we never claim
155
+ // them here). Pure-attachment pastes are uploaded at the cursor.
156
+ handlePaste: (_view, event): boolean => {
157
+ if (!can('uploadAttachmentFiles')) return false
158
+ const files = collectFiles(event.clipboardData)
159
+ if (files.length === 0) return false
160
+ const others = files.filter(
161
+ (f) => !IMAGE_RE.test(f.type) && !VIDEO_RE.test(f.type),
162
+ )
163
+ // Only claim when the paste is exclusively attachments; otherwise
164
+ // defer to the image/video paste handlers.
165
+ if (others.length !== files.length) return false
166
+
167
+ event.preventDefault()
168
+ editor.commands.uploadAttachmentFiles(others)
169
+ return true
170
+ },
171
+ },
172
+ }),
173
+ ]
174
+ },
175
+ })
176
+
177
+ export default MediaDrop
@@ -11,6 +11,7 @@
11
11
  export interface MediaDimensions {
12
12
  width: number
13
13
  height: number
14
+ poster?: string
14
15
  }
15
16
 
16
17
  /** Probe an image source via `<img>.naturalWidth`/`naturalHeight`. */
@@ -35,21 +36,53 @@ export function probeImageDimensions(src: string): Promise<MediaDimensions> {
35
36
  })
36
37
  }
37
38
 
38
- /** Probe a video source via `<video>.videoWidth`/`videoHeight` (metadata only). */
39
+ function captureVideoPoster(video: HTMLVideoElement): string | undefined {
40
+ if (!video.videoWidth || !video.videoHeight) return undefined
41
+ const canvas = document.createElement('canvas')
42
+ canvas.width = video.videoWidth
43
+ canvas.height = video.videoHeight
44
+ const ctx = canvas.getContext('2d')
45
+ if (!ctx) return undefined
46
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
47
+ return canvas.toDataURL('image/jpeg', 0.72)
48
+ }
49
+
50
+ /** Probe a video source via `<video>.videoWidth`/`videoHeight` and a poster frame. */
39
51
  export function probeVideoDimensions(src: string): Promise<MediaDimensions> {
40
52
  return new Promise<MediaDimensions>((resolve, reject) => {
41
53
  const video = document.createElement('video')
42
54
  video.preload = 'metadata'
55
+ video.muted = true
56
+ video.playsInline = true
43
57
  const cleanup = () => {
44
58
  video.onloadedmetadata = null
59
+ video.onseeked = null
45
60
  video.onerror = null
46
61
  video.removeAttribute('src')
47
62
  video.load()
48
63
  }
49
- video.onloadedmetadata = () => {
64
+ const resolveWithPoster = () => {
50
65
  const dims = { width: video.videoWidth, height: video.videoHeight }
66
+ let poster: string | undefined
67
+ try {
68
+ poster = captureVideoPoster(video)
69
+ } catch {
70
+ poster = undefined
71
+ }
51
72
  cleanup()
52
- resolve(dims)
73
+ resolve({ ...dims, poster })
74
+ }
75
+ video.onloadedmetadata = () => {
76
+ if (Number.isFinite(video.duration) && video.duration > 0.15) {
77
+ video.onseeked = resolveWithPoster
78
+ try {
79
+ video.currentTime = 0.1
80
+ } catch {
81
+ resolveWithPoster()
82
+ }
83
+ } else {
84
+ resolveWithPoster()
85
+ }
53
86
  }
54
87
  video.onerror = () => {
55
88
  cleanup()
@@ -22,6 +22,7 @@ import type {
22
22
  export interface OptionalDimensions {
23
23
  width: number | null
24
24
  height: number | null
25
+ poster?: string
25
26
  }
26
27
 
27
28
  /**
@@ -76,8 +77,10 @@ export function insertPlaceholder(
76
77
  mode: InsertMode,
77
78
  uploadId: string,
78
79
  dims: OptionalDimensions,
80
+ attrs: Record<string, unknown> = {},
79
81
  ): void {
80
82
  const node = view.state.schema.nodes[nodeName].create({
83
+ ...attrs,
81
84
  loading: true,
82
85
  uploadId,
83
86
  src: null,
@@ -99,6 +102,19 @@ export function insertPlaceholder(
99
102
  dispatchIfAlive(view, tr)
100
103
  }
101
104
 
105
+ /** Remove a loading placeholder after user cancellation. */
106
+ export function removeNodeByUploadId(
107
+ view: EditorView,
108
+ nodeName: string,
109
+ uploadId: string,
110
+ ): void {
111
+ const pos = findNodeByUploadId(view, nodeName, uploadId)
112
+ if (pos === null) return
113
+ const node = view.state.doc.nodeAt(pos)
114
+ if (!node) return
115
+ dispatchIfAlive(view, view.state.tr.delete(pos, pos + node.nodeSize))
116
+ }
117
+
102
118
  /** Write the uploaded src/dimensions back onto the placeholder node. */
103
119
  export function applyUploadSuccess(
104
120
  view: EditorView,
@@ -118,6 +134,7 @@ export function applyUploadSuccess(
118
134
  width: uploaded.width || node.attrs.width,
119
135
  height: uploaded.height || node.attrs.height,
120
136
  loading: false,
137
+ error: null,
121
138
  }),
122
139
  )
123
140
  }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import { describe, it, expect, vi } from 'vitest'
6
+
7
+ vi.mock('#molecules/editor/extensions/shared/node-view', () => ({
8
+ dispatchIfAlive: vi.fn(),
9
+ }))
10
+
11
+ import { createMediaPlugin } from '#molecules/editor/extensions/shared/media-plugin'
12
+ import { dispatchIfAlive } from '#molecules/editor/extensions/shared/node-view'
13
+ import type { MediaUploadConfig } from '#molecules/editor/extensions/shared/media-upload-types'
14
+
15
+ function mediaNode(src: string, attrs: Record<string, unknown> = {}) {
16
+ return {
17
+ type: { name: 'image' },
18
+ attrs: { src, ...attrs },
19
+ }
20
+ }
21
+
22
+ describe('media plugin dimension backfill', () => {
23
+ it('does not write stale dimensions when the node at the captured position changed source', async () => {
24
+ const inserted = mediaNode('/files/old.png')
25
+ const live = mediaNode('/files/new.png')
26
+ const config: MediaUploadConfig = {
27
+ nodeName: 'image',
28
+ accept: /image/i,
29
+ storeBase64: true,
30
+ probeDimensions: vi.fn(async () => ({ width: 100, height: 50 })),
31
+ }
32
+ const view = {
33
+ state: {
34
+ doc: { nodeAt: () => live },
35
+ tr: { setNodeMarkup: vi.fn() },
36
+ },
37
+ }
38
+ const plugin = createMediaPlugin({} as never, config, {
39
+ editor: { view } as never,
40
+ options: {},
41
+ })
42
+ const newState = {
43
+ doc: {
44
+ descendants: (visit: (node: unknown, pos: number) => void) => {
45
+ visit(inserted, 5)
46
+ },
47
+ nodeAt: () => inserted,
48
+ },
49
+ }
50
+
51
+ ;(plugin as any).spec.appendTransaction(
52
+ [{ docChanged: true }],
53
+ {} as never,
54
+ newState,
55
+ )
56
+ await Promise.resolve()
57
+
58
+ expect(dispatchIfAlive).not.toHaveBeenCalled()
59
+ })
60
+ })
@@ -8,7 +8,7 @@
8
8
  * is handled under `props.handlePaste` (NOT `handleDOMEvents.paste`), per the
9
9
  * conventions §1.6 contract.
10
10
  */
11
- import { Plugin, Selection } from '@tiptap/pm/state'
11
+ import { Plugin } from '@tiptap/pm/state'
12
12
  import type { Transaction, EditorState } from '@tiptap/pm/state'
13
13
  import type { EditorView } from '@tiptap/pm/view'
14
14
  import type { Editor } from '@tiptap/core'
@@ -61,42 +61,11 @@ export function createMediaPlugin(
61
61
 
62
62
  return new Plugin({
63
63
  props: {
64
- handleDOMEvents: {
65
- drop: (view: EditorView, event: DragEvent): boolean => {
66
- const editor = host.editor
67
- const options = resolve()
68
- if (
69
- !editor ||
70
- !event.dataTransfer?.files?.length ||
71
- !options.uploadFunction
72
- ) {
73
- return false
74
- }
75
- const files = collectFiles(event.dataTransfer, config.accept)
76
- if (files.length === 0) return false
77
-
78
- event.preventDefault()
79
-
80
- let pos: number | null = null
81
- const coords = view.posAtCoords({
82
- left: event.clientX,
83
- top: event.clientY,
84
- })
85
- if (coords) {
86
- pos = coords.pos
87
- view.dispatch(
88
- view.state.tr.setSelection(
89
- Selection.near(view.state.doc.resolve(pos)),
90
- ),
91
- )
92
- }
93
-
94
- void engine.processMultiple(files, editor, pos, options)
95
- return true
96
- },
97
- },
98
-
99
- handlePaste: (view: EditorView, event: ClipboardEvent): boolean => {
64
+ // NOTE: drop is NOT handled here. The single drop pipeline lives in the
65
+ // `MediaDrop` extension (`media-drop-extension.ts`), which routes a whole
66
+ // drop by type/count. This per-node plugin owns only paste + the
67
+ // intrinsic-dimension back-fill below.
68
+ handlePaste: (_view: EditorView, event: ClipboardEvent): boolean => {
100
69
  const editor = host.editor
101
70
  const options = resolve()
102
71
  if (!editor || !options.uploadFunction) return false
@@ -145,6 +114,7 @@ export function createMediaPlugin(
145
114
  const view = editor.view
146
115
  const live = view.state.doc.nodeAt(pos)
147
116
  if (!live || live.type.name !== config.nodeName) return
117
+ if (live.attrs.src !== src) return
148
118
  if (live.attrs.width != null && live.attrs.height != null) return
149
119
  dispatchIfAlive(
150
120
  view,