@parto-system-design/ui 1.1.9 → 1.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/brand/parto-logo.cjs +130 -0
- package/dist/components/brand/parto-logo.cjs.map +1 -0
- package/dist/components/brand/parto-logo.d.cts +38 -0
- package/dist/components/brand/parto-logo.d.ts +38 -0
- package/dist/components/brand/parto-logo.js +108 -0
- package/dist/components/brand/parto-logo.js.map +1 -0
- package/dist/components/charts/PartoAreaChart.cjs +579 -7
- package/dist/components/charts/PartoAreaChart.cjs.map +1 -1
- package/dist/components/charts/PartoAreaChart.js +564 -4
- package/dist/components/charts/PartoAreaChart.js.map +1 -1
- package/dist/components/charts/PartoBarChart.cjs +616 -7
- package/dist/components/charts/PartoBarChart.cjs.map +1 -1
- package/dist/components/charts/PartoBarChart.js +601 -4
- package/dist/components/charts/PartoBarChart.js.map +1 -1
- package/dist/components/charts/PartoLineChart.cjs +584 -7
- package/dist/components/charts/PartoLineChart.cjs.map +1 -1
- package/dist/components/charts/PartoLineChart.js +569 -4
- package/dist/components/charts/PartoLineChart.js.map +1 -1
- package/dist/components/charts/PartoPieChart.cjs +566 -7
- package/dist/components/charts/PartoPieChart.cjs.map +1 -1
- package/dist/components/charts/PartoPieChart.js +551 -4
- package/dist/components/charts/PartoPieChart.js.map +1 -1
- package/dist/components/ui/accordion.cjs +97 -0
- package/dist/components/ui/accordion.cjs.map +1 -0
- package/dist/components/ui/accordion.d.cts +22 -0
- package/dist/components/ui/accordion.d.ts +22 -0
- package/dist/components/ui/accordion.js +72 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/{chunk-MMC6M35Q.cjs → components/ui/alert-dialog.cjs} +216 -22
- package/dist/components/ui/alert-dialog.cjs.map +1 -0
- package/dist/components/ui/alert-dialog.d.cts +17 -0
- package/dist/components/ui/alert-dialog.d.ts +17 -0
- package/dist/{chunk-3QYYPPFJ.js → components/ui/alert-dialog.js} +175 -10
- package/dist/components/ui/alert-dialog.js.map +1 -0
- package/dist/components/ui/alert-rule-card.cjs +289 -8
- package/dist/components/ui/alert-rule-card.cjs.map +1 -1
- package/dist/components/ui/alert-rule-card.d.cts +1 -1
- package/dist/components/ui/alert-rule-card.d.ts +1 -1
- package/dist/components/ui/alert-rule-card.js +271 -4
- package/dist/components/ui/alert-rule-card.js.map +1 -1
- package/dist/components/ui/alert.cjs +81 -0
- package/dist/components/ui/alert.cjs.map +1 -0
- package/dist/components/ui/alert.d.cts +11 -0
- package/dist/components/ui/alert.d.ts +11 -0
- package/dist/components/ui/alert.js +57 -0
- package/dist/components/ui/alert.js.map +1 -0
- package/dist/components/ui/app-bar.cjs +67 -0
- package/dist/components/ui/app-bar.cjs.map +1 -0
- package/dist/components/ui/app-bar.d.cts +22 -0
- package/dist/components/ui/app-bar.d.ts +22 -0
- package/dist/components/ui/app-bar.js +44 -0
- package/dist/components/ui/app-bar.js.map +1 -0
- package/dist/components/ui/avatar.cjs +66 -14
- package/dist/components/ui/avatar.cjs.map +1 -1
- package/dist/components/ui/avatar.js +47 -2
- package/dist/components/ui/avatar.js.map +1 -1
- package/dist/components/ui/badge.cjs +113 -9
- package/dist/components/ui/badge.cjs.map +1 -1
- package/dist/components/ui/badge.d.cts +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/badge.js +96 -2
- package/dist/components/ui/badge.js.map +1 -1
- package/dist/components/ui/breadcrumb.cjs +100 -0
- package/dist/components/ui/breadcrumb.cjs.map +1 -0
- package/dist/components/ui/breadcrumb.d.cts +35 -0
- package/dist/components/ui/breadcrumb.d.ts +35 -0
- package/dist/components/ui/breadcrumb.js +92 -0
- package/dist/components/ui/breadcrumb.js.map +1 -0
- package/dist/components/ui/button.cjs +304 -11
- package/dist/components/ui/button.cjs.map +1 -1
- package/dist/components/ui/button.d.cts +3 -3
- package/dist/components/ui/button.d.ts +3 -3
- package/dist/components/ui/button.js +306 -3
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/calendar.cjs +401 -8
- package/dist/components/ui/calendar.cjs.map +1 -1
- package/dist/components/ui/calendar.js +404 -4
- package/dist/components/ui/calendar.js.map +1 -1
- package/dist/components/ui/card.cjs +154 -30
- package/dist/components/ui/card.cjs.map +1 -1
- package/dist/components/ui/card.js +131 -2
- package/dist/components/ui/card.js.map +1 -1
- package/dist/{chunk-CAJKSTXX.cjs → components/ui/checkbox.cjs} +10 -5
- package/dist/components/ui/checkbox.cjs.map +1 -0
- package/dist/components/ui/checkbox.d.cts +6 -0
- package/dist/components/ui/checkbox.d.ts +6 -0
- package/dist/{chunk-5JJSRGJD.js → components/ui/checkbox.js} +9 -4
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/concept-card.cjs +728 -11
- package/dist/components/ui/concept-card.cjs.map +1 -1
- package/dist/components/ui/concept-card.d.cts +2 -2
- package/dist/components/ui/concept-card.d.ts +2 -2
- package/dist/components/ui/concept-card.js +710 -7
- package/dist/components/ui/concept-card.js.map +1 -1
- package/dist/components/ui/data-table.cjs +1553 -10
- package/dist/components/ui/data-table.cjs.map +1 -1
- package/dist/components/ui/data-table.js +1537 -7
- package/dist/components/ui/data-table.js.map +1 -1
- package/dist/components/ui/dialog.cjs +119 -42
- package/dist/components/ui/dialog.cjs.map +1 -1
- package/dist/components/ui/dialog.js +92 -2
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/components/ui/dropdown-menu.cjs +268 -0
- package/dist/components/ui/dropdown-menu.cjs.map +1 -0
- package/dist/components/ui/dropdown-menu.d.cts +73 -0
- package/dist/components/ui/dropdown-menu.d.ts +73 -0
- package/dist/components/ui/dropdown-menu.js +232 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/filter-provider.cjs +70 -13
- package/dist/components/ui/filter-provider.cjs.map +1 -1
- package/dist/components/ui/filter-provider.js +51 -1
- package/dist/components/ui/filter-provider.js.map +1 -1
- package/dist/components/ui/form.cjs +169 -0
- package/dist/components/ui/form.cjs.map +1 -0
- package/dist/components/ui/form.d.cts +46 -0
- package/dist/components/ui/form.d.ts +46 -0
- package/dist/components/ui/form.js +139 -0
- package/dist/components/ui/form.js.map +1 -0
- package/dist/components/ui/input.cjs +135 -15
- package/dist/components/ui/input.cjs.map +1 -1
- package/dist/components/ui/input.d.cts +15 -0
- package/dist/components/ui/input.d.ts +15 -0
- package/dist/components/ui/input.js +116 -3
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/iran-province-heat.cjs +328 -5
- package/dist/components/ui/iran-province-heat.cjs.map +1 -1
- package/dist/components/ui/iran-province-heat.js +312 -2
- package/dist/components/ui/iran-province-heat.js.map +1 -1
- package/dist/components/ui/label.cjs +52 -0
- package/dist/components/ui/label.cjs.map +1 -0
- package/dist/components/ui/label.d.cts +10 -0
- package/dist/components/ui/label.d.ts +10 -0
- package/dist/components/ui/label.js +30 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/page-card.cjs +627 -8
- package/dist/components/ui/page-card.cjs.map +1 -1
- package/dist/components/ui/page-card.d.cts +3 -2
- package/dist/components/ui/page-card.d.ts +3 -2
- package/dist/components/ui/page-card.js +611 -5
- package/dist/components/ui/page-card.js.map +1 -1
- package/dist/components/ui/page-header.cjs +299 -0
- package/dist/components/ui/page-header.cjs.map +1 -0
- package/dist/components/ui/page-header.d.cts +21 -0
- package/dist/components/ui/page-header.d.ts +21 -0
- package/dist/components/ui/page-header.js +277 -0
- package/dist/components/ui/page-header.js.map +1 -0
- package/dist/components/ui/password-input.cjs +168 -0
- package/dist/components/ui/password-input.cjs.map +1 -0
- package/dist/components/ui/password-input.d.cts +48 -0
- package/dist/components/ui/password-input.d.ts +48 -0
- package/dist/components/ui/password-input.js +146 -0
- package/dist/components/ui/password-input.js.map +1 -0
- package/dist/components/ui/popover.cjs +51 -18
- package/dist/components/ui/popover.cjs.map +1 -1
- package/dist/components/ui/popover.js +30 -2
- package/dist/components/ui/popover.js.map +1 -1
- package/dist/components/ui/progress.cjs +95 -0
- package/dist/components/ui/progress.cjs.map +1 -0
- package/dist/components/ui/progress.d.cts +18 -0
- package/dist/components/ui/progress.d.ts +18 -0
- package/dist/components/ui/progress.js +72 -0
- package/dist/components/ui/progress.js.map +1 -0
- package/dist/components/ui/radio-card.cjs +84 -0
- package/dist/components/ui/radio-card.cjs.map +1 -0
- package/dist/components/ui/radio-card.d.cts +12 -0
- package/dist/components/ui/radio-card.d.ts +12 -0
- package/dist/components/ui/radio-card.js +58 -0
- package/dist/components/ui/radio-card.js.map +1 -0
- package/dist/components/ui/radio-group.cjs +62 -0
- package/dist/components/ui/radio-group.cjs.map +1 -0
- package/dist/components/ui/radio-group.d.cts +7 -0
- package/dist/components/ui/radio-group.d.ts +7 -0
- package/dist/components/ui/radio-group.js +38 -0
- package/dist/components/ui/radio-group.js.map +1 -0
- package/dist/components/ui/saved-query-card.cjs +409 -7
- package/dist/components/ui/saved-query-card.cjs.map +1 -1
- package/dist/components/ui/saved-query-card.js +394 -4
- package/dist/components/ui/saved-query-card.js.map +1 -1
- package/dist/components/ui/scroll-area.cjs +79 -0
- package/dist/components/ui/scroll-area.cjs.map +1 -0
- package/dist/components/ui/scroll-area.d.cts +14 -0
- package/dist/components/ui/scroll-area.d.ts +14 -0
- package/dist/components/ui/scroll-area.js +56 -0
- package/dist/components/ui/scroll-area.js.map +1 -0
- package/dist/components/ui/select.cjs +242 -0
- package/dist/components/ui/select.cjs.map +1 -0
- package/dist/components/ui/select.d.cts +29 -0
- package/dist/components/ui/select.d.ts +29 -0
- package/dist/components/ui/select.js +210 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/separator.cjs +105 -6
- package/dist/components/ui/separator.cjs.map +1 -1
- package/dist/components/ui/separator.js +87 -2
- package/dist/components/ui/separator.js.map +1 -1
- package/dist/components/ui/sheet.cjs +134 -38
- package/dist/components/ui/sheet.cjs.map +1 -1
- package/dist/components/ui/sheet.js +109 -2
- package/dist/components/ui/sheet.js.map +1 -1
- package/dist/{chunk-D2EBLE2B.cjs → components/ui/skeleton.cjs} +21 -16
- package/dist/components/ui/skeleton.cjs.map +1 -0
- package/dist/components/ui/skeleton.d.cts +90 -0
- package/dist/components/ui/skeleton.d.ts +90 -0
- package/dist/{chunk-SB5DSYR5.js → components/ui/skeleton.js} +8 -3
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/slider.cjs +129 -0
- package/dist/components/ui/slider.cjs.map +1 -0
- package/dist/components/ui/slider.d.cts +10 -0
- package/dist/components/ui/slider.d.ts +10 -0
- package/dist/components/ui/slider.js +107 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/social-platform-badge.cjs +120 -0
- package/dist/components/ui/social-platform-badge.cjs.map +1 -0
- package/dist/components/ui/social-platform-badge.d.cts +21 -0
- package/dist/components/ui/social-platform-badge.d.ts +21 -0
- package/dist/components/ui/social-platform-badge.js +97 -0
- package/dist/components/ui/social-platform-badge.js.map +1 -0
- package/dist/components/ui/sonner.cjs +51 -0
- package/dist/components/ui/sonner.cjs.map +1 -0
- package/dist/components/ui/sonner.d.cts +13 -0
- package/dist/components/ui/sonner.d.ts +13 -0
- package/dist/components/ui/sonner.js +45 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/sparkline.cjs +159 -6
- package/dist/components/ui/sparkline.cjs.map +1 -1
- package/dist/components/ui/sparkline.js +142 -2
- package/dist/components/ui/sparkline.js.map +1 -1
- package/dist/components/ui/switch.cjs +96 -0
- package/dist/components/ui/switch.cjs.map +1 -0
- package/dist/components/ui/switch.d.cts +13 -0
- package/dist/components/ui/switch.d.ts +13 -0
- package/dist/components/ui/switch.js +73 -0
- package/dist/components/ui/switch.js.map +1 -0
- package/dist/components/ui/table.cjs +188 -0
- package/dist/components/ui/table.cjs.map +1 -0
- package/dist/components/ui/table.d.cts +59 -0
- package/dist/components/ui/table.d.ts +59 -0
- package/dist/components/ui/table.js +178 -0
- package/dist/components/ui/table.js.map +1 -0
- package/dist/components/ui/tabs.cjs +140 -0
- package/dist/components/ui/tabs.cjs.map +1 -0
- package/dist/components/ui/tabs.d.cts +21 -0
- package/dist/components/ui/tabs.d.ts +21 -0
- package/dist/components/ui/tabs.js +115 -0
- package/dist/components/ui/tabs.js.map +1 -0
- package/dist/components/ui/textarea.cjs +56 -0
- package/dist/components/ui/textarea.cjs.map +1 -0
- package/dist/components/ui/textarea.d.cts +5 -0
- package/dist/components/ui/textarea.d.ts +5 -0
- package/dist/components/ui/textarea.js +34 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/toggle-group.cjs +123 -0
- package/dist/components/ui/toggle-group.cjs.map +1 -0
- package/dist/components/ui/toggle-group.d.cts +7 -0
- package/dist/components/ui/toggle-group.d.ts +7 -0
- package/dist/components/ui/toggle-group.js +99 -0
- package/dist/components/ui/toggle-group.js.map +1 -0
- package/dist/components/ui/tooltip.cjs +77 -18
- package/dist/components/ui/tooltip.cjs.map +1 -1
- package/dist/components/ui/tooltip.js +56 -2
- package/dist/components/ui/tooltip.js.map +1 -1
- package/dist/{concept-card-RwPbqJ06.d.cts → concept-card-BXra9mr0.d.cts} +2 -2
- package/dist/{concept-card-CcOBb2Nz.d.ts → concept-card-BoJ5gIJD.d.ts} +2 -2
- package/dist/hooks/use-hotkey-registry.cjs +201 -14
- package/dist/hooks/use-hotkey-registry.cjs.map +1 -1
- package/dist/hooks/use-hotkey-registry.js +182 -2
- package/dist/hooks/use-hotkey-registry.js.map +1 -1
- package/dist/hooks/use-hotkeys.cjs +144 -9
- package/dist/hooks/use-hotkeys.cjs.map +1 -1
- package/dist/hooks/use-hotkeys.js +126 -1
- package/dist/hooks/use-hotkeys.js.map +1 -1
- package/dist/{i18n-CAd9wGOr.d.cts → i18n-BfRhV5aw.d.cts} +5 -3
- package/dist/{i18n-ArS3mqj0.d.ts → i18n-ewyqbKM-.d.ts} +5 -3
- package/dist/index.cjs +20940 -15745
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +396 -69
- package/dist/index.d.cts +60 -503
- package/dist/index.d.ts +60 -503
- package/dist/index.js +7716 -2049
- package/dist/index.js.map +1 -1
- package/dist/{page-card-CmShVqG-.d.cts → page-card-C9XXXOVr.d.cts} +3 -20
- package/dist/{page-card-HBn-cy4J.d.ts → page-card-DAnbez_f.d.ts} +3 -20
- package/dist/toggle-group-B8r4LOQw.d.cts +26 -0
- package/dist/toggle-group-B8r4LOQw.d.ts +26 -0
- package/package.json +132 -2
- package/tailwind.config.ts +45 -0
- package/dist/chunk-2ACKKPWA.cjs +0 -112
- package/dist/chunk-2ACKKPWA.cjs.map +0 -1
- package/dist/chunk-2UD3LGVX.cjs +0 -316
- package/dist/chunk-2UD3LGVX.cjs.map +0 -1
- package/dist/chunk-3QYYPPFJ.js.map +0 -1
- package/dist/chunk-4SVQNEVH.js +0 -173
- package/dist/chunk-4SVQNEVH.js.map +0 -1
- package/dist/chunk-4WONHORR.cjs +0 -152
- package/dist/chunk-4WONHORR.cjs.map +0 -1
- package/dist/chunk-5HCXH6GS.js +0 -409
- package/dist/chunk-5HCXH6GS.js.map +0 -1
- package/dist/chunk-5JJSRGJD.js.map +0 -1
- package/dist/chunk-5K6E4ZSW.cjs +0 -77
- package/dist/chunk-5K6E4ZSW.cjs.map +0 -1
- package/dist/chunk-5NY26ULO.js +0 -89
- package/dist/chunk-5NY26ULO.js.map +0 -1
- package/dist/chunk-7RVPG3LE.cjs +0 -231
- package/dist/chunk-7RVPG3LE.cjs.map +0 -1
- package/dist/chunk-AYEK3WOM.js +0 -207
- package/dist/chunk-AYEK3WOM.js.map +0 -1
- package/dist/chunk-BRMBLIQG.js +0 -53
- package/dist/chunk-BRMBLIQG.js.map +0 -1
- package/dist/chunk-CAJKSTXX.cjs.map +0 -1
- package/dist/chunk-CKFWMHQU.js +0 -401
- package/dist/chunk-CKFWMHQU.js.map +0 -1
- package/dist/chunk-CV3N3HVK.js +0 -672
- package/dist/chunk-CV3N3HVK.js.map +0 -1
- package/dist/chunk-D2EBLE2B.cjs.map +0 -1
- package/dist/chunk-GCZ6YATL.js +0 -940
- package/dist/chunk-GCZ6YATL.js.map +0 -1
- package/dist/chunk-GKRAZGDI.cjs +0 -84
- package/dist/chunk-GKRAZGDI.cjs.map +0 -1
- package/dist/chunk-GPYJ66CG.js +0 -45
- package/dist/chunk-GPYJ66CG.js.map +0 -1
- package/dist/chunk-HF6XU5NI.js +0 -84
- package/dist/chunk-HF6XU5NI.js.map +0 -1
- package/dist/chunk-HJPDZOMJ.cjs +0 -87
- package/dist/chunk-HJPDZOMJ.cjs.map +0 -1
- package/dist/chunk-HS3XI3CC.cjs +0 -69
- package/dist/chunk-HS3XI3CC.cjs.map +0 -1
- package/dist/chunk-HUCC3QH5.cjs +0 -53
- package/dist/chunk-HUCC3QH5.cjs.map +0 -1
- package/dist/chunk-HYZ6BQPS.cjs +0 -425
- package/dist/chunk-HYZ6BQPS.cjs.map +0 -1
- package/dist/chunk-ISCSZMYW.cjs +0 -106
- package/dist/chunk-ISCSZMYW.cjs.map +0 -1
- package/dist/chunk-IXFEFIDO.js +0 -82
- package/dist/chunk-IXFEFIDO.js.map +0 -1
- package/dist/chunk-JCJLN437.js +0 -108
- package/dist/chunk-JCJLN437.js.map +0 -1
- package/dist/chunk-JMKNNH63.cjs +0 -982
- package/dist/chunk-JMKNNH63.cjs.map +0 -1
- package/dist/chunk-JUBHQAA2.js +0 -53
- package/dist/chunk-JUBHQAA2.js.map +0 -1
- package/dist/chunk-K6G63EED.cjs +0 -41
- package/dist/chunk-K6G63EED.cjs.map +0 -1
- package/dist/chunk-KCWRCSI7.js +0 -62
- package/dist/chunk-KCWRCSI7.js.map +0 -1
- package/dist/chunk-KYM7NIJO.cjs +0 -433
- package/dist/chunk-KYM7NIJO.cjs.map +0 -1
- package/dist/chunk-L2L5CKC2.js +0 -291
- package/dist/chunk-L2L5CKC2.js.map +0 -1
- package/dist/chunk-M5CHZ5BA.js +0 -124
- package/dist/chunk-M5CHZ5BA.js.map +0 -1
- package/dist/chunk-MEK4RSGC.js +0 -65
- package/dist/chunk-MEK4RSGC.js.map +0 -1
- package/dist/chunk-MEKWH3GS.js +0 -89
- package/dist/chunk-MEKWH3GS.js.map +0 -1
- package/dist/chunk-MFTX2DDQ.js +0 -27
- package/dist/chunk-MFTX2DDQ.js.map +0 -1
- package/dist/chunk-MMC6M35Q.cjs.map +0 -1
- package/dist/chunk-NMH43BDC.js +0 -130
- package/dist/chunk-NMH43BDC.js.map +0 -1
- package/dist/chunk-NORDUD2T.cjs +0 -135
- package/dist/chunk-NORDUD2T.cjs.map +0 -1
- package/dist/chunk-NV4JOKWL.cjs +0 -197
- package/dist/chunk-NV4JOKWL.cjs.map +0 -1
- package/dist/chunk-O2JG7WY5.cjs +0 -121
- package/dist/chunk-O2JG7WY5.cjs.map +0 -1
- package/dist/chunk-ONO2FTV4.cjs +0 -68
- package/dist/chunk-ONO2FTV4.cjs.map +0 -1
- package/dist/chunk-OQB6HIUL.cjs +0 -108
- package/dist/chunk-OQB6HIUL.cjs.map +0 -1
- package/dist/chunk-OS6CMYAS.cjs +0 -79
- package/dist/chunk-OS6CMYAS.cjs.map +0 -1
- package/dist/chunk-PYURPUTV.js +0 -402
- package/dist/chunk-PYURPUTV.js.map +0 -1
- package/dist/chunk-RJ3HYZ7S.js +0 -44
- package/dist/chunk-RJ3HYZ7S.js.map +0 -1
- package/dist/chunk-RZNRIOLT.js +0 -128
- package/dist/chunk-RZNRIOLT.js.map +0 -1
- package/dist/chunk-S3T2L6NA.js +0 -38
- package/dist/chunk-S3T2L6NA.js.map +0 -1
- package/dist/chunk-S5IPJQZ3.cjs +0 -161
- package/dist/chunk-S5IPJQZ3.cjs.map +0 -1
- package/dist/chunk-SB5DSYR5.js.map +0 -1
- package/dist/chunk-SFXV2DUH.js +0 -106
- package/dist/chunk-SFXV2DUH.js.map +0 -1
- package/dist/chunk-SXEPGD4Z.cjs +0 -152
- package/dist/chunk-SXEPGD4Z.cjs.map +0 -1
- package/dist/chunk-SXWSOU3Y.js +0 -89
- package/dist/chunk-SXWSOU3Y.js.map +0 -1
- package/dist/chunk-SZMVOHT7.cjs +0 -107
- package/dist/chunk-SZMVOHT7.cjs.map +0 -1
- package/dist/chunk-TWJXOV4C.js +0 -145
- package/dist/chunk-TWJXOV4C.js.map +0 -1
- package/dist/chunk-U3ADRIVO.cjs +0 -434
- package/dist/chunk-U3ADRIVO.cjs.map +0 -1
- package/dist/chunk-U5FLLCGC.cjs +0 -151
- package/dist/chunk-U5FLLCGC.cjs.map +0 -1
- package/dist/chunk-UOZN45G4.cjs +0 -130
- package/dist/chunk-UOZN45G4.cjs.map +0 -1
- package/dist/chunk-VHLDOG74.cjs +0 -167
- package/dist/chunk-VHLDOG74.cjs.map +0 -1
- package/dist/chunk-YC5KLN6I.js +0 -139
- package/dist/chunk-YC5KLN6I.js.map +0 -1
- package/dist/chunk-YENXXYUV.cjs +0 -111
- package/dist/chunk-YENXXYUV.cjs.map +0 -1
- package/dist/chunk-YFQWC2PW.js +0 -113
- package/dist/chunk-YFQWC2PW.js.map +0 -1
- package/dist/chunk-Z2TY4A75.cjs +0 -700
- package/dist/chunk-Z2TY4A75.cjs.map +0 -1
- package/dist/chunk-Z56O7UEU.cjs +0 -136
- package/dist/chunk-Z56O7UEU.cjs.map +0 -1
- package/dist/chunk-ZBZDR4ZC.js +0 -106
- package/dist/chunk-ZBZDR4ZC.js.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var React2 = require('react');
|
|
5
|
+
var lucideReact = require('lucide-react');
|
|
6
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
7
|
+
var clsx = require('clsx');
|
|
8
|
+
var tailwindMerge = require('tailwind-merge');
|
|
9
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
+
|
|
11
|
+
function _interopNamespace(e) {
|
|
12
|
+
if (e && e.__esModule) return e;
|
|
13
|
+
var n = Object.create(null);
|
|
14
|
+
if (e) {
|
|
15
|
+
Object.keys(e).forEach(function (k) {
|
|
16
|
+
if (k !== 'default') {
|
|
17
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
18
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () { return e[k]; }
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
n.default = e;
|
|
26
|
+
return Object.freeze(n);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
|
|
30
|
+
|
|
31
|
+
// src/lib/constants.ts
|
|
32
|
+
var SIZE = {
|
|
33
|
+
text: {
|
|
34
|
+
xs: "text-xs",
|
|
35
|
+
sm: "text-sm leading-4",
|
|
36
|
+
md: "text-sm",
|
|
37
|
+
lg: "text-base",
|
|
38
|
+
xl: "text-base"
|
|
39
|
+
},
|
|
40
|
+
padding: {
|
|
41
|
+
xs: "px-2.5 py-1",
|
|
42
|
+
sm: "px-3 py-2",
|
|
43
|
+
md: "px-4 py-2",
|
|
44
|
+
lg: "px-4 py-2",
|
|
45
|
+
xl: "px-6 py-3"
|
|
46
|
+
},
|
|
47
|
+
height: {
|
|
48
|
+
xs: "h-[26px]",
|
|
49
|
+
sm: "h-[34px]",
|
|
50
|
+
md: "h-[38px]",
|
|
51
|
+
lg: "h-[42px]",
|
|
52
|
+
xl: "h-[50px]"
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var SIZE_VARIANTS = {
|
|
56
|
+
xs: `${SIZE.text["xs"]} ${SIZE.padding["xs"]} ${SIZE.height["xs"]}`,
|
|
57
|
+
sm: `${SIZE.text["sm"]} ${SIZE.padding["sm"]} ${SIZE.height["sm"]}`,
|
|
58
|
+
md: `${SIZE.text["md"]} ${SIZE.padding["md"]} ${SIZE.height["md"]}`,
|
|
59
|
+
lg: `${SIZE.text["lg"]} ${SIZE.padding["lg"]} ${SIZE.height["lg"]}`,
|
|
60
|
+
xl: `${SIZE.text["xl"]} ${SIZE.padding["xl"]} ${SIZE.height["xl"]}`
|
|
61
|
+
};
|
|
62
|
+
function cn(...inputs) {
|
|
63
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
64
|
+
}
|
|
65
|
+
var inputVariants = classVarianceAuthority.cva(
|
|
66
|
+
cn(
|
|
67
|
+
// 1.1.16 — bg-control (now 19% in dark) instead of foreground/2.6%
|
|
68
|
+
// opacity overlay, so the input is visibly distinct from any Card
|
|
69
|
+
// it sits inside. text-start makes text-align follow the input's
|
|
70
|
+
// own `dir` (set explicitly or auto for LTR types), so an email
|
|
71
|
+
// field with `dir="ltr"` is left-aligned even in an RTL form.
|
|
72
|
+
"flex w-full rounded-md border border-control read-only:border-button bg-control text-sm text-foreground text-start file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-foreground-lighter read-only:text-foreground-light",
|
|
73
|
+
"transition-colors duration-150",
|
|
74
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
|
|
75
|
+
"aria-[invalid=true]:bg-destructive-200 dark:aria-[invalid=true]:bg-destructive/5 aria-[invalid=true]:border-destructive-400 dark:aria-[invalid=true]:border-destructive-default aria-[invalid=true]:focus:border-destructive aria-[invalid=true]:focus-visible:border-destructive"
|
|
76
|
+
),
|
|
77
|
+
{
|
|
78
|
+
variants: {
|
|
79
|
+
size: {
|
|
80
|
+
...SIZE_VARIANTS
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
defaultVariants: {
|
|
84
|
+
size: "sm"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
var LTR_INPUT_TYPES = /* @__PURE__ */ new Set(["email", "url", "tel", "number", "password"]);
|
|
89
|
+
var Input = React2__namespace.forwardRef(
|
|
90
|
+
({ className, type, size = "sm", dir, startAdornment, endAdornment, ...props }, ref) => {
|
|
91
|
+
const resolvedDir = dir ?? (type && LTR_INPUT_TYPES.has(type) ? "ltr" : void 0);
|
|
92
|
+
if (!startAdornment && !endAdornment) {
|
|
93
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
94
|
+
"input",
|
|
95
|
+
{
|
|
96
|
+
type,
|
|
97
|
+
ref,
|
|
98
|
+
"data-slot": "input",
|
|
99
|
+
dir: resolvedDir,
|
|
100
|
+
...props,
|
|
101
|
+
className: cn(inputVariants({ size }), className)
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "input-wrapper", dir: resolvedDir, className: "relative w-full", children: [
|
|
106
|
+
startAdornment && /* @__PURE__ */ jsxRuntime.jsx(
|
|
107
|
+
"span",
|
|
108
|
+
{
|
|
109
|
+
"data-slot": "input-start-adornment",
|
|
110
|
+
className: "pointer-events-none absolute start-3 top-1/2 flex -translate-y-1/2 items-center text-foreground-light [&_button]:pointer-events-auto",
|
|
111
|
+
children: startAdornment
|
|
112
|
+
}
|
|
113
|
+
),
|
|
114
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
115
|
+
"input",
|
|
116
|
+
{
|
|
117
|
+
type,
|
|
118
|
+
ref,
|
|
119
|
+
"data-slot": "input",
|
|
120
|
+
dir: resolvedDir,
|
|
121
|
+
...props,
|
|
122
|
+
className: cn(inputVariants({ size }), startAdornment && "ps-10", endAdornment && "pe-10", className)
|
|
123
|
+
}
|
|
124
|
+
),
|
|
125
|
+
endAdornment && /* @__PURE__ */ jsxRuntime.jsx(
|
|
126
|
+
"span",
|
|
127
|
+
{
|
|
128
|
+
"data-slot": "input-end-adornment",
|
|
129
|
+
className: "pointer-events-none absolute end-3 top-1/2 flex -translate-y-1/2 items-center text-foreground-light [&_button]:pointer-events-auto",
|
|
130
|
+
children: endAdornment
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
] });
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
Input.displayName = "Input";
|
|
137
|
+
var PasswordInput = React2__namespace.forwardRef(
|
|
138
|
+
({ enableVisibilityToggle = true, showLabel = "\u0646\u0645\u0627\u06CC\u0634 \u0631\u0645\u0632", hideLabel = "\u0645\u062E\u0641\u06CC \u06A9\u0631\u062F\u0646 \u0631\u0645\u0632", dir, ...props }, ref) => {
|
|
139
|
+
const [visible, setVisible] = React2__namespace.useState(false);
|
|
140
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
141
|
+
Input,
|
|
142
|
+
{
|
|
143
|
+
ref,
|
|
144
|
+
type: visible ? "text" : "password",
|
|
145
|
+
dir: dir ?? "ltr",
|
|
146
|
+
"data-slot": "password-input",
|
|
147
|
+
endAdornment: enableVisibilityToggle ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
148
|
+
"button",
|
|
149
|
+
{
|
|
150
|
+
type: "button",
|
|
151
|
+
onClick: () => setVisible((v) => !v),
|
|
152
|
+
tabIndex: -1,
|
|
153
|
+
className: "text-foreground-light hover:text-foreground transition-colors",
|
|
154
|
+
"aria-label": visible ? hideLabel : showLabel,
|
|
155
|
+
"aria-pressed": visible,
|
|
156
|
+
children: visible ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { size: 15, "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 15, "aria-hidden": "true" })
|
|
157
|
+
}
|
|
158
|
+
) : void 0,
|
|
159
|
+
...props
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
PasswordInput.displayName = "PasswordInput";
|
|
165
|
+
|
|
166
|
+
exports.PasswordInput = PasswordInput;
|
|
167
|
+
//# sourceMappingURL=password-input.cjs.map
|
|
168
|
+
//# sourceMappingURL=password-input.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/constants.ts","../../../src/lib/utils.ts","../../../src/components/ui/input.tsx","../../../src/components/ui/password-input.tsx"],"names":["twMerge","clsx","cva","React","jsx","React2","EyeOff","Eye"],"mappings":"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","file":"password-input.cjs","sourcesContent":["/**\n * Standard size scale used across the design system.\n * Components should accept these values for their `size` prop.\n */\nexport type StandardSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n\n/** @deprecated Use `StandardSize` instead — legacy names have been removed */\nexport type LegacySize = StandardSize\n\n/** @deprecated Use `StandardSize` instead */\nexport type SizeWithLegacy = StandardSize\n\n/**\n * Normalizes a size value to standard names.\n * @deprecated All sizes are standard now — this function is a no-op passthrough.\n */\nexport function normalizeSize(size: StandardSize): StandardSize {\n return size\n}\n\nexport const SIZE = {\n text: {\n xs: 'text-xs',\n sm: 'text-sm leading-4',\n md: 'text-sm',\n lg: 'text-base',\n xl: 'text-base',\n },\n padding: {\n xs: 'px-2.5 py-1',\n sm: 'px-3 py-2',\n md: 'px-4 py-2',\n lg: 'px-4 py-2',\n xl: 'px-6 py-3',\n },\n height: {\n xs: 'h-[26px]',\n sm: 'h-[34px]',\n md: 'h-[38px]',\n lg: 'h-[42px]',\n xl: 'h-[50px]',\n },\n}\n\n/** Inner sizes for nested elements (badges inside buttons, multi-select items, etc.) */\nexport const SIZE_INNER = {\n text: {\n xs: 'text-xs',\n sm: 'text-sm leading-4',\n md: 'text-sm',\n lg: 'text-base',\n xl: 'text-base',\n },\n padding: {\n xs: 'px-2.5 py-1',\n sm: 'px-3 py-2',\n md: 'px-4 py-2',\n lg: 'px-4 py-2',\n xl: 'px-6 py-3',\n },\n height: {\n xs: 'h-[24px]',\n sm: 'h-[28px]',\n md: 'h-[32px]',\n lg: 'h-[36px]',\n xl: 'h-[44px]',\n },\n}\n\nexport const SIZE_VARIANTS = {\n xs: `${SIZE.text['xs']} ${SIZE.padding['xs']} ${SIZE.height['xs']}`,\n sm: `${SIZE.text['sm']} ${SIZE.padding['sm']} ${SIZE.height['sm']}`,\n md: `${SIZE.text['md']} ${SIZE.padding['md']} ${SIZE.height['md']}`,\n lg: `${SIZE.text['lg']} ${SIZE.padding['lg']} ${SIZE.height['lg']}`,\n xl: `${SIZE.text['xl']} ${SIZE.padding['xl']} ${SIZE.height['xl']}`,\n}\n\nexport const SIZE_VARIANTS_INNER = {\n xs: `${SIZE.text['xs']} ${SIZE.padding['xs']} ${SIZE_INNER.height['xs']}`,\n sm: `${SIZE.text['sm']} ${SIZE.padding['sm']} ${SIZE_INNER.height['sm']}`,\n md: `${SIZE.text['md']} ${SIZE.padding['md']} ${SIZE_INNER.height['md']}`,\n lg: `${SIZE.text['lg']} ${SIZE.padding['lg']} ${SIZE_INNER.height['lg']}`,\n xl: `${SIZE.text['xl']} ${SIZE.padding['xl']} ${SIZE_INNER.height['xl']}`,\n}\n\n/** @deprecated Use 'sm' instead */\nexport const SIZE_VARIANTS_DEFAULT = 'sm'\n","import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\nimport { formatJalaliDate } from '@/lib/jalali-utils'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\nexport type SupportedLocale = 'fa' | 'ar' | 'en'\n\n/**\n * Convert digits in a string to Persian/Arabic numerals based on locale.\n * @example convertToLocalNumbers('123', 'fa') => '۱۲۳'\n * @example convertToLocalNumbers('123', 'en') => '123'\n */\nexport function convertToLocalNumbers(text: string | number, locale: SupportedLocale): string {\n if (locale === 'fa' || locale === 'ar') {\n const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']\n return String(text).replace(/\\d/g, (digit) => persianDigits[parseInt(digit)])\n }\n return String(text)\n}\n\n/**\n * Format large numbers with locale-aware suffixes (K/M/B).\n * @example formatLargeNumber(1500, 'fa') => '۱.۵ هزار'\n * @example formatLargeNumber(1500, 'en') => '1.5K'\n */\nexport function formatLargeNumber(num: number, locale: SupportedLocale): string {\n if (num >= 1_000_000_000) {\n const formatted = (num / 1_000_000_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'B' : ' میلیارد')\n }\n if (num >= 1_000_000) {\n const formatted = (num / 1_000_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'M' : ' میلیون')\n }\n if (num >= 1_000) {\n const formatted = (num / 1_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'K' : ' هزار')\n }\n return convertToLocalNumbers(num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ','), locale)\n}\n\n/**\n * Format number to Instagram-style short format (English only).\n * @example formatNumber(123456, 'short') => '123K'\n * @example formatNumber(123456, 'exact') => '123,456'\n */\nexport function formatNumber(num: number | undefined, format: 'exact' | 'short' = 'exact'): string {\n if (num === undefined || num === null) return '0'\n\n if (format === 'exact') {\n return num.toLocaleString('en-US')\n }\n\n // Short format (Instagram style)\n if (num >= 1_000_000_000) {\n return `${(num / 1_000_000_000).toFixed(1).replace(/\\.0$/, '')}B`\n }\n if (num >= 1_000_000) {\n return `${(num / 1_000_000).toFixed(1).replace(/\\.0$/, '')}M`\n }\n if (num >= 1_000) {\n return `${(num / 1_000).toFixed(1).replace(/\\.0$/, '')}K`\n }\n return num.toString()\n}\n\n/**\n * Format date to relative time with absolute on hover (Persian)\n * @example formatRelativeTime(new Date()) => '۲ ساعت پیش'\n */\nexport function formatRelativeTime(date: Date | string | number): string {\n const now = new Date()\n const then = new Date(date)\n const diffInSeconds = Math.floor((now.getTime() - then.getTime()) / 1000)\n\n if (diffInSeconds < 60) {\n return 'همین الان'\n }\n\n const diffInMinutes = Math.floor(diffInSeconds / 60)\n if (diffInMinutes < 60) {\n return `${convertToLocalNumbers(diffInMinutes, 'fa')} دقیقه پیش`\n }\n\n const diffInHours = Math.floor(diffInMinutes / 60)\n if (diffInHours < 24) {\n return `${convertToLocalNumbers(diffInHours, 'fa')} ساعت پیش`\n }\n\n const diffInDays = Math.floor(diffInHours / 24)\n if (diffInDays < 7) {\n return `${convertToLocalNumbers(diffInDays, 'fa')} روز پیش`\n }\n\n const diffInWeeks = Math.floor(diffInDays / 7)\n if (diffInWeeks < 4) {\n return `${convertToLocalNumbers(diffInWeeks, 'fa')} هفته پیش`\n }\n\n const diffInMonths = Math.floor(diffInDays / 30)\n if (diffInMonths < 12) {\n return `${convertToLocalNumbers(diffInMonths, 'fa')} ماه پیش`\n }\n\n const diffInYears = Math.floor(diffInDays / 365)\n return `${convertToLocalNumbers(diffInYears, 'fa')} سال پیش`\n}\n\n/**\n * Format date to absolute format (Persian / Jalali)\n * Uses date-fns-jalali for accurate Jalali conversion.\n * @example formatAbsoluteTime(new Date()) => '۱۵ دی ۱۴۰۳، ۱۵:۳۰'\n */\nexport function formatAbsoluteTime(date: Date | string | number): string {\n const d = new Date(date)\n return formatJalaliDate(d, 'd MMMM yyyy، HH:mm')\n}\n","'use client'\n\nimport { VariantProps, cva } from 'class-variance-authority'\nimport * as React from 'react'\nimport { SIZE_VARIANTS } from '@/lib/constants'\nimport { cn } from '@/lib/utils'\n\nexport const inputVariants = cva(\n cn(\n // 1.1.16 — bg-control (now 19% in dark) instead of foreground/2.6%\n // opacity overlay, so the input is visibly distinct from any Card\n // it sits inside. text-start makes text-align follow the input's\n // own `dir` (set explicitly or auto for LTR types), so an email\n // field with `dir=\"ltr\"` is left-aligned even in an RTL form.\n 'flex w-full rounded-md border border-control read-only:border-button bg-control text-sm text-foreground text-start file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-foreground-lighter read-only:text-foreground-light',\n 'transition-colors duration-150',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50',\n 'aria-[invalid=true]:bg-destructive-200 dark:aria-[invalid=true]:bg-destructive/5 aria-[invalid=true]:border-destructive-400 dark:aria-[invalid=true]:border-destructive-default aria-[invalid=true]:focus:border-destructive aria-[invalid=true]:focus-visible:border-destructive'\n ),\n {\n variants: {\n size: {\n ...SIZE_VARIANTS,\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n }\n)\n\n/** @deprecated Use inputVariants instead */\nexport const InputVariants = inputVariants\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>, VariantProps<typeof inputVariants> {\n /**\n * Node rendered at the start of the input (left in LTR, right in RTL).\n * Common use: a search icon, a country flag, a currency symbol.\n * The adornment wrapper is `pointer-events-none` by default so it doesn't\n * steal focus from the input — interactive elements inside (e.g. a\n * `<button>` for a password show/hide toggle) get `pointer-events-auto`\n * back automatically.\n */\n startAdornment?: React.ReactNode\n /**\n * Node rendered at the end of the input (right in LTR, left in RTL).\n * Common use: a password show/hide toggle, a clear button, a unit suffix.\n * See `startAdornment` for the pointer-events behavior.\n */\n endAdornment?: React.ReactNode\n}\n\nconst LTR_INPUT_TYPES = new Set(['email', 'url', 'tel', 'number', 'password'])\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, size = 'sm', dir, startAdornment, endAdornment, ...props }, ref) => {\n // LTR content types: auto-set dir=\"ltr\" unless caller explicitly overrides\n const resolvedDir = dir ?? (type && LTR_INPUT_TYPES.has(type) ? 'ltr' : undefined)\n\n // Fast path: no adornments → render the bare <input>. Zero wrapper cost,\n // identical to the pre-1.1.14 behavior for backward compatibility.\n if (!startAdornment && !endAdornment) {\n return (\n <input\n type={type}\n ref={ref}\n data-slot=\"input\"\n dir={resolvedDir}\n {...props}\n className={cn(inputVariants({ size }), className)}\n />\n )\n }\n\n // Adornment path: wrap in a relative container that inherits the input's\n // OWN direction. This is the key bug fix: when a password input declares\n // `dir=\"ltr\"` inside an `dir=\"rtl\"` page, the adornment must be positioned\n // relative to the input's flow (right side for LTR), not the page's flow\n // (which would put it under the typed characters).\n return (\n <div data-slot=\"input-wrapper\" dir={resolvedDir} className=\"relative w-full\">\n {startAdornment && (\n <span\n data-slot=\"input-start-adornment\"\n className=\"pointer-events-none absolute start-3 top-1/2 flex -translate-y-1/2 items-center text-foreground-light [&_button]:pointer-events-auto\"\n >\n {startAdornment}\n </span>\n )}\n <input\n type={type}\n ref={ref}\n data-slot=\"input\"\n dir={resolvedDir}\n {...props}\n className={cn(inputVariants({ size }), startAdornment && 'ps-10', endAdornment && 'pe-10', className)}\n />\n {endAdornment && (\n <span\n data-slot=\"input-end-adornment\"\n className=\"pointer-events-none absolute end-3 top-1/2 flex -translate-y-1/2 items-center text-foreground-light [&_button]:pointer-events-auto\"\n >\n {endAdornment}\n </span>\n )}\n </div>\n )\n }\n)\n\nInput.displayName = 'Input'\n\nexport { Input }\n","'use client'\n\nimport * as React from 'react'\nimport { Eye, EyeOff } from 'lucide-react'\nimport { Input, type InputProps } from './input'\n\n/**\n * Password input with built-in show/hide toggle.\n *\n * Why this exists as a dedicated component rather than asking consumers to\n * compose Input + endAdornment:\n *\n * 1. **Stable direction across visibility toggles.** A naive composition\n * flips the `type` between `password` and `text` on click. The base\n * `Input` auto-resolves `dir=\"ltr\"` only for the `password` type — so\n * when type becomes `text`, the input wrapper drops back to the page's\n * `rtl` direction and the eye-icon adornment visibly jumps to the\n * opposite side mid-interaction. This component forces `dir=\"ltr\"`\n * once for the whole lifecycle.\n *\n * 2. **Standard pattern.** Mantine `<PasswordInput>`, Chakra `<InputGroup>`,\n * MUI `<TextField type=\"password\" endAdornment>` — every major DS\n * surfaces this as a first-class component because the composition is\n * fiddly and easy to get wrong.\n *\n * 3. **Persian aria labels by default.** \"نمایش رمز\" / \"مخفی کردن رمز\"\n * so consumers don't have to remember to localize the toggle.\n */\nexport interface PasswordInputProps extends Omit<InputProps, 'type' | 'endAdornment'> {\n /**\n * Show the eye toggle button. Defaults to true. Set to false for cases\n * where you want a pure password field (e.g. forms with a separate\n * \"show password\" checkbox).\n */\n enableVisibilityToggle?: boolean\n /**\n * Aria-label for the toggle when the password is currently hidden.\n * Defaults to \"نمایش رمز\".\n */\n showLabel?: string\n /**\n * Aria-label for the toggle when the password is currently visible.\n * Defaults to \"مخفی کردن رمز\".\n */\n hideLabel?: string\n}\n\nconst PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(\n ({ enableVisibilityToggle = true, showLabel = 'نمایش رمز', hideLabel = 'مخفی کردن رمز', dir, ...props }, ref) => {\n const [visible, setVisible] = React.useState(false)\n\n return (\n <Input\n ref={ref}\n type={visible ? 'text' : 'password'}\n // Force ltr so the adornment stays on the same side when the type\n // toggles between password and text. Consumer can still override by\n // explicitly passing `dir`.\n dir={dir ?? 'ltr'}\n data-slot=\"password-input\"\n endAdornment={\n enableVisibilityToggle ? (\n <button\n type=\"button\"\n onClick={() => setVisible((v) => !v)}\n // tabIndex=-1: keep keyboard flow on submit, not on the toggle.\n tabIndex={-1}\n className=\"text-foreground-light hover:text-foreground transition-colors\"\n aria-label={visible ? hideLabel : showLabel}\n aria-pressed={visible}\n >\n {visible ? <EyeOff size={15} aria-hidden=\"true\" /> : <Eye size={15} aria-hidden=\"true\" />}\n </button>\n ) : undefined\n }\n {...props}\n />\n )\n }\n)\n\nPasswordInput.displayName = 'PasswordInput'\n\nexport { PasswordInput }\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { InputProps } from './input.cjs';
|
|
3
|
+
import 'class-variance-authority/types';
|
|
4
|
+
import 'class-variance-authority';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Password input with built-in show/hide toggle.
|
|
8
|
+
*
|
|
9
|
+
* Why this exists as a dedicated component rather than asking consumers to
|
|
10
|
+
* compose Input + endAdornment:
|
|
11
|
+
*
|
|
12
|
+
* 1. **Stable direction across visibility toggles.** A naive composition
|
|
13
|
+
* flips the `type` between `password` and `text` on click. The base
|
|
14
|
+
* `Input` auto-resolves `dir="ltr"` only for the `password` type — so
|
|
15
|
+
* when type becomes `text`, the input wrapper drops back to the page's
|
|
16
|
+
* `rtl` direction and the eye-icon adornment visibly jumps to the
|
|
17
|
+
* opposite side mid-interaction. This component forces `dir="ltr"`
|
|
18
|
+
* once for the whole lifecycle.
|
|
19
|
+
*
|
|
20
|
+
* 2. **Standard pattern.** Mantine `<PasswordInput>`, Chakra `<InputGroup>`,
|
|
21
|
+
* MUI `<TextField type="password" endAdornment>` — every major DS
|
|
22
|
+
* surfaces this as a first-class component because the composition is
|
|
23
|
+
* fiddly and easy to get wrong.
|
|
24
|
+
*
|
|
25
|
+
* 3. **Persian aria labels by default.** "نمایش رمز" / "مخفی کردن رمز"
|
|
26
|
+
* so consumers don't have to remember to localize the toggle.
|
|
27
|
+
*/
|
|
28
|
+
interface PasswordInputProps extends Omit<InputProps, 'type' | 'endAdornment'> {
|
|
29
|
+
/**
|
|
30
|
+
* Show the eye toggle button. Defaults to true. Set to false for cases
|
|
31
|
+
* where you want a pure password field (e.g. forms with a separate
|
|
32
|
+
* "show password" checkbox).
|
|
33
|
+
*/
|
|
34
|
+
enableVisibilityToggle?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Aria-label for the toggle when the password is currently hidden.
|
|
37
|
+
* Defaults to "نمایش رمز".
|
|
38
|
+
*/
|
|
39
|
+
showLabel?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Aria-label for the toggle when the password is currently visible.
|
|
42
|
+
* Defaults to "مخفی کردن رمز".
|
|
43
|
+
*/
|
|
44
|
+
hideLabel?: string;
|
|
45
|
+
}
|
|
46
|
+
declare const PasswordInput: React.ForwardRefExoticComponent<PasswordInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
47
|
+
|
|
48
|
+
export { PasswordInput, type PasswordInputProps };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { InputProps } from './input.js';
|
|
3
|
+
import 'class-variance-authority/types';
|
|
4
|
+
import 'class-variance-authority';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Password input with built-in show/hide toggle.
|
|
8
|
+
*
|
|
9
|
+
* Why this exists as a dedicated component rather than asking consumers to
|
|
10
|
+
* compose Input + endAdornment:
|
|
11
|
+
*
|
|
12
|
+
* 1. **Stable direction across visibility toggles.** A naive composition
|
|
13
|
+
* flips the `type` between `password` and `text` on click. The base
|
|
14
|
+
* `Input` auto-resolves `dir="ltr"` only for the `password` type — so
|
|
15
|
+
* when type becomes `text`, the input wrapper drops back to the page's
|
|
16
|
+
* `rtl` direction and the eye-icon adornment visibly jumps to the
|
|
17
|
+
* opposite side mid-interaction. This component forces `dir="ltr"`
|
|
18
|
+
* once for the whole lifecycle.
|
|
19
|
+
*
|
|
20
|
+
* 2. **Standard pattern.** Mantine `<PasswordInput>`, Chakra `<InputGroup>`,
|
|
21
|
+
* MUI `<TextField type="password" endAdornment>` — every major DS
|
|
22
|
+
* surfaces this as a first-class component because the composition is
|
|
23
|
+
* fiddly and easy to get wrong.
|
|
24
|
+
*
|
|
25
|
+
* 3. **Persian aria labels by default.** "نمایش رمز" / "مخفی کردن رمز"
|
|
26
|
+
* so consumers don't have to remember to localize the toggle.
|
|
27
|
+
*/
|
|
28
|
+
interface PasswordInputProps extends Omit<InputProps, 'type' | 'endAdornment'> {
|
|
29
|
+
/**
|
|
30
|
+
* Show the eye toggle button. Defaults to true. Set to false for cases
|
|
31
|
+
* where you want a pure password field (e.g. forms with a separate
|
|
32
|
+
* "show password" checkbox).
|
|
33
|
+
*/
|
|
34
|
+
enableVisibilityToggle?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Aria-label for the toggle when the password is currently hidden.
|
|
37
|
+
* Defaults to "نمایش رمز".
|
|
38
|
+
*/
|
|
39
|
+
showLabel?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Aria-label for the toggle when the password is currently visible.
|
|
42
|
+
* Defaults to "مخفی کردن رمز".
|
|
43
|
+
*/
|
|
44
|
+
hideLabel?: string;
|
|
45
|
+
}
|
|
46
|
+
declare const PasswordInput: React.ForwardRefExoticComponent<PasswordInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
47
|
+
|
|
48
|
+
export { PasswordInput, type PasswordInputProps };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React2 from 'react';
|
|
3
|
+
import { EyeOff, Eye } from 'lucide-react';
|
|
4
|
+
import { cva } from 'class-variance-authority';
|
|
5
|
+
import { clsx } from 'clsx';
|
|
6
|
+
import { twMerge } from 'tailwind-merge';
|
|
7
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
// src/lib/constants.ts
|
|
10
|
+
var SIZE = {
|
|
11
|
+
text: {
|
|
12
|
+
xs: "text-xs",
|
|
13
|
+
sm: "text-sm leading-4",
|
|
14
|
+
md: "text-sm",
|
|
15
|
+
lg: "text-base",
|
|
16
|
+
xl: "text-base"
|
|
17
|
+
},
|
|
18
|
+
padding: {
|
|
19
|
+
xs: "px-2.5 py-1",
|
|
20
|
+
sm: "px-3 py-2",
|
|
21
|
+
md: "px-4 py-2",
|
|
22
|
+
lg: "px-4 py-2",
|
|
23
|
+
xl: "px-6 py-3"
|
|
24
|
+
},
|
|
25
|
+
height: {
|
|
26
|
+
xs: "h-[26px]",
|
|
27
|
+
sm: "h-[34px]",
|
|
28
|
+
md: "h-[38px]",
|
|
29
|
+
lg: "h-[42px]",
|
|
30
|
+
xl: "h-[50px]"
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var SIZE_VARIANTS = {
|
|
34
|
+
xs: `${SIZE.text["xs"]} ${SIZE.padding["xs"]} ${SIZE.height["xs"]}`,
|
|
35
|
+
sm: `${SIZE.text["sm"]} ${SIZE.padding["sm"]} ${SIZE.height["sm"]}`,
|
|
36
|
+
md: `${SIZE.text["md"]} ${SIZE.padding["md"]} ${SIZE.height["md"]}`,
|
|
37
|
+
lg: `${SIZE.text["lg"]} ${SIZE.padding["lg"]} ${SIZE.height["lg"]}`,
|
|
38
|
+
xl: `${SIZE.text["xl"]} ${SIZE.padding["xl"]} ${SIZE.height["xl"]}`
|
|
39
|
+
};
|
|
40
|
+
function cn(...inputs) {
|
|
41
|
+
return twMerge(clsx(inputs));
|
|
42
|
+
}
|
|
43
|
+
var inputVariants = cva(
|
|
44
|
+
cn(
|
|
45
|
+
// 1.1.16 — bg-control (now 19% in dark) instead of foreground/2.6%
|
|
46
|
+
// opacity overlay, so the input is visibly distinct from any Card
|
|
47
|
+
// it sits inside. text-start makes text-align follow the input's
|
|
48
|
+
// own `dir` (set explicitly or auto for LTR types), so an email
|
|
49
|
+
// field with `dir="ltr"` is left-aligned even in an RTL form.
|
|
50
|
+
"flex w-full rounded-md border border-control read-only:border-button bg-control text-sm text-foreground text-start file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-foreground-lighter read-only:text-foreground-light",
|
|
51
|
+
"transition-colors duration-150",
|
|
52
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
|
|
53
|
+
"aria-[invalid=true]:bg-destructive-200 dark:aria-[invalid=true]:bg-destructive/5 aria-[invalid=true]:border-destructive-400 dark:aria-[invalid=true]:border-destructive-default aria-[invalid=true]:focus:border-destructive aria-[invalid=true]:focus-visible:border-destructive"
|
|
54
|
+
),
|
|
55
|
+
{
|
|
56
|
+
variants: {
|
|
57
|
+
size: {
|
|
58
|
+
...SIZE_VARIANTS
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
defaultVariants: {
|
|
62
|
+
size: "sm"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
var LTR_INPUT_TYPES = /* @__PURE__ */ new Set(["email", "url", "tel", "number", "password"]);
|
|
67
|
+
var Input = React2.forwardRef(
|
|
68
|
+
({ className, type, size = "sm", dir, startAdornment, endAdornment, ...props }, ref) => {
|
|
69
|
+
const resolvedDir = dir ?? (type && LTR_INPUT_TYPES.has(type) ? "ltr" : void 0);
|
|
70
|
+
if (!startAdornment && !endAdornment) {
|
|
71
|
+
return /* @__PURE__ */ jsx(
|
|
72
|
+
"input",
|
|
73
|
+
{
|
|
74
|
+
type,
|
|
75
|
+
ref,
|
|
76
|
+
"data-slot": "input",
|
|
77
|
+
dir: resolvedDir,
|
|
78
|
+
...props,
|
|
79
|
+
className: cn(inputVariants({ size }), className)
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return /* @__PURE__ */ jsxs("div", { "data-slot": "input-wrapper", dir: resolvedDir, className: "relative w-full", children: [
|
|
84
|
+
startAdornment && /* @__PURE__ */ jsx(
|
|
85
|
+
"span",
|
|
86
|
+
{
|
|
87
|
+
"data-slot": "input-start-adornment",
|
|
88
|
+
className: "pointer-events-none absolute start-3 top-1/2 flex -translate-y-1/2 items-center text-foreground-light [&_button]:pointer-events-auto",
|
|
89
|
+
children: startAdornment
|
|
90
|
+
}
|
|
91
|
+
),
|
|
92
|
+
/* @__PURE__ */ jsx(
|
|
93
|
+
"input",
|
|
94
|
+
{
|
|
95
|
+
type,
|
|
96
|
+
ref,
|
|
97
|
+
"data-slot": "input",
|
|
98
|
+
dir: resolvedDir,
|
|
99
|
+
...props,
|
|
100
|
+
className: cn(inputVariants({ size }), startAdornment && "ps-10", endAdornment && "pe-10", className)
|
|
101
|
+
}
|
|
102
|
+
),
|
|
103
|
+
endAdornment && /* @__PURE__ */ jsx(
|
|
104
|
+
"span",
|
|
105
|
+
{
|
|
106
|
+
"data-slot": "input-end-adornment",
|
|
107
|
+
className: "pointer-events-none absolute end-3 top-1/2 flex -translate-y-1/2 items-center text-foreground-light [&_button]:pointer-events-auto",
|
|
108
|
+
children: endAdornment
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
] });
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
Input.displayName = "Input";
|
|
115
|
+
var PasswordInput = React2.forwardRef(
|
|
116
|
+
({ enableVisibilityToggle = true, showLabel = "\u0646\u0645\u0627\u06CC\u0634 \u0631\u0645\u0632", hideLabel = "\u0645\u062E\u0641\u06CC \u06A9\u0631\u062F\u0646 \u0631\u0645\u0632", dir, ...props }, ref) => {
|
|
117
|
+
const [visible, setVisible] = React2.useState(false);
|
|
118
|
+
return /* @__PURE__ */ jsx(
|
|
119
|
+
Input,
|
|
120
|
+
{
|
|
121
|
+
ref,
|
|
122
|
+
type: visible ? "text" : "password",
|
|
123
|
+
dir: dir ?? "ltr",
|
|
124
|
+
"data-slot": "password-input",
|
|
125
|
+
endAdornment: enableVisibilityToggle ? /* @__PURE__ */ jsx(
|
|
126
|
+
"button",
|
|
127
|
+
{
|
|
128
|
+
type: "button",
|
|
129
|
+
onClick: () => setVisible((v) => !v),
|
|
130
|
+
tabIndex: -1,
|
|
131
|
+
className: "text-foreground-light hover:text-foreground transition-colors",
|
|
132
|
+
"aria-label": visible ? hideLabel : showLabel,
|
|
133
|
+
"aria-pressed": visible,
|
|
134
|
+
children: visible ? /* @__PURE__ */ jsx(EyeOff, { size: 15, "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Eye, { size: 15, "aria-hidden": "true" })
|
|
135
|
+
}
|
|
136
|
+
) : void 0,
|
|
137
|
+
...props
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
PasswordInput.displayName = "PasswordInput";
|
|
143
|
+
|
|
144
|
+
export { PasswordInput };
|
|
145
|
+
//# sourceMappingURL=password-input.js.map
|
|
146
|
+
//# sourceMappingURL=password-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/constants.ts","../../../src/lib/utils.ts","../../../src/components/ui/input.tsx","../../../src/components/ui/password-input.tsx"],"names":["React","jsx"],"mappings":"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","file":"password-input.js","sourcesContent":["/**\n * Standard size scale used across the design system.\n * Components should accept these values for their `size` prop.\n */\nexport type StandardSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n\n/** @deprecated Use `StandardSize` instead — legacy names have been removed */\nexport type LegacySize = StandardSize\n\n/** @deprecated Use `StandardSize` instead */\nexport type SizeWithLegacy = StandardSize\n\n/**\n * Normalizes a size value to standard names.\n * @deprecated All sizes are standard now — this function is a no-op passthrough.\n */\nexport function normalizeSize(size: StandardSize): StandardSize {\n return size\n}\n\nexport const SIZE = {\n text: {\n xs: 'text-xs',\n sm: 'text-sm leading-4',\n md: 'text-sm',\n lg: 'text-base',\n xl: 'text-base',\n },\n padding: {\n xs: 'px-2.5 py-1',\n sm: 'px-3 py-2',\n md: 'px-4 py-2',\n lg: 'px-4 py-2',\n xl: 'px-6 py-3',\n },\n height: {\n xs: 'h-[26px]',\n sm: 'h-[34px]',\n md: 'h-[38px]',\n lg: 'h-[42px]',\n xl: 'h-[50px]',\n },\n}\n\n/** Inner sizes for nested elements (badges inside buttons, multi-select items, etc.) */\nexport const SIZE_INNER = {\n text: {\n xs: 'text-xs',\n sm: 'text-sm leading-4',\n md: 'text-sm',\n lg: 'text-base',\n xl: 'text-base',\n },\n padding: {\n xs: 'px-2.5 py-1',\n sm: 'px-3 py-2',\n md: 'px-4 py-2',\n lg: 'px-4 py-2',\n xl: 'px-6 py-3',\n },\n height: {\n xs: 'h-[24px]',\n sm: 'h-[28px]',\n md: 'h-[32px]',\n lg: 'h-[36px]',\n xl: 'h-[44px]',\n },\n}\n\nexport const SIZE_VARIANTS = {\n xs: `${SIZE.text['xs']} ${SIZE.padding['xs']} ${SIZE.height['xs']}`,\n sm: `${SIZE.text['sm']} ${SIZE.padding['sm']} ${SIZE.height['sm']}`,\n md: `${SIZE.text['md']} ${SIZE.padding['md']} ${SIZE.height['md']}`,\n lg: `${SIZE.text['lg']} ${SIZE.padding['lg']} ${SIZE.height['lg']}`,\n xl: `${SIZE.text['xl']} ${SIZE.padding['xl']} ${SIZE.height['xl']}`,\n}\n\nexport const SIZE_VARIANTS_INNER = {\n xs: `${SIZE.text['xs']} ${SIZE.padding['xs']} ${SIZE_INNER.height['xs']}`,\n sm: `${SIZE.text['sm']} ${SIZE.padding['sm']} ${SIZE_INNER.height['sm']}`,\n md: `${SIZE.text['md']} ${SIZE.padding['md']} ${SIZE_INNER.height['md']}`,\n lg: `${SIZE.text['lg']} ${SIZE.padding['lg']} ${SIZE_INNER.height['lg']}`,\n xl: `${SIZE.text['xl']} ${SIZE.padding['xl']} ${SIZE_INNER.height['xl']}`,\n}\n\n/** @deprecated Use 'sm' instead */\nexport const SIZE_VARIANTS_DEFAULT = 'sm'\n","import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\nimport { formatJalaliDate } from '@/lib/jalali-utils'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\nexport type SupportedLocale = 'fa' | 'ar' | 'en'\n\n/**\n * Convert digits in a string to Persian/Arabic numerals based on locale.\n * @example convertToLocalNumbers('123', 'fa') => '۱۲۳'\n * @example convertToLocalNumbers('123', 'en') => '123'\n */\nexport function convertToLocalNumbers(text: string | number, locale: SupportedLocale): string {\n if (locale === 'fa' || locale === 'ar') {\n const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']\n return String(text).replace(/\\d/g, (digit) => persianDigits[parseInt(digit)])\n }\n return String(text)\n}\n\n/**\n * Format large numbers with locale-aware suffixes (K/M/B).\n * @example formatLargeNumber(1500, 'fa') => '۱.۵ هزار'\n * @example formatLargeNumber(1500, 'en') => '1.5K'\n */\nexport function formatLargeNumber(num: number, locale: SupportedLocale): string {\n if (num >= 1_000_000_000) {\n const formatted = (num / 1_000_000_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'B' : ' میلیارد')\n }\n if (num >= 1_000_000) {\n const formatted = (num / 1_000_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'M' : ' میلیون')\n }\n if (num >= 1_000) {\n const formatted = (num / 1_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'K' : ' هزار')\n }\n return convertToLocalNumbers(num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ','), locale)\n}\n\n/**\n * Format number to Instagram-style short format (English only).\n * @example formatNumber(123456, 'short') => '123K'\n * @example formatNumber(123456, 'exact') => '123,456'\n */\nexport function formatNumber(num: number | undefined, format: 'exact' | 'short' = 'exact'): string {\n if (num === undefined || num === null) return '0'\n\n if (format === 'exact') {\n return num.toLocaleString('en-US')\n }\n\n // Short format (Instagram style)\n if (num >= 1_000_000_000) {\n return `${(num / 1_000_000_000).toFixed(1).replace(/\\.0$/, '')}B`\n }\n if (num >= 1_000_000) {\n return `${(num / 1_000_000).toFixed(1).replace(/\\.0$/, '')}M`\n }\n if (num >= 1_000) {\n return `${(num / 1_000).toFixed(1).replace(/\\.0$/, '')}K`\n }\n return num.toString()\n}\n\n/**\n * Format date to relative time with absolute on hover (Persian)\n * @example formatRelativeTime(new Date()) => '۲ ساعت پیش'\n */\nexport function formatRelativeTime(date: Date | string | number): string {\n const now = new Date()\n const then = new Date(date)\n const diffInSeconds = Math.floor((now.getTime() - then.getTime()) / 1000)\n\n if (diffInSeconds < 60) {\n return 'همین الان'\n }\n\n const diffInMinutes = Math.floor(diffInSeconds / 60)\n if (diffInMinutes < 60) {\n return `${convertToLocalNumbers(diffInMinutes, 'fa')} دقیقه پیش`\n }\n\n const diffInHours = Math.floor(diffInMinutes / 60)\n if (diffInHours < 24) {\n return `${convertToLocalNumbers(diffInHours, 'fa')} ساعت پیش`\n }\n\n const diffInDays = Math.floor(diffInHours / 24)\n if (diffInDays < 7) {\n return `${convertToLocalNumbers(diffInDays, 'fa')} روز پیش`\n }\n\n const diffInWeeks = Math.floor(diffInDays / 7)\n if (diffInWeeks < 4) {\n return `${convertToLocalNumbers(diffInWeeks, 'fa')} هفته پیش`\n }\n\n const diffInMonths = Math.floor(diffInDays / 30)\n if (diffInMonths < 12) {\n return `${convertToLocalNumbers(diffInMonths, 'fa')} ماه پیش`\n }\n\n const diffInYears = Math.floor(diffInDays / 365)\n return `${convertToLocalNumbers(diffInYears, 'fa')} سال پیش`\n}\n\n/**\n * Format date to absolute format (Persian / Jalali)\n * Uses date-fns-jalali for accurate Jalali conversion.\n * @example formatAbsoluteTime(new Date()) => '۱۵ دی ۱۴۰۳، ۱۵:۳۰'\n */\nexport function formatAbsoluteTime(date: Date | string | number): string {\n const d = new Date(date)\n return formatJalaliDate(d, 'd MMMM yyyy، HH:mm')\n}\n","'use client'\n\nimport { VariantProps, cva } from 'class-variance-authority'\nimport * as React from 'react'\nimport { SIZE_VARIANTS } from '@/lib/constants'\nimport { cn } from '@/lib/utils'\n\nexport const inputVariants = cva(\n cn(\n // 1.1.16 — bg-control (now 19% in dark) instead of foreground/2.6%\n // opacity overlay, so the input is visibly distinct from any Card\n // it sits inside. text-start makes text-align follow the input's\n // own `dir` (set explicitly or auto for LTR types), so an email\n // field with `dir=\"ltr\"` is left-aligned even in an RTL form.\n 'flex w-full rounded-md border border-control read-only:border-button bg-control text-sm text-foreground text-start file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-foreground-lighter read-only:text-foreground-light',\n 'transition-colors duration-150',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50',\n 'aria-[invalid=true]:bg-destructive-200 dark:aria-[invalid=true]:bg-destructive/5 aria-[invalid=true]:border-destructive-400 dark:aria-[invalid=true]:border-destructive-default aria-[invalid=true]:focus:border-destructive aria-[invalid=true]:focus-visible:border-destructive'\n ),\n {\n variants: {\n size: {\n ...SIZE_VARIANTS,\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n }\n)\n\n/** @deprecated Use inputVariants instead */\nexport const InputVariants = inputVariants\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>, VariantProps<typeof inputVariants> {\n /**\n * Node rendered at the start of the input (left in LTR, right in RTL).\n * Common use: a search icon, a country flag, a currency symbol.\n * The adornment wrapper is `pointer-events-none` by default so it doesn't\n * steal focus from the input — interactive elements inside (e.g. a\n * `<button>` for a password show/hide toggle) get `pointer-events-auto`\n * back automatically.\n */\n startAdornment?: React.ReactNode\n /**\n * Node rendered at the end of the input (right in LTR, left in RTL).\n * Common use: a password show/hide toggle, a clear button, a unit suffix.\n * See `startAdornment` for the pointer-events behavior.\n */\n endAdornment?: React.ReactNode\n}\n\nconst LTR_INPUT_TYPES = new Set(['email', 'url', 'tel', 'number', 'password'])\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, size = 'sm', dir, startAdornment, endAdornment, ...props }, ref) => {\n // LTR content types: auto-set dir=\"ltr\" unless caller explicitly overrides\n const resolvedDir = dir ?? (type && LTR_INPUT_TYPES.has(type) ? 'ltr' : undefined)\n\n // Fast path: no adornments → render the bare <input>. Zero wrapper cost,\n // identical to the pre-1.1.14 behavior for backward compatibility.\n if (!startAdornment && !endAdornment) {\n return (\n <input\n type={type}\n ref={ref}\n data-slot=\"input\"\n dir={resolvedDir}\n {...props}\n className={cn(inputVariants({ size }), className)}\n />\n )\n }\n\n // Adornment path: wrap in a relative container that inherits the input's\n // OWN direction. This is the key bug fix: when a password input declares\n // `dir=\"ltr\"` inside an `dir=\"rtl\"` page, the adornment must be positioned\n // relative to the input's flow (right side for LTR), not the page's flow\n // (which would put it under the typed characters).\n return (\n <div data-slot=\"input-wrapper\" dir={resolvedDir} className=\"relative w-full\">\n {startAdornment && (\n <span\n data-slot=\"input-start-adornment\"\n className=\"pointer-events-none absolute start-3 top-1/2 flex -translate-y-1/2 items-center text-foreground-light [&_button]:pointer-events-auto\"\n >\n {startAdornment}\n </span>\n )}\n <input\n type={type}\n ref={ref}\n data-slot=\"input\"\n dir={resolvedDir}\n {...props}\n className={cn(inputVariants({ size }), startAdornment && 'ps-10', endAdornment && 'pe-10', className)}\n />\n {endAdornment && (\n <span\n data-slot=\"input-end-adornment\"\n className=\"pointer-events-none absolute end-3 top-1/2 flex -translate-y-1/2 items-center text-foreground-light [&_button]:pointer-events-auto\"\n >\n {endAdornment}\n </span>\n )}\n </div>\n )\n }\n)\n\nInput.displayName = 'Input'\n\nexport { Input }\n","'use client'\n\nimport * as React from 'react'\nimport { Eye, EyeOff } from 'lucide-react'\nimport { Input, type InputProps } from './input'\n\n/**\n * Password input with built-in show/hide toggle.\n *\n * Why this exists as a dedicated component rather than asking consumers to\n * compose Input + endAdornment:\n *\n * 1. **Stable direction across visibility toggles.** A naive composition\n * flips the `type` between `password` and `text` on click. The base\n * `Input` auto-resolves `dir=\"ltr\"` only for the `password` type — so\n * when type becomes `text`, the input wrapper drops back to the page's\n * `rtl` direction and the eye-icon adornment visibly jumps to the\n * opposite side mid-interaction. This component forces `dir=\"ltr\"`\n * once for the whole lifecycle.\n *\n * 2. **Standard pattern.** Mantine `<PasswordInput>`, Chakra `<InputGroup>`,\n * MUI `<TextField type=\"password\" endAdornment>` — every major DS\n * surfaces this as a first-class component because the composition is\n * fiddly and easy to get wrong.\n *\n * 3. **Persian aria labels by default.** \"نمایش رمز\" / \"مخفی کردن رمز\"\n * so consumers don't have to remember to localize the toggle.\n */\nexport interface PasswordInputProps extends Omit<InputProps, 'type' | 'endAdornment'> {\n /**\n * Show the eye toggle button. Defaults to true. Set to false for cases\n * where you want a pure password field (e.g. forms with a separate\n * \"show password\" checkbox).\n */\n enableVisibilityToggle?: boolean\n /**\n * Aria-label for the toggle when the password is currently hidden.\n * Defaults to \"نمایش رمز\".\n */\n showLabel?: string\n /**\n * Aria-label for the toggle when the password is currently visible.\n * Defaults to \"مخفی کردن رمز\".\n */\n hideLabel?: string\n}\n\nconst PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(\n ({ enableVisibilityToggle = true, showLabel = 'نمایش رمز', hideLabel = 'مخفی کردن رمز', dir, ...props }, ref) => {\n const [visible, setVisible] = React.useState(false)\n\n return (\n <Input\n ref={ref}\n type={visible ? 'text' : 'password'}\n // Force ltr so the adornment stays on the same side when the type\n // toggles between password and text. Consumer can still override by\n // explicitly passing `dir`.\n dir={dir ?? 'ltr'}\n data-slot=\"password-input\"\n endAdornment={\n enableVisibilityToggle ? (\n <button\n type=\"button\"\n onClick={() => setVisible((v) => !v)}\n // tabIndex=-1: keep keyboard flow on submit, not on the toggle.\n tabIndex={-1}\n className=\"text-foreground-light hover:text-foreground transition-colors\"\n aria-label={visible ? hideLabel : showLabel}\n aria-pressed={visible}\n >\n {visible ? <EyeOff size={15} aria-hidden=\"true\" /> : <Eye size={15} aria-hidden=\"true\" />}\n </button>\n ) : undefined\n }\n {...props}\n />\n )\n }\n)\n\nPasswordInput.displayName = 'PasswordInput'\n\nexport { PasswordInput }\n"]}
|
|
@@ -1,25 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
|
-
var
|
|
4
|
-
require('
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var PopoverPrimitive = require('@radix-ui/react-popover');
|
|
6
|
+
var clsx = require('clsx');
|
|
7
|
+
var tailwindMerge = require('tailwind-merge');
|
|
8
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
9
|
|
|
10
|
+
function _interopNamespace(e) {
|
|
11
|
+
if (e && e.__esModule) return e;
|
|
12
|
+
var n = Object.create(null);
|
|
13
|
+
if (e) {
|
|
14
|
+
Object.keys(e).forEach(function (k) {
|
|
15
|
+
if (k !== 'default') {
|
|
16
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function () { return e[k]; }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
n.default = e;
|
|
25
|
+
return Object.freeze(n);
|
|
26
|
+
}
|
|
6
27
|
|
|
28
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
29
|
+
var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
|
|
7
30
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
function cn(...inputs) {
|
|
32
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
33
|
+
}
|
|
34
|
+
var Popover = PopoverPrimitive__namespace.Root;
|
|
35
|
+
var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
|
|
36
|
+
var PopoverAnchor = PopoverPrimitive__namespace.Anchor;
|
|
37
|
+
var PopoverContent = React__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
38
|
+
PopoverPrimitive__namespace.Content,
|
|
39
|
+
{
|
|
40
|
+
ref,
|
|
41
|
+
"data-slot": "popover-content",
|
|
42
|
+
align,
|
|
43
|
+
sideOffset,
|
|
44
|
+
className: cn(
|
|
45
|
+
"z-50 rounded-md border border-overlay bg-overlay p-4 text-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
|
|
46
|
+
className
|
|
47
|
+
),
|
|
48
|
+
...props
|
|
49
|
+
}
|
|
50
|
+
) }));
|
|
51
|
+
PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
|
|
52
|
+
|
|
53
|
+
exports.Popover = Popover;
|
|
54
|
+
exports.PopoverAnchor = PopoverAnchor;
|
|
55
|
+
exports.PopoverContent = PopoverContent;
|
|
56
|
+
exports.PopoverTrigger = PopoverTrigger;
|
|
24
57
|
//# sourceMappingURL=popover.cjs.map
|
|
25
58
|
//# sourceMappingURL=popover.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"popover.cjs"}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/popover.tsx"],"names":["twMerge","clsx","PopoverPrimitive","React","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACCA,IAAM,OAAA,GAA2BC,2BAAA,CAAA;AAEjC,IAAM,cAAA,GAAkCA,2BAAA,CAAA;AAExC,IAAM,aAAA,GAAiCA,2BAAA,CAAA;AAEvC,IAAM,cAAA,GAAuBC,gBAAA,CAAA,UAAA,CAG3B,CAAC,EAAE,WAAW,KAAA,GAAQ,QAAA,EAAU,UAAA,GAAa,CAAA,EAAG,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC5DC,cAAA,CAAkBF,oCAAjB,EACC,QAAA,kBAAAE,cAAA;AAAA,EAAkBF,2BAAA,CAAA,OAAA;AAAA,EAAjB;AAAA,IACC,GAAA;AAAA,IACA,WAAA,EAAU,iBAAA;AAAA,IACV,KAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,geAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG;AAAA;AACN,CAAA,EACF,CACD;AACD,cAAA,CAAe,cAA+BA,2BAAA,CAAA,OAAA,CAAQ,WAAA","file":"popover.cjs","sourcesContent":["import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\nimport { formatJalaliDate } from '@/lib/jalali-utils'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\nexport type SupportedLocale = 'fa' | 'ar' | 'en'\n\n/**\n * Convert digits in a string to Persian/Arabic numerals based on locale.\n * @example convertToLocalNumbers('123', 'fa') => '۱۲۳'\n * @example convertToLocalNumbers('123', 'en') => '123'\n */\nexport function convertToLocalNumbers(text: string | number, locale: SupportedLocale): string {\n if (locale === 'fa' || locale === 'ar') {\n const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']\n return String(text).replace(/\\d/g, (digit) => persianDigits[parseInt(digit)])\n }\n return String(text)\n}\n\n/**\n * Format large numbers with locale-aware suffixes (K/M/B).\n * @example formatLargeNumber(1500, 'fa') => '۱.۵ هزار'\n * @example formatLargeNumber(1500, 'en') => '1.5K'\n */\nexport function formatLargeNumber(num: number, locale: SupportedLocale): string {\n if (num >= 1_000_000_000) {\n const formatted = (num / 1_000_000_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'B' : ' میلیارد')\n }\n if (num >= 1_000_000) {\n const formatted = (num / 1_000_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'M' : ' میلیون')\n }\n if (num >= 1_000) {\n const formatted = (num / 1_000).toFixed(1).replace(/\\.0$/, '')\n return convertToLocalNumbers(formatted, locale) + (locale === 'en' ? 'K' : ' هزار')\n }\n return convertToLocalNumbers(num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ','), locale)\n}\n\n/**\n * Format number to Instagram-style short format (English only).\n * @example formatNumber(123456, 'short') => '123K'\n * @example formatNumber(123456, 'exact') => '123,456'\n */\nexport function formatNumber(num: number | undefined, format: 'exact' | 'short' = 'exact'): string {\n if (num === undefined || num === null) return '0'\n\n if (format === 'exact') {\n return num.toLocaleString('en-US')\n }\n\n // Short format (Instagram style)\n if (num >= 1_000_000_000) {\n return `${(num / 1_000_000_000).toFixed(1).replace(/\\.0$/, '')}B`\n }\n if (num >= 1_000_000) {\n return `${(num / 1_000_000).toFixed(1).replace(/\\.0$/, '')}M`\n }\n if (num >= 1_000) {\n return `${(num / 1_000).toFixed(1).replace(/\\.0$/, '')}K`\n }\n return num.toString()\n}\n\n/**\n * Format date to relative time with absolute on hover (Persian)\n * @example formatRelativeTime(new Date()) => '۲ ساعت پیش'\n */\nexport function formatRelativeTime(date: Date | string | number): string {\n const now = new Date()\n const then = new Date(date)\n const diffInSeconds = Math.floor((now.getTime() - then.getTime()) / 1000)\n\n if (diffInSeconds < 60) {\n return 'همین الان'\n }\n\n const diffInMinutes = Math.floor(diffInSeconds / 60)\n if (diffInMinutes < 60) {\n return `${convertToLocalNumbers(diffInMinutes, 'fa')} دقیقه پیش`\n }\n\n const diffInHours = Math.floor(diffInMinutes / 60)\n if (diffInHours < 24) {\n return `${convertToLocalNumbers(diffInHours, 'fa')} ساعت پیش`\n }\n\n const diffInDays = Math.floor(diffInHours / 24)\n if (diffInDays < 7) {\n return `${convertToLocalNumbers(diffInDays, 'fa')} روز پیش`\n }\n\n const diffInWeeks = Math.floor(diffInDays / 7)\n if (diffInWeeks < 4) {\n return `${convertToLocalNumbers(diffInWeeks, 'fa')} هفته پیش`\n }\n\n const diffInMonths = Math.floor(diffInDays / 30)\n if (diffInMonths < 12) {\n return `${convertToLocalNumbers(diffInMonths, 'fa')} ماه پیش`\n }\n\n const diffInYears = Math.floor(diffInDays / 365)\n return `${convertToLocalNumbers(diffInYears, 'fa')} سال پیش`\n}\n\n/**\n * Format date to absolute format (Persian / Jalali)\n * Uses date-fns-jalali for accurate Jalali conversion.\n * @example formatAbsoluteTime(new Date()) => '۱۵ دی ۱۴۰۳، ۱۵:۳۰'\n */\nexport function formatAbsoluteTime(date: Date | string | number): string {\n const d = new Date(date)\n return formatJalaliDate(d, 'd MMMM yyyy، HH:mm')\n}\n","'use client'\n\nimport * as React from 'react'\nimport * as PopoverPrimitive from '@radix-ui/react-popover'\n\nimport { cn } from '@/lib/utils'\n\nconst Popover = PopoverPrimitive.Root\n\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverAnchor = PopoverPrimitive.Anchor\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 rounded-md border border-overlay bg-overlay p-4 text-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]',\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }\n"]}
|
|
@@ -1,4 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
import '
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
6
|
+
import { jsx } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
function cn(...inputs) {
|
|
9
|
+
return twMerge(clsx(inputs));
|
|
10
|
+
}
|
|
11
|
+
var Popover = PopoverPrimitive.Root;
|
|
12
|
+
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
13
|
+
var PopoverAnchor = PopoverPrimitive.Anchor;
|
|
14
|
+
var PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
15
|
+
PopoverPrimitive.Content,
|
|
16
|
+
{
|
|
17
|
+
ref,
|
|
18
|
+
"data-slot": "popover-content",
|
|
19
|
+
align,
|
|
20
|
+
sideOffset,
|
|
21
|
+
className: cn(
|
|
22
|
+
"z-50 rounded-md border border-overlay bg-overlay p-4 text-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
|
|
23
|
+
className
|
|
24
|
+
),
|
|
25
|
+
...props
|
|
26
|
+
}
|
|
27
|
+
) }));
|
|
28
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
29
|
+
|
|
30
|
+
export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
|
|
3
31
|
//# sourceMappingURL=popover.js.map
|
|
4
32
|
//# sourceMappingURL=popover.js.map
|