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