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
@@ -0,0 +1,303 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ nextTick,
4
+ onBeforeUnmount,
5
+ ref,
6
+ shallowRef,
7
+ useTemplateRef,
8
+ watch,
9
+ } from 'vue'
10
+ import { computePosition, flip, offset, shift } from '@floating-ui/dom'
11
+ import { CellSelection, cellAround, isInTable, selectionCell } from '@tiptap/pm/tables'
12
+ import { verticalScrollParent } from './extensions/table/drag-scroll'
13
+ import MenuItems from './MenuItems.vue'
14
+ import TableContextMenu from './components/TableContextMenu.vue'
15
+ import { tableToolbar } from './menu'
16
+ import type { Editor } from './useEditor'
17
+ import { useResolvedEditor } from './editor-context'
18
+ import {
19
+ useFloatingPopup,
20
+ type FloatingPopupHandle,
21
+ } from './composables/useFloatingPopup'
22
+
23
+ /**
24
+ * Contextual table toolbar with row/column insert + delete, header-row toggle,
25
+ * merge/split, and delete-table controls (see `tableToolbar`).
26
+ *
27
+ * Unlike a stock bubble menu — which anchors to the text selection and so jumps
28
+ * from cell to cell as the caret moves — this anchors to the *table* element. It
29
+ * therefore stays put while you move between cells and only re-positions when
30
+ * you enter a different table (or the table / viewport changes). The buttons
31
+ * still act on the active cell, so the toolbar adapts to context without moving.
32
+ *
33
+ * Safe to render unconditionally: it's hidden outside tables and the items
34
+ * self-prune when the Table extension is absent, so it's inert in a comment
35
+ * editor.
36
+ */
37
+ const props = defineProps<{
38
+ // Optional inside <Editor> — falls back to the provided editor context.
39
+ editor?: Editor | null
40
+ }>()
41
+
42
+ const editor = useResolvedEditor(() => props.editor)
43
+
44
+ const floating = useTemplateRef<HTMLElement>('floating')
45
+ const anchor = shallowRef<HTMLElement | null>(null)
46
+ const visible = ref(false)
47
+
48
+ /** The DOM element of the table the selection is currently inside, if any. */
49
+ function activeTableEl(ed: Editor): HTMLElement | null {
50
+ if (!ed.isEditable || !ed.isActive('table')) return null
51
+ // `editor.view` is a proxy that throws on access until the view is mounted;
52
+ // the immediate watch can run sync() before that. `isInitialized` flips true
53
+ // on mount, so bail until then.
54
+ if (!ed.isInitialized) return null
55
+ const { $from } = ed.state.selection
56
+ for (let depth = $from.depth; depth > 0; depth--) {
57
+ if ($from.node(depth).type.name === 'table') {
58
+ const dom = ed.view.nodeDOM($from.before(depth))
59
+ // nodeDOM returns the table's wrapper; anchor to the inner <table> so the
60
+ // toolbar sits against the table edge, not the wrapper's outer spacing.
61
+ if (dom instanceof HTMLElement) {
62
+ return dom.tagName === 'TABLE'
63
+ ? dom
64
+ : (dom.querySelector('table') ?? dom)
65
+ }
66
+ }
67
+ }
68
+ return null
69
+ }
70
+
71
+ /**
72
+ * The vertical band the toolbar may occupy: the visible part of the editor's
73
+ * scroll container (so a pinned toolbar never floats over the app chrome
74
+ * above/below it), clamped to the viewport.
75
+ */
76
+ function verticalBounds(table: HTMLElement): { top: number; bottom: number } {
77
+ const parent = verticalScrollParent(table)
78
+ if (parent === document.scrollingElement || parent === document.documentElement) {
79
+ return { top: 0, bottom: window.innerHeight }
80
+ }
81
+ const rect = parent.getBoundingClientRect()
82
+ return {
83
+ top: Math.max(rect.top, 0),
84
+ bottom: Math.min(rect.bottom, window.innerHeight),
85
+ }
86
+ }
87
+
88
+ /** Whether any part of the table is visible inside its scroll container. */
89
+ function tableInView(table: HTMLElement): boolean {
90
+ const rect = table.getBoundingClientRect()
91
+ const bounds = verticalBounds(table)
92
+ return (
93
+ rect.bottom > bounds.top &&
94
+ rect.top < bounds.bottom &&
95
+ rect.right > 0 &&
96
+ rect.left < window.innerWidth
97
+ )
98
+ }
99
+
100
+ function reposition() {
101
+ const table = anchor.value
102
+ const el = floating.value
103
+ if (!table || !el) return
104
+ // A wide table scrolls inside its `.tableWrapper` (overflow-x: auto), so the
105
+ // table's own horizontal center can be scrolled out of view — centering the
106
+ // toolbar on it would float it over the clipped region. Anchor instead to the
107
+ // part of the table actually visible inside the wrapper's viewport: the
108
+ // horizontal intersection of table and wrapper. That collapses to the table
109
+ // for a narrow (fully visible) table and to the visible window for a wide,
110
+ // scrolled one. Vertical anchor stays at the table's top edge.
111
+ const wrapper = table.closest<HTMLElement>('.tableWrapper')
112
+ const reference = wrapper
113
+ ? {
114
+ getBoundingClientRect: () => {
115
+ const t = table.getBoundingClientRect()
116
+ const w = wrapper.getBoundingClientRect()
117
+ const left = Math.max(t.left, w.left)
118
+ const right = Math.min(t.right, w.right)
119
+ return new DOMRect(left, t.top, Math.max(0, right - left), 0)
120
+ },
121
+ }
122
+ : table
123
+ void computePosition(reference, el, {
124
+ strategy: 'fixed',
125
+ placement: 'top',
126
+ middleware: [offset(4), flip(), shift({ padding: 8 })],
127
+ }).then(({ x, y }) => {
128
+ // Pin the toolbar inside the visible band while scrolling through a tall
129
+ // table, instead of letting it follow the table's top edge off-screen.
130
+ const bounds = verticalBounds(table)
131
+ const minY = bounds.top + 4
132
+ const maxY = bounds.bottom - el.offsetHeight - 4
133
+ el.style.left = `${x}px`
134
+ el.style.top = `${Math.min(Math.max(y, minY), Math.max(maxY, minY))}px`
135
+ })
136
+ }
137
+
138
+ function sync() {
139
+ const ed = editor.value
140
+ const table = ed ? activeTableEl(ed) : null
141
+ anchor.value = table
142
+ visible.value = !!table && tableInView(table)
143
+ // Wait for v-show to reveal the element before measuring it.
144
+ if (visible.value) void nextTick(reposition)
145
+ }
146
+
147
+ // --- Right-click context menu ---------------------------------------------
148
+ let contextMenu: FloatingPopupHandle | null = null
149
+
150
+ function closeContextMenu() {
151
+ contextMenu?.destroy()
152
+ contextMenu = null
153
+ }
154
+
155
+ function openContextMenu(ed: Editor, clientX: number, clientY: number) {
156
+ closeContextMenu()
157
+ contextMenu = useFloatingPopup({
158
+ anchor: ed.view.dom,
159
+ component: TableContextMenu,
160
+ props: { editor: ed, items: tableToolbar, onRun: closeContextMenu },
161
+ // Anchor at the cursor point so the menu opens where the user clicked.
162
+ virtualReference: {
163
+ getBoundingClientRect: () => new DOMRect(clientX, clientY, 0, 0),
164
+ },
165
+ closeOnAnchorPointerDown: true,
166
+ animate: true,
167
+ floatingOptions: { placement: 'right-start', strategy: 'fixed', offset: 0 },
168
+ })
169
+ }
170
+
171
+ function onContextMenu(event: MouseEvent) {
172
+ const ed = editor.value
173
+ if (!ed || ed.isDestroyed || !ed.isEditable) return
174
+ // The view getter throws until the editor is mounted; a real right-click
175
+ // always happens after mount, but guard anyway.
176
+ let dom: HTMLElement
177
+ try {
178
+ dom = ed.view.dom as HTMLElement
179
+ } catch {
180
+ return
181
+ }
182
+ const target = event.target
183
+ if (!(target instanceof Node) || !dom.contains(target)) return
184
+ const coords = ed.view.posAtCoords({
185
+ left: event.clientX,
186
+ top: event.clientY,
187
+ })
188
+ let $cell = coords ? cellAround(ed.state.doc.resolve(coords.pos)) : null
189
+ let point = { x: event.clientX, y: event.clientY }
190
+ if (!$cell) {
191
+ // A real right-click outside any table — let the native menu through.
192
+ if (event.button === 2) return
193
+ // Keyboard-initiated (ContextMenu key / Shift+F10) events carry no usable
194
+ // coordinates; fall back to the active cell and anchor the menu to it.
195
+ if (!isInTable(ed.state)) return
196
+ $cell = selectionCell(ed.state)
197
+ const cellDom = ed.view.nodeDOM($cell.pos)
198
+ if (!(cellDom instanceof HTMLElement)) return
199
+ const rect = cellDom.getBoundingClientRect()
200
+ point = { x: rect.left + Math.min(rect.width / 2, 24), y: rect.bottom - 4 }
201
+ }
202
+ event.preventDefault()
203
+ // Keep an existing multi-cell selection when the click lands inside it — the
204
+ // menu is the natural place to act on the selected block (merge, color).
205
+ // Otherwise select the right-clicked cell so the actions target it.
206
+ const selection = ed.state.selection
207
+ let inSelection = false
208
+ if (selection instanceof CellSelection) {
209
+ selection.forEachCell((_node, pos) => {
210
+ if (pos === $cell!.pos) inSelection = true
211
+ })
212
+ }
213
+ if (!inSelection) {
214
+ ed.view.dispatch(
215
+ ed.state.tr.setSelection(CellSelection.create(ed.state.doc, $cell.pos)),
216
+ )
217
+ }
218
+ openContextMenu(ed, point.x, point.y)
219
+ }
220
+
221
+ // (Re)subscribe whenever the editor instance changes. The toolbar shows on
222
+ // transactions (selection / content) and follows the table on scroll/resize —
223
+ // re-clamped into the scroll container's visible band by `reposition`, and
224
+ // hidden only once the table itself scrolls out of view.
225
+ let scrollRaf = 0
226
+ watch(
227
+ editor,
228
+ (ed, _old, onCleanup) => {
229
+ if (typeof ed?.on !== 'function') {
230
+ visible.value = false
231
+ return
232
+ }
233
+ const onChange = () => sync()
234
+ const onScroll = () => {
235
+ if (scrollRaf) return
236
+ scrollRaf = requestAnimationFrame(() => {
237
+ scrollRaf = 0
238
+ sync()
239
+ })
240
+ }
241
+ const onResize = () => sync()
242
+ ed.on('transaction', onChange)
243
+ ed.on('focus', onChange)
244
+ // Capture phase so inner scroll containers are caught too.
245
+ document.addEventListener('scroll', onScroll, true)
246
+ window.addEventListener('resize', onResize)
247
+ // Bound on document (not the view DOM) so it never touches `ed.view` before
248
+ // the view is mounted; the handler scopes itself to this editor.
249
+ document.addEventListener('contextmenu', onContextMenu, true)
250
+ sync()
251
+ onCleanup(() => {
252
+ ed.off('transaction', onChange)
253
+ ed.off('focus', onChange)
254
+ if (scrollRaf) cancelAnimationFrame(scrollRaf)
255
+ scrollRaf = 0
256
+ document.removeEventListener('scroll', onScroll, true)
257
+ window.removeEventListener('resize', onResize)
258
+ document.removeEventListener('contextmenu', onContextMenu, true)
259
+ closeContextMenu()
260
+ })
261
+ },
262
+ { immediate: true },
263
+ )
264
+
265
+ onBeforeUnmount(closeContextMenu)
266
+ </script>
267
+
268
+ <template>
269
+ <Teleport to="body">
270
+ <Transition name="table-menu">
271
+ <div
272
+ v-show="visible && editor"
273
+ ref="floating"
274
+ data-slot="table-menu"
275
+ class="fixed left-0 top-0 z-[100] flex items-center gap-1 rounded-lg border border-outline-gray-2 bg-surface-elevation-2 p-1 shadow-sm"
276
+ >
277
+ <MenuItems v-if="editor" :editor="editor" :items="tableToolbar" />
278
+ </div>
279
+ </Transition>
280
+ </Teleport>
281
+ </template>
282
+
283
+ <style scoped>
284
+ /* Fast appear only; leave is instant so the toolbar clears the moment the
285
+ * selection leaves a table. Mirrors EditorPopover's 90ms fade+scale. */
286
+ .table-menu-enter-active {
287
+ transition:
288
+ opacity 90ms ease-out,
289
+ transform 90ms ease-out;
290
+ transform-origin: center bottom;
291
+ }
292
+
293
+ .table-menu-enter-from {
294
+ opacity: 0;
295
+ transform: scale(0.98);
296
+ }
297
+
298
+ @media (prefers-reduced-motion: reduce) {
299
+ .table-menu-enter-active {
300
+ transition: none;
301
+ }
302
+ }
303
+ </style>
@@ -1,11 +1,15 @@
1
1
  <script setup lang="ts">
2
- import { computed, h, ref, watch, type Component } from 'vue'
2
+ import { computed, ref, watch, type Component } from 'vue'
3
3
  import type { CommandMenuItem, MenuGroupItem, MenuItem } from './menu'
4
4
  import type { Editor } from './useEditor'
5
+ import Button from '#components/Button/Button.vue'
6
+ import Tooltip from '#components/Tooltip/Tooltip.vue'
7
+ import TooltipProvider from '#components/Tooltip/TooltipProvider.vue'
5
8
 
6
9
  const props = defineProps<{
7
10
  editor: Editor | null
8
11
  items: MenuItem[]
12
+ buttonSize?: 'xs' | 'sm'
9
13
  }>()
10
14
 
11
15
  // The editor from `useEditor` is built on `@tiptap/core` (not `@tiptap/vue-3`),
@@ -39,15 +43,11 @@ function isItemDisabled(item: CommandMenuItem): boolean {
39
43
  return !props.editor || item.isDisabled?.(props.editor) === true
40
44
  }
41
45
 
42
- // Renders an item's glyph: a `lucide-*` (or any) string becomes a masked icon
43
- // span (sized here so item definitions stay terse); a component renders as-is;
44
- // with no icon we fall back to the label text.
45
- function ItemContent(p: { item: CommandMenuItem }) {
46
- const { icon, label } = p.item
47
- if (!icon) return h('span', label)
48
- if (typeof icon === 'string')
49
- return h('span', { class: ['size-4', icon], 'aria-hidden': 'true' })
50
- return h(icon as Component)
46
+ /** Display label, honoring state-dependent `getLabel` (e.g. merge vs split). */
47
+ function labelOf(item: CommandMenuItem): string {
48
+ void version.value
49
+ if (props.editor && item.getLabel) return item.getLabel(props.editor)
50
+ return item.label
51
51
  }
52
52
 
53
53
  /** A command item that ships its own interactive component (e.g. color picker). */
@@ -100,68 +100,80 @@ function run(item: CommandMenuItem, event?: MouseEvent) {
100
100
  })
101
101
  }
102
102
  }
103
+
104
+ const menuButtonSize = computed(() => props.buttonSize ?? 'xs')
103
105
  </script>
104
106
 
105
107
  <template>
106
- <template
107
- v-for="(item, index) in visibleItems"
108
- :key="`${'label' in item ? item.label : item.type}-${index}`"
109
- >
110
- <span
111
- v-if="isSeparator(item)"
112
- data-slot="menu-separator"
113
- class="mx-1 h-5 w-px bg-surface-gray-3"
114
- aria-hidden="true"
115
- />
116
- <component
117
- :is="item.component"
118
- v-else-if="isComponentItem(item) && editor"
119
- :editor="editor"
120
- >
121
- <template #default="trigger">
122
- <button
123
- type="button"
124
- class="inline-flex size-6 items-center justify-center rounded text-sm text-ink-gray-7 hover:bg-surface-gray-3 disabled:cursor-not-allowed disabled:opacity-50 aria-pressed:bg-surface-gray-3"
125
- :aria-label="item.label"
126
- :aria-pressed="trigger.isActive === true || isPressed(item)"
127
- :disabled="isItemDisabled(item)"
128
- @click="isItemDisabled(item) ? undefined : trigger.onClick()"
129
- >
130
- <ItemContent :item="item" />
131
- </button>
132
- </template>
133
- </component>
134
- <div
135
- v-else-if="isGroup(item)"
136
- data-slot="menu-group"
137
- class="flex items-center gap-1"
108
+ <!-- One shared provider so once any button's tooltip opens, neighbouring
109
+ buttons show theirs instantly (skip-delay) toolbar-friendly. Renderless,
110
+ so the parent's flex layout is unaffected. -->
111
+ <TooltipProvider>
112
+ <template
113
+ v-for="(item, index) in visibleItems"
114
+ :key="`${'label' in item ? item.label : item.type}-${index}`"
138
115
  >
139
- <span class="px-2 text-sm font-medium text-ink-gray-7">{{
140
- item.label
141
- }}</span>
142
- <button
143
- v-for="groupItem in item.items"
144
- :key="groupItem.label"
145
- type="button"
146
- class="inline-flex size-6 items-center justify-center rounded text-sm text-ink-gray-7 hover:bg-surface-gray-3 disabled:cursor-not-allowed disabled:opacity-50 aria-pressed:bg-surface-gray-3"
147
- :aria-label="groupItem.label"
148
- :aria-pressed="isPressed(groupItem)"
149
- :disabled="isItemDisabled(groupItem)"
150
- @click="run(groupItem, $event)"
116
+ <span
117
+ v-if="isSeparator(item)"
118
+ data-slot="menu-separator"
119
+ class="mx-1 h-5 w-px bg-surface-gray-3"
120
+ aria-hidden="true"
121
+ />
122
+ <component
123
+ :is="item.component"
124
+ v-else-if="isComponentItem(item) && editor"
125
+ :editor="editor"
151
126
  >
152
- <ItemContent :item="groupItem" />
153
- </button>
154
- </div>
155
- <button
156
- v-else
157
- type="button"
158
- class="inline-flex size-6 items-center justify-center rounded text-sm text-ink-gray-7 hover:bg-surface-gray-3 disabled:cursor-not-allowed disabled:opacity-50 aria-pressed:bg-surface-gray-3"
159
- :aria-label="item.label"
160
- :aria-pressed="isPressed(item)"
161
- :disabled="isItemDisabled(item)"
162
- @click="run(item, $event)"
163
- >
164
- <ItemContent :item="item" />
165
- </button>
166
- </template>
127
+ <template #default="trigger">
128
+ <Button
129
+ :size="menuButtonSize"
130
+ variant="ghost"
131
+ :icon="item.icon"
132
+ :label="item.label"
133
+ class="aria-pressed:bg-surface-gray-3"
134
+ :aria-pressed="trigger.isActive === true || isPressed(item)"
135
+ :disabled="isItemDisabled(item)"
136
+ @click="isItemDisabled(item) ? undefined : trigger.onClick()"
137
+ />
138
+ </template>
139
+ </component>
140
+ <div
141
+ v-else-if="isGroup(item)"
142
+ data-slot="menu-group"
143
+ class="flex items-center gap-1"
144
+ >
145
+ <span class="px-2 text-sm-medium text-ink-gray-7">{{
146
+ item.label
147
+ }}</span>
148
+ <Tooltip
149
+ v-for="groupItem in item.items"
150
+ :key="groupItem.label"
151
+ :text="groupItem.label"
152
+ >
153
+ <Button
154
+ :size="menuButtonSize"
155
+ variant="ghost"
156
+ :icon="groupItem.icon"
157
+ :label="groupItem.label"
158
+ class="aria-pressed:bg-surface-gray-3"
159
+ :aria-pressed="isPressed(groupItem)"
160
+ :disabled="isItemDisabled(groupItem)"
161
+ @click="run(groupItem, $event)"
162
+ />
163
+ </Tooltip>
164
+ </div>
165
+ <Tooltip v-else :text="labelOf(item)">
166
+ <Button
167
+ :size="menuButtonSize"
168
+ variant="ghost"
169
+ :icon="item.icon"
170
+ :label="labelOf(item)"
171
+ class="aria-pressed:bg-surface-gray-3"
172
+ :aria-pressed="isPressed(item)"
173
+ :disabled="isItemDisabled(item)"
174
+ @click="run(item, $event)"
175
+ />
176
+ </Tooltip>
177
+ </template>
178
+ </TooltipProvider>
167
179
  </template>
@@ -134,7 +134,7 @@ export const commandMeta = {
134
134
  isAvailable: hasMark('namedHighlight'),
135
135
  },
136
136
  image: {
137
- label: 'Image',
137
+ label: 'Image / Gallery',
138
138
  icon: 'lucide-image',
139
139
  isAvailable: (editor) =>
140
140
  hasNode('image')(editor) && hasCommand('selectAndUploadImage')(editor),
@@ -145,11 +145,19 @@ export const commandMeta = {
145
145
  isAvailable: (editor) =>
146
146
  hasNode('video')(editor) && hasCommand('selectAndUploadVideo')(editor),
147
147
  },
148
+ attachment: {
149
+ label: 'Attachment',
150
+ icon: 'lucide-paperclip',
151
+ isAvailable: (editor) =>
152
+ hasNode('attachment')(editor) &&
153
+ hasCommand('selectAndUploadFile')(editor),
154
+ },
148
155
  link: {
149
156
  label: 'Link',
150
157
  icon: 'lucide-link',
151
158
  isActive: (editor) => editor.isActive('link'),
152
- isAvailable: hasMark('link'),
159
+ isAvailable: (editor) =>
160
+ hasMark('link')(editor) && hasCommand('openLinkEditor')(editor),
153
161
  },
154
162
  table: {
155
163
  label: 'Table',
@@ -0,0 +1,115 @@
1
+ <script setup lang="ts">
2
+ import { computed, toRaw } from 'vue'
3
+ import { NodeViewWrapper, nodeViewProps } from '@tiptap/vue-3'
4
+ import { formatBytes } from '#utils/fileSize'
5
+ import {
6
+ abortUpload,
7
+ getUploadProgress,
8
+ } from '#molecules/editor/extensions/shared/media-upload-state'
9
+ import { useNodeViewEditable } from '#molecules/editor/composables/useNodeViewEditable'
10
+
11
+ const props = defineProps(nodeViewProps)
12
+
13
+ // Operate on the raw editor for commands (see MediaNodeView for the rationale:
14
+ // the proxied editor throws "Applying a mismatched transaction").
15
+ const editor = toRaw(props.editor)
16
+ const isEditable = useNodeViewEditable(editor)
17
+
18
+ const fileName = computed(() => props.node.attrs.fileName || 'Attachment')
19
+ const fileSize = computed(() => {
20
+ const size = Number(props.node.attrs.fileSize)
21
+ return Number.isFinite(size) && size > 0 ? formatBytes(size) : ''
22
+ })
23
+ const href = computed(() => props.node.attrs.src || undefined)
24
+ const isLoading = computed(() => Boolean(props.node.attrs.loading))
25
+ const error = computed(() => props.node.attrs.error as string | null)
26
+ const isUploaded = computed(() => Boolean(props.node.attrs.src))
27
+
28
+ const uploadId = computed(() => props.node.attrs.uploadId as string | undefined)
29
+ const progress = computed(() =>
30
+ uploadId.value ? getUploadProgress(uploadId.value) : undefined,
31
+ )
32
+ const percent = computed(() => progress.value?.percent ?? 0)
33
+
34
+ function cancel() {
35
+ if (uploadId.value) abortUpload(uploadId.value)
36
+ }
37
+
38
+ function retry() {
39
+ if (uploadId.value) editor.commands.reuploadAttachment(uploadId.value)
40
+ }
41
+
42
+ // Plain link is non-interactive while a chip is loading/errored.
43
+ const isLink = computed(() => isUploaded.value && !isLoading.value)
44
+ </script>
45
+
46
+ <template>
47
+ <!-- Gray-only chip (frappe-ui / Gameplan rule: never color shades). -->
48
+ <NodeViewWrapper
49
+ as="span"
50
+ class="inline-flex max-w-full items-center gap-1 align-baseline"
51
+ data-drag-handle
52
+ draggable="true"
53
+ >
54
+ <component
55
+ :is="isLink ? 'a' : 'span'"
56
+ class="inline-flex h-6 max-w-full items-center gap-1.5 rounded-lg border bg-surface-gray-2 px-2 text-sm no-underline"
57
+ :class="[
58
+ error
59
+ ? 'border-dashed border-outline-gray-2 text-ink-gray-6'
60
+ : 'border-outline-gray-2 text-ink-gray-8',
61
+ isLink ? 'cursor-pointer hover:bg-surface-gray-3' : 'cursor-default',
62
+ ]"
63
+ :href="isLink ? href : undefined"
64
+ :target="isLink ? '_blank' : undefined"
65
+ :rel="isLink ? 'noopener noreferrer' : undefined"
66
+ :download="isLink ? fileName : undefined"
67
+ contenteditable="false"
68
+ >
69
+ <span
70
+ v-if="isLoading"
71
+ class="lucide-loader-circle size-3.5 shrink-0 animate-spin text-ink-gray-6"
72
+ aria-hidden="true"
73
+ />
74
+ <span
75
+ v-else-if="error"
76
+ class="lucide-triangle-alert size-3.5 shrink-0 text-ink-gray-6"
77
+ aria-hidden="true"
78
+ />
79
+ <span
80
+ v-else
81
+ class="lucide-paperclip size-3.5 shrink-0 text-ink-gray-6"
82
+ aria-hidden="true"
83
+ />
84
+
85
+ <span class="max-w-64 truncate">{{ fileName }}</span>
86
+ <span v-if="fileSize && !error" class="shrink-0 text-ink-gray-5">
87
+ {{ fileSize }}
88
+ </span>
89
+ <span v-if="isLoading && percent > 0" class="shrink-0 text-ink-gray-5">
90
+ {{ percent }}%
91
+ </span>
92
+ </component>
93
+
94
+ <button
95
+ v-if="isLoading && isEditable"
96
+ type="button"
97
+ class="inline-flex items-center justify-center rounded p-0.5 text-ink-gray-6 hover:bg-surface-gray-3"
98
+ title="Cancel upload"
99
+ contenteditable="false"
100
+ @click="cancel"
101
+ >
102
+ <span class="lucide-x size-3.5 shrink-0" aria-hidden="true" />
103
+ </button>
104
+ <button
105
+ v-else-if="error && isEditable"
106
+ type="button"
107
+ class="inline-flex items-center justify-center rounded p-0.5 text-ink-gray-6 hover:bg-surface-gray-3"
108
+ title="Try again"
109
+ contenteditable="false"
110
+ @click="retry"
111
+ >
112
+ <span class="lucide-rotate-cw size-3.5 shrink-0" aria-hidden="true" />
113
+ </button>
114
+ </NodeViewWrapper>
115
+ </template>