@customafk/lunas-ui 0.2.83 → 0.2.85
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.
- package/dist/LoginPage-DGgThT3s.mjs +2 -0
- package/dist/LoginPage-DGgThT3s.mjs.map +1 -0
- package/dist/LoginPage-DPUdRD0r.cjs +2 -0
- package/dist/LoginPage-DPUdRD0r.cjs.map +1 -0
- package/dist/action-submit-B2qFdfi6.cjs +2 -0
- package/dist/{action-submit-B9vHpLoN.cjs.map → action-submit-B2qFdfi6.cjs.map} +1 -1
- package/dist/action-submit-DyNvI-F2.mjs +2 -0
- package/dist/{action-submit-BQdkz4mS.mjs.map → action-submit-DyNvI-F2.mjs.map} +1 -1
- package/dist/actions-form-CB0lZlE6.mjs +2 -0
- package/dist/{actions-form-D4n1W3-X.mjs.map → actions-form-CB0lZlE6.mjs.map} +1 -1
- package/dist/actions-form-DnlpVrgF.cjs +2 -0
- package/dist/{actions-form-DF2eYxGQ.cjs.map → actions-form-DnlpVrgF.cjs.map} +1 -1
- package/dist/checkbox-field-CFPHAcwN.cjs +2 -0
- package/dist/{checkbox-field-ldZRSCca.cjs.map → checkbox-field-CFPHAcwN.cjs.map} +1 -1
- package/dist/checkbox-field-DodKeFS_.mjs +2 -0
- package/dist/{checkbox-field-BRGTLOjq.mjs.map → checkbox-field-DodKeFS_.mjs.map} +1 -1
- package/dist/{cms-layout-BGsf1E4E.cjs → cms-layout-DYEmSqzx.cjs} +2 -2
- package/dist/{cms-layout-BGsf1E4E.cjs.map → cms-layout-DYEmSqzx.cjs.map} +1 -1
- package/dist/combobox-field-D7cZ8fhZ.cjs +2 -0
- package/dist/{combobox-field-ZYr7636s.cjs.map → combobox-field-D7cZ8fhZ.cjs.map} +1 -1
- package/dist/combobox-field-ebIvbhJn.mjs +2 -0
- package/dist/{combobox-field-CvkdZkQE.mjs.map → combobox-field-ebIvbhJn.mjs.map} +1 -1
- package/dist/data-display/country.cjs +1 -1
- package/dist/date-field-CNkxebta.mjs +2 -0
- package/dist/{date-field-DGMTG_hu.mjs.map → date-field-CNkxebta.mjs.map} +1 -1
- package/dist/date-field-Dm367ro9.cjs +2 -0
- package/dist/{date-field-1Hmcv8Zp.cjs.map → date-field-Dm367ro9.cjs.map} +1 -1
- package/dist/dialog-form-D9Bifsx6.cjs +2 -0
- package/dist/{dialog-form-C1qpltYx.cjs.map → dialog-form-D9Bifsx6.cjs.map} +1 -1
- package/dist/dialog-form-zK6Gk9Gk.mjs +2 -0
- package/dist/{dialog-form-BRSZpRTC.mjs.map → dialog-form-zK6Gk9Gk.mjs.map} +1 -1
- package/dist/{dist-DzA--RwW.cjs → dist-CIdWHwhj.cjs} +2 -2
- package/dist/{dist-DzA--RwW.cjs.map → dist-CIdWHwhj.cjs.map} +1 -1
- package/dist/email-field-BVl7u9pR.mjs +2 -0
- package/dist/{email-field-C2Lvl_rQ.mjs.map → email-field-BVl7u9pR.mjs.map} +1 -1
- package/dist/email-field-CqXXRG3w.cjs +2 -0
- package/dist/{email-field-D3nSkHj2.cjs.map → email-field-CqXXRG3w.cjs.map} +1 -1
- package/dist/features/tables/index.d.cts +1 -1
- package/dist/features/tables/index.d.mts +1 -1
- package/dist/features/tanstack-form/index.cjs +1 -1
- package/dist/features/tanstack-form/index.d.cts +1 -1
- package/dist/features/tanstack-form/index.d.mts +1 -1
- package/dist/features/tanstack-form/index.mjs +1 -1
- package/dist/features/text-editor/index.cjs +1 -1
- package/dist/features/text-editor/index.d.cts +1 -1
- package/dist/features/text-editor/index.d.mts +1 -1
- package/dist/features/text-editor/index.mjs +1 -1
- package/dist/{flex-C63_IqSY.d.cts → flex-D6RCsrv1.d.cts} +2 -2
- package/dist/{flex-C63_IqSY.d.mts → flex-D6RCsrv1.d.mts} +2 -2
- package/dist/group-field-8nINgAeO.mjs +2 -0
- package/dist/{group-field-gejvx_Td.mjs.map → group-field-8nINgAeO.mjs.map} +1 -1
- package/dist/group-field-DfGPDLyp.cjs +2 -0
- package/dist/{group-field-sVykO2JZ.cjs.map → group-field-DfGPDLyp.cjs.map} +1 -1
- package/dist/{index-DvC1inRy.d.cts → index-0HuXxgjQ.d.cts} +13 -10
- package/dist/index-6_zytlWu.d.cts +70 -0
- package/dist/index-6_zytlWu.d.mts +70 -0
- package/dist/{index-CrkOhm--.d.mts → index-BCBEYTyA.d.mts} +5 -5
- package/dist/{index--wNkNzCB.d.cts → index-CQPyC0Q2.d.cts} +5 -5
- package/dist/{index-DvC1inRy.d.mts → index-CZ_2KVir.d.mts} +13 -10
- package/dist/{index-DRAyYm8g.d.mts → index-CvFEJoon.d.cts} +12 -3
- package/dist/{index-DRAyYm8g.d.cts → index-CvFEJoon.d.mts} +12 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +1 -1
- package/dist/layouts/cms-layout/index.cjs +1 -1
- package/dist/layouts/flex.d.cts +1 -1
- package/dist/layouts/flex.d.mts +1 -1
- package/dist/layouts/payment-layout/index.cjs +1 -1
- package/dist/number-field-BjGl_IiN.cjs +2 -0
- package/dist/{number-field-CWDYA3La.cjs.map → number-field-BjGl_IiN.cjs.map} +1 -1
- package/dist/number-field-CVemIwIg.mjs +2 -0
- package/dist/{number-field-CR5PLX6H.mjs.map → number-field-CVemIwIg.mjs.map} +1 -1
- package/dist/pages/LoginPage/index.cjs +1 -0
- package/dist/pages/LoginPage/index.d.cts +2 -0
- package/dist/pages/LoginPage/index.d.mts +2 -0
- package/dist/pages/LoginPage/index.mjs +1 -0
- package/dist/password-field-Be0Ltlxh.cjs +2 -0
- package/dist/{password-field-BHRhVyZ0.cjs.map → password-field-Be0Ltlxh.cjs.map} +1 -1
- package/dist/password-field-BxYaT8lO.mjs +2 -0
- package/dist/{password-field-B2_kzss6.mjs.map → password-field-BxYaT8lO.mjs.map} +1 -1
- package/dist/{payment-layout-BZtIcu-3.cjs → payment-layout-C38xIc2X.cjs} +2 -2
- package/dist/{payment-layout-BZtIcu-3.cjs.map → payment-layout-C38xIc2X.cjs.map} +1 -1
- package/dist/popover-form-Ba_Nw79b.cjs +2 -0
- package/dist/{popover-form-Ch_iMMSm.cjs.map → popover-form-Ba_Nw79b.cjs.map} +1 -1
- package/dist/popover-form-C9mNInr2.mjs +2 -0
- package/dist/{popover-form-CeRVpy1B.mjs.map → popover-form-C9mNInr2.mjs.map} +1 -1
- package/dist/radio-group-field-BCJWamjd.cjs +2 -0
- package/dist/{radio-group-field-BFhBfzoT.cjs.map → radio-group-field-BCJWamjd.cjs.map} +1 -1
- package/dist/radio-group-field-DYqU_6hW.mjs +2 -0
- package/dist/{radio-group-field-Iwo2Q2Ig.mjs.map → radio-group-field-DYqU_6hW.mjs.map} +1 -1
- package/dist/{resizable-CNqPu4Ck.d.cts → resizable-DTnfCua-.d.cts} +2 -2
- package/dist/{resizable-CNqPu4Ck.d.mts → resizable-DTnfCua-.d.mts} +2 -2
- package/dist/rolldown-runtime-DWNI8pZO.cjs +1 -0
- package/dist/select-field-D7Ny2Qne.mjs +2 -0
- package/dist/{select-field-NJgDDCO2.mjs.map → select-field-D7Ny2Qne.mjs.map} +1 -1
- package/dist/select-field-UWnBMAzL.cjs +2 -0
- package/dist/{select-field-CvDBZQTl.cjs.map → select-field-UWnBMAzL.cjs.map} +1 -1
- package/dist/simple-array-field-BSMxRilE.cjs +2 -0
- package/dist/{simple-array-field-aGXkDZXD.cjs.map → simple-array-field-BSMxRilE.cjs.map} +1 -1
- package/dist/simple-array-field-DJXa_vST.mjs +2 -0
- package/dist/{simple-array-field-BwNCeUnn.mjs.map → simple-array-field-DJXa_vST.mjs.map} +1 -1
- package/dist/simple-boolean-field-CVNT8NBk.mjs +2 -0
- package/dist/{simple-boolean-field-t_XDXqYs.mjs.map → simple-boolean-field-CVNT8NBk.mjs.map} +1 -1
- package/dist/simple-boolean-field-CxAyVQ1w.cjs +2 -0
- package/dist/{simple-boolean-field-BeVkn3c4.cjs.map → simple-boolean-field-CxAyVQ1w.cjs.map} +1 -1
- package/dist/simple-combobox-field-BP4IeDkA.cjs +2 -0
- package/dist/{simple-combobox-field-U0ZAl7VQ.cjs.map → simple-combobox-field-BP4IeDkA.cjs.map} +1 -1
- package/dist/simple-combobox-field-BnAUDfQU.mjs +2 -0
- package/dist/{simple-combobox-field-HCB4A33-.mjs.map → simple-combobox-field-BnAUDfQU.mjs.map} +1 -1
- package/dist/simple-date-field-DIa6UBF2.mjs +2 -0
- package/dist/{simple-date-field-Dj4bJoji.mjs.map → simple-date-field-DIa6UBF2.mjs.map} +1 -1
- package/dist/simple-date-field-NSawlSff.cjs +2 -0
- package/dist/{simple-date-field-DtxEpEZj.cjs.map → simple-date-field-NSawlSff.cjs.map} +1 -1
- package/dist/simple-email-field-2Abh3qZw.cjs +2 -0
- package/dist/{simple-email-field-DK9I_Tc_.cjs.map → simple-email-field-2Abh3qZw.cjs.map} +1 -1
- package/dist/simple-email-field-CKDQgzh5.mjs +2 -0
- package/dist/{simple-email-field-BDyhkmHV.mjs.map → simple-email-field-CKDQgzh5.mjs.map} +1 -1
- package/dist/simple-number-field-BjEYE54F.cjs +2 -0
- package/dist/{simple-number-field-BspqWU-3.cjs.map → simple-number-field-BjEYE54F.cjs.map} +1 -1
- package/dist/simple-number-field-SDbxL6L7.mjs +2 -0
- package/dist/{simple-number-field-hneXMhfJ.mjs.map → simple-number-field-SDbxL6L7.mjs.map} +1 -1
- package/dist/simple-password-field-Cjp6yzWd.cjs +2 -0
- package/dist/{simple-password-field-BEEcleom.cjs.map → simple-password-field-Cjp6yzWd.cjs.map} +1 -1
- package/dist/simple-password-field-Cnj-hf5g.mjs +2 -0
- package/dist/{simple-password-field-vsLRHDk4.mjs.map → simple-password-field-Cnj-hf5g.mjs.map} +1 -1
- package/dist/simple-radio-group-field-4-eWSXY7.mjs +2 -0
- package/dist/{simple-radio-group-field-BURm_BSA.mjs.map → simple-radio-group-field-4-eWSXY7.mjs.map} +1 -1
- package/dist/simple-radio-group-field-CuA0Q-XI.cjs +2 -0
- package/dist/{simple-radio-group-field-Wm8xB0fN.cjs.map → simple-radio-group-field-CuA0Q-XI.cjs.map} +1 -1
- package/dist/simple-select-field-C0ecQx68.mjs +2 -0
- package/dist/{simple-select-field-8cY51U4d.mjs.map → simple-select-field-C0ecQx68.mjs.map} +1 -1
- package/dist/simple-select-field-CXYJcRY2.cjs +2 -0
- package/dist/{simple-select-field-QQ65caBf.cjs.map → simple-select-field-CXYJcRY2.cjs.map} +1 -1
- package/dist/simple-text-field-DJl5SIGn.mjs +2 -0
- package/dist/{simple-text-field-DK72_OA_.mjs.map → simple-text-field-DJl5SIGn.mjs.map} +1 -1
- package/dist/simple-text-field-DPXqNCXh.cjs +2 -0
- package/dist/{simple-text-field-BHkCPiE5.cjs.map → simple-text-field-DPXqNCXh.cjs.map} +1 -1
- package/dist/simple-textarea-field-BcHdUMTK.mjs +2 -0
- package/dist/{simple-textarea-field-B72nNQHv.mjs.map → simple-textarea-field-BcHdUMTK.mjs.map} +1 -1
- package/dist/simple-textarea-field-ZpXPwYz-.cjs +2 -0
- package/dist/{simple-textarea-field-Bu5h7sfH.cjs.map → simple-textarea-field-ZpXPwYz-.cjs.map} +1 -1
- package/dist/switch-field-CCDuDdpf.cjs +2 -0
- package/dist/{switch-field-eLVlQZSI.cjs.map → switch-field-CCDuDdpf.cjs.map} +1 -1
- package/dist/switch-field-DBGFsmEZ.mjs +2 -0
- package/dist/{switch-field-DoPUWb9d.mjs.map → switch-field-DBGFsmEZ.mjs.map} +1 -1
- package/dist/tanstack-form-BhKAn9I0.mjs +2 -0
- package/dist/tanstack-form-BhKAn9I0.mjs.map +1 -0
- package/dist/tanstack-form-DCB2addt.cjs +2 -0
- package/dist/tanstack-form-DCB2addt.cjs.map +1 -0
- package/dist/text-editor-DWZf3yrW.cjs +2 -0
- package/dist/text-editor-DWZf3yrW.cjs.map +1 -0
- package/dist/text-editor-XBOAwJk-.mjs +2 -0
- package/dist/text-editor-XBOAwJk-.mjs.map +1 -0
- package/dist/text-field-Bx_vnc4O.mjs +2 -0
- package/dist/{text-field-Bm-k6Jr7.mjs.map → text-field-Bx_vnc4O.mjs.map} +1 -1
- package/dist/text-field-DMZZ6CND.cjs +2 -0
- package/dist/{text-field-DT50dOVI.cjs.map → text-field-DMZZ6CND.cjs.map} +1 -1
- package/dist/textarea-field-BmImMdg-.cjs +2 -0
- package/dist/{textarea-field-BhqX29CS.cjs.map → textarea-field-BmImMdg-.cjs.map} +1 -1
- package/dist/textarea-field-Cim3l0y8.mjs +2 -0
- package/dist/{textarea-field-DNLyrRH7.mjs.map → textarea-field-Cim3l0y8.mjs.map} +1 -1
- package/dist/title-field-2dABwspv.mjs +2 -0
- package/dist/{title-field-oAqHRw59.mjs.map → title-field-2dABwspv.mjs.map} +1 -1
- package/dist/title-field-CFnSgTGH.cjs +2 -0
- package/dist/{title-field-B2hM3S_S.cjs.map → title-field-CFnSgTGH.cjs.map} +1 -1
- package/dist/ui/breadcrumb.cjs +1 -1
- package/dist/ui/button-group.cjs +1 -1
- package/dist/ui/button.cjs +1 -1
- package/dist/ui/carousel.cjs +1 -1
- package/dist/ui/dropdown-menu.cjs +1 -1
- package/dist/ui/dropdown-menu.cjs.map +1 -1
- package/dist/ui/dropdown-menu.mjs +1 -1
- package/dist/ui/dropdown-menu.mjs.map +1 -1
- package/dist/ui/file-uploader.cjs +1 -1
- package/dist/ui/item.cjs +1 -1
- package/dist/ui/resizable.cjs +1 -1
- package/dist/ui/resizable.d.cts +1 -1
- package/dist/ui/resizable.d.mts +1 -1
- package/package.json +9 -4
- package/styles/text-editor.css +205 -38
- package/dist/LoginPage-DDljzV6A.d.cts +0 -43
- package/dist/LoginPage-DDljzV6A.d.mts +0 -43
- package/dist/action-submit-B9vHpLoN.cjs +0 -2
- package/dist/action-submit-BQdkz4mS.mjs +0 -2
- package/dist/actions-form-D4n1W3-X.mjs +0 -2
- package/dist/actions-form-DF2eYxGQ.cjs +0 -2
- package/dist/checkbox-field-BRGTLOjq.mjs +0 -2
- package/dist/checkbox-field-ldZRSCca.cjs +0 -2
- package/dist/combobox-field-CvkdZkQE.mjs +0 -2
- package/dist/combobox-field-ZYr7636s.cjs +0 -2
- package/dist/date-field-1Hmcv8Zp.cjs +0 -2
- package/dist/date-field-DGMTG_hu.mjs +0 -2
- package/dist/dialog-form-BRSZpRTC.mjs +0 -2
- package/dist/dialog-form-C1qpltYx.cjs +0 -2
- package/dist/email-field-C2Lvl_rQ.mjs +0 -2
- package/dist/email-field-D3nSkHj2.cjs +0 -2
- package/dist/field-BSLi-P0Q.cjs +0 -2
- package/dist/field-BSLi-P0Q.cjs.map +0 -1
- package/dist/field-V2DoD8qL.mjs +0 -2
- package/dist/field-V2DoD8qL.mjs.map +0 -1
- package/dist/group-field-gejvx_Td.mjs +0 -2
- package/dist/group-field-sVykO2JZ.cjs +0 -2
- package/dist/number-field-CR5PLX6H.mjs +0 -2
- package/dist/number-field-CWDYA3La.cjs +0 -2
- package/dist/pages/LoginPage.cjs +0 -2
- package/dist/pages/LoginPage.cjs.map +0 -1
- package/dist/pages/LoginPage.d.cts +0 -2
- package/dist/pages/LoginPage.d.mts +0 -2
- package/dist/pages/LoginPage.mjs +0 -2
- package/dist/pages/LoginPage.mjs.map +0 -1
- package/dist/password-field-B2_kzss6.mjs +0 -2
- package/dist/password-field-BHRhVyZ0.cjs +0 -2
- package/dist/popover-form-CeRVpy1B.mjs +0 -2
- package/dist/popover-form-Ch_iMMSm.cjs +0 -2
- package/dist/radio-group-field-BFhBfzoT.cjs +0 -2
- package/dist/radio-group-field-Iwo2Q2Ig.mjs +0 -2
- package/dist/rolldown-runtime-CMqjfN_6.cjs +0 -1
- package/dist/select-field-CvDBZQTl.cjs +0 -2
- package/dist/select-field-NJgDDCO2.mjs +0 -2
- package/dist/simple-array-field-BwNCeUnn.mjs +0 -2
- package/dist/simple-array-field-aGXkDZXD.cjs +0 -2
- package/dist/simple-boolean-field-BeVkn3c4.cjs +0 -2
- package/dist/simple-boolean-field-t_XDXqYs.mjs +0 -2
- package/dist/simple-combobox-field-HCB4A33-.mjs +0 -2
- package/dist/simple-combobox-field-U0ZAl7VQ.cjs +0 -2
- package/dist/simple-date-field-Dj4bJoji.mjs +0 -2
- package/dist/simple-date-field-DtxEpEZj.cjs +0 -2
- package/dist/simple-email-field-BDyhkmHV.mjs +0 -2
- package/dist/simple-email-field-DK9I_Tc_.cjs +0 -2
- package/dist/simple-number-field-BspqWU-3.cjs +0 -2
- package/dist/simple-number-field-hneXMhfJ.mjs +0 -2
- package/dist/simple-password-field-BEEcleom.cjs +0 -2
- package/dist/simple-password-field-vsLRHDk4.mjs +0 -2
- package/dist/simple-radio-group-field-BURm_BSA.mjs +0 -2
- package/dist/simple-radio-group-field-Wm8xB0fN.cjs +0 -2
- package/dist/simple-select-field-8cY51U4d.mjs +0 -2
- package/dist/simple-select-field-QQ65caBf.cjs +0 -2
- package/dist/simple-text-field-BHkCPiE5.cjs +0 -2
- package/dist/simple-text-field-DK72_OA_.mjs +0 -2
- package/dist/simple-textarea-field-B72nNQHv.mjs +0 -2
- package/dist/simple-textarea-field-Bu5h7sfH.cjs +0 -2
- package/dist/switch-field-DoPUWb9d.mjs +0 -2
- package/dist/switch-field-eLVlQZSI.cjs +0 -2
- package/dist/tanstack-form-C0ab8EEl.cjs +0 -2
- package/dist/tanstack-form-C0ab8EEl.cjs.map +0 -1
- package/dist/tanstack-form-fkaBh9RO.mjs +0 -2
- package/dist/tanstack-form-fkaBh9RO.mjs.map +0 -1
- package/dist/text-editor-BtfyZSgR.cjs +0 -2
- package/dist/text-editor-BtfyZSgR.cjs.map +0 -1
- package/dist/text-editor-CtR27_PR.mjs +0 -2
- package/dist/text-editor-CtR27_PR.mjs.map +0 -1
- package/dist/text-editor-field-B6HEsAHt.mjs +0 -2
- package/dist/text-editor-field-B6HEsAHt.mjs.map +0 -1
- package/dist/text-editor-field-DcEUC0iH.cjs +0 -2
- package/dist/text-editor-field-DcEUC0iH.cjs.map +0 -1
- package/dist/text-field-Bm-k6Jr7.mjs +0 -2
- package/dist/text-field-DT50dOVI.cjs +0 -2
- package/dist/textarea-field-BhqX29CS.cjs +0 -2
- package/dist/textarea-field-DNLyrRH7.mjs +0 -2
- package/dist/title-field-B2hM3S_S.cjs +0 -2
- package/dist/title-field-oAqHRw59.mjs +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack-form-DCB2addt.cjs","names":["LabelPrimitive","FieldGroup","Field","FieldContent","FieldContentMain","FieldLabel","InfoIcon","Tooltip","TooltipTrigger","HelpCircleIcon","TooltipContent","FieldSeparator","Separator","FieldError","FieldGroup","Field","FieldContent","FieldLabel","TextEditor","FieldError","FieldSeparator","Skeleton","Suspense","Impl"],"sources":["../packages/components/features/tanstack-form/components/form-context.ts","../packages/components/features/tanstack-form/components/ui/label.tsx","../packages/components/features/tanstack-form/components/ui/field.tsx","../packages/components/features/tanstack-form/components/fields/text-editor-field.tsx","../packages/components/features/tanstack-form/tanstack-form.tsx"],"sourcesContent":["'use client';\n\nimport { createFormHookContexts } from '@tanstack/react-form';\n\n/**\n * Shared field/form contexts, split out from `tanstack-form.tsx` so that field and form\n * components can depend on them directly instead of importing back through the file that\n * lazy-loads those same components (which would reintroduce a circular import).\n */\nexport const { fieldContext, formContext, useFieldContext: useTanStackFieldContext, useFormContext: useTanStackFormContext } = createFormHookContexts();\n","'use client';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Label as LabelPrimitive } from 'radix-ui';\n\n/**\n * Form field label that automatically renders a \"Required\" badge when the field is marked aria-required.\n *\n * @example\n * import { Label } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <Label htmlFor=\"email\">Email address</Label>\n */\nfunction Label({ className, children, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {\n return (\n <LabelPrimitive.Root\n data-slot=\"label\"\n className={cn(\n 'text-text-positive',\n 'flex w-full items-center justify-between',\n 'select-none font-medium text-sm/6 leading-none',\n 'group-data-[disabled=true]:pointer-events-none',\n 'group-data-[disabled=true]:opacity-50',\n 'peer-disabled:cursor-not-allowed',\n 'peer-disabled:opacity-50',\n 'aria-required:*:data-[slot=required-indicator]:inline-block',\n className\n )}\n {...props}\n >\n <span className=\"flex items-center gap-1\">{children}</span>\n <span\n data-slot=\"required-indicator\"\n className=\"hidden shrink-0 rounded-lg bg-danger-strong px-1.5 py-1 font-semibold text-[11px] leading-none text-white\"\n >\n Bắt buộc\n </span>\n </LabelPrimitive.Root>\n );\n}\n\nexport { Label };\n","'use client';\n\nimport { memo, useMemo } from 'react';\n\nimport { HelpCircleIcon, InfoIcon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Separator } from '@/components/ui/separator';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Label } from './label';\n\nconst fieldVariants = cva('group/field flex w-full gap-2 data-[invalid=true]:text-danger *:data-[slot=field-content]:gap-0', {\n variants: {\n orientation: {\n vertical: ['flex-col *:w-full [&>.sr-only]:w-auto'],\n horizontal: [\n 'flex-row items-center gap-4',\n '*:data-[slot=field-content]:basis-1/2',\n '*:data-[slot=field-content-main]:flex-1',\n '*:data-[slot=field-label]:flex-auto',\n 'has-[>[data-slot=field-content]]:items-start',\n 'has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',\n ],\n responsive: [\n 'flex-col *:w-full [&>.sr-only]:w-auto',\n '@md/field-group:flex-row',\n '@md/field-group:items-center',\n '@md/field-group:gap-4',\n '@md/field-group:*:w-auto',\n '@md/field-group:*:data-[slot=field-content]:basis-1/2',\n '@md/field-group:*:data-[slot=field-content-main]:basis-1/2',\n '@md/field-group:*:data-[slot=field-label]:flex-auto',\n '@md/field-group:has-[>[data-slot=field-content]]:items-start',\n '@md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',\n ],\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n});\n\n/**\n * Outermost `<fieldset>` wrapper that stacks multiple `Field` rows with consistent vertical spacing.\n *\n * @example\n * import { FieldSet } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldSet>\n * <Field><FieldLabel>Name</FieldLabel><FieldContent><input /></FieldContent></Field>\n * </FieldSet>\n */\nconst FieldSet = memo(({ className, ...props }: React.ComponentProps<'fieldset'>) => {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn('flex flex-col gap-6 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3', className)}\n {...props}\n />\n );\n});\nFieldSet.displayName = 'FieldSet';\n\n/**\n * Props for {@link FieldLegend}.\n */\ntype FieldLegendProps = React.ComponentProps<'legend'> & {\n /**\n * Visual weight of the legend text.\n * - `'legend'` — larger base-size text (section heading).\n * - `'label'` — smaller label-size text (matches field label weight).\n * @default 'legend'\n */\n variant?: 'legend' | 'label';\n};\n\n/**\n * `<legend>` element for a `<fieldset>`, styled as either a section heading or a compact label.\n *\n * @example\n * import { FieldSet, FieldLegend } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldSet>\n * <FieldLegend variant=\"legend\">Personal details</FieldLegend>\n * </FieldSet>\n */\nconst FieldLegend = memo(({ className, variant = 'legend', ...props }: FieldLegendProps) => {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn('mb-3 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base', className)}\n {...props}\n />\n );\n});\nFieldLegend.displayName = 'FieldLegend';\n\n/**\n * Container `<div>` that groups a set of `Field` rows with container-query support for responsive layouts.\n *\n * @example\n * import { FieldGroup } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldGroup>\n * <Field>…</Field>\n * <Field>…</Field>\n * </FieldGroup>\n */\nconst FieldGroup = memo(({ className, ...props }: React.ComponentProps<'div'>) => {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n 'group/field-group @container/field-group',\n 'flex flex-col gap-7 pt-4',\n 'data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4',\n className\n )}\n {...props}\n />\n );\n});\nFieldGroup.displayName = 'FieldGroup';\n\n/**\n * Single form field row that arranges label, input, and meta elements with configurable orientation.\n *\n * @example\n * import { Field } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <Field orientation=\"horizontal\">\n * <FieldLabel htmlFor=\"username\">Username</FieldLabel>\n * <FieldContent><input id=\"username\" /></FieldContent>\n * </Field>\n */\nconst Field = memo(({ className, orientation = 'vertical', ...props }: React.ComponentProps<'div'> & VariantProps<typeof fieldVariants>) => {\n return <div data-slot=\"field\" data-orientation={orientation} className={cn(fieldVariants({ orientation }), className)} {...props} />;\n});\nField.displayName = 'Field';\n\n/**\n * Flex column wrapper that houses the primary input control together with description and error slots.\n *\n * @example\n * import { FieldContent } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldContent>\n * <input type=\"text\" />\n * <FieldDescription>Enter your full name.</FieldDescription>\n * </FieldContent>\n */\nconst FieldContent = memo(({ className, ...props }: React.ComponentProps<'div'>) => {\n return <div data-slot=\"field-content\" className={cn('group/field-content flex flex-col gap-1.5 leading-snug', className)} {...props} />;\n});\nFieldContent.displayName = 'FieldContent';\n\n/**\n * Positioned wrapper for the main input element that enables absolutely-placed adornments (icons, spinners).\n *\n * @example\n * import { FieldContentMain } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldContentMain>\n * <input type=\"text\" className=\"pr-8\" />\n * <SearchIcon className=\"absolute right-2 top-2\" />\n * </FieldContentMain>\n */\nconst FieldContentMain = memo(({ className, ...props }: React.ComponentProps<'div'>) => {\n return <div data-slot=\"field-content-main\" className={cn('relative', className)} {...props} />;\n});\nFieldContentMain.displayName = 'FieldContentMain';\n\n/**\n * Styled `<label>` element for a `Field`, extending the base `Label` with field-group-aware spacing and border states.\n *\n * @example\n * import { FieldLabel } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldLabel htmlFor=\"email\" aria-required>Email</FieldLabel>\n */\nconst FieldLabel = memo(({ className, ...props }: React.ComponentProps<typeof Label>) => {\n return (\n <Label\n data-slot=\"field-label\"\n className={cn(\n 'group/field-label peer/field-label min-h-6 gap-1 font-medium leading-snug',\n 'has-[>[data-slot=field]]:w-full',\n 'has-[>[data-slot=field]]:flex-col',\n 'has-[>[data-slot=field]]:rounded-md',\n 'has-[>[data-slot=field]]:border',\n 'has-[>[data-slot=field]]:border-border',\n 'has-data-[state=checked]:border-primary',\n '*:data-[slot=field]:p-4 group-data-[disabled=true]/field:opacity-50',\n className\n )}\n {...props}\n />\n );\n});\nFieldLabel.displayName = 'FieldLabel';\n\n/**\n * Inline title element (non-`<label>`) for fields whose label cannot be a native `<label>`, such as custom checkbox groups.\n *\n * @example\n * import { FieldTitle } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldTitle>Notification preferences</FieldTitle>\n */\nconst FieldTitle = memo(({ className, ...props }: React.ComponentProps<'div'>) => {\n return (\n <div\n data-slot=\"field-label\"\n className={cn('flex w-fit items-center gap-2 font-medium text-sm leading-snug group-data-[disabled=true]/field:opacity-50', className)}\n {...props}\n />\n );\n});\nFieldTitle.displayName = 'FieldTitle';\n\n/**\n * Supplementary hint text rendered below the input to guide the user, with support for inline anchor links.\n *\n * @example\n * import { FieldDescription } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldDescription>Must be at least 8 characters.</FieldDescription>\n */\nconst FieldDescription = memo(({ className, ...props }: React.ComponentProps<'p'>) => {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(\n // biome-ignore lint/security/noSecrets: true\n 'nth-last-2:-mt-1 font-normal text-text-positive-weak text-xs leading-normal last:mt-0 [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4 [[data-variant=legend]+&]:-mt-1.5',\n className\n )}\n {...props}\n />\n );\n});\nFieldDescription.displayName = 'FieldDescription';\n\n/**\n * Props for {@link FieldNote}.\n */\ntype FieldNoteProps = React.ComponentProps<'div'> & {\n /**\n * When `false` the note is not rendered at all; useful for conditional display without wrapper conditionals.\n * @default true\n */\n isShow?: boolean;\n};\n\n/**\n * Highlighted informational callout box with an info icon, shown below a field to surface contextual guidance.\n *\n * @example\n * import { FieldNote } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldNote isShow={isDraftMode}>Changes are saved automatically in draft mode.</FieldNote>\n */\nconst FieldNote = memo(({ isShow = true, className, children, ...props }: FieldNoteProps) => {\n if (isShow === false) return null;\n return (\n <div\n data-slot=\"field-note\"\n className={cn(\n 'flex items-start gap-1.5 rounded border border-primary-muted/60 bg-primary-bg-subtle/80 px-2.5 py-2 text-text-positive-weak text-xs mt-1',\n className\n )}\n {...props}\n >\n <InfoIcon size={12} className=\"mt-0.5 shrink-0 text-primary/70\" />\n <span>{children}</span>\n </div>\n );\n});\nFieldNote.displayName = 'FieldNote';\n\n/**\n * Props for {@link FieldTooltip}.\n */\ntype FieldTooltipProps = {\n /** Text content displayed inside the tooltip when the help icon is hovered or focused. */\n tooltip: string;\n};\n\n/**\n * Small help-circle icon button that reveals a tooltip with additional field context on hover or focus.\n *\n * @example\n * import { FieldTooltip } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldLabel>\n * Password <FieldTooltip tooltip=\"Use at least one uppercase letter and one number.\" />\n * </FieldLabel>\n */\nconst FieldTooltip = memo(({ tooltip }: FieldTooltipProps) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n tabIndex={-1}\n className=\"inline-flex cursor-default items-center text-text-positive-weak/70 hover:text-text-positive focus:outline-none\"\n >\n <HelpCircleIcon size={13} aria-hidden=\"true\" />\n <span className=\"sr-only\">Thêm thông tin</span>\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-xs text-balance\">\n {tooltip}\n </TooltipContent>\n </Tooltip>\n );\n});\nFieldTooltip.displayName = 'FieldTooltip';\n\n/**\n * Visual divider row that optionally displays a centered text label, used to separate logical sections within a `FieldGroup`.\n *\n * @example\n * import { FieldSeparator } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <FieldSeparator>or</FieldSeparator>\n */\nconst FieldSeparator = memo(({ children, className, ...props }: React.PropsWithChildren<React.ComponentProps<'div'>>) => {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn('relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2', className)}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span className=\"relative mx-auto block w-fit bg-background px-2 text-text-positive-weak\" data-slot=\"field-separator-content\">\n {children}\n </span>\n )}\n </div>\n );\n});\nFieldSeparator.displayName = 'FieldSeparator';\n\n/**\n * Props for {@link FieldError}.\n */\ntype FieldErrorProps = React.ComponentProps<'div'> & {\n errors?: Array<{ code?: string; message?: string } | undefined>;\n requiredMessage?: string;\n};\n\nconst FieldError = memo(({ className, children, errors, requiredMessage = 'Trường này là bắt buộc', ...props }: FieldErrorProps) => {\n const content = useMemo(() => {\n const resolve = (error: { code?: string; message?: string }) => (error.code === 'invalid_type' ? requiredMessage : error.message);\n\n if (children) {\n return children;\n }\n\n if (!errors) {\n return null;\n }\n\n if (errors?.length === 1 && errors[0]?.message) {\n return (\n <div className=\"flex flex-row items-center justify-start gap-x-0.5\">\n <p>{resolve(errors[0])}</p>\n </div>\n );\n }\n\n return (\n <ul className=\"flex list-none flex-col\">\n {errors.map(error => {\n if (typeof error === 'string') return <li key={error}>{error}</li>;\n if (!error?.message) return null;\n return <li key={error.code ?? error.message}>{resolve(error)}</li>;\n })}\n </ul>\n );\n }, [children, errors, requiredMessage]);\n\n if (!content) {\n return null;\n }\n\n return (\n <div role=\"alert\" data-slot=\"field-error\" className={cn('w-full font-medium text-danger-strong text-xs', className)} {...props}>\n {content}\n </div>\n );\n});\nFieldError.displayName = 'FieldError';\n\nexport {\n Field,\n FieldLabel,\n FieldDescription,\n FieldNote,\n FieldError,\n FieldGroup,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldContent,\n FieldContentMain,\n FieldTitle,\n FieldTooltip,\n};\n","'use client';\n\nimport { memo, useCallback } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { TextEditor } from '@/components/features/text-editor';\n\nimport type { TextEditorFieldProps as Props } from '../../types';\nimport { useTanStackFieldContext } from '../form-context';\nimport { Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldNote, FieldSeparator, FieldTooltip } from '../ui/field';\n\nexport const TextEditorField: React.FC<Props> = memo(\n ({\n label,\n description,\n placeholder,\n tooltip,\n helperText,\n showErrorMessage = true,\n required = false,\n maxLength,\n showCharacterCount,\n enableLink,\n enableBubbleMenu,\n enableTaskList,\n enableHighlight,\n enableColor,\n enableImage,\n enableTable,\n enableSlashCommand,\n onImageUpload,\n variant,\n size,\n }) => {\n const { form, state, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n\n const _invalid = state.meta.isDirty && state.meta.isTouched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n\n const onChange = useCallback(\n (html: string) => {\n if (isSubmitting) return;\n handleChange(html || null);\n },\n [isSubmitting, handleChange]\n );\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation=\"vertical\" data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <TextEditor\n value={state.value ?? ''}\n placeholder={placeholder}\n readOnly={isSubmitting}\n onChange={onChange}\n maxLength={maxLength}\n showCharacterCount={showCharacterCount}\n enableLink={enableLink}\n enableBubbleMenu={enableBubbleMenu}\n enableTaskList={enableTaskList}\n enableHighlight={enableHighlight}\n enableColor={enableColor}\n enableImage={enableImage}\n enableTable={enableTable}\n enableSlashCommand={enableSlashCommand}\n onImageUpload={onImageUpload}\n variant={variant}\n size={size}\n />\n {state.meta.isDirty && showErrorMessage && !!state.meta.errors.length && <FieldError errors={state.meta.errors} />}\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\nTextEditorField.displayName = 'TextEditorField';\n","'use client';\n\nimport type { ComponentProps, ComponentType } from 'react';\nimport { lazy, Suspense } from 'react';\n\nimport { createFormHook } from '@tanstack/react-form';\n\nimport { Skeleton } from '@/components/ui/skeleton';\n\nimport type { ArrayCol as ArrayColType, ArrayHeaderRow as ArrayHeaderRowType, SimpleArrayFieldProps } from './components/atoms/simple-array-field';\nimport type { SimpleBooleanField as SimpleBooleanFieldType } from './components/atoms/simple-boolean-field';\nimport type { SimpleComboboxField as SimpleComboboxFieldType } from './components/atoms/simple-combobox-field';\nimport type { SimpleDateField as SimpleDateFieldType } from './components/atoms/simple-date-field';\nimport type { SimpleEmailField as SimpleEmailFieldType } from './components/atoms/simple-email-field';\nimport type { SimpleNumberField as SimpleNumberFieldType } from './components/atoms/simple-number-field';\nimport type { SimplePasswordField as SimplePasswordFieldType } from './components/atoms/simple-password-field';\nimport type { SimpleRadioGroupField as SimpleRadioGroupFieldType } from './components/atoms/simple-radio-group-field';\nimport type { SimpleSelectField as SimpleSelectFieldType } from './components/atoms/simple-select-field';\nimport type { SimpleTextField as SimpleTextFieldType } from './components/atoms/simple-text-field';\nimport type { SimpleTextareaField as SimpleTextareaFieldType } from './components/atoms/simple-textarea-field';\nimport type { CheckboxField as CheckboxFieldType } from './components/fields/checkbox-field';\nimport type { ComboboxField as ComboboxFieldType } from './components/fields/combobox-field';\nimport type { DateField as DateFieldType } from './components/fields/date-field';\nimport type { EmailField as EmailFieldType } from './components/fields/email-field';\nimport type { NumberField as NumberFieldType } from './components/fields/number-field';\nimport type { PasswordField as PasswordFieldType } from './components/fields/password-field';\nimport type { RadioGroupField as RadioGroupFieldType } from './components/fields/radio-group-field';\nimport type { SelectField as SelectFieldType } from './components/fields/select-field';\nimport type { SwitchField as SwitchFieldType } from './components/fields/switch-field';\nimport { TextEditorField } from './components/fields/text-editor-field';\nimport type { TextField as TextFieldType } from './components/fields/text-field';\nimport type { TextareaField as TextareaFieldType } from './components/fields/textarea-field';\nimport { fieldContext, formContext, useTanStackFieldContext, useTanStackFormContext } from './components/form-context';\nimport type { TanStackActionSubmit as TanStackActionSubmitType } from './components/forms/action-submit';\nimport type { TanStackActionsForm as TanStackActionsFormType } from './components/forms/actions-form';\nimport type { TanStackCardForm as TanStackCardFormType } from './components/forms/card-form';\nimport type { TanStackContainerForm as TanStackContainerFormType } from './components/forms/container-form';\nimport type { TanStackDialogForm as TanStackDialogFormType } from './components/forms/dialog-form';\nimport type { TanStackFieldGroup as TanStackFieldGroupType } from './components/forms/group-field';\nimport type { TanStackPopoverForm as TanStackPopoverFormType } from './components/forms/popover-form';\nimport type { TanStackSectionForm as TanStackSectionFormType } from './components/forms/section-form';\nimport type { TanStackTitleField as TanStackTitleFieldType } from './components/forms/title-field';\nimport type {\n FieldContentMain as FieldContentMainType,\n FieldContent as FieldContentType,\n FieldError as FieldErrorType,\n FieldGroup as FieldGroupType,\n FieldLabel as FieldLabelType,\n FieldSeparator as FieldSeparatorType,\n Field as FieldType,\n} from './components/ui/field';\n\n/** Input-shaped pulse placeholder shown while a lazy field/form chunk is still loading. */\nfunction FieldSkeleton() {\n return <Skeleton data-slot=\"tanstack-field-skeleton\" className=\"h-9 w-full rounded\" />;\n}\n\n/**\n * Wraps a `lazy()`-loaded component in its own `Suspense` boundary so it can be dropped\n * anywhere (inside or outside our own form containers) without callers needing to set up\n * Suspense themselves. Keeps this file itself small — the heavy per-field-type\n * implementations (Radix Select/Combobox/date-picker, the rich text editor, etc.) only load\n * when a form actually renders that field type.\n */\nfunction lazyField<P extends object>(loader: () => Promise<{ default: ComponentType<P> }>): ComponentType<P> {\n const LazyComponent = lazy(loader);\n return (props: P) => (\n <Suspense fallback={<FieldSkeleton />}>\n <LazyComponent {...props} />\n </Suspense>\n );\n}\n\n// ─── Rich field components (lazy) ─────────────────────────────────────────────\n\nconst TextField = lazyField<ComponentProps<typeof TextFieldType>>(() => import('./components/fields/text-field').then(m => ({ default: m.TextField })));\nconst TextareaField = lazyField<ComponentProps<typeof TextareaFieldType>>(() =>\n import('./components/fields/textarea-field').then(m => ({ default: m.TextareaField }))\n);\nconst NumberField = lazyField<ComponentProps<typeof NumberFieldType>>(() => import('./components/fields/number-field').then(m => ({ default: m.NumberField })));\nconst EmailField = lazyField<ComponentProps<typeof EmailFieldType>>(() => import('./components/fields/email-field').then(m => ({ default: m.EmailField })));\nconst PasswordField = lazyField<ComponentProps<typeof PasswordFieldType>>(() =>\n import('./components/fields/password-field').then(m => ({ default: m.PasswordField }))\n);\nconst SelectField = lazyField<ComponentProps<typeof SelectFieldType>>(() => import('./components/fields/select-field').then(m => ({ default: m.SelectField })));\nconst ComboboxField = lazyField<ComponentProps<typeof ComboboxFieldType>>(() =>\n import('./components/fields/combobox-field').then(m => ({ default: m.ComboboxField }))\n);\nconst DateField = lazyField<ComponentProps<typeof DateFieldType>>(() => import('./components/fields/date-field').then(m => ({ default: m.DateField })));\nconst SwitchField = lazyField<ComponentProps<typeof SwitchFieldType>>(() => import('./components/fields/switch-field').then(m => ({ default: m.SwitchField })));\nconst RadioGroupField = lazyField<ComponentProps<typeof RadioGroupFieldType>>(() =>\n import('./components/fields/radio-group-field').then(m => ({ default: m.RadioGroupField }))\n);\nconst CheckboxField = lazyField<ComponentProps<typeof CheckboxFieldType>>(() =>\n import('./components/fields/checkbox-field').then(m => ({ default: m.CheckboxField }))\n);\n\n// ─── Simple (minimal) field components (lazy) ─────────────────────────────────\n\nconst SimpleTextField = lazyField<ComponentProps<typeof SimpleTextFieldType>>(() =>\n import('./components/atoms/simple-text-field').then(m => ({ default: m.SimpleTextField }))\n);\nconst SimpleEmailField = lazyField<ComponentProps<typeof SimpleEmailFieldType>>(() =>\n import('./components/atoms/simple-email-field').then(m => ({ default: m.SimpleEmailField }))\n);\nconst SimplePasswordField = lazyField<ComponentProps<typeof SimplePasswordFieldType>>(() =>\n import('./components/atoms/simple-password-field').then(m => ({ default: m.SimplePasswordField }))\n);\nconst SimpleTextareaField = lazyField<ComponentProps<typeof SimpleTextareaFieldType>>(() =>\n import('./components/atoms/simple-textarea-field').then(m => ({ default: m.SimpleTextareaField }))\n);\nconst SimpleNumberField = lazyField<ComponentProps<typeof SimpleNumberFieldType>>(() =>\n import('./components/atoms/simple-number-field').then(m => ({ default: m.SimpleNumberField }))\n);\nconst SimpleSelectField = lazyField<ComponentProps<typeof SimpleSelectFieldType>>(() =>\n import('./components/atoms/simple-select-field').then(m => ({ default: m.SimpleSelectField }))\n);\nconst LazySimpleArrayField = lazy(() =>\n import('./components/atoms/simple-array-field').then(m => ({ default: m.SimpleArrayField as ComponentType<SimpleArrayFieldProps<unknown>> }))\n);\n\n/** Kept as its own generic wrapper (instead of `lazyField`) so callers can still write `<SimpleArrayField<Row> />`. */\nfunction SimpleArrayField<T>(props: SimpleArrayFieldProps<T>) {\n const Impl = LazySimpleArrayField as ComponentType<SimpleArrayFieldProps<T>>;\n return (\n <Suspense fallback={<FieldSkeleton />}>\n <Impl {...props} />\n </Suspense>\n );\n}\n\nconst SimpleBooleanField = lazyField<ComponentProps<typeof SimpleBooleanFieldType>>(() =>\n import('./components/atoms/simple-boolean-field').then(m => ({ default: m.SimpleBooleanField }))\n);\nconst SimpleComboboxField = lazyField<ComponentProps<typeof SimpleComboboxFieldType>>(() =>\n import('./components/atoms/simple-combobox-field').then(m => ({ default: m.SimpleComboboxField }))\n);\nconst SimpleDateField = lazyField<ComponentProps<typeof SimpleDateFieldType>>(() =>\n import('./components/atoms/simple-date-field').then(m => ({ default: m.SimpleDateField }))\n);\nconst SimpleRadioGroupField = lazyField<ComponentProps<typeof SimpleRadioGroupFieldType>>(() =>\n import('./components/atoms/simple-radio-group-field').then(m => ({ default: m.SimpleRadioGroupField }))\n);\n\n// ─── Array field layout helpers (lazy, co-located with SimpleArrayField) ──────\n\nconst ArrayCol = lazyField<ComponentProps<typeof ArrayColType>>(() => import('./components/atoms/simple-array-field').then(m => ({ default: m.ArrayCol })));\nconst ArrayHeaderRow = lazyField<ComponentProps<typeof ArrayHeaderRowType>>(() =>\n import('./components/atoms/simple-array-field').then(m => ({ default: m.ArrayHeaderRow }))\n);\n\n// ─── Form containers (lazy) ───────────────────────────────────────────────────\n\nconst TanStackDialogForm = lazyField<ComponentProps<typeof TanStackDialogFormType>>(() =>\n import('./components/forms/dialog-form').then(m => ({ default: m.TanStackDialogForm }))\n);\nconst TanStackPopoverForm = lazyField<ComponentProps<typeof TanStackPopoverFormType>>(() =>\n import('./components/forms/popover-form').then(m => ({ default: m.TanStackPopoverForm }))\n);\nconst TanStackContainerForm = lazyField<ComponentProps<typeof TanStackContainerFormType>>(() =>\n import('./components/forms/container-form').then(m => ({ default: m.TanStackContainerForm }))\n);\nconst TanStackSectionForm = lazyField<ComponentProps<typeof TanStackSectionFormType>>(() =>\n import('./components/forms/section-form').then(m => ({ default: m.TanStackSectionForm }))\n);\nconst TanStackCardForm = lazyField<ComponentProps<typeof TanStackCardFormType>>(() =>\n import('./components/forms/card-form').then(m => ({ default: m.TanStackCardForm }))\n);\nconst TanStackFieldGroup = lazyField<ComponentProps<typeof TanStackFieldGroupType>>(() =>\n import('./components/forms/group-field').then(m => ({ default: m.TanStackFieldGroup }))\n);\nconst TanStackTitleField = lazyField<ComponentProps<typeof TanStackTitleFieldType>>(() =>\n import('./components/forms/title-field').then(m => ({ default: m.TanStackTitleField }))\n);\nconst TanStackActionsForm = lazyField<ComponentProps<typeof TanStackActionsFormType>>(() =>\n import('./components/forms/actions-form').then(m => ({ default: m.TanStackActionsForm }))\n);\nconst TanStackActionSubmit = lazyField<ComponentProps<typeof TanStackActionSubmitType>>(() =>\n import('./components/forms/action-submit').then(m => ({ default: m.TanStackActionSubmit }))\n);\n\n// ─── Field UI primitives (lazy) ───────────────────────────────────────────────\n\nconst FieldGroup = lazyField<ComponentProps<typeof FieldGroupType>>(() => import('./components/ui/field').then(m => ({ default: m.FieldGroup })));\nconst Field = lazyField<ComponentProps<typeof FieldType>>(() => import('./components/ui/field').then(m => ({ default: m.Field })));\nconst FieldContent = lazyField<ComponentProps<typeof FieldContentType>>(() => import('./components/ui/field').then(m => ({ default: m.FieldContent })));\nconst FieldLabel = lazyField<ComponentProps<typeof FieldLabelType>>(() => import('./components/ui/field').then(m => ({ default: m.FieldLabel })));\nconst FieldContentMain = lazyField<ComponentProps<typeof FieldContentMainType>>(() =>\n import('./components/ui/field').then(m => ({ default: m.FieldContentMain }))\n);\nconst FieldSeparator = lazyField<ComponentProps<typeof FieldSeparatorType>>(() => import('./components/ui/field').then(m => ({ default: m.FieldSeparator })));\nconst FieldError = lazyField<ComponentProps<typeof FieldErrorType>>(() => import('./components/ui/field').then(m => ({ default: m.FieldError })));\n\n/**\n * Factory result from {@link createFormHook} pre-wired with all Lunas UI field and form components.\n *\n * ### `useTanStackForm`\n * Pre-configured TanStack Form hook that returns a type-safe form instance bound to all Lunas UI\n * field and form components.\n *\n * @example\n * import { useTanStackForm } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * const form = useTanStackForm({\n * defaultValues: { name: '', email: '' },\n * onSubmit: async ({ value }) => console.log(value),\n * });\n *\n * return (\n * <form.Provider>\n * <form.AppForm>\n * <form.AppField name=\"name\" children={(field) => <field.TextField label=\"Name\" />} />\n * <form.Subscribe selector={(s) => s.canSubmit}>\n * {(canSubmit) => <form.TanStackActionSubmit disabled={!canSubmit} />}\n * </form.Subscribe>\n * </form.AppForm>\n * </form.Provider>\n * );\n *\n * ### `withTanStackForm`\n * Higher-order component that wraps a sub-form component with access to the parent\n * `useTanStackForm` form context, enabling isolated field groups that still participate in the\n * top-level form state.\n *\n * @example\n * import { withTanStackForm } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * const AddressFields = withTanStackForm(\n * { street: '', city: '' } as const,\n * ({ form }) => (\n * <>\n * <form.AppField name=\"street\" children={(f) => <f.TextField label=\"Street\" />} />\n * <form.AppField name=\"city\" children={(f) => <f.TextField label=\"City\" />} />\n * </>\n * ),\n * );\n *\n * ### `withTanStackFieldGroup`\n * Higher-order component that creates a reusable field-group component sharing the enclosing\n * `useTanStackForm` context without requiring additional form providers.\n *\n * @example\n * import { withTanStackFieldGroup } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * const ContactGroup = withTanStackFieldGroup(({ form }) => (\n * <form.AppField name=\"phone\" children={(f) => <f.TextField label=\"Phone\" />} />\n * ));\n */\nconst {\n useAppForm: useTanStackForm,\n withForm: withTanStackForm,\n withFieldGroup: withTanStackFieldGroup,\n} = createFormHook({\n fieldContext,\n formContext,\n\n fieldComponents: {\n TextField,\n TextareaField,\n TextEditorField,\n NumberField,\n EmailField,\n PasswordField,\n\n SelectField,\n ComboboxField,\n DateField,\n SwitchField,\n RadioGroupField,\n CheckboxField,\n\n SimpleTextField,\n SimpleEmailField,\n SimplePasswordField,\n SimpleTextareaField,\n SimpleNumberField,\n SimpleSelectField,\n SimpleArrayField,\n SimpleBooleanField,\n SimpleComboboxField,\n SimpleDateField,\n SimpleRadioGroupField,\n\n FieldGroup,\n Field,\n FieldContent,\n FieldLabel,\n FieldContentMain,\n FieldSeparator,\n FieldError,\n },\n formComponents: {\n TanStackDialogForm,\n TanStackPopoverForm,\n TanStackContainerForm,\n TanStackSectionForm,\n TanStackCardForm,\n TanStackFieldGroup,\n TanStackTitleField,\n\n TanStackActionsForm,\n TanStackActionSubmit,\n\n ArrayCol,\n ArrayHeaderRow,\n },\n});\n\nexport {\n // Array helpers\n ArrayCol,\n ArrayHeaderRow,\n CheckboxField,\n ComboboxField,\n DateField,\n EmailField,\n Field,\n FieldContent,\n FieldContentMain,\n FieldError,\n // Field UI primitives\n FieldGroup,\n FieldLabel,\n FieldSeparator,\n NumberField,\n PasswordField,\n RadioGroupField,\n SelectField,\n SimpleArrayField,\n SimpleBooleanField,\n SimpleComboboxField,\n SimpleDateField,\n SimpleEmailField,\n SimpleNumberField,\n SimplePasswordField,\n SimpleRadioGroupField,\n SimpleSelectField,\n SimpleTextareaField,\n // Simple (minimal) field components\n SimpleTextField,\n SwitchField,\n TanStackActionSubmit,\n // Form actions\n TanStackActionsForm,\n TanStackCardForm,\n TanStackContainerForm,\n // Form containers\n TanStackDialogForm,\n TanStackFieldGroup,\n TanStackPopoverForm,\n TanStackSectionForm,\n TanStackTitleField,\n TextareaField,\n TextEditorField,\n // Rich field components\n TextField,\n useTanStackFieldContext,\n // Hooks & HOCs\n useTanStackForm,\n useTanStackFormContext,\n withTanStackFieldGroup,\n withTanStackForm,\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./rolldown-runtime-DWNI8pZO.cjs"),t=require("./ui/dropdown-menu.cjs"),n=require("./ui/spinner.cjs"),r=require("./ui/popover.cjs");let i=require("lucide-react"),a=require("react"),o=require("@customafk/react-toolkit/utils"),s=require("class-variance-authority"),c=require("react/jsx-runtime"),l=require("@tiptap/react"),u=require("@tiptap/extension-character-count"),d=require("@tiptap/extension-code-block-lowlight");d=e.n(d,1);let f=require("@tiptap/extension-highlight"),p=require("@tiptap/extension-image");p=e.n(p,1);let m=require("@tiptap/extension-link"),h=require("@tiptap/extension-list-keymap"),g=require("@tiptap/extension-placeholder");g=e.n(g,1);let _=require("@tiptap/extension-table"),v=require("@tiptap/extension-task-item"),y=require("@tiptap/extension-task-list"),b=require("@tiptap/extension-text-align");b=e.n(b,1);let x=require("@tiptap/extension-text-style"),S=require("@tiptap/extension-underline");S=e.n(S,1);let ee=require("@tiptap/react/menus"),C=require("@tiptap/starter-kit");C=e.n(C,1);let w=require("dompurify");w=e.n(w,1);let T=require("lowlight"),te=require("@tiptap/suggestion");function E({isActive:e,className:t,children:n,...r}){return(0,c.jsx)(`button`,{type:`button`,"data-slot":`toolbar-button`,"data-active":e||void 0,"aria-pressed":e===void 0?void 0:e,className:(0,o.cn)(`inline-flex size-8 shrink-0 items-center justify-center rounded text-sm outline-none transition-colors min-w-8`,`hover:bg-muted-weak hover:text-text-positive-strong`,`focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1`,`disabled:pointer-events-none disabled:opacity-40`,e&&`bg-primary-muted text-primary hover:bg-primary-muted/80 hover:text-primary`,t),...r,children:n})}function D(){return(0,c.jsx)(`div`,{"data-slot":`toolbar-divider`,role:`separator`,"aria-orientation":`vertical`,className:`mx-0.5 h-5 w-px shrink-0 bg-border`})}function O({editor:e}){let[t,n]=(0,a.useState)(!1),[s,u]=(0,a.useState)(``),d=(0,l.useEditorState)({editor:e,selector:e=>e.editor.isActive(`link`)}),f=(0,a.useCallback)(t=>{if(t){let t=e.getAttributes(`link`).href??``;u(t)}n(t)},[e]),p=(0,a.useCallback)(()=>{let t=s.trim();t&&(e.chain().focus().setLink({href:t,target:`_blank`}).run(),n(!1))},[e,s]),m=(0,a.useCallback)(()=>{e.chain().focus().unsetLink().run(),n(!1)},[e]);return(0,c.jsxs)(r.Popover,{open:t,onOpenChange:f,children:[(0,c.jsx)(r.PopoverTrigger,{asChild:!0,children:(0,c.jsx)(E,{isActive:d,"aria-label":`Liên kết`,title:`Link (Ctrl+K)`,"data-slot":`toolbar-link-button`,children:(0,c.jsx)(i.Link2,{className:`h-3.5 w-3.5`})})}),(0,c.jsxs)(r.PopoverContent,{"data-slot":`link-dialog`,sideOffset:6,align:`start`,className:`w-72 p-3`,children:[(0,c.jsx)(`p`,{className:`mb-2 font-medium text-text-positive-strong text-xs`,children:d?`Edit Link`:`Insert Link`}),(0,c.jsxs)(`div`,{className:`flex gap-1.5`,children:[(0,c.jsx)(`input`,{type:`url`,placeholder:`https://example.com`,value:s,onChange:e=>u(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),p()),e.key===`Escape`&&n(!1)},"aria-label":`Đường dẫn liên kết`,autoFocus:!0,className:(0,o.cn)(`flex-1 rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive`,`outline-none placeholder:text-text-positive-muted`,`focus:border-primary focus:ring-1 focus:ring-primary/30`)}),(0,c.jsx)(`button`,{type:`button`,onClick:p,disabled:!s.trim(),className:(0,o.cn)(`rounded bg-primary px-2.5 py-1.5 font-medium text-text-negative text-xs`,`transition-colors hover:bg-primary-strong`,`disabled:pointer-events-none disabled:opacity-50`),children:`Apply`})]}),d&&(0,c.jsxs)(`button`,{type:`button`,onClick:m,className:`mt-2 flex items-center gap-1 text-danger-strong text-xs hover:underline`,children:[(0,c.jsx)(i.Link2Off,{className:`h-3 w-3`}),`Remove link`]})]})]})}function k(e){try{return new URL(e).hostname}catch{return e}}function A({node:e,selected:t}){let n=e.attrs.src,r=e.attrs.alt;return(0,c.jsxs)(l.NodeViewWrapper,{"data-slot":`text-editor-image`,className:`my-5 flex flex-col items-center`,children:[(0,c.jsx)(`img`,{src:n,alt:r??``,className:(0,o.cn)(`max-w-full rounded-lg border border-border`,t&&`outline-2 outline-primary outline-offset-2`)}),(0,c.jsx)(`a`,{href:n,target:`_blank`,rel:`noopener noreferrer`,contentEditable:!1,className:`mt-1.5 text-text-positive-weak text-xs hover:text-text-positive hover:underline`,children:k(n)})]})}const j=(0,a.forwardRef)(({items:e,command:t},n)=>{let[r,i]=(0,a.useState)(0);return(0,a.useEffect)(()=>{i(0)},[]),(0,a.useImperativeHandle)(n,()=>({onKeyDown:({event:n})=>{if(e.length===0)return!1;if(n.key===`ArrowDown`)return i(t=>(t+1)%e.length),!0;if(n.key===`ArrowUp`)return i(t=>(t-1+e.length)%e.length),!0;if(n.key===`Enter`){let n=e[r];return n&&t(n),!0}return!1}})),e.length===0?(0,c.jsx)(`div`,{"data-slot":`slash-command-menu`,className:`w-56 rounded-md border border-border bg-popover p-2 text-text-positive-weak text-xs shadow-dropdown`,children:`Không tìm thấy lệnh phù hợp`}):(0,c.jsx)(`div`,{"data-slot":`slash-command-menu`,role:`listbox`,"aria-label":`Lệnh chèn nhanh`,className:`max-h-72 w-56 overflow-y-auto rounded-md border border-border bg-popover p-1 shadow-dropdown`,children:e.map((e,n)=>{let a=e.icon;return(0,c.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":n===r,onClick:()=>t(e),onMouseEnter:()=>i(n),className:(0,o.cn)(`flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors`,n===r?`bg-primary-muted text-primary`:`text-text-positive hover:bg-muted-muted`),children:[(0,c.jsx)(a,{className:`h-3.5 w-3.5 shrink-0`}),(0,c.jsx)(`span`,{children:e.label})]},e.label)})})});j.displayName=`SlashCommandMenu`;function M(e){let t=[{label:`Heading 1`,icon:i.Heading1,command:(e,t)=>e.chain().focus().deleteRange(t).toggleHeading({level:1}).run()},{label:`Heading 2`,icon:i.Heading2,command:(e,t)=>e.chain().focus().deleteRange(t).toggleHeading({level:2}).run()},{label:`Heading 3`,icon:i.Heading3,command:(e,t)=>e.chain().focus().deleteRange(t).toggleHeading({level:3}).run()},{label:`Bullet list`,icon:i.List,command:(e,t)=>e.chain().focus().deleteRange(t).toggleBulletList().run()},{label:`Ordered list`,icon:i.ListOrdered,command:(e,t)=>e.chain().focus().deleteRange(t).toggleOrderedList().run()}];if(e.enableTaskList&&t.push({label:`Task list`,icon:i.ListChecks,command:(e,t)=>e.chain().focus().deleteRange(t).toggleTaskList().run()}),t.push({label:`Blockquote`,icon:i.Quote,command:(e,t)=>e.chain().focus().deleteRange(t).toggleBlockquote().run()},{label:`Code block`,icon:i.Code2,command:(e,t)=>e.chain().focus().deleteRange(t).toggleCodeBlock().run()},{label:`Horizontal rule`,icon:i.Minus,command:(e,t)=>e.chain().focus().deleteRange(t).setHorizontalRule().run()}),e.enableTable&&t.push({label:`Table`,icon:i.Table,command:(e,t)=>e.chain().focus().deleteRange(t).insertTable({rows:3,cols:3,withHeaderRow:!0}).run()}),e.enableImage&&e.onImageUpload){let n=e.onImageUpload;t.push({label:`Image`,icon:i.Image,command:(e,t)=>{e.chain().focus().deleteRange(t).run();let r=document.createElement(`input`);r.type=`file`,r.accept=`image/*`,r.onchange=()=>{let t=r.files?.[0];if(!t)return;let i=t.name.replace(/\.[^./]+$/,``);n(t).then(t=>e.chain().focus().setImage({src:t,alt:i}).run())},r.click()}})}return t}function ne(e){return l.Extension.create({name:`slashCommand`,addProseMirrorPlugins(){let t=this.editor;return[(0,te.Suggestion)({editor:t,char:`/`,startOfLine:!1,command:({editor:e,range:t,props:n})=>n.command(e,t),items:({query:t})=>M(e).filter(e=>e.label.toLowerCase().includes(t.toLowerCase())),render:()=>{let e,t;return{onStart:n=>{e=new l.ReactRenderer(j,{editor:n.editor,props:{items:n.items,command:e=>n.command(e)}}),t=n.mount(e.element)},onUpdate:t=>{e?.updateProps({items:t.items,command:e=>t.command(e)})},onKeyDown:n=>n.event.key===`Escape`?(t?.(),!0):e?.ref?.onKeyDown(n)??!1,onExit:()=>{t?.(),e?.destroy()}}}})]}})}const re=(0,s.cva)([`flex flex-col overflow-hidden rounded-md`],{variants:{variant:{outline:`border border-border bg-background shadow-xs`,ghost:`border-0`},size:{sm:`text-xs [&_.ProseMirror]:min-h-24 [&_.ProseMirror]:px-2.5 [&_.ProseMirror]:py-1.5`,md:`text-sm`,lg:`text-base [&_.ProseMirror]:min-h-56 [&_.ProseMirror]:px-4 [&_.ProseMirror]:py-3`}},defaultVariants:{variant:`outline`,size:`md`}});function N({editor:e,onImageUpload:t}){let[s,l]=(0,a.useState)(!1),[u,d]=(0,a.useState)(``),[f,p]=(0,a.useState)(``),[m,h]=(0,a.useState)(!1),[g,_]=(0,a.useState)(null),v=(0,a.useRef)(null),y=(0,a.useCallback)(e=>{e&&(d(``),p(``),_(null)),l(e)},[]),b=(0,a.useCallback)((t,n)=>{e.chain().focus().setImage({src:t,alt:n||void 0}).run(),l(!1)},[e]),x=(0,a.useCallback)(()=>{let e=u.trim();e&&b(e,f.trim())},[u,f,b]),S=(0,a.useCallback)(async e=>{let n=e.target.files?.[0];if(e.target.value=``,!(!n||!t)){_(null),h(!0);try{let e=await t(n);b(e,f.trim()||n.name.replace(/\.[^./]+$/,``))}catch{_(`Tải ảnh lên thất bại. Vui lòng thử lại.`)}finally{h(!1)}}},[t,f,b]);return(0,c.jsxs)(r.Popover,{open:s,onOpenChange:y,children:[(0,c.jsx)(r.PopoverTrigger,{asChild:!0,children:(0,c.jsx)(E,{title:`Chèn ảnh`,"aria-label":`Chèn ảnh`,"data-slot":`toolbar-image-button`,children:(0,c.jsx)(i.ImageIcon,{className:`h-3.5 w-3.5`})})}),(0,c.jsxs)(r.PopoverContent,{"data-slot":`image-dialog`,sideOffset:6,align:`start`,className:`w-72 p-3`,children:[(0,c.jsx)(`p`,{className:`mb-2 font-medium text-text-positive-strong text-xs`,children:`Chèn ảnh`}),t&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`input`,{ref:v,type:`file`,accept:`image/*`,className:`hidden`,onChange:S}),(0,c.jsx)(`button`,{type:`button`,onClick:()=>v.current?.click(),disabled:m,className:(0,o.cn)(`flex w-full items-center justify-center gap-1.5 rounded border border-border border-dashed py-2 text-text-positive-weak text-xs`,`transition-colors hover:border-primary hover:text-primary`,`disabled:pointer-events-none disabled:opacity-60`),children:m?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(n.Spinner,{className:`size-3.5`}),` Đang tải lên…`]}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i.Upload,{className:`h-3.5 w-3.5`}),` Tải ảnh từ máy`]})}),g&&(0,c.jsx)(`p`,{className:`mt-1.5 text-danger-strong text-xs`,children:g}),(0,c.jsxs)(`div`,{className:`my-2 flex items-center gap-2`,children:[(0,c.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,c.jsx)(`span`,{className:`text-text-positive-muted text-xs`,children:`hoặc`}),(0,c.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})]}),(0,c.jsxs)(`div`,{className:`flex gap-1.5`,children:[(0,c.jsx)(`input`,{type:`url`,placeholder:`https://example.com/image.png`,value:u,onChange:e=>d(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),x()),e.key===`Escape`&&l(!1)},"aria-label":`Đường dẫn ảnh`,disabled:m,className:(0,o.cn)(`flex-1 rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive`,`outline-none placeholder:text-text-positive-muted`,`focus:border-primary focus:ring-1 focus:ring-primary/30`,`disabled:pointer-events-none disabled:opacity-60`)}),(0,c.jsx)(`button`,{type:`button`,onClick:x,disabled:!u.trim()||m,className:(0,o.cn)(`rounded bg-primary px-2.5 py-1.5 font-medium text-text-negative text-xs`,`transition-colors hover:bg-primary-strong`,`disabled:pointer-events-none disabled:opacity-50`),children:`Chèn`})]}),(0,c.jsx)(`input`,{type:`text`,placeholder:`Mô tả ảnh (alt text) — tùy chọn`,value:f,onChange:e=>p(e.target.value),"aria-label":`Mô tả ảnh`,disabled:m,className:(0,o.cn)(`mt-1.5 w-full rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive`,`outline-none placeholder:text-text-positive-muted`,`focus:border-primary focus:ring-1 focus:ring-primary/30`,`disabled:pointer-events-none disabled:opacity-60`)})]})]})}function P({editor:e}){let[t,n]=(0,a.useState)(!1),[s,l]=(0,a.useState)({rows:0,cols:0}),u=(0,a.useCallback)((t,r)=>{e.chain().focus().insertTable({rows:t,cols:r,withHeaderRow:!0}).run(),n(!1)},[e]);return(0,c.jsxs)(r.Popover,{open:t,onOpenChange:e=>{n(e),e||l({rows:0,cols:0})},children:[(0,c.jsx)(r.PopoverTrigger,{asChild:!0,children:(0,c.jsx)(E,{title:`Chèn bảng`,"aria-label":`Chèn bảng`,"data-slot":`toolbar-table-button`,children:(0,c.jsx)(i.Table,{className:`h-3.5 w-3.5`})})}),(0,c.jsxs)(r.PopoverContent,{"data-slot":`table-insert-menu`,sideOffset:6,align:`start`,className:`w-auto p-3`,children:[(0,c.jsx)(`p`,{className:`mb-2 font-medium text-text-positive-strong text-xs`,children:s.rows>0?`Bảng ${s.rows} × ${s.cols}`:`Chọn kích thước bảng`}),(0,c.jsx)(`div`,{className:`grid grid-cols-6 gap-1`,onMouseLeave:()=>l({rows:0,cols:0}),children:Array.from({length:36},(e,t)=>{let n=Math.floor(t/6)+1,r=t%6+1,i=n<=s.rows&&r<=s.cols;return(0,c.jsx)(`button`,{type:`button`,"aria-label":`Bảng ${n} hàng, ${r} cột`,onMouseEnter:()=>l({rows:n,cols:r}),onClick:()=>u(n,r),className:(0,o.cn)(`h-4 w-4 rounded-sm border border-border`,i?`border-primary bg-primary-muted`:`bg-muted-muted/40`)},`${n}-${r}`)})})]})]})}const ie=[{label:`Yellow`,value:`#fde047`},{label:`Green`,value:`#86efac`},{label:`Blue`,value:`#93c5fd`},{label:`Pink`,value:`#f9a8d4`},{label:`Orange`,value:`#fdba74`},{label:`Purple`,value:`#c4b5fd`},{label:`Red`,value:`#fca5a5`},{label:`Cyan`,value:`#67e8f9`},{label:`Lime`,value:`#bef264`},{label:`Gray`,value:`#d1d5db`}],F=[{label:`Default`,value:``},{label:`Red`,value:`#ef4444`},{label:`Orange`,value:`#f97316`},{label:`Yellow`,value:`#eab308`},{label:`Green`,value:`#22c55e`},{label:`Blue`,value:`#3b82f6`},{label:`Purple`,value:`#a855f7`},{label:`Pink`,value:`#ec4899`},{label:`Gray`,value:`#6b7280`},{label:`Black`,value:`#000000`}],I=[{label:`Plain text`,value:`plaintext`},{label:`JavaScript`,value:`javascript`},{label:`TypeScript`,value:`typescript`},{label:`Python`,value:`python`},{label:`Java`,value:`java`},{label:`C#`,value:`csharp`},{label:`C++`,value:`cpp`},{label:`Go`,value:`go`},{label:`Rust`,value:`rust`},{label:`PHP`,value:`php`},{label:`Ruby`,value:`ruby`},{label:`Swift`,value:`swift`},{label:`Kotlin`,value:`kotlin`},{label:`SQL`,value:`sql`},{label:`Bash`,value:`bash`},{label:`JSON`,value:`json`},{label:`YAML`,value:`yaml`},{label:`CSS`,value:`css`},{label:`HTML/XML`,value:`xml`},{label:`Markdown`,value:`markdown`}];function L({editor:e,className:n,enableLink:a,enableTaskList:s,enableHighlight:u,enableColor:d,enableImage:f,enableTable:p,onImageUpload:m}){let h=(0,l.useEditorState)({editor:e,selector:e=>e.editor.isActive(`heading`,{level:1})?1:e.editor.isActive(`heading`,{level:2})?2:e.editor.isActive(`heading`,{level:3})?3:null}),g=(0,l.useEditorState)({editor:e,selector:e=>({bold:e.editor.isActive(`bold`),italic:e.editor.isActive(`italic`),underline:e.editor.isActive(`underline`),strike:e.editor.isActive(`strike`),code:e.editor.isActive(`code`)})}),_=(0,l.useEditorState)({editor:e,selector:e=>({bulletList:e.editor.isActive(`bulletList`),orderedList:e.editor.isActive(`orderedList`),taskList:e.editor.isActive(`taskList`),blockquote:e.editor.isActive(`blockquote`),codeBlock:e.editor.isActive(`codeBlock`),codeBlockLanguage:e.editor.getAttributes(`codeBlock`).language??`plaintext`,table:e.editor.isActive(`table`)})}),v=(0,l.useEditorState)({editor:e,selector:e=>({left:e.editor.isActive({textAlign:`left`}),center:e.editor.isActive({textAlign:`center`}),right:e.editor.isActive({textAlign:`right`}),justify:e.editor.isActive({textAlign:`justify`})})}),y=h?`H${h}`:`P`;return(0,c.jsxs)(`div`,{"data-slot":`text-editor-toolbar`,role:`toolbar`,"aria-label":`Định dạng văn bản`,className:(0,o.cn)(`sticky top-0 z-10 flex flex-wrap items-center gap-0.5 border-border border-b bg-muted-muted p-1.5`,n),children:[(0,c.jsx)(E,{onClick:()=>e.chain().focus().undo().run(),disabled:!e.can().undo(),"aria-label":`Hoàn tác`,title:`Undo (Ctrl+Z)`,children:(0,c.jsx)(i.Undo,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().redo().run(),disabled:!e.can().redo(),"aria-label":`Làm lại`,title:`Redo (Ctrl+Y)`,children:(0,c.jsx)(i.Redo,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(D,{}),(0,c.jsxs)(t.DropdownMenu,{children:[(0,c.jsx)(t.DropdownMenuTrigger,{asChild:!0,children:(0,c.jsxs)(`button`,{type:`button`,"data-slot":`toolbar-heading-trigger`,"aria-label":`Kiểu đoạn văn`,"aria-haspopup":`menu`,className:(0,o.cn)(`inline-flex h-8 items-center gap-1 rounded px-1.5 font-medium text-xs transition-colors`,`hover:bg-muted-muted hover:text-text-positive-strong`,`disabled:pointer-events-none disabled:opacity-40`,h!==null&&`bg-primary-muted text-primary hover:bg-primary-muted/80 hover:text-primary`),children:[(0,c.jsx)(`span`,{className:`w-5 text-center`,children:y}),(0,c.jsx)(i.ChevronDown,{className:`h-3 w-3 opacity-60`})]})}),(0,c.jsxs)(t.DropdownMenuContent,{align:`start`,className:`min-w-32`,children:[(0,c.jsx)(t.DropdownMenuItem,{className:`px-2 py-1.5`,onClick:()=>e.chain().focus().setParagraph().run(),children:(0,c.jsx)(`span`,{className:`text-sm`,children:`Paragraph`})}),(0,c.jsx)(t.DropdownMenuItem,{className:`px-2 py-1.5`,onClick:()=>e.chain().focus().toggleHeading({level:1}).run(),children:(0,c.jsx)(`span`,{className:`font-extrabold text-sm`,children:`Heading 1`})}),(0,c.jsx)(t.DropdownMenuItem,{className:`px-2 py-1.5`,onClick:()=>e.chain().focus().toggleHeading({level:2}).run(),children:(0,c.jsx)(`span`,{className:`font-semibold text-sm`,children:`Heading 2`})}),(0,c.jsx)(t.DropdownMenuItem,{className:`px-2 py-1.5`,onClick:()=>e.chain().focus().toggleHeading({level:3}).run(),children:(0,c.jsx)(`span`,{className:`font-medium text-sm`,children:`Heading 3`})})]})]}),(0,c.jsx)(D,{}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleBold().run(),isActive:g.bold,"aria-label":`In đậm`,title:`Bold (Ctrl+B)`,children:(0,c.jsx)(i.Bold,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleItalic().run(),isActive:g.italic,"aria-label":`In nghiêng`,title:`Italic (Ctrl+I)`,children:(0,c.jsx)(i.Italic,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleUnderline().run(),isActive:g.underline,"aria-label":`Gạch chân`,title:`Underline (Ctrl+U)`,children:(0,c.jsx)(i.Underline,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleStrike().run(),isActive:g.strike,"aria-label":`Gạch ngang`,title:`Strikethrough`,children:(0,c.jsx)(i.Strikethrough,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleCode().run(),isActive:g.code,"aria-label":`Mã inline`,title:`Inline Code`,children:(0,c.jsx)(i.Code,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(D,{}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleBulletList().run(),isActive:_.bulletList,"aria-label":`Danh sách chấm`,title:`Bullet List`,children:(0,c.jsx)(i.List,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleOrderedList().run(),isActive:_.orderedList,"aria-label":`Danh sách số`,title:`Ordered List`,children:(0,c.jsx)(i.ListOrdered,{className:`h-3.5 w-3.5`})}),s&&(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleTaskList().run(),isActive:_.taskList,"aria-label":`Danh sách công việc`,title:`Task List`,children:(0,c.jsx)(i.ListChecks,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(D,{}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleBlockquote().run(),isActive:_.blockquote,"aria-label":`Trích dẫn`,title:`Blockquote`,children:(0,c.jsx)(i.Quote,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().toggleCodeBlock().run(),isActive:_.codeBlock,"aria-label":`Khối mã`,title:`Code Block`,children:(0,c.jsx)(i.Code2,{className:`h-3.5 w-3.5`})}),_.codeBlock&&(0,c.jsxs)(t.DropdownMenu,{children:[(0,c.jsx)(t.DropdownMenuTrigger,{asChild:!0,children:(0,c.jsxs)(`button`,{type:`button`,"data-slot":`toolbar-code-language-trigger`,"aria-label":`Ngôn ngữ lập trình`,"aria-haspopup":`menu`,className:(0,o.cn)(`inline-flex h-7 items-center gap-1 rounded px-1.5 text-text-positive-weak text-xs transition-colors`,`hover:bg-muted-muted hover:text-text-positive-strong`),children:[(0,c.jsx)(`span`,{children:I.find(e=>e.value===_.codeBlockLanguage)?.label??`Plain text`}),(0,c.jsx)(i.ChevronDown,{className:`h-3 w-3 opacity-60`})]})}),(0,c.jsx)(t.DropdownMenuContent,{align:`start`,className:`max-h-72 min-w-40 overflow-y-auto`,children:I.map(n=>(0,c.jsx)(t.DropdownMenuItem,{onClick:()=>e.chain().focus().updateAttributes(`codeBlock`,{language:n.value}).run(),children:(0,c.jsx)(`span`,{className:`text-sm`,children:n.label})},n.value))})]}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().setHorizontalRule().run(),"aria-label":`Đường kẻ ngang`,title:`Horizontal Rule`,children:(0,c.jsx)(i.Minus,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(D,{}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().setTextAlign(`left`).run(),isActive:v.left,"aria-label":`Căn trái`,title:`Align Left`,children:(0,c.jsx)(i.AlignLeft,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().setTextAlign(`center`).run(),isActive:v.center,"aria-label":`Căn giữa`,title:`Align Center`,children:(0,c.jsx)(i.AlignCenter,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().setTextAlign(`right`).run(),isActive:v.right,"aria-label":`Căn phải`,title:`Align Right`,children:(0,c.jsx)(i.AlignRight,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>e.chain().focus().setTextAlign(`justify`).run(),isActive:v.justify,"aria-label":`Căn đều`,title:`Align Justify`,children:(0,c.jsx)(i.AlignJustify,{className:`h-3.5 w-3.5`})}),a&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(D,{}),(0,c.jsx)(O,{editor:e})]}),f&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(D,{}),(0,c.jsx)(N,{editor:e,onImageUpload:m})]}),p&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(D,{}),(0,c.jsx)(P,{editor:e}),_.table&&(0,c.jsxs)(t.DropdownMenu,{children:[(0,c.jsx)(t.DropdownMenuTrigger,{asChild:!0,children:(0,c.jsx)(E,{title:`Sửa bảng`,"aria-label":`Sửa bảng`,children:(0,c.jsx)(i.TableCellsMerge,{className:`h-3.5 w-3.5`})})}),(0,c.jsxs)(t.DropdownMenuContent,{align:`start`,className:`min-w-44`,children:[(0,c.jsxs)(t.DropdownMenuItem,{onClick:()=>e.chain().focus().addRowBefore().run(),children:[(0,c.jsx)(i.Rows3,{className:`mr-2 h-3.5 w-3.5`}),` Thêm hàng phía trên`]}),(0,c.jsxs)(t.DropdownMenuItem,{onClick:()=>e.chain().focus().addRowAfter().run(),children:[(0,c.jsx)(i.Rows3,{className:`mr-2 h-3.5 w-3.5`}),` Thêm hàng phía dưới`]}),(0,c.jsxs)(t.DropdownMenuItem,{onClick:()=>e.chain().focus().deleteRow().run(),children:[(0,c.jsx)(i.Trash2,{className:`mr-2 h-3.5 w-3.5`}),` Xóa hàng`]}),(0,c.jsx)(t.DropdownMenuSeparator,{}),(0,c.jsxs)(t.DropdownMenuItem,{onClick:()=>e.chain().focus().addColumnBefore().run(),children:[(0,c.jsx)(i.Columns3,{className:`mr-2 h-3.5 w-3.5`}),` Thêm cột bên trái`]}),(0,c.jsxs)(t.DropdownMenuItem,{onClick:()=>e.chain().focus().addColumnAfter().run(),children:[(0,c.jsx)(i.Columns3,{className:`mr-2 h-3.5 w-3.5`}),` Thêm cột bên phải`]}),(0,c.jsxs)(t.DropdownMenuItem,{onClick:()=>e.chain().focus().deleteColumn().run(),children:[(0,c.jsx)(i.Trash2,{className:`mr-2 h-3.5 w-3.5`}),` Xóa cột`]}),(0,c.jsx)(t.DropdownMenuSeparator,{}),(0,c.jsxs)(t.DropdownMenuItem,{onClick:()=>e.chain().focus().deleteTable().run(),className:`text-danger-strong`,children:[(0,c.jsx)(i.Trash2,{className:`mr-2 h-3.5 w-3.5`}),` Xóa bảng`]})]})]})]}),(d||u)&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(D,{}),d&&(0,c.jsxs)(r.Popover,{children:[(0,c.jsx)(r.PopoverTrigger,{asChild:!0,children:(0,c.jsx)(E,{title:`Text Color`,"aria-label":`Màu chữ`,children:(0,c.jsx)(i.Palette,{className:`h-3.5 w-3.5`})})}),(0,c.jsxs)(r.PopoverContent,{align:`start`,className:`w-44 p-2`,children:[(0,c.jsx)(`p`,{className:`mb-1.5 font-medium text-text-positive-weak text-xs`,children:`Text Color`}),(0,c.jsx)(`div`,{className:`grid grid-cols-5 gap-1`,children:F.map(t=>(0,c.jsx)(`button`,{type:`button`,title:t.label,onClick:()=>{t.value?e.chain().focus().setColor(t.value).run():e.chain().focus().unsetColor().run()},className:(0,o.cn)(`h-6 w-6 rounded border border-border transition-transform hover:scale-110`,!t.value&&`bg-background text-[10px] text-text-positive leading-none`),style:t.value?{backgroundColor:t.value}:void 0,children:!t.value&&`∅`},t.label))})]})]}),u&&(0,c.jsxs)(r.Popover,{children:[(0,c.jsx)(r.PopoverTrigger,{asChild:!0,children:(0,c.jsx)(E,{title:`Highlight`,"aria-label":`Tô sáng`,children:(0,c.jsx)(i.Highlighter,{className:`h-3.5 w-3.5`})})}),(0,c.jsxs)(r.PopoverContent,{align:`start`,className:`w-44 p-2`,children:[(0,c.jsx)(`p`,{className:`mb-1.5 font-medium text-text-positive-weak text-xs`,children:`Highlight`}),(0,c.jsx)(`div`,{className:`grid grid-cols-5 gap-1`,children:ie.map(t=>(0,c.jsx)(`button`,{type:`button`,title:t.label,onClick:()=>e.chain().focus().toggleHighlight({color:t.value}).run(),className:`h-6 w-6 rounded border border-border transition-transform hover:scale-110`,style:{backgroundColor:t.value}},t.label))}),(0,c.jsx)(`button`,{type:`button`,onClick:()=>e.chain().focus().unsetHighlight().run(),className:`mt-1.5 w-full rounded border border-border py-0.5 text-center text-text-positive-weak text-xs hover:bg-muted-muted`,children:`Clear highlight`})]})]})]})]})}const ae=(0,T.createLowlight)(T.common),oe=p.default.extend({addNodeView(){return(0,l.ReactNodeViewRenderer)(A)}}),R=[`p`,`h1`,`h2`,`h3`,`strong`,`em`,`s`,`u`,`code`,`pre`,`blockquote`,`ul`,`ol`,`li`,`hr`,`br`],z=[`class`,`style`];function se(e){let t=new Set(R),n=new Set(z);if(e.enableLink&&(t.add(`a`),n.add(`href`).add(`target`).add(`rel`)),e.enableHighlight&&(t.add(`mark`),n.add(`data-color`)),e.enableColor&&t.add(`span`),e.enableTaskList){for(let e of[`label`,`input`,`div`,`span`])t.add(e);for(let e of[`data-type`,`data-checked`,`type`,`checked`,`disabled`])n.add(e)}if(e.enableImage){t.add(`img`);for(let e of[`src`,`alt`,`title`])n.add(e)}if(e.enableTable){for(let e of[`table`,`tbody`,`thead`,`tr`,`td`,`th`,`colgroup`,`col`])t.add(e);for(let e of[`colspan`,`rowspan`,`colwidth`])n.add(e)}return{ALLOWED_TAGS:Array.from(t),ALLOWED_ATTR:Array.from(n)}}function B(e,t){return typeof window>`u`?e:w.default.sanitize(e,t)}function V(e){return e.name.replace(/\.[^./]+$/,``)}function H({value:e,defaultValue:t,onChange:n,placeholder:r=`Start writing...`,readOnly:s=!1,showToolbar:p=!0,variant:w,size:T,className:te,toolbarClassName:k,editorClassName:A,maxLength:j,showCharacterCount:M,onCharacterCount:N,enableLink:P,enableBubbleMenu:ie,enableTaskList:F,enableHighlight:I,enableColor:R,enableImage:z,enableTable:H,enableSlashCommand:U,onImageUpload:W}){let G=j!==void 0||M||N!==void 0,K=R||I,q=(0,a.useMemo)(()=>se({enableLink:P,enableHighlight:I,enableColor:R,enableTaskList:F,enableImage:z,enableTable:H}),[P,I,R,F,z,H]),ce=(0,a.useMemo)(()=>{let e=[C.default.configure({link:!1,underline:!1,codeBlock:!1,listKeymap:!1}),S.default,g.default.configure({placeholder:r}),b.default.configure({types:[`heading`,`paragraph`]}),h.ListKeymap,d.default.configure({lowlight:ae,defaultLanguage:`plaintext`})];return K&&e.push(x.TextStyle),P&&e.push(m.Link.configure({openOnClick:!1,linkOnPaste:!0,defaultProtocol:`https`})),F&&e.push(y.TaskList,v.TaskItem.configure({nested:!0})),I&&e.push(f.Highlight.configure({multicolor:!0})),R&&e.push(x.Color),z&&e.push(oe.configure({inline:!1,allowBase64:!1})),H&&e.push(_.Table.configure({resizable:!0}),_.TableRow,_.TableHeader,_.TableCell),U&&e.push(ne({enableTaskList:F,enableTable:H,enableImage:z,onImageUpload:W})),G&&e.push(u.CharacterCount.configure({limit:j})),e},[G,r,j,I,K,F,P,R,z,H,U,W]),[le]=(0,a.useState)(()=>{let n=e??t;return n&&B(n,q)}),J=(0,a.useRef)(n);J.current=n;let Y=(0,a.useRef)(null),X=e=>{Y.current&&(clearTimeout(Y.current),Y.current=null,J.current?.(B(e,q)))},ue=(0,a.useRef)(X);ue.current=X;let Z=(0,l.useEditor)({extensions:ce,content:le,editable:!s,shouldRerenderOnTransaction:!1,editorProps:{handleDrop:(e,t)=>{if(!z||!W)return!1;let n=t.dataTransfer?.files?.[0];return n?.type.startsWith(`image/`)?(t.preventDefault(),W(n).then(e=>Z?.chain().focus().setImage({src:e,alt:V(n)}).run()),!0):!1},handlePaste:(e,t)=>{if(!z||!W)return!1;let n=Array.from(t.clipboardData?.items??[]).find(e=>e.type.startsWith(`image/`))?.getAsFile();return n?(t.preventDefault(),W(n).then(e=>Z?.chain().focus().setImage({src:e,alt:V(n)}).run()),!0):!1}},onUpdate:({editor:e})=>{if(N){let t=e.storage.characterCount;N({characters:t.characters(),words:t.words()})}J.current&&(Y.current&&clearTimeout(Y.current),Y.current=setTimeout(()=>X(e.getHTML()),200))},onBlur:({editor:e})=>X(e.getHTML())}),Q=(0,a.useRef)(Z);Q.current=Z,(0,a.useEffect)(()=>()=>{Q.current&&ue.current(Q.current.getHTML())},[]),(0,a.useEffect)(()=>{if(!Z||e===void 0)return;let t=B(e,q);Z.getHTML()!==t&&Z.commands.setContent(t)},[Z,e,q]),(0,a.useEffect)(()=>{Z&&Z.setEditable(!s)},[Z,s]);let de=(0,l.useEditorState)({editor:Z,selector:e=>{let t=e.editor?.storage?.characterCount;return t?t.characters():0}}),fe=(0,l.useEditorState)({editor:Z,selector:e=>{let t=e.editor?.storage?.characterCount;return t?t.words():0}}),pe=M||j!==void 0,me=j!==void 0&&de>j*.9,$=(0,l.useEditorState)({editor:Z,selector:e=>e.editor?{bold:e.editor.isActive(`bold`),italic:e.editor.isActive(`italic`),underline:e.editor.isActive(`underline`),strike:e.editor.isActive(`strike`)}:{bold:!1,italic:!1,underline:!1,strike:!1}});return(0,c.jsxs)(`div`,{"data-slot":`text-editor`,className:(0,o.cn)(`lunas-text-editor`,re({variant:w,size:T}),te),children:[p&&!s&&Z&&(0,c.jsx)(L,{editor:Z,className:k,enableLink:P,enableTaskList:F,enableHighlight:I,enableColor:R,enableImage:z,enableTable:H,onImageUpload:W}),ie&&!s&&Z&&(0,c.jsxs)(ee.BubbleMenu,{editor:Z,options:{placement:`top`},className:(0,o.cn)(`z-50 flex items-center gap-0.5 rounded-md border border-border bg-popover p-1 shadow-dropdown`),children:[(0,c.jsx)(E,{onClick:()=>Z.chain().focus().toggleBold().run(),isActive:$.bold,"aria-label":`In đậm`,title:`Bold (Ctrl+B)`,children:(0,c.jsx)(i.Bold,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>Z.chain().focus().toggleItalic().run(),isActive:$.italic,"aria-label":`In nghiêng`,title:`Italic (Ctrl+I)`,children:(0,c.jsx)(i.Italic,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>Z.chain().focus().toggleUnderline().run(),isActive:$.underline,"aria-label":`Gạch chân`,title:`Underline (Ctrl+U)`,children:(0,c.jsx)(i.Underline,{className:`h-3.5 w-3.5`})}),(0,c.jsx)(E,{onClick:()=>Z.chain().focus().toggleStrike().run(),isActive:$.strike,"aria-label":`Gạch ngang`,title:`Strikethrough`,children:(0,c.jsx)(i.Strikethrough,{className:`h-3.5 w-3.5`})}),P&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(D,{}),(0,c.jsx)(O,{editor:Z})]})]}),(0,c.jsx)(l.EditorContent,{editor:Z,"data-slot":`text-editor-content`,className:(0,o.cn)(`flex-1 bg-white text-text-positive`,A)}),pe&&G&&(0,c.jsxs)(`div`,{"data-slot":`text-editor-footer`,className:`flex items-center justify-between border-border border-t bg-muted-muted/30 px-3 py-1 text-text-positive-weak text-xs`,children:[(0,c.jsxs)(`span`,{children:[fe,` words`]}),(0,c.jsxs)(`span`,{"data-warning":me||void 0,className:`data-warning:text-warning-strong`,children:[de,j?` / ${j}`:``,` characters`]})]})]})}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return H}});
|
|
2
|
+
//# sourceMappingURL=text-editor-DWZf3yrW.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-editor-DWZf3yrW.cjs","names":["Popover","PopoverTrigger","Link2","PopoverContent","Link2Off","NodeViewWrapper","Heading1","Heading2","Heading3","List","ListOrdered","ListChecks","Quote","Code2","Minus","TableIcon","ImageIcon","Extension","ReactRenderer","Popover","PopoverTrigger","ImageIcon","PopoverContent","Spinner","Upload","Popover","PopoverTrigger","TableIcon","PopoverContent","Undo","Redo","DropdownMenu","DropdownMenuTrigger","ChevronDown","DropdownMenuContent","DropdownMenuItem","Bold","Italic","Underline","Strikethrough","Code","List","ListOrdered","ListChecks","Quote","Code2","Minus","AlignLeft","AlignCenter","AlignRight","AlignJustify","TableCellsMerge","Rows3","Trash2","DropdownMenuSeparator","Columns3","Popover","PopoverTrigger","Palette","PopoverContent","Highlighter","lowlight","common","Image","DOMPurify","StarterKit","Underline","Placeholder","TextAlign","ListKeymap","CodeBlockLowlight","TextStyle","Link","TaskList","TaskItem","Highlight","Color","Table","TableRow","TableHeader","TableCell","CharacterCount","BubbleMenu","Bold","Italic","UnderlineIcon","Strikethrough","EditorContent"],"sources":["../packages/components/features/text-editor/toolbar-primitives.tsx","../packages/components/features/text-editor/link-dialog.tsx","../packages/components/features/text-editor/image-node-view.tsx","../packages/components/features/text-editor/slash-command-menu.tsx","../packages/components/features/text-editor/slash-command.ts","../packages/components/features/text-editor/text-editor.variants.ts","../packages/components/features/text-editor/image-dialog.tsx","../packages/components/features/text-editor/table-insert-menu.tsx","../packages/components/features/text-editor/toolbar.tsx","../packages/components/features/text-editor/text-editor.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\ninterface ToolbarButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n isActive?: boolean;\n}\n\nfunction ToolbarButton({ isActive, className, children, ...props }: ToolbarButtonProps) {\n return (\n <button\n type=\"button\"\n data-slot=\"toolbar-button\"\n data-active={isActive || undefined}\n aria-pressed={isActive === undefined ? undefined : isActive}\n className={cn(\n 'inline-flex size-8 shrink-0 items-center justify-center rounded text-sm outline-none transition-colors min-w-8',\n 'hover:bg-muted-weak hover:text-text-positive-strong',\n 'focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',\n 'disabled:pointer-events-none disabled:opacity-40',\n isActive && 'bg-primary-muted text-primary hover:bg-primary-muted/80 hover:text-primary',\n className\n )}\n {...props}\n >\n {children}\n </button>\n );\n}\n\nfunction ToolbarDivider() {\n return <div data-slot=\"toolbar-divider\" role=\"separator\" aria-orientation=\"vertical\" className=\"mx-0.5 h-5 w-px shrink-0 bg-border\" />;\n}\n\n// biome-ignore lint/style/useComponentExportOnlyModules: type export needed by sibling feature files\nexport type { ToolbarButtonProps };\nexport { ToolbarButton, ToolbarDivider };\n","'use client';\n\nimport { useCallback, useState } from 'react';\n\nimport { Link2, Link2Off } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nimport { type Editor, useEditorState } from '@tiptap/react';\nimport { ToolbarButton } from './toolbar-primitives';\n\nexport interface LinkDialogProps {\n editor: Editor;\n}\n\nfunction LinkDialog({ editor }: LinkDialogProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [url, setUrl] = useState('');\n\n const isLinkActive = useEditorState({\n editor,\n selector: ctx => ctx.editor.isActive('link'),\n });\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (open) {\n const existingHref = editor.getAttributes('link').href ?? '';\n setUrl(existingHref);\n }\n setIsOpen(open);\n },\n [editor]\n );\n\n const handleApply = useCallback(() => {\n const trimmed = url.trim();\n if (!trimmed) return;\n editor.chain().focus().setLink({ href: trimmed, target: '_blank' }).run();\n setIsOpen(false);\n }, [editor, url]);\n\n const handleRemove = useCallback(() => {\n editor.chain().focus().unsetLink().run();\n setIsOpen(false);\n }, [editor]);\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleApply();\n }\n if (e.key === 'Escape') {\n setIsOpen(false);\n }\n };\n\n return (\n <Popover open={isOpen} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <ToolbarButton isActive={isLinkActive} aria-label=\"Liên kết\" title=\"Link (Ctrl+K)\" data-slot=\"toolbar-link-button\">\n <Link2 className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent data-slot=\"link-dialog\" sideOffset={6} align=\"start\" className=\"w-72 p-3\">\n <p className=\"mb-2 font-medium text-text-positive-strong text-xs\">{isLinkActive ? 'Edit Link' : 'Insert Link'}</p>\n <div className=\"flex gap-1.5\">\n <input\n type=\"url\"\n placeholder=\"https://example.com\"\n value={url}\n onChange={e => setUrl(e.target.value)}\n onKeyDown={handleKeyDown}\n aria-label=\"Đường dẫn liên kết\"\n autoFocus\n className={cn(\n 'flex-1 rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive',\n 'outline-none placeholder:text-text-positive-muted',\n 'focus:border-primary focus:ring-1 focus:ring-primary/30'\n )}\n />\n <button\n type=\"button\"\n onClick={handleApply}\n disabled={!url.trim()}\n className={cn(\n 'rounded bg-primary px-2.5 py-1.5 font-medium text-text-negative text-xs',\n 'transition-colors hover:bg-primary-strong',\n 'disabled:pointer-events-none disabled:opacity-50'\n )}\n >\n Apply\n </button>\n </div>\n {isLinkActive && (\n <button type=\"button\" onClick={handleRemove} className=\"mt-2 flex items-center gap-1 text-danger-strong text-xs hover:underline\">\n <Link2Off className=\"h-3 w-3\" />\n Remove link\n </button>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n\nexport { LinkDialog };\n","'use client';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport type { ReactNodeViewProps } from '@tiptap/react';\nimport { NodeViewWrapper } from '@tiptap/react';\n\n/** Best-effort short label for the caption link — falls back to the raw src for relative/unparsable URLs. */\nfunction captionLabel(src: string): string {\n try {\n return new URL(src).hostname;\n } catch {\n return src;\n }\n}\n\nfunction ImageNodeView({ node, selected }: ReactNodeViewProps) {\n const src = node.attrs.src as string;\n const alt = node.attrs.alt as string | undefined;\n\n return (\n <NodeViewWrapper data-slot=\"text-editor-image\" className=\"my-5 flex flex-col items-center\">\n <img src={src} alt={alt ?? ''} className={cn('max-w-full rounded-lg border border-border', selected && 'outline-2 outline-primary outline-offset-2')} />\n <a\n href={src}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n contentEditable={false}\n className=\"mt-1.5 text-text-positive-weak text-xs hover:text-text-positive hover:underline\"\n >\n {captionLabel(src)}\n </a>\n </NodeViewWrapper>\n );\n}\n\nexport { ImageNodeView };\n","'use client';\n\nimport { forwardRef, useEffect, useImperativeHandle, useState } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport type { SlashCommandItem } from './slash-command';\n\nexport interface SlashCommandMenuProps {\n items: SlashCommandItem[];\n command: (item: SlashCommandItem) => void;\n}\n\nexport interface SlashCommandMenuHandle {\n onKeyDown: (props: { event: KeyboardEvent }) => boolean;\n}\n\nconst SlashCommandMenu = forwardRef<SlashCommandMenuHandle, SlashCommandMenuProps>(({ items, command }, ref) => {\n const [selectedIndex, setSelectedIndex] = useState(0);\n\n useEffect(() => {\n setSelectedIndex(0);\n }, []);\n\n useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }) => {\n if (items.length === 0) return false;\n if (event.key === 'ArrowDown') {\n setSelectedIndex(i => (i + 1) % items.length);\n return true;\n }\n if (event.key === 'ArrowUp') {\n setSelectedIndex(i => (i - 1 + items.length) % items.length);\n return true;\n }\n if (event.key === 'Enter') {\n const item = items[selectedIndex];\n if (item) command(item);\n return true;\n }\n return false;\n },\n }));\n\n if (items.length === 0) {\n return (\n <div data-slot=\"slash-command-menu\" className=\"w-56 rounded-md border border-border bg-popover p-2 text-text-positive-weak text-xs shadow-dropdown\">\n Không tìm thấy lệnh phù hợp\n </div>\n );\n }\n\n return (\n <div\n data-slot=\"slash-command-menu\"\n role=\"listbox\"\n aria-label=\"Lệnh chèn nhanh\"\n className=\"max-h-72 w-56 overflow-y-auto rounded-md border border-border bg-popover p-1 shadow-dropdown\"\n >\n {items.map((item, index) => {\n const Icon = item.icon;\n return (\n <button\n key={item.label}\n type=\"button\"\n role=\"option\"\n aria-selected={index === selectedIndex}\n onClick={() => command(item)}\n onMouseEnter={() => setSelectedIndex(index)}\n className={cn(\n 'flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors',\n index === selectedIndex ? 'bg-primary-muted text-primary' : 'text-text-positive hover:bg-muted-muted'\n )}\n >\n <Icon className=\"h-3.5 w-3.5 shrink-0\" />\n <span>{item.label}</span>\n </button>\n );\n })}\n </div>\n );\n});\nSlashCommandMenu.displayName = 'SlashCommandMenu';\n\nexport { SlashCommandMenu };\n","import {\n Code2,\n Heading1,\n Heading2,\n Heading3,\n Image as ImageIcon,\n List,\n ListChecks,\n ListOrdered,\n type LucideIcon,\n Minus,\n Quote,\n Table as TableIcon,\n} from 'lucide-react';\n\nimport { type Editor, Extension, type Range, ReactRenderer } from '@tiptap/react';\nimport { Suggestion } from '@tiptap/suggestion';\nimport { SlashCommandMenu, type SlashCommandMenuHandle } from './slash-command-menu';\n\nexport interface SlashCommandItem {\n label: string;\n icon: LucideIcon;\n command: (editor: Editor, range: Range) => void;\n}\n\nexport interface SlashCommandExtensionOptions {\n enableTaskList?: boolean;\n enableTable?: boolean;\n enableImage?: boolean;\n onImageUpload?: (file: File) => Promise<string>;\n}\n\nfunction buildItems(options: SlashCommandExtensionOptions): SlashCommandItem[] {\n const items: SlashCommandItem[] = [\n { label: 'Heading 1', icon: Heading1, command: (editor, range) => editor.chain().focus().deleteRange(range).toggleHeading({ level: 1 }).run() },\n { label: 'Heading 2', icon: Heading2, command: (editor, range) => editor.chain().focus().deleteRange(range).toggleHeading({ level: 2 }).run() },\n { label: 'Heading 3', icon: Heading3, command: (editor, range) => editor.chain().focus().deleteRange(range).toggleHeading({ level: 3 }).run() },\n { label: 'Bullet list', icon: List, command: (editor, range) => editor.chain().focus().deleteRange(range).toggleBulletList().run() },\n { label: 'Ordered list', icon: ListOrdered, command: (editor, range) => editor.chain().focus().deleteRange(range).toggleOrderedList().run() },\n ];\n\n if (options.enableTaskList) {\n items.push({\n label: 'Task list',\n icon: ListChecks,\n command: (editor, range) => editor.chain().focus().deleteRange(range).toggleTaskList().run(),\n });\n }\n\n items.push(\n { label: 'Blockquote', icon: Quote, command: (editor, range) => editor.chain().focus().deleteRange(range).toggleBlockquote().run() },\n { label: 'Code block', icon: Code2, command: (editor, range) => editor.chain().focus().deleteRange(range).toggleCodeBlock().run() },\n { label: 'Horizontal rule', icon: Minus, command: (editor, range) => editor.chain().focus().deleteRange(range).setHorizontalRule().run() }\n );\n\n if (options.enableTable) {\n items.push({\n label: 'Table',\n icon: TableIcon,\n command: (editor, range) => editor.chain().focus().deleteRange(range).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run(),\n });\n }\n\n // Slash-triggered image insertion only makes sense when there's an upload target —\n // there's no room in this transient popup to fall back to a \"paste a URL\" flow.\n if (options.enableImage && options.onImageUpload) {\n const upload = options.onImageUpload;\n items.push({\n label: 'Image',\n icon: ImageIcon,\n command: (editor, range) => {\n editor.chain().focus().deleteRange(range).run();\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = 'image/*';\n input.onchange = () => {\n const file = input.files?.[0];\n if (!file) return;\n const alt = file.name.replace(/\\.[^./]+$/, '');\n upload(file).then(src => editor.chain().focus().setImage({ src, alt }).run());\n };\n input.click();\n },\n });\n }\n\n return items;\n}\n\n/** Builds the `/` slash-command extension, scoped to whichever features are enabled on this editor instance. */\nfunction createSlashCommandExtension(options: SlashCommandExtensionOptions) {\n return Extension.create({\n name: 'slashCommand',\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n\n return [\n Suggestion<SlashCommandItem>({\n editor,\n char: '/',\n startOfLine: false,\n command: ({ editor: e, range, props }) => props.command(e, range),\n items: ({ query }) => buildItems(options).filter(item => item.label.toLowerCase().includes(query.toLowerCase())),\n render: () => {\n let component: ReactRenderer<SlashCommandMenuHandle, SlashCommandMenuProps> | undefined;\n let unmount: (() => void) | undefined;\n\n return {\n onStart: props => {\n component = new ReactRenderer(SlashCommandMenu, {\n editor: props.editor,\n props: { items: props.items, command: (item: SlashCommandItem) => props.command(item) },\n });\n unmount = props.mount(component.element);\n },\n onUpdate: props => {\n component?.updateProps({ items: props.items, command: (item: SlashCommandItem) => props.command(item) });\n },\n onKeyDown: props => {\n if (props.event.key === 'Escape') {\n unmount?.();\n return true;\n }\n return component?.ref?.onKeyDown(props) ?? false;\n },\n onExit: () => {\n unmount?.();\n component?.destroy();\n },\n };\n },\n }),\n ];\n },\n });\n}\n\ninterface SlashCommandMenuProps {\n items: SlashCommandItem[];\n command: (item: SlashCommandItem) => void;\n}\n\nexport { createSlashCommandExtension };\n","import { cva, type VariantProps } from 'class-variance-authority';\n\nexport const textEditorVariants = cva(['flex flex-col overflow-hidden rounded-md'], {\n variants: {\n variant: {\n outline: 'border border-border bg-background shadow-xs',\n ghost: 'border-0',\n },\n size: {\n sm: 'text-xs [&_.ProseMirror]:min-h-24 [&_.ProseMirror]:px-2.5 [&_.ProseMirror]:py-1.5',\n md: 'text-sm',\n lg: 'text-base [&_.ProseMirror]:min-h-56 [&_.ProseMirror]:px-4 [&_.ProseMirror]:py-3',\n },\n },\n defaultVariants: {\n variant: 'outline',\n size: 'md',\n },\n});\n\nexport type TextEditorVariantProps = VariantProps<typeof textEditorVariants>;\n","'use client';\n\nimport { useCallback, useRef, useState } from 'react';\n\nimport { ImageIcon, Upload } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { Spinner } from '@/components/ui/spinner';\n\nimport type { Editor } from '@tiptap/react';\nimport { ToolbarButton } from './toolbar-primitives';\n\nexport interface ImageDialogProps {\n editor: Editor;\n onImageUpload?: (file: File) => Promise<string>;\n}\n\nfunction ImageDialog({ editor, onImageUpload }: ImageDialogProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [url, setUrl] = useState('');\n const [alt, setAlt] = useState('');\n const [isUploading, setIsUploading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleOpenChange = useCallback((open: boolean) => {\n if (open) {\n setUrl('');\n setAlt('');\n setError(null);\n }\n setIsOpen(open);\n }, []);\n\n const insertImage = useCallback(\n (src: string, altText: string) => {\n editor\n .chain()\n .focus()\n .setImage({ src, alt: altText || undefined })\n .run();\n setIsOpen(false);\n },\n [editor]\n );\n\n const handleApplyUrl = useCallback(() => {\n const trimmed = url.trim();\n if (!trimmed) return;\n insertImage(trimmed, alt.trim());\n }, [url, alt, insertImage]);\n\n const handleFileChange = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (!file || !onImageUpload) return;\n\n setError(null);\n setIsUploading(true);\n try {\n const uploadedUrl = await onImageUpload(file);\n // Falls back to the file name (no extension) when the user didn't type an alt text.\n insertImage(uploadedUrl, alt.trim() || file.name.replace(/\\.[^./]+$/, ''));\n } catch {\n setError('Tải ảnh lên thất bại. Vui lòng thử lại.');\n } finally {\n setIsUploading(false);\n }\n },\n [onImageUpload, alt, insertImage]\n );\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleApplyUrl();\n }\n if (e.key === 'Escape') {\n setIsOpen(false);\n }\n };\n\n return (\n <Popover open={isOpen} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <ToolbarButton title=\"Chèn ảnh\" aria-label=\"Chèn ảnh\" data-slot=\"toolbar-image-button\">\n <ImageIcon className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent data-slot=\"image-dialog\" sideOffset={6} align=\"start\" className=\"w-72 p-3\">\n <p className=\"mb-2 font-medium text-text-positive-strong text-xs\">Chèn ảnh</p>\n\n {onImageUpload && (\n <>\n <input ref={fileInputRef} type=\"file\" accept=\"image/*\" className=\"hidden\" onChange={handleFileChange} />\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploading}\n className={cn(\n 'flex w-full items-center justify-center gap-1.5 rounded border border-border border-dashed py-2 text-text-positive-weak text-xs',\n 'transition-colors hover:border-primary hover:text-primary',\n 'disabled:pointer-events-none disabled:opacity-60'\n )}\n >\n {isUploading ? (\n <>\n <Spinner className=\"size-3.5\" /> Đang tải lên…\n </>\n ) : (\n <>\n <Upload className=\"h-3.5 w-3.5\" /> Tải ảnh từ máy\n </>\n )}\n </button>\n {error && <p className=\"mt-1.5 text-danger-strong text-xs\">{error}</p>}\n <div className=\"my-2 flex items-center gap-2\">\n <div className=\"h-px flex-1 bg-border\" />\n <span className=\"text-text-positive-muted text-xs\">hoặc</span>\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n </>\n )}\n\n <div className=\"flex gap-1.5\">\n <input\n type=\"url\"\n placeholder=\"https://example.com/image.png\"\n value={url}\n onChange={e => setUrl(e.target.value)}\n onKeyDown={handleKeyDown}\n aria-label=\"Đường dẫn ảnh\"\n disabled={isUploading}\n className={cn(\n 'flex-1 rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive',\n 'outline-none placeholder:text-text-positive-muted',\n 'focus:border-primary focus:ring-1 focus:ring-primary/30',\n 'disabled:pointer-events-none disabled:opacity-60'\n )}\n />\n <button\n type=\"button\"\n onClick={handleApplyUrl}\n disabled={!url.trim() || isUploading}\n className={cn(\n 'rounded bg-primary px-2.5 py-1.5 font-medium text-text-negative text-xs',\n 'transition-colors hover:bg-primary-strong',\n 'disabled:pointer-events-none disabled:opacity-50'\n )}\n >\n Chèn\n </button>\n </div>\n <input\n type=\"text\"\n placeholder=\"Mô tả ảnh (alt text) — tùy chọn\"\n value={alt}\n onChange={e => setAlt(e.target.value)}\n aria-label=\"Mô tả ảnh\"\n disabled={isUploading}\n className={cn(\n 'mt-1.5 w-full rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive',\n 'outline-none placeholder:text-text-positive-muted',\n 'focus:border-primary focus:ring-1 focus:ring-primary/30',\n 'disabled:pointer-events-none disabled:opacity-60'\n )}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\nexport { ImageDialog };\n","'use client';\n\nimport { useCallback, useState } from 'react';\n\nimport { Table as TableIcon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nimport type { Editor } from '@tiptap/react';\nimport { ToolbarButton } from './toolbar-primitives';\n\nexport interface TableInsertMenuProps {\n editor: Editor;\n}\n\nconst GRID_SIZE = 6;\n\nfunction TableInsertMenu({ editor }: TableInsertMenuProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [hovered, setHovered] = useState({ rows: 0, cols: 0 });\n\n const handleInsert = useCallback(\n (rows: number, cols: number) => {\n editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();\n setIsOpen(false);\n },\n [editor]\n );\n\n return (\n <Popover\n open={isOpen}\n onOpenChange={open => {\n setIsOpen(open);\n if (!open) setHovered({ rows: 0, cols: 0 });\n }}\n >\n <PopoverTrigger asChild>\n <ToolbarButton title=\"Chèn bảng\" aria-label=\"Chèn bảng\" data-slot=\"toolbar-table-button\">\n <TableIcon className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent data-slot=\"table-insert-menu\" sideOffset={6} align=\"start\" className=\"w-auto p-3\">\n <p className=\"mb-2 font-medium text-text-positive-strong text-xs\">\n {hovered.rows > 0 ? `Bảng ${hovered.rows} × ${hovered.cols}` : 'Chọn kích thước bảng'}\n </p>\n <div className=\"grid grid-cols-6 gap-1\" onMouseLeave={() => setHovered({ rows: 0, cols: 0 })}>\n {Array.from({ length: GRID_SIZE * GRID_SIZE }, (_, i) => {\n const row = Math.floor(i / GRID_SIZE) + 1;\n const col = (i % GRID_SIZE) + 1;\n const active = row <= hovered.rows && col <= hovered.cols;\n return (\n <button\n key={`${row}-${col}`}\n type=\"button\"\n aria-label={`Bảng ${row} hàng, ${col} cột`}\n onMouseEnter={() => setHovered({ rows: row, cols: col })}\n onClick={() => handleInsert(row, col)}\n className={cn('h-4 w-4 rounded-sm border border-border', active ? 'border-primary bg-primary-muted' : 'bg-muted-muted/40')}\n />\n );\n })}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nexport { TableInsertMenu };\n","'use client';\n\nimport {\n AlignCenter,\n AlignJustify,\n AlignLeft,\n AlignRight,\n Bold,\n ChevronDown,\n Code,\n Code2,\n Columns3,\n Highlighter,\n Italic,\n List,\n ListChecks,\n ListOrdered,\n Minus,\n Palette,\n Quote,\n Redo,\n Rows3,\n Strikethrough,\n TableCellsMerge,\n Trash2,\n Underline,\n Undo,\n} from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nimport { type Editor, useEditorState } from '@tiptap/react';\nimport { ImageDialog } from './image-dialog';\nimport { LinkDialog } from './link-dialog';\nimport { TableInsertMenu } from './table-insert-menu';\nimport { ToolbarButton, ToolbarDivider } from './toolbar-primitives';\n\nconst HIGHLIGHT_COLORS = [\n { label: 'Yellow', value: '#fde047' },\n { label: 'Green', value: '#86efac' },\n { label: 'Blue', value: '#93c5fd' },\n { label: 'Pink', value: '#f9a8d4' },\n { label: 'Orange', value: '#fdba74' },\n { label: 'Purple', value: '#c4b5fd' },\n { label: 'Red', value: '#fca5a5' },\n { label: 'Cyan', value: '#67e8f9' },\n { label: 'Lime', value: '#bef264' },\n { label: 'Gray', value: '#d1d5db' },\n];\n\nconst TEXT_COLORS = [\n { label: 'Default', value: '' },\n { label: 'Red', value: '#ef4444' },\n { label: 'Orange', value: '#f97316' },\n { label: 'Yellow', value: '#eab308' },\n { label: 'Green', value: '#22c55e' },\n { label: 'Blue', value: '#3b82f6' },\n { label: 'Purple', value: '#a855f7' },\n { label: 'Pink', value: '#ec4899' },\n { label: 'Gray', value: '#6b7280' },\n { label: 'Black', value: '#000000' },\n];\n\n/** Subset of lowlight's `common` grammar bundle relevant to a blog/docs editor. */\nconst CODE_LANGUAGES = [\n { label: 'Plain text', value: 'plaintext' },\n { label: 'JavaScript', value: 'javascript' },\n { label: 'TypeScript', value: 'typescript' },\n { label: 'Python', value: 'python' },\n { label: 'Java', value: 'java' },\n { label: 'C#', value: 'csharp' },\n { label: 'C++', value: 'cpp' },\n { label: 'Go', value: 'go' },\n { label: 'Rust', value: 'rust' },\n { label: 'PHP', value: 'php' },\n { label: 'Ruby', value: 'ruby' },\n { label: 'Swift', value: 'swift' },\n { label: 'Kotlin', value: 'kotlin' },\n { label: 'SQL', value: 'sql' },\n { label: 'Bash', value: 'bash' },\n { label: 'JSON', value: 'json' },\n { label: 'YAML', value: 'yaml' },\n { label: 'CSS', value: 'css' },\n { label: 'HTML/XML', value: 'xml' },\n { label: 'Markdown', value: 'markdown' },\n];\n\nexport interface TextEditorToolbarProps {\n editor: Editor;\n className?: string;\n enableLink?: boolean;\n enableTaskList?: boolean;\n enableHighlight?: boolean;\n enableColor?: boolean;\n enableImage?: boolean;\n enableTable?: boolean;\n onImageUpload?: (file: File) => Promise<string>;\n}\n\nfunction TextEditorToolbar({\n editor,\n className,\n enableLink,\n enableTaskList,\n enableHighlight,\n enableColor,\n enableImage,\n enableTable,\n onImageUpload,\n}: TextEditorToolbarProps) {\n // Grouped into a handful of object-returning selectors (instead of one hook per\n // boolean) to cut down `useEditorState` subscription overhead on every keystroke —\n // `useEditorState` deep-compares the returned value by default, so batching related\n // flags together is safe and doesn't cause extra re-renders.\n const heading = useEditorState({\n editor,\n selector: ctx => {\n if (ctx.editor.isActive('heading', { level: 1 })) return 1;\n if (ctx.editor.isActive('heading', { level: 2 })) return 2;\n if (ctx.editor.isActive('heading', { level: 3 })) return 3;\n return null;\n },\n });\n const marks = useEditorState({\n editor,\n selector: ctx => ({\n bold: ctx.editor.isActive('bold'),\n italic: ctx.editor.isActive('italic'),\n underline: ctx.editor.isActive('underline'),\n strike: ctx.editor.isActive('strike'),\n code: ctx.editor.isActive('code'),\n }),\n });\n const blocks = useEditorState({\n editor,\n selector: ctx => ({\n bulletList: ctx.editor.isActive('bulletList'),\n orderedList: ctx.editor.isActive('orderedList'),\n taskList: ctx.editor.isActive('taskList'),\n blockquote: ctx.editor.isActive('blockquote'),\n codeBlock: ctx.editor.isActive('codeBlock'),\n codeBlockLanguage: (ctx.editor.getAttributes('codeBlock').language as string | undefined) ?? 'plaintext',\n table: ctx.editor.isActive('table'),\n }),\n });\n const align = useEditorState({\n editor,\n selector: ctx => ({\n left: ctx.editor.isActive({ textAlign: 'left' }),\n center: ctx.editor.isActive({ textAlign: 'center' }),\n right: ctx.editor.isActive({ textAlign: 'right' }),\n justify: ctx.editor.isActive({ textAlign: 'justify' }),\n }),\n });\n\n const headingLabel = heading ? (`H${heading}` as const) : 'P';\n\n return (\n <div\n data-slot=\"text-editor-toolbar\"\n role=\"toolbar\"\n aria-label=\"Định dạng văn bản\"\n className={cn('sticky top-0 z-10 flex flex-wrap items-center gap-0.5 border-border border-b bg-muted-muted p-1.5', className)}\n >\n {/* History */}\n <ToolbarButton onClick={() => editor.chain().focus().undo().run()} disabled={!editor.can().undo()} aria-label=\"Hoàn tác\" title=\"Undo (Ctrl+Z)\">\n <Undo className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton onClick={() => editor.chain().focus().redo().run()} disabled={!editor.can().redo()} aria-label=\"Làm lại\" title=\"Redo (Ctrl+Y)\">\n <Redo className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n\n <ToolbarDivider />\n\n {/* Heading dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n data-slot=\"toolbar-heading-trigger\"\n aria-label=\"Kiểu đoạn văn\"\n aria-haspopup=\"menu\"\n className={cn(\n 'inline-flex h-8 items-center gap-1 rounded px-1.5 font-medium text-xs transition-colors',\n 'hover:bg-muted-muted hover:text-text-positive-strong',\n 'disabled:pointer-events-none disabled:opacity-40',\n heading !== null && 'bg-primary-muted text-primary hover:bg-primary-muted/80 hover:text-primary'\n )}\n >\n <span className=\"w-5 text-center\">{headingLabel}</span>\n <ChevronDown className=\"h-3 w-3 opacity-60\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"min-w-32\">\n <DropdownMenuItem className=\"px-2 py-1.5\" onClick={() => editor.chain().focus().setParagraph().run()}>\n <span className=\"text-sm\">Paragraph</span>\n </DropdownMenuItem>\n <DropdownMenuItem className=\"px-2 py-1.5\" onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}>\n <span className=\"font-extrabold text-sm\">Heading 1</span>\n </DropdownMenuItem>\n <DropdownMenuItem className=\"px-2 py-1.5\" onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}>\n <span className=\"font-semibold text-sm\">Heading 2</span>\n </DropdownMenuItem>\n <DropdownMenuItem className=\"px-2 py-1.5\" onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}>\n <span className=\"font-medium text-sm\">Heading 3</span>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <ToolbarDivider />\n\n {/* Text formatting */}\n <ToolbarButton onClick={() => editor.chain().focus().toggleBold().run()} isActive={marks.bold} aria-label=\"In đậm\" title=\"Bold (Ctrl+B)\">\n <Bold className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton onClick={() => editor.chain().focus().toggleItalic().run()} isActive={marks.italic} aria-label=\"In nghiêng\" title=\"Italic (Ctrl+I)\">\n <Italic className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleUnderline().run()}\n isActive={marks.underline}\n aria-label=\"Gạch chân\"\n title=\"Underline (Ctrl+U)\"\n >\n <Underline className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton onClick={() => editor.chain().focus().toggleStrike().run()} isActive={marks.strike} aria-label=\"Gạch ngang\" title=\"Strikethrough\">\n <Strikethrough className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton onClick={() => editor.chain().focus().toggleCode().run()} isActive={marks.code} aria-label=\"Mã inline\" title=\"Inline Code\">\n <Code className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n\n <ToolbarDivider />\n\n {/* Lists */}\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleBulletList().run()}\n isActive={blocks.bulletList}\n aria-label=\"Danh sách chấm\"\n title=\"Bullet List\"\n >\n <List className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleOrderedList().run()}\n isActive={blocks.orderedList}\n aria-label=\"Danh sách số\"\n title=\"Ordered List\"\n >\n <ListOrdered className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n {enableTaskList && (\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleTaskList().run()}\n isActive={blocks.taskList}\n aria-label=\"Danh sách công việc\"\n title=\"Task List\"\n >\n <ListChecks className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n )}\n\n <ToolbarDivider />\n\n {/* Blocks */}\n <ToolbarButton onClick={() => editor.chain().focus().toggleBlockquote().run()} isActive={blocks.blockquote} aria-label=\"Trích dẫn\" title=\"Blockquote\">\n <Quote className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton onClick={() => editor.chain().focus().toggleCodeBlock().run()} isActive={blocks.codeBlock} aria-label=\"Khối mã\" title=\"Code Block\">\n <Code2 className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n {blocks.codeBlock && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n data-slot=\"toolbar-code-language-trigger\"\n aria-label=\"Ngôn ngữ lập trình\"\n aria-haspopup=\"menu\"\n className={cn(\n 'inline-flex h-7 items-center gap-1 rounded px-1.5 text-text-positive-weak text-xs transition-colors',\n 'hover:bg-muted-muted hover:text-text-positive-strong'\n )}\n >\n <span>{CODE_LANGUAGES.find(l => l.value === blocks.codeBlockLanguage)?.label ?? 'Plain text'}</span>\n <ChevronDown className=\"h-3 w-3 opacity-60\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"max-h-72 min-w-40 overflow-y-auto\">\n {CODE_LANGUAGES.map(lang => (\n <DropdownMenuItem key={lang.value} onClick={() => editor.chain().focus().updateAttributes('codeBlock', { language: lang.value }).run()}>\n <span className=\"text-sm\">{lang.label}</span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n <ToolbarButton onClick={() => editor.chain().focus().setHorizontalRule().run()} aria-label=\"Đường kẻ ngang\" title=\"Horizontal Rule\">\n <Minus className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n\n <ToolbarDivider />\n\n {/* Text alignment */}\n <ToolbarButton onClick={() => editor.chain().focus().setTextAlign('left').run()} isActive={align.left} aria-label=\"Căn trái\" title=\"Align Left\">\n <AlignLeft className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton onClick={() => editor.chain().focus().setTextAlign('center').run()} isActive={align.center} aria-label=\"Căn giữa\" title=\"Align Center\">\n <AlignCenter className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton onClick={() => editor.chain().focus().setTextAlign('right').run()} isActive={align.right} aria-label=\"Căn phải\" title=\"Align Right\">\n <AlignRight className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton onClick={() => editor.chain().focus().setTextAlign('justify').run()} isActive={align.justify} aria-label=\"Căn đều\" title=\"Align Justify\">\n <AlignJustify className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n\n {/* Link */}\n {enableLink && (\n <>\n <ToolbarDivider />\n <LinkDialog editor={editor} />\n </>\n )}\n\n {/* Image */}\n {enableImage && (\n <>\n <ToolbarDivider />\n <ImageDialog editor={editor} onImageUpload={onImageUpload} />\n </>\n )}\n\n {/* Table */}\n {enableTable && (\n <>\n <ToolbarDivider />\n <TableInsertMenu editor={editor} />\n {blocks.table && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <ToolbarButton title=\"Sửa bảng\" aria-label=\"Sửa bảng\">\n <TableCellsMerge className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"min-w-44\">\n <DropdownMenuItem onClick={() => editor.chain().focus().addRowBefore().run()}>\n <Rows3 className=\"mr-2 h-3.5 w-3.5\" /> Thêm hàng phía trên\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => editor.chain().focus().addRowAfter().run()}>\n <Rows3 className=\"mr-2 h-3.5 w-3.5\" /> Thêm hàng phía dưới\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => editor.chain().focus().deleteRow().run()}>\n <Trash2 className=\"mr-2 h-3.5 w-3.5\" /> Xóa hàng\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem onClick={() => editor.chain().focus().addColumnBefore().run()}>\n <Columns3 className=\"mr-2 h-3.5 w-3.5\" /> Thêm cột bên trái\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => editor.chain().focus().addColumnAfter().run()}>\n <Columns3 className=\"mr-2 h-3.5 w-3.5\" /> Thêm cột bên phải\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => editor.chain().focus().deleteColumn().run()}>\n <Trash2 className=\"mr-2 h-3.5 w-3.5\" /> Xóa cột\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem onClick={() => editor.chain().focus().deleteTable().run()} className=\"text-danger-strong\">\n <Trash2 className=\"mr-2 h-3.5 w-3.5\" /> Xóa bảng\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </>\n )}\n\n {/* Color & Highlight */}\n {(enableColor || enableHighlight) && (\n <>\n <ToolbarDivider />\n {enableColor && (\n <Popover>\n <PopoverTrigger asChild>\n <ToolbarButton title=\"Text Color\" aria-label=\"Màu chữ\">\n <Palette className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-44 p-2\">\n <p className=\"mb-1.5 font-medium text-text-positive-weak text-xs\">Text Color</p>\n <div className=\"grid grid-cols-5 gap-1\">\n {TEXT_COLORS.map(color => (\n <button\n key={color.label}\n type=\"button\"\n title={color.label}\n onClick={() => {\n if (!color.value) {\n editor.chain().focus().unsetColor().run();\n } else {\n editor.chain().focus().setColor(color.value).run();\n }\n }}\n className={cn(\n 'h-6 w-6 rounded border border-border transition-transform hover:scale-110',\n !color.value && 'bg-background text-[10px] text-text-positive leading-none'\n )}\n style={color.value ? { backgroundColor: color.value } : undefined}\n >\n {!color.value && '∅'}\n </button>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n )}\n {enableHighlight && (\n <Popover>\n <PopoverTrigger asChild>\n <ToolbarButton title=\"Highlight\" aria-label=\"Tô sáng\">\n <Highlighter className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-44 p-2\">\n <p className=\"mb-1.5 font-medium text-text-positive-weak text-xs\">Highlight</p>\n <div className=\"grid grid-cols-5 gap-1\">\n {HIGHLIGHT_COLORS.map(color => (\n <button\n key={color.label}\n type=\"button\"\n title={color.label}\n onClick={() => editor.chain().focus().toggleHighlight({ color: color.value }).run()}\n className=\"h-6 w-6 rounded border border-border transition-transform hover:scale-110\"\n style={{ backgroundColor: color.value }}\n />\n ))}\n </div>\n <button\n type=\"button\"\n onClick={() => editor.chain().focus().unsetHighlight().run()}\n className=\"mt-1.5 w-full rounded border border-border py-0.5 text-center text-text-positive-weak text-xs hover:bg-muted-muted\"\n >\n Clear highlight\n </button>\n </PopoverContent>\n </Popover>\n )}\n </>\n )}\n </div>\n );\n}\n\nexport { TextEditorToolbar };\n","'use client';\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\n\nimport { Bold, Italic, Strikethrough, Underline as UnderlineIcon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { CharacterCount } from '@tiptap/extension-character-count';\nimport CodeBlockLowlight from '@tiptap/extension-code-block-lowlight';\nimport { Highlight } from '@tiptap/extension-highlight';\nimport Image from '@tiptap/extension-image';\nimport { Link } from '@tiptap/extension-link';\nimport { ListKeymap } from '@tiptap/extension-list-keymap';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport { Table, TableCell, TableHeader, TableRow } from '@tiptap/extension-table';\nimport { TaskItem } from '@tiptap/extension-task-item';\nimport { TaskList } from '@tiptap/extension-task-list';\nimport TextAlign from '@tiptap/extension-text-align';\nimport { Color, TextStyle } from '@tiptap/extension-text-style';\nimport Underline from '@tiptap/extension-underline';\nimport { type AnyExtension, EditorContent, ReactNodeViewRenderer, useEditor, useEditorState } from '@tiptap/react';\nimport { BubbleMenu } from '@tiptap/react/menus';\nimport StarterKit from '@tiptap/starter-kit';\nimport DOMPurify, { type Config as SanitizeConfig } from 'dompurify';\nimport { common, createLowlight } from 'lowlight';\nimport { ImageNodeView } from './image-node-view';\nimport { LinkDialog } from './link-dialog';\nimport { createSlashCommandExtension } from './slash-command';\nimport { type TextEditorVariantProps, textEditorVariants } from './text-editor.variants';\nimport { TextEditorToolbar } from './toolbar';\nimport { ToolbarButton, ToolbarDivider } from './toolbar-primitives';\n\n// Built once at module scope — constructing the grammar registry per render would be wasteful.\nconst lowlight = createLowlight(common);\n\n// Adds a centered wrapper + small \"source\" caption link below every image — purely a\n// live-rendering affordance (both editing and `readOnly`), not persisted: the caption is\n// derived from `src` on the fly, so `getHTML()` output is unaffected (still a plain `<img>`).\nconst ImageWithCaption = Image.extend({\n addNodeView() {\n return ReactNodeViewRenderer(ImageNodeView);\n },\n});\n\n// Node types every configuration can produce, regardless of feature flags.\nconst BASE_ALLOWED_TAGS = ['p', 'h1', 'h2', 'h3', 'strong', 'em', 's', 'u', 'code', 'pre', 'blockquote', 'ul', 'ol', 'li', 'hr', 'br'];\nconst BASE_ALLOWED_ATTR = ['class', 'style'];\n\ninterface SanitizeFlags {\n enableLink?: boolean;\n enableHighlight?: boolean;\n enableColor?: boolean;\n enableTaskList?: boolean;\n enableImage?: boolean;\n enableTable?: boolean;\n}\n\n/**\n * Builds a DOMPurify allowlist scoped to exactly the node/mark types the currently\n * enabled extensions can produce — not a generic \"allow all HTML\" config.\n */\nfunction buildSanitizeConfig(flags: SanitizeFlags): SanitizeConfig {\n const tags = new Set(BASE_ALLOWED_TAGS);\n const attr = new Set(BASE_ALLOWED_ATTR);\n\n if (flags.enableLink) {\n tags.add('a');\n attr.add('href').add('target').add('rel');\n }\n if (flags.enableHighlight) {\n tags.add('mark');\n attr.add('data-color');\n }\n if (flags.enableColor) {\n tags.add('span');\n }\n if (flags.enableTaskList) {\n for (const t of ['label', 'input', 'div', 'span']) tags.add(t);\n for (const a of ['data-type', 'data-checked', 'type', 'checked', 'disabled']) attr.add(a);\n }\n if (flags.enableImage) {\n tags.add('img');\n for (const a of ['src', 'alt', 'title']) attr.add(a);\n }\n if (flags.enableTable) {\n for (const t of ['table', 'tbody', 'thead', 'tr', 'td', 'th', 'colgroup', 'col']) tags.add(t);\n for (const a of ['colspan', 'rowspan', 'colwidth']) attr.add(a);\n }\n\n return { ALLOWED_TAGS: Array.from(tags), ALLOWED_ATTR: Array.from(attr) };\n}\n\n/** No-op on the server — DOMPurify needs a DOM, and SSR content gets sanitized again on hydration anyway. */\nfunction sanitizeHtml(html: string, config: SanitizeConfig): string {\n if (typeof window === 'undefined') return html;\n return DOMPurify.sanitize(html, config);\n}\n\n/** Best-effort alt text for drag/drop/paste image inserts, which have no dialog to ask for one. */\nfunction imageAltFromFile(file: File): string {\n return file.name.replace(/\\.[^./]+$/, '');\n}\n\nexport interface TextEditorProps extends TextEditorVariantProps {\n value?: string;\n defaultValue?: string;\n onChange?: (html: string) => void;\n placeholder?: string;\n readOnly?: boolean;\n showToolbar?: boolean;\n className?: string;\n toolbarClassName?: string;\n editorClassName?: string;\n // Character count\n maxLength?: number;\n showCharacterCount?: boolean;\n onCharacterCount?: (stats: { characters: number; words: number }) => void;\n // Feature flags\n enableLink?: boolean;\n enableBubbleMenu?: boolean;\n enableTaskList?: boolean;\n enableHighlight?: boolean;\n enableColor?: boolean;\n enableImage?: boolean;\n enableTable?: boolean;\n /** Enables the `/` slash-command menu for quickly inserting blocks (headings, lists, table, image, etc.). */\n enableSlashCommand?: boolean;\n /** Called when the user picks/drops/pastes an image file. Return the URL to embed. Without it, only pasting an image URL as text works. */\n onImageUpload?: (file: File) => Promise<string>;\n}\n\nfunction TextEditor({\n value,\n defaultValue,\n onChange,\n placeholder = 'Start writing...',\n readOnly = false,\n showToolbar = true,\n variant,\n size,\n className,\n toolbarClassName,\n editorClassName,\n maxLength,\n showCharacterCount,\n onCharacterCount,\n enableLink,\n enableBubbleMenu,\n enableTaskList,\n enableHighlight,\n enableColor,\n enableImage,\n enableTable,\n enableSlashCommand,\n onImageUpload,\n}: TextEditorProps) {\n const needsCharCount = maxLength !== undefined || showCharacterCount || onCharacterCount !== undefined;\n const needsTextStyle = enableColor || enableHighlight;\n\n const sanitizeConfig = useMemo(\n () => buildSanitizeConfig({ enableLink, enableHighlight, enableColor, enableTaskList, enableImage, enableTable }),\n [enableLink, enableHighlight, enableColor, enableTaskList, enableImage, enableTable]\n );\n\n const extensions = useMemo(() => {\n const base: AnyExtension[] = [\n // `link`/`underline`/`codeBlock`/`listKeymap` are disabled here because we register\n // our own configured instances below — leaving StarterKit's defaults on causes\n // duplicate extension name warnings and the later-registered config silently wins.\n StarterKit.configure({ link: false, underline: false, codeBlock: false, listKeymap: false }),\n Underline,\n Placeholder.configure({ placeholder }),\n TextAlign.configure({ types: ['heading', 'paragraph'] }),\n ListKeymap,\n CodeBlockLowlight.configure({ lowlight, defaultLanguage: 'plaintext' }),\n ];\n\n if (needsTextStyle) base.push(TextStyle);\n if (enableLink) {\n base.push(Link.configure({ openOnClick: false, linkOnPaste: true, defaultProtocol: 'https' }));\n }\n if (enableTaskList) {\n base.push(TaskList, TaskItem.configure({ nested: true }));\n }\n if (enableHighlight) {\n base.push(Highlight.configure({ multicolor: true }));\n }\n if (enableColor) {\n base.push(Color);\n }\n if (enableImage) {\n // `allowBase64: false` is deliberate — base64 images would bloat the stored HTML\n // (the API column has no size cap) instead of going through `onImageUpload`.\n base.push(ImageWithCaption.configure({ inline: false, allowBase64: false }));\n }\n if (enableTable) {\n base.push(Table.configure({ resizable: true }), TableRow, TableHeader, TableCell);\n }\n if (enableSlashCommand) {\n base.push(createSlashCommandExtension({ enableTaskList, enableTable, enableImage, onImageUpload }));\n }\n if (needsCharCount) {\n base.push(CharacterCount.configure({ limit: maxLength }));\n }\n\n return base;\n }, [\n needsCharCount,\n placeholder,\n maxLength,\n enableHighlight,\n needsTextStyle,\n enableTaskList,\n enableLink,\n enableColor,\n enableImage,\n enableTable,\n enableSlashCommand,\n onImageUpload,\n ]);\n\n // Computed once at mount via lazy initializer — `content` is only read the first time\n // `useEditor` builds the editor, so there's no dependency array to keep in sync.\n const [initialContent] = useState(() => {\n const html = value ?? defaultValue;\n return html ? sanitizeHtml(html, sanitizeConfig) : html;\n });\n\n // Debounce the outward-facing `onChange` — typing itself is always instant (ProseMirror\n // manages its own state independent of React), but serializing the whole doc to HTML,\n // sanitizing it, and pushing it into (often form) state on every keystroke is what causes\n // visible lag when typing fast, especially once the doc has tables/images/code blocks.\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const emitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Flushes any pending debounced emit immediately — called on blur and on unmount so a\n // \"type the last word then instantly submit/close\" sequence never drops the final edit\n // (the debounce alone would silently discard it if it fires within the 200ms window).\n const flushPendingChange = (html: string) => {\n if (!emitTimerRef.current) return;\n clearTimeout(emitTimerRef.current);\n emitTimerRef.current = null;\n onChangeRef.current?.(sanitizeHtml(html, sanitizeConfig));\n };\n const flushRef = useRef(flushPendingChange);\n flushRef.current = flushPendingChange;\n\n const editor = useEditor({\n extensions,\n content: initialContent,\n editable: !readOnly,\n // v3 default — kept explicit so a future `useEditor` option addition doesn't\n // accidentally reintroduce a re-render on every transaction/keystroke.\n shouldRerenderOnTransaction: false,\n editorProps: {\n handleDrop: (_view, event) => {\n if (!enableImage || !onImageUpload) return false;\n const file = event.dataTransfer?.files?.[0];\n if (!file?.type.startsWith('image/')) return false;\n event.preventDefault();\n onImageUpload(file).then(src =>\n editor\n ?.chain()\n .focus()\n .setImage({ src, alt: imageAltFromFile(file) })\n .run()\n );\n return true;\n },\n handlePaste: (_view, event) => {\n if (!enableImage || !onImageUpload) return false;\n const file = Array.from(event.clipboardData?.items ?? [])\n .find(item => item.type.startsWith('image/'))\n ?.getAsFile();\n if (!file) return false;\n event.preventDefault();\n onImageUpload(file).then(src =>\n editor\n ?.chain()\n .focus()\n .setImage({ src, alt: imageAltFromFile(file) })\n .run()\n );\n return true;\n },\n },\n onUpdate: ({ editor: e }) => {\n if (onCharacterCount) {\n const storage = e.storage.characterCount;\n onCharacterCount({ characters: storage.characters(), words: storage.words() });\n }\n if (!onChangeRef.current) return;\n if (emitTimerRef.current) clearTimeout(emitTimerRef.current);\n emitTimerRef.current = setTimeout(() => flushPendingChange(e.getHTML()), 200);\n },\n onBlur: ({ editor: e }) => flushPendingChange(e.getHTML()),\n });\n\n // Unmount-only flush. Reads `flushRef`/`editor` via refs (not the effect's own closure)\n // so it always uses the latest editor instance and sanitize config, not whatever they\n // were on first render.\n const editorRef = useRef(editor);\n editorRef.current = editor;\n useEffect(\n () => () => {\n if (editorRef.current) flushRef.current(editorRef.current.getHTML());\n },\n []\n );\n\n useEffect(() => {\n if (!editor || value === undefined) return;\n const sanitized = sanitizeHtml(value, sanitizeConfig);\n if (editor.getHTML() === sanitized) return;\n editor.commands.setContent(sanitized);\n }, [editor, value, sanitizeConfig]);\n\n useEffect(() => {\n if (!editor) return;\n editor.setEditable(!readOnly);\n }, [editor, readOnly]);\n\n const charCount = useEditorState({\n editor,\n selector: ctx => {\n const storage = ctx.editor?.storage?.characterCount;\n return storage ? (storage.characters() as number) : 0;\n },\n });\n\n const wordCount = useEditorState({\n editor,\n selector: ctx => {\n const storage = ctx.editor?.storage?.characterCount;\n return storage ? (storage.words() as number) : 0;\n },\n });\n\n const showCharCount = showCharacterCount || maxLength !== undefined;\n const isNearLimit = maxLength !== undefined && charCount > maxLength * 0.9;\n\n // Grouped for the same reason as `toolbar.tsx`'s selectors: a single deep-compared\n // object subscription instead of reading `editor.isActive()` straight in JSX, which\n // would silently go stale now that `TextEditor` itself doesn't re-render per transaction.\n const bubbleMarks = useEditorState({\n editor,\n selector: ctx =>\n ctx.editor\n ? {\n bold: ctx.editor.isActive('bold'),\n italic: ctx.editor.isActive('italic'),\n underline: ctx.editor.isActive('underline'),\n strike: ctx.editor.isActive('strike'),\n }\n : { bold: false, italic: false, underline: false, strike: false },\n });\n\n return (\n <div data-slot=\"text-editor\" className={cn('lunas-text-editor', textEditorVariants({ variant, size }), className)}>\n {showToolbar && !readOnly && editor && (\n <TextEditorToolbar\n editor={editor}\n className={toolbarClassName}\n enableLink={enableLink}\n enableTaskList={enableTaskList}\n enableHighlight={enableHighlight}\n enableColor={enableColor}\n enableImage={enableImage}\n enableTable={enableTable}\n onImageUpload={onImageUpload}\n />\n )}\n\n {enableBubbleMenu && !readOnly && editor && (\n <BubbleMenu\n editor={editor}\n options={{ placement: 'top' }}\n className={cn('z-50 flex items-center gap-0.5 rounded-md border border-border bg-popover p-1 shadow-dropdown')}\n >\n <ToolbarButton onClick={() => editor.chain().focus().toggleBold().run()} isActive={bubbleMarks.bold} aria-label=\"In đậm\" title=\"Bold (Ctrl+B)\">\n <Bold className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleItalic().run()}\n isActive={bubbleMarks.italic}\n aria-label=\"In nghiêng\"\n title=\"Italic (Ctrl+I)\"\n >\n <Italic className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleUnderline().run()}\n isActive={bubbleMarks.underline}\n aria-label=\"Gạch chân\"\n title=\"Underline (Ctrl+U)\"\n >\n <UnderlineIcon className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n <ToolbarButton\n onClick={() => editor.chain().focus().toggleStrike().run()}\n isActive={bubbleMarks.strike}\n aria-label=\"Gạch ngang\"\n title=\"Strikethrough\"\n >\n <Strikethrough className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n {enableLink && (\n <>\n <ToolbarDivider />\n <LinkDialog editor={editor} />\n </>\n )}\n </BubbleMenu>\n )}\n\n {/* No hardcoded font-size here — it inherits from `textEditorVariants`'s `size` class\n on the root (sm/md/lg), which is what lets the whole typography scale in\n `text-editor.css` (headings, paragraphs, lists use `em`) actually respond to `size`. */}\n <EditorContent editor={editor} data-slot=\"text-editor-content\" className={cn('flex-1 bg-white text-text-positive', editorClassName)} />\n\n {showCharCount && needsCharCount && (\n <div\n data-slot=\"text-editor-footer\"\n className=\"flex items-center justify-between border-border border-t bg-muted-muted/30 px-3 py-1 text-text-positive-weak text-xs\"\n >\n <span>{wordCount} words</span>\n <span data-warning={isNearLimit || undefined} className=\"data-warning:text-warning-strong\">\n {charCount}\n {maxLength ? ` / ${maxLength}` : ''} characters\n </span>\n </div>\n )}\n </div>\n );\n}\n\nexport { TextEditor };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{DropdownMenu as e,DropdownMenuContent as t,DropdownMenuItem as n,DropdownMenuSeparator as r,DropdownMenuTrigger as i}from"./ui/dropdown-menu.mjs";import{Spinner as a}from"./ui/spinner.mjs";import{Popover as o,PopoverContent as s,PopoverTrigger as c}from"./ui/popover.mjs";import{AlignCenter as l,AlignJustify as u,AlignLeft as d,AlignRight as f,Bold as p,ChevronDown as m,Code as h,Code2 as g,Columns3 as _,Heading1 as v,Heading2 as y,Heading3 as b,Highlighter as x,Image as S,ImageIcon as C,Italic as ee,Link2 as w,Link2Off as T,List as E,ListChecks as D,ListOrdered as O,Minus as k,Palette as A,Quote as j,Redo as M,Rows3 as N,Strikethrough as te,Table as P,TableCellsMerge as F,Trash2 as I,Underline as L,Undo as R,Upload as z}from"lucide-react";import{forwardRef as B,useCallback as V,useEffect as H,useImperativeHandle as ne,useMemo as re,useRef as U,useState as W}from"react";import{cn as G}from"@customafk/react-toolkit/utils";import{cva as ie}from"class-variance-authority";import{Fragment as K,jsx as q,jsxs as J}from"react/jsx-runtime";import{EditorContent as ae,Extension as oe,NodeViewWrapper as se,ReactNodeViewRenderer as ce,ReactRenderer as le,useEditor as ue,useEditorState as Y}from"@tiptap/react";import{CharacterCount as de}from"@tiptap/extension-character-count";import fe from"@tiptap/extension-code-block-lowlight";import{Highlight as pe}from"@tiptap/extension-highlight";import me from"@tiptap/extension-image";import{Link as he}from"@tiptap/extension-link";import{ListKeymap as ge}from"@tiptap/extension-list-keymap";import _e from"@tiptap/extension-placeholder";import{Table as ve,TableCell as ye,TableHeader as be,TableRow as xe}from"@tiptap/extension-table";import{TaskItem as Se}from"@tiptap/extension-task-item";import{TaskList as Ce}from"@tiptap/extension-task-list";import we from"@tiptap/extension-text-align";import{Color as Te,TextStyle as Ee}from"@tiptap/extension-text-style";import De from"@tiptap/extension-underline";import{BubbleMenu as Oe}from"@tiptap/react/menus";import ke from"@tiptap/starter-kit";import Ae from"dompurify";import{common as je,createLowlight as Me}from"lowlight";import{Suggestion as Ne}from"@tiptap/suggestion";function X({isActive:e,className:t,children:n,...r}){return q(`button`,{type:`button`,"data-slot":`toolbar-button`,"data-active":e||void 0,"aria-pressed":e===void 0?void 0:e,className:G(`inline-flex size-8 shrink-0 items-center justify-center rounded text-sm outline-none transition-colors min-w-8`,`hover:bg-muted-weak hover:text-text-positive-strong`,`focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1`,`disabled:pointer-events-none disabled:opacity-40`,e&&`bg-primary-muted text-primary hover:bg-primary-muted/80 hover:text-primary`,t),...r,children:n})}function Z(){return q(`div`,{"data-slot":`toolbar-divider`,role:`separator`,"aria-orientation":`vertical`,className:`mx-0.5 h-5 w-px shrink-0 bg-border`})}function Q({editor:e}){let[t,n]=W(!1),[r,i]=W(``),a=Y({editor:e,selector:e=>e.editor.isActive(`link`)}),l=V(t=>{if(t){let t=e.getAttributes(`link`).href??``;i(t)}n(t)},[e]),u=V(()=>{let t=r.trim();t&&(e.chain().focus().setLink({href:t,target:`_blank`}).run(),n(!1))},[e,r]),d=V(()=>{e.chain().focus().unsetLink().run(),n(!1)},[e]);return J(o,{open:t,onOpenChange:l,children:[q(c,{asChild:!0,children:q(X,{isActive:a,"aria-label":`Liên kết`,title:`Link (Ctrl+K)`,"data-slot":`toolbar-link-button`,children:q(w,{className:`h-3.5 w-3.5`})})}),J(s,{"data-slot":`link-dialog`,sideOffset:6,align:`start`,className:`w-72 p-3`,children:[q(`p`,{className:`mb-2 font-medium text-text-positive-strong text-xs`,children:a?`Edit Link`:`Insert Link`}),J(`div`,{className:`flex gap-1.5`,children:[q(`input`,{type:`url`,placeholder:`https://example.com`,value:r,onChange:e=>i(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),u()),e.key===`Escape`&&n(!1)},"aria-label":`Đường dẫn liên kết`,autoFocus:!0,className:G(`flex-1 rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive`,`outline-none placeholder:text-text-positive-muted`,`focus:border-primary focus:ring-1 focus:ring-primary/30`)}),q(`button`,{type:`button`,onClick:u,disabled:!r.trim(),className:G(`rounded bg-primary px-2.5 py-1.5 font-medium text-text-negative text-xs`,`transition-colors hover:bg-primary-strong`,`disabled:pointer-events-none disabled:opacity-50`),children:`Apply`})]}),a&&J(`button`,{type:`button`,onClick:d,className:`mt-2 flex items-center gap-1 text-danger-strong text-xs hover:underline`,children:[q(T,{className:`h-3 w-3`}),`Remove link`]})]})]})}function Pe(e){try{return new URL(e).hostname}catch{return e}}function Fe({node:e,selected:t}){let n=e.attrs.src,r=e.attrs.alt;return J(se,{"data-slot":`text-editor-image`,className:`my-5 flex flex-col items-center`,children:[q(`img`,{src:n,alt:r??``,className:G(`max-w-full rounded-lg border border-border`,t&&`outline-2 outline-primary outline-offset-2`)}),q(`a`,{href:n,target:`_blank`,rel:`noopener noreferrer`,contentEditable:!1,className:`mt-1.5 text-text-positive-weak text-xs hover:text-text-positive hover:underline`,children:Pe(n)})]})}const Ie=B(({items:e,command:t},n)=>{let[r,i]=W(0);return H(()=>{i(0)},[]),ne(n,()=>({onKeyDown:({event:n})=>{if(e.length===0)return!1;if(n.key===`ArrowDown`)return i(t=>(t+1)%e.length),!0;if(n.key===`ArrowUp`)return i(t=>(t-1+e.length)%e.length),!0;if(n.key===`Enter`){let n=e[r];return n&&t(n),!0}return!1}})),e.length===0?q(`div`,{"data-slot":`slash-command-menu`,className:`w-56 rounded-md border border-border bg-popover p-2 text-text-positive-weak text-xs shadow-dropdown`,children:`Không tìm thấy lệnh phù hợp`}):q(`div`,{"data-slot":`slash-command-menu`,role:`listbox`,"aria-label":`Lệnh chèn nhanh`,className:`max-h-72 w-56 overflow-y-auto rounded-md border border-border bg-popover p-1 shadow-dropdown`,children:e.map((e,n)=>{let a=e.icon;return J(`button`,{type:`button`,role:`option`,"aria-selected":n===r,onClick:()=>t(e),onMouseEnter:()=>i(n),className:G(`flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-sm transition-colors`,n===r?`bg-primary-muted text-primary`:`text-text-positive hover:bg-muted-muted`),children:[q(a,{className:`h-3.5 w-3.5 shrink-0`}),q(`span`,{children:e.label})]},e.label)})})});Ie.displayName=`SlashCommandMenu`;function Le(e){let t=[{label:`Heading 1`,icon:v,command:(e,t)=>e.chain().focus().deleteRange(t).toggleHeading({level:1}).run()},{label:`Heading 2`,icon:y,command:(e,t)=>e.chain().focus().deleteRange(t).toggleHeading({level:2}).run()},{label:`Heading 3`,icon:b,command:(e,t)=>e.chain().focus().deleteRange(t).toggleHeading({level:3}).run()},{label:`Bullet list`,icon:E,command:(e,t)=>e.chain().focus().deleteRange(t).toggleBulletList().run()},{label:`Ordered list`,icon:O,command:(e,t)=>e.chain().focus().deleteRange(t).toggleOrderedList().run()}];if(e.enableTaskList&&t.push({label:`Task list`,icon:D,command:(e,t)=>e.chain().focus().deleteRange(t).toggleTaskList().run()}),t.push({label:`Blockquote`,icon:j,command:(e,t)=>e.chain().focus().deleteRange(t).toggleBlockquote().run()},{label:`Code block`,icon:g,command:(e,t)=>e.chain().focus().deleteRange(t).toggleCodeBlock().run()},{label:`Horizontal rule`,icon:k,command:(e,t)=>e.chain().focus().deleteRange(t).setHorizontalRule().run()}),e.enableTable&&t.push({label:`Table`,icon:P,command:(e,t)=>e.chain().focus().deleteRange(t).insertTable({rows:3,cols:3,withHeaderRow:!0}).run()}),e.enableImage&&e.onImageUpload){let n=e.onImageUpload;t.push({label:`Image`,icon:S,command:(e,t)=>{e.chain().focus().deleteRange(t).run();let r=document.createElement(`input`);r.type=`file`,r.accept=`image/*`,r.onchange=()=>{let t=r.files?.[0];if(!t)return;let i=t.name.replace(/\.[^./]+$/,``);n(t).then(t=>e.chain().focus().setImage({src:t,alt:i}).run())},r.click()}})}return t}function Re(e){return oe.create({name:`slashCommand`,addProseMirrorPlugins(){let t=this.editor;return[Ne({editor:t,char:`/`,startOfLine:!1,command:({editor:e,range:t,props:n})=>n.command(e,t),items:({query:t})=>Le(e).filter(e=>e.label.toLowerCase().includes(t.toLowerCase())),render:()=>{let e,t;return{onStart:n=>{e=new le(Ie,{editor:n.editor,props:{items:n.items,command:e=>n.command(e)}}),t=n.mount(e.element)},onUpdate:t=>{e?.updateProps({items:t.items,command:e=>t.command(e)})},onKeyDown:n=>n.event.key===`Escape`?(t?.(),!0):e?.ref?.onKeyDown(n)??!1,onExit:()=>{t?.(),e?.destroy()}}}})]}})}const ze=ie([`flex flex-col overflow-hidden rounded-md`],{variants:{variant:{outline:`border border-border bg-background shadow-xs`,ghost:`border-0`},size:{sm:`text-xs [&_.ProseMirror]:min-h-24 [&_.ProseMirror]:px-2.5 [&_.ProseMirror]:py-1.5`,md:`text-sm`,lg:`text-base [&_.ProseMirror]:min-h-56 [&_.ProseMirror]:px-4 [&_.ProseMirror]:py-3`}},defaultVariants:{variant:`outline`,size:`md`}});function Be({editor:e,onImageUpload:t}){let[n,r]=W(!1),[i,l]=W(``),[u,d]=W(``),[f,p]=W(!1),[m,h]=W(null),g=U(null),_=V(e=>{e&&(l(``),d(``),h(null)),r(e)},[]),v=V((t,n)=>{e.chain().focus().setImage({src:t,alt:n||void 0}).run(),r(!1)},[e]),y=V(()=>{let e=i.trim();e&&v(e,u.trim())},[i,u,v]),b=V(async e=>{let n=e.target.files?.[0];if(e.target.value=``,!(!n||!t)){h(null),p(!0);try{let e=await t(n);v(e,u.trim()||n.name.replace(/\.[^./]+$/,``))}catch{h(`Tải ảnh lên thất bại. Vui lòng thử lại.`)}finally{p(!1)}}},[t,u,v]);return J(o,{open:n,onOpenChange:_,children:[q(c,{asChild:!0,children:q(X,{title:`Chèn ảnh`,"aria-label":`Chèn ảnh`,"data-slot":`toolbar-image-button`,children:q(C,{className:`h-3.5 w-3.5`})})}),J(s,{"data-slot":`image-dialog`,sideOffset:6,align:`start`,className:`w-72 p-3`,children:[q(`p`,{className:`mb-2 font-medium text-text-positive-strong text-xs`,children:`Chèn ảnh`}),t&&J(K,{children:[q(`input`,{ref:g,type:`file`,accept:`image/*`,className:`hidden`,onChange:b}),q(`button`,{type:`button`,onClick:()=>g.current?.click(),disabled:f,className:G(`flex w-full items-center justify-center gap-1.5 rounded border border-border border-dashed py-2 text-text-positive-weak text-xs`,`transition-colors hover:border-primary hover:text-primary`,`disabled:pointer-events-none disabled:opacity-60`),children:f?J(K,{children:[q(a,{className:`size-3.5`}),` Đang tải lên…`]}):J(K,{children:[q(z,{className:`h-3.5 w-3.5`}),` Tải ảnh từ máy`]})}),m&&q(`p`,{className:`mt-1.5 text-danger-strong text-xs`,children:m}),J(`div`,{className:`my-2 flex items-center gap-2`,children:[q(`div`,{className:`h-px flex-1 bg-border`}),q(`span`,{className:`text-text-positive-muted text-xs`,children:`hoặc`}),q(`div`,{className:`h-px flex-1 bg-border`})]})]}),J(`div`,{className:`flex gap-1.5`,children:[q(`input`,{type:`url`,placeholder:`https://example.com/image.png`,value:i,onChange:e=>l(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),y()),e.key===`Escape`&&r(!1)},"aria-label":`Đường dẫn ảnh`,disabled:f,className:G(`flex-1 rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive`,`outline-none placeholder:text-text-positive-muted`,`focus:border-primary focus:ring-1 focus:ring-primary/30`,`disabled:pointer-events-none disabled:opacity-60`)}),q(`button`,{type:`button`,onClick:y,disabled:!i.trim()||f,className:G(`rounded bg-primary px-2.5 py-1.5 font-medium text-text-negative text-xs`,`transition-colors hover:bg-primary-strong`,`disabled:pointer-events-none disabled:opacity-50`),children:`Chèn`})]}),q(`input`,{type:`text`,placeholder:`Mô tả ảnh (alt text) — tùy chọn`,value:u,onChange:e=>d(e.target.value),"aria-label":`Mô tả ảnh`,disabled:f,className:G(`mt-1.5 w-full rounded border border-border bg-transparent px-2.5 py-1.5 text-sm text-text-positive`,`outline-none placeholder:text-text-positive-muted`,`focus:border-primary focus:ring-1 focus:ring-primary/30`,`disabled:pointer-events-none disabled:opacity-60`)})]})]})}function Ve({editor:e}){let[t,n]=W(!1),[r,i]=W({rows:0,cols:0}),a=V((t,r)=>{e.chain().focus().insertTable({rows:t,cols:r,withHeaderRow:!0}).run(),n(!1)},[e]);return J(o,{open:t,onOpenChange:e=>{n(e),e||i({rows:0,cols:0})},children:[q(c,{asChild:!0,children:q(X,{title:`Chèn bảng`,"aria-label":`Chèn bảng`,"data-slot":`toolbar-table-button`,children:q(P,{className:`h-3.5 w-3.5`})})}),J(s,{"data-slot":`table-insert-menu`,sideOffset:6,align:`start`,className:`w-auto p-3`,children:[q(`p`,{className:`mb-2 font-medium text-text-positive-strong text-xs`,children:r.rows>0?`Bảng ${r.rows} × ${r.cols}`:`Chọn kích thước bảng`}),q(`div`,{className:`grid grid-cols-6 gap-1`,onMouseLeave:()=>i({rows:0,cols:0}),children:Array.from({length:36},(e,t)=>{let n=Math.floor(t/6)+1,o=t%6+1,s=n<=r.rows&&o<=r.cols;return q(`button`,{type:`button`,"aria-label":`Bảng ${n} hàng, ${o} cột`,onMouseEnter:()=>i({rows:n,cols:o}),onClick:()=>a(n,o),className:G(`h-4 w-4 rounded-sm border border-border`,s?`border-primary bg-primary-muted`:`bg-muted-muted/40`)},`${n}-${o}`)})})]})]})}const He=[{label:`Yellow`,value:`#fde047`},{label:`Green`,value:`#86efac`},{label:`Blue`,value:`#93c5fd`},{label:`Pink`,value:`#f9a8d4`},{label:`Orange`,value:`#fdba74`},{label:`Purple`,value:`#c4b5fd`},{label:`Red`,value:`#fca5a5`},{label:`Cyan`,value:`#67e8f9`},{label:`Lime`,value:`#bef264`},{label:`Gray`,value:`#d1d5db`}],Ue=[{label:`Default`,value:``},{label:`Red`,value:`#ef4444`},{label:`Orange`,value:`#f97316`},{label:`Yellow`,value:`#eab308`},{label:`Green`,value:`#22c55e`},{label:`Blue`,value:`#3b82f6`},{label:`Purple`,value:`#a855f7`},{label:`Pink`,value:`#ec4899`},{label:`Gray`,value:`#6b7280`},{label:`Black`,value:`#000000`}],We=[{label:`Plain text`,value:`plaintext`},{label:`JavaScript`,value:`javascript`},{label:`TypeScript`,value:`typescript`},{label:`Python`,value:`python`},{label:`Java`,value:`java`},{label:`C#`,value:`csharp`},{label:`C++`,value:`cpp`},{label:`Go`,value:`go`},{label:`Rust`,value:`rust`},{label:`PHP`,value:`php`},{label:`Ruby`,value:`ruby`},{label:`Swift`,value:`swift`},{label:`Kotlin`,value:`kotlin`},{label:`SQL`,value:`sql`},{label:`Bash`,value:`bash`},{label:`JSON`,value:`json`},{label:`YAML`,value:`yaml`},{label:`CSS`,value:`css`},{label:`HTML/XML`,value:`xml`},{label:`Markdown`,value:`markdown`}];function Ge({editor:a,className:v,enableLink:y,enableTaskList:b,enableHighlight:S,enableColor:C,enableImage:w,enableTable:T,onImageUpload:P}){let z=Y({editor:a,selector:e=>e.editor.isActive(`heading`,{level:1})?1:e.editor.isActive(`heading`,{level:2})?2:e.editor.isActive(`heading`,{level:3})?3:null}),B=Y({editor:a,selector:e=>({bold:e.editor.isActive(`bold`),italic:e.editor.isActive(`italic`),underline:e.editor.isActive(`underline`),strike:e.editor.isActive(`strike`),code:e.editor.isActive(`code`)})}),V=Y({editor:a,selector:e=>({bulletList:e.editor.isActive(`bulletList`),orderedList:e.editor.isActive(`orderedList`),taskList:e.editor.isActive(`taskList`),blockquote:e.editor.isActive(`blockquote`),codeBlock:e.editor.isActive(`codeBlock`),codeBlockLanguage:e.editor.getAttributes(`codeBlock`).language??`plaintext`,table:e.editor.isActive(`table`)})}),H=Y({editor:a,selector:e=>({left:e.editor.isActive({textAlign:`left`}),center:e.editor.isActive({textAlign:`center`}),right:e.editor.isActive({textAlign:`right`}),justify:e.editor.isActive({textAlign:`justify`})})}),ne=z?`H${z}`:`P`;return J(`div`,{"data-slot":`text-editor-toolbar`,role:`toolbar`,"aria-label":`Định dạng văn bản`,className:G(`sticky top-0 z-10 flex flex-wrap items-center gap-0.5 border-border border-b bg-muted-muted p-1.5`,v),children:[q(X,{onClick:()=>a.chain().focus().undo().run(),disabled:!a.can().undo(),"aria-label":`Hoàn tác`,title:`Undo (Ctrl+Z)`,children:q(R,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().redo().run(),disabled:!a.can().redo(),"aria-label":`Làm lại`,title:`Redo (Ctrl+Y)`,children:q(M,{className:`h-3.5 w-3.5`})}),q(Z,{}),J(e,{children:[q(i,{asChild:!0,children:J(`button`,{type:`button`,"data-slot":`toolbar-heading-trigger`,"aria-label":`Kiểu đoạn văn`,"aria-haspopup":`menu`,className:G(`inline-flex h-8 items-center gap-1 rounded px-1.5 font-medium text-xs transition-colors`,`hover:bg-muted-muted hover:text-text-positive-strong`,`disabled:pointer-events-none disabled:opacity-40`,z!==null&&`bg-primary-muted text-primary hover:bg-primary-muted/80 hover:text-primary`),children:[q(`span`,{className:`w-5 text-center`,children:ne}),q(m,{className:`h-3 w-3 opacity-60`})]})}),J(t,{align:`start`,className:`min-w-32`,children:[q(n,{className:`px-2 py-1.5`,onClick:()=>a.chain().focus().setParagraph().run(),children:q(`span`,{className:`text-sm`,children:`Paragraph`})}),q(n,{className:`px-2 py-1.5`,onClick:()=>a.chain().focus().toggleHeading({level:1}).run(),children:q(`span`,{className:`font-extrabold text-sm`,children:`Heading 1`})}),q(n,{className:`px-2 py-1.5`,onClick:()=>a.chain().focus().toggleHeading({level:2}).run(),children:q(`span`,{className:`font-semibold text-sm`,children:`Heading 2`})}),q(n,{className:`px-2 py-1.5`,onClick:()=>a.chain().focus().toggleHeading({level:3}).run(),children:q(`span`,{className:`font-medium text-sm`,children:`Heading 3`})})]})]}),q(Z,{}),q(X,{onClick:()=>a.chain().focus().toggleBold().run(),isActive:B.bold,"aria-label":`In đậm`,title:`Bold (Ctrl+B)`,children:q(p,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().toggleItalic().run(),isActive:B.italic,"aria-label":`In nghiêng`,title:`Italic (Ctrl+I)`,children:q(ee,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().toggleUnderline().run(),isActive:B.underline,"aria-label":`Gạch chân`,title:`Underline (Ctrl+U)`,children:q(L,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().toggleStrike().run(),isActive:B.strike,"aria-label":`Gạch ngang`,title:`Strikethrough`,children:q(te,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().toggleCode().run(),isActive:B.code,"aria-label":`Mã inline`,title:`Inline Code`,children:q(h,{className:`h-3.5 w-3.5`})}),q(Z,{}),q(X,{onClick:()=>a.chain().focus().toggleBulletList().run(),isActive:V.bulletList,"aria-label":`Danh sách chấm`,title:`Bullet List`,children:q(E,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().toggleOrderedList().run(),isActive:V.orderedList,"aria-label":`Danh sách số`,title:`Ordered List`,children:q(O,{className:`h-3.5 w-3.5`})}),b&&q(X,{onClick:()=>a.chain().focus().toggleTaskList().run(),isActive:V.taskList,"aria-label":`Danh sách công việc`,title:`Task List`,children:q(D,{className:`h-3.5 w-3.5`})}),q(Z,{}),q(X,{onClick:()=>a.chain().focus().toggleBlockquote().run(),isActive:V.blockquote,"aria-label":`Trích dẫn`,title:`Blockquote`,children:q(j,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().toggleCodeBlock().run(),isActive:V.codeBlock,"aria-label":`Khối mã`,title:`Code Block`,children:q(g,{className:`h-3.5 w-3.5`})}),V.codeBlock&&J(e,{children:[q(i,{asChild:!0,children:J(`button`,{type:`button`,"data-slot":`toolbar-code-language-trigger`,"aria-label":`Ngôn ngữ lập trình`,"aria-haspopup":`menu`,className:G(`inline-flex h-7 items-center gap-1 rounded px-1.5 text-text-positive-weak text-xs transition-colors`,`hover:bg-muted-muted hover:text-text-positive-strong`),children:[q(`span`,{children:We.find(e=>e.value===V.codeBlockLanguage)?.label??`Plain text`}),q(m,{className:`h-3 w-3 opacity-60`})]})}),q(t,{align:`start`,className:`max-h-72 min-w-40 overflow-y-auto`,children:We.map(e=>q(n,{onClick:()=>a.chain().focus().updateAttributes(`codeBlock`,{language:e.value}).run(),children:q(`span`,{className:`text-sm`,children:e.label})},e.value))})]}),q(X,{onClick:()=>a.chain().focus().setHorizontalRule().run(),"aria-label":`Đường kẻ ngang`,title:`Horizontal Rule`,children:q(k,{className:`h-3.5 w-3.5`})}),q(Z,{}),q(X,{onClick:()=>a.chain().focus().setTextAlign(`left`).run(),isActive:H.left,"aria-label":`Căn trái`,title:`Align Left`,children:q(d,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().setTextAlign(`center`).run(),isActive:H.center,"aria-label":`Căn giữa`,title:`Align Center`,children:q(l,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().setTextAlign(`right`).run(),isActive:H.right,"aria-label":`Căn phải`,title:`Align Right`,children:q(f,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>a.chain().focus().setTextAlign(`justify`).run(),isActive:H.justify,"aria-label":`Căn đều`,title:`Align Justify`,children:q(u,{className:`h-3.5 w-3.5`})}),y&&J(K,{children:[q(Z,{}),q(Q,{editor:a})]}),w&&J(K,{children:[q(Z,{}),q(Be,{editor:a,onImageUpload:P})]}),T&&J(K,{children:[q(Z,{}),q(Ve,{editor:a}),V.table&&J(e,{children:[q(i,{asChild:!0,children:q(X,{title:`Sửa bảng`,"aria-label":`Sửa bảng`,children:q(F,{className:`h-3.5 w-3.5`})})}),J(t,{align:`start`,className:`min-w-44`,children:[J(n,{onClick:()=>a.chain().focus().addRowBefore().run(),children:[q(N,{className:`mr-2 h-3.5 w-3.5`}),` Thêm hàng phía trên`]}),J(n,{onClick:()=>a.chain().focus().addRowAfter().run(),children:[q(N,{className:`mr-2 h-3.5 w-3.5`}),` Thêm hàng phía dưới`]}),J(n,{onClick:()=>a.chain().focus().deleteRow().run(),children:[q(I,{className:`mr-2 h-3.5 w-3.5`}),` Xóa hàng`]}),q(r,{}),J(n,{onClick:()=>a.chain().focus().addColumnBefore().run(),children:[q(_,{className:`mr-2 h-3.5 w-3.5`}),` Thêm cột bên trái`]}),J(n,{onClick:()=>a.chain().focus().addColumnAfter().run(),children:[q(_,{className:`mr-2 h-3.5 w-3.5`}),` Thêm cột bên phải`]}),J(n,{onClick:()=>a.chain().focus().deleteColumn().run(),children:[q(I,{className:`mr-2 h-3.5 w-3.5`}),` Xóa cột`]}),q(r,{}),J(n,{onClick:()=>a.chain().focus().deleteTable().run(),className:`text-danger-strong`,children:[q(I,{className:`mr-2 h-3.5 w-3.5`}),` Xóa bảng`]})]})]})]}),(C||S)&&J(K,{children:[q(Z,{}),C&&J(o,{children:[q(c,{asChild:!0,children:q(X,{title:`Text Color`,"aria-label":`Màu chữ`,children:q(A,{className:`h-3.5 w-3.5`})})}),J(s,{align:`start`,className:`w-44 p-2`,children:[q(`p`,{className:`mb-1.5 font-medium text-text-positive-weak text-xs`,children:`Text Color`}),q(`div`,{className:`grid grid-cols-5 gap-1`,children:Ue.map(e=>q(`button`,{type:`button`,title:e.label,onClick:()=>{e.value?a.chain().focus().setColor(e.value).run():a.chain().focus().unsetColor().run()},className:G(`h-6 w-6 rounded border border-border transition-transform hover:scale-110`,!e.value&&`bg-background text-[10px] text-text-positive leading-none`),style:e.value?{backgroundColor:e.value}:void 0,children:!e.value&&`∅`},e.label))})]})]}),S&&J(o,{children:[q(c,{asChild:!0,children:q(X,{title:`Highlight`,"aria-label":`Tô sáng`,children:q(x,{className:`h-3.5 w-3.5`})})}),J(s,{align:`start`,className:`w-44 p-2`,children:[q(`p`,{className:`mb-1.5 font-medium text-text-positive-weak text-xs`,children:`Highlight`}),q(`div`,{className:`grid grid-cols-5 gap-1`,children:He.map(e=>q(`button`,{type:`button`,title:e.label,onClick:()=>a.chain().focus().toggleHighlight({color:e.value}).run(),className:`h-6 w-6 rounded border border-border transition-transform hover:scale-110`,style:{backgroundColor:e.value}},e.label))}),q(`button`,{type:`button`,onClick:()=>a.chain().focus().unsetHighlight().run(),className:`mt-1.5 w-full rounded border border-border py-0.5 text-center text-text-positive-weak text-xs hover:bg-muted-muted`,children:`Clear highlight`})]})]})]})]})}const Ke=Me(je),qe=me.extend({addNodeView(){return ce(Fe)}}),Je=[`p`,`h1`,`h2`,`h3`,`strong`,`em`,`s`,`u`,`code`,`pre`,`blockquote`,`ul`,`ol`,`li`,`hr`,`br`],Ye=[`class`,`style`];function Xe(e){let t=new Set(Je),n=new Set(Ye);if(e.enableLink&&(t.add(`a`),n.add(`href`).add(`target`).add(`rel`)),e.enableHighlight&&(t.add(`mark`),n.add(`data-color`)),e.enableColor&&t.add(`span`),e.enableTaskList){for(let e of[`label`,`input`,`div`,`span`])t.add(e);for(let e of[`data-type`,`data-checked`,`type`,`checked`,`disabled`])n.add(e)}if(e.enableImage){t.add(`img`);for(let e of[`src`,`alt`,`title`])n.add(e)}if(e.enableTable){for(let e of[`table`,`tbody`,`thead`,`tr`,`td`,`th`,`colgroup`,`col`])t.add(e);for(let e of[`colspan`,`rowspan`,`colwidth`])n.add(e)}return{ALLOWED_TAGS:Array.from(t),ALLOWED_ATTR:Array.from(n)}}function $(e,t){return typeof window>`u`?e:Ae.sanitize(e,t)}function Ze(e){return e.name.replace(/\.[^./]+$/,``)}function Qe({value:e,defaultValue:t,onChange:n,placeholder:r=`Start writing...`,readOnly:i=!1,showToolbar:a=!0,variant:o,size:s,className:c,toolbarClassName:l,editorClassName:u,maxLength:d,showCharacterCount:f,onCharacterCount:m,enableLink:h,enableBubbleMenu:g,enableTaskList:_,enableHighlight:v,enableColor:y,enableImage:b,enableTable:x,enableSlashCommand:S,onImageUpload:C}){let w=d!==void 0||f||m!==void 0,T=y||v,E=re(()=>Xe({enableLink:h,enableHighlight:v,enableColor:y,enableTaskList:_,enableImage:b,enableTable:x}),[h,v,y,_,b,x]),D=re(()=>{let e=[ke.configure({link:!1,underline:!1,codeBlock:!1,listKeymap:!1}),De,_e.configure({placeholder:r}),we.configure({types:[`heading`,`paragraph`]}),ge,fe.configure({lowlight:Ke,defaultLanguage:`plaintext`})];return T&&e.push(Ee),h&&e.push(he.configure({openOnClick:!1,linkOnPaste:!0,defaultProtocol:`https`})),_&&e.push(Ce,Se.configure({nested:!0})),v&&e.push(pe.configure({multicolor:!0})),y&&e.push(Te),b&&e.push(qe.configure({inline:!1,allowBase64:!1})),x&&e.push(ve.configure({resizable:!0}),xe,be,ye),S&&e.push(Re({enableTaskList:_,enableTable:x,enableImage:b,onImageUpload:C})),w&&e.push(de.configure({limit:d})),e},[w,r,d,v,T,_,h,y,b,x,S,C]),[O]=W(()=>{let n=e??t;return n&&$(n,E)}),k=U(n);k.current=n;let A=U(null),j=e=>{A.current&&(clearTimeout(A.current),A.current=null,k.current?.($(e,E)))},M=U(j);M.current=j;let N=ue({extensions:D,content:O,editable:!i,shouldRerenderOnTransaction:!1,editorProps:{handleDrop:(e,t)=>{if(!b||!C)return!1;let n=t.dataTransfer?.files?.[0];return n?.type.startsWith(`image/`)?(t.preventDefault(),C(n).then(e=>N?.chain().focus().setImage({src:e,alt:Ze(n)}).run()),!0):!1},handlePaste:(e,t)=>{if(!b||!C)return!1;let n=Array.from(t.clipboardData?.items??[]).find(e=>e.type.startsWith(`image/`))?.getAsFile();return n?(t.preventDefault(),C(n).then(e=>N?.chain().focus().setImage({src:e,alt:Ze(n)}).run()),!0):!1}},onUpdate:({editor:e})=>{if(m){let t=e.storage.characterCount;m({characters:t.characters(),words:t.words()})}k.current&&(A.current&&clearTimeout(A.current),A.current=setTimeout(()=>j(e.getHTML()),200))},onBlur:({editor:e})=>j(e.getHTML())}),P=U(N);P.current=N,H(()=>()=>{P.current&&M.current(P.current.getHTML())},[]),H(()=>{if(!N||e===void 0)return;let t=$(e,E);N.getHTML()!==t&&N.commands.setContent(t)},[N,e,E]),H(()=>{N&&N.setEditable(!i)},[N,i]);let F=Y({editor:N,selector:e=>{let t=e.editor?.storage?.characterCount;return t?t.characters():0}}),I=Y({editor:N,selector:e=>{let t=e.editor?.storage?.characterCount;return t?t.words():0}}),R=f||d!==void 0,z=d!==void 0&&F>d*.9,B=Y({editor:N,selector:e=>e.editor?{bold:e.editor.isActive(`bold`),italic:e.editor.isActive(`italic`),underline:e.editor.isActive(`underline`),strike:e.editor.isActive(`strike`)}:{bold:!1,italic:!1,underline:!1,strike:!1}});return J(`div`,{"data-slot":`text-editor`,className:G(`lunas-text-editor`,ze({variant:o,size:s}),c),children:[a&&!i&&N&&q(Ge,{editor:N,className:l,enableLink:h,enableTaskList:_,enableHighlight:v,enableColor:y,enableImage:b,enableTable:x,onImageUpload:C}),g&&!i&&N&&J(Oe,{editor:N,options:{placement:`top`},className:G(`z-50 flex items-center gap-0.5 rounded-md border border-border bg-popover p-1 shadow-dropdown`),children:[q(X,{onClick:()=>N.chain().focus().toggleBold().run(),isActive:B.bold,"aria-label":`In đậm`,title:`Bold (Ctrl+B)`,children:q(p,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>N.chain().focus().toggleItalic().run(),isActive:B.italic,"aria-label":`In nghiêng`,title:`Italic (Ctrl+I)`,children:q(ee,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>N.chain().focus().toggleUnderline().run(),isActive:B.underline,"aria-label":`Gạch chân`,title:`Underline (Ctrl+U)`,children:q(L,{className:`h-3.5 w-3.5`})}),q(X,{onClick:()=>N.chain().focus().toggleStrike().run(),isActive:B.strike,"aria-label":`Gạch ngang`,title:`Strikethrough`,children:q(te,{className:`h-3.5 w-3.5`})}),h&&J(K,{children:[q(Z,{}),q(Q,{editor:N})]})]}),q(ae,{editor:N,"data-slot":`text-editor-content`,className:G(`flex-1 bg-white text-text-positive`,u)}),R&&w&&J(`div`,{"data-slot":`text-editor-footer`,className:`flex items-center justify-between border-border border-t bg-muted-muted/30 px-3 py-1 text-text-positive-weak text-xs`,children:[J(`span`,{children:[I,` words`]}),J(`span`,{"data-warning":z||void 0,className:`data-warning:text-warning-strong`,children:[F,d?` / ${d}`:``,` characters`]})]})]})}export{Ge as n,Q as r,Qe as t};
|
|
2
|
+
//# sourceMappingURL=text-editor-XBOAwJk-.mjs.map
|