@techzyapp/ui-library 1.0.23 → 1.0.25

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 (320) hide show
  1. package/dist/{AdminRoot-C7Idu7FQ.cjs → AdminRoot-BkPPRkyQ.cjs} +2 -2
  2. package/dist/{AdminRoot-C7Idu7FQ.cjs.map → AdminRoot-BkPPRkyQ.cjs.map} +1 -1
  3. package/dist/{AdminRoot-aDy6rNqI.js → AdminRoot-CgvtgUpW.js} +4 -4
  4. package/dist/{AdminRoot-aDy6rNqI.js.map → AdminRoot-CgvtgUpW.js.map} +1 -1
  5. package/dist/Alert-DXmzM_rh.js +71 -0
  6. package/dist/{Alert-D6VL2C-E.js.map → Alert-DXmzM_rh.js.map} +1 -1
  7. package/dist/Alert-udX1ybuC.cjs +2 -0
  8. package/dist/{Alert-Cl1zxmX9.cjs.map → Alert-udX1ybuC.cjs.map} +1 -1
  9. package/dist/Blockquote-BWGxIL_V.cjs +2 -0
  10. package/dist/{Blockquote-CxHwOecc.cjs.map → Blockquote-BWGxIL_V.cjs.map} +1 -1
  11. package/dist/Blockquote-Ma-2naET.js +46 -0
  12. package/dist/{Blockquote-CNIuJFHq.js.map → Blockquote-Ma-2naET.js.map} +1 -1
  13. package/dist/{Breadcrumbs-BnFW4LgK.cjs → Breadcrumbs-CsYTiX2h.cjs} +2 -2
  14. package/dist/{Breadcrumbs-BnFW4LgK.cjs.map → Breadcrumbs-CsYTiX2h.cjs.map} +1 -1
  15. package/dist/{Breadcrumbs-CicfjfIu.js → Breadcrumbs-DQHHeLId.js} +3 -3
  16. package/dist/{Breadcrumbs-CicfjfIu.js.map → Breadcrumbs-DQHHeLId.js.map} +1 -1
  17. package/dist/{Button-ZplrHYKw.cjs → Button-CXmDOzPk.cjs} +2 -2
  18. package/dist/{Button-ZplrHYKw.cjs.map → Button-CXmDOzPk.cjs.map} +1 -1
  19. package/dist/{Button-Cfxd7qhd.js → Button-DBs8xnA5.js} +2 -2
  20. package/dist/{Button-Cfxd7qhd.js.map → Button-DBs8xnA5.js.map} +1 -1
  21. package/dist/{Calendar-S9vyp-qv.cjs → Calendar-B2nMXk4C.cjs} +2 -2
  22. package/dist/{Calendar-S9vyp-qv.cjs.map → Calendar-B2nMXk4C.cjs.map} +1 -1
  23. package/dist/{Calendar-DTxCT-ki.js → Calendar-CtteUt82.js} +3 -3
  24. package/dist/{Calendar-DTxCT-ki.js.map → Calendar-CtteUt82.js.map} +1 -1
  25. package/dist/{Card-BeE2ohcn.cjs → Card-DGF22HbS.cjs} +2 -2
  26. package/dist/{Card-BeE2ohcn.cjs.map → Card-DGF22HbS.cjs.map} +1 -1
  27. package/dist/{Card-eXJfA4rU.js → Card-DYKnWt-L.js} +2 -2
  28. package/dist/{Card-eXJfA4rU.js.map → Card-DYKnWt-L.js.map} +1 -1
  29. package/dist/{Chip-BOXXdzap.js → Chip-DdKhcstm.js} +2 -2
  30. package/dist/{Chip-BOXXdzap.js.map → Chip-DdKhcstm.js.map} +1 -1
  31. package/dist/{Chip-B4XERWb_.cjs → Chip-gUH_7nQc.cjs} +2 -2
  32. package/dist/{Chip-B4XERWb_.cjs.map → Chip-gUH_7nQc.cjs.map} +1 -1
  33. package/dist/{CodeBlock-C7_A6CTT.cjs → CodeBlock-C6tQtbHU.cjs} +2 -2
  34. package/dist/{CodeBlock-C7_A6CTT.cjs.map → CodeBlock-C6tQtbHU.cjs.map} +1 -1
  35. package/dist/{CodeBlock-D_PRiWMq.js → CodeBlock-DD_d3-sM.js} +3 -3
  36. package/dist/{CodeBlock-D_PRiWMq.js.map → CodeBlock-DD_d3-sM.js.map} +1 -1
  37. package/dist/{ColorPicker-ClVpWf77.cjs → ColorPicker-DtzFwNWk.cjs} +2 -2
  38. package/dist/{ColorPicker-ClVpWf77.cjs.map → ColorPicker-DtzFwNWk.cjs.map} +1 -1
  39. package/dist/{ColorPicker-DAjs7PmR.js → ColorPicker-Dw6Qk0iy.js} +3 -3
  40. package/dist/{ColorPicker-DAjs7PmR.js.map → ColorPicker-Dw6Qk0iy.js.map} +1 -1
  41. package/dist/{ColorPickerPanel-Dk6bI0Xy.cjs → ColorPickerPanel--wBX-m7J.cjs} +2 -2
  42. package/dist/{ColorPickerPanel-Dk6bI0Xy.cjs.map → ColorPickerPanel--wBX-m7J.cjs.map} +1 -1
  43. package/dist/{ColorPickerPanel-BGzm2had.js → ColorPickerPanel-Dp7bnnVf.js} +2 -2
  44. package/dist/{ColorPickerPanel-BGzm2had.js.map → ColorPickerPanel-Dp7bnnVf.js.map} +1 -1
  45. package/dist/ConfigProvider-Bszl3Wr3.cjs +2 -0
  46. package/dist/ConfigProvider-Bszl3Wr3.cjs.map +1 -0
  47. package/dist/ConfigProvider-DR9YMy9U.js +320 -0
  48. package/dist/ConfigProvider-DR9YMy9U.js.map +1 -0
  49. package/dist/{CopyButton-COF3hIV-.cjs → CopyButton-Ct-8AmmX.cjs} +2 -2
  50. package/dist/{CopyButton-COF3hIV-.cjs.map → CopyButton-Ct-8AmmX.cjs.map} +1 -1
  51. package/dist/{CopyButton-Bv7L4xJf.js → CopyButton-DJ1PSJZU.js} +3 -3
  52. package/dist/{CopyButton-Bv7L4xJf.js.map → CopyButton-DJ1PSJZU.js.map} +1 -1
  53. package/dist/{DatePicker-kA-xn5ET.cjs → DatePicker-BxEydgfu.cjs} +2 -2
  54. package/dist/{DatePicker-kA-xn5ET.cjs.map → DatePicker-BxEydgfu.cjs.map} +1 -1
  55. package/dist/{DatePicker-DZfOvxUR.js → DatePicker-CJioG5M7.js} +4 -4
  56. package/dist/{DatePicker-DZfOvxUR.js.map → DatePicker-CJioG5M7.js.map} +1 -1
  57. package/dist/{DateTimePicker-DEGmn5UX.cjs → DateTimePicker-COEj2Z0F.cjs} +2 -2
  58. package/dist/{DateTimePicker-DEGmn5UX.cjs.map → DateTimePicker-COEj2Z0F.cjs.map} +1 -1
  59. package/dist/{DateTimePicker-BxBXhSN_.js → DateTimePicker-e2zj2bhS.js} +7 -7
  60. package/dist/{DateTimePicker-BxBXhSN_.js.map → DateTimePicker-e2zj2bhS.js.map} +1 -1
  61. package/dist/{EmptyState-Du4vA3bC.js → EmptyState-BTd7aVgu.js} +12 -12
  62. package/dist/{EmptyState-Du4vA3bC.js.map → EmptyState-BTd7aVgu.js.map} +1 -1
  63. package/dist/EmptyState-Bv4XXnD1.cjs +2 -0
  64. package/dist/{EmptyState-DlX-BLLI.cjs.map → EmptyState-Bv4XXnD1.cjs.map} +1 -1
  65. package/dist/{FileCard-zyCpTrJ-.cjs → FileCard-DW5Ur8Aj.cjs} +2 -2
  66. package/dist/{FileCard-zyCpTrJ-.cjs.map → FileCard-DW5Ur8Aj.cjs.map} +1 -1
  67. package/dist/{FileCard-juQ1fWbG.js → FileCard-DY8N9Lzz.js} +3 -3
  68. package/dist/{FileCard-juQ1fWbG.js.map → FileCard-DY8N9Lzz.js.map} +1 -1
  69. package/dist/{FileUploader-DOe3CyJB.cjs → FileUploader-B7VfhcR7.cjs} +2 -2
  70. package/dist/{FileUploader-DOe3CyJB.cjs.map → FileUploader-B7VfhcR7.cjs.map} +1 -1
  71. package/dist/{FileUploader-DL9atihI.js → FileUploader-BYF5FvUc.js} +5 -5
  72. package/dist/{FileUploader-DL9atihI.js.map → FileUploader-BYF5FvUc.js.map} +1 -1
  73. package/dist/{Flag-DFKHYnqk.cjs → Flag-CB4YyPj3.cjs} +2 -2
  74. package/dist/{Flag-DFKHYnqk.cjs.map → Flag-CB4YyPj3.cjs.map} +1 -1
  75. package/dist/{Flag-BxRrjCTB.js → Flag-yA1y5XzR.js} +2 -2
  76. package/dist/{Flag-BxRrjCTB.js.map → Flag-yA1y5XzR.js.map} +1 -1
  77. package/dist/{FullscreenToggle-BNK7RcRq.cjs → FullscreenToggle-0lskYnpx.cjs} +2 -2
  78. package/dist/{FullscreenToggle-BNK7RcRq.cjs.map → FullscreenToggle-0lskYnpx.cjs.map} +1 -1
  79. package/dist/{FullscreenToggle-BMCNsyzb.js → FullscreenToggle-jSLruiKt.js} +3 -3
  80. package/dist/{FullscreenToggle-BMCNsyzb.js.map → FullscreenToggle-jSLruiKt.js.map} +1 -1
  81. package/dist/{IconButton-CfvsE_p3.js → IconButton-BEGWfcVc.js} +2 -2
  82. package/dist/{IconButton-CfvsE_p3.js.map → IconButton-BEGWfcVc.js.map} +1 -1
  83. package/dist/{IconButton-B9eVM18U.cjs → IconButton-BN-bZxEi.cjs} +2 -2
  84. package/dist/{IconButton-B9eVM18U.cjs.map → IconButton-BN-bZxEi.cjs.map} +1 -1
  85. package/dist/{Loader-CxLrhAz9.cjs → Loader-B5YqzEYy.cjs} +2 -2
  86. package/dist/{Loader-CxLrhAz9.cjs.map → Loader-B5YqzEYy.cjs.map} +1 -1
  87. package/dist/Loader-BZIa8hwv.js +29 -0
  88. package/dist/{Loader-DwmyJFwG.js.map → Loader-BZIa8hwv.js.map} +1 -1
  89. package/dist/Modal-0V-REVV-.cjs +2 -0
  90. package/dist/{Modal-DXZdMmJh.cjs.map → Modal-0V-REVV-.cjs.map} +1 -1
  91. package/dist/Modal-B7yoFC3o.js +195 -0
  92. package/dist/{Modal-Cx0JEQ-j.js.map → Modal-B7yoFC3o.js.map} +1 -1
  93. package/dist/{MultiSelect-yGlvweEq.js → MultiSelect-C8xuXaoR.js} +4 -4
  94. package/dist/{MultiSelect-yGlvweEq.js.map → MultiSelect-C8xuXaoR.js.map} +1 -1
  95. package/dist/{MultiSelect-DfhyGxDU.cjs → MultiSelect-gj9Ymeh2.cjs} +2 -2
  96. package/dist/{MultiSelect-DfhyGxDU.cjs.map → MultiSelect-gj9Ymeh2.cjs.map} +1 -1
  97. package/dist/{NumberField-cAjPU1P5.js → NumberField-2yM0mmyj.js} +3 -3
  98. package/dist/{NumberField-cAjPU1P5.js.map → NumberField-2yM0mmyj.js.map} +1 -1
  99. package/dist/{NumberField-B7yPXIw_.cjs → NumberField-CEt95jcC.cjs} +2 -2
  100. package/dist/{NumberField-B7yPXIw_.cjs.map → NumberField-CEt95jcC.cjs.map} +1 -1
  101. package/dist/OtpField-CkliY82J.js +174 -0
  102. package/dist/OtpField-CkliY82J.js.map +1 -0
  103. package/dist/OtpField-on-K0_fM.cjs +2 -0
  104. package/dist/OtpField-on-K0_fM.cjs.map +1 -0
  105. package/dist/{PageLayout-BSHyKoQ4.cjs → PageLayout-DGHu7Vm3.cjs} +2 -2
  106. package/dist/{PageLayout-BSHyKoQ4.cjs.map → PageLayout-DGHu7Vm3.cjs.map} +1 -1
  107. package/dist/{PageLayout-C9Je7kfF.js → PageLayout-DzPh_G6H.js} +2 -2
  108. package/dist/{PageLayout-C9Je7kfF.js.map → PageLayout-DzPh_G6H.js.map} +1 -1
  109. package/dist/{PageNotFound-voB9ylPF.cjs → PageNotFound-B8_eIT8p.cjs} +2 -2
  110. package/dist/{PageNotFound-voB9ylPF.cjs.map → PageNotFound-B8_eIT8p.cjs.map} +1 -1
  111. package/dist/{PageNotFound-CUN2OntP.js → PageNotFound-CCFfPHgA.js} +5 -5
  112. package/dist/{PageNotFound-CUN2OntP.js.map → PageNotFound-CCFfPHgA.js.map} +1 -1
  113. package/dist/{Pagination-BUGaylZa.cjs → Pagination-BdVebW2L.cjs} +2 -2
  114. package/dist/{Pagination-BUGaylZa.cjs.map → Pagination-BdVebW2L.cjs.map} +1 -1
  115. package/dist/{Pagination-BaVHgIWT.js → Pagination-CmskZjcz.js} +2 -2
  116. package/dist/{Pagination-BaVHgIWT.js.map → Pagination-CmskZjcz.js.map} +1 -1
  117. package/dist/{RemoveDialog-BpL2-gnz.js → RemoveDialog-CV75B0aN.js} +4 -4
  118. package/dist/{RemoveDialog-BpL2-gnz.js.map → RemoveDialog-CV75B0aN.js.map} +1 -1
  119. package/dist/{RemoveDialog-DGt_72we.cjs → RemoveDialog-DmOk0ezc.cjs} +2 -2
  120. package/dist/{RemoveDialog-DGt_72we.cjs.map → RemoveDialog-DmOk0ezc.cjs.map} +1 -1
  121. package/dist/{RichTextEditor-C_6pzqYY.js → RichTextEditor-Bm8FFbcR.js} +7 -7
  122. package/dist/{RichTextEditor-C_6pzqYY.js.map → RichTextEditor-Bm8FFbcR.js.map} +1 -1
  123. package/dist/{RichTextEditor-BuoywqBu.cjs → RichTextEditor-uXddgtlk.cjs} +2 -2
  124. package/dist/{RichTextEditor-BuoywqBu.cjs.map → RichTextEditor-uXddgtlk.cjs.map} +1 -1
  125. package/dist/RootLayout-Cf7Rr9Iz.js +515 -0
  126. package/dist/RootLayout-Cf7Rr9Iz.js.map +1 -0
  127. package/dist/RootLayout-kssj9exn.cjs +2 -0
  128. package/dist/RootLayout-kssj9exn.cjs.map +1 -0
  129. package/dist/{Select-CVy5BnKe.cjs → Select-7vEGJCvA.cjs} +2 -2
  130. package/dist/{Select-CVy5BnKe.cjs.map → Select-7vEGJCvA.cjs.map} +1 -1
  131. package/dist/{Select-ChT-6_bM.js → Select-CdX3Ks7y.js} +3 -3
  132. package/dist/{Select-ChT-6_bM.js.map → Select-CdX3Ks7y.js.map} +1 -1
  133. package/dist/{Sidebar-D2MsR33k.cjs → Sidebar-DcKIEfhy.cjs} +2 -2
  134. package/dist/{Sidebar-D2MsR33k.cjs.map → Sidebar-DcKIEfhy.cjs.map} +1 -1
  135. package/dist/{Sidebar-ZA1wxCez.js → Sidebar-YH-DoNG9.js} +3 -3
  136. package/dist/{Sidebar-ZA1wxCez.js.map → Sidebar-YH-DoNG9.js.map} +1 -1
  137. package/dist/{SpeedDial-B9JTNNUU.cjs → SpeedDial-9_Yk8AGx.cjs} +2 -2
  138. package/dist/{SpeedDial-B9JTNNUU.cjs.map → SpeedDial-9_Yk8AGx.cjs.map} +1 -1
  139. package/dist/{SpeedDial-DUYQMDCY.js → SpeedDial-DWNuC6f8.js} +2 -2
  140. package/dist/{SpeedDial-DUYQMDCY.js.map → SpeedDial-DWNuC6f8.js.map} +1 -1
  141. package/dist/{Stepper-BaC934rb.cjs → Stepper-B1z_u650.cjs} +2 -2
  142. package/dist/{Stepper-BaC934rb.cjs.map → Stepper-B1z_u650.cjs.map} +1 -1
  143. package/dist/{Stepper-D89I17pC.js → Stepper-CuqFpamY.js} +2 -2
  144. package/dist/{Stepper-D89I17pC.js.map → Stepper-CuqFpamY.js.map} +1 -1
  145. package/dist/{Table-DvgBWTLx.cjs → Table-BPit83Pn.cjs} +2 -2
  146. package/dist/{Table-DvgBWTLx.cjs.map → Table-BPit83Pn.cjs.map} +1 -1
  147. package/dist/{Table-CdIQ5Wfh.js → Table-Drdhfm99.js} +15 -15
  148. package/dist/{Table-CdIQ5Wfh.js.map → Table-Drdhfm99.js.map} +1 -1
  149. package/dist/{Tabs-CejCwV3O.cjs → Tabs-BiKDy_fv.cjs} +2 -2
  150. package/dist/{Tabs-CejCwV3O.cjs.map → Tabs-BiKDy_fv.cjs.map} +1 -1
  151. package/dist/{Tabs-8-klG-y-.js → Tabs-ytbBzAxG.js} +2 -2
  152. package/dist/{Tabs-8-klG-y-.js.map → Tabs-ytbBzAxG.js.map} +1 -1
  153. package/dist/{TagsField-BQLqUckB.js → TagsField-CEt_PC5y.js} +4 -4
  154. package/dist/{TagsField-BQLqUckB.js.map → TagsField-CEt_PC5y.js.map} +1 -1
  155. package/dist/{TagsField-BSAd4eUr.cjs → TagsField-DpDbf0ru.cjs} +2 -2
  156. package/dist/{TagsField-BSAd4eUr.cjs.map → TagsField-DpDbf0ru.cjs.map} +1 -1
  157. package/dist/{TextField-B4YtjNUs.js → TextField-BWdmF-HE.js} +3 -3
  158. package/dist/{TextField-B4YtjNUs.js.map → TextField-BWdmF-HE.js.map} +1 -1
  159. package/dist/{TextField-DzYGA_St.cjs → TextField-Df_kGy2l.cjs} +2 -2
  160. package/dist/{TextField-DzYGA_St.cjs.map → TextField-Df_kGy2l.cjs.map} +1 -1
  161. package/dist/{ThemeToggle-BKk0eFiB.cjs → ThemeToggle-BJdXhmfc.cjs} +2 -2
  162. package/dist/{ThemeToggle-BKk0eFiB.cjs.map → ThemeToggle-BJdXhmfc.cjs.map} +1 -1
  163. package/dist/{ThemeToggle-B4_zRHJY.js → ThemeToggle-CgxF6oUu.js} +3 -3
  164. package/dist/{ThemeToggle-B4_zRHJY.js.map → ThemeToggle-CgxF6oUu.js.map} +1 -1
  165. package/dist/{TimeColumns-BAzRrkqY.cjs → TimeColumns-DxVN0V8l.cjs} +2 -2
  166. package/dist/{TimeColumns-BAzRrkqY.cjs.map → TimeColumns-DxVN0V8l.cjs.map} +1 -1
  167. package/dist/{TimeColumns-CAPyli9V.js → TimeColumns-n-fz50mr.js} +2 -2
  168. package/dist/{TimeColumns-CAPyli9V.js.map → TimeColumns-n-fz50mr.js.map} +1 -1
  169. package/dist/{TimePicker-BebBSlQF.js → TimePicker-Bopxx3zU.js} +5 -5
  170. package/dist/{TimePicker-BebBSlQF.js.map → TimePicker-Bopxx3zU.js.map} +1 -1
  171. package/dist/{TimePicker-BUnXYR5g.cjs → TimePicker-DvoemiGz.cjs} +2 -2
  172. package/dist/{TimePicker-BUnXYR5g.cjs.map → TimePicker-DvoemiGz.cjs.map} +1 -1
  173. package/dist/{Toaster-ywqAKP8s.js → Toaster-BxIY2H4V.js} +2 -2
  174. package/dist/{Toaster-ywqAKP8s.js.map → Toaster-BxIY2H4V.js.map} +1 -1
  175. package/dist/{Toaster-B2rO4BkG.cjs → Toaster-DZSzFse_.cjs} +2 -2
  176. package/dist/{Toaster-B2rO4BkG.cjs.map → Toaster-DZSzFse_.cjs.map} +1 -1
  177. package/dist/{TranslatedFields-DQQUb0RD.cjs → TranslatedFields-BtDLkQy7.cjs} +2 -2
  178. package/dist/{TranslatedFields-DQQUb0RD.cjs.map → TranslatedFields-BtDLkQy7.cjs.map} +1 -1
  179. package/dist/{TranslatedFields-C-wlh51E.js → TranslatedFields-DmR8LKSG.js} +5 -5
  180. package/dist/{TranslatedFields-C-wlh51E.js.map → TranslatedFields-DmR8LKSG.js.map} +1 -1
  181. package/dist/{UserCard-Be1kl0TZ.cjs → UserCard-C1yFvVIc.cjs} +2 -2
  182. package/dist/{UserCard-Be1kl0TZ.cjs.map → UserCard-C1yFvVIc.cjs.map} +1 -1
  183. package/dist/{UserCard-BqWt0S-c.js → UserCard-J8Bpbh3x.js} +3 -3
  184. package/dist/{UserCard-BqWt0S-c.js.map → UserCard-J8Bpbh3x.js.map} +1 -1
  185. package/dist/components/Alert/index.cjs +1 -1
  186. package/dist/components/Alert/index.js +1 -1
  187. package/dist/components/Blockquote/Blockquote.d.cts +1 -1
  188. package/dist/components/Blockquote/Blockquote.d.ts +1 -1
  189. package/dist/components/Blockquote/index.cjs +1 -1
  190. package/dist/components/Blockquote/index.js +1 -1
  191. package/dist/components/Breadcrumbs/index.cjs +1 -1
  192. package/dist/components/Breadcrumbs/index.js +1 -1
  193. package/dist/components/Button/index.cjs +1 -1
  194. package/dist/components/Button/index.js +1 -1
  195. package/dist/components/Card/index.cjs +1 -1
  196. package/dist/components/Card/index.js +1 -1
  197. package/dist/components/Chip/index.cjs +1 -1
  198. package/dist/components/Chip/index.js +1 -1
  199. package/dist/components/CodeBlock/index.cjs +1 -1
  200. package/dist/components/CodeBlock/index.js +1 -1
  201. package/dist/components/ColorPicker/index.cjs +1 -1
  202. package/dist/components/ColorPicker/index.js +1 -1
  203. package/dist/components/CopyButton/index.cjs +1 -1
  204. package/dist/components/CopyButton/index.js +1 -1
  205. package/dist/components/DatePicker/index.cjs +1 -1
  206. package/dist/components/DatePicker/index.js +1 -1
  207. package/dist/components/DateTimePicker/index.cjs +1 -1
  208. package/dist/components/DateTimePicker/index.js +1 -1
  209. package/dist/components/EmptyState/index.cjs +1 -1
  210. package/dist/components/EmptyState/index.js +1 -1
  211. package/dist/components/FileCard/index.cjs +1 -1
  212. package/dist/components/FileCard/index.js +1 -1
  213. package/dist/components/FileUploader/index.cjs +1 -1
  214. package/dist/components/FileUploader/index.js +1 -1
  215. package/dist/components/Flag/index.cjs +1 -1
  216. package/dist/components/Flag/index.js +1 -1
  217. package/dist/components/FullscreenToggle/index.cjs +1 -1
  218. package/dist/components/FullscreenToggle/index.js +1 -1
  219. package/dist/components/IconButton/index.cjs +1 -1
  220. package/dist/components/IconButton/index.js +1 -1
  221. package/dist/components/Loader/index.cjs +1 -1
  222. package/dist/components/Loader/index.js +1 -1
  223. package/dist/components/Modal/index.cjs +1 -1
  224. package/dist/components/Modal/index.js +1 -1
  225. package/dist/components/MultiSelect/index.cjs +1 -1
  226. package/dist/components/MultiSelect/index.js +1 -1
  227. package/dist/components/NumberField/index.cjs +1 -1
  228. package/dist/components/NumberField/index.js +1 -1
  229. package/dist/components/OtpField/OtpField.d.cts +3 -0
  230. package/dist/components/OtpField/OtpField.d.ts +3 -0
  231. package/dist/components/OtpField/index.cjs +1 -1
  232. package/dist/components/OtpField/index.d.cts +1 -1
  233. package/dist/components/OtpField/index.d.ts +1 -1
  234. package/dist/components/OtpField/index.js +1 -1
  235. package/dist/components/PageLayout/index.cjs +1 -1
  236. package/dist/components/PageLayout/index.js +1 -1
  237. package/dist/components/PageNotFound/index.cjs +1 -1
  238. package/dist/components/PageNotFound/index.js +1 -1
  239. package/dist/components/Pagination/index.cjs +1 -1
  240. package/dist/components/Pagination/index.js +1 -1
  241. package/dist/components/RemoveDialog/index.cjs +1 -1
  242. package/dist/components/RemoveDialog/index.js +1 -1
  243. package/dist/components/RichTextEditor/index.cjs +1 -1
  244. package/dist/components/RichTextEditor/index.js +1 -1
  245. package/dist/components/RootLayout/SettingsDrawer.d.cts +3 -1
  246. package/dist/components/RootLayout/SettingsDrawer.d.ts +3 -1
  247. package/dist/components/RootLayout/index.cjs +1 -1
  248. package/dist/components/RootLayout/index.js +1 -1
  249. package/dist/components/Select/index.cjs +1 -1
  250. package/dist/components/Select/index.js +1 -1
  251. package/dist/components/Sidebar/index.cjs +1 -1
  252. package/dist/components/Sidebar/index.js +1 -1
  253. package/dist/components/SpeedDial/index.cjs +1 -1
  254. package/dist/components/SpeedDial/index.js +1 -1
  255. package/dist/components/Stepper/index.cjs +1 -1
  256. package/dist/components/Stepper/index.js +1 -1
  257. package/dist/components/Table/index.cjs +1 -1
  258. package/dist/components/Table/index.js +1 -1
  259. package/dist/components/Tabs/index.cjs +1 -1
  260. package/dist/components/Tabs/index.js +1 -1
  261. package/dist/components/TagsField/index.cjs +1 -1
  262. package/dist/components/TagsField/index.js +1 -1
  263. package/dist/components/TextField/index.cjs +1 -1
  264. package/dist/components/TextField/index.js +1 -1
  265. package/dist/components/ThemeToggle/index.cjs +1 -1
  266. package/dist/components/ThemeToggle/index.js +1 -1
  267. package/dist/components/TimePicker/index.cjs +1 -1
  268. package/dist/components/TimePicker/index.js +1 -1
  269. package/dist/components/Toast/index.cjs +1 -1
  270. package/dist/components/Toast/index.js +1 -1
  271. package/dist/components/TranslatedFields/index.cjs +1 -1
  272. package/dist/components/TranslatedFields/index.js +1 -1
  273. package/dist/components/UserCard/index.cjs +1 -1
  274. package/dist/components/UserCard/index.js +1 -1
  275. package/dist/entries/app.cjs +1 -1
  276. package/dist/entries/app.js +1 -1
  277. package/dist/entries/components.cjs +1 -1
  278. package/dist/entries/components.js +41 -41
  279. package/dist/entries/i18n.cjs +1 -1
  280. package/dist/entries/i18n.js +2 -2
  281. package/dist/entries/theme.cjs +1 -1
  282. package/dist/entries/theme.d.cts +1 -1
  283. package/dist/entries/theme.d.ts +1 -1
  284. package/dist/entries/theme.js +1 -1
  285. package/dist/i18n/messages.d.cts +6 -0
  286. package/dist/i18n/messages.d.ts +6 -0
  287. package/dist/index.cjs +1 -1
  288. package/dist/index.css +25 -2
  289. package/dist/index.js +44 -44
  290. package/dist/{messages-Dvn_tEp0.cjs → messages-DKT0SRM0.cjs} +9 -9
  291. package/dist/messages-DKT0SRM0.cjs.map +1 -0
  292. package/dist/{messages-CL8uoIRj.js → messages-ogohLC5P.js} +67 -25
  293. package/dist/messages-ogohLC5P.js.map +1 -0
  294. package/dist/theme/ConfigProvider.d.cts +19 -0
  295. package/dist/theme/ConfigProvider.d.ts +19 -0
  296. package/dist/theme/index.d.cts +1 -1
  297. package/dist/theme/index.d.ts +1 -1
  298. package/package.json +1 -1
  299. package/dist/Alert-Cl1zxmX9.cjs +0 -2
  300. package/dist/Alert-D6VL2C-E.js +0 -71
  301. package/dist/Blockquote-CNIuJFHq.js +0 -46
  302. package/dist/Blockquote-CxHwOecc.cjs +0 -2
  303. package/dist/ConfigProvider-Blhvj6UQ.js +0 -296
  304. package/dist/ConfigProvider-Blhvj6UQ.js.map +0 -1
  305. package/dist/ConfigProvider-CUG8Mfy2.cjs +0 -2
  306. package/dist/ConfigProvider-CUG8Mfy2.cjs.map +0 -1
  307. package/dist/EmptyState-DlX-BLLI.cjs +0 -2
  308. package/dist/Loader-DwmyJFwG.js +0 -28
  309. package/dist/Modal-Cx0JEQ-j.js +0 -195
  310. package/dist/Modal-DXZdMmJh.cjs +0 -2
  311. package/dist/OtpField-BujZAy2A.cjs +0 -2
  312. package/dist/OtpField-BujZAy2A.cjs.map +0 -1
  313. package/dist/OtpField-D0eTOLtg.js +0 -171
  314. package/dist/OtpField-D0eTOLtg.js.map +0 -1
  315. package/dist/RootLayout-1am1CwPQ.cjs +0 -2
  316. package/dist/RootLayout-1am1CwPQ.cjs.map +0 -1
  317. package/dist/RootLayout-x7qWzXPc.js +0 -479
  318. package/dist/RootLayout-x7qWzXPc.js.map +0 -1
  319. package/dist/messages-CL8uoIRj.js.map +0 -1
  320. package/dist/messages-Dvn_tEp0.cjs.map +0 -1
@@ -2,7 +2,7 @@ import { jsx as r, jsxs as Q } from "react/jsx-runtime";
2
2
  import { forwardRef as U, useState as V } from "react";
3
3
  import { clsx as d } from "clsx";
4
4
  import { I as W } from "./Icon-DaTvzLBu.js";
5
- import { a as X } from "./ConfigProvider-Blhvj6UQ.js";
5
+ import { a as X } from "./ConfigProvider-DR9YMy9U.js";
6
6
  const w = (s, t) => Array.from({ length: Math.max(t - s + 1, 0) }, (l, a) => s + a);
7
7
  function Y({
8
8
  count: s,
@@ -136,4 +136,4 @@ const Z = "_pagination_wk3op_3", b = "_list_wk3op_8", y = "_item_wk3op_18", u =
136
136
  export {
137
137
  fa as P
138
138
  };
139
- //# sourceMappingURL=Pagination-BaVHgIWT.js.map
139
+ //# sourceMappingURL=Pagination-CmskZjcz.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination-BaVHgIWT.js","sources":["../src/components/Pagination/paginationRange.ts","../src/components/Pagination/Pagination.tsx"],"sourcesContent":["/** A gap placeholder rendered as `…` — at the start (`1 … 4`) or end (`6 … 10`) of the range. */\nexport type PaginationEllipsis = 'start-ellipsis' | 'end-ellipsis'\n\n/** One item in a pagination range: a 1-based page number, or an ellipsis placeholder. */\nexport type PaginationItem = number | PaginationEllipsis\n\n/** Inputs for {@link paginationRange}. */\nexport interface PaginationRangeOptions {\n /** Total number of pages. */\n count: number\n /** Current page (1-based). */\n page: number\n /** Pages shown on each side of the current page. Defaults to `1`. */\n siblingCount?: number\n /** Pages always shown at the start and end. Defaults to `1`. */\n boundaryCount?: number\n}\n\n/** Inclusive integer range `[start, end]` (empty when `end < start`). */\nconst range = (start: number, end: number): number[] =>\n Array.from({ length: Math.max(end - start + 1, 0) }, (_, i) => start + i)\n\n/**\n * Build the page-item sequence for a pager — the boundary pages, the current page with its siblings,\n * and `start`/`end` ellipses where pages are skipped (the classic `1 … 4 5 6 … 10`). Pure and\n * framework-free so it can be unit-tested in isolation and reused. Assumes `1 <= page <= count`.\n */\nexport function paginationRange({\n count,\n page,\n siblingCount = 1,\n boundaryCount = 1,\n}: PaginationRangeOptions): PaginationItem[] {\n if (count <= 0) return []\n\n // Pages pinned at each edge.\n const startPages = range(1, Math.min(boundaryCount, count))\n const endPages = range(Math.max(count - boundaryCount + 1, boundaryCount + 1), count)\n\n // The window of pages around the current one, clamped so it never overlaps the boundaries.\n const siblingsStart = Math.max(\n Math.min(page - siblingCount, count - boundaryCount - siblingCount * 2 - 1),\n boundaryCount + 2,\n )\n const siblingsEnd = Math.min(\n Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2),\n endPages.length > 0 ? endPages[0] - 2 : count - 1,\n )\n\n return [\n ...startPages,\n // A start ellipsis, OR the single page that sits between the start boundary and the siblings.\n ...(siblingsStart > boundaryCount + 2\n ? (['start-ellipsis'] as PaginationItem[])\n : boundaryCount + 1 < count - boundaryCount\n ? [boundaryCount + 1]\n : []),\n ...range(siblingsStart, siblingsEnd),\n // An end ellipsis, OR the single page between the siblings and the end boundary.\n ...(siblingsEnd < count - boundaryCount - 1\n ? (['end-ellipsis'] as PaginationItem[])\n : count - boundaryCount > boundaryCount\n ? [count - boundaryCount]\n : []),\n ...endPages,\n ]\n}\n","import {\n forwardRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { Icon, type IconName } from '../Icon'\nimport { useT, type ThemeColor } from '../../theme'\nimport { paginationRange } from './paginationRange'\nimport styles from './Pagination.module.css'\n\nexport type PaginationVariant = 'outlined' | 'text'\nexport type PaginationSize = 'sm' | 'md' | 'lg'\n\nexport interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, 'color' | 'onChange'> {\n /** Total number of pages (required). From a row count, pass `Math.ceil(total / pageSize)`. */\n count: number\n /** Controlled current page (1-based). */\n page?: number\n /** Initial page for uncontrolled use (1-based). Defaults to `1`. */\n defaultPage?: number\n /** Fires with the next page (1-based) when a page or arrow is activated. */\n onChange?: (page: number) => void\n /** Pages shown on each side of the current page. Defaults to `1`. */\n siblingCount?: number\n /** Pages always shown at the start and end. Defaults to `1`. */\n boundaryCount?: number\n /** Show a jump-to-first-page button before the previous arrow. Defaults to `false`. */\n showFirstButton?: boolean\n /** Show a jump-to-last-page button after the next arrow. Defaults to `false`. */\n showLastButton?: boolean\n /** Hide the previous-page arrow. Defaults to `false`. */\n hidePrevButton?: boolean\n /** Hide the next-page arrow. Defaults to `false`. */\n hideNextButton?: boolean\n /** Item style: `outlined` (bordered boxes, default) or `text` (borderless). */\n variant?: PaginationVariant\n /** Control size — sets the box, font, and icon sizes. Defaults to `md`. */\n size?: PaginationSize\n /** Theme palette token that tints the selected page. Defaults to `accent`. */\n color?: ThemeColor\n /** Render circular page buttons instead of rounded rectangles. Defaults to `false`. */\n rounded?: boolean\n /** Disable the whole control. Defaults to `false`. */\n disabled?: boolean\n}\n\nconst clamp = (n: number, lo: number, hi: number) => Math.min(Math.max(n, lo), hi)\n\n/**\n * A page navigator — previous/next arrows around a numbered range with `…` gaps (`1 … 4 5 6 … 10`),\n * the classic pager. Reusable across tables, lists, and galleries: drive it with `count` (total\n * pages) + `page`/`onChange`, computing `count` as `Math.ceil(total / pageSize)`. The selected page\n * is tinted via the shared `--tz-btn-rgb` pattern; unselected items are bordered (`outlined`) or\n * borderless (`text`). Controlled (`page` + `onChange`) or uncontrolled (`defaultPage`).\n */\nexport const Pagination = forwardRef<HTMLElement, PaginationProps>(function Pagination(\n {\n count,\n page,\n defaultPage = 1,\n onChange,\n siblingCount = 1,\n boundaryCount = 1,\n showFirstButton = false,\n showLastButton = false,\n hidePrevButton = false,\n hideNextButton = false,\n variant = 'outlined',\n size = 'md',\n color = 'accent',\n rounded = false,\n disabled = false,\n className,\n style,\n 'aria-label': ariaLabel = 'Pagination',\n ...props\n },\n ref,\n) {\n const isControlled = page !== undefined\n const [internal, setInternal] = useState(defaultPage)\n const lastPage = Math.max(count, 1)\n const current = clamp(isControlled ? page! : internal, 1, lastPage)\n\n const go = (next: number) => {\n const target = clamp(next, 1, lastPage)\n if (target === current) return\n if (!isControlled) setInternal(target)\n onChange?.(target)\n }\n\n const t = useT()\n const items = paginationRange({ count, page: current, siblingCount, boundaryCount })\n\n // The selected fill + its readable text color, derived once via the shared button-tint vars.\n const rootStyle = {\n '--tz-btn-rgb': `var(--tz-color-${color}-rgb)`,\n '--tz-btn-on': `var(--tz-color-${color}-contrast, #fff)`,\n ...style,\n } as CSSProperties\n\n // An arrow / jump control. `flip` mirrors the (left-pointing) icon to face right — the icon set has\n // no matching plain right arrow, so the next/last glyphs are the left ones flipped for symmetry.\n const control = (\n key: string,\n icon: IconName,\n label: string,\n target: number,\n hidden: boolean,\n atBound: boolean,\n flip = false,\n ): ReactNode =>\n hidden ? null : (\n <li key={key} className={styles.item}>\n <button\n type=\"button\"\n className={clsx(styles.page, styles.arrow)}\n aria-label={label}\n disabled={disabled || atBound}\n onClick={() => go(target)}\n >\n <Icon name={icon} size={size} className={flip ? styles.flip : undefined} />\n </button>\n </li>\n )\n\n return (\n <nav\n ref={ref}\n aria-label={ariaLabel}\n className={clsx(\n styles.pagination,\n styles[variant],\n styles[size],\n rounded && styles.rounded,\n className,\n )}\n style={rootStyle}\n {...props}\n >\n <ul className={styles.list}>\n {showFirstButton &&\n control('first', 'Previous', t('pagination.first'), 1, false, current <= 1)}\n {control(\n 'prev',\n 'ArrowLeft',\n t('pagination.previous'),\n current - 1,\n hidePrevButton,\n current <= 1,\n )}\n {items.map((item, i) =>\n typeof item === 'number' ? (\n <li key={item} className={styles.item}>\n <button\n type=\"button\"\n className={clsx(styles.page, item === current && styles.selected)}\n aria-label={t('pagination.page', { page: item })}\n aria-current={item === current ? 'page' : undefined}\n disabled={disabled}\n onClick={() => go(item)}\n >\n {item}\n </button>\n </li>\n ) : (\n <li key={`${item}-${i}`} className={styles.item} aria-hidden>\n <span className={styles.ellipsis}>…</span>\n </li>\n ),\n )}\n {control(\n 'next',\n 'ArrowLeft',\n t('pagination.next'),\n current + 1,\n hideNextButton,\n current >= count,\n true,\n )}\n {showLastButton &&\n control('last', 'Next', t('pagination.last'), count, false, current >= count)}\n </ul>\n </nav>\n )\n})\n"],"names":["range","start","end","_","i","paginationRange","count","page","siblingCount","boundaryCount","startPages","endPages","siblingsStart","siblingsEnd","clamp","n","lo","hi","Pagination","forwardRef","defaultPage","onChange","showFirstButton","showLastButton","hidePrevButton","hideNextButton","variant","size","color","rounded","disabled","className","style","ariaLabel","props","ref","isControlled","internal","setInternal","useState","lastPage","current","go","next","target","t","useT","items","rootStyle","control","key","icon","label","hidden","atBound","flip","jsx","styles","clsx","Icon","jsxs","item"],"mappings":"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"}
1
+ {"version":3,"file":"Pagination-CmskZjcz.js","sources":["../src/components/Pagination/paginationRange.ts","../src/components/Pagination/Pagination.tsx"],"sourcesContent":["/** A gap placeholder rendered as `…` — at the start (`1 … 4`) or end (`6 … 10`) of the range. */\nexport type PaginationEllipsis = 'start-ellipsis' | 'end-ellipsis'\n\n/** One item in a pagination range: a 1-based page number, or an ellipsis placeholder. */\nexport type PaginationItem = number | PaginationEllipsis\n\n/** Inputs for {@link paginationRange}. */\nexport interface PaginationRangeOptions {\n /** Total number of pages. */\n count: number\n /** Current page (1-based). */\n page: number\n /** Pages shown on each side of the current page. Defaults to `1`. */\n siblingCount?: number\n /** Pages always shown at the start and end. Defaults to `1`. */\n boundaryCount?: number\n}\n\n/** Inclusive integer range `[start, end]` (empty when `end < start`). */\nconst range = (start: number, end: number): number[] =>\n Array.from({ length: Math.max(end - start + 1, 0) }, (_, i) => start + i)\n\n/**\n * Build the page-item sequence for a pager — the boundary pages, the current page with its siblings,\n * and `start`/`end` ellipses where pages are skipped (the classic `1 … 4 5 6 … 10`). Pure and\n * framework-free so it can be unit-tested in isolation and reused. Assumes `1 <= page <= count`.\n */\nexport function paginationRange({\n count,\n page,\n siblingCount = 1,\n boundaryCount = 1,\n}: PaginationRangeOptions): PaginationItem[] {\n if (count <= 0) return []\n\n // Pages pinned at each edge.\n const startPages = range(1, Math.min(boundaryCount, count))\n const endPages = range(Math.max(count - boundaryCount + 1, boundaryCount + 1), count)\n\n // The window of pages around the current one, clamped so it never overlaps the boundaries.\n const siblingsStart = Math.max(\n Math.min(page - siblingCount, count - boundaryCount - siblingCount * 2 - 1),\n boundaryCount + 2,\n )\n const siblingsEnd = Math.min(\n Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2),\n endPages.length > 0 ? endPages[0] - 2 : count - 1,\n )\n\n return [\n ...startPages,\n // A start ellipsis, OR the single page that sits between the start boundary and the siblings.\n ...(siblingsStart > boundaryCount + 2\n ? (['start-ellipsis'] as PaginationItem[])\n : boundaryCount + 1 < count - boundaryCount\n ? [boundaryCount + 1]\n : []),\n ...range(siblingsStart, siblingsEnd),\n // An end ellipsis, OR the single page between the siblings and the end boundary.\n ...(siblingsEnd < count - boundaryCount - 1\n ? (['end-ellipsis'] as PaginationItem[])\n : count - boundaryCount > boundaryCount\n ? [count - boundaryCount]\n : []),\n ...endPages,\n ]\n}\n","import {\n forwardRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { Icon, type IconName } from '../Icon'\nimport { useT, type ThemeColor } from '../../theme'\nimport { paginationRange } from './paginationRange'\nimport styles from './Pagination.module.css'\n\nexport type PaginationVariant = 'outlined' | 'text'\nexport type PaginationSize = 'sm' | 'md' | 'lg'\n\nexport interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, 'color' | 'onChange'> {\n /** Total number of pages (required). From a row count, pass `Math.ceil(total / pageSize)`. */\n count: number\n /** Controlled current page (1-based). */\n page?: number\n /** Initial page for uncontrolled use (1-based). Defaults to `1`. */\n defaultPage?: number\n /** Fires with the next page (1-based) when a page or arrow is activated. */\n onChange?: (page: number) => void\n /** Pages shown on each side of the current page. Defaults to `1`. */\n siblingCount?: number\n /** Pages always shown at the start and end. Defaults to `1`. */\n boundaryCount?: number\n /** Show a jump-to-first-page button before the previous arrow. Defaults to `false`. */\n showFirstButton?: boolean\n /** Show a jump-to-last-page button after the next arrow. Defaults to `false`. */\n showLastButton?: boolean\n /** Hide the previous-page arrow. Defaults to `false`. */\n hidePrevButton?: boolean\n /** Hide the next-page arrow. Defaults to `false`. */\n hideNextButton?: boolean\n /** Item style: `outlined` (bordered boxes, default) or `text` (borderless). */\n variant?: PaginationVariant\n /** Control size — sets the box, font, and icon sizes. Defaults to `md`. */\n size?: PaginationSize\n /** Theme palette token that tints the selected page. Defaults to `accent`. */\n color?: ThemeColor\n /** Render circular page buttons instead of rounded rectangles. Defaults to `false`. */\n rounded?: boolean\n /** Disable the whole control. Defaults to `false`. */\n disabled?: boolean\n}\n\nconst clamp = (n: number, lo: number, hi: number) => Math.min(Math.max(n, lo), hi)\n\n/**\n * A page navigator — previous/next arrows around a numbered range with `…` gaps (`1 … 4 5 6 … 10`),\n * the classic pager. Reusable across tables, lists, and galleries: drive it with `count` (total\n * pages) + `page`/`onChange`, computing `count` as `Math.ceil(total / pageSize)`. The selected page\n * is tinted via the shared `--tz-btn-rgb` pattern; unselected items are bordered (`outlined`) or\n * borderless (`text`). Controlled (`page` + `onChange`) or uncontrolled (`defaultPage`).\n */\nexport const Pagination = forwardRef<HTMLElement, PaginationProps>(function Pagination(\n {\n count,\n page,\n defaultPage = 1,\n onChange,\n siblingCount = 1,\n boundaryCount = 1,\n showFirstButton = false,\n showLastButton = false,\n hidePrevButton = false,\n hideNextButton = false,\n variant = 'outlined',\n size = 'md',\n color = 'accent',\n rounded = false,\n disabled = false,\n className,\n style,\n 'aria-label': ariaLabel = 'Pagination',\n ...props\n },\n ref,\n) {\n const isControlled = page !== undefined\n const [internal, setInternal] = useState(defaultPage)\n const lastPage = Math.max(count, 1)\n const current = clamp(isControlled ? page! : internal, 1, lastPage)\n\n const go = (next: number) => {\n const target = clamp(next, 1, lastPage)\n if (target === current) return\n if (!isControlled) setInternal(target)\n onChange?.(target)\n }\n\n const t = useT()\n const items = paginationRange({ count, page: current, siblingCount, boundaryCount })\n\n // The selected fill + its readable text color, derived once via the shared button-tint vars.\n const rootStyle = {\n '--tz-btn-rgb': `var(--tz-color-${color}-rgb)`,\n '--tz-btn-on': `var(--tz-color-${color}-contrast, #fff)`,\n ...style,\n } as CSSProperties\n\n // An arrow / jump control. `flip` mirrors the (left-pointing) icon to face right — the icon set has\n // no matching plain right arrow, so the next/last glyphs are the left ones flipped for symmetry.\n const control = (\n key: string,\n icon: IconName,\n label: string,\n target: number,\n hidden: boolean,\n atBound: boolean,\n flip = false,\n ): ReactNode =>\n hidden ? null : (\n <li key={key} className={styles.item}>\n <button\n type=\"button\"\n className={clsx(styles.page, styles.arrow)}\n aria-label={label}\n disabled={disabled || atBound}\n onClick={() => go(target)}\n >\n <Icon name={icon} size={size} className={flip ? styles.flip : undefined} />\n </button>\n </li>\n )\n\n return (\n <nav\n ref={ref}\n aria-label={ariaLabel}\n className={clsx(\n styles.pagination,\n styles[variant],\n styles[size],\n rounded && styles.rounded,\n className,\n )}\n style={rootStyle}\n {...props}\n >\n <ul className={styles.list}>\n {showFirstButton &&\n control('first', 'Previous', t('pagination.first'), 1, false, current <= 1)}\n {control(\n 'prev',\n 'ArrowLeft',\n t('pagination.previous'),\n current - 1,\n hidePrevButton,\n current <= 1,\n )}\n {items.map((item, i) =>\n typeof item === 'number' ? (\n <li key={item} className={styles.item}>\n <button\n type=\"button\"\n className={clsx(styles.page, item === current && styles.selected)}\n aria-label={t('pagination.page', { page: item })}\n aria-current={item === current ? 'page' : undefined}\n disabled={disabled}\n onClick={() => go(item)}\n >\n {item}\n </button>\n </li>\n ) : (\n <li key={`${item}-${i}`} className={styles.item} aria-hidden>\n <span className={styles.ellipsis}>…</span>\n </li>\n ),\n )}\n {control(\n 'next',\n 'ArrowLeft',\n t('pagination.next'),\n current + 1,\n hideNextButton,\n current >= count,\n true,\n )}\n {showLastButton &&\n control('last', 'Next', t('pagination.last'), count, false, current >= count)}\n </ul>\n </nav>\n )\n})\n"],"names":["range","start","end","_","i","paginationRange","count","page","siblingCount","boundaryCount","startPages","endPages","siblingsStart","siblingsEnd","clamp","n","lo","hi","Pagination","forwardRef","defaultPage","onChange","showFirstButton","showLastButton","hidePrevButton","hideNextButton","variant","size","color","rounded","disabled","className","style","ariaLabel","props","ref","isControlled","internal","setInternal","useState","lastPage","current","go","next","target","t","useT","items","rootStyle","control","key","icon","label","hidden","atBound","flip","jsx","styles","clsx","Icon","jsxs","item"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { jsx as e, jsxs as a, Fragment as b } from "react/jsx-runtime";
2
2
  import { forwardRef as v, useState as B } from "react";
3
- import { B as s } from "./Button-Cfxd7qhd.js";
3
+ import { B as s } from "./Button-DBs8xnA5.js";
4
4
  import { I as _ } from "./Icon-DaTvzLBu.js";
5
- import { M as C } from "./Modal-Cx0JEQ-j.js";
5
+ import { M as C } from "./Modal-B7yoFC3o.js";
6
6
  import { T as D } from "./Typography-Cta6Rg4L.js";
7
- import { a as R } from "./ConfigProvider-Blhvj6UQ.js";
7
+ import { a as R } from "./ConfigProvider-DR9YMy9U.js";
8
8
  const T = "_body_1xrr0_3", k = "_iconBox_1xrr0_13", c = {
9
9
  body: T,
10
10
  iconBox: k
@@ -44,4 +44,4 @@ const T = "_body_1xrr0_3", k = "_iconBox_1xrr0_13", c = {
44
44
  export {
45
45
  E as R
46
46
  };
47
- //# sourceMappingURL=RemoveDialog-BpL2-gnz.js.map
47
+ //# sourceMappingURL=RemoveDialog-CV75B0aN.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RemoveDialog-BpL2-gnz.js","sources":["../src/components/RemoveDialog/RemoveDialog.tsx"],"sourcesContent":["import { forwardRef, useState, type ReactNode } from 'react'\nimport { useT } from '../../theme'\nimport { Button } from '../Button'\nimport { Icon } from '../Icon'\nimport { Modal } from '../Modal'\nimport { Typography } from '../Typography'\nimport styles from './RemoveDialog.module.css'\n\nexport interface RemoveDialogProps {\n /** Whether the dialog is open. */\n open: boolean\n /** Called on Cancel, the × button, backdrop, or Escape (ignored while a confirm is in flight). */\n onClose: () => void\n /**\n * The destructive action. May be async — while its promise is pending the Delete button shows a\n * loader and the dialog locks (no dismiss); on success the dialog **auto-closes**, on rejection it\n * stays open so the user can retry (surface the error yourself, e.g. a toast).\n */\n onConfirm: () => void | Promise<void>\n /** Header title. Defaults to `\"Remove\"`. */\n title?: ReactNode\n /** Body prompt shown under the icon. Defaults to `\"Are you sure you want to delete?\"`. */\n message?: ReactNode\n /** Confirm (destructive) button label. Defaults to `\"Delete\"`. */\n confirmLabel?: string\n /** Cancel button label. Defaults to `\"Cancel\"`. */\n cancelLabel?: string\n /** External loading override — combined with the internal async-confirm state. */\n loading?: boolean\n}\n\n/**\n * A ready-made delete confirmation — a thin convenience wrapper over `Modal` for the ubiquitous\n * \"Are you sure you want to delete?\" prompt. Hardcodes the destructive flavor (a `Trash` glyph in a\n * soft error circle + an `error` Delete button); just wire `open` / `onClose` / `onConfirm`. An async\n * `onConfirm` drives the button loader and locks dismissal, then auto-closes on success. Built on\n * `Modal`, so it inherits the portal, scroll-lock, focus-trap, and backdrop/Escape dismissal.\n *\n * @example\n * const { isOpen, open, close } = useDisclosure()\n * <RemoveDialog open={isOpen} onClose={close} onConfirm={() => deleteItem(id)} />\n */\nexport const RemoveDialog = forwardRef<HTMLDivElement, RemoveDialogProps>(function RemoveDialog(\n { open, onClose, onConfirm, title, message, confirmLabel, cancelLabel, loading = false },\n ref,\n) {\n const t = useT()\n const [submitting, setSubmitting] = useState(false)\n const busy = loading || submitting\n\n // dismissal is blocked while the confirm is running (so the delete can't be abandoned mid-flight)\n const handleClose = () => {\n if (!busy) onClose()\n }\n\n const handleConfirm = async () => {\n try {\n setSubmitting(true)\n await onConfirm()\n onClose() // auto-close on success\n } catch {\n // keep the dialog open on failure so the user can retry; the consumer surfaces the error\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <Modal\n ref={ref}\n open={open}\n onClose={handleClose}\n size=\"sm\"\n title={title ?? t('removeDialog.title')}\n showCloseButton={!busy}\n closeOnBackdrop={!busy}\n closeOnEscape={!busy}\n footer={\n <>\n <Button variant=\"text\" onClick={handleClose} disabled={busy}>\n {cancelLabel ?? t('common.cancel')}\n </Button>\n <Button color=\"error\" variant=\"filled\" onClick={handleConfirm} loading={busy}>\n {confirmLabel ?? t('common.delete')}\n </Button>\n </>\n }\n >\n <div className={styles.body}>\n <div className={styles.iconBox} aria-hidden>\n <Icon name=\"Trash\" />\n </div>\n <Typography align=\"center\">{message ?? t('removeDialog.message')}</Typography>\n </div>\n </Modal>\n )\n})\n"],"names":["RemoveDialog","forwardRef","open","onClose","onConfirm","title","message","confirmLabel","cancelLabel","loading","ref","t","useT","submitting","setSubmitting","useState","busy","handleClose","handleConfirm","jsx","Modal","jsxs","Fragment","Button","styles","Icon","Typography"],"mappings":";;;;;;;;;;GA0CaA,IAAeC,EAA8C,SACxE,EAAE,MAAAC,GAAM,SAAAC,GAAS,WAAAC,GAAW,OAAAC,GAAO,SAAAC,GAAS,cAAAC,GAAc,aAAAC,GAAa,SAAAC,IAAU,GAAA,GACjFC,GACA;AACA,QAAMC,IAAIC,EAAA,GACJ,CAACC,GAAYC,CAAa,IAAIC,EAAS,EAAK,GAC5CC,IAAOP,KAAWI,GAGlBI,IAAc,MAAM;AACxB,IAAKD,KAAMb,EAAA;AAAA,EACb,GAEMe,IAAgB,YAAY;AAChC,QAAI;AACF,MAAAJ,EAAc,EAAI,GAClB,MAAMV,EAAA,GACND,EAAA;AAAA,IACF,QAAQ;AAAA,IAER,UAAA;AACE,MAAAW,EAAc,EAAK;AAAA,IACrB;AAAA,EACF;AAEA,SACE,gBAAAK;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,KAAAV;AAAA,MACA,MAAAR;AAAA,MACA,SAASe;AAAA,MACT,MAAK;AAAA,MACL,OAAOZ,KAASM,EAAE,oBAAoB;AAAA,MACtC,iBAAiB,CAACK;AAAA,MAClB,iBAAiB,CAACA;AAAA,MAClB,eAAe,CAACA;AAAA,MAChB,QACE,gBAAAK,EAAAC,GAAA,EACE,UAAA;AAAA,QAAA,gBAAAH,EAACI,GAAA,EAAO,SAAQ,QAAO,SAASN,GAAa,UAAUD,GACpD,UAAAR,KAAeG,EAAE,eAAe,EAAA,CACnC;AAAA,QACA,gBAAAQ,EAACI,GAAA,EAAO,OAAM,SAAQ,SAAQ,UAAS,SAASL,GAAe,SAASF,GACrE,UAAAT,KAAgBI,EAAE,eAAe,EAAA,CACpC;AAAA,MAAA,GACF;AAAA,MAGF,UAAA,gBAAAU,EAAC,OAAA,EAAI,WAAWG,EAAO,MACrB,UAAA;AAAA,QAAA,gBAAAL,EAAC,OAAA,EAAI,WAAWK,EAAO,SAAS,eAAW,IACzC,UAAA,gBAAAL,EAACM,GAAA,EAAK,MAAK,QAAA,CAAQ,EAAA,CACrB;AAAA,0BACCC,GAAA,EAAW,OAAM,UAAU,UAAApB,KAAWK,EAAE,sBAAsB,EAAA,CAAE;AAAA,MAAA,EAAA,CACnE;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;"}
1
+ {"version":3,"file":"RemoveDialog-CV75B0aN.js","sources":["../src/components/RemoveDialog/RemoveDialog.tsx"],"sourcesContent":["import { forwardRef, useState, type ReactNode } from 'react'\nimport { useT } from '../../theme'\nimport { Button } from '../Button'\nimport { Icon } from '../Icon'\nimport { Modal } from '../Modal'\nimport { Typography } from '../Typography'\nimport styles from './RemoveDialog.module.css'\n\nexport interface RemoveDialogProps {\n /** Whether the dialog is open. */\n open: boolean\n /** Called on Cancel, the × button, backdrop, or Escape (ignored while a confirm is in flight). */\n onClose: () => void\n /**\n * The destructive action. May be async — while its promise is pending the Delete button shows a\n * loader and the dialog locks (no dismiss); on success the dialog **auto-closes**, on rejection it\n * stays open so the user can retry (surface the error yourself, e.g. a toast).\n */\n onConfirm: () => void | Promise<void>\n /** Header title. Defaults to `\"Remove\"`. */\n title?: ReactNode\n /** Body prompt shown under the icon. Defaults to `\"Are you sure you want to delete?\"`. */\n message?: ReactNode\n /** Confirm (destructive) button label. Defaults to `\"Delete\"`. */\n confirmLabel?: string\n /** Cancel button label. Defaults to `\"Cancel\"`. */\n cancelLabel?: string\n /** External loading override — combined with the internal async-confirm state. */\n loading?: boolean\n}\n\n/**\n * A ready-made delete confirmation — a thin convenience wrapper over `Modal` for the ubiquitous\n * \"Are you sure you want to delete?\" prompt. Hardcodes the destructive flavor (a `Trash` glyph in a\n * soft error circle + an `error` Delete button); just wire `open` / `onClose` / `onConfirm`. An async\n * `onConfirm` drives the button loader and locks dismissal, then auto-closes on success. Built on\n * `Modal`, so it inherits the portal, scroll-lock, focus-trap, and backdrop/Escape dismissal.\n *\n * @example\n * const { isOpen, open, close } = useDisclosure()\n * <RemoveDialog open={isOpen} onClose={close} onConfirm={() => deleteItem(id)} />\n */\nexport const RemoveDialog = forwardRef<HTMLDivElement, RemoveDialogProps>(function RemoveDialog(\n { open, onClose, onConfirm, title, message, confirmLabel, cancelLabel, loading = false },\n ref,\n) {\n const t = useT()\n const [submitting, setSubmitting] = useState(false)\n const busy = loading || submitting\n\n // dismissal is blocked while the confirm is running (so the delete can't be abandoned mid-flight)\n const handleClose = () => {\n if (!busy) onClose()\n }\n\n const handleConfirm = async () => {\n try {\n setSubmitting(true)\n await onConfirm()\n onClose() // auto-close on success\n } catch {\n // keep the dialog open on failure so the user can retry; the consumer surfaces the error\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <Modal\n ref={ref}\n open={open}\n onClose={handleClose}\n size=\"sm\"\n title={title ?? t('removeDialog.title')}\n showCloseButton={!busy}\n closeOnBackdrop={!busy}\n closeOnEscape={!busy}\n footer={\n <>\n <Button variant=\"text\" onClick={handleClose} disabled={busy}>\n {cancelLabel ?? t('common.cancel')}\n </Button>\n <Button color=\"error\" variant=\"filled\" onClick={handleConfirm} loading={busy}>\n {confirmLabel ?? t('common.delete')}\n </Button>\n </>\n }\n >\n <div className={styles.body}>\n <div className={styles.iconBox} aria-hidden>\n <Icon name=\"Trash\" />\n </div>\n <Typography align=\"center\">{message ?? t('removeDialog.message')}</Typography>\n </div>\n </Modal>\n )\n})\n"],"names":["RemoveDialog","forwardRef","open","onClose","onConfirm","title","message","confirmLabel","cancelLabel","loading","ref","t","useT","submitting","setSubmitting","useState","busy","handleClose","handleConfirm","jsx","Modal","jsxs","Fragment","Button","styles","Icon","Typography"],"mappings":";;;;;;;;;;GA0CaA,IAAeC,EAA8C,SACxE,EAAE,MAAAC,GAAM,SAAAC,GAAS,WAAAC,GAAW,OAAAC,GAAO,SAAAC,GAAS,cAAAC,GAAc,aAAAC,GAAa,SAAAC,IAAU,GAAA,GACjFC,GACA;AACA,QAAMC,IAAIC,EAAA,GACJ,CAACC,GAAYC,CAAa,IAAIC,EAAS,EAAK,GAC5CC,IAAOP,KAAWI,GAGlBI,IAAc,MAAM;AACxB,IAAKD,KAAMb,EAAA;AAAA,EACb,GAEMe,IAAgB,YAAY;AAChC,QAAI;AACF,MAAAJ,EAAc,EAAI,GAClB,MAAMV,EAAA,GACND,EAAA;AAAA,IACF,QAAQ;AAAA,IAER,UAAA;AACE,MAAAW,EAAc,EAAK;AAAA,IACrB;AAAA,EACF;AAEA,SACE,gBAAAK;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,KAAAV;AAAA,MACA,MAAAR;AAAA,MACA,SAASe;AAAA,MACT,MAAK;AAAA,MACL,OAAOZ,KAASM,EAAE,oBAAoB;AAAA,MACtC,iBAAiB,CAACK;AAAA,MAClB,iBAAiB,CAACA;AAAA,MAClB,eAAe,CAACA;AAAA,MAChB,QACE,gBAAAK,EAAAC,GAAA,EACE,UAAA;AAAA,QAAA,gBAAAH,EAACI,GAAA,EAAO,SAAQ,QAAO,SAASN,GAAa,UAAUD,GACpD,UAAAR,KAAeG,EAAE,eAAe,EAAA,CACnC;AAAA,QACA,gBAAAQ,EAACI,GAAA,EAAO,OAAM,SAAQ,SAAQ,UAAS,SAASL,GAAe,SAASF,GACrE,UAAAT,KAAgBI,EAAE,eAAe,EAAA,CACpC;AAAA,MAAA,GACF;AAAA,MAGF,UAAA,gBAAAU,EAAC,OAAA,EAAI,WAAWG,EAAO,MACrB,UAAA;AAAA,QAAA,gBAAAL,EAAC,OAAA,EAAI,WAAWK,EAAO,SAAS,eAAW,IACzC,UAAA,gBAAAL,EAACM,GAAA,EAAK,MAAK,QAAA,CAAQ,EAAA,CACrB;AAAA,0BACCC,GAAA,EAAW,OAAM,UAAU,UAAApB,KAAWK,EAAE,sBAAsB,EAAA,CAAE;AAAA,MAAA,EAAA,CACnE;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;"}
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("react/jsx-runtime"),i=require("react"),c=require("./Button-ZplrHYKw.cjs"),j=require("./Icon-BVULqOJD.cjs"),B=require("./Modal-DXZdMmJh.cjs"),b=require("./Typography-BFatE1_A.cjs"),q=require("./ConfigProvider-CUG8Mfy2.cjs"),p="_body_1xrr0_3",C="_iconBox_1xrr0_13",a={body:p,iconBox:C},_=i.forwardRef(function({open:l,onClose:s,onConfirm:d,title:u,message:m,confirmLabel:x,cancelLabel:h,loading:g=!1},y){const n=q.useT(),[f,t]=i.useState(!1),o=g||f,r=()=>{o||s()},v=async()=>{try{t(!0),await d(),s()}catch{}finally{t(!1)}};return e.jsx(B.Modal,{ref:y,open:l,onClose:r,size:"sm",title:u??n("removeDialog.title"),showCloseButton:!o,closeOnBackdrop:!o,closeOnEscape:!o,footer:e.jsxs(e.Fragment,{children:[e.jsx(c.Button,{variant:"text",onClick:r,disabled:o,children:h??n("common.cancel")}),e.jsx(c.Button,{color:"error",variant:"filled",onClick:v,loading:o,children:x??n("common.delete")})]}),children:e.jsxs("div",{className:a.body,children:[e.jsx("div",{className:a.iconBox,"aria-hidden":!0,children:e.jsx(j.Icon,{name:"Trash"})}),e.jsx(b.Typography,{align:"center",children:m??n("removeDialog.message")})]})})});exports.RemoveDialog=_;
2
- //# sourceMappingURL=RemoveDialog-DGt_72we.cjs.map
1
+ "use strict";const e=require("react/jsx-runtime"),i=require("react"),c=require("./Button-CXmDOzPk.cjs"),j=require("./Icon-BVULqOJD.cjs"),B=require("./Modal-0V-REVV-.cjs"),b=require("./Typography-BFatE1_A.cjs"),q=require("./ConfigProvider-Bszl3Wr3.cjs"),p="_body_1xrr0_3",C="_iconBox_1xrr0_13",a={body:p,iconBox:C},_=i.forwardRef(function({open:l,onClose:s,onConfirm:d,title:u,message:m,confirmLabel:x,cancelLabel:h,loading:g=!1},y){const n=q.useT(),[f,t]=i.useState(!1),o=g||f,r=()=>{o||s()},v=async()=>{try{t(!0),await d(),s()}catch{}finally{t(!1)}};return e.jsx(B.Modal,{ref:y,open:l,onClose:r,size:"sm",title:u??n("removeDialog.title"),showCloseButton:!o,closeOnBackdrop:!o,closeOnEscape:!o,footer:e.jsxs(e.Fragment,{children:[e.jsx(c.Button,{variant:"text",onClick:r,disabled:o,children:h??n("common.cancel")}),e.jsx(c.Button,{color:"error",variant:"filled",onClick:v,loading:o,children:x??n("common.delete")})]}),children:e.jsxs("div",{className:a.body,children:[e.jsx("div",{className:a.iconBox,"aria-hidden":!0,children:e.jsx(j.Icon,{name:"Trash"})}),e.jsx(b.Typography,{align:"center",children:m??n("removeDialog.message")})]})})});exports.RemoveDialog=_;
2
+ //# sourceMappingURL=RemoveDialog-DmOk0ezc.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"RemoveDialog-DGt_72we.cjs","sources":["../src/components/RemoveDialog/RemoveDialog.tsx"],"sourcesContent":["import { forwardRef, useState, type ReactNode } from 'react'\nimport { useT } from '../../theme'\nimport { Button } from '../Button'\nimport { Icon } from '../Icon'\nimport { Modal } from '../Modal'\nimport { Typography } from '../Typography'\nimport styles from './RemoveDialog.module.css'\n\nexport interface RemoveDialogProps {\n /** Whether the dialog is open. */\n open: boolean\n /** Called on Cancel, the × button, backdrop, or Escape (ignored while a confirm is in flight). */\n onClose: () => void\n /**\n * The destructive action. May be async — while its promise is pending the Delete button shows a\n * loader and the dialog locks (no dismiss); on success the dialog **auto-closes**, on rejection it\n * stays open so the user can retry (surface the error yourself, e.g. a toast).\n */\n onConfirm: () => void | Promise<void>\n /** Header title. Defaults to `\"Remove\"`. */\n title?: ReactNode\n /** Body prompt shown under the icon. Defaults to `\"Are you sure you want to delete?\"`. */\n message?: ReactNode\n /** Confirm (destructive) button label. Defaults to `\"Delete\"`. */\n confirmLabel?: string\n /** Cancel button label. Defaults to `\"Cancel\"`. */\n cancelLabel?: string\n /** External loading override — combined with the internal async-confirm state. */\n loading?: boolean\n}\n\n/**\n * A ready-made delete confirmation — a thin convenience wrapper over `Modal` for the ubiquitous\n * \"Are you sure you want to delete?\" prompt. Hardcodes the destructive flavor (a `Trash` glyph in a\n * soft error circle + an `error` Delete button); just wire `open` / `onClose` / `onConfirm`. An async\n * `onConfirm` drives the button loader and locks dismissal, then auto-closes on success. Built on\n * `Modal`, so it inherits the portal, scroll-lock, focus-trap, and backdrop/Escape dismissal.\n *\n * @example\n * const { isOpen, open, close } = useDisclosure()\n * <RemoveDialog open={isOpen} onClose={close} onConfirm={() => deleteItem(id)} />\n */\nexport const RemoveDialog = forwardRef<HTMLDivElement, RemoveDialogProps>(function RemoveDialog(\n { open, onClose, onConfirm, title, message, confirmLabel, cancelLabel, loading = false },\n ref,\n) {\n const t = useT()\n const [submitting, setSubmitting] = useState(false)\n const busy = loading || submitting\n\n // dismissal is blocked while the confirm is running (so the delete can't be abandoned mid-flight)\n const handleClose = () => {\n if (!busy) onClose()\n }\n\n const handleConfirm = async () => {\n try {\n setSubmitting(true)\n await onConfirm()\n onClose() // auto-close on success\n } catch {\n // keep the dialog open on failure so the user can retry; the consumer surfaces the error\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <Modal\n ref={ref}\n open={open}\n onClose={handleClose}\n size=\"sm\"\n title={title ?? t('removeDialog.title')}\n showCloseButton={!busy}\n closeOnBackdrop={!busy}\n closeOnEscape={!busy}\n footer={\n <>\n <Button variant=\"text\" onClick={handleClose} disabled={busy}>\n {cancelLabel ?? t('common.cancel')}\n </Button>\n <Button color=\"error\" variant=\"filled\" onClick={handleConfirm} loading={busy}>\n {confirmLabel ?? t('common.delete')}\n </Button>\n </>\n }\n >\n <div className={styles.body}>\n <div className={styles.iconBox} aria-hidden>\n <Icon name=\"Trash\" />\n </div>\n <Typography align=\"center\">{message ?? t('removeDialog.message')}</Typography>\n </div>\n </Modal>\n )\n})\n"],"names":["RemoveDialog","forwardRef","open","onClose","onConfirm","title","message","confirmLabel","cancelLabel","loading","ref","t","useT","submitting","setSubmitting","useState","busy","handleClose","handleConfirm","jsx","Modal","jsxs","Fragment","Button","styles","Icon","Typography"],"mappings":"0TA0CaA,EAAeC,EAAAA,WAA8C,SACxE,CAAE,KAAAC,EAAM,QAAAC,EAAS,UAAAC,EAAW,MAAAC,EAAO,QAAAC,EAAS,aAAAC,EAAc,YAAAC,EAAa,QAAAC,EAAU,EAAA,EACjFC,EACA,CACA,MAAMC,EAAIC,EAAAA,KAAA,EACJ,CAACC,EAAYC,CAAa,EAAIC,EAAAA,SAAS,EAAK,EAC5CC,EAAOP,GAAWI,EAGlBI,EAAc,IAAM,CACnBD,GAAMb,EAAA,CACb,EAEMe,EAAgB,SAAY,CAChC,GAAI,CACFJ,EAAc,EAAI,EAClB,MAAMV,EAAA,EACND,EAAA,CACF,MAAQ,CAER,QAAA,CACEW,EAAc,EAAK,CACrB,CACF,EAEA,OACEK,EAAAA,IAACC,EAAAA,MAAA,CACC,IAAAV,EACA,KAAAR,EACA,QAASe,EACT,KAAK,KACL,MAAOZ,GAASM,EAAE,oBAAoB,EACtC,gBAAiB,CAACK,EAClB,gBAAiB,CAACA,EAClB,cAAe,CAACA,EAChB,OACEK,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAH,EAAAA,IAACI,EAAAA,OAAA,CAAO,QAAQ,OAAO,QAASN,EAAa,SAAUD,EACpD,SAAAR,GAAeG,EAAE,eAAe,CAAA,CACnC,EACAQ,EAAAA,IAACI,EAAAA,OAAA,CAAO,MAAM,QAAQ,QAAQ,SAAS,QAASL,EAAe,QAASF,EACrE,SAAAT,GAAgBI,EAAE,eAAe,CAAA,CACpC,CAAA,EACF,EAGF,SAAAU,EAAAA,KAAC,MAAA,CAAI,UAAWG,EAAO,KACrB,SAAA,CAAAL,EAAAA,IAAC,MAAA,CAAI,UAAWK,EAAO,QAAS,cAAW,GACzC,SAAAL,EAAAA,IAACM,EAAAA,KAAA,CAAK,KAAK,OAAA,CAAQ,CAAA,CACrB,QACCC,EAAAA,WAAA,CAAW,MAAM,SAAU,SAAApB,GAAWK,EAAE,sBAAsB,CAAA,CAAE,CAAA,CAAA,CACnE,CAAA,CAAA,CAGN,CAAC"}
1
+ {"version":3,"file":"RemoveDialog-DmOk0ezc.cjs","sources":["../src/components/RemoveDialog/RemoveDialog.tsx"],"sourcesContent":["import { forwardRef, useState, type ReactNode } from 'react'\nimport { useT } from '../../theme'\nimport { Button } from '../Button'\nimport { Icon } from '../Icon'\nimport { Modal } from '../Modal'\nimport { Typography } from '../Typography'\nimport styles from './RemoveDialog.module.css'\n\nexport interface RemoveDialogProps {\n /** Whether the dialog is open. */\n open: boolean\n /** Called on Cancel, the × button, backdrop, or Escape (ignored while a confirm is in flight). */\n onClose: () => void\n /**\n * The destructive action. May be async — while its promise is pending the Delete button shows a\n * loader and the dialog locks (no dismiss); on success the dialog **auto-closes**, on rejection it\n * stays open so the user can retry (surface the error yourself, e.g. a toast).\n */\n onConfirm: () => void | Promise<void>\n /** Header title. Defaults to `\"Remove\"`. */\n title?: ReactNode\n /** Body prompt shown under the icon. Defaults to `\"Are you sure you want to delete?\"`. */\n message?: ReactNode\n /** Confirm (destructive) button label. Defaults to `\"Delete\"`. */\n confirmLabel?: string\n /** Cancel button label. Defaults to `\"Cancel\"`. */\n cancelLabel?: string\n /** External loading override — combined with the internal async-confirm state. */\n loading?: boolean\n}\n\n/**\n * A ready-made delete confirmation — a thin convenience wrapper over `Modal` for the ubiquitous\n * \"Are you sure you want to delete?\" prompt. Hardcodes the destructive flavor (a `Trash` glyph in a\n * soft error circle + an `error` Delete button); just wire `open` / `onClose` / `onConfirm`. An async\n * `onConfirm` drives the button loader and locks dismissal, then auto-closes on success. Built on\n * `Modal`, so it inherits the portal, scroll-lock, focus-trap, and backdrop/Escape dismissal.\n *\n * @example\n * const { isOpen, open, close } = useDisclosure()\n * <RemoveDialog open={isOpen} onClose={close} onConfirm={() => deleteItem(id)} />\n */\nexport const RemoveDialog = forwardRef<HTMLDivElement, RemoveDialogProps>(function RemoveDialog(\n { open, onClose, onConfirm, title, message, confirmLabel, cancelLabel, loading = false },\n ref,\n) {\n const t = useT()\n const [submitting, setSubmitting] = useState(false)\n const busy = loading || submitting\n\n // dismissal is blocked while the confirm is running (so the delete can't be abandoned mid-flight)\n const handleClose = () => {\n if (!busy) onClose()\n }\n\n const handleConfirm = async () => {\n try {\n setSubmitting(true)\n await onConfirm()\n onClose() // auto-close on success\n } catch {\n // keep the dialog open on failure so the user can retry; the consumer surfaces the error\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <Modal\n ref={ref}\n open={open}\n onClose={handleClose}\n size=\"sm\"\n title={title ?? t('removeDialog.title')}\n showCloseButton={!busy}\n closeOnBackdrop={!busy}\n closeOnEscape={!busy}\n footer={\n <>\n <Button variant=\"text\" onClick={handleClose} disabled={busy}>\n {cancelLabel ?? t('common.cancel')}\n </Button>\n <Button color=\"error\" variant=\"filled\" onClick={handleConfirm} loading={busy}>\n {confirmLabel ?? t('common.delete')}\n </Button>\n </>\n }\n >\n <div className={styles.body}>\n <div className={styles.iconBox} aria-hidden>\n <Icon name=\"Trash\" />\n </div>\n <Typography align=\"center\">{message ?? t('removeDialog.message')}</Typography>\n </div>\n </Modal>\n )\n})\n"],"names":["RemoveDialog","forwardRef","open","onClose","onConfirm","title","message","confirmLabel","cancelLabel","loading","ref","t","useT","submitting","setSubmitting","useState","busy","handleClose","handleConfirm","jsx","Modal","jsxs","Fragment","Button","styles","Icon","Typography"],"mappings":"0TA0CaA,EAAeC,EAAAA,WAA8C,SACxE,CAAE,KAAAC,EAAM,QAAAC,EAAS,UAAAC,EAAW,MAAAC,EAAO,QAAAC,EAAS,aAAAC,EAAc,YAAAC,EAAa,QAAAC,EAAU,EAAA,EACjFC,EACA,CACA,MAAMC,EAAIC,EAAAA,KAAA,EACJ,CAACC,EAAYC,CAAa,EAAIC,EAAAA,SAAS,EAAK,EAC5CC,EAAOP,GAAWI,EAGlBI,EAAc,IAAM,CACnBD,GAAMb,EAAA,CACb,EAEMe,EAAgB,SAAY,CAChC,GAAI,CACFJ,EAAc,EAAI,EAClB,MAAMV,EAAA,EACND,EAAA,CACF,MAAQ,CAER,QAAA,CACEW,EAAc,EAAK,CACrB,CACF,EAEA,OACEK,EAAAA,IAACC,EAAAA,MAAA,CACC,IAAAV,EACA,KAAAR,EACA,QAASe,EACT,KAAK,KACL,MAAOZ,GAASM,EAAE,oBAAoB,EACtC,gBAAiB,CAACK,EAClB,gBAAiB,CAACA,EAClB,cAAe,CAACA,EAChB,OACEK,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAH,EAAAA,IAACI,EAAAA,OAAA,CAAO,QAAQ,OAAO,QAASN,EAAa,SAAUD,EACpD,SAAAR,GAAeG,EAAE,eAAe,CAAA,CACnC,EACAQ,EAAAA,IAACI,EAAAA,OAAA,CAAO,MAAM,QAAQ,QAAQ,SAAS,QAASL,EAAe,QAASF,EACrE,SAAAT,GAAgBI,EAAE,eAAe,CAAA,CACpC,CAAA,EACF,EAGF,SAAAU,EAAAA,KAAC,MAAA,CAAI,UAAWG,EAAO,KACrB,SAAA,CAAAL,EAAAA,IAAC,MAAA,CAAI,UAAWK,EAAO,QAAS,cAAW,GACzC,SAAAL,EAAAA,IAACM,EAAAA,KAAA,CAAK,KAAK,OAAA,CAAQ,CAAA,CACrB,QACCC,EAAAA,WAAA,CAAW,MAAM,SAAU,SAAApB,GAAWK,EAAE,sBAAsB,CAAA,CAAE,CAAA,CAAA,CACnE,CAAA,CAAA,CAGN,CAAC"}
@@ -22,17 +22,17 @@ import { T as ve } from "./Typography-Cta6Rg4L.js";
22
22
  import { t as Dt } from "./toastStore-Cx_JOKwS.js";
23
23
  import { $getSelectionStyleValueForProperty as ye, $patchStyleText as Ce, $setBlocksType as le } from "@lexical/selection";
24
24
  import { $findMatchingParent as It, $getNearestNodeOfType as jt, mergeRegister as Ut, $insertNodeToNearestRoot as ae } from "@lexical/utils";
25
- import { B as V } from "./Button-Cfxd7qhd.js";
26
- import { C as wt, D as Ft } from "./ColorPickerPanel-BGzm2had.js";
25
+ import { B as V } from "./Button-DBs8xnA5.js";
26
+ import { C as wt, D as Ft } from "./ColorPickerPanel-Dp7bnnVf.js";
27
27
  import { D as O } from "./Divider-LtH3dLgw.js";
28
28
  import { D as ce } from "./Dropdown-FfkmluRu.js";
29
29
  import { F as $t } from "./FloatingPanel-BG9Uag__.js";
30
30
  import { I as u } from "./Icon-DaTvzLBu.js";
31
- import { I as R } from "./IconButton-CfvsE_p3.js";
31
+ import { I as R } from "./IconButton-BEGWfcVc.js";
32
32
  import { L as z } from "./ListItem-Cn15lJBr.js";
33
- import { M as Bt } from "./Modal-Cx0JEQ-j.js";
34
- import { T as Ht } from "./TextField-B4YtjNUs.js";
35
- import { a as se } from "./ConfigProvider-Blhvj6UQ.js";
33
+ import { M as Bt } from "./Modal-B7yoFC3o.js";
34
+ import { T as Ht } from "./TextField-BWdmF-HE.js";
35
+ import { a as se } from "./ConfigProvider-DR9YMy9U.js";
36
36
  const Pt = /^(?:https?:|mailto:|tel:|ftp:|#|\/|\?|\.)/i, qt = /^[a-z][a-z0-9+.-]*:/i;
37
37
  function me(o) {
38
38
  const t = o.trim();
@@ -803,4 +803,4 @@ const Lo = Ke(
803
803
  export {
804
804
  Lo as R
805
805
  };
806
- //# sourceMappingURL=RichTextEditor-C_6pzqYY.js.map
806
+ //# sourceMappingURL=RichTextEditor-Bm8FFbcR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RichTextEditor-C_6pzqYY.js","sources":["../src/components/RichTextEditor/urlSafety.ts","../src/components/RichTextEditor/nodes/ImageNode.tsx","../src/components/RichTextEditor/nodes/VideoNode.tsx","../src/components/RichTextEditor/Toolbar.tsx","../src/components/RichTextEditor/RichTextEditor.tsx"],"sourcesContent":["/**\n * URL-scheme allowlist for the RichTextEditor — the single defense against script-URL XSS\n * (`javascript:`, `vbscript:`, `data:text/html`, …) reaching the exported HTML value, whether a URL\n * arrives via the toolbar dialogs, a paste, or a loaded value. Rejected URLs are neutralized (an\n * empty `src`, or a `'#'` `href`) rather than executed.\n */\n\n// Link schemes we trust, plus relative/anchor/query starts (which carry no scheme at all).\nconst SAFE_LINK = /^(?:https?:|mailto:|tel:|ftp:|#|\\/|\\?|\\.)/i\n// Does the string begin with an explicit `scheme:` at all? (Anything schemeless is treated as relative.)\nconst HAS_SCHEME = /^[a-z][a-z0-9+.-]*:/i\n\n/**\n * Sanitize a link `href`: allow `http(s)`/`mailto`/`tel`/`ftp` and relative/anchor/query URLs; any\n * other explicit scheme (`javascript:`, `data:`, `vbscript:`, …) collapses to `'#'`.\n */\nexport function sanitizeLinkUrl(url: string): string {\n const trimmed = url.trim()\n if (trimmed === '') return ''\n if (SAFE_LINK.test(trimmed)) return trimmed\n if (!HAS_SCHEME.test(trimmed)) return trimmed // schemeless (e.g. `example.com/x`) → relative, safe\n return '#' // a disallowed scheme\n}\n\n/**\n * Sanitize an image/video `src`: like {@link sanitizeLinkUrl}, but also permits inline\n * `data:image`/`data:video` (upload embeds) and `blob:` object URLs. A disallowed scheme yields `''`.\n */\nexport function sanitizeMediaUrl(url: string): string {\n const trimmed = url.trim()\n if (/^data:(?:image|video)\\//i.test(trimmed) || /^blob:/i.test(trimmed)) return trimmed\n const safe = sanitizeLinkUrl(trimmed)\n return safe === '#' ? '' : safe\n}\n","import {\n $applyNodeReplacement,\n DecoratorNode,\n type DOMConversionMap,\n type DOMConversionOutput,\n type DOMExportOutput,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n type Spread,\n} from 'lexical'\nimport type { ReactNode } from 'react'\nimport { sanitizeMediaUrl } from '../urlSafety'\n\n/** Serialized shape of an {@link ImageNode} (editor-state JSON). */\nexport type SerializedImageNode = Spread<{ src: string; alt: string }, SerializedLexicalNode>\n\n/** Rebuilds an `ImageNode` from a pasted/loaded `<img>` element. */\nfunction convertImageElement(domNode: HTMLElement): DOMConversionOutput | null {\n if (domNode instanceof HTMLImageElement && domNode.src) {\n return { node: $createImageNode(domNode.getAttribute('src') ?? domNode.src, domNode.alt) }\n }\n return null\n}\n\n/**\n * A block-level image node. Renders a plain `<img>` (the `src` may be a remote URL or a base64\n * `data:` URL when inserted via upload). Serializes to a clean `<img src alt>` for the HTML value and\n * parses back from any `<img>` on paste/load.\n */\nexport class ImageNode extends DecoratorNode<ReactNode> {\n __src: string\n __alt: string\n\n static getType(): string {\n return 'tz-image'\n }\n\n static clone(node: ImageNode): ImageNode {\n return new ImageNode(node.__src, node.__alt, node.__key)\n }\n\n constructor(src: string, alt = '', key?: NodeKey) {\n super(key)\n // sanitize here so every path (insert, paste import, JSON load, clone) gets a safe scheme\n this.__src = sanitizeMediaUrl(src)\n this.__alt = alt\n }\n\n static importJSON(json: SerializedImageNode): ImageNode {\n return $createImageNode(json.src, json.alt)\n }\n\n exportJSON(): SerializedImageNode {\n return { ...super.exportJSON(), type: 'tz-image', version: 1, src: this.__src, alt: this.__alt }\n }\n\n static importDOM(): DOMConversionMap | null {\n return { img: () => ({ conversion: convertImageElement, priority: 0 }) }\n }\n\n exportDOM(): DOMExportOutput {\n const element = document.createElement('img')\n element.setAttribute('src', this.__src)\n element.setAttribute('alt', this.__alt)\n return { element }\n }\n\n /** A block wrapper; the actual `<img>` is rendered by {@link decorate}. */\n createDOM(): HTMLElement {\n const div = document.createElement('div')\n div.style.display = 'contents'\n return div\n }\n\n updateDOM(): false {\n return false\n }\n\n getSrc(): string {\n return this.__src\n }\n\n getAltText(): string {\n return this.__alt\n }\n\n decorate(): ReactNode {\n return <img src={this.__src} alt={this.__alt} draggable={false} />\n }\n}\n\n/** Creates an `ImageNode` (use inside an `editor.update`). */\nexport function $createImageNode(src: string, alt = ''): ImageNode {\n return $applyNodeReplacement(new ImageNode(src, alt))\n}\n\n/** Type guard for `ImageNode`. */\nexport function $isImageNode(node: LexicalNode | null | undefined): node is ImageNode {\n return node instanceof ImageNode\n}\n","import {\n $applyNodeReplacement,\n DecoratorNode,\n type DOMConversionMap,\n type DOMConversionOutput,\n type DOMExportOutput,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n type Spread,\n} from 'lexical'\nimport type { ReactNode } from 'react'\nimport { useT } from '../../../theme'\nimport { sanitizeMediaUrl } from '../urlSafety'\n\n/** Serialized shape of a {@link VideoNode} (editor-state JSON). */\nexport type SerializedVideoNode = Spread<{ src: string }, SerializedLexicalNode>\n\n/** A direct video file (rendered with `<video controls>` rather than an embed `<iframe>`). */\nfunction isFileVideo(src: string): boolean {\n return /\\.(mp4|webm|ogg|ogv|mov|m4v)(\\?.*)?$/i.test(src)\n}\n\n/**\n * Normalizes a pasted video URL into an embeddable one — YouTube/Vimeo watch links become their\n * `embed` form; everything else (incl. already-embed URLs and direct files) is returned unchanged,\n * so the conversion is idempotent across HTML round-trips.\n */\nexport function toVideoEmbedSrc(raw: string): string {\n const youtube = raw.match(\n /(?:youtube\\.com\\/(?:watch\\?(?:.*&)?v=|embed\\/|shorts\\/)|youtu\\.be\\/)([\\w-]{11})/,\n )\n if (youtube) return `https://www.youtube.com/embed/${youtube[1]}`\n const vimeo = raw.match(/vimeo\\.com\\/(?:video\\/)?(\\d+)/)\n if (vimeo) return `https://player.vimeo.com/video/${vimeo[1]}`\n return raw\n}\n\n/** Rebuilds a `VideoNode` from a pasted/loaded `<iframe>` or `<video>` element. */\nfunction convertVideoElement(domNode: HTMLElement): DOMConversionOutput | null {\n const src = domNode.getAttribute('src') || domNode.querySelector('source')?.getAttribute('src')\n if (src) return { node: $createVideoNode(src) }\n return null\n}\n\n/**\n * A block-level video node. Direct media files render with `<video controls>`; everything else is\n * treated as an embed and renders in a responsive `<iframe>` (YouTube/Vimeo links are normalized to\n * their embed URL). Serializes to a clean `<video>` / `<iframe>` for the HTML value.\n */\nexport class VideoNode extends DecoratorNode<ReactNode> {\n __src: string\n\n static getType(): string {\n return 'tz-video'\n }\n\n static clone(node: VideoNode): VideoNode {\n return new VideoNode(node.__src, node.__key)\n }\n\n constructor(src: string, key?: NodeKey) {\n super(key)\n // sanitize here so every path (insert, paste import, JSON load, clone) gets a safe scheme\n this.__src = sanitizeMediaUrl(src)\n }\n\n static importJSON(json: SerializedVideoNode): VideoNode {\n return $createVideoNode(json.src)\n }\n\n exportJSON(): SerializedVideoNode {\n return { ...super.exportJSON(), type: 'tz-video', version: 1, src: this.__src }\n }\n\n static importDOM(): DOMConversionMap | null {\n return {\n iframe: () => ({ conversion: convertVideoElement, priority: 0 }),\n video: () => ({ conversion: convertVideoElement, priority: 0 }),\n }\n }\n\n exportDOM(): DOMExportOutput {\n if (isFileVideo(this.__src)) {\n const video = document.createElement('video')\n video.setAttribute('src', this.__src)\n video.setAttribute('controls', 'true')\n return { element: video }\n }\n const iframe = document.createElement('iframe')\n iframe.setAttribute('src', this.__src)\n iframe.setAttribute('frameborder', '0')\n iframe.setAttribute('allowfullscreen', 'true')\n iframe.setAttribute(\n 'allow',\n 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',\n )\n return { element: iframe }\n }\n\n /** A block wrapper; the actual media element is rendered by {@link decorate}. */\n createDOM(): HTMLElement {\n const div = document.createElement('div')\n div.style.display = 'contents'\n return div\n }\n\n updateDOM(): false {\n return false\n }\n\n getSrc(): string {\n return this.__src\n }\n\n decorate(): ReactNode {\n if (isFileVideo(this.__src)) return <video src={this.__src} controls />\n return <VideoEmbed src={this.__src} />\n }\n}\n\n/** The in-editor embed `<iframe>` — a component so its `title` can be localized via `useT()`. */\nfunction VideoEmbed({ src }: { src: string }) {\n const t = useT()\n return (\n <div className=\"tz-rte-embed\">\n <iframe\n src={src}\n title={t('rte.embeddedVideo')}\n frameBorder={0}\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n />\n </div>\n )\n}\n\n/** Creates a `VideoNode`, normalizing the URL to an embeddable one (use inside an `editor.update`). */\nexport function $createVideoNode(src: string): VideoNode {\n return $applyNodeReplacement(new VideoNode(toVideoEmbedSrc(src)))\n}\n\n/** Type guard for `VideoNode`. */\nexport function $isVideoNode(node: LexicalNode | null | undefined): node is VideoNode {\n return node instanceof VideoNode\n}\n","import { useCallback, useEffect, useRef, useState, type ChangeEvent } from 'react'\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'\nimport {\n $createParagraphNode,\n $getSelection,\n $isElementNode,\n $isRangeSelection,\n CAN_REDO_COMMAND,\n CAN_UNDO_COMMAND,\n COMMAND_PRIORITY_LOW,\n FORMAT_ELEMENT_COMMAND,\n FORMAT_TEXT_COMMAND,\n REDO_COMMAND,\n SELECTION_CHANGE_COMMAND,\n UNDO_COMMAND,\n type ElementFormatType,\n type TextFormatType,\n} from 'lexical'\nimport {\n $createHeadingNode,\n $createQuoteNode,\n $isHeadingNode,\n $isQuoteNode,\n type HeadingTagType,\n} from '@lexical/rich-text'\nimport {\n INSERT_CHECK_LIST_COMMAND,\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n ListNode,\n REMOVE_LIST_COMMAND,\n} from '@lexical/list'\nimport { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link'\nimport { sanitizeLinkUrl } from './urlSafety'\nimport { toast } from '../Toast/toastStore'\nimport { useT, type MessageKey } from '../../theme'\nimport {\n $getSelectionStyleValueForProperty,\n $patchStyleText,\n $setBlocksType,\n} from '@lexical/selection'\nimport { $findMatchingParent, $getNearestNodeOfType, mergeRegister } from '@lexical/utils'\nimport { $insertNodeToNearestRoot } from '@lexical/utils'\nimport type { IconName } from '../../icons/names'\nimport { Button } from '../Button'\nimport { ColorPickerPanel, DEFAULT_SWATCHES } from '../ColorPicker/ColorPickerPanel'\nimport { Divider } from '../Divider'\nimport { Dropdown } from '../Dropdown'\nimport { FloatingPanel } from '../FloatingPanel/FloatingPanel'\nimport { Icon } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { ListItem } from '../List'\nimport { Modal } from '../Modal'\nimport { TextField } from '../TextField'\nimport { $createImageNode } from './nodes/ImageNode'\nimport { $createVideoNode } from './nodes/VideoNode'\nimport styles from './RichTextEditor.module.css'\n\ntype Size = 'sm' | 'md' | 'lg'\ntype BlockType = 'paragraph' | HeadingTagType | 'quote' | 'bullet' | 'number' | 'check'\n\n// Block-type labels stay **English in every language** by design — \"Paragraph\" / \"Heading\" are\n// editor-standard terms the maintainer prefers untranslated, so these are literals, not i18n keys.\nconst BLOCK_LABEL: Partial<Record<BlockType, string>> = {\n paragraph: 'Paragraph',\n h1: 'Heading 1',\n h2: 'Heading 2',\n h3: 'Heading 3',\n quote: 'Quote',\n bullet: 'Bullet List',\n number: 'Numbered List',\n check: 'Check List',\n}\n\n/** Items in the block-type dropdown — lists & quote are standalone toolbar buttons; check lists are excluded. */\nconst BLOCKS: { type: BlockType; icon?: IconName }[] = [\n { type: 'paragraph', icon: 'Text' },\n { type: 'h1', icon: 'Hashtag' },\n { type: 'h2', icon: 'Hashtag' },\n { type: 'h3', icon: 'Hashtag' },\n]\n\n/** Text-alignment controls (set the block element's `text-align`); `labelKey` resolves via `t`. */\nconst ALIGNS: { value: ElementFormatType; labelKey: MessageKey; icon: IconName }[] = [\n { value: 'left', labelKey: 'rte.alignLeft', icon: 'TextalignLeft' },\n { value: 'center', labelKey: 'rte.alignCenter', icon: 'TextalignCenter' },\n { value: 'right', labelKey: 'rte.alignRight', icon: 'TextalignRight' },\n]\n\n/** Font-size options (the `font-size` style value). */\nconst FONT_SIZES = ['10px', '12px', '14px', '16px', '18px', '20px']\n\n/** The editor's default content size per `size` (mirrors `.content` in the CSS) — shown active when the\n * selection has no explicit `font-size`. */\nconst DEFAULT_FONT_SIZE: Record<Size, string> = { sm: '12px', md: '14px', lg: '16px' }\n\n/** Config for the shared URL-input `Modal` (link / image-by-URL / video) — replaces `window.prompt`. */\ntype UrlDialog = {\n icon: IconName\n title: string\n label: string\n placeholder: string\n confirmLabel: string\n onConfirm: (url: string) => void\n}\n\n/** The text-color button glyph — a brush icon with a corner triangle tinted with the current text\n * color (so the selected color is always visible). Accepts the `size` `IconButton` injects so it\n * doesn't hit the DOM. */\nfunction ColorGlyph({ color, size }: { color: string; size?: Size }) {\n return (\n <span className={styles.colorGlyph}>\n <Icon name=\"Brush\" size={size} />\n <span\n className={styles.colorBar}\n style={{ borderColor: `transparent transparent ${color || 'currentColor'} transparent` }}\n aria-hidden=\"true\"\n />\n </span>\n )\n}\n\nexport interface ToolbarProps {\n size: Size\n disabled: boolean\n /** Optional async upload — when set, an inserted image uses the returned URL instead of a base64 data URL. */\n onImageUpload?: (file: File) => Promise<string>\n}\n\n/** The editor toolbar — reads the live selection and dispatches Lexical commands. */\nexport function Toolbar({ size, disabled, onImageUpload }: ToolbarProps) {\n const t = useT()\n const blockLabel = (b: BlockType): string => BLOCK_LABEL[b] ?? b // h4–h6 aren't offered by the editor\n const [editor] = useLexicalComposerContext()\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const [isBold, setIsBold] = useState(false)\n const [isItalic, setIsItalic] = useState(false)\n const [isUnderline, setIsUnderline] = useState(false)\n const [isLink, setIsLink] = useState(false)\n const [linkUrl, setLinkUrl] = useState('')\n const [blockType, setBlockType] = useState<BlockType>('paragraph')\n const [elementFormat, setElementFormat] = useState<ElementFormatType>('left')\n const [fontSize, setFontSize] = useState('')\n const [textColor, setTextColor] = useState('')\n const [colorOpen, setColorOpen] = useState(false)\n const colorTriggerRef = useRef<HTMLButtonElement | null>(null)\n const [canUndo, setCanUndo] = useState(false)\n const [canRedo, setCanRedo] = useState(false)\n // shared URL-input modal (link / image-by-URL / video)\n const [urlDialog, setUrlDialog] = useState<UrlDialog | null>(null)\n const [urlValue, setUrlValue] = useState('')\n\n const syncState = useCallback(() => {\n const selection = $getSelection()\n if (!$isRangeSelection(selection)) return\n setIsBold(selection.hasFormat('bold'))\n setIsItalic(selection.hasFormat('italic'))\n setIsUnderline(selection.hasFormat('underline'))\n setTextColor($getSelectionStyleValueForProperty(selection, 'color', ''))\n setFontSize($getSelectionStyleValueForProperty(selection, 'font-size', ''))\n\n const anchorNode = selection.anchor.getNode()\n const parent = anchorNode.getParent()\n const linkNode = $isLinkNode(anchorNode) ? anchorNode : $isLinkNode(parent) ? parent : null\n setIsLink(linkNode !== null)\n setLinkUrl(linkNode?.getURL() ?? '')\n\n // the block element under the cursor — drives both the alignment and block-type state\n const element =\n anchorNode.getKey() === 'root'\n ? anchorNode\n : ($findMatchingParent(anchorNode, (e) => {\n const parent = e.getParent()\n return parent === null || parent.getKey() === 'root'\n }) ?? anchorNode.getTopLevelElement())\n\n setElementFormat(($isElementNode(element) && element.getFormatType()) || 'left')\n\n const listNode = $getNearestNodeOfType(anchorNode, ListNode)\n if (listNode) setBlockType(listNode.getListType())\n else if ($isHeadingNode(element)) setBlockType(element.getTag())\n else if ($isQuoteNode(element)) setBlockType('quote')\n else setBlockType('paragraph')\n }, [])\n\n useEffect(() => {\n return mergeRegister(\n editor.registerUpdateListener(({ editorState }) => editorState.read(syncState)),\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n syncState()\n return false\n },\n COMMAND_PRIORITY_LOW,\n ),\n editor.registerCommand(\n CAN_UNDO_COMMAND,\n (payload) => {\n setCanUndo(payload)\n return false\n },\n COMMAND_PRIORITY_LOW,\n ),\n editor.registerCommand(\n CAN_REDO_COMMAND,\n (payload) => {\n setCanRedo(payload)\n return false\n },\n COMMAND_PRIORITY_LOW,\n ),\n )\n }, [editor, syncState])\n\n const format = (type: TextFormatType) => editor.dispatchCommand(FORMAT_TEXT_COMMAND, type)\n\n const applyAlign = (fmt: ElementFormatType) => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, fmt)\n\n // apply the picked color to the (retained) selection; `''` clears it back to the default\n const applyColor = (color: string) => {\n setTextColor(color)\n editor.update(() => {\n const selection = $getSelection()\n if ($isRangeSelection(selection)) $patchStyleText(selection, { color: color || null })\n })\n }\n\n // apply a font size to the (retained) selection; `''` clears it back to the editor default\n const applyFontSize = (value: string) => {\n setFontSize(value)\n editor.update(() => {\n const selection = $getSelection()\n if ($isRangeSelection(selection)) $patchStyleText(selection, { 'font-size': value || null })\n })\n }\n\n const applyBlock = (type: BlockType) => {\n if (type === 'bullet' || type === 'number' || type === 'check') {\n if (blockType === type) {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined)\n } else {\n const command =\n type === 'bullet'\n ? INSERT_UNORDERED_LIST_COMMAND\n : type === 'number'\n ? INSERT_ORDERED_LIST_COMMAND\n : INSERT_CHECK_LIST_COMMAND\n editor.dispatchCommand(command, undefined)\n }\n return\n }\n editor.update(() => {\n const selection = $getSelection()\n if (!$isRangeSelection(selection)) return\n if (type === 'paragraph') $setBlocksType(selection, () => $createParagraphNode())\n else if (type === 'quote') $setBlocksType(selection, () => $createQuoteNode())\n else $setBlocksType(selection, () => $createHeadingNode(type))\n })\n }\n\n const toggleQuote = () => applyBlock(blockType === 'quote' ? 'paragraph' : 'quote')\n\n // open the shared URL modal (prefilled value + handler differ per action)\n const openUrlDialog = (config: UrlDialog, initial = '') => {\n setUrlValue(initial)\n setUrlDialog(config)\n }\n const closeUrlDialog = () => setUrlDialog(null)\n const confirmUrlDialog = () => {\n urlDialog?.onConfirm(urlValue.trim())\n setUrlDialog(null)\n }\n\n const insertLink = () =>\n openUrlDialog(\n {\n icon: 'Link2',\n title: t('rte.linkTitle'),\n label: t('rte.linkUrl'),\n placeholder: 'https://example.com',\n confirmLabel: isLink ? t('common.update') : t('common.insert'),\n // an empty value removes the link (matches the old prompt behavior); sanitize the scheme\n onConfirm: (url) =>\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, url === '' ? null : sanitizeLinkUrl(url)),\n },\n linkUrl, // prefill the current link's URL when the cursor sits in one\n )\n\n const insertImageByUrl = () =>\n openUrlDialog({\n icon: 'GalleryAdd',\n title: t('rte.imageTitle'),\n label: t('rte.imageUrl'),\n placeholder: 'https://example.com/image.jpg',\n confirmLabel: t('common.insert'),\n onConfirm: (url) => {\n if (url) editor.update(() => $insertNodeToNearestRoot($createImageNode(url)))\n },\n })\n\n const onImageFile = async (event: ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0]\n event.target.value = '' // allow re-picking the same file\n if (!file) return\n try {\n const url = onImageUpload ? await onImageUpload(file) : await fileToDataUrl(file)\n editor.update(() => $insertNodeToNearestRoot($createImageNode(url, file.name)))\n } catch {\n // a rejecting consumer upload handler (or a failed data-URL read) shouldn't fail silently\n toast.error(t('rte.imageError'))\n }\n }\n\n const insertVideo = () =>\n openUrlDialog({\n icon: 'VideoSquare',\n title: t('rte.videoTitle'),\n label: t('rte.videoUrl'),\n placeholder: t('rte.videoUrlPlaceholder'),\n confirmLabel: t('common.insert'),\n onConfirm: (url) => {\n if (url) editor.update(() => $insertNodeToNearestRoot($createVideoNode(url)))\n },\n })\n\n /** A format toggle — soft-filled while active. */\n const fmtBtn = (\n active: boolean,\n label: string,\n onClick: () => void,\n child: React.ReactNode,\n key?: string,\n ) => (\n <IconButton\n key={key}\n variant={active ? 'filled' : 'text'}\n color=\"primary\"\n size={size}\n disabled={disabled}\n aria-label={label}\n aria-pressed={active}\n onMouseDown={(e) => e.preventDefault()} // keep focus/selection in the editor\n onClick={onClick}\n >\n {child}\n </IconButton>\n )\n\n // the block dropdown only manages Paragraph / Headings — lists & quote are separate toggle buttons,\n // so when the cursor is in a list/quote/check the trigger shows \"Paragraph\", not e.g. \"Bullet List\".\n const dropdownBlock: BlockType = blockType.startsWith('h') ? blockType : 'paragraph'\n\n // font-size shown active: the selection's explicit size, else the editor's default for this `size`\n const effectiveFontSize = fontSize || DEFAULT_FONT_SIZE[size]\n\n return (\n <div\n className={styles.toolbar}\n role=\"toolbar\"\n aria-label={t('rte.formatting')}\n aria-orientation=\"horizontal\"\n >\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled || !canUndo}\n aria-label={t('rte.undo')}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => editor.dispatchCommand(UNDO_COMMAND, undefined)}\n >\n <Icon name=\"UndoArrow\" />\n </IconButton>\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled || !canRedo}\n aria-label={t('rte.redo')}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => editor.dispatchCommand(REDO_COMMAND, undefined)}\n >\n <Icon name=\"RedoArrow\" />\n </IconButton>\n\n <Divider orientation=\"vertical\" />\n\n <Dropdown\n size={size}\n disabled={disabled}\n minWidth={false}\n trigger={\n <Button\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n endIcon={<Icon name=\"ArrowDown4\" />}\n aria-label={t('rte.fontSize')}\n onMouseDown={(e) => e.preventDefault()} // keep the selection while opening\n >\n {effectiveFontSize}\n </Button>\n }\n >\n {FONT_SIZES.map((f) => (\n <ListItem\n key={f}\n clickable\n selected={f === effectiveFontSize}\n onClick={() => applyFontSize(f)}\n >\n {f}\n </ListItem>\n ))}\n </Dropdown>\n\n <Divider orientation=\"vertical\" />\n\n <Dropdown\n size={size}\n disabled={disabled}\n trigger={\n <Button\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n endIcon={<Icon name=\"ArrowDown4\" />}\n onMouseDown={(e) => e.preventDefault()} // keep the selection while opening\n >\n {blockLabel(dropdownBlock)}\n </Button>\n }\n >\n {BLOCKS.map((b) => (\n <ListItem\n key={b.type}\n clickable\n selected={dropdownBlock === b.type}\n icon={b.icon}\n onClick={() => applyBlock(b.type)}\n >\n {blockLabel(b.type)}\n </ListItem>\n ))}\n </Dropdown>\n\n <Divider orientation=\"vertical\" />\n\n {fmtBtn(isBold, t('rte.bold'), () => format('bold'), <Icon name=\"TextBold\" />)}\n {fmtBtn(isItalic, t('rte.italic'), () => format('italic'), <Icon name=\"TextItalic\" />)}\n {fmtBtn(\n isUnderline,\n t('rte.underline'),\n () => format('underline'),\n <Icon name=\"TextUnderline\" />,\n )}\n\n <Divider orientation=\"vertical\" />\n\n {fmtBtn(\n blockType === 'bullet',\n t('rte.bulletList'),\n () => applyBlock('bullet'),\n <Icon name=\"ListBullet\" />,\n )}\n {fmtBtn(\n blockType === 'number',\n t('rte.numberedList'),\n () => applyBlock('number'),\n <Icon name=\"ListNumber\" />,\n )}\n {fmtBtn(blockType === 'quote', t('rte.quote'), toggleQuote, <Icon name=\"QuoteUp\" />)}\n\n <Divider orientation=\"vertical\" />\n\n {ALIGNS.map((a) =>\n fmtBtn(\n elementFormat === a.value,\n t(a.labelKey),\n () => applyAlign(a.value),\n <Icon name={a.icon} />,\n a.value,\n ),\n )}\n\n <Divider orientation=\"vertical\" />\n\n <IconButton\n ref={colorTriggerRef}\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n aria-label={t('rte.textColor')}\n aria-expanded={colorOpen}\n onMouseDown={(e) => e.preventDefault()} // keep the editor's selection while opening\n onClick={() => setColorOpen((o) => !o)}\n >\n <ColorGlyph color={textColor} />\n </IconButton>\n <FloatingPanel\n open={colorOpen}\n triggerRef={colorTriggerRef}\n onClose={(refocus) => {\n setColorOpen(false)\n if (refocus) colorTriggerRef.current?.focus()\n }}\n role=\"dialog\"\n ariaLabel={t('rte.textColor')}\n width={232}\n >\n {/* no \"no color\" swatch; with no explicit color the accent default (first swatch) shows selected */}\n <ColorPickerPanel\n value={textColor || DEFAULT_SWATCHES[0]}\n onChange={applyColor}\n clearable={false}\n />\n </FloatingPanel>\n\n {fmtBtn(isLink, t('rte.link'), insertLink, <Icon name=\"Link2\" />)}\n\n <Dropdown\n size={size}\n disabled={disabled}\n minWidth={false}\n trigger={\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n aria-label={t('rte.insertImage')}\n >\n <Icon name=\"GalleryAdd\" />\n </IconButton>\n }\n >\n <ListItem clickable icon=\"GalleryImport\" onClick={() => fileInputRef.current?.click()}>\n {t('rte.uploadImage')}\n </ListItem>\n <ListItem clickable icon=\"Link\" onClick={insertImageByUrl}>\n {t('rte.imageByUrl')}\n </ListItem>\n </Dropdown>\n\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n aria-label={t('rte.insertVideo')}\n onClick={insertVideo}\n >\n <Icon name=\"VideoSquare\" />\n </IconButton>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n hidden\n onChange={onImageFile}\n aria-hidden=\"true\"\n tabIndex={-1}\n />\n\n {/* shared URL-input dialog for link / image-by-URL / video (replaces window.prompt). The footer\n Submit drives the body <form> via the `form` attribute (works across the modal's portal). */}\n <Modal\n open={urlDialog !== null}\n onClose={closeUrlDialog}\n size=\"sm\"\n icon={urlDialog?.icon}\n title={urlDialog?.title}\n footer={\n <>\n <Button variant=\"text\" onClick={closeUrlDialog}>\n {t('common.cancel')}\n </Button>\n <Button type=\"submit\" form=\"rte-url-form\">\n {urlDialog?.confirmLabel ?? t('common.insert')}\n </Button>\n </>\n }\n >\n <form\n id=\"rte-url-form\"\n onSubmit={(e) => {\n e.preventDefault()\n confirmUrlDialog()\n }}\n >\n <TextField\n label={urlDialog?.label}\n placeholder={urlDialog?.placeholder}\n value={urlValue}\n onChange={(e) => setUrlValue(e.target.value)}\n />\n </form>\n </Modal>\n </div>\n )\n}\n\n/** Reads a picked file into a base64 `data:` URL (the no-backend default for image upload). */\nfunction fileToDataUrl(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(reader.result as string)\n reader.onerror = () => reject(reader.error)\n reader.readAsDataURL(file)\n })\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n type CSSProperties,\n type FocusEvent,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport {\n $createParagraphNode,\n $getRoot,\n $insertNodes,\n $isParagraphNode,\n $setSelection,\n type EditorThemeClasses,\n} from 'lexical'\nimport { LexicalComposer } from '@lexical/react/LexicalComposer'\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable'\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'\nimport { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'\nimport { ListPlugin } from '@lexical/react/LexicalListPlugin'\nimport { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'\nimport { LinkPlugin } from '@lexical/react/LexicalLinkPlugin'\nimport { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin'\nimport {\n ELEMENT_TRANSFORMERS,\n TEXT_FORMAT_TRANSFORMERS,\n TEXT_MATCH_TRANSFORMERS,\n} from '@lexical/markdown'\nimport { HeadingNode, QuoteNode } from '@lexical/rich-text'\nimport { ListItemNode, ListNode } from '@lexical/list'\nimport { LinkNode } from '@lexical/link'\nimport { sanitizeLinkUrl } from './urlSafety'\nimport { $generateHtmlFromNodes, $generateNodesFromDOM } from '@lexical/html'\nimport { useT } from '../../theme'\nimport { useFormContext } from '../../form/formContext'\nimport { Typography } from '../Typography'\nimport { Toolbar } from './Toolbar'\nimport { ImageNode } from './nodes/ImageNode'\nimport { VideoNode } from './nodes/VideoNode'\nimport styles from './RichTextEditor.module.css'\n\nexport type RichTextEditorSize = 'sm' | 'md' | 'lg'\n\n/** Lexical node-type → CSS-module class map (so content is styled with `--tz-*` tokens). */\nconst THEME: EditorThemeClasses = {\n paragraph: styles.paragraph,\n heading: {\n h1: styles.h1,\n h2: styles.h2,\n h3: styles.h3,\n h4: styles.h4,\n h5: styles.h5,\n h6: styles.h6,\n },\n quote: styles.quote,\n list: {\n ul: styles.ul,\n ol: styles.ol,\n listitem: styles.li,\n listitemChecked: styles.liChecked,\n listitemUnchecked: styles.liUnchecked,\n nested: { listitem: styles.nestedLi },\n },\n link: styles.link,\n text: {\n bold: styles.bold,\n italic: styles.italic,\n underline: styles.underline,\n strikethrough: styles.strike,\n code: styles.codeInline,\n },\n}\n\nconst EDITOR_NODES = [\n HeadingNode,\n QuoteNode,\n ListNode,\n ListItemNode,\n LinkNode,\n ImageNode,\n VideoNode,\n]\n\n/**\n * Markdown shortcuts for headings/quote/lists + inline formats + links. Excludes the multiline\n * fenced-code-block transformer (it needs `CodeNode`, which is out of scope for v1).\n */\nconst MARKDOWN_TRANSFORMERS = [\n ...ELEMENT_TRANSFORMERS,\n ...TEXT_FORMAT_TRANSFORMERS,\n ...TEXT_MATCH_TRANSFORMERS,\n]\n\n/**\n * Strips the editor's (hashed, CSS-module) `class` attributes from exported HTML so the value is clean,\n * portable markup (`<h2>` not `<h2 class=\"_h2_ab12\">`). Classes aren't needed to re-import — parsing\n * keys off tag names — so this is round-trip-safe.\n */\nfunction cleanExportedHtml(html: string): string {\n if (typeof document === 'undefined') return html\n const template = document.createElement('template')\n template.innerHTML = html\n template.content.querySelectorAll('[class]').forEach((el) => el.removeAttribute('class'))\n return template.innerHTML\n}\n\n/**\n * True when the editor holds nothing but an empty paragraph (Lexical's \"blank\" state, which serializes\n * to `<p><br></p>`). Lets the value emit `''` instead, so a cleared editor reads as truly empty (and a\n * `required` rule fires). Call inside an `editor.read`/`update`.\n */\nfunction $isEditorEmpty(): boolean {\n const root = $getRoot()\n const first = root.getFirstChild()\n return (\n root.getChildrenSize() <= 1 &&\n (first === null || ($isParagraphNode(first) && first.getChildrenSize() === 0))\n )\n}\n\n/** Replaces the editor's content with the nodes parsed from an HTML string (call inside `editor.update`). */\nfunction $setRootFromHtml(editor: Parameters<typeof $generateNodesFromDOM>[0], html: string) {\n const root = $getRoot()\n root.clear()\n if (html) {\n const dom = new DOMParser().parseFromString(html, 'text/html')\n const nodes = $generateNodesFromDOM(editor, dom)\n root.select()\n $insertNodes(nodes)\n }\n if (root.getChildrenSize() === 0) root.append($createParagraphNode())\n // clear the caret the insert left at the end of the content — otherwise Lexical scrolls it into\n // view when setting the initial/controlled value on mount, dragging the whole page down to a\n // below-the-fold editor (e.g. the prefilled RTEs on the Edit form). Focus re-places it later.\n $setSelection(null)\n}\n\ninterface ValuePluginProps {\n value?: string\n defaultValue?: string\n onChange: (html: string) => void\n disabled: boolean\n}\n\n/** Bridges the HTML `value` ↔ the Lexical editor state, and toggles read-only mode. */\nfunction ValuePlugin({ value, defaultValue, onChange, disabled }: ValuePluginProps) {\n const [editor] = useLexicalComposerContext()\n // the last HTML we wrote-in or emitted-out — guards the controlled-sync ↔ onChange feedback loop\n const lastHtml = useRef<string | undefined>(undefined)\n const onChangeRef = useRef(onChange)\n onChangeRef.current = onChange\n\n useEffect(() => editor.setEditable(!disabled), [editor, disabled])\n\n // neutralize unsafe link schemes (javascript:, data:, …) on every LinkNode — covers pasted anchors\n // as well as toolbar inserts (which are also pre-sanitized), so no script URL survives into the value\n useEffect(\n () =>\n editor.registerNodeTransform(LinkNode, (node) => {\n const url = node.getURL()\n const safe = sanitizeLinkUrl(url)\n if (safe !== url) node.setURL(safe)\n }),\n [editor],\n )\n\n // initial defaultValue (uncontrolled) — once\n useEffect(() => {\n if (value !== undefined || !defaultValue) return\n lastHtml.current = defaultValue\n editor.update(() => $setRootFromHtml(editor, defaultValue), { tag: 'history-merge' })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // controlled value → editor (only on a genuine external change, not our own echo)\n useEffect(() => {\n if (value === undefined || value === lastHtml.current) return\n lastHtml.current = value\n editor.update(() => $setRootFromHtml(editor, value), { tag: 'history-merge' })\n }, [editor, value])\n\n // editor → HTML out. NB: must be `editor.read` (not `editorState.read`) so the active editor is\n // bound — `$generateHtmlFromNodes` → node `createDOM` needs it, else it throws \"no active editor\".\n useEffect(\n () =>\n editor.registerUpdateListener(({ dirtyElements, dirtyLeaves }) => {\n if (dirtyElements.size === 0 && dirtyLeaves.size === 0) return\n editor.read(() => {\n const html = $isEditorEmpty()\n ? ''\n : cleanExportedHtml($generateHtmlFromNodes(editor, null))\n if (html === lastHtml.current) return\n lastHtml.current = html\n onChangeRef.current(html)\n })\n }),\n [editor],\n )\n\n return null\n}\n\nexport interface RichTextEditorProps {\n /** Label rendered above the editor. */\n label?: ReactNode\n /** Preset size — drives toolbar density, content font size and min-height. */\n size?: RichTextEditorSize\n /** Marks the field invalid: red border/ring and `helperText` in the error color. */\n error?: boolean\n /** Helper / validation text under the editor. Adopts the error color while `error`. */\n helperText?: ReactNode\n /** Adds a red asterisk after the label (visual hint). */\n required?: boolean\n /** Read-only mode — the toolbar disables and the content isn't editable. */\n disabled?: boolean\n /** Placeholder shown while the editor is empty. */\n placeholder?: string\n /** Form field name — auto-binds value/validation to a surrounding `<Form>` (value = the HTML string). */\n name?: string\n /** Controlled HTML value. */\n value?: string\n /** Initial HTML value (uncontrolled). */\n defaultValue?: string\n /** Fires with the serialized **HTML** on every edit. */\n onChange?: (html: string) => void\n /**\n * Async image upload. When provided, an uploaded image is sent through this and the returned URL is\n * inserted; when omitted, the image is embedded inline as a base64 `data:` URL (no backend needed).\n */\n onImageUpload?: (file: File) => Promise<string>\n /** Min height of the editable area in px. Defaults to `220`. */\n minHeight?: number\n /** Accessible label for the editable region. Defaults to `'Rich text editor'`. */\n 'aria-label'?: string\n className?: string\n style?: CSSProperties\n}\n\n/**\n * A rich text editor built on **Lexical** (an optional peer — install `lexical` + `@lexical/*`). Its\n * value is an **HTML string**: bold/italic/underline/strikethrough/inline-code, headings, lists\n * (bullet/ordered/check), links, block quote, plus **images** (insert by URL or upload — embedded as a\n * base64 `data:` URL unless an `onImageUpload` handler is given) and **video** embeds (paste a\n * YouTube/Vimeo/file URL). Markdown shortcuts work while typing (`# `, `- `, `> `, …). The toolbar is\n * built from the library's own `IconButton`/`Button`/`Dropdown`, and the content is styled entirely\n * with `--tz-*` tokens. Controlled (`value` + `onChange`) or uncontrolled (`defaultValue`); inside a\n * `<Form>`, a `name` prop auto-binds the HTML value (validate with e.g. `z.string().min(1)`).\n */\nexport const RichTextEditor = forwardRef<HTMLDivElement, RichTextEditorProps>(\n function RichTextEditor(\n {\n label,\n size = 'md',\n error,\n helperText,\n required = false,\n disabled = false,\n placeholder,\n name,\n value,\n defaultValue,\n onChange,\n onImageUpload,\n minHeight = 220,\n 'aria-label': ariaLabel = 'Rich text editor',\n className,\n style,\n },\n ref,\n ) {\n const t = useT()\n const form = useFormContext()\n const bound = form && name ? form.field(name) : undefined\n const resolvedError = error ?? bound?.error ?? false\n const resolvedHelperText = helperText ?? bound?.helperText\n\n const formValue = form && name ? (form.values as Record<string, unknown>)[name] : undefined\n const effValue =\n value !== undefined ? value : form && name ? String(formValue ?? '') : undefined\n\n const handleChange = useCallback(\n (html: string) => {\n if (form && name) form.setValue(name, html as never)\n onChange?.(html)\n },\n [form, name, onChange],\n )\n\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => bound?.onBlur(event as never)\n\n // Mirror the form `name` onto the editable DOM node so a `<Form>`'s scroll-to-error can find and\n // focus it — the contenteditable isn't an `<input>`, and Lexical's `ContentEditable` doesn't take\n // a `name` prop, so set the attribute imperatively via a ref.\n const contentRef = useRef<HTMLDivElement | null>(null)\n useEffect(() => {\n const el = contentRef.current\n if (!el) return\n if (name) el.setAttribute('name', name)\n else el.removeAttribute('name')\n }, [name])\n\n const initialConfig = {\n namespace: 'tz-rich-text-editor',\n theme: THEME,\n nodes: EDITOR_NODES,\n editable: !disabled,\n onError: (e: Error) => {\n throw e\n },\n }\n\n return (\n <div\n ref={ref}\n className={clsx(\n styles.editor,\n styles[size],\n resolvedError && styles.error,\n disabled && styles.disabled,\n className,\n )}\n style={{ '--tz-rte-min-height': `${minHeight}px`, ...style } as CSSProperties}\n >\n {label != null && (\n <div className={styles.label}>\n <Typography as=\"span\" variant=\"bodySmall\" color=\"muted\">\n {label}\n </Typography>\n {required && (\n <span className={styles.required} aria-hidden=\"true\">\n *\n </span>\n )}\n </div>\n )}\n\n <div className={styles.control}>\n <LexicalComposer initialConfig={initialConfig}>\n <Toolbar size={size} disabled={disabled} onImageUpload={onImageUpload} />\n <div className={styles.shell}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n ref={contentRef}\n className={styles.content}\n aria-label={ariaLabel}\n aria-invalid={resolvedError || undefined}\n onBlur={handleBlur}\n />\n }\n placeholder={\n <div className={styles.placeholder}>{placeholder ?? t('rte.placeholder')}</div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n </div>\n <HistoryPlugin />\n <ListPlugin />\n <CheckListPlugin />\n <LinkPlugin />\n <MarkdownShortcutPlugin transformers={MARKDOWN_TRANSFORMERS} />\n <ValuePlugin\n value={effValue}\n defaultValue={defaultValue}\n onChange={handleChange}\n disabled={disabled}\n />\n </LexicalComposer>\n </div>\n\n {resolvedHelperText != null && (\n <Typography\n as=\"span\"\n variant=\"bodySmall\"\n color={resolvedError ? 'error' : 'muted'}\n className={styles.helper}\n >\n {resolvedHelperText}\n </Typography>\n )}\n </div>\n )\n },\n)\n"],"names":["SAFE_LINK","HAS_SCHEME","sanitizeLinkUrl","url","trimmed","sanitizeMediaUrl","safe","convertImageElement","domNode","$createImageNode","ImageNode","DecoratorNode","node","src","alt","key","json","element","div","jsx","$applyNodeReplacement","isFileVideo","toVideoEmbedSrc","raw","youtube","vimeo","convertVideoElement","_a","$createVideoNode","VideoNode","video","iframe","VideoEmbed","useT","BLOCK_LABEL","BLOCKS","ALIGNS","FONT_SIZES","DEFAULT_FONT_SIZE","ColorGlyph","color","size","jsxs","styles","Icon","Toolbar","disabled","onImageUpload","t","blockLabel","b","editor","useLexicalComposerContext","fileInputRef","useRef","isBold","setIsBold","useState","isItalic","setIsItalic","isUnderline","setIsUnderline","isLink","setIsLink","linkUrl","setLinkUrl","blockType","setBlockType","elementFormat","setElementFormat","fontSize","setFontSize","textColor","setTextColor","colorOpen","setColorOpen","colorTriggerRef","canUndo","setCanUndo","canRedo","setCanRedo","urlDialog","setUrlDialog","urlValue","setUrlValue","syncState","useCallback","selection","$getSelection","$isRangeSelection","$getSelectionStyleValueForProperty","anchorNode","parent","linkNode","$isLinkNode","$findMatchingParent","e","$isElementNode","listNode","$getNearestNodeOfType","ListNode","$isHeadingNode","$isQuoteNode","useEffect","mergeRegister","editorState","SELECTION_CHANGE_COMMAND","COMMAND_PRIORITY_LOW","CAN_UNDO_COMMAND","payload","CAN_REDO_COMMAND","format","type","FORMAT_TEXT_COMMAND","applyAlign","fmt","FORMAT_ELEMENT_COMMAND","applyColor","$patchStyleText","applyFontSize","value","applyBlock","REMOVE_LIST_COMMAND","command","INSERT_UNORDERED_LIST_COMMAND","INSERT_ORDERED_LIST_COMMAND","INSERT_CHECK_LIST_COMMAND","$setBlocksType","$createParagraphNode","$createQuoteNode","$createHeadingNode","toggleQuote","openUrlDialog","config","initial","closeUrlDialog","confirmUrlDialog","insertLink","TOGGLE_LINK_COMMAND","insertImageByUrl","$insertNodeToNearestRoot","onImageFile","event","file","fileToDataUrl","toast","insertVideo","fmtBtn","active","label","onClick","child","IconButton","dropdownBlock","effectiveFontSize","UNDO_COMMAND","REDO_COMMAND","Divider","Dropdown","Button","f","ListItem","a","o","FloatingPanel","refocus","ColorPickerPanel","DEFAULT_SWATCHES","Modal","Fragment","TextField","resolve","reject","reader","THEME","EDITOR_NODES","HeadingNode","QuoteNode","ListItemNode","LinkNode","MARKDOWN_TRANSFORMERS","ELEMENT_TRANSFORMERS","TEXT_FORMAT_TRANSFORMERS","TEXT_MATCH_TRANSFORMERS","cleanExportedHtml","html","template","el","$isEditorEmpty","root","$getRoot","first","$isParagraphNode","$setRootFromHtml","dom","nodes","$generateNodesFromDOM","$insertNodes","$setSelection","ValuePlugin","defaultValue","onChange","lastHtml","onChangeRef","dirtyElements","dirtyLeaves","$generateHtmlFromNodes","RichTextEditor","forwardRef","error","helperText","required","placeholder","name","minHeight","ariaLabel","className","style","ref","form","useFormContext","bound","resolvedError","resolvedHelperText","formValue","effValue","handleChange","handleBlur","contentRef","initialConfig","clsx","Typography","LexicalComposer","RichTextPlugin","ContentEditable","LexicalErrorBoundary","HistoryPlugin","ListPlugin","CheckListPlugin","LinkPlugin","MarkdownShortcutPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"RichTextEditor-Bm8FFbcR.js","sources":["../src/components/RichTextEditor/urlSafety.ts","../src/components/RichTextEditor/nodes/ImageNode.tsx","../src/components/RichTextEditor/nodes/VideoNode.tsx","../src/components/RichTextEditor/Toolbar.tsx","../src/components/RichTextEditor/RichTextEditor.tsx"],"sourcesContent":["/**\n * URL-scheme allowlist for the RichTextEditor — the single defense against script-URL XSS\n * (`javascript:`, `vbscript:`, `data:text/html`, …) reaching the exported HTML value, whether a URL\n * arrives via the toolbar dialogs, a paste, or a loaded value. Rejected URLs are neutralized (an\n * empty `src`, or a `'#'` `href`) rather than executed.\n */\n\n// Link schemes we trust, plus relative/anchor/query starts (which carry no scheme at all).\nconst SAFE_LINK = /^(?:https?:|mailto:|tel:|ftp:|#|\\/|\\?|\\.)/i\n// Does the string begin with an explicit `scheme:` at all? (Anything schemeless is treated as relative.)\nconst HAS_SCHEME = /^[a-z][a-z0-9+.-]*:/i\n\n/**\n * Sanitize a link `href`: allow `http(s)`/`mailto`/`tel`/`ftp` and relative/anchor/query URLs; any\n * other explicit scheme (`javascript:`, `data:`, `vbscript:`, …) collapses to `'#'`.\n */\nexport function sanitizeLinkUrl(url: string): string {\n const trimmed = url.trim()\n if (trimmed === '') return ''\n if (SAFE_LINK.test(trimmed)) return trimmed\n if (!HAS_SCHEME.test(trimmed)) return trimmed // schemeless (e.g. `example.com/x`) → relative, safe\n return '#' // a disallowed scheme\n}\n\n/**\n * Sanitize an image/video `src`: like {@link sanitizeLinkUrl}, but also permits inline\n * `data:image`/`data:video` (upload embeds) and `blob:` object URLs. A disallowed scheme yields `''`.\n */\nexport function sanitizeMediaUrl(url: string): string {\n const trimmed = url.trim()\n if (/^data:(?:image|video)\\//i.test(trimmed) || /^blob:/i.test(trimmed)) return trimmed\n const safe = sanitizeLinkUrl(trimmed)\n return safe === '#' ? '' : safe\n}\n","import {\n $applyNodeReplacement,\n DecoratorNode,\n type DOMConversionMap,\n type DOMConversionOutput,\n type DOMExportOutput,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n type Spread,\n} from 'lexical'\nimport type { ReactNode } from 'react'\nimport { sanitizeMediaUrl } from '../urlSafety'\n\n/** Serialized shape of an {@link ImageNode} (editor-state JSON). */\nexport type SerializedImageNode = Spread<{ src: string; alt: string }, SerializedLexicalNode>\n\n/** Rebuilds an `ImageNode` from a pasted/loaded `<img>` element. */\nfunction convertImageElement(domNode: HTMLElement): DOMConversionOutput | null {\n if (domNode instanceof HTMLImageElement && domNode.src) {\n return { node: $createImageNode(domNode.getAttribute('src') ?? domNode.src, domNode.alt) }\n }\n return null\n}\n\n/**\n * A block-level image node. Renders a plain `<img>` (the `src` may be a remote URL or a base64\n * `data:` URL when inserted via upload). Serializes to a clean `<img src alt>` for the HTML value and\n * parses back from any `<img>` on paste/load.\n */\nexport class ImageNode extends DecoratorNode<ReactNode> {\n __src: string\n __alt: string\n\n static getType(): string {\n return 'tz-image'\n }\n\n static clone(node: ImageNode): ImageNode {\n return new ImageNode(node.__src, node.__alt, node.__key)\n }\n\n constructor(src: string, alt = '', key?: NodeKey) {\n super(key)\n // sanitize here so every path (insert, paste import, JSON load, clone) gets a safe scheme\n this.__src = sanitizeMediaUrl(src)\n this.__alt = alt\n }\n\n static importJSON(json: SerializedImageNode): ImageNode {\n return $createImageNode(json.src, json.alt)\n }\n\n exportJSON(): SerializedImageNode {\n return { ...super.exportJSON(), type: 'tz-image', version: 1, src: this.__src, alt: this.__alt }\n }\n\n static importDOM(): DOMConversionMap | null {\n return { img: () => ({ conversion: convertImageElement, priority: 0 }) }\n }\n\n exportDOM(): DOMExportOutput {\n const element = document.createElement('img')\n element.setAttribute('src', this.__src)\n element.setAttribute('alt', this.__alt)\n return { element }\n }\n\n /** A block wrapper; the actual `<img>` is rendered by {@link decorate}. */\n createDOM(): HTMLElement {\n const div = document.createElement('div')\n div.style.display = 'contents'\n return div\n }\n\n updateDOM(): false {\n return false\n }\n\n getSrc(): string {\n return this.__src\n }\n\n getAltText(): string {\n return this.__alt\n }\n\n decorate(): ReactNode {\n return <img src={this.__src} alt={this.__alt} draggable={false} />\n }\n}\n\n/** Creates an `ImageNode` (use inside an `editor.update`). */\nexport function $createImageNode(src: string, alt = ''): ImageNode {\n return $applyNodeReplacement(new ImageNode(src, alt))\n}\n\n/** Type guard for `ImageNode`. */\nexport function $isImageNode(node: LexicalNode | null | undefined): node is ImageNode {\n return node instanceof ImageNode\n}\n","import {\n $applyNodeReplacement,\n DecoratorNode,\n type DOMConversionMap,\n type DOMConversionOutput,\n type DOMExportOutput,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n type Spread,\n} from 'lexical'\nimport type { ReactNode } from 'react'\nimport { useT } from '../../../theme'\nimport { sanitizeMediaUrl } from '../urlSafety'\n\n/** Serialized shape of a {@link VideoNode} (editor-state JSON). */\nexport type SerializedVideoNode = Spread<{ src: string }, SerializedLexicalNode>\n\n/** A direct video file (rendered with `<video controls>` rather than an embed `<iframe>`). */\nfunction isFileVideo(src: string): boolean {\n return /\\.(mp4|webm|ogg|ogv|mov|m4v)(\\?.*)?$/i.test(src)\n}\n\n/**\n * Normalizes a pasted video URL into an embeddable one — YouTube/Vimeo watch links become their\n * `embed` form; everything else (incl. already-embed URLs and direct files) is returned unchanged,\n * so the conversion is idempotent across HTML round-trips.\n */\nexport function toVideoEmbedSrc(raw: string): string {\n const youtube = raw.match(\n /(?:youtube\\.com\\/(?:watch\\?(?:.*&)?v=|embed\\/|shorts\\/)|youtu\\.be\\/)([\\w-]{11})/,\n )\n if (youtube) return `https://www.youtube.com/embed/${youtube[1]}`\n const vimeo = raw.match(/vimeo\\.com\\/(?:video\\/)?(\\d+)/)\n if (vimeo) return `https://player.vimeo.com/video/${vimeo[1]}`\n return raw\n}\n\n/** Rebuilds a `VideoNode` from a pasted/loaded `<iframe>` or `<video>` element. */\nfunction convertVideoElement(domNode: HTMLElement): DOMConversionOutput | null {\n const src = domNode.getAttribute('src') || domNode.querySelector('source')?.getAttribute('src')\n if (src) return { node: $createVideoNode(src) }\n return null\n}\n\n/**\n * A block-level video node. Direct media files render with `<video controls>`; everything else is\n * treated as an embed and renders in a responsive `<iframe>` (YouTube/Vimeo links are normalized to\n * their embed URL). Serializes to a clean `<video>` / `<iframe>` for the HTML value.\n */\nexport class VideoNode extends DecoratorNode<ReactNode> {\n __src: string\n\n static getType(): string {\n return 'tz-video'\n }\n\n static clone(node: VideoNode): VideoNode {\n return new VideoNode(node.__src, node.__key)\n }\n\n constructor(src: string, key?: NodeKey) {\n super(key)\n // sanitize here so every path (insert, paste import, JSON load, clone) gets a safe scheme\n this.__src = sanitizeMediaUrl(src)\n }\n\n static importJSON(json: SerializedVideoNode): VideoNode {\n return $createVideoNode(json.src)\n }\n\n exportJSON(): SerializedVideoNode {\n return { ...super.exportJSON(), type: 'tz-video', version: 1, src: this.__src }\n }\n\n static importDOM(): DOMConversionMap | null {\n return {\n iframe: () => ({ conversion: convertVideoElement, priority: 0 }),\n video: () => ({ conversion: convertVideoElement, priority: 0 }),\n }\n }\n\n exportDOM(): DOMExportOutput {\n if (isFileVideo(this.__src)) {\n const video = document.createElement('video')\n video.setAttribute('src', this.__src)\n video.setAttribute('controls', 'true')\n return { element: video }\n }\n const iframe = document.createElement('iframe')\n iframe.setAttribute('src', this.__src)\n iframe.setAttribute('frameborder', '0')\n iframe.setAttribute('allowfullscreen', 'true')\n iframe.setAttribute(\n 'allow',\n 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',\n )\n return { element: iframe }\n }\n\n /** A block wrapper; the actual media element is rendered by {@link decorate}. */\n createDOM(): HTMLElement {\n const div = document.createElement('div')\n div.style.display = 'contents'\n return div\n }\n\n updateDOM(): false {\n return false\n }\n\n getSrc(): string {\n return this.__src\n }\n\n decorate(): ReactNode {\n if (isFileVideo(this.__src)) return <video src={this.__src} controls />\n return <VideoEmbed src={this.__src} />\n }\n}\n\n/** The in-editor embed `<iframe>` — a component so its `title` can be localized via `useT()`. */\nfunction VideoEmbed({ src }: { src: string }) {\n const t = useT()\n return (\n <div className=\"tz-rte-embed\">\n <iframe\n src={src}\n title={t('rte.embeddedVideo')}\n frameBorder={0}\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n />\n </div>\n )\n}\n\n/** Creates a `VideoNode`, normalizing the URL to an embeddable one (use inside an `editor.update`). */\nexport function $createVideoNode(src: string): VideoNode {\n return $applyNodeReplacement(new VideoNode(toVideoEmbedSrc(src)))\n}\n\n/** Type guard for `VideoNode`. */\nexport function $isVideoNode(node: LexicalNode | null | undefined): node is VideoNode {\n return node instanceof VideoNode\n}\n","import { useCallback, useEffect, useRef, useState, type ChangeEvent } from 'react'\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'\nimport {\n $createParagraphNode,\n $getSelection,\n $isElementNode,\n $isRangeSelection,\n CAN_REDO_COMMAND,\n CAN_UNDO_COMMAND,\n COMMAND_PRIORITY_LOW,\n FORMAT_ELEMENT_COMMAND,\n FORMAT_TEXT_COMMAND,\n REDO_COMMAND,\n SELECTION_CHANGE_COMMAND,\n UNDO_COMMAND,\n type ElementFormatType,\n type TextFormatType,\n} from 'lexical'\nimport {\n $createHeadingNode,\n $createQuoteNode,\n $isHeadingNode,\n $isQuoteNode,\n type HeadingTagType,\n} from '@lexical/rich-text'\nimport {\n INSERT_CHECK_LIST_COMMAND,\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n ListNode,\n REMOVE_LIST_COMMAND,\n} from '@lexical/list'\nimport { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link'\nimport { sanitizeLinkUrl } from './urlSafety'\nimport { toast } from '../Toast/toastStore'\nimport { useT, type MessageKey } from '../../theme'\nimport {\n $getSelectionStyleValueForProperty,\n $patchStyleText,\n $setBlocksType,\n} from '@lexical/selection'\nimport { $findMatchingParent, $getNearestNodeOfType, mergeRegister } from '@lexical/utils'\nimport { $insertNodeToNearestRoot } from '@lexical/utils'\nimport type { IconName } from '../../icons/names'\nimport { Button } from '../Button'\nimport { ColorPickerPanel, DEFAULT_SWATCHES } from '../ColorPicker/ColorPickerPanel'\nimport { Divider } from '../Divider'\nimport { Dropdown } from '../Dropdown'\nimport { FloatingPanel } from '../FloatingPanel/FloatingPanel'\nimport { Icon } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { ListItem } from '../List'\nimport { Modal } from '../Modal'\nimport { TextField } from '../TextField'\nimport { $createImageNode } from './nodes/ImageNode'\nimport { $createVideoNode } from './nodes/VideoNode'\nimport styles from './RichTextEditor.module.css'\n\ntype Size = 'sm' | 'md' | 'lg'\ntype BlockType = 'paragraph' | HeadingTagType | 'quote' | 'bullet' | 'number' | 'check'\n\n// Block-type labels stay **English in every language** by design — \"Paragraph\" / \"Heading\" are\n// editor-standard terms the maintainer prefers untranslated, so these are literals, not i18n keys.\nconst BLOCK_LABEL: Partial<Record<BlockType, string>> = {\n paragraph: 'Paragraph',\n h1: 'Heading 1',\n h2: 'Heading 2',\n h3: 'Heading 3',\n quote: 'Quote',\n bullet: 'Bullet List',\n number: 'Numbered List',\n check: 'Check List',\n}\n\n/** Items in the block-type dropdown — lists & quote are standalone toolbar buttons; check lists are excluded. */\nconst BLOCKS: { type: BlockType; icon?: IconName }[] = [\n { type: 'paragraph', icon: 'Text' },\n { type: 'h1', icon: 'Hashtag' },\n { type: 'h2', icon: 'Hashtag' },\n { type: 'h3', icon: 'Hashtag' },\n]\n\n/** Text-alignment controls (set the block element's `text-align`); `labelKey` resolves via `t`. */\nconst ALIGNS: { value: ElementFormatType; labelKey: MessageKey; icon: IconName }[] = [\n { value: 'left', labelKey: 'rte.alignLeft', icon: 'TextalignLeft' },\n { value: 'center', labelKey: 'rte.alignCenter', icon: 'TextalignCenter' },\n { value: 'right', labelKey: 'rte.alignRight', icon: 'TextalignRight' },\n]\n\n/** Font-size options (the `font-size` style value). */\nconst FONT_SIZES = ['10px', '12px', '14px', '16px', '18px', '20px']\n\n/** The editor's default content size per `size` (mirrors `.content` in the CSS) — shown active when the\n * selection has no explicit `font-size`. */\nconst DEFAULT_FONT_SIZE: Record<Size, string> = { sm: '12px', md: '14px', lg: '16px' }\n\n/** Config for the shared URL-input `Modal` (link / image-by-URL / video) — replaces `window.prompt`. */\ntype UrlDialog = {\n icon: IconName\n title: string\n label: string\n placeholder: string\n confirmLabel: string\n onConfirm: (url: string) => void\n}\n\n/** The text-color button glyph — a brush icon with a corner triangle tinted with the current text\n * color (so the selected color is always visible). Accepts the `size` `IconButton` injects so it\n * doesn't hit the DOM. */\nfunction ColorGlyph({ color, size }: { color: string; size?: Size }) {\n return (\n <span className={styles.colorGlyph}>\n <Icon name=\"Brush\" size={size} />\n <span\n className={styles.colorBar}\n style={{ borderColor: `transparent transparent ${color || 'currentColor'} transparent` }}\n aria-hidden=\"true\"\n />\n </span>\n )\n}\n\nexport interface ToolbarProps {\n size: Size\n disabled: boolean\n /** Optional async upload — when set, an inserted image uses the returned URL instead of a base64 data URL. */\n onImageUpload?: (file: File) => Promise<string>\n}\n\n/** The editor toolbar — reads the live selection and dispatches Lexical commands. */\nexport function Toolbar({ size, disabled, onImageUpload }: ToolbarProps) {\n const t = useT()\n const blockLabel = (b: BlockType): string => BLOCK_LABEL[b] ?? b // h4–h6 aren't offered by the editor\n const [editor] = useLexicalComposerContext()\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const [isBold, setIsBold] = useState(false)\n const [isItalic, setIsItalic] = useState(false)\n const [isUnderline, setIsUnderline] = useState(false)\n const [isLink, setIsLink] = useState(false)\n const [linkUrl, setLinkUrl] = useState('')\n const [blockType, setBlockType] = useState<BlockType>('paragraph')\n const [elementFormat, setElementFormat] = useState<ElementFormatType>('left')\n const [fontSize, setFontSize] = useState('')\n const [textColor, setTextColor] = useState('')\n const [colorOpen, setColorOpen] = useState(false)\n const colorTriggerRef = useRef<HTMLButtonElement | null>(null)\n const [canUndo, setCanUndo] = useState(false)\n const [canRedo, setCanRedo] = useState(false)\n // shared URL-input modal (link / image-by-URL / video)\n const [urlDialog, setUrlDialog] = useState<UrlDialog | null>(null)\n const [urlValue, setUrlValue] = useState('')\n\n const syncState = useCallback(() => {\n const selection = $getSelection()\n if (!$isRangeSelection(selection)) return\n setIsBold(selection.hasFormat('bold'))\n setIsItalic(selection.hasFormat('italic'))\n setIsUnderline(selection.hasFormat('underline'))\n setTextColor($getSelectionStyleValueForProperty(selection, 'color', ''))\n setFontSize($getSelectionStyleValueForProperty(selection, 'font-size', ''))\n\n const anchorNode = selection.anchor.getNode()\n const parent = anchorNode.getParent()\n const linkNode = $isLinkNode(anchorNode) ? anchorNode : $isLinkNode(parent) ? parent : null\n setIsLink(linkNode !== null)\n setLinkUrl(linkNode?.getURL() ?? '')\n\n // the block element under the cursor — drives both the alignment and block-type state\n const element =\n anchorNode.getKey() === 'root'\n ? anchorNode\n : ($findMatchingParent(anchorNode, (e) => {\n const parent = e.getParent()\n return parent === null || parent.getKey() === 'root'\n }) ?? anchorNode.getTopLevelElement())\n\n setElementFormat(($isElementNode(element) && element.getFormatType()) || 'left')\n\n const listNode = $getNearestNodeOfType(anchorNode, ListNode)\n if (listNode) setBlockType(listNode.getListType())\n else if ($isHeadingNode(element)) setBlockType(element.getTag())\n else if ($isQuoteNode(element)) setBlockType('quote')\n else setBlockType('paragraph')\n }, [])\n\n useEffect(() => {\n return mergeRegister(\n editor.registerUpdateListener(({ editorState }) => editorState.read(syncState)),\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n syncState()\n return false\n },\n COMMAND_PRIORITY_LOW,\n ),\n editor.registerCommand(\n CAN_UNDO_COMMAND,\n (payload) => {\n setCanUndo(payload)\n return false\n },\n COMMAND_PRIORITY_LOW,\n ),\n editor.registerCommand(\n CAN_REDO_COMMAND,\n (payload) => {\n setCanRedo(payload)\n return false\n },\n COMMAND_PRIORITY_LOW,\n ),\n )\n }, [editor, syncState])\n\n const format = (type: TextFormatType) => editor.dispatchCommand(FORMAT_TEXT_COMMAND, type)\n\n const applyAlign = (fmt: ElementFormatType) => editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, fmt)\n\n // apply the picked color to the (retained) selection; `''` clears it back to the default\n const applyColor = (color: string) => {\n setTextColor(color)\n editor.update(() => {\n const selection = $getSelection()\n if ($isRangeSelection(selection)) $patchStyleText(selection, { color: color || null })\n })\n }\n\n // apply a font size to the (retained) selection; `''` clears it back to the editor default\n const applyFontSize = (value: string) => {\n setFontSize(value)\n editor.update(() => {\n const selection = $getSelection()\n if ($isRangeSelection(selection)) $patchStyleText(selection, { 'font-size': value || null })\n })\n }\n\n const applyBlock = (type: BlockType) => {\n if (type === 'bullet' || type === 'number' || type === 'check') {\n if (blockType === type) {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined)\n } else {\n const command =\n type === 'bullet'\n ? INSERT_UNORDERED_LIST_COMMAND\n : type === 'number'\n ? INSERT_ORDERED_LIST_COMMAND\n : INSERT_CHECK_LIST_COMMAND\n editor.dispatchCommand(command, undefined)\n }\n return\n }\n editor.update(() => {\n const selection = $getSelection()\n if (!$isRangeSelection(selection)) return\n if (type === 'paragraph') $setBlocksType(selection, () => $createParagraphNode())\n else if (type === 'quote') $setBlocksType(selection, () => $createQuoteNode())\n else $setBlocksType(selection, () => $createHeadingNode(type))\n })\n }\n\n const toggleQuote = () => applyBlock(blockType === 'quote' ? 'paragraph' : 'quote')\n\n // open the shared URL modal (prefilled value + handler differ per action)\n const openUrlDialog = (config: UrlDialog, initial = '') => {\n setUrlValue(initial)\n setUrlDialog(config)\n }\n const closeUrlDialog = () => setUrlDialog(null)\n const confirmUrlDialog = () => {\n urlDialog?.onConfirm(urlValue.trim())\n setUrlDialog(null)\n }\n\n const insertLink = () =>\n openUrlDialog(\n {\n icon: 'Link2',\n title: t('rte.linkTitle'),\n label: t('rte.linkUrl'),\n placeholder: 'https://example.com',\n confirmLabel: isLink ? t('common.update') : t('common.insert'),\n // an empty value removes the link (matches the old prompt behavior); sanitize the scheme\n onConfirm: (url) =>\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, url === '' ? null : sanitizeLinkUrl(url)),\n },\n linkUrl, // prefill the current link's URL when the cursor sits in one\n )\n\n const insertImageByUrl = () =>\n openUrlDialog({\n icon: 'GalleryAdd',\n title: t('rte.imageTitle'),\n label: t('rte.imageUrl'),\n placeholder: 'https://example.com/image.jpg',\n confirmLabel: t('common.insert'),\n onConfirm: (url) => {\n if (url) editor.update(() => $insertNodeToNearestRoot($createImageNode(url)))\n },\n })\n\n const onImageFile = async (event: ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0]\n event.target.value = '' // allow re-picking the same file\n if (!file) return\n try {\n const url = onImageUpload ? await onImageUpload(file) : await fileToDataUrl(file)\n editor.update(() => $insertNodeToNearestRoot($createImageNode(url, file.name)))\n } catch {\n // a rejecting consumer upload handler (or a failed data-URL read) shouldn't fail silently\n toast.error(t('rte.imageError'))\n }\n }\n\n const insertVideo = () =>\n openUrlDialog({\n icon: 'VideoSquare',\n title: t('rte.videoTitle'),\n label: t('rte.videoUrl'),\n placeholder: t('rte.videoUrlPlaceholder'),\n confirmLabel: t('common.insert'),\n onConfirm: (url) => {\n if (url) editor.update(() => $insertNodeToNearestRoot($createVideoNode(url)))\n },\n })\n\n /** A format toggle — soft-filled while active. */\n const fmtBtn = (\n active: boolean,\n label: string,\n onClick: () => void,\n child: React.ReactNode,\n key?: string,\n ) => (\n <IconButton\n key={key}\n variant={active ? 'filled' : 'text'}\n color=\"primary\"\n size={size}\n disabled={disabled}\n aria-label={label}\n aria-pressed={active}\n onMouseDown={(e) => e.preventDefault()} // keep focus/selection in the editor\n onClick={onClick}\n >\n {child}\n </IconButton>\n )\n\n // the block dropdown only manages Paragraph / Headings — lists & quote are separate toggle buttons,\n // so when the cursor is in a list/quote/check the trigger shows \"Paragraph\", not e.g. \"Bullet List\".\n const dropdownBlock: BlockType = blockType.startsWith('h') ? blockType : 'paragraph'\n\n // font-size shown active: the selection's explicit size, else the editor's default for this `size`\n const effectiveFontSize = fontSize || DEFAULT_FONT_SIZE[size]\n\n return (\n <div\n className={styles.toolbar}\n role=\"toolbar\"\n aria-label={t('rte.formatting')}\n aria-orientation=\"horizontal\"\n >\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled || !canUndo}\n aria-label={t('rte.undo')}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => editor.dispatchCommand(UNDO_COMMAND, undefined)}\n >\n <Icon name=\"UndoArrow\" />\n </IconButton>\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled || !canRedo}\n aria-label={t('rte.redo')}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => editor.dispatchCommand(REDO_COMMAND, undefined)}\n >\n <Icon name=\"RedoArrow\" />\n </IconButton>\n\n <Divider orientation=\"vertical\" />\n\n <Dropdown\n size={size}\n disabled={disabled}\n minWidth={false}\n trigger={\n <Button\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n endIcon={<Icon name=\"ArrowDown4\" />}\n aria-label={t('rte.fontSize')}\n onMouseDown={(e) => e.preventDefault()} // keep the selection while opening\n >\n {effectiveFontSize}\n </Button>\n }\n >\n {FONT_SIZES.map((f) => (\n <ListItem\n key={f}\n clickable\n selected={f === effectiveFontSize}\n onClick={() => applyFontSize(f)}\n >\n {f}\n </ListItem>\n ))}\n </Dropdown>\n\n <Divider orientation=\"vertical\" />\n\n <Dropdown\n size={size}\n disabled={disabled}\n trigger={\n <Button\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n endIcon={<Icon name=\"ArrowDown4\" />}\n onMouseDown={(e) => e.preventDefault()} // keep the selection while opening\n >\n {blockLabel(dropdownBlock)}\n </Button>\n }\n >\n {BLOCKS.map((b) => (\n <ListItem\n key={b.type}\n clickable\n selected={dropdownBlock === b.type}\n icon={b.icon}\n onClick={() => applyBlock(b.type)}\n >\n {blockLabel(b.type)}\n </ListItem>\n ))}\n </Dropdown>\n\n <Divider orientation=\"vertical\" />\n\n {fmtBtn(isBold, t('rte.bold'), () => format('bold'), <Icon name=\"TextBold\" />)}\n {fmtBtn(isItalic, t('rte.italic'), () => format('italic'), <Icon name=\"TextItalic\" />)}\n {fmtBtn(\n isUnderline,\n t('rte.underline'),\n () => format('underline'),\n <Icon name=\"TextUnderline\" />,\n )}\n\n <Divider orientation=\"vertical\" />\n\n {fmtBtn(\n blockType === 'bullet',\n t('rte.bulletList'),\n () => applyBlock('bullet'),\n <Icon name=\"ListBullet\" />,\n )}\n {fmtBtn(\n blockType === 'number',\n t('rte.numberedList'),\n () => applyBlock('number'),\n <Icon name=\"ListNumber\" />,\n )}\n {fmtBtn(blockType === 'quote', t('rte.quote'), toggleQuote, <Icon name=\"QuoteUp\" />)}\n\n <Divider orientation=\"vertical\" />\n\n {ALIGNS.map((a) =>\n fmtBtn(\n elementFormat === a.value,\n t(a.labelKey),\n () => applyAlign(a.value),\n <Icon name={a.icon} />,\n a.value,\n ),\n )}\n\n <Divider orientation=\"vertical\" />\n\n <IconButton\n ref={colorTriggerRef}\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n aria-label={t('rte.textColor')}\n aria-expanded={colorOpen}\n onMouseDown={(e) => e.preventDefault()} // keep the editor's selection while opening\n onClick={() => setColorOpen((o) => !o)}\n >\n <ColorGlyph color={textColor} />\n </IconButton>\n <FloatingPanel\n open={colorOpen}\n triggerRef={colorTriggerRef}\n onClose={(refocus) => {\n setColorOpen(false)\n if (refocus) colorTriggerRef.current?.focus()\n }}\n role=\"dialog\"\n ariaLabel={t('rte.textColor')}\n width={232}\n >\n {/* no \"no color\" swatch; with no explicit color the accent default (first swatch) shows selected */}\n <ColorPickerPanel\n value={textColor || DEFAULT_SWATCHES[0]}\n onChange={applyColor}\n clearable={false}\n />\n </FloatingPanel>\n\n {fmtBtn(isLink, t('rte.link'), insertLink, <Icon name=\"Link2\" />)}\n\n <Dropdown\n size={size}\n disabled={disabled}\n minWidth={false}\n trigger={\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n aria-label={t('rte.insertImage')}\n >\n <Icon name=\"GalleryAdd\" />\n </IconButton>\n }\n >\n <ListItem clickable icon=\"GalleryImport\" onClick={() => fileInputRef.current?.click()}>\n {t('rte.uploadImage')}\n </ListItem>\n <ListItem clickable icon=\"Link\" onClick={insertImageByUrl}>\n {t('rte.imageByUrl')}\n </ListItem>\n </Dropdown>\n\n <IconButton\n variant=\"text\"\n color=\"primary\"\n size={size}\n disabled={disabled}\n aria-label={t('rte.insertVideo')}\n onClick={insertVideo}\n >\n <Icon name=\"VideoSquare\" />\n </IconButton>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n hidden\n onChange={onImageFile}\n aria-hidden=\"true\"\n tabIndex={-1}\n />\n\n {/* shared URL-input dialog for link / image-by-URL / video (replaces window.prompt). The footer\n Submit drives the body <form> via the `form` attribute (works across the modal's portal). */}\n <Modal\n open={urlDialog !== null}\n onClose={closeUrlDialog}\n size=\"sm\"\n icon={urlDialog?.icon}\n title={urlDialog?.title}\n footer={\n <>\n <Button variant=\"text\" onClick={closeUrlDialog}>\n {t('common.cancel')}\n </Button>\n <Button type=\"submit\" form=\"rte-url-form\">\n {urlDialog?.confirmLabel ?? t('common.insert')}\n </Button>\n </>\n }\n >\n <form\n id=\"rte-url-form\"\n onSubmit={(e) => {\n e.preventDefault()\n confirmUrlDialog()\n }}\n >\n <TextField\n label={urlDialog?.label}\n placeholder={urlDialog?.placeholder}\n value={urlValue}\n onChange={(e) => setUrlValue(e.target.value)}\n />\n </form>\n </Modal>\n </div>\n )\n}\n\n/** Reads a picked file into a base64 `data:` URL (the no-backend default for image upload). */\nfunction fileToDataUrl(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(reader.result as string)\n reader.onerror = () => reject(reader.error)\n reader.readAsDataURL(file)\n })\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useRef,\n type CSSProperties,\n type FocusEvent,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport {\n $createParagraphNode,\n $getRoot,\n $insertNodes,\n $isParagraphNode,\n $setSelection,\n type EditorThemeClasses,\n} from 'lexical'\nimport { LexicalComposer } from '@lexical/react/LexicalComposer'\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'\nimport { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable'\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'\nimport { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'\nimport { ListPlugin } from '@lexical/react/LexicalListPlugin'\nimport { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'\nimport { LinkPlugin } from '@lexical/react/LexicalLinkPlugin'\nimport { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin'\nimport {\n ELEMENT_TRANSFORMERS,\n TEXT_FORMAT_TRANSFORMERS,\n TEXT_MATCH_TRANSFORMERS,\n} from '@lexical/markdown'\nimport { HeadingNode, QuoteNode } from '@lexical/rich-text'\nimport { ListItemNode, ListNode } from '@lexical/list'\nimport { LinkNode } from '@lexical/link'\nimport { sanitizeLinkUrl } from './urlSafety'\nimport { $generateHtmlFromNodes, $generateNodesFromDOM } from '@lexical/html'\nimport { useT } from '../../theme'\nimport { useFormContext } from '../../form/formContext'\nimport { Typography } from '../Typography'\nimport { Toolbar } from './Toolbar'\nimport { ImageNode } from './nodes/ImageNode'\nimport { VideoNode } from './nodes/VideoNode'\nimport styles from './RichTextEditor.module.css'\n\nexport type RichTextEditorSize = 'sm' | 'md' | 'lg'\n\n/** Lexical node-type → CSS-module class map (so content is styled with `--tz-*` tokens). */\nconst THEME: EditorThemeClasses = {\n paragraph: styles.paragraph,\n heading: {\n h1: styles.h1,\n h2: styles.h2,\n h3: styles.h3,\n h4: styles.h4,\n h5: styles.h5,\n h6: styles.h6,\n },\n quote: styles.quote,\n list: {\n ul: styles.ul,\n ol: styles.ol,\n listitem: styles.li,\n listitemChecked: styles.liChecked,\n listitemUnchecked: styles.liUnchecked,\n nested: { listitem: styles.nestedLi },\n },\n link: styles.link,\n text: {\n bold: styles.bold,\n italic: styles.italic,\n underline: styles.underline,\n strikethrough: styles.strike,\n code: styles.codeInline,\n },\n}\n\nconst EDITOR_NODES = [\n HeadingNode,\n QuoteNode,\n ListNode,\n ListItemNode,\n LinkNode,\n ImageNode,\n VideoNode,\n]\n\n/**\n * Markdown shortcuts for headings/quote/lists + inline formats + links. Excludes the multiline\n * fenced-code-block transformer (it needs `CodeNode`, which is out of scope for v1).\n */\nconst MARKDOWN_TRANSFORMERS = [\n ...ELEMENT_TRANSFORMERS,\n ...TEXT_FORMAT_TRANSFORMERS,\n ...TEXT_MATCH_TRANSFORMERS,\n]\n\n/**\n * Strips the editor's (hashed, CSS-module) `class` attributes from exported HTML so the value is clean,\n * portable markup (`<h2>` not `<h2 class=\"_h2_ab12\">`). Classes aren't needed to re-import — parsing\n * keys off tag names — so this is round-trip-safe.\n */\nfunction cleanExportedHtml(html: string): string {\n if (typeof document === 'undefined') return html\n const template = document.createElement('template')\n template.innerHTML = html\n template.content.querySelectorAll('[class]').forEach((el) => el.removeAttribute('class'))\n return template.innerHTML\n}\n\n/**\n * True when the editor holds nothing but an empty paragraph (Lexical's \"blank\" state, which serializes\n * to `<p><br></p>`). Lets the value emit `''` instead, so a cleared editor reads as truly empty (and a\n * `required` rule fires). Call inside an `editor.read`/`update`.\n */\nfunction $isEditorEmpty(): boolean {\n const root = $getRoot()\n const first = root.getFirstChild()\n return (\n root.getChildrenSize() <= 1 &&\n (first === null || ($isParagraphNode(first) && first.getChildrenSize() === 0))\n )\n}\n\n/** Replaces the editor's content with the nodes parsed from an HTML string (call inside `editor.update`). */\nfunction $setRootFromHtml(editor: Parameters<typeof $generateNodesFromDOM>[0], html: string) {\n const root = $getRoot()\n root.clear()\n if (html) {\n const dom = new DOMParser().parseFromString(html, 'text/html')\n const nodes = $generateNodesFromDOM(editor, dom)\n root.select()\n $insertNodes(nodes)\n }\n if (root.getChildrenSize() === 0) root.append($createParagraphNode())\n // clear the caret the insert left at the end of the content — otherwise Lexical scrolls it into\n // view when setting the initial/controlled value on mount, dragging the whole page down to a\n // below-the-fold editor (e.g. the prefilled RTEs on the Edit form). Focus re-places it later.\n $setSelection(null)\n}\n\ninterface ValuePluginProps {\n value?: string\n defaultValue?: string\n onChange: (html: string) => void\n disabled: boolean\n}\n\n/** Bridges the HTML `value` ↔ the Lexical editor state, and toggles read-only mode. */\nfunction ValuePlugin({ value, defaultValue, onChange, disabled }: ValuePluginProps) {\n const [editor] = useLexicalComposerContext()\n // the last HTML we wrote-in or emitted-out — guards the controlled-sync ↔ onChange feedback loop\n const lastHtml = useRef<string | undefined>(undefined)\n const onChangeRef = useRef(onChange)\n onChangeRef.current = onChange\n\n useEffect(() => editor.setEditable(!disabled), [editor, disabled])\n\n // neutralize unsafe link schemes (javascript:, data:, …) on every LinkNode — covers pasted anchors\n // as well as toolbar inserts (which are also pre-sanitized), so no script URL survives into the value\n useEffect(\n () =>\n editor.registerNodeTransform(LinkNode, (node) => {\n const url = node.getURL()\n const safe = sanitizeLinkUrl(url)\n if (safe !== url) node.setURL(safe)\n }),\n [editor],\n )\n\n // initial defaultValue (uncontrolled) — once\n useEffect(() => {\n if (value !== undefined || !defaultValue) return\n lastHtml.current = defaultValue\n editor.update(() => $setRootFromHtml(editor, defaultValue), { tag: 'history-merge' })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // controlled value → editor (only on a genuine external change, not our own echo)\n useEffect(() => {\n if (value === undefined || value === lastHtml.current) return\n lastHtml.current = value\n editor.update(() => $setRootFromHtml(editor, value), { tag: 'history-merge' })\n }, [editor, value])\n\n // editor → HTML out. NB: must be `editor.read` (not `editorState.read`) so the active editor is\n // bound — `$generateHtmlFromNodes` → node `createDOM` needs it, else it throws \"no active editor\".\n useEffect(\n () =>\n editor.registerUpdateListener(({ dirtyElements, dirtyLeaves }) => {\n if (dirtyElements.size === 0 && dirtyLeaves.size === 0) return\n editor.read(() => {\n const html = $isEditorEmpty()\n ? ''\n : cleanExportedHtml($generateHtmlFromNodes(editor, null))\n if (html === lastHtml.current) return\n lastHtml.current = html\n onChangeRef.current(html)\n })\n }),\n [editor],\n )\n\n return null\n}\n\nexport interface RichTextEditorProps {\n /** Label rendered above the editor. */\n label?: ReactNode\n /** Preset size — drives toolbar density, content font size and min-height. */\n size?: RichTextEditorSize\n /** Marks the field invalid: red border/ring and `helperText` in the error color. */\n error?: boolean\n /** Helper / validation text under the editor. Adopts the error color while `error`. */\n helperText?: ReactNode\n /** Adds a red asterisk after the label (visual hint). */\n required?: boolean\n /** Read-only mode — the toolbar disables and the content isn't editable. */\n disabled?: boolean\n /** Placeholder shown while the editor is empty. */\n placeholder?: string\n /** Form field name — auto-binds value/validation to a surrounding `<Form>` (value = the HTML string). */\n name?: string\n /** Controlled HTML value. */\n value?: string\n /** Initial HTML value (uncontrolled). */\n defaultValue?: string\n /** Fires with the serialized **HTML** on every edit. */\n onChange?: (html: string) => void\n /**\n * Async image upload. When provided, an uploaded image is sent through this and the returned URL is\n * inserted; when omitted, the image is embedded inline as a base64 `data:` URL (no backend needed).\n */\n onImageUpload?: (file: File) => Promise<string>\n /** Min height of the editable area in px. Defaults to `220`. */\n minHeight?: number\n /** Accessible label for the editable region. Defaults to `'Rich text editor'`. */\n 'aria-label'?: string\n className?: string\n style?: CSSProperties\n}\n\n/**\n * A rich text editor built on **Lexical** (an optional peer — install `lexical` + `@lexical/*`). Its\n * value is an **HTML string**: bold/italic/underline/strikethrough/inline-code, headings, lists\n * (bullet/ordered/check), links, block quote, plus **images** (insert by URL or upload — embedded as a\n * base64 `data:` URL unless an `onImageUpload` handler is given) and **video** embeds (paste a\n * YouTube/Vimeo/file URL). Markdown shortcuts work while typing (`# `, `- `, `> `, …). The toolbar is\n * built from the library's own `IconButton`/`Button`/`Dropdown`, and the content is styled entirely\n * with `--tz-*` tokens. Controlled (`value` + `onChange`) or uncontrolled (`defaultValue`); inside a\n * `<Form>`, a `name` prop auto-binds the HTML value (validate with e.g. `z.string().min(1)`).\n */\nexport const RichTextEditor = forwardRef<HTMLDivElement, RichTextEditorProps>(\n function RichTextEditor(\n {\n label,\n size = 'md',\n error,\n helperText,\n required = false,\n disabled = false,\n placeholder,\n name,\n value,\n defaultValue,\n onChange,\n onImageUpload,\n minHeight = 220,\n 'aria-label': ariaLabel = 'Rich text editor',\n className,\n style,\n },\n ref,\n ) {\n const t = useT()\n const form = useFormContext()\n const bound = form && name ? form.field(name) : undefined\n const resolvedError = error ?? bound?.error ?? false\n const resolvedHelperText = helperText ?? bound?.helperText\n\n const formValue = form && name ? (form.values as Record<string, unknown>)[name] : undefined\n const effValue =\n value !== undefined ? value : form && name ? String(formValue ?? '') : undefined\n\n const handleChange = useCallback(\n (html: string) => {\n if (form && name) form.setValue(name, html as never)\n onChange?.(html)\n },\n [form, name, onChange],\n )\n\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => bound?.onBlur(event as never)\n\n // Mirror the form `name` onto the editable DOM node so a `<Form>`'s scroll-to-error can find and\n // focus it — the contenteditable isn't an `<input>`, and Lexical's `ContentEditable` doesn't take\n // a `name` prop, so set the attribute imperatively via a ref.\n const contentRef = useRef<HTMLDivElement | null>(null)\n useEffect(() => {\n const el = contentRef.current\n if (!el) return\n if (name) el.setAttribute('name', name)\n else el.removeAttribute('name')\n }, [name])\n\n const initialConfig = {\n namespace: 'tz-rich-text-editor',\n theme: THEME,\n nodes: EDITOR_NODES,\n editable: !disabled,\n onError: (e: Error) => {\n throw e\n },\n }\n\n return (\n <div\n ref={ref}\n className={clsx(\n styles.editor,\n styles[size],\n resolvedError && styles.error,\n disabled && styles.disabled,\n className,\n )}\n style={{ '--tz-rte-min-height': `${minHeight}px`, ...style } as CSSProperties}\n >\n {label != null && (\n <div className={styles.label}>\n <Typography as=\"span\" variant=\"bodySmall\" color=\"muted\">\n {label}\n </Typography>\n {required && (\n <span className={styles.required} aria-hidden=\"true\">\n *\n </span>\n )}\n </div>\n )}\n\n <div className={styles.control}>\n <LexicalComposer initialConfig={initialConfig}>\n <Toolbar size={size} disabled={disabled} onImageUpload={onImageUpload} />\n <div className={styles.shell}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n ref={contentRef}\n className={styles.content}\n aria-label={ariaLabel}\n aria-invalid={resolvedError || undefined}\n onBlur={handleBlur}\n />\n }\n placeholder={\n <div className={styles.placeholder}>{placeholder ?? t('rte.placeholder')}</div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n </div>\n <HistoryPlugin />\n <ListPlugin />\n <CheckListPlugin />\n <LinkPlugin />\n <MarkdownShortcutPlugin transformers={MARKDOWN_TRANSFORMERS} />\n <ValuePlugin\n value={effValue}\n defaultValue={defaultValue}\n onChange={handleChange}\n disabled={disabled}\n />\n </LexicalComposer>\n </div>\n\n {resolvedHelperText != null && (\n <Typography\n as=\"span\"\n variant=\"bodySmall\"\n color={resolvedError ? 'error' : 'muted'}\n className={styles.helper}\n >\n {resolvedHelperText}\n </Typography>\n )}\n </div>\n )\n },\n)\n"],"names":["SAFE_LINK","HAS_SCHEME","sanitizeLinkUrl","url","trimmed","sanitizeMediaUrl","safe","convertImageElement","domNode","$createImageNode","ImageNode","DecoratorNode","node","src","alt","key","json","element","div","jsx","$applyNodeReplacement","isFileVideo","toVideoEmbedSrc","raw","youtube","vimeo","convertVideoElement","_a","$createVideoNode","VideoNode","video","iframe","VideoEmbed","useT","BLOCK_LABEL","BLOCKS","ALIGNS","FONT_SIZES","DEFAULT_FONT_SIZE","ColorGlyph","color","size","jsxs","styles","Icon","Toolbar","disabled","onImageUpload","t","blockLabel","b","editor","useLexicalComposerContext","fileInputRef","useRef","isBold","setIsBold","useState","isItalic","setIsItalic","isUnderline","setIsUnderline","isLink","setIsLink","linkUrl","setLinkUrl","blockType","setBlockType","elementFormat","setElementFormat","fontSize","setFontSize","textColor","setTextColor","colorOpen","setColorOpen","colorTriggerRef","canUndo","setCanUndo","canRedo","setCanRedo","urlDialog","setUrlDialog","urlValue","setUrlValue","syncState","useCallback","selection","$getSelection","$isRangeSelection","$getSelectionStyleValueForProperty","anchorNode","parent","linkNode","$isLinkNode","$findMatchingParent","e","$isElementNode","listNode","$getNearestNodeOfType","ListNode","$isHeadingNode","$isQuoteNode","useEffect","mergeRegister","editorState","SELECTION_CHANGE_COMMAND","COMMAND_PRIORITY_LOW","CAN_UNDO_COMMAND","payload","CAN_REDO_COMMAND","format","type","FORMAT_TEXT_COMMAND","applyAlign","fmt","FORMAT_ELEMENT_COMMAND","applyColor","$patchStyleText","applyFontSize","value","applyBlock","REMOVE_LIST_COMMAND","command","INSERT_UNORDERED_LIST_COMMAND","INSERT_ORDERED_LIST_COMMAND","INSERT_CHECK_LIST_COMMAND","$setBlocksType","$createParagraphNode","$createQuoteNode","$createHeadingNode","toggleQuote","openUrlDialog","config","initial","closeUrlDialog","confirmUrlDialog","insertLink","TOGGLE_LINK_COMMAND","insertImageByUrl","$insertNodeToNearestRoot","onImageFile","event","file","fileToDataUrl","toast","insertVideo","fmtBtn","active","label","onClick","child","IconButton","dropdownBlock","effectiveFontSize","UNDO_COMMAND","REDO_COMMAND","Divider","Dropdown","Button","f","ListItem","a","o","FloatingPanel","refocus","ColorPickerPanel","DEFAULT_SWATCHES","Modal","Fragment","TextField","resolve","reject","reader","THEME","EDITOR_NODES","HeadingNode","QuoteNode","ListItemNode","LinkNode","MARKDOWN_TRANSFORMERS","ELEMENT_TRANSFORMERS","TEXT_FORMAT_TRANSFORMERS","TEXT_MATCH_TRANSFORMERS","cleanExportedHtml","html","template","el","$isEditorEmpty","root","$getRoot","first","$isParagraphNode","$setRootFromHtml","dom","nodes","$generateNodesFromDOM","$insertNodes","$setSelection","ValuePlugin","defaultValue","onChange","lastHtml","onChangeRef","dirtyElements","dirtyLeaves","$generateHtmlFromNodes","RichTextEditor","forwardRef","error","helperText","required","placeholder","name","minHeight","ariaLabel","className","style","ref","form","useFormContext","bound","resolvedError","resolvedHelperText","formValue","effValue","handleChange","handleBlur","contentRef","initialConfig","clsx","Typography","LexicalComposer","RichTextPlugin","ContentEditable","LexicalErrorBoundary","HistoryPlugin","ListPlugin","CheckListPlugin","LinkPlugin","MarkdownShortcutPlugin"],"mappings":"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"}