@vonage/vivid 5.25.0 → 5.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (737) hide show
  1. package/accordion/index.cjs +1 -1
  2. package/accordion/index.js +8 -8
  3. package/accordion-item/index.cjs +1 -1
  4. package/action-group/index.cjs +3 -3
  5. package/action-group/index.js +10 -5
  6. package/alert/index.cjs +7 -7
  7. package/alert/index.js +47 -35
  8. package/audio-player/index.cjs +18 -18
  9. package/audio-player/index.js +15 -11
  10. package/avatar/index.cjs +9 -9
  11. package/avatar/index.js +27 -18
  12. package/badge/index.cjs +1 -1
  13. package/banner/index.cjs +5 -5
  14. package/banner/index.js +33 -27
  15. package/breadcrumb/index.cjs +1 -1
  16. package/breadcrumb/index.js +5 -1
  17. package/breadcrumb-item/index.cjs +1 -1
  18. package/breadcrumb-item/index.js +6 -6
  19. package/bundled/affix.cjs +3 -3
  20. package/bundled/affix.js +1 -1
  21. package/bundled/anchored.cjs +2 -2
  22. package/bundled/anchored.js +13 -1
  23. package/bundled/aria-binding-directive.cjs +1 -1
  24. package/bundled/aria-binding-directive.js +2 -2
  25. package/bundled/aria.cjs +1 -1
  26. package/bundled/base-color-picker.cjs +2 -2
  27. package/bundled/base-color-picker.js +1 -1
  28. package/bundled/base-progress.cjs +1 -1
  29. package/bundled/breadcrumb-item.cjs +1 -1
  30. package/bundled/button.cjs +1 -1
  31. package/bundled/calendar-event.cjs +1 -1
  32. package/bundled/calendar-event.js +17 -4
  33. package/bundled/calendar-picker.template.cjs +5 -5
  34. package/bundled/calendar-picker.template.js +53 -55
  35. package/bundled/char-count.cjs +2 -2
  36. package/bundled/children.cjs +1 -1
  37. package/bundled/children.js +1 -1
  38. package/bundled/class-names.cjs +1 -1
  39. package/bundled/component-enum.cjs +1 -0
  40. package/bundled/component-enum.js +9 -0
  41. package/bundled/data-grid.options.cjs +1 -1
  42. package/bundled/data-grid.options.js +7 -6
  43. package/bundled/decorate.cjs +1 -1
  44. package/bundled/decorate.js +1 -1
  45. package/bundled/definition.cjs +1 -1
  46. package/bundled/definition10.cjs +10 -20
  47. package/bundled/definition10.js +23 -72
  48. package/bundled/definition11.cjs +74 -10
  49. package/bundled/definition11.js +194 -24
  50. package/bundled/definition12.cjs +18 -70
  51. package/bundled/definition12.js +48 -186
  52. package/bundled/definition13.cjs +5 -22
  53. package/bundled/definition13.js +9 -58
  54. package/bundled/definition14.cjs +1 -5
  55. package/bundled/definition14.js +9 -9
  56. package/bundled/definition15.cjs +3 -3
  57. package/bundled/definition15.js +18 -18
  58. package/bundled/definition16.cjs +3 -3
  59. package/bundled/definition16.js +23 -17
  60. package/bundled/definition17.cjs +6 -6
  61. package/bundled/definition17.js +8 -8
  62. package/bundled/definition18.cjs +2 -2
  63. package/bundled/definition19.cjs +21 -21
  64. package/bundled/definition19.js +66 -61
  65. package/bundled/definition2.cjs +13 -1
  66. package/bundled/definition2.js +22 -185
  67. package/bundled/definition20.cjs +3 -3
  68. package/bundled/definition20.js +6 -7
  69. package/bundled/definition21.cjs +7 -7
  70. package/bundled/definition21.js +22 -23
  71. package/bundled/definition22.cjs +3 -3
  72. package/bundled/definition22.js +25 -25
  73. package/bundled/definition23.cjs +3 -3
  74. package/bundled/definition23.js +26 -8
  75. package/bundled/definition24.cjs +2 -2
  76. package/bundled/definition24.js +1 -1
  77. package/bundled/definition25.cjs +5 -5
  78. package/bundled/definition25.js +16 -11
  79. package/bundled/definition3.cjs +25 -12
  80. package/bundled/definition3.js +90 -21
  81. package/bundled/definition4.cjs +29 -25
  82. package/bundled/definition4.js +50 -89
  83. package/bundled/definition5.cjs +28 -29
  84. package/bundled/definition5.js +143 -45
  85. package/bundled/definition6.cjs +6 -29
  86. package/bundled/definition6.js +20 -130
  87. package/bundled/definition7.cjs +14 -6
  88. package/bundled/definition7.js +159 -20
  89. package/bundled/definition8.cjs +22 -14
  90. package/bundled/definition8.js +88 -144
  91. package/bundled/definition9.cjs +20 -22
  92. package/bundled/definition9.js +54 -80
  93. package/bundled/delegates-aria.cjs +1 -1
  94. package/bundled/delegates-aria.js +3 -2
  95. package/bundled/dialog.cjs +1 -1
  96. package/bundled/dialog.js +1 -1
  97. package/bundled/divider.cjs +1 -1
  98. package/bundled/divider.js +9 -9
  99. package/bundled/dom.cjs +1 -1
  100. package/bundled/enums.cjs +1 -1
  101. package/bundled/extractOptions.cjs +1 -1
  102. package/bundled/feedback-message.cjs +8 -0
  103. package/bundled/feedback-message.js +41 -0
  104. package/bundled/floating-ui.dom.cjs +1 -1
  105. package/bundled/floating-ui.dom.js +163 -197
  106. package/bundled/form-associated.cjs +1 -1
  107. package/bundled/form-associated.js +3 -4
  108. package/bundled/form-element.cjs +1 -1
  109. package/bundled/host-semantics.cjs +1 -1
  110. package/bundled/icon.cjs +1 -1
  111. package/bundled/kbd-shortcut.cjs +1 -1
  112. package/bundled/key-codes.cjs +1 -1
  113. package/bundled/linkable.cjs +2 -2
  114. package/bundled/listbox.cjs +1 -1
  115. package/bundled/listbox.js +3 -5
  116. package/bundled/localized.cjs +1 -1
  117. package/bundled/localized.js +33 -32
  118. package/bundled/mixins.cjs +9 -16
  119. package/bundled/mixins.js +23 -57
  120. package/bundled/numberConverter.cjs +2 -2
  121. package/bundled/numberConverter.js +1 -1
  122. package/bundled/numbers.cjs +1 -1
  123. package/bundled/optgroup.cjs +1 -1
  124. package/bundled/option.cjs +1 -1
  125. package/bundled/option.js +9 -7
  126. package/bundled/picker-field.template.cjs +2 -2
  127. package/bundled/picker-field.template.js +8 -8
  128. package/bundled/platform.cjs +1 -1
  129. package/bundled/playbackRates.cjs +1 -1
  130. package/bundled/ref.cjs +1 -1
  131. package/bundled/ref.js +1 -1
  132. package/bundled/render-in-light-dom.cjs +1 -1
  133. package/bundled/render-in-light-dom.js +1 -1
  134. package/bundled/repeat.cjs +1 -1
  135. package/bundled/repeat.js +16 -15
  136. package/bundled/scrollIntoView.cjs +1 -1
  137. package/bundled/scrollIntoView.js +1 -3
  138. package/bundled/single-date-picker.cjs +1 -1
  139. package/bundled/single-value-picker.cjs +1 -1
  140. package/bundled/single-value-picker.js +1 -1
  141. package/bundled/slider.template.cjs +12 -12
  142. package/bundled/slider.template.js +209 -32
  143. package/bundled/slottable-request.cjs +3 -3
  144. package/bundled/slottable-request.js +26 -17
  145. package/bundled/slotted.cjs +1 -1
  146. package/bundled/slotted.js +1 -1
  147. package/bundled/text-field.cjs +1 -1
  148. package/bundled/text-field.js +1 -1
  149. package/bundled/time-selection-picker.template.cjs +4 -4
  150. package/bundled/time-selection-picker.template.js +10 -7
  151. package/bundled/trapped-focus.cjs +1 -1
  152. package/bundled/utils.cjs +1 -1
  153. package/bundled/vivid-element.cjs +3 -3
  154. package/bundled/vivid-element.js +397 -358
  155. package/bundled/when.cjs +1 -1
  156. package/bundled/when.js +1 -1
  157. package/bundled/with-contextual-help.cjs +1 -1
  158. package/bundled/with-contextual-help.js +1 -1
  159. package/bundled/with-error-text.cjs +1 -1
  160. package/bundled/with-success-text.cjs +1 -1
  161. package/button/index.cjs +1 -1
  162. package/button/index.js +1 -1
  163. package/calendar/index.cjs +1 -1
  164. package/calendar/index.js +7 -7
  165. package/calendar-event/index.cjs +2 -2
  166. package/calendar-event/index.js +10 -8
  167. package/card/index.cjs +4 -2
  168. package/card/index.js +12 -7
  169. package/checkbox/index.cjs +1 -1
  170. package/color-picker/index.cjs +17 -17
  171. package/color-picker/index.js +19 -17
  172. package/combobox/index.cjs +9 -9
  173. package/combobox/index.js +46 -44
  174. package/contextual-help/index.cjs +1 -1
  175. package/contextual-help/index.js +1 -1
  176. package/country/index.cjs +1 -1
  177. package/country-group/index.cjs +1 -1
  178. package/country-group/index.js +8 -4
  179. package/custom-elements.json +7322 -7254
  180. package/data-grid/index.cjs +6 -6
  181. package/data-grid/index.js +92 -99
  182. package/date-picker/index.cjs +1 -1
  183. package/date-picker/index.js +10 -6
  184. package/date-range-picker/index.cjs +1 -1
  185. package/date-range-picker/index.js +13 -9
  186. package/date-time-picker/index.cjs +1 -1
  187. package/date-time-picker/index.js +11 -7
  188. package/dial-pad/index.cjs +4 -3
  189. package/dial-pad/index.js +14 -9
  190. package/dialog/index.cjs +1 -1
  191. package/dialog/index.js +9 -6
  192. package/divider/index.cjs +1 -1
  193. package/elevation/definition.cjs +1 -0
  194. package/elevation/definition.js +2 -2
  195. package/elevation/index.cjs +1 -1
  196. package/elevation/index.js +1 -1
  197. package/empty-state/index.cjs +3 -3
  198. package/empty-state/index.js +18 -6
  199. package/fab/index.cjs +3 -3
  200. package/fab/index.js +14 -6
  201. package/file-picker/index.cjs +8 -10
  202. package/file-picker/index.js +25 -22
  203. package/flag/index.cjs +1 -1
  204. package/flag/index.js +7 -3
  205. package/form-field/definition.cjs +5 -0
  206. package/form-field/definition.js +2 -0
  207. package/form-field/index.cjs +29 -0
  208. package/form-field/index.js +57 -0
  209. package/header/definition.cjs +1 -1
  210. package/header/definition.js +1 -1
  211. package/header/index.cjs +1 -1
  212. package/header/index.js +9 -5
  213. package/icon/index.cjs +1 -1
  214. package/icon/index.js +1 -1
  215. package/index.cjs +159 -154
  216. package/index.js +42 -40
  217. package/kbd-key/definition.cjs +1 -1
  218. package/kbd-key/definition.js +1 -1
  219. package/kbd-key/index.cjs +3 -3
  220. package/kbd-key/index.js +22 -13
  221. package/kbd-shortcut/definition.cjs +1 -1
  222. package/kbd-shortcut/definition.js +1 -1
  223. package/kbd-shortcut/index.cjs +1 -1
  224. package/kbd-shortcut/index.js +6 -6
  225. package/layout/definition.cjs +1 -1
  226. package/layout/definition.js +1 -1
  227. package/layout/index.cjs +1 -1
  228. package/layout/index.js +7 -3
  229. package/lib/accordion-item/accordion-item.d.ts +11 -6
  230. package/lib/action-group/action-group.d.ts +10 -5
  231. package/lib/alert/alert.d.ts +15 -18
  232. package/lib/avatar/avatar.d.ts +16 -7
  233. package/lib/badge/badge.d.ts +17 -7
  234. package/lib/banner/banner.d.ts +18 -20
  235. package/lib/button/button.d.ts +25 -16
  236. package/lib/calendar-event/calendar-event.d.ts +14 -7
  237. package/lib/checkbox/checkbox.d.ts +31 -28
  238. package/lib/combobox/combobox.d.ts +37 -32
  239. package/lib/components.d.ts +1 -0
  240. package/lib/data-grid/data-grid.options.d.ts +6 -1
  241. package/lib/dial-pad/locale.d.ts +1 -0
  242. package/lib/divider/divider.d.ts +9 -6
  243. package/lib/elevation/definition.d.ts +2 -0
  244. package/lib/empty-state/empty-state.d.ts +7 -2
  245. package/lib/fab/fab.d.ts +3 -2
  246. package/lib/form-field/definition.d.ts +4 -0
  247. package/lib/form-field/form-field.d.ts +6 -0
  248. package/lib/form-field/form-field.template.d.ts +3 -0
  249. package/lib/kbd-key/kbd-key.d.ts +7 -2
  250. package/lib/listbox/listbox.d.ts +1 -0
  251. package/lib/menu-item/menu-item.d.ts +17 -14
  252. package/lib/nav-disclosure/nav-disclosure.d.ts +18 -11
  253. package/lib/nav-item/nav-item.d.ts +19 -12
  254. package/lib/note/note.d.ts +10 -6
  255. package/lib/number-field/number-field.d.ts +45 -40
  256. package/lib/option/option.d.ts +13 -10
  257. package/lib/popup/definition.d.ts +2 -0
  258. package/lib/progress/progress.d.ts +10 -5
  259. package/lib/progress-ring/progress-ring.d.ts +9 -5
  260. package/lib/radio/radio.d.ts +18 -15
  261. package/lib/range-slider/range-slider.d.ts +19 -15
  262. package/lib/rich-text-editor/rich-text-editor.d.ts +9 -5
  263. package/lib/rich-text-editor/rte/utils/ui.d.ts +2 -1
  264. package/lib/searchable-select/option-tag.d.ts +12 -7
  265. package/lib/searchable-select/searchable-select.d.ts +7 -2
  266. package/lib/select/select.d.ts +45 -40
  267. package/lib/selectable-box/selectable-box.d.ts +9 -5
  268. package/lib/slider/slider.d.ts +18 -14
  269. package/lib/split-button/split-button.d.ts +24 -15
  270. package/lib/status/status.d.ts +10 -7
  271. package/lib/switch/switch.d.ts +13 -9
  272. package/lib/tab/tab.d.ts +19 -14
  273. package/lib/tabs/tabs.d.ts +6 -3
  274. package/lib/tag/tag.d.ts +24 -15
  275. package/lib/tag-name-map.d.ts +2 -1
  276. package/lib/text-field/text-field.d.ts +46 -41
  277. package/lib/video-player/__tests__/video-fixtures.d.ts +3 -0
  278. package/listbox/definition.cjs +1 -1
  279. package/listbox/definition.js +1 -1
  280. package/listbox/index.cjs +7 -5
  281. package/listbox/index.js +24 -10
  282. package/locales/de-DE.cjs +34 -33
  283. package/locales/de-DE.js +34 -33
  284. package/locales/en-GB.cjs +34 -33
  285. package/locales/en-GB.js +34 -33
  286. package/locales/ja-JP.cjs +35 -33
  287. package/locales/ja-JP.js +35 -33
  288. package/locales/zh-CN.cjs +34 -33
  289. package/locales/zh-CN.js +34 -33
  290. package/menu/index.cjs +1 -1
  291. package/menu-item/index.cjs +1 -1
  292. package/nav/definition.cjs +1 -1
  293. package/nav/definition.js +1 -1
  294. package/nav/index.cjs +1 -1
  295. package/nav/index.js +6 -4
  296. package/nav-disclosure/definition.cjs +1 -1
  297. package/nav-disclosure/definition.js +1 -1
  298. package/nav-disclosure/index.cjs +3 -3
  299. package/nav-disclosure/index.js +13 -8
  300. package/nav-item/definition.cjs +1 -1
  301. package/nav-item/definition.js +1 -1
  302. package/nav-item/index.cjs +2 -2
  303. package/nav-item/index.js +15 -10
  304. package/note/definition.cjs +1 -1
  305. package/note/definition.js +1 -1
  306. package/note/index.cjs +6 -4
  307. package/note/index.js +22 -9
  308. package/number-field/definition.cjs +1 -1
  309. package/number-field/definition.js +1 -1
  310. package/number-field/index.cjs +11 -11
  311. package/number-field/index.js +41 -36
  312. package/optgroup/index.cjs +1 -1
  313. package/option/index.cjs +1 -1
  314. package/package.json +29 -36
  315. package/pagination/definition.cjs +1 -1
  316. package/pagination/definition.js +1 -1
  317. package/pagination/index.cjs +1 -1
  318. package/pagination/index.js +9 -9
  319. package/platform-switch/definition.cjs +1 -1
  320. package/platform-switch/definition.js +1 -1
  321. package/platform-switch/index.cjs +1 -1
  322. package/platform-switch/index.js +6 -2
  323. package/popover/definition.cjs +1 -1
  324. package/popover/definition.js +1 -1
  325. package/popover/index.cjs +2 -2
  326. package/popover/index.js +43 -35
  327. package/popup/definition.cjs +1 -0
  328. package/popup/definition.js +2 -2
  329. package/popup/index.cjs +1 -1
  330. package/popup/index.js +1 -1
  331. package/progress/definition.cjs +1 -1
  332. package/progress/definition.js +1 -1
  333. package/progress/index.cjs +7 -7
  334. package/progress/index.js +21 -11
  335. package/progress-ring/index.cjs +1 -1
  336. package/progress-ring/index.js +1 -1
  337. package/radio/definition.cjs +1 -1
  338. package/radio/definition.js +1 -1
  339. package/radio/index.cjs +1 -1
  340. package/radio-group/definition.cjs +1 -1
  341. package/radio-group/definition.js +1 -1
  342. package/radio-group/index.cjs +2 -2
  343. package/radio-group/index.js +14 -9
  344. package/range-slider/definition.cjs +1 -1
  345. package/range-slider/definition.js +1 -1
  346. package/range-slider/index.cjs +8 -8
  347. package/range-slider/index.js +31 -32
  348. package/rich-text-editor/definition.cjs +1 -1
  349. package/rich-text-editor/definition.js +1 -1
  350. package/rich-text-editor/index.cjs +13 -10
  351. package/rich-text-editor/index.js +1942 -1711
  352. package/rich-text-view/definition.cjs +1 -1
  353. package/rich-text-view/definition.js +1 -1
  354. package/rich-text-view/index.cjs +1 -1
  355. package/rich-text-view/index.js +6 -4
  356. package/searchable-select/definition.cjs +1 -1
  357. package/searchable-select/definition.js +1 -1
  358. package/searchable-select/index.cjs +22 -22
  359. package/searchable-select/index.js +97 -93
  360. package/select/definition.cjs +1 -1
  361. package/select/definition.js +1 -1
  362. package/select/index.cjs +1 -1
  363. package/selectable-box/definition.cjs +1 -1
  364. package/selectable-box/definition.js +1 -1
  365. package/selectable-box/index.cjs +8 -8
  366. package/selectable-box/index.js +24 -20
  367. package/shared/patterns/anchored.d.ts +2 -0
  368. package/shared/styles/appearance.d.ts +2 -0
  369. package/shared/styles/connotation.d.ts +2 -0
  370. package/shared/styles/connotationOverrides.d.ts +1 -0
  371. package/shared/utils/component-enum.d.ts +7 -0
  372. package/side-drawer/definition.cjs +1 -1
  373. package/side-drawer/definition.js +1 -1
  374. package/side-drawer/index.cjs +1 -1
  375. package/side-drawer/index.js +10 -7
  376. package/simple-color-picker/definition.cjs +1 -1
  377. package/simple-color-picker/definition.js +1 -1
  378. package/simple-color-picker/index.cjs +2 -2
  379. package/simple-color-picker/index.js +20 -20
  380. package/slider/definition.cjs +2 -1
  381. package/slider/definition.js +2 -1
  382. package/slider/index.cjs +1 -1
  383. package/slider/index.js +1 -1
  384. package/split-button/definition.cjs +1 -1
  385. package/split-button/definition.js +1 -1
  386. package/split-button/index.cjs +9 -7
  387. package/split-button/index.js +58 -37
  388. package/status/definition.cjs +1 -1
  389. package/status/definition.js +1 -1
  390. package/status/index.cjs +5 -5
  391. package/status/index.js +22 -13
  392. package/switch/definition.cjs +1 -1
  393. package/switch/definition.js +1 -1
  394. package/switch/index.cjs +3 -3
  395. package/switch/index.js +22 -11
  396. package/tab/definition.cjs +1 -1
  397. package/tab/definition.js +1 -1
  398. package/tab/index.cjs +1 -1
  399. package/tab/index.js +1 -1
  400. package/tab-panel/definition.cjs +1 -1
  401. package/tab-panel/definition.js +1 -1
  402. package/tab-panel/index.cjs +1 -1
  403. package/tab-panel/index.js +1 -1
  404. package/table/definition.cjs +1 -1
  405. package/table/definition.js +1 -1
  406. package/table/index.cjs +4 -2
  407. package/table/index.js +12 -10
  408. package/tabs/definition.cjs +1 -1
  409. package/tabs/definition.js +1 -1
  410. package/tabs/index.cjs +4 -4
  411. package/tabs/index.js +32 -30
  412. package/tag/definition.cjs +1 -1
  413. package/tag/definition.js +1 -1
  414. package/tag/index.cjs +6 -6
  415. package/tag/index.js +28 -12
  416. package/tag-group/definition.cjs +1 -1
  417. package/tag-group/definition.js +1 -1
  418. package/tag-group/index.cjs +1 -1
  419. package/tag-group/index.js +6 -4
  420. package/text-area/definition.cjs +1 -1
  421. package/text-area/definition.js +1 -1
  422. package/text-area/index.cjs +5 -5
  423. package/text-area/index.js +18 -15
  424. package/text-field/index.cjs +1 -1
  425. package/text-field/index.js +1 -1
  426. package/time-picker/definition.cjs +1 -1
  427. package/time-picker/definition.js +1 -1
  428. package/time-picker/index.cjs +1 -1
  429. package/time-picker/index.js +9 -6
  430. package/toggletip/index.cjs +1 -1
  431. package/toggletip/index.js +1 -1
  432. package/tooltip/index.cjs +1 -1
  433. package/tooltip/index.js +1 -1
  434. package/tree-item/definition.cjs +1 -1
  435. package/tree-item/definition.js +1 -1
  436. package/tree-item/index.cjs +1 -1
  437. package/tree-item/index.js +1 -1
  438. package/tree-view/definition.cjs +1 -1
  439. package/tree-view/definition.js +1 -1
  440. package/tree-view/index.cjs +1 -1
  441. package/tree-view/index.js +7 -5
  442. package/unbundled/affix.cjs +0 -1
  443. package/unbundled/anchored.cjs +39 -1
  444. package/unbundled/anchored.js +28 -1
  445. package/unbundled/aria-binding-directive.cjs +2 -2
  446. package/unbundled/aria-binding-directive.js +2 -1
  447. package/unbundled/base-color-picker.cjs +0 -1
  448. package/unbundled/base-progress.cjs +0 -1
  449. package/unbundled/breadcrumb-item.cjs +0 -1
  450. package/unbundled/button.cjs +0 -1
  451. package/unbundled/calendar-event.cjs +29 -1
  452. package/unbundled/calendar-event.js +18 -1
  453. package/unbundled/calendar-picker.template.cjs +109 -91
  454. package/unbundled/calendar-picker.template.js +109 -90
  455. package/unbundled/char-count.cjs +0 -1
  456. package/unbundled/component-enum.cjs +18 -0
  457. package/unbundled/component-enum.js +13 -0
  458. package/unbundled/data-grid.options.cjs +8 -0
  459. package/unbundled/data-grid.options.js +3 -1
  460. package/unbundled/decorate.cjs +1 -1
  461. package/unbundled/decorate.js +1 -1
  462. package/unbundled/definition.cjs +1 -2
  463. package/unbundled/definition.js +1 -1
  464. package/unbundled/definition10.cjs +2 -343
  465. package/unbundled/definition10.js +4 -338
  466. package/unbundled/definition11.cjs +6 -7
  467. package/unbundled/definition11.js +6 -6
  468. package/unbundled/definition12.cjs +4 -4
  469. package/unbundled/definition12.js +5 -4
  470. package/unbundled/definition13.cjs +2 -2
  471. package/unbundled/definition13.js +2 -1
  472. package/unbundled/definition14.cjs +11 -3
  473. package/unbundled/definition14.js +11 -2
  474. package/unbundled/definition15.cjs +26 -5
  475. package/unbundled/definition15.js +26 -4
  476. package/unbundled/definition16.cjs +20 -14
  477. package/unbundled/definition16.js +20 -13
  478. package/unbundled/definition17.cjs +0 -1
  479. package/unbundled/definition18.cjs +4 -3
  480. package/unbundled/definition18.js +4 -2
  481. package/unbundled/definition19.cjs +2 -3
  482. package/unbundled/definition19.js +9 -8
  483. package/unbundled/definition2.cjs +8 -3
  484. package/unbundled/definition2.js +8 -2
  485. package/unbundled/definition20.cjs +1 -2
  486. package/unbundled/definition20.js +7 -6
  487. package/unbundled/definition21.cjs +4 -3
  488. package/unbundled/definition21.js +4 -2
  489. package/unbundled/definition22.cjs +0 -1
  490. package/unbundled/definition23.cjs +12 -6
  491. package/unbundled/definition23.js +11 -4
  492. package/unbundled/definition24.cjs +4 -4
  493. package/unbundled/definition24.js +5 -4
  494. package/unbundled/definition25.cjs +2 -3
  495. package/unbundled/definition25.js +2 -2
  496. package/unbundled/definition26.cjs +6 -4
  497. package/unbundled/definition26.js +5 -2
  498. package/unbundled/definition27.cjs +2 -2
  499. package/unbundled/definition27.js +2 -1
  500. package/unbundled/definition28.cjs +3 -3
  501. package/unbundled/definition28.js +2 -1
  502. package/unbundled/definition29.cjs +2 -3
  503. package/unbundled/definition29.js +3 -3
  504. package/unbundled/definition3.cjs +5 -6
  505. package/unbundled/definition3.js +5 -5
  506. package/unbundled/definition30.cjs +0 -1
  507. package/unbundled/definition31.cjs +15 -13
  508. package/unbundled/definition31.js +14 -11
  509. package/unbundled/definition32.cjs +0 -1
  510. package/unbundled/definition33.cjs +0 -1
  511. package/unbundled/definition34.cjs +0 -1
  512. package/unbundled/definition35.cjs +39 -51
  513. package/unbundled/definition35.js +40 -51
  514. package/unbundled/definition36.cjs +2 -3
  515. package/unbundled/definition36.js +9 -8
  516. package/unbundled/definition37.cjs +0 -1
  517. package/unbundled/definition38.cjs +0 -1
  518. package/unbundled/definition39.cjs +0 -1
  519. package/unbundled/definition4.cjs +4 -3
  520. package/unbundled/definition4.js +11 -6
  521. package/unbundled/definition40.cjs +5 -4
  522. package/unbundled/definition40.js +5 -3
  523. package/unbundled/definition41.cjs +0 -1
  524. package/unbundled/definition42.cjs +11 -3
  525. package/unbundled/definition42.js +11 -2
  526. package/unbundled/definition43.cjs +7 -3
  527. package/unbundled/definition43.js +7 -2
  528. package/unbundled/definition44.cjs +12 -11
  529. package/unbundled/definition44.js +11 -9
  530. package/unbundled/definition45.cjs +73 -52
  531. package/unbundled/definition45.js +69 -47
  532. package/unbundled/definition46.cjs +53 -46
  533. package/unbundled/definition46.js +49 -41
  534. package/unbundled/definition47.cjs +40 -165
  535. package/unbundled/definition47.js +36 -160
  536. package/unbundled/definition48.cjs +177 -32
  537. package/unbundled/definition48.js +174 -22
  538. package/unbundled/definition49.cjs +32 -596
  539. package/unbundled/definition49.js +29 -591
  540. package/unbundled/definition5.cjs +9 -3
  541. package/unbundled/definition5.js +15 -7
  542. package/unbundled/definition50.cjs +609 -78
  543. package/unbundled/definition50.js +605 -75
  544. package/unbundled/definition51.cjs +74 -34
  545. package/unbundled/definition51.js +70 -29
  546. package/unbundled/definition52.cjs +59 -24
  547. package/unbundled/definition52.js +57 -18
  548. package/unbundled/definition53.cjs +23 -40
  549. package/unbundled/definition53.js +19 -35
  550. package/unbundled/definition54.cjs +40 -316
  551. package/unbundled/definition54.js +38 -313
  552. package/unbundled/definition55.cjs +305 -196
  553. package/unbundled/definition55.js +301 -191
  554. package/unbundled/definition56.cjs +210 -41
  555. package/unbundled/definition56.js +206 -36
  556. package/unbundled/definition57.cjs +42 -271
  557. package/unbundled/definition57.js +38 -266
  558. package/unbundled/definition58.cjs +286 -51
  559. package/unbundled/definition58.js +283 -46
  560. package/unbundled/definition59.cjs +58 -147
  561. package/unbundled/definition59.js +59 -144
  562. package/unbundled/definition6.cjs +20 -6
  563. package/unbundled/definition6.js +20 -5
  564. package/unbundled/definition60.cjs +129 -226
  565. package/unbundled/definition60.js +126 -222
  566. package/unbundled/definition61.cjs +200 -420
  567. package/unbundled/definition61.js +197 -416
  568. package/unbundled/definition62.cjs +442 -3743
  569. package/unbundled/definition62.js +433 -3570
  570. package/unbundled/definition63.cjs +3729 -729
  571. package/unbundled/definition63.js +3558 -721
  572. package/unbundled/definition64.cjs +784 -98
  573. package/unbundled/definition64.js +781 -94
  574. package/unbundled/definition65.cjs +100 -1003
  575. package/unbundled/definition65.js +98 -997
  576. package/unbundled/definition66.cjs +996 -94
  577. package/unbundled/definition66.js +992 -89
  578. package/unbundled/definition67.cjs +111 -74
  579. package/unbundled/definition67.js +107 -63
  580. package/unbundled/definition68.cjs +69 -157
  581. package/unbundled/definition68.js +65 -152
  582. package/unbundled/definition69.cjs +156 -120
  583. package/unbundled/definition69.js +152 -115
  584. package/unbundled/definition7.cjs +0 -1
  585. package/unbundled/definition7.js +10 -4
  586. package/unbundled/definition70.cjs +154 -50
  587. package/unbundled/definition70.js +150 -45
  588. package/unbundled/definition71.cjs +58 -86
  589. package/unbundled/definition71.js +57 -81
  590. package/unbundled/definition72.cjs +99 -20
  591. package/unbundled/definition72.js +98 -15
  592. package/unbundled/definition73.cjs +20 -89
  593. package/unbundled/definition73.js +16 -84
  594. package/unbundled/definition74.cjs +79 -296
  595. package/unbundled/definition74.js +73 -217
  596. package/unbundled/definition75.cjs +291 -312
  597. package/unbundled/definition75.js +221 -306
  598. package/unbundled/definition76.cjs +328 -27
  599. package/unbundled/definition76.js +320 -23
  600. package/unbundled/definition77.cjs +27 -125
  601. package/unbundled/definition77.js +23 -120
  602. package/unbundled/definition78.cjs +120 -233
  603. package/unbundled/definition78.js +116 -228
  604. package/unbundled/definition79.cjs +258 -26
  605. package/unbundled/definition79.js +249 -23
  606. package/unbundled/definition8.cjs +17 -10
  607. package/unbundled/definition8.js +17 -9
  608. package/unbundled/definition80.cjs +29 -149
  609. package/unbundled/definition80.js +27 -134
  610. package/unbundled/definition81.cjs +118 -174
  611. package/unbundled/definition81.js +109 -169
  612. package/unbundled/definition82.cjs +180 -477
  613. package/unbundled/definition82.js +178 -472
  614. package/unbundled/definition83.cjs +517 -0
  615. package/unbundled/definition83.js +498 -0
  616. package/unbundled/definition9.cjs +4 -3
  617. package/unbundled/definition9.js +4 -2
  618. package/unbundled/delegates-aria.cjs +4 -2
  619. package/unbundled/delegates-aria.js +4 -2
  620. package/unbundled/divider.cjs +8 -3
  621. package/unbundled/divider.js +3 -3
  622. package/unbundled/en-US.cjs +34 -33
  623. package/unbundled/en-US.js +34 -33
  624. package/unbundled/feedback-message.cjs +59 -0
  625. package/unbundled/feedback-message.js +48 -0
  626. package/unbundled/form-associated.cjs +1 -4
  627. package/unbundled/form-associated.js +1 -3
  628. package/unbundled/form-element.cjs +0 -1
  629. package/unbundled/icon.cjs +0 -1
  630. package/unbundled/kbd-shortcut.cjs +0 -1
  631. package/unbundled/linkable.cjs +0 -1
  632. package/unbundled/listbox.cjs +0 -2
  633. package/unbundled/listbox.js +0 -1
  634. package/unbundled/localized.cjs +0 -1
  635. package/unbundled/mixins.cjs +3 -54
  636. package/unbundled/mixins.js +3 -47
  637. package/unbundled/numberConverter.cjs +8 -3
  638. package/unbundled/numberConverter.js +8 -3
  639. package/unbundled/optgroup.cjs +0 -1
  640. package/unbundled/option.cjs +8 -1
  641. package/unbundled/option.js +3 -1
  642. package/unbundled/picker-field.template.cjs +1 -2
  643. package/unbundled/picker-field.template.js +1 -1
  644. package/unbundled/randomId.cjs +0 -1
  645. package/unbundled/{chunk.cjs → rolldown-runtime.cjs} +1 -1
  646. package/unbundled/scrollIntoView.cjs +0 -1
  647. package/unbundled/scrollIntoView.js +0 -1
  648. package/unbundled/slider.template.cjs +340 -2
  649. package/unbundled/slider.template.js +338 -5
  650. package/unbundled/text-field.cjs +1 -1
  651. package/unbundled/text-field.js +1 -1
  652. package/unbundled/time-selection-picker.template.cjs +2 -3
  653. package/unbundled/time-selection-picker.template.js +2 -2
  654. package/unbundled/vivid-element.cjs +63 -4
  655. package/unbundled/vivid-element.js +63 -3
  656. package/unbundled/with-contextual-help.cjs +0 -1
  657. package/unbundled/with-error-text.cjs +0 -1
  658. package/unbundled/with-success-text.cjs +0 -1
  659. package/video-player/definition.cjs +1 -1
  660. package/video-player/definition.js +1 -1
  661. package/video-player/index.cjs +31 -31
  662. package/video-player/index.js +2094 -2085
  663. package/visually-hidden/index.cjs +1 -1
  664. package/vivid.api.json +488 -1165
  665. package/lib/accordion/variations.browser-spec.d.ts +0 -1
  666. package/lib/action-group/variations.browser-spec.d.ts +0 -1
  667. package/lib/alert/variations.browser-spec.d.ts +0 -1
  668. package/lib/audio-player/variations.browser-spec.d.ts +0 -1
  669. package/lib/avatar/variations.browser-spec.d.ts +0 -1
  670. package/lib/badge/variations.browser-spec.d.ts +0 -1
  671. package/lib/banner/variations.browser-spec.d.ts +0 -1
  672. package/lib/breadcrumb-item/variations.browser-spec.d.ts +0 -1
  673. package/lib/button/variations.browser-spec.d.ts +0 -1
  674. package/lib/calendar/variations.browser-spec.d.ts +0 -1
  675. package/lib/calendar-event/variations.browser-spec.d.ts +0 -1
  676. package/lib/card/variations.browser-spec.d.ts +0 -1
  677. package/lib/checkbox/variations.browser-spec.d.ts +0 -1
  678. package/lib/color-picker/variations.browser-spec.d.ts +0 -1
  679. package/lib/combobox/variations.browser-spec.d.ts +0 -1
  680. package/lib/contextual-help/variations.browser-spec.d.ts +0 -1
  681. package/lib/country/variations.browser-spec.d.ts +0 -1
  682. package/lib/data-grid/variations.browser-spec.d.ts +0 -1
  683. package/lib/date-picker/variations.browser-spec.d.ts +0 -1
  684. package/lib/date-range-picker/variations.browser-spec.d.ts +0 -1
  685. package/lib/date-time-picker/variations.browser-spec.d.ts +0 -1
  686. package/lib/dial-pad/variations.browser-spec.d.ts +0 -1
  687. package/lib/dialog/variations.browser-spec.d.ts +0 -1
  688. package/lib/divider/variations.browser-spec.d.ts +0 -1
  689. package/lib/empty-state/variations.browser-spec.d.ts +0 -1
  690. package/lib/fab/variations.browser-spec.d.ts +0 -1
  691. package/lib/file-picker/variations.browser-spec.d.ts +0 -1
  692. package/lib/flag/variations.browser-spec.d.ts +0 -1
  693. package/lib/header/variations.browser-spec.d.ts +0 -1
  694. package/lib/icon/variations.browser-spec.d.ts +0 -1
  695. package/lib/kbd-key/variations.browser-spec.d.ts +0 -1
  696. package/lib/kbd-shortcut/variations.browser-spec.d.ts +0 -1
  697. package/lib/layout/variations.browser-spec.d.ts +0 -1
  698. package/lib/listbox/variations.browser-spec.d.ts +0 -1
  699. package/lib/menu/variations.browser-spec.d.ts +0 -1
  700. package/lib/menu-item/variations.browser-spec.d.ts +0 -1
  701. package/lib/nav/variations.browser-spec.d.ts +0 -1
  702. package/lib/nav-disclosure/variations.browser-spec.d.ts +0 -1
  703. package/lib/nav-item/variations.browser-spec.d.ts +0 -1
  704. package/lib/note/variations.browser-spec.d.ts +0 -1
  705. package/lib/number-field/variations.browser-spec.d.ts +0 -1
  706. package/lib/optgroup/variations.browser-spec.d.ts +0 -1
  707. package/lib/option/variations.browser-spec.d.ts +0 -1
  708. package/lib/pagination/variations.browser-spec.d.ts +0 -1
  709. package/lib/popover/variations.browser-spec.d.ts +0 -1
  710. package/lib/progress/variations.browser-spec.d.ts +0 -1
  711. package/lib/progress-ring/variations.browser-spec.d.ts +0 -1
  712. package/lib/radio/variations.browser-spec.d.ts +0 -1
  713. package/lib/radio-group/variations.browser-spec.d.ts +0 -1
  714. package/lib/range-slider/variations.browser-spec.d.ts +0 -1
  715. package/lib/rich-text-editor/variations.browser-spec.d.ts +0 -1
  716. package/lib/rich-text-view/variations.browser-spec.d.ts +0 -1
  717. package/lib/searchable-select/variations.browser-spec.d.ts +0 -1
  718. package/lib/select/variations.browser-spec.d.ts +0 -1
  719. package/lib/selectable-box/variations.browser-spec.d.ts +0 -1
  720. package/lib/side-drawer/variations.browser-spec.d.ts +0 -1
  721. package/lib/simple-color-picker/variations.browser-spec.d.ts +0 -1
  722. package/lib/slider/variations.browser-spec.d.ts +0 -1
  723. package/lib/split-button/variations.browser-spec.d.ts +0 -1
  724. package/lib/status/variations.browser-spec.d.ts +0 -1
  725. package/lib/switch/variations.browser-spec.d.ts +0 -1
  726. package/lib/table/variations.browser-spec.d.ts +0 -1
  727. package/lib/tabs/variations.browser-spec.d.ts +0 -1
  728. package/lib/tag/variations.browser-spec.d.ts +0 -1
  729. package/lib/text-area/variations.browser-spec.d.ts +0 -1
  730. package/lib/text-field/variations.browser-spec.d.ts +0 -1
  731. package/lib/time-picker/variations.browser-spec.d.ts +0 -1
  732. package/lib/toggletip/variations.browser-spec.d.ts +0 -1
  733. package/lib/tooltip/variations.browser-spec.d.ts +0 -1
  734. package/lib/tree-item/variations.browser-spec.d.ts +0 -1
  735. package/lib/video-player/variations.browser-spec.d.ts +0 -1
  736. /package/lib/{accordion-item/variations.browser-spec.d.ts → form-field/index.d.ts} +0 -0
  737. /package/unbundled/{chunk.js → rolldown-runtime.js} +0 -0
@@ -1,3619 +1,482 @@
1
1
  import { d as createRegisterFunction, t as VividElement, u as defineVividComponent } from "./vivid-element.js";
2
2
  import { t as __decorate } from "./decorate.js";
3
- import { r as ProgressRing, t as progressRingDefinition } from "./definition5.js";
4
- import { n as WithObservableLocale } from "./localized.js";
5
- import { i as Button, t as buttonDefinition } from "./definition6.js";
3
+ import { t as componentEnum } from "./component-enum.js";
4
+ import { n as FormAssociated } from "./form-associated.js";
5
+ import { t as Localized } from "./localized.js";
6
6
  import { i as Popup, r as PlacementStrategy, t as popupDefinition } from "./definition9.js";
7
- import { i as MenuItem, t as menuItemDefinition } from "./definition11.js";
8
- import { r as Menu, t as menuDefinition } from "./definition12.js";
9
- import { t as Divider } from "./divider.js";
10
- import { t as generateRandomId } from "./randomId.js";
11
- import { n as textFieldDefinition, r as TextField } from "./definition26.js";
12
- import { n as tooltipDefinition, r as Tooltip } from "./definition27.js";
13
- import { t as ListboxOption } from "./option.js";
14
- import { t as listboxOptionDefinition } from "./definition29.js";
15
- import { t as dividerDefinition } from "./definition36.js";
16
- import { a as featureFacade, c as impl, i as contributionPriority, n as removeSymbol, o as getFeatureImpl, r as RteFeatureImpl, s as sortedContributions, t as dispatchSlottableRequest } from "./slottable-request.js";
17
- import { n as selectDefinition, r as Select } from "./definition63.js";
18
- import { ElementStyles, html, observable, ref, volatile } from "@microsoft/fast-element";
19
- import { DOMParser, DOMSerializer, Fragment, NodeRange, Schema, Slice } from "prosemirror-model";
20
- import { AllSelection, EditorState, NodeSelection, Plugin, PluginKey, TextSelection } from "prosemirror-state";
21
- import { Decoration, DecorationSet, EditorView } from "prosemirror-view";
22
- import { keymap } from "prosemirror-keymap";
23
- import { autoJoin, baseKeymap, chainCommands, createParagraphNear, liftEmptyBlock, newlineInCode, splitBlockAs, toggleMark } from "prosemirror-commands";
24
- import { dropCursor } from "prosemirror-dropcursor";
25
- import { gapCursor } from "prosemirror-gapcursor";
26
- import DOMPurify from "dompurify";
27
- import { closeHistory, history, redo, undo } from "prosemirror-history";
28
- import { InputRule, inputRules, undoInputRule } from "prosemirror-inputrules";
29
- import { RemoveMarkStep, ReplaceAroundStep, dropPoint } from "prosemirror-transform";
30
- import { marks } from "prosemirror-schema-basic";
31
- //#region src/lib/rich-text-editor/rich-text-editor.scss?inline
32
- var rich_text_editor_default = ":host{display:block}.rte{--editor-padding-inline:var(--rich-text-editor-padding-inline,16px);--editor-padding-block:var(--rich-text-editor-padding-block,8px);block-size:100%;max-block-size:inherit;min-block-size:inherit;flex-direction:column;display:flex}.editor{display:contents}.editor-viewport{contain:layout;flex-direction:column;flex:1;min-block-size:0;display:flex;position:relative;overflow:hidden}.editor-scroll-area{background-color:var(--vvd-color-canvas);color:var(--vvd-color-canvas-text);font:var(--vvd-typography-base);--scrollbar-track-color:transparent;--scrollbar-thumb-color:color-mix(in sRGB, var(--vvd-color-neutral-950), transparent 70%);scrollbar-color:var(--scrollbar-thumb-color) var(--scrollbar-track-color);scrollbar-width:thin;flex-direction:column;flex:1;min-block-size:0;display:flex;overflow-y:auto}.editor-scroll-area ::-webkit-scrollbar{width:4px}.editor-scroll-area ::-webkit-scrollbar-track{background:var(--scrollbar-track-color)}.editor-scroll-area ::-webkit-scrollbar-thumb{background-color:var(--scrollbar-fallback-track-color,var(--scrollbar-thumb-color));border:0;border-radius:4px}.popovers--disabled>*{display:none!important}";
33
- //#endregion
34
- //#region src/lib/rich-text-editor/rich-text-editor.ts
7
+ import { n as keyArrowRight$1, t as keyArrowLeft$1 } from "./key-codes.js";
8
+ import { a as lerp, i as inverseLerp, n as getMarkersTemplate, o as defaultToOneConverter, s as roundToStepValue } from "./slider.template.js";
9
+ import { t as FormElement } from "./form-element.js";
10
+ import { attr, html, nullableNumberConverter, observable, ref, when } from "@microsoft/fast-element";
11
+ import { Orientation, classNames, keyArrowDown, keyArrowUp, keyEnd, keyHome, limit } from "@microsoft/fast-web-utilities";
12
+ //#region src/lib/range-slider/range-slider.scss?inline
13
+ var range_slider_default = ":host{display:inline-block}:host(:not([orientation=vertical])){inline-size:100%}:host([orientation=vertical]){block-size:100%;min-block-size:calc(var(--_thumb-interaction-indicator-size) * 5)}:host([disabled]){cursor:not-allowed}.control{--_thumb-size:12px;--_thumb-interaction-indicator-size:36px;--_track-start-inset-inline-start:0;--_track-start-inset-block-start:0;cursor:pointer;user-select:none;outline:none}.control .positioning-region{position:relative}.control .track{background:var(--_track-background-color);border-radius:4px;position:absolute}.control .track-start{border-radius:inherit;background:var(--_track-start-background-color);block-size:100%;position:absolute;inset-inline-start:var(--_track-start-inset-inline-start)}.control.horizontal{block-size:var(--_thumb-interaction-indicator-size);inline-size:calc(100% - var(--_thumb-size));min-inline-size:var(--_thumb-size);margin-inline-start:calc(var(--_thumb-size) / 2)}.control.horizontal .track{top:calc((var(--_thumb-interaction-indicator-size) - 2px) / 2);block-size:2px;left:0;right:0}:host([markers]) .control.horizontal .track-start{--_track-start-inset-inline-start:1px;border-top-left-radius:0;border-bottom-left-radius:0}.control.horizontal .track .mark{block-size:6px;inline-size:100%;position:absolute;inset-block-start:-2px;inset-inline-start:0}.control.vertical{margin-top:calc(var(--_thumb-interaction-indicator-size) / 2);block-size:calc(100% - var(--_thumb-interaction-indicator-size));inline-size:var(--_thumb-interaction-indicator-size);min-block-size:var(--_thumb-interaction-indicator-size)}.control.vertical .positioning-region{block-size:100%}.control.vertical .track{left:calc((var(--_thumb-interaction-indicator-size) - 2px) / 2);block-size:100%;inline-size:2px}.control.vertical .track .mark{block-size:100%;inline-size:6px;position:absolute;inset-block-start:0;inset-inline-start:-2px}.control.vertical .track-start{block-size:auto;inline-size:100%;inset-block-start:var(--_track-start-inset-block-start)}:host([markers]) .control.vertical .track-start{--_track-start-inset-block-start:1px;border-radius:0}.control.disabled{--_track-background-color:var(--vvd-color-neutral-100);--_track-start-background-color:var(--vvd-color-neutral-300);pointer-events:none}.control:not(.disabled){--_track-background-color:var(--vvd-color-neutral-300);--_track-start-background-color:var(--_appearance-color-fill)}.control:not(.disabled) .mark{color:var(--vvd-color-neutral-950)}.control.disabled .mark{color:var(--_track-start-background-color)}.thumb-container{block-size:var(--_thumb-interaction-indicator-size);cursor:inherit;inline-size:var(--_thumb-interaction-indicator-size);touch-action:none;border-radius:50%;outline:none;position:absolute}.thumb-container.focus-visible{box-shadow:0 0 0 4px color-mix(in sRGB, var(--focus-stroke-color,var(--vvd-color-cta-500)), transparent 85%), inset 0 0 0 3px var(--focus-stroke-gap-color,currentColor);outline:1px solid var(--focus-stroke-color,var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset,0px));--focus-stroke-gap-color:transparent;--_thumb-interaction-indicator-alpha:.05;border-radius:50%}.control.horizontal .thumb-container{transform:translateX(calc(var(--_thumb-interaction-indicator-size) / 2))}.control.vertical .thumb-container{transform:translateY(calc(var(--_thumb-interaction-indicator-size) / 2))}@media (hover:hover){.control:not(.disabled) .thumb-container:hover{--_thumb-interaction-indicator-alpha:.12}}.control:not(.disabled) .thumb-container:active{--_thumb-interaction-indicator-alpha:.25}.thumb-container:before{border-radius:inherit;background-color:var(--_track-start-background-color);block-size:var(--_thumb-interaction-indicator-size);content:\"\";inline-size:var(--_thumb-interaction-indicator-size);opacity:var(--_thumb-interaction-indicator-alpha,0);display:block;position:absolute}@media (prefers-reduced-motion:no-preference){.thumb-container:before{transition:opacity .2s ease-out}}.thumb-container:after{border-radius:inherit;background-color:var(--_track-start-background-color);block-size:var(--_thumb-size);content:\"\";inline-size:var(--_thumb-size);inset:calc((var(--_thumb-interaction-indicator-size) - var(--_thumb-size)) / 2);display:block;position:absolute}.popup{pointer-events:none}.tooltip{width:auto;color:var(--vvd-color-canvas-text);font:var(--vvd-typography-base-bold);padding:8px 12px}:host([internal-part]) .thumb-container{opacity:0}@media (prefers-reduced-motion:no-preference){:host([internal-part]) .thumb-container{transition:opacity .2s}}:host([internal-part]) .control.horizontal .track{block-size:4px;top:16px;overflow:hidden}:host([internal-part]) .control:focus .thumb-container{opacity:1}@media (hover:hover){:host([internal-part]) .control:hover .thumb-container{opacity:1}}.control,:host([markers]) .control.horizontal .track-start,:host([markers]) .control.vertical .track-start{--_track-start-inset-inline-start:auto;--_track-start-inset-block-start:auto}";
14
+ //#endregion
15
+ //#region src/lib/range-slider/range-slider.ts
16
+ var rangeSliderConnotation = componentEnum(["accent", "cta"], "accent");
17
+ var Direction$1 = {
18
+ Increment: 1,
19
+ Decrement: -1
20
+ };
35
21
  /**
22
+ * Base class for range-slider
23
+ *
24
+ * @component range-slider
36
25
  * @public
37
- * @component rich-text-editor
38
- * @slot editor-before - Displayed before the scrollable editor area.
39
- * @slot editor-start - Displayed at the start of the scrollable editor area.
40
- * @slot editor-end - Displayed at the end of the scrollable editor area.
41
- * @slot editor-after - Displayed after the scrollable editor area.
42
- * @slot status - Displayed between the editor viewport and the toolbar.
43
- * @slot text-color-picker - Color picker for the RteTextColorFeature.
44
- * @dynamicSlot `{ url: string }` inline-image-placeholder - Placeholder content for inline images.
45
- * @dynamicSlot `{ id: string }` suggestions-empty - Empty state if no suggestions are found.
26
+ * @event {CustomEvent<undefined>} input:start - Event emitted when the start value changes
27
+ * @event {CustomEvent<undefined>} input:end - Event emitted when the end value changes
28
+ * @event {CustomEvent<undefined>} input - Event emitted when either the start or end value changes.
29
+ * @event {CustomEvent<undefined>} change - Event emitted when either the start or end value changes.
30
+ * @vueModel start start input:start `event.currentTarget.start`
31
+ * @vueModel end end input:end `event.currentTarget.end`
32
+ * @vueModel startAsNumber startAsNumber input:start `event.currentTarget.startAsNumber`
33
+ * @vueModel endAsNumber endAsNumber input:end `event.currentTarget.endAsNumber`
34
+ * @testSelector byLabel byLabel
35
+ * @testAction slideStartTo slideTo #track #startThumb
36
+ * @testAction slideEndTo slideTo #track #endThumb
37
+ * @testQuery range rangeAsNumber
38
+ * @testRef track shadow .control
39
+ * @testRef startThumb shadow #start-thumb
40
+ * @testRef endThumb shadow #end-thumb
46
41
  */
47
- var RichTextEditor = class extends WithObservableLocale(VividElement) {
48
- /** @internal */
49
- instanceChanged(prevInstance) {
50
- prevInstance?.[impl].destroyViewIfNeeded();
51
- this._initViewIfNeeded();
52
- prevInstance?.[impl].styles.removeStylesFrom(this.shadowRoot);
53
- this.instance?.[impl].styles.addStylesTo(this.shadowRoot);
54
- }
55
- _initViewIfNeeded() {
56
- const instance = this.instance?.[impl];
57
- if (instance && this.$fastController.isConnected && !instance.view) {
58
- this._syncStateIfNeeded();
59
- instance.createView(this._editorEl);
60
- }
61
- }
62
- _destroyViewIfNeeded() {
63
- this.instance?.[impl].destroyViewIfNeeded();
64
- }
65
- connectedCallback() {
66
- super.connectedCallback();
67
- this._initViewIfNeeded();
68
- }
69
- disconnectedCallback() {
70
- super.disconnectedCallback();
71
- this._destroyViewIfNeeded();
72
- }
73
- /** @internal */
74
- localeChanged() {
75
- this._syncStateIfNeeded();
76
- }
77
- _syncStateIfNeeded() {
78
- this.instance?.[impl].updateHostState({
79
- locale: this.locale,
80
- ctx: this._ctx
81
- });
82
- }
83
- };
84
- __decorate([observable], RichTextEditor.prototype, "instance", void 0);
85
- //#endregion
86
- //#region src/lib/rich-text-editor/rich-text-editor.template.ts
87
- var RichTextEditorTemplate = (ctx) => {
88
- return html`<template :_ctx="${() => ctx}">
89
- <div class="rte">
90
- <slot name="editor-before"></slot>
91
- <div class="editor-viewport" ${ref("editorViewportElement")}>
92
- <div class="editor-scroll-area" part="editor-scrollable-area">
93
- <slot name="editor-start"></slot>
94
- <div class="editor rich-text" ${ref("_editorEl")}></div>
95
- <div class="popovers"></div>
96
- <slot name="editor-end"></slot>
97
- </div>
98
- </div>
99
- <slot name="editor-after"></slot>
100
- <slot name="status"></slot>
101
- <div class="toolbar"></div>
102
- </div>
103
- </template>`;
104
- };
105
- //#endregion
106
- //#region src/lib/rich-text-editor/popover.ts
107
- var Kind = {
108
- default: {
109
- placement: void 0,
110
- placementStrategy: PlacementStrategy.AutoPlacementHorizontal,
111
- shiftCrossAxis: false,
112
- strategy: "absolute"
113
- },
114
- autocomplete: {
115
- placement: "bottom-start",
116
- placementStrategy: PlacementStrategy.Flip,
117
- shiftCrossAxis: false,
118
- strategy: "fixed"
119
- },
120
- imageOptions: {
121
- placement: "bottom",
122
- placementStrategy: PlacementStrategy.Flip,
123
- shiftCrossAxis: true,
124
- strategy: "absolute"
125
- }
126
- };
127
- var popoverTemplate = (context) => {
128
- const popup = context.tagFor(Popup);
129
- return html`<${popup}
130
- :anchor="${(x) => x.anchorEl}"
131
- :placement="${(x) => Kind[x.kind].placement}"
132
- :placementStrategy="${(x) => Kind[x.kind].placementStrategy}"
133
- :shiftCrossAxis="${(x) => Kind[x.kind].shiftCrossAxis}"
134
- :open="${(x) => x.open}"
135
- :offset="${(x) => x.offset}"
136
- :strategy="${(x) => Kind[x.kind].strategy}"
137
- exportparts="vvd-theme-alternate"
138
- >
139
- <slot></slot>
140
- </${popup}>`;
141
- };
142
- var Popover = class extends VividElement {
42
+ var RangeSlider = class extends Localized(FormElement(FormAssociated(VividElement))) {
143
43
  constructor(..._args) {
144
44
  super(..._args);
145
- this.kind = "default";
146
- this.anchorBlocksPopover = false;
147
- this.onAnchorBlockPopoverChanged = () => {
148
- this.anchorBlocksPopover = this.anchorEl?.dataset.blockPopover === "true" || false;
149
- };
150
- this.requestedOpenState = false;
151
- }
152
- static setBlockPopover(onElement, block) {
153
- onElement.dataset.blockPopover = block ? "true" : "false";
154
- const event = new CustomEvent("block-popover-changed", {
155
- bubbles: false,
156
- composed: false
157
- });
158
- onElement.dispatchEvent(event);
159
- }
160
- /** Closes the popover. It reopens when anchorEl changes to a new element that does not block it. */
161
- dismiss() {
162
- this.anchorBlocksPopover = true;
163
- }
164
- anchorElChanged(prev, next) {
165
- prev?.removeEventListener("block-popover-changed", this.onAnchorBlockPopoverChanged);
166
- next?.addEventListener("block-popover-changed", this.onAnchorBlockPopoverChanged);
167
- this.onAnchorBlockPopoverChanged();
168
- }
169
- anchorIdChanged() {
170
- this.updateAnchor();
171
- }
172
- updateAnchor() {
173
- if (this.anchorId && this.isConnected) this.anchorEl = this.getRootNode().getElementById(this.anchorId) || void 0;
174
- else this.anchorEl = void 0;
175
- }
176
- requestOpenState(open) {
177
- this.requestedOpenState = open;
178
- }
179
- get open() {
180
- return this.requestedOpenState && !!this.anchorEl && !this.anchorBlocksPopover;
181
- }
182
- #observer;
183
- connectedCallback() {
184
- super.connectedCallback();
185
- this.updateAnchor();
186
- this.#observer = new MutationObserver((records) => {
187
- if (records.some((r) => Array.from(r.addedNodes).some((n) => n instanceof HTMLElement && n.id === this.anchorId))) this.updateAnchor();
188
- });
189
- this.#observer.observe(this.getRootNode(), {
190
- childList: true,
191
- subtree: true
192
- });
193
- }
194
- disconnectedCallback() {
195
- super.disconnectedCallback();
196
- this.#observer.disconnect();
197
- }
198
- };
199
- __decorate([observable], Popover.prototype, "kind", void 0);
200
- __decorate([observable], Popover.prototype, "offset", void 0);
201
- __decorate([observable], Popover.prototype, "anchorBlocksPopover", void 0);
202
- __decorate([observable], Popover.prototype, "anchorEl", void 0);
203
- __decorate([observable], Popover.prototype, "anchorId", void 0);
204
- __decorate([observable], Popover.prototype, "requestedOpenState", void 0);
205
- __decorate([volatile], Popover.prototype, "open", null);
206
- var popoverDefinition = defineVividComponent("rich-text-editor-popover", Popover, popoverTemplate, [popupDefinition], {});
207
- //#endregion
208
- //#region ../../node_modules/.pnpm/prosemirror-view@1.41.8/node_modules/prosemirror-view/style/prosemirror.css?inline
209
- var prosemirror_default = ".ProseMirror{word-wrap:break-word;white-space:pre-wrap;white-space:break-spaces;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;font-feature-settings:\"liga\" 0;position:relative}.ProseMirror pre{white-space:pre-wrap}.ProseMirror li{position:relative}.ProseMirror-hideselection ::selection{background:0 0}.ProseMirror-hideselection ::selection{background:0 0}.ProseMirror-hideselection{caret-color:#0000}.ProseMirror [draggable][contenteditable=false]{user-select:text}.ProseMirror-selectednode{outline:2px solid #8cf}li.ProseMirror-selectednode{outline:none}li.ProseMirror-selectednode:after{content:\"\";pointer-events:none;border:2px solid #8cf;position:absolute;inset:-2px -2px -2px -32px}img.ProseMirror-separator{border:none!important;margin:0!important;display:inline!important}";
210
- //#endregion
211
- //#region src/lib/rich-text-editor/rte/utils/default-textblock.ts
212
- function defaultTextblockForMatch(match) {
213
- for (let i = 0; i < match.edgeCount; i++) {
214
- const { type } = match.edge(i);
215
- /* v8 ignore if -- @preserve It's currently not possible to exercise this code in our RTE */
216
- if (type.isTextblock && !type.hasRequiredAttrs()) return type;
217
- }
218
- }
219
- //#endregion
220
- //#region src/lib/rich-text-editor/rte/utils/ui.style.scss?inline
221
- var ui_style_default = "[data-class=ui-select]{min-inline-size:120px;margin-block:-4px}.ui-divider{block-size:20px}.ui-button-group{gap:4px;display:flex}.ui-tooltip,.ui-menu{--_popup-display:contents;display:contents}.ui-tooltip-wrapper{display:contents}";
222
- //#endregion
223
- //#region src/lib/rich-text-editor/rte/utils/feature-state.ts
224
- var FeatureState = class {
225
- constructor(initialValue) {
226
- this.plugin = new Plugin({ state: {
227
- init: () => initialValue,
228
- apply: (tr, value) => {
229
- const meta = tr.getMeta(this.plugin);
230
- return meta !== void 0 ? meta : value;
45
+ this.#isInternalValueUpdate = false;
46
+ this.start = "";
47
+ this.end = "";
48
+ this.min = 0;
49
+ this.max = 10;
50
+ this.step = 1;
51
+ this.orientation = Orientation.horizontal;
52
+ this.ariaStartLabel = null;
53
+ this.ariaEndLabel = null;
54
+ this.markers = false;
55
+ this.pin = false;
56
+ this.valueTextFormatter = (value) => parseFloat(value).toLocaleString(this.locale.lang);
57
+ this.proxy = document.createElement("input");
58
+ this._trackEl = null;
59
+ this._startThumbEl = null;
60
+ this._endThumbEl = null;
61
+ this._draggingThumb = false;
62
+ this._visiblyFocusedThumb = null;
63
+ this._hoveredThumb = null;
64
+ this._startThumbCss = "";
65
+ this._endThumbCss = "";
66
+ this._selectedRangeCss = "";
67
+ this.#isNonVisibleFocus = false;
68
+ this.#onThumbFocus = (e) => {
69
+ if (!this.#isNonVisibleFocus) this._visiblyFocusedThumb = this.#getThumbIdFromEvent(e);
70
+ this.#isNonVisibleFocus = false;
71
+ };
72
+ this.#onThumbBlur = () => {
73
+ this._visiblyFocusedThumb = null;
74
+ };
75
+ this.#onVisibilityChange = () => {
76
+ if (document.hidden && (this.shadowRoot.activeElement === this._startThumbEl || this.shadowRoot.activeElement === this._endThumbEl)) this.#isNonVisibleFocus = true;
77
+ };
78
+ this.#onMouseOver = (e) => {
79
+ this._hoveredThumb = this.#getThumbIdFromEvent(e);
80
+ };
81
+ this.#onMouseOut = () => {
82
+ this._hoveredThumb = null;
83
+ };
84
+ this.#onThumbMousedown = (event) => {
85
+ if (this.disabled || event.defaultPrevented) return;
86
+ let target = event.target;
87
+ if (target === this._endThumbEl && this.startAsNumber === this.max && this.endAsNumber === this.max) target = this._startThumbEl;
88
+ this.#focusThumbNonVisibly(target);
89
+ this._draggingThumb = this.#getThumbId(target);
90
+ this.#registerDragHandlers();
91
+ };
92
+ this.#onThumbKeydown = (e) => {
93
+ const thumb = this.#getThumbIdFromEvent(e);
94
+ this._visiblyFocusedThumb = thumb;
95
+ if (e.key === keyHome) {
96
+ e.preventDefault();
97
+ this.#updateValues({ [thumb]: `${this.#thumbConstraints[thumb].min}` });
98
+ } else if (e.key === keyEnd) {
99
+ e.preventDefault();
100
+ this.#updateValues({ [thumb]: `${this.#thumbConstraints[thumb].max}` });
101
+ } else {
102
+ if (e.shiftKey) return;
103
+ switch (e.key) {
104
+ case keyArrowRight$1:
105
+ case keyArrowDown:
106
+ e.preventDefault();
107
+ this.#applyStep(thumb, Direction$1.Increment);
108
+ break;
109
+ case keyArrowLeft$1:
110
+ case keyArrowUp:
111
+ e.preventDefault();
112
+ this.#applyStep(thumb, Direction$1.Decrement);
113
+ }
231
114
  }
232
- } });
233
- }
234
- getValue(rte) {
235
- return this.plugin.getState(rte.state);
236
- }
237
- setValue(rte, newValue) {
238
- rte.dispatchTransaction(rte.tr.setMeta(this.plugin, newValue));
239
- }
240
- };
241
- //#endregion
242
- //#region src/lib/rich-text-editor/rte/features/internal/core.style.scss?inline
243
- var core_style_default = ".ProseMirror{box-sizing:border-box;padding:var(--editor-padding-block) var(--editor-padding-inline);outline:none;flex:1 0 0}.ProseMirror-selectednode{--focus-stroke-gap-color:transparent;--focus-border-radius:2px;outline:none;position:relative}.ProseMirror-selectednode:after{box-shadow:0 0 0 4px color-mix(in sRGB, var(--focus-stroke-color,var(--vvd-color-cta-500)), transparent 85%), inset 0 0 0 3px var(--focus-stroke-gap-color,currentColor);outline:1px solid var(--focus-stroke-color,var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset,0px));border-radius:var(--focus-border-radius,inherit);block-size:calc(100% + var(--focus-block-size-addition,4px));content:\"\";inline-size:calc(100% + var(--focus-block-size-addition,4px));display:block;position:absolute;inset-block-start:50%;inset-inline-start:50%;transform:translate(-50%,-50%)}.editor--disabled .ProseMirror{color:var(--vvd-color-neutral-300);cursor:not-allowed}";
244
- //#endregion
245
- //#region src/lib/rich-text-editor/rte/features/internal/foreign-html.ts
246
- var RteForeignHtmlFeatureImpl = class extends RteFeatureImpl {
247
- constructor(..._args) {
248
- super(..._args);
249
- this.name = "RteForeignHtmlFeature";
250
- }
251
- getPlugins(rte) {
252
- return [this.contribution(new Plugin({ props: {
253
- transformPastedHTML: (html) => rte.foreignHtmlParser[impl].transform(html),
254
- clipboardParser: rte.foreignHtmlParser[impl].parser,
255
- clipboardSerializer: rte.foreignHtmlSerializer[impl].serializer
256
- } }))];
257
- }
258
- };
259
- //#endregion
260
- //#region src/lib/rich-text-editor/rte/features/internal/cursor-fix.ts
261
- /**
262
- * When the cursor is positioned after an inline atom node at the end of a line,
263
- * browsers may display the cursor inside the atom.
264
- */
265
- var atomCursorFix = ($cursor) => {
266
- if (!($cursor.parentOffset === $cursor.parent.content.size)) return null;
267
- const nodeBefore = $cursor.nodeBefore;
268
- if (nodeBefore && nodeBefore.isInline && nodeBefore.isAtom && !nodeBefore.isText) return {};
269
- return null;
270
- };
271
- /**
272
- * When the cursor is positioned directly before an inline atom node (e.g. an image)
273
- * that wraps to the next line, browsers may display the cursor on the next line even
274
- * though typing inserts text on the previous line. A ZWSP between cursor and atom will be
275
- * layouted to the previous line and therefore fix the cursor position.
276
- */
277
- var beforeAtomCursorFix = ($cursor) => {
278
- const nodeAfter = $cursor.nodeAfter;
279
- if (nodeAfter && nodeAfter.isInline && nodeAfter.isAtom && !nodeAfter.isText) return { afterCursor: true };
280
- return null;
281
- };
282
- function createZwspWidget(style) {
283
- const span = document.createElement("span");
284
- span.textContent = "​";
285
- for (const [prop, value] of Object.entries(style)) span.style.setProperty(prop, value);
286
- return span;
287
- }
288
- var RteCursorFixFeatureImpl = class extends RteFeatureImpl {
289
- constructor(..._args) {
290
- super(..._args);
291
- this.name = "RteCursorFix";
115
+ };
116
+ this.#onDragMove = (e) => {
117
+ if (this.disabled || e.defaultPrevented || !this._draggingThumb) return;
118
+ const sourceEvent = "TouchEvent" in window && e instanceof TouchEvent ? e.touches[0] : e;
119
+ const value = this.#calculateValueFromMouseEvent(sourceEvent);
120
+ this.#updateValues({ [this._draggingThumb]: `${this.#roundToNearestStep(this._draggingThumb, value)}` });
121
+ };
122
+ this.#onDragEnd = () => {
123
+ this._draggingThumb = false;
124
+ this.#unregisterDragListeners();
125
+ };
292
126
  }
293
- getPlugins(rte) {
294
- const cursorFixes = [atomCursorFix, beforeAtomCursorFix];
295
- for (const markType of Object.values(rte.schema.marks)) {
296
- const spec = markType.spec;
297
- if (spec.cursorFix) cursorFixes.push(spec.cursorFix);
127
+ #isInternalValueUpdate;
128
+ /** @internal */
129
+ startChanged() {
130
+ this.currentStart = this.start;
131
+ if (!this.#isInternalValueUpdate) {
132
+ this.dirtyValue = true;
133
+ this.#updateFormValue();
298
134
  }
299
- return [this.contribution(new Plugin({ props: { decorations: (state) => {
300
- const { $cursor } = state.selection;
301
- if (!$cursor) return null;
302
- const decorations = [];
303
- const cursorFixStyles = {};
304
- let before = false;
305
- let after = false;
306
- for (const fn of cursorFixes) {
307
- const result = fn($cursor, state);
308
- if (!result) continue;
309
- if (result.style) Object.assign(cursorFixStyles, result.style);
310
- if (result.afterCursor) after = true;
311
- else before = true;
312
- }
313
- if (before) decorations.push(Decoration.widget($cursor.pos, () => createZwspWidget(cursorFixStyles), { side: -1 }));
314
- if (after) decorations.push(Decoration.widget($cursor.pos, () => createZwspWidget(cursorFixStyles), { side: 1 }));
315
- if (decorations.length === 0) return null;
316
- return DecorationSet.create(state.doc, decorations);
317
- } } }))];
318
- }
319
- };
320
- featureFacade(RteCursorFixFeatureImpl);
321
- //#endregion
322
- //#region src/lib/rich-text-editor/rte/features/internal/core.ts
323
- /** Plugin to bring state from the host web component into ProseMirror. */
324
- var hostBridgePlugin = new Plugin({ state: {
325
- init() {
326
- return null;
327
- },
328
- apply(tr, value) {
329
- const meta = tr.getMeta(hostBridgePlugin);
330
- if (meta) return meta;
331
- else return value;
332
- }
333
- } });
334
- var RteCoreImpl = class extends RteFeatureImpl {
335
- constructor(..._args) {
336
- super(..._args);
337
- this.name = "RteCore";
338
- this.disabled = new FeatureState(false);
339
- this.scrollThreshold = void 0;
340
- this.scrollMargin = void 0;
341
- }
342
- getStyles() {
343
- return [
344
- this.contribution(prosemirror_default),
345
- this.contribution(core_style_default),
346
- this.contribution(ui_style_default)
347
- ];
348
- }
349
- getPlugins(rte) {
350
- const splitFn = splitBlockAs((node, atEnd, $from) => {
351
- if (!atEnd) return {
352
- type: node.type,
353
- attrs: node.attrs
354
- };
355
- const defaultTextblock = defaultTextblockForMatch($from.node($from.depth - 1).contentMatchAt($from.indexAfter($from.depth - 1)));
356
- if (!defaultTextblock) return null;
357
- return {
358
- type: defaultTextblock,
359
- attrs: rte.textblockAttrs.extractFromNode(node)
360
- };
361
- });
362
- const splitFnKeepMarks = (state, dispatch) => splitFn(state, dispatch && ((tr) => {
363
- const marks = state.storedMarks || state.selection.$to.parentOffset && state.selection.$from.marks();
364
- if (marks) tr.ensureMarks(marks);
365
- dispatch(tr);
366
- }));
367
- const enterKeyChainCommands = chainCommands(newlineInCode, createParagraphNear, liftEmptyBlock, splitFnKeepMarks);
368
- return [
369
- this.contribution(this.disabled.plugin),
370
- this.contribution(new Plugin({
371
- props: {
372
- editable: () => !this.disabled.getValue(rte),
373
- handleDOMEvents: { click: (_view, event) => {
374
- if (this.disabled.getValue(rte)) {
375
- event.preventDefault();
376
- return true;
377
- }
378
- return false;
379
- } }
380
- },
381
- view: (view) => {
382
- const popovers = view.dom.getRootNode().querySelector(".popovers");
383
- const updateDisabled = () => {
384
- const disabled = this.disabled.getValue(rte);
385
- popovers.classList.toggle("popovers--disabled", disabled);
386
- view.dom.parentElement.classList.toggle("editor--disabled", disabled);
387
- };
388
- updateDisabled();
389
- return { update: () => {
390
- updateDisabled();
391
- } };
392
- }
393
- })),
394
- this.contribution(keymap({
395
- ...baseKeymap,
396
- Enter: enterKeyChainCommands,
397
- "Shift-Enter": enterKeyChainCommands
398
- })),
399
- this.contribution(dropCursor()),
400
- this.contribution(gapCursor()),
401
- this.contribution(hostBridgePlugin)
402
- ];
403
- }
404
- getFeatures() {
405
- return [
406
- this,
407
- new RteForeignHtmlFeatureImpl(),
408
- new RteCursorFixFeatureImpl()
409
- ];
410
- }
411
- };
412
- featureFacade(RteCoreImpl);
413
- //#endregion
414
- //#region src/lib/rich-text-editor/rte/utils/sanitization.ts
415
- var DEFAULT_ALLOWED_URI_REGEXP = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i;
416
- var ALLOWED_URI_REGEXP_WITH_BLOB = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|blob):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i;
417
- var ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
418
- var domPurifyConfig = { ALLOWED_URI_REGEXP: ALLOWED_URI_REGEXP_WITH_BLOB };
419
- /**
420
- * Sanitize potentially dangerous URLs, like "javascript:", in anchor href attributes.
421
- * Returns empty string if the URL is unsafe.
422
- */
423
- var sanitizeLinkHref = (url) => {
424
- if (!DEFAULT_ALLOWED_URI_REGEXP.test(url.replace(ATTR_WHITESPACE, ""))) return "";
425
- const anchor = document.createElement("a");
426
- anchor.setAttribute("href", url);
427
- /* v8 ignore next -- since href is already validated it's probably always present @preserve */
428
- return DOMPurify.sanitize(anchor, {
429
- RETURN_DOM: true,
430
- ...domPurifyConfig
431
- }).querySelector("a").getAttribute("href") ?? "";
432
- };
433
- /**
434
- * Sanitize potentially dangerous URLs, like "javascript:", in image src attributes.
435
- * Returns empty string if the URL is unsafe.
436
- */
437
- var sanitizeImageSrc = (url) => {
438
- const img = document.createElement("img");
439
- img.setAttribute("src", url);
440
- return DOMPurify.sanitize(img, {
441
- RETURN_DOM: true,
442
- ...domPurifyConfig
443
- }).querySelector("img").getAttribute("src") ?? "";
444
- };
445
- /**
446
- * Escapes a CSS value for insertion into style attribute.
447
- * E.g. "15px; background: red" => "15px"
448
- */
449
- var escapeCssProperty = (value) => value.replace(/[;!].*/, "");
450
- //#endregion
451
- //#region src/lib/rich-text-editor/rte/html-parser.ts
452
- var copy = (obj) => ({ ...obj });
453
- var parseRulesFromSchema = (schema) => ({
454
- nodes: Object.fromEntries(Object.keys(schema.nodes).map((name) => [name, (schema.nodes[name].spec.parseDOM ?? []).map(copy)])),
455
- marks: Object.fromEntries(Object.keys(schema.marks).map((name) => [name, (schema.marks[name].spec.parseDOM ?? []).map(copy)]))
456
- });
457
- var RteHtmlParser = class {
458
- constructor(config, options) {
459
- this[impl] = new RteHtmlParserImpl(config[impl], options);
460
- }
461
- /** Converts an HTML string to an RteDocument. */
462
- parseDocument(html, options) {
463
- return this[impl].parser.parse(this.parseHtml(html, options), { preserveWhitespace: true }).toJSON();
464
- }
465
- /** Converts an HTML string to an RteFragment. */
466
- parseFragment(html, options) {
467
- return this[impl].parser.parseSlice(this.parseHtml(html, options), { preserveWhitespace: true }).content.toJSON() ?? [];
468
- }
469
- parseHtml(html, options) {
470
- const dom = DOMPurify.sanitize(html, {
471
- RETURN_DOM: true,
472
- ...domPurifyConfig
473
- });
474
- const container = document.createDocumentFragment();
475
- container.appendChild(dom);
476
- options?.modifyDom?.(container);
477
- return container;
135
+ if (this.$fastController.isConnected) this.#updateThumbPositions();
478
136
  }
479
- };
480
- var RteHtmlParserImpl = class {
481
- constructor(config, options) {
482
- const rules = parseRulesFromSchema(config.schema);
483
- options?.modifyParseRules?.(rules);
484
- this.parser = buildDomParser(config.schema, rules);
485
- }
486
- /** Used by the editor when foreign HTML is pasted or dropped */
487
- transform(html) {
488
- return DOMPurify.sanitize(html);
489
- }
490
- };
491
- var buildDomParser = (schema, { marks, nodes }) => {
492
- const parserRules = [];
493
- const priority = (rule) => rule.priority ?? 50;
494
- function insert(rule) {
495
- let i = 0;
496
- for (; i < parserRules.length; i++) {
497
- const next = parserRules[i];
498
- if (priority(next) < priority(rule)) break;
137
+ /** @internal */
138
+ initialStartChanged(_, newValue) {
139
+ if (newValue && !this.dirtyValue) {
140
+ this.start = newValue;
141
+ this.dirtyValue = false;
499
142
  }
500
- parserRules.splice(i, 0, rule);
501
- }
502
- for (const name in marks) marks[name]?.forEach((rule) => {
503
- insert(rule = copy(rule));
504
- if (!(rule.mark || rule.ignore || rule.clearMark)) rule.mark = name;
505
- });
506
- for (const name in nodes) nodes[name]?.forEach((rule) => {
507
- insert(rule = copy(rule));
508
- if (!(rule.node || rule.ignore || rule.mark)) rule.node = name;
509
- });
510
- parserRules.push({
511
- tag: "br",
512
- closeParent: true
513
- });
514
- return new DOMParser(schema, parserRules);
515
- };
516
- //#endregion
517
- //#region src/lib/rich-text-editor/rte/html-serializer.ts
518
- var RteHtmlSerializer = class {
519
- constructor(config, options) {
520
- this[impl] = new RteHtmlSerializerImpl(config[impl], options);
521
143
  }
522
- /** Converts an RteDocument to an HTML string. */
523
- serializeDocument(doc, options) {
524
- return this[impl].serializeFragment(doc.content, options);
144
+ /** @internal */
145
+ currentStartChanged() {
146
+ this.start = this.currentStart;
525
147
  }
526
- /** Converts an RteFragment to an HTML string. */
527
- serializeFragment(fragment, options) {
528
- return this[impl].serializeFragment(fragment, options);
148
+ /** The start property, typed as a number. */
149
+ get startAsNumber() {
150
+ return parseFloat(this.start);
529
151
  }
530
- };
531
- var RteHtmlSerializerImpl = class RteHtmlSerializerImpl {
532
- constructor(config, options) {
533
- this.config = config;
534
- const serializers = RteHtmlSerializerImpl.domSerializersFromSchema(config.schema);
535
- Object.assign(serializers.nodes, options?.serializers?.nodes ?? {});
536
- Object.assign(serializers.marks, options?.serializers?.marks ?? {});
537
- this.serializer = new DOMSerializer(serializers.nodes, serializers.marks);
152
+ set startAsNumber(next) {
153
+ this.start = next.toString();
538
154
  }
539
- static domSerializersFromSchema(schema) {
540
- const result = {
541
- nodes: {},
542
- marks: {}
543
- };
544
- for (const name in schema.marks) {
545
- const toDOM = schema.marks[name].spec.toDOM;
546
- if (toDOM) result.marks[name] = toDOM;
547
- }
548
- for (const name in schema.nodes) {
549
- const toDOM = schema.nodes[name].spec.serializeToDOM ?? schema.nodes[name].spec.toDOM;
550
- if (toDOM) result.nodes[name] = toDOM;
155
+ /** @internal */
156
+ endChanged() {
157
+ this.currentEnd = this.end;
158
+ if (!this.#isInternalValueUpdate) {
159
+ this.dirtyValue = true;
160
+ this.#updateFormValue();
551
161
  }
552
- result.nodes.text = (node) => document.createTextNode(node.text);
553
- return result;
554
- }
555
- serializeFragment(fragment, options) {
556
- const parsedFragment = Fragment.fromJSON(this.config.schema, fragment);
557
- const serializedFragment = this.serializer.serializeFragment(parsedFragment);
558
- const container = document.createDocumentFragment();
559
- container.appendChild(serializedFragment);
560
- options?.modifyDom?.(container);
561
- const output = document.createElement("div");
562
- output.appendChild(container);
563
- return output.innerHTML;
564
- }
565
- };
566
- //#endregion
567
- //#region src/lib/rich-text-editor/rte/instance.ts
568
- var parseDocument = (schema, doc) => {
569
- const node = schema.topNodeType.createAndFill(null, doc ? Fragment.fromJSON(schema, doc.content) : null);
570
- if (!node) throw new Error("Document could not be parsed");
571
- node.check();
572
- return node;
573
- };
574
- var RteInstance = class {
575
- constructor(config, options) {
576
- this.options = options;
577
- this.feature = (Feature, featureId) => {
578
- return this[impl].getPublicInterface(Feature, featureId);
579
- };
580
- this[impl] = new RteInstanceImpl(this, config, options);
581
- }
582
- /** Returns the current document state. */
583
- getDocument() {
584
- return this[impl].state.doc.toJSON();
585
- }
586
- /** Reset the editor to its initial state. Optionally, an initial document can be provided. */
587
- reset(initialDocument) {
588
- this[impl].reset(initialDocument);
589
- }
590
- /**
591
- * Replaces the current selection with the given content.
592
- * If no text is selected, this inserts the content at the cursor position.
593
- */
594
- replaceSelection(content, options) {
595
- const { state, tr, schema, dispatchTransaction } = this[impl];
596
- tr.replaceSelection(new Slice(Fragment.fromJSON(schema, content), 0, 0));
597
- tr.doc.check();
598
- const $from = tr.doc.resolve(tr.mapping.map(state.selection.from));
599
- const $to = tr.doc.resolve(tr.selection.to);
600
- const [$head, $anchor] = options?.cursorPlacement === "start" ? [$from, $to] : [$to, $from];
601
- if (options?.selectContent) tr.setSelection(state.selection instanceof AllSelection ? new AllSelection(tr.doc) : TextSelection.between($anchor, $head));
602
- else tr.setSelection(TextSelection.between($head, $head));
603
- dispatchTransaction(tr);
604
- }
605
- /**
606
- * Replaces the entire document with the given new document.
607
- * Unlike reset, this preserves the rest of the editor state. The undo history is preserved, so the user can undo the replacement.
608
- */
609
- replaceDocument(newDocument, options) {
610
- const { state, tr, schema, dispatchTransaction } = this[impl];
611
- tr.replaceWith(0, state.doc.content.size, parseDocument(schema, newDocument));
612
- if (options?.selectContent) tr.setSelection(new AllSelection(tr.doc));
613
- else if (options?.cursorPlacement === "end") tr.setSelection(TextSelection.atEnd(tr.doc));
614
- else tr.setSelection(TextSelection.atStart(tr.doc));
615
- dispatchTransaction(tr);
616
- }
617
- /**
618
- * Scrolls the cursor into view.
619
- * Has no effect if the editor is not currently mounted.
620
- */
621
- scrollIntoView() {
622
- const instance = this[impl];
623
- if (!instance.view) return;
624
- instance.dispatchTransaction(instance.tr.scrollIntoView());
162
+ if (this.$fastController.isConnected) this.#updateThumbPositions();
625
163
  }
626
- };
627
- var RteInstanceImpl = class {
628
- getFeature(name) {
629
- const f = this.config.featureMap.get(name);
630
- if (!f) throw new Error(`Feature not found: ${name}`);
631
- return f;
632
- }
633
- getPublicInterface(Feature, featureId) {
634
- const instances = this.config.featureFacadesMap.get(Feature);
635
- if (!instances || instances.length === 0) throw new Error(`Feature not found`);
636
- if (instances[0].featureId !== void 0) {
637
- if (featureId === void 0) throw new Error(`No featureId provided for multi-instance feature.`);
638
- const instance = instances.find((f) => f.featureId === featureId);
639
- if (!instance) throw new Error(`Feature with id "${featureId}" not found`);
640
- return instance.getPublicInterface(this);
164
+ /** @internal */
165
+ initialEndChanged(_, newValue) {
166
+ if (newValue && !this.dirtyValue) {
167
+ this.end = newValue;
168
+ this.dirtyValue = false;
641
169
  }
642
- if (featureId !== void 0) throw new Error(`Feature does not support featureId`);
643
- return instances[0].getPublicInterface(this);
644
- }
645
- constructor(instanceFacade, configFacade, options) {
646
- this.options = options;
647
- this.view = null;
648
- this.dispatchTransaction = (tr) => {
649
- const prevState = this.state;
650
- this.state = this.state.apply(tr);
651
- this.view?.updateState(this.state);
652
- if (prevState.doc !== this.state.doc) this.options?.onChange?.();
653
- return this.state;
654
- };
655
- this.facade = instanceFacade;
656
- const config = configFacade[impl];
657
- this.config = config;
658
- this.schema = config.schema;
659
- this.textblockAttrs = config.textblockAttrs;
660
- this.features = config.features;
661
- this.foreignHtmlParser = options?.foreignHtmlParser ?? new RteHtmlParser(configFacade);
662
- this.foreignHtmlSerializer = options?.foreignHtmlSerializer ?? new RteHtmlSerializer(configFacade);
663
- this.styles = new ElementStyles(sortedContributions(config.features.flatMap((f) => f.getStyles())));
664
- this.initState(options?.initialDocument);
665
- }
666
- initState(initialDoc) {
667
- this.state = EditorState.create({
668
- doc: parseDocument(this.schema, initialDoc),
669
- schema: this.config.schema,
670
- plugins: sortedContributions(this.config.features.flatMap((feature) => feature.getPlugins(this)))
671
- });
672
- }
673
- reset(initialDocument) {
674
- const currentHostState = hostBridgePlugin.getState(this.state);
675
- this.initState(initialDocument);
676
- this.updateHostState(currentHostState);
677
- this.view?.updateState(this.state);
678
170
  }
679
- createView(target) {
680
- const core = this.config.featureMap.get("RteCore");
681
- this.view = new EditorView((editor) => {
682
- editor.part = "editor";
683
- target.appendChild(editor);
684
- }, {
685
- state: this.state,
686
- dispatchTransaction: this.dispatchTransaction,
687
- ...core?.scrollThreshold !== void 0 && { scrollThreshold: core.scrollThreshold },
688
- ...core?.scrollMargin !== void 0 && { scrollMargin: core.scrollMargin }
689
- });
690
- }
691
- destroyViewIfNeeded() {
692
- if (this.view) {
693
- this.view.destroy();
694
- this.view = null;
171
+ /** @internal */
172
+ currentEndChanged() {
173
+ this.end = this.currentEnd;
174
+ }
175
+ /** The end property, typed as a number. */
176
+ get endAsNumber() {
177
+ return parseFloat(this.end);
178
+ }
179
+ set endAsNumber(next) {
180
+ this.end = next.toString();
181
+ }
182
+ #updateValues({ start, end }, emitEvents = true) {
183
+ if (start === this.start) start = void 0;
184
+ if (end === this.end) end = void 0;
185
+ if (start === void 0 && end === void 0) return;
186
+ this.#isInternalValueUpdate = true;
187
+ if (start !== void 0) this.start = start;
188
+ if (end !== void 0) this.end = end;
189
+ this.#isInternalValueUpdate = false;
190
+ if (emitEvents) {
191
+ if (start !== void 0) this.$emit("input:start");
192
+ if (end !== void 0) this.$emit("input:end");
193
+ this.$emit("input");
194
+ this.$emit("change");
195
+ this.dirtyValue = true;
695
196
  }
197
+ this.#updateFormValue();
696
198
  }
697
- createComponent(type) {
698
- return document.createElement(this.hostState().ctx.tagFor(type, true));
699
- }
700
- getLocale() {
701
- return this.hostState().locale;
702
- }
703
- get tr() {
704
- return this.state.tr;
705
- }
706
- hostState() {
707
- const state = hostBridgePlugin.getState(this.state);
708
- if (!state) throw new Error("No host state available");
709
- return state;
710
- }
711
- updateHostState(hostState) {
712
- this.dispatchTransaction(this.tr.setMeta(hostBridgePlugin, hostState));
713
- }
714
- };
715
- //#endregion
716
- //#region src/lib/rich-text-editor/rte/utils/textblock-attrs.ts
717
- var TextblockAttrs = class {
718
- constructor(specs) {
719
- this.specs = specs;
720
- this.attrs = {};
721
- for (const spec of specs) this.attrs[spec.name] = { default: spec.default };
722
- }
723
- fromDOM(dom) {
724
- return Object.assign({}, ...this.specs.map((s) => ({ [s.name]: s.fromDOM(dom) })));
725
- }
726
- getStyle(node) {
727
- return this.specs.flatMap((s) => s.toStyles(node)).join("; ");
728
- }
729
- getDOMAttrsProperties(node) {
730
- if (!this.specs.length) return {};
731
- return { style: this.getStyle(node) };
732
- }
733
- getDOMAttrs(node) {
734
- if (!this.specs.length) return [];
735
- return [this.getDOMAttrsProperties(node)];
736
- }
737
- extractFromNode(node) {
738
- return Object.assign({}, ...Object.keys(this.attrs).map((attr) => ({ [attr]: node.attrs[attr] })));
739
- }
740
- };
741
- //#endregion
742
- //#region src/lib/rich-text-editor/rte/utils/textblock-marks.ts
743
- var TextblockMarks = class {
744
- constructor(specs) {
745
- this.specs = specs;
199
+ #applyStep(thumb, direction) {
200
+ this.#updateValues({ [thumb]: this.#roundToNearestStep(thumb, Number(this[thumb]) + direction * this.step).toString() });
746
201
  }
747
- getAllowedMarksForNode(nodeName) {
748
- return this.specs.filter((spec) => !spec.onNodeName || spec.onNodeName === nodeName).map((spec) => spec.markName);
749
- }
750
- getReferencedNodeNames() {
751
- return new Set(this.specs.map((spec) => spec.onNodeName).filter(Boolean));
202
+ /** @internal */
203
+ orientationChanged() {
204
+ if (this.$fastController.isConnected) this.#updateThumbPositions();
752
205
  }
753
- };
754
- //#endregion
755
- //#region src/lib/rich-text-editor/rte/view.ts
756
- /**
757
- * Converts an RteDocument to an RteView tree for rendering outside the editor.
758
- * The logic is adapted from ProseMirror's DOM serialization to ensure the resulting structure
759
- * matches the editor's HTML structure.
760
- */
761
- var convertToView = (doc, ctx) => {
762
- const schema = ctx.config[impl].schema;
763
- const getMarkRank = (mark) => schema.marks[mark.type].rank;
764
- const marksEqual = (a, b) => {
765
- if (a.type !== b.type) return false;
766
- const attrsA = a.attrs;
767
- const attrsB = b.attrs;
768
- if (attrsA === attrsB) return true;
769
- /* v8 ignore next -- not currently reachable since all attrs are required @preserve */
770
- if (!attrsA || !attrsB) return false;
771
- const keysA = Object.keys(attrsA);
772
- const keysB = Object.keys(attrsB);
773
- /* v8 ignore next -- not currently reachable since all attrs are required @preserve */
774
- if (keysA.length !== keysB.length) return false;
775
- for (const key of keysA) if (attrsA[key] !== attrsB[key]) return false;
776
- return true;
777
- };
778
- const convertFragment = (nodes) => {
779
- const result = [];
780
- const active = [];
781
- const activeContents = [result];
782
- for (const node of nodes) {
783
- const nodeMarks = [...node.marks ?? []].sort((a, b) => getMarkRank(a) - getMarkRank(b));
784
- let keep = 0;
785
- let rendered = 0;
786
- while (keep < active.length && rendered < nodeMarks.length) {
787
- if (!marksEqual(active[keep], nodeMarks[rendered])) break;
788
- keep++;
789
- rendered++;
790
- }
791
- while (active.length > keep) {
792
- active.pop();
793
- activeContents.pop();
794
- }
795
- while (rendered < nodeMarks.length) {
796
- const mark = nodeMarks[rendered];
797
- const markContent = [];
798
- activeContents[activeContents.length - 1].push({
799
- type: "mark",
800
- mark,
801
- children: {
802
- type: "fragment",
803
- content: markContent,
804
- [impl]: ctx
805
- },
806
- [impl]: ctx
807
- });
808
- active.push(mark);
809
- activeContents.push(markContent);
810
- rendered++;
811
- }
812
- activeContents[activeContents.length - 1].push({
813
- type: "node",
814
- node,
815
- children: convertFragment(node.content ?? []),
816
- [impl]: ctx
817
- });
206
+ /** @internal */
207
+ nameChanged(previous, next) {
208
+ super.nameChanged(previous, next);
209
+ this.#updateFormValue();
210
+ }
211
+ #updateFormValue() {
212
+ if (!this.name) this.setFormValue(null);
213
+ else {
214
+ const formData = new FormData();
215
+ formData.append(this.name, this.start);
216
+ formData.append(this.name, this.end);
217
+ this.setFormValue(formData);
818
218
  }
819
- return {
820
- type: "fragment",
821
- content: result,
822
- [impl]: ctx
823
- };
824
- };
825
- return {
826
- type: "node",
827
- node: doc,
828
- children: convertFragment(doc.content),
829
- [impl]: ctx
830
- };
831
- };
832
- //#endregion
833
- //#region src/lib/rich-text-editor/rte/config.ts
834
- var RteConfig = class {
835
- constructor(features) {
836
- this[impl] = new RteConfigImpl(features);
837
219
  }
838
- instantiateEditor(options) {
839
- return new RteInstance(this, options);
840
- }
841
- instantiateView(document, options) {
842
- return convertToView(document, {
843
- config: this,
844
- options: { ...options }
220
+ /** Resets `start` and `end` to their initial values when the form is reset. */
221
+ formResetCallback() {
222
+ this.#updateValues({
223
+ start: this.initialStart ?? this.min.toString(),
224
+ end: this.initialEnd ?? this.max.toString()
845
225
  });
226
+ super.formResetCallback();
846
227
  }
847
- };
848
- var RteConfigImpl = class {
849
- constructor(featuresFacades) {
850
- const resolveFeatures = (features) => features.flatMap((f) => f.getFeatures().flatMap((subFeature) => subFeature === f ? f : resolveFeatures([subFeature])));
851
- this.features = resolveFeatures(featuresFacades.map(getFeatureImpl));
852
- this.featureMap = /* @__PURE__ */ new Map();
853
- for (const f of this.features) {
854
- if (this.featureMap.has(f.name)) throw new Error(`Duplicate feature: ${f.name}`);
855
- this.featureMap.set(f.name, f);
856
- }
857
- this.featureFacadesMap = /* @__PURE__ */ new Map();
858
- for (const facade of featuresFacades) {
859
- const FacadeClass = facade.constructor;
860
- const feature = getFeatureImpl(facade);
861
- const instances = this.featureFacadesMap.get(FacadeClass);
862
- if (instances) instances.push(feature);
863
- else this.featureFacadesMap.set(FacadeClass, [feature]);
864
- }
865
- if (!this.featureMap.has("RteBase")) throw new Error("RteBase feature is required");
866
- if (this.featureMap.has("RteLinkFeature") && !this.featureMap.has("RteToolbarFeature")) throw new Error("RteToolbarFeature is required for RteLinkFeature");
867
- this.textblockAttrs = new TextblockAttrs(sortedContributions(this.features.flatMap((f) => f.getTextblockAttrs())));
868
- this.textblockMarks = new TextblockMarks(sortedContributions(this.features.flatMap((f) => f.getTextblockMarks())));
869
- const schemaContributions = sortedContributions(this.features.flatMap((f) => f.getSchema(this.textblockAttrs, this.textblockMarks)));
870
- const schemaSpec = {
871
- nodes: {},
872
- marks: {}
228
+ get #thumbs() {
229
+ return {
230
+ start: this._startThumbEl,
231
+ end: this._endThumbEl
873
232
  };
874
- for (const schema of schemaContributions) {
875
- Object.assign(schemaSpec.nodes, schema.nodes ?? {});
876
- Object.assign(schemaSpec.marks, schema.marks ?? {});
877
- }
878
- for (const referencedNodeName of this.textblockMarks.getReferencedNodeNames()) if (!(referencedNodeName in schemaSpec.nodes)) throw new Error(`Unknown node "${referencedNodeName}"`);
879
- this.schema = new Schema(schemaSpec);
880
- }
881
- };
882
- //#endregion
883
- //#region src/lib/rich-text-editor/rte/utils/ui.ts
884
- var isPropBinding = (prop) => typeof prop === "function";
885
- var on = (event, prop, handler) => [
886
- event,
887
- prop,
888
- handler
889
- ];
890
- var UiCtx = class {
891
- constructor(view, rte, props) {
892
- this.view = view;
893
- this.rte = rte;
894
- this.props = props;
895
- this.bindings = [];
896
- }
897
- /** Evaluates a prop, returning its current value. */
898
- evalProp(prop) {
899
- return isPropBinding(prop) ? prop(this) : prop;
900
- }
901
- /** On every state change, prop is re-evaluated and passed to bindFn. */
902
- bindProp(prop, bindFn) {
903
- if (prop === void 0) return;
904
- else if (isPropBinding(prop)) {
905
- const binding = () => bindFn(prop(this));
906
- this.bindings.push(binding);
907
- binding();
908
- } else bindFn(prop);
909
- }
910
- /** To be called on each state update to refresh all bindings. */
911
- updateBindings() {
912
- for (const binding of this.bindings) binding();
913
- }
914
- /** Whether to return focus to the editor after a toolbar action */
915
- shouldReturnFocusToEditor() {
916
- return this.evalProp(this.props.shouldReturnFocusToEditor);
917
- }
918
- /** Utility to more conveniently bind props to elements */
919
- bindToEl(target, props = {}, events = [], children = []) {
920
- for (const name in props) this.bindProp(props[name], (value) => {
921
- target[name] = value;
922
- });
923
- for (const [name, value, bindFn] of events) if (value) target.addEventListener(name, bindFn(value));
924
- for (const child of children) target.appendChild(child);
925
- }
926
- };
927
- var createDiv = (ctx, props) => {
928
- const div = document.createElement("div");
929
- ctx.bindToEl(div, {
930
- className: props.className,
931
- slot: props.slot
932
- }, [], props.children);
933
- return div;
934
- };
935
- var createAnchor = (ctx, props) => {
936
- const anchor = document.createElement("a");
937
- ctx.bindToEl(anchor, {
938
- href: props.href,
939
- target: props.target,
940
- rel: props.rel,
941
- className: props.className
942
- }, [], props.children);
943
- return anchor;
944
- };
945
- var wrapperTargets = /* @__PURE__ */ new WeakMap();
946
- var createOptionalTooltip = (ctx, props) => {
947
- const tooltip = ctx.rte.createComponent(Tooltip);
948
- tooltip.setAttribute("exportparts", "vvd-theme-alternate");
949
- ctx.bindToEl(tooltip, {
950
- className: "ui-tooltip",
951
- text: props.label,
952
- placement: ctx.props.popupPlacement
953
- });
954
- ctx.bindProp(props.enabled, (enabled) => {
955
- if (!enabled) tooltip.open = false;
956
- tooltip.anchor = enabled ? props.anchor : void 0;
957
- });
958
- const wrapper = createDiv(ctx, {
959
- className: "ui-tooltip-wrapper",
960
- slot: props.slot,
961
- children: [props.anchor, tooltip]
962
- });
963
- wrapperTargets.set(wrapper, props.anchor);
964
- return wrapper;
965
- };
966
- var createButton = (ctx, props) => {
967
- const variant = () => ctx.evalProp(props.variant) ?? "toolbar";
968
- const size = () => variant() === "toolbar" ? "super-condensed" : "condensed";
969
- const appearanceInactive = () => variant() === "popover-primary" ? "outlined" : "ghost-light";
970
- const appearanceActive = () => variant() === "toolbar-menu" || variant() === "popover" ? "filled" : appearanceInactive();
971
- const appearance = () => ctx.evalProp(props.active) ? appearanceActive() : appearanceInactive();
972
- const connotation = () => ctx.evalProp(props.connotation) ?? (variant() === "toolbar-menu" && ctx.evalProp(props.active) ? "cta" : void 0);
973
- const disabled = () => Boolean(ctx.evalProp(ctx.props.disabled) || ctx.evalProp(props.disabled));
974
- const button = ctx.rte.createComponent(Button);
975
- ctx.bindToEl(button, {
976
- size,
977
- appearance,
978
- disabled,
979
- icon: props.icon,
980
- autofocus: props.autofocus,
981
- connotation,
982
- [props.icon ? "ariaLabel" : "label"]: props.label,
983
- pressed: () => Boolean(ctx.evalProp(props.active)),
984
- ariaPressed: props.active !== void 0 ? () => ctx.evalProp(props.active) ? "true" : "false" : void 0
985
- }, [on("click", props.onClick, (onClick) => () => {
986
- if (!onClick() && ctx.shouldReturnFocusToEditor()) ctx.view.focus();
987
- })]);
988
- return createOptionalTooltip(ctx, {
989
- enabled: () => Boolean(ctx.evalProp(props.icon) && !ctx.evalProp(props.noTooltip) && !disabled()),
990
- label: props.label,
991
- anchor: button,
992
- slot: props.slot
993
- });
994
- };
995
- var createMenu = (ctx, props) => {
996
- const menu = ctx.rte.createComponent(Menu);
997
- ctx.bindToEl(menu, {
998
- className: "ui-menu",
999
- autoDismiss: true,
1000
- ariaLabel: props.label,
1001
- anchor: wrapperTargets.get(props.trigger) ?? props.trigger,
1002
- placement: ctx.props.popupPlacement,
1003
- offset: () => ctx.evalProp(ctx.props.menuOffset) ?? null
1004
- }, [], props.children);
1005
- const fragment = document.createDocumentFragment();
1006
- fragment.appendChild(props.trigger);
1007
- fragment.appendChild(menu);
1008
- return fragment;
1009
- };
1010
- var createMenuItem = (ctx, props) => {
1011
- const disabled = () => Boolean(ctx.evalProp(ctx.props.disabled) || ctx.evalProp(props.disabled));
1012
- const item = ctx.rte.createComponent(MenuItem);
1013
- ctx.bindToEl(item, {
1014
- text: props.text,
1015
- checked: props.checked,
1016
- disabled,
1017
- controlType: "radio",
1018
- checkedAppearance: "tick-only"
1019
- }, [on("change", props.onSelect, (onSelect) => () => {
1020
- if (item.checked && !item.disabled) {
1021
- if (ctx.evalProp(props.checked) !== item.checked) {
1022
- onSelect();
1023
- if (ctx.shouldReturnFocusToEditor()) ctx.view.focus();
1024
- }
1025
- }
1026
- })]);
1027
- return item;
1028
- };
1029
- var createButtonGroup = (ctx, props) => createDiv(ctx, {
1030
- slot: props.slot,
1031
- className: "ui-button-group",
1032
- children: props.children
1033
- });
1034
- function markActive(state, type) {
1035
- const { from, $from, to, empty } = state.selection;
1036
- if (empty) return !!type.isInSet(state.storedMarks || $from.marks());
1037
- else return state.doc.rangeHasMark(from, to, type);
1038
- }
1039
- var createMarkToggle = (ctx, props) => createButton(ctx, {
1040
- label: props.label,
1041
- icon: props.icon,
1042
- active: () => markActive(ctx.view.state, props.markType),
1043
- disabled: () => !toggleMark(props.markType)(ctx.view.state),
1044
- onClick: () => {
1045
- toggleMark(props.markType)(ctx.view.state, ctx.view.dispatch);
1046
- }
1047
- });
1048
- var createOption = (ctx, props) => {
1049
- const disabled = () => Boolean(ctx.evalProp(ctx.props.disabled) || ctx.evalProp(props.disabled));
1050
- const option = ctx.rte.createComponent(ListboxOption);
1051
- ctx.bindToEl(option, {
1052
- value: props.value,
1053
- text: props.text,
1054
- disabled
1055
- });
1056
- return option;
1057
- };
1058
- var createSelect = (ctx, props) => {
1059
- const disabled = () => Boolean(ctx.evalProp(ctx.props.disabled));
1060
- const select = ctx.rte.createComponent(Select);
1061
- select.setAttribute("data-class", "ui-select");
1062
- ctx.bindToEl(select, {
1063
- placeholder: " ",
1064
- ariaLabel: props.label,
1065
- appearance: "ghost",
1066
- disabled
1067
- }, [on("change", props.onSelect, (onSelect) => () => {
1068
- const value = select.value;
1069
- if (value) {
1070
- onSelect(value);
1071
- if (ctx.shouldReturnFocusToEditor()) ctx.view.focus();
1072
- }
1073
- })], props.children);
1074
- queueMicrotask(() => {
1075
- ctx.bindProp(props.value, (value) => select.value = value);
1076
- });
1077
- let hideTooltip = false;
1078
- select.addEventListener("vwc-popup:open", () => {
1079
- hideTooltip = true;
1080
- ctx.updateBindings();
1081
- });
1082
- select.addEventListener("vwc-popup:close", () => {
1083
- hideTooltip = false;
1084
- ctx.updateBindings();
1085
- });
1086
- return createOptionalTooltip(ctx, {
1087
- enabled: () => !hideTooltip && !disabled(),
1088
- label: props.label,
1089
- anchor: select
1090
- });
1091
- };
1092
- var createDivider = (ctx) => {
1093
- const divider = ctx.rte.createComponent(Divider);
1094
- ctx.bindToEl(divider, {
1095
- className: "ui-divider",
1096
- orientation: "vertical"
1097
- });
1098
- return divider;
1099
- };
1100
- var createTextField = (ctx, props) => {
1101
- const textField = ctx.rte.createComponent(TextField);
1102
- ctx.bindToEl(textField, {
1103
- label: props.label,
1104
- value: props.value,
1105
- placeholder: props.placeholder,
1106
- slot: props.slot,
1107
- autofocus: props.autofocus,
1108
- type: props.type,
1109
- helperText: props.helperText
1110
- }, [on("input", props.onInput, (onInput) => () => {
1111
- onInput(textField.value);
1112
- })]);
1113
- return textField;
1114
- };
1115
- var createText = (ctx, props) => {
1116
- const textNode = document.createTextNode("");
1117
- ctx.bindToEl(textNode, { textContent: props.text });
1118
- return textNode;
1119
- };
1120
- var createSingleSlot = (ctx, props) => {
1121
- const slot = document.createElement("slot");
1122
- slot.name = props.name;
1123
- let currentEl = null;
1124
- const listeners = [];
1125
- function cleanup() {
1126
- for (const { el, type, handler } of listeners) el.removeEventListener(type, handler);
1127
- listeners.length = 0;
1128
- currentEl = null;
1129
- }
1130
- for (const [key, prop] of Object.entries(props.assignedProps)) ctx.bindProp(prop, (value) => {
1131
- if (currentEl) currentEl[key] = value;
1132
- });
1133
- function applyPropsAndEvents(el) {
1134
- for (const [key, prop] of Object.entries(props.assignedProps)) el[key] = ctx.evalProp(prop);
1135
- for (const [type, handler] of Object.entries(props.assignedEvents)) {
1136
- const listener = (e) => {
1137
- handler(e);
1138
- if (ctx.shouldReturnFocusToEditor()) ctx.view.focus();
1139
- };
1140
- el.addEventListener(type, listener);
1141
- listeners.push({
1142
- el,
1143
- type,
1144
- handler: listener
1145
- });
1146
- }
1147
233
  }
1148
- const processSlot = () => {
1149
- const first = slot.assignedElements({ flatten: true })[0];
1150
- if (first === currentEl) return;
1151
- cleanup();
1152
- if (first) {
1153
- currentEl = first;
1154
- applyPropsAndEvents(first);
1155
- }
1156
- };
1157
- slot.addEventListener("slotchange", processSlot);
1158
- queueMicrotask(processSlot);
1159
- return slot;
1160
- };
1161
- //#endregion
1162
- //#region src/lib/rich-text-editor/rte/features/internal/history.ts
1163
- var RteHistoryFeatureImpl = class extends RteFeatureImpl {
1164
- constructor(config) {
1165
- super();
1166
- this.config = config;
1167
- this.name = "RteHistoryFeature";
234
+ get #thumbConstraints() {
235
+ return {
236
+ start: {
237
+ min: this.min,
238
+ max: this.endAsNumber
239
+ },
240
+ end: {
241
+ min: this.startAsNumber,
242
+ max: this.max
243
+ }
244
+ };
245
+ }
246
+ #getThumbId(thumb) {
247
+ return thumb === this._startThumbEl ? "start" : "end";
248
+ }
249
+ #getThumbIdFromEvent(e) {
250
+ return this.#getThumbId(e.target);
251
+ }
252
+ #updateThumbPositions() {
253
+ const startOffsetPct = this.#thumbTrackEndOffset(this.startAsNumber);
254
+ const endOffsetPct = this.#thumbTrackEndOffset(this.endAsNumber);
255
+ const [dirProp, dimProp] = this.orientation === Orientation.horizontal ? ["right", "width"] : ["bottom", "height"];
256
+ const transition = `transition: ${this._draggingThumb ? "none" : "all 0.2s ease"};`;
257
+ this._startThumbCss = `${dirProp}: ${startOffsetPct}%; ${transition}`;
258
+ this._endThumbCss = `${dirProp}: ${endOffsetPct}%; ${transition}`;
259
+ this._selectedRangeCss = `${dirProp}: ${endOffsetPct}%; ${dimProp}: ${startOffsetPct - endOffsetPct}%; ${transition}`;
260
+ }
261
+ #thumbTrackEndOffset(value) {
262
+ return (1 - inverseLerp(this.min, this.max, value)) * 100;
263
+ }
264
+ #calculateValueFromMouseEvent(e) {
265
+ const trackClientRect = this._trackEl.getBoundingClientRect();
266
+ const [minPos, maxPos, valuePos] = this.orientation === Orientation.horizontal ? [
267
+ this._trackEl.clientLeft,
268
+ this._trackEl.clientWidth,
269
+ e.pageX - document.documentElement.scrollLeft - this.getBoundingClientRect().left
270
+ ] : [
271
+ trackClientRect.top,
272
+ trackClientRect.bottom,
273
+ e.pageY - document.documentElement.scrollTop
274
+ ];
275
+ return lerp(this.min, this.max, inverseLerp(minPos, maxPos, valuePos));
1168
276
  }
1169
- getPlugins() {
1170
- return [this.contribution(history()), this.contribution(keymap({
1171
- "Mod-z": undo,
1172
- "Ctrl-y": redo,
1173
- "Cmd-Z": redo
1174
- }))];
277
+ #roundToNearestStep(thumb, value) {
278
+ return limit(this.#thumbConstraints[thumb].min, this.#thumbConstraints[thumb].max, roundToStepValue(value - this.min, this.step) + this.min);
1175
279
  }
1176
- getToolbarItems() {
1177
- if (!this.config.showToolbarButtons) return [];
1178
- return [this.contribution({
1179
- section: "history",
1180
- render: (ctx) => createButton(ctx, {
1181
- label: (ctx) => ctx.rte.getLocale().richTextEditor.undo,
1182
- icon: "undo-line",
1183
- disabled: (ctx) => !undo(ctx.view.state),
1184
- onClick: () => {
1185
- const { state, dispatch } = ctx.view;
1186
- undo(state, dispatch);
1187
- }
1188
- })
1189
- }, 1), this.contribution({
1190
- section: "history",
1191
- render: (ctx) => createButton(ctx, {
1192
- label: (ctx) => ctx.rte.getLocale().richTextEditor.redo,
1193
- icon: "redo-line",
1194
- disabled: (ctx) => !redo(ctx.view.state),
1195
- onClick: () => {
1196
- const { state, dispatch } = ctx.view;
1197
- redo(state, dispatch);
1198
- }
1199
- })
1200
- }, 2)];
280
+ #isNonVisibleFocus;
281
+ #focusThumbNonVisibly(thumb) {
282
+ this.#isNonVisibleFocus = true;
283
+ thumb.focus();
284
+ this.#isNonVisibleFocus = false;
1201
285
  }
1202
- };
1203
- //#endregion
1204
- //#region src/lib/rich-text-editor/rte/features/internal/basic-text-blocks.style.scss?inline
1205
- var basic_text_blocks_style_default = "h1,h2,h3,p{all:unset;display:block}h1:first-child,h2:first-child,h3:first-child,p:first-child{margin-block-start:0}h1:last-child,h2:last-child,h3:last-child,p:last-child{margin-block-end:0}p{font:var(--vvd-typography-base);font-variant-ligatures:unset;font-feature-settings:unset;margin-block:16px;line-height:20px}.heading-step-1{font:var(--vvd-typography-heading-4);font-variant-ligatures:unset;font-feature-settings:unset;margin-block:24px 12px;line-height:28px}.heading-step-2{font:var(--vvd-typography-heading-3);font-variant-ligatures:unset;font-feature-settings:unset;margin-block:24px 12px;line-height:36px}.heading-step-3{font:var(--vvd-typography-heading-2);font-variant-ligatures:unset;font-feature-settings:unset;margin-block:32px 16px;line-height:42px}";
1206
- //#endregion
1207
- //#region src/lib/rich-text-editor/rte/features/internal/basic-text-blocks.ts
1208
- var RteBasicTextBlocksImpl = class extends RteFeatureImpl {
1209
- constructor(enabledBlocks) {
1210
- super();
1211
- this.enabledBlocks = enabledBlocks;
1212
- this.name = "RteBasicTextBlocks";
286
+ /** @internal */
287
+ _isThumbPopupOpen(thumb) {
288
+ return this._visiblyFocusedThumb === thumb || this._hoveredThumb === thumb || this._draggingThumb === thumb;
1213
289
  }
1214
- getStyles() {
1215
- return [this.contribution(basic_text_blocks_style_default)];
290
+ connectedCallback() {
291
+ super.connectedCallback();
292
+ this.#updateValues({
293
+ start: this.start || this.initialStart || this.min.toString(),
294
+ end: this.end || this.initialEnd || this.max.toString()
295
+ }, false);
296
+ this.#registerThumbListeners();
297
+ this.#updateThumbPositions();
298
+ document.addEventListener("visibilitychange", this.#onVisibilityChange);
1216
299
  }
1217
- getSchema(textblockAttrs, textblockMarks) {
1218
- const nodes = {};
1219
- if (this.enabledBlocks.paragraph) nodes["paragraph"] = {
1220
- group: "block",
1221
- content: "inline*",
1222
- attrs: { ...textblockAttrs.attrs },
1223
- parseDOM: [{
1224
- tag: "p",
1225
- getAttrs: (dom) => textblockAttrs.fromDOM(dom)
1226
- }],
1227
- marks: textblockMarks.getAllowedMarksForNode("paragraph").join(" "),
1228
- toDOM(node) {
1229
- return [
1230
- "p",
1231
- {
1232
- part: `node--paragraph`,
1233
- ...textblockAttrs.getDOMAttrsProperties(node)
1234
- },
1235
- 0
1236
- ];
1237
- },
1238
- serializeToDOM(node) {
1239
- return [
1240
- "p",
1241
- ...textblockAttrs.getDOMAttrs(node),
1242
- 0
1243
- ];
1244
- }
1245
- };
1246
- let headingCount = 0;
1247
- for (const level of [
1248
- 3,
1249
- 2,
1250
- 1
1251
- ]) {
1252
- const nodeName = `heading${level}`;
1253
- const tag = `h${level}`;
1254
- if (!this.enabledBlocks[nodeName]) continue;
1255
- headingCount++;
1256
- const visualLevel = headingCount;
1257
- nodes[nodeName] = {
1258
- group: "block",
1259
- content: "inline*",
1260
- attrs: { ...textblockAttrs.attrs },
1261
- parseDOM: [{
1262
- tag,
1263
- getAttrs: (dom) => textblockAttrs.fromDOM(dom)
1264
- }],
1265
- marks: textblockMarks.getAllowedMarksForNode(nodeName).join(" "),
1266
- defining: true,
1267
- toDOM(node) {
1268
- return [
1269
- tag,
1270
- {
1271
- class: `heading-step-${visualLevel}`,
1272
- part: `node--${nodeName}`,
1273
- ...textblockAttrs.getDOMAttrsProperties(node)
1274
- },
1275
- 0
1276
- ];
1277
- },
1278
- serializeToDOM(node) {
1279
- return [
1280
- tag,
1281
- ...textblockAttrs.getDOMAttrs(node),
1282
- 0
1283
- ];
1284
- }
1285
- };
300
+ disconnectedCallback() {
301
+ super.disconnectedCallback();
302
+ this.#unregisterThumbListeners();
303
+ this.#unregisterDragListeners();
304
+ document.removeEventListener("visibilitychange", this.#onVisibilityChange);
305
+ }
306
+ #registerThumbListeners() {
307
+ for (const thumb of ["start", "end"]) {
308
+ this.#thumbs[thumb].addEventListener("keydown", this.#onThumbKeydown);
309
+ this.#thumbs[thumb].addEventListener("mousedown", this.#onThumbMousedown, { passive: true });
310
+ this.#thumbs[thumb].addEventListener("touchstart", this.#onThumbMousedown, { passive: true });
311
+ this.#thumbs[thumb].addEventListener("mouseover", this.#onMouseOver, { passive: true });
312
+ this.#thumbs[thumb].addEventListener("mouseout", this.#onMouseOut, { passive: true });
313
+ this.#thumbs[thumb].addEventListener("focus", this.#onThumbFocus);
314
+ this.#thumbs[thumb].addEventListener("blur", this.#onThumbBlur);
1286
315
  }
1287
- return [this.contribution({ nodes })];
1288
316
  }
1289
- getPlugins(rte) {
1290
- const keyBindings = {};
1291
- if (this.enabledBlocks.paragraph) keyBindings["Mod-Alt-0"] = this.setBlockType(rte, "paragraph");
1292
- for (const level of [
1293
- 1,
1294
- 2,
1295
- 3
1296
- ]) {
1297
- const nodeName = `heading${level}`;
1298
- if (this.enabledBlocks[nodeName]) keyBindings[`Mod-Alt-${level}`] = this.setBlockType(rte, nodeName);
317
+ #unregisterThumbListeners() {
318
+ for (const thumb of ["start", "end"]) {
319
+ this.#thumbs[thumb].removeEventListener("keydown", this.#onThumbKeydown);
320
+ this.#thumbs[thumb].removeEventListener("mousedown", this.#onThumbMousedown);
321
+ this.#thumbs[thumb].removeEventListener("touchstart", this.#onThumbMousedown);
322
+ this.#thumbs[thumb].removeEventListener("mouseover", this.#onMouseOver);
323
+ this.#thumbs[thumb].removeEventListener("mouseout", this.#onMouseOut);
324
+ this.#thumbs[thumb].removeEventListener("focus", this.#onThumbFocus);
325
+ this.#thumbs[thumb].removeEventListener("blur", this.#onThumbBlur);
1299
326
  }
1300
- return [this.contribution(keymap(keyBindings))];
1301
- }
1302
- getCurrentBlockType(state) {
1303
- const { $from, $to } = state.selection;
1304
- const fromTopBlock = $from.depth === 0 ? state.doc.childAfter($from.pos).node : $from.node(1);
1305
- if (fromTopBlock !== ($to.depth === 0 ? state.doc.childBefore($to.pos).node : $to.node(1))) return null;
1306
- if (!(fromTopBlock.type.name in this.enabledBlocks)) return null;
1307
- return fromTopBlock.type.name;
1308
- }
1309
- setBlockType(rte, name) {
1310
- return (state, dispatch) => {
1311
- const { from, to } = state.selection;
1312
- const tr = state.tr;
1313
- let supportedNodeFound = false;
1314
- state.doc.nodesBetween(from, to, (node, pos) => {
1315
- if (node.type.name in this.enabledBlocks) {
1316
- supportedNodeFound = true;
1317
- tr.setBlockType(pos, pos + node.nodeSize, state.schema.nodes[name], (oldNode) => rte.textblockAttrs.extractFromNode(oldNode));
1318
- }
1319
- return false;
1320
- });
1321
- if (!supportedNodeFound) return false;
1322
- dispatch?.(tr);
1323
- return true;
1324
- };
1325
- }
1326
- };
1327
- //#endregion
1328
- //#region src/lib/rich-text-editor/rte/utils/text-before-cursor.ts
1329
- /** Get the text content before the cursor position in the current text block. */
1330
- var textBeforeCursor = ($cursor) => $cursor.parent.textBetween(0, $cursor.parentOffset, void 0, "");
1331
- //#endregion
1332
- //#region src/lib/rich-text-editor/rte/features/internal/input-rules.ts
1333
- /** Aggregates all input rules from other features. */
1334
- var RteInputRulesFeatureImpl = class extends RteFeatureImpl {
1335
- constructor(..._args) {
1336
- super(..._args);
1337
- this.name = "RteInputRulesFeature";
1338
- }
1339
- getPlugins(rte) {
1340
- const ruleSpecs = sortedContributions(rte.config.features.flatMap((f) => f.getInputRules(rte)));
1341
- if (ruleSpecs.length === 0) return [];
1342
- const plugins = [];
1343
- const rules = ruleSpecs.map((spec) => spec.rule);
1344
- plugins.push(this.contribution(inputRules({ rules })));
1345
- plugins.push(this.contribution(keymap({ Backspace: undoInputRule }), contributionPriority.high));
1346
- const enterHandlers = ruleSpecs.filter((spec) => spec.enterHandler).map((spec) => spec.enterHandler);
1347
- if (enterHandlers.length > 0) plugins.push(this.contribution(keymap({ Enter: (state, dispatch) => {
1348
- const { $cursor } = state.selection;
1349
- if (!$cursor) return false;
1350
- const textBefore = textBeforeCursor($cursor);
1351
- for (const { regex, handler } of enterHandlers) {
1352
- const match = regex.exec(textBefore);
1353
- if (!match) continue;
1354
- const matchStart = $cursor.pos - $cursor.parentOffset + match.index;
1355
- const tr = handler(state, match, matchStart, matchStart + match[0].length);
1356
- if (tr) dispatch?.(tr);
1357
- break;
1358
- }
1359
- return false;
1360
- } }), contributionPriority.highest));
1361
- return plugins;
1362
- }
1363
- };
1364
- //#endregion
1365
- //#region src/lib/rich-text-editor/rte/features/base.ts
1366
- var RteBaseImpl = class extends RteFeatureImpl {
1367
- constructor(config) {
1368
- super();
1369
- this.config = config;
1370
- this.name = "RteBase";
1371
- }
1372
- getSchema() {
1373
- return [this.contribution({ nodes: {
1374
- doc: { content: this.config?.singleBlock ? "block" : "block+" },
1375
- text: { group: "inline" }
1376
- } })];
1377
- }
1378
- getFeatures() {
1379
- return [
1380
- this,
1381
- new RteCoreImpl(),
1382
- new RteHistoryFeatureImpl({ showToolbarButtons: this.config?.historyToolbarButtons ?? true }),
1383
- new RteBasicTextBlocksImpl({
1384
- heading1: this.config?.heading1 ?? false,
1385
- heading2: this.config?.heading2 ?? false,
1386
- heading3: this.config?.heading3 ?? false,
1387
- paragraph: this.config?.paragraph ?? true
1388
- }),
1389
- new RteInputRulesFeatureImpl()
1390
- ];
1391
- }
1392
- getPublicInterface(rte) {
1393
- const core = rte.getFeature("RteCore");
1394
- return {
1395
- get disabled() {
1396
- return core.disabled.getValue(rte);
1397
- },
1398
- set disabled(value) {
1399
- core.disabled.setValue(rte, value);
1400
- },
1401
- get scrollThreshold() {
1402
- return core.scrollThreshold;
1403
- },
1404
- set scrollThreshold(value) {
1405
- core.scrollThreshold = value;
1406
- rte.view?.setProps({ scrollThreshold: value });
1407
- },
1408
- get scrollMargin() {
1409
- return core.scrollMargin;
1410
- },
1411
- set scrollMargin(value) {
1412
- core.scrollMargin = value;
1413
- rte.view?.setProps({ scrollMargin: value });
1414
- }
1415
- };
1416
- }
1417
- };
1418
- var RteBase = featureFacade(RteBaseImpl);
1419
- //#endregion
1420
- //#region src/lib/rich-text-editor/rte/features/text-block-picker.ts
1421
- var RteTextBlockPickerFeatureImpl = class extends RteFeatureImpl {
1422
- constructor(config) {
1423
- super();
1424
- this.config = config;
1425
- this.name = "RteTextBlockPickerFeature";
1426
- }
1427
- getToolbarItems(rte) {
1428
- const blocks = rte.getFeature("RteBasicTextBlocks");
1429
- return [this.contribution({
1430
- section: "font",
1431
- render: (ctx) => {
1432
- return createSelect(ctx, {
1433
- label: () => ctx.rte.getLocale().richTextEditor.paragraphStyles,
1434
- value: (ctx) => blocks.getCurrentBlockType(ctx.view.state) ?? "",
1435
- onSelect: (value) => {
1436
- const { state, dispatch } = ctx.view;
1437
- blocks.setBlockType(rte, value)(state, dispatch);
1438
- },
1439
- children: this.config.options.map((opt) => createOption(ctx, {
1440
- text: opt.label,
1441
- value: opt.node,
1442
- disabled: () => !blocks.setBlockType(rte, opt.node)(ctx.view.state)
1443
- }))
1444
- });
1445
- }
1446
- }, 1)];
1447
- }
1448
- };
1449
- var RteTextBlockPickerFeature = featureFacade(RteTextBlockPickerFeatureImpl);
1450
- //#endregion
1451
- //#region src/lib/rich-text-editor/rte/features/toolbar.style.scss?inline
1452
- var toolbar_style_default = ".toolbar{background-color:var(--vvd-color-neutral-50);flex-wrap:wrap;align-items:center;gap:8px;padding:4px;display:flex}.toolbar--hidden{display:none}";
1453
- //#endregion
1454
- //#region src/lib/rich-text-editor/rte/features/toolbar.ts
1455
- var RteToolbarFeatureImpl = class extends RteFeatureImpl {
1456
- constructor(config) {
1457
- super();
1458
- this.config = config;
1459
- this.name = "RteToolbarFeature";
1460
- this.hidden = new FeatureState(false);
1461
- }
1462
- getStyles() {
1463
- return [this.contribution(toolbar_style_default)];
1464
- }
1465
- getPlugins(rte) {
1466
- const sections = [
1467
- "history",
1468
- "font",
1469
- "text-style",
1470
- "textblock",
1471
- "insert"
1472
- ];
1473
- const itemsBySection = new Map(sections.map((section) => [section, []]));
1474
- for (const toolbarItem of sortedContributions(rte.features.flatMap((f) => f.getToolbarItems(rte)))) itemsBySection.get(toolbarItem.section).push(toolbarItem);
1475
- const core = rte.getFeature("RteCore");
1476
- return [this.contribution(this.hidden.plugin), this.contribution(new Plugin({ view: (view) => {
1477
- let focusCameFromEditorWithMouse = false;
1478
- const ctx = new UiCtx(view, rte, {
1479
- popupPlacement: this.config?.popupDirection === "outward" ? "bottom" : "top",
1480
- menuOffset: 8,
1481
- disabled: () => core.disabled.getValue(rte),
1482
- shouldReturnFocusToEditor: () => focusCameFromEditorWithMouse
1483
- });
1484
- const toolbar = view.dom.getRootNode().querySelector(".toolbar");
1485
- let mouseDownTime = -Infinity;
1486
- const onMouseDown = () => {
1487
- if (view.hasFocus()) focusCameFromEditorWithMouse = true;
1488
- mouseDownTime = Date.now();
1489
- };
1490
- const onFocusIn = () => {
1491
- if (Date.now() - mouseDownTime > 250) focusCameFromEditorWithMouse = false;
1492
- };
1493
- const onFocusOut = (e) => {
1494
- if (!toolbar.contains(e.relatedTarget)) focusCameFromEditorWithMouse = false;
1495
- };
1496
- toolbar.addEventListener("mousedown", onMouseDown, { capture: true });
1497
- toolbar.addEventListener("focusin", onFocusIn);
1498
- toolbar.addEventListener("focusout", onFocusOut);
1499
- ctx.bindProp(() => this.hidden.getValue(rte), (hidden) => {
1500
- toolbar.classList.toggle("toolbar--hidden", hidden);
1501
- });
1502
- let openSection = false;
1503
- for (const section of sections) {
1504
- const items = itemsBySection.get(section);
1505
- if (items.length && openSection) {
1506
- toolbar.appendChild(createDivider(ctx));
1507
- openSection = false;
1508
- }
1509
- for (const toolbarItemSpec of items) {
1510
- toolbar.appendChild(toolbarItemSpec.render(ctx));
1511
- openSection = true;
1512
- }
1513
- }
1514
- return {
1515
- update() {
1516
- ctx.updateBindings();
1517
- },
1518
- destroy() {
1519
- toolbar.innerHTML = "";
1520
- toolbar.removeEventListener("mousedown", onMouseDown, { capture: true });
1521
- toolbar.removeEventListener("focusin", onFocusIn);
1522
- toolbar.removeEventListener("focusout", onFocusOut);
1523
- focusCameFromEditorWithMouse = false;
1524
- }
1525
- };
1526
- } }))];
1527
- }
1528
- getPublicInterface(rte) {
1529
- const hidden = this.hidden;
1530
- return {
1531
- get hidden() {
1532
- return hidden.getValue(rte);
1533
- },
1534
- set hidden(value) {
1535
- hidden.setValue(rte, value);
1536
- }
1537
- };
1538
- }
1539
- };
1540
- var RteToolbarFeature = featureFacade(RteToolbarFeatureImpl);
1541
- //#endregion
1542
- //#region src/lib/rich-text-editor/rte/features/placeholder.style.scss?inline
1543
- var placeholder_style_default = ".placeholder{display:contents}.placeholder:before{color:var(--vvd-color-neutral-600);content:attr(data-placeholder);font-size:var(--placeholder-font-size,inherit);inset-inline:var(--editor-padding-inline);line-height:inherit;pointer-events:none;position:absolute}.editor--disabled .placeholder:before{color:var(--vvd-color-neutral-300)}";
1544
- //#endregion
1545
- //#region src/lib/rich-text-editor/rte/features/placeholder.ts
1546
- var RtePlaceholderFeatureImpl = class extends RteFeatureImpl {
1547
- constructor(config) {
1548
- super();
1549
- this.config = config;
1550
- this.name = "RtePlaceholderFeature";
1551
- }
1552
- getStyles() {
1553
- return [this.contribution(placeholder_style_default)];
1554
- }
1555
- getPlugins() {
1556
- const placeholderPlugin = new Plugin({ props: { decorations: (state) => {
1557
- if (state.doc.nodeSize === 4) {
1558
- const storedSize = state.schema.marks.fontSize?.isInSet(state.storedMarks ?? [])?.attrs.size;
1559
- return DecorationSet.create(state.doc, [Decoration.widget(1, () => {
1560
- const placeholder = document.createElement("span");
1561
- placeholder.className = "placeholder";
1562
- placeholder.dataset.placeholder = this.config.text;
1563
- if (storedSize) placeholder.style.setProperty("--placeholder-font-size", storedSize);
1564
- return placeholder;
1565
- })]);
1566
- }
1567
- return null;
1568
- } } });
1569
- return [this.contribution(placeholderPlugin)];
1570
- }
1571
- };
1572
- var RtePlaceholderFeature = featureFacade(RtePlaceholderFeatureImpl);
1573
- //#endregion
1574
- //#region src/lib/rich-text-editor/rte/features/hard-break.ts
1575
- var RteHardBreakFeatureImpl = class extends RteFeatureImpl {
1576
- constructor(..._args) {
1577
- super(..._args);
1578
- this.name = "RteHardBreakFeature";
1579
- }
1580
- getSchema() {
1581
- return [this.contribution({ nodes: { hardBreak: {
1582
- inline: true,
1583
- group: "inline",
1584
- selectable: false,
1585
- parseDOM: [{ tag: "br" }],
1586
- toDOM() {
1587
- return ["br"];
1588
- }
1589
- } } })];
1590
- }
1591
- getPlugins(_rte) {
1592
- const forceBreak = (state, dispatch) => {
1593
- const marks = state.storedMarks || state.selection.$from.marks();
1594
- const tr = state.tr.replaceSelectionWith(state.schema.nodes.hardBreak.create(), true).scrollIntoView();
1595
- if (marks.length) tr.setStoredMarks(marks);
1596
- dispatch?.(tr);
1597
- return true;
1598
- };
1599
- const keyBindings = { "Shift-Enter": forceBreak };
1600
- return [this.contribution(keymap(keyBindings), contributionPriority.high)];
1601
- }
1602
- };
1603
- var RteHardBreakFeature = featureFacade(RteHardBreakFeatureImpl);
1604
- //#endregion
1605
- //#region src/lib/rich-text-editor/rte/features/font-size-picker.ts
1606
- var mixedFontSize = Symbol("mixedFontSize");
1607
- var RteFontSizePickerFeatureImpl = class extends RteFeatureImpl {
1608
- constructor(config) {
1609
- super();
1610
- this.config = config;
1611
- this.name = "RteFontSizePickerFeature";
1612
- this.fontSizes = config.options;
1613
- if (config.onBlocks) {
1614
- this.defaultFontSizeForNode = {};
1615
- for (const block of config.onBlocks) this.defaultFontSizeForNode[block.node] = block.defaultSize ?? null;
1616
- }
1617
- }
1618
- getTextblockMarks() {
1619
- if (this.config?.onBlocks) return this.config.onBlocks.map((block) => this.contribution({
1620
- markName: "fontSize",
1621
- onNodeName: block.node
1622
- }));
1623
- return [this.contribution({ markName: "fontSize" })];
1624
- }
1625
- getSchema() {
1626
- return [this.contribution({ marks: { fontSize: {
1627
- attrs: { size: { validate: "string" } },
1628
- parseDOM: [{
1629
- tag: "span[style*='font-size']",
1630
- getAttrs: (node) => {
1631
- const size = node.getAttribute("style").match(/font-size:\s*([^;]+)/)?.[1]?.trim();
1632
- if (size) return { size };
1633
- return false;
1634
- }
1635
- }],
1636
- toDOM: (mark) => {
1637
- return [
1638
- "span",
1639
- { style: `font-size: ${escapeCssProperty(mark.attrs.size)};` },
1640
- 0
1641
- ];
1642
- },
1643
- cursorFix: ($cursor, state) => {
1644
- const storedMarks = state.storedMarks;
1645
- if (!storedMarks) return null;
1646
- const fontSizeMark = storedMarks.find((m) => m.type.name === "fontSize");
1647
- if (fontSizeMark) return { style: { "font-size": fontSizeMark.attrs.size } };
1648
- if (storedMarks.length === 0) {
1649
- const defaultSize = this.defaultFontSizeForNode?.[$cursor.parent.type.name];
1650
- if (defaultSize) return { style: { "font-size": defaultSize } };
1651
- }
1652
- return null;
1653
- }
1654
- } } })];
1655
- }
1656
- getPlugins() {
1657
- return [this.contribution(keymap({
1658
- "Mod-Shift-.": this.adjustFontSize(-1),
1659
- "Mod-Shift-,": this.adjustFontSize(1)
1660
- }))];
1661
- }
1662
- getToolbarItems(rte) {
1663
- return [this.contribution({
1664
- section: "font",
1665
- render: (ctx) => createMenu(ctx, {
1666
- label: () => rte.getLocale().richTextEditor.textSize,
1667
- trigger: createButton(ctx, {
1668
- label: () => rte.getLocale().richTextEditor.textSize,
1669
- icon: "text-size-line"
1670
- }),
1671
- children: this.fontSizes.map((fs) => createMenuItem(ctx, {
1672
- text: fs.label,
1673
- checked: () => this.getFontSizeFromSelection(ctx.view.state) === fs.size,
1674
- disabled: () => !this.setFontSize(fs.size)(ctx.view.state),
1675
- onSelect: () => {
1676
- const { state, dispatch } = ctx.view;
1677
- this.setFontSize(fs.size)(state, dispatch);
1678
- }
1679
- }))
1680
- })
1681
- }, 2)];
1682
- }
1683
- getFontSizeFromSelection(state) {
1684
- const { from, to, $from, empty } = state.selection;
1685
- const { fontSize } = state.schema.marks;
1686
- if (empty) {
1687
- const defaultSize = this.defaultFontSizeForNode?.[$from.parent.type.name] ?? null;
1688
- return fontSize.isInSet(state.storedMarks || $from.marks())?.attrs.size ?? defaultSize;
1689
- }
1690
- let size = null;
1691
- const observeSize = (observedSize) => {
1692
- if (size === null) size = observedSize ?? null;
1693
- else if (observedSize !== size) size = mixedFontSize;
1694
- };
1695
- state.doc.nodesBetween(from, to, (node, _, parent) => {
1696
- if (size === mixedFontSize) return false;
1697
- if (!node.isLeaf) {
1698
- if (node.type.allowsMarkType(fontSize) && node.childCount === 0) observeSize(this.defaultFontSizeForNode?.[node.type.name]);
1699
- return true;
1700
- }
1701
- observeSize(fontSize.isInSet(node.marks)?.attrs.size ?? (parent && this.defaultFontSizeForNode?.[parent.type.name]));
1702
- return true;
1703
- });
1704
- return size;
1705
- }
1706
- setFontSize(size) {
1707
- return (state, dispatch) => {
1708
- const { from, to, empty, $from } = state.selection;
1709
- const { fontSize } = state.schema.marks;
1710
- if (!toggleMark(fontSize, { size })(state)) return false;
1711
- const tr = state.tr;
1712
- if (empty) {
1713
- const newStoredMarks = (state.storedMarks || []).filter((m) => m.type !== fontSize);
1714
- if (size !== this.defaultFontSizeForNode?.[$from.parent.type.name]) newStoredMarks.push(fontSize.create({ size }));
1715
- tr.setStoredMarks(newStoredMarks);
1716
- } else {
1717
- tr.addMark(from, to, fontSize.create({ size }));
1718
- tr.doc.nodesBetween(from, to, (node, pos, parent) => {
1719
- if (!node.isInline) return;
1720
- const mark = fontSize.isInSet(node.marks);
1721
- const defaultSize = this.defaultFontSizeForNode?.[parent.type.name];
1722
- if (mark && mark.attrs.size === defaultSize) tr.step(new RemoveMarkStep(pos, pos + node.nodeSize, mark));
1723
- });
1724
- }
1725
- dispatch?.(tr.scrollIntoView());
1726
- return true;
1727
- };
1728
- }
1729
- adjustFontSize(adjustment) {
1730
- return (state, dispatch) => {
1731
- const currentSize = this.getFontSizeFromSelection(state);
1732
- if (currentSize === null || currentSize === mixedFontSize) return false;
1733
- const nextIndex = this.fontSizes.findIndex((fs) => fs.size === currentSize) + adjustment;
1734
- if (nextIndex < 0 || nextIndex >= this.fontSizes.length) return false;
1735
- return this.setFontSize(this.fontSizes[nextIndex].size)(state, dispatch);
1736
- };
1737
- }
1738
- };
1739
- var RteFontSizePickerFeature = featureFacade(RteFontSizePickerFeatureImpl);
1740
- //#endregion
1741
- //#region src/lib/rich-text-editor/rte/features/internal/text-style.ts
1742
- var RteTextStyleFeatureImpl = class extends RteFeatureImpl {
1743
- constructor(config) {
1744
- super();
1745
- this.config = config;
1746
- }
1747
- getTextblockMarks() {
1748
- if (this.config?.onBlocks) return this.config.onBlocks.map((block) => this.contribution({
1749
- markName: this.markName,
1750
- onNodeName: block.node
1751
- }));
1752
- return [this.contribution({ markName: this.markName })];
1753
- }
1754
- };
1755
- //#endregion
1756
- //#region src/lib/rich-text-editor/rte/features/bold.ts
1757
- var RteBoldFeatureImpl = class extends RteTextStyleFeatureImpl {
1758
- constructor(..._args) {
1759
- super(..._args);
1760
- this.name = "RteBoldFeature";
1761
- this.markName = "bold";
1762
- }
1763
- getSchema() {
1764
- return [this.contribution({ marks: { bold: marks.strong } })];
1765
- }
1766
- getPlugins(rte) {
1767
- return [this.contribution(keymap({ "Mod-b": toggleMark(rte.schema.marks.bold) }))];
1768
- }
1769
- getToolbarItems(rte) {
1770
- return [this.contribution({
1771
- section: "text-style",
1772
- render: (ctx) => createMarkToggle(ctx, {
1773
- label: () => ctx.rte.getLocale().richTextEditor.bold,
1774
- icon: "bold-line",
1775
- markType: rte.schema.marks.bold
1776
- })
1777
- }, 1)];
1778
- }
1779
- };
1780
- var RteBoldFeature = featureFacade(RteBoldFeatureImpl);
1781
- //#endregion
1782
- //#region src/lib/rich-text-editor/rte/features/italic.ts
1783
- var RteItalicFeatureImpl = class extends RteTextStyleFeatureImpl {
1784
- constructor(..._args) {
1785
- super(..._args);
1786
- this.name = "RteItalicFeature";
1787
- this.markName = "italic";
1788
- }
1789
- getSchema() {
1790
- return [this.contribution({ marks: { italic: marks.em } })];
1791
- }
1792
- getPlugins(rte) {
1793
- return [this.contribution(keymap({ "Mod-i": toggleMark(rte.schema.marks.italic) }))];
1794
- }
1795
- getToolbarItems(rte) {
1796
- return [this.contribution({
1797
- section: "text-style",
1798
- render: (ctx) => createMarkToggle(ctx, {
1799
- label: () => ctx.rte.getLocale().richTextEditor.italic,
1800
- icon: "italic-line",
1801
- markType: rte.schema.marks.italic
1802
- })
1803
- }, 2)];
1804
- }
1805
- };
1806
- var RteItalicFeature = featureFacade(RteItalicFeatureImpl);
1807
- //#endregion
1808
- //#region src/lib/rich-text-editor/rte/features/underline.ts
1809
- var RteUnderlineFeatureImpl = class extends RteTextStyleFeatureImpl {
1810
- constructor(..._args) {
1811
- super(..._args);
1812
- this.name = "RteUnderlineFeature";
1813
- this.markName = "underline";
1814
- }
1815
- getSchema() {
1816
- return [this.contribution({ marks: { underline: {
1817
- parseDOM: [{ tag: "u" }],
1818
- toDOM() {
1819
- return ["u", 0];
1820
- }
1821
- } } })];
1822
- }
1823
- getPlugins(rte) {
1824
- return [this.contribution(keymap({ "Mod-u": toggleMark(rte.schema.marks.underline) }))];
1825
- }
1826
- getToolbarItems(rte) {
1827
- return [this.contribution({
1828
- section: "text-style",
1829
- render: (ctx) => createMarkToggle(ctx, {
1830
- label: () => ctx.rte.getLocale().richTextEditor.underline,
1831
- icon: "underline-line",
1832
- markType: rte.schema.marks.underline
1833
- })
1834
- }, 3)];
1835
- }
1836
- };
1837
- var RteUnderlineFeature = featureFacade(RteUnderlineFeatureImpl);
1838
- //#endregion
1839
- //#region src/lib/rich-text-editor/rte/features/strikethrough.ts
1840
- var RteStrikethroughFeatureImpl = class extends RteTextStyleFeatureImpl {
1841
- constructor(..._args) {
1842
- super(..._args);
1843
- this.name = "RteStrikethroughFeature";
1844
- this.markName = "strikethrough";
1845
- }
1846
- getSchema() {
1847
- return [this.contribution({ marks: { strikethrough: {
1848
- parseDOM: [{ tag: "s" }, { tag: "del" }],
1849
- toDOM() {
1850
- return ["s", 0];
1851
- }
1852
- } } })];
1853
- }
1854
- getPlugins(rte) {
1855
- return [this.contribution(keymap({
1856
- "Alt-Shift-5": toggleMark(rte.schema.marks.strikethrough),
1857
- "Cmd-Shift-X": toggleMark(rte.schema.marks.strikethrough)
1858
- }))];
1859
- }
1860
- getToolbarItems(rte) {
1861
- return [this.contribution({
1862
- section: "text-style",
1863
- render: (ctx) => createMarkToggle(ctx, {
1864
- label: () => ctx.rte.getLocale().richTextEditor.strikethrough,
1865
- icon: "strikethrough-line",
1866
- markType: rte.schema.marks.strikethrough
1867
- })
1868
- }, 4)];
1869
- }
1870
- };
1871
- var RteStrikethroughFeature = featureFacade(RteStrikethroughFeatureImpl);
1872
- //#endregion
1873
- //#region src/lib/rich-text-editor/rte/features/monospace.style.scss?inline
1874
- var monospace_style_default = "tt{font:var(--vvd-typography-base-code);font-variant-ligatures:unset;font-feature-settings:unset;font-size:unset;font-weight:unset;line-height:unset}";
1875
- //#endregion
1876
- //#region src/lib/rich-text-editor/rte/features/monospace.ts
1877
- var RteMonospaceFeatureImpl = class extends RteTextStyleFeatureImpl {
1878
- constructor(..._args) {
1879
- super(..._args);
1880
- this.name = "RteMonospaceFeature";
1881
- this.markName = "monospace";
1882
- }
1883
- getStyles() {
1884
- return [this.contribution(monospace_style_default)];
1885
- }
1886
- getSchema() {
1887
- return [this.contribution({ marks: { monospace: {
1888
- parseDOM: [{ tag: "tt" }, { tag: "code" }],
1889
- toDOM() {
1890
- return ["tt", 0];
1891
- }
1892
- } } })];
1893
- }
1894
- getPlugins(rte) {
1895
- return [this.contribution(keymap({ "Mod-M": toggleMark(rte.schema.marks.monospace) }))];
1896
- }
1897
- getToolbarItems(rte) {
1898
- return [this.contribution({
1899
- section: "text-style",
1900
- render: (ctx) => createMarkToggle(ctx, {
1901
- label: () => ctx.rte.getLocale().richTextEditor.monospace,
1902
- icon: "monospace-line",
1903
- markType: rte.schema.marks.monospace
1904
- })
1905
- }, 5)];
1906
- }
1907
- };
1908
- var RteMonospaceFeature = featureFacade(RteMonospaceFeatureImpl);
1909
- //#endregion
1910
- //#region src/lib/rich-text-editor/rte/features/text-color-picker.ts
1911
- function markApplies(doc, ranges, type) {
1912
- for (let i = 0; i < ranges.length; i++) {
1913
- const { $from, $to } = ranges[i];
1914
- let can = $from.depth == 0 ? doc.type.allowsMarkType(type) : false;
1915
- doc.nodesBetween($from.pos, $to.pos, (node) => {
1916
- if (can) return false;
1917
- can = node.inlineContent && node.type.allowsMarkType(type);
1918
- return true;
1919
- });
1920
- if (can) return true;
1921
- }
1922
- return false;
1923
- }
1924
- var mixedColor = Symbol("mixedColor");
1925
- var RteTextColorPickerFeatureImpl = class extends RteFeatureImpl {
1926
- constructor(config) {
1927
- super();
1928
- this.config = config;
1929
- this.name = "RteTextColorPicker";
1930
- if (config?.onBlocks) {
1931
- this.defaultColorForNode = {};
1932
- for (const block of config.onBlocks) this.defaultColorForNode[block.node] = block.defaultColor ?? null;
1933
- }
1934
- }
1935
- getTextblockMarks() {
1936
- if (this.config?.onBlocks) return this.config.onBlocks.map((block) => this.contribution({
1937
- markName: "textColor",
1938
- onNodeName: block.node
1939
- }));
1940
- return [this.contribution({ markName: "textColor" })];
1941
- }
1942
- getSchema() {
1943
- return [this.contribution({ marks: { textColor: {
1944
- attrs: { color: { validate: "string" } },
1945
- parseDOM: [{
1946
- tag: "span[data-text-color]",
1947
- getAttrs: (dom) => {
1948
- return { color: dom.getAttribute("data-text-color") };
1949
- }
1950
- }, {
1951
- style: "color",
1952
- getAttrs: (value) => {
1953
- return { color: value };
1954
- }
1955
- }],
1956
- toDOM(node) {
1957
- const { color } = node.attrs;
1958
- return [
1959
- "span",
1960
- {
1961
- style: `color: ${escapeCssProperty(color)};`,
1962
- "data-text-color": color
1963
- },
1964
- 0
1965
- ];
1966
- },
1967
- inclusive: true
1968
- } } })];
1969
- }
1970
- getToolbarItems() {
1971
- return [this.contribution({
1972
- section: "text-style",
1973
- render: (ctx) => {
1974
- const tooltipButton = createButton(ctx, {
1975
- label: () => ctx.rte.getLocale().richTextEditor.textColor,
1976
- disabled: () => !this.setColor("any")(ctx.view.state),
1977
- icon: "textcolor-line"
1978
- });
1979
- const button = tooltipButton.firstElementChild;
1980
- return createDiv(ctx, { children: [tooltipButton, createSingleSlot(ctx, {
1981
- name: "text-color-picker",
1982
- assignedProps: {
1983
- anchor: button,
1984
- value: () => this.getSelectionColor(ctx.view.state) || ""
1985
- },
1986
- assignedEvents: { change: (e) => {
1987
- const value = e.currentTarget.value;
1988
- this.setColor(value)(ctx.view.state, ctx.view.dispatch);
1989
- } }
1990
- })] });
1991
- }
1992
- }, 6)];
1993
- }
1994
- /** Determine the color of the current selection or null if colors are mixed */
1995
- getSelectionColor(state) {
1996
- const { selection } = state;
1997
- const { textColor } = state.schema.marks;
1998
- const { from, to, $from, empty } = selection;
1999
- if (empty) {
2000
- const defaultColor = this.defaultColorForNode?.[$from.parent.type.name] ?? null;
2001
- return textColor.isInSet(state.storedMarks || $from.marks())?.attrs.color ?? defaultColor;
2002
- }
2003
- let selectionColor = null;
2004
- const observeColor = (observedColor) => {
2005
- if (selectionColor === null) selectionColor = observedColor ?? null;
2006
- else if (observedColor !== selectionColor) selectionColor = mixedColor;
2007
- };
2008
- state.doc.nodesBetween(from, to, (node, _pos, parent) => {
2009
- if (selectionColor === mixedColor) return false;
2010
- if (!node.isLeaf) {
2011
- if (node.type.allowsMarkType(textColor) && node.childCount === 0) observeColor(this.defaultColorForNode?.[node.type.name]);
2012
- return true;
2013
- }
2014
- observeColor(textColor.isInSet(node.marks)?.attrs.color ?? (parent && this.defaultColorForNode?.[parent.type.name]));
2015
- return true;
2016
- });
2017
- return selectionColor === mixedColor ? null : selectionColor;
2018
- }
2019
- setColor(color) {
2020
- return (state, dispatch) => {
2021
- const { textColor } = state.schema.marks;
2022
- const { from, to, empty, $from } = state.selection;
2023
- if (!markApplies(state.doc, state.selection.ranges, textColor)) return false;
2024
- const tr = state.tr;
2025
- if (empty) {
2026
- const newStoredMarks = (state.storedMarks || []).filter((m) => m.type !== textColor);
2027
- if (color !== this.defaultColorForNode?.[$from.parent.type.name]) newStoredMarks.push(textColor.create({ color }));
2028
- tr.setStoredMarks(newStoredMarks);
2029
- } else {
2030
- tr.addMark(from, to, textColor.create({ color }));
2031
- tr.doc.nodesBetween(from, to, (node, pos, parent) => {
2032
- if (!node.isInline) return;
2033
- const mark = textColor.isInSet(node.marks);
2034
- const defaultColor = this.defaultColorForNode?.[parent.type.name];
2035
- if (mark && mark.attrs.color === defaultColor) tr.step(new RemoveMarkStep(pos, pos + node.nodeSize, mark));
2036
- });
2037
- }
2038
- dispatch?.(tr.scrollIntoView());
2039
- return true;
2040
- };
2041
- }
2042
- };
2043
- var RteTextColorPickerFeature = featureFacade(RteTextColorPickerFeatureImpl);
2044
- //#endregion
2045
- //#region src/lib/rich-text-editor/rte/features/list.style.scss?inline
2046
- var list_style_default = ".rich-text ul,.rich-text ol{padding-inline-start:1.5em}.rich-text li{list-style-position:inside}";
2047
- //#endregion
2048
- //#region src/lib/rich-text-editor/rte/features/list.ts
2049
- var atStartOfNode = ($cursor) => $cursor.parentOffset === 0;
2050
- var isEmpty = (node) => node.nodeSize === 2;
2051
- var listDepth = ($li) => $li.depth - 1;
2052
- var outOfListDepth = ($li) => $li.depth - 2;
2053
- var getLi = ($li) => $li.parent;
2054
- var getList = ($li) => $li.node(listDepth($li));
2055
- var isNested = ($li) => $li.depth > 2;
2056
- var isFirstChild = ($pos, depth) => $pos.index(depth) === 0;
2057
- var isLastChild = ($pos, depth) => $pos.index(depth) === $pos.node(depth).childCount - 1;
2058
- var prevSibling = ($pos, depth) => {
2059
- const parent = $pos.node(depth);
2060
- const index = $pos.index(depth);
2061
- return parent.maybeChild(index - 1);
2062
- };
2063
- var nextSibling = ($pos, depth) => {
2064
- const parent = $pos.node(depth);
2065
- const index = $pos.index(depth);
2066
- return parent.maybeChild(index + 1);
2067
- };
2068
- var asTextSelection = (selection) => {
2069
- let { $from, $to } = selection;
2070
- if (selection instanceof AllSelection) {
2071
- const textSelection = TextSelection.between(selection.$from, selection.$to);
2072
- $from = textSelection.$from;
2073
- $to = textSelection.$to;
2074
- }
2075
- return {
2076
- $from,
2077
- $to
2078
- };
2079
- };
2080
- var getSharedAncestor = ($from, $to) => $from.sameParent($to) ? $from.node(-1) : $from.node($from.sharedDepth($to.pos));
2081
- var cursorInListItem = (state) => {
2082
- const { $cursor } = state.selection;
2083
- if ($cursor?.parent.type === state.schema.nodes.listItem) return $cursor;
2084
- return null;
2085
- };
2086
- var allListItemsAreOfType = (state, $from, $to, type) => {
2087
- let currentListType;
2088
- let allLisAreOurType = true;
2089
- state.doc.nodesBetween($from.pos, $to.pos, (node) => {
2090
- if (node.type.isInGroup("list")) currentListType = node.type;
2091
- if (node.type === state.schema.nodes.listItem && currentListType !== type) allLisAreOurType = false;
2092
- });
2093
- return allLisAreOurType;
2094
- };
2095
- var lift = (rte, $li, tr) => {
2096
- if (isNested($li)) {
2097
- liftToOuterList($li, tr);
2098
- return true;
2099
- }
2100
- return liftOutOfList(rte, $li, tr);
2101
- };
2102
- var liftToOuterList = ($li, tr) => {
2103
- const liRange = new NodeRange($li.doc.resolve($li.before()), $li.doc.resolve($li.after()), $li.depth - 1);
2104
- tr.lift(liRange, $li.depth - 2);
2105
- };
2106
- var liftOutOfList = (rte, $li, tr) => {
2107
- const list = getList($li);
2108
- const listIndex = $li.index(outOfListDepth($li));
2109
- const defaultTextblock = defaultTextblockForMatch($li.node(outOfListDepth($li)).contentMatchAt(listIndex + 1));
2110
- if (!defaultTextblock) return false;
2111
- const atStart = isFirstChild($li, listDepth($li));
2112
- const atEnd = isLastChild($li, listDepth($li));
2113
- tr.step(new ReplaceAroundStep($li.before() - (atStart ? 1 : 0), $li.after() + (atEnd ? 1 : 0), $li.start(), $li.end(), new Slice((atStart ? Fragment.empty : Fragment.from(list.copy(Fragment.empty))).append(Fragment.from(defaultTextblock.create(rte.textblockAttrs.extractFromNode(getLi($li))))).append(atEnd ? Fragment.empty : Fragment.from(list.copy(Fragment.empty))), atStart ? 0 : 1, atEnd ? 0 : 1), (atStart ? 0 : 1) + 1));
2114
- return true;
2115
- };
2116
- var sink = (rte, listType, $node, tr) => {
2117
- if ($node.parent.type === rte.schema.nodes.listItem) sinkLi(listType, $node, tr);
2118
- else sinkNode(rte, listType, $node, tr);
2119
- };
2120
- var sinkLi = (listType, $li, tr) => {
2121
- const canJoinWithPrev = prevSibling($li, listDepth($li))?.type === listType;
2122
- const canJoinWithNext = nextSibling($li, listDepth($li))?.type === listType;
2123
- const openStart = canJoinWithPrev ? 1 : 0;
2124
- const openEnd = canJoinWithNext ? 1 : 0;
2125
- tr.step(new ReplaceAroundStep($li.before() - (canJoinWithPrev ? 1 : 0), $li.after() + (canJoinWithNext ? 1 : 0), $li.before(), $li.after(), new Slice(Fragment.from(listType.create(null, [])), openStart, openEnd), 1 - openStart));
2126
- };
2127
- var sinkNode = (rte, listType, $node, tr) => {
2128
- tr.step(new ReplaceAroundStep($node.before(), $node.after(), $node.start(), $node.end(), new Slice(Fragment.from(listType.create(null, [rte.schema.nodes.listItem.create(rte.textblockAttrs.extractFromNode($node.parent))])), 0, 0), 2));
2129
- };
2130
- var RteListFeatureImpl = class extends RteFeatureImpl {
2131
- constructor(config) {
2132
- super();
2133
- this.config = config;
2134
- this.name = "RteListFeature";
2135
- if (!config.bulletList && !config.numberedList) throw new Error("RteListFeature requires at least one of bulletList or numberedList to be enabled");
2136
- }
2137
- getStyles() {
2138
- return [this.contribution(list_style_default)];
2139
- }
2140
- getSchema(textblockAttrs) {
2141
- return [this.contribution({ nodes: {
2142
- listItem: {
2143
- content: "inline*",
2144
- attrs: textblockAttrs.attrs,
2145
- defining: true,
2146
- parseDOM: [{
2147
- tag: "li",
2148
- getAttrs: (dom) => textblockAttrs.fromDOM(dom)
2149
- }],
2150
- toDOM(node) {
2151
- return [
2152
- "li",
2153
- ...textblockAttrs.getDOMAttrs(node),
2154
- 0
2155
- ];
2156
- }
2157
- },
2158
- ...this.config.bulletList ? { bulletList: {
2159
- group: "block list",
2160
- content: "(listItem | list)+",
2161
- parseDOM: [{ tag: "ul" }],
2162
- toDOM() {
2163
- return ["ul", 0];
2164
- }
2165
- } } : {},
2166
- ...this.config.numberedList ? { numberedList: {
2167
- group: "block list",
2168
- content: "(listItem | list)+",
2169
- parseDOM: [{ tag: "ol" }],
2170
- toDOM() {
2171
- return ["ol", 0];
2172
- }
2173
- } } : {}
2174
- } })];
2175
- }
2176
- getPlugins(rte) {
2177
- this.rte = rte;
2178
- const tabCommand = (state, dispatch) => {
2179
- const $liCursor = cursorInListItem(state);
2180
- if ($liCursor && atStartOfNode($liCursor)) {
2181
- const tr = state.tr;
2182
- sinkLi(getList($liCursor).type, $liCursor, tr);
2183
- dispatch?.(tr.scrollIntoView());
2184
- return true;
2185
- }
2186
- return false;
2187
- };
2188
- const shiftTabCommand = (state, dispatch) => {
2189
- const $liCursor = cursorInListItem(state);
2190
- if ($liCursor && atStartOfNode($liCursor) && isNested($liCursor)) {
2191
- const tr = state.tr;
2192
- liftToOuterList($liCursor, tr);
2193
- dispatch?.(tr.scrollIntoView());
2194
- return true;
2195
- }
2196
- return false;
2197
- };
2198
- const enterCommand = (state, dispatch) => {
2199
- const $liCursor = cursorInListItem(state);
2200
- if ($liCursor && isEmpty(getLi($liCursor))) {
2201
- const tr = state.tr;
2202
- if (!lift(this.rte, $liCursor, tr)) return false;
2203
- dispatch?.(tr.scrollIntoView());
2204
- return true;
2205
- }
2206
- return false;
2207
- };
2208
- const backspaceCommand = (state, dispatch) => {
2209
- const $liCursor = cursorInListItem(state);
2210
- if ($liCursor && atStartOfNode($liCursor)) {
2211
- if (isFirstChild($liCursor, listDepth($liCursor)) && prevSibling($liCursor, outOfListDepth($liCursor))?.type === getList($liCursor).type) return false;
2212
- const tr = state.tr;
2213
- if (!lift(this.rte, $liCursor, tr)) return false;
2214
- dispatch?.(tr.scrollIntoView());
2215
- return true;
2216
- }
2217
- return false;
2218
- };
2219
- return [this.contribution(keymap({
2220
- Enter: enterCommand,
2221
- Backspace: backspaceCommand,
2222
- Tab: tabCommand,
2223
- "Shift-Tab": shiftTabCommand,
2224
- ...this.config.bulletList ? { "Mod-Shift-8": this.toggleList(rte.schema.nodes.bulletList) } : {},
2225
- ...this.config.numberedList ? { "Mod-Shift-7": this.toggleList(rte.schema.nodes.numberedList) } : {}
2226
- }), contributionPriority.high)];
2227
- }
2228
- getToolbarItems(rte) {
2229
- const toolbarItems = [];
2230
- if (this.config.bulletList) toolbarItems.push(this.contribution({
2231
- section: "textblock",
2232
- render: (ctx) => createButton(ctx, {
2233
- label: () => ctx.rte.getLocale().richTextEditor.bulletList,
2234
- icon: "bullet-list-2-line",
2235
- active: () => this.isSelectionInList(rte.schema.nodes.bulletList, ctx.rte.state),
2236
- onClick: () => {
2237
- const { state, dispatch } = ctx.view;
2238
- this.toggleList(rte.schema.nodes.bulletList)(state, dispatch);
2239
- }
2240
- })
2241
- }, 1));
2242
- if (this.config.numberedList) toolbarItems.push(this.contribution({
2243
- section: "textblock",
2244
- render: (ctx) => createButton(ctx, {
2245
- label: () => ctx.rte.getLocale().richTextEditor.numberedList,
2246
- icon: "list-numbered-line",
2247
- active: () => this.isSelectionInList(rte.schema.nodes.numberedList, ctx.rte.state),
2248
- onClick: () => {
2249
- const { state, dispatch } = ctx.view;
2250
- this.toggleList(rte.schema.nodes.numberedList)(state, dispatch);
2251
- }
2252
- })
2253
- }, 2));
2254
- return toolbarItems;
2255
- }
2256
- toggleList(type) {
2257
- return autoJoin((state, dispatch) => {
2258
- const { $from, $to } = asTextSelection(state.selection);
2259
- if (getSharedAncestor($from, $to).type.isInGroup("list")) if (allListItemsAreOfType(state, $from, $to, type)) {
2260
- const tr = state.tr;
2261
- state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
2262
- if (node.type === state.schema.nodes.listItem) {
2263
- const $li = tr.doc.resolve(tr.mapping.map(pos + 1));
2264
- lift(this.rte, $li, tr);
2265
- }
2266
- });
2267
- dispatch?.(tr.scrollIntoView());
2268
- return true;
2269
- } else {
2270
- const tr = state.tr;
2271
- state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
2272
- if (node.type.isInGroup("list") && node.type !== type) tr.setNodeMarkup(pos, type, node.attrs);
2273
- });
2274
- dispatch?.(tr.scrollIntoView());
2275
- return true;
2276
- }
2277
- else {
2278
- const tr = state.tr;
2279
- state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
2280
- if (!node.isTextblock) return;
2281
- const $node = tr.doc.resolve(tr.mapping.map(pos + 1));
2282
- sink(this.rte, type, $node, tr);
2283
- });
2284
- dispatch?.(tr.scrollIntoView());
2285
- return true;
2286
- }
2287
- }, (before, after) => before.type === type && after.type === type);
2288
- }
2289
- isSelectionInList(type, state) {
2290
- const { $from, $to } = asTextSelection(state.selection);
2291
- if (getSharedAncestor($from, $to).type.isInGroup("list")) return allListItemsAreOfType(state, $from, $to, type);
2292
- else return false;
2293
- }
2294
- };
2295
- var RteListFeature = featureFacade(RteListFeatureImpl);
2296
- //#endregion
2297
- //#region src/lib/rich-text-editor/rte/features/alignment.ts
2298
- var alignments = [
2299
- {
2300
- value: "left",
2301
- icon: "align-left-line",
2302
- label: "left"
2303
- },
2304
- {
2305
- value: "center",
2306
- icon: "align-center-line",
2307
- label: "center"
2308
- },
2309
- {
2310
- value: "right",
2311
- icon: "align-right-line",
2312
- label: "right"
2313
- }
2314
- ];
2315
- var validTextAlign = (value) => alignments.find((a) => a.value === value)?.value ?? "left";
2316
- var RteAlignmentFeatureImpl = class extends RteFeatureImpl {
2317
- constructor(..._args) {
2318
- super(..._args);
2319
- this.name = "RteAlignmentFeature";
2320
- }
2321
- getTextblockAttrs() {
2322
- return [this.contribution({
2323
- name: "textAlign",
2324
- default: "left",
2325
- fromDOM(dom) {
2326
- return validTextAlign(dom.style.textAlign);
2327
- },
2328
- toStyles(node) {
2329
- return [`text-align: ${validTextAlign(node.attrs.textAlign)}`];
2330
- }
2331
- })];
2332
- }
2333
- getPlugins() {
2334
- return [this.contribution(keymap({
2335
- "Mod-L": this.setAlignment("left"),
2336
- "Mod-E": this.setAlignment("center"),
2337
- "Mod-R": this.setAlignment("right")
2338
- }))];
2339
- }
2340
- getToolbarItems() {
2341
- return [this.contribution({
2342
- section: "textblock",
2343
- render: (ctx) => createMenu(ctx, {
2344
- label: () => ctx.rte.getLocale().richTextEditor.alignment,
2345
- trigger: createButton(ctx, {
2346
- label: () => ctx.rte.getLocale().richTextEditor.alignment,
2347
- icon: () => {
2348
- const currentAlign = this.getAlignmentFromSelection(ctx.view.state);
2349
- return alignments.find((a) => a.value === currentAlign)?.icon ?? "align-left-line";
2350
- }
2351
- }),
2352
- children: [createButtonGroup(ctx, {
2353
- slot: "header",
2354
- children: alignments.map((align, index) => createButton(ctx, {
2355
- icon: align.icon,
2356
- label: () => ctx.rte.getLocale().richTextEditor.alignments[align.label],
2357
- noTooltip: true,
2358
- variant: "toolbar-menu",
2359
- autofocus: () => {
2360
- const currentAlign = this.getAlignmentFromSelection(ctx.view.state);
2361
- if ((currentAlign === "mixed" || currentAlign === null) && index === 0) return true;
2362
- return align.value === currentAlign;
2363
- },
2364
- active: () => this.getAlignmentFromSelection(ctx.view.state) === align.value,
2365
- disabled: () => this.getAlignmentFromSelection(ctx.view.state) === null,
2366
- onClick: () => {
2367
- const { state, dispatch } = ctx.view;
2368
- this.setAlignment(align.value)(state, dispatch);
2369
- }
2370
- }))
2371
- })]
2372
- })
2373
- }, 3)];
2374
- }
2375
- getAlignmentFromSelection(state) {
2376
- const { selection } = state;
2377
- const { from, to } = selection;
2378
- let align = null;
2379
- state.doc.nodesBetween(from, to, (node) => {
2380
- if (align === "mixed") return;
2381
- if (node.type.isTextblock) {
2382
- if (!align) align = node.attrs.textAlign;
2383
- else if (align !== node.attrs.textAlign) align = "mixed";
2384
- }
2385
- });
2386
- return align;
2387
- }
2388
- setAlignment(align) {
2389
- return (state, dispatch) => {
2390
- const { tr, selection } = state;
2391
- const { from, to } = selection;
2392
- state.doc.nodesBetween(from, to, (node, pos) => {
2393
- if (node.type.isTextblock) tr.setNodeMarkup(pos, node.type, {
2394
- ...node.attrs,
2395
- textAlign: align
2396
- });
2397
- });
2398
- dispatch?.(tr.scrollIntoView());
2399
- return true;
2400
- };
2401
- }
2402
- };
2403
- var RteAlignmentFeature = featureFacade(RteAlignmentFeatureImpl);
2404
- //#endregion
2405
- //#region src/lib/rich-text-editor/rte/features/link.style.scss?inline
2406
- var link_style_default = ".link-popover{flex-direction:column;gap:8px;inline-size:450px;padding:16px;display:flex}.link-popover-header{justify-content:space-between;align-items:center;display:flex}.link-popover-label{color:var(--vvd-color-neutral-600);font:var(--vvd-typography-base-condensed)}.link-popover-content{flex-direction:column;gap:16px;display:flex}.link,.rich-text a[href],.link:visited,.rich-text a[href]:visited{color:var(--vvd-color-cta-600)}.link:hover,.rich-text a[href]:hover{color:var(--vvd-color-cta-500)}.link:active,.rich-text a[href]:active{color:var(--vvd-color-cta-400)}.link-action-bar{justify-content:end;gap:8px;display:flex}.link-toolbar-menu{flex-direction:column;gap:16px;inline-size:368px;padding:8px;display:flex}";
2407
- //#endregion
2408
- //#region src/lib/rich-text-editor/rte/features/link.ts
2409
- var linkPattern = "(?:https?://|www\\.)[^\\s<]+";
2410
- function convertToLink(state, matchedText, start, end) {
2411
- if (state.doc.rangeHasMark(start, start + 1, state.schema.marks.link)) return null;
2412
- const link = matchedText.replace(/[.,;:!?) ]+$/, "");
2413
- const href = link.startsWith("www.") ? `https://${link}` : link;
2414
- const linkMark = state.schema.marks.link.create({ href });
2415
- const linkEnd = start + link.length;
2416
- const trailingChars = matchedText.slice(link.length);
2417
- const tr = state.tr.addMark(start, linkEnd, linkMark);
2418
- if (trailingChars) tr.replaceWith(linkEnd, end, state.schema.text(trailingChars));
2419
- return tr;
2420
- }
2421
- var RteLinkFeatureImpl = class extends RteFeatureImpl {
2422
- constructor(..._args) {
2423
- super(..._args);
2424
- this.name = "RteLinkFeature";
2425
- this.removeLink = (state, dispatch) => {
2426
- const tr = state.tr;
2427
- const existingLink = this.getCurrentLink(state);
2428
- tr.removeMark(existingLink.start, existingLink.end, state.schema.marks.link);
2429
- dispatch?.(tr.scrollIntoView());
2430
- return true;
2431
- };
2432
- }
2433
- getStyles() {
2434
- return [this.contribution(link_style_default)];
2435
- }
2436
- getSchema() {
2437
- return [this.contribution({ marks: { link: {
2438
- attrs: { href: { validate: "string" } },
2439
- inclusive: false,
2440
- parseDOM: [{
2441
- tag: "a[href]",
2442
- getAttrs(dom) {
2443
- return { href: dom.getAttribute("href") };
2444
- }
2445
- }],
2446
- toDOM(node) {
2447
- const { href } = node.attrs;
2448
- return [
2449
- "a",
2450
- { href: sanitizeLinkHref(href) },
2451
- 0
2452
- ];
2453
- }
2454
- } } }, contributionPriority.high)];
2455
- }
2456
- getTextblockMarks() {
2457
- return [this.contribution({ markName: "link" })];
2458
- }
2459
- getInputRules() {
2460
- const linkRegex = new RegExp(`${linkPattern}$`);
2461
- return [this.contribution({
2462
- rule: new InputRule(new RegExp(`${linkPattern} $`), (state, match, start, end) => convertToLink(state, match[0], start, end)),
2463
- enterHandler: {
2464
- regex: linkRegex,
2465
- handler: (state, match, start, end) => convertToLink(state, match[0], start, end)
2466
- }
2467
- })];
2468
- }
2469
- getPlugins(rte) {
2470
- const insertLinkCommand = () => {
2471
- this.toolbarMenu.open = true;
2472
- return true;
2473
- };
2474
- let popup;
2475
- return [this.contribution(new Plugin({
2476
- props: { decorations: (state) => {
2477
- const link = this.getCurrentLink(state);
2478
- if (link) {
2479
- const deco = Decoration.inline(link.start, link.end, { id: "current-link" });
2480
- return DecorationSet.create(state.doc, [deco]);
2481
- }
2482
- return null;
2483
- } },
2484
- view: (view) => {
2485
- const ctx = new UiCtx(view, rte, {
2486
- popupPlacement: "bottom",
2487
- shouldReturnFocusToEditor: true
2488
- });
2489
- popup = rte.createComponent(Popover);
2490
- popup.anchorId = "current-link";
2491
- const content = createDiv(ctx, {
2492
- className: "link-popover",
2493
- children: [createDiv(ctx, {
2494
- className: "link-popover-header",
2495
- children: [createDiv(ctx, {
2496
- className: "link-popover-label",
2497
- children: [createText(ctx, { text: () => this.getCurrentLink(ctx.view.state)?.text || "" })]
2498
- }), createButton(ctx, {
2499
- icon: "close-line",
2500
- label: () => ctx.rte.getLocale().richTextEditor.close,
2501
- noTooltip: true,
2502
- onClick: () => {
2503
- popup.dismiss();
2504
- }
2505
- })]
2506
- }), createDiv(ctx, {
2507
- className: "link-popover-content",
2508
- children: [createAnchor(ctx, {
2509
- className: "link",
2510
- href: () => this.getCurrentLink(ctx.view.state)?.href || "",
2511
- target: "_blank",
2512
- rel: "noopener",
2513
- children: [createText(ctx, { text: () => this.getCurrentLink(ctx.view.state)?.href || "" })]
2514
- }), createDiv(ctx, {
2515
- className: "link-action-bar",
2516
- children: [createButton(ctx, {
2517
- icon: "delete-line",
2518
- label: () => ctx.rte.getLocale().richTextEditor.delete,
2519
- connotation: "alert",
2520
- variant: "popover",
2521
- noTooltip: true,
2522
- onClick: () => {
2523
- const { state, dispatch } = ctx.view;
2524
- this.removeLink(state, dispatch);
2525
- }
2526
- }), createButton(ctx, {
2527
- icon: "edit-line",
2528
- label: () => ctx.rte.getLocale().richTextEditor.edit,
2529
- variant: "popover",
2530
- noTooltip: true,
2531
- onClick: () => {
2532
- this.toolbarMenu.open = true;
2533
- popup.requestOpenState(false);
2534
- return true;
2535
- }
2536
- })]
2537
- })]
2538
- })]
2539
- });
2540
- popup.appendChild(content);
2541
- view.dom.getRootNode().querySelector(".popovers").appendChild(popup);
2542
- return {
2543
- update: (view) => {
2544
- const state = view.state;
2545
- ctx.updateBindings();
2546
- const link = this.getCurrentLink(state);
2547
- popup.requestOpenState(Boolean(link));
2548
- },
2549
- destroy: () => {
2550
- popup.remove();
2551
- }
2552
- };
2553
- }
2554
- })), this.contribution(keymap({
2555
- Escape: (state) => {
2556
- if (this.getCurrentLink(state)) {
2557
- popup?.dismiss();
2558
- return true;
2559
- }
2560
- return false;
2561
- },
2562
- "Mod-k": insertLinkCommand
2563
- }))];
2564
- }
2565
- getToolbarItems(rte) {
2566
- const getSelectionText = (state) => {
2567
- const { from, to } = state.selection;
2568
- if (from === to) return "";
2569
- return state.doc.textBetween(from, to, " ");
2570
- };
2571
- const isValidUrl = (url) => {
2572
- try {
2573
- new URL(url);
2574
- return true;
2575
- } catch {
2576
- return false;
2577
- }
2578
- };
2579
- return [this.contribution({
2580
- section: "insert",
2581
- render: (ctx) => {
2582
- const textField = createTextField(ctx, {
2583
- label: () => ctx.rte.getLocale().richTextEditor.linkText,
2584
- placeholder: () => ctx.rte.getLocale().richTextEditor.linkTextPlaceholder,
2585
- slot: "header",
2586
- autofocus: true,
2587
- value: () => this.getCurrentLink(ctx.view.state)?.text || getSelectionText(ctx.view.state) || "",
2588
- onInput: () => {
2589
- updateValidation();
2590
- }
2591
- });
2592
- const urlField = createTextField(ctx, {
2593
- label: () => ctx.rte.getLocale().richTextEditor.linkUrl,
2594
- type: "url",
2595
- placeholder: () => ctx.rte.getLocale().richTextEditor.linkUrlPlaceholder,
2596
- helperText: () => ctx.rte.getLocale().richTextEditor.linkUrlHelperText,
2597
- slot: "header",
2598
- value: () => this.getCurrentLink(ctx.view.state)?.href || "",
2599
- onInput: () => {
2600
- updateValidation();
2601
- }
2602
- });
2603
- const applyButton = createButton(ctx, {
2604
- label: () => ctx.rte.getLocale().richTextEditor.apply,
2605
- variant: "popover-primary",
2606
- disabled: () => {
2607
- const link = this.getCurrentLink(ctx.view.state);
2608
- return !(link && link.text.length && isValidUrl(link.href));
2609
- },
2610
- onClick: () => {
2611
- const { state, dispatch } = ctx.view;
2612
- this.insertLink(rte, urlField.value, textField.value)(state, dispatch);
2613
- this.toolbarMenu.open = false;
2614
- }
2615
- });
2616
- const updateValidation = () => {
2617
- applyButton.querySelector("[data-vvd-component=\"button\"]").disabled = !(textField.value.length && isValidUrl(urlField.value));
2618
- };
2619
- const menu = createMenu(ctx, {
2620
- label: () => ctx.rte.getLocale().richTextEditor.hyperlink,
2621
- trigger: createButton(ctx, {
2622
- label: () => ctx.rte.getLocale().richTextEditor.hyperlink,
2623
- icon: "link-line"
2624
- }),
2625
- children: [createDiv(ctx, {
2626
- className: "link-toolbar-menu",
2627
- slot: "header",
2628
- children: [
2629
- textField,
2630
- urlField,
2631
- createDiv(ctx, {
2632
- className: "link-action-bar",
2633
- slot: "header",
2634
- children: [createButton(ctx, {
2635
- label: () => ctx.rte.getLocale().richTextEditor.cancel,
2636
- variant: "popover",
2637
- onClick: () => {
2638
- this.toolbarMenu.open = false;
2639
- }
2640
- }), applyButton]
2641
- })
2642
- ]
2643
- })]
2644
- });
2645
- this.toolbarMenu = menu.lastElementChild;
2646
- return menu;
2647
- }
2648
- }, 1)];
2649
- }
2650
- getCurrentLink(state) {
2651
- const selection = state.selection;
2652
- if (!(selection instanceof TextSelection)) return null;
2653
- const linkMark = state.schema.marks.link;
2654
- const { $from, $to } = selection;
2655
- const selectionStartMarks = state.selection.empty ? $from.marks() : $from.nodeAfter?.marks ?? [];
2656
- const targetHref = linkMark.isInSet(selectionStartMarks)?.attrs.href;
2657
- if (!targetHref) return null;
2658
- const isTargetLink = (node) => linkMark.isInSet(node.marks)?.attrs.href === targetHref;
2659
- let currentRun = null;
2660
- const runs = [];
2661
- state.doc.nodesBetween($from.start(), $to.end(), (node, pos) => {
2662
- if (!node.isText) return true;
2663
- const nodeEnd = pos + node.nodeSize;
2664
- if (isTargetLink(node)) if (!currentRun) {
2665
- currentRun = {
2666
- start: pos,
2667
- end: nodeEnd
2668
- };
2669
- runs.push(currentRun);
2670
- } else currentRun.end = nodeEnd;
2671
- else currentRun = null;
2672
- return false;
2673
- });
2674
- const selectionRun = runs.find((run) => run.start <= selection.from && run.end >= selection.to);
2675
- if (!selectionRun) return null;
2676
- return {
2677
- text: state.doc.textBetween(selectionRun.start, selectionRun.end, " "),
2678
- href: targetHref,
2679
- start: selectionRun.start,
2680
- end: selectionRun.end
2681
- };
2682
- }
2683
- insertLink(rte, href, text) {
2684
- return (state, dispatch) => {
2685
- let { from, to } = state.selection;
2686
- const tr = state.tr;
2687
- const existingLink = this.getCurrentLink(state);
2688
- if (existingLink) {
2689
- from = existingLink.start;
2690
- to = existingLink.end;
2691
- }
2692
- tr.insertText(text, from, to);
2693
- tr.addMark(from, from + text.length, rte.schema.marks.link.create({ href }));
2694
- dispatch?.(tr.scrollIntoView());
2695
- return true;
2696
- };
2697
- }
2698
- };
2699
- var RteLinkFeature = featureFacade(RteLinkFeatureImpl);
2700
- //#endregion
2701
- //#region src/lib/rich-text-editor/rte/features/inline-image.style.scss?inline
2702
- var inline_image_style_default = ".inline-image-wrapper{vertical-align:text-bottom;display:inline-block}.inline-image{block-size:auto;display:block}.inline-image-popover{align-items:center;gap:4px;padding:8px;display:flex}.inline-image-placeholder{color:var(--vvd-color-canvas-text);font:var(--vvd-typography-base);font-feature-settings:normal;font-variant-ligatures:normal;overflow-wrap:normal;pointer-events:none;white-space:normal}";
2703
- //#endregion
2704
- //#region src/lib/rich-text-editor/rte/features/inline-image.ts
2705
- var isGenerator$1 = (value) => value !== null && Boolean(value["next"]);
2706
- var uniqueId = 1;
2707
- var generateUniqueId = () => uniqueId++;
2708
- var InlineImageView = class {
2709
- constructor(node, view, getPos, config) {
2710
- this.view = view;
2711
- this.getPos = getPos;
2712
- this.config = config;
2713
- this.content = null;
2714
- this.dom = document.createElement("div");
2715
- this.dom.className = "inline-image-wrapper";
2716
- this.imageUrl = node.attrs.imageUrl;
2717
- this.img = document.createElement("img");
2718
- this.initializeImg(node);
2719
- const resolveResult = this.config.resolveUrl ? this.config.resolveUrl(this.imageUrl) : this.imageUrl;
2720
- const initialResolvedUrl = isGenerator$1(resolveResult) ? null : resolveResult;
2721
- this.handleResolvedUrl(initialResolvedUrl);
2722
- if (isGenerator$1(resolveResult)) this.handleResolvedUrlGenerator(resolveResult);
2723
- }
2724
- setContent(content, { onDestroy, allowPopover } = {}) {
2725
- this.content?.remove();
2726
- this.onContentDestroy?.();
2727
- this.content = content;
2728
- if (content) {
2729
- this.onContentDestroy = onDestroy;
2730
- this.dom.appendChild(content);
2731
- }
2732
- Popover.setBlockPopover(this.dom, !allowPopover);
2733
- }
2734
- async handleResolvedUrlGenerator(generator) {
2735
- const iterator = generator[Symbol.asyncIterator]();
2736
- let result;
2737
- do {
2738
- result = await iterator.next();
2739
- this.handleResolvedUrl(result.value);
2740
- } while (!result.done);
2741
- }
2742
- handleResolvedUrl(result) {
2743
- if (typeof result === "string") this.renderImg(result);
2744
- else if (result?.type === "placeholder") {
2745
- const slotName = `inline-image-placeholder-${generateUniqueId()}`;
2746
- const slot = document.createElement("slot");
2747
- slot.className = "inline-image-placeholder";
2748
- slot.name = slotName;
2749
- const onDestroy = result.create?.(slotName);
2750
- const host = this.view.dom.getRootNode().host;
2751
- dispatchSlottableRequest(host, "inline-image-placeholder", slotName, { url: this.imageUrl });
2752
- this.setContent(slot, { onDestroy: () => {
2753
- dispatchSlottableRequest(host, "inline-image-placeholder", slotName, removeSymbol);
2754
- onDestroy?.();
2755
- } });
2756
- } else this.setContent(null);
2757
- }
2758
- initializeImg(node) {
2759
- this.img.className = "inline-image";
2760
- this.update(node);
2761
- this.img.addEventListener("load", () => {
2762
- const pos = this.getPos();
2763
- if (pos) {
2764
- const { state, dispatch } = this.view;
2765
- const currentNode = state.doc.nodeAt(pos);
2766
- if (!currentNode || currentNode.attrs.naturalWidth === this.img.naturalWidth && currentNode.attrs.naturalHeight === this.img.naturalHeight) return;
2767
- const tr = state.tr;
2768
- tr.setNodeAttribute(pos, "naturalWidth", this.img.naturalWidth);
2769
- tr.setNodeAttribute(pos, "naturalHeight", this.img.naturalHeight);
2770
- tr.setMeta("addToHistory", false);
2771
- dispatch(tr);
2772
- }
2773
- });
2774
- }
2775
- renderImg(src) {
2776
- this.img.src = sanitizeImageSrc(src);
2777
- this.setContent(this.img, { allowPopover: true });
2778
- }
2779
- update(node) {
2780
- this.img.alt = node.attrs.alt;
2781
- this.img.width = node.attrs.naturalWidth;
2782
- this.img.height = node.attrs.naturalHeight;
2783
- this.img.style.maxWidth = node.attrs.size;
2784
- return true;
2785
- }
2786
- destroy() {
2787
- this.setContent(null);
2788
- }
2789
- };
2790
- var RteInlineImageFeatureImpl = class extends RteFeatureImpl {
2791
- constructor(config = {}) {
2792
- super();
2793
- this.config = config;
2794
- this.name = "RteInlineImageFeature";
2795
- }
2796
- getStyles() {
2797
- return [this.contribution(inline_image_style_default)];
2798
- }
2799
- getSchema() {
2800
- return [this.contribution({ nodes: { inlineImage: {
2801
- inline: true,
2802
- group: "inline",
2803
- selectable: true,
2804
- atom: true,
2805
- attrs: {
2806
- imageUrl: { validate: "string" },
2807
- alt: {
2808
- validate: "string",
2809
- default: ""
2810
- },
2811
- size: {
2812
- validate: "string|null",
2813
- default: null
2814
- },
2815
- naturalWidth: {
2816
- validate: "number|null",
2817
- default: null
2818
- },
2819
- naturalHeight: {
2820
- validate: "number|null",
2821
- default: null
2822
- }
2823
- },
2824
- parseDOM: [{
2825
- tag: "img[src],img[data-src]",
2826
- getAttrs: (dom) => {
2827
- const parseDimension = (dim) => {
2828
- const value = parseInt(dim ?? "", 10);
2829
- return isNaN(value) ? null : value;
2830
- };
2831
- const srcAttr = dom.getAttribute("data-src") ?? dom.getAttribute("src");
2832
- const imageUrl = this.config.parseUrlFromHtml ? this.config.parseUrlFromHtml(srcAttr) : srcAttr;
2833
- if (imageUrl === null) return false;
2834
- return {
2835
- imageUrl,
2836
- alt: dom.getAttribute("alt") || "",
2837
- size: dom.style.maxWidth || null,
2838
- naturalWidth: parseDimension(dom.getAttribute("width")),
2839
- naturalHeight: parseDimension(dom.getAttribute("height"))
2840
- };
2841
- }
2842
- }],
2843
- /** Since we use a NodeView, this is only used for HTML serialization */
2844
- toDOM: (node) => {
2845
- const { imageUrl, alt, size, naturalWidth, naturalHeight } = node.attrs;
2846
- const resolvedUrl = this.config.serializeUrlToHtml ? this.config.serializeUrlToHtml(imageUrl) : imageUrl;
2847
- if (resolvedUrl === null) return document.createTextNode("");
2848
- const attrs = {
2849
- src: sanitizeImageSrc(resolvedUrl),
2850
- "data-src": resolvedUrl,
2851
- alt
2852
- };
2853
- if (size) attrs.style = `max-width: ${escapeCssProperty(size)}; height: auto;`;
2854
- if (naturalWidth) attrs.width = naturalWidth;
2855
- if (naturalHeight) attrs.height = naturalHeight;
2856
- return ["img", attrs];
2857
- }
2858
- } } })];
2859
- }
2860
- getPlugins(rte) {
2861
- let popover;
2862
- return [this.contribution(new Plugin({
2863
- props: { nodeViews: { inlineImage: (node, view, getPos) => new InlineImageView(node, view, getPos, this.config) } },
2864
- view: (view) => {
2865
- const ctx = new UiCtx(view, rte, {
2866
- popupPlacement: "bottom",
2867
- shouldReturnFocusToEditor: true
2868
- });
2869
- popover = rte.createComponent(Popover);
2870
- popover.kind = "imageOptions";
2871
- popover.offset = 4;
2872
- const content = createDiv(ctx, {
2873
- className: "inline-image-popover",
2874
- children: [
2875
- createButton(ctx, {
2876
- label: () => ctx.rte.getLocale().richTextEditor.imageSizes.small,
2877
- variant: "popover",
2878
- active: () => this.getSelectedImageSize(ctx.view.state) === "small",
2879
- onClick: () => {
2880
- this.setSelectedImageSize("small")(ctx.view.state, ctx.view.dispatch);
2881
- }
2882
- }),
2883
- createDivider(ctx),
2884
- createButton(ctx, {
2885
- label: () => ctx.rte.getLocale().richTextEditor.imageSizes.fit,
2886
- variant: "popover",
2887
- active: () => this.getSelectedImageSize(ctx.view.state) === "fit",
2888
- onClick: () => {
2889
- this.setSelectedImageSize("fit")(ctx.view.state, ctx.view.dispatch);
2890
- }
2891
- }),
2892
- createDivider(ctx),
2893
- createButton(ctx, {
2894
- label: () => ctx.rte.getLocale().richTextEditor.imageSizes.original,
2895
- variant: "popover",
2896
- active: () => this.getSelectedImageSize(ctx.view.state) === "original",
2897
- onClick: () => {
2898
- this.setSelectedImageSize("original")(ctx.view.state, ctx.view.dispatch);
2899
- }
2900
- })
2901
- ]
2902
- });
2903
- popover.appendChild(content);
2904
- view.dom.getRootNode().querySelector(".popovers").appendChild(popover);
2905
- return {
2906
- update: (view) => {
2907
- ctx.updateBindings();
2908
- const selectedImage = this.getSelectedInlineImage(view.state);
2909
- if (selectedImage) {
2910
- popover.anchorEl = view.nodeDOM(selectedImage.pos);
2911
- popover.requestOpenState(true);
2912
- } else {
2913
- popover.anchorEl = void 0;
2914
- popover.requestOpenState(false);
2915
- }
2916
- },
2917
- destroy: () => {
2918
- popover.remove();
2919
- }
2920
- };
2921
- }
2922
- })), this.contribution(keymap({ Escape: (state) => {
2923
- if (this.getSelectedInlineImage(state)) {
2924
- popover?.dismiss();
2925
- return true;
2926
- }
2927
- return false;
2928
- } }))];
2929
- }
2930
- calculateSmallWidth(naturalWidth) {
2931
- return `${Math.min(300, naturalWidth / 2)}px`;
2932
- }
2933
- getSelectedInlineImage(state) {
2934
- const sel = state.selection;
2935
- if (sel instanceof NodeSelection && sel.node.type === state.schema.nodes.inlineImage) return {
2936
- pos: sel.from,
2937
- node: sel.node
2938
- };
2939
- return null;
2940
- }
2941
- setSelectedImageSize(size) {
2942
- return (state, dispatch) => {
2943
- const selectedImage = this.getSelectedInlineImage(state);
2944
- if (!selectedImage) return false;
2945
- const { naturalWidth } = selectedImage.node.attrs;
2946
- if (size === "small" && naturalWidth === null) return false;
2947
- const tr = state.tr;
2948
- tr.setNodeAttribute(selectedImage.pos, "size", size === "small" ? this.calculateSmallWidth(naturalWidth) : size === "fit" ? "100%" : null);
2949
- dispatch?.(tr.scrollIntoView());
2950
- return true;
2951
- };
2952
- }
2953
- getSelectedImageSize(state) {
2954
- const selectedImage = this.getSelectedInlineImage(state);
2955
- if (!selectedImage) return null;
2956
- const { size, naturalWidth } = selectedImage.node.attrs;
2957
- if (naturalWidth !== null && size === this.calculateSmallWidth(naturalWidth)) return "small";
2958
- if (size === "100%") return "fit";
2959
- if (size === null) return "original";
2960
- return null;
2961
- }
2962
- };
2963
- var RteInlineImageFeature = featureFacade(RteInlineImageFeatureImpl);
2964
- //#endregion
2965
- //#region src/shared/utils/promise.ts
2966
- var resolvePromise = async (promise) => {
2967
- try {
2968
- return {
2969
- type: "ok",
2970
- result: await promise
2971
- };
2972
- } catch (e) {
2973
- return {
2974
- type: "error",
2975
- error: e
2976
- };
2977
- }
2978
- };
2979
- //#endregion
2980
- //#region src/lib/rich-text-editor/rte/features/file-handler.ts
2981
- var RteFileHandlerFeatureImpl = class extends RteFeatureImpl {
2982
- constructor(config) {
2983
- super();
2984
- this.config = config;
2985
- this.name = "RteFileHandlerFeature";
2986
- }
2987
- getPlugins(rte) {
2988
- const insertPointPlaceholderPlugin = new Plugin({
2989
- state: {
2990
- init() {
2991
- return DecorationSet.empty;
2992
- },
2993
- apply(tr, set) {
2994
- set = set.map(tr.mapping, tr.doc);
2995
- const action = tr.getMeta(insertPointPlaceholderPlugin);
2996
- if (action && action.add) {
2997
- const placeholder = document.createElement("placeholder");
2998
- const deco = Decoration.widget(action.add.pos, placeholder, {
2999
- id: action.add.id,
3000
- relaxedSide: true
3001
- });
3002
- set = set.add(tr.doc, [deco]);
3003
- } else if (action && action.remove) set = set.remove(set.find(void 0, void 0, (spec) => spec.id == action.remove.id));
3004
- return set;
3005
- }
3006
- },
3007
- props: { decorations(state) {
3008
- return this.getState(state);
3009
- } }
3010
- });
3011
- const createInsertPointPlaceholder = (tr, pos) => {
3012
- const id = generateRandomId();
3013
- tr.setMeta(insertPointPlaceholderPlugin, { add: {
3014
- id,
3015
- pos
3016
- } });
3017
- return {
3018
- getPos: (state) => {
3019
- const found = insertPointPlaceholderPlugin.getState(state).find(void 0, void 0, (spec) => spec.id == id);
3020
- return found.length ? found[0].from : null;
3021
- },
3022
- remove: (tr) => {
3023
- tr.setMeta(insertPointPlaceholderPlugin, { remove: { id } });
3024
- }
3025
- };
3026
- };
3027
- const insertFragment = (tr, fragment, insertPoint) => {
3028
- if (insertPoint.type === "selection") {
3029
- const parsed = Slice.fromJSON(rte.schema, { content: fragment });
3030
- tr.replaceSelection(parsed);
3031
- } else {
3032
- const parsed = Fragment.fromJSON(rte.schema, fragment);
3033
- tr.insert(insertPoint.pos, parsed);
3034
- }
3035
- };
3036
- const handleFiles = (files, insertPoint) => {
3037
- const result = this.config.handleFiles(files);
3038
- if (result === null) return;
3039
- else if (result instanceof Promise) handleAsyncResult(result, insertPoint);
3040
- else handleSyncResult(result, insertPoint);
3041
- };
3042
- const handleSyncResult = (result, insertPoint) => {
3043
- const tr = rte.state.tr;
3044
- insertFragment(tr, result, insertPoint);
3045
- rte.dispatchTransaction(tr);
3046
- };
3047
- const handleAsyncResult = async (promise, insertPoint) => {
3048
- const tr = rte.state.tr;
3049
- if (insertPoint.type === "selection" && !tr.selection.empty) tr.deleteSelection();
3050
- const placeholder = createInsertPointPlaceholder(tr, insertPoint.type === "selection" ? tr.selection.from : insertPoint.pos);
3051
- rte.dispatchTransaction(tr);
3052
- const resolved = await resolvePromise(promise);
3053
- const updatedPos = placeholder.getPos(rte.state);
3054
- const insertTr = rte.state.tr;
3055
- placeholder.remove(insertTr);
3056
- if (updatedPos !== null && resolved.type === "ok") insertFragment(insertTr, resolved.result, {
3057
- type: "pos",
3058
- pos: updatedPos
3059
- });
3060
- rte.dispatchTransaction(insertTr);
3061
- if (resolved.type === "error") console.error("Error in handleFiles handler:", resolved.error);
3062
- };
3063
- return [this.contribution(insertPointPlaceholderPlugin), this.contribution(new Plugin({ props: {
3064
- handlePaste: (_view, event) => {
3065
- const files = Array.from(event.clipboardData.files);
3066
- if (!files.length) return false;
3067
- handleFiles(files, { type: "selection" });
3068
- return true;
3069
- },
3070
- handleDrop: (view, event) => {
3071
- const files = Array.from(event.dataTransfer.files);
3072
- if (!files.length) return false;
3073
- let target = view.posAtCoords({
3074
- left: event.clientX,
3075
- top: event.clientY
3076
- }).pos;
3077
- if (view.dragging && view.dragging.slice) {
3078
- const point = dropPoint(view.state.doc, target, view.dragging.slice);
3079
- if (point != null) target = point;
3080
- }
3081
- handleFiles(files, {
3082
- type: "pos",
3083
- pos: target
3084
- });
3085
- return true;
3086
- }
3087
- } }))];
3088
- }
3089
- };
3090
- var RteFileHandlerFeature = featureFacade(RteFileHandlerFeatureImpl);
3091
- //#endregion
3092
- //#region src/lib/rich-text-editor/rte/features/drop-handler.ts
3093
- var RteDropHandlerFeatureImpl = class extends RteFeatureImpl {
3094
- constructor(config) {
3095
- super();
3096
- this.config = config;
3097
- this.name = "RteDebugFeature";
3098
- }
3099
- getPlugins() {
3100
- const dragOverResults = /* @__PURE__ */ new WeakMap();
3101
- let lastResult = false;
3102
- const onDragOver = (event) => {
3103
- if (dragOverResults.get(event) !== void 0) return;
3104
- lastResult = this.config.onViewportDragOver?.(event) ?? false;
3105
- };
3106
- const onDrop = (event) => {
3107
- this.config.onViewportDrop?.(event);
3108
- this.config.onViewportDragFinish?.();
3109
- };
3110
- const onDragEnd = () => {
3111
- this.config.onViewportDragFinish?.();
3112
- };
3113
- let isEntering = false;
3114
- const onDragEnter = () => {
3115
- isEntering = true;
3116
- window.setTimeout(() => isEntering = false, 0);
3117
- };
3118
- const onDragLeave = () => {
3119
- if (isEntering) return;
3120
- this.config.onViewportDragFinish?.();
3121
- };
3122
- return [this.contribution(new Plugin({ view: (view) => {
3123
- const viewport = view.root.host.editorViewportElement;
3124
- viewport.addEventListener("dragover", onDragOver);
3125
- viewport.addEventListener("drop", onDrop);
3126
- viewport.addEventListener("dragend", onDragEnd);
3127
- viewport.addEventListener("dragenter", onDragEnter);
3128
- viewport.addEventListener("dragleave", onDragLeave);
3129
- return { destroy() {
3130
- viewport.removeEventListener("dragover", onDragOver);
3131
- viewport.removeEventListener("drop", onDrop);
3132
- viewport.removeEventListener("dragend", onDragEnd);
3133
- viewport.removeEventListener("dragenter", onDragEnter);
3134
- viewport.removeEventListener("dragleave", onDragLeave);
3135
- } };
3136
- } })), this.contribution(new Plugin({ props: { handleDOMEvents: {
3137
- dragover: (_view, event) => {
3138
- const result = this.config.onViewportDragOver?.(event) ?? false;
3139
- dragOverResults.set(event, result);
3140
- lastResult = result;
3141
- if (result) {
3142
- event.stopImmediatePropagation();
3143
- event.preventDefault();
3144
- return true;
3145
- }
3146
- return false;
3147
- },
3148
- drop: () => {
3149
- return lastResult;
3150
- }
3151
- } } }), contributionPriority.high)];
3152
- }
3153
- };
3154
- var RteDropHandlerFeature = featureFacade(RteDropHandlerFeatureImpl);
3155
- //#endregion
3156
- //#region src/lib/rich-text-editor/rte/features/toolbar-button.ts
3157
- var RteToolbarButtonFeatureImpl = class extends RteFeatureImpl {
3158
- constructor(featureId, options) {
3159
- super();
3160
- this.featureId = featureId;
3161
- this.options = options;
3162
- this.name = `RteToolbarButtonFeature[${featureId}]`;
3163
- }
3164
- getToolbarItems() {
3165
- return [this.contribution({
3166
- section: "insert",
3167
- render: (ctx) => createButton(ctx, {
3168
- label: this.options.label,
3169
- icon: this.options.icon,
3170
- onClick: () => {
3171
- this.executeAction(ctx);
3172
- }
3173
- })
3174
- }, 2 + (this.options.order ?? 0) / Number.MAX_SAFE_INTEGER)];
3175
- }
3176
- executeAction(ctx) {
3177
- const { action } = this.options;
3178
- switch (action.type) {
3179
- case "insert-text": {
3180
- const { state, dispatch } = ctx.view;
3181
- const { from, to } = state.selection;
3182
- dispatch(state.tr.insertText(action.text, from, to));
3183
- break;
3184
- }
3185
- }
3186
- }
3187
- };
3188
- var RteToolbarButtonFeature = featureFacade(RteToolbarButtonFeatureImpl);
3189
- //#endregion
3190
- //#region src/lib/rich-text-editor/rte/features/atom.ts
3191
- var isGenerator = (value) => value !== null && typeof value === "object" && "next" in value;
3192
- var AtomView = class {
3193
- constructor(node, config, atomName) {
3194
- this.dom = document.createElement("span");
3195
- this.dom.className = "atom-wrapper";
3196
- this.dom.setAttribute("part", `node--${atomName}`);
3197
- const result = config.resolveValue ? config.resolveValue(node.attrs.value) : node.attrs.value;
3198
- if (isGenerator(result)) {
3199
- this.dom.textContent = "";
3200
- this.handleResolvedGenerator(result);
3201
- } else this.dom.textContent = result ?? "";
3202
- }
3203
- async handleResolvedGenerator(generator) {
3204
- const iterator = generator[Symbol.asyncIterator]();
3205
- let result;
3206
- do {
3207
- result = await iterator.next();
3208
- this.dom.textContent = result.value ?? "";
3209
- } while (!result.done);
3210
- }
3211
- };
3212
- var RteAtomFeatureImpl = class extends RteFeatureImpl {
3213
- constructor(atomName, config = {}) {
3214
- super();
3215
- this.atomName = atomName;
3216
- this.config = config;
3217
- this.name = `RteAtomFeature[${atomName}]`;
3218
- }
3219
- getSchema() {
3220
- const atomSpec = {
3221
- inline: true,
3222
- group: "inline",
3223
- selectable: true,
3224
- atom: true,
3225
- attrs: { value: { validate: "string" } },
3226
- parseDOM: [{
3227
- tag: `span[data-atom-type="${this.atomName}"][data-value]`,
3228
- getAttrs: (dom) => ({ value: dom.getAttribute("data-value") })
3229
- }],
3230
- /** Since we use a NodeView, toDOM is only used for Rich Text View */
3231
- toDOM: (node) => {
3232
- const serializedValue = this.config.serializeValueToHtml ? this.config.serializeValueToHtml(node.attrs.value) : node.attrs.value;
3233
- if (serializedValue === null) return document.createDocumentFragment();
3234
- return [
3235
- "span",
3236
- { part: `node--${this.atomName}` },
3237
- serializedValue
3238
- ];
3239
- },
3240
- serializeToDOM: (node) => {
3241
- const serializedValue = this.config.serializeValueToHtml ? this.config.serializeValueToHtml(node.attrs.value) : node.attrs.value;
3242
- if (serializedValue === null) return document.createTextNode("");
3243
- return [
3244
- "span",
3245
- {
3246
- "data-atom-type": this.atomName,
3247
- "data-value": node.attrs.value
3248
- },
3249
- serializedValue
3250
- ];
3251
- }
3252
- };
3253
- return [this.contribution({ nodes: { [this.atomName]: atomSpec } })];
3254
- }
3255
- getPlugins(_rte) {
3256
- return [this.contribution(new Plugin({ props: { nodeViews: { [this.atomName]: (node) => new AtomView(node, this.config, this.atomName) } } }))];
3257
- }
3258
- };
3259
- var RteAtomFeature = featureFacade(RteAtomFeatureImpl);
3260
- //#endregion
3261
- //#region src/lib/rich-text-editor/rte/features/input-rule.ts
3262
- var RteInputRuleFeatureImpl = class extends RteFeatureImpl {
3263
- constructor(featureId, options) {
3264
- super();
3265
- this.featureId = featureId;
3266
- this.options = options;
3267
- this.name = `RteInputRuleFeature[${featureId}]`;
3268
- }
3269
- getInputRules(rte) {
3270
- const basePattern = `(?:${this.options.pattern.source})`;
3271
- const handler = (state, match, start, end) => {
3272
- const fragment = this.options.handler(match);
3273
- if (!fragment) return null;
3274
- return state.tr.replaceWith(start, end, Fragment.fromJSON(rte.schema, fragment));
3275
- };
3276
- const spec = { rule: new InputRule(this.options.matchAfterWhitespace ? new RegExp(`${basePattern} $`) : new RegExp(`${basePattern}$`), handler) };
3277
- if (this.options.matchAfterWhitespace) spec.enterHandler = {
3278
- regex: new RegExp(`${basePattern}$`),
3279
- handler
3280
- };
3281
- return [this.contribution(spec)];
3282
- }
3283
- };
3284
- var RteInputRuleFeature = featureFacade(RteInputRuleFeatureImpl);
3285
- //#endregion
3286
- //#region src/lib/rich-text-editor/rte/features/keyboard-shortcuts.ts
3287
- function toCommand(handler, rteInstance) {
3288
- return (_state, _dispatch) => handler(rteInstance);
3289
- }
3290
- var RteKeyboardShortcutsFeatureImpl = class extends RteFeatureImpl {
3291
- constructor(featureId, options) {
3292
- super();
3293
- this.featureId = featureId;
3294
- this.options = options;
3295
- this.name = `RteKeyboardShortcutsFeature[${featureId}]`;
3296
- }
3297
- getPlugins(rte) {
3298
- const bindings = {};
3299
- for (const [key, handler] of Object.entries(this.options.shortcuts)) bindings[key] = toCommand(handler, rte.facade);
3300
- return [this.contribution(keymap(bindings), contributionPriority.high)];
3301
- }
3302
- };
3303
- var RteKeyboardShortcutsFeature = featureFacade(RteKeyboardShortcutsFeatureImpl);
3304
- //#endregion
3305
- //#region src/lib/rich-text-editor/rte/features/suggest.style.scss?inline
3306
- var suggest_style_default = ".suggest-popover{flex-direction:column;gap:2px;max-block-size:408px;min-inline-size:128px;max-inline-size:248px;padding:4px;display:flex}.suggest-loading-widget{vertical-align:middle;white-space:normal;align-items:center;margin-inline-start:2px;display:inline-flex}.suggest-empty-message{color:var(--vvd-color-neutral-300);font:var(--vvd-typography-base);text-align:center;justify-content:center;align-items:center;min-block-size:40px;display:flex}";
3307
- //#endregion
3308
- //#region src/lib/rich-text-editor/rte/features/suggest.ts
3309
- var isPopoverOpen = (state) => Boolean(state?.suggestions && !state.dismissed);
3310
- var popoverShowsResults = (state) => isPopoverOpen(state) && state.suggestions.items.length > 0;
3311
- function findMatch(state, regex) {
3312
- const { $cursor } = state.selection;
3313
- if (!$cursor) return null;
3314
- const textBefore = textBeforeCursor($cursor);
3315
- const match = regex.exec(textBefore);
3316
- if (!match) return null;
3317
- const blockStart = $cursor.pos - $cursor.parentOffset;
3318
- return {
3319
- text: match[0],
3320
- groups: [...match],
3321
- start: blockStart + match.index,
3322
- end: blockStart + match.index + match[0].length
3323
- };
3324
- }
3325
- var replaceMatch = (view, match, fragment) => {
3326
- const { state } = view;
3327
- view.dispatch(closeHistory(state.tr));
3328
- const tr = view.state.tr;
3329
- tr.replaceWith(match.start, match.end, Fragment.fromJSON(view.state.schema, fragment));
3330
- const newPos = tr.mapping.map(match.end);
3331
- tr.setSelection(TextSelection.create(tr.doc, newPos));
3332
- view.dispatch(tr.scrollIntoView());
3333
- };
3334
- var RteSuggestFeatureImpl = class extends RteFeatureImpl {
3335
- selectSuggestion(view, suggestState, suggestion) {
3336
- const fragment = this.options.select(suggestion);
3337
- replaceMatch(view, suggestState.match, fragment);
3338
- view.focus();
3339
- }
3340
- async startLoadingSuggestions(match, dispatch) {
3341
- const gen = ++this.loadGeneration;
3342
- const suggestions = await this.options.load(match);
3343
- if (gen !== this.loadGeneration) return;
3344
- dispatch({
3345
- type: "load",
3346
- generation: gen,
3347
- suggestions
3348
- });
3349
- }
3350
- constructor(featureId, options) {
3351
- super();
3352
- this.featureId = featureId;
3353
- this.options = options;
3354
- this.pluginKey = new PluginKey("suggest");
3355
- this.loadGeneration = 0;
3356
- this.name = `RteSuggestFeature[${featureId}]`;
3357
- }
3358
- getStyles() {
3359
- return [this.contribution(suggest_style_default)];
3360
- }
3361
- getPlugins(rte) {
3362
- const createSuggestActionTr = (action) => rte.state.tr.setMeta(this.pluginKey, action);
3363
- const dispatchSuggestAction = (action) => rte.dispatchTransaction(createSuggestActionTr(action));
3364
- const suggestPlugin = new Plugin({
3365
- key: this.pluginKey,
3366
- state: {
3367
- init: () => null,
3368
- apply: (tr, prevState, _prevEditor, newEditor) => {
3369
- const match = findMatch(newEditor, this.options.pattern);
3370
- if (!match) return null;
3371
- if (!prevState && !tr.docChanged) return null;
3372
- if (prevState?.dismissed) return prevState;
3373
- const loadingDecoration = (isLoading) => {
3374
- if (!isLoading) return DecorationSet.empty;
3375
- return Boolean(prevState?.loadingDecoration.find().length ?? 0) ? prevState.loadingDecoration.map(tr.mapping, tr.doc) : DecorationSet.create(tr.doc, [Decoration.widget(match.end, () => {
3376
- const wrapper = document.createElement("span");
3377
- wrapper.className = "suggest-loading-widget";
3378
- const spinner = rte.createComponent(ProgressRing);
3379
- spinner.size = -6;
3380
- wrapper.appendChild(spinner);
3381
- return wrapper;
3382
- }, {
3383
- ignoreSelection: true,
3384
- side: 1
3385
- })]);
3386
- };
3387
- const action = tr.getMeta(this.pluginKey);
3388
- if (prevState && action) switch (action.type) {
3389
- case "load": return {
3390
- ...prevState,
3391
- suggestions: {
3392
- generation: action.generation,
3393
- items: action.suggestions,
3394
- selectedIndex: 0,
3395
- visibleFocus: false
3396
- },
3397
- loadingDecoration: loadingDecoration(false)
3398
- };
3399
- case "navigate": {
3400
- /* v8 ignore next 3 -- defensive: navigate is only dispatched after results are loaded @preserve */
3401
- if (!prevState.suggestions?.items.length) return prevState;
3402
- if (!prevState.suggestions.visibleFocus) return {
3403
- ...prevState,
3404
- suggestions: {
3405
- ...prevState.suggestions,
3406
- visibleFocus: true
3407
- }
3408
- };
3409
- const newIndex = Math.max(0, Math.min(prevState.suggestions.items.length - 1, prevState.suggestions.selectedIndex + (action.action === "up" ? -1 : 1)));
3410
- return {
3411
- ...prevState,
3412
- suggestions: {
3413
- ...prevState.suggestions,
3414
- selectedIndex: newIndex
3415
- }
3416
- };
3417
- }
3418
- case "dismiss": return {
3419
- ...prevState,
3420
- dismissed: true,
3421
- loadingDecoration: DecorationSet.empty
3422
- };
3423
- }
3424
- if (!prevState) {
3425
- this.startLoadingSuggestions(match.groups, dispatchSuggestAction);
3426
- return {
3427
- match,
3428
- loadingDecoration: loadingDecoration(true)
3429
- };
3430
- }
3431
- const matchChanged = match.groups[0] !== prevState.match.groups[0];
3432
- if (matchChanged) this.startLoadingSuggestions(match.groups, dispatchSuggestAction);
3433
- return {
3434
- ...prevState,
3435
- match,
3436
- suggestions: prevState.suggestions ? {
3437
- ...prevState.suggestions,
3438
- visibleFocus: false
3439
- } : void 0,
3440
- loadingDecoration: loadingDecoration(matchChanged)
3441
- };
3442
- }
3443
- },
3444
- props: { decorations: (state) => {
3445
- const suggestState = this.pluginKey.getState(state);
3446
- if (!suggestState) return null;
3447
- return suggestState.loadingDecoration.add(state.doc, [Decoration.inline(suggestState.match.start, suggestState.match.end, { id: `suggest-anchor-${this.featureId}` })]);
3448
- } },
3449
- view: (view) => {
3450
- const ctx = new UiCtx(view, rte, {
3451
- popupPlacement: "bottom",
3452
- shouldReturnFocusToEditor: true
3453
- });
3454
- const popover = rte.createComponent(Popover);
3455
- popover.anchorId = `suggest-anchor-${this.featureId}`;
3456
- popover.kind = "autocomplete";
3457
- popover.offset = 4;
3458
- const content = createDiv(ctx, {
3459
- className: "suggest-popover",
3460
- children: []
3461
- });
3462
- popover.appendChild(content);
3463
- view.dom.getRootNode().querySelector(".popovers").appendChild(popover);
3464
- const emptySlotName = `${this.featureId}-suggestions-empty`;
3465
- const host = view.dom.getRootNode().host;
3466
- let emptySlotShowing = false;
3467
- const updateEmptySlotShowing = (showing) => {
3468
- if (!emptySlotShowing && showing) dispatchSlottableRequest(host, "suggestions-empty-state", emptySlotName, { id: this.featureId });
3469
- if (emptySlotShowing && !showing) dispatchSlottableRequest(host, "suggestions-empty-state", emptySlotName, removeSymbol);
3470
- emptySlotShowing = showing;
3471
- };
3472
- const updatePopoverContent = (suggestState) => {
3473
- content.innerHTML = "";
3474
- const suggestions = suggestState.suggestions;
3475
- const showEmptyState = suggestions.items.length === 0;
3476
- updateEmptySlotShowing(showEmptyState);
3477
- if (showEmptyState) {
3478
- const emptySlot = document.createElement("slot");
3479
- emptySlot.name = emptySlotName;
3480
- emptySlot.textContent = rte.getLocale().richTextEditor.suggestNoResults;
3481
- content.appendChild(createDiv(ctx, {
3482
- className: "suggest-empty-message",
3483
- children: [emptySlot]
3484
- }));
3485
- return;
3486
- }
3487
- for (const [index, suggestion] of suggestions.items.entries()) {
3488
- const item = rte.createComponent(ListboxOption);
3489
- item.text = suggestion.text;
3490
- item.textSecondary = suggestion.textSecondary;
3491
- if (index === suggestions.selectedIndex) {
3492
- item.selected = true;
3493
- if (suggestions.visibleFocus) item._highlighted = true;
3494
- queueMicrotask(() => {
3495
- item.scrollIntoView({ block: "nearest" });
3496
- });
3497
- }
3498
- item.addEventListener("click", (e) => {
3499
- e.preventDefault();
3500
- e.stopPropagation();
3501
- this.selectSuggestion(view, suggestState, suggestion);
3502
- });
3503
- content.appendChild(item);
3504
- }
3505
- };
3506
- return {
3507
- update: (view) => {
3508
- ctx.updateBindings();
3509
- const suggestState = this.pluginKey.getState(view.state);
3510
- const showPopover = isPopoverOpen(suggestState);
3511
- popover.requestOpenState(showPopover);
3512
- if (showPopover) updatePopoverContent(suggestState);
3513
- else updateEmptySlotShowing(false);
3514
- },
3515
- destroy: () => {
3516
- updateEmptySlotShowing(false);
3517
- popover.remove();
3518
- }
3519
- };
3520
- }
3521
- });
3522
- return [this.contribution(suggestPlugin), this.contribution(keymap({
3523
- ArrowUp: (state, dispatch) => {
3524
- if (!popoverShowsResults(this.pluginKey.getState(state))) return false;
3525
- dispatch?.(createSuggestActionTr({
3526
- type: "navigate",
3527
- action: "up"
3528
- }));
3529
- return true;
3530
- },
3531
- ArrowDown: (state, dispatch) => {
3532
- if (!popoverShowsResults(this.pluginKey.getState(state))) return false;
3533
- dispatch?.(createSuggestActionTr({
3534
- type: "navigate",
3535
- action: "down"
3536
- }));
3537
- return true;
3538
- },
3539
- Enter: (state, _dispatch, view) => {
3540
- const suggestState = this.pluginKey.getState(state);
3541
- if (!popoverShowsResults(suggestState)) return false;
3542
- const suggestion = suggestState.suggestions.items[suggestState.suggestions.selectedIndex];
3543
- /* v8 ignore next 3 -- defensive: view is always passed by keymap @preserve */
3544
- if (view) this.selectSuggestion(view, suggestState, suggestion);
3545
- return true;
3546
- },
3547
- Escape: (state, dispatch) => {
3548
- if (!isPopoverOpen(this.pluginKey.getState(state))) return false;
3549
- dispatch?.(createSuggestActionTr({ type: "dismiss" }));
3550
- return true;
3551
- }
3552
- }), contributionPriority.high)];
3553
- }
3554
- };
3555
- var RteSuggestFeature = featureFacade(RteSuggestFeatureImpl);
3556
- //#endregion
3557
- //#region src/lib/rich-text-editor/rte/features/character-count.ts
3558
- var countCharacters = (doc) => doc.textBetween(0, doc.content.size, void 0, " ").length;
3559
- var RteCharacterCountFeatureImpl = class extends RteFeatureImpl {
3560
- constructor(config) {
3561
- super();
3562
- this.config = config;
3563
- this.name = "RteCharacterCountFeature";
3564
- }
3565
- getPlugins() {
3566
- const limit = this.config?.limit;
3567
- if (limit === void 0) return [];
3568
- return [this.contribution(new Plugin({ filterTransaction: (transaction, state) => {
3569
- if (!transaction.docChanged) return true;
3570
- const oldSize = countCharacters(state.doc);
3571
- const newSize = countCharacters(transaction.doc);
3572
- if (newSize <= limit) return true;
3573
- if (oldSize > limit) return newSize <= oldSize;
3574
- if (!transaction.getMeta("paste")) return false;
3575
- const pos = transaction.selection.$head.pos;
3576
- const from = pos - (newSize - limit);
3577
- const to = pos;
3578
- transaction.deleteRange(from, to);
3579
- return countCharacters(transaction.doc) <= limit;
3580
- } }))];
3581
- }
3582
- getPublicInterface(rte) {
3583
- const limit = this.config?.limit;
3584
- return {
3585
- get characters() {
3586
- return countCharacters(rte.state.doc);
3587
- },
3588
- get limit() {
3589
- return limit;
3590
- }
3591
- };
3592
327
  }
328
+ /** @internal */
329
+ _onMouseDown(e) {
330
+ if (this.disabled || this._draggingThumb) return;
331
+ const value = this.#calculateValueFromMouseEvent(e);
332
+ const startDistance = Math.abs(value - Number(this.start));
333
+ const endDistance = Math.abs(value - Number(this.end));
334
+ const thumb = startDistance < endDistance || startDistance === endDistance && value < Number(this.start) ? "start" : "end";
335
+ this.#updateValues({ [thumb]: `${this.#roundToNearestStep(thumb, value)}` });
336
+ this._draggingThumb = thumb;
337
+ this.#focusThumbNonVisibly(this.#thumbs[thumb]);
338
+ this.#registerDragHandlers();
339
+ }
340
+ #onThumbFocus;
341
+ #onThumbBlur;
342
+ #onVisibilityChange;
343
+ #onMouseOver;
344
+ #onMouseOut;
345
+ #onThumbMousedown;
346
+ #onThumbKeydown;
347
+ #registerDragHandlers() {
348
+ window.addEventListener("mousemove", this.#onDragMove, { passive: true });
349
+ window.addEventListener("touchmove", this.#onDragMove, { passive: true });
350
+ window.addEventListener("mouseup", this.#onDragEnd);
351
+ window.addEventListener("touchend", this.#onDragEnd);
352
+ window.document.addEventListener("mouseleave", this.#onDragEnd);
353
+ }
354
+ #unregisterDragListeners() {
355
+ window.removeEventListener("mouseup", this.#onDragEnd);
356
+ window.document.removeEventListener("mouseleave", this.#onDragEnd);
357
+ window.removeEventListener("mousemove", this.#onDragMove);
358
+ window.removeEventListener("touchmove", this.#onDragMove);
359
+ window.removeEventListener("touchend", this.#onDragEnd);
360
+ }
361
+ #onDragMove;
362
+ #onDragEnd;
363
+ };
364
+ __decorate([observable], RangeSlider.prototype, "start", void 0);
365
+ __decorate([attr({
366
+ mode: "fromView",
367
+ attribute: "start"
368
+ })], RangeSlider.prototype, "initialStart", void 0);
369
+ __decorate([attr({ attribute: "current-start" })], RangeSlider.prototype, "currentStart", void 0);
370
+ __decorate([observable], RangeSlider.prototype, "end", void 0);
371
+ __decorate([attr({
372
+ mode: "fromView",
373
+ attribute: "end"
374
+ })], RangeSlider.prototype, "initialEnd", void 0);
375
+ __decorate([attr({ attribute: "current-end" })], RangeSlider.prototype, "currentEnd", void 0);
376
+ __decorate([attr({ converter: nullableNumberConverter })], RangeSlider.prototype, "min", void 0);
377
+ __decorate([attr({ converter: nullableNumberConverter })], RangeSlider.prototype, "max", void 0);
378
+ __decorate([attr({ converter: defaultToOneConverter })], RangeSlider.prototype, "step", void 0);
379
+ __decorate([attr], RangeSlider.prototype, "orientation", void 0);
380
+ __decorate([attr({ attribute: "aria-start-label" })], RangeSlider.prototype, "ariaStartLabel", void 0);
381
+ __decorate([attr({ attribute: "aria-end-label" })], RangeSlider.prototype, "ariaEndLabel", void 0);
382
+ __decorate([attr({ mode: "boolean" })], RangeSlider.prototype, "markers", void 0);
383
+ __decorate([attr], RangeSlider.prototype, "connotation", void 0);
384
+ __decorate([attr({ mode: "boolean" })], RangeSlider.prototype, "pin", void 0);
385
+ __decorate([observable], RangeSlider.prototype, "valueTextFormatter", void 0);
386
+ __decorate([observable], RangeSlider.prototype, "_draggingThumb", void 0);
387
+ __decorate([observable], RangeSlider.prototype, "_visiblyFocusedThumb", void 0);
388
+ __decorate([observable], RangeSlider.prototype, "_hoveredThumb", void 0);
389
+ __decorate([observable], RangeSlider.prototype, "_startThumbCss", void 0);
390
+ __decorate([observable], RangeSlider.prototype, "_endThumbCss", void 0);
391
+ __decorate([observable], RangeSlider.prototype, "_selectedRangeCss", void 0);
392
+ //#endregion
393
+ //#region src/lib/range-slider/range-slider.template.ts
394
+ var getThumbClassesFor = (thumb) => ({ _visiblyFocusedThumb }) => classNames("thumb-container", ["focus-visible", _visiblyFocusedThumb === thumb]);
395
+ var RangeSliderTemplate = (context) => {
396
+ const popupTag = context.tagFor(Popup);
397
+ return html` <template
398
+ @mousedown="${(x, c) => x._onMouseDown(c.event)}"
399
+ >
400
+ <div
401
+ class="${(x) => classNames("control", ["disabled", x.disabled], `connotation-${rangeSliderConnotation.parse(x.connotation)}`, "appearance-filled", "with-idle")} ${(x) => x.orientation}"
402
+ >
403
+ <div class="positioning-region">
404
+ <div ${ref("_trackEl")} class="track">
405
+ <div class="track-start" style="${(x) => x._selectedRangeCss}"></div>
406
+ ${when((x) => x.markers, html`${(x) => getMarkersTemplate(x.orientation === Orientation.horizontal, Math.floor((x.max - x.min) / x.step))}`)}
407
+ </div>
408
+ <div
409
+ id="start-thumb"
410
+ ${ref("_startThumbEl")}
411
+ class="${getThumbClassesFor("start")}"
412
+ style="${(x) => x._startThumbCss}"
413
+ role="slider"
414
+ tabindex="${(x) => x.disabled ? null : 0}"
415
+ aria-label="${(x) => x.ariaStartLabel || x.locale.rangeSlider.startThumbLabel}"
416
+ aria-valuetext="${(x) => x.valueTextFormatter(x.start)}"
417
+ aria-valuenow="${(x) => x.start}"
418
+ aria-valuemin="${(x) => x.min}"
419
+ aria-valuemax="${(x) => x.end}"
420
+ aria-disabled="${(x) => x.disabled}"
421
+ aria-orientation="${(x) => x.orientation}"
422
+ ></div>
423
+ ${when((x) => x.pin, html`<${popupTag}
424
+ class="popup"
425
+ arrow
426
+ alternate
427
+ :anchor="${(x) => x._startThumbEl}"
428
+ :open=${(x) => x._isThumbPopupOpen("start")}
429
+ :placementStrategy=${(x) => x.orientation === Orientation.horizontal ? PlacementStrategy.AutoPlacementHorizontal : PlacementStrategy.AutoPlacementVertical}
430
+ animation-frame
431
+ exportparts="vvd-theme-alternate"
432
+ aria-hidden="true"
433
+ >
434
+ <div class="tooltip">${(x) => x.valueTextFormatter(x.start)}</div>
435
+ </${popupTag}>`)}
436
+ <div
437
+ id="end-thumb"
438
+ ${ref("_endThumbEl")}
439
+ class="${getThumbClassesFor("end")}"
440
+ style="${(x) => x._endThumbCss}"
441
+ role="slider"
442
+ tabindex="${(x) => x.disabled ? null : 0}"
443
+ aria-label="${(x) => x.ariaEndLabel || x.locale.rangeSlider.endThumbLabel}"
444
+ aria-valuetext="${(x) => x.valueTextFormatter(x.end)}"
445
+ aria-valuenow="${(x) => x.end}"
446
+ aria-valuemin="${(x) => x.start}"
447
+ aria-valuemax="${(x) => x.max}"
448
+ aria-disabled="${(x) => x.disabled}"
449
+ aria-orientation="${(x) => x.orientation}"
450
+ ></div>
451
+ ${when((x) => x.pin, html`<${popupTag}
452
+ class="popup"
453
+ arrow
454
+ alternate
455
+ :anchor="${(x) => x._endThumbEl}"
456
+ :open=${(x) => x._isThumbPopupOpen("end")}
457
+ :placementStrategy=${(x) => x.orientation === Orientation.horizontal ? PlacementStrategy.AutoPlacementHorizontal : PlacementStrategy.AutoPlacementVertical}
458
+ animation-frame
459
+ exportparts="vvd-theme-alternate"
460
+ aria-hidden="true"
461
+ >
462
+ <div class="tooltip">${(x) => x.valueTextFormatter(x.end)}</div>
463
+ </${popupTag}>`)}
464
+ </div>
465
+ </div>
466
+ </template>`;
3593
467
  };
3594
- var RteCharacterCountFeature = featureFacade(RteCharacterCountFeatureImpl);
3595
468
  //#endregion
3596
- //#region src/lib/rich-text-editor/definition.ts
3597
- var richTextEditorDefinition = defineVividComponent("rich-text-editor", RichTextEditor, RichTextEditorTemplate, [
3598
- dividerDefinition,
3599
- selectDefinition,
3600
- listboxOptionDefinition,
3601
- buttonDefinition,
3602
- tooltipDefinition,
3603
- menuDefinition,
3604
- menuItemDefinition,
3605
- textFieldDefinition,
3606
- popoverDefinition,
3607
- progressRingDefinition
3608
- ], {
3609
- styles: rich_text_editor_default,
469
+ //#region src/lib/range-slider/definition.ts
470
+ /** @internal */
471
+ var rangeSliderDefinition = defineVividComponent("range-slider", RangeSlider, RangeSliderTemplate, [popupDefinition], {
472
+ styles: range_slider_default,
3610
473
  shadowOptions: { delegatesFocus: true }
3611
474
  });
3612
475
  /**
3613
- * Registers the rich-text-editor element with the design system.
476
+ * Registers the range-slider element with the design system.
3614
477
  *
3615
478
  * @param prefix - the prefix to use for the component name
3616
479
  */
3617
- var registerRichTextEditor = createRegisterFunction(richTextEditorDefinition);
480
+ var registerRangeSlider = createRegisterFunction(rangeSliderDefinition);
3618
481
  //#endregion
3619
- export { RichTextEditor as A, RtePlaceholderFeature as C, RteConfig as D, RteBase as E, RteHtmlSerializer as O, RteHardBreakFeature as S, RteTextBlockPickerFeature as T, RteStrikethroughFeature as _, RteKeyboardShortcutsFeature as a, RteBoldFeature as b, RteToolbarButtonFeature as c, RteInlineImageFeature as d, RteLinkFeature as f, RteMonospaceFeature as g, RteTextColorPickerFeature as h, RteSuggestFeature as i, RteHtmlParser as k, RteDropHandlerFeature as l, RteListFeature as m, richTextEditorDefinition as n, RteInputRuleFeature as o, RteAlignmentFeature as p, RteCharacterCountFeature as r, RteAtomFeature as s, registerRichTextEditor as t, RteFileHandlerFeature as u, RteUnderlineFeature as v, RteToolbarFeature as w, RteFontSizePickerFeature as x, RteItalicFeature as y };
482
+ export { registerRangeSlider as n, RangeSlider as r, rangeSliderDefinition as t };