@parto-system-design/ui 1.1.5 → 1.1.7

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 (301) hide show
  1. package/AGENTS.md +233 -0
  2. package/LICENSE +21 -0
  3. package/README.md +96 -43
  4. package/dist/chunk-2UD3LGVX.cjs +316 -0
  5. package/dist/chunk-2UD3LGVX.cjs.map +1 -0
  6. package/dist/chunk-34JUCX2G.cjs +43 -0
  7. package/dist/chunk-34JUCX2G.cjs.map +1 -0
  8. package/dist/chunk-3AIJKXBV.cjs +242 -0
  9. package/dist/chunk-3AIJKXBV.cjs.map +1 -0
  10. package/dist/chunk-4SVQNEVH.js +173 -0
  11. package/dist/chunk-4SVQNEVH.js.map +1 -0
  12. package/dist/chunk-53QY4PD3.js +908 -0
  13. package/dist/chunk-53QY4PD3.js.map +1 -0
  14. package/dist/chunk-5JJSRGJD.js +31 -0
  15. package/dist/chunk-5JJSRGJD.js.map +1 -0
  16. package/dist/chunk-5K6E4ZSW.cjs +77 -0
  17. package/dist/chunk-5K6E4ZSW.cjs.map +1 -0
  18. package/dist/chunk-5NY26ULO.js +89 -0
  19. package/dist/chunk-5NY26ULO.js.map +1 -0
  20. package/dist/chunk-7RVPG3LE.cjs +231 -0
  21. package/dist/chunk-7RVPG3LE.cjs.map +1 -0
  22. package/dist/chunk-7Y4V3R3Y.cjs +120 -0
  23. package/dist/chunk-7Y4V3R3Y.cjs.map +1 -0
  24. package/dist/chunk-AXAY64KL.js +39 -0
  25. package/dist/chunk-AXAY64KL.js.map +1 -0
  26. package/dist/chunk-AYEK3WOM.js +207 -0
  27. package/dist/chunk-AYEK3WOM.js.map +1 -0
  28. package/dist/chunk-BRMBLIQG.js +53 -0
  29. package/dist/chunk-BRMBLIQG.js.map +1 -0
  30. package/dist/chunk-CAJKSTXX.cjs +54 -0
  31. package/dist/chunk-CAJKSTXX.cjs.map +1 -0
  32. package/dist/chunk-CKFWMHQU.js +401 -0
  33. package/dist/chunk-CKFWMHQU.js.map +1 -0
  34. package/dist/chunk-CV3N3HVK.js +672 -0
  35. package/dist/chunk-CV3N3HVK.js.map +1 -0
  36. package/dist/chunk-D2EBLE2B.cjs +220 -0
  37. package/dist/chunk-D2EBLE2B.cjs.map +1 -0
  38. package/dist/chunk-D5XCQDFS.js +92 -0
  39. package/dist/chunk-D5XCQDFS.js.map +1 -0
  40. package/dist/chunk-GDHRYKVM.js +45 -0
  41. package/dist/chunk-GDHRYKVM.js.map +1 -0
  42. package/dist/chunk-GKRAZGDI.cjs +84 -0
  43. package/dist/chunk-GKRAZGDI.cjs.map +1 -0
  44. package/dist/chunk-HEYMLQOV.cjs +94 -0
  45. package/dist/chunk-HEYMLQOV.cjs.map +1 -0
  46. package/dist/chunk-HF6XU5NI.js +84 -0
  47. package/dist/chunk-HF6XU5NI.js.map +1 -0
  48. package/dist/chunk-HJPDZOMJ.cjs +87 -0
  49. package/dist/chunk-HJPDZOMJ.cjs.map +1 -0
  50. package/dist/chunk-HUCC3QH5.cjs +53 -0
  51. package/dist/chunk-HUCC3QH5.cjs.map +1 -0
  52. package/dist/chunk-HYZ6BQPS.cjs +425 -0
  53. package/dist/chunk-HYZ6BQPS.cjs.map +1 -0
  54. package/dist/chunk-IQHKJ4SS.js +213 -0
  55. package/dist/chunk-IQHKJ4SS.js.map +1 -0
  56. package/dist/chunk-ISCSZMYW.cjs +106 -0
  57. package/dist/chunk-ISCSZMYW.cjs.map +1 -0
  58. package/dist/chunk-IXFEFIDO.js +82 -0
  59. package/dist/chunk-IXFEFIDO.js.map +1 -0
  60. package/dist/chunk-JUBHQAA2.js +53 -0
  61. package/dist/chunk-JUBHQAA2.js.map +1 -0
  62. package/dist/chunk-KCWRCSI7.js +62 -0
  63. package/dist/chunk-KCWRCSI7.js.map +1 -0
  64. package/dist/chunk-L2L5CKC2.js +291 -0
  65. package/dist/chunk-L2L5CKC2.js.map +1 -0
  66. package/dist/chunk-LLJR7FV3.js +135 -0
  67. package/dist/chunk-LLJR7FV3.js.map +1 -0
  68. package/dist/chunk-LZMCMZZF.js +118 -0
  69. package/dist/chunk-LZMCMZZF.js.map +1 -0
  70. package/dist/chunk-M5CHZ5BA.js +124 -0
  71. package/dist/chunk-M5CHZ5BA.js.map +1 -0
  72. package/dist/chunk-MBCTRNTG.js +89 -0
  73. package/dist/chunk-MBCTRNTG.js.map +1 -0
  74. package/dist/chunk-MEK4RSGC.js +65 -0
  75. package/dist/chunk-MEK4RSGC.js.map +1 -0
  76. package/dist/chunk-MFTX2DDQ.js +27 -0
  77. package/dist/chunk-MFTX2DDQ.js.map +1 -0
  78. package/dist/chunk-MKYVQQBV.cjs +114 -0
  79. package/dist/chunk-MKYVQQBV.cjs.map +1 -0
  80. package/dist/chunk-MQGQVI3W.cjs +950 -0
  81. package/dist/chunk-MQGQVI3W.cjs.map +1 -0
  82. package/dist/chunk-NEFZJHE4.cjs +157 -0
  83. package/dist/chunk-NEFZJHE4.cjs.map +1 -0
  84. package/dist/chunk-NEML6RCV.js +405 -0
  85. package/dist/chunk-NEML6RCV.js.map +1 -0
  86. package/dist/chunk-NV4JOKWL.cjs +197 -0
  87. package/dist/chunk-NV4JOKWL.cjs.map +1 -0
  88. package/dist/chunk-O2JG7WY5.cjs +121 -0
  89. package/dist/chunk-O2JG7WY5.cjs.map +1 -0
  90. package/dist/chunk-OEVMKFFL.cjs +140 -0
  91. package/dist/chunk-OEVMKFFL.cjs.map +1 -0
  92. package/dist/chunk-ONO2FTV4.cjs +68 -0
  93. package/dist/chunk-ONO2FTV4.cjs.map +1 -0
  94. package/dist/chunk-OS6CMYAS.cjs +79 -0
  95. package/dist/chunk-OS6CMYAS.cjs.map +1 -0
  96. package/dist/chunk-P5XHPNJG.cjs +430 -0
  97. package/dist/chunk-P5XHPNJG.cjs.map +1 -0
  98. package/dist/chunk-QJ7UB2ZQ.js +98 -0
  99. package/dist/chunk-QJ7UB2ZQ.js.map +1 -0
  100. package/dist/chunk-RA5KZNG5.js +269 -0
  101. package/dist/chunk-RA5KZNG5.js.map +1 -0
  102. package/dist/chunk-RJ3HYZ7S.js +44 -0
  103. package/dist/chunk-RJ3HYZ7S.js.map +1 -0
  104. package/dist/chunk-RZNRIOLT.js +128 -0
  105. package/dist/chunk-RZNRIOLT.js.map +1 -0
  106. package/dist/chunk-S5IPJQZ3.cjs +161 -0
  107. package/dist/chunk-S5IPJQZ3.cjs.map +1 -0
  108. package/dist/chunk-SB5DSYR5.js +211 -0
  109. package/dist/chunk-SB5DSYR5.js.map +1 -0
  110. package/dist/chunk-SCGW2BH4.cjs +69 -0
  111. package/dist/chunk-SCGW2BH4.cjs.map +1 -0
  112. package/dist/chunk-SCX6AR53.cjs +108 -0
  113. package/dist/chunk-SCX6AR53.cjs.map +1 -0
  114. package/dist/chunk-SFXV2DUH.js +106 -0
  115. package/dist/chunk-SFXV2DUH.js.map +1 -0
  116. package/dist/chunk-SXEPGD4Z.cjs +152 -0
  117. package/dist/chunk-SXEPGD4Z.cjs.map +1 -0
  118. package/dist/chunk-SZMVOHT7.cjs +107 -0
  119. package/dist/chunk-SZMVOHT7.cjs.map +1 -0
  120. package/dist/chunk-U5FLLCGC.cjs +151 -0
  121. package/dist/chunk-U5FLLCGC.cjs.map +1 -0
  122. package/dist/chunk-VO3B75F6.cjs +111 -0
  123. package/dist/chunk-VO3B75F6.cjs.map +1 -0
  124. package/dist/chunk-YAJWTNOX.js +106 -0
  125. package/dist/chunk-YAJWTNOX.js.map +1 -0
  126. package/dist/chunk-YC5KLN6I.js +139 -0
  127. package/dist/chunk-YC5KLN6I.js.map +1 -0
  128. package/dist/chunk-YE477L2H.cjs +272 -0
  129. package/dist/chunk-YE477L2H.cjs.map +1 -0
  130. package/dist/chunk-Z2TY4A75.cjs +700 -0
  131. package/dist/chunk-Z2TY4A75.cjs.map +1 -0
  132. package/dist/chunk-Z56O7UEU.cjs +136 -0
  133. package/dist/chunk-Z56O7UEU.cjs.map +1 -0
  134. package/dist/chunk-ZZFNJR2E.js +71 -0
  135. package/dist/chunk-ZZFNJR2E.js.map +1 -0
  136. package/dist/components/charts/PartoAreaChart.cjs +15 -0
  137. package/dist/components/charts/PartoAreaChart.cjs.map +1 -0
  138. package/dist/components/charts/PartoAreaChart.d.cts +51 -0
  139. package/dist/components/charts/PartoAreaChart.d.ts +51 -0
  140. package/dist/components/charts/PartoAreaChart.js +6 -0
  141. package/dist/components/charts/PartoAreaChart.js.map +1 -0
  142. package/dist/components/charts/PartoBarChart.cjs +15 -0
  143. package/dist/components/charts/PartoBarChart.cjs.map +1 -0
  144. package/dist/components/charts/PartoBarChart.d.cts +55 -0
  145. package/dist/components/charts/PartoBarChart.d.ts +55 -0
  146. package/dist/components/charts/PartoBarChart.js +6 -0
  147. package/dist/components/charts/PartoBarChart.js.map +1 -0
  148. package/dist/components/charts/PartoLineChart.cjs +15 -0
  149. package/dist/components/charts/PartoLineChart.cjs.map +1 -0
  150. package/dist/components/charts/PartoLineChart.d.cts +49 -0
  151. package/dist/components/charts/PartoLineChart.d.ts +49 -0
  152. package/dist/components/charts/PartoLineChart.js +6 -0
  153. package/dist/components/charts/PartoLineChart.js.map +1 -0
  154. package/dist/components/charts/PartoPieChart.cjs +15 -0
  155. package/dist/components/charts/PartoPieChart.cjs.map +1 -0
  156. package/dist/components/charts/PartoPieChart.d.cts +44 -0
  157. package/dist/components/charts/PartoPieChart.d.ts +44 -0
  158. package/dist/components/charts/PartoPieChart.js +6 -0
  159. package/dist/components/charts/PartoPieChart.js.map +1 -0
  160. package/dist/components/ui/alert-rule-card.cjs +15 -0
  161. package/dist/components/ui/alert-rule-card.cjs.map +1 -0
  162. package/dist/components/ui/alert-rule-card.d.cts +38 -0
  163. package/dist/components/ui/alert-rule-card.d.ts +38 -0
  164. package/dist/components/ui/alert-rule-card.js +6 -0
  165. package/dist/components/ui/alert-rule-card.js.map +1 -0
  166. package/dist/components/ui/avatar.cjs +21 -0
  167. package/dist/components/ui/avatar.cjs.map +1 -0
  168. package/dist/components/ui/avatar.d.cts +18 -0
  169. package/dist/components/ui/avatar.d.ts +18 -0
  170. package/dist/components/ui/avatar.js +4 -0
  171. package/dist/components/ui/avatar.js.map +1 -0
  172. package/dist/components/ui/badge.cjs +17 -0
  173. package/dist/components/ui/badge.cjs.map +1 -0
  174. package/dist/components/ui/badge.d.cts +16 -0
  175. package/dist/components/ui/badge.d.ts +16 -0
  176. package/dist/components/ui/badge.js +4 -0
  177. package/dist/components/ui/badge.js.map +1 -0
  178. package/dist/components/ui/button.cjs +18 -0
  179. package/dist/components/ui/button.cjs.map +1 -0
  180. package/dist/components/ui/button.d.cts +37 -0
  181. package/dist/components/ui/button.d.ts +37 -0
  182. package/dist/components/ui/button.js +5 -0
  183. package/dist/components/ui/button.js.map +1 -0
  184. package/dist/components/ui/calendar.cjs +15 -0
  185. package/dist/components/ui/calendar.cjs.map +1 -0
  186. package/dist/components/ui/calendar.d.cts +17 -0
  187. package/dist/components/ui/calendar.d.ts +17 -0
  188. package/dist/components/ui/calendar.js +6 -0
  189. package/dist/components/ui/calendar.js.map +1 -0
  190. package/dist/components/ui/card.cjs +37 -0
  191. package/dist/components/ui/card.cjs.map +1 -0
  192. package/dist/components/ui/card.d.cts +18 -0
  193. package/dist/components/ui/card.d.ts +18 -0
  194. package/dist/components/ui/card.js +4 -0
  195. package/dist/components/ui/card.js.map +1 -0
  196. package/dist/components/ui/concept-card.cjs +18 -0
  197. package/dist/components/ui/concept-card.cjs.map +1 -0
  198. package/dist/components/ui/concept-card.d.cts +5 -0
  199. package/dist/components/ui/concept-card.d.ts +5 -0
  200. package/dist/components/ui/concept-card.js +9 -0
  201. package/dist/components/ui/concept-card.js.map +1 -0
  202. package/dist/components/ui/data-table.cjs +18 -0
  203. package/dist/components/ui/data-table.cjs.map +1 -0
  204. package/dist/components/ui/data-table.d.cts +181 -0
  205. package/dist/components/ui/data-table.d.ts +181 -0
  206. package/dist/components/ui/data-table.js +9 -0
  207. package/dist/components/ui/data-table.js.map +1 -0
  208. package/dist/components/ui/dialog.cjs +49 -0
  209. package/dist/components/ui/dialog.cjs.map +1 -0
  210. package/dist/components/ui/dialog.d.cts +22 -0
  211. package/dist/components/ui/dialog.d.ts +22 -0
  212. package/dist/components/ui/dialog.js +4 -0
  213. package/dist/components/ui/dialog.js.map +1 -0
  214. package/dist/components/ui/filter-provider.cjs +20 -0
  215. package/dist/components/ui/filter-provider.cjs.map +1 -0
  216. package/dist/components/ui/filter-provider.d.cts +49 -0
  217. package/dist/components/ui/filter-provider.d.ts +49 -0
  218. package/dist/components/ui/filter-provider.js +3 -0
  219. package/dist/components/ui/filter-provider.js.map +1 -0
  220. package/dist/components/ui/input.cjs +22 -0
  221. package/dist/components/ui/input.cjs.map +1 -0
  222. package/dist/components/ui/input.d.cts +16 -0
  223. package/dist/components/ui/input.d.ts +16 -0
  224. package/dist/components/ui/input.js +5 -0
  225. package/dist/components/ui/input.js.map +1 -0
  226. package/dist/components/ui/iran-province-heat.cjs +13 -0
  227. package/dist/components/ui/iran-province-heat.cjs.map +1 -0
  228. package/dist/components/ui/iran-province-heat.d.cts +64 -0
  229. package/dist/components/ui/iran-province-heat.d.ts +64 -0
  230. package/dist/components/ui/iran-province-heat.js +4 -0
  231. package/dist/components/ui/iran-province-heat.js.map +1 -0
  232. package/dist/components/ui/page-card.cjs +16 -0
  233. package/dist/components/ui/page-card.cjs.map +1 -0
  234. package/dist/components/ui/page-card.d.cts +6 -0
  235. package/dist/components/ui/page-card.d.ts +6 -0
  236. package/dist/components/ui/page-card.js +7 -0
  237. package/dist/components/ui/page-card.js.map +1 -0
  238. package/dist/components/ui/popover.cjs +25 -0
  239. package/dist/components/ui/popover.cjs.map +1 -0
  240. package/dist/components/ui/popover.d.cts +9 -0
  241. package/dist/components/ui/popover.d.ts +9 -0
  242. package/dist/components/ui/popover.js +4 -0
  243. package/dist/components/ui/popover.js.map +1 -0
  244. package/dist/components/ui/saved-query-card.cjs +15 -0
  245. package/dist/components/ui/saved-query-card.cjs.map +1 -0
  246. package/dist/components/ui/saved-query-card.d.cts +41 -0
  247. package/dist/components/ui/saved-query-card.d.ts +41 -0
  248. package/dist/components/ui/saved-query-card.js +6 -0
  249. package/dist/components/ui/saved-query-card.js.map +1 -0
  250. package/dist/components/ui/separator.cjs +13 -0
  251. package/dist/components/ui/separator.cjs.map +1 -0
  252. package/dist/components/ui/separator.d.cts +9 -0
  253. package/dist/components/ui/separator.d.ts +9 -0
  254. package/dist/components/ui/separator.js +4 -0
  255. package/dist/components/ui/separator.js.map +1 -0
  256. package/dist/components/ui/sheet.cjs +45 -0
  257. package/dist/components/ui/sheet.cjs.map +1 -0
  258. package/dist/components/ui/sheet.d.cts +44 -0
  259. package/dist/components/ui/sheet.d.ts +44 -0
  260. package/dist/components/ui/sheet.js +4 -0
  261. package/dist/components/ui/sheet.js.map +1 -0
  262. package/dist/components/ui/sparkline.cjs +13 -0
  263. package/dist/components/ui/sparkline.cjs.map +1 -0
  264. package/dist/components/ui/sparkline.d.cts +36 -0
  265. package/dist/components/ui/sparkline.d.ts +36 -0
  266. package/dist/components/ui/sparkline.js +4 -0
  267. package/dist/components/ui/sparkline.js.map +1 -0
  268. package/dist/components/ui/tooltip.cjs +25 -0
  269. package/dist/components/ui/tooltip.cjs.map +1 -0
  270. package/dist/components/ui/tooltip.d.cts +17 -0
  271. package/dist/components/ui/tooltip.d.ts +17 -0
  272. package/dist/components/ui/tooltip.js +4 -0
  273. package/dist/components/ui/tooltip.js.map +1 -0
  274. package/dist/concept-card-CcOBb2Nz.d.ts +83 -0
  275. package/dist/concept-card-RwPbqJ06.d.cts +83 -0
  276. package/dist/hooks/use-hotkey-registry.cjs +21 -0
  277. package/dist/hooks/use-hotkey-registry.cjs.map +1 -0
  278. package/dist/hooks/use-hotkey-registry.d.cts +65 -0
  279. package/dist/hooks/use-hotkey-registry.d.ts +65 -0
  280. package/dist/hooks/use-hotkey-registry.js +4 -0
  281. package/dist/hooks/use-hotkey-registry.js.map +1 -0
  282. package/dist/hooks/use-hotkeys.cjs +16 -0
  283. package/dist/hooks/use-hotkeys.cjs.map +1 -0
  284. package/dist/hooks/use-hotkeys.d.cts +66 -0
  285. package/dist/hooks/use-hotkeys.d.ts +66 -0
  286. package/dist/hooks/use-hotkeys.js +3 -0
  287. package/dist/hooks/use-hotkeys.js.map +1 -0
  288. package/dist/i18n-ArS3mqj0.d.ts +344 -0
  289. package/dist/i18n-CAd9wGOr.d.cts +344 -0
  290. package/dist/index.cjs +7383 -10955
  291. package/dist/index.cjs.map +1 -1
  292. package/dist/index.css +157 -0
  293. package/dist/index.d.cts +726 -1144
  294. package/dist/index.d.ts +726 -1144
  295. package/dist/index.js +6735 -10912
  296. package/dist/index.js.map +1 -1
  297. package/dist/page-card-CO92oXkc.d.ts +100 -0
  298. package/dist/page-card-DOl50DqJ.d.cts +100 -0
  299. package/dist/utils-DlXWmDZ-.d.cts +35 -0
  300. package/dist/utils-DlXWmDZ-.d.ts +35 -0
  301. package/package.json +160 -4
@@ -0,0 +1,213 @@
1
+ import { Skeleton } from './chunk-SB5DSYR5.js';
2
+ import { formatLargeNumber, convertToLocalNumbers } from './chunk-4SVQNEVH.js';
3
+ import * as React from 'react';
4
+ import { useState, useEffect, useMemo } from 'react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ function useRootStyles() {
8
+ const [version, setVersion] = useState(0);
9
+ useEffect(() => {
10
+ if (typeof window === "undefined" || !document?.documentElement) {
11
+ return;
12
+ }
13
+ const target = document.documentElement;
14
+ const observer = new MutationObserver(() => {
15
+ setVersion((prev) => prev + 1);
16
+ });
17
+ observer.observe(target, {
18
+ attributes: true,
19
+ attributeFilter: ["class", "data-theme"]
20
+ });
21
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
22
+ const mediaHandler = () => setVersion((prev) => prev + 1);
23
+ media.addEventListener("change", mediaHandler);
24
+ return () => {
25
+ observer.disconnect();
26
+ media.removeEventListener("change", mediaHandler);
27
+ };
28
+ }, []);
29
+ return useMemo(() => {
30
+ if (typeof window === "undefined" || !document?.documentElement) {
31
+ return null;
32
+ }
33
+ return getComputedStyle(document.documentElement);
34
+ }, [version]);
35
+ }
36
+
37
+ // src/lib/theme.ts
38
+ var COLOR_VALUE_REGEX = /^(#|rgb|hsl|oklch)/i;
39
+ function resolveCssColor(styles, variable, fallback) {
40
+ if (!styles) return fallback;
41
+ const raw = styles.getPropertyValue(variable).trim();
42
+ if (!raw) return fallback;
43
+ if (COLOR_VALUE_REGEX.test(raw)) return raw;
44
+ if (raw.includes("%")) return `hsl(${raw})`;
45
+ return raw;
46
+ }
47
+
48
+ // src/hooks/use-chart-theme.ts
49
+ var FALLBACKS = {
50
+ foregroundMuted: "hsl(0 0% 50%)",
51
+ border: "hsl(0 0% 22%)",
52
+ popover: "hsl(0 0% 10%)",
53
+ popoverForeground: "hsl(0 0% 98%)",
54
+ chart1: "hsl(153 55% 42%)",
55
+ chart2: "hsl(198 50% 48%)",
56
+ chart3: "hsl(240 40% 54%)",
57
+ chart4: "hsl(310 38% 52%)",
58
+ chart5: "hsl(355 45% 52%)",
59
+ chart6: "hsl(35 52% 48%)",
60
+ chart7: "hsl(75 38% 46%)",
61
+ chart8: "hsl(118 35% 46%)"
62
+ };
63
+ var CHART_FONT_FAMILY = "Yekan Bakh, system-ui, -apple-system, sans-serif";
64
+ function useChartTheme() {
65
+ const styles = useRootStyles();
66
+ return React.useMemo(() => {
67
+ const getColor = (variable, fallback) => resolveCssColor(styles, variable, fallback);
68
+ const chartColors = [
69
+ getColor("--chart-1", FALLBACKS.chart1),
70
+ getColor("--chart-2", FALLBACKS.chart2),
71
+ getColor("--chart-3", FALLBACKS.chart3),
72
+ getColor("--chart-4", FALLBACKS.chart4),
73
+ getColor("--chart-5", FALLBACKS.chart5),
74
+ getColor("--chart-6", FALLBACKS.chart6),
75
+ getColor("--chart-7", FALLBACKS.chart7),
76
+ getColor("--chart-8", FALLBACKS.chart8)
77
+ ];
78
+ const axisTickStyle = {
79
+ fontFamily: CHART_FONT_FAMILY,
80
+ fill: getColor("--foreground-lighter", FALLBACKS.foregroundMuted),
81
+ fontSize: 11,
82
+ fontWeight: 400
83
+ };
84
+ const gridStyle = {
85
+ stroke: getColor("--border", FALLBACKS.border),
86
+ strokeDasharray: "3 3",
87
+ strokeOpacity: 0.15
88
+ };
89
+ const tooltipStyle = {
90
+ fontFamily: CHART_FONT_FAMILY,
91
+ background: getColor("--background-overlay-default", FALLBACKS.popover),
92
+ color: getColor("--foreground-default", FALLBACKS.popoverForeground),
93
+ fontSize: 12,
94
+ lineHeight: "1.5",
95
+ borderRadius: "10px",
96
+ border: `1px solid ${getColor("--border-muted", FALLBACKS.border)}`,
97
+ boxShadow: "0 4px 24px -4px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.06)",
98
+ padding: "10px 14px",
99
+ backdropFilter: "blur(8px)",
100
+ WebkitBackdropFilter: "blur(8px)"
101
+ };
102
+ const crosshairStyle = {
103
+ stroke: getColor("--foreground-muted", FALLBACKS.foregroundMuted),
104
+ strokeWidth: 1,
105
+ strokeDasharray: "4 4",
106
+ strokeOpacity: 0.5
107
+ };
108
+ return {
109
+ chartColors,
110
+ getColor,
111
+ fontFamily: CHART_FONT_FAMILY,
112
+ axisTickStyle,
113
+ gridStyle,
114
+ tooltipStyle,
115
+ crosshairStyle
116
+ };
117
+ }, [styles]);
118
+ }
119
+ var ChartContainer = React.forwardRef(
120
+ ({ className, dataSlot, ariaLabel, children }, ref) => /* @__PURE__ */ jsx(
121
+ "div",
122
+ {
123
+ ref,
124
+ className,
125
+ dir: "ltr",
126
+ "data-slot": dataSlot,
127
+ role: "img",
128
+ "aria-label": ariaLabel ?? "\u0646\u0645\u0648\u062F\u0627\u0631",
129
+ style: { position: "relative", width: "100%", height: "100%" },
130
+ children
131
+ }
132
+ )
133
+ );
134
+ ChartContainer.displayName = "ChartContainer";
135
+ function ChartLoadingSkeleton({ className, shape = "rect" }) {
136
+ return /* @__PURE__ */ jsx(
137
+ "div",
138
+ {
139
+ "data-slot": "chart-loading-skeleton",
140
+ className,
141
+ dir: "ltr",
142
+ style: { position: "relative", width: "100%", height: "100%" },
143
+ role: "status",
144
+ "aria-label": "Loading chart",
145
+ children: /* @__PURE__ */ jsx(
146
+ Skeleton,
147
+ {
148
+ shape,
149
+ className: shape === "circle" ? "w-full h-full min-h-[200px] aspect-square mx-auto" : "w-full h-full min-h-[200px]"
150
+ }
151
+ )
152
+ }
153
+ );
154
+ }
155
+ var LOCALE_TO_BCP47 = {
156
+ fa: "fa-IR",
157
+ ar: "ar",
158
+ en: "en-US"
159
+ };
160
+ function ChartTooltip({ active, payload, label, tooltipStyle, formatter, locale = "fa" }) {
161
+ if (!active || !payload?.length) return null;
162
+ const bcp47 = LOCALE_TO_BCP47[locale] ?? "fa-IR";
163
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "chart-tooltip", style: tooltipStyle, children: [
164
+ label && /* @__PURE__ */ jsx("div", { style: { fontWeight: 500, fontSize: 13, marginBottom: 6 }, children: label }),
165
+ payload.map((entry, i) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: i > 0 ? 4 : 0 }, children: [
166
+ /* @__PURE__ */ jsx(
167
+ "div",
168
+ {
169
+ style: {
170
+ width: 10,
171
+ height: 10,
172
+ borderRadius: 2,
173
+ backgroundColor: entry.color,
174
+ flexShrink: 0
175
+ }
176
+ }
177
+ ),
178
+ formatter ? formatter(entry.name, entry.value) : /* @__PURE__ */ jsxs("span", { style: { display: "flex", justifyContent: "space-between", width: "100%", gap: 16 }, children: [
179
+ /* @__PURE__ */ jsx("span", { style: { opacity: 0.7 }, children: entry.name }),
180
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontVariantNumeric: "tabular-nums" }, children: typeof entry.value === "number" ? entry.value.toLocaleString(bcp47) : entry.value })
181
+ ] })
182
+ ] }, i))
183
+ ] });
184
+ }
185
+ function localeAwareNumberTick(locale) {
186
+ return (value) => {
187
+ if (typeof value === "number") return formatLargeNumber(value, locale);
188
+ if (typeof value === "string") {
189
+ if (/^-?\d+(\.\d+)?$/.test(value)) return convertToLocalNumbers(value, locale);
190
+ return value;
191
+ }
192
+ return String(value ?? "");
193
+ };
194
+ }
195
+ function localeAwareCategoryTick(locale) {
196
+ return (value) => convertToLocalNumbers(String(value ?? ""), locale);
197
+ }
198
+ function transformNivoLineData(nivoData) {
199
+ const dataKeys = nivoData.map((s) => s.id);
200
+ const xValues = nivoData[0]?.data.map((d) => d.x) ?? [];
201
+ const data = xValues.map((x, xi) => {
202
+ const row = { name: x };
203
+ for (const series of nivoData) {
204
+ row[series.id] = series.data[xi]?.y ?? 0;
205
+ }
206
+ return row;
207
+ });
208
+ return { data, dataKeys };
209
+ }
210
+
211
+ export { CHART_FONT_FAMILY, ChartContainer, ChartLoadingSkeleton, ChartTooltip, localeAwareCategoryTick, localeAwareNumberTick, transformNivoLineData, useChartTheme, useRootStyles };
212
+ //# sourceMappingURL=chunk-IQHKJ4SS.js.map
213
+ //# sourceMappingURL=chunk-IQHKJ4SS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-root-styles.ts","../src/lib/theme.ts","../src/hooks/use-chart-theme.ts","../src/components/charts/chart-utils.tsx"],"names":["React2"],"mappings":";;;;;;AAQO,SAAS,aAAA,GAAgB;AAC9B,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,CAAC,CAAA;AAExC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,UAAU,eAAA,EAAiB;AAC/D,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,SAAS,QAAA,CAAS,eAAA;AACxB,IAAA,MAAM,QAAA,GAAW,IAAI,gBAAA,CAAiB,MAAM;AAC1C,MAAA,UAAA,CAAW,CAAC,IAAA,KAAS,IAAA,GAAO,CAAC,CAAA;AAAA,IAC/B,CAAC,CAAA;AAED,IAAA,QAAA,CAAS,QAAQ,MAAA,EAAQ;AAAA,MACvB,UAAA,EAAY,IAAA;AAAA,MACZ,eAAA,EAAiB,CAAC,OAAA,EAAS,YAAY;AAAA,KACxC,CAAA;AAED,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,UAAA,CAAW,8BAA8B,CAAA;AAC9D,IAAA,MAAM,eAAe,MAAM,UAAA,CAAW,CAAC,IAAA,KAAS,OAAO,CAAC,CAAA;AACxD,IAAA,KAAA,CAAM,gBAAA,CAAiB,UAAU,YAAY,CAAA;AAE7C,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,UAAA,EAAW;AACpB,MAAA,KAAA,CAAM,mBAAA,CAAoB,UAAU,YAAY,CAAA;AAAA,IAClD,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,QAAQ,MAAM;AACnB,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,UAAU,eAAA,EAAiB;AAC/D,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,gBAAA,CAAiB,SAAS,eAAe,CAAA;AAAA,EAClD,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AACd;;;AC3CA,IAAM,iBAAA,GAAoB,qBAAA;AAEnB,SAAS,eAAA,CACd,MAAA,EACA,QAAA,EACA,QAAA,EACA;AACA,EAAA,IAAI,CAAC,QAAQ,OAAO,QAAA;AACpB,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,gBAAA,CAAiB,QAAQ,EAAE,IAAA,EAAK;AACnD,EAAA,IAAI,CAAC,KAAK,OAAO,QAAA;AACjB,EAAA,IAAI,iBAAA,CAAkB,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,GAAA;AACxC,EAAA,IAAI,IAAI,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,OAAO,GAAG,CAAA,CAAA,CAAA;AACxC,EAAA,OAAO,GAAA;AACT;;;ACDA,IAAM,SAAA,GAAY;AAAA,EAEhB,eAAA,EAAiB,eAAA;AAAA,EACjB,MAAA,EAAQ,eAAA;AAAA,EACR,OAAA,EAAS,eAAA;AAAA,EACT,iBAAA,EAAmB,eAAA;AAAA,EACnB,MAAA,EAAQ,kBAAA;AAAA,EACR,MAAA,EAAQ,kBAAA;AAAA,EACR,MAAA,EAAQ,kBAAA;AAAA,EACR,MAAA,EAAQ,kBAAA;AAAA,EACR,MAAA,EAAQ,kBAAA;AAAA,EACR,MAAA,EAAQ,iBAAA;AAAA,EACR,MAAA,EAAQ,iBAAA;AAAA,EACR,MAAA,EAAQ;AACV,CAAA;AAEO,IAAM,iBAAA,GAAoB;AAE1B,SAAS,aAAA,GAAgB;AAC9B,EAAA,MAAM,SAAS,aAAA,EAAc;AAE7B,EAAA,OAAa,cAAQ,MAAM;AACzB,IAAA,MAAM,WAAW,CAAC,QAAA,EAAkB,aAAqB,eAAA,CAAgB,MAAA,EAAQ,UAAU,QAAQ,CAAA;AAEnG,IAAA,MAAM,WAAA,GAAc;AAAA,MAClB,QAAA,CAAS,WAAA,EAAa,SAAA,CAAU,MAAM,CAAA;AAAA,MACtC,QAAA,CAAS,WAAA,EAAa,SAAA,CAAU,MAAM,CAAA;AAAA,MACtC,QAAA,CAAS,WAAA,EAAa,SAAA,CAAU,MAAM,CAAA;AAAA,MACtC,QAAA,CAAS,WAAA,EAAa,SAAA,CAAU,MAAM,CAAA;AAAA,MACtC,QAAA,CAAS,WAAA,EAAa,SAAA,CAAU,MAAM,CAAA;AAAA,MACtC,QAAA,CAAS,WAAA,EAAa,SAAA,CAAU,MAAM,CAAA;AAAA,MACtC,QAAA,CAAS,WAAA,EAAa,SAAA,CAAU,MAAM,CAAA;AAAA,MACtC,QAAA,CAAS,WAAA,EAAa,SAAA,CAAU,MAAM;AAAA,KACxC;AAEA,IAAA,MAAM,aAAA,GAAgB;AAAA,MACpB,UAAA,EAAY,iBAAA;AAAA,MACZ,IAAA,EAAM,QAAA,CAAS,sBAAA,EAAwB,SAAA,CAAU,eAAe,CAAA;AAAA,MAChE,QAAA,EAAU,EAAA;AAAA,MACV,UAAA,EAAY;AAAA,KACd;AAEA,IAAA,MAAM,SAAA,GAAY;AAAA,MAChB,MAAA,EAAQ,QAAA,CAAS,UAAA,EAAY,SAAA,CAAU,MAAM,CAAA;AAAA,MAC7C,eAAA,EAAiB,KAAA;AAAA,MACjB,aAAA,EAAe;AAAA,KACjB;AAEA,IAAA,MAAM,YAAA,GAAoC;AAAA,MACxC,UAAA,EAAY,iBAAA;AAAA,MACZ,UAAA,EAAY,QAAA,CAAS,8BAAA,EAAgC,SAAA,CAAU,OAAO,CAAA;AAAA,MACtE,KAAA,EAAO,QAAA,CAAS,sBAAA,EAAwB,SAAA,CAAU,iBAAiB,CAAA;AAAA,MACnE,QAAA,EAAU,EAAA;AAAA,MACV,UAAA,EAAY,KAAA;AAAA,MACZ,YAAA,EAAc,MAAA;AAAA,MACd,QAAQ,CAAA,UAAA,EAAa,QAAA,CAAS,gBAAA,EAAkB,SAAA,CAAU,MAAM,CAAC,CAAA,CAAA;AAAA,MACjE,SAAA,EAAW,8DAAA;AAAA,MACX,OAAA,EAAS,WAAA;AAAA,MACT,cAAA,EAAgB,WAAA;AAAA,MAChB,oBAAA,EAAsB;AAAA,KACxB;AAEA,IAAA,MAAM,cAAA,GAAiB;AAAA,MACrB,MAAA,EAAQ,QAAA,CAAS,oBAAA,EAAsB,SAAA,CAAU,eAAe,CAAA;AAAA,MAChE,WAAA,EAAa,CAAA;AAAA,MACb,eAAA,EAAiB,KAAA;AAAA,MACjB,aAAA,EAAe;AAAA,KACjB;AAEA,IAAA,OAAO;AAAA,MACL,WAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA,EAAY,iBAAA;AAAA,MACZ,aAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACb;AC5EO,IAAM,cAAA,GAAuBA,KAAA,CAAA,UAAA;AAAA,EAClC,CAAC,EAAE,SAAA,EAAW,UAAU,SAAA,EAAW,QAAA,IAAY,GAAA,qBAC7C,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,SAAA;AAAA,MACA,GAAA,EAAI,KAAA;AAAA,MACJ,WAAA,EAAW,QAAA;AAAA,MACX,IAAA,EAAK,KAAA;AAAA,MACL,cAAY,SAAA,IAAa,sCAAA;AAAA,MACzB,OAAO,EAAE,QAAA,EAAU,YAAY,KAAA,EAAO,MAAA,EAAQ,QAAQ,MAAA,EAAO;AAAA,MAE5D;AAAA;AAAA;AAGP;AACA,cAAA,CAAe,WAAA,GAAc,gBAAA;AAStB,SAAS,oBAAA,CAAqB,EAAE,SAAA,EAAW,KAAA,GAAQ,QAAO,EAAuB;AACtF,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,wBAAA;AAAA,MACV,SAAA;AAAA,MACA,GAAA,EAAI,KAAA;AAAA,MACJ,OAAO,EAAE,QAAA,EAAU,YAAY,KAAA,EAAO,MAAA,EAAQ,QAAQ,MAAA,EAAO;AAAA,MAC7D,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAW,eAAA;AAAA,MAEX,QAAA,kBAAA,GAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,KAAA;AAAA,UACA,SAAA,EACE,KAAA,KAAU,QAAA,GAAW,mDAAA,GAAsD;AAAA;AAAA;AAE/E;AAAA,GACF;AAEJ;AAcA,IAAM,eAAA,GAAmD;AAAA,EACvD,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,IAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEO,SAAS,YAAA,CAAa,EAAE,MAAA,EAAQ,OAAA,EAAS,OAAO,YAAA,EAAc,SAAA,EAAW,MAAA,GAAS,IAAA,EAAK,EAAsB;AAClH,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,OAAA,EAAS,QAAQ,OAAO,IAAA;AAExC,EAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,MAAM,CAAA,IAAK,OAAA;AAEzC,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,WAAA,EAAU,eAAA,EAAgB,OAAO,YAAA,EACnC,QAAA,EAAA;AAAA,IAAA,KAAA,oBAAS,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,UAAA,EAAY,GAAA,EAAK,QAAA,EAAU,EAAA,EAAI,YAAA,EAAc,CAAA,EAAE,EAAI,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IAChF,OAAA,CAAQ,IAAI,CAAC,KAAA,EAAO,sBACnB,IAAA,CAAC,KAAA,EAAA,EAAY,OAAO,EAAE,OAAA,EAAS,QAAQ,UAAA,EAAY,QAAA,EAAU,KAAK,CAAA,EAAG,SAAA,EAAW,IAAI,CAAA,GAAI,CAAA,GAAI,GAAE,EAC5F,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO;AAAA,YACL,KAAA,EAAO,EAAA;AAAA,YACP,MAAA,EAAQ,EAAA;AAAA,YACR,YAAA,EAAc,CAAA;AAAA,YACd,iBAAiB,KAAA,CAAM,KAAA;AAAA,YACvB,UAAA,EAAY;AAAA;AACd;AAAA,OACF;AAAA,MACC,YACC,SAAA,CAAU,KAAA,CAAM,MAAM,KAAA,CAAM,KAAK,oBAEjC,IAAA,CAAC,MAAA,EAAA,EAAK,OAAO,EAAE,OAAA,EAAS,QAAQ,cAAA,EAAgB,eAAA,EAAiB,OAAO,MAAA,EAAQ,GAAA,EAAK,IAAG,EACtF,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,UAAK,KAAA,EAAO,EAAE,SAAS,GAAA,EAAI,EAAI,gBAAM,IAAA,EAAK,CAAA;AAAA,4BAC1C,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,UAAA,EAAY,GAAA,EAAK,oBAAoB,cAAA,EAAe,EAChE,iBAAO,KAAA,CAAM,KAAA,KAAU,WAAW,KAAA,CAAM,KAAA,CAAM,eAAe,KAAK,CAAA,GAAI,MAAM,KAAA,EAC/E;AAAA,OAAA,EACF;AAAA,KAAA,EAAA,EAlBM,CAoBV,CACD;AAAA,GAAA,EACH,CAAA;AAEJ;AAYO,SAAS,sBAAsB,MAAA,EAAqD;AACzF,EAAA,OAAO,CAAC,KAAA,KAAU;AAChB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,iBAAA,CAAkB,OAAO,MAAM,CAAA;AACrE,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAE7B,MAAA,IAAI,kBAAkB,IAAA,CAAK,KAAK,GAAG,OAAO,qBAAA,CAAsB,OAAO,MAAM,CAAA;AAC7E,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,MAAA,CAAO,SAAS,EAAE,CAAA;AAAA,EAC3B,CAAA;AACF;AAOO,SAAS,wBAAwB,MAAA,EAAqD;AAC3F,EAAA,OAAO,CAAC,KAAA,KAAU,qBAAA,CAAsB,OAAO,KAAA,IAAS,EAAE,GAAG,MAAM,CAAA;AACrE;AAYO,SAAS,sBACd,QAAA,EACsE;AACtE,EAAA,MAAM,WAAW,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,EAAE,CAAA;AACzC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,CAAC,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAA,IAAK,EAAC;AAEtD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,GAAG,EAAA,KAAO;AAClC,IAAA,MAAM,GAAA,GAAuC,EAAE,IAAA,EAAM,CAAA,EAAE;AACvD,IAAA,KAAA,MAAW,UAAU,QAAA,EAAU;AAC7B,MAAA,GAAA,CAAI,OAAO,EAAE,CAAA,GAAI,OAAO,IAAA,CAAK,EAAE,GAAG,CAAA,IAAK,CAAA;AAAA,IACzC;AACA,IAAA,OAAO,GAAA;AAAA,EACT,CAAC,CAAA;AAED,EAAA,OAAO,EAAE,MAAM,QAAA,EAAS;AAC1B","file":"chunk-IQHKJ4SS.js","sourcesContent":["'use client'\n\nimport { useEffect, useMemo, useState } from 'react'\n\n/**\n * Returns a snapshot of the current document root computed styles and\n * re-renders when the theme class or OS color scheme changes.\n */\nexport function useRootStyles() {\n const [version, setVersion] = useState(0)\n\n useEffect(() => {\n if (typeof window === 'undefined' || !document?.documentElement) {\n return\n }\n\n const target = document.documentElement\n const observer = new MutationObserver(() => {\n setVersion((prev) => prev + 1)\n })\n\n observer.observe(target, {\n attributes: true,\n attributeFilter: ['class', 'data-theme'],\n })\n\n const media = window.matchMedia('(prefers-color-scheme: dark)')\n const mediaHandler = () => setVersion((prev) => prev + 1)\n media.addEventListener('change', mediaHandler)\n\n return () => {\n observer.disconnect()\n media.removeEventListener('change', mediaHandler)\n }\n }, [])\n\n return useMemo(() => {\n if (typeof window === 'undefined' || !document?.documentElement) {\n return null\n }\n\n return getComputedStyle(document.documentElement)\n }, [version])\n}\n","const COLOR_VALUE_REGEX = /^(#|rgb|hsl|oklch)/i;\n\nexport function resolveCssColor(\n styles: CSSStyleDeclaration | null,\n variable: string,\n fallback: string,\n) {\n if (!styles) return fallback;\n const raw = styles.getPropertyValue(variable).trim();\n if (!raw) return fallback;\n if (COLOR_VALUE_REGEX.test(raw)) return raw;\n if (raw.includes('%')) return `hsl(${raw})`;\n return raw;\n}\n\n","'use client'\n\nimport * as React from 'react'\nimport { useRootStyles } from './use-root-styles'\nimport { resolveCssColor } from '@/lib/theme'\n\n/**\n * Chart theme hook — reads CSS design tokens at runtime and produces\n * resolved colors and styles for Recharts + Visx chart components.\n * Inspired by Linear, Vercel, and Stripe data visualizations.\n */\n\nconst FALLBACKS = {\n foreground: 'hsl(0 0% 98%)',\n foregroundMuted: 'hsl(0 0% 50%)',\n border: 'hsl(0 0% 22%)',\n popover: 'hsl(0 0% 10%)',\n popoverForeground: 'hsl(0 0% 98%)',\n chart1: 'hsl(153 55% 42%)',\n chart2: 'hsl(198 50% 48%)',\n chart3: 'hsl(240 40% 54%)',\n chart4: 'hsl(310 38% 52%)',\n chart5: 'hsl(355 45% 52%)',\n chart6: 'hsl(35 52% 48%)',\n chart7: 'hsl(75 38% 46%)',\n chart8: 'hsl(118 35% 46%)',\n}\n\nexport const CHART_FONT_FAMILY = 'Yekan Bakh, system-ui, -apple-system, sans-serif'\n\nexport function useChartTheme() {\n const styles = useRootStyles()\n\n return React.useMemo(() => {\n const getColor = (variable: string, fallback: string) => resolveCssColor(styles, variable, fallback)\n\n const chartColors = [\n getColor('--chart-1', FALLBACKS.chart1),\n getColor('--chart-2', FALLBACKS.chart2),\n getColor('--chart-3', FALLBACKS.chart3),\n getColor('--chart-4', FALLBACKS.chart4),\n getColor('--chart-5', FALLBACKS.chart5),\n getColor('--chart-6', FALLBACKS.chart6),\n getColor('--chart-7', FALLBACKS.chart7),\n getColor('--chart-8', FALLBACKS.chart8),\n ]\n\n const axisTickStyle = {\n fontFamily: CHART_FONT_FAMILY,\n fill: getColor('--foreground-lighter', FALLBACKS.foregroundMuted),\n fontSize: 11,\n fontWeight: 400 as const,\n }\n\n const gridStyle = {\n stroke: getColor('--border', FALLBACKS.border),\n strokeDasharray: '3 3',\n strokeOpacity: 0.15,\n }\n\n const tooltipStyle: React.CSSProperties = {\n fontFamily: CHART_FONT_FAMILY,\n background: getColor('--background-overlay-default', FALLBACKS.popover),\n color: getColor('--foreground-default', FALLBACKS.popoverForeground),\n fontSize: 12,\n lineHeight: '1.5',\n borderRadius: '10px',\n border: `1px solid ${getColor('--border-muted', FALLBACKS.border)}`,\n boxShadow: '0 4px 24px -4px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.06)',\n padding: '10px 14px',\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n }\n\n const crosshairStyle = {\n stroke: getColor('--foreground-muted', FALLBACKS.foregroundMuted),\n strokeWidth: 1,\n strokeDasharray: '4 4',\n strokeOpacity: 0.5,\n }\n\n return {\n chartColors,\n getColor,\n fontFamily: CHART_FONT_FAMILY,\n axisTickStyle,\n gridStyle,\n tooltipStyle,\n crosshairStyle,\n }\n }, [styles])\n}\n","'use client'\n\nimport * as React from 'react'\nimport { Skeleton } from '@/components/ui/skeleton'\nimport { convertToLocalNumbers, formatLargeNumber, type SupportedLocale } from '@/lib/utils'\n\n// ─── Chart Container ─────────────────────────────────────────────────────────\n\ninterface ChartContainerProps {\n className?: string\n dataSlot: string\n ariaLabel?: string\n children: React.ReactNode\n}\n\nexport const ChartContainer = React.forwardRef<HTMLDivElement, ChartContainerProps>(\n ({ className, dataSlot, ariaLabel, children }, ref) => (\n <div\n ref={ref}\n className={className}\n dir=\"ltr\"\n data-slot={dataSlot}\n role=\"img\"\n aria-label={ariaLabel ?? 'نمودار'}\n style={{ position: 'relative', width: '100%', height: '100%' }}\n >\n {children}\n </div>\n )\n)\nChartContainer.displayName = 'ChartContainer'\n\n// ─── Chart Skeleton ──────────────────────────────────────────────────────────\n\ninterface ChartSkeletonProps {\n className?: string\n shape?: 'rect' | 'circle'\n}\n\nexport function ChartLoadingSkeleton({ className, shape = 'rect' }: ChartSkeletonProps) {\n return (\n <div\n data-slot=\"chart-loading-skeleton\"\n className={className}\n dir=\"ltr\"\n style={{ position: 'relative', width: '100%', height: '100%' }}\n role=\"status\"\n aria-label=\"Loading chart\"\n >\n <Skeleton\n shape={shape}\n className={\n shape === 'circle' ? 'w-full h-full min-h-[200px] aspect-square mx-auto' : 'w-full h-full min-h-[200px]'\n }\n />\n </div>\n )\n}\n\n// ─── Chart Tooltip ───────────────────────────────────────────────────────────\n\ninterface ChartTooltipProps {\n active?: boolean\n payload?: Array<{ name: string; value: number; color: string; dataKey?: string }>\n label?: string\n tooltipStyle: React.CSSProperties\n formatter?: (name: string, value: number) => React.ReactNode\n /** Locale for the default value formatter. fa/ar render Persian/Arabic digits with thousands separators; en uses Latin. */\n locale?: SupportedLocale\n}\n\nconst LOCALE_TO_BCP47: Record<SupportedLocale, string> = {\n fa: 'fa-IR',\n ar: 'ar',\n en: 'en-US',\n}\n\nexport function ChartTooltip({ active, payload, label, tooltipStyle, formatter, locale = 'fa' }: ChartTooltipProps) {\n if (!active || !payload?.length) return null\n\n const bcp47 = LOCALE_TO_BCP47[locale] ?? 'fa-IR'\n\n return (\n <div data-slot=\"chart-tooltip\" style={tooltipStyle}>\n {label && <div style={{ fontWeight: 500, fontSize: 13, marginBottom: 6 }}>{label}</div>}\n {payload.map((entry, i) => (\n <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: i > 0 ? 4 : 0 }}>\n <div\n style={{\n width: 10,\n height: 10,\n borderRadius: 2,\n backgroundColor: entry.color,\n flexShrink: 0,\n }}\n />\n {formatter ? (\n formatter(entry.name, entry.value)\n ) : (\n <span style={{ display: 'flex', justifyContent: 'space-between', width: '100%', gap: 16 }}>\n <span style={{ opacity: 0.7 }}>{entry.name}</span>\n <span style={{ fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>\n {typeof entry.value === 'number' ? entry.value.toLocaleString(bcp47) : entry.value}\n </span>\n </span>\n )}\n </div>\n ))}\n </div>\n )\n}\n\n// ─── Locale-aware tick formatter ─────────────────────────────────────────────\n\n/**\n * Default tickFormatter for numeric chart axes (Y axis on Line/Area/Bar, both\n * axes on Scatter, radial on Radar). Renders Persian/Arabic digits + locale\n * suffix (\"۱.۵ هزار\", \"1.5K\") for fa/ar, Latin K/M/B for en.\n *\n * Pass via `axisLeft={{ tickFormatter: localeAwareNumberTick('fa') }}`, or rely\n * on the chart wrapper's `locale` prop which wires this in by default.\n */\nexport function localeAwareNumberTick(locale: SupportedLocale): (value: unknown) => string {\n return (value) => {\n if (typeof value === 'number') return formatLargeNumber(value, locale)\n if (typeof value === 'string') {\n // Numeric strings: convert digits only (don't touch labels).\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) return convertToLocalNumbers(value, locale)\n return value\n }\n return String(value ?? '')\n }\n}\n\n/**\n * Default tickFormatter for categorical chart axes — converts embedded digits\n * to the locale's numerals (e.g. \"۱۴۰۳-۰۱\" for \"1403-01\") without altering\n * letters. Use on date/time axes whose labels carry digits.\n */\nexport function localeAwareCategoryTick(locale: SupportedLocale): (value: unknown) => string {\n return (value) => convertToLocalNumbers(String(value ?? ''), locale)\n}\n\n// ─── Data Transform Utility ──────────────────────────────────────────────────\n\n/**\n * Transforms Nivo line/area data format to Recharts row-oriented format.\n * Useful for consumers migrating from Nivo data shape.\n *\n * @example\n * // Nivo: [{ id: \"فروش\", data: [{ x: \"فروردین\", y: 50 }] }]\n * // Recharts: [{ name: \"فروردین\", فروش: 50 }]\n */\nexport function transformNivoLineData(\n nivoData: Array<{ id: string; data: Array<{ x: string | number; y: number }> }>\n): { data: Array<Record<string, string | number>>; dataKeys: string[] } {\n const dataKeys = nivoData.map((s) => s.id)\n const xValues = nivoData[0]?.data.map((d) => d.x) ?? []\n\n const data = xValues.map((x, xi) => {\n const row: Record<string, string | number> = { name: x }\n for (const series of nivoData) {\n row[series.id] = series.data[xi]?.y ?? 0\n }\n return row\n })\n\n return { data, dataKeys }\n}\n"]}
@@ -0,0 +1,106 @@
1
+ 'use strict';
2
+
3
+ var chunkU5FLLCGC_cjs = require('./chunk-U5FLLCGC.cjs');
4
+ var React = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ function _interopNamespace(e) {
8
+ if (e && e.__esModule) return e;
9
+ var n = Object.create(null);
10
+ if (e) {
11
+ Object.keys(e).forEach(function (k) {
12
+ if (k !== 'default') {
13
+ var d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: function () { return e[k]; }
17
+ });
18
+ }
19
+ });
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+
25
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
26
+
27
+ var HotkeyRegisterContext = React__namespace.createContext(null);
28
+ var HotkeyListContext = React__namespace.createContext([]);
29
+ function HotkeyProvider({ enabled = true, children }) {
30
+ const [entries, setEntries] = React__namespace.useState(() => /* @__PURE__ */ new Map());
31
+ const handlersRef = React__namespace.useRef(/* @__PURE__ */ new Map());
32
+ const register = React__namespace.useRef((entry, handler) => {
33
+ handlersRef.current.set(entry.id, handler);
34
+ setEntries((prev) => {
35
+ const next = new Map(prev);
36
+ next.set(entry.id, entry);
37
+ return next;
38
+ });
39
+ return () => {
40
+ handlersRef.current.delete(entry.id);
41
+ setEntries((prev) => {
42
+ if (!prev.has(entry.id)) return prev;
43
+ const next = new Map(prev);
44
+ next.delete(entry.id);
45
+ return next;
46
+ });
47
+ };
48
+ }).current;
49
+ const hotkeys = React__namespace.useMemo(() => Array.from(entries.values()), [entries]);
50
+ return /* @__PURE__ */ jsxRuntime.jsx(HotkeyRegisterContext.Provider, { value: register, children: /* @__PURE__ */ jsxRuntime.jsxs(HotkeyListContext.Provider, { value: hotkeys, children: [
51
+ children,
52
+ enabled && /* @__PURE__ */ jsxRuntime.jsx(HotkeyDispatcher, { entries: hotkeys, handlersRef })
53
+ ] }) });
54
+ }
55
+ function HotkeyDispatcher({
56
+ entries,
57
+ handlersRef
58
+ }) {
59
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(HotkeyEntry, { entry, handlersRef }, entry.id)) });
60
+ }
61
+ function HotkeyEntry({
62
+ entry,
63
+ handlersRef
64
+ }) {
65
+ chunkU5FLLCGC_cjs.useHotkeys(
66
+ entry.combo,
67
+ (event) => {
68
+ const handler = handlersRef.current.get(entry.id);
69
+ handler?.(event);
70
+ },
71
+ { enabled: entry.enabled !== false }
72
+ );
73
+ return null;
74
+ }
75
+ function useHotkey(id, combo, handler, options = {}) {
76
+ const register = React__namespace.useContext(HotkeyRegisterContext);
77
+ const handlerRef = React__namespace.useRef(handler);
78
+ React__namespace.useEffect(() => {
79
+ handlerRef.current = handler;
80
+ });
81
+ const comboKey = Array.isArray(combo) ? combo.join("|") : combo;
82
+ React__namespace.useEffect(() => {
83
+ if (!register) return;
84
+ if (!comboKey) return;
85
+ return register(
86
+ {
87
+ id,
88
+ combo,
89
+ description: options.description,
90
+ group: options.group,
91
+ enabled: options.enabled
92
+ },
93
+ (event) => handlerRef.current(event)
94
+ );
95
+ }, [register, id, comboKey, options.description, options.group, options.enabled]);
96
+ }
97
+ function useHotkeyRegistry() {
98
+ const hotkeys = React__namespace.useContext(HotkeyListContext);
99
+ return { hotkeys };
100
+ }
101
+
102
+ exports.HotkeyProvider = HotkeyProvider;
103
+ exports.useHotkey = useHotkey;
104
+ exports.useHotkeyRegistry = useHotkeyRegistry;
105
+ //# sourceMappingURL=chunk-ISCSZMYW.cjs.map
106
+ //# sourceMappingURL=chunk-ISCSZMYW.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-hotkey-registry.tsx"],"names":["React","jsx","jsxs","Fragment","useHotkeys"],"mappings":"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","file":"chunk-ISCSZMYW.cjs","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useHotkeys, type HotkeyCombo } from './use-hotkeys'\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\nexport interface RegisteredHotkey {\n /** Stable id — used for de-registration + dedupe. */\n id: string\n /** The combo string(s) — `'mod+k'`, `['escape', 'mod+w']`, etc. */\n combo: HotkeyCombo\n /** Short human-readable description (e.g. \"باز کردن پالت دستور\"). */\n description?: string\n /** Optional grouping label for cheatsheet rendering (\"سراسری\", \"ناوبری\"…). */\n group?: string\n /** When false, the entry is listed but the listener doesn't fire. */\n enabled?: boolean\n}\n\ntype RegisterFn = (entry: RegisteredHotkey, handler: (event: KeyboardEvent) => void) => () => void\n\n/**\n * Two contexts so consumers can depend on a *stable* register fn (never\n * changes for the provider's lifetime) without re-running their effect\n * every time the entries list updates.\n */\nconst HotkeyRegisterContext = React.createContext<RegisterFn | null>(null)\nconst HotkeyListContext = React.createContext<RegisteredHotkey[]>([])\n\n/* -------------------------------------------------------------------------- */\n/* Provider */\n/* -------------------------------------------------------------------------- */\n\nexport interface HotkeyProviderProps {\n /** Globally disable all registered hotkeys (e.g. while a modal owns the page). */\n enabled?: boolean\n children: React.ReactNode\n}\n\n/**\n * Centralised hotkey registry. Wrap your app once; descendants register\n * combos via `useHotkey()` and any UI (CommandPalette, help cheatsheet)\n * can read the full list via `useHotkeyRegistry()`.\n *\n * Compared to scattering `useHotkeys` calls across the tree:\n * - Per-entry mounting is centralized (one place that handles\n * `enabled`, key parsing, ignore-when-typing semantics)\n * - Discoverable: cheatsheets / palettes can list every active combo\n * - De-duplicated: registering the same id twice replaces the entry\n *\n * Optional. `useHotkeys` (the bare hook) continues to work outside a provider.\n */\nexport function HotkeyProvider({ enabled = true, children }: HotkeyProviderProps) {\n const [entries, setEntries] = React.useState<Map<string, RegisteredHotkey>>(() => new Map())\n const handlersRef = React.useRef<Map<string, (event: KeyboardEvent) => void>>(new Map())\n\n // Stable across the provider's lifetime so descendants don't re-register\n // every time the entries list changes.\n const register = React.useRef<RegisterFn>((entry, handler) => {\n handlersRef.current.set(entry.id, handler)\n setEntries((prev) => {\n const next = new Map(prev)\n next.set(entry.id, entry)\n return next\n })\n return () => {\n handlersRef.current.delete(entry.id)\n setEntries((prev) => {\n if (!prev.has(entry.id)) return prev\n const next = new Map(prev)\n next.delete(entry.id)\n return next\n })\n }\n }).current\n\n const hotkeys = React.useMemo(() => Array.from(entries.values()), [entries])\n\n return (\n <HotkeyRegisterContext.Provider value={register}>\n <HotkeyListContext.Provider value={hotkeys}>\n {children}\n {enabled && <HotkeyDispatcher entries={hotkeys} handlersRef={handlersRef} />}\n </HotkeyListContext.Provider>\n </HotkeyRegisterContext.Provider>\n )\n}\n\n/**\n * Internal — one useHotkeys per registered entry, mounted under the\n * provider rather than per-component. Per-entry useHotkeys keeps key\n * parsing and ignoreWhenTyping logic in one tested place.\n */\nfunction HotkeyDispatcher({\n entries,\n handlersRef,\n}: {\n entries: RegisteredHotkey[]\n handlersRef: React.MutableRefObject<Map<string, (event: KeyboardEvent) => void>>\n}) {\n return (\n <>\n {entries.map((entry) => (\n <HotkeyEntry key={entry.id} entry={entry} handlersRef={handlersRef} />\n ))}\n </>\n )\n}\n\nfunction HotkeyEntry({\n entry,\n handlersRef,\n}: {\n entry: RegisteredHotkey\n handlersRef: React.MutableRefObject<Map<string, (event: KeyboardEvent) => void>>\n}) {\n useHotkeys(\n entry.combo,\n (event) => {\n const handler = handlersRef.current.get(entry.id)\n handler?.(event)\n },\n { enabled: entry.enabled !== false }\n )\n return null\n}\n\n/* -------------------------------------------------------------------------- */\n/* Hooks */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Register a hotkey under the active provider. The combo is added to the\n * cheatsheet-readable registry; the handler fires when the combo matches\n * (subject to `useHotkeys` rules around editable targets + modifiers).\n *\n * @example\n * useHotkey('palette', 'mod+k', () => setOpen(true), {\n * description: 'باز کردن پالت دستور',\n * group: 'سراسری',\n * })\n *\n * The first argument is a stable id — use a unique slug per call site so\n * registry updates can dedupe. When called outside a `<HotkeyProvider>`,\n * silently no-ops (so consumers can layer the provider in later without\n * a refactor sweep).\n */\nexport function useHotkey(\n id: string,\n combo: HotkeyCombo,\n handler: (event: KeyboardEvent) => void,\n options: { description?: string; group?: string; enabled?: boolean } = {}\n): void {\n const register = React.useContext(HotkeyRegisterContext)\n\n // Capture the latest handler so callers can pass an inline arrow each\n // render without re-registering the entry.\n const handlerRef = React.useRef(handler)\n React.useEffect(() => {\n handlerRef.current = handler\n })\n\n // Stringify combo for stable dependency tracking.\n const comboKey = Array.isArray(combo) ? combo.join('|') : combo\n\n React.useEffect(() => {\n if (!register) return\n // Skip registration when combo is empty/falsy — lets consumers conditionally\n // disable a hotkey without violating rules of hooks (still call useHotkey\n // unconditionally, but pass `''` to opt out).\n if (!comboKey) return\n return register(\n {\n id,\n combo,\n description: options.description,\n group: options.group,\n enabled: options.enabled,\n },\n (event) => handlerRef.current(event)\n )\n // `combo` (the original value) intentionally elided; comboKey covers it.\n }, [register, id, comboKey, options.description, options.group, options.enabled])\n}\n\n/**\n * Read the active registry. Returns an empty array outside a provider.\n * Useful for CommandPalette items, \"?\" cheatsheet overlays, settings pages.\n */\nexport function useHotkeyRegistry(): { hotkeys: RegisteredHotkey[] } {\n const hotkeys = React.useContext(HotkeyListContext)\n return { hotkeys }\n}\n"]}
@@ -0,0 +1,82 @@
1
+ import { useHotkeys } from './chunk-RZNRIOLT.js';
2
+ import * as React from 'react';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+
5
+ var HotkeyRegisterContext = React.createContext(null);
6
+ var HotkeyListContext = React.createContext([]);
7
+ function HotkeyProvider({ enabled = true, children }) {
8
+ const [entries, setEntries] = React.useState(() => /* @__PURE__ */ new Map());
9
+ const handlersRef = React.useRef(/* @__PURE__ */ new Map());
10
+ const register = React.useRef((entry, handler) => {
11
+ handlersRef.current.set(entry.id, handler);
12
+ setEntries((prev) => {
13
+ const next = new Map(prev);
14
+ next.set(entry.id, entry);
15
+ return next;
16
+ });
17
+ return () => {
18
+ handlersRef.current.delete(entry.id);
19
+ setEntries((prev) => {
20
+ if (!prev.has(entry.id)) return prev;
21
+ const next = new Map(prev);
22
+ next.delete(entry.id);
23
+ return next;
24
+ });
25
+ };
26
+ }).current;
27
+ const hotkeys = React.useMemo(() => Array.from(entries.values()), [entries]);
28
+ return /* @__PURE__ */ jsx(HotkeyRegisterContext.Provider, { value: register, children: /* @__PURE__ */ jsxs(HotkeyListContext.Provider, { value: hotkeys, children: [
29
+ children,
30
+ enabled && /* @__PURE__ */ jsx(HotkeyDispatcher, { entries: hotkeys, handlersRef })
31
+ ] }) });
32
+ }
33
+ function HotkeyDispatcher({
34
+ entries,
35
+ handlersRef
36
+ }) {
37
+ return /* @__PURE__ */ jsx(Fragment, { children: entries.map((entry) => /* @__PURE__ */ jsx(HotkeyEntry, { entry, handlersRef }, entry.id)) });
38
+ }
39
+ function HotkeyEntry({
40
+ entry,
41
+ handlersRef
42
+ }) {
43
+ useHotkeys(
44
+ entry.combo,
45
+ (event) => {
46
+ const handler = handlersRef.current.get(entry.id);
47
+ handler?.(event);
48
+ },
49
+ { enabled: entry.enabled !== false }
50
+ );
51
+ return null;
52
+ }
53
+ function useHotkey(id, combo, handler, options = {}) {
54
+ const register = React.useContext(HotkeyRegisterContext);
55
+ const handlerRef = React.useRef(handler);
56
+ React.useEffect(() => {
57
+ handlerRef.current = handler;
58
+ });
59
+ const comboKey = Array.isArray(combo) ? combo.join("|") : combo;
60
+ React.useEffect(() => {
61
+ if (!register) return;
62
+ if (!comboKey) return;
63
+ return register(
64
+ {
65
+ id,
66
+ combo,
67
+ description: options.description,
68
+ group: options.group,
69
+ enabled: options.enabled
70
+ },
71
+ (event) => handlerRef.current(event)
72
+ );
73
+ }, [register, id, comboKey, options.description, options.group, options.enabled]);
74
+ }
75
+ function useHotkeyRegistry() {
76
+ const hotkeys = React.useContext(HotkeyListContext);
77
+ return { hotkeys };
78
+ }
79
+
80
+ export { HotkeyProvider, useHotkey, useHotkeyRegistry };
81
+ //# sourceMappingURL=chunk-IXFEFIDO.js.map
82
+ //# sourceMappingURL=chunk-IXFEFIDO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-hotkey-registry.tsx"],"names":[],"mappings":"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","file":"chunk-IXFEFIDO.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useHotkeys, type HotkeyCombo } from './use-hotkeys'\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\nexport interface RegisteredHotkey {\n /** Stable id — used for de-registration + dedupe. */\n id: string\n /** The combo string(s) — `'mod+k'`, `['escape', 'mod+w']`, etc. */\n combo: HotkeyCombo\n /** Short human-readable description (e.g. \"باز کردن پالت دستور\"). */\n description?: string\n /** Optional grouping label for cheatsheet rendering (\"سراسری\", \"ناوبری\"…). */\n group?: string\n /** When false, the entry is listed but the listener doesn't fire. */\n enabled?: boolean\n}\n\ntype RegisterFn = (entry: RegisteredHotkey, handler: (event: KeyboardEvent) => void) => () => void\n\n/**\n * Two contexts so consumers can depend on a *stable* register fn (never\n * changes for the provider's lifetime) without re-running their effect\n * every time the entries list updates.\n */\nconst HotkeyRegisterContext = React.createContext<RegisterFn | null>(null)\nconst HotkeyListContext = React.createContext<RegisteredHotkey[]>([])\n\n/* -------------------------------------------------------------------------- */\n/* Provider */\n/* -------------------------------------------------------------------------- */\n\nexport interface HotkeyProviderProps {\n /** Globally disable all registered hotkeys (e.g. while a modal owns the page). */\n enabled?: boolean\n children: React.ReactNode\n}\n\n/**\n * Centralised hotkey registry. Wrap your app once; descendants register\n * combos via `useHotkey()` and any UI (CommandPalette, help cheatsheet)\n * can read the full list via `useHotkeyRegistry()`.\n *\n * Compared to scattering `useHotkeys` calls across the tree:\n * - Per-entry mounting is centralized (one place that handles\n * `enabled`, key parsing, ignore-when-typing semantics)\n * - Discoverable: cheatsheets / palettes can list every active combo\n * - De-duplicated: registering the same id twice replaces the entry\n *\n * Optional. `useHotkeys` (the bare hook) continues to work outside a provider.\n */\nexport function HotkeyProvider({ enabled = true, children }: HotkeyProviderProps) {\n const [entries, setEntries] = React.useState<Map<string, RegisteredHotkey>>(() => new Map())\n const handlersRef = React.useRef<Map<string, (event: KeyboardEvent) => void>>(new Map())\n\n // Stable across the provider's lifetime so descendants don't re-register\n // every time the entries list changes.\n const register = React.useRef<RegisterFn>((entry, handler) => {\n handlersRef.current.set(entry.id, handler)\n setEntries((prev) => {\n const next = new Map(prev)\n next.set(entry.id, entry)\n return next\n })\n return () => {\n handlersRef.current.delete(entry.id)\n setEntries((prev) => {\n if (!prev.has(entry.id)) return prev\n const next = new Map(prev)\n next.delete(entry.id)\n return next\n })\n }\n }).current\n\n const hotkeys = React.useMemo(() => Array.from(entries.values()), [entries])\n\n return (\n <HotkeyRegisterContext.Provider value={register}>\n <HotkeyListContext.Provider value={hotkeys}>\n {children}\n {enabled && <HotkeyDispatcher entries={hotkeys} handlersRef={handlersRef} />}\n </HotkeyListContext.Provider>\n </HotkeyRegisterContext.Provider>\n )\n}\n\n/**\n * Internal — one useHotkeys per registered entry, mounted under the\n * provider rather than per-component. Per-entry useHotkeys keeps key\n * parsing and ignoreWhenTyping logic in one tested place.\n */\nfunction HotkeyDispatcher({\n entries,\n handlersRef,\n}: {\n entries: RegisteredHotkey[]\n handlersRef: React.MutableRefObject<Map<string, (event: KeyboardEvent) => void>>\n}) {\n return (\n <>\n {entries.map((entry) => (\n <HotkeyEntry key={entry.id} entry={entry} handlersRef={handlersRef} />\n ))}\n </>\n )\n}\n\nfunction HotkeyEntry({\n entry,\n handlersRef,\n}: {\n entry: RegisteredHotkey\n handlersRef: React.MutableRefObject<Map<string, (event: KeyboardEvent) => void>>\n}) {\n useHotkeys(\n entry.combo,\n (event) => {\n const handler = handlersRef.current.get(entry.id)\n handler?.(event)\n },\n { enabled: entry.enabled !== false }\n )\n return null\n}\n\n/* -------------------------------------------------------------------------- */\n/* Hooks */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Register a hotkey under the active provider. The combo is added to the\n * cheatsheet-readable registry; the handler fires when the combo matches\n * (subject to `useHotkeys` rules around editable targets + modifiers).\n *\n * @example\n * useHotkey('palette', 'mod+k', () => setOpen(true), {\n * description: 'باز کردن پالت دستور',\n * group: 'سراسری',\n * })\n *\n * The first argument is a stable id — use a unique slug per call site so\n * registry updates can dedupe. When called outside a `<HotkeyProvider>`,\n * silently no-ops (so consumers can layer the provider in later without\n * a refactor sweep).\n */\nexport function useHotkey(\n id: string,\n combo: HotkeyCombo,\n handler: (event: KeyboardEvent) => void,\n options: { description?: string; group?: string; enabled?: boolean } = {}\n): void {\n const register = React.useContext(HotkeyRegisterContext)\n\n // Capture the latest handler so callers can pass an inline arrow each\n // render without re-registering the entry.\n const handlerRef = React.useRef(handler)\n React.useEffect(() => {\n handlerRef.current = handler\n })\n\n // Stringify combo for stable dependency tracking.\n const comboKey = Array.isArray(combo) ? combo.join('|') : combo\n\n React.useEffect(() => {\n if (!register) return\n // Skip registration when combo is empty/falsy — lets consumers conditionally\n // disable a hotkey without violating rules of hooks (still call useHotkey\n // unconditionally, but pass `''` to opt out).\n if (!comboKey) return\n return register(\n {\n id,\n combo,\n description: options.description,\n group: options.group,\n enabled: options.enabled,\n },\n (event) => handlerRef.current(event)\n )\n // `combo` (the original value) intentionally elided; comboKey covers it.\n }, [register, id, comboKey, options.description, options.group, options.enabled])\n}\n\n/**\n * Read the active registry. Returns an empty array outside a provider.\n * Useful for CommandPalette items, \"?\" cheatsheet overlays, settings pages.\n */\nexport function useHotkeyRegistry(): { hotkeys: RegisteredHotkey[] } {\n const hotkeys = React.useContext(HotkeyListContext)\n return { hotkeys }\n}\n"]}
@@ -0,0 +1,53 @@
1
+ import { cn } from './chunk-4SVQNEVH.js';
2
+ import * as React from 'react';
3
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ var TooltipProvider = TooltipPrimitive.Provider;
7
+ var Tooltip = TooltipPrimitive.Root;
8
+ var TooltipTrigger = TooltipPrimitive.Trigger;
9
+ var TooltipContent = React.forwardRef(
10
+ ({ className, variant = "default", size = "sm", showArrow = false, sideOffset = 4, children, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
11
+ TooltipPrimitive.Content,
12
+ {
13
+ ref,
14
+ "data-slot": "tooltip-content",
15
+ sideOffset,
16
+ className: cn(
17
+ "z-50 overflow-hidden rounded-md shadow-dropdown",
18
+ "animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",
19
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
20
+ // Variant styles
21
+ variant === "default" && "border bg-alternative text-foreground",
22
+ variant === "light" && "border bg-surface-100 text-foreground shadow-dropdown",
23
+ variant === "error" && "border border-destructive-500 bg-destructive-200 text-destructive-600",
24
+ // Size
25
+ size === "sm" && "px-3 py-1.5 text-xs",
26
+ size === "md" && "px-4 py-2 text-sm",
27
+ className
28
+ ),
29
+ ...props,
30
+ children: [
31
+ children,
32
+ showArrow && /* @__PURE__ */ jsx(
33
+ TooltipPrimitive.Arrow,
34
+ {
35
+ className: cn(
36
+ "fill-current",
37
+ variant === "default" && "text-alternative",
38
+ variant === "light" && "text-surface-100",
39
+ variant === "error" && "text-destructive-200"
40
+ ),
41
+ width: 8,
42
+ height: 4
43
+ }
44
+ )
45
+ ]
46
+ }
47
+ ) })
48
+ );
49
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
50
+
51
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
52
+ //# sourceMappingURL=chunk-JUBHQAA2.js.map
53
+ //# sourceMappingURL=chunk-JUBHQAA2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/tooltip.tsx"],"names":[],"mappings":";;;;;AAOA,IAAM,eAAA,GAAmC,gBAAA,CAAA;AAEzC,IAAM,OAAA,GAA2B,gBAAA,CAAA;AAEjC,IAAM,cAAA,GAAkC,gBAAA,CAAA;AAexC,IAAM,cAAA,GAAuB,KAAA,CAAA,UAAA;AAAA,EAC3B,CAAC,EAAE,SAAA,EAAW,UAAU,SAAA,EAAW,IAAA,GAAO,MAAM,SAAA,GAAY,KAAA,EAAO,UAAA,GAAa,CAAA,EAAG,UAAU,GAAG,KAAA,IAAS,GAAA,qBACvG,GAAA,CAAkB,yBAAjB,EACC,QAAA,kBAAA,IAAA;AAAA,IAAkB,gBAAA,CAAA,OAAA;AAAA,IAAjB;AAAA,MACC,GAAA;AAAA,MACA,WAAA,EAAU,iBAAA;AAAA,MACV,UAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,iDAAA;AAAA,QACA,mLAAA;AAAA,QACA,gGAAA;AAAA;AAAA,QAEA,YAAY,SAAA,IAAa,uCAAA;AAAA,QACzB,YAAY,OAAA,IAAW,uDAAA;AAAA,QACvB,YAAY,OAAA,IAAW,uEAAA;AAAA;AAAA,QAEvB,SAAS,IAAA,IAAQ,qBAAA;AAAA,QACjB,SAAS,IAAA,IAAQ,mBAAA;AAAA,QACjB;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEH,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,QACA,SAAA,oBACC,GAAA;AAAA,UAAkB,gBAAA,CAAA,KAAA;AAAA,UAAjB;AAAA,YACC,SAAA,EAAW,EAAA;AAAA,cACT,cAAA;AAAA,cACA,YAAY,SAAA,IAAa,kBAAA;AAAA,cACzB,YAAY,OAAA,IAAW,kBAAA;AAAA,cACvB,YAAY,OAAA,IAAW;AAAA,aACzB;AAAA,YACA,KAAA,EAAO,CAAA;AAAA,YACP,MAAA,EAAQ;AAAA;AAAA;AACV;AAAA;AAAA,GAEJ,EACF;AAEJ;AACA,cAAA,CAAe,cAA+B,gBAAA,CAAA,OAAA,CAAQ,WAAA","file":"chunk-JUBHQAA2.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip'\n\nimport { cn } from '@/lib/utils'\n\nconst TooltipProvider = TooltipPrimitive.Provider\n\nconst Tooltip = TooltipPrimitive.Root\n\nconst TooltipTrigger = TooltipPrimitive.Trigger\n\n/* -------------------------------------------------------------------------- */\n/* TooltipContent */\n/* -------------------------------------------------------------------------- */\n\ninterface TooltipContentProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /** Visual variant */\n variant?: 'default' | 'light' | 'error'\n /** Size */\n size?: 'sm' | 'md'\n /** Show arrow/caret pointing to trigger */\n showArrow?: boolean\n}\n\nconst TooltipContent = React.forwardRef<React.ElementRef<typeof TooltipPrimitive.Content>, TooltipContentProps>(\n ({ className, variant = 'default', size = 'sm', showArrow = false, sideOffset = 4, children, ...props }, ref) => (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n 'z-50 overflow-hidden rounded-md shadow-dropdown',\n 'animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1',\n 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',\n // Variant styles\n variant === 'default' && 'border bg-alternative text-foreground',\n variant === 'light' && 'border bg-surface-100 text-foreground shadow-dropdown',\n variant === 'error' && 'border border-destructive-500 bg-destructive-200 text-destructive-600',\n // Size\n size === 'sm' && 'px-3 py-1.5 text-xs',\n size === 'md' && 'px-4 py-2 text-sm',\n className\n )}\n {...props}\n >\n {children}\n {showArrow && (\n <TooltipPrimitive.Arrow\n className={cn(\n 'fill-current',\n variant === 'default' && 'text-alternative',\n variant === 'light' && 'text-surface-100',\n variant === 'error' && 'text-destructive-200'\n )}\n width={8}\n height={4}\n />\n )}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )\n)\nTooltipContent.displayName = TooltipPrimitive.Content.displayName\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n"]}
@@ -0,0 +1,62 @@
1
+ import { severityLabels } from './chunk-CV3N3HVK.js';
2
+ import { cn } from './chunk-4SVQNEVH.js';
3
+ import * as React from 'react';
4
+ import { ChevronDown, Minus, ChevronUp, Flame } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var SEVERITY_ICON = {
8
+ urgent: Flame,
9
+ high: ChevronUp,
10
+ medium: Minus,
11
+ low: ChevronDown
12
+ };
13
+ var SIZE_CLASSES = {
14
+ sm: { badge: "h-6 text-xs px-2 gap-1", icon: "size-3" },
15
+ md: { badge: "h-7 text-sm px-2.5 gap-1.5", icon: "size-3.5" }
16
+ };
17
+ function tokenVar(severity) {
18
+ return `--severity-${severity}`;
19
+ }
20
+ var SeverityBadge = React.forwardRef(
21
+ ({ className, severity, size = "md", showLabel = true, variant = "soft", locale = "fa", ...props }, ref) => {
22
+ const label = severityLabels[locale]?.[severity] ?? severityLabels.fa[severity];
23
+ const Icon = SEVERITY_ICON[severity];
24
+ const token = tokenVar(severity);
25
+ const softStyle = {
26
+ backgroundColor: `hsl(var(${token}) / 0.1)`,
27
+ borderColor: `hsl(var(${token}) / 0.3)`,
28
+ color: `hsl(var(${token}))`
29
+ };
30
+ const solidStyle = {
31
+ backgroundColor: `hsl(var(${token}))`,
32
+ borderColor: `hsl(var(${token}))`,
33
+ color: "hsl(var(--foreground-contrast))"
34
+ };
35
+ return /* @__PURE__ */ jsxs(
36
+ "span",
37
+ {
38
+ ref,
39
+ "data-slot": "severity-badge",
40
+ "data-severity": severity,
41
+ "data-variant": variant,
42
+ "aria-label": showLabel ? void 0 : label,
43
+ className: cn(
44
+ "inline-flex items-center rounded-full border font-medium transition-colors duration-150",
45
+ SIZE_CLASSES[size].badge,
46
+ className
47
+ ),
48
+ style: variant === "solid" ? solidStyle : softStyle,
49
+ ...props,
50
+ children: [
51
+ /* @__PURE__ */ jsx(Icon, { className: SIZE_CLASSES[size].icon, "aria-hidden": "true" }),
52
+ showLabel && /* @__PURE__ */ jsx("span", { children: label })
53
+ ]
54
+ }
55
+ );
56
+ }
57
+ );
58
+ SeverityBadge.displayName = "SeverityBadge";
59
+
60
+ export { SeverityBadge };
61
+ //# sourceMappingURL=chunk-KCWRCSI7.js.map
62
+ //# sourceMappingURL=chunk-KCWRCSI7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ui/severity-badge.tsx"],"names":[],"mappings":";;;;;;AAoBA,IAAM,aAAA,GAAiD;AAAA,EACrD,MAAA,EAAQ,KAAA;AAAA,EACR,IAAA,EAAM,SAAA;AAAA,EACN,MAAA,EAAQ,KAAA;AAAA,EACR,GAAA,EAAK;AACP,CAAA;AAEA,IAAM,YAAA,GAAe;AAAA,EACnB,EAAA,EAAI,EAAE,KAAA,EAAO,wBAAA,EAA0B,MAAM,QAAA,EAAS;AAAA,EACtD,EAAA,EAAI,EAAE,KAAA,EAAO,4BAAA,EAA8B,MAAM,UAAA;AACnD,CAAA;AAEA,SAAS,SAAS,QAAA,EAA+B;AAC/C,EAAA,OAAO,cAAc,QAAQ,CAAA,CAAA;AAC/B;AAEA,IAAM,aAAA,GAAsB,KAAA,CAAA,UAAA;AAAA,EAC1B,CAAC,EAAE,SAAA,EAAW,QAAA,EAAU,OAAO,IAAA,EAAM,SAAA,GAAY,IAAA,EAAM,OAAA,GAAU,QAAQ,MAAA,GAAS,IAAA,EAAM,GAAG,KAAA,IAAS,GAAA,KAAQ;AAC1G,IAAA,MAAM,KAAA,GAAQ,eAAe,MAAM,CAAA,GAAI,QAAQ,CAAA,IAAK,cAAA,CAAe,GAAG,QAAQ,CAAA;AAC9E,IAAA,MAAM,IAAA,GAAO,cAAc,QAAQ,CAAA;AACnC,IAAA,MAAM,KAAA,GAAQ,SAAS,QAAQ,CAAA;AAE/B,IAAA,MAAM,SAAA,GAAiC;AAAA,MACrC,eAAA,EAAiB,WAAW,KAAK,CAAA,QAAA,CAAA;AAAA,MACjC,WAAA,EAAa,WAAW,KAAK,CAAA,QAAA,CAAA;AAAA,MAC7B,KAAA,EAAO,WAAW,KAAK,CAAA,EAAA;AAAA,KACzB;AACA,IAAA,MAAM,UAAA,GAAkC;AAAA,MACtC,eAAA,EAAiB,WAAW,KAAK,CAAA,EAAA,CAAA;AAAA,MACjC,WAAA,EAAa,WAAW,KAAK,CAAA,EAAA,CAAA;AAAA,MAC7B,KAAA,EAAO;AAAA,KACT;AAEA,IAAA,uBACE,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAA,EAAU,gBAAA;AAAA,QACV,eAAA,EAAe,QAAA;AAAA,QACf,cAAA,EAAc,OAAA;AAAA,QACd,YAAA,EAAY,YAAY,MAAA,GAAY,KAAA;AAAA,QACpC,SAAA,EAAW,EAAA;AAAA,UACT,yFAAA;AAAA,UACA,YAAA,CAAa,IAAI,CAAA,CAAE,KAAA;AAAA,UACnB;AAAA,SACF;AAAA,QACA,KAAA,EAAO,OAAA,KAAY,OAAA,GAAU,UAAA,GAAa,SAAA;AAAA,QACzC,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,QAAK,SAAA,EAAW,YAAA,CAAa,IAAI,CAAA,CAAE,IAAA,EAAM,eAAY,MAAA,EAAO,CAAA;AAAA,UAC5D,SAAA,oBAAa,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA,KAC7B;AAAA,EAEJ;AACF;AAEA,aAAA,CAAc,WAAA,GAAc,eAAA","file":"chunk-KCWRCSI7.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Flame, ChevronUp, Minus, ChevronDown, type LucideIcon } from 'lucide-react'\nimport { cn, type SupportedLocale } from '@/lib/utils'\nimport { severityLabels, type SeverityKey } from '@/lib/i18n'\n\nexport interface SeverityBadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Urgency level — independent from operational status */\n severity: SeverityKey\n /** Size */\n size?: 'sm' | 'md'\n /** Show text label */\n showLabel?: boolean\n /** Render as a solid chip instead of the soft tinted pill (for high-contrast lists) */\n variant?: 'soft' | 'solid'\n /** Locale */\n locale?: SupportedLocale\n}\n\nconst SEVERITY_ICON: Record<SeverityKey, LucideIcon> = {\n urgent: Flame,\n high: ChevronUp,\n medium: Minus,\n low: ChevronDown,\n}\n\nconst SIZE_CLASSES = {\n sm: { badge: 'h-6 text-xs px-2 gap-1', icon: 'size-3' },\n md: { badge: 'h-7 text-sm px-2.5 gap-1.5', icon: 'size-3.5' },\n} as const\n\nfunction tokenVar(severity: SeverityKey): string {\n return `--severity-${severity}`\n}\n\nconst SeverityBadge = React.forwardRef<HTMLSpanElement, SeverityBadgeProps>(\n ({ className, severity, size = 'md', showLabel = true, variant = 'soft', locale = 'fa', ...props }, ref) => {\n const label = severityLabels[locale]?.[severity] ?? severityLabels.fa[severity]\n const Icon = SEVERITY_ICON[severity]\n const token = tokenVar(severity)\n\n const softStyle: React.CSSProperties = {\n backgroundColor: `hsl(var(${token}) / 0.1)`,\n borderColor: `hsl(var(${token}) / 0.3)`,\n color: `hsl(var(${token}))`,\n }\n const solidStyle: React.CSSProperties = {\n backgroundColor: `hsl(var(${token}))`,\n borderColor: `hsl(var(${token}))`,\n color: 'hsl(var(--foreground-contrast))',\n }\n\n return (\n <span\n ref={ref}\n data-slot=\"severity-badge\"\n data-severity={severity}\n data-variant={variant}\n aria-label={showLabel ? undefined : label}\n className={cn(\n 'inline-flex items-center rounded-full border font-medium transition-colors duration-150',\n SIZE_CLASSES[size].badge,\n className\n )}\n style={variant === 'solid' ? solidStyle : softStyle}\n {...props}\n >\n <Icon className={SIZE_CLASSES[size].icon} aria-hidden=\"true\" />\n {showLabel && <span>{label}</span>}\n </span>\n )\n }\n)\n\nSeverityBadge.displayName = 'SeverityBadge'\n\nexport { SeverityBadge }\n"]}