@parto-system-design/ui 1.1.11 → 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.
Files changed (411) hide show
  1. package/dist/components/brand/parto-logo.cjs +130 -0
  2. package/dist/components/brand/parto-logo.cjs.map +1 -0
  3. package/dist/components/brand/parto-logo.d.cts +38 -0
  4. package/dist/components/brand/parto-logo.d.ts +38 -0
  5. package/dist/components/brand/parto-logo.js +108 -0
  6. package/dist/components/brand/parto-logo.js.map +1 -0
  7. package/dist/components/charts/PartoAreaChart.cjs +579 -7
  8. package/dist/components/charts/PartoAreaChart.cjs.map +1 -1
  9. package/dist/components/charts/PartoAreaChart.js +564 -4
  10. package/dist/components/charts/PartoAreaChart.js.map +1 -1
  11. package/dist/components/charts/PartoBarChart.cjs +616 -7
  12. package/dist/components/charts/PartoBarChart.cjs.map +1 -1
  13. package/dist/components/charts/PartoBarChart.js +601 -4
  14. package/dist/components/charts/PartoBarChart.js.map +1 -1
  15. package/dist/components/charts/PartoLineChart.cjs +584 -7
  16. package/dist/components/charts/PartoLineChart.cjs.map +1 -1
  17. package/dist/components/charts/PartoLineChart.js +569 -4
  18. package/dist/components/charts/PartoLineChart.js.map +1 -1
  19. package/dist/components/charts/PartoPieChart.cjs +566 -7
  20. package/dist/components/charts/PartoPieChart.cjs.map +1 -1
  21. package/dist/components/charts/PartoPieChart.js +551 -4
  22. package/dist/components/charts/PartoPieChart.js.map +1 -1
  23. package/dist/components/ui/accordion.cjs +97 -0
  24. package/dist/components/ui/accordion.cjs.map +1 -0
  25. package/dist/components/ui/accordion.d.cts +22 -0
  26. package/dist/components/ui/accordion.d.ts +22 -0
  27. package/dist/components/ui/accordion.js +72 -0
  28. package/dist/components/ui/accordion.js.map +1 -0
  29. package/dist/{chunk-MMC6M35Q.cjs → components/ui/alert-dialog.cjs} +216 -22
  30. package/dist/components/ui/alert-dialog.cjs.map +1 -0
  31. package/dist/components/ui/alert-dialog.d.cts +17 -0
  32. package/dist/components/ui/alert-dialog.d.ts +17 -0
  33. package/dist/{chunk-3QYYPPFJ.js → components/ui/alert-dialog.js} +175 -10
  34. package/dist/components/ui/alert-dialog.js.map +1 -0
  35. package/dist/components/ui/alert-rule-card.cjs +289 -8
  36. package/dist/components/ui/alert-rule-card.cjs.map +1 -1
  37. package/dist/components/ui/alert-rule-card.d.cts +1 -1
  38. package/dist/components/ui/alert-rule-card.d.ts +1 -1
  39. package/dist/components/ui/alert-rule-card.js +271 -4
  40. package/dist/components/ui/alert-rule-card.js.map +1 -1
  41. package/dist/components/ui/alert.cjs +81 -0
  42. package/dist/components/ui/alert.cjs.map +1 -0
  43. package/dist/components/ui/alert.d.cts +11 -0
  44. package/dist/components/ui/alert.d.ts +11 -0
  45. package/dist/components/ui/alert.js +57 -0
  46. package/dist/components/ui/alert.js.map +1 -0
  47. package/dist/components/ui/app-bar.cjs +67 -0
  48. package/dist/components/ui/app-bar.cjs.map +1 -0
  49. package/dist/components/ui/app-bar.d.cts +22 -0
  50. package/dist/components/ui/app-bar.d.ts +22 -0
  51. package/dist/components/ui/app-bar.js +44 -0
  52. package/dist/components/ui/app-bar.js.map +1 -0
  53. package/dist/components/ui/avatar.cjs +66 -14
  54. package/dist/components/ui/avatar.cjs.map +1 -1
  55. package/dist/components/ui/avatar.js +47 -2
  56. package/dist/components/ui/avatar.js.map +1 -1
  57. package/dist/components/ui/badge.cjs +113 -9
  58. package/dist/components/ui/badge.cjs.map +1 -1
  59. package/dist/components/ui/badge.d.cts +1 -1
  60. package/dist/components/ui/badge.d.ts +1 -1
  61. package/dist/components/ui/badge.js +96 -2
  62. package/dist/components/ui/badge.js.map +1 -1
  63. package/dist/components/ui/breadcrumb.cjs +100 -0
  64. package/dist/components/ui/breadcrumb.cjs.map +1 -0
  65. package/dist/components/ui/breadcrumb.d.cts +35 -0
  66. package/dist/components/ui/breadcrumb.d.ts +35 -0
  67. package/dist/components/ui/breadcrumb.js +92 -0
  68. package/dist/components/ui/breadcrumb.js.map +1 -0
  69. package/dist/components/ui/button.cjs +304 -11
  70. package/dist/components/ui/button.cjs.map +1 -1
  71. package/dist/components/ui/button.d.cts +3 -3
  72. package/dist/components/ui/button.d.ts +3 -3
  73. package/dist/components/ui/button.js +306 -3
  74. package/dist/components/ui/button.js.map +1 -1
  75. package/dist/components/ui/calendar.cjs +401 -8
  76. package/dist/components/ui/calendar.cjs.map +1 -1
  77. package/dist/components/ui/calendar.js +404 -4
  78. package/dist/components/ui/calendar.js.map +1 -1
  79. package/dist/components/ui/card.cjs +154 -30
  80. package/dist/components/ui/card.cjs.map +1 -1
  81. package/dist/components/ui/card.js +131 -2
  82. package/dist/components/ui/card.js.map +1 -1
  83. package/dist/{chunk-CAJKSTXX.cjs → components/ui/checkbox.cjs} +10 -5
  84. package/dist/components/ui/checkbox.cjs.map +1 -0
  85. package/dist/components/ui/checkbox.d.cts +6 -0
  86. package/dist/components/ui/checkbox.d.ts +6 -0
  87. package/dist/{chunk-5JJSRGJD.js → components/ui/checkbox.js} +9 -4
  88. package/dist/components/ui/checkbox.js.map +1 -0
  89. package/dist/components/ui/concept-card.cjs +728 -11
  90. package/dist/components/ui/concept-card.cjs.map +1 -1
  91. package/dist/components/ui/concept-card.d.cts +2 -2
  92. package/dist/components/ui/concept-card.d.ts +2 -2
  93. package/dist/components/ui/concept-card.js +710 -7
  94. package/dist/components/ui/concept-card.js.map +1 -1
  95. package/dist/components/ui/data-table.cjs +1553 -10
  96. package/dist/components/ui/data-table.cjs.map +1 -1
  97. package/dist/components/ui/data-table.js +1537 -7
  98. package/dist/components/ui/data-table.js.map +1 -1
  99. package/dist/components/ui/dialog.cjs +119 -42
  100. package/dist/components/ui/dialog.cjs.map +1 -1
  101. package/dist/components/ui/dialog.js +92 -2
  102. package/dist/components/ui/dialog.js.map +1 -1
  103. package/dist/components/ui/dropdown-menu.cjs +268 -0
  104. package/dist/components/ui/dropdown-menu.cjs.map +1 -0
  105. package/dist/components/ui/dropdown-menu.d.cts +73 -0
  106. package/dist/components/ui/dropdown-menu.d.ts +73 -0
  107. package/dist/components/ui/dropdown-menu.js +232 -0
  108. package/dist/components/ui/dropdown-menu.js.map +1 -0
  109. package/dist/components/ui/filter-provider.cjs +70 -13
  110. package/dist/components/ui/filter-provider.cjs.map +1 -1
  111. package/dist/components/ui/filter-provider.js +51 -1
  112. package/dist/components/ui/filter-provider.js.map +1 -1
  113. package/dist/components/ui/form.cjs +169 -0
  114. package/dist/components/ui/form.cjs.map +1 -0
  115. package/dist/components/ui/form.d.cts +46 -0
  116. package/dist/components/ui/form.d.ts +46 -0
  117. package/dist/components/ui/form.js +139 -0
  118. package/dist/components/ui/form.js.map +1 -0
  119. package/dist/components/ui/input.cjs +135 -15
  120. package/dist/components/ui/input.cjs.map +1 -1
  121. package/dist/components/ui/input.d.cts +15 -0
  122. package/dist/components/ui/input.d.ts +15 -0
  123. package/dist/components/ui/input.js +116 -3
  124. package/dist/components/ui/input.js.map +1 -1
  125. package/dist/components/ui/iran-province-heat.cjs +328 -5
  126. package/dist/components/ui/iran-province-heat.cjs.map +1 -1
  127. package/dist/components/ui/iran-province-heat.js +312 -2
  128. package/dist/components/ui/iran-province-heat.js.map +1 -1
  129. package/dist/components/ui/label.cjs +52 -0
  130. package/dist/components/ui/label.cjs.map +1 -0
  131. package/dist/components/ui/label.d.cts +10 -0
  132. package/dist/components/ui/label.d.ts +10 -0
  133. package/dist/components/ui/label.js +30 -0
  134. package/dist/components/ui/label.js.map +1 -0
  135. package/dist/components/ui/page-card.cjs +627 -8
  136. package/dist/components/ui/page-card.cjs.map +1 -1
  137. package/dist/components/ui/page-card.d.cts +3 -2
  138. package/dist/components/ui/page-card.d.ts +3 -2
  139. package/dist/components/ui/page-card.js +611 -5
  140. package/dist/components/ui/page-card.js.map +1 -1
  141. package/dist/components/ui/page-header.cjs +299 -0
  142. package/dist/components/ui/page-header.cjs.map +1 -0
  143. package/dist/components/ui/page-header.d.cts +21 -0
  144. package/dist/components/ui/page-header.d.ts +21 -0
  145. package/dist/components/ui/page-header.js +277 -0
  146. package/dist/components/ui/page-header.js.map +1 -0
  147. package/dist/components/ui/password-input.cjs +168 -0
  148. package/dist/components/ui/password-input.cjs.map +1 -0
  149. package/dist/components/ui/password-input.d.cts +48 -0
  150. package/dist/components/ui/password-input.d.ts +48 -0
  151. package/dist/components/ui/password-input.js +146 -0
  152. package/dist/components/ui/password-input.js.map +1 -0
  153. package/dist/components/ui/popover.cjs +51 -18
  154. package/dist/components/ui/popover.cjs.map +1 -1
  155. package/dist/components/ui/popover.js +30 -2
  156. package/dist/components/ui/popover.js.map +1 -1
  157. package/dist/components/ui/progress.cjs +95 -0
  158. package/dist/components/ui/progress.cjs.map +1 -0
  159. package/dist/components/ui/progress.d.cts +18 -0
  160. package/dist/components/ui/progress.d.ts +18 -0
  161. package/dist/components/ui/progress.js +72 -0
  162. package/dist/components/ui/progress.js.map +1 -0
  163. package/dist/components/ui/radio-card.cjs +84 -0
  164. package/dist/components/ui/radio-card.cjs.map +1 -0
  165. package/dist/components/ui/radio-card.d.cts +12 -0
  166. package/dist/components/ui/radio-card.d.ts +12 -0
  167. package/dist/components/ui/radio-card.js +58 -0
  168. package/dist/components/ui/radio-card.js.map +1 -0
  169. package/dist/components/ui/radio-group.cjs +62 -0
  170. package/dist/components/ui/radio-group.cjs.map +1 -0
  171. package/dist/components/ui/radio-group.d.cts +7 -0
  172. package/dist/components/ui/radio-group.d.ts +7 -0
  173. package/dist/components/ui/radio-group.js +38 -0
  174. package/dist/components/ui/radio-group.js.map +1 -0
  175. package/dist/components/ui/saved-query-card.cjs +409 -7
  176. package/dist/components/ui/saved-query-card.cjs.map +1 -1
  177. package/dist/components/ui/saved-query-card.js +394 -4
  178. package/dist/components/ui/saved-query-card.js.map +1 -1
  179. package/dist/components/ui/scroll-area.cjs +79 -0
  180. package/dist/components/ui/scroll-area.cjs.map +1 -0
  181. package/dist/components/ui/scroll-area.d.cts +14 -0
  182. package/dist/components/ui/scroll-area.d.ts +14 -0
  183. package/dist/components/ui/scroll-area.js +56 -0
  184. package/dist/components/ui/scroll-area.js.map +1 -0
  185. package/dist/components/ui/select.cjs +242 -0
  186. package/dist/components/ui/select.cjs.map +1 -0
  187. package/dist/components/ui/select.d.cts +29 -0
  188. package/dist/components/ui/select.d.ts +29 -0
  189. package/dist/components/ui/select.js +210 -0
  190. package/dist/components/ui/select.js.map +1 -0
  191. package/dist/components/ui/separator.cjs +105 -6
  192. package/dist/components/ui/separator.cjs.map +1 -1
  193. package/dist/components/ui/separator.js +87 -2
  194. package/dist/components/ui/separator.js.map +1 -1
  195. package/dist/components/ui/sheet.cjs +134 -38
  196. package/dist/components/ui/sheet.cjs.map +1 -1
  197. package/dist/components/ui/sheet.js +109 -2
  198. package/dist/components/ui/sheet.js.map +1 -1
  199. package/dist/{chunk-D2EBLE2B.cjs → components/ui/skeleton.cjs} +21 -16
  200. package/dist/components/ui/skeleton.cjs.map +1 -0
  201. package/dist/components/ui/skeleton.d.cts +90 -0
  202. package/dist/components/ui/skeleton.d.ts +90 -0
  203. package/dist/{chunk-SB5DSYR5.js → components/ui/skeleton.js} +8 -3
  204. package/dist/components/ui/skeleton.js.map +1 -0
  205. package/dist/components/ui/slider.cjs +129 -0
  206. package/dist/components/ui/slider.cjs.map +1 -0
  207. package/dist/components/ui/slider.d.cts +10 -0
  208. package/dist/components/ui/slider.d.ts +10 -0
  209. package/dist/components/ui/slider.js +107 -0
  210. package/dist/components/ui/slider.js.map +1 -0
  211. package/dist/components/ui/social-platform-badge.cjs +120 -0
  212. package/dist/components/ui/social-platform-badge.cjs.map +1 -0
  213. package/dist/components/ui/social-platform-badge.d.cts +21 -0
  214. package/dist/components/ui/social-platform-badge.d.ts +21 -0
  215. package/dist/components/ui/social-platform-badge.js +97 -0
  216. package/dist/components/ui/social-platform-badge.js.map +1 -0
  217. package/dist/components/ui/sonner.cjs +51 -0
  218. package/dist/components/ui/sonner.cjs.map +1 -0
  219. package/dist/components/ui/sonner.d.cts +13 -0
  220. package/dist/components/ui/sonner.d.ts +13 -0
  221. package/dist/components/ui/sonner.js +45 -0
  222. package/dist/components/ui/sonner.js.map +1 -0
  223. package/dist/components/ui/sparkline.cjs +159 -6
  224. package/dist/components/ui/sparkline.cjs.map +1 -1
  225. package/dist/components/ui/sparkline.js +142 -2
  226. package/dist/components/ui/sparkline.js.map +1 -1
  227. package/dist/components/ui/switch.cjs +96 -0
  228. package/dist/components/ui/switch.cjs.map +1 -0
  229. package/dist/components/ui/switch.d.cts +13 -0
  230. package/dist/components/ui/switch.d.ts +13 -0
  231. package/dist/components/ui/switch.js +73 -0
  232. package/dist/components/ui/switch.js.map +1 -0
  233. package/dist/components/ui/table.cjs +188 -0
  234. package/dist/components/ui/table.cjs.map +1 -0
  235. package/dist/components/ui/table.d.cts +59 -0
  236. package/dist/components/ui/table.d.ts +59 -0
  237. package/dist/components/ui/table.js +178 -0
  238. package/dist/components/ui/table.js.map +1 -0
  239. package/dist/components/ui/tabs.cjs +140 -0
  240. package/dist/components/ui/tabs.cjs.map +1 -0
  241. package/dist/components/ui/tabs.d.cts +21 -0
  242. package/dist/components/ui/tabs.d.ts +21 -0
  243. package/dist/components/ui/tabs.js +115 -0
  244. package/dist/components/ui/tabs.js.map +1 -0
  245. package/dist/components/ui/textarea.cjs +56 -0
  246. package/dist/components/ui/textarea.cjs.map +1 -0
  247. package/dist/components/ui/textarea.d.cts +5 -0
  248. package/dist/components/ui/textarea.d.ts +5 -0
  249. package/dist/components/ui/textarea.js +34 -0
  250. package/dist/components/ui/textarea.js.map +1 -0
  251. package/dist/components/ui/toggle-group.cjs +123 -0
  252. package/dist/components/ui/toggle-group.cjs.map +1 -0
  253. package/dist/components/ui/toggle-group.d.cts +7 -0
  254. package/dist/components/ui/toggle-group.d.ts +7 -0
  255. package/dist/components/ui/toggle-group.js +99 -0
  256. package/dist/components/ui/toggle-group.js.map +1 -0
  257. package/dist/components/ui/tooltip.cjs +77 -18
  258. package/dist/components/ui/tooltip.cjs.map +1 -1
  259. package/dist/components/ui/tooltip.js +56 -2
  260. package/dist/components/ui/tooltip.js.map +1 -1
  261. package/dist/{concept-card-RwPbqJ06.d.cts → concept-card-BXra9mr0.d.cts} +2 -2
  262. package/dist/{concept-card-CcOBb2Nz.d.ts → concept-card-BoJ5gIJD.d.ts} +2 -2
  263. package/dist/hooks/use-hotkey-registry.cjs +201 -14
  264. package/dist/hooks/use-hotkey-registry.cjs.map +1 -1
  265. package/dist/hooks/use-hotkey-registry.js +182 -2
  266. package/dist/hooks/use-hotkey-registry.js.map +1 -1
  267. package/dist/hooks/use-hotkeys.cjs +144 -9
  268. package/dist/hooks/use-hotkeys.cjs.map +1 -1
  269. package/dist/hooks/use-hotkeys.js +126 -1
  270. package/dist/hooks/use-hotkeys.js.map +1 -1
  271. package/dist/{i18n-CAd9wGOr.d.cts → i18n-BfRhV5aw.d.cts} +5 -3
  272. package/dist/{i18n-ArS3mqj0.d.ts → i18n-ewyqbKM-.d.ts} +5 -3
  273. package/dist/index.cjs +20906 -15706
  274. package/dist/index.cjs.map +1 -1
  275. package/dist/index.css +396 -69
  276. package/dist/index.d.cts +49 -490
  277. package/dist/index.d.ts +49 -490
  278. package/dist/index.js +7704 -2032
  279. package/dist/index.js.map +1 -1
  280. package/dist/{page-card-CmShVqG-.d.cts → page-card-C9XXXOVr.d.cts} +3 -20
  281. package/dist/{page-card-HBn-cy4J.d.ts → page-card-DAnbez_f.d.ts} +3 -20
  282. package/dist/toggle-group-B8r4LOQw.d.cts +26 -0
  283. package/dist/toggle-group-B8r4LOQw.d.ts +26 -0
  284. package/package.json +132 -2
  285. package/tailwind.config.ts +45 -0
  286. package/dist/chunk-2ACKKPWA.cjs +0 -112
  287. package/dist/chunk-2ACKKPWA.cjs.map +0 -1
  288. package/dist/chunk-2UD3LGVX.cjs +0 -316
  289. package/dist/chunk-2UD3LGVX.cjs.map +0 -1
  290. package/dist/chunk-3QYYPPFJ.js.map +0 -1
  291. package/dist/chunk-4SVQNEVH.js +0 -173
  292. package/dist/chunk-4SVQNEVH.js.map +0 -1
  293. package/dist/chunk-4WONHORR.cjs +0 -152
  294. package/dist/chunk-4WONHORR.cjs.map +0 -1
  295. package/dist/chunk-5HCXH6GS.js +0 -409
  296. package/dist/chunk-5HCXH6GS.js.map +0 -1
  297. package/dist/chunk-5JJSRGJD.js.map +0 -1
  298. package/dist/chunk-5K6E4ZSW.cjs +0 -77
  299. package/dist/chunk-5K6E4ZSW.cjs.map +0 -1
  300. package/dist/chunk-5NY26ULO.js +0 -89
  301. package/dist/chunk-5NY26ULO.js.map +0 -1
  302. package/dist/chunk-7RVPG3LE.cjs +0 -231
  303. package/dist/chunk-7RVPG3LE.cjs.map +0 -1
  304. package/dist/chunk-AYEK3WOM.js +0 -207
  305. package/dist/chunk-AYEK3WOM.js.map +0 -1
  306. package/dist/chunk-BRMBLIQG.js +0 -53
  307. package/dist/chunk-BRMBLIQG.js.map +0 -1
  308. package/dist/chunk-CAJKSTXX.cjs.map +0 -1
  309. package/dist/chunk-CKFWMHQU.js +0 -401
  310. package/dist/chunk-CKFWMHQU.js.map +0 -1
  311. package/dist/chunk-CV3N3HVK.js +0 -672
  312. package/dist/chunk-CV3N3HVK.js.map +0 -1
  313. package/dist/chunk-D2EBLE2B.cjs.map +0 -1
  314. package/dist/chunk-GCZ6YATL.js +0 -940
  315. package/dist/chunk-GCZ6YATL.js.map +0 -1
  316. package/dist/chunk-GKRAZGDI.cjs +0 -84
  317. package/dist/chunk-GKRAZGDI.cjs.map +0 -1
  318. package/dist/chunk-GPYJ66CG.js +0 -45
  319. package/dist/chunk-GPYJ66CG.js.map +0 -1
  320. package/dist/chunk-HF6XU5NI.js +0 -84
  321. package/dist/chunk-HF6XU5NI.js.map +0 -1
  322. package/dist/chunk-HJPDZOMJ.cjs +0 -87
  323. package/dist/chunk-HJPDZOMJ.cjs.map +0 -1
  324. package/dist/chunk-HS3XI3CC.cjs +0 -69
  325. package/dist/chunk-HS3XI3CC.cjs.map +0 -1
  326. package/dist/chunk-HUCC3QH5.cjs +0 -53
  327. package/dist/chunk-HUCC3QH5.cjs.map +0 -1
  328. package/dist/chunk-HYZ6BQPS.cjs +0 -425
  329. package/dist/chunk-HYZ6BQPS.cjs.map +0 -1
  330. package/dist/chunk-ISCSZMYW.cjs +0 -106
  331. package/dist/chunk-ISCSZMYW.cjs.map +0 -1
  332. package/dist/chunk-IXFEFIDO.js +0 -82
  333. package/dist/chunk-IXFEFIDO.js.map +0 -1
  334. package/dist/chunk-JCJLN437.js +0 -108
  335. package/dist/chunk-JCJLN437.js.map +0 -1
  336. package/dist/chunk-JMKNNH63.cjs +0 -982
  337. package/dist/chunk-JMKNNH63.cjs.map +0 -1
  338. package/dist/chunk-JUBHQAA2.js +0 -53
  339. package/dist/chunk-JUBHQAA2.js.map +0 -1
  340. package/dist/chunk-K6G63EED.cjs +0 -41
  341. package/dist/chunk-K6G63EED.cjs.map +0 -1
  342. package/dist/chunk-KCWRCSI7.js +0 -62
  343. package/dist/chunk-KCWRCSI7.js.map +0 -1
  344. package/dist/chunk-KYM7NIJO.cjs +0 -433
  345. package/dist/chunk-KYM7NIJO.cjs.map +0 -1
  346. package/dist/chunk-L2L5CKC2.js +0 -291
  347. package/dist/chunk-L2L5CKC2.js.map +0 -1
  348. package/dist/chunk-M5CHZ5BA.js +0 -124
  349. package/dist/chunk-M5CHZ5BA.js.map +0 -1
  350. package/dist/chunk-MEK4RSGC.js +0 -65
  351. package/dist/chunk-MEK4RSGC.js.map +0 -1
  352. package/dist/chunk-MEKWH3GS.js +0 -89
  353. package/dist/chunk-MEKWH3GS.js.map +0 -1
  354. package/dist/chunk-MFTX2DDQ.js +0 -27
  355. package/dist/chunk-MFTX2DDQ.js.map +0 -1
  356. package/dist/chunk-MMC6M35Q.cjs.map +0 -1
  357. package/dist/chunk-NMH43BDC.js +0 -130
  358. package/dist/chunk-NMH43BDC.js.map +0 -1
  359. package/dist/chunk-NORDUD2T.cjs +0 -135
  360. package/dist/chunk-NORDUD2T.cjs.map +0 -1
  361. package/dist/chunk-NV4JOKWL.cjs +0 -197
  362. package/dist/chunk-NV4JOKWL.cjs.map +0 -1
  363. package/dist/chunk-O2JG7WY5.cjs +0 -121
  364. package/dist/chunk-O2JG7WY5.cjs.map +0 -1
  365. package/dist/chunk-ONO2FTV4.cjs +0 -68
  366. package/dist/chunk-ONO2FTV4.cjs.map +0 -1
  367. package/dist/chunk-OQB6HIUL.cjs +0 -108
  368. package/dist/chunk-OQB6HIUL.cjs.map +0 -1
  369. package/dist/chunk-OS6CMYAS.cjs +0 -79
  370. package/dist/chunk-OS6CMYAS.cjs.map +0 -1
  371. package/dist/chunk-PYURPUTV.js +0 -402
  372. package/dist/chunk-PYURPUTV.js.map +0 -1
  373. package/dist/chunk-RJ3HYZ7S.js +0 -44
  374. package/dist/chunk-RJ3HYZ7S.js.map +0 -1
  375. package/dist/chunk-RZNRIOLT.js +0 -128
  376. package/dist/chunk-RZNRIOLT.js.map +0 -1
  377. package/dist/chunk-S3T2L6NA.js +0 -38
  378. package/dist/chunk-S3T2L6NA.js.map +0 -1
  379. package/dist/chunk-S5IPJQZ3.cjs +0 -161
  380. package/dist/chunk-S5IPJQZ3.cjs.map +0 -1
  381. package/dist/chunk-SB5DSYR5.js.map +0 -1
  382. package/dist/chunk-SFXV2DUH.js +0 -106
  383. package/dist/chunk-SFXV2DUH.js.map +0 -1
  384. package/dist/chunk-SXEPGD4Z.cjs +0 -152
  385. package/dist/chunk-SXEPGD4Z.cjs.map +0 -1
  386. package/dist/chunk-SXWSOU3Y.js +0 -89
  387. package/dist/chunk-SXWSOU3Y.js.map +0 -1
  388. package/dist/chunk-SZMVOHT7.cjs +0 -107
  389. package/dist/chunk-SZMVOHT7.cjs.map +0 -1
  390. package/dist/chunk-TWJXOV4C.js +0 -145
  391. package/dist/chunk-TWJXOV4C.js.map +0 -1
  392. package/dist/chunk-U3ADRIVO.cjs +0 -434
  393. package/dist/chunk-U3ADRIVO.cjs.map +0 -1
  394. package/dist/chunk-U5FLLCGC.cjs +0 -151
  395. package/dist/chunk-U5FLLCGC.cjs.map +0 -1
  396. package/dist/chunk-UOZN45G4.cjs +0 -130
  397. package/dist/chunk-UOZN45G4.cjs.map +0 -1
  398. package/dist/chunk-VHLDOG74.cjs +0 -167
  399. package/dist/chunk-VHLDOG74.cjs.map +0 -1
  400. package/dist/chunk-YC5KLN6I.js +0 -139
  401. package/dist/chunk-YC5KLN6I.js.map +0 -1
  402. package/dist/chunk-YENXXYUV.cjs +0 -111
  403. package/dist/chunk-YENXXYUV.cjs.map +0 -1
  404. package/dist/chunk-YFQWC2PW.js +0 -113
  405. package/dist/chunk-YFQWC2PW.js.map +0 -1
  406. package/dist/chunk-Z2TY4A75.cjs +0 -700
  407. package/dist/chunk-Z2TY4A75.cjs.map +0 -1
  408. package/dist/chunk-Z56O7UEU.cjs +0 -136
  409. package/dist/chunk-Z56O7UEU.cjs.map +0 -1
  410. package/dist/chunk-ZBZDR4ZC.js +0 -106
  411. package/dist/chunk-ZBZDR4ZC.js.map +0 -1
@@ -0,0 +1,130 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
27
+
28
+ // src/components/brand/parto-logo.tsx
29
+ function cn(...inputs) {
30
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
31
+ }
32
+ var IconSvg = React__namespace.forwardRef(({ size, className }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
33
+ "svg",
34
+ {
35
+ ref,
36
+ viewBox: "0 0 75 75",
37
+ width: size,
38
+ height: size,
39
+ role: "img",
40
+ "aria-label": "Parto",
41
+ "data-slot": "parto-logo-icon",
42
+ className: cn("text-brand", className),
43
+ children: /* @__PURE__ */ jsxRuntime.jsxs("g", { fill: "currentColor", children: [
44
+ /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "75 0 0 0 0 25 75 0" }),
45
+ /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "75 75 50 75 75 0 75 75" }),
46
+ /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "75 0 25 75 0 75 0 50 75 0" })
47
+ ] })
48
+ }
49
+ ));
50
+ IconSvg.displayName = "PartoLogoIcon";
51
+ var LogotypeSvg = React__namespace.forwardRef(
52
+ ({ height, className }, ref) => {
53
+ const aspectRatio = 106.03 / 48.15;
54
+ const width = Math.round(height * aspectRatio);
55
+ return /* @__PURE__ */ jsxRuntime.jsx(
56
+ "svg",
57
+ {
58
+ ref,
59
+ viewBox: "0 0 106.03 48.15",
60
+ width,
61
+ height,
62
+ role: "img",
63
+ "aria-label": "\u067E\u0631\u062A\u0648",
64
+ "data-slot": "parto-logo-logotype",
65
+ className: cn("text-foreground", className),
66
+ children: /* @__PURE__ */ jsxRuntime.jsxs("g", { fill: "currentColor", children: [
67
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M41.44,0v6.02h18.75V0h-18.75Z" }),
68
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15.22,44.28H6.43l5.1-9.36.02-.04c-4.33-.08-7.61-2.21-9.19-4.14-1.58-1.94-2.36-4.57-2.36-7.9,0-4.28,1.23-7.54,3.71-9.79,2.47-2.24,6.4-3.36,11.8-3.36h18.21v19.23s11.43,0,11.43,0c2.07,0,3.64-.52,4.7-1.53,1.06-1.01,1.59-2.45,1.59-4.27v-13.43h8.74v12.74c-.06,3.2-.66,5.7-1.86,7.51-1.18,1.81-2.87,3.07-5.08,3.8-2.21.74-5.05,1.1-8.55,1.1h-19.28V15.55s-9.29,0-9.29,0c-1.82,0-3.27.19-4.33.57s-1.86,1.04-2.38,1.99c-.52.96-.77,2.35-.77,4.18v1.56c.04,1.63.28,2.89.71,3.81.43.9,1.18,1.59,2.24,2.05s2.57.69,4.52.69h6.37l-7.3,13.88Z" }),
69
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M76.86,9.56h-8.21v20.23l-7.92,14.48h8.79l4.94-9.37v-.02h16.1c3.5,0,6.34-.36,8.55-1.1,2.21-.72,3.89-1.99,5.08-3.8.22-.33.4-.66.57-1.02.82-1.69,1.24-3.86,1.28-6.49v-12.78h-8.73v13.47c0,1.82-.53,3.26-1.59,4.27-1.06,1.01-2.63,1.53-4.7,1.53h-14.15V9.56Z" }),
70
+ /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "97.58 38.26 81.25 38.26 81.25 44.28 91.72 44.28 91.72 48.15 97.58 48.15 97.58 38.26" })
71
+ ] })
72
+ }
73
+ );
74
+ }
75
+ );
76
+ LogotypeSvg.displayName = "PartoLogoLogotype";
77
+ var PartoLogo = React__namespace.forwardRef(
78
+ ({ variant = "combined", size = 28, productName, className, ...props }, ref) => {
79
+ if (variant === "icon") {
80
+ return /* @__PURE__ */ jsxRuntime.jsx(
81
+ "span",
82
+ {
83
+ ref,
84
+ "data-slot": "parto-logo",
85
+ "data-variant": "icon",
86
+ className: cn("inline-flex items-center", className),
87
+ ...props,
88
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSvg, { size })
89
+ }
90
+ );
91
+ }
92
+ if (variant === "logotype") {
93
+ return /* @__PURE__ */ jsxRuntime.jsx(
94
+ "span",
95
+ {
96
+ ref,
97
+ "data-slot": "parto-logo",
98
+ "data-variant": "logotype",
99
+ className: cn("inline-flex items-center", className),
100
+ ...props,
101
+ children: /* @__PURE__ */ jsxRuntime.jsx(LogotypeSvg, { height: size })
102
+ }
103
+ );
104
+ }
105
+ const iconSize = Math.round(size * 1.05);
106
+ return /* @__PURE__ */ jsxRuntime.jsxs(
107
+ "span",
108
+ {
109
+ ref,
110
+ "data-slot": "parto-logo",
111
+ "data-variant": "combined",
112
+ className: cn("inline-flex items-center gap-2.5", className),
113
+ ...props,
114
+ children: [
115
+ /* @__PURE__ */ jsxRuntime.jsx(IconSvg, { size: iconSize }),
116
+ /* @__PURE__ */ jsxRuntime.jsx(LogotypeSvg, { height: size }),
117
+ productName && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
118
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", "data-slot": "parto-logo-divider", className: "h-5 w-px bg-border-stronger/60" }),
119
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "parto-logo-product-name", className: "text-foreground-light text-sm font-medium", children: productName })
120
+ ] })
121
+ ]
122
+ }
123
+ );
124
+ }
125
+ );
126
+ PartoLogo.displayName = "PartoLogo";
127
+
128
+ exports.PartoLogo = PartoLogo;
129
+ //# sourceMappingURL=parto-logo.cjs.map
130
+ //# sourceMappingURL=parto-logo.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/brand/parto-logo.tsx"],"names":["twMerge","clsx","React","jsx","jsxs","Fragment"],"mappings":"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","file":"parto-logo.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","import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\n/**\n * Parto brand logo. Every Parto product surfaces this in its header / login /\n * empty-state / about screens so the brand stays visible while individual\n * product names live alongside it.\n *\n * Variants:\n * - `icon` — the 75×75 brand mark (three triangular shapes). Uses the DS\n * brand color by default (`text-brand`) but accepts any\n * `className` overrides for one-off accents.\n * - `logotype` — the \"پرتو\" Persian wordmark. Uses `currentColor` so it\n * inherits the parent's text color (works in both light\n * and dark themes).\n * - `combined` — icon + wordmark side-by-side. The recommended default\n * for headers and login pages.\n *\n * The SVGs are inlined here (kept tiny — under 1KB each) so consumers don't\n * have to copy logo files into `public/` and the component renders as plain\n * markup with no extra network requests.\n */\n\ntype Variant = 'icon' | 'logotype' | 'combined'\n\ninterface PartoLogoProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: Variant\n /**\n * Height in pixels (icon-only) or wordmark height (logotype/combined).\n * Width auto-scales to preserve aspect ratio.\n */\n size?: number\n /**\n * Set to a Persian product name to render as `پرتو | <name>` next to the\n * logo. Skip for marketing surfaces where only the brand should appear.\n */\n productName?: string\n}\n\nconst IconSvg = React.forwardRef<SVGSVGElement, { size: number; className?: string }>(({ size, className }, ref) => (\n <svg\n ref={ref}\n viewBox=\"0 0 75 75\"\n width={size}\n height={size}\n role=\"img\"\n aria-label=\"Parto\"\n data-slot=\"parto-logo-icon\"\n className={cn('text-brand', className)}\n >\n <g fill=\"currentColor\">\n <polygon points=\"75 0 0 0 0 25 75 0\" />\n <polygon points=\"75 75 50 75 75 0 75 75\" />\n <polygon points=\"75 0 25 75 0 75 0 50 75 0\" />\n </g>\n </svg>\n))\nIconSvg.displayName = 'PartoLogoIcon'\n\nconst LogotypeSvg = React.forwardRef<SVGSVGElement, { height: number; className?: string }>(\n ({ height, className }, ref) => {\n const aspectRatio = 106.03 / 48.15\n const width = Math.round(height * aspectRatio)\n return (\n <svg\n ref={ref}\n viewBox=\"0 0 106.03 48.15\"\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"پرتو\"\n data-slot=\"parto-logo-logotype\"\n className={cn('text-foreground', className)}\n >\n <g fill=\"currentColor\">\n <path d=\"M41.44,0v6.02h18.75V0h-18.75Z\" />\n <path d=\"M15.22,44.28H6.43l5.1-9.36.02-.04c-4.33-.08-7.61-2.21-9.19-4.14-1.58-1.94-2.36-4.57-2.36-7.9,0-4.28,1.23-7.54,3.71-9.79,2.47-2.24,6.4-3.36,11.8-3.36h18.21v19.23s11.43,0,11.43,0c2.07,0,3.64-.52,4.7-1.53,1.06-1.01,1.59-2.45,1.59-4.27v-13.43h8.74v12.74c-.06,3.2-.66,5.7-1.86,7.51-1.18,1.81-2.87,3.07-5.08,3.8-2.21.74-5.05,1.1-8.55,1.1h-19.28V15.55s-9.29,0-9.29,0c-1.82,0-3.27.19-4.33.57s-1.86,1.04-2.38,1.99c-.52.96-.77,2.35-.77,4.18v1.56c.04,1.63.28,2.89.71,3.81.43.9,1.18,1.59,2.24,2.05s2.57.69,4.52.69h6.37l-7.3,13.88Z\" />\n <path d=\"M76.86,9.56h-8.21v20.23l-7.92,14.48h8.79l4.94-9.37v-.02h16.1c3.5,0,6.34-.36,8.55-1.1,2.21-.72,3.89-1.99,5.08-3.8.22-.33.4-.66.57-1.02.82-1.69,1.24-3.86,1.28-6.49v-12.78h-8.73v13.47c0,1.82-.53,3.26-1.59,4.27-1.06,1.01-2.63,1.53-4.7,1.53h-14.15V9.56Z\" />\n <polygon points=\"97.58 38.26 81.25 38.26 81.25 44.28 91.72 44.28 91.72 48.15 97.58 48.15 97.58 38.26\" />\n </g>\n </svg>\n )\n }\n)\nLogotypeSvg.displayName = 'PartoLogoLogotype'\n\nconst PartoLogo = React.forwardRef<HTMLSpanElement, PartoLogoProps>(\n ({ variant = 'combined', size = 28, productName, className, ...props }, ref) => {\n if (variant === 'icon') {\n return (\n <span\n ref={ref}\n data-slot=\"parto-logo\"\n data-variant=\"icon\"\n className={cn('inline-flex items-center', className)}\n {...props}\n >\n <IconSvg size={size} />\n </span>\n )\n }\n\n if (variant === 'logotype') {\n return (\n <span\n ref={ref}\n data-slot=\"parto-logo\"\n data-variant=\"logotype\"\n className={cn('inline-flex items-center', className)}\n {...props}\n >\n <LogotypeSvg height={size} />\n </span>\n )\n }\n\n // combined (default): icon + wordmark, optionally followed by product name\n const iconSize = Math.round(size * 1.05)\n return (\n <span\n ref={ref}\n data-slot=\"parto-logo\"\n data-variant=\"combined\"\n className={cn('inline-flex items-center gap-2.5', className)}\n {...props}\n >\n <IconSvg size={iconSize} />\n <LogotypeSvg height={size} />\n {productName && (\n <>\n <span aria-hidden=\"true\" data-slot=\"parto-logo-divider\" className=\"h-5 w-px bg-border-stronger/60\" />\n <span data-slot=\"parto-logo-product-name\" className=\"text-foreground-light text-sm font-medium\">\n {productName}\n </span>\n </>\n )}\n </span>\n )\n }\n)\nPartoLogo.displayName = 'PartoLogo'\n\nexport { PartoLogo, type PartoLogoProps }\n"]}
@@ -0,0 +1,38 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Parto brand logo. Every Parto product surfaces this in its header / login /
5
+ * empty-state / about screens so the brand stays visible while individual
6
+ * product names live alongside it.
7
+ *
8
+ * Variants:
9
+ * - `icon` — the 75×75 brand mark (three triangular shapes). Uses the DS
10
+ * brand color by default (`text-brand`) but accepts any
11
+ * `className` overrides for one-off accents.
12
+ * - `logotype` — the "پرتو" Persian wordmark. Uses `currentColor` so it
13
+ * inherits the parent's text color (works in both light
14
+ * and dark themes).
15
+ * - `combined` — icon + wordmark side-by-side. The recommended default
16
+ * for headers and login pages.
17
+ *
18
+ * The SVGs are inlined here (kept tiny — under 1KB each) so consumers don't
19
+ * have to copy logo files into `public/` and the component renders as plain
20
+ * markup with no extra network requests.
21
+ */
22
+ type Variant = 'icon' | 'logotype' | 'combined';
23
+ interface PartoLogoProps extends React.HTMLAttributes<HTMLSpanElement> {
24
+ variant?: Variant;
25
+ /**
26
+ * Height in pixels (icon-only) or wordmark height (logotype/combined).
27
+ * Width auto-scales to preserve aspect ratio.
28
+ */
29
+ size?: number;
30
+ /**
31
+ * Set to a Persian product name to render as `پرتو | <name>` next to the
32
+ * logo. Skip for marketing surfaces where only the brand should appear.
33
+ */
34
+ productName?: string;
35
+ }
36
+ declare const PartoLogo: React.ForwardRefExoticComponent<PartoLogoProps & React.RefAttributes<HTMLSpanElement>>;
37
+
38
+ export { PartoLogo, type PartoLogoProps };
@@ -0,0 +1,38 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Parto brand logo. Every Parto product surfaces this in its header / login /
5
+ * empty-state / about screens so the brand stays visible while individual
6
+ * product names live alongside it.
7
+ *
8
+ * Variants:
9
+ * - `icon` — the 75×75 brand mark (three triangular shapes). Uses the DS
10
+ * brand color by default (`text-brand`) but accepts any
11
+ * `className` overrides for one-off accents.
12
+ * - `logotype` — the "پرتو" Persian wordmark. Uses `currentColor` so it
13
+ * inherits the parent's text color (works in both light
14
+ * and dark themes).
15
+ * - `combined` — icon + wordmark side-by-side. The recommended default
16
+ * for headers and login pages.
17
+ *
18
+ * The SVGs are inlined here (kept tiny — under 1KB each) so consumers don't
19
+ * have to copy logo files into `public/` and the component renders as plain
20
+ * markup with no extra network requests.
21
+ */
22
+ type Variant = 'icon' | 'logotype' | 'combined';
23
+ interface PartoLogoProps extends React.HTMLAttributes<HTMLSpanElement> {
24
+ variant?: Variant;
25
+ /**
26
+ * Height in pixels (icon-only) or wordmark height (logotype/combined).
27
+ * Width auto-scales to preserve aspect ratio.
28
+ */
29
+ size?: number;
30
+ /**
31
+ * Set to a Persian product name to render as `پرتو | <name>` next to the
32
+ * logo. Skip for marketing surfaces where only the brand should appear.
33
+ */
34
+ productName?: string;
35
+ }
36
+ declare const PartoLogo: React.ForwardRefExoticComponent<PartoLogoProps & React.RefAttributes<HTMLSpanElement>>;
37
+
38
+ export { PartoLogo, type PartoLogoProps };
@@ -0,0 +1,108 @@
1
+ import * as React from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+
6
+ // src/components/brand/parto-logo.tsx
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ var IconSvg = React.forwardRef(({ size, className }, ref) => /* @__PURE__ */ jsx(
11
+ "svg",
12
+ {
13
+ ref,
14
+ viewBox: "0 0 75 75",
15
+ width: size,
16
+ height: size,
17
+ role: "img",
18
+ "aria-label": "Parto",
19
+ "data-slot": "parto-logo-icon",
20
+ className: cn("text-brand", className),
21
+ children: /* @__PURE__ */ jsxs("g", { fill: "currentColor", children: [
22
+ /* @__PURE__ */ jsx("polygon", { points: "75 0 0 0 0 25 75 0" }),
23
+ /* @__PURE__ */ jsx("polygon", { points: "75 75 50 75 75 0 75 75" }),
24
+ /* @__PURE__ */ jsx("polygon", { points: "75 0 25 75 0 75 0 50 75 0" })
25
+ ] })
26
+ }
27
+ ));
28
+ IconSvg.displayName = "PartoLogoIcon";
29
+ var LogotypeSvg = React.forwardRef(
30
+ ({ height, className }, ref) => {
31
+ const aspectRatio = 106.03 / 48.15;
32
+ const width = Math.round(height * aspectRatio);
33
+ return /* @__PURE__ */ jsx(
34
+ "svg",
35
+ {
36
+ ref,
37
+ viewBox: "0 0 106.03 48.15",
38
+ width,
39
+ height,
40
+ role: "img",
41
+ "aria-label": "\u067E\u0631\u062A\u0648",
42
+ "data-slot": "parto-logo-logotype",
43
+ className: cn("text-foreground", className),
44
+ children: /* @__PURE__ */ jsxs("g", { fill: "currentColor", children: [
45
+ /* @__PURE__ */ jsx("path", { d: "M41.44,0v6.02h18.75V0h-18.75Z" }),
46
+ /* @__PURE__ */ jsx("path", { d: "M15.22,44.28H6.43l5.1-9.36.02-.04c-4.33-.08-7.61-2.21-9.19-4.14-1.58-1.94-2.36-4.57-2.36-7.9,0-4.28,1.23-7.54,3.71-9.79,2.47-2.24,6.4-3.36,11.8-3.36h18.21v19.23s11.43,0,11.43,0c2.07,0,3.64-.52,4.7-1.53,1.06-1.01,1.59-2.45,1.59-4.27v-13.43h8.74v12.74c-.06,3.2-.66,5.7-1.86,7.51-1.18,1.81-2.87,3.07-5.08,3.8-2.21.74-5.05,1.1-8.55,1.1h-19.28V15.55s-9.29,0-9.29,0c-1.82,0-3.27.19-4.33.57s-1.86,1.04-2.38,1.99c-.52.96-.77,2.35-.77,4.18v1.56c.04,1.63.28,2.89.71,3.81.43.9,1.18,1.59,2.24,2.05s2.57.69,4.52.69h6.37l-7.3,13.88Z" }),
47
+ /* @__PURE__ */ jsx("path", { d: "M76.86,9.56h-8.21v20.23l-7.92,14.48h8.79l4.94-9.37v-.02h16.1c3.5,0,6.34-.36,8.55-1.1,2.21-.72,3.89-1.99,5.08-3.8.22-.33.4-.66.57-1.02.82-1.69,1.24-3.86,1.28-6.49v-12.78h-8.73v13.47c0,1.82-.53,3.26-1.59,4.27-1.06,1.01-2.63,1.53-4.7,1.53h-14.15V9.56Z" }),
48
+ /* @__PURE__ */ jsx("polygon", { points: "97.58 38.26 81.25 38.26 81.25 44.28 91.72 44.28 91.72 48.15 97.58 48.15 97.58 38.26" })
49
+ ] })
50
+ }
51
+ );
52
+ }
53
+ );
54
+ LogotypeSvg.displayName = "PartoLogoLogotype";
55
+ var PartoLogo = React.forwardRef(
56
+ ({ variant = "combined", size = 28, productName, className, ...props }, ref) => {
57
+ if (variant === "icon") {
58
+ return /* @__PURE__ */ jsx(
59
+ "span",
60
+ {
61
+ ref,
62
+ "data-slot": "parto-logo",
63
+ "data-variant": "icon",
64
+ className: cn("inline-flex items-center", className),
65
+ ...props,
66
+ children: /* @__PURE__ */ jsx(IconSvg, { size })
67
+ }
68
+ );
69
+ }
70
+ if (variant === "logotype") {
71
+ return /* @__PURE__ */ jsx(
72
+ "span",
73
+ {
74
+ ref,
75
+ "data-slot": "parto-logo",
76
+ "data-variant": "logotype",
77
+ className: cn("inline-flex items-center", className),
78
+ ...props,
79
+ children: /* @__PURE__ */ jsx(LogotypeSvg, { height: size })
80
+ }
81
+ );
82
+ }
83
+ const iconSize = Math.round(size * 1.05);
84
+ return /* @__PURE__ */ jsxs(
85
+ "span",
86
+ {
87
+ ref,
88
+ "data-slot": "parto-logo",
89
+ "data-variant": "combined",
90
+ className: cn("inline-flex items-center gap-2.5", className),
91
+ ...props,
92
+ children: [
93
+ /* @__PURE__ */ jsx(IconSvg, { size: iconSize }),
94
+ /* @__PURE__ */ jsx(LogotypeSvg, { height: size }),
95
+ productName && /* @__PURE__ */ jsxs(Fragment, { children: [
96
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-slot": "parto-logo-divider", className: "h-5 w-px bg-border-stronger/60" }),
97
+ /* @__PURE__ */ jsx("span", { "data-slot": "parto-logo-product-name", className: "text-foreground-light text-sm font-medium", children: productName })
98
+ ] })
99
+ ]
100
+ }
101
+ );
102
+ }
103
+ );
104
+ PartoLogo.displayName = "PartoLogo";
105
+
106
+ export { PartoLogo };
107
+ //# sourceMappingURL=parto-logo.js.map
108
+ //# sourceMappingURL=parto-logo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/brand/parto-logo.tsx"],"names":[],"mappings":"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","file":"parto-logo.js","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","import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\n/**\n * Parto brand logo. Every Parto product surfaces this in its header / login /\n * empty-state / about screens so the brand stays visible while individual\n * product names live alongside it.\n *\n * Variants:\n * - `icon` — the 75×75 brand mark (three triangular shapes). Uses the DS\n * brand color by default (`text-brand`) but accepts any\n * `className` overrides for one-off accents.\n * - `logotype` — the \"پرتو\" Persian wordmark. Uses `currentColor` so it\n * inherits the parent's text color (works in both light\n * and dark themes).\n * - `combined` — icon + wordmark side-by-side. The recommended default\n * for headers and login pages.\n *\n * The SVGs are inlined here (kept tiny — under 1KB each) so consumers don't\n * have to copy logo files into `public/` and the component renders as plain\n * markup with no extra network requests.\n */\n\ntype Variant = 'icon' | 'logotype' | 'combined'\n\ninterface PartoLogoProps extends React.HTMLAttributes<HTMLSpanElement> {\n variant?: Variant\n /**\n * Height in pixels (icon-only) or wordmark height (logotype/combined).\n * Width auto-scales to preserve aspect ratio.\n */\n size?: number\n /**\n * Set to a Persian product name to render as `پرتو | <name>` next to the\n * logo. Skip for marketing surfaces where only the brand should appear.\n */\n productName?: string\n}\n\nconst IconSvg = React.forwardRef<SVGSVGElement, { size: number; className?: string }>(({ size, className }, ref) => (\n <svg\n ref={ref}\n viewBox=\"0 0 75 75\"\n width={size}\n height={size}\n role=\"img\"\n aria-label=\"Parto\"\n data-slot=\"parto-logo-icon\"\n className={cn('text-brand', className)}\n >\n <g fill=\"currentColor\">\n <polygon points=\"75 0 0 0 0 25 75 0\" />\n <polygon points=\"75 75 50 75 75 0 75 75\" />\n <polygon points=\"75 0 25 75 0 75 0 50 75 0\" />\n </g>\n </svg>\n))\nIconSvg.displayName = 'PartoLogoIcon'\n\nconst LogotypeSvg = React.forwardRef<SVGSVGElement, { height: number; className?: string }>(\n ({ height, className }, ref) => {\n const aspectRatio = 106.03 / 48.15\n const width = Math.round(height * aspectRatio)\n return (\n <svg\n ref={ref}\n viewBox=\"0 0 106.03 48.15\"\n width={width}\n height={height}\n role=\"img\"\n aria-label=\"پرتو\"\n data-slot=\"parto-logo-logotype\"\n className={cn('text-foreground', className)}\n >\n <g fill=\"currentColor\">\n <path d=\"M41.44,0v6.02h18.75V0h-18.75Z\" />\n <path d=\"M15.22,44.28H6.43l5.1-9.36.02-.04c-4.33-.08-7.61-2.21-9.19-4.14-1.58-1.94-2.36-4.57-2.36-7.9,0-4.28,1.23-7.54,3.71-9.79,2.47-2.24,6.4-3.36,11.8-3.36h18.21v19.23s11.43,0,11.43,0c2.07,0,3.64-.52,4.7-1.53,1.06-1.01,1.59-2.45,1.59-4.27v-13.43h8.74v12.74c-.06,3.2-.66,5.7-1.86,7.51-1.18,1.81-2.87,3.07-5.08,3.8-2.21.74-5.05,1.1-8.55,1.1h-19.28V15.55s-9.29,0-9.29,0c-1.82,0-3.27.19-4.33.57s-1.86,1.04-2.38,1.99c-.52.96-.77,2.35-.77,4.18v1.56c.04,1.63.28,2.89.71,3.81.43.9,1.18,1.59,2.24,2.05s2.57.69,4.52.69h6.37l-7.3,13.88Z\" />\n <path d=\"M76.86,9.56h-8.21v20.23l-7.92,14.48h8.79l4.94-9.37v-.02h16.1c3.5,0,6.34-.36,8.55-1.1,2.21-.72,3.89-1.99,5.08-3.8.22-.33.4-.66.57-1.02.82-1.69,1.24-3.86,1.28-6.49v-12.78h-8.73v13.47c0,1.82-.53,3.26-1.59,4.27-1.06,1.01-2.63,1.53-4.7,1.53h-14.15V9.56Z\" />\n <polygon points=\"97.58 38.26 81.25 38.26 81.25 44.28 91.72 44.28 91.72 48.15 97.58 48.15 97.58 38.26\" />\n </g>\n </svg>\n )\n }\n)\nLogotypeSvg.displayName = 'PartoLogoLogotype'\n\nconst PartoLogo = React.forwardRef<HTMLSpanElement, PartoLogoProps>(\n ({ variant = 'combined', size = 28, productName, className, ...props }, ref) => {\n if (variant === 'icon') {\n return (\n <span\n ref={ref}\n data-slot=\"parto-logo\"\n data-variant=\"icon\"\n className={cn('inline-flex items-center', className)}\n {...props}\n >\n <IconSvg size={size} />\n </span>\n )\n }\n\n if (variant === 'logotype') {\n return (\n <span\n ref={ref}\n data-slot=\"parto-logo\"\n data-variant=\"logotype\"\n className={cn('inline-flex items-center', className)}\n {...props}\n >\n <LogotypeSvg height={size} />\n </span>\n )\n }\n\n // combined (default): icon + wordmark, optionally followed by product name\n const iconSize = Math.round(size * 1.05)\n return (\n <span\n ref={ref}\n data-slot=\"parto-logo\"\n data-variant=\"combined\"\n className={cn('inline-flex items-center gap-2.5', className)}\n {...props}\n >\n <IconSvg size={iconSize} />\n <LogotypeSvg height={size} />\n {productName && (\n <>\n <span aria-hidden=\"true\" data-slot=\"parto-logo-divider\" className=\"h-5 w-px bg-border-stronger/60\" />\n <span data-slot=\"parto-logo-product-name\" className=\"text-foreground-light text-sm font-medium\">\n {productName}\n </span>\n </>\n )}\n </span>\n )\n }\n)\nPartoLogo.displayName = 'PartoLogo'\n\nexport { PartoLogo, type PartoLogoProps }\n"]}