@customafk/lunas-ui 0.2.4 → 0.2.6
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/README.md +39 -9
- package/ai-docs.md +419 -0
- package/dist/alert-5MxGtf3j.d.mts +88 -0
- package/dist/alert-DIC1_ymv.cjs +2 -0
- package/dist/alert-DIC1_ymv.cjs.map +1 -0
- package/dist/alert-DwdUOFaC.d.cts +88 -0
- package/dist/alert-VP3giy31.mjs +2 -0
- package/dist/alert-VP3giy31.mjs.map +1 -0
- package/dist/avatar-CTS9-raY.cjs +2 -0
- package/dist/avatar-CTS9-raY.cjs.map +1 -0
- package/dist/avatar-DbxqvCjT.mjs +2 -0
- package/dist/avatar-DbxqvCjT.mjs.map +1 -0
- package/dist/badge-B8bw2UEY.mjs +2 -0
- package/dist/badge-B8bw2UEY.mjs.map +1 -0
- package/dist/badge-BFTGDsBm.d.cts +42 -0
- package/dist/badge-sL8O2yfv.d.mts +42 -0
- package/dist/badge-uQ0pIZbQ.cjs +2 -0
- package/dist/badge-uQ0pIZbQ.cjs.map +1 -0
- package/dist/button-BlQb81It.d.mts +174 -0
- package/dist/button-C6ybzxxj.mjs +2 -0
- package/dist/button-C6ybzxxj.mjs.map +1 -0
- package/dist/button-CEOQ3-82.d.cts +174 -0
- package/dist/button-CwDT3m4m.cjs +2 -0
- package/dist/button-CwDT3m4m.cjs.map +1 -0
- package/dist/button.variants-DeCyas1F.mjs +2 -0
- package/dist/button.variants-DeCyas1F.mjs.map +1 -0
- package/dist/button.variants-tnhb123u.cjs +2 -0
- package/dist/button.variants-tnhb123u.cjs.map +1 -0
- package/dist/{calendar-CG-WMM8e.cjs → calendar-CyAPpT2m.cjs} +2 -2
- package/dist/calendar-CyAPpT2m.cjs.map +1 -0
- package/dist/calendar-JKxWM6AF.mjs +2 -0
- package/dist/calendar-JKxWM6AF.mjs.map +1 -0
- package/dist/cards/grid-product-card.cjs +1 -1
- package/dist/cards/grid-product-card.cjs.map +1 -1
- package/dist/cards/grid-product-card.d.cts +23 -0
- package/dist/cards/grid-product-card.d.mts +23 -0
- package/dist/cards/grid-product-card.mjs +1 -1
- package/dist/cards/grid-product-card.mjs.map +1 -1
- package/dist/cards/product-card.cjs +1 -1
- package/dist/cards/product-card.cjs.map +1 -1
- package/dist/cards/product-card.d.cts +23 -0
- package/dist/cards/product-card.d.mts +23 -0
- package/dist/cards/product-card.mjs +1 -1
- package/dist/cards/product-card.mjs.map +1 -1
- package/dist/cards/simple-card.cjs +1 -1
- package/dist/cards/simple-card.cjs.map +1 -1
- package/dist/cards/simple-card.d.cts +16 -0
- package/dist/cards/simple-card.d.mts +16 -0
- package/dist/cards/simple-card.mjs +1 -1
- package/dist/cards/simple-card.mjs.map +1 -1
- package/dist/{checkbox-Bg2FiuQw.mjs → checkbox-DJEdYOjA.mjs} +2 -2
- package/dist/checkbox-DJEdYOjA.mjs.map +1 -0
- package/dist/{checkbox-C0fSWwmD.cjs → checkbox-RZrRNYP2.cjs} +2 -2
- package/dist/checkbox-RZrRNYP2.cjs.map +1 -0
- package/dist/close-BU0kWRVo.mjs +2 -0
- package/dist/{close-DfuHB7kq.mjs.map → close-BU0kWRVo.mjs.map} +1 -1
- package/dist/close-DXk_H3Gt.cjs +2 -0
- package/dist/{close-D_Ge7gnP.cjs.map → close-DXk_H3Gt.cjs.map} +1 -1
- package/dist/cms-layout-Dc4moos1.cjs +2 -0
- package/dist/cms-layout-Dc4moos1.cjs.map +1 -0
- package/dist/cms-layout-HfnOQS16.mjs +2 -0
- package/dist/cms-layout-HfnOQS16.mjs.map +1 -0
- package/dist/{command-_zpTaaIk.cjs → command-SHd-d_o0.cjs} +2 -2
- package/dist/command-SHd-d_o0.cjs.map +1 -0
- package/dist/{command-DhBTNTqz.mjs → command-bpcnKEbR.mjs} +2 -2
- package/dist/command-bpcnKEbR.mjs.map +1 -0
- package/dist/data-display/country.cjs +1 -1
- package/dist/data-display/country.cjs.map +1 -1
- package/dist/data-display/country.d.cts +15 -3
- package/dist/data-display/country.d.mts +15 -3
- package/dist/data-display/country.mjs +1 -1
- package/dist/data-display/country.mjs.map +1 -1
- package/dist/data-display/data-list.cjs +1 -1
- package/dist/data-display/data-list.cjs.map +1 -1
- package/dist/data-display/data-list.d.cts +31 -2
- package/dist/data-display/data-list.d.mts +31 -2
- package/dist/data-display/data-list.mjs +1 -1
- package/dist/data-display/data-list.mjs.map +1 -1
- package/dist/data-display/date-tooltip.cjs +1 -1
- package/dist/data-display/date-tooltip.cjs.map +1 -1
- package/dist/data-display/date-tooltip.d.cts +13 -2
- package/dist/data-display/date-tooltip.d.mts +13 -2
- package/dist/data-display/date-tooltip.mjs +1 -1
- package/dist/data-display/date-tooltip.mjs.map +1 -1
- package/dist/data-display/date.cjs +1 -1
- package/dist/data-display/date.d.cts +28 -2
- package/dist/data-display/date.d.mts +28 -2
- package/dist/data-display/date.mjs +1 -1
- package/dist/data-display/empty.cjs +1 -1
- package/dist/data-display/empty.cjs.map +1 -1
- package/dist/data-display/empty.d.cts +17 -3
- package/dist/data-display/empty.d.mts +17 -3
- package/dist/data-display/empty.mjs +1 -1
- package/dist/data-display/empty.mjs.map +1 -1
- package/dist/data-display/name.cjs +1 -1
- package/dist/data-display/name.cjs.map +1 -1
- package/dist/data-display/name.d.cts +12 -1
- package/dist/data-display/name.d.mts +12 -1
- package/dist/data-display/name.mjs +1 -1
- package/dist/data-display/name.mjs.map +1 -1
- package/dist/data-display/phone-number.cjs +1 -1
- package/dist/data-display/phone-number.cjs.map +1 -1
- package/dist/data-display/phone-number.d.cts +14 -2
- package/dist/data-display/phone-number.d.mts +14 -2
- package/dist/data-display/phone-number.mjs +1 -1
- package/dist/data-display/phone-number.mjs.map +1 -1
- package/dist/data-display/role-badge.cjs +1 -1
- package/dist/data-display/role-badge.cjs.map +1 -1
- package/dist/data-display/role-badge.d.cts +15 -3
- package/dist/data-display/role-badge.d.mts +15 -3
- package/dist/data-display/role-badge.mjs +1 -1
- package/dist/data-display/role-badge.mjs.map +1 -1
- package/dist/data-display/statistic.cjs +1 -1
- package/dist/data-display/statistic.cjs.map +1 -1
- package/dist/data-display/statistic.d.cts +35 -6
- package/dist/data-display/statistic.d.mts +35 -6
- package/dist/data-display/statistic.mjs +1 -1
- package/dist/data-display/statistic.mjs.map +1 -1
- package/dist/data-display/user.cjs +1 -2
- package/dist/data-display/user.d.cts +14 -1
- package/dist/data-display/user.d.mts +14 -1
- package/dist/data-display/user.mjs +1 -2
- package/dist/date-CVz9xdCg.mjs +2 -0
- package/dist/date-CVz9xdCg.mjs.map +1 -0
- package/dist/date-a3RI5Pwo.cjs +2 -0
- package/dist/date-a3RI5Pwo.cjs.map +1 -0
- package/dist/dialog-Bah7jLoO.d.cts +90 -0
- package/dist/dialog-BchwY6-N.mjs +2 -0
- package/dist/dialog-BchwY6-N.mjs.map +1 -0
- package/dist/dialog-DSg5IKmb.d.mts +90 -0
- package/dist/dialog-o_68LQXd.cjs +2 -0
- package/dist/dialog-o_68LQXd.cjs.map +1 -0
- package/dist/dialogs/confirm-dialog.cjs +1 -1
- package/dist/dialogs/confirm-dialog.cjs.map +1 -1
- package/dist/dialogs/confirm-dialog.d.cts +129 -3
- package/dist/dialogs/confirm-dialog.d.mts +129 -3
- package/dist/dialogs/confirm-dialog.mjs +1 -1
- package/dist/dialogs/confirm-dialog.mjs.map +1 -1
- package/dist/dialogs/detail-dialog/components/sidebar.cjs +1 -2
- package/dist/dialogs/detail-dialog/components/sidebar.d.cts +71 -24
- package/dist/dialogs/detail-dialog/components/sidebar.d.mts +71 -24
- package/dist/dialogs/detail-dialog/components/sidebar.mjs +1 -2
- package/dist/dialogs/detail-dialog/index.cjs +1 -1
- package/dist/dialogs/detail-dialog/index.cjs.map +1 -1
- package/dist/dialogs/detail-dialog/index.d.cts +37 -8
- package/dist/dialogs/detail-dialog/index.d.mts +37 -8
- package/dist/dialogs/detail-dialog/index.mjs +1 -1
- package/dist/dialogs/detail-dialog/index.mjs.map +1 -1
- package/dist/dialogs/error-dialog.cjs +1 -1
- package/dist/dialogs/error-dialog.cjs.map +1 -1
- package/dist/dialogs/error-dialog.d.cts +18 -4
- package/dist/dialogs/error-dialog.d.mts +18 -4
- package/dist/dialogs/error-dialog.mjs +1 -1
- package/dist/dialogs/error-dialog.mjs.map +1 -1
- package/dist/dialogs/loading-dialog.cjs +1 -1
- package/dist/dialogs/loading-dialog.cjs.map +1 -1
- package/dist/dialogs/loading-dialog.d.cts +15 -3
- package/dist/dialogs/loading-dialog.d.mts +15 -3
- package/dist/dialogs/loading-dialog.mjs +1 -1
- package/dist/dialogs/loading-dialog.mjs.map +1 -1
- package/dist/{dist-CvmzZ_6C.mjs → dist-CIN9T2FB.mjs} +1 -1
- package/dist/{dist-CvmzZ_6C.mjs.map → dist-CIN9T2FB.mjs.map} +1 -1
- package/dist/{dist-BudM04oj.cjs → dist-Dh8WwRa8.cjs} +1 -1
- package/dist/{dist-BudM04oj.cjs.map → dist-Dh8WwRa8.cjs.map} +1 -1
- package/dist/dropdown-menu-Ct9BLGfa.cjs +2 -0
- package/dist/dropdown-menu-Ct9BLGfa.cjs.map +1 -0
- package/dist/dropdown-menu-DWSfXhHo.mjs +2 -0
- package/dist/dropdown-menu-DWSfXhHo.mjs.map +1 -0
- package/dist/features/descriptions/index.cjs +1 -1
- package/dist/features/descriptions/index.cjs.map +1 -1
- package/dist/features/descriptions/index.d.cts +158 -19
- package/dist/features/descriptions/index.d.mts +158 -19
- package/dist/features/descriptions/index.mjs +1 -1
- package/dist/features/descriptions/index.mjs.map +1 -1
- package/dist/features/search-modal/index.cjs +1 -2
- package/dist/features/search-modal/index.d.cts +12 -2
- package/dist/features/search-modal/index.d.mts +12 -2
- package/dist/features/search-modal/index.mjs +1 -2
- package/dist/features/tables/index.cjs +1 -2
- package/dist/features/tables/index.d.cts +746 -24
- package/dist/features/tables/index.d.mts +742 -20
- package/dist/features/tables/index.mjs +1 -2
- package/dist/features/tanstack-form/index.cjs +1 -2
- package/dist/features/tanstack-form/index.d.cts +2 -1786
- package/dist/features/tanstack-form/index.d.mts +2 -1786
- package/dist/features/tanstack-form/index.mjs +1 -2
- package/dist/field-CXVnw75a.mjs +2 -0
- package/dist/field-CXVnw75a.mjs.map +1 -0
- package/dist/field-CppNvoxV.cjs +2 -0
- package/dist/field-CppNvoxV.cjs.map +1 -0
- package/dist/{flex-BP8sTi70.mjs → flex-BLMTj7Ev.mjs} +2 -2
- package/dist/flex-BLMTj7Ev.mjs.map +1 -0
- package/dist/{flex-twCgWyx1.cjs → flex-BbbogTsZ.cjs} +2 -2
- package/dist/flex-BbbogTsZ.cjs.map +1 -0
- package/dist/heading-AKz5ewy-.cjs +2 -0
- package/dist/heading-AKz5ewy-.cjs.map +1 -0
- package/dist/heading-DN67djxs.mjs +2 -0
- package/dist/heading-DN67djxs.mjs.map +1 -0
- package/dist/{image-DuFv8sPr.cjs → image-B1Dm5LWk.cjs} +2 -2
- package/dist/image-B1Dm5LWk.cjs.map +1 -0
- package/dist/{image-CS_Q0WA7.mjs → image-BlzrSaoE.mjs} +2 -2
- package/dist/image-BlzrSaoE.mjs.map +1 -0
- package/dist/index-D4shnfqM.d.cts +2030 -0
- package/dist/index-Dktb6D35.d.mts +2030 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +90 -0
- package/dist/index.d.mts +90 -0
- package/dist/index.mjs +1 -0
- package/dist/{input-DBtIgQB6.mjs → input-Cd0G5y-9.mjs} +2 -2
- package/dist/input-Cd0G5y-9.mjs.map +1 -0
- package/dist/{input-BFWWaN-v.cjs → input-Cl5VkKQh.cjs} +2 -2
- package/dist/input-Cl5VkKQh.cjs.map +1 -0
- package/dist/input-DAGzv97v.d.mts +44 -0
- package/dist/input-DPLvx5x8.d.cts +44 -0
- package/dist/{label-BzfsTrVt.cjs → label-DkMTQ3Ch.cjs} +2 -2
- package/dist/label-DkMTQ3Ch.cjs.map +1 -0
- package/dist/label-OmlGaZ5h.mjs +2 -0
- package/dist/label-OmlGaZ5h.mjs.map +1 -0
- package/dist/layouts/cms-layout/index.cjs +1 -2
- package/dist/layouts/cms-layout/index.d.cts +66 -13
- package/dist/layouts/cms-layout/index.d.mts +66 -13
- package/dist/layouts/cms-layout/index.mjs +1 -2
- package/dist/layouts/flex.cjs +1 -1
- package/dist/layouts/flex.d.cts +90 -6
- package/dist/layouts/flex.d.mts +93 -9
- package/dist/layouts/flex.mjs +1 -1
- package/dist/layouts/grid.cjs +1 -1
- package/dist/layouts/grid.cjs.map +1 -1
- package/dist/layouts/grid.d.cts +14 -0
- package/dist/layouts/grid.d.mts +14 -0
- package/dist/layouts/grid.mjs +1 -1
- package/dist/layouts/grid.mjs.map +1 -1
- package/dist/layouts/payment-layout/index.cjs +1 -2
- package/dist/layouts/payment-layout/index.d.cts +35 -0
- package/dist/layouts/payment-layout/index.d.mts +35 -0
- package/dist/layouts/payment-layout/index.mjs +1 -2
- package/dist/pages/FeatureDeveloping.cjs +1 -1
- package/dist/pages/FeatureDeveloping.cjs.map +1 -1
- package/dist/pages/FeatureDeveloping.d.cts +21 -3
- package/dist/pages/FeatureDeveloping.d.mts +21 -3
- package/dist/pages/FeatureDeveloping.mjs +1 -1
- package/dist/pages/FeatureDeveloping.mjs.map +1 -1
- package/dist/pages/FeatureFixing.cjs +1 -1
- package/dist/pages/FeatureFixing.cjs.map +1 -1
- package/dist/pages/FeatureFixing.d.cts +21 -3
- package/dist/pages/FeatureFixing.d.mts +21 -3
- package/dist/pages/FeatureFixing.mjs +1 -1
- package/dist/pages/FeatureFixing.mjs.map +1 -1
- package/dist/pages/NotAuthorized.cjs +1 -1
- package/dist/pages/NotAuthorized.cjs.map +1 -1
- package/dist/pages/NotAuthorized.d.cts +21 -3
- package/dist/pages/NotAuthorized.d.mts +21 -3
- package/dist/pages/NotAuthorized.mjs +1 -1
- package/dist/pages/NotAuthorized.mjs.map +1 -1
- package/dist/pages/NotFound.cjs +1 -1
- package/dist/pages/NotFound.cjs.map +1 -1
- package/dist/pages/NotFound.d.cts +21 -3
- package/dist/pages/NotFound.d.mts +21 -3
- package/dist/pages/NotFound.mjs +1 -1
- package/dist/pages/NotFound.mjs.map +1 -1
- package/dist/paragraph-Ch5TvEqL.mjs +2 -0
- package/dist/paragraph-Ch5TvEqL.mjs.map +1 -0
- package/dist/paragraph-DN85Huc4.cjs +2 -0
- package/dist/paragraph-DN85Huc4.cjs.map +1 -0
- package/dist/payment-layout-Da29dHJe.cjs +2 -0
- package/dist/payment-layout-Da29dHJe.cjs.map +1 -0
- package/dist/payment-layout-wN5c7MCM.mjs +2 -0
- package/dist/payment-layout-wN5c7MCM.mjs.map +1 -0
- package/dist/{popover-DzDrgttC.cjs → popover-AEt-aSy3.cjs} +2 -2
- package/dist/popover-AEt-aSy3.cjs.map +1 -0
- package/dist/popover-OJXFbqJi.mjs +2 -0
- package/dist/popover-OJXFbqJi.mjs.map +1 -0
- package/dist/{radio-group-CBhRsUjN.cjs → radio-group-BWLdQw7M.cjs} +2 -2
- package/dist/radio-group-BWLdQw7M.cjs.map +1 -0
- package/dist/{radio-group-Cem8O6BK.mjs → radio-group-CAgfOr7-.mjs} +2 -2
- package/dist/radio-group-CAgfOr7-.mjs.map +1 -0
- package/dist/{resizable-mlGS6Zto.cjs → resizable-D6UKwvFa.cjs} +2 -2
- package/dist/resizable-D6UKwvFa.cjs.map +1 -0
- package/dist/{resizable-DXHfkbaz.mjs → resizable-DWh_mp5P.mjs} +2 -2
- package/dist/resizable-DWh_mp5P.mjs.map +1 -0
- package/dist/search-modal-BxjKY8I7.mjs +2 -0
- package/dist/search-modal-BxjKY8I7.mjs.map +1 -0
- package/dist/search-modal-C-jNqQI1.cjs +2 -0
- package/dist/search-modal-C-jNqQI1.cjs.map +1 -0
- package/dist/{select-2CgwiefV.cjs → select-Py_t2nX1.cjs} +2 -2
- package/dist/select-Py_t2nX1.cjs.map +1 -0
- package/dist/{select-CivtMKTM.mjs → select-Ze8Fq88G.mjs} +2 -2
- package/dist/select-Ze8Fq88G.mjs.map +1 -0
- package/dist/separator-BMsbHAVt.mjs +2 -0
- package/dist/separator-BMsbHAVt.mjs.map +1 -0
- package/dist/{separator-C3ip6sbh.cjs → separator-BwZb12bh.cjs} +2 -2
- package/dist/separator-BwZb12bh.cjs.map +1 -0
- package/dist/{sheet-5MJRtrfG.cjs → sheet-CaDXTx7n.cjs} +2 -2
- package/dist/sheet-CaDXTx7n.cjs.map +1 -0
- package/dist/{sheet-oadGRiie.mjs → sheet-DMIqn1iv.mjs} +2 -2
- package/dist/sheet-DMIqn1iv.mjs.map +1 -0
- package/dist/sidebar-C27_pwLR.cjs +2 -0
- package/dist/sidebar-C27_pwLR.cjs.map +1 -0
- package/dist/sidebar-meLttL0V.mjs +2 -0
- package/dist/sidebar-meLttL0V.mjs.map +1 -0
- package/dist/skeleton-BPxcW2yu.mjs +2 -0
- package/dist/skeleton-BPxcW2yu.mjs.map +1 -0
- package/dist/skeleton-BfMCjXYM.cjs +2 -0
- package/dist/skeleton-BfMCjXYM.cjs.map +1 -0
- package/dist/spinner-EgMJOaQi.mjs +2 -0
- package/dist/spinner-EgMJOaQi.mjs.map +1 -0
- package/dist/spinner-MKXqwF9G.cjs +2 -0
- package/dist/spinner-MKXqwF9G.cjs.map +1 -0
- package/dist/systems/google.cjs.map +1 -1
- package/dist/systems/google.d.cts +36 -0
- package/dist/systems/google.d.mts +36 -0
- package/dist/systems/google.mjs.map +1 -1
- package/dist/tables-CmOVrvXM.cjs +2 -0
- package/dist/tables-CmOVrvXM.cjs.map +1 -0
- package/dist/tables-cBo0_szt.mjs +2 -0
- package/dist/tables-cBo0_szt.mjs.map +1 -0
- package/dist/tanstack-form-BmV2BXDz.cjs +2 -0
- package/dist/tanstack-form-BmV2BXDz.cjs.map +1 -0
- package/dist/tanstack-form-CJ43hVb_.mjs +2 -0
- package/dist/tanstack-form-CJ43hVb_.mjs.map +1 -0
- package/dist/{textarea-COQoSVSc.cjs → textarea-BsgmN4jy.cjs} +2 -2
- package/dist/textarea-BsgmN4jy.cjs.map +1 -0
- package/dist/{textarea-bLtmb71c.mjs → textarea-CdGSEkZB.mjs} +2 -2
- package/dist/textarea-CdGSEkZB.mjs.map +1 -0
- package/dist/tooltip-Bj0iOG4s.mjs +2 -0
- package/dist/tooltip-Bj0iOG4s.mjs.map +1 -0
- package/dist/{tooltip-DC6i1A25.cjs → tooltip-itUmYz9k.cjs} +2 -2
- package/dist/tooltip-itUmYz9k.cjs.map +1 -0
- package/dist/{types-Bd0JePtp.d.cts → types-B_32Ieia.d.mts} +1 -1
- package/dist/{types-BpHcqlOI.d.mts → types-CDYHkcOk.d.cts} +1 -1
- package/dist/{types-DBD4LOem.mjs → types-DNphnTW-.mjs} +1 -1
- package/dist/{types-DBD4LOem.mjs.map → types-DNphnTW-.mjs.map} +1 -1
- package/dist/typography/paragraph.cjs +1 -1
- package/dist/typography/paragraph.d.cts +40 -20
- package/dist/typography/paragraph.d.mts +40 -20
- package/dist/typography/paragraph.mjs +1 -1
- package/dist/typography/title.cjs +1 -1
- package/dist/typography/title.cjs.map +1 -1
- package/dist/typography/title.d.cts +33 -5
- package/dist/typography/title.d.mts +33 -5
- package/dist/typography/title.mjs +1 -1
- package/dist/typography/title.mjs.map +1 -1
- package/dist/ui/alert-dialog.cjs +1 -1
- package/dist/ui/alert-dialog.cjs.map +1 -1
- package/dist/ui/alert-dialog.d.cts +54 -12
- package/dist/ui/alert-dialog.d.mts +54 -12
- package/dist/ui/alert-dialog.mjs +1 -1
- package/dist/ui/alert-dialog.mjs.map +1 -1
- package/dist/ui/alert.cjs +1 -2
- package/dist/ui/alert.d.cts +2 -69
- package/dist/ui/alert.d.mts +2 -69
- package/dist/ui/alert.mjs +1 -2
- package/dist/ui/aspect-ratio.cjs +1 -1
- package/dist/ui/aspect-ratio.cjs.map +1 -1
- package/dist/ui/aspect-ratio.d.cts +15 -2
- package/dist/ui/aspect-ratio.d.mts +15 -2
- package/dist/ui/aspect-ratio.mjs +1 -1
- package/dist/ui/aspect-ratio.mjs.map +1 -1
- package/dist/ui/avatar.cjs +1 -1
- package/dist/ui/avatar.d.cts +20 -4
- package/dist/ui/avatar.d.mts +20 -4
- package/dist/ui/avatar.mjs +1 -1
- package/dist/ui/badge.cjs +1 -1
- package/dist/ui/badge.d.cts +2 -21
- package/dist/ui/badge.d.mts +2 -21
- package/dist/ui/badge.mjs +1 -1
- package/dist/ui/breadcrumb.cjs +1 -1
- package/dist/ui/breadcrumb.cjs.map +1 -1
- package/dist/ui/breadcrumb.d.cts +38 -25
- package/dist/ui/breadcrumb.d.mts +38 -25
- package/dist/ui/breadcrumb.mjs +1 -1
- package/dist/ui/breadcrumb.mjs.map +1 -1
- package/dist/ui/button-group.cjs +1 -1
- package/dist/ui/button-group.cjs.map +1 -1
- package/dist/ui/button-group.d.cts +27 -6
- package/dist/ui/button-group.d.mts +27 -6
- package/dist/ui/button-group.mjs +1 -1
- package/dist/ui/button-group.mjs.map +1 -1
- package/dist/ui/button.cjs +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.cjs +1 -1
- package/dist/ui/buttons/add-new.cjs.map +1 -1
- package/dist/ui/buttons/add-new.d.cts +9 -0
- package/dist/ui/buttons/add-new.d.mts +9 -0
- package/dist/ui/buttons/add-new.mjs +1 -1
- package/dist/ui/buttons/add-new.mjs.map +1 -1
- package/dist/ui/buttons/edit.cjs +1 -1
- package/dist/ui/buttons/edit.cjs.map +1 -1
- package/dist/ui/buttons/edit.d.cts +9 -0
- package/dist/ui/buttons/edit.d.mts +9 -0
- package/dist/ui/buttons/edit.mjs +1 -1
- package/dist/ui/buttons/edit.mjs.map +1 -1
- package/dist/ui/buttons/refresh.cjs +1 -1
- package/dist/ui/buttons/refresh.cjs.map +1 -1
- package/dist/ui/buttons/refresh.d.cts +9 -0
- package/dist/ui/buttons/refresh.d.mts +9 -0
- package/dist/ui/buttons/refresh.mjs +1 -1
- package/dist/ui/buttons/refresh.mjs.map +1 -1
- package/dist/ui/buttons/trash.cjs +1 -1
- package/dist/ui/buttons/trash.cjs.map +1 -1
- package/dist/ui/buttons/trash.d.cts +9 -0
- package/dist/ui/buttons/trash.d.mts +9 -0
- package/dist/ui/buttons/trash.mjs +1 -1
- package/dist/ui/buttons/trash.mjs.map +1 -1
- package/dist/ui/buttons/upload-image.cjs +1 -1
- package/dist/ui/buttons/upload-image.cjs.map +1 -1
- package/dist/ui/buttons/upload-image.d.cts +13 -0
- package/dist/ui/buttons/upload-image.d.mts +13 -0
- package/dist/ui/buttons/upload-image.mjs +1 -1
- package/dist/ui/buttons/upload-image.mjs.map +1 -1
- package/dist/ui/calendar.cjs +1 -1
- package/dist/ui/calendar.d.cts +22 -4
- package/dist/ui/calendar.d.mts +22 -4
- package/dist/ui/calendar.mjs +1 -1
- package/dist/ui/card.cjs +1 -1
- package/dist/ui/card.cjs.map +1 -1
- package/dist/ui/card.d.cts +37 -8
- package/dist/ui/card.d.mts +37 -8
- package/dist/ui/card.mjs +1 -1
- package/dist/ui/card.mjs.map +1 -1
- package/dist/ui/carousel.cjs +1 -1
- package/dist/ui/carousel.cjs.map +1 -1
- package/dist/ui/carousel.d.cts +31 -7
- package/dist/ui/carousel.d.mts +31 -7
- package/dist/ui/carousel.mjs +1 -1
- package/dist/ui/carousel.mjs.map +1 -1
- package/dist/ui/checkbox.cjs +1 -1
- package/dist/ui/checkbox.d.cts +17 -2
- package/dist/ui/checkbox.d.mts +17 -2
- package/dist/ui/checkbox.mjs +1 -1
- package/dist/ui/collapsible.cjs.map +1 -1
- package/dist/ui/collapsible.d.cts +22 -4
- package/dist/ui/collapsible.d.mts +22 -4
- package/dist/ui/collapsible.mjs.map +1 -1
- package/dist/ui/command.cjs +1 -1
- package/dist/ui/command.d.cts +48 -11
- package/dist/ui/command.d.mts +48 -11
- package/dist/ui/command.mjs +1 -1
- package/dist/ui/context-menu.cjs +1 -1
- package/dist/ui/context-menu.cjs.map +1 -1
- package/dist/ui/context-menu.d.cts +65 -16
- package/dist/ui/context-menu.d.mts +65 -16
- package/dist/ui/context-menu.mjs +1 -1
- package/dist/ui/context-menu.mjs.map +1 -1
- package/dist/ui/dialog.cjs +1 -1
- 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.cjs +1 -1
- package/dist/ui/drawer.cjs.map +1 -1
- package/dist/ui/drawer.d.cts +39 -11
- package/dist/ui/drawer.d.mts +39 -11
- package/dist/ui/drawer.mjs +1 -1
- package/dist/ui/drawer.mjs.map +1 -1
- package/dist/ui/dropdown-menu.cjs +1 -1
- package/dist/ui/dropdown-menu.d.cts +65 -16
- package/dist/ui/dropdown-menu.d.mts +65 -16
- package/dist/ui/dropdown-menu.mjs +1 -1
- package/dist/ui/empty.cjs +1 -1
- package/dist/ui/empty.cjs.map +1 -1
- package/dist/ui/empty.d.cts +41 -9
- package/dist/ui/empty.d.mts +41 -9
- package/dist/ui/empty.mjs +1 -1
- package/dist/ui/empty.mjs.map +1 -1
- package/dist/ui/field.cjs +1 -2
- package/dist/ui/field.d.cts +13 -13
- package/dist/ui/field.d.mts +24 -24
- package/dist/ui/field.mjs +1 -2
- package/dist/ui/file-uploader.cjs +2 -2
- package/dist/ui/file-uploader.cjs.map +1 -1
- package/dist/ui/file-uploader.d.cts +27 -2
- package/dist/ui/file-uploader.d.mts +27 -2
- package/dist/ui/file-uploader.mjs +2 -2
- package/dist/ui/file-uploader.mjs.map +1 -1
- package/dist/ui/form.cjs +1 -1
- package/dist/ui/form.cjs.map +1 -1
- package/dist/ui/form.d.cts +51 -7
- package/dist/ui/form.d.mts +55 -11
- package/dist/ui/form.mjs +1 -1
- package/dist/ui/form.mjs.map +1 -1
- package/dist/ui/hover-card.cjs +1 -1
- package/dist/ui/hover-card.cjs.map +1 -1
- package/dist/ui/hover-card.d.cts +22 -4
- package/dist/ui/hover-card.d.mts +22 -4
- package/dist/ui/hover-card.mjs +1 -1
- package/dist/ui/hover-card.mjs.map +1 -1
- package/dist/ui/image.cjs +1 -1
- package/dist/ui/image.d.cts +20 -0
- package/dist/ui/image.d.mts +20 -0
- package/dist/ui/image.mjs +1 -1
- package/dist/ui/input-otp.cjs +1 -1
- package/dist/ui/input-otp.cjs.map +1 -1
- package/dist/ui/input-otp.d.cts +36 -5
- package/dist/ui/input-otp.d.mts +36 -5
- package/dist/ui/input-otp.mjs +1 -1
- package/dist/ui/input-otp.mjs.map +1 -1
- package/dist/ui/input.cjs +1 -1
- 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.cjs +1 -1
- package/dist/ui/inputs/search-input.cjs.map +1 -1
- package/dist/ui/inputs/search-input.d.cts +20 -3
- package/dist/ui/inputs/search-input.d.mts +20 -3
- package/dist/ui/inputs/search-input.mjs +1 -1
- package/dist/ui/inputs/search-input.mjs.map +1 -1
- package/dist/ui/item.cjs +1 -1
- package/dist/ui/item.cjs.map +1 -1
- package/dist/ui/item.d.cts +56 -16
- package/dist/ui/item.d.mts +56 -16
- package/dist/ui/item.mjs +1 -1
- package/dist/ui/item.mjs.map +1 -1
- package/dist/ui/label.cjs +1 -1
- package/dist/ui/label.d.cts +15 -2
- package/dist/ui/label.d.mts +15 -2
- package/dist/ui/label.mjs +1 -1
- package/dist/ui/menubar.cjs +1 -1
- package/dist/ui/menubar.cjs.map +1 -1
- package/dist/ui/menubar.d.cts +68 -17
- package/dist/ui/menubar.d.mts +68 -17
- package/dist/ui/menubar.mjs +1 -1
- package/dist/ui/menubar.mjs.map +1 -1
- package/dist/ui/multi-select.cjs +1 -1
- package/dist/ui/multi-select.cjs.map +1 -1
- package/dist/ui/multi-select.d.cts +39 -2
- package/dist/ui/multi-select.d.mts +40 -3
- package/dist/ui/multi-select.mjs +1 -1
- package/dist/ui/multi-select.mjs.map +1 -1
- package/dist/ui/navigation-menu.cjs +1 -1
- package/dist/ui/navigation-menu.cjs.map +1 -1
- package/dist/ui/navigation-menu.d.cts +42 -11
- package/dist/ui/navigation-menu.d.mts +42 -11
- package/dist/ui/navigation-menu.mjs +1 -1
- package/dist/ui/navigation-menu.mjs.map +1 -1
- package/dist/ui/pagination.cjs +1 -1
- package/dist/ui/pagination.cjs.map +1 -1
- package/dist/ui/pagination.d.cts +37 -9
- package/dist/ui/pagination.d.mts +37 -9
- package/dist/ui/pagination.mjs +1 -1
- package/dist/ui/pagination.mjs.map +1 -1
- package/dist/ui/popover.cjs +1 -1
- package/dist/ui/popover.d.cts +32 -6
- package/dist/ui/popover.d.mts +32 -6
- package/dist/ui/popover.mjs +1 -1
- package/dist/ui/progress.cjs +1 -1
- package/dist/ui/progress.cjs.map +1 -1
- package/dist/ui/progress.d.cts +13 -2
- package/dist/ui/progress.d.mts +13 -2
- package/dist/ui/progress.mjs +1 -1
- package/dist/ui/progress.mjs.map +1 -1
- package/dist/ui/radio-group.cjs +1 -1
- package/dist/ui/radio-group.d.cts +25 -3
- package/dist/ui/radio-group.d.mts +25 -3
- package/dist/ui/radio-group.mjs +1 -1
- package/dist/ui/resizable.cjs +1 -1
- package/dist/ui/resizable.d.cts +29 -9
- package/dist/ui/resizable.d.mts +29 -9
- package/dist/ui/resizable.mjs +1 -1
- package/dist/ui/scroll-area.cjs +1 -1
- package/dist/ui/scroll-area.cjs.map +1 -1
- package/dist/ui/scroll-area.d.cts +24 -6
- package/dist/ui/scroll-area.d.mts +24 -6
- package/dist/ui/scroll-area.mjs +1 -1
- package/dist/ui/scroll-area.mjs.map +1 -1
- package/dist/ui/select.cjs +1 -1
- package/dist/ui/select.d.cts +43 -9
- package/dist/ui/select.d.mts +43 -9
- package/dist/ui/select.mjs +1 -1
- package/dist/ui/separator.cjs +1 -1
- package/dist/ui/separator.d.cts +23 -2
- package/dist/ui/separator.d.mts +23 -2
- package/dist/ui/separator.mjs +1 -1
- package/dist/ui/sheet.cjs +1 -1
- package/dist/ui/sheet.d.cts +38 -9
- package/dist/ui/sheet.d.mts +38 -9
- package/dist/ui/sheet.mjs +1 -1
- package/dist/ui/sidebar.cjs +1 -1
- package/dist/ui/sidebar.cjs.map +1 -1
- package/dist/ui/sidebar.d.cts +125 -28
- package/dist/ui/sidebar.d.mts +123 -26
- package/dist/ui/sidebar.mjs +1 -1
- package/dist/ui/sidebar.mjs.map +1 -1
- package/dist/ui/skeleton.cjs +1 -1
- package/dist/ui/skeleton.d.cts +19 -2
- package/dist/ui/skeleton.d.mts +19 -2
- package/dist/ui/skeleton.mjs +1 -1
- package/dist/ui/slider.cjs +1 -1
- package/dist/ui/slider.cjs.map +1 -1
- package/dist/ui/slider.d.cts +13 -2
- package/dist/ui/slider.d.mts +13 -2
- package/dist/ui/slider.mjs +1 -1
- package/dist/ui/slider.mjs.map +1 -1
- package/dist/ui/sonner.cjs +1 -1
- package/dist/ui/sonner.cjs.map +1 -1
- package/dist/ui/sonner.d.cts +18 -2
- package/dist/ui/sonner.d.mts +18 -2
- package/dist/ui/sonner.mjs +1 -1
- package/dist/ui/sonner.mjs.map +1 -1
- package/dist/ui/spinner.cjs +1 -1
- package/dist/ui/spinner.d.cts +17 -2
- package/dist/ui/spinner.d.mts +17 -2
- package/dist/ui/spinner.mjs +1 -1
- package/dist/ui/switch.cjs +1 -1
- package/dist/ui/switch.cjs.map +1 -1
- package/dist/ui/switch.d.cts +17 -2
- package/dist/ui/switch.d.mts +17 -2
- package/dist/ui/switch.mjs +1 -1
- package/dist/ui/switch.mjs.map +1 -1
- package/dist/ui/table.cjs +1 -1
- package/dist/ui/table.cjs.map +1 -1
- package/dist/ui/table.d.cts +44 -9
- package/dist/ui/table.d.mts +53 -18
- package/dist/ui/table.mjs +1 -1
- package/dist/ui/table.mjs.map +1 -1
- package/dist/ui/tabs.cjs +1 -1
- package/dist/ui/tabs.cjs.map +1 -1
- package/dist/ui/tabs.d.cts +26 -5
- package/dist/ui/tabs.d.mts +26 -5
- package/dist/ui/tabs.mjs +1 -1
- package/dist/ui/tabs.mjs.map +1 -1
- package/dist/ui/textarea.cjs +1 -1
- package/dist/ui/textarea.d.cts +18 -2
- package/dist/ui/textarea.d.mts +18 -2
- package/dist/ui/textarea.mjs +1 -1
- package/dist/ui/toggle-group.cjs +1 -1
- package/dist/ui/toggle-group.cjs.map +1 -1
- package/dist/ui/toggle-group.d.cts +19 -3
- package/dist/ui/toggle-group.d.mts +19 -3
- package/dist/ui/toggle-group.mjs +1 -1
- package/dist/ui/toggle-group.mjs.map +1 -1
- package/dist/ui/toggle.cjs +1 -1
- package/dist/ui/toggle.cjs.map +1 -1
- package/dist/ui/toggle.d.cts +15 -2
- package/dist/ui/toggle.d.mts +17 -4
- package/dist/ui/toggle.mjs +1 -1
- package/dist/ui/toggle.mjs.map +1 -1
- package/dist/ui/tooltip.cjs +1 -1
- package/dist/ui/tooltip.d.cts +37 -5
- package/dist/ui/tooltip.d.mts +37 -5
- package/dist/ui/tooltip.mjs +1 -1
- package/dist/user-BEyYLDNK.cjs +2 -0
- package/dist/user-BEyYLDNK.cjs.map +1 -0
- package/dist/user-DONsffqr.mjs +2 -0
- package/dist/user-DONsffqr.mjs.map +1 -0
- package/package.json +14 -5
- package/styles/theme.css +44 -23
- package/dist/avatar-DReNH6rV.mjs +0 -2
- package/dist/avatar-DReNH6rV.mjs.map +0 -1
- package/dist/avatar-aVxo69zP.cjs +0 -2
- package/dist/avatar-aVxo69zP.cjs.map +0 -1
- package/dist/badge-B4Fa7-J3.mjs +0 -2
- package/dist/badge-B4Fa7-J3.mjs.map +0 -1
- package/dist/badge-cvLJyaCA.cjs +0 -2
- package/dist/badge-cvLJyaCA.cjs.map +0 -1
- package/dist/button-BFcXpjqF.cjs +0 -2
- package/dist/button-BFcXpjqF.cjs.map +0 -1
- package/dist/button-BQTNG97Y.mjs +0 -2
- package/dist/button-BQTNG97Y.mjs.map +0 -1
- package/dist/button-BX8Kz9y6.d.cts +0 -59
- package/dist/button-Bo4oQsyD.d.mts +0 -59
- package/dist/button.variants-CS-Cmarr.cjs +0 -2
- package/dist/button.variants-CS-Cmarr.cjs.map +0 -1
- package/dist/button.variants-DRWf66hR.mjs +0 -2
- package/dist/button.variants-DRWf66hR.mjs.map +0 -1
- package/dist/calendar-CG-WMM8e.cjs.map +0 -1
- package/dist/calendar-CfOkrubO.mjs +0 -2
- package/dist/calendar-CfOkrubO.mjs.map +0 -1
- package/dist/checkbox-Bg2FiuQw.mjs.map +0 -1
- package/dist/checkbox-C0fSWwmD.cjs.map +0 -1
- package/dist/close-D_Ge7gnP.cjs +0 -2
- package/dist/close-DfuHB7kq.mjs +0 -2
- package/dist/command-DhBTNTqz.mjs.map +0 -1
- package/dist/command-_zpTaaIk.cjs.map +0 -1
- package/dist/data-display/user.cjs.map +0 -1
- package/dist/data-display/user.mjs.map +0 -1
- package/dist/date-By93kONr.mjs +0 -2
- package/dist/date-By93kONr.mjs.map +0 -1
- package/dist/date-em5f7hCx.cjs +0 -2
- package/dist/date-em5f7hCx.cjs.map +0 -1
- package/dist/dialog-CxELDK98.mjs +0 -2
- package/dist/dialog-CxELDK98.mjs.map +0 -1
- package/dist/dialog-DjRiV5vR.cjs +0 -2
- package/dist/dialog-DjRiV5vR.cjs.map +0 -1
- package/dist/dialog-PWeGBpsm.d.mts +0 -47
- package/dist/dialog-aSu9xFOW.d.cts +0 -47
- package/dist/dialogs/detail-dialog/components/sidebar.cjs.map +0 -1
- package/dist/dialogs/detail-dialog/components/sidebar.mjs.map +0 -1
- package/dist/dropdown-menu-B8GUTfTp.mjs +0 -2
- package/dist/dropdown-menu-B8GUTfTp.mjs.map +0 -1
- package/dist/dropdown-menu-BuyuU6uF.cjs +0 -2
- package/dist/dropdown-menu-BuyuU6uF.cjs.map +0 -1
- package/dist/features/search-modal/index.cjs.map +0 -1
- package/dist/features/search-modal/index.mjs.map +0 -1
- package/dist/features/tables/index.cjs.map +0 -1
- package/dist/features/tables/index.mjs.map +0 -1
- package/dist/features/tanstack-form/index.cjs.map +0 -1
- package/dist/features/tanstack-form/index.mjs.map +0 -1
- package/dist/flex-BP8sTi70.mjs.map +0 -1
- package/dist/flex-twCgWyx1.cjs.map +0 -1
- package/dist/heading--VmdIi7C.mjs +0 -2
- package/dist/heading--VmdIi7C.mjs.map +0 -1
- package/dist/heading-BEm5CCSE.cjs +0 -2
- package/dist/heading-BEm5CCSE.cjs.map +0 -1
- package/dist/image-CS_Q0WA7.mjs.map +0 -1
- package/dist/image-DuFv8sPr.cjs.map +0 -1
- package/dist/input-BFWWaN-v.cjs.map +0 -1
- package/dist/input-BgHvD7zf.d.mts +0 -25
- package/dist/input-DBtIgQB6.mjs.map +0 -1
- package/dist/input-DhQmoNrK.d.cts +0 -25
- package/dist/label-BzfsTrVt.cjs.map +0 -1
- package/dist/label-Dqr8nxWi.mjs +0 -2
- package/dist/label-Dqr8nxWi.mjs.map +0 -1
- package/dist/layouts/cms-layout/index.cjs.map +0 -1
- package/dist/layouts/cms-layout/index.mjs.map +0 -1
- package/dist/layouts/payment-layout/index.cjs.map +0 -1
- package/dist/layouts/payment-layout/index.mjs.map +0 -1
- package/dist/paragraph-B72bHMf7.cjs +0 -2
- package/dist/paragraph-B72bHMf7.cjs.map +0 -1
- package/dist/paragraph-moBSTPmT.mjs +0 -2
- package/dist/paragraph-moBSTPmT.mjs.map +0 -1
- package/dist/popover-BckwBuuD.mjs +0 -2
- package/dist/popover-BckwBuuD.mjs.map +0 -1
- package/dist/popover-DzDrgttC.cjs.map +0 -1
- package/dist/radio-group-CBhRsUjN.cjs.map +0 -1
- package/dist/radio-group-Cem8O6BK.mjs.map +0 -1
- package/dist/resizable-DXHfkbaz.mjs.map +0 -1
- package/dist/resizable-mlGS6Zto.cjs.map +0 -1
- package/dist/select-2CgwiefV.cjs.map +0 -1
- package/dist/select-CivtMKTM.mjs.map +0 -1
- package/dist/separator-Bf0gymN4.mjs +0 -2
- package/dist/separator-Bf0gymN4.mjs.map +0 -1
- package/dist/separator-C3ip6sbh.cjs.map +0 -1
- package/dist/sheet-5MJRtrfG.cjs.map +0 -1
- package/dist/sheet-oadGRiie.mjs.map +0 -1
- package/dist/skeleton-Ba6koCVf.mjs +0 -2
- package/dist/skeleton-Ba6koCVf.mjs.map +0 -1
- package/dist/skeleton-CHympz8k.cjs +0 -2
- package/dist/skeleton-CHympz8k.cjs.map +0 -1
- package/dist/spinner-Chm_2fLr.cjs +0 -2
- package/dist/spinner-Chm_2fLr.cjs.map +0 -1
- package/dist/spinner-D1v3Bard.mjs +0 -2
- package/dist/spinner-D1v3Bard.mjs.map +0 -1
- package/dist/textarea-COQoSVSc.cjs.map +0 -1
- package/dist/textarea-bLtmb71c.mjs.map +0 -1
- package/dist/tooltip-B3dTcgcc.mjs +0 -2
- package/dist/tooltip-B3dTcgcc.mjs.map +0 -1
- package/dist/tooltip-DC6i1A25.cjs.map +0 -1
- package/dist/ui/alert.cjs.map +0 -1
- package/dist/ui/alert.mjs.map +0 -1
- package/dist/ui/field.cjs.map +0 -1
- package/dist/ui/field.mjs.map +0 -1
package/dist/ui/field.d.mts
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
1
|
import { Label } from "./label.mjs";
|
|
2
|
+
import * as react19 from "react";
|
|
3
|
+
import * as react_jsx_runtime203 from "react/jsx-runtime";
|
|
2
4
|
import { VariantProps } from "class-variance-authority";
|
|
3
|
-
import * as
|
|
4
|
-
import * as react_jsx_runtime278 from "react/jsx-runtime";
|
|
5
|
-
import * as class_variance_authority_types11 from "class-variance-authority/types";
|
|
5
|
+
import * as class_variance_authority_types12 from "class-variance-authority/types";
|
|
6
6
|
|
|
7
7
|
//#region packages/components/ui/field.d.ts
|
|
8
|
-
declare const FieldSet:
|
|
8
|
+
declare const FieldSet: react19.MemoExoticComponent<({
|
|
9
9
|
className,
|
|
10
10
|
...props
|
|
11
|
-
}: React.ComponentProps<"fieldset">) =>
|
|
12
|
-
declare const FieldLegend:
|
|
11
|
+
}: React.ComponentProps<"fieldset">) => react_jsx_runtime203.JSX.Element>;
|
|
12
|
+
declare const FieldLegend: react19.MemoExoticComponent<({
|
|
13
13
|
className,
|
|
14
14
|
variant,
|
|
15
15
|
...props
|
|
16
16
|
}: React.ComponentProps<"legend"> & {
|
|
17
17
|
variant?: "legend" | "label";
|
|
18
|
-
}) =>
|
|
19
|
-
declare const FieldGroup:
|
|
18
|
+
}) => react_jsx_runtime203.JSX.Element>;
|
|
19
|
+
declare const FieldGroup: react19.MemoExoticComponent<({
|
|
20
20
|
className,
|
|
21
21
|
...props
|
|
22
|
-
}: React.ComponentProps<"div">) =>
|
|
22
|
+
}: React.ComponentProps<"div">) => react_jsx_runtime203.JSX.Element>;
|
|
23
23
|
declare const fieldVariants: (props?: ({
|
|
24
24
|
orientation?: "vertical" | "horizontal" | "responsive" | null | undefined;
|
|
25
|
-
} &
|
|
26
|
-
declare const Field:
|
|
25
|
+
} & class_variance_authority_types12.ClassProp) | undefined) => string;
|
|
26
|
+
declare const Field: react19.MemoExoticComponent<({
|
|
27
27
|
className,
|
|
28
28
|
orientation,
|
|
29
29
|
...props
|
|
30
|
-
}: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) =>
|
|
31
|
-
declare const FieldContent:
|
|
30
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) => react_jsx_runtime203.JSX.Element>;
|
|
31
|
+
declare const FieldContent: react19.MemoExoticComponent<({
|
|
32
32
|
className,
|
|
33
33
|
...props
|
|
34
|
-
}: React.ComponentProps<"div">) =>
|
|
35
|
-
declare const FieldLabel:
|
|
34
|
+
}: React.ComponentProps<"div">) => react_jsx_runtime203.JSX.Element>;
|
|
35
|
+
declare const FieldLabel: react19.MemoExoticComponent<({
|
|
36
36
|
className,
|
|
37
37
|
...props
|
|
38
|
-
}: React.ComponentProps<typeof Label>) =>
|
|
39
|
-
declare const FieldTitle:
|
|
38
|
+
}: React.ComponentProps<typeof Label>) => react_jsx_runtime203.JSX.Element>;
|
|
39
|
+
declare const FieldTitle: react19.MemoExoticComponent<({
|
|
40
40
|
className,
|
|
41
41
|
...props
|
|
42
|
-
}: React.ComponentProps<"div">) =>
|
|
43
|
-
declare const FieldDescription:
|
|
42
|
+
}: React.ComponentProps<"div">) => react_jsx_runtime203.JSX.Element>;
|
|
43
|
+
declare const FieldDescription: react19.MemoExoticComponent<({
|
|
44
44
|
className,
|
|
45
45
|
...props
|
|
46
|
-
}: React.ComponentProps<"p">) =>
|
|
47
|
-
declare const FieldSeparator:
|
|
46
|
+
}: React.ComponentProps<"p">) => react_jsx_runtime203.JSX.Element>;
|
|
47
|
+
declare const FieldSeparator: react19.MemoExoticComponent<({
|
|
48
48
|
children,
|
|
49
49
|
className,
|
|
50
50
|
...props
|
|
51
51
|
}: React.ComponentProps<"div"> & {
|
|
52
52
|
children?: React.ReactNode;
|
|
53
|
-
}) =>
|
|
54
|
-
declare const FieldError:
|
|
53
|
+
}) => react_jsx_runtime203.JSX.Element>;
|
|
54
|
+
declare const FieldError: react19.MemoExoticComponent<({
|
|
55
55
|
className,
|
|
56
56
|
children,
|
|
57
57
|
errors,
|
|
@@ -60,7 +60,7 @@ declare const FieldError: react16.MemoExoticComponent<({
|
|
|
60
60
|
errors?: Array<{
|
|
61
61
|
message?: string;
|
|
62
62
|
} | undefined>;
|
|
63
|
-
}) =>
|
|
63
|
+
}) => react_jsx_runtime203.JSX.Element | null>;
|
|
64
64
|
//#endregion
|
|
65
65
|
export { Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle };
|
|
66
66
|
//# sourceMappingURL=field.d.mts.map
|
package/dist/ui/field.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
"use client";import
|
|
2
|
-
//# sourceMappingURL=field.mjs.map
|
|
1
|
+
"use client";import"../separator-BMsbHAVt.mjs";import"../label-OmlGaZ5h.mjs";import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c,u as l}from"../field-CXVnw75a.mjs";export{c as Field,i as FieldContent,o as FieldDescription,n as FieldError,e as FieldGroup,a as FieldLabel,s as FieldLegend,t as FieldSeparator,r as FieldSet,l as FieldTitle};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use client";const e=require(`../chunk-Bmb41Sf3.cjs`);require(`../button.variants-
|
|
2
|
-
files (up to ${(0,
|
|
1
|
+
"use client";const e=require(`../chunk-Bmb41Sf3.cjs`);require(`../button.variants-tnhb123u.cjs`);const t=require(`../button-CwDT3m4m.cjs`),n=require(`./progress.cjs`);let r=require(`lucide-react`),i=require(`react`),a=require(`react/jsx-runtime`),o=require(`@customafk/react-toolkit/utils`),s=require(`react-dropzone`);s=e.t(s);let c=require(`@customafk/react-toolkit/hooks/useControllableState`),l=require(`sonner`);function u(e){let{value:t,onValueChange:n,onUpload:u,progresses:p,accept:m={"image/*":[]},maxSize:h=1024*1024*2,maxFileCount:g=1,multiple:_=!1,disabled:v=!1,showText:y=!0,iconSize:b,className:x,...S}=e,[C,w]=(0,c.useControllableState)({prop:t,onChange:n}),T=(0,i.useCallback)((e,t)=>{if(!_&&g===1&&e.length>1){l.toast.error(`Cannot upload more than 1 file at a time`);return}if((C?.length??0)+e.length>g){l.toast.error(`Cannot upload more than ${g} files`);return}let n=e.map(e=>Object.assign(e,{preview:URL.createObjectURL(e)})),r=C?[...C,...n]:n;if(w(r),t.length>0&&t.forEach(({file:e})=>{l.toast.error(`File ${e.name} was rejected`)}),u&&r.length>0&&r.length<=g){let e=r.length>0?`${r.length} files`:`file`;u(r).then(()=>{w([]),(0,l.toast)(`${e} uploaded`)})}},[C,g,_,u,w]);function E(e){if(!C)return;f(C[e])&&URL.revokeObjectURL(C[e].preview);let t=C.filter((t,n)=>n!==e);w(t),n?.(t)}(0,i.useEffect)(()=>()=>{C&&C.forEach(e=>{f(e)&&URL.revokeObjectURL(e.preview)})},[]);let D=v||(C?.length??0)>=g;return(0,a.jsxs)(`div`,{className:`relative flex w-full flex-col gap-6`,children:[(0,a.jsx)(s.default,{onDrop:T,accept:m,maxSize:h,maxFiles:g,multiple:g>1||_,disabled:D,children:({getRootProps:e,getInputProps:t,isDragActive:n})=>(0,a.jsxs)(`div`,{...e(),className:(0,o.cn)(`group`,`border-border-weak`,`hover:bg-border-weak/20`,`relative grid h-52 w-full cursor-pointer place-items-center rounded-lg border-2 border-dashed px-5 py-2.5 text-center transition`,`ring-offset-background`,`focus-visible:ring-primary-weak`,`focus-visible:ring-2`,`focus-visible:ring-offset-2`,`focus-visible:outline-hidden`,n&&`border-border-primary-strong bg-border-weak/40`,D&&`pointer-events-none opacity-60`,x),...S,children:[(0,a.jsx)(`input`,{...t()}),n?(0,a.jsxs)(`div`,{className:`flex flex-col items-center justify-center gap-4 sm:px-5`,children:[(0,a.jsx)(`div`,{className:`rounded-full border border-dashed p-3`,children:(0,a.jsx)(r.Upload,{className:`text-text-positive-muted size-7`,"aria-hidden":`true`})}),(0,a.jsx)(`p`,{className:`text-text-positive-muted font-medium`,children:`Drop the files here`})]}):(0,a.jsxs)(`div`,{className:`flex flex-col items-center justify-center gap-4 sm:px-5`,children:[(0,a.jsx)(`div`,{className:`rounded-full border border-dashed p-3`,children:(0,a.jsx)(r.Upload,{size:b||24,className:`text-muted-foreground`,"aria-hidden":`true`})}),y&&(0,a.jsxs)(`div`,{className:`flex flex-col gap-px`,children:[(0,a.jsxs)(`p`,{className:`text-text-positive-weak text-xs font-medium`,children:[`Drag `,`'n'`,` drop files here, or click to select files`]}),(0,a.jsxs)(`p`,{className:`text-text-positive-muted text-xs`,children:[`You can upload`,g>1?` ${g===1/0?`multiple`:g}
|
|
2
|
+
files (up to ${(0,o.formatBytes)(h)} each)`:` a file with ${(0,o.formatBytes)(h)}`]})]})]})]})}),C?.length?(0,a.jsxs)(`div`,{className:`h-fit w-full overflow-y-auto`,children:[(0,a.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2.5`,children:[(0,a.jsxs)(`div`,{className:`text-text-positive-weak flex items-center gap-1`,children:[(0,a.jsx)(r.Image,{size:16,"aria-hidden":`true`}),(0,a.jsxs)(`p`,{className:`text-sm`,children:[`Ảnh đã tải lên (`,C.length,`)`]})]}),(0,a.jsxs)(`button`,{className:`hover:text-text-positive text-text-positive-muted flex cursor-pointer items-center gap-1 transition-colors duration-200`,onClick:()=>{C&&(C.forEach(e=>{f(e)&&URL.revokeObjectURL(e.preview)}),w([]),n?.([]))},children:[(0,a.jsx)(r.Trash2,{size:16,"aria-hidden":`true`}),(0,a.jsx)(`p`,{className:`text-sm`,children:`Xóa tất cả`})]})]}),(0,a.jsx)(`div`,{className:`flex flex-col gap-2.5`,children:C?.map((e,t)=>(0,a.jsx)(d,{file:e,onRemove:()=>E(t),progress:p?.[e.name]},t))})]}):null]})}function d({file:e,progress:i,onRemove:s}){return(0,a.jsxs)(`div`,{className:`border-border-weak hover:border-border relative flex items-center gap-4 rounded-md border py-2 pr-3 pl-2 shadow-xs transition-colors`,children:[(0,a.jsxs)(`div`,{className:`flex flex-1 gap-2.5`,children:[f(e)?(0,a.jsx)(p,{file:e}):null,(0,a.jsxs)(`div`,{className:`flex w-full flex-col gap-2`,children:[(0,a.jsxs)(`div`,{className:`flex flex-col gap-y-0.5`,children:[(0,a.jsx)(`p`,{className:`text-text-positive line-clamp-1 text-sm`,children:e.name}),(0,a.jsx)(`p`,{className:`text-text-positive-muted text-xs`,children:(0,o.formatBytes)(e.size)})]}),i?(0,a.jsx)(n.Progress,{value:i}):null]})]}),(0,a.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,a.jsxs)(t.t,{type:`button`,variant:`ghost`,color:`secondary`,size:`icon`,className:`size-7`,onClick:s,children:[(0,a.jsx)(r.Trash2,{size:16,className:`text-text-positive-muted`,"aria-hidden":`true`}),(0,a.jsx)(`span`,{className:`sr-only`,children:`Remove file`})]})})]})}function f(e){return`preview`in e&&typeof e.preview==`string`}function p({file:e}){return e.type.startsWith(`image/`)?(0,a.jsx)(`img`,{src:e.preview,className:`border-border aspect-square size-10 shrink-0 rounded border object-cover object-top shadow-sm`}):(0,a.jsx)(r.FileText,{className:`text-text-positive-muted size-10 border`,"aria-hidden":`true`})}exports.FileUploader=u;
|
|
3
3
|
//# sourceMappingURL=file-uploader.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-uploader.cjs","names":["Dropzone","Upload","Image","Trash2","Progress","Button","FileText"],"sources":["../../packages/components/ui/file-uploader.tsx"],"sourcesContent":["'use client';\nimport { useCallback, useEffect } from 'react';\nimport Dropzone, { type DropzoneProps, type FileRejection } from 'react-dropzone';\nimport { useControllableState } from '@customafk/react-toolkit/hooks/useControllableState';\nimport { cn, formatBytes } from '@customafk/react-toolkit/utils';\n\nimport { FileText, Image, Trash2, Upload } from 'lucide-react';\nimport { toast } from 'sonner';\n\nimport { Button } from '@/components/ui/button';\nimport { Progress } from '@/components/ui/progress';\n\ninterface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Value of the uploader.\n * @type File[]\n * @default undefined\n * @example value={files}\n */\n value?: File[];\n\n /**\n * Function to be called when the value changes.\n * @type (files: File[]) => void\n * @default undefined\n * @example onValueChange={(files) => setFiles(files)}\n */\n onValueChange?: (files: File[]) => void;\n\n /**\n * Function to be called when files are uploaded.\n * @type (files: File[]) => Promise<void>\n * @default undefined\n * @example onUpload={(files) => uploadFiles(files)}\n */\n onUpload?: (files: File[]) => Promise<void>;\n\n /**\n * Progress of the uploaded files.\n * @type Record<string, number> | undefined\n * @default undefined\n * @example progresses={{ \"file1.png\": 50 }}\n */\n progresses?: Record<string, number>;\n\n /**\n * Accepted file types for the uploader.\n * @type { [key: string]: string[]}\n * @default\n * ```ts\n * { \"image/*\": [] }\n * ```\n * @example accept={[\"image/png\", \"image/jpeg\"]}\n */\n accept?: DropzoneProps['accept'];\n\n /**\n * Maximum file size for the uploader.\n * @type number | undefined\n * @default 1024 * 1024 * 2 // 2MB\n * @example maxSize={1024 * 1024 * 2} // 2MB\n */\n maxSize?: DropzoneProps['maxSize'];\n\n /**\n * Maximum number of files for the uploader.\n * @type number | undefined\n * @default 1\n * @example maxFileCount={4}\n */\n maxFileCount?: DropzoneProps['maxFiles'];\n\n /**\n * Whether the uploader should accept multiple files.\n * @type boolean\n * @default false\n * @example multiple\n */\n multiple?: boolean;\n\n /**\n * Whether the uploader is disabled.\n * @type boolean\n * @default false\n * @example disabled\n */\n disabled?: boolean;\n\n showText?: boolean;\n iconSize?: number;\n}\n\nexport function FileUploader(props: FileUploaderProps) {\n const {\n value: valueProp,\n onValueChange,\n onUpload,\n progresses,\n accept = {\n 'image/*': [],\n },\n maxSize = 1024 * 1024 * 2,\n maxFileCount = 1,\n multiple = false,\n disabled = false,\n showText = true,\n iconSize,\n className,\n ...dropzoneProps\n } = props;\n\n const [files, setFiles] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n });\n\n const onDrop = useCallback(\n (acceptedFiles: File[], rejectedFiles: FileRejection[]) => {\n if (!multiple && maxFileCount === 1 && acceptedFiles.length > 1) {\n toast.error('Cannot upload more than 1 file at a time');\n\n return;\n }\n\n if ((files?.length ?? 0) + acceptedFiles.length > maxFileCount) {\n toast.error(`Cannot upload more than ${maxFileCount} files`);\n return;\n }\n\n const newFiles = acceptedFiles.map(file =>\n Object.assign(file, {\n preview: URL.createObjectURL(file),\n })\n );\n\n const updatedFiles = files ? [...files, ...newFiles] : newFiles;\n\n setFiles(updatedFiles);\n\n if (rejectedFiles.length > 0) {\n rejectedFiles.forEach(({ file }) => {\n toast.error(`File ${file.name} was rejected`);\n });\n }\n\n if (onUpload && updatedFiles.length > 0 && updatedFiles.length <= maxFileCount) {\n const target = updatedFiles.length > 0 ? `${updatedFiles.length} files` : `file`;\n\n onUpload(updatedFiles).then(() => {\n setFiles([]);\n toast(`${target} uploaded`);\n });\n }\n },\n\n [files, maxFileCount, multiple, onUpload, setFiles]\n );\n\n function onRemove(index: number) {\n if (!files) return;\n\n if (isFileWithPreview(files[index])) {\n URL.revokeObjectURL(files[index].preview);\n }\n\n const newFiles = files.filter((_, i) => i !== index);\n setFiles(newFiles);\n onValueChange?.(newFiles);\n }\n\n // Revoke preview url when component unmounts\n useEffect(() => {\n return () => {\n if (!files) return;\n files.forEach(file => {\n if (isFileWithPreview(file)) {\n URL.revokeObjectURL(file.preview);\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const isDisabled = disabled || (files?.length ?? 0) >= maxFileCount;\n\n return (\n <div className=\"relative flex w-full flex-col gap-6\">\n <Dropzone onDrop={onDrop} accept={accept} maxSize={maxSize} maxFiles={maxFileCount} multiple={maxFileCount > 1 || multiple} disabled={isDisabled}>\n {({ getRootProps, getInputProps, isDragActive }) => (\n <div\n {...getRootProps()}\n className={cn(\n 'group',\n 'border-border-weak',\n 'hover:bg-border-weak/20',\n 'relative grid h-52 w-full cursor-pointer place-items-center rounded-lg border-2 border-dashed px-5 py-2.5 text-center transition',\n 'ring-offset-background',\n 'focus-visible:ring-primary-weak',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-2',\n 'focus-visible:outline-hidden',\n isDragActive && 'border-border-primary-strong bg-border-weak/40',\n isDisabled && 'pointer-events-none opacity-60',\n className\n )}\n {...dropzoneProps}\n >\n <input {...getInputProps()} />\n {isDragActive ? (\n <div className=\"flex flex-col items-center justify-center gap-4 sm:px-5\">\n <div className=\"rounded-full border border-dashed p-3\">\n <Upload className=\"text-text-positive-muted size-7\" aria-hidden=\"true\" />\n </div>\n <p className=\"text-text-positive-muted font-medium\">Drop the files here</p>\n </div>\n ) : (\n <div className=\"flex flex-col items-center justify-center gap-4 sm:px-5\">\n <div className=\"rounded-full border border-dashed p-3\">\n <Upload size={iconSize || 24} className=\"text-muted-foreground\" aria-hidden=\"true\" />\n </div>\n {showText && (\n <div className=\"flex flex-col gap-px\">\n <p className=\"text-text-positive-weak text-xs font-medium\">Drag {`'n'`} drop files here, or click to select files</p>\n <p className=\"text-text-positive-muted text-xs\">\n You can upload\n {maxFileCount > 1\n ? ` ${maxFileCount === Infinity ? 'multiple' : maxFileCount}\n files (up to ${formatBytes(maxSize)} each)`\n : ` a file with ${formatBytes(maxSize)}`}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </Dropzone>\n {files?.length ? (\n <div className=\"h-fit w-full overflow-y-auto\">\n <div className=\"flex items-center justify-between px-3 py-2.5\">\n <div className=\"text-text-positive-weak flex items-center gap-1\">\n <Image size={16} aria-hidden=\"true\" />\n <p className=\"text-sm\">Ảnh đã tải lên ({files.length})</p>\n </div>\n <button\n className=\"hover:text-text-positive text-text-positive-muted flex cursor-pointer items-center gap-1 transition-colors duration-200\"\n onClick={() => {\n if (!files) return;\n files.forEach(file => {\n if (!isFileWithPreview(file)) return;\n URL.revokeObjectURL(file.preview);\n });\n setFiles([]);\n onValueChange?.([]);\n }}\n >\n <Trash2 size={16} aria-hidden=\"true\" />\n <p className=\"text-sm\">Xóa tất cả</p>\n </button>\n </div>\n <div className=\"flex flex-col gap-2.5\">\n {files?.map((file, index) => (\n <FileCard key={index} file={file} onRemove={() => onRemove(index)} progress={progresses?.[file.name]} />\n ))}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\ninterface FileCardProps {\n file: File;\n onRemove: () => void;\n progress?: number;\n}\n\nfunction FileCard({ file, progress, onRemove }: FileCardProps) {\n return (\n <div className=\"border-border-weak hover:border-border relative flex items-center gap-4 rounded-md border py-2 pr-3 pl-2 shadow-xs transition-colors\">\n <div className=\"flex flex-1 gap-2.5\">\n {isFileWithPreview(file) ? <FilePreview file={file} /> : null}\n <div className=\"flex w-full flex-col gap-2\">\n <div className=\"flex flex-col gap-y-0.5\">\n <p className=\"text-text-positive line-clamp-1 text-sm\">{file.name}</p>\n <p className=\"text-text-positive-muted text-xs\">{formatBytes(file.size)}</p>\n </div>\n {progress ? <Progress value={progress} /> : null}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"ghost\" color=\"secondary\" size=\"icon\" className=\"size-7\" onClick={onRemove}>\n <Trash2 size={16} className=\"text-text-positive-muted\" aria-hidden=\"true\" />\n <span className=\"sr-only\">Remove file</span>\n </Button>\n </div>\n </div>\n );\n}\n\nfunction isFileWithPreview(file: File): file is File & { preview: string } {\n return 'preview' in file && typeof file.preview === 'string';\n}\n\ninterface FilePreviewProps {\n file: File & { preview: string };\n}\n\nfunction FilePreview({ file }: FilePreviewProps) {\n if (file.type.startsWith('image/')) {\n return <img src={file.preview} className=\"border-border aspect-square size-10 shrink-0 rounded border object-cover object-top shadow-sm\" />;\n }\n\n return <FileText className=\"text-text-positive-muted size-10 border\" aria-hidden=\"true\" />;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-uploader.cjs","names":["Dropzone","Upload","Image","Trash2","Progress","Button","FileText"],"sources":["../../packages/components/ui/file-uploader.tsx"],"sourcesContent":["'use client';\nimport { useCallback, useEffect } from 'react';\nimport Dropzone, { type DropzoneProps, type FileRejection } from 'react-dropzone';\nimport { useControllableState } from '@customafk/react-toolkit/hooks/useControllableState';\nimport { cn, formatBytes } from '@customafk/react-toolkit/utils';\n\nimport { FileText, Image, Trash2, Upload } from 'lucide-react';\nimport { toast } from 'sonner';\n\nimport { Button } from '@/components/ui/button';\nimport { Progress } from '@/components/ui/progress';\n\n/**\n * Props for the FileUploader component.\n *\n * @example\n * ```tsx\n * import { FileUploader } from '@customafk/lunas-ui/ui/file-uploader';\n *\n * <FileUploader\n * accept={{ 'image/*': [] }}\n * maxSize={1024 * 1024 * 5}\n * maxFileCount={3}\n * multiple\n * onUpload={async (files) => { await uploadFiles(files); }}\n * />\n * ```\n */\ninterface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Value of the uploader.\n * @type File[]\n * @default undefined\n * @example value={files}\n */\n value?: File[];\n\n /**\n * Function to be called when the value changes.\n * @type (files: File[]) => void\n * @default undefined\n * @example onValueChange={(files) => setFiles(files)}\n */\n onValueChange?: (files: File[]) => void;\n\n /**\n * Function to be called when files are uploaded.\n * @type (files: File[]) => Promise<void>\n * @default undefined\n * @example onUpload={(files) => uploadFiles(files)}\n */\n onUpload?: (files: File[]) => Promise<void>;\n\n /**\n * Progress of the uploaded files.\n * @type Record<string, number> | undefined\n * @default undefined\n * @example progresses={{ \"file1.png\": 50 }}\n */\n progresses?: Record<string, number>;\n\n /**\n * Accepted file types for the uploader.\n * @type { [key: string]: string[]}\n * @default\n * ```ts\n * { \"image/*\": [] }\n * ```\n * @example accept={[\"image/png\", \"image/jpeg\"]}\n */\n accept?: DropzoneProps['accept'];\n\n /**\n * Maximum file size for the uploader.\n * @type number | undefined\n * @default 1024 * 1024 * 2 // 2MB\n * @example maxSize={1024 * 1024 * 2} // 2MB\n */\n maxSize?: DropzoneProps['maxSize'];\n\n /**\n * Maximum number of files for the uploader.\n * @type number | undefined\n * @default 1\n * @example maxFileCount={4}\n */\n maxFileCount?: DropzoneProps['maxFiles'];\n\n /**\n * Whether the uploader should accept multiple files.\n * @type boolean\n * @default false\n * @example multiple\n */\n multiple?: boolean;\n\n /**\n * Whether the uploader is disabled.\n * @type boolean\n * @default false\n * @example disabled\n */\n disabled?: boolean;\n\n /**\n * Whether to show the instructional drag-and-drop text inside the drop zone.\n * @default true\n */\n showText?: boolean;\n /** Size in pixels for the upload icon. */\n iconSize?: number;\n}\n\n/**\n * A drag-and-drop file upload zone that manages file selection, validation, preview generation, and optional async upload with progress tracking.\n */\nexport function FileUploader(props: FileUploaderProps) {\n const {\n value: valueProp,\n onValueChange,\n onUpload,\n progresses,\n accept = {\n 'image/*': [],\n },\n maxSize = 1024 * 1024 * 2,\n maxFileCount = 1,\n multiple = false,\n disabled = false,\n showText = true,\n iconSize,\n className,\n ...dropzoneProps\n } = props;\n\n const [files, setFiles] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n });\n\n const onDrop = useCallback(\n (acceptedFiles: File[], rejectedFiles: FileRejection[]) => {\n if (!multiple && maxFileCount === 1 && acceptedFiles.length > 1) {\n toast.error('Cannot upload more than 1 file at a time');\n\n return;\n }\n\n if ((files?.length ?? 0) + acceptedFiles.length > maxFileCount) {\n toast.error(`Cannot upload more than ${maxFileCount} files`);\n return;\n }\n\n const newFiles = acceptedFiles.map(file =>\n Object.assign(file, {\n preview: URL.createObjectURL(file),\n })\n );\n\n const updatedFiles = files ? [...files, ...newFiles] : newFiles;\n\n setFiles(updatedFiles);\n\n if (rejectedFiles.length > 0) {\n rejectedFiles.forEach(({ file }) => {\n toast.error(`File ${file.name} was rejected`);\n });\n }\n\n if (onUpload && updatedFiles.length > 0 && updatedFiles.length <= maxFileCount) {\n const target = updatedFiles.length > 0 ? `${updatedFiles.length} files` : `file`;\n\n onUpload(updatedFiles).then(() => {\n setFiles([]);\n toast(`${target} uploaded`);\n });\n }\n },\n\n [files, maxFileCount, multiple, onUpload, setFiles]\n );\n\n function onRemove(index: number) {\n if (!files) return;\n\n if (isFileWithPreview(files[index])) {\n URL.revokeObjectURL(files[index].preview);\n }\n\n const newFiles = files.filter((_, i) => i !== index);\n setFiles(newFiles);\n onValueChange?.(newFiles);\n }\n\n // Revoke preview url when component unmounts\n useEffect(() => {\n return () => {\n if (!files) return;\n files.forEach(file => {\n if (isFileWithPreview(file)) {\n URL.revokeObjectURL(file.preview);\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const isDisabled = disabled || (files?.length ?? 0) >= maxFileCount;\n\n return (\n <div className=\"relative flex w-full flex-col gap-6\">\n <Dropzone onDrop={onDrop} accept={accept} maxSize={maxSize} maxFiles={maxFileCount} multiple={maxFileCount > 1 || multiple} disabled={isDisabled}>\n {({ getRootProps, getInputProps, isDragActive }) => (\n <div\n {...getRootProps()}\n className={cn(\n 'group',\n 'border-border-weak',\n 'hover:bg-border-weak/20',\n 'relative grid h-52 w-full cursor-pointer place-items-center rounded-lg border-2 border-dashed px-5 py-2.5 text-center transition',\n 'ring-offset-background',\n 'focus-visible:ring-primary-weak',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-2',\n 'focus-visible:outline-hidden',\n isDragActive && 'border-border-primary-strong bg-border-weak/40',\n isDisabled && 'pointer-events-none opacity-60',\n className\n )}\n {...dropzoneProps}\n >\n <input {...getInputProps()} />\n {isDragActive ? (\n <div className=\"flex flex-col items-center justify-center gap-4 sm:px-5\">\n <div className=\"rounded-full border border-dashed p-3\">\n <Upload className=\"text-text-positive-muted size-7\" aria-hidden=\"true\" />\n </div>\n <p className=\"text-text-positive-muted font-medium\">Drop the files here</p>\n </div>\n ) : (\n <div className=\"flex flex-col items-center justify-center gap-4 sm:px-5\">\n <div className=\"rounded-full border border-dashed p-3\">\n <Upload size={iconSize || 24} className=\"text-muted-foreground\" aria-hidden=\"true\" />\n </div>\n {showText && (\n <div className=\"flex flex-col gap-px\">\n <p className=\"text-text-positive-weak text-xs font-medium\">Drag {`'n'`} drop files here, or click to select files</p>\n <p className=\"text-text-positive-muted text-xs\">\n You can upload\n {maxFileCount > 1\n ? ` ${maxFileCount === Infinity ? 'multiple' : maxFileCount}\n files (up to ${formatBytes(maxSize)} each)`\n : ` a file with ${formatBytes(maxSize)}`}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </Dropzone>\n {files?.length ? (\n <div className=\"h-fit w-full overflow-y-auto\">\n <div className=\"flex items-center justify-between px-3 py-2.5\">\n <div className=\"text-text-positive-weak flex items-center gap-1\">\n <Image size={16} aria-hidden=\"true\" />\n <p className=\"text-sm\">Ảnh đã tải lên ({files.length})</p>\n </div>\n <button\n className=\"hover:text-text-positive text-text-positive-muted flex cursor-pointer items-center gap-1 transition-colors duration-200\"\n onClick={() => {\n if (!files) return;\n files.forEach(file => {\n if (!isFileWithPreview(file)) return;\n URL.revokeObjectURL(file.preview);\n });\n setFiles([]);\n onValueChange?.([]);\n }}\n >\n <Trash2 size={16} aria-hidden=\"true\" />\n <p className=\"text-sm\">Xóa tất cả</p>\n </button>\n </div>\n <div className=\"flex flex-col gap-2.5\">\n {files?.map((file, index) => (\n <FileCard key={index} file={file} onRemove={() => onRemove(index)} progress={progresses?.[file.name]} />\n ))}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\ninterface FileCardProps {\n file: File;\n onRemove: () => void;\n progress?: number;\n}\n\nfunction FileCard({ file, progress, onRemove }: FileCardProps) {\n return (\n <div className=\"border-border-weak hover:border-border relative flex items-center gap-4 rounded-md border py-2 pr-3 pl-2 shadow-xs transition-colors\">\n <div className=\"flex flex-1 gap-2.5\">\n {isFileWithPreview(file) ? <FilePreview file={file} /> : null}\n <div className=\"flex w-full flex-col gap-2\">\n <div className=\"flex flex-col gap-y-0.5\">\n <p className=\"text-text-positive line-clamp-1 text-sm\">{file.name}</p>\n <p className=\"text-text-positive-muted text-xs\">{formatBytes(file.size)}</p>\n </div>\n {progress ? <Progress value={progress} /> : null}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"ghost\" color=\"secondary\" size=\"icon\" className=\"size-7\" onClick={onRemove}>\n <Trash2 size={16} className=\"text-text-positive-muted\" aria-hidden=\"true\" />\n <span className=\"sr-only\">Remove file</span>\n </Button>\n </div>\n </div>\n );\n}\n\nfunction isFileWithPreview(file: File): file is File & { preview: string } {\n return 'preview' in file && typeof file.preview === 'string';\n}\n\ninterface FilePreviewProps {\n file: File & { preview: string };\n}\n\nfunction FilePreview({ file }: FilePreviewProps) {\n if (file.type.startsWith('image/')) {\n return <img src={file.preview} className=\"border-border aspect-square size-10 shrink-0 rounded border object-cover object-top shadow-sm\" />;\n }\n\n return <FileText className=\"text-text-positive-muted size-10 border\" aria-hidden=\"true\" />;\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,24 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime168 from "react/jsx-runtime";
|
|
2
2
|
import { DropzoneProps } from "react-dropzone";
|
|
3
3
|
|
|
4
4
|
//#region packages/components/ui/file-uploader.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Props for the FileUploader component.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { FileUploader } from '@customafk/lunas-ui/ui/file-uploader';
|
|
12
|
+
*
|
|
13
|
+
* <FileUploader
|
|
14
|
+
* accept={{ 'image/*': [] }}
|
|
15
|
+
* maxSize={1024 * 1024 * 5}
|
|
16
|
+
* maxFileCount={3}
|
|
17
|
+
* multiple
|
|
18
|
+
* onUpload={async (files) => { await uploadFiles(files); }}
|
|
19
|
+
* />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
5
22
|
interface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
23
|
/**
|
|
7
24
|
* Value of the uploader.
|
|
@@ -69,10 +86,18 @@ interface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
69
86
|
* @example disabled
|
|
70
87
|
*/
|
|
71
88
|
disabled?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Whether to show the instructional drag-and-drop text inside the drop zone.
|
|
91
|
+
* @default true
|
|
92
|
+
*/
|
|
72
93
|
showText?: boolean;
|
|
94
|
+
/** Size in pixels for the upload icon. */
|
|
73
95
|
iconSize?: number;
|
|
74
96
|
}
|
|
75
|
-
|
|
97
|
+
/**
|
|
98
|
+
* A drag-and-drop file upload zone that manages file selection, validation, preview generation, and optional async upload with progress tracking.
|
|
99
|
+
*/
|
|
100
|
+
declare function FileUploader(props: FileUploaderProps): react_jsx_runtime168.JSX.Element;
|
|
76
101
|
//#endregion
|
|
77
102
|
export { FileUploader };
|
|
78
103
|
//# sourceMappingURL=file-uploader.d.cts.map
|
|
@@ -1,7 +1,24 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime198 from "react/jsx-runtime";
|
|
2
2
|
import { DropzoneProps } from "react-dropzone";
|
|
3
3
|
|
|
4
4
|
//#region packages/components/ui/file-uploader.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Props for the FileUploader component.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { FileUploader } from '@customafk/lunas-ui/ui/file-uploader';
|
|
12
|
+
*
|
|
13
|
+
* <FileUploader
|
|
14
|
+
* accept={{ 'image/*': [] }}
|
|
15
|
+
* maxSize={1024 * 1024 * 5}
|
|
16
|
+
* maxFileCount={3}
|
|
17
|
+
* multiple
|
|
18
|
+
* onUpload={async (files) => { await uploadFiles(files); }}
|
|
19
|
+
* />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
5
22
|
interface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
23
|
/**
|
|
7
24
|
* Value of the uploader.
|
|
@@ -69,10 +86,18 @@ interface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
69
86
|
* @example disabled
|
|
70
87
|
*/
|
|
71
88
|
disabled?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Whether to show the instructional drag-and-drop text inside the drop zone.
|
|
91
|
+
* @default true
|
|
92
|
+
*/
|
|
72
93
|
showText?: boolean;
|
|
94
|
+
/** Size in pixels for the upload icon. */
|
|
73
95
|
iconSize?: number;
|
|
74
96
|
}
|
|
75
|
-
|
|
97
|
+
/**
|
|
98
|
+
* A drag-and-drop file upload zone that manages file selection, validation, preview generation, and optional async upload with progress tracking.
|
|
99
|
+
*/
|
|
100
|
+
declare function FileUploader(props: FileUploaderProps): react_jsx_runtime198.JSX.Element;
|
|
76
101
|
//#endregion
|
|
77
102
|
export { FileUploader };
|
|
78
103
|
//# sourceMappingURL=file-uploader.d.mts.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use client";import"../button.variants-
|
|
2
|
-
files (up to ${
|
|
1
|
+
"use client";import"../button.variants-DeCyas1F.mjs";import{t as e}from"../button-C6ybzxxj.mjs";import{Progress as t}from"./progress.mjs";import{FileText as n,Image as r,Trash2 as i,Upload as a}from"lucide-react";import{useCallback as o,useEffect as s}from"react";import{jsx as c,jsxs as l}from"react/jsx-runtime";import{cn as u,formatBytes as d}from"@customafk/react-toolkit/utils";import f from"react-dropzone";import{useControllableState as p}from"@customafk/react-toolkit/hooks/useControllableState";import{toast as m}from"sonner";function h(e){let{value:t,onValueChange:n,onUpload:h,progresses:v,accept:y={"image/*":[]},maxSize:b=1024*1024*2,maxFileCount:x=1,multiple:S=!1,disabled:C=!1,showText:w=!0,iconSize:T,className:E,...D}=e,[O,k]=p({prop:t,onChange:n}),A=o((e,t)=>{if(!S&&x===1&&e.length>1){m.error(`Cannot upload more than 1 file at a time`);return}if((O?.length??0)+e.length>x){m.error(`Cannot upload more than ${x} files`);return}let n=e.map(e=>Object.assign(e,{preview:URL.createObjectURL(e)})),r=O?[...O,...n]:n;if(k(r),t.length>0&&t.forEach(({file:e})=>{m.error(`File ${e.name} was rejected`)}),h&&r.length>0&&r.length<=x){let e=r.length>0?`${r.length} files`:`file`;h(r).then(()=>{k([]),m(`${e} uploaded`)})}},[O,x,S,h,k]);function j(e){if(!O)return;_(O[e])&&URL.revokeObjectURL(O[e].preview);let t=O.filter((t,n)=>n!==e);k(t),n?.(t)}s(()=>()=>{O&&O.forEach(e=>{_(e)&&URL.revokeObjectURL(e.preview)})},[]);let M=C||(O?.length??0)>=x;return l(`div`,{className:`relative flex w-full flex-col gap-6`,children:[c(f,{onDrop:A,accept:y,maxSize:b,maxFiles:x,multiple:x>1||S,disabled:M,children:({getRootProps:e,getInputProps:t,isDragActive:n})=>l(`div`,{...e(),className:u(`group`,`border-border-weak`,`hover:bg-border-weak/20`,`relative grid h-52 w-full cursor-pointer place-items-center rounded-lg border-2 border-dashed px-5 py-2.5 text-center transition`,`ring-offset-background`,`focus-visible:ring-primary-weak`,`focus-visible:ring-2`,`focus-visible:ring-offset-2`,`focus-visible:outline-hidden`,n&&`border-border-primary-strong bg-border-weak/40`,M&&`pointer-events-none opacity-60`,E),...D,children:[c(`input`,{...t()}),n?l(`div`,{className:`flex flex-col items-center justify-center gap-4 sm:px-5`,children:[c(`div`,{className:`rounded-full border border-dashed p-3`,children:c(a,{className:`text-text-positive-muted size-7`,"aria-hidden":`true`})}),c(`p`,{className:`text-text-positive-muted font-medium`,children:`Drop the files here`})]}):l(`div`,{className:`flex flex-col items-center justify-center gap-4 sm:px-5`,children:[c(`div`,{className:`rounded-full border border-dashed p-3`,children:c(a,{size:T||24,className:`text-muted-foreground`,"aria-hidden":`true`})}),w&&l(`div`,{className:`flex flex-col gap-px`,children:[l(`p`,{className:`text-text-positive-weak text-xs font-medium`,children:[`Drag `,`'n'`,` drop files here, or click to select files`]}),l(`p`,{className:`text-text-positive-muted text-xs`,children:[`You can upload`,x>1?` ${x===1/0?`multiple`:x}
|
|
2
|
+
files (up to ${d(b)} each)`:` a file with ${d(b)}`]})]})]})]})}),O?.length?l(`div`,{className:`h-fit w-full overflow-y-auto`,children:[l(`div`,{className:`flex items-center justify-between px-3 py-2.5`,children:[l(`div`,{className:`text-text-positive-weak flex items-center gap-1`,children:[c(r,{size:16,"aria-hidden":`true`}),l(`p`,{className:`text-sm`,children:[`Ảnh đã tải lên (`,O.length,`)`]})]}),l(`button`,{className:`hover:text-text-positive text-text-positive-muted flex cursor-pointer items-center gap-1 transition-colors duration-200`,onClick:()=>{O&&(O.forEach(e=>{_(e)&&URL.revokeObjectURL(e.preview)}),k([]),n?.([]))},children:[c(i,{size:16,"aria-hidden":`true`}),c(`p`,{className:`text-sm`,children:`Xóa tất cả`})]})]}),c(`div`,{className:`flex flex-col gap-2.5`,children:O?.map((e,t)=>c(g,{file:e,onRemove:()=>j(t),progress:v?.[e.name]},t))})]}):null]})}function g({file:n,progress:r,onRemove:a}){return l(`div`,{className:`border-border-weak hover:border-border relative flex items-center gap-4 rounded-md border py-2 pr-3 pl-2 shadow-xs transition-colors`,children:[l(`div`,{className:`flex flex-1 gap-2.5`,children:[_(n)?c(v,{file:n}):null,l(`div`,{className:`flex w-full flex-col gap-2`,children:[l(`div`,{className:`flex flex-col gap-y-0.5`,children:[c(`p`,{className:`text-text-positive line-clamp-1 text-sm`,children:n.name}),c(`p`,{className:`text-text-positive-muted text-xs`,children:d(n.size)})]}),r?c(t,{value:r}):null]})]}),c(`div`,{className:`flex items-center gap-2`,children:l(e,{type:`button`,variant:`ghost`,color:`secondary`,size:`icon`,className:`size-7`,onClick:a,children:[c(i,{size:16,className:`text-text-positive-muted`,"aria-hidden":`true`}),c(`span`,{className:`sr-only`,children:`Remove file`})]})})]})}function _(e){return`preview`in e&&typeof e.preview==`string`}function v({file:e}){return e.type.startsWith(`image/`)?c(`img`,{src:e.preview,className:`border-border aspect-square size-10 shrink-0 rounded border object-cover object-top shadow-sm`}):c(n,{className:`text-text-positive-muted size-10 border`,"aria-hidden":`true`})}export{h as FileUploader};
|
|
3
3
|
//# sourceMappingURL=file-uploader.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-uploader.mjs","names":[],"sources":["../../packages/components/ui/file-uploader.tsx"],"sourcesContent":["'use client';\nimport { useCallback, useEffect } from 'react';\nimport Dropzone, { type DropzoneProps, type FileRejection } from 'react-dropzone';\nimport { useControllableState } from '@customafk/react-toolkit/hooks/useControllableState';\nimport { cn, formatBytes } from '@customafk/react-toolkit/utils';\n\nimport { FileText, Image, Trash2, Upload } from 'lucide-react';\nimport { toast } from 'sonner';\n\nimport { Button } from '@/components/ui/button';\nimport { Progress } from '@/components/ui/progress';\n\ninterface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Value of the uploader.\n * @type File[]\n * @default undefined\n * @example value={files}\n */\n value?: File[];\n\n /**\n * Function to be called when the value changes.\n * @type (files: File[]) => void\n * @default undefined\n * @example onValueChange={(files) => setFiles(files)}\n */\n onValueChange?: (files: File[]) => void;\n\n /**\n * Function to be called when files are uploaded.\n * @type (files: File[]) => Promise<void>\n * @default undefined\n * @example onUpload={(files) => uploadFiles(files)}\n */\n onUpload?: (files: File[]) => Promise<void>;\n\n /**\n * Progress of the uploaded files.\n * @type Record<string, number> | undefined\n * @default undefined\n * @example progresses={{ \"file1.png\": 50 }}\n */\n progresses?: Record<string, number>;\n\n /**\n * Accepted file types for the uploader.\n * @type { [key: string]: string[]}\n * @default\n * ```ts\n * { \"image/*\": [] }\n * ```\n * @example accept={[\"image/png\", \"image/jpeg\"]}\n */\n accept?: DropzoneProps['accept'];\n\n /**\n * Maximum file size for the uploader.\n * @type number | undefined\n * @default 1024 * 1024 * 2 // 2MB\n * @example maxSize={1024 * 1024 * 2} // 2MB\n */\n maxSize?: DropzoneProps['maxSize'];\n\n /**\n * Maximum number of files for the uploader.\n * @type number | undefined\n * @default 1\n * @example maxFileCount={4}\n */\n maxFileCount?: DropzoneProps['maxFiles'];\n\n /**\n * Whether the uploader should accept multiple files.\n * @type boolean\n * @default false\n * @example multiple\n */\n multiple?: boolean;\n\n /**\n * Whether the uploader is disabled.\n * @type boolean\n * @default false\n * @example disabled\n */\n disabled?: boolean;\n\n showText?: boolean;\n iconSize?: number;\n}\n\nexport function FileUploader(props: FileUploaderProps) {\n const {\n value: valueProp,\n onValueChange,\n onUpload,\n progresses,\n accept = {\n 'image/*': [],\n },\n maxSize = 1024 * 1024 * 2,\n maxFileCount = 1,\n multiple = false,\n disabled = false,\n showText = true,\n iconSize,\n className,\n ...dropzoneProps\n } = props;\n\n const [files, setFiles] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n });\n\n const onDrop = useCallback(\n (acceptedFiles: File[], rejectedFiles: FileRejection[]) => {\n if (!multiple && maxFileCount === 1 && acceptedFiles.length > 1) {\n toast.error('Cannot upload more than 1 file at a time');\n\n return;\n }\n\n if ((files?.length ?? 0) + acceptedFiles.length > maxFileCount) {\n toast.error(`Cannot upload more than ${maxFileCount} files`);\n return;\n }\n\n const newFiles = acceptedFiles.map(file =>\n Object.assign(file, {\n preview: URL.createObjectURL(file),\n })\n );\n\n const updatedFiles = files ? [...files, ...newFiles] : newFiles;\n\n setFiles(updatedFiles);\n\n if (rejectedFiles.length > 0) {\n rejectedFiles.forEach(({ file }) => {\n toast.error(`File ${file.name} was rejected`);\n });\n }\n\n if (onUpload && updatedFiles.length > 0 && updatedFiles.length <= maxFileCount) {\n const target = updatedFiles.length > 0 ? `${updatedFiles.length} files` : `file`;\n\n onUpload(updatedFiles).then(() => {\n setFiles([]);\n toast(`${target} uploaded`);\n });\n }\n },\n\n [files, maxFileCount, multiple, onUpload, setFiles]\n );\n\n function onRemove(index: number) {\n if (!files) return;\n\n if (isFileWithPreview(files[index])) {\n URL.revokeObjectURL(files[index].preview);\n }\n\n const newFiles = files.filter((_, i) => i !== index);\n setFiles(newFiles);\n onValueChange?.(newFiles);\n }\n\n // Revoke preview url when component unmounts\n useEffect(() => {\n return () => {\n if (!files) return;\n files.forEach(file => {\n if (isFileWithPreview(file)) {\n URL.revokeObjectURL(file.preview);\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const isDisabled = disabled || (files?.length ?? 0) >= maxFileCount;\n\n return (\n <div className=\"relative flex w-full flex-col gap-6\">\n <Dropzone onDrop={onDrop} accept={accept} maxSize={maxSize} maxFiles={maxFileCount} multiple={maxFileCount > 1 || multiple} disabled={isDisabled}>\n {({ getRootProps, getInputProps, isDragActive }) => (\n <div\n {...getRootProps()}\n className={cn(\n 'group',\n 'border-border-weak',\n 'hover:bg-border-weak/20',\n 'relative grid h-52 w-full cursor-pointer place-items-center rounded-lg border-2 border-dashed px-5 py-2.5 text-center transition',\n 'ring-offset-background',\n 'focus-visible:ring-primary-weak',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-2',\n 'focus-visible:outline-hidden',\n isDragActive && 'border-border-primary-strong bg-border-weak/40',\n isDisabled && 'pointer-events-none opacity-60',\n className\n )}\n {...dropzoneProps}\n >\n <input {...getInputProps()} />\n {isDragActive ? (\n <div className=\"flex flex-col items-center justify-center gap-4 sm:px-5\">\n <div className=\"rounded-full border border-dashed p-3\">\n <Upload className=\"text-text-positive-muted size-7\" aria-hidden=\"true\" />\n </div>\n <p className=\"text-text-positive-muted font-medium\">Drop the files here</p>\n </div>\n ) : (\n <div className=\"flex flex-col items-center justify-center gap-4 sm:px-5\">\n <div className=\"rounded-full border border-dashed p-3\">\n <Upload size={iconSize || 24} className=\"text-muted-foreground\" aria-hidden=\"true\" />\n </div>\n {showText && (\n <div className=\"flex flex-col gap-px\">\n <p className=\"text-text-positive-weak text-xs font-medium\">Drag {`'n'`} drop files here, or click to select files</p>\n <p className=\"text-text-positive-muted text-xs\">\n You can upload\n {maxFileCount > 1\n ? ` ${maxFileCount === Infinity ? 'multiple' : maxFileCount}\n files (up to ${formatBytes(maxSize)} each)`\n : ` a file with ${formatBytes(maxSize)}`}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </Dropzone>\n {files?.length ? (\n <div className=\"h-fit w-full overflow-y-auto\">\n <div className=\"flex items-center justify-between px-3 py-2.5\">\n <div className=\"text-text-positive-weak flex items-center gap-1\">\n <Image size={16} aria-hidden=\"true\" />\n <p className=\"text-sm\">Ảnh đã tải lên ({files.length})</p>\n </div>\n <button\n className=\"hover:text-text-positive text-text-positive-muted flex cursor-pointer items-center gap-1 transition-colors duration-200\"\n onClick={() => {\n if (!files) return;\n files.forEach(file => {\n if (!isFileWithPreview(file)) return;\n URL.revokeObjectURL(file.preview);\n });\n setFiles([]);\n onValueChange?.([]);\n }}\n >\n <Trash2 size={16} aria-hidden=\"true\" />\n <p className=\"text-sm\">Xóa tất cả</p>\n </button>\n </div>\n <div className=\"flex flex-col gap-2.5\">\n {files?.map((file, index) => (\n <FileCard key={index} file={file} onRemove={() => onRemove(index)} progress={progresses?.[file.name]} />\n ))}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\ninterface FileCardProps {\n file: File;\n onRemove: () => void;\n progress?: number;\n}\n\nfunction FileCard({ file, progress, onRemove }: FileCardProps) {\n return (\n <div className=\"border-border-weak hover:border-border relative flex items-center gap-4 rounded-md border py-2 pr-3 pl-2 shadow-xs transition-colors\">\n <div className=\"flex flex-1 gap-2.5\">\n {isFileWithPreview(file) ? <FilePreview file={file} /> : null}\n <div className=\"flex w-full flex-col gap-2\">\n <div className=\"flex flex-col gap-y-0.5\">\n <p className=\"text-text-positive line-clamp-1 text-sm\">{file.name}</p>\n <p className=\"text-text-positive-muted text-xs\">{formatBytes(file.size)}</p>\n </div>\n {progress ? <Progress value={progress} /> : null}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"ghost\" color=\"secondary\" size=\"icon\" className=\"size-7\" onClick={onRemove}>\n <Trash2 size={16} className=\"text-text-positive-muted\" aria-hidden=\"true\" />\n <span className=\"sr-only\">Remove file</span>\n </Button>\n </div>\n </div>\n );\n}\n\nfunction isFileWithPreview(file: File): file is File & { preview: string } {\n return 'preview' in file && typeof file.preview === 'string';\n}\n\ninterface FilePreviewProps {\n file: File & { preview: string };\n}\n\nfunction FilePreview({ file }: FilePreviewProps) {\n if (file.type.startsWith('image/')) {\n return <img src={file.preview} className=\"border-border aspect-square size-10 shrink-0 rounded border object-cover object-top shadow-sm\" />;\n }\n\n return <FileText className=\"text-text-positive-muted size-10 border\" aria-hidden=\"true\" />;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-uploader.mjs","names":[],"sources":["../../packages/components/ui/file-uploader.tsx"],"sourcesContent":["'use client';\nimport { useCallback, useEffect } from 'react';\nimport Dropzone, { type DropzoneProps, type FileRejection } from 'react-dropzone';\nimport { useControllableState } from '@customafk/react-toolkit/hooks/useControllableState';\nimport { cn, formatBytes } from '@customafk/react-toolkit/utils';\n\nimport { FileText, Image, Trash2, Upload } from 'lucide-react';\nimport { toast } from 'sonner';\n\nimport { Button } from '@/components/ui/button';\nimport { Progress } from '@/components/ui/progress';\n\n/**\n * Props for the FileUploader component.\n *\n * @example\n * ```tsx\n * import { FileUploader } from '@customafk/lunas-ui/ui/file-uploader';\n *\n * <FileUploader\n * accept={{ 'image/*': [] }}\n * maxSize={1024 * 1024 * 5}\n * maxFileCount={3}\n * multiple\n * onUpload={async (files) => { await uploadFiles(files); }}\n * />\n * ```\n */\ninterface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Value of the uploader.\n * @type File[]\n * @default undefined\n * @example value={files}\n */\n value?: File[];\n\n /**\n * Function to be called when the value changes.\n * @type (files: File[]) => void\n * @default undefined\n * @example onValueChange={(files) => setFiles(files)}\n */\n onValueChange?: (files: File[]) => void;\n\n /**\n * Function to be called when files are uploaded.\n * @type (files: File[]) => Promise<void>\n * @default undefined\n * @example onUpload={(files) => uploadFiles(files)}\n */\n onUpload?: (files: File[]) => Promise<void>;\n\n /**\n * Progress of the uploaded files.\n * @type Record<string, number> | undefined\n * @default undefined\n * @example progresses={{ \"file1.png\": 50 }}\n */\n progresses?: Record<string, number>;\n\n /**\n * Accepted file types for the uploader.\n * @type { [key: string]: string[]}\n * @default\n * ```ts\n * { \"image/*\": [] }\n * ```\n * @example accept={[\"image/png\", \"image/jpeg\"]}\n */\n accept?: DropzoneProps['accept'];\n\n /**\n * Maximum file size for the uploader.\n * @type number | undefined\n * @default 1024 * 1024 * 2 // 2MB\n * @example maxSize={1024 * 1024 * 2} // 2MB\n */\n maxSize?: DropzoneProps['maxSize'];\n\n /**\n * Maximum number of files for the uploader.\n * @type number | undefined\n * @default 1\n * @example maxFileCount={4}\n */\n maxFileCount?: DropzoneProps['maxFiles'];\n\n /**\n * Whether the uploader should accept multiple files.\n * @type boolean\n * @default false\n * @example multiple\n */\n multiple?: boolean;\n\n /**\n * Whether the uploader is disabled.\n * @type boolean\n * @default false\n * @example disabled\n */\n disabled?: boolean;\n\n /**\n * Whether to show the instructional drag-and-drop text inside the drop zone.\n * @default true\n */\n showText?: boolean;\n /** Size in pixels for the upload icon. */\n iconSize?: number;\n}\n\n/**\n * A drag-and-drop file upload zone that manages file selection, validation, preview generation, and optional async upload with progress tracking.\n */\nexport function FileUploader(props: FileUploaderProps) {\n const {\n value: valueProp,\n onValueChange,\n onUpload,\n progresses,\n accept = {\n 'image/*': [],\n },\n maxSize = 1024 * 1024 * 2,\n maxFileCount = 1,\n multiple = false,\n disabled = false,\n showText = true,\n iconSize,\n className,\n ...dropzoneProps\n } = props;\n\n const [files, setFiles] = useControllableState({\n prop: valueProp,\n onChange: onValueChange,\n });\n\n const onDrop = useCallback(\n (acceptedFiles: File[], rejectedFiles: FileRejection[]) => {\n if (!multiple && maxFileCount === 1 && acceptedFiles.length > 1) {\n toast.error('Cannot upload more than 1 file at a time');\n\n return;\n }\n\n if ((files?.length ?? 0) + acceptedFiles.length > maxFileCount) {\n toast.error(`Cannot upload more than ${maxFileCount} files`);\n return;\n }\n\n const newFiles = acceptedFiles.map(file =>\n Object.assign(file, {\n preview: URL.createObjectURL(file),\n })\n );\n\n const updatedFiles = files ? [...files, ...newFiles] : newFiles;\n\n setFiles(updatedFiles);\n\n if (rejectedFiles.length > 0) {\n rejectedFiles.forEach(({ file }) => {\n toast.error(`File ${file.name} was rejected`);\n });\n }\n\n if (onUpload && updatedFiles.length > 0 && updatedFiles.length <= maxFileCount) {\n const target = updatedFiles.length > 0 ? `${updatedFiles.length} files` : `file`;\n\n onUpload(updatedFiles).then(() => {\n setFiles([]);\n toast(`${target} uploaded`);\n });\n }\n },\n\n [files, maxFileCount, multiple, onUpload, setFiles]\n );\n\n function onRemove(index: number) {\n if (!files) return;\n\n if (isFileWithPreview(files[index])) {\n URL.revokeObjectURL(files[index].preview);\n }\n\n const newFiles = files.filter((_, i) => i !== index);\n setFiles(newFiles);\n onValueChange?.(newFiles);\n }\n\n // Revoke preview url when component unmounts\n useEffect(() => {\n return () => {\n if (!files) return;\n files.forEach(file => {\n if (isFileWithPreview(file)) {\n URL.revokeObjectURL(file.preview);\n }\n });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const isDisabled = disabled || (files?.length ?? 0) >= maxFileCount;\n\n return (\n <div className=\"relative flex w-full flex-col gap-6\">\n <Dropzone onDrop={onDrop} accept={accept} maxSize={maxSize} maxFiles={maxFileCount} multiple={maxFileCount > 1 || multiple} disabled={isDisabled}>\n {({ getRootProps, getInputProps, isDragActive }) => (\n <div\n {...getRootProps()}\n className={cn(\n 'group',\n 'border-border-weak',\n 'hover:bg-border-weak/20',\n 'relative grid h-52 w-full cursor-pointer place-items-center rounded-lg border-2 border-dashed px-5 py-2.5 text-center transition',\n 'ring-offset-background',\n 'focus-visible:ring-primary-weak',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-2',\n 'focus-visible:outline-hidden',\n isDragActive && 'border-border-primary-strong bg-border-weak/40',\n isDisabled && 'pointer-events-none opacity-60',\n className\n )}\n {...dropzoneProps}\n >\n <input {...getInputProps()} />\n {isDragActive ? (\n <div className=\"flex flex-col items-center justify-center gap-4 sm:px-5\">\n <div className=\"rounded-full border border-dashed p-3\">\n <Upload className=\"text-text-positive-muted size-7\" aria-hidden=\"true\" />\n </div>\n <p className=\"text-text-positive-muted font-medium\">Drop the files here</p>\n </div>\n ) : (\n <div className=\"flex flex-col items-center justify-center gap-4 sm:px-5\">\n <div className=\"rounded-full border border-dashed p-3\">\n <Upload size={iconSize || 24} className=\"text-muted-foreground\" aria-hidden=\"true\" />\n </div>\n {showText && (\n <div className=\"flex flex-col gap-px\">\n <p className=\"text-text-positive-weak text-xs font-medium\">Drag {`'n'`} drop files here, or click to select files</p>\n <p className=\"text-text-positive-muted text-xs\">\n You can upload\n {maxFileCount > 1\n ? ` ${maxFileCount === Infinity ? 'multiple' : maxFileCount}\n files (up to ${formatBytes(maxSize)} each)`\n : ` a file with ${formatBytes(maxSize)}`}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </Dropzone>\n {files?.length ? (\n <div className=\"h-fit w-full overflow-y-auto\">\n <div className=\"flex items-center justify-between px-3 py-2.5\">\n <div className=\"text-text-positive-weak flex items-center gap-1\">\n <Image size={16} aria-hidden=\"true\" />\n <p className=\"text-sm\">Ảnh đã tải lên ({files.length})</p>\n </div>\n <button\n className=\"hover:text-text-positive text-text-positive-muted flex cursor-pointer items-center gap-1 transition-colors duration-200\"\n onClick={() => {\n if (!files) return;\n files.forEach(file => {\n if (!isFileWithPreview(file)) return;\n URL.revokeObjectURL(file.preview);\n });\n setFiles([]);\n onValueChange?.([]);\n }}\n >\n <Trash2 size={16} aria-hidden=\"true\" />\n <p className=\"text-sm\">Xóa tất cả</p>\n </button>\n </div>\n <div className=\"flex flex-col gap-2.5\">\n {files?.map((file, index) => (\n <FileCard key={index} file={file} onRemove={() => onRemove(index)} progress={progresses?.[file.name]} />\n ))}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\ninterface FileCardProps {\n file: File;\n onRemove: () => void;\n progress?: number;\n}\n\nfunction FileCard({ file, progress, onRemove }: FileCardProps) {\n return (\n <div className=\"border-border-weak hover:border-border relative flex items-center gap-4 rounded-md border py-2 pr-3 pl-2 shadow-xs transition-colors\">\n <div className=\"flex flex-1 gap-2.5\">\n {isFileWithPreview(file) ? <FilePreview file={file} /> : null}\n <div className=\"flex w-full flex-col gap-2\">\n <div className=\"flex flex-col gap-y-0.5\">\n <p className=\"text-text-positive line-clamp-1 text-sm\">{file.name}</p>\n <p className=\"text-text-positive-muted text-xs\">{formatBytes(file.size)}</p>\n </div>\n {progress ? <Progress value={progress} /> : null}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"ghost\" color=\"secondary\" size=\"icon\" className=\"size-7\" onClick={onRemove}>\n <Trash2 size={16} className=\"text-text-positive-muted\" aria-hidden=\"true\" />\n <span className=\"sr-only\">Remove file</span>\n </Button>\n </div>\n </div>\n );\n}\n\nfunction isFileWithPreview(file: File): file is File & { preview: string } {\n return 'preview' in file && typeof file.preview === 'string';\n}\n\ninterface FilePreviewProps {\n file: File & { preview: string };\n}\n\nfunction FilePreview({ file }: FilePreviewProps) {\n if (file.type.startsWith('image/')) {\n return <img src={file.preview} className=\"border-border aspect-square size-10 shrink-0 rounded border object-cover object-top shadow-sm\" />;\n }\n\n return <FileText className=\"text-text-positive-muted size-10 border\" aria-hidden=\"true\" />;\n}\n"],"mappings":"uhBAoHA,SAAgB,EAAa,EAA0B,CACrD,GAAM,CACJ,MAAO,EACP,gBACA,WACA,aACA,SAAS,CACP,UAAW,EAAE,CACd,CACD,UAAU,KAAO,KAAO,EACxB,eAAe,EACf,WAAW,GACX,WAAW,GACX,WAAW,GACX,WACA,YACA,GAAG,GACD,EAEE,CAAC,EAAO,GAAY,EAAqB,CAC7C,KAAM,EACN,SAAU,EACX,CAAC,CAEI,EAAS,GACZ,EAAuB,IAAmC,CACzD,GAAI,CAAC,GAAY,IAAiB,GAAK,EAAc,OAAS,EAAG,CAC/D,EAAM,MAAM,2CAA2C,CAEvD,OAGF,IAAK,GAAO,QAAU,GAAK,EAAc,OAAS,EAAc,CAC9D,EAAM,MAAM,2BAA2B,EAAa,QAAQ,CAC5D,OAGF,IAAM,EAAW,EAAc,IAAI,GACjC,OAAO,OAAO,EAAM,CAClB,QAAS,IAAI,gBAAgB,EAAK,CACnC,CAAC,CACH,CAEK,EAAe,EAAQ,CAAC,GAAG,EAAO,GAAG,EAAS,CAAG,EAUvD,GARA,EAAS,EAAa,CAElB,EAAc,OAAS,GACzB,EAAc,SAAS,CAAE,UAAW,CAClC,EAAM,MAAM,QAAQ,EAAK,KAAK,eAAe,EAC7C,CAGA,GAAY,EAAa,OAAS,GAAK,EAAa,QAAU,EAAc,CAC9E,IAAM,EAAS,EAAa,OAAS,EAAI,GAAG,EAAa,OAAO,QAAU,OAE1E,EAAS,EAAa,CAAC,SAAW,CAChC,EAAS,EAAE,CAAC,CACZ,EAAM,GAAG,EAAO,WAAW,EAC3B,GAIN,CAAC,EAAO,EAAc,EAAU,EAAU,EAAS,CACpD,CAED,SAAS,EAAS,EAAe,CAC/B,GAAI,CAAC,EAAO,OAER,EAAkB,EAAM,GAAO,EACjC,IAAI,gBAAgB,EAAM,GAAO,QAAQ,CAG3C,IAAM,EAAW,EAAM,QAAQ,EAAG,IAAM,IAAM,EAAM,CACpD,EAAS,EAAS,CAClB,IAAgB,EAAS,CAI3B,UACe,CACN,GACL,EAAM,QAAQ,GAAQ,CAChB,EAAkB,EAAK,EACzB,IAAI,gBAAgB,EAAK,QAAQ,EAEnC,EAGH,EAAE,CAAC,CAEN,IAAM,EAAa,IAAa,GAAO,QAAU,IAAM,EAEvD,OACE,EAAC,MAAA,CAAI,UAAU,gDACb,EAAC,EAAA,CAAiB,SAAgB,SAAiB,UAAS,SAAU,EAAc,SAAU,EAAe,GAAK,EAAU,SAAU,YAClI,CAAE,eAAc,gBAAe,kBAC/B,EAAC,MAAA,CACC,GAAI,GAAc,CAClB,UAAW,EACT,QACA,qBACA,0BACA,mIACA,yBACA,kCACA,uBACA,8BACA,+BACA,GAAgB,iDAChB,GAAc,iCACd,EACD,CACD,GAAI,YAEJ,EAAC,QAAA,CAAM,GAAI,GAAe,CAAA,CAAI,CAC7B,EACC,EAAC,MAAA,CAAI,UAAU,oEACb,EAAC,MAAA,CAAI,UAAU,iDACb,EAAC,EAAA,CAAO,UAAU,kCAAkC,cAAY,QAAS,EACrE,CACN,EAAC,IAAA,CAAE,UAAU,gDAAuC,uBAAuB,CAAA,EACvE,CAEN,EAAC,MAAA,CAAI,UAAU,oEACb,EAAC,MAAA,CAAI,UAAU,iDACb,EAAC,EAAA,CAAO,KAAM,GAAY,GAAI,UAAU,wBAAwB,cAAY,QAAS,EACjF,CACL,GACC,EAAC,MAAA,CAAI,UAAU,iCACb,EAAC,IAAA,CAAE,UAAU,wDAA8C,QAAM,MAAM,+CAA8C,CACrH,EAAC,IAAA,CAAE,UAAU,6CAAmC,iBAE7C,EAAe,EACZ,IAAI,IAAiB,IAAW,WAAa,EAAa;qCAC/C,EAAY,EAAQ,CAAC,QAChC,gBAAgB,EAAY,EAAQ,GAAA,EACtC,CAAA,EACA,CAAA,EAEJ,CAAA,EAEJ,EAEC,CACV,GAAO,OACN,EAAC,MAAA,CAAI,UAAU,yCACb,EAAC,MAAA,CAAI,UAAU,0DACb,EAAC,MAAA,CAAI,UAAU,4DACb,EAAC,EAAA,CAAM,KAAM,GAAI,cAAY,QAAS,CACtC,EAAC,IAAA,CAAE,UAAU,oBAAU,mBAAiB,EAAM,OAAO,MAAK,CAAA,EACtD,CACN,EAAC,SAAA,CACC,UAAU,0HACV,YAAe,CACR,IACL,EAAM,QAAQ,GAAQ,CACf,EAAkB,EAAK,EAC5B,IAAI,gBAAgB,EAAK,QAAQ,EACjC,CACF,EAAS,EAAE,CAAC,CACZ,IAAgB,EAAE,CAAC,aAGrB,EAAC,EAAA,CAAO,KAAM,GAAI,cAAY,QAAS,CACvC,EAAC,IAAA,CAAE,UAAU,mBAAU,cAAc,CAAA,EAC9B,CAAA,EACL,CACN,EAAC,MAAA,CAAI,UAAU,iCACZ,GAAO,KAAK,EAAM,IACjB,EAAC,EAAA,CAA2B,OAAM,aAAgB,EAAS,EAAM,CAAE,SAAU,IAAa,EAAK,OAAhF,EAAyF,CACxG,EACE,CAAA,EACF,CACJ,KAAA,EACA,CAUV,SAAS,EAAS,CAAE,OAAM,WAAU,YAA2B,CAC7D,OACE,EAAC,MAAA,CAAI,UAAU,iJACb,EAAC,MAAA,CAAI,UAAU,gCACZ,EAAkB,EAAK,CAAG,EAAC,EAAA,CAAkB,OAAA,CAAQ,CAAG,KACzD,EAAC,MAAA,CAAI,UAAU,uCACb,EAAC,MAAA,CAAI,UAAU,oCACb,EAAC,IAAA,CAAE,UAAU,mDAA2C,EAAK,MAAS,CACtE,EAAC,IAAA,CAAE,UAAU,4CAAoC,EAAY,EAAK,KAAK,EAAK,CAAA,EACxE,CACL,EAAW,EAAC,EAAA,CAAS,MAAO,EAAA,CAAY,CAAG,KAAA,EACxC,CAAA,EACF,CACN,EAAC,MAAA,CAAI,UAAU,mCACb,EAAC,EAAA,CAAO,KAAK,SAAS,QAAQ,QAAQ,MAAM,YAAY,KAAK,OAAO,UAAU,SAAS,QAAS,YAC9F,EAAC,EAAA,CAAO,KAAM,GAAI,UAAU,2BAA2B,cAAY,QAAS,CAC5E,EAAC,OAAA,CAAK,UAAU,mBAAU,eAAkB,CAAA,EACrC,EACL,CAAA,EACF,CAIV,SAAS,EAAkB,EAAgD,CACzE,MAAO,YAAa,GAAQ,OAAO,EAAK,SAAY,SAOtD,SAAS,EAAY,CAAE,QAA0B,CAK/C,OAJI,EAAK,KAAK,WAAW,SAAS,CACzB,EAAC,MAAA,CAAI,IAAK,EAAK,QAAS,UAAU,iGAAkG,CAGtI,EAAC,EAAA,CAAS,UAAU,0CAA0C,cAAY,QAAS"}
|
package/dist/ui/form.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";const e=require(`../chunk-Bmb41Sf3.cjs`);require(`../separator-
|
|
1
|
+
"use client";const e=require(`../chunk-Bmb41Sf3.cjs`);require(`../separator-BwZb12bh.cjs`),require(`../label-DkMTQ3Ch.cjs`);const t=require(`../field-CppNvoxV.cjs`);let n=require(`react`),r=require(`react/jsx-runtime`),i=require(`@customafk/react-toolkit/utils`),a=require(`radix-ui`),o=require(`react-hook-form`);const s=o.FormProvider,c=(0,n.createContext)({}),l=({...e})=>(0,r.jsx)(c.Provider,{value:{name:e.name},children:(0,r.jsx)(o.Controller,{...e})}),u=()=>{let e=(0,n.use)(c),t=(0,n.use)(d),{getFieldState:r,control:i,resetField:a}=(0,o.useFormContext)(),s=(0,o.useFormState)({name:e.name}),l=r(e.name,s);if(!e)throw Error(`useFormField should be used within <FormField>`);let{id:u}=t;return{id:u,control:i,resetField:a,name:e.name,formItemId:`${u}-form-item`,formDescriptionId:`${u}-form-item-description`,formMessageId:`${u}-form-item-message`,...l}},d=(0,n.createContext)({}),f=(0,n.memo)(({className:e,orientation:i=`responsive`,...a})=>{let o=(0,n.useId)();return(0,r.jsx)(d.Provider,{value:{id:o},children:(0,r.jsx)(t.t,{orientation:i,...a,className:e})})});f.displayName=`FormItem`;const p=(0,n.memo)(({...e})=>{let{formItemId:n}=u();return(0,r.jsx)(t.o,{htmlFor:n,...e})});p.displayName=`FormLabel`;const m=(0,n.memo)(({...e})=>{let{error:t,formItemId:n,formDescriptionId:i,formMessageId:o}=u();return(0,r.jsx)(a.Slot.Slot,{"data-slot":`form-control`,id:n,"aria-describedby":t?`${i} ${o}`:`${i}`,"aria-invalid":!!t,...e})});m.displayName=`FormControl`;function h({className:e,...n}){let{formDescriptionId:a}=u();return(0,r.jsx)(t.r,{id:a,className:(0,i.cn)(`text-text-positive-weak text-sm/6 leading-normal font-normal`,`group-has-data-[orientation=horizontal]/field:text-balance`,`last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5`,`[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4`,e),...n})}function g({className:e,children:t,...n}){let{error:a,formMessageId:o}=u();return(0,r.jsx)(`span`,{"data-slot":`form-message`,id:o,className:(0,i.cn)(`text-danger text-xs`,e),...n,children:a?String(a?.message??``):t})}exports.Form=s,exports.FormControl=m,exports.FormDescription=h,exports.FormField=l,exports.FormItem=f,exports.FormLabel=p,exports.FormMessage=g,exports.useFormField=u;
|
|
2
2
|
//# sourceMappingURL=form.cjs.map
|
package/dist/ui/form.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.cjs","names":["FormProvider","Controller","Field","FieldLabel","SlotPrimitive","FieldDescription"],"sources":["../../packages/components/ui/form.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@customafk/react-toolkit/utils';\nimport { type Label as LabelPrimitive, Slot as SlotPrimitive } from 'radix-ui';\nimport { createContext, memo, use, useId } from 'react';\nimport type { ControllerProps, FieldPath, FieldValues } from 'react-hook-form';\nimport { Controller, FormProvider, useFormContext, useFormState } from 'react-hook-form';\nimport { Field, FieldDescription, FieldLabel } from './field';\n\nconst Form = FormProvider;\n\ntype FormFieldContextValue<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = {\n name: TName;\n};\n\nconst FormFieldContext = createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nconst FormField = <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\nconst useFormField = () => {\n const fieldContext = use(FormFieldContext);\n const itemContext = use(FormItemContext);\n const { getFieldState, control, resetField } = useFormContext();\n const formState = useFormState({ name: fieldContext.name });\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error('useFormField should be used within <FormField>');\n }\n\n const { id } = itemContext;\n\n return {\n id,\n control,\n resetField,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n };\n};\n\ntype FormItemContextValue = {\n id: string;\n};\n\nconst FormItemContext = createContext<FormItemContextValue>({} as FormItemContextValue);\n\nconst FormItem = memo(\n ({\n className,\n orientation = 'responsive',\n ...props\n }: React.ComponentProps<'div'> & {\n orientation?: 'vertical' | 'horizontal' | 'responsive';\n }) => {\n const id = useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <Field orientation={orientation} {...props} className={className} />\n </FormItemContext.Provider>\n );\n }\n);\nFormItem.displayName = 'FormItem';\n\nconst FormLabel = memo(({ ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) => {\n const { formItemId } = useFormField();\n return <FieldLabel htmlFor={formItemId} {...props} />;\n});\nFormLabel.displayName = 'FormLabel';\n\nconst FormControl = memo(({ ...props }: React.ComponentProps<typeof SlotPrimitive.Slot>) => {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <SlotPrimitive.Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n});\nFormControl.displayName = 'FormControl';\n\nfunction FormDescription({ className, ...props }: React.ComponentProps<'p'>) {\n const { formDescriptionId } = useFormField();\n\n return (\n <FieldDescription\n id={formDescriptionId}\n className={cn(\n 'text-text-positive-weak text-sm/6 leading-normal font-normal',\n 'group-has-data-[orientation=horizontal]/field:text-balance',\n 'last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5',\n '[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction FormMessage({ className, children, ...props }: React.ComponentProps<'p'>) {\n const { error, formMessageId } = useFormField();\n\n return (\n <span data-slot=\"form-message\" id={formMessageId} className={cn('text-danger text-xs', className)} {...props}>\n {error ? String(error?.message ?? '') : children}\n </span>\n );\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"form.cjs","names":["FormProvider","Controller","Field","FieldLabel","SlotPrimitive","FieldDescription"],"sources":["../../packages/components/ui/form.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@customafk/react-toolkit/utils';\nimport { type Label as LabelPrimitive, Slot as SlotPrimitive } from 'radix-ui';\nimport { createContext, memo, use, useId } from 'react';\nimport type { ControllerProps, FieldPath, FieldValues } from 'react-hook-form';\nimport { Controller, FormProvider, useFormContext, useFormState } from 'react-hook-form';\nimport { Field, FieldDescription, FieldLabel } from './field';\n\n/**\n * Re-export of react-hook-form's `FormProvider`; wrap your form with this to give all nested form components access to the form context.\n *\n * @example\n * ```tsx\n * import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@customafk/lunas-ui/ui/form';\n * import { useForm } from 'react-hook-form';\n *\n * const form = useForm<{ username: string }>();\n *\n * <Form {...form}>\n * <form onSubmit={form.handleSubmit(onSubmit)}>\n * <FormField\n * control={form.control}\n * name=\"username\"\n * render={({ field }) => (\n * <FormItem>\n * <FormLabel>Username</FormLabel>\n * <FormControl><input {...field} /></FormControl>\n * <FormMessage />\n * </FormItem>\n * )}\n * />\n * </form>\n * </Form>\n * ```\n */\nconst Form = FormProvider;\n\ntype FormFieldContextValue<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = {\n name: TName;\n};\n\nconst FormFieldContext = createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\n/**\n * Connects a single react-hook-form field to the form context; renders a `Controller` and passes `name` down to nested FormItem, FormLabel, FormControl, and FormMessage.\n */\nconst FormField = <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\n/**\n * Hook that returns the field state and IDs for the enclosing FormField.\n * Must be called inside a component rendered within a `<FormField>`.\n */\nconst useFormField = () => {\n const fieldContext = use(FormFieldContext);\n const itemContext = use(FormItemContext);\n const { getFieldState, control, resetField } = useFormContext();\n const formState = useFormState({ name: fieldContext.name });\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error('useFormField should be used within <FormField>');\n }\n\n const { id } = itemContext;\n\n return {\n id,\n control,\n resetField,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n };\n};\n\ntype FormItemContextValue = {\n id: string;\n};\n\nconst FormItemContext = createContext<FormItemContextValue>({} as FormItemContextValue);\n\n/**\n * Container for a single form field — generates a unique ID and provides it via context to FormLabel, FormControl, and FormMessage.\n *\n * @param orientation - Layout direction: `'vertical'`, `'horizontal'`, or `'responsive'` (default).\n */\nconst FormItem = memo(\n ({\n className,\n orientation = 'responsive',\n ...props\n }: React.ComponentProps<'div'> & {\n orientation?: 'vertical' | 'horizontal' | 'responsive';\n }) => {\n const id = useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <Field orientation={orientation} {...props} className={className} />\n </FormItemContext.Provider>\n );\n }\n);\nFormItem.displayName = 'FormItem';\n\n/** Styled label automatically associated with the FormItem's control via `htmlFor`. */\nconst FormLabel = memo(({ ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) => {\n const { formItemId } = useFormField();\n return <FieldLabel htmlFor={formItemId} {...props} />;\n});\nFormLabel.displayName = 'FormLabel';\n\n/** Radix Slot wrapper that wires the correct `id`, `aria-describedby`, and `aria-invalid` attributes onto the underlying control element. */\nconst FormControl = memo(({ ...props }: React.ComponentProps<typeof SlotPrimitive.Slot>) => {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <SlotPrimitive.Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n});\nFormControl.displayName = 'FormControl';\n\n/** Helper text displayed below the control that provides additional context about the field. */\nfunction FormDescription({ className, ...props }: React.ComponentProps<'p'>) {\n const { formDescriptionId } = useFormField();\n\n return (\n <FieldDescription\n id={formDescriptionId}\n className={cn(\n 'text-text-positive-weak text-sm/6 leading-normal font-normal',\n 'group-has-data-[orientation=horizontal]/field:text-balance',\n 'last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5',\n '[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',\n className\n )}\n {...props}\n />\n );\n}\n\n/** Displays the validation error message for the field, or falls back to `children` when there is no error. */\nfunction FormMessage({ className, children, ...props }: React.ComponentProps<'p'>) {\n const { error, formMessageId } = useFormField();\n\n return (\n <span data-slot=\"form-message\" id={formMessageId} className={cn('text-danger text-xs', className)} {...props}>\n {error ? String(error?.message ?? '') : children}\n </span>\n );\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };\n"],"mappings":"0TAoCA,MAAM,EAAOA,EAAAA,aAMP,GAAA,EAAA,EAAA,eAAwD,EAAE,CAA0B,CAKpF,GAA8H,CAClI,GAAG,MAGD,EAAA,EAAA,KAAC,EAAiB,SAAA,CAAS,MAAO,CAAE,KAAM,EAAM,KAAM,WACpD,EAAA,EAAA,KAACC,EAAAA,WAAAA,CAAW,GAAI,EAAA,CAAS,EACC,CAQ1B,MAAqB,CACzB,IAAM,GAAA,EAAA,EAAA,KAAmB,EAAiB,CACpC,GAAA,EAAA,EAAA,KAAkB,EAAgB,CAClC,CAAE,gBAAe,UAAS,eAAA,EAAA,EAAA,iBAA+B,CACzD,GAAA,EAAA,EAAA,cAAyB,CAAE,KAAM,EAAa,KAAM,CAAC,CACrD,EAAa,EAAc,EAAa,KAAM,EAAU,CAE9D,GAAI,CAAC,EACH,MAAU,MAAM,iDAAiD,CAGnE,GAAM,CAAE,MAAO,EAEf,MAAO,CACL,KACA,UACA,aACA,KAAM,EAAa,KACnB,WAAY,GAAG,EAAG,YAClB,kBAAmB,GAAG,EAAG,wBACzB,cAAe,GAAG,EAAG,oBACrB,GAAG,EACJ,EAOG,GAAA,EAAA,EAAA,eAAsD,EAAE,CAAyB,CAOjF,GAAA,EAAA,EAAA,OACH,CACC,YACA,cAAc,aACd,GAAG,KAGC,CACJ,IAAM,GAAA,EAAA,EAAA,QAAY,CAElB,OACE,EAAA,EAAA,KAAC,EAAgB,SAAA,CAAS,MAAO,CAAE,KAAI,WACrC,EAAA,EAAA,KAACC,EAAAA,EAAAA,CAAmB,cAAa,GAAI,EAAkB,aAAa,EAC3C,EAGhC,CACD,EAAS,YAAc,WAGvB,MAAM,GAAA,EAAA,EAAA,OAAkB,CAAE,GAAG,KAA8D,CACzF,GAAM,CAAE,cAAe,GAAc,CACrC,OAAO,EAAA,EAAA,KAACC,EAAAA,EAAAA,CAAW,QAAS,EAAY,GAAI,GAAS,EACrD,CACF,EAAU,YAAc,YAGxB,MAAM,GAAA,EAAA,EAAA,OAAoB,CAAE,GAAG,KAA6D,CAC1F,GAAM,CAAE,QAAO,aAAY,oBAAmB,iBAAkB,GAAc,CAE9E,OACE,EAAA,EAAA,KAACC,EAAAA,KAAc,KAAA,CACb,YAAU,eACV,GAAI,EACJ,mBAAmB,EAAiC,GAAG,EAAkB,GAAG,IAAjD,GAAG,IAC9B,eAAc,CAAC,CAAC,EAChB,GAAI,GACJ,EAEJ,CACF,EAAY,YAAc,cAG1B,SAAS,EAAgB,CAAE,YAAW,GAAG,GAAoC,CAC3E,GAAM,CAAE,qBAAsB,GAAc,CAE5C,OACE,EAAA,EAAA,KAACC,EAAAA,EAAAA,CACC,GAAI,EACJ,WAAA,EAAA,EAAA,IACE,+DACA,6DACA,+DACA,oEACA,EACD,CACD,GAAI,GACJ,CAKN,SAAS,EAAY,CAAE,YAAW,WAAU,GAAG,GAAoC,CACjF,GAAM,CAAE,QAAO,iBAAkB,GAAc,CAE/C,OACE,EAAA,EAAA,KAAC,OAAA,CAAK,YAAU,eAAe,GAAI,EAAe,WAAA,EAAA,EAAA,IAAc,sBAAuB,EAAU,CAAE,GAAI,WACpG,EAAQ,OAAO,GAAO,SAAW,GAAG,CAAG,GACnC"}
|
package/dist/ui/form.d.cts
CHANGED
|
@@ -1,14 +1,49 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime158 from "react/jsx-runtime";
|
|
2
2
|
import * as react11 from "react";
|
|
3
3
|
import { Label, Slot } from "radix-ui";
|
|
4
4
|
import * as react_hook_form0 from "react-hook-form";
|
|
5
5
|
import { ControllerProps, FieldPath, FieldValues } from "react-hook-form";
|
|
6
6
|
|
|
7
7
|
//#region packages/components/ui/form.d.ts
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Re-export of react-hook-form's `FormProvider`; wrap your form with this to give all nested form components access to the form context.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@customafk/lunas-ui/ui/form';
|
|
15
|
+
* import { useForm } from 'react-hook-form';
|
|
16
|
+
*
|
|
17
|
+
* const form = useForm<{ username: string }>();
|
|
18
|
+
*
|
|
19
|
+
* <Form {...form}>
|
|
20
|
+
* <form onSubmit={form.handleSubmit(onSubmit)}>
|
|
21
|
+
* <FormField
|
|
22
|
+
* control={form.control}
|
|
23
|
+
* name="username"
|
|
24
|
+
* render={({ field }) => (
|
|
25
|
+
* <FormItem>
|
|
26
|
+
* <FormLabel>Username</FormLabel>
|
|
27
|
+
* <FormControl><input {...field} /></FormControl>
|
|
28
|
+
* <FormMessage />
|
|
29
|
+
* </FormItem>
|
|
30
|
+
* )}
|
|
31
|
+
* />
|
|
32
|
+
* </form>
|
|
33
|
+
* </Form>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
8
36
|
declare const Form: <TFieldValues extends FieldValues, TContext = any, TTransformedValues = TFieldValues>(props: react_hook_form0.FormProviderProps<TFieldValues, TContext, TTransformedValues>) => React.JSX.Element;
|
|
37
|
+
/**
|
|
38
|
+
* Connects a single react-hook-form field to the form context; renders a `Controller` and passes `name` down to nested FormItem, FormLabel, FormControl, and FormMessage.
|
|
39
|
+
*/
|
|
9
40
|
declare const FormField: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({
|
|
10
41
|
...props
|
|
11
|
-
}: ControllerProps<TFieldValues, TName>) =>
|
|
42
|
+
}: ControllerProps<TFieldValues, TName>) => react_jsx_runtime158.JSX.Element;
|
|
43
|
+
/**
|
|
44
|
+
* Hook that returns the field state and IDs for the enclosing FormField.
|
|
45
|
+
* Must be called inside a component rendered within a `<FormField>`.
|
|
46
|
+
*/
|
|
12
47
|
declare const useFormField: () => {
|
|
13
48
|
invalid: boolean;
|
|
14
49
|
isDirty: boolean;
|
|
@@ -23,28 +58,37 @@ declare const useFormField: () => {
|
|
|
23
58
|
formDescriptionId: string;
|
|
24
59
|
formMessageId: string;
|
|
25
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Container for a single form field — generates a unique ID and provides it via context to FormLabel, FormControl, and FormMessage.
|
|
63
|
+
*
|
|
64
|
+
* @param orientation - Layout direction: `'vertical'`, `'horizontal'`, or `'responsive'` (default).
|
|
65
|
+
*/
|
|
26
66
|
declare const FormItem: react11.MemoExoticComponent<({
|
|
27
67
|
className,
|
|
28
68
|
orientation,
|
|
29
69
|
...props
|
|
30
70
|
}: React.ComponentProps<"div"> & {
|
|
31
71
|
orientation?: "vertical" | "horizontal" | "responsive";
|
|
32
|
-
}) =>
|
|
72
|
+
}) => react_jsx_runtime158.JSX.Element>;
|
|
73
|
+
/** Styled label automatically associated with the FormItem's control via `htmlFor`. */
|
|
33
74
|
declare const FormLabel: react11.MemoExoticComponent<({
|
|
34
75
|
...props
|
|
35
|
-
}: React.ComponentProps<typeof Label.Root>) =>
|
|
76
|
+
}: React.ComponentProps<typeof Label.Root>) => react_jsx_runtime158.JSX.Element>;
|
|
77
|
+
/** Radix Slot wrapper that wires the correct `id`, `aria-describedby`, and `aria-invalid` attributes onto the underlying control element. */
|
|
36
78
|
declare const FormControl: react11.MemoExoticComponent<({
|
|
37
79
|
...props
|
|
38
|
-
}: React.ComponentProps<typeof Slot.Slot>) =>
|
|
80
|
+
}: React.ComponentProps<typeof Slot.Slot>) => react_jsx_runtime158.JSX.Element>;
|
|
81
|
+
/** Helper text displayed below the control that provides additional context about the field. */
|
|
39
82
|
declare function FormDescription({
|
|
40
83
|
className,
|
|
41
84
|
...props
|
|
42
|
-
}: React.ComponentProps<'p'>):
|
|
85
|
+
}: React.ComponentProps<'p'>): react_jsx_runtime158.JSX.Element;
|
|
86
|
+
/** Displays the validation error message for the field, or falls back to `children` when there is no error. */
|
|
43
87
|
declare function FormMessage({
|
|
44
88
|
className,
|
|
45
89
|
children,
|
|
46
90
|
...props
|
|
47
|
-
}: React.ComponentProps<'p'>):
|
|
91
|
+
}: React.ComponentProps<'p'>): react_jsx_runtime158.JSX.Element;
|
|
48
92
|
//#endregion
|
|
49
93
|
export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField };
|
|
50
94
|
//# sourceMappingURL=form.d.cts.map
|