@modern-admin/web 0.4.1 → 0.5.0

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 (285) hide show
  1. package/dist/standalone/assets/action-component-host-QVowRL_F.js +2 -0
  2. package/dist/standalone/assets/action-component-host-QVowRL_F.js.br +0 -0
  3. package/dist/standalone/assets/action-component-host-QVowRL_F.js.gz +0 -0
  4. package/dist/standalone/assets/{action-component-host-BrEZDHZt.js.map → action-component-host-QVowRL_F.js.map} +1 -1
  5. package/dist/standalone/assets/action-page-CET1s1MA.js +2 -0
  6. package/dist/standalone/assets/action-page-CET1s1MA.js.br +0 -0
  7. package/dist/standalone/assets/action-page-CET1s1MA.js.gz +0 -0
  8. package/dist/standalone/assets/{action-page-Bx7kzeK7.js.map → action-page-CET1s1MA.js.map} +1 -1
  9. package/dist/standalone/assets/ai-assistant-widget-pJHSP1PB.js +2 -0
  10. package/dist/standalone/assets/ai-assistant-widget-pJHSP1PB.js.br +0 -0
  11. package/dist/standalone/assets/ai-assistant-widget-pJHSP1PB.js.gz +0 -0
  12. package/dist/standalone/assets/{ai-assistant-widget-BbIXVrSu.js.map → ai-assistant-widget-pJHSP1PB.js.map} +1 -1
  13. package/dist/standalone/assets/audit-log-page-DoZPtbGo.js +2 -0
  14. package/dist/standalone/assets/audit-log-page-DoZPtbGo.js.br +0 -0
  15. package/dist/standalone/assets/audit-log-page-DoZPtbGo.js.gz +0 -0
  16. package/dist/standalone/assets/{audit-log-page-BoZh23oQ.js.map → audit-log-page-DoZPtbGo.js.map} +1 -1
  17. package/dist/standalone/assets/badge-8oeWEs3P.js +2 -0
  18. package/dist/standalone/assets/{badge-6nyM5Jft.js.map → badge-8oeWEs3P.js.map} +1 -1
  19. package/dist/standalone/assets/cache-page-CoKusfv-.js +2 -0
  20. package/dist/standalone/assets/cache-page-CoKusfv-.js.br +0 -0
  21. package/dist/standalone/assets/cache-page-CoKusfv-.js.gz +0 -0
  22. package/dist/standalone/assets/cache-page-CoKusfv-.js.map +1 -0
  23. package/dist/standalone/assets/calendar-DDv0Qalf.js +2 -0
  24. package/dist/standalone/assets/calendar-DDv0Qalf.js.br +0 -0
  25. package/dist/standalone/assets/calendar-DDv0Qalf.js.gz +0 -0
  26. package/dist/standalone/assets/{calendar-nvD_z7KQ.js.map → calendar-DDv0Qalf.js.map} +1 -1
  27. package/dist/standalone/assets/card-MNH_XK0V.js +2 -0
  28. package/dist/standalone/assets/card-MNH_XK0V.js.br +0 -0
  29. package/dist/standalone/assets/card-MNH_XK0V.js.gz +0 -0
  30. package/dist/standalone/assets/{card-4cS4uWCP.js.map → card-MNH_XK0V.js.map} +1 -1
  31. package/dist/standalone/assets/chart-widget-R2NG5T1y.js +2 -0
  32. package/dist/standalone/assets/chart-widget-R2NG5T1y.js.br +0 -0
  33. package/dist/standalone/assets/chart-widget-R2NG5T1y.js.gz +0 -0
  34. package/dist/standalone/assets/chart-widget-R2NG5T1y.js.map +1 -0
  35. package/dist/standalone/assets/command-Cw-hTtpk.js +2 -0
  36. package/dist/standalone/assets/command-Cw-hTtpk.js.br +0 -0
  37. package/dist/standalone/assets/command-Cw-hTtpk.js.gz +0 -0
  38. package/dist/standalone/assets/command-Cw-hTtpk.js.map +1 -0
  39. package/dist/standalone/assets/date-picker-DQ4XOgO6.js +2 -0
  40. package/dist/standalone/assets/date-picker-DQ4XOgO6.js.br +0 -0
  41. package/dist/standalone/assets/date-picker-DQ4XOgO6.js.gz +0 -0
  42. package/dist/standalone/assets/{date-picker-C4HcgidQ.js.map → date-picker-DQ4XOgO6.js.map} +1 -1
  43. package/dist/standalone/assets/dist-CmyV2PEd.js +2 -0
  44. package/dist/standalone/assets/dist-CmyV2PEd.js.br +0 -0
  45. package/dist/standalone/assets/dist-CmyV2PEd.js.gz +0 -0
  46. package/dist/standalone/assets/{dist-Dpg8xy_r.js.map → dist-CmyV2PEd.js.map} +1 -1
  47. package/dist/standalone/assets/dist-DI9XNddW.js +2 -0
  48. package/dist/standalone/assets/dist-DI9XNddW.js.br +0 -0
  49. package/dist/standalone/assets/dist-DI9XNddW.js.gz +0 -0
  50. package/dist/standalone/assets/{dist-BSbFjTlr.js.map → dist-DI9XNddW.js.map} +1 -1
  51. package/dist/standalone/assets/dist-jC1pK2zN.js +2 -0
  52. package/dist/standalone/assets/dist-jC1pK2zN.js.br +0 -0
  53. package/dist/standalone/assets/dist-jC1pK2zN.js.gz +0 -0
  54. package/dist/standalone/assets/{dist-BcL2U6dT.js.map → dist-jC1pK2zN.js.map} +1 -1
  55. package/dist/standalone/assets/edit-page-CVjik6T5.js +2 -0
  56. package/dist/standalone/assets/edit-page-CVjik6T5.js.br +0 -0
  57. package/dist/standalone/assets/edit-page-CVjik6T5.js.gz +0 -0
  58. package/dist/standalone/assets/{edit-page-CW7-FAPC.js.map → edit-page-CVjik6T5.js.map} +1 -1
  59. package/dist/standalone/assets/empty-DcETRWsu.js +2 -0
  60. package/dist/standalone/assets/empty-DcETRWsu.js.br +0 -0
  61. package/dist/standalone/assets/empty-DcETRWsu.js.gz +0 -0
  62. package/dist/standalone/assets/{empty-Cposcczv.js.map → empty-DcETRWsu.js.map} +1 -1
  63. package/dist/standalone/assets/floating-layer-DJGCYMex.js +2 -0
  64. package/dist/standalone/assets/floating-layer-DJGCYMex.js.br +0 -0
  65. package/dist/standalone/assets/floating-layer-DJGCYMex.js.gz +0 -0
  66. package/dist/standalone/assets/floating-layer-DJGCYMex.js.map +1 -0
  67. package/dist/standalone/assets/global-search-dialog-CT30gcRv.js +2 -0
  68. package/dist/standalone/assets/global-search-dialog-CT30gcRv.js.br +0 -0
  69. package/dist/standalone/assets/global-search-dialog-CT30gcRv.js.gz +0 -0
  70. package/dist/standalone/assets/{global-search-dialog-DLv_nIvM.js.map → global-search-dialog-CT30gcRv.js.map} +1 -1
  71. package/dist/standalone/assets/heavy-fields-ByzRCqe0.js +181 -0
  72. package/dist/standalone/assets/heavy-fields-ByzRCqe0.js.br +0 -0
  73. package/dist/standalone/assets/heavy-fields-ByzRCqe0.js.gz +0 -0
  74. package/dist/standalone/assets/{heavy-fields-BiCEgD2L.js.map → heavy-fields-ByzRCqe0.js.map} +1 -1
  75. package/dist/standalone/assets/home-page-B3WVGerG.js +3 -0
  76. package/dist/standalone/assets/home-page-B3WVGerG.js.br +0 -0
  77. package/dist/standalone/assets/home-page-B3WVGerG.js.gz +0 -0
  78. package/dist/standalone/assets/home-page-B3WVGerG.js.map +1 -0
  79. package/dist/standalone/assets/hooks-DHDUQgzs.js +186 -0
  80. package/dist/standalone/assets/hooks-DHDUQgzs.js.br +0 -0
  81. package/dist/standalone/assets/hooks-DHDUQgzs.js.gz +0 -0
  82. package/dist/standalone/assets/hooks-DHDUQgzs.js.map +1 -0
  83. package/dist/standalone/assets/icon-registry-O7MDzgTi.js +2 -0
  84. package/dist/standalone/assets/icon-registry-O7MDzgTi.js.br +0 -0
  85. package/dist/standalone/assets/icon-registry-O7MDzgTi.js.gz +0 -0
  86. package/dist/standalone/assets/icon-registry-O7MDzgTi.js.map +1 -0
  87. package/dist/standalone/assets/index-BvESJd1R.js +15 -0
  88. package/dist/standalone/assets/index-BvESJd1R.js.br +0 -0
  89. package/dist/standalone/assets/index-BvESJd1R.js.gz +0 -0
  90. package/dist/standalone/assets/index-BvESJd1R.js.map +1 -0
  91. package/dist/standalone/assets/index-DSYyF4Ah.css +2 -0
  92. package/dist/standalone/assets/index-DSYyF4Ah.css.br +0 -0
  93. package/dist/standalone/assets/index-DSYyF4Ah.css.gz +0 -0
  94. package/dist/standalone/assets/json-editor-DJ-yNmlx.js +2 -0
  95. package/dist/standalone/assets/json-editor-DJ-yNmlx.js.br +0 -0
  96. package/dist/standalone/assets/json-editor-DJ-yNmlx.js.gz +0 -0
  97. package/dist/standalone/assets/json-editor-DJ-yNmlx.js.map +1 -0
  98. package/dist/standalone/assets/property-renderer-DeykD9hp.js +7 -0
  99. package/dist/standalone/assets/property-renderer-DeykD9hp.js.br +0 -0
  100. package/dist/standalone/assets/property-renderer-DeykD9hp.js.gz +0 -0
  101. package/dist/standalone/assets/property-renderer-DeykD9hp.js.map +1 -0
  102. package/dist/standalone/assets/reference-BDP1QYCg.js +2 -0
  103. package/dist/standalone/assets/reference-BDP1QYCg.js.br +0 -0
  104. package/dist/standalone/assets/reference-BDP1QYCg.js.gz +0 -0
  105. package/dist/standalone/assets/reference-BDP1QYCg.js.map +1 -0
  106. package/dist/standalone/assets/revisions-button-CI74_D14.js +2 -0
  107. package/dist/standalone/assets/revisions-button-CI74_D14.js.br +0 -0
  108. package/dist/standalone/assets/revisions-button-CI74_D14.js.gz +0 -0
  109. package/dist/standalone/assets/{revisions-button-0WtL6bsZ.js.map → revisions-button-CI74_D14.js.map} +1 -1
  110. package/dist/standalone/assets/{richtext-render-DnVcQ34I.js → richtext-render-BHGG3eKV.js} +3 -3
  111. package/dist/standalone/assets/richtext-render-BHGG3eKV.js.br +0 -0
  112. package/dist/standalone/assets/richtext-render-BHGG3eKV.js.gz +0 -0
  113. package/dist/standalone/assets/{richtext-render-DnVcQ34I.js.map → richtext-render-BHGG3eKV.js.map} +1 -1
  114. package/dist/standalone/assets/select-BR1RMqsn.js +2 -0
  115. package/dist/standalone/assets/select-BR1RMqsn.js.br +0 -0
  116. package/dist/standalone/assets/select-BR1RMqsn.js.gz +0 -0
  117. package/dist/standalone/assets/select-BR1RMqsn.js.map +1 -0
  118. package/dist/standalone/assets/settings-page-CdIWVeh0.js +2 -0
  119. package/dist/standalone/assets/settings-page-CdIWVeh0.js.br +0 -0
  120. package/dist/standalone/assets/settings-page-CdIWVeh0.js.gz +0 -0
  121. package/dist/standalone/assets/{settings-page-DtguXLAP.js.map → settings-page-CdIWVeh0.js.map} +1 -1
  122. package/dist/standalone/assets/show-page-Dgw-9Pmn.js +2 -0
  123. package/dist/standalone/assets/show-page-Dgw-9Pmn.js.br +0 -0
  124. package/dist/standalone/assets/show-page-Dgw-9Pmn.js.gz +0 -0
  125. package/dist/standalone/assets/{show-page-Dnox2NwO.js.map → show-page-Dgw-9Pmn.js.map} +1 -1
  126. package/dist/standalone/assets/table-DzBSPeVH.js +2 -0
  127. package/dist/standalone/assets/table-DzBSPeVH.js.br +0 -0
  128. package/dist/standalone/assets/table-DzBSPeVH.js.gz +0 -0
  129. package/dist/standalone/assets/table-DzBSPeVH.js.map +1 -0
  130. package/dist/standalone/assets/tabs-Dr7UA219.js +2 -0
  131. package/dist/standalone/assets/tabs-Dr7UA219.js.br +0 -0
  132. package/dist/standalone/assets/tabs-Dr7UA219.js.gz +0 -0
  133. package/dist/standalone/assets/{tabs-DUS8e6dR.js.map → tabs-Dr7UA219.js.map} +1 -1
  134. package/dist/standalone/assets/textarea-T25SXcrC.js +2 -0
  135. package/dist/standalone/assets/{textarea-CX_0QVSz.js.map → textarea-T25SXcrC.js.map} +1 -1
  136. package/dist/standalone/assets/use-dashboard-charts-aymvhXUB.js +2 -0
  137. package/dist/standalone/assets/use-dashboard-charts-aymvhXUB.js.br +0 -0
  138. package/dist/standalone/assets/use-dashboard-charts-aymvhXUB.js.gz +0 -0
  139. package/dist/standalone/assets/{use-dashboard-charts-Cr3OUSL5.js.map → use-dashboard-charts-aymvhXUB.js.map} +1 -1
  140. package/dist/standalone/assets/useQueries-Dch5Ggjr.js +2 -0
  141. package/dist/standalone/assets/useQueries-Dch5Ggjr.js.br +0 -0
  142. package/dist/standalone/assets/useQueries-Dch5Ggjr.js.gz +0 -0
  143. package/dist/standalone/assets/useQueries-Dch5Ggjr.js.map +1 -0
  144. package/dist/standalone/assets/{user-directory-9COoW6AO.js → user-directory-C33bGZdb.js} +3 -3
  145. package/dist/standalone/assets/user-directory-C33bGZdb.js.br +0 -0
  146. package/dist/standalone/assets/user-directory-C33bGZdb.js.gz +0 -0
  147. package/dist/standalone/assets/{user-directory-9COoW6AO.js.map → user-directory-C33bGZdb.js.map} +1 -1
  148. package/dist/standalone/assets/{value-format-Cgau0meh.js → value-format-CLzWct9Y.js} +3 -3
  149. package/dist/standalone/assets/value-format-CLzWct9Y.js.br +0 -0
  150. package/dist/standalone/assets/value-format-CLzWct9Y.js.gz +0 -0
  151. package/dist/standalone/assets/{value-format-Cgau0meh.js.map → value-format-CLzWct9Y.js.map} +1 -1
  152. package/dist/standalone/assets/wizard-create-page-BtfveXmP.js +2 -0
  153. package/dist/standalone/assets/wizard-create-page-BtfveXmP.js.br +0 -0
  154. package/dist/standalone/assets/wizard-create-page-BtfveXmP.js.gz +0 -0
  155. package/dist/standalone/assets/{wizard-create-page-v2-Aw8Oj.js.map → wizard-create-page-BtfveXmP.js.map} +1 -1
  156. package/dist/standalone/assets/zod-N7mHo7BX.js +2 -0
  157. package/dist/standalone/assets/zod-N7mHo7BX.js.br +0 -0
  158. package/dist/standalone/assets/zod-N7mHo7BX.js.gz +0 -0
  159. package/dist/standalone/assets/{zod-BrelKLfy.js.map → zod-N7mHo7BX.js.map} +1 -1
  160. package/dist/standalone/index.html +10 -10
  161. package/dist/standalone/index.html.br +0 -0
  162. package/dist/standalone/index.html.gz +0 -0
  163. package/package.json +5 -5
  164. package/dist/standalone/assets/action-component-host-BrEZDHZt.js +0 -2
  165. package/dist/standalone/assets/action-component-host-BrEZDHZt.js.br +0 -0
  166. package/dist/standalone/assets/action-component-host-BrEZDHZt.js.gz +0 -0
  167. package/dist/standalone/assets/action-page-Bx7kzeK7.js +0 -2
  168. package/dist/standalone/assets/action-page-Bx7kzeK7.js.br +0 -0
  169. package/dist/standalone/assets/action-page-Bx7kzeK7.js.gz +0 -0
  170. package/dist/standalone/assets/ai-assistant-widget-BbIXVrSu.js +0 -2
  171. package/dist/standalone/assets/ai-assistant-widget-BbIXVrSu.js.br +0 -0
  172. package/dist/standalone/assets/ai-assistant-widget-BbIXVrSu.js.gz +0 -0
  173. package/dist/standalone/assets/audit-log-page-BoZh23oQ.js +0 -2
  174. package/dist/standalone/assets/audit-log-page-BoZh23oQ.js.br +0 -0
  175. package/dist/standalone/assets/audit-log-page-BoZh23oQ.js.gz +0 -0
  176. package/dist/standalone/assets/badge-6nyM5Jft.js +0 -2
  177. package/dist/standalone/assets/calendar-nvD_z7KQ.js +0 -2
  178. package/dist/standalone/assets/calendar-nvD_z7KQ.js.br +0 -0
  179. package/dist/standalone/assets/calendar-nvD_z7KQ.js.gz +0 -0
  180. package/dist/standalone/assets/card-4cS4uWCP.js +0 -2
  181. package/dist/standalone/assets/card-4cS4uWCP.js.br +0 -0
  182. package/dist/standalone/assets/card-4cS4uWCP.js.gz +0 -0
  183. package/dist/standalone/assets/chart-widget-YeCL7jdB.js +0 -2
  184. package/dist/standalone/assets/chart-widget-YeCL7jdB.js.br +0 -0
  185. package/dist/standalone/assets/chart-widget-YeCL7jdB.js.gz +0 -0
  186. package/dist/standalone/assets/chart-widget-YeCL7jdB.js.map +0 -1
  187. package/dist/standalone/assets/command-Sb0xL-se.js +0 -2
  188. package/dist/standalone/assets/command-Sb0xL-se.js.br +0 -0
  189. package/dist/standalone/assets/command-Sb0xL-se.js.gz +0 -0
  190. package/dist/standalone/assets/command-Sb0xL-se.js.map +0 -1
  191. package/dist/standalone/assets/date-picker-C4HcgidQ.js +0 -2
  192. package/dist/standalone/assets/date-picker-C4HcgidQ.js.br +0 -0
  193. package/dist/standalone/assets/date-picker-C4HcgidQ.js.gz +0 -0
  194. package/dist/standalone/assets/dist-BSbFjTlr.js +0 -2
  195. package/dist/standalone/assets/dist-BSbFjTlr.js.br +0 -0
  196. package/dist/standalone/assets/dist-BSbFjTlr.js.gz +0 -0
  197. package/dist/standalone/assets/dist-BcL2U6dT.js +0 -2
  198. package/dist/standalone/assets/dist-BcL2U6dT.js.br +0 -0
  199. package/dist/standalone/assets/dist-BcL2U6dT.js.gz +0 -0
  200. package/dist/standalone/assets/dist-Dpg8xy_r.js +0 -2
  201. package/dist/standalone/assets/dist-Dpg8xy_r.js.br +0 -0
  202. package/dist/standalone/assets/dist-Dpg8xy_r.js.gz +0 -0
  203. package/dist/standalone/assets/edit-page-CW7-FAPC.js +0 -2
  204. package/dist/standalone/assets/edit-page-CW7-FAPC.js.br +0 -0
  205. package/dist/standalone/assets/edit-page-CW7-FAPC.js.gz +0 -0
  206. package/dist/standalone/assets/empty-Cposcczv.js +0 -2
  207. package/dist/standalone/assets/empty-Cposcczv.js.br +0 -0
  208. package/dist/standalone/assets/empty-Cposcczv.js.gz +0 -0
  209. package/dist/standalone/assets/global-search-dialog-DLv_nIvM.js +0 -2
  210. package/dist/standalone/assets/global-search-dialog-DLv_nIvM.js.br +0 -0
  211. package/dist/standalone/assets/global-search-dialog-DLv_nIvM.js.gz +0 -0
  212. package/dist/standalone/assets/heavy-fields-BiCEgD2L.js +0 -181
  213. package/dist/standalone/assets/heavy-fields-BiCEgD2L.js.br +0 -0
  214. package/dist/standalone/assets/heavy-fields-BiCEgD2L.js.gz +0 -0
  215. package/dist/standalone/assets/home-page-BSz1wGk0.js +0 -3
  216. package/dist/standalone/assets/home-page-BSz1wGk0.js.br +0 -0
  217. package/dist/standalone/assets/home-page-BSz1wGk0.js.gz +0 -0
  218. package/dist/standalone/assets/home-page-BSz1wGk0.js.map +0 -1
  219. package/dist/standalone/assets/icon-registry-BQU4fIc4.js +0 -2
  220. package/dist/standalone/assets/icon-registry-BQU4fIc4.js.br +0 -0
  221. package/dist/standalone/assets/icon-registry-BQU4fIc4.js.gz +0 -0
  222. package/dist/standalone/assets/icon-registry-BQU4fIc4.js.map +0 -1
  223. package/dist/standalone/assets/index-95cwJ2RY.css +0 -2
  224. package/dist/standalone/assets/index-95cwJ2RY.css.br +0 -0
  225. package/dist/standalone/assets/index-95cwJ2RY.css.gz +0 -0
  226. package/dist/standalone/assets/index-BL8keDxQ.js +0 -15
  227. package/dist/standalone/assets/index-BL8keDxQ.js.br +0 -0
  228. package/dist/standalone/assets/index-BL8keDxQ.js.gz +0 -0
  229. package/dist/standalone/assets/index-BL8keDxQ.js.map +0 -1
  230. package/dist/standalone/assets/json-editor-CAIgxYb3.js +0 -2
  231. package/dist/standalone/assets/json-editor-CAIgxYb3.js.br +0 -0
  232. package/dist/standalone/assets/json-editor-CAIgxYb3.js.gz +0 -0
  233. package/dist/standalone/assets/json-editor-CAIgxYb3.js.map +0 -1
  234. package/dist/standalone/assets/property-renderer-B8Md-EqW.js +0 -7
  235. package/dist/standalone/assets/property-renderer-B8Md-EqW.js.br +0 -0
  236. package/dist/standalone/assets/property-renderer-B8Md-EqW.js.gz +0 -0
  237. package/dist/standalone/assets/property-renderer-B8Md-EqW.js.map +0 -1
  238. package/dist/standalone/assets/reference-WPaf6IdD.js +0 -2
  239. package/dist/standalone/assets/reference-WPaf6IdD.js.br +0 -0
  240. package/dist/standalone/assets/reference-WPaf6IdD.js.gz +0 -0
  241. package/dist/standalone/assets/reference-WPaf6IdD.js.map +0 -1
  242. package/dist/standalone/assets/revisions-button-0WtL6bsZ.js +0 -2
  243. package/dist/standalone/assets/revisions-button-0WtL6bsZ.js.br +0 -0
  244. package/dist/standalone/assets/revisions-button-0WtL6bsZ.js.gz +0 -0
  245. package/dist/standalone/assets/richtext-render-DnVcQ34I.js.br +0 -0
  246. package/dist/standalone/assets/richtext-render-DnVcQ34I.js.gz +0 -0
  247. package/dist/standalone/assets/router-wFvtgo77.js +0 -186
  248. package/dist/standalone/assets/router-wFvtgo77.js.br +0 -0
  249. package/dist/standalone/assets/router-wFvtgo77.js.gz +0 -0
  250. package/dist/standalone/assets/router-wFvtgo77.js.map +0 -1
  251. package/dist/standalone/assets/select-CR4acjX0.js +0 -2
  252. package/dist/standalone/assets/select-CR4acjX0.js.br +0 -0
  253. package/dist/standalone/assets/select-CR4acjX0.js.gz +0 -0
  254. package/dist/standalone/assets/select-CR4acjX0.js.map +0 -1
  255. package/dist/standalone/assets/settings-page-DtguXLAP.js +0 -2
  256. package/dist/standalone/assets/settings-page-DtguXLAP.js.br +0 -0
  257. package/dist/standalone/assets/settings-page-DtguXLAP.js.gz +0 -0
  258. package/dist/standalone/assets/show-page-Dnox2NwO.js +0 -2
  259. package/dist/standalone/assets/show-page-Dnox2NwO.js.br +0 -0
  260. package/dist/standalone/assets/show-page-Dnox2NwO.js.gz +0 -0
  261. package/dist/standalone/assets/tabs-DUS8e6dR.js +0 -2
  262. package/dist/standalone/assets/tabs-DUS8e6dR.js.br +0 -0
  263. package/dist/standalone/assets/tabs-DUS8e6dR.js.gz +0 -0
  264. package/dist/standalone/assets/textarea-CX_0QVSz.js +0 -2
  265. package/dist/standalone/assets/use-dashboard-charts-Cr3OUSL5.js +0 -2
  266. package/dist/standalone/assets/use-dashboard-charts-Cr3OUSL5.js.br +0 -0
  267. package/dist/standalone/assets/use-dashboard-charts-Cr3OUSL5.js.gz +0 -0
  268. package/dist/standalone/assets/useQueries-BCUhWYX4.js +0 -2
  269. package/dist/standalone/assets/useQueries-BCUhWYX4.js.br +0 -0
  270. package/dist/standalone/assets/useQueries-BCUhWYX4.js.gz +0 -0
  271. package/dist/standalone/assets/useQueries-BCUhWYX4.js.map +0 -1
  272. package/dist/standalone/assets/user-directory-9COoW6AO.js.br +0 -0
  273. package/dist/standalone/assets/user-directory-9COoW6AO.js.gz +0 -0
  274. package/dist/standalone/assets/value-format-Cgau0meh.js.br +0 -0
  275. package/dist/standalone/assets/value-format-Cgau0meh.js.gz +0 -0
  276. package/dist/standalone/assets/with-selector-NDLhu4dT.js +0 -2
  277. package/dist/standalone/assets/with-selector-NDLhu4dT.js.br +0 -0
  278. package/dist/standalone/assets/with-selector-NDLhu4dT.js.gz +0 -0
  279. package/dist/standalone/assets/with-selector-NDLhu4dT.js.map +0 -1
  280. package/dist/standalone/assets/wizard-create-page-v2-Aw8Oj.js +0 -2
  281. package/dist/standalone/assets/wizard-create-page-v2-Aw8Oj.js.br +0 -0
  282. package/dist/standalone/assets/wizard-create-page-v2-Aw8Oj.js.gz +0 -0
  283. package/dist/standalone/assets/zod-BrelKLfy.js +0 -2
  284. package/dist/standalone/assets/zod-BrelKLfy.js.br +0 -0
  285. package/dist/standalone/assets/zod-BrelKLfy.js.gz +0 -0
@@ -0,0 +1,3 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./chart-widget-R2NG5T1y.js","./createLucideIcon-CUopU_LC.js","./floating-layer-DJGCYMex.js","./refresh-cw-DHvUQTMb.js","./trash-2-DhyKQCKv.js","./minimize-2-Bx2cH_WS.js","./copy-BexCWf4U.js","./ellipsis-lEjcTxo0.js","./pencil-BO-k3yTG.js","./palette-DVP_4RAn.js","./triangle-alert-CyaaNWN8.js","./dist-CmyV2PEd.js","./select-BR1RMqsn.js","./dist-DI9XNddW.js","./hooks-DHDUQgzs.js","./index-BvESJd1R.js","./x-C3kLunD6.js","./dist-jC1pK2zN.js","./index-DSYyF4Ah.css","./date-picker-DQ4XOgO6.js","./calendar-DDv0Qalf.js","./calendar-Chw94eNX.css","./useQueries-Dch5Ggjr.js","./card-MNH_XK0V.js","./value-format-CLzWct9Y.js","./pipette-CqHYfQnn.js","./use-dashboard-charts-aymvhXUB.js","./uuid-DLSnbsz2.js","./schemas-twnCb1uT.js","./reference-BDP1QYCg.js","./chevrons-up-down-BHCs46XQ.js","./badge-8oeWEs3P.js","./command-Cw-hTtpk.js"])))=>i.map(i=>d[i]);
2
+ import{a as e,n as t}from"./createLucideIcon-CUopU_LC.js";import{w as n}from"./floating-layer-DJGCYMex.js";import{a as r,i,n as a,o,r as s}from"./pipette-CqHYfQnn.js";import{t as c}from"./trash-2-DhyKQCKv.js";import{t as l}from"./pencil-BO-k3yTG.js";import{t as u}from"./plus-Dk-FzitW.js";import{t as d}from"./x-C3kLunD6.js";import{s as f}from"./dist-CmyV2PEd.js";import{a as p,i as m,n as h,o as g,t as _}from"./select-BR1RMqsn.js";import{a as v,c as y,i as b,o as x,r as S,s as C,t as w}from"./empty-DcETRWsu.js";import{E as ee,I as te,N as T,c as E}from"./hooks-DHDUQgzs.js";import{a as D,i as O,n as k,t as A}from"./card-MNH_XK0V.js";import{i as ne,n as j,r as re,t as ie}from"./tabs-Dr7UA219.js";import{a as M,o as ae,r as oe,t as se}from"./value-format-CLzWct9Y.js";import{t as ce}from"./uuid-DLSnbsz2.js";import{a as le,i as N,t as ue}from"./use-dashboard-charts-aymvhXUB.js";import{t as P}from"./reference-BDP1QYCg.js";import{B as F,G as I,St as de,U as L,V as R,W as z,Y as B,et as V,i as fe,nt as H,r as pe,t as U}from"./index-BvESJd1R.js";var W=e(t(),1),G=n(),me=[{value:`kpi`,icon:(0,G.jsx)(o,{className:`size-4`}),labelKey:`dashboard:visKpi`},{value:`line`,icon:(0,G.jsx)(i,{className:`size-4`}),labelKey:`dashboard:visLine`},{value:`area`,icon:(0,G.jsx)(r,{className:`size-4`}),labelKey:`dashboard:visArea`},{value:`bar`,icon:(0,G.jsx)(s,{className:`size-4`}),labelKey:`dashboard:visBar`}],K=`__none__`,he=[`count`,`sum`,`avg`,`min`,`max`],ge=[`divide`,`multiply`,`add`,`subtract`],_e=[`number`,`currency`,`percent`],ve=[`7d`,`30d`,`90d`,`1y`,`all`];function ye(e){if(e.type===`date`||e.type===`datetime`)return!0;let t=e.path.toLowerCase();return t.endsWith(`at`)||t.endsWith(`_at`)||t.endsWith(`date`)}function be(e){if(ye(e))return!1;if(e.type===`reference`&&!e.isArray){let t=e.path;return t.endsWith(`Id`)||t.endsWith(`_id`)}return!(e.type===`json`||e.type===`mixed`||e.type===`richtext`||e.type===`markdown`||e.type===`textarea`||e.type===`previewMedia`||e.type===`file`)}function q({initial:e,onSave:t,onClose:n}){let{t:r,locale:i}=T(),a=ee(),[o,s]=W.useState(e?.title??``),[c,l]=W.useState(e?.visualisation??`area`),[v,b]=W.useState(e?.resource??a[0]?.id??``),[x,S]=W.useState(e?.dateField??``),[w,te]=W.useState(e?.metric??`count`),[E,D]=W.useState(e?.field??``),[O,k]=W.useState(e?.groupBy??``),[A,N]=W.useState(e?.groupByLabelResource??``),[ue,P]=W.useState(e?.topN??10),[de,B]=W.useState(e&&e.timeRange.preset!==`custom`?e.timeRange.preset:`30d`),[fe,pe]=W.useState(e?.filters??{}),[U,q]=W.useState(e?.quickFilters??[]),[Te,Ee]=W.useState(e?.order??0),[De,Oe]=W.useState(e?.comparePrevious??!1),[J,Y]=W.useState(()=>e?.transform?.map(e=>({...e}))??[]),[X,ke]=W.useState(e?.format?.style??`number`),[Ae,je]=W.useState(e?.format?.currency??``),[Me,Ne]=W.useState(e?.format?.decimals==null?``:String(e.format.decimals)),[Pe,Fe]=W.useState(e?.format?.compact??!1),[Ie,Le]=W.useState(e?.format?.prefix??``),[Re,ze]=W.useState(e?.format?.suffix??``),[Be,Ve]=W.useState(e?.series?.__total__?.color),[Z,He]=W.useState({}),[Ue,We]=W.useState(`data`),Ge=a.find(e=>e.id===v),Q=Ge?.properties??[],Ke=Q.filter(ye),qe=Q.filter(e=>e.type===`number`||e.type===`float`||e.type===`currency`);W.useEffect(()=>{e?.resource!==v&&(S(Ke[0]?.path??``),D(``),k(``),N(``),pe({}),q([]))},[v]),W.useEffect(()=>{A||!O||Q.length===0||N(we(O,Q))},[O,Q]);let $=c===`kpi`,Je=()=>({preset:de}),Ye=()=>{let e=Me===``?void 0:Math.max(0,Math.min(6,Math.trunc(Number(Me)))),t={style:X,...X===`currency`&&Ae.trim().length===3?{currency:Ae.trim().toUpperCase()}:{},...e!=null&&Number.isFinite(e)?{decimals:e}:{},...Ie?{prefix:Ie.slice(0,8)}:{},...Re?{suffix:Re.slice(0,8)}:{},...Pe?{compact:!0}:{}};return t.style===`number`&&Object.keys(t).length===1?void 0:t},Xe=()=>{let t={...e?.series};return!$&&!O&&(Be?t.__total__={color:Be}:delete t.__total__),Object.keys(t).length?t:void 0},Ze=W.useMemo(()=>oe(Ye(),i),[X,Ae,Me,Pe,Ie,Re,i]),Qe=1234,$e=`${Qe} → ${Ze(se(Qe,J))}`,et=(e,t)=>{pe(n=>{let r={...n};return t===``?delete r[e]:r[e]=t,r})},tt=e=>{q(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])};return(0,G.jsx)(F,{open:!0,onOpenChange:e=>{e||n()},children:(0,G.jsxs)(R,{className:`w-full max-w-2xl max-h-[90vh] overflow-y-auto`,children:[(0,G.jsx)(z,{children:(0,G.jsx)(I,{children:r(e?`chart:editChart`:`chart:newChart`)})}),(0,G.jsxs)(ie,{value:Ue,onValueChange:e=>We(e),className:`py-1`,children:[(0,G.jsxs)(re,{children:[(0,G.jsx)(ne,{value:`data`,children:r(`dashboard:builder.tabData`)}),(0,G.jsx)(ne,{value:`display`,children:r(`dashboard:builder.tabDisplay`)}),(0,G.jsx)(ne,{value:`filters`,children:r(`dashboard:builder.tabFilters`)})]}),(0,G.jsxs)(j,{value:`data`,className:`space-y-4`,children:[(0,G.jsxs)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-[1fr_8rem]`,children:[(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-title`,children:r(`chart:title`)}),(0,G.jsx)(H,{id:`chart-title`,placeholder:r(`chart:titlePlaceholder`),value:o,onChange:e=>s(e.target.value)})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-order`,children:r(`chart:order`)}),(0,G.jsx)(C,{content:r(`chart:orderHint`)})]}),(0,G.jsx)(H,{id:`chart-order`,type:`number`,step:1,value:Te,onChange:e=>Ee(Number.isFinite(Number(e.target.value))?Math.trunc(Number(e.target.value)):0)})]})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{children:r(`dashboard:vis`)}),(0,G.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:me.map(({value:e,icon:t,labelKey:n})=>(0,G.jsxs)(f,{type:`button`,variant:c===e?`default`:`outline`,size:`sm`,className:`flex-1 min-w-[5rem] gap-1.5 capitalize`,onClick:()=>l(e),children:[t,(0,G.jsx)(`span`,{className:`hidden sm:inline`,children:r(n)})]},e))})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-resource`,children:r(`chart:resource`)}),(0,G.jsxs)(_,{value:v,onValueChange:e=>b(e),children:[(0,G.jsx)(p,{id:`chart-resource`,children:(0,G.jsx)(g,{})}),(0,G.jsx)(h,{children:a.map(e=>(0,G.jsxs)(m,{value:e.id,children:[e.name,e.name!==e.id&&(0,G.jsxs)(`span`,{className:`ml-1.5 text-xs text-muted-foreground`,children:[`(`,e.id,`)`]})]},e.id))})]}),Z.resource&&(0,G.jsx)(`p`,{className:`text-xs text-destructive`,children:Z.resource})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-datefield`,children:r(`dashboard:builder.dateField`)}),(0,G.jsxs)(_,{value:x||K,onValueChange:e=>S(e===K?``:e),children:[(0,G.jsx)(p,{id:`chart-datefield`,children:(0,G.jsx)(g,{placeholder:r(`chart:selectField`)})}),(0,G.jsxs)(h,{children:[(0,G.jsx)(m,{value:K,children:r(`chart:selectField`)}),(Ke.length>0?Ke:Q).map(e=>(0,G.jsx)(m,{value:e.path,children:e.label},e.path))]})]}),(0,G.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:r(`dashboard:builder.dateFieldHint`)}),Z.dateField&&(0,G.jsx)(`p`,{className:`text-xs text-destructive`,children:Z.dateField})]}),(0,G.jsxs)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2`,children:[(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-metric`,children:r(`chart:metric`)}),(0,G.jsxs)(_,{value:w,onValueChange:e=>te(e),children:[(0,G.jsx)(p,{id:`chart-metric`,children:(0,G.jsx)(g,{})}),(0,G.jsx)(h,{children:he.map(e=>(0,G.jsx)(m,{value:e,children:r(`dashboard:metric${xe(e)}`)},e))})]})]}),w!==`count`&&(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-field`,children:r(`chart:aggregateField`)}),(0,G.jsxs)(_,{value:E||K,onValueChange:e=>D(e===K?``:e),children:[(0,G.jsx)(p,{id:`chart-field`,children:(0,G.jsx)(g,{placeholder:r(`chart:selectField`)})}),(0,G.jsxs)(h,{children:[(0,G.jsx)(m,{value:K,children:r(`chart:selectField`)}),qe.map(e=>(0,G.jsx)(m,{value:e.path,children:e.label},e.path))]})]}),Z.field&&(0,G.jsx)(`p`,{className:`text-xs text-destructive`,children:Z.field})]})]}),!$&&(0,G.jsxs)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2`,children:[(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-groupby`,children:r(`dashboard:builder.secondaryGroupBy`)}),(0,G.jsxs)(_,{value:O||K,onValueChange:e=>{let t=e===K?``:e;k(t),N(we(t,Q))},children:[(0,G.jsx)(p,{id:`chart-groupby`,children:(0,G.jsx)(g,{})}),(0,G.jsxs)(h,{children:[(0,G.jsx)(m,{value:K,children:r(`dashboard:builder.noBreakdown`)}),Q.filter(e=>be(e)&&e.path!==x).map(e=>(0,G.jsx)(m,{value:e.path,children:e.label},e.path))]})]})]}),O&&(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-topn`,children:r(`dashboard:builder.topN`)}),(0,G.jsx)(H,{id:`chart-topn`,type:`number`,min:1,max:50,value:ue,onChange:e=>P(Math.max(1,Math.min(50,Number(e.target.value)||10)))})]})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{children:r(`dashboard:builder.range`)}),(0,G.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:ve.map(e=>(0,G.jsx)(f,{type:`button`,variant:de===e?`default`:`outline`,size:`sm`,className:`flex-1 min-w-[4rem]`,onClick:()=>B(e),children:r(`dashboard:range.${e}`)},e))})]})]}),(0,G.jsxs)(j,{value:`display`,className:`space-y-4`,children:[!$&&(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,G.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,G.jsx)(V,{htmlFor:`chart-compare`,children:r(`dashboard:builder.comparePrevious`)}),(0,G.jsx)(C,{content:r(`dashboard:builder.comparePreviousHint`)})]}),(0,G.jsx)(y,{id:`chart-compare`,checked:!O&&De,disabled:!!O,onCheckedChange:Oe,"aria-label":r(`dashboard:builder.comparePrevious`)})]}),!!O&&(0,G.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:r(`dashboard:builder.comparePreviousDisabled`)})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,G.jsx)(V,{children:r(`dashboard:builder.transform`)}),(0,G.jsx)(C,{content:r(`dashboard:builder.transformHint`)})]}),J.map((e,t)=>(0,G.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,G.jsxs)(_,{value:e.op,onValueChange:e=>Y(n=>n.map((n,r)=>r===t?{...n,op:e}:n)),children:[(0,G.jsx)(p,{className:`w-40`,"aria-label":r(`dashboard:builder.transform`),children:(0,G.jsx)(g,{})}),(0,G.jsx)(h,{children:ge.map(e=>(0,G.jsx)(m,{value:e,children:r(`dashboard:builder.op${xe(e)}`)},e))})]}),(0,G.jsx)(H,{type:`number`,className:`w-28`,value:Number.isFinite(e.value)?e.value:``,onChange:e=>Y(n=>n.map((n,r)=>r===t?{...n,value:Number(e.target.value)}:n))}),(0,G.jsx)(f,{type:`button`,variant:`ghost`,size:`icon`,className:`size-8`,onClick:()=>Y(e=>e.filter((e,n)=>n!==t)),"aria-label":r(`dashboard:builder.transformRemove`),children:(0,G.jsx)(d,{className:`size-4`})})]},t)),J.length<8&&(0,G.jsxs)(f,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>Y(e=>[...e,{op:`divide`,value:100}]),children:[(0,G.jsx)(u,{className:`size-4 mr-1`}),r(`dashboard:builder.transformAdd`)]})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{children:r(`dashboard:builder.format`)}),(0,G.jsxs)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2`,children:[(0,G.jsxs)(`div`,{className:`space-y-1`,children:[(0,G.jsx)(V,{htmlFor:`chart-format-style`,className:`text-xs text-muted-foreground`,children:r(`dashboard:builder.formatStyle`)}),(0,G.jsxs)(_,{value:X,onValueChange:e=>ke(e),children:[(0,G.jsx)(p,{id:`chart-format-style`,children:(0,G.jsx)(g,{})}),(0,G.jsx)(h,{children:_e.map(e=>(0,G.jsx)(m,{value:e,children:r(`dashboard:builder.format${xe(e)}`)},e))})]})]}),X===`currency`&&(0,G.jsxs)(`div`,{className:`space-y-1`,children:[(0,G.jsx)(V,{htmlFor:`chart-format-currency`,className:`text-xs text-muted-foreground`,children:r(`dashboard:builder.formatCurrencyCode`)}),(0,G.jsx)(H,{id:`chart-format-currency`,placeholder:`USD`,maxLength:3,value:Ae,onChange:e=>je(e.target.value.toUpperCase())})]}),(0,G.jsxs)(`div`,{className:`space-y-1`,children:[(0,G.jsx)(V,{htmlFor:`chart-format-decimals`,className:`text-xs text-muted-foreground`,children:r(`dashboard:builder.formatDecimals`)}),(0,G.jsx)(H,{id:`chart-format-decimals`,type:`number`,min:0,max:6,value:Me,onChange:e=>Ne(e.target.value)})]}),(0,G.jsxs)(`div`,{className:`space-y-1`,children:[(0,G.jsxs)(V,{htmlFor:`chart-format-prefix`,className:`text-xs text-muted-foreground`,children:[r(`dashboard:builder.formatPrefix`),` / `,r(`dashboard:builder.formatSuffix`)]}),(0,G.jsxs)(`div`,{className:`flex gap-2`,children:[(0,G.jsx)(H,{id:`chart-format-prefix`,maxLength:8,placeholder:r(`dashboard:builder.formatPrefix`),value:Ie,onChange:e=>Le(e.target.value)}),(0,G.jsx)(H,{maxLength:8,placeholder:r(`dashboard:builder.formatSuffix`),value:Re,onChange:e=>ze(e.target.value),"aria-label":r(`dashboard:builder.formatSuffix`)})]})]}),(0,G.jsxs)(`div`,{className:`flex items-center justify-between gap-2 sm:col-span-2`,children:[(0,G.jsx)(V,{htmlFor:`chart-format-compact`,children:r(`dashboard:builder.formatCompact`)}),(0,G.jsx)(y,{id:`chart-format-compact`,checked:Pe,onCheckedChange:Fe})]})]}),(0,G.jsx)(`p`,{className:`text-xs text-muted-foreground tabular-nums`,children:$e})]}),!$&&!O&&(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{children:r(`dashboard:builder.color`)}),(0,G.jsx)(M,{value:Be,onChange:Ve,presets:ae,labels:{custom:r(`dashboard:widget.colorCustom`),pick:r(`dashboard:widget.colorPick`),auto:r(`dashboard:widget.colorAuto`)}})]})]}),(0,G.jsx)(j,{value:`filters`,className:`space-y-4`,children:Q.length>0?(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{children:r(`dashboard:builder.filters`)}),(0,G.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:r(`dashboard:builder.filtersHint`)}),(0,G.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-3`,children:Q.filter(Se).map(e=>{let t=U.includes(e.path);return(0,G.jsxs)(`div`,{className:`space-y-1`,children:[(0,G.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,G.jsx)(V,{htmlFor:`flt-${e.path}`,className:`text-xs text-muted-foreground`,children:e.label}),(0,G.jsx)(y,{checked:t,onCheckedChange:()=>tt(e.path),"aria-label":r(`dashboard:builder.quickFilterToggle`).replace(`{field}`,e.label),title:r(`dashboard:builder.quickFilterHint`)})]}),(0,G.jsx)(Ce,{property:e,value:fe[e.path]??``,onChange:t=>et(e.path,t)})]},e.path)})})]}):(0,G.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:r(`dashboard:builder.filtersEmpty`)})})]}),(0,G.jsxs)(L,{children:[(0,G.jsx)(f,{variant:`outline`,onClick:n,children:r(`common:cancel`)}),(0,G.jsx)(f,{onClick:()=>{let n=new Date().toISOString(),r=$?`all`:e&&e.step!==`all`?e.step:`day`,i={id:e?.id??ce(),title:o.trim()||Ge?.name||v,resource:v,visualisation:c,dateField:x,step:r,metric:w,width:e?.width??`half`,topN:ue,filters:fe,quickFilters:U.filter(e=>Q.some(t=>t.path===e)),timeRange:Je(),order:Te,...e?.groupId?{groupId:e.groupId}:{},createdAt:e?.createdAt??n,updatedAt:n,...w!==`count`&&E?{field:E}:{},...!$&&O?{groupBy:O}:{},...!$&&O&&A?{groupByLabelResource:A}:{},transform:J,comparePrevious:!$&&!O&&De,...Ye()?{format:Ye()}:{},...Xe()?{series:Xe()}:{}},a=le.safeParse(i);if(!a.success){let e={};for(let t of a.error.issues){let n=t.path[0];typeof n==`string`&&!e[n]&&(e[n]=t.message)}He(e),We(`data`);return}He({}),t(i)},disabled:!v||!x,children:r(`chart:saveChart`)})]})]})})}var xe=e=>e.charAt(0).toUpperCase()+e.slice(1);function Se(e){if(e.isId||e.isArray||e.type===`json`||e.type===`mixed`||e.type===`richtext`||e.type===`markdown`||e.type===`textarea`||e.type===`previewMedia`||e.type===`file`)return!1;if(e.type===`reference`&&!e.isArray){let t=e.path;if(!(t.endsWith(`Id`)||t.endsWith(`_id`)))return!1}return!0}function Ce({property:e,value:t,onChange:n}){if(e.reference)return(0,G.jsx)(P,{referenceResourceId:e.reference,value:t||null,onChange:e=>n(e==null?``:String(e))});if(e.availableValues&&e.availableValues.length>0)return(0,G.jsxs)(_,{value:t||K,onValueChange:e=>n(e===K?``:e),children:[(0,G.jsx)(p,{id:`flt-${e.path}`,children:(0,G.jsx)(g,{})}),(0,G.jsxs)(h,{children:[(0,G.jsx)(m,{value:K,children:`—`}),e.availableValues.map(e=>(0,G.jsx)(m,{value:e.value,children:e.label},e.value))]})]});if(e.type===`boolean`)return(0,G.jsxs)(_,{value:t||K,onValueChange:e=>n(e===K?``:e),children:[(0,G.jsx)(p,{id:`flt-${e.path}`,children:(0,G.jsx)(g,{})}),(0,G.jsxs)(h,{children:[(0,G.jsx)(m,{value:K,children:`—`}),(0,G.jsx)(m,{value:`true`,children:`true`}),(0,G.jsx)(m,{value:`false`,children:`false`})]})]});let r=e.type===`number`||e.type===`float`||e.type===`currency`;return(0,G.jsx)(H,{id:`flt-${e.path}`,type:r?`number`:`text`,value:t,onChange:e=>n(e.target.value)})}function we(e,t){if(!e)return``;let n=t.find(t=>t.path===e);if(!n)return``;if(n.reference)return n.reference;let r=n.path.endsWith(`_id`)?n.path.slice(0,-3):n.path.endsWith(`Id`)?n.path.slice(0,-2):``;if(r){let e=t.find(e=>e.path===r&&e.reference);if(e?.reference)return e.reference}return``}function Te({initial:e,onSave:t,onClose:n}){let{t:r}=T(),[i,a]=W.useState(e?.name??``),[o,s]=W.useState(e?.order??0),[c,l]=W.useState(``);return(0,G.jsx)(F,{open:!0,onOpenChange:e=>{e||n()},children:(0,G.jsxs)(R,{className:`w-full max-w-md`,children:[(0,G.jsx)(z,{children:(0,G.jsx)(I,{children:r(e?`chart:editGroup`:`chart:newGroup`)})}),(0,G.jsxs)(`div`,{className:`space-y-4 py-1`,children:[(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`group-name`,children:r(`chart:groupName`)}),(0,G.jsx)(H,{id:`group-name`,placeholder:r(`chart:groupNamePlaceholder`),value:i,onChange:e=>a(e.target.value),autoFocus:!0}),c&&(0,G.jsx)(`p`,{className:`text-xs text-destructive`,children:c})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,G.jsx)(V,{htmlFor:`group-order`,children:r(`chart:groupOrder`)}),(0,G.jsx)(C,{content:r(`chart:orderHint`)})]}),(0,G.jsx)(H,{id:`group-order`,type:`number`,step:1,value:o,onChange:e=>s(Number.isFinite(Number(e.target.value))?Math.trunc(Number(e.target.value)):0)})]})]}),(0,G.jsxs)(L,{children:[(0,G.jsx)(f,{variant:`outline`,onClick:n,children:r(`common:cancel`)}),(0,G.jsx)(f,{onClick:()=>{let e=i.trim();if(!e){l(r(`chart:groupNameRequired`));return}l(``),t({name:e,order:Number.isFinite(o)?Math.trunc(o):0})},children:r(`chart:saveGroup`)})]})]})})}function Ee({groups:e,initialGroupId:t,initialOrder:n,onSave:r,onClose:i,onCreateGroup:o}){let{t:s}=T(),c=W.useMemo(()=>[...e].sort((e,t)=>e.order-t.order),[e]),l=t??c[0]?.id??``,[u,d]=W.useState(l),[v,y]=W.useState(n??0);return(0,G.jsx)(F,{open:!0,onOpenChange:e=>{e||i()},children:(0,G.jsxs)(R,{className:`w-full max-w-md`,children:[(0,G.jsx)(z,{children:(0,G.jsx)(I,{children:s(`chart:moveChart`)})}),c.length===0?(0,G.jsxs)(`div`,{className:`space-y-3 py-2`,children:[(0,G.jsx)(`p`,{className:`text-sm font-medium`,children:s(`chart:moveNoGroups`)}),(0,G.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:s(`chart:moveNoGroupsHint`)}),(0,G.jsxs)(f,{variant:`outline`,className:`w-full`,onClick:()=>{i(),o()},children:[(0,G.jsx)(a,{className:`size-4 mr-2`}),s(`chart:addGroup`)]})]}):(0,G.jsxs)(`div`,{className:`space-y-4 py-1`,children:[(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsx)(V,{htmlFor:`move-group`,children:s(`chart:moveGroup`)}),(0,G.jsxs)(_,{value:u,onValueChange:d,children:[(0,G.jsx)(p,{id:`move-group`,className:`w-full`,children:(0,G.jsx)(g,{})}),(0,G.jsx)(h,{children:c.map(e=>(0,G.jsx)(m,{value:e.id,children:e.name},e.id))})]})]}),(0,G.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,G.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,G.jsx)(V,{htmlFor:`move-order`,children:s(`chart:order`)}),(0,G.jsx)(C,{content:s(`chart:orderHint`)})]}),(0,G.jsx)(H,{id:`move-order`,type:`number`,step:1,value:v,onChange:e=>y(Number.isFinite(Number(e.target.value))?Math.trunc(Number(e.target.value)):0)})]})]}),(0,G.jsxs)(L,{children:[(0,G.jsx)(f,{variant:`outline`,onClick:i,children:s(`common:cancel`)}),c.length>0&&(0,G.jsx)(f,{onClick:()=>{u&&r({groupId:u,order:Number.isFinite(v)?Math.trunc(v):0})},disabled:!u,children:s(`chart:moveToGroup`)})]})]})})}var De=W.lazy(()=>U(()=>import(`./chart-widget-R2NG5T1y.js`).then(e=>({default:e.ChartWidget})),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]),import.meta.url));function Oe(e){return(0,G.jsx)(W.Suspense,{fallback:(0,G.jsx)(B,{className:`h-[320px] w-full rounded-md`}),children:(0,G.jsx)(De,{...e})})}function J(){let{t:e}=T(),t=ee(),{user:n}=E(),r=te(),i=pe(),o=W.useMemo(()=>new ue(r),[r]),{charts:d,groups:p,addChart:m,updateChart:h,removeChart:g,addGroup:_,updateGroup:y,removeGroup:C}=N({userId:n?.id??null,store:o}),j=W.useMemo(()=>t.filter(e=>e.navigation!==null),[t]),[M,ae]=W.useState(``),oe=W.useMemo(()=>{let e=M.trim().toLocaleLowerCase();return e?j.filter(t=>[t.name,t.id].some(t=>t.toLocaleLowerCase().includes(e))):j},[j,M]),[se,ce]=W.useState(!1),[le,P]=W.useState(null),[F,I]=W.useState(null),[L,R]=W.useState(null),[z,B]=W.useState(null);W.useEffect(()=>{if(p.length===0){R(null);return}(!L||!p.some(e=>e.id===L))&&R(p[0].id)},[p,L]);let V=le?d.find(e=>e.id===le):void 0,U=p[0]?.id??null,me=W.useMemo(()=>p.length===0?[...d].sort(Y):L?d.filter(e=>e.groupId?e.groupId===L:L===U).sort(Y):[],[d,p.length,L,U]),K=L?p.find(e=>e.id===L)??null:null,he=async t=>{await i.confirm({title:e(`chart:deleteChartConfirm`),description:e(`chart:deleteChartConfirmHint`),confirmLabel:e(`common:delete`),destructive:!0})&&g(t.id)},ge=async t=>{let n=d.filter(e=>e.groupId?e.groupId===t.id:t.id===U).length;await i.confirm({title:e(`chart:deleteGroupConfirm`),description:e(`chart:deleteGroupConfirmHint`).replace(`{count}`,String(n)),confirmLabel:e(`common:delete`),destructive:!0})&&C(t.id)};return(0,G.jsxs)(`div`,{className:`space-y-3 sm:space-y-6`,children:[(0,G.jsxs)(A,{children:[(0,G.jsxs)(O,{className:`flex flex-row items-center justify-between p-3 pb-2 space-y-0 gap-2 sm:p-6 sm:pb-2`,children:[(0,G.jsx)(D,{children:e(`chart:dashboard`)}),(0,G.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,G.jsxs)(f,{size:`sm`,variant:`outline`,onClick:()=>I(`new`),children:[(0,G.jsx)(a,{className:`size-4`}),(0,G.jsx)(`span`,{className:`hidden sm:inline ml-1.5`,children:e(`chart:addGroup`)})]}),(0,G.jsxs)(f,{size:`sm`,onClick:()=>ce(!0),disabled:j.length===0,children:[(0,G.jsx)(u,{className:`size-4`}),(0,G.jsx)(`span`,{className:`hidden sm:inline ml-1.5`,children:e(`chart:addChart`)})]})]})]}),(0,G.jsxs)(k,{className:`p-3 pt-0 sm:p-6 sm:pt-0`,children:[p.length>0&&L&&(0,G.jsx)(ie,{value:L,onValueChange:e=>R(e),className:`mb-4`,children:(0,G.jsxs)(`div`,{className:`flex items-end justify-between gap-2`,children:[(0,G.jsx)(re,{className:`flex-1`,children:p.map(e=>(0,G.jsx)(ne,{value:e.id,children:e.name},e.id))}),K&&(0,G.jsxs)(`div`,{className:`mb-1 flex shrink-0 items-center gap-1`,children:[(0,G.jsxs)(f,{size:`sm`,variant:`ghost`,onClick:()=>I(K),"aria-label":e(`chart:editGroup`),children:[(0,G.jsx)(l,{className:`size-3.5`}),(0,G.jsx)(`span`,{className:`hidden sm:inline ml-1.5`,children:e(`chart:editGroup`)})]}),(0,G.jsxs)(f,{size:`sm`,variant:`ghost`,onClick:()=>void ge(K),"aria-label":e(`chart:deleteGroup`),children:[(0,G.jsx)(c,{className:`size-3.5`}),(0,G.jsx)(`span`,{className:`hidden sm:inline ml-1.5`,children:e(`chart:deleteGroup`)})]})]})]})}),me.length===0?(0,G.jsx)(w,{className:`border-0 py-4`,children:(0,G.jsxs)(b,{children:[(0,G.jsx)(v,{children:(0,G.jsx)(s,{})}),(0,G.jsx)(x,{children:e(`chart:noCharts`)}),(0,G.jsx)(S,{children:e(`chart:noChartsHint`)})]})}):(0,G.jsx)(`div`,{className:`grid gap-3 grid-cols-1 sm:gap-4 md:grid-cols-2`,children:me.map(e=>(0,G.jsx)(`div`,{className:e.width===`full`?`md:col-span-2`:void 0,children:(0,G.jsx)(Oe,{config:e,onEdit:()=>P(e.id),onDelete:()=>void he(e),onMove:()=>B(e),onUpdate:t=>h(e.id,t)})},e.id))})]})]}),(0,G.jsxs)(A,{children:[(0,G.jsxs)(O,{className:`flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between`,children:[(0,G.jsx)(D,{children:e(`common:resources`)}),j.length>0&&(0,G.jsx)(`div`,{className:`w-full sm:w-64`,children:(0,G.jsx)(H,{type:`search`,value:M,onChange:e=>ae(e.target.value),placeholder:e(`home:searchResources`),"aria-label":e(`home:searchResources`),onClear:()=>ae(``),clearLabel:e(`common:clear`)})})]}),(0,G.jsx)(k,{children:j.length===0?(0,G.jsx)(w,{className:`border-0`,children:(0,G.jsxs)(b,{children:[(0,G.jsx)(v,{children:(0,G.jsx)(de,{})}),(0,G.jsx)(x,{children:e(`common:noRecords`)}),(0,G.jsx)(S,{children:e(`common:noRecordsHint`,{resource:`resource`})})]})}):oe.length===0?(0,G.jsx)(w,{className:`border-0`,children:(0,G.jsxs)(b,{children:[(0,G.jsx)(v,{children:(0,G.jsx)(de,{})}),(0,G.jsx)(x,{children:e(`home:noMatchingResources`)})]})}):(0,G.jsx)(`ul`,{className:`grid gap-2 sm:grid-cols-2 md:grid-cols-3`,children:oe.map(e=>(0,G.jsx)(`li`,{children:(0,G.jsxs)(fe,{to:{name:`list`,resourceId:e.id},className:`block rounded-md border border-border bg-card p-4 hover:border-primary/40 hover:shadow-sm transition-shadow`,children:[(0,G.jsx)(`div`,{className:`font-semibold`,children:e.name}),e.name!==e.id&&(0,G.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.id})]})},e.id))})})]}),se&&(0,G.jsx)(q,{onSave:e=>{m(L?{...e,groupId:L}:e),ce(!1)},onClose:()=>ce(!1)}),V&&(0,G.jsx)(q,{initial:V,onSave:e=>{h(V.id,e),P(null)},onClose:()=>P(null)}),z&&(0,G.jsx)(Ee,{groups:p,initialGroupId:z.groupId,initialOrder:z.order,onSave:({groupId:e,order:t})=>{h(z.id,{...z,groupId:e,order:t}),B(null)},onClose:()=>B(null),onCreateGroup:()=>{B(null),I(`new`)}}),F&&(0,G.jsx)(Te,{initial:F===`new`?void 0:F,onSave:e=>{if(F===`new`){let t=_(e);R(t)}else y(F.id,e);I(null)},onClose:()=>I(null)})]})}function Y(e,t){return e.order===t.order?e.createdAt.localeCompare(t.createdAt):e.order-t.order}export{J as HomePage};
3
+ //# sourceMappingURL=home-page-B3WVGerG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../../../react/src/components/chart-builder-dialog.tsx","../../../../react/src/components/group-settings-dialog.tsx","../../../../react/src/components/move-chart-dialog.tsx","../../../../react/src/pages/home-page.tsx"],"sourcesContent":["// Phase 10: time-series-first chart builder.\n//\n// X-axis is ALWAYS a date — the user picks `dateField` (required). `groupBy`\n// becomes an optional *secondary* breakdown that produces multiple series\n// (Metabase-style: pick \"status\" → one line per status value). Pie removed.\n// `width` lets the chart take half or full row on the dashboard grid.\n\nimport * as React from 'react'\nimport {\n BarChart2,\n LineChart,\n AreaChart,\n Activity,\n Plus,\n X,\n} from 'lucide-react'\nimport {\n Button,\n CHART_COLOR_PRESETS,\n ColorSwatchPicker,\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n InfoTooltip,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@modern-admin/ui'\nimport {\n chartDefZ,\n uuidv7,\n type AggregationOpName,\n type ChartDef,\n type ChartDefInput,\n type ChartFormat,\n type ChartTransformStep,\n type ChartVisualisation,\n type TimeRange,\n type TimeRangePreset,\n} from '@modern-admin/core'\nimport { applyTransform, makeValueFormatter } from '../dashboard/value-format.js'\nimport { useI18n } from '../i18n.js'\nimport { useResources } from '../hooks.js'\nimport { ReferenceCombobox } from '../reference.js'\nimport type { PropertyJSON } from '../types.js'\n\nexport interface ChartBuilderDialogProps {\n /** Pre-populate for editing an existing chart. */\n initial?: ChartDef\n onSave(input: ChartDefInput): void\n onClose(): void\n}\n\nconst VIS_OPTIONS: { value: ChartVisualisation; icon: React.ReactElement; labelKey: string }[] = [\n { value: 'kpi', icon: <Activity className=\"size-4\" />, labelKey: 'dashboard:visKpi' },\n { value: 'line', icon: <LineChart className=\"size-4\" />, labelKey: 'dashboard:visLine' },\n { value: 'area', icon: <AreaChart className=\"size-4\" />, labelKey: 'dashboard:visArea' },\n { value: 'bar', icon: <BarChart2 className=\"size-4\" />, labelKey: 'dashboard:visBar' },\n]\n\nconst NONE = '__none__'\nconst METRICS: AggregationOpName[] = ['count', 'sum', 'avg', 'min', 'max']\nconst TRANSFORM_OPS: ChartTransformStep['op'][] = ['divide', 'multiply', 'add', 'subtract']\nconst FORMAT_STYLES: NonNullable<ChartFormat['style']>[] = ['number', 'currency', 'percent']\n// `custom` is intentionally excluded from the builder — the builder sets a\n// default interval; ad-hoc custom ranges are picked on the widget toolbar.\nconst PRESETS: Exclude<TimeRangePreset, 'custom'>[] = ['7d', '30d', '90d', '1y', 'all']\n\n/** Date-ish heuristic for the dateField selector when adapter metadata is sparse. */\nfunction isDateProperty(p: { type?: string; path: string }): boolean {\n if (p.type === 'date' || p.type === 'datetime') return true\n const lower = p.path.toLowerCase()\n return lower.endsWith('at') || lower.endsWith('_at') || lower.endsWith('date')\n}\n\n/**\n * Properties that make sense as a `groupBy` axis: anything that resolves to\n * a discrete column value the adapter can group on. Virtual relation columns\n * (`type: 'reference'` with `isArray: false` and no FK suffix) carry full\n * record objects in their values and would serialise to `[object Object]` —\n * exclude them so the user picks the underlying FK column instead.\n */\nfunction isGroupable(p: { path: string; type?: string; isArray?: boolean }): boolean {\n if (isDateProperty(p)) return false\n if (p.type === 'reference' && !p.isArray) {\n // Allow scalar FK columns (named `*Id`/`*_id` with type 'reference' set\n // via adapter override) — they group cleanly to id strings. Reject virtual\n // relation fields whose values are objects.\n const path = p.path\n return path.endsWith('Id') || path.endsWith('_id')\n }\n if (p.type === 'json' || p.type === 'mixed') return false\n if (p.type === 'richtext' || p.type === 'markdown' || p.type === 'textarea') return false\n if (p.type === 'previewMedia' || p.type === 'file') return false\n return true\n}\n\nexport function ChartBuilderDialog({\n initial,\n onSave,\n onClose,\n}: ChartBuilderDialogProps): React.ReactElement {\n const { t, locale } = useI18n()\n const resources = useResources()\n\n const [title, setTitle] = React.useState(initial?.title ?? '')\n const [visualisation, setVisualisation] = React.useState<ChartVisualisation>(\n initial?.visualisation ?? 'area',\n )\n const [resourceId, setResourceId] = React.useState(\n initial?.resource ?? resources[0]?.id ?? '',\n )\n const [dateField, setDateField] = React.useState(initial?.dateField ?? '')\n const [metric, setMetric] = React.useState<AggregationOpName>(initial?.metric ?? 'count')\n const [field, setField] = React.useState(initial?.field ?? '')\n const [groupBy, setGroupBy] = React.useState(initial?.groupBy ?? '')\n const [groupByLabelResource, setGroupByLabelResource] = React.useState(\n initial?.groupByLabelResource ?? '',\n )\n const [topN, setTopN] = React.useState(initial?.topN ?? 10)\n // The builder only sets a default time-range preset; custom ranges are\n // picked on the widget toolbar. If the saved chart is on 'custom', fall\n // back to the most useful preset for the builder UI.\n const [preset, setPreset] = React.useState<Exclude<TimeRangePreset, 'custom'>>(\n initial && initial.timeRange.preset !== 'custom' ? initial.timeRange.preset : '30d',\n )\n const [filters, setFilters] = React.useState<Record<string, string>>(\n initial?.filters ?? {},\n )\n const [quickFilters, setQuickFilters] = React.useState<string[]>(\n initial?.quickFilters ?? [],\n )\n const [order, setOrder] = React.useState<number>(initial?.order ?? 0)\n const [comparePrevious, setComparePrevious] = React.useState(\n initial?.comparePrevious ?? false,\n )\n const [transform, setTransform] = React.useState<ChartTransformStep[]>(\n () => initial?.transform?.map((s) => ({ ...s })) ?? [],\n )\n const [formatStyle, setFormatStyle] = React.useState<NonNullable<ChartFormat['style']>>(\n initial?.format?.style ?? 'number',\n )\n const [currency, setCurrency] = React.useState(initial?.format?.currency ?? '')\n const [decimals, setDecimals] = React.useState<string>(\n initial?.format?.decimals != null ? String(initial.format.decimals) : '',\n )\n const [compact, setCompact] = React.useState(initial?.format?.compact ?? false)\n const [prefix, setPrefix] = React.useState(initial?.format?.prefix ?? '')\n const [suffix, setSuffix] = React.useState(initial?.format?.suffix ?? '')\n const [totalColor, setTotalColor] = React.useState<string | undefined>(\n initial?.series?.['__total__']?.color,\n )\n const [errors, setErrors] = React.useState<Record<string, string>>({})\n const [tab, setTab] = React.useState<'data' | 'display' | 'filters'>('data')\n\n const resource = resources.find((r) => r.id === resourceId)\n const properties = resource?.properties ?? []\n const dateProps = properties.filter(isDateProperty)\n const numericProps = properties.filter(\n (p) => p.type === 'number' || p.type === 'float' || p.type === 'currency',\n )\n\n // Auto-select dateField when resource changes (skip the very first\n // render of edit-mode so we keep the saved value).\n React.useEffect(() => {\n if (initial?.resource === resourceId) return\n setDateField(dateProps[0]?.path ?? '')\n setField('')\n setGroupBy('')\n setGroupByLabelResource('')\n setFilters({})\n setQuickFilters([])\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [resourceId])\n\n // When opening an existing chart that predates the groupByLabelResource\n // feature (groupByLabelResource is empty but groupBy is set): auto-derive\n // the label resource so the user gets resolved labels without re-saving.\n React.useEffect(() => {\n if (groupByLabelResource || !groupBy || properties.length === 0) return\n setGroupByLabelResource(resolveGroupByLabelResource(groupBy, properties))\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [groupBy, properties])\n\n const isKpi = visualisation === 'kpi'\n\n const buildTimeRange = (): TimeRange => ({ preset })\n\n // Omit `format` entirely while everything is at its default so old charts\n // don't accumulate noise on re-save.\n const buildFormat = (): ChartFormat | undefined => {\n const dec = decimals === '' ? undefined : Math.max(0, Math.min(6, Math.trunc(Number(decimals))))\n const fmt = {\n style: formatStyle,\n ...(formatStyle === 'currency' && currency.trim().length === 3\n ? { currency: currency.trim().toUpperCase() }\n : {}),\n ...(dec != null && Number.isFinite(dec) ? { decimals: dec } : {}),\n ...(prefix ? { prefix: prefix.slice(0, 8) } : {}),\n ...(suffix ? { suffix: suffix.slice(0, 8) } : {}),\n ...(compact ? { compact: true } : {}),\n }\n const isDefault = fmt.style === 'number' && Object.keys(fmt).length === 1\n return isDefault ? undefined : fmt\n }\n\n // Preserve per-series overrides saved from the widget colors dialog; the\n // builder itself only edits the single-series (__total__) color.\n const buildSeries = (): Record<string, { color?: string }> | undefined => {\n const next: Record<string, { color?: string }> = { ...initial?.series }\n if (!isKpi && !groupBy) {\n if (totalColor) next.__total__ = { color: totalColor }\n else delete next.__total__\n }\n return Object.keys(next).length ? next : undefined\n }\n\n // Live preview for the transform/format sections — pure helpers, cheap.\n const previewFormat = React.useMemo(\n () => makeValueFormatter(buildFormat(), locale),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [formatStyle, currency, decimals, compact, prefix, suffix, locale],\n )\n const PREVIEW_SAMPLE = 1234\n const previewText = `${PREVIEW_SAMPLE} → ${previewFormat(applyTransform(PREVIEW_SAMPLE, transform))}`\n\n const handleFilterChange = (path: string, value: string): void => {\n setFilters((prev) => {\n const next = { ...prev }\n if (value === '') delete next[path]\n else next[path] = value\n return next\n })\n }\n\n const toggleQuickFilter = (path: string): void => {\n setQuickFilters((prev) =>\n prev.includes(path) ? prev.filter((p) => p !== path) : [...prev, path],\n )\n }\n\n const handleSave = (): void => {\n const now = new Date().toISOString()\n // step is not user-editable in the builder; keep the previous value (or\n // pick a sane default) so chartDefZ stays valid. The widget toolbar\n // remains the place to tweak step on the fly.\n const savedStep = isKpi\n ? 'all'\n : initial && initial.step !== 'all'\n ? initial.step\n : 'day'\n const candidate: ChartDefInput = {\n id: initial?.id ?? uuidv7(),\n title: title.trim() || resource?.name || resourceId,\n resource: resourceId,\n visualisation,\n dateField,\n step: savedStep,\n metric,\n width: initial?.width ?? 'half',\n topN,\n filters,\n quickFilters: quickFilters.filter((p) => properties.some((q) => q.path === p)),\n timeRange: buildTimeRange(),\n order,\n // Preserve groupId on edit — the builder does not (yet) change group\n // membership directly; groups are managed from the dashboard tab strip.\n ...(initial?.groupId ? { groupId: initial.groupId } : {}),\n createdAt: initial?.createdAt ?? now,\n updatedAt: now,\n ...(metric !== 'count' && field ? { field } : {}),\n ...(!isKpi && groupBy ? { groupBy } : {}),\n ...(!isKpi && groupBy && groupByLabelResource ? { groupByLabelResource } : {}),\n transform,\n // Compare is only meaningful for time-series without a breakdown.\n comparePrevious: !isKpi && !groupBy ? comparePrevious : false,\n ...(buildFormat() ? { format: buildFormat() } : {}),\n ...(buildSeries() ? { series: buildSeries() } : {}),\n }\n const result = chartDefZ.safeParse(candidate)\n if (!result.success) {\n const fieldErrs: Record<string, string> = {}\n for (const issue of result.error.issues) {\n const key = issue.path[0]\n if (typeof key === 'string' && !fieldErrs[key]) fieldErrs[key] = issue.message\n }\n setErrors(fieldErrs)\n // Every schema-validated field lives on the Data tab — surface it so\n // the inline error isn't hidden behind another tab.\n setTab('data')\n return\n }\n setErrors({})\n onSave(candidate)\n }\n\n return (\n <Dialog open onOpenChange={(open) => { if (!open) onClose() }}>\n <DialogContent className=\"w-full max-w-2xl max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle>\n {initial ? t('chart:editChart') : t('chart:newChart')}\n </DialogTitle>\n </DialogHeader>\n\n <Tabs\n value={tab}\n onValueChange={(v) => setTab(v as 'data' | 'display' | 'filters')}\n className=\"py-1\"\n >\n <TabsList>\n <TabsTrigger value=\"data\">{t('dashboard:builder.tabData')}</TabsTrigger>\n <TabsTrigger value=\"display\">{t('dashboard:builder.tabDisplay')}</TabsTrigger>\n <TabsTrigger value=\"filters\">{t('dashboard:builder.tabFilters')}</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"data\" className=\"space-y-4\">\n {/* Title + order */}\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-[1fr_8rem]\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"chart-title\">{t('chart:title')}</Label>\n <Input\n id=\"chart-title\"\n placeholder={t('chart:titlePlaceholder')}\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n </div>\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label htmlFor=\"chart-order\">{t('chart:order')}</Label>\n <InfoTooltip content={t('chart:orderHint')} />\n </div>\n <Input\n id=\"chart-order\"\n type=\"number\"\n step={1}\n value={order}\n onChange={(e) => setOrder(Number.isFinite(Number(e.target.value)) ? Math.trunc(Number(e.target.value)) : 0)}\n />\n </div>\n </div>\n\n {/* Visualisation (incl. KPI) */}\n <div className=\"space-y-1.5\">\n <Label>{t('dashboard:vis')}</Label>\n <div className=\"flex flex-wrap gap-2\">\n {VIS_OPTIONS.map(({ value, icon, labelKey }) => (\n <Button\n key={value}\n type=\"button\"\n variant={visualisation === value ? 'default' : 'outline'}\n size=\"sm\"\n className=\"flex-1 min-w-[5rem] gap-1.5 capitalize\"\n onClick={() => setVisualisation(value)}\n >\n {icon}\n <span className=\"hidden sm:inline\">{t(labelKey)}</span>\n </Button>\n ))}\n </div>\n </div>\n\n {/* Resource */}\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"chart-resource\">{t('chart:resource')}</Label>\n <Select value={resourceId} onValueChange={(v) => setResourceId(v)}>\n <SelectTrigger id=\"chart-resource\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {resources.map((r) => (\n <SelectItem key={r.id} value={r.id}>\n {r.name}\n {r.name !== r.id && (\n <span className=\"ml-1.5 text-xs text-muted-foreground\">({r.id})</span>\n )}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {errors.resource && (\n <p className=\"text-xs text-destructive\">{errors.resource}</p>\n )}\n </div>\n\n {/* Date field — required, drives the X-axis bucketing */}\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"chart-datefield\">{t('dashboard:builder.dateField')}</Label>\n <Select\n value={dateField || NONE}\n onValueChange={(v) => setDateField(v === NONE ? '' : v)}\n >\n <SelectTrigger id=\"chart-datefield\">\n <SelectValue placeholder={t('chart:selectField')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t('chart:selectField')}</SelectItem>\n {(dateProps.length > 0 ? dateProps : properties).map((p) => (\n <SelectItem key={p.path} value={p.path}>{p.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p className=\"text-xs text-muted-foreground\">\n {t('dashboard:builder.dateFieldHint')}\n </p>\n {errors.dateField && (\n <p className=\"text-xs text-destructive\">{errors.dateField}</p>\n )}\n </div>\n\n {/* Metric + field */}\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"chart-metric\">{t('chart:metric')}</Label>\n <Select value={metric} onValueChange={(v) => setMetric(v as AggregationOpName)}>\n <SelectTrigger id=\"chart-metric\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {METRICS.map((m) => (\n <SelectItem key={m} value={m}>{t(`dashboard:metric${cap(m)}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {metric !== 'count' && (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"chart-field\">{t('chart:aggregateField')}</Label>\n <Select\n value={field || NONE}\n onValueChange={(v) => setField(v === NONE ? '' : v)}\n >\n <SelectTrigger id=\"chart-field\">\n <SelectValue placeholder={t('chart:selectField')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t('chart:selectField')}</SelectItem>\n {numericProps.map((p) => (\n <SelectItem key={p.path} value={p.path}>{p.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n {errors.field && (\n <p className=\"text-xs text-destructive\">{errors.field}</p>\n )}\n </div>\n )}\n </div>\n\n {/* Secondary groupBy + topN — non-KPI only */}\n {!isKpi && (\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"chart-groupby\">\n {t('dashboard:builder.secondaryGroupBy')}\n </Label>\n <Select\n value={groupBy || NONE}\n onValueChange={(v) => {\n const path = v === NONE ? '' : v\n setGroupBy(path)\n setGroupByLabelResource(resolveGroupByLabelResource(path, properties))\n }}\n >\n <SelectTrigger id=\"chart-groupby\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t('dashboard:builder.noBreakdown')}</SelectItem>\n {properties\n .filter((p) => isGroupable(p) && p.path !== dateField)\n .map((p) => (\n <SelectItem key={p.path} value={p.path}>{p.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {groupBy && (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"chart-topn\">{t('dashboard:builder.topN')}</Label>\n <Input\n id=\"chart-topn\"\n type=\"number\"\n min={1}\n max={50}\n value={topN}\n onChange={(e) =>\n setTopN(Math.max(1, Math.min(50, Number(e.target.value) || 10)))\n }\n />\n </div>\n )}\n </div>\n )}\n\n {/* Default time-range preset. Custom ranges are picked on the\n widget toolbar — not in the builder. */}\n <div className=\"space-y-1.5\">\n <Label>{t('dashboard:builder.range')}</Label>\n <div className=\"flex flex-wrap gap-2\">\n {PRESETS.map((p) => (\n <Button\n key={p}\n type=\"button\"\n variant={preset === p ? 'default' : 'outline'}\n size=\"sm\"\n className=\"flex-1 min-w-[4rem]\"\n onClick={() => setPreset(p)}\n >\n {t(`dashboard:range.${p}`)}\n </Button>\n ))}\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"display\" className=\"space-y-4\">\n {/* Previous-period compare — time-series without breakdown only. */}\n {!isKpi && (\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-1.5\">\n <Label htmlFor=\"chart-compare\">\n {t('dashboard:builder.comparePrevious')}\n </Label>\n <InfoTooltip content={t('dashboard:builder.comparePreviousHint')} />\n </div>\n <Switch\n id=\"chart-compare\"\n checked={!groupBy && comparePrevious}\n disabled={!!groupBy}\n onCheckedChange={setComparePrevious}\n aria-label={t('dashboard:builder.comparePrevious')}\n />\n </div>\n {!!groupBy && (\n <p className=\"text-xs text-muted-foreground\">\n {t('dashboard:builder.comparePreviousDisabled')}\n </p>\n )}\n </div>\n )}\n\n {/* Value transform — ordered scalar pipeline (e.g. cents → dollars). */}\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('dashboard:builder.transform')}</Label>\n <InfoTooltip content={t('dashboard:builder.transformHint')} />\n </div>\n {transform.map((step, i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <Select\n value={step.op}\n onValueChange={(v) =>\n setTransform((prev) =>\n prev.map((s, j) =>\n j === i ? { ...s, op: v as ChartTransformStep['op'] } : s,\n ),\n )\n }\n >\n <SelectTrigger className=\"w-40\" aria-label={t('dashboard:builder.transform')}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSFORM_OPS.map((op) => (\n <SelectItem key={op} value={op}>\n {t(`dashboard:builder.op${cap(op)}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Input\n type=\"number\"\n className=\"w-28\"\n value={Number.isFinite(step.value) ? step.value : ''}\n onChange={(e) =>\n setTransform((prev) =>\n prev.map((s, j) =>\n j === i ? { ...s, value: Number(e.target.value) } : s,\n ),\n )\n }\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8\"\n onClick={() =>\n setTransform((prev) => prev.filter((_, j) => j !== i))\n }\n aria-label={t('dashboard:builder.transformRemove')}\n >\n <X className=\"size-4\" />\n </Button>\n </div>\n ))}\n {transform.length < 8 && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() =>\n setTransform((prev) => [...prev, { op: 'divide', value: 100 }])\n }\n >\n <Plus className=\"size-4 mr-1\" />\n {t('dashboard:builder.transformAdd')}\n </Button>\n )}\n </div>\n\n {/* Value format */}\n <div className=\"space-y-1.5\">\n <Label>{t('dashboard:builder.format')}</Label>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"space-y-1\">\n <Label\n htmlFor=\"chart-format-style\"\n className=\"text-xs text-muted-foreground\"\n >\n {t('dashboard:builder.formatStyle')}\n </Label>\n <Select\n value={formatStyle}\n onValueChange={(v) => setFormatStyle(v as NonNullable<ChartFormat['style']>)}\n >\n <SelectTrigger id=\"chart-format-style\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FORMAT_STYLES.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`dashboard:builder.format${cap(s)}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {formatStyle === 'currency' && (\n <div className=\"space-y-1\">\n <Label\n htmlFor=\"chart-format-currency\"\n className=\"text-xs text-muted-foreground\"\n >\n {t('dashboard:builder.formatCurrencyCode')}\n </Label>\n <Input\n id=\"chart-format-currency\"\n placeholder=\"USD\"\n maxLength={3}\n value={currency}\n onChange={(e) => setCurrency(e.target.value.toUpperCase())}\n />\n </div>\n )}\n <div className=\"space-y-1\">\n <Label\n htmlFor=\"chart-format-decimals\"\n className=\"text-xs text-muted-foreground\"\n >\n {t('dashboard:builder.formatDecimals')}\n </Label>\n <Input\n id=\"chart-format-decimals\"\n type=\"number\"\n min={0}\n max={6}\n value={decimals}\n onChange={(e) => setDecimals(e.target.value)}\n />\n </div>\n <div className=\"space-y-1\">\n <Label\n htmlFor=\"chart-format-prefix\"\n className=\"text-xs text-muted-foreground\"\n >\n {t('dashboard:builder.formatPrefix')} / {t('dashboard:builder.formatSuffix')}\n </Label>\n <div className=\"flex gap-2\">\n <Input\n id=\"chart-format-prefix\"\n maxLength={8}\n placeholder={t('dashboard:builder.formatPrefix')}\n value={prefix}\n onChange={(e) => setPrefix(e.target.value)}\n />\n <Input\n maxLength={8}\n placeholder={t('dashboard:builder.formatSuffix')}\n value={suffix}\n onChange={(e) => setSuffix(e.target.value)}\n aria-label={t('dashboard:builder.formatSuffix')}\n />\n </div>\n </div>\n <div className=\"flex items-center justify-between gap-2 sm:col-span-2\">\n <Label htmlFor=\"chart-format-compact\">\n {t('dashboard:builder.formatCompact')}\n </Label>\n <Switch\n id=\"chart-format-compact\"\n checked={compact}\n onCheckedChange={setCompact}\n />\n </div>\n </div>\n <p className=\"text-xs text-muted-foreground tabular-nums\">{previewText}</p>\n </div>\n\n {/* Series color — single-series charts; breakdown colors are edited\n from the widget menu once the series are known. */}\n {!isKpi && !groupBy && (\n <div className=\"space-y-1.5\">\n <Label>{t('dashboard:builder.color')}</Label>\n <ColorSwatchPicker\n value={totalColor}\n onChange={setTotalColor}\n presets={CHART_COLOR_PRESETS}\n labels={{\n custom: t('dashboard:widget.colorCustom'),\n pick: t('dashboard:widget.colorPick'),\n auto: t('dashboard:widget.colorAuto'),\n }}\n />\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"filters\" className=\"space-y-4\">\n {/* Filters — one row per property, with a checkbox to mark the\n filter as a \"quick filter\" (exposed above the chart for inline\n tweaking on the dashboard). Reference fields use a combobox. */}\n {properties.length > 0 ? (\n <div className=\"space-y-1.5\">\n <Label>{t('dashboard:builder.filters')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('dashboard:builder.filtersHint')}\n </p>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-3\">\n {properties.filter(isFilterable).map((p) => {\n const exposed = quickFilters.includes(p.path)\n return (\n <div key={p.path} className=\"space-y-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <Label\n htmlFor={`flt-${p.path}`}\n className=\"text-xs text-muted-foreground\"\n >\n {p.label}\n </Label>\n <Switch\n checked={exposed}\n onCheckedChange={() => toggleQuickFilter(p.path)}\n aria-label={t('dashboard:builder.quickFilterToggle').replace(\n '{field}',\n p.label,\n )}\n title={t('dashboard:builder.quickFilterHint')}\n />\n </div>\n <FilterInput\n property={p}\n value={filters[p.path] ?? ''}\n onChange={(v) => handleFilterChange(p.path, v)}\n />\n </div>\n )\n })}\n </div>\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n {t('dashboard:builder.filtersEmpty')}\n </p>\n )}\n </TabsContent>\n </Tabs>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose}>{t('common:cancel')}</Button>\n <Button onClick={handleSave} disabled={!resourceId || !dateField}>\n {t('chart:saveChart')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nconst cap = (s: string): string => s.charAt(0).toUpperCase() + s.slice(1)\n\n/**\n * Property is exposable as a filter. Excludes ids, array fields, free-form\n * blobs (json/mixed/richtext), media fields, and virtual relation columns\n * (we keep the underlying FK column so we don't list `authorId` and `author`\n * twice).\n */\nfunction isFilterable(p: PropertyJSON): boolean {\n if (p.isId) return false\n if (p.isArray) return false\n if (p.type === 'json' || p.type === 'mixed') return false\n if (p.type === 'richtext' || p.type === 'markdown' || p.type === 'textarea') return false\n if (p.type === 'previewMedia' || p.type === 'file') return false\n // Drop virtual relation columns (full objects) — keep FK siblings instead.\n if (p.type === 'reference' && !p.isArray) {\n const path = p.path\n if (!(path.endsWith('Id') || path.endsWith('_id'))) return false\n }\n return true\n}\n\n/**\n * Renders an inline input for one filter row in the builder. Reference\n * properties get the same combobox the resource forms use; enums/booleans\n * get a Select; numerics get a number input; everything else falls back to\n * a plain text input.\n */\nfunction FilterInput({\n property,\n value,\n onChange,\n}: {\n property: PropertyJSON\n value: string\n onChange(next: string): void\n}): React.ReactElement {\n if (property.reference) {\n return (\n <ReferenceCombobox\n referenceResourceId={property.reference}\n value={value || null}\n onChange={(next) => onChange(next == null ? '' : String(next))}\n />\n )\n }\n if (property.availableValues && property.availableValues.length > 0) {\n return (\n <Select\n value={value || NONE}\n onValueChange={(v) => onChange(v === NONE ? '' : v)}\n >\n <SelectTrigger id={`flt-${property.path}`}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>—</SelectItem>\n {property.availableValues.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n }\n if (property.type === 'boolean') {\n return (\n <Select\n value={value || NONE}\n onValueChange={(v) => onChange(v === NONE ? '' : v)}\n >\n <SelectTrigger id={`flt-${property.path}`}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>—</SelectItem>\n <SelectItem value=\"true\">true</SelectItem>\n <SelectItem value=\"false\">false</SelectItem>\n </SelectContent>\n </Select>\n )\n }\n const isNumeric =\n property.type === 'number' || property.type === 'float' || property.type === 'currency'\n return (\n <Input\n id={`flt-${property.path}`}\n type={isNumeric ? 'number' : 'text'}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n />\n )\n}\n\n/**\n * Resolve which resource to use for groupBy label resolution.\n *\n * 1. If the property itself is `type: 'reference'` (virtual relation field),\n * use its `reference` resource id directly — same mechanism as the record\n * title display in resource forms.\n * 2. If it is a raw FK column (e.g. `authorId`), look for a sibling property\n * whose path is the FK name without the trailing `Id`/`_id` suffix AND\n * has `reference` set. Covers the Prisma/Drizzle naming convention.\n */\nfunction resolveGroupByLabelResource(\n path: string,\n properties: ReadonlyArray<{ path: string; type: string; reference: string | null }>,\n): string {\n if (!path) return ''\n const prop = properties.find((p) => p.path === path)\n if (!prop) return ''\n // Direct reference property (virtual relation).\n if (prop.reference) return prop.reference\n // FK column heuristic: strip Id / _id suffix and look for sibling.\n const base = prop.path.endsWith('_id')\n ? prop.path.slice(0, -3)\n : prop.path.endsWith('Id')\n ? prop.path.slice(0, -2)\n : ''\n if (base) {\n const sibling = properties.find((p) => p.path === base && p.reference)\n if (sibling?.reference) return sibling.reference\n }\n return ''\n}\n","// Create / edit dialog for a dashboard chart group. Lives in the react\n// package because it is i18n-aware; the actual primitives come from\n// @modern-admin/ui.\n\nimport * as React from 'react'\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n InfoTooltip,\n Input,\n Label,\n} from '@modern-admin/ui'\nimport type { ChartGroup } from '@modern-admin/core'\nimport { useI18n } from '../i18n.js'\n\nexport interface GroupSettingsDialogProps {\n /** When set, the dialog is in edit mode and pre-populates from this group. */\n initial?: ChartGroup\n onSave(input: { name: string; order: number }): void\n onClose(): void\n}\n\nexport function GroupSettingsDialog({\n initial,\n onSave,\n onClose,\n}: GroupSettingsDialogProps): React.ReactElement {\n const { t } = useI18n()\n const [name, setName] = React.useState(initial?.name ?? '')\n const [order, setOrder] = React.useState<number>(initial?.order ?? 0)\n const [error, setError] = React.useState<string>('')\n\n const handleSave = (): void => {\n const trimmed = name.trim()\n if (!trimmed) {\n setError(t('chart:groupNameRequired'))\n return\n }\n setError('')\n onSave({ name: trimmed, order: Number.isFinite(order) ? Math.trunc(order) : 0 })\n }\n\n return (\n <Dialog open onOpenChange={(open) => { if (!open) onClose() }}>\n <DialogContent className=\"w-full max-w-md\">\n <DialogHeader>\n <DialogTitle>\n {initial ? t('chart:editGroup') : t('chart:newGroup')}\n </DialogTitle>\n </DialogHeader>\n\n <div className=\"space-y-4 py-1\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"group-name\">{t('chart:groupName')}</Label>\n <Input\n id=\"group-name\"\n placeholder={t('chart:groupNamePlaceholder')}\n value={name}\n onChange={(e) => setName(e.target.value)}\n autoFocus\n />\n {error && <p className=\"text-xs text-destructive\">{error}</p>}\n </div>\n\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label htmlFor=\"group-order\">{t('chart:groupOrder')}</Label>\n <InfoTooltip content={t('chart:orderHint')} />\n </div>\n <Input\n id=\"group-order\"\n type=\"number\"\n step={1}\n value={order}\n onChange={(e) =>\n setOrder(Number.isFinite(Number(e.target.value)) ? Math.trunc(Number(e.target.value)) : 0)\n }\n />\n </div>\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose}>{t('common:cancel')}</Button>\n <Button onClick={handleSave}>{t('chart:saveGroup')}</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","// Dialog for moving a chart to a different group and adjusting its order.\n// Opened from the chart widget's \"…\" dropdown menu.\n\nimport * as React from 'react'\nimport { FolderPlus } from 'lucide-react'\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n InfoTooltip,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@modern-admin/ui'\nimport type { ChartGroup } from '@modern-admin/core'\nimport { useI18n } from '../i18n.js'\n\nexport interface MoveChartDialogProps {\n groups: ChartGroup[]\n /** Current group id of the chart being moved. */\n initialGroupId?: string\n /** Current order value of the chart being moved. */\n initialOrder?: number\n onSave(input: { groupId: string; order: number }): void\n onClose(): void\n /** Called when the user wants to create a group first (no groups exist). */\n onCreateGroup(): void\n}\n\nexport function MoveChartDialog({\n groups,\n initialGroupId,\n initialOrder,\n onSave,\n onClose,\n onCreateGroup,\n}: MoveChartDialogProps): React.ReactElement {\n const { t } = useI18n()\n\n const sorted = React.useMemo(\n () => [...groups].sort((a, b) => a.order - b.order),\n [groups],\n )\n\n // Seed from the chart's current group, or the first group if unset.\n const defaultGroupId = initialGroupId ?? sorted[0]?.id ?? ''\n const [groupId, setGroupId] = React.useState(defaultGroupId)\n const [order, setOrder] = React.useState<number>(initialOrder ?? 0)\n\n const handleSave = (): void => {\n if (!groupId) return\n onSave({ groupId, order: Number.isFinite(order) ? Math.trunc(order) : 0 })\n }\n\n return (\n <Dialog open onOpenChange={(open) => { if (!open) onClose() }}>\n <DialogContent className=\"w-full max-w-md\">\n <DialogHeader>\n <DialogTitle>{t('chart:moveChart')}</DialogTitle>\n </DialogHeader>\n\n {sorted.length === 0 ? (\n // No groups yet — prompt to create one.\n <div className=\"space-y-3 py-2\">\n <p className=\"text-sm font-medium\">{t('chart:moveNoGroups')}</p>\n <p className=\"text-sm text-muted-foreground\">{t('chart:moveNoGroupsHint')}</p>\n <Button\n variant=\"outline\"\n className=\"w-full\"\n onClick={() => { onClose(); onCreateGroup() }}\n >\n <FolderPlus className=\"size-4 mr-2\" />\n {t('chart:addGroup')}\n </Button>\n </div>\n ) : (\n <div className=\"space-y-4 py-1\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"move-group\">{t('chart:moveGroup')}</Label>\n <Select value={groupId} onValueChange={setGroupId}>\n <SelectTrigger id=\"move-group\" className=\"w-full\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {sorted.map((g) => (\n <SelectItem key={g.id} value={g.id}>\n {g.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label htmlFor=\"move-order\">{t('chart:order')}</Label>\n <InfoTooltip content={t('chart:orderHint')} />\n </div>\n <Input\n id=\"move-order\"\n type=\"number\"\n step={1}\n value={order}\n onChange={(e) =>\n setOrder(Number.isFinite(Number(e.target.value)) ? Math.trunc(Number(e.target.value)) : 0)\n }\n />\n </div>\n </div>\n )}\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose}>{t('common:cancel')}</Button>\n {sorted.length > 0 && (\n <Button onClick={handleSave} disabled={!groupId}>\n {t('chart:moveToGroup')}\n </Button>\n )}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import * as React from 'react'\nimport { Plus, Database, BarChart2, FolderPlus, Pencil, Trash2 } from 'lucide-react'\nimport {\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Empty,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n Input,\n Skeleton,\n Tabs,\n TabsList,\n TabsTrigger,\n} from '@modern-admin/ui'\nimport { useResources, useCurrentUser } from '../hooks.js'\nimport { useI18n } from '../i18n.js'\nimport { Link } from '../router.js'\nimport { useDashboardCharts, ServerDashboardStore } from '../use-dashboard-charts.js'\nimport { useAdminClient } from '../provider.js'\nimport { useDialogs } from '../dialogs.js'\nimport type { ChartWidgetProps } from '../components/chart-widget.js'\nimport { ChartBuilderDialog } from '../components/chart-builder-dialog.js'\nimport { GroupSettingsDialog } from '../components/group-settings-dialog.js'\nimport { MoveChartDialog } from '../components/move-chart-dialog.js'\nimport type { ChartDef, ChartGroup } from '@modern-admin/core'\n\n// ChartWidget statically pulls in Recharts (via ui's TimeSeriesChart/KpiCard).\n// Split it into its own async chunk so the dashboard's charting library never\n// loads until a chart is actually rendered — dashboards with no charts (and\n// the initial home-page paint) skip the Recharts payload entirely.\nconst ChartWidgetImpl = React.lazy(() =>\n import('../components/chart-widget.js').then((m) => ({ default: m.ChartWidget })),\n)\n\nfunction LazyChartWidget(props: ChartWidgetProps): React.ReactElement {\n return (\n <React.Suspense fallback={<Skeleton className=\"h-[320px] w-full rounded-md\" />}>\n <ChartWidgetImpl {...props} />\n </React.Suspense>\n )\n}\n\nexport function HomePage(): React.ReactElement {\n const { t } = useI18n()\n const resources = useResources()\n const { user } = useCurrentUser()\n const adminClient = useAdminClient()\n const dialogs = useDialogs()\n // Use server-backed store so charts persist across devices/browsers.\n // Falls back gracefully when configStore is not configured server-side.\n const serverStore = React.useMemo(() => new ServerDashboardStore(adminClient), [adminClient])\n const {\n charts,\n groups,\n addChart,\n updateChart,\n removeChart,\n addGroup,\n updateGroup,\n removeGroup,\n } = useDashboardCharts({\n userId: user?.id ?? null,\n store: serverStore,\n })\n\n // Only show resources explicitly visible in navigation (same rule as sidebar).\n const navResources = React.useMemo(\n () => resources.filter((r) => r.navigation !== null),\n [resources],\n )\n\n const [resourceSearch, setResourceSearch] = React.useState('')\n const matchingResources = React.useMemo(() => {\n const query = resourceSearch.trim().toLocaleLowerCase()\n if (!query) return navResources\n return navResources.filter((resource) =>\n [resource.name, resource.id].some((value) => value.toLocaleLowerCase().includes(query)),\n )\n }, [navResources, resourceSearch])\n\n const [building, setBuilding] = React.useState(false)\n const [editingId, setEditingId] = React.useState<string | null>(null)\n // null = no dialog; 'new' = create; ChartGroup = edit-existing.\n const [groupDialog, setGroupDialog] = React.useState<ChartGroup | 'new' | null>(null)\n const [activeGroupId, setActiveGroupId] = React.useState<string | null>(null)\n // Chart being moved — null when dialog is closed.\n const [movingChart, setMovingChart] = React.useState<ChartDef | null>(null)\n\n // Keep `activeGroupId` valid when groups change (group removed, list reloaded\n // from store, etc.). When at least one group exists we always render charts\n // bucketed by group, so we need a definite active id.\n React.useEffect(() => {\n if (groups.length === 0) {\n setActiveGroupId(null)\n return\n }\n if (!activeGroupId || !groups.some((g) => g.id === activeGroupId)) {\n setActiveGroupId(groups[0]!.id)\n }\n }, [groups, activeGroupId])\n\n const editingChart = editingId ? charts.find((c) => c.id === editingId) : undefined\n\n // Build the chart bucket for the active group: charts whose `groupId`\n // matches OR (fallback) ungrouped charts when the active group is the\n // first one. Sorted by `order` then `createdAt`.\n const firstGroupId = groups[0]?.id ?? null\n const visibleCharts = React.useMemo(() => {\n if (groups.length === 0) return [...charts].sort(byChartOrder)\n if (!activeGroupId) return []\n const filtered = charts.filter((c) => {\n if (c.groupId) return c.groupId === activeGroupId\n // Ungrouped charts default into the first group so they remain visible.\n return activeGroupId === firstGroupId\n })\n return filtered.sort(byChartOrder)\n }, [charts, groups.length, activeGroupId, firstGroupId])\n\n const activeGroup = activeGroupId ? groups.find((g) => g.id === activeGroupId) ?? null : null\n\n const handleDeleteChart = async (chart: ChartDef): Promise<void> => {\n const ok = await dialogs.confirm({\n title: t('chart:deleteChartConfirm'),\n description: t('chart:deleteChartConfirmHint'),\n confirmLabel: t('common:delete'),\n destructive: true,\n })\n if (ok) removeChart(chart.id)\n }\n\n const handleDeleteGroup = async (group: ChartGroup): Promise<void> => {\n const count = charts.filter((c) => {\n if (c.groupId) return c.groupId === group.id\n // Ungrouped charts also belong to the first group at display time.\n return group.id === firstGroupId\n }).length\n const ok = await dialogs.confirm({\n title: t('chart:deleteGroupConfirm'),\n description: t('chart:deleteGroupConfirmHint').replace('{count}', String(count)),\n confirmLabel: t('common:delete'),\n destructive: true,\n })\n if (ok) removeGroup(group.id)\n }\n\n return (\n <div className=\"space-y-3 sm:space-y-6\">\n {/* ── Dashboard charts ──────────────────────────────────────── */}\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between p-3 pb-2 space-y-0 gap-2 sm:p-6 sm:pb-2\">\n <CardTitle>{t('chart:dashboard')}</CardTitle>\n <div className=\"flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setGroupDialog('new')}\n >\n <FolderPlus className=\"size-4\" />\n <span className=\"hidden sm:inline ml-1.5\">{t('chart:addGroup')}</span>\n </Button>\n <Button size=\"sm\" onClick={() => setBuilding(true)} disabled={navResources.length === 0}>\n <Plus className=\"size-4\" />\n <span className=\"hidden sm:inline ml-1.5\">{t('chart:addChart')}</span>\n </Button>\n </div>\n </CardHeader>\n <CardContent className=\"p-3 pt-0 sm:p-6 sm:pt-0\">\n {groups.length > 0 && activeGroupId && (\n <Tabs\n value={activeGroupId}\n onValueChange={(v) => setActiveGroupId(v)}\n className=\"mb-4\"\n >\n <div className=\"flex items-end justify-between gap-2\">\n <TabsList className=\"flex-1\">\n {groups.map((g) => (\n <TabsTrigger key={g.id} value={g.id}>\n {g.name}\n </TabsTrigger>\n ))}\n </TabsList>\n {activeGroup && (\n <div className=\"mb-1 flex shrink-0 items-center gap-1\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setGroupDialog(activeGroup)}\n aria-label={t('chart:editGroup')}\n >\n <Pencil className=\"size-3.5\" />\n <span className=\"hidden sm:inline ml-1.5\">{t('chart:editGroup')}</span>\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => void handleDeleteGroup(activeGroup)}\n aria-label={t('chart:deleteGroup')}\n >\n <Trash2 className=\"size-3.5\" />\n <span className=\"hidden sm:inline ml-1.5\">{t('chart:deleteGroup')}</span>\n </Button>\n </div>\n )}\n </div>\n </Tabs>\n )}\n\n {visibleCharts.length === 0 ? (\n <Empty className=\"border-0 py-4\">\n <EmptyHeader>\n <EmptyMedia>\n <BarChart2 />\n </EmptyMedia>\n <EmptyTitle>{t('chart:noCharts')}</EmptyTitle>\n <EmptyDescription>{t('chart:noChartsHint')}</EmptyDescription>\n </EmptyHeader>\n </Empty>\n ) : (\n <div className=\"grid gap-3 grid-cols-1 sm:gap-4 md:grid-cols-2\">\n {visibleCharts.map((c) => (\n <div\n key={c.id}\n className={c.width === 'full' ? 'md:col-span-2' : undefined}\n >\n <LazyChartWidget\n config={c}\n onEdit={() => setEditingId(c.id)}\n onDelete={() => void handleDeleteChart(c)}\n onMove={() => setMovingChart(c)}\n onUpdate={(input) => updateChart(c.id, input)}\n />\n </div>\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* ── Resources list ────────────────────────────────────────── */}\n <Card>\n <CardHeader className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <CardTitle>{t('common:resources')}</CardTitle>\n {navResources.length > 0 && (\n <div className=\"w-full sm:w-64\">\n <Input\n type=\"search\"\n value={resourceSearch}\n onChange={(event) => setResourceSearch(event.target.value)}\n placeholder={t('home:searchResources')}\n aria-label={t('home:searchResources')}\n onClear={() => setResourceSearch('')}\n clearLabel={t('common:clear')}\n />\n </div>\n )}\n </CardHeader>\n <CardContent>\n {navResources.length === 0 ? (\n <Empty className=\"border-0\">\n <EmptyHeader>\n <EmptyMedia>\n <Database />\n </EmptyMedia>\n <EmptyTitle>{t('common:noRecords')}</EmptyTitle>\n <EmptyDescription>\n {t('common:noRecordsHint', { resource: 'resource' })}\n </EmptyDescription>\n </EmptyHeader>\n </Empty>\n ) : matchingResources.length === 0 ? (\n <Empty className=\"border-0\">\n <EmptyHeader>\n <EmptyMedia>\n <Database />\n </EmptyMedia>\n <EmptyTitle>{t('home:noMatchingResources')}</EmptyTitle>\n </EmptyHeader>\n </Empty>\n ) : (\n <ul className=\"grid gap-2 sm:grid-cols-2 md:grid-cols-3\">\n {matchingResources.map((r) => (\n <li key={r.id}>\n <Link\n to={{ name: 'list', resourceId: r.id }}\n className=\"block rounded-md border border-border bg-card p-4 hover:border-primary/40 hover:shadow-sm transition-shadow\"\n >\n <div className=\"font-semibold\">{r.name}</div>\n {r.name !== r.id && (\n <div className=\"text-xs text-muted-foreground\">{r.id}</div>\n )}\n </Link>\n </li>\n ))}\n </ul>\n )}\n </CardContent>\n </Card>\n\n {/* ── Chart builder dialog ──────────────────────────────────── */}\n {building && (\n <ChartBuilderDialog\n onSave={(input) => {\n // New charts inherit the active group so the user sees them in\n // the tab they were on. The hook also auto-falls back to the\n // first group if `groupId` is undefined.\n addChart(activeGroupId ? { ...input, groupId: activeGroupId } : input)\n setBuilding(false)\n }}\n onClose={() => setBuilding(false)}\n />\n )}\n {editingChart && (\n <ChartBuilderDialog\n initial={editingChart}\n onSave={(input) => { updateChart(editingChart.id, input); setEditingId(null) }}\n onClose={() => setEditingId(null)}\n />\n )}\n\n {/* ── Move chart dialog ─────────────────────────────────────── */}\n {movingChart && (\n <MoveChartDialog\n groups={groups}\n initialGroupId={movingChart.groupId}\n initialOrder={movingChart.order}\n onSave={({ groupId, order }) => {\n updateChart(movingChart.id, { ...movingChart, groupId, order })\n setMovingChart(null)\n }}\n onClose={() => setMovingChart(null)}\n onCreateGroup={() => {\n setMovingChart(null)\n setGroupDialog('new')\n }}\n />\n )}\n\n {/* ── Group settings dialog ─────────────────────────────────── */}\n {groupDialog && (\n <GroupSettingsDialog\n initial={groupDialog === 'new' ? undefined : groupDialog}\n onSave={(input) => {\n if (groupDialog === 'new') {\n const newId = addGroup(input)\n setActiveGroupId(newId)\n } else {\n updateGroup(groupDialog.id, input)\n }\n setGroupDialog(null)\n }}\n onClose={() => setGroupDialog(null)}\n />\n )}\n </div>\n )\n}\n\n/** Sort charts within a group: by `order` asc, ties broken by `createdAt`. */\nfunction byChartOrder(a: ChartDef, b: ChartDef): number {\n if (a.order !== b.order) return a.order - b.order\n return a.createdAt.localeCompare(b.createdAt)\n}\n"],"file":"home-page-B3WVGerG.js"}