@customafk/lunas-ui 0.2.20 → 0.2.22
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/{alert-Dn5x8pBc.mjs → alert-C-Y4ZWNd.mjs} +1 -1
- package/dist/{alert-Dn5x8pBc.mjs.map → alert-C-Y4ZWNd.mjs.map} +1 -1
- package/dist/{alert-iwPuxYjG.d.cts → alert-CrrRLYNJ.d.mts} +7 -7
- package/dist/{alert-CwIH3Hkd.d.mts → alert-YcsH9M6y.d.cts} +7 -7
- package/dist/{avatar-5LzTjIjo.mjs → avatar-SJmvlfqm.mjs} +1 -1
- package/dist/{avatar-5LzTjIjo.mjs.map → avatar-SJmvlfqm.mjs.map} +1 -1
- package/dist/{badge-DBsYYM8d.d.cts → badge-84HgXhHg.d.cts} +7 -7
- package/dist/{badge-CINaZwOW.d.mts → badge-BiFukfpS.d.mts} +5 -5
- package/dist/{badge-DYcJtNU0.mjs → badge-DSwkF4C4.mjs} +1 -1
- package/dist/{badge-DYcJtNU0.mjs.map → badge-DSwkF4C4.mjs.map} +1 -1
- package/dist/{button-DPABon17.mjs → button-Bc8L9sFb.mjs} +2 -2
- package/dist/{button-DPABon17.mjs.map → button-Bc8L9sFb.mjs.map} +1 -1
- package/dist/{button-DdwLbwWQ.d.mts → button-DXeUzeTa.d.cts} +7 -7
- package/dist/{button-UgIAM1cP.d.cts → button-xMJ2hylr.d.mts} +7 -7
- package/dist/{button.variants-B8KCLWPT.mjs → button.variants-CwcJHcI5.mjs} +1 -1
- package/dist/{button.variants-B8KCLWPT.mjs.map → button.variants-CwcJHcI5.mjs.map} +1 -1
- package/dist/{calendar-DJnuujFC.mjs → calendar-C2psGpju.mjs} +2 -2
- package/dist/{calendar-DJnuujFC.mjs.map → calendar-C2psGpju.mjs.map} +1 -1
- package/dist/cards/grid-product-card.mjs +1 -1
- package/dist/cards/product-card.mjs +1 -1
- package/dist/cards/simple-card.d.mts +2 -2
- package/dist/cards/simple-card.mjs +1 -1
- package/dist/{checkbox-dDSDiwLB.mjs → checkbox-Bwy_4QS_.mjs} +1 -1
- package/dist/{checkbox-dDSDiwLB.mjs.map → checkbox-Bwy_4QS_.mjs.map} +1 -1
- package/dist/{close-BcOkVqd8.mjs → close-BS6EeCrQ.mjs} +1 -1
- package/dist/{close-BcOkVqd8.mjs.map → close-BS6EeCrQ.mjs.map} +1 -1
- package/dist/{cms-layout-CujBx9FA.mjs → cms-layout-DCODI3eE.mjs} +2 -2
- package/dist/{cms-layout-CujBx9FA.mjs.map → cms-layout-DCODI3eE.mjs.map} +1 -1
- package/dist/{command-B8y4H5q5.mjs → command-B5DpL6OG.mjs} +2 -2
- package/dist/{command-B8y4H5q5.mjs.map → command-B5DpL6OG.mjs.map} +1 -1
- package/dist/data-display/country.d.cts +1 -1
- package/dist/data-display/country.d.mts +1 -1
- package/dist/data-display/country.mjs +1 -1
- package/dist/data-display/date-tooltip.mjs +1 -1
- package/dist/data-display/date.mjs +1 -1
- package/dist/data-display/name.mjs +1 -1
- package/dist/data-display/phone-number.mjs +1 -1
- package/dist/data-display/role-badge.d.cts +1 -1
- package/dist/data-display/role-badge.d.mts +1 -1
- package/dist/data-display/role-badge.mjs +1 -1
- package/dist/data-display/statistic.d.mts +6 -6
- package/dist/data-display/user.mjs +1 -1
- package/dist/{date-C76vNHGL.mjs → date-D_nB7Lh1.mjs} +1 -1
- package/dist/{date-C76vNHGL.mjs.map → date-D_nB7Lh1.mjs.map} +1 -1
- package/dist/{dialog-dqqupmOT.mjs → dialog-DG4vMCr5.mjs} +2 -2
- package/dist/{dialog-dqqupmOT.mjs.map → dialog-DG4vMCr5.mjs.map} +1 -1
- package/dist/{dialog-CfbtCisP.d.mts → dialog-DeQiptoB.d.cts} +12 -12
- package/dist/{dialog-HXH3FYKH.d.cts → dialog-Dsuo8PP7.d.mts} +12 -12
- package/dist/dialogs/confirm-dialog.mjs +1 -1
- package/dist/dialogs/detail-dialog/components/sidebar.d.cts +2 -2
- package/dist/dialogs/detail-dialog/components/sidebar.d.mts +27 -27
- package/dist/dialogs/detail-dialog/components/sidebar.mjs +1 -1
- package/dist/dialogs/detail-dialog/index.mjs +1 -1
- package/dist/dialogs/error-dialog.mjs +1 -1
- package/dist/dialogs/loading-dialog.mjs +1 -1
- package/dist/{dist-DPEjz4kv.mjs → dist-XxWAVHy8.mjs} +1 -1
- package/dist/{dist-DPEjz4kv.mjs.map → dist-XxWAVHy8.mjs.map} +1 -1
- package/dist/{dropdown-menu-BocQ2Vev.mjs → dropdown-menu-BlsIwe4B.mjs} +1 -1
- package/dist/{dropdown-menu-BocQ2Vev.mjs.map → dropdown-menu-BlsIwe4B.mjs.map} +1 -1
- package/dist/features/descriptions/index.d.cts +7 -7
- package/dist/features/descriptions/index.d.mts +3 -3
- package/dist/features/descriptions/index.mjs +1 -1
- package/dist/features/search-modal/index.d.cts +2 -2
- package/dist/features/search-modal/index.d.mts +2 -2
- package/dist/features/search-modal/index.mjs +1 -1
- package/dist/features/tables/index.cjs +1 -1
- package/dist/features/tables/index.d.cts +1 -1
- package/dist/features/tables/index.d.mts +2 -2
- package/dist/features/tables/index.mjs +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.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/{field-DaZocB_E.mjs → field-Mn2bf2Ns.mjs} +2 -2
- package/dist/{field-DaZocB_E.mjs.map → field-Mn2bf2Ns.mjs.map} +1 -1
- package/dist/{flex-zl_w1yeZ.mjs → flex-Br7F9Fln.mjs} +1 -1
- package/dist/{flex-zl_w1yeZ.mjs.map → flex-Br7F9Fln.mjs.map} +1 -1
- package/dist/{heading-D8K7UGv2.mjs → heading-BnaNuvDS.mjs} +1 -1
- package/dist/{heading-D8K7UGv2.mjs.map → heading-BnaNuvDS.mjs.map} +1 -1
- package/dist/{image-WRAFECmc.mjs → image-C-CdKKP1.mjs} +2 -2
- package/dist/{image-WRAFECmc.mjs.map → image-C-CdKKP1.mjs.map} +1 -1
- package/dist/{index-D09-9eQ8.d.cts → index-6xsKIhtm.d.mts} +193 -193
- package/dist/{index-DXXR4oq-.d.mts → index-BG-MpSBd.d.cts} +340 -340
- package/dist/{index-Dn6FVL5X.d.cts → index-BMUK7c5C.d.cts} +4 -4
- package/dist/{index-3ZBP9XKI.d.mts → index-Bway3IIA.d.mts} +4 -4
- package/dist/{index-DWGlOnex.d.cts → index-CpeGB7w3.d.cts} +9 -9
- package/dist/{index-BreahdZP.d.mts → index-DriR2xP5.d.mts} +29 -29
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +13 -10
- package/dist/index.d.mts +13 -10
- package/dist/index.mjs +1 -1
- package/dist/{input-DjEul_uK.d.cts → input-BdcIab9N.d.cts} +6 -6
- package/dist/{input-BTm2GrZP.mjs → input-DLRypEj3.mjs} +1 -1
- package/dist/{input-BTm2GrZP.mjs.map → input-DLRypEj3.mjs.map} +1 -1
- package/dist/{input-BpTmuYnJ.d.mts → input-DLztWYaq.d.mts} +6 -6
- package/dist/{label-BC2u42kJ.mjs → label-BukQnBn7.mjs} +1 -1
- package/dist/{label-BC2u42kJ.mjs.map → label-BukQnBn7.mjs.map} +1 -1
- package/dist/layouts/cms-layout/index.mjs +1 -1
- package/dist/layouts/flex.d.cts +8 -8
- package/dist/layouts/flex.d.mts +12 -12
- package/dist/layouts/flex.mjs +1 -1
- package/dist/layouts/payment-layout/index.cjs +1 -1
- package/dist/layouts/payment-layout/index.d.cts +17 -2
- package/dist/layouts/payment-layout/index.d.mts +17 -2
- package/dist/layouts/payment-layout/index.mjs +1 -1
- package/dist/pages/FeatureDeveloping.d.cts +2 -2
- package/dist/pages/FeatureDeveloping.d.mts +2 -2
- package/dist/pages/FeatureDeveloping.mjs +1 -1
- package/dist/pages/FeatureFixing.d.mts +2 -2
- package/dist/pages/FeatureFixing.mjs +1 -1
- package/dist/pages/LoginPage.cjs +2 -0
- package/dist/pages/LoginPage.cjs.map +1 -0
- package/dist/pages/LoginPage.d.cts +55 -0
- package/dist/pages/LoginPage.d.mts +55 -0
- package/dist/pages/LoginPage.mjs +2 -0
- package/dist/pages/LoginPage.mjs.map +1 -0
- package/dist/pages/NotAuthorized.d.cts +2 -2
- package/dist/pages/NotAuthorized.d.mts +2 -2
- package/dist/pages/NotAuthorized.mjs +1 -1
- package/dist/pages/NotFound.d.cts +2 -2
- package/dist/pages/NotFound.d.mts +2 -2
- package/dist/pages/NotFound.mjs +1 -1
- package/dist/pages/RegisterPage.cjs +2 -0
- package/dist/pages/RegisterPage.cjs.map +1 -0
- package/dist/pages/RegisterPage.d.cts +52 -0
- package/dist/pages/RegisterPage.d.mts +52 -0
- package/dist/pages/RegisterPage.mjs +2 -0
- package/dist/pages/RegisterPage.mjs.map +1 -0
- package/dist/pages/VerifyEmailPage.cjs +2 -0
- package/dist/pages/VerifyEmailPage.cjs.map +1 -0
- package/dist/pages/VerifyEmailPage.d.cts +64 -0
- package/dist/pages/VerifyEmailPage.d.mts +64 -0
- package/dist/pages/VerifyEmailPage.mjs +2 -0
- package/dist/pages/VerifyEmailPage.mjs.map +1 -0
- package/dist/{paragraph-jzLzzEYZ.mjs → paragraph-CnHNC0rS.mjs} +1 -1
- package/dist/{paragraph-jzLzzEYZ.mjs.map → paragraph-CnHNC0rS.mjs.map} +1 -1
- package/dist/payment-layout-0mqqno1V.cjs +2 -0
- package/dist/payment-layout-0mqqno1V.cjs.map +1 -0
- package/dist/payment-layout-ClqGIxV7.mjs +2 -0
- package/dist/payment-layout-ClqGIxV7.mjs.map +1 -0
- package/dist/{popover-HZvZNeka.mjs → popover-DvGJ23lJ.mjs} +2 -2
- package/dist/{popover-HZvZNeka.mjs.map → popover-DvGJ23lJ.mjs.map} +1 -1
- package/dist/{progress-CgQ13rSf.mjs → progress-2G9rCupJ.mjs} +1 -1
- package/dist/{progress-CgQ13rSf.mjs.map → progress-2G9rCupJ.mjs.map} +1 -1
- package/dist/{radio-group-BN5y5gZY.mjs → radio-group-fN6o0QBx.mjs} +1 -1
- package/dist/{radio-group-BN5y5gZY.mjs.map → radio-group-fN6o0QBx.mjs.map} +1 -1
- package/dist/{resizable-CLUR91Hx.mjs → resizable-BxsL978e.mjs} +1 -1
- package/dist/{resizable-CLUR91Hx.mjs.map → resizable-BxsL978e.mjs.map} +1 -1
- package/dist/{search-modal-Dz7rfifb.mjs → search-modal-DZI6O6ua.mjs} +2 -2
- package/dist/{search-modal-Dz7rfifb.mjs.map → search-modal-DZI6O6ua.mjs.map} +1 -1
- package/dist/{select-1Z1p9bmp.mjs → select-Ze8Fq88G.mjs} +1 -1
- package/dist/{select-1Z1p9bmp.mjs.map → select-Ze8Fq88G.mjs.map} +1 -1
- package/dist/{separator-DVI2h_rd.mjs → separator-DXnFHf3v.mjs} +1 -1
- package/dist/{separator-DVI2h_rd.mjs.map → separator-DXnFHf3v.mjs.map} +1 -1
- package/dist/{sheet-BRXYSJDv.mjs → sheet-GUUifKAd.mjs} +1 -1
- package/dist/{sheet-BRXYSJDv.mjs.map → sheet-GUUifKAd.mjs.map} +1 -1
- package/dist/{sidebar-QPaK3ryM.mjs → sidebar-C_jArO1q.mjs} +2 -2
- package/dist/{sidebar-QPaK3ryM.mjs.map → sidebar-C_jArO1q.mjs.map} +1 -1
- package/dist/{skeleton-CZVkWN4p.mjs → skeleton-BLwzHejl.mjs} +1 -1
- package/dist/{skeleton-CZVkWN4p.mjs.map → skeleton-BLwzHejl.mjs.map} +1 -1
- package/dist/{spinner-DkmcGiVT.mjs → spinner-BaZ19Lla.mjs} +1 -1
- package/dist/{spinner-DkmcGiVT.mjs.map → spinner-BaZ19Lla.mjs.map} +1 -1
- package/dist/tables-CI2AZcbt.cjs +4 -0
- package/dist/tables-CI2AZcbt.cjs.map +1 -0
- package/dist/tables-EnSyNV7J.mjs +4 -0
- package/dist/tables-EnSyNV7J.mjs.map +1 -0
- package/dist/{tanstack-form-Sqj9ZD9z.mjs → tanstack-form-C1EVQJ-n.mjs} +2 -2
- package/dist/{tanstack-form-Sqj9ZD9z.mjs.map → tanstack-form-C1EVQJ-n.mjs.map} +1 -1
- package/dist/{text-editor-BLK_EeiU.mjs → text-editor-ae2UTKW8.mjs} +1 -1
- package/dist/{text-editor-BLK_EeiU.mjs.map → text-editor-ae2UTKW8.mjs.map} +1 -1
- package/dist/{textarea-D2ILgz82.mjs → textarea-CEtUNLwy.mjs} +1 -1
- package/dist/{textarea-D2ILgz82.mjs.map → textarea-CEtUNLwy.mjs.map} +1 -1
- package/dist/{tooltip-C7UhtrFf.mjs → tooltip-Cy0HbyAx.mjs} +1 -1
- package/dist/{tooltip-C7UhtrFf.mjs.map → tooltip-Cy0HbyAx.mjs.map} +1 -1
- package/dist/{types-BonWRhox.d.mts → types-CLkAmCre.d.cts} +1 -1
- package/dist/{types-COppLTPh.mjs → types-CuAlMviO.mjs} +1 -1
- package/dist/{types-COppLTPh.mjs.map → types-CuAlMviO.mjs.map} +1 -1
- package/dist/{types-CILbFL3j.d.cts → types-wApFGHmV.d.mts} +1 -1
- package/dist/typography/paragraph.d.cts +3 -3
- package/dist/typography/paragraph.d.mts +5 -5
- package/dist/typography/paragraph.mjs +1 -1
- package/dist/typography/title.d.cts +2 -2
- package/dist/typography/title.d.mts +2 -2
- package/dist/ui/alert-dialog.d.cts +12 -12
- package/dist/ui/alert-dialog.d.mts +12 -12
- package/dist/ui/alert-dialog.mjs +1 -1
- package/dist/ui/alert.d.cts +1 -1
- package/dist/ui/alert.d.mts +1 -1
- package/dist/ui/alert.mjs +1 -1
- package/dist/ui/aspect-ratio.d.cts +2 -2
- package/dist/ui/aspect-ratio.d.mts +2 -2
- package/dist/ui/avatar.d.cts +4 -4
- package/dist/ui/avatar.d.mts +4 -4
- package/dist/ui/avatar.mjs +1 -1
- package/dist/ui/badge.d.cts +1 -1
- package/dist/ui/badge.d.mts +1 -1
- package/dist/ui/badge.mjs +1 -1
- package/dist/ui/breadcrumb.d.cts +8 -8
- package/dist/ui/breadcrumb.d.mts +8 -8
- package/dist/ui/breadcrumb.mjs +1 -1
- package/dist/ui/button-group.d.cts +7 -7
- package/dist/ui/button-group.d.mts +7 -7
- package/dist/ui/button-group.mjs +1 -1
- package/dist/ui/button.d.cts +1 -1
- package/dist/ui/button.d.mts +1 -1
- package/dist/ui/button.mjs +1 -1
- package/dist/ui/buttons/add-new.mjs +1 -1
- package/dist/ui/buttons/edit.mjs +1 -1
- package/dist/ui/buttons/refresh.mjs +1 -1
- package/dist/ui/buttons/trash.mjs +1 -1
- package/dist/ui/buttons/upload-image.mjs +1 -1
- package/dist/ui/calendar.d.cts +4 -4
- package/dist/ui/calendar.d.mts +4 -4
- package/dist/ui/calendar.mjs +1 -1
- package/dist/ui/card.d.cts +8 -8
- package/dist/ui/card.d.mts +8 -8
- package/dist/ui/card.mjs +1 -1
- package/dist/ui/carousel.d.cts +7 -7
- package/dist/ui/carousel.d.mts +7 -7
- package/dist/ui/carousel.mjs +1 -1
- package/dist/ui/checkbox.d.cts +2 -2
- package/dist/ui/checkbox.d.mts +2 -2
- package/dist/ui/checkbox.mjs +1 -1
- package/dist/ui/collapsible.d.cts +4 -4
- package/dist/ui/collapsible.d.mts +4 -4
- package/dist/ui/command.d.cts +11 -11
- package/dist/ui/command.d.mts +11 -11
- package/dist/ui/command.mjs +1 -1
- package/dist/ui/context-menu.d.cts +16 -16
- package/dist/ui/context-menu.d.mts +16 -16
- package/dist/ui/dialog.d.cts +1 -1
- package/dist/ui/dialog.d.mts +1 -1
- package/dist/ui/dialog.mjs +1 -1
- package/dist/ui/drawer.d.cts +11 -11
- package/dist/ui/drawer.d.mts +11 -11
- package/dist/ui/dropdown-menu.d.cts +16 -16
- package/dist/ui/dropdown-menu.d.mts +16 -16
- package/dist/ui/dropdown-menu.mjs +1 -1
- package/dist/ui/empty.d.cts +9 -9
- package/dist/ui/empty.d.mts +9 -9
- package/dist/ui/field.d.cts +25 -25
- package/dist/ui/field.d.mts +25 -25
- package/dist/ui/field.mjs +1 -1
- package/dist/ui/file-uploader.d.cts +2 -2
- package/dist/ui/file-uploader.d.mts +2 -2
- package/dist/ui/file-uploader.mjs +1 -1
- package/dist/ui/form.d.cts +11 -11
- package/dist/ui/form.d.mts +11 -11
- package/dist/ui/form.mjs +1 -1
- package/dist/ui/hover-card.d.cts +4 -4
- package/dist/ui/hover-card.d.mts +4 -4
- package/dist/ui/image.mjs +1 -1
- package/dist/ui/input-otp.d.cts +5 -5
- package/dist/ui/input-otp.d.mts +5 -5
- package/dist/ui/input.d.cts +1 -1
- package/dist/ui/input.d.mts +1 -1
- package/dist/ui/input.mjs +1 -1
- package/dist/ui/inputs/search-input.d.cts +3 -3
- package/dist/ui/inputs/search-input.d.mts +3 -3
- package/dist/ui/inputs/search-input.mjs +1 -1
- package/dist/ui/item.d.cts +16 -16
- package/dist/ui/item.d.mts +16 -16
- package/dist/ui/item.mjs +1 -1
- package/dist/ui/label.d.cts +2 -2
- package/dist/ui/label.d.mts +2 -2
- package/dist/ui/label.mjs +1 -1
- package/dist/ui/menubar.d.cts +17 -17
- package/dist/ui/menubar.d.mts +17 -17
- package/dist/ui/multi-select.d.cts +2 -2
- package/dist/ui/multi-select.d.mts +3 -3
- package/dist/ui/multi-select.mjs +1 -1
- package/dist/ui/navigation-menu.d.cts +11 -11
- package/dist/ui/navigation-menu.d.mts +11 -11
- package/dist/ui/pagination.d.cts +9 -9
- package/dist/ui/pagination.d.mts +9 -9
- package/dist/ui/pagination.mjs +1 -1
- package/dist/ui/popover.d.cts +6 -6
- package/dist/ui/popover.d.mts +6 -6
- package/dist/ui/popover.mjs +1 -1
- package/dist/ui/progress.d.cts +2 -2
- package/dist/ui/progress.d.mts +2 -2
- package/dist/ui/progress.mjs +1 -1
- package/dist/ui/radio-group.d.cts +3 -3
- package/dist/ui/radio-group.d.mts +3 -3
- package/dist/ui/radio-group.mjs +1 -1
- package/dist/ui/resizable.d.cts +9 -9
- package/dist/ui/resizable.d.mts +9 -9
- package/dist/ui/resizable.mjs +1 -1
- package/dist/ui/scroll-area.d.cts +6 -6
- package/dist/ui/scroll-area.d.mts +6 -6
- package/dist/ui/select.d.cts +9 -9
- package/dist/ui/select.d.mts +9 -9
- package/dist/ui/select.mjs +1 -1
- package/dist/ui/separator.d.cts +2 -2
- package/dist/ui/separator.d.mts +2 -2
- package/dist/ui/separator.mjs +1 -1
- package/dist/ui/sheet.d.cts +9 -9
- package/dist/ui/sheet.d.mts +9 -9
- package/dist/ui/sheet.mjs +1 -1
- package/dist/ui/sidebar.d.cts +29 -29
- package/dist/ui/sidebar.d.mts +29 -29
- package/dist/ui/sidebar.mjs +1 -1
- package/dist/ui/skeleton.d.cts +2 -2
- package/dist/ui/skeleton.d.mts +2 -2
- package/dist/ui/skeleton.mjs +1 -1
- package/dist/ui/slider.d.cts +2 -2
- package/dist/ui/slider.d.mts +2 -2
- package/dist/ui/sonner.d.cts +2 -2
- package/dist/ui/sonner.d.mts +2 -2
- package/dist/ui/spinner.d.cts +2 -2
- package/dist/ui/spinner.d.mts +2 -2
- package/dist/ui/spinner.mjs +1 -1
- package/dist/ui/switch.d.cts +2 -2
- package/dist/ui/switch.d.mts +2 -2
- package/dist/ui/table.d.cts +18 -18
- package/dist/ui/table.d.mts +18 -18
- package/dist/ui/tabs.d.cts +5 -5
- package/dist/ui/tabs.d.mts +5 -5
- package/dist/ui/textarea.d.cts +2 -2
- package/dist/ui/textarea.d.mts +2 -2
- package/dist/ui/textarea.mjs +1 -1
- package/dist/ui/toggle-group.d.cts +3 -3
- package/dist/ui/toggle-group.d.mts +3 -3
- package/dist/ui/toggle.d.cts +5 -5
- package/dist/ui/toggle.d.mts +5 -5
- package/dist/ui/tooltip.d.cts +5 -5
- package/dist/ui/tooltip.d.mts +5 -5
- package/dist/ui/tooltip.mjs +1 -1
- package/dist/{user-DIEH54XW.mjs → user-DxSilm4V.mjs} +2 -2
- package/dist/{user-DIEH54XW.mjs.map → user-DxSilm4V.mjs.map} +1 -1
- package/package.json +13 -1
- package/dist/payment-layout-BKJ5xJra.mjs +0 -2
- package/dist/payment-layout-BKJ5xJra.mjs.map +0 -1
- package/dist/payment-layout-CcMvKPaX.cjs +0 -2
- package/dist/payment-layout-CcMvKPaX.cjs.map +0 -1
- package/dist/tables--hUSBZFP.cjs +0 -4
- package/dist/tables--hUSBZFP.cjs.map +0 -1
- package/dist/tables-BZ5jLRGG.mjs +0 -4
- package/dist/tables-BZ5jLRGG.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoginPage.mjs","names":[],"sources":["../../packages/components/pages/LoginPage.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useState } from 'react';\n\nimport { Eye, EyeOff } from 'lucide-react';\nimport { z } from 'zod';\n\nimport { Alert, AlertDescription } from '../ui/alert';\nimport { Button } from '../ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/dialog';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\n\nexport interface LoginPageProps {\n /** Controls whether the dialog is open */\n open: boolean;\n /** Called when the dialog open state changes */\n onOpenChange: (open: boolean) => void;\n /** Called when the user submits login credentials */\n onLogin: (email: string, password: string) => Promise<void> | void;\n /** Called when the \"Quên mật khẩu?\" link is clicked */\n onForgotPassword?: () => void;\n /** Called when the \"Đăng ký\" link is clicked */\n onRegister?: () => void;\n /** Disables the form and shows a spinner on the submit button */\n isLoading?: boolean;\n /** Server-side error message rendered in a destructive Alert */\n errorMessage?: string;\n /** Dialog heading. Default: \"Đăng nhập\" */\n title?: string;\n /** Dialog subheading. Default: \"Nhập thông tin để tiếp tục\" */\n subtitle?: string;\n}\n\nconst loginSchema = z.object({\n email: z.string().min(1, 'Vui lòng nhập email').email('Email không hợp lệ'),\n password: z.string().min(1, 'Vui lòng nhập mật khẩu'),\n});\n\n/**\n * Modal login dialog for the client authentication flow.\n *\n * @example\n * ```tsx\n * import { LoginPage } from '@customafk/lunas-ui/pages/LoginPage';\n *\n * <LoginPage\n * open={open}\n * onOpenChange={setOpen}\n * onLogin={async (email, password) => {\n * await authService.login(email, password);\n * setOpen(false);\n * }}\n * onRegister={() => { setOpen(false); setRegisterOpen(true); }}\n * />\n * ```\n */\nexport const LoginPage = ({\n open,\n onOpenChange,\n onLogin,\n onForgotPassword,\n onRegister,\n isLoading = false,\n errorMessage,\n title = 'Đăng nhập',\n subtitle = 'Nhập thông tin để tiếp tục',\n}: LoginPageProps) => {\n const emailId = useId();\n const passwordId = useId();\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [showPassword, setShowPassword] = useState(false);\n const [fieldErrors, setFieldErrors] = useState<{ email?: string; password?: string }>({});\n\n const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n const result = loginSchema.safeParse({ email, password });\n if (!result.success) {\n const errors = result.error.flatten().fieldErrors;\n setFieldErrors({ email: errors.email?.[0], password: errors.password?.[0] });\n return;\n }\n setFieldErrors({});\n await onLogin(email, password);\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{subtitle}</DialogDescription>\n </DialogHeader>\n\n <form onSubmit={handleSubmit} noValidate className=\"flex flex-col gap-4\">\n {errorMessage && (\n <Alert variant=\"destructive\">\n <AlertDescription>{errorMessage}</AlertDescription>\n </Alert>\n )}\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={emailId}>Email</Label>\n <Input\n id={emailId}\n type=\"email\"\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n value={email}\n onChange={e => setEmail(e.target.value)}\n aria-invalid={!!fieldErrors.email}\n disabled={isLoading}\n />\n {fieldErrors.email && <p className=\"text-destructive text-xs\">{fieldErrors.email}</p>}\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-center justify-between\">\n <Label htmlFor={passwordId}>Mật khẩu</Label>\n {onForgotPassword && (\n <Button type=\"button\" variant=\"link\" size=\"sm\" className=\"h-auto p-0 text-xs\" onClick={onForgotPassword}>\n Quên mật khẩu?\n </Button>\n )}\n </div>\n <div className=\"relative\">\n <Input\n id={passwordId}\n type={showPassword ? 'text' : 'password'}\n autoComplete=\"current-password\"\n placeholder=\"••••••••\"\n value={password}\n onChange={e => setPassword(e.target.value)}\n aria-invalid={!!fieldErrors.password}\n disabled={isLoading}\n className=\"pr-10\"\n />\n <button\n type=\"button\"\n className=\"absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground\"\n onMouseDown={e => {\n e.preventDefault();\n setShowPassword(v => !v);\n }}\n aria-label={showPassword ? 'Ẩn mật khẩu' : 'Hiện mật khẩu'}\n >\n {showPassword ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n {fieldErrors.password && <p className=\"text-destructive text-xs\">{fieldErrors.password}</p>}\n </div>\n\n <Button type=\"submit\" isLoading={isLoading} className=\"w-full\">\n Đăng nhập\n </Button>\n </form>\n\n {onRegister && (\n <div className=\"flex justify-center gap-1 text-muted-foreground text-sm\">\n <span>Chưa có tài khoản?</span>\n <Button variant=\"link\" size=\"sm\" className=\"h-auto p-0\" onClick={onRegister}>\n Đăng ký\n </Button>\n </div>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n"],"mappings":"ijBAkCA,MAAM,EAAc,EAAE,OAAO,CAC3B,MAAO,EAAE,QAAQ,CAAC,IAAI,EAAG,sBAAsB,CAAC,MAAM,qBAAqB,CAC3E,SAAU,EAAE,QAAQ,CAAC,IAAI,EAAG,yBAAyB,CACtD,CAAC,CAoBW,GAAa,CACxB,OACA,eACA,UACA,mBACA,aACA,YAAY,GACZ,eACA,QAAQ,YACR,WAAW,gCACS,CACpB,IAAM,EAAU,GAAO,CACjB,EAAa,GAAO,CACpB,CAAC,EAAO,GAAY,EAAS,GAAG,CAChC,CAAC,EAAU,GAAe,EAAS,GAAG,CACtC,CAAC,EAAc,GAAmB,EAAS,GAAM,CACjD,CAAC,EAAa,GAAkB,EAAgD,EAAE,CAAC,CAczF,OACE,EAAC,EAAA,CAAa,OAAoB,wBAChC,EAAC,EAAA,CAAc,UAAU,wBACvB,EAAC,EAAA,CAAA,SAAA,CACC,EAAC,EAAA,CAAA,SAAa,EAAA,CAAoB,CAClC,EAAC,EAAA,CAAA,SAAmB,EAAA,CAA6B,CAAA,CAAA,CACpC,CAEf,EAAC,OAAA,CAAK,SApBS,KAAO,IAAwC,CAClE,EAAE,gBAAgB,CAClB,IAAM,EAAS,EAAY,UAAU,CAAE,QAAO,WAAU,CAAC,CACzD,GAAI,CAAC,EAAO,QAAS,CACnB,IAAM,EAAS,EAAO,MAAM,SAAS,CAAC,YACtC,EAAe,CAAE,MAAO,EAAO,QAAQ,GAAI,SAAU,EAAO,WAAW,GAAI,CAAC,CAC5E,OAEF,EAAe,EAAE,CAAC,CAClB,MAAM,EAAQ,EAAO,EAAS,EAWI,WAAA,GAAW,UAAU,gCAChD,GACC,EAAC,EAAA,CAAM,QAAQ,uBACb,EAAC,EAAA,CAAA,SAAkB,EAAA,CAAgC,EAC7C,CAGV,EAAC,MAAA,CAAI,UAAU,kCACb,EAAC,EAAA,CAAM,QAAS,WAAS,SAAa,CACtC,EAAC,EAAA,CACC,GAAI,EACJ,KAAK,QACL,aAAa,QACb,YAAY,kBACZ,MAAO,EACP,SAAU,GAAK,EAAS,EAAE,OAAO,MAAM,CACvC,eAAc,CAAC,CAAC,EAAY,MAC5B,SAAU,GACV,CACD,EAAY,OAAS,EAAC,IAAA,CAAE,UAAU,oCAA4B,EAAY,OAAU,GACjF,CAEN,EAAC,MAAA,CAAI,UAAU,kCACb,EAAC,MAAA,CAAI,UAAU,8CACb,EAAC,EAAA,CAAM,QAAS,WAAY,YAAgB,CAC3C,GACC,EAAC,EAAA,CAAO,KAAK,SAAS,QAAQ,OAAO,KAAK,KAAK,UAAU,qBAAqB,QAAS,WAAkB,kBAEhG,CAAA,EAEP,CACN,EAAC,MAAA,CAAI,UAAU,qBACb,EAAC,EAAA,CACC,GAAI,EACJ,KAAM,EAAe,OAAS,WAC9B,aAAa,mBACb,YAAY,WACZ,MAAO,EACP,SAAU,GAAK,EAAY,EAAE,OAAO,MAAM,CAC1C,eAAc,CAAC,CAAC,EAAY,SAC5B,SAAU,EACV,UAAU,SACV,CACF,EAAC,SAAA,CACC,KAAK,SACL,UAAU,gGACV,YAAa,GAAK,CAChB,EAAE,gBAAgB,CAClB,EAAgB,GAAK,CAAC,EAAE,EAE1B,aAAY,EAAe,cAAgB,yBAE3B,EAAf,EAAgB,EAAuB,EAAvB,CAAO,KAAM,GAAA,CAA0B,EACjD,CAAA,EACL,CACL,EAAY,UAAY,EAAC,IAAA,CAAE,UAAU,oCAA4B,EAAY,UAAa,GACvF,CAEN,EAAC,EAAA,CAAO,KAAK,SAAoB,YAAW,UAAU,kBAAS,aAEtD,GACJ,CAEN,GACC,EAAC,MAAA,CAAI,UAAU,oEACb,EAAC,OAAA,CAAA,SAAK,qBAAA,CAAyB,CAC/B,EAAC,EAAA,CAAO,QAAQ,OAAO,KAAK,KAAK,UAAU,aAAa,QAAS,WAAY,WAEpE,CAAA,EACL,GAEM,EACT"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime29 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region packages/components/pages/NotAuthorized.d.ts
|
|
4
4
|
interface NotAuthorizedProps {
|
|
@@ -37,7 +37,7 @@ declare const NotAuthorized: ({
|
|
|
37
37
|
onButtonClick,
|
|
38
38
|
className,
|
|
39
39
|
iconClassName
|
|
40
|
-
}: NotAuthorizedProps) =>
|
|
40
|
+
}: NotAuthorizedProps) => react_jsx_runtime29.JSX.Element;
|
|
41
41
|
//#endregion
|
|
42
42
|
export { NotAuthorized, NotAuthorized as default, NotAuthorizedProps };
|
|
43
43
|
//# sourceMappingURL=NotAuthorized.d.cts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime253 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region packages/components/pages/NotAuthorized.d.ts
|
|
4
4
|
interface NotAuthorizedProps {
|
|
@@ -37,7 +37,7 @@ declare const NotAuthorized: ({
|
|
|
37
37
|
onButtonClick,
|
|
38
38
|
className,
|
|
39
39
|
iconClassName
|
|
40
|
-
}: NotAuthorizedProps) =>
|
|
40
|
+
}: NotAuthorizedProps) => react_jsx_runtime253.JSX.Element;
|
|
41
41
|
//#endregion
|
|
42
42
|
export { NotAuthorized, NotAuthorized as default, NotAuthorizedProps };
|
|
43
43
|
//# sourceMappingURL=NotAuthorized.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../button.variants-
|
|
1
|
+
import"../button.variants-CwcJHcI5.mjs";import{t as e}from"../button-Bc8L9sFb.mjs";import{ShieldAlert as t}from"lucide-react";import{jsx as n,jsxs as r}from"react/jsx-runtime";import{cn as i}from"@customafk/react-toolkit/utils";const a=({title:a=`Quyền truy cập bị từ chối`,subtitle:o=`Xin lỗi, bạn không có quyền truy cập vào trang này.`,buttonText:s=`Quay lại`,onButtonClick:c=()=>window.history.back(),className:l,iconClassName:u})=>r(`div`,{className:i(`flex flex-col items-center justify-center min-h-[50vh] gap-4 sm:gap-6 py-8 sm:py-10 px-4 text-center w-full`,l),children:[r(`div`,{className:`flex flex-col items-center gap-2`,children:[n(t,{className:i(`size-16 sm:size-24 text-primary`,u)}),n(`div`,{className:`text-4xl sm:text-6xl font-bold text-primary`,children:`403`})]}),n(`h1`,{className:`text-xl sm:text-2xl font-semibold mt-2`,children:a}),n(`p`,{className:`text-muted-foreground max-w-md text-sm sm:text-base`,children:o}),n(e,{onClick:c,variant:`default`,className:`mt-2`,size:`sm`,children:s})]});var o=a;export{a as NotAuthorized,o as default};
|
|
2
2
|
//# sourceMappingURL=NotAuthorized.mjs.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime26 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region packages/components/pages/NotFound.d.ts
|
|
4
4
|
interface NotFoundProps {
|
|
@@ -37,7 +37,7 @@ declare const NotFound: ({
|
|
|
37
37
|
onButtonClick,
|
|
38
38
|
className,
|
|
39
39
|
iconClassName
|
|
40
|
-
}: NotFoundProps) =>
|
|
40
|
+
}: NotFoundProps) => react_jsx_runtime26.JSX.Element;
|
|
41
41
|
//#endregion
|
|
42
42
|
export { NotFound, NotFound as default, NotFoundProps };
|
|
43
43
|
//# sourceMappingURL=NotFound.d.cts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime230 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region packages/components/pages/NotFound.d.ts
|
|
4
4
|
interface NotFoundProps {
|
|
@@ -37,7 +37,7 @@ declare const NotFound: ({
|
|
|
37
37
|
onButtonClick,
|
|
38
38
|
className,
|
|
39
39
|
iconClassName
|
|
40
|
-
}: NotFoundProps) =>
|
|
40
|
+
}: NotFoundProps) => react_jsx_runtime230.JSX.Element;
|
|
41
41
|
//#endregion
|
|
42
42
|
export { NotFound, NotFound as default, NotFoundProps };
|
|
43
43
|
//# sourceMappingURL=NotFound.d.mts.map
|
package/dist/pages/NotFound.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../button.variants-
|
|
1
|
+
import"../button.variants-CwcJHcI5.mjs";import{t as e}from"../button-Bc8L9sFb.mjs";import{FileQuestion as t}from"lucide-react";import{jsx as n,jsxs as r}from"react/jsx-runtime";import{cn as i}from"@customafk/react-toolkit/utils";const a=({title:a=`Không tìm thấy trang`,subtitle:o=`Xin lỗi, trang bạn đang tìm kiếm không tồn tại hoặc đã bị di chuyển.`,buttonText:s=`Trở về trang chủ`,onButtonClick:c=()=>window.history.back(),className:l,iconClassName:u})=>r(`div`,{className:i(`flex flex-col items-center justify-center min-h-[50vh] gap-4 sm:gap-6 py-8 sm:py-10 px-4 text-center w-full`,l),children:[r(`div`,{className:`flex flex-col items-center gap-2`,children:[n(t,{className:i(`size-16 sm:size-24 text-primary`,u)}),n(`div`,{className:`text-4xl sm:text-6xl font-bold text-primary`,children:`404`})]}),n(`h1`,{className:`text-xl sm:text-2xl font-semibold mt-2`,children:a}),n(`p`,{className:`text-muted-foreground max-w-md text-sm sm:text-base`,children:o}),n(e,{onClick:c,variant:`default`,className:`mt-2`,size:`sm`,children:s})]});var o=a;export{a as NotFound,o as default};
|
|
2
2
|
//# sourceMappingURL=NotFound.mjs.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require(`../chunk-Bmb41Sf3.cjs`);require(`../button.variants-tnhb123u.cjs`);const t=require(`../button-CwDT3m4m.cjs`);require(`../heading-AKz5ewy-.cjs`),require(`../paragraph-DN85Huc4.cjs`),require(`../close-DXk_H3Gt.cjs`);const n=require(`../dialog-o_68LQXd.cjs`),r=require(`../input-BMOYFJYM.cjs`),i=require(`../label-DYsRdKMt.cjs`),a=require(`../alert-B7TDxb35.cjs`);let o=require(`lucide-react`),s=require(`react`),c=require(`react/jsx-runtime`),l=require(`zod`);const u=l.z.object({email:l.z.string().min(1,`Vui lòng nhập email`).email(`Email không hợp lệ`),password:l.z.string().min(8,`Mật khẩu phải có ít nhất 8 ký tự`).max(50,`Mật khẩu không được vượt quá 50 ký tự`).regex(/[A-Z]/,`Phải có ít nhất một chữ hoa`).regex(/[a-z]/,`Phải có ít nhất một chữ thường`).regex(/[0-9]/,`Phải có ít nhất một chữ số`).regex(/[^A-Za-z0-9]/,`Phải có ít nhất một ký tự đặc biệt`),confirmPassword:l.z.string().min(1,`Vui lòng xác nhận mật khẩu`)}).refine(e=>e.password===e.confirmPassword,{message:`Mật khẩu xác nhận không khớp`,path:[`confirmPassword`]}),d=({open:e,onOpenChange:l,onRegister:d,onLogin:f,isLoading:p=!1,errorMessage:m,title:h=`Đăng ký`,subtitle:g=`Tạo tài khoản mới để bắt đầu`})=>{let _=(0,s.useId)(),v=(0,s.useId)(),y=(0,s.useId)(),[b,x]=(0,s.useState)(``),[S,C]=(0,s.useState)(``),[w,T]=(0,s.useState)(``),[E,D]=(0,s.useState)(!1),[O,k]=(0,s.useState)(!1),[A,j]=(0,s.useState)({});return(0,c.jsx)(n.t,{open:e,onOpenChange:l,children:(0,c.jsxs)(n.r,{className:`sm:max-w-sm`,children:[(0,c.jsxs)(n.o,{children:[(0,c.jsx)(n.l,{children:h}),(0,c.jsx)(n.i,{children:g})]}),(0,c.jsxs)(`form`,{onSubmit:async e=>{e.preventDefault();let t=u.safeParse({email:b,password:S,confirmPassword:w});if(!t.success){let e=t.error.flatten().fieldErrors;j({email:e.email?.[0],password:e.password?.[0],confirmPassword:e.confirmPassword?.[0]});return}j({}),await d(b,S)},noValidate:!0,className:`flex flex-col gap-4`,children:[m&&(0,c.jsx)(a.t,{variant:`destructive`,children:(0,c.jsx)(a.n,{children:m})}),(0,c.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,c.jsx)(i.t,{htmlFor:_,children:`Email`}),(0,c.jsx)(r.t,{id:_,type:`email`,autoComplete:`email`,placeholder:`you@example.com`,value:b,onChange:e=>x(e.target.value),"aria-invalid":!!A.email,disabled:p}),A.email&&(0,c.jsx)(`p`,{className:`text-destructive text-xs`,children:A.email})]}),(0,c.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,c.jsx)(i.t,{htmlFor:v,children:`Mật khẩu`}),(0,c.jsxs)(`div`,{className:`relative`,children:[(0,c.jsx)(r.t,{id:v,type:E?`text`:`password`,autoComplete:`new-password`,placeholder:`••••••••`,value:S,onChange:e=>C(e.target.value),"aria-invalid":!!A.password,disabled:p,className:`pr-10`}),(0,c.jsx)(`button`,{type:`button`,className:`absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground`,onMouseDown:e=>{e.preventDefault(),D(e=>!e)},"aria-label":E?`Ẩn mật khẩu`:`Hiện mật khẩu`,children:E?(0,c.jsx)(o.EyeOff,{size:16}):(0,c.jsx)(o.Eye,{size:16})})]}),A.password?(0,c.jsx)(`p`,{className:`text-destructive text-xs`,children:A.password}):(0,c.jsx)(`p`,{className:`text-muted-foreground text-xs`,children:`Tối thiểu 8 ký tự, bao gồm chữ hoa, chữ thường, số và ký tự đặc biệt.`})]}),(0,c.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,c.jsx)(i.t,{htmlFor:y,children:`Xác nhận mật khẩu`}),(0,c.jsxs)(`div`,{className:`relative`,children:[(0,c.jsx)(r.t,{id:y,type:O?`text`:`password`,autoComplete:`new-password`,placeholder:`••••••••`,value:w,onChange:e=>T(e.target.value),"aria-invalid":!!A.confirmPassword,disabled:p,className:`pr-10`}),(0,c.jsx)(`button`,{type:`button`,className:`absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground`,onMouseDown:e=>{e.preventDefault(),k(e=>!e)},"aria-label":O?`Ẩn mật khẩu`:`Hiện mật khẩu`,children:O?(0,c.jsx)(o.EyeOff,{size:16}):(0,c.jsx)(o.Eye,{size:16})})]}),A.confirmPassword&&(0,c.jsx)(`p`,{className:`text-destructive text-xs`,children:A.confirmPassword})]}),(0,c.jsx)(t.t,{type:`submit`,isLoading:p,className:`w-full`,children:`Đăng ký`})]}),f&&(0,c.jsxs)(`div`,{className:`flex justify-center gap-1 text-muted-foreground text-sm`,children:[(0,c.jsx)(`span`,{children:`Đã có tài khoản?`}),(0,c.jsx)(t.t,{variant:`link`,size:`sm`,className:`h-auto p-0`,onClick:f,children:`Đăng nhập`})]})]})})};exports.RegisterPage=d;
|
|
2
|
+
//# sourceMappingURL=RegisterPage.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegisterPage.cjs","names":["z","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Alert","AlertDescription","Label","Input","EyeOff","Eye","Button"],"sources":["../../packages/components/pages/RegisterPage.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useState } from 'react';\n\nimport { Eye, EyeOff } from 'lucide-react';\nimport { z } from 'zod';\n\nimport { Alert, AlertDescription } from '../ui/alert';\nimport { Button } from '../ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/dialog';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\n\nexport interface RegisterPageProps {\n /** Controls whether the dialog is open */\n open: boolean;\n /** Called when the dialog open state changes */\n onOpenChange: (open: boolean) => void;\n /** Called when the user submits registration credentials */\n onRegister: (email: string, password: string) => Promise<void> | void;\n /** Called when the \"Đăng nhập\" link is clicked */\n onLogin?: () => void;\n /** Disables the form and shows a spinner on the submit button */\n isLoading?: boolean;\n /** Server-side error message rendered in a destructive Alert */\n errorMessage?: string;\n /** Dialog heading. Default: \"Đăng ký\" */\n title?: string;\n /** Dialog subheading. Default: \"Tạo tài khoản mới để bắt đầu\" */\n subtitle?: string;\n}\n\nconst registerSchema = z\n .object({\n email: z.string().min(1, 'Vui lòng nhập email').email('Email không hợp lệ'),\n password: z\n .string()\n .min(8, 'Mật khẩu phải có ít nhất 8 ký tự')\n .max(50, 'Mật khẩu không được vượt quá 50 ký tự')\n .regex(/[A-Z]/, 'Phải có ít nhất một chữ hoa')\n .regex(/[a-z]/, 'Phải có ít nhất một chữ thường')\n .regex(/[0-9]/, 'Phải có ít nhất một chữ số')\n .regex(/[^A-Za-z0-9]/, 'Phải có ít nhất một ký tự đặc biệt'),\n confirmPassword: z.string().min(1, 'Vui lòng xác nhận mật khẩu'),\n })\n .refine(data => data.password === data.confirmPassword, {\n message: 'Mật khẩu xác nhận không khớp',\n path: ['confirmPassword'],\n });\n\n/**\n * Modal registration dialog for the client authentication flow.\n *\n * @example\n * ```tsx\n * import { RegisterPage } from '@customafk/lunas-ui/pages/RegisterPage';\n *\n * <RegisterPage\n * open={open}\n * onOpenChange={setOpen}\n * onRegister={async (email, password) => {\n * await authService.register(email, password);\n * setOpen(false);\n * }}\n * onLogin={() => { setOpen(false); setLoginOpen(true); }}\n * />\n * ```\n */\nexport const RegisterPage = ({\n open,\n onOpenChange,\n onRegister,\n onLogin,\n isLoading = false,\n errorMessage,\n title = 'Đăng ký',\n subtitle = 'Tạo tài khoản mới để bắt đầu',\n}: RegisterPageProps) => {\n const emailId = useId();\n const passwordId = useId();\n const confirmPasswordId = useId();\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [confirmPassword, setConfirmPassword] = useState('');\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n const [fieldErrors, setFieldErrors] = useState<{\n email?: string;\n password?: string;\n confirmPassword?: string;\n }>({});\n\n const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n const result = registerSchema.safeParse({ email, password, confirmPassword });\n if (!result.success) {\n const errors = result.error.flatten().fieldErrors;\n setFieldErrors({\n email: errors.email?.[0],\n password: errors.password?.[0],\n confirmPassword: errors.confirmPassword?.[0],\n });\n return;\n }\n setFieldErrors({});\n await onRegister(email, password);\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{subtitle}</DialogDescription>\n </DialogHeader>\n\n <form onSubmit={handleSubmit} noValidate className=\"flex flex-col gap-4\">\n {errorMessage && (\n <Alert variant=\"destructive\">\n <AlertDescription>{errorMessage}</AlertDescription>\n </Alert>\n )}\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={emailId}>Email</Label>\n <Input\n id={emailId}\n type=\"email\"\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n value={email}\n onChange={e => setEmail(e.target.value)}\n aria-invalid={!!fieldErrors.email}\n disabled={isLoading}\n />\n {fieldErrors.email && <p className=\"text-destructive text-xs\">{fieldErrors.email}</p>}\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={passwordId}>Mật khẩu</Label>\n <div className=\"relative\">\n <Input\n id={passwordId}\n type={showPassword ? 'text' : 'password'}\n autoComplete=\"new-password\"\n placeholder=\"••••••••\"\n value={password}\n onChange={e => setPassword(e.target.value)}\n aria-invalid={!!fieldErrors.password}\n disabled={isLoading}\n className=\"pr-10\"\n />\n <button\n type=\"button\"\n className=\"absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground\"\n onMouseDown={e => {\n e.preventDefault();\n setShowPassword(v => !v);\n }}\n aria-label={showPassword ? 'Ẩn mật khẩu' : 'Hiện mật khẩu'}\n >\n {showPassword ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n {fieldErrors.password ? (\n <p className=\"text-destructive text-xs\">{fieldErrors.password}</p>\n ) : (\n <p className=\"text-muted-foreground text-xs\">Tối thiểu 8 ký tự, bao gồm chữ hoa, chữ thường, số và ký tự đặc biệt.</p>\n )}\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={confirmPasswordId}>Xác nhận mật khẩu</Label>\n <div className=\"relative\">\n <Input\n id={confirmPasswordId}\n type={showConfirmPassword ? 'text' : 'password'}\n autoComplete=\"new-password\"\n placeholder=\"••••••••\"\n value={confirmPassword}\n onChange={e => setConfirmPassword(e.target.value)}\n aria-invalid={!!fieldErrors.confirmPassword}\n disabled={isLoading}\n className=\"pr-10\"\n />\n <button\n type=\"button\"\n className=\"absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground\"\n onMouseDown={e => {\n e.preventDefault();\n setShowConfirmPassword(v => !v);\n }}\n aria-label={showConfirmPassword ? 'Ẩn mật khẩu' : 'Hiện mật khẩu'}\n >\n {showConfirmPassword ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n {fieldErrors.confirmPassword && <p className=\"text-destructive text-xs\">{fieldErrors.confirmPassword}</p>}\n </div>\n\n <Button type=\"submit\" isLoading={isLoading} className=\"w-full\">\n Đăng ký\n </Button>\n </form>\n\n {onLogin && (\n <div className=\"flex justify-center gap-1 text-muted-foreground text-sm\">\n <span>Đã có tài khoản?</span>\n <Button variant=\"link\" size=\"sm\" className=\"h-auto p-0\" onClick={onLogin}>\n Đăng nhập\n </Button>\n </div>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as react_jsx_runtime28 from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region packages/components/pages/RegisterPage.d.ts
|
|
4
|
+
interface RegisterPageProps {
|
|
5
|
+
/** Controls whether the dialog is open */
|
|
6
|
+
open: boolean;
|
|
7
|
+
/** Called when the dialog open state changes */
|
|
8
|
+
onOpenChange: (open: boolean) => void;
|
|
9
|
+
/** Called when the user submits registration credentials */
|
|
10
|
+
onRegister: (email: string, password: string) => Promise<void> | void;
|
|
11
|
+
/** Called when the "Đăng nhập" link is clicked */
|
|
12
|
+
onLogin?: () => void;
|
|
13
|
+
/** Disables the form and shows a spinner on the submit button */
|
|
14
|
+
isLoading?: boolean;
|
|
15
|
+
/** Server-side error message rendered in a destructive Alert */
|
|
16
|
+
errorMessage?: string;
|
|
17
|
+
/** Dialog heading. Default: "Đăng ký" */
|
|
18
|
+
title?: string;
|
|
19
|
+
/** Dialog subheading. Default: "Tạo tài khoản mới để bắt đầu" */
|
|
20
|
+
subtitle?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Modal registration dialog for the client authentication flow.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* import { RegisterPage } from '@customafk/lunas-ui/pages/RegisterPage';
|
|
28
|
+
*
|
|
29
|
+
* <RegisterPage
|
|
30
|
+
* open={open}
|
|
31
|
+
* onOpenChange={setOpen}
|
|
32
|
+
* onRegister={async (email, password) => {
|
|
33
|
+
* await authService.register(email, password);
|
|
34
|
+
* setOpen(false);
|
|
35
|
+
* }}
|
|
36
|
+
* onLogin={() => { setOpen(false); setLoginOpen(true); }}
|
|
37
|
+
* />
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
declare const RegisterPage: ({
|
|
41
|
+
open,
|
|
42
|
+
onOpenChange,
|
|
43
|
+
onRegister,
|
|
44
|
+
onLogin,
|
|
45
|
+
isLoading,
|
|
46
|
+
errorMessage,
|
|
47
|
+
title,
|
|
48
|
+
subtitle
|
|
49
|
+
}: RegisterPageProps) => react_jsx_runtime28.JSX.Element;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { RegisterPage, RegisterPageProps };
|
|
52
|
+
//# sourceMappingURL=RegisterPage.d.cts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as react_jsx_runtime251 from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region packages/components/pages/RegisterPage.d.ts
|
|
4
|
+
interface RegisterPageProps {
|
|
5
|
+
/** Controls whether the dialog is open */
|
|
6
|
+
open: boolean;
|
|
7
|
+
/** Called when the dialog open state changes */
|
|
8
|
+
onOpenChange: (open: boolean) => void;
|
|
9
|
+
/** Called when the user submits registration credentials */
|
|
10
|
+
onRegister: (email: string, password: string) => Promise<void> | void;
|
|
11
|
+
/** Called when the "Đăng nhập" link is clicked */
|
|
12
|
+
onLogin?: () => void;
|
|
13
|
+
/** Disables the form and shows a spinner on the submit button */
|
|
14
|
+
isLoading?: boolean;
|
|
15
|
+
/** Server-side error message rendered in a destructive Alert */
|
|
16
|
+
errorMessage?: string;
|
|
17
|
+
/** Dialog heading. Default: "Đăng ký" */
|
|
18
|
+
title?: string;
|
|
19
|
+
/** Dialog subheading. Default: "Tạo tài khoản mới để bắt đầu" */
|
|
20
|
+
subtitle?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Modal registration dialog for the client authentication flow.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* import { RegisterPage } from '@customafk/lunas-ui/pages/RegisterPage';
|
|
28
|
+
*
|
|
29
|
+
* <RegisterPage
|
|
30
|
+
* open={open}
|
|
31
|
+
* onOpenChange={setOpen}
|
|
32
|
+
* onRegister={async (email, password) => {
|
|
33
|
+
* await authService.register(email, password);
|
|
34
|
+
* setOpen(false);
|
|
35
|
+
* }}
|
|
36
|
+
* onLogin={() => { setOpen(false); setLoginOpen(true); }}
|
|
37
|
+
* />
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
declare const RegisterPage: ({
|
|
41
|
+
open,
|
|
42
|
+
onOpenChange,
|
|
43
|
+
onRegister,
|
|
44
|
+
onLogin,
|
|
45
|
+
isLoading,
|
|
46
|
+
errorMessage,
|
|
47
|
+
title,
|
|
48
|
+
subtitle
|
|
49
|
+
}: RegisterPageProps) => react_jsx_runtime251.JSX.Element;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { RegisterPage, RegisterPageProps };
|
|
52
|
+
//# sourceMappingURL=RegisterPage.d.mts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import"../button.variants-CwcJHcI5.mjs";import{t as e}from"../button-Bc8L9sFb.mjs";import"../heading-BnaNuvDS.mjs";import"../paragraph-CnHNC0rS.mjs";import"../close-BS6EeCrQ.mjs";import{i as t,l as n,o as r,r as i,t as a}from"../dialog-DG4vMCr5.mjs";import{t as o}from"../input-DLRypEj3.mjs";import{t as s}from"../label-BukQnBn7.mjs";import{n as c,t as l}from"../alert-C-Y4ZWNd.mjs";import{Eye as u,EyeOff as d}from"lucide-react";import{useId as f,useState as p}from"react";import{jsx as m,jsxs as h}from"react/jsx-runtime";import{z as g}from"zod";const _=g.object({email:g.string().min(1,`Vui lòng nhập email`).email(`Email không hợp lệ`),password:g.string().min(8,`Mật khẩu phải có ít nhất 8 ký tự`).max(50,`Mật khẩu không được vượt quá 50 ký tự`).regex(/[A-Z]/,`Phải có ít nhất một chữ hoa`).regex(/[a-z]/,`Phải có ít nhất một chữ thường`).regex(/[0-9]/,`Phải có ít nhất một chữ số`).regex(/[^A-Za-z0-9]/,`Phải có ít nhất một ký tự đặc biệt`),confirmPassword:g.string().min(1,`Vui lòng xác nhận mật khẩu`)}).refine(e=>e.password===e.confirmPassword,{message:`Mật khẩu xác nhận không khớp`,path:[`confirmPassword`]}),v=({open:g,onOpenChange:v,onRegister:y,onLogin:b,isLoading:x=!1,errorMessage:S,title:C=`Đăng ký`,subtitle:w=`Tạo tài khoản mới để bắt đầu`})=>{let T=f(),E=f(),D=f(),[O,k]=p(``),[A,j]=p(``),[M,N]=p(``),[P,F]=p(!1),[I,L]=p(!1),[R,z]=p({});return m(a,{open:g,onOpenChange:v,children:h(i,{className:`sm:max-w-sm`,children:[h(r,{children:[m(n,{children:C}),m(t,{children:w})]}),h(`form`,{onSubmit:async e=>{e.preventDefault();let t=_.safeParse({email:O,password:A,confirmPassword:M});if(!t.success){let e=t.error.flatten().fieldErrors;z({email:e.email?.[0],password:e.password?.[0],confirmPassword:e.confirmPassword?.[0]});return}z({}),await y(O,A)},noValidate:!0,className:`flex flex-col gap-4`,children:[S&&m(l,{variant:`destructive`,children:m(c,{children:S})}),h(`div`,{className:`flex flex-col gap-1.5`,children:[m(s,{htmlFor:T,children:`Email`}),m(o,{id:T,type:`email`,autoComplete:`email`,placeholder:`you@example.com`,value:O,onChange:e=>k(e.target.value),"aria-invalid":!!R.email,disabled:x}),R.email&&m(`p`,{className:`text-destructive text-xs`,children:R.email})]}),h(`div`,{className:`flex flex-col gap-1.5`,children:[m(s,{htmlFor:E,children:`Mật khẩu`}),h(`div`,{className:`relative`,children:[m(o,{id:E,type:P?`text`:`password`,autoComplete:`new-password`,placeholder:`••••••••`,value:A,onChange:e=>j(e.target.value),"aria-invalid":!!R.password,disabled:x,className:`pr-10`}),m(`button`,{type:`button`,className:`absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground`,onMouseDown:e=>{e.preventDefault(),F(e=>!e)},"aria-label":P?`Ẩn mật khẩu`:`Hiện mật khẩu`,children:m(P?d:u,{size:16})})]}),R.password?m(`p`,{className:`text-destructive text-xs`,children:R.password}):m(`p`,{className:`text-muted-foreground text-xs`,children:`Tối thiểu 8 ký tự, bao gồm chữ hoa, chữ thường, số và ký tự đặc biệt.`})]}),h(`div`,{className:`flex flex-col gap-1.5`,children:[m(s,{htmlFor:D,children:`Xác nhận mật khẩu`}),h(`div`,{className:`relative`,children:[m(o,{id:D,type:I?`text`:`password`,autoComplete:`new-password`,placeholder:`••••••••`,value:M,onChange:e=>N(e.target.value),"aria-invalid":!!R.confirmPassword,disabled:x,className:`pr-10`}),m(`button`,{type:`button`,className:`absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground`,onMouseDown:e=>{e.preventDefault(),L(e=>!e)},"aria-label":I?`Ẩn mật khẩu`:`Hiện mật khẩu`,children:m(I?d:u,{size:16})})]}),R.confirmPassword&&m(`p`,{className:`text-destructive text-xs`,children:R.confirmPassword})]}),m(e,{type:`submit`,isLoading:x,className:`w-full`,children:`Đăng ký`})]}),b&&h(`div`,{className:`flex justify-center gap-1 text-muted-foreground text-sm`,children:[m(`span`,{children:`Đã có tài khoản?`}),m(e,{variant:`link`,size:`sm`,className:`h-auto p-0`,onClick:b,children:`Đăng nhập`})]})]})})};export{v as RegisterPage};
|
|
2
|
+
//# sourceMappingURL=RegisterPage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegisterPage.mjs","names":[],"sources":["../../packages/components/pages/RegisterPage.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useState } from 'react';\n\nimport { Eye, EyeOff } from 'lucide-react';\nimport { z } from 'zod';\n\nimport { Alert, AlertDescription } from '../ui/alert';\nimport { Button } from '../ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/dialog';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\n\nexport interface RegisterPageProps {\n /** Controls whether the dialog is open */\n open: boolean;\n /** Called when the dialog open state changes */\n onOpenChange: (open: boolean) => void;\n /** Called when the user submits registration credentials */\n onRegister: (email: string, password: string) => Promise<void> | void;\n /** Called when the \"Đăng nhập\" link is clicked */\n onLogin?: () => void;\n /** Disables the form and shows a spinner on the submit button */\n isLoading?: boolean;\n /** Server-side error message rendered in a destructive Alert */\n errorMessage?: string;\n /** Dialog heading. Default: \"Đăng ký\" */\n title?: string;\n /** Dialog subheading. Default: \"Tạo tài khoản mới để bắt đầu\" */\n subtitle?: string;\n}\n\nconst registerSchema = z\n .object({\n email: z.string().min(1, 'Vui lòng nhập email').email('Email không hợp lệ'),\n password: z\n .string()\n .min(8, 'Mật khẩu phải có ít nhất 8 ký tự')\n .max(50, 'Mật khẩu không được vượt quá 50 ký tự')\n .regex(/[A-Z]/, 'Phải có ít nhất một chữ hoa')\n .regex(/[a-z]/, 'Phải có ít nhất một chữ thường')\n .regex(/[0-9]/, 'Phải có ít nhất một chữ số')\n .regex(/[^A-Za-z0-9]/, 'Phải có ít nhất một ký tự đặc biệt'),\n confirmPassword: z.string().min(1, 'Vui lòng xác nhận mật khẩu'),\n })\n .refine(data => data.password === data.confirmPassword, {\n message: 'Mật khẩu xác nhận không khớp',\n path: ['confirmPassword'],\n });\n\n/**\n * Modal registration dialog for the client authentication flow.\n *\n * @example\n * ```tsx\n * import { RegisterPage } from '@customafk/lunas-ui/pages/RegisterPage';\n *\n * <RegisterPage\n * open={open}\n * onOpenChange={setOpen}\n * onRegister={async (email, password) => {\n * await authService.register(email, password);\n * setOpen(false);\n * }}\n * onLogin={() => { setOpen(false); setLoginOpen(true); }}\n * />\n * ```\n */\nexport const RegisterPage = ({\n open,\n onOpenChange,\n onRegister,\n onLogin,\n isLoading = false,\n errorMessage,\n title = 'Đăng ký',\n subtitle = 'Tạo tài khoản mới để bắt đầu',\n}: RegisterPageProps) => {\n const emailId = useId();\n const passwordId = useId();\n const confirmPasswordId = useId();\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [confirmPassword, setConfirmPassword] = useState('');\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n const [fieldErrors, setFieldErrors] = useState<{\n email?: string;\n password?: string;\n confirmPassword?: string;\n }>({});\n\n const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n const result = registerSchema.safeParse({ email, password, confirmPassword });\n if (!result.success) {\n const errors = result.error.flatten().fieldErrors;\n setFieldErrors({\n email: errors.email?.[0],\n password: errors.password?.[0],\n confirmPassword: errors.confirmPassword?.[0],\n });\n return;\n }\n setFieldErrors({});\n await onRegister(email, password);\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{subtitle}</DialogDescription>\n </DialogHeader>\n\n <form onSubmit={handleSubmit} noValidate className=\"flex flex-col gap-4\">\n {errorMessage && (\n <Alert variant=\"destructive\">\n <AlertDescription>{errorMessage}</AlertDescription>\n </Alert>\n )}\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={emailId}>Email</Label>\n <Input\n id={emailId}\n type=\"email\"\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n value={email}\n onChange={e => setEmail(e.target.value)}\n aria-invalid={!!fieldErrors.email}\n disabled={isLoading}\n />\n {fieldErrors.email && <p className=\"text-destructive text-xs\">{fieldErrors.email}</p>}\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={passwordId}>Mật khẩu</Label>\n <div className=\"relative\">\n <Input\n id={passwordId}\n type={showPassword ? 'text' : 'password'}\n autoComplete=\"new-password\"\n placeholder=\"••••••••\"\n value={password}\n onChange={e => setPassword(e.target.value)}\n aria-invalid={!!fieldErrors.password}\n disabled={isLoading}\n className=\"pr-10\"\n />\n <button\n type=\"button\"\n className=\"absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground\"\n onMouseDown={e => {\n e.preventDefault();\n setShowPassword(v => !v);\n }}\n aria-label={showPassword ? 'Ẩn mật khẩu' : 'Hiện mật khẩu'}\n >\n {showPassword ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n {fieldErrors.password ? (\n <p className=\"text-destructive text-xs\">{fieldErrors.password}</p>\n ) : (\n <p className=\"text-muted-foreground text-xs\">Tối thiểu 8 ký tự, bao gồm chữ hoa, chữ thường, số và ký tự đặc biệt.</p>\n )}\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor={confirmPasswordId}>Xác nhận mật khẩu</Label>\n <div className=\"relative\">\n <Input\n id={confirmPasswordId}\n type={showConfirmPassword ? 'text' : 'password'}\n autoComplete=\"new-password\"\n placeholder=\"••••••••\"\n value={confirmPassword}\n onChange={e => setConfirmPassword(e.target.value)}\n aria-invalid={!!fieldErrors.confirmPassword}\n disabled={isLoading}\n className=\"pr-10\"\n />\n <button\n type=\"button\"\n className=\"absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground hover:text-foreground\"\n onMouseDown={e => {\n e.preventDefault();\n setShowConfirmPassword(v => !v);\n }}\n aria-label={showConfirmPassword ? 'Ẩn mật khẩu' : 'Hiện mật khẩu'}\n >\n {showConfirmPassword ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n {fieldErrors.confirmPassword && <p className=\"text-destructive text-xs\">{fieldErrors.confirmPassword}</p>}\n </div>\n\n <Button type=\"submit\" isLoading={isLoading} className=\"w-full\">\n Đăng ký\n </Button>\n </form>\n\n {onLogin && (\n <div className=\"flex justify-center gap-1 text-muted-foreground text-sm\">\n <span>Đã có tài khoản?</span>\n <Button variant=\"link\" size=\"sm\" className=\"h-auto p-0\" onClick={onLogin}>\n Đăng nhập\n </Button>\n </div>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require(`../chunk-Bmb41Sf3.cjs`);require(`../button.variants-tnhb123u.cjs`);const t=require(`../button-CwDT3m4m.cjs`);require(`../heading-AKz5ewy-.cjs`),require(`../paragraph-DN85Huc4.cjs`),require(`../close-DXk_H3Gt.cjs`);const n=require(`../dialog-o_68LQXd.cjs`),r=require(`../alert-B7TDxb35.cjs`),i=require(`../ui/input-otp.cjs`);let a=require(`react`),o=require(`react/jsx-runtime`);const s=({open:e,onOpenChange:s,email:c,onVerify:l,onResend:u,onBack:d,isLoading:f=!1,errorMessage:p,title:m=`Xác thực email`,subtitle:h,resendCooldownSeconds:g=60})=>{let[_,v]=(0,a.useState)(``),[y,b]=(0,a.useState)(g),x=(0,a.useRef)(null),S=(0,a.useCallback)(e=>{x.current&&clearInterval(x.current),b(e),x.current=setInterval(()=>{b(e=>e<=1?(x.current&&clearInterval(x.current),0):e-1)},1e3)},[]);(0,a.useEffect)(()=>(e&&g>0&&S(g),()=>{x.current&&clearInterval(x.current)}),[e,g,S]);let C=(0,a.useCallback)(async()=>{S(g),await u(c)},[c,u,g,S]),w=(0,a.useCallback)(async()=>{_.length<6||await l(c,_)},[c,_,l]);return(0,o.jsx)(n.t,{open:e,onOpenChange:s,children:(0,o.jsxs)(n.r,{className:`sm:max-w-sm`,children:[(0,o.jsxs)(n.o,{children:[(0,o.jsx)(n.l,{children:m}),(0,o.jsx)(n.i,{children:h??(0,o.jsxs)(o.Fragment,{children:[`Nhập mã OTP đã được gửi tới `,(0,o.jsx)(`span`,{className:`font-medium text-foreground`,children:c}),`. Mã có hiệu lực trong 10 phút.`]})})]}),(0,o.jsxs)(`div`,{className:`flex flex-col items-center gap-4`,children:[p&&(0,o.jsx)(r.t,{variant:`destructive`,className:`w-full`,children:(0,o.jsx)(r.n,{children:p})}),(0,o.jsxs)(i.InputOTP,{maxLength:6,value:_,onChange:v,onComplete:w,disabled:f,children:[(0,o.jsxs)(i.InputOTPGroup,{children:[(0,o.jsx)(i.InputOTPSlot,{index:0}),(0,o.jsx)(i.InputOTPSlot,{index:1}),(0,o.jsx)(i.InputOTPSlot,{index:2})]}),(0,o.jsx)(i.InputOTPSeparator,{}),(0,o.jsxs)(i.InputOTPGroup,{children:[(0,o.jsx)(i.InputOTPSlot,{index:3}),(0,o.jsx)(i.InputOTPSlot,{index:4}),(0,o.jsx)(i.InputOTPSlot,{index:5})]})]}),(0,o.jsx)(t.t,{type:`button`,isLoading:f,disabled:_.length<6,className:`w-full`,onClick:w,children:`Xác thực`}),(0,o.jsxs)(`div`,{className:`flex items-center gap-1 text-muted-foreground text-sm`,children:[(0,o.jsx)(`span`,{children:`Chưa nhận được mã?`}),(0,o.jsx)(t.t,{variant:`link`,size:`sm`,className:`h-auto p-0`,disabled:y>0||f,onClick:C,children:y>0?`Gửi lại (${y}s)`:`Gửi lại`})]}),d&&(0,o.jsx)(t.t,{variant:`ghost`,size:`sm`,className:`w-full`,onClick:d,children:`Quay lại`})]})]})})};exports.VerifyEmailPage=s;
|
|
2
|
+
//# sourceMappingURL=VerifyEmailPage.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VerifyEmailPage.cjs","names":["Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Alert","AlertDescription","InputOTP","InputOTPGroup","InputOTPSlot","InputOTPSeparator","Button"],"sources":["../../packages/components/pages/VerifyEmailPage.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Alert, AlertDescription } from '../ui/alert';\nimport { Button } from '../ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/dialog';\nimport { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from '../ui/input-otp';\n\nexport interface VerifyEmailPageProps {\n /** Controls whether the dialog is open */\n open: boolean;\n /** Called when the dialog open state changes */\n onOpenChange: (open: boolean) => void;\n /** The email address the OTP was dispatched to — displayed as context and passed to callbacks */\n email: string;\n /** Called when the user submits the OTP code */\n onVerify: (email: string, otp: string) => Promise<void> | void;\n /** Called when the user requests a new OTP; triggers a fresh cooldown */\n onResend: (email: string) => Promise<void> | void;\n /** Called when the back link is clicked */\n onBack?: () => void;\n /** Disables the form and shows a spinner on the submit button */\n isLoading?: boolean;\n /** Server-side error message rendered in a destructive Alert */\n errorMessage?: string;\n /** Dialog heading. Default: \"Xác thực email\" */\n title?: string;\n /** Dialog subheading. Default: built from the email prop */\n subtitle?: string;\n /** Seconds before the resend button becomes available. Default: 60 */\n resendCooldownSeconds?: number;\n}\n\n/**\n * Modal email OTP verification dialog for the client authentication flow.\n *\n * @example\n * ```tsx\n * import { VerifyEmailPage } from '@customafk/lunas-ui/pages/VerifyEmailPage';\n *\n * <VerifyEmailPage\n * open={open}\n * onOpenChange={setOpen}\n * email=\"user@example.com\"\n * onVerify={async (email, otp) => {\n * await authService.verifyEmail(email, otp);\n * setOpen(false);\n * }}\n * onResend={async (email) => {\n * await authService.resendVerification(email);\n * }}\n * />\n * ```\n */\nexport const VerifyEmailPage = ({\n open,\n onOpenChange,\n email,\n onVerify,\n onResend,\n onBack,\n isLoading = false,\n errorMessage,\n title = 'Xác thực email',\n subtitle,\n resendCooldownSeconds = 60,\n}: VerifyEmailPageProps) => {\n const [otp, setOtp] = useState('');\n const [countdown, setCountdown] = useState(resendCooldownSeconds);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const startCountdown = useCallback((seconds: number) => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n setCountdown(seconds);\n intervalRef.current = setInterval(() => {\n setCountdown(prev => {\n if (prev <= 1) {\n if (intervalRef.current) clearInterval(intervalRef.current);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n }, []);\n\n useEffect(() => {\n if (open && resendCooldownSeconds > 0) startCountdown(resendCooldownSeconds);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [open, resendCooldownSeconds, startCountdown]);\n\n const handleResend = useCallback(async () => {\n startCountdown(resendCooldownSeconds);\n await onResend(email);\n }, [email, onResend, resendCooldownSeconds, startCountdown]);\n\n const handleVerify = useCallback(async () => {\n if (otp.length < 6) return;\n await onVerify(email, otp);\n }, [email, otp, onVerify]);\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>\n {subtitle ?? (\n <>\n Nhập mã OTP đã được gửi tới <span className=\"font-medium text-foreground\">{email}</span>. Mã có hiệu lực trong 10 phút.\n </>\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex flex-col items-center gap-4\">\n {errorMessage && (\n <Alert variant=\"destructive\" className=\"w-full\">\n <AlertDescription>{errorMessage}</AlertDescription>\n </Alert>\n )}\n\n <InputOTP maxLength={6} value={otp} onChange={setOtp} onComplete={handleVerify} disabled={isLoading}>\n <InputOTPGroup>\n <InputOTPSlot index={0} />\n <InputOTPSlot index={1} />\n <InputOTPSlot index={2} />\n </InputOTPGroup>\n <InputOTPSeparator />\n <InputOTPGroup>\n <InputOTPSlot index={3} />\n <InputOTPSlot index={4} />\n <InputOTPSlot index={5} />\n </InputOTPGroup>\n </InputOTP>\n\n <Button type=\"button\" isLoading={isLoading} disabled={otp.length < 6} className=\"w-full\" onClick={handleVerify}>\n Xác thực\n </Button>\n\n <div className=\"flex items-center gap-1 text-muted-foreground text-sm\">\n <span>Chưa nhận được mã?</span>\n <Button variant=\"link\" size=\"sm\" className=\"h-auto p-0\" disabled={countdown > 0 || isLoading} onClick={handleResend}>\n {countdown > 0 ? `Gửi lại (${countdown}s)` : 'Gửi lại'}\n </Button>\n </div>\n\n {onBack && (\n <Button variant=\"ghost\" size=\"sm\" className=\"w-full\" onClick={onBack}>\n Quay lại\n </Button>\n )}\n </div>\n </DialogContent>\n </Dialog>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as react_jsx_runtime32 from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region packages/components/pages/VerifyEmailPage.d.ts
|
|
4
|
+
interface VerifyEmailPageProps {
|
|
5
|
+
/** Controls whether the dialog is open */
|
|
6
|
+
open: boolean;
|
|
7
|
+
/** Called when the dialog open state changes */
|
|
8
|
+
onOpenChange: (open: boolean) => void;
|
|
9
|
+
/** The email address the OTP was dispatched to — displayed as context and passed to callbacks */
|
|
10
|
+
email: string;
|
|
11
|
+
/** Called when the user submits the OTP code */
|
|
12
|
+
onVerify: (email: string, otp: string) => Promise<void> | void;
|
|
13
|
+
/** Called when the user requests a new OTP; triggers a fresh cooldown */
|
|
14
|
+
onResend: (email: string) => Promise<void> | void;
|
|
15
|
+
/** Called when the back link is clicked */
|
|
16
|
+
onBack?: () => void;
|
|
17
|
+
/** Disables the form and shows a spinner on the submit button */
|
|
18
|
+
isLoading?: boolean;
|
|
19
|
+
/** Server-side error message rendered in a destructive Alert */
|
|
20
|
+
errorMessage?: string;
|
|
21
|
+
/** Dialog heading. Default: "Xác thực email" */
|
|
22
|
+
title?: string;
|
|
23
|
+
/** Dialog subheading. Default: built from the email prop */
|
|
24
|
+
subtitle?: string;
|
|
25
|
+
/** Seconds before the resend button becomes available. Default: 60 */
|
|
26
|
+
resendCooldownSeconds?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Modal email OTP verification dialog for the client authentication flow.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* import { VerifyEmailPage } from '@customafk/lunas-ui/pages/VerifyEmailPage';
|
|
34
|
+
*
|
|
35
|
+
* <VerifyEmailPage
|
|
36
|
+
* open={open}
|
|
37
|
+
* onOpenChange={setOpen}
|
|
38
|
+
* email="user@example.com"
|
|
39
|
+
* onVerify={async (email, otp) => {
|
|
40
|
+
* await authService.verifyEmail(email, otp);
|
|
41
|
+
* setOpen(false);
|
|
42
|
+
* }}
|
|
43
|
+
* onResend={async (email) => {
|
|
44
|
+
* await authService.resendVerification(email);
|
|
45
|
+
* }}
|
|
46
|
+
* />
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare const VerifyEmailPage: ({
|
|
50
|
+
open,
|
|
51
|
+
onOpenChange,
|
|
52
|
+
email,
|
|
53
|
+
onVerify,
|
|
54
|
+
onResend,
|
|
55
|
+
onBack,
|
|
56
|
+
isLoading,
|
|
57
|
+
errorMessage,
|
|
58
|
+
title,
|
|
59
|
+
subtitle,
|
|
60
|
+
resendCooldownSeconds
|
|
61
|
+
}: VerifyEmailPageProps) => react_jsx_runtime32.JSX.Element;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { VerifyEmailPage, VerifyEmailPageProps };
|
|
64
|
+
//# sourceMappingURL=VerifyEmailPage.d.cts.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as react_jsx_runtime252 from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region packages/components/pages/VerifyEmailPage.d.ts
|
|
4
|
+
interface VerifyEmailPageProps {
|
|
5
|
+
/** Controls whether the dialog is open */
|
|
6
|
+
open: boolean;
|
|
7
|
+
/** Called when the dialog open state changes */
|
|
8
|
+
onOpenChange: (open: boolean) => void;
|
|
9
|
+
/** The email address the OTP was dispatched to — displayed as context and passed to callbacks */
|
|
10
|
+
email: string;
|
|
11
|
+
/** Called when the user submits the OTP code */
|
|
12
|
+
onVerify: (email: string, otp: string) => Promise<void> | void;
|
|
13
|
+
/** Called when the user requests a new OTP; triggers a fresh cooldown */
|
|
14
|
+
onResend: (email: string) => Promise<void> | void;
|
|
15
|
+
/** Called when the back link is clicked */
|
|
16
|
+
onBack?: () => void;
|
|
17
|
+
/** Disables the form and shows a spinner on the submit button */
|
|
18
|
+
isLoading?: boolean;
|
|
19
|
+
/** Server-side error message rendered in a destructive Alert */
|
|
20
|
+
errorMessage?: string;
|
|
21
|
+
/** Dialog heading. Default: "Xác thực email" */
|
|
22
|
+
title?: string;
|
|
23
|
+
/** Dialog subheading. Default: built from the email prop */
|
|
24
|
+
subtitle?: string;
|
|
25
|
+
/** Seconds before the resend button becomes available. Default: 60 */
|
|
26
|
+
resendCooldownSeconds?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Modal email OTP verification dialog for the client authentication flow.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* import { VerifyEmailPage } from '@customafk/lunas-ui/pages/VerifyEmailPage';
|
|
34
|
+
*
|
|
35
|
+
* <VerifyEmailPage
|
|
36
|
+
* open={open}
|
|
37
|
+
* onOpenChange={setOpen}
|
|
38
|
+
* email="user@example.com"
|
|
39
|
+
* onVerify={async (email, otp) => {
|
|
40
|
+
* await authService.verifyEmail(email, otp);
|
|
41
|
+
* setOpen(false);
|
|
42
|
+
* }}
|
|
43
|
+
* onResend={async (email) => {
|
|
44
|
+
* await authService.resendVerification(email);
|
|
45
|
+
* }}
|
|
46
|
+
* />
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare const VerifyEmailPage: ({
|
|
50
|
+
open,
|
|
51
|
+
onOpenChange,
|
|
52
|
+
email,
|
|
53
|
+
onVerify,
|
|
54
|
+
onResend,
|
|
55
|
+
onBack,
|
|
56
|
+
isLoading,
|
|
57
|
+
errorMessage,
|
|
58
|
+
title,
|
|
59
|
+
subtitle,
|
|
60
|
+
resendCooldownSeconds
|
|
61
|
+
}: VerifyEmailPageProps) => react_jsx_runtime252.JSX.Element;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { VerifyEmailPage, VerifyEmailPageProps };
|
|
64
|
+
//# sourceMappingURL=VerifyEmailPage.d.mts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import"../button.variants-CwcJHcI5.mjs";import{t as e}from"../button-Bc8L9sFb.mjs";import"../heading-BnaNuvDS.mjs";import"../paragraph-CnHNC0rS.mjs";import"../close-BS6EeCrQ.mjs";import{i as t,l as n,o as r,r as i,t as a}from"../dialog-DG4vMCr5.mjs";import{n as o,t as s}from"../alert-C-Y4ZWNd.mjs";import{InputOTP as c,InputOTPGroup as l,InputOTPSeparator as u,InputOTPSlot as d}from"../ui/input-otp.mjs";import{useCallback as f,useEffect as p,useRef as m,useState as h}from"react";import{Fragment as g,jsx as _,jsxs as v}from"react/jsx-runtime";const y=({open:y,onOpenChange:b,email:x,onVerify:S,onResend:C,onBack:w,isLoading:T=!1,errorMessage:E,title:D=`Xác thực email`,subtitle:O,resendCooldownSeconds:k=60})=>{let[A,j]=h(``),[M,N]=h(k),P=m(null),F=f(e=>{P.current&&clearInterval(P.current),N(e),P.current=setInterval(()=>{N(e=>e<=1?(P.current&&clearInterval(P.current),0):e-1)},1e3)},[]);p(()=>(y&&k>0&&F(k),()=>{P.current&&clearInterval(P.current)}),[y,k,F]);let I=f(async()=>{F(k),await C(x)},[x,C,k,F]),L=f(async()=>{A.length<6||await S(x,A)},[x,A,S]);return _(a,{open:y,onOpenChange:b,children:v(i,{className:`sm:max-w-sm`,children:[v(r,{children:[_(n,{children:D}),_(t,{children:O??v(g,{children:[`Nhập mã OTP đã được gửi tới `,_(`span`,{className:`font-medium text-foreground`,children:x}),`. Mã có hiệu lực trong 10 phút.`]})})]}),v(`div`,{className:`flex flex-col items-center gap-4`,children:[E&&_(s,{variant:`destructive`,className:`w-full`,children:_(o,{children:E})}),v(c,{maxLength:6,value:A,onChange:j,onComplete:L,disabled:T,children:[v(l,{children:[_(d,{index:0}),_(d,{index:1}),_(d,{index:2})]}),_(u,{}),v(l,{children:[_(d,{index:3}),_(d,{index:4}),_(d,{index:5})]})]}),_(e,{type:`button`,isLoading:T,disabled:A.length<6,className:`w-full`,onClick:L,children:`Xác thực`}),v(`div`,{className:`flex items-center gap-1 text-muted-foreground text-sm`,children:[_(`span`,{children:`Chưa nhận được mã?`}),_(e,{variant:`link`,size:`sm`,className:`h-auto p-0`,disabled:M>0||T,onClick:I,children:M>0?`Gửi lại (${M}s)`:`Gửi lại`})]}),w&&_(e,{variant:`ghost`,size:`sm`,className:`w-full`,onClick:w,children:`Quay lại`})]})]})})};export{y as VerifyEmailPage};
|
|
2
|
+
//# sourceMappingURL=VerifyEmailPage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VerifyEmailPage.mjs","names":[],"sources":["../../packages/components/pages/VerifyEmailPage.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Alert, AlertDescription } from '../ui/alert';\nimport { Button } from '../ui/button';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/dialog';\nimport { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from '../ui/input-otp';\n\nexport interface VerifyEmailPageProps {\n /** Controls whether the dialog is open */\n open: boolean;\n /** Called when the dialog open state changes */\n onOpenChange: (open: boolean) => void;\n /** The email address the OTP was dispatched to — displayed as context and passed to callbacks */\n email: string;\n /** Called when the user submits the OTP code */\n onVerify: (email: string, otp: string) => Promise<void> | void;\n /** Called when the user requests a new OTP; triggers a fresh cooldown */\n onResend: (email: string) => Promise<void> | void;\n /** Called when the back link is clicked */\n onBack?: () => void;\n /** Disables the form and shows a spinner on the submit button */\n isLoading?: boolean;\n /** Server-side error message rendered in a destructive Alert */\n errorMessage?: string;\n /** Dialog heading. Default: \"Xác thực email\" */\n title?: string;\n /** Dialog subheading. Default: built from the email prop */\n subtitle?: string;\n /** Seconds before the resend button becomes available. Default: 60 */\n resendCooldownSeconds?: number;\n}\n\n/**\n * Modal email OTP verification dialog for the client authentication flow.\n *\n * @example\n * ```tsx\n * import { VerifyEmailPage } from '@customafk/lunas-ui/pages/VerifyEmailPage';\n *\n * <VerifyEmailPage\n * open={open}\n * onOpenChange={setOpen}\n * email=\"user@example.com\"\n * onVerify={async (email, otp) => {\n * await authService.verifyEmail(email, otp);\n * setOpen(false);\n * }}\n * onResend={async (email) => {\n * await authService.resendVerification(email);\n * }}\n * />\n * ```\n */\nexport const VerifyEmailPage = ({\n open,\n onOpenChange,\n email,\n onVerify,\n onResend,\n onBack,\n isLoading = false,\n errorMessage,\n title = 'Xác thực email',\n subtitle,\n resendCooldownSeconds = 60,\n}: VerifyEmailPageProps) => {\n const [otp, setOtp] = useState('');\n const [countdown, setCountdown] = useState(resendCooldownSeconds);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const startCountdown = useCallback((seconds: number) => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n setCountdown(seconds);\n intervalRef.current = setInterval(() => {\n setCountdown(prev => {\n if (prev <= 1) {\n if (intervalRef.current) clearInterval(intervalRef.current);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n }, []);\n\n useEffect(() => {\n if (open && resendCooldownSeconds > 0) startCountdown(resendCooldownSeconds);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [open, resendCooldownSeconds, startCountdown]);\n\n const handleResend = useCallback(async () => {\n startCountdown(resendCooldownSeconds);\n await onResend(email);\n }, [email, onResend, resendCooldownSeconds, startCountdown]);\n\n const handleVerify = useCallback(async () => {\n if (otp.length < 6) return;\n await onVerify(email, otp);\n }, [email, otp, onVerify]);\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>\n {subtitle ?? (\n <>\n Nhập mã OTP đã được gửi tới <span className=\"font-medium text-foreground\">{email}</span>. Mã có hiệu lực trong 10 phút.\n </>\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex flex-col items-center gap-4\">\n {errorMessage && (\n <Alert variant=\"destructive\" className=\"w-full\">\n <AlertDescription>{errorMessage}</AlertDescription>\n </Alert>\n )}\n\n <InputOTP maxLength={6} value={otp} onChange={setOtp} onComplete={handleVerify} disabled={isLoading}>\n <InputOTPGroup>\n <InputOTPSlot index={0} />\n <InputOTPSlot index={1} />\n <InputOTPSlot index={2} />\n </InputOTPGroup>\n <InputOTPSeparator />\n <InputOTPGroup>\n <InputOTPSlot index={3} />\n <InputOTPSlot index={4} />\n <InputOTPSlot index={5} />\n </InputOTPGroup>\n </InputOTP>\n\n <Button type=\"button\" isLoading={isLoading} disabled={otp.length < 6} className=\"w-full\" onClick={handleVerify}>\n Xác thực\n </Button>\n\n <div className=\"flex items-center gap-1 text-muted-foreground text-sm\">\n <span>Chưa nhận được mã?</span>\n <Button variant=\"link\" size=\"sm\" className=\"h-auto p-0\" disabled={countdown > 0 || isLoading} onClick={handleResend}>\n {countdown > 0 ? `Gửi lại (${countdown}s)` : 'Gửi lại'}\n </Button>\n </div>\n\n {onBack && (\n <Button variant=\"ghost\" size=\"sm\" className=\"w-full\" onClick={onBack}>\n Quay lại\n </Button>\n )}\n </div>\n </DialogContent>\n </Dialog>\n );\n};\n"],"mappings":"gjBAuDA,MAAa,GAAmB,CAC9B,OACA,eACA,QACA,WACA,WACA,SACA,YAAY,GACZ,eACA,QAAQ,iBACR,WACA,wBAAwB,MACE,CAC1B,GAAM,CAAC,EAAK,GAAU,EAAS,GAAG,CAC5B,CAAC,EAAW,GAAgB,EAAS,EAAsB,CAC3D,EAAc,EAA8C,KAAK,CAEjE,EAAiB,EAAa,GAAoB,CAClD,EAAY,SAAS,cAAc,EAAY,QAAQ,CAC3D,EAAa,EAAQ,CACrB,EAAY,QAAU,gBAAkB,CACtC,EAAa,GACP,GAAQ,GACN,EAAY,SAAS,cAAc,EAAY,QAAQ,CACpD,GAEF,EAAO,EACd,EACD,IAAK,EACP,EAAE,CAAC,CAEN,OACM,GAAQ,EAAwB,GAAG,EAAe,EAAsB,KAC/D,CACP,EAAY,SAAS,cAAc,EAAY,QAAQ,GAE5D,CAAC,EAAM,EAAuB,EAAe,CAAC,CAEjD,IAAM,EAAe,EAAY,SAAY,CAC3C,EAAe,EAAsB,CACrC,MAAM,EAAS,EAAM,EACpB,CAAC,EAAO,EAAU,EAAuB,EAAe,CAAC,CAEtD,EAAe,EAAY,SAAY,CACvC,EAAI,OAAS,GACjB,MAAM,EAAS,EAAO,EAAI,EACzB,CAAC,EAAO,EAAK,EAAS,CAAC,CAE1B,OACE,EAAC,EAAA,CAAa,OAAoB,wBAChC,EAAC,EAAA,CAAc,UAAU,wBACvB,EAAC,EAAA,CAAA,SAAA,CACC,EAAC,EAAA,CAAA,SAAa,EAAA,CAAoB,CAClC,EAAC,EAAA,CAAA,SACE,GACC,EAAA,EAAA,CAAA,SAAA,CAAE,+BAC4B,EAAC,OAAA,CAAK,UAAU,uCAA+B,GAAa,qCACvF,CAAA,CAEa,CAAA,CAAA,CACP,CAEf,EAAC,MAAA,CAAI,UAAU,6CACZ,GACC,EAAC,EAAA,CAAM,QAAQ,cAAc,UAAU,kBACrC,EAAC,EAAA,CAAA,SAAkB,EAAA,CAAgC,EAC7C,CAGV,EAAC,EAAA,CAAS,UAAW,EAAG,MAAO,EAAK,SAAU,EAAQ,WAAY,EAAc,SAAU,YACxF,EAAC,EAAA,CAAA,SAAA,CACC,EAAC,EAAA,CAAa,MAAO,EAAA,CAAK,CAC1B,EAAC,EAAA,CAAa,MAAO,EAAA,CAAK,CAC1B,EAAC,EAAA,CAAa,MAAO,EAAA,CAAK,GACZ,CAChB,EAAC,EAAA,EAAA,CAAoB,CACrB,EAAC,EAAA,CAAA,SAAA,CACC,EAAC,EAAA,CAAa,MAAO,EAAA,CAAK,CAC1B,EAAC,EAAA,CAAa,MAAO,EAAA,CAAK,CAC1B,EAAC,EAAA,CAAa,MAAO,EAAA,CAAK,GACZ,GACP,CAEX,EAAC,EAAA,CAAO,KAAK,SAAoB,YAAW,SAAU,EAAI,OAAS,EAAG,UAAU,SAAS,QAAS,WAAc,YAEvG,CAET,EAAC,MAAA,CAAI,UAAU,kEACb,EAAC,OAAA,CAAA,SAAK,qBAAA,CAAyB,CAC/B,EAAC,EAAA,CAAO,QAAQ,OAAO,KAAK,KAAK,UAAU,aAAa,SAAU,EAAY,GAAK,EAAW,QAAS,WACpG,EAAY,EAAI,YAAY,EAAU,IAAM,WACtC,CAAA,EACL,CAEL,GACC,EAAC,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,UAAU,SAAS,QAAS,WAAQ,YAE7D,GAEP,CAAA,EACQ,EACT"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{jsx as e}from"react/jsx-runtime";import{cn as t}from"@customafk/react-toolkit/utils";import{cva as n}from"class-variance-authority";const r=n(`not-first:mt-3 max-w-prose whitespace-pre-line text-pretty text-start leading-7 transition-colors`,{variants:{variant:{lead:`text-base leading-8 font-medium text-text-positive-strong md:text-lg`,lg:`text-base leading-8 font-normal text-text-positive md:text-lg`,p:`text-sm font-normal text-text-positive md:text-base`,sm:`text-sm leading-6 font-normal text-text-positive`,muted:`text-sm font-normal text-text-positive-weak md:text-base`,xs:`text-xs leading-5 font-normal text-text-positive-weak`}},defaultVariants:{variant:`p`}}),i=({variant:n,className:i,...a})=>e(`p`,{"data-slot":`paragraph`,className:t(r({variant:n}),i),...a});export{r as n,i as t};
|
|
2
|
-
//# sourceMappingURL=paragraph-
|
|
2
|
+
//# sourceMappingURL=paragraph-CnHNC0rS.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paragraph-
|
|
1
|
+
{"version":3,"file":"paragraph-CnHNC0rS.mjs","names":[],"sources":["../packages/components/typography/paragraph.tsx"],"sourcesContent":["'use client';\n\nimport type { ComponentPropsWithoutRef } from 'react';\nimport { cn } from '@customafk/react-toolkit/utils';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nexport const paragraphVariants = cva('not-first:mt-3 max-w-prose whitespace-pre-line text-pretty text-start leading-7 transition-colors', {\n variants: {\n variant: {\n lead: 'text-base leading-8 font-medium text-text-positive-strong md:text-lg',\n lg: 'text-base leading-8 font-normal text-text-positive md:text-lg',\n p: 'text-sm font-normal text-text-positive md:text-base',\n sm: 'text-sm leading-6 font-normal text-text-positive',\n muted: 'text-sm font-normal text-text-positive-weak md:text-base',\n xs: 'text-xs leading-5 font-normal text-text-positive-weak',\n },\n },\n defaultVariants: {\n variant: 'p',\n },\n});\n\n/**\n * Props for the {@link Paragraph} component.\n *\n * Extends all native `<p>` HTML attributes plus the CVA variant.\n *\n * @property variant - Visual style variant.\n * - `'lead'` — large, medium-weight introductory text (default size `text-base` / `md:text-lg`)\n * - `'lg'` — large normal-weight text\n * - `'p'` — standard body text (default)\n * - `'sm'` — small normal-weight text with tighter leading\n * - `'muted'` — subdued colour, standard body size\n * - `'xs'` — extra-small text in a muted colour\n */\nexport type ParagraphProps = ComponentPropsWithoutRef<'p'> & VariantProps<typeof paragraphVariants>;\n\n/**\n * A styled `<p>` element with semantic size and weight variants for body text.\n *\n * @example\n * ```tsx\n * import { Paragraph } from '@customafk/lunas-ui/typography/paragraph';\n *\n * // Default body paragraph\n * <Paragraph>This is body text.</Paragraph>\n *\n * // Lead paragraph with larger, medium-weight text\n * <Paragraph variant=\"lead\">Introducing our new feature.</Paragraph>\n *\n * // Muted helper text\n * <Paragraph variant=\"muted\">Last updated 3 days ago.</Paragraph>\n * ```\n */\nexport const Paragraph = ({ variant, className, ...props }: ParagraphProps) => {\n return <p data-slot=\"paragraph\" className={cn(paragraphVariants({ variant }), className)} {...props} />;\n};\n"],"mappings":"2IAMA,MAAa,EAAoB,EAAI,oGAAqG,CACxI,SAAU,CACR,QAAS,CACP,KAAM,uEACN,GAAI,gEACJ,EAAG,sDACH,GAAI,mDACJ,MAAO,2DACP,GAAI,wDACL,CACF,CACD,gBAAiB,CACf,QAAS,IACV,CACF,CAAC,CAkCW,GAAa,CAAE,UAAS,YAAW,GAAG,KAC1C,EAAC,IAAA,CAAE,YAAU,YAAY,UAAW,EAAG,EAAkB,CAAE,UAAS,CAAC,CAAE,EAAU,CAAE,GAAI,GAAS"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`./chunk-Bmb41Sf3.cjs`),t=require(`./dist-Dh8WwRa8.cjs`),n=require(`./button-CwDT3m4m.cjs`),r=require(`./tooltip-itUmYz9k.cjs`),i=require(`./avatar-CTS9-raY.cjs`),a=require(`./sheet-CaDXTx7n.cjs`),o=require(`./dropdown-menu-Ct9BLGfa.cjs`);let s=require(`lucide-react`),c=require(`react`),l=require(`react/jsx-runtime`),u=require(`@customafk/react-toolkit/utils`),d=require(`class-variance-authority`),f=require(`@customafk/react-toolkit/hooks/useMobile`);const p=`sidebar_state`,m=3600*24*7,h=`16rem`,g=`18rem`,_=`3rem`,v=`b`,y=(0,c.createContext)(null);function b(){let e=(0,c.useContext)(y);if(!e)throw Error(`useSidebar must be used within a SidebarProvider.`);return e}function x({defaultOpen:e=!0,open:t,onOpenChange:n,className:i,style:a,children:o,...s}){let d=(0,f.useIsMobile)(),[p,m]=(0,c.useState)(!1),[h,g]=(0,c.useState)(e),_=t??h,v=(0,c.useCallback)(e=>{let t=typeof e==`function`?e(_):e;n?n(t):g(t),document.cookie=`sidebar_state=${t}; path=/; max-age=604800`},[n,_]),b=(0,c.useCallback)(()=>d?m(e=>!e):v(e=>!e),[d,v]);(0,c.useEffect)(()=>{let e=e=>{e.key===`b`&&(e.metaKey||e.ctrlKey)&&(e.preventDefault(),b())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[b]);let x=_?`expanded`:`collapsed`,S=(0,c.useMemo)(()=>({state:x,open:_,setOpen:v,isMobile:d,openMobile:p,setOpenMobile:m,toggleSidebar:b}),[x,_,v,d,p,b]);return(0,l.jsx)(y.Provider,{value:S,children:(0,l.jsx)(r.r,{delayDuration:0,children:(0,l.jsx)(`div`,{"data-slot":`sidebar-wrapper`,style:{"--sidebar-width":`16rem`,"--sidebar-width-icon":`3rem`,...a},className:(0,u.cn)(`group/sidebar-wrapper flex h-dvh w-full`,i),...s,children:o})})})}function S({side:e=`left`,variant:t=`sidebar`,collapsible:r=`offcanvas`,className:i,children:o,...c}){let{isMobile:d,state:f,openMobile:p,setOpenMobile:m,toggleSidebar:h}=b();return r===`none`?(0,l.jsx)(`aside`,{"data-slot":`sidebar`,className:(0,u.cn)(`flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground`,i),...c,children:o}):d?(0,l.jsx)(a.t,{open:p,onOpenChange:m,...c,children:(0,l.jsxs)(a.r,{"data-sidebar":`sidebar`,"data-slot":`sidebar`,"data-mobile":`true`,className:`w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground sm:max-w-3xs [&>button]:hidden`,style:{"--sidebar-width":`18rem`},side:e,children:[(0,l.jsxs)(a.o,{className:`sr-only`,children:[(0,l.jsx)(a.s,{children:`Sidebar`}),(0,l.jsx)(a.i,{children:`Displays the mobile sidebar.`})]}),(0,l.jsxs)(`div`,{className:`flex size-full flex-col`,children:[(0,l.jsxs)(`div`,{className:`flex flex-0 items-center gap-x-2 border-border-weak border-b p-2 pr-4`,children:[(0,l.jsxs)(n.t,{"data-sidebar":`trigger`,"data-slot":`sidebar-trigger`,variant:`ghost`,color:`muted`,size:`icon`,className:(0,u.cn)(`size-10 rounded-full`,i),onClick:e=>{h(),e.preventDefault(),e.stopPropagation()},children:[(0,l.jsx)(s.MenuIcon,{className:`size-6!`}),(0,l.jsx)(`span`,{className:`sr-only`,children:`Toggle Sidebar`})]}),(0,l.jsx)(`div`,{className:`ml-2 flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground`,children:(0,l.jsx)(s.ShoppingCartIcon,{size:20})}),(0,l.jsxs)(`div`,{className:`grid flex-1 text-left text-sm leading-tight`,children:[(0,l.jsx)(`span`,{className:`truncate font-medium`,children:`Lunas Store`}),(0,l.jsx)(`span`,{className:`truncate text-xs`,children:`Established 2023`})]})]}),(0,l.jsx)(`div`,{className:`flex flex-1 flex-col p-2`,children:o})]})]})}):(0,l.jsxs)(`aside`,{className:`group peer hidden bg-card text-sidebar-foreground md:block`,"data-state":f,"data-collapsible":f===`collapsed`?r:``,"data-variant":t,"data-side":e,"data-slot":`sidebar`,children:[(0,l.jsx)(`div`,{"data-slot":`sidebar-gap`,className:(0,u.cn)(`relative`,`bg-transparent`,`transition-[width] duration-200 ease-linear`,`h-(--header-height) w-(--sidebar-width)`,`sm:h-[calc(var(--header-height)+0.5rem)]`,`group-data-[collapsible=offcanvas]:w-0`,`group-data-[side=right]:rotate-180`,t===`floating`||t===`inset`?`group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]`:`group-data-[collapsible=icon]:w-(--sidebar-width-icon)`)}),(0,l.jsx)(`div`,{"data-slot":`sidebar-container`,className:(0,u.cn)(`hidden md:flex`,`fixed inset-y-0 top-14 z-10 shadow-nav`,`h-[calc(100dvh-3.5rem)] w-(--sidebar-width)`,`transition-[left,right,width] duration-200 ease-linear`,e===`left`&&`left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]`,e===`right`&&`right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]`,t===`floating`||t===`inset`?`p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]`:`group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l`,i),...c,children:(0,l.jsx)(`div`,{"data-sidebar":`sidebar`,"data-slot":`sidebar-inner`,className:(0,u.cn)(`flex size-full flex-col`,`group-data-[variant=floating]:rounded-lg`,`group-data-[variant=floating]:border`,`group-data-[variant=floating]:border-sidebar-border`,`group-data-[variant=floating]:shadow-sm`),children:o})})]})}function C({className:e,children:t,...n}){return(0,l.jsxs)(`main`,{"data-slot":`sidebar-inset`,className:(0,u.cn)(`relative flex w-full flex-1 flex-col`,e),...n,children:[(0,l.jsx)(`div`,{className:`h-(--header-height) w-full sm:h-[calc(var(--header-height)+0.5rem)]`}),(0,l.jsx)(`div`,{className:`inset-shadow-sm flex-1`,children:t})]})}function w({className:e,...t}){return(0,l.jsx)(`div`,{"data-slot":`sidebar-footer`,"data-sidebar":`footer`,className:(0,u.cn)(`flex flex-col gap-2 p-2`,e),...t})}function T({className:e,...t}){return(0,l.jsx)(`div`,{"data-slot":`sidebar-content`,"data-sidebar":`content`,className:(0,u.cn)(`flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden`,e),...t})}function E({className:e,...t}){return(0,l.jsx)(`div`,{"data-slot":`sidebar-group`,"data-sidebar":`group`,className:(0,u.cn)(`relative flex w-full min-w-0 flex-col`,e),...t})}function D({className:e,asChild:n=!1,...r}){return(0,l.jsx)(n?t.t:`div`,{"data-slot":`sidebar-group-label`,"data-sidebar":`group-label`,className:(0,u.cn)(`flex h-8 shrink-0 items-center rounded-md px-2 font-medium text-sidebar-foreground/70 text-xs outline-hidden ring-sidebar-ring transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0`,`group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0`,e),...r})}function O({className:e,...t}){return(0,l.jsx)(`div`,{"data-slot":`sidebar-group-content`,"data-sidebar":`group-content`,className:(0,u.cn)(`w-full text-sm`,e),...t})}function k({className:e,...t}){return(0,l.jsx)(`ul`,{"data-slot":`sidebar-menu`,"data-sidebar":`menu`,className:(0,u.cn)(`flex w-full min-w-0 flex-col gap-1`,e),...t})}function A({className:e,...t}){return(0,l.jsx)(`li`,{"data-slot":`sidebar-menu-item`,"data-sidebar":`menu-item`,className:(0,u.cn)(`group/menu-item relative`,e),...t})}const j=(0,d.cva)([`peer/menu-button`,`cursor-pointer`,`flex w-full items-center gap-2`,`overflow-hidden rounded-md p-2 outline-hidden`,`truncate text-left font-normal`,`transition-[color,width,height,padding]`,`hover:bg-sidebar-accent`,`hover:text-sidebar-accent-foreground`,`active:bg-sidebar-accent`,`active:text-sidebar-accent-foreground`,`disabled:pointer-events-none`,`disabled:opacity-50`,`group-has-data-[sidebar=menu-action]/menu-item:pr-8`,`aria-disabled:pointer-events-none`,`aria-disabled:opacity-50`,`data-[active=true]:bg-sidebar-primary-muted`,`data-[active=true]:text-sidebar-primary`,`data-[state=open]:hover:bg-sidebar-accent`,`data-[state=open]:hover:text-sidebar-accent-foreground`,`group-data-[collapsible=icon]:size-12!`,`group-data-[collapsible=icon]:p-3!`,`group-data-[collapsible=icon]:gap-3!`,`[&>svg]:size-6`,`[&>svg]:shrink-0`,`[&>span:last-child]:truncate`],{variants:{variant:{default:`hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground/80`,outline:`bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]`},size:{default:`h-10 text-sm`,sm:`h-7 text-xs`,lg:`h-12 text-sm group-data-[collapsible=icon]:p-0!`}},defaultVariants:{variant:`default`,size:`default`}});function M({asChild:e=!1,isActive:n=!1,variant:i=`default`,size:a=`default`,tooltip:o,className:s,...c}){let d=e?t.t:`button`,{isMobile:f,state:p}=b(),m=(0,l.jsx)(d,{"data-slot":`sidebar-menu-button`,"data-sidebar":`menu-button`,"data-size":a,"data-active":n,className:(0,u.cn)(j({variant:i,size:a}),s),...c});return o?(typeof o==`string`&&(o={children:o}),(0,l.jsxs)(r.t,{children:[(0,l.jsx)(r.i,{asChild:!0,children:m}),(0,l.jsx)(r.n,{side:`right`,align:`center`,hidden:p!==`collapsed`||f,...o})]})):m}function N(e){let t=e.trim().split(/\s+/);return t.length===1?t[0].slice(0,2).toUpperCase():(t[0][0]+t[t.length-1][0]).toUpperCase()}const P=({user:e,onLogin:t,onLogout:r})=>{let{toggleSidebar:a}=b(),d=(0,c.useCallback)(e=>{e.preventDefault(),e.stopPropagation(),a()},[a]),f=(0,c.useCallback)(e=>{e.preventDefault(),e.stopPropagation(),r?.()},[r]),p=(0,c.useCallback)(e=>{e.preventDefault(),e.stopPropagation(),t?.()},[t]);return(0,l.jsxs)(`header`,{"data-slot":`payment-layout-header`,className:(0,u.cn)(`bg-card`,`h-(--header-height)`,`sm:h-[calc(var(--header-height)+0.5rem)] sm:px-4 sm:pr-6`,`absolute inset-x-0 top-0 z-20 gap-2 px-2 pr-4.5`,`flex items-center shadow-nav`,`transition-[width,height] ease-linear`),children:[(0,l.jsxs)(n.t,{"data-sidebar":`trigger`,"data-slot":`sidebar-trigger`,variant:`ghost`,color:`muted`,size:`icon`,className:`size-10 rounded-full transition-all hover:text-text-positive`,onClick:d,children:[(0,l.jsx)(s.MenuIcon,{className:`size-6!`}),(0,l.jsx)(`span`,{className:`sr-only`,children:`Toggle Sidebar`})]}),(0,l.jsxs)(`div`,{className:`flex flex-1 gap-x-2 sm:ml-2.5`,children:[(0,l.jsx)(`div`,{className:`flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground`,children:(0,l.jsx)(s.ShoppingCartIcon,{size:20})}),(0,l.jsxs)(`div`,{className:`grid flex-1 text-left text-sm leading-tight`,children:[(0,l.jsx)(`span`,{className:`truncate font-medium`,children:`Lunas Enterprise`}),(0,l.jsx)(`span`,{className:`truncate text-xs`,children:`Established 2025`})]})]}),e?(0,l.jsxs)(o.t,{children:[(0,l.jsx)(o.h,{asChild:!0,children:(0,l.jsxs)(n.t,{variant:`ghost`,color:`muted`,className:`gap-x-2 rounded-full px-2 transition-all hover:text-text-positive`,children:[(0,l.jsxs)(i.t,{className:`size-8`,children:[e.avatar&&(0,l.jsx)(i.r,{src:e.avatar,alt:e.fullname}),(0,l.jsx)(i.n,{className:`text-xs`,children:N(e.fullname)})]}),(0,l.jsx)(`span`,{className:`hidden max-w-32 truncate font-medium text-sm sm:block`,children:e.fullname})]})}),(0,l.jsxs)(o.r,{align:`end`,className:`w-56`,children:[(0,l.jsxs)(o.o,{className:`font-normal`,children:[(0,l.jsx)(`p`,{className:`font-medium`,children:e.fullname}),(0,l.jsx)(`p`,{className:`text-muted-foreground text-xs`,children:e.email})]}),(0,l.jsx)(o.u,{}),(0,l.jsx)(o.i,{children:(0,l.jsxs)(o.a,{onClick:f,children:[(0,l.jsx)(s.LogOutIcon,{size:14}),`Đăng xuất`]})})]})]}):(0,l.jsx)(n.t,{size:`sm`,onClick:p,children:`Đăng nhập`})]})},F=({activeNavItemId:e,sidebar:t,user:n,onLogin:r,onLogout:i,children:a})=>{let o=(0,c.useMemo)(()=>t?.groupcontent||[],[t]);return(0,l.jsxs)(x,{children:[(0,l.jsx)(P,{user:n,onLogin:r,onLogout:i}),(0,l.jsxs)(S,{variant:`inset`,collapsible:`icon`,children:[(0,l.jsx)(T,{children:o.map(t=>(0,l.jsxs)(E,{children:[(0,l.jsx)(D,{children:t.label}),(0,l.jsx)(O,{children:(0,l.jsx)(k,{children:t.items.map(t=>(0,l.jsx)(A,{children:(0,l.jsxs)(M,{isActive:t.id===e,onClick:e=>{t.onClick?.(),e.preventDefault(),e.stopPropagation()},children:[t.icon,t.label]})},t.id))})})]},t.id))}),(0,l.jsx)(w,{children:(0,l.jsx)(k,{children:(0,l.jsx)(A,{className:`mt-2 border-t border-t-border`,children:(0,l.jsx)(`p`,{className:`pt-2 text-center text-muted-foreground text-xs`,children:`Copyright © 2025, Lunas.`})})})})]}),(0,l.jsx)(C,{children:(0,l.jsx)(`section`,{className:`relative size-full`,children:(0,l.jsx)(`div`,{className:`absolute inset-0`,children:a})})})]})};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return F}});
|
|
2
|
+
//# sourceMappingURL=payment-layout-0mqqno1V.cjs.map
|