@techzyapp/ui-library 1.0.40 → 1.0.42

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 (546) hide show
  1. package/README.md +14 -8
  2. package/dist/AdminRoot-DufZpgdm.js +100 -0
  3. package/dist/AdminRoot-DufZpgdm.js.map +1 -0
  4. package/dist/AdminRoot-DwJ5jdXr.cjs +2 -0
  5. package/dist/AdminRoot-DwJ5jdXr.cjs.map +1 -0
  6. package/dist/Alert-C8BBxL_7.cjs +2 -0
  7. package/dist/Alert-C8BBxL_7.cjs.map +1 -0
  8. package/dist/Alert-D6oBxBdP.js +70 -0
  9. package/dist/Alert-D6oBxBdP.js.map +1 -0
  10. package/dist/AuthLayout-exuNQicH.cjs.map +1 -1
  11. package/dist/AuthLayout-q8pbCGdt.js.map +1 -1
  12. package/dist/{Breadcrumbs-hi6dJhfN.cjs → Breadcrumbs-B-olYVdw.cjs} +2 -2
  13. package/dist/Breadcrumbs-B-olYVdw.cjs.map +1 -0
  14. package/dist/{Breadcrumbs-Dqhk-dY2.js → Breadcrumbs-cXET6OM5.js} +3 -3
  15. package/dist/Breadcrumbs-cXET6OM5.js.map +1 -0
  16. package/dist/{Button-Bst_NtPJ.js → Button-0ZgdNjX-.js} +2 -2
  17. package/dist/{Button-Bst_NtPJ.js.map → Button-0ZgdNjX-.js.map} +1 -1
  18. package/dist/{Button-CYZoF18-.cjs → Button-CwrDiZek.cjs} +2 -2
  19. package/dist/{Button-CYZoF18-.cjs.map → Button-CwrDiZek.cjs.map} +1 -1
  20. package/dist/{Calendar-OYXsfuWz.js → Calendar-CxzdnzdK.js} +3 -3
  21. package/dist/{Calendar-OYXsfuWz.js.map → Calendar-CxzdnzdK.js.map} +1 -1
  22. package/dist/{Calendar-CMNBHtvY.cjs → Calendar-d3CX5UJp.cjs} +2 -2
  23. package/dist/{Calendar-CMNBHtvY.cjs.map → Calendar-d3CX5UJp.cjs.map} +1 -1
  24. package/dist/Card-CjqStov5.js +129 -0
  25. package/dist/Card-CjqStov5.js.map +1 -0
  26. package/dist/Card-CxnUoWsi.cjs +2 -0
  27. package/dist/Card-CxnUoWsi.cjs.map +1 -0
  28. package/dist/{Chip-B7cAHjlx.cjs → Chip-BkU3yx6G.cjs} +2 -2
  29. package/dist/Chip-BkU3yx6G.cjs.map +1 -0
  30. package/dist/{Chip-D5ZZs3QH.js → Chip-CzJjbaKx.js} +2 -2
  31. package/dist/Chip-CzJjbaKx.js.map +1 -0
  32. package/dist/ChoiceCardGroup-C7Eengyd.cjs +2 -0
  33. package/dist/ChoiceCardGroup-C7Eengyd.cjs.map +1 -0
  34. package/dist/ChoiceCardGroup-q0yN-TeQ.js +180 -0
  35. package/dist/{ChoiceCardGroup-143hR0v_.cjs.map → ChoiceCardGroup-q0yN-TeQ.js.map} +1 -1
  36. package/dist/{CodeBlock-DrWRSRmO.js → CodeBlock-BHcvQrs9.js} +3 -3
  37. package/dist/CodeBlock-BHcvQrs9.js.map +1 -0
  38. package/dist/{CodeBlock-C3mG_seZ.cjs → CodeBlock-DRBQ_S5t.cjs} +2 -2
  39. package/dist/CodeBlock-DRBQ_S5t.cjs.map +1 -0
  40. package/dist/{ColorPicker-w7NdprlW.js → ColorPicker-BQKFdTNr.js} +51 -51
  41. package/dist/{ColorPicker-w7NdprlW.js.map → ColorPicker-BQKFdTNr.js.map} +1 -1
  42. package/dist/ColorPicker-BzCEMN7B.cjs +2 -0
  43. package/dist/{ColorPicker-C1pDI4su.cjs.map → ColorPicker-BzCEMN7B.cjs.map} +1 -1
  44. package/dist/{ColorPickerPanel-CKMd-dqd.js → ColorPickerPanel-DKTKC9KH.js} +2 -2
  45. package/dist/{ColorPickerPanel-CKMd-dqd.js.map → ColorPickerPanel-DKTKC9KH.js.map} +1 -1
  46. package/dist/{ColorPickerPanel-BbgujQ3X.cjs → ColorPickerPanel-kl2jUix-.cjs} +2 -2
  47. package/dist/{ColorPickerPanel-BbgujQ3X.cjs.map → ColorPickerPanel-kl2jUix-.cjs.map} +1 -1
  48. package/dist/{ColorRamp-D9_5JULy.cjs → ColorRamp-n7muILK3.cjs} +2 -2
  49. package/dist/{ColorRamp-D9_5JULy.cjs.map → ColorRamp-n7muILK3.cjs.map} +1 -1
  50. package/dist/{ColorRamp-Mp_ddhmb.js → ColorRamp-yfMyJCyx.js} +2 -2
  51. package/dist/{ColorRamp-Mp_ddhmb.js.map → ColorRamp-yfMyJCyx.js.map} +1 -1
  52. package/dist/ConfigProvider-BaiTKZKC.cjs +2 -0
  53. package/dist/ConfigProvider-BaiTKZKC.cjs.map +1 -0
  54. package/dist/ConfigProvider-D61cpCz-.js +379 -0
  55. package/dist/ConfigProvider-D61cpCz-.js.map +1 -0
  56. package/dist/{CopyButton-DZeYcG68.cjs → CopyButton-DlSi82gv.cjs} +2 -2
  57. package/dist/{CopyButton-DZeYcG68.cjs.map → CopyButton-DlSi82gv.cjs.map} +1 -1
  58. package/dist/{CopyButton-Yg5ZVTiX.js → CopyButton-ecxn-ghi.js} +3 -3
  59. package/dist/{CopyButton-Yg5ZVTiX.js.map → CopyButton-ecxn-ghi.js.map} +1 -1
  60. package/dist/DatePicker-BjZ_P21i.cjs +2 -0
  61. package/dist/{DatePicker-CXRsT-lt.cjs.map → DatePicker-BjZ_P21i.cjs.map} +1 -1
  62. package/dist/{DatePicker-BMJlfCKB.js → DatePicker-CAGpJbDi.js} +42 -42
  63. package/dist/{DatePicker-BMJlfCKB.js.map → DatePicker-CAGpJbDi.js.map} +1 -1
  64. package/dist/{DateTimePicker-B-Jjejzm.js → DateTimePicker-BJmF0Su6.js} +50 -50
  65. package/dist/DateTimePicker-BJmF0Su6.js.map +1 -0
  66. package/dist/DateTimePicker-DZqWQeUL.cjs +2 -0
  67. package/dist/DateTimePicker-DZqWQeUL.cjs.map +1 -0
  68. package/dist/{DescriptionList-S9C6Tp90.cjs → DescriptionList-CvPDn-kh.cjs} +2 -2
  69. package/dist/DescriptionList-CvPDn-kh.cjs.map +1 -0
  70. package/dist/{DescriptionList-CG08_qwT.js → DescriptionList-Knq5eCiY.js} +4 -4
  71. package/dist/DescriptionList-Knq5eCiY.js.map +1 -0
  72. package/dist/{Dropdown-DYYhzKSo.cjs → Dropdown-CMjURWYd.cjs} +2 -2
  73. package/dist/{Dropdown-DYYhzKSo.cjs.map → Dropdown-CMjURWYd.cjs.map} +1 -1
  74. package/dist/{Dropdown-CcC-Hwx4.js → Dropdown-CnDBlB02.js} +2 -2
  75. package/dist/{Dropdown-CcC-Hwx4.js.map → Dropdown-CnDBlB02.js.map} +1 -1
  76. package/dist/{EmptyState-DnGds1ch.cjs → EmptyState-CX1g47y_.cjs} +2 -2
  77. package/dist/{EmptyState-DnGds1ch.cjs.map → EmptyState-CX1g47y_.cjs.map} +1 -1
  78. package/dist/{EmptyState-BCoPw8jf.js → EmptyState-Dqtpmtje.js} +2 -2
  79. package/dist/{EmptyState-BCoPw8jf.js.map → EmptyState-Dqtpmtje.js.map} +1 -1
  80. package/dist/{ErrorBoundary-JCNa0_Ys.cjs → ErrorBoundary-B8KwWXXp.cjs} +2 -2
  81. package/dist/{ErrorBoundary-JCNa0_Ys.cjs.map → ErrorBoundary-B8KwWXXp.cjs.map} +1 -1
  82. package/dist/{ErrorBoundary-BILk_3fM.js → ErrorBoundary-Dos7VLb-.js} +3 -3
  83. package/dist/{ErrorBoundary-BILk_3fM.js.map → ErrorBoundary-Dos7VLb-.js.map} +1 -1
  84. package/dist/{ErrorState-MQBeyF2n.cjs → ErrorState-CwCqd2PU.cjs} +2 -2
  85. package/dist/{ErrorState-MQBeyF2n.cjs.map → ErrorState-CwCqd2PU.cjs.map} +1 -1
  86. package/dist/{ErrorState-DI28ZCJN.js → ErrorState-KhzrGIJ-.js} +7 -7
  87. package/dist/{ErrorState-DI28ZCJN.js.map → ErrorState-KhzrGIJ-.js.map} +1 -1
  88. package/dist/{FileCard-Cl88Gu6L.cjs → FileCard-DEc10T2G.cjs} +2 -2
  89. package/dist/FileCard-DEc10T2G.cjs.map +1 -0
  90. package/dist/{FileCard-5QvVkO1-.js → FileCard-SSuFS13E.js} +3 -3
  91. package/dist/FileCard-SSuFS13E.js.map +1 -0
  92. package/dist/{FileUploader-FMVbj7rz.cjs → FileUploader-D58_6kDA.cjs} +2 -2
  93. package/dist/FileUploader-D58_6kDA.cjs.map +1 -0
  94. package/dist/{FileUploader-DwAl3UXI.js → FileUploader-DfYOBFa4.js} +5 -5
  95. package/dist/FileUploader-DfYOBFa4.js.map +1 -0
  96. package/dist/{Flag-Do7x-AhS.cjs → Flag-B1ZvZVXi.cjs} +2 -2
  97. package/dist/{Flag-Do7x-AhS.cjs.map → Flag-B1ZvZVXi.cjs.map} +1 -1
  98. package/dist/{Flag-DfA2t0yd.js → Flag-BEIqYQZg.js} +2 -2
  99. package/dist/{Flag-DfA2t0yd.js.map → Flag-BEIqYQZg.js.map} +1 -1
  100. package/dist/FloatingPanel-C5c_eMQ0.js.map +1 -1
  101. package/dist/FloatingPanel-tGCG2nhA.cjs.map +1 -1
  102. package/dist/{FullscreenToggle-DM6wWZ1a.js → FullscreenToggle-I_In47BB.js} +3 -3
  103. package/dist/{FullscreenToggle-DM6wWZ1a.js.map → FullscreenToggle-I_In47BB.js.map} +1 -1
  104. package/dist/{FullscreenToggle-Bbb_z2xj.cjs → FullscreenToggle-Po769CoC.cjs} +2 -2
  105. package/dist/{FullscreenToggle-Bbb_z2xj.cjs.map → FullscreenToggle-Po769CoC.cjs.map} +1 -1
  106. package/dist/{IconButton-CQ25TtBc.cjs → IconButton-CxSXEYce.cjs} +2 -2
  107. package/dist/{IconButton-CQ25TtBc.cjs.map → IconButton-CxSXEYce.cjs.map} +1 -1
  108. package/dist/{IconButton-06pmftMo.js → IconButton-D9MCwRK_.js} +2 -2
  109. package/dist/{IconButton-06pmftMo.js.map → IconButton-D9MCwRK_.js.map} +1 -1
  110. package/dist/{List-CwuAJDTi.js → List-2Y3ktTcF.js} +2 -2
  111. package/dist/{List-CwuAJDTi.js.map → List-2Y3ktTcF.js.map} +1 -1
  112. package/dist/{List-B5Ppe9R1.cjs → List-CKoNx21F.cjs} +2 -2
  113. package/dist/{List-B5Ppe9R1.cjs.map → List-CKoNx21F.cjs.map} +1 -1
  114. package/dist/{ListItem-BWNIbyTh.js → ListItem-2Lr5_NRY.js} +15 -15
  115. package/dist/{ListItem-BWNIbyTh.js.map → ListItem-2Lr5_NRY.js.map} +1 -1
  116. package/dist/ListItem-DkCYXucd.cjs +2 -0
  117. package/dist/{ListItem-Qo1Tt6Fi.cjs.map → ListItem-DkCYXucd.cjs.map} +1 -1
  118. package/dist/{Loader-B5Pm8AaT.cjs → Loader-5zp2MPm5.cjs} +2 -2
  119. package/dist/{Loader-B5Pm8AaT.cjs.map → Loader-5zp2MPm5.cjs.map} +1 -1
  120. package/dist/{Loader-Bj5uwVR9.js → Loader-Bluu6z0-.js} +2 -2
  121. package/dist/{Loader-Bj5uwVR9.js.map → Loader-Bluu6z0-.js.map} +1 -1
  122. package/dist/{LocationPicker-D-sT4rSe.cjs → LocationPicker-CGHXTIml.cjs} +2 -2
  123. package/dist/{LocationPicker-D-sT4rSe.cjs.map → LocationPicker-CGHXTIml.cjs.map} +1 -1
  124. package/dist/{LocationPicker-Ce8aLubZ.js → LocationPicker-hULpHBVG.js} +7 -7
  125. package/dist/{LocationPicker-Ce8aLubZ.js.map → LocationPicker-hULpHBVG.js.map} +1 -1
  126. package/dist/{Modal-DTnB_mGg.js → Modal-C6Zgwz_6.js} +3 -3
  127. package/dist/Modal-C6Zgwz_6.js.map +1 -0
  128. package/dist/{Modal-DjSOhZqd.cjs → Modal-D9_OG53G.cjs} +2 -2
  129. package/dist/Modal-D9_OG53G.cjs.map +1 -0
  130. package/dist/{MultiSelect-C4RvohFY.cjs → MultiSelect-BdPvjiTj.cjs} +2 -2
  131. package/dist/{MultiSelect-C4RvohFY.cjs.map → MultiSelect-BdPvjiTj.cjs.map} +1 -1
  132. package/dist/{MultiSelect-Dn8l5z52.js → MultiSelect-CHLMpim4.js} +4 -4
  133. package/dist/{MultiSelect-Dn8l5z52.js.map → MultiSelect-CHLMpim4.js.map} +1 -1
  134. package/dist/{NumberField-DvQ5UP1R.js → NumberField-BlpFmetF.js} +3 -3
  135. package/dist/{NumberField-DvQ5UP1R.js.map → NumberField-BlpFmetF.js.map} +1 -1
  136. package/dist/{NumberField-C3TLdAgT.cjs → NumberField-C-FZ-uRI.cjs} +2 -2
  137. package/dist/{NumberField-C3TLdAgT.cjs.map → NumberField-C-FZ-uRI.cjs.map} +1 -1
  138. package/dist/OtpField-D4-r7I0A.js +174 -0
  139. package/dist/OtpField-D4-r7I0A.js.map +1 -0
  140. package/dist/OtpField-Drjy2wwq.cjs +2 -0
  141. package/dist/OtpField-Drjy2wwq.cjs.map +1 -0
  142. package/dist/{PageError-aUV0vUfB.cjs → PageError-DXUOkE14.cjs} +2 -2
  143. package/dist/{PageError-aUV0vUfB.cjs.map → PageError-DXUOkE14.cjs.map} +1 -1
  144. package/dist/{PageError-BORFaxGW.js → PageError-DyDj1wQZ.js} +5 -5
  145. package/dist/{PageError-BORFaxGW.js.map → PageError-DyDj1wQZ.js.map} +1 -1
  146. package/dist/{PageLayout-rtEl8uqS.cjs → PageLayout-CoG0AaUs.cjs} +2 -2
  147. package/dist/PageLayout-CoG0AaUs.cjs.map +1 -0
  148. package/dist/{PageLayout-ojiBEcxI.js → PageLayout-nsJa8CbT.js} +4 -4
  149. package/dist/PageLayout-nsJa8CbT.js.map +1 -0
  150. package/dist/{PageNotFound-D536Tshv.js → PageNotFound-BNNwMkwE.js} +5 -5
  151. package/dist/{PageNotFound-D536Tshv.js.map → PageNotFound-BNNwMkwE.js.map} +1 -1
  152. package/dist/{PageNotFound-f-dxrnol.cjs → PageNotFound-CGSxT_n9.cjs} +2 -2
  153. package/dist/{PageNotFound-f-dxrnol.cjs.map → PageNotFound-CGSxT_n9.cjs.map} +1 -1
  154. package/dist/Pagination-CZtewveA.cjs +2 -0
  155. package/dist/Pagination-CZtewveA.cjs.map +1 -0
  156. package/dist/Pagination-tuWRnGwR.js +139 -0
  157. package/dist/Pagination-tuWRnGwR.js.map +1 -0
  158. package/dist/PaletteField-CTPl3D43.js +56 -0
  159. package/dist/PaletteField-CTPl3D43.js.map +1 -0
  160. package/dist/PaletteField-PDcu2vUp.cjs +2 -0
  161. package/dist/PaletteField-PDcu2vUp.cjs.map +1 -0
  162. package/dist/{PhoneField-DzLTXJcw.cjs → PhoneField-BPYg5ZHW.cjs} +2 -2
  163. package/dist/{PhoneField-DzLTXJcw.cjs.map → PhoneField-BPYg5ZHW.cjs.map} +1 -1
  164. package/dist/{PhoneField-CjYw-Unw.js → PhoneField-pdWDCszb.js} +4 -4
  165. package/dist/{PhoneField-CjYw-Unw.js.map → PhoneField-pdWDCszb.js.map} +1 -1
  166. package/dist/{Popconfirm-B3GhhrRM.js → Popconfirm-CMVzLaC_.js} +3 -3
  167. package/dist/{Popconfirm-B3GhhrRM.js.map → Popconfirm-CMVzLaC_.js.map} +1 -1
  168. package/dist/{Popconfirm-CYc8ywDI.cjs → Popconfirm-cNpJmkuR.cjs} +2 -2
  169. package/dist/{Popconfirm-CYc8ywDI.cjs.map → Popconfirm-cNpJmkuR.cjs.map} +1 -1
  170. package/dist/Popover-DsYUT23r.cjs.map +1 -1
  171. package/dist/Popover-WaVH3jsN.js.map +1 -1
  172. package/dist/{Progress-ZNQrxw_Q.js → Progress-BNEFGn-O.js} +2 -2
  173. package/dist/{Progress-ZNQrxw_Q.js.map → Progress-BNEFGn-O.js.map} +1 -1
  174. package/dist/{Progress-BABBBG2y.cjs → Progress-x12Rkh06.cjs} +2 -2
  175. package/dist/{Progress-BABBBG2y.cjs.map → Progress-x12Rkh06.cjs.map} +1 -1
  176. package/dist/QrCode-CrNJZV_8.js +81 -0
  177. package/dist/QrCode-CrNJZV_8.js.map +1 -0
  178. package/dist/QrCode-TcQQE0h7.cjs +2 -0
  179. package/dist/QrCode-TcQQE0h7.cjs.map +1 -0
  180. package/dist/{RemoveDialog-ayAfGXpB.js → RemoveDialog-ARFp1UJM.js} +5 -5
  181. package/dist/{RemoveDialog-ayAfGXpB.js.map → RemoveDialog-ARFp1UJM.js.map} +1 -1
  182. package/dist/{RemoveDialog-B_Y18MeJ.cjs → RemoveDialog-IWOAQFNK.cjs} +2 -2
  183. package/dist/{RemoveDialog-B_Y18MeJ.cjs.map → RemoveDialog-IWOAQFNK.cjs.map} +1 -1
  184. package/dist/RichTextEditor-C9jT2cLl.cjs +2 -0
  185. package/dist/RichTextEditor-C9jT2cLl.cjs.map +1 -0
  186. package/dist/{RichTextEditor-itYD1PfE.js → RichTextEditor-DrwJUEYz.js} +148 -148
  187. package/dist/RichTextEditor-DrwJUEYz.js.map +1 -0
  188. package/dist/RootLayout-CZ2GQ8XA.js +647 -0
  189. package/dist/RootLayout-CZ2GQ8XA.js.map +1 -0
  190. package/dist/RootLayout-DStUP263.cjs +2 -0
  191. package/dist/RootLayout-DStUP263.cjs.map +1 -0
  192. package/dist/{Select-1FWkryTK.cjs → Select-C2DIfuoB.cjs} +2 -2
  193. package/dist/{Select-1FWkryTK.cjs.map → Select-C2DIfuoB.cjs.map} +1 -1
  194. package/dist/{Select-K0a_7ROf.js → Select-KGsA8PbI.js} +3 -3
  195. package/dist/{Select-K0a_7ROf.js.map → Select-KGsA8PbI.js.map} +1 -1
  196. package/dist/{Sidebar-Dg15hPpM.js → Sidebar-_pcwxdd8.js} +133 -131
  197. package/dist/{Sidebar-Dg15hPpM.js.map → Sidebar-_pcwxdd8.js.map} +1 -1
  198. package/dist/Sidebar-wK1_xaY_.cjs +2 -0
  199. package/dist/{Sidebar-C3-u3Agj.cjs.map → Sidebar-wK1_xaY_.cjs.map} +1 -1
  200. package/dist/Slider-CXAz9SUY.cjs +2 -0
  201. package/dist/Slider-CXAz9SUY.cjs.map +1 -0
  202. package/dist/Slider-Cpc5_dPl.js +185 -0
  203. package/dist/Slider-Cpc5_dPl.js.map +1 -0
  204. package/dist/{SpeedDial-D6me6w_m.cjs → SpeedDial-BT_boD06.cjs} +2 -2
  205. package/dist/{SpeedDial-D6me6w_m.cjs.map → SpeedDial-BT_boD06.cjs.map} +1 -1
  206. package/dist/{SpeedDial-CEBAWIYo.js → SpeedDial-SMMfes9f.js} +2 -2
  207. package/dist/{SpeedDial-CEBAWIYo.js.map → SpeedDial-SMMfes9f.js.map} +1 -1
  208. package/dist/{Stepper-wPPs57uZ.cjs → Stepper-BmA_DjTS.cjs} +2 -2
  209. package/dist/Stepper-BmA_DjTS.cjs.map +1 -0
  210. package/dist/{Stepper-BN0GsRZW.js → Stepper-CR0Mlkq7.js} +2 -2
  211. package/dist/Stepper-CR0Mlkq7.js.map +1 -0
  212. package/dist/{Table-CFl3OYlo.cjs → Table-BkjY1Lwt.cjs} +2 -2
  213. package/dist/Table-BkjY1Lwt.cjs.map +1 -0
  214. package/dist/{Table-DChIfjqj.js → Table-D-F68lcm.js} +18 -18
  215. package/dist/Table-D-F68lcm.js.map +1 -0
  216. package/dist/{Tabs-BAKPWO4g.cjs → Tabs-Cgp6D1WP.cjs} +2 -2
  217. package/dist/{Tabs-BAKPWO4g.cjs.map → Tabs-Cgp6D1WP.cjs.map} +1 -1
  218. package/dist/{Tabs-DfVFgOfs.js → Tabs-DP0aZ5TB.js} +2 -2
  219. package/dist/{Tabs-DfVFgOfs.js.map → Tabs-DP0aZ5TB.js.map} +1 -1
  220. package/dist/TagsField-9nKu6ZW4.cjs +2 -0
  221. package/dist/TagsField-9nKu6ZW4.cjs.map +1 -0
  222. package/dist/{TagsField-CoBRqcjW.js → TagsField-CcY9MTMw.js} +64 -64
  223. package/dist/TagsField-CcY9MTMw.js.map +1 -0
  224. package/dist/{TextField-0gFvIFs8.js → TextField-0WvJsHhA.js} +3 -3
  225. package/dist/{TextField-0gFvIFs8.js.map → TextField-0WvJsHhA.js.map} +1 -1
  226. package/dist/{TextField-BL6OAJcP.cjs → TextField-C5MgCQIV.cjs} +2 -2
  227. package/dist/{TextField-BL6OAJcP.cjs.map → TextField-C5MgCQIV.cjs.map} +1 -1
  228. package/dist/{ThemeToggle-BgKfcb02.cjs → ThemeToggle-BvcCxRpF.cjs} +2 -2
  229. package/dist/{ThemeToggle-BgKfcb02.cjs.map → ThemeToggle-BvcCxRpF.cjs.map} +1 -1
  230. package/dist/ThemeToggle-DmCePuTy.js +28 -0
  231. package/dist/{ThemeToggle-_SUmLxmU.js.map → ThemeToggle-DmCePuTy.js.map} +1 -1
  232. package/dist/{TimeColumns-DkJsIu1w.cjs → TimeColumns-Q-vsHFZU.cjs} +2 -2
  233. package/dist/{TimeColumns-DkJsIu1w.cjs.map → TimeColumns-Q-vsHFZU.cjs.map} +1 -1
  234. package/dist/{TimeColumns-BE1sLoRV.js → TimeColumns-WJRHQuFv.js} +2 -2
  235. package/dist/{TimeColumns-BE1sLoRV.js.map → TimeColumns-WJRHQuFv.js.map} +1 -1
  236. package/dist/TimePicker-CvbQFzBf.cjs +2 -0
  237. package/dist/{TimePicker-6nHQx0P5.cjs.map → TimePicker-CvbQFzBf.cjs.map} +1 -1
  238. package/dist/{TimePicker-Bv2qIFf9.js → TimePicker-DJDuSxAg.js} +54 -54
  239. package/dist/{TimePicker-Bv2qIFf9.js.map → TimePicker-DJDuSxAg.js.map} +1 -1
  240. package/dist/{Toaster-Fq6-ImDJ.js → Toaster-Bb5YEN5j.js} +2 -2
  241. package/dist/{Toaster-Fq6-ImDJ.js.map → Toaster-Bb5YEN5j.js.map} +1 -1
  242. package/dist/{Toaster-Brcspf7v.cjs → Toaster-Dy1AonLa.cjs} +2 -2
  243. package/dist/{Toaster-Brcspf7v.cjs.map → Toaster-Dy1AonLa.cjs.map} +1 -1
  244. package/dist/TranslatedFields-CuK5KKzE.cjs +2 -0
  245. package/dist/TranslatedFields-CuK5KKzE.cjs.map +1 -0
  246. package/dist/TranslatedFields-DKXznBtD.js +86 -0
  247. package/dist/TranslatedFields-DKXznBtD.js.map +1 -0
  248. package/dist/{UserCard-1ubnvBV6.cjs → UserCard-DbudGMvG.cjs} +2 -2
  249. package/dist/UserCard-DbudGMvG.cjs.map +1 -0
  250. package/dist/{UserCard-DcTLEHFu.js → UserCard-UG_Cwe-Y.js} +3 -3
  251. package/dist/UserCard-UG_Cwe-Y.js.map +1 -0
  252. package/dist/app/AdminRoot.d.cts +13 -3
  253. package/dist/app/AdminRoot.d.ts +13 -3
  254. package/dist/components/Alert/Alert.d.cts +1 -1
  255. package/dist/components/Alert/Alert.d.ts +1 -1
  256. package/dist/components/Alert/index.cjs +1 -1
  257. package/dist/components/Alert/index.js +1 -1
  258. package/dist/components/AuthLayout/AuthLayout.d.cts +2 -2
  259. package/dist/components/AuthLayout/AuthLayout.d.ts +2 -2
  260. package/dist/components/Breadcrumbs/Breadcrumbs.d.cts +2 -1
  261. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +2 -1
  262. package/dist/components/Breadcrumbs/index.cjs +1 -1
  263. package/dist/components/Breadcrumbs/index.js +1 -1
  264. package/dist/components/Button/index.cjs +1 -1
  265. package/dist/components/Button/index.js +1 -1
  266. package/dist/components/Card/Card.d.cts +1 -1
  267. package/dist/components/Card/Card.d.ts +1 -1
  268. package/dist/components/Card/index.cjs +1 -1
  269. package/dist/components/Card/index.js +1 -1
  270. package/dist/components/Chip/Chip.d.cts +1 -1
  271. package/dist/components/Chip/Chip.d.ts +1 -1
  272. package/dist/components/Chip/index.cjs +1 -1
  273. package/dist/components/Chip/index.js +1 -1
  274. package/dist/components/ChoiceCard/ChoiceCard.d.cts +1 -1
  275. package/dist/components/ChoiceCard/ChoiceCard.d.ts +1 -1
  276. package/dist/components/ChoiceCard/index.cjs +1 -1
  277. package/dist/components/ChoiceCard/index.js +1 -1
  278. package/dist/components/CodeBlock/CodeBlock.d.cts +1 -1
  279. package/dist/components/CodeBlock/CodeBlock.d.ts +1 -1
  280. package/dist/components/CodeBlock/index.cjs +1 -1
  281. package/dist/components/CodeBlock/index.js +1 -1
  282. package/dist/components/ColorPicker/index.cjs +1 -1
  283. package/dist/components/ColorPicker/index.js +1 -1
  284. package/dist/components/ColorRamp/index.cjs +1 -1
  285. package/dist/components/ColorRamp/index.js +1 -1
  286. package/dist/components/CopyButton/index.cjs +1 -1
  287. package/dist/components/CopyButton/index.js +1 -1
  288. package/dist/components/DatePicker/index.cjs +1 -1
  289. package/dist/components/DatePicker/index.js +1 -1
  290. package/dist/components/DateTimePicker/DateTimePicker.d.cts +2 -2
  291. package/dist/components/DateTimePicker/DateTimePicker.d.ts +2 -2
  292. package/dist/components/DateTimePicker/index.cjs +1 -1
  293. package/dist/components/DateTimePicker/index.js +1 -1
  294. package/dist/components/DescriptionList/DescriptionList.d.cts +1 -1
  295. package/dist/components/DescriptionList/DescriptionList.d.ts +1 -1
  296. package/dist/components/DescriptionList/index.cjs +1 -1
  297. package/dist/components/DescriptionList/index.js +1 -1
  298. package/dist/components/Dropdown/index.cjs +1 -1
  299. package/dist/components/Dropdown/index.js +1 -1
  300. package/dist/components/EmptyState/index.cjs +1 -1
  301. package/dist/components/EmptyState/index.js +1 -1
  302. package/dist/components/ErrorState/index.cjs +1 -1
  303. package/dist/components/ErrorState/index.js +2 -2
  304. package/dist/components/FileCard/FileCard.d.cts +5 -2
  305. package/dist/components/FileCard/FileCard.d.ts +5 -2
  306. package/dist/components/FileCard/index.cjs +1 -1
  307. package/dist/components/FileCard/index.js +1 -1
  308. package/dist/components/FileUploader/FileUploader.d.cts +5 -5
  309. package/dist/components/FileUploader/FileUploader.d.ts +5 -5
  310. package/dist/components/FileUploader/index.cjs +1 -1
  311. package/dist/components/FileUploader/index.js +1 -1
  312. package/dist/components/Flag/index.cjs +1 -1
  313. package/dist/components/Flag/index.js +1 -1
  314. package/dist/components/FloatingPanel/FloatingPanel.d.cts +6 -5
  315. package/dist/components/FloatingPanel/FloatingPanel.d.ts +6 -5
  316. package/dist/components/FullscreenToggle/index.cjs +1 -1
  317. package/dist/components/FullscreenToggle/index.js +1 -1
  318. package/dist/components/IconButton/index.cjs +1 -1
  319. package/dist/components/IconButton/index.js +1 -1
  320. package/dist/components/List/index.cjs +1 -1
  321. package/dist/components/List/index.js +2 -2
  322. package/dist/components/Loader/Loader.d.cts +1 -1
  323. package/dist/components/Loader/Loader.d.ts +1 -1
  324. package/dist/components/Loader/index.cjs +1 -1
  325. package/dist/components/Loader/index.js +1 -1
  326. package/dist/components/LocationPicker/index.cjs +1 -1
  327. package/dist/components/LocationPicker/index.js +1 -1
  328. package/dist/components/Modal/Modal.d.cts +1 -1
  329. package/dist/components/Modal/Modal.d.ts +1 -1
  330. package/dist/components/Modal/index.cjs +1 -1
  331. package/dist/components/Modal/index.js +1 -1
  332. package/dist/components/MultiSelect/index.cjs +1 -1
  333. package/dist/components/MultiSelect/index.js +1 -1
  334. package/dist/components/NumberField/index.cjs +1 -1
  335. package/dist/components/NumberField/index.js +1 -1
  336. package/dist/components/OtpField/OtpField.d.cts +1 -1
  337. package/dist/components/OtpField/OtpField.d.ts +1 -1
  338. package/dist/components/OtpField/index.cjs +1 -1
  339. package/dist/components/OtpField/index.js +1 -1
  340. package/dist/components/PageError/index.cjs +1 -1
  341. package/dist/components/PageError/index.js +1 -1
  342. package/dist/components/PageLayout/PageLayout.d.cts +2 -2
  343. package/dist/components/PageLayout/PageLayout.d.ts +2 -2
  344. package/dist/components/PageLayout/index.cjs +1 -1
  345. package/dist/components/PageLayout/index.js +1 -1
  346. package/dist/components/PageNotFound/index.cjs +1 -1
  347. package/dist/components/PageNotFound/index.js +1 -1
  348. package/dist/components/Pagination/index.cjs +1 -1
  349. package/dist/components/Pagination/index.js +1 -1
  350. package/dist/components/PaletteField/PaletteField.d.cts +8 -2
  351. package/dist/components/PaletteField/PaletteField.d.ts +8 -2
  352. package/dist/components/PaletteField/index.cjs +1 -1
  353. package/dist/components/PaletteField/index.js +1 -1
  354. package/dist/components/PhoneField/index.cjs +1 -1
  355. package/dist/components/PhoneField/index.js +1 -1
  356. package/dist/components/Popconfirm/index.cjs +1 -1
  357. package/dist/components/Popconfirm/index.js +1 -1
  358. package/dist/components/Popover/Popover.d.cts +1 -1
  359. package/dist/components/Popover/Popover.d.ts +1 -1
  360. package/dist/components/Progress/index.cjs +1 -1
  361. package/dist/components/Progress/index.js +1 -1
  362. package/dist/components/QrCode/QrCode.d.cts +5 -2
  363. package/dist/components/QrCode/QrCode.d.ts +5 -2
  364. package/dist/components/QrCode/index.cjs +1 -1
  365. package/dist/components/QrCode/index.js +1 -1
  366. package/dist/components/RemoveDialog/index.cjs +1 -1
  367. package/dist/components/RemoveDialog/index.js +1 -1
  368. package/dist/components/RichTextEditor/RichTextEditor.d.cts +1 -1
  369. package/dist/components/RichTextEditor/RichTextEditor.d.ts +1 -1
  370. package/dist/components/RichTextEditor/index.cjs +1 -1
  371. package/dist/components/RichTextEditor/index.js +1 -1
  372. package/dist/components/RootLayout/RootLayout.d.cts +26 -6
  373. package/dist/components/RootLayout/RootLayout.d.ts +26 -6
  374. package/dist/components/RootLayout/SettingsDrawer.d.cts +8 -2
  375. package/dist/components/RootLayout/SettingsDrawer.d.ts +8 -2
  376. package/dist/components/RootLayout/index.cjs +1 -1
  377. package/dist/components/RootLayout/index.d.cts +1 -1
  378. package/dist/components/RootLayout/index.d.ts +1 -1
  379. package/dist/components/RootLayout/index.js +1 -1
  380. package/dist/components/Select/index.cjs +1 -1
  381. package/dist/components/Select/index.js +1 -1
  382. package/dist/components/Sidebar/index.cjs +1 -1
  383. package/dist/components/Sidebar/index.js +1 -1
  384. package/dist/components/Slider/Slider.d.cts +2 -2
  385. package/dist/components/Slider/Slider.d.ts +2 -2
  386. package/dist/components/Slider/index.cjs +1 -1
  387. package/dist/components/Slider/index.js +1 -1
  388. package/dist/components/SpeedDial/index.cjs +1 -1
  389. package/dist/components/SpeedDial/index.js +1 -1
  390. package/dist/components/Stepper/Stepper.d.cts +2 -2
  391. package/dist/components/Stepper/Stepper.d.ts +2 -2
  392. package/dist/components/Stepper/index.cjs +1 -1
  393. package/dist/components/Stepper/index.js +1 -1
  394. package/dist/components/Table/Table.d.cts +1 -1
  395. package/dist/components/Table/Table.d.ts +1 -1
  396. package/dist/components/Table/index.cjs +1 -1
  397. package/dist/components/Table/index.js +1 -1
  398. package/dist/components/Tabs/index.cjs +1 -1
  399. package/dist/components/Tabs/index.js +1 -1
  400. package/dist/components/TagsField/TagsField.d.cts +1 -1
  401. package/dist/components/TagsField/TagsField.d.ts +1 -1
  402. package/dist/components/TagsField/index.cjs +1 -1
  403. package/dist/components/TagsField/index.js +1 -1
  404. package/dist/components/TextField/index.cjs +1 -1
  405. package/dist/components/TextField/index.js +1 -1
  406. package/dist/components/ThemeToggle/index.cjs +1 -1
  407. package/dist/components/ThemeToggle/index.js +1 -1
  408. package/dist/components/TimePicker/index.cjs +1 -1
  409. package/dist/components/TimePicker/index.js +1 -1
  410. package/dist/components/Toast/index.cjs +1 -1
  411. package/dist/components/Toast/index.js +1 -1
  412. package/dist/components/TranslatedFields/TranslatedFields.d.cts +1 -1
  413. package/dist/components/TranslatedFields/TranslatedFields.d.ts +1 -1
  414. package/dist/components/TranslatedFields/index.cjs +1 -1
  415. package/dist/components/TranslatedFields/index.js +1 -1
  416. package/dist/components/UserCard/UserCard.d.cts +6 -5
  417. package/dist/components/UserCard/UserCard.d.ts +6 -5
  418. package/dist/components/UserCard/index.cjs +1 -1
  419. package/dist/components/UserCard/index.js +1 -1
  420. package/dist/entries/app.cjs +1 -1
  421. package/dist/entries/app.js +1 -1
  422. package/dist/entries/components.cjs +1 -1
  423. package/dist/entries/components.js +56 -56
  424. package/dist/entries/i18n.cjs +1 -1
  425. package/dist/entries/i18n.js +2 -2
  426. package/dist/entries/theme.cjs +1 -1
  427. package/dist/entries/theme.d.cts +2 -2
  428. package/dist/entries/theme.d.ts +2 -2
  429. package/dist/entries/theme.js +12 -11
  430. package/dist/form/useForm.d.cts +1 -1
  431. package/dist/form/useForm.d.ts +1 -1
  432. package/dist/hooks/useMediaQuery.d.cts +3 -3
  433. package/dist/hooks/useMediaQuery.d.ts +3 -3
  434. package/dist/i18n/messages.d.cts +26 -0
  435. package/dist/i18n/messages.d.ts +26 -0
  436. package/dist/index.cjs +1 -1
  437. package/dist/index.css +3 -3
  438. package/dist/index.js +232 -231
  439. package/dist/{messages-CMgYU5p6.js → messages-BiRLMy1E.js} +228 -46
  440. package/dist/messages-BiRLMy1E.js.map +1 -0
  441. package/dist/messages-C_fRRCg6.cjs +36 -0
  442. package/dist/messages-C_fRRCg6.cjs.map +1 -0
  443. package/dist/theme/ConfigProvider.d.cts +47 -7
  444. package/dist/theme/ConfigProvider.d.ts +47 -7
  445. package/dist/theme/index.d.cts +2 -2
  446. package/dist/theme/index.d.ts +2 -2
  447. package/dist/useForm-CGbJ44Gp.js.map +1 -1
  448. package/dist/useForm-CSw6r1n1.cjs.map +1 -1
  449. package/dist/{useHomeTo-MfvJxziQ.cjs → useHomeTo-BaM7kBDh.cjs} +2 -2
  450. package/dist/{useHomeTo-MfvJxziQ.cjs.map → useHomeTo-BaM7kBDh.cjs.map} +1 -1
  451. package/dist/{useHomeTo-Ckq7scIY.js → useHomeTo-DQj9tVZI.js} +2 -2
  452. package/dist/{useHomeTo-Ckq7scIY.js.map → useHomeTo-DQj9tVZI.js.map} +1 -1
  453. package/dist/useMediaQuery-CHMrI6Dy.cjs.map +1 -1
  454. package/dist/useMediaQuery-DrDUrkmJ.js.map +1 -1
  455. package/dist/{useOptionMenu-3YlvxPAM.cjs → useOptionMenu-BKC1y6oj.cjs} +2 -2
  456. package/dist/{useOptionMenu-3YlvxPAM.cjs.map → useOptionMenu-BKC1y6oj.cjs.map} +1 -1
  457. package/dist/{useOptionMenu-BBsyUow1.js → useOptionMenu-Dom1-bqm.js} +5 -5
  458. package/dist/{useOptionMenu-BBsyUow1.js.map → useOptionMenu-Dom1-bqm.js.map} +1 -1
  459. package/package.json +1 -1
  460. package/dist/AdminRoot-CRTBGUxq.cjs +0 -2
  461. package/dist/AdminRoot-CRTBGUxq.cjs.map +0 -1
  462. package/dist/AdminRoot-JOgiNkJA.js +0 -107
  463. package/dist/AdminRoot-JOgiNkJA.js.map +0 -1
  464. package/dist/Alert-CY8iU1zd.cjs +0 -2
  465. package/dist/Alert-CY8iU1zd.cjs.map +0 -1
  466. package/dist/Alert-CtUr-0s8.js +0 -70
  467. package/dist/Alert-CtUr-0s8.js.map +0 -1
  468. package/dist/Breadcrumbs-Dqhk-dY2.js.map +0 -1
  469. package/dist/Breadcrumbs-hi6dJhfN.cjs.map +0 -1
  470. package/dist/Card-B91LGIzF.js +0 -128
  471. package/dist/Card-B91LGIzF.js.map +0 -1
  472. package/dist/Card-CkZtVNyV.cjs +0 -2
  473. package/dist/Card-CkZtVNyV.cjs.map +0 -1
  474. package/dist/Chip-B7cAHjlx.cjs.map +0 -1
  475. package/dist/Chip-D5ZZs3QH.js.map +0 -1
  476. package/dist/ChoiceCardGroup-143hR0v_.cjs +0 -2
  477. package/dist/ChoiceCardGroup-Cx8CtmPl.js +0 -180
  478. package/dist/ChoiceCardGroup-Cx8CtmPl.js.map +0 -1
  479. package/dist/CodeBlock-C3mG_seZ.cjs.map +0 -1
  480. package/dist/CodeBlock-DrWRSRmO.js.map +0 -1
  481. package/dist/ColorPicker-C1pDI4su.cjs +0 -2
  482. package/dist/ConfigProvider-B_Bb6pk1.cjs +0 -2
  483. package/dist/ConfigProvider-B_Bb6pk1.cjs.map +0 -1
  484. package/dist/ConfigProvider-DeMASTVo.js +0 -347
  485. package/dist/ConfigProvider-DeMASTVo.js.map +0 -1
  486. package/dist/DatePicker-CXRsT-lt.cjs +0 -2
  487. package/dist/DateTimePicker-B-Jjejzm.js.map +0 -1
  488. package/dist/DateTimePicker-BuTIRTUX.cjs +0 -2
  489. package/dist/DateTimePicker-BuTIRTUX.cjs.map +0 -1
  490. package/dist/DescriptionList-CG08_qwT.js.map +0 -1
  491. package/dist/DescriptionList-S9C6Tp90.cjs.map +0 -1
  492. package/dist/FileCard-5QvVkO1-.js.map +0 -1
  493. package/dist/FileCard-Cl88Gu6L.cjs.map +0 -1
  494. package/dist/FileUploader-DwAl3UXI.js.map +0 -1
  495. package/dist/FileUploader-FMVbj7rz.cjs.map +0 -1
  496. package/dist/ListItem-Qo1Tt6Fi.cjs +0 -2
  497. package/dist/Modal-DTnB_mGg.js.map +0 -1
  498. package/dist/Modal-DjSOhZqd.cjs.map +0 -1
  499. package/dist/OtpField-Dy4O1MeD.js +0 -174
  500. package/dist/OtpField-Dy4O1MeD.js.map +0 -1
  501. package/dist/OtpField-OdkuKKcV.cjs +0 -2
  502. package/dist/OtpField-OdkuKKcV.cjs.map +0 -1
  503. package/dist/PageLayout-ojiBEcxI.js.map +0 -1
  504. package/dist/PageLayout-rtEl8uqS.cjs.map +0 -1
  505. package/dist/Pagination-DoDGKGpQ.js +0 -139
  506. package/dist/Pagination-DoDGKGpQ.js.map +0 -1
  507. package/dist/Pagination-Ffv6IFIU.cjs +0 -2
  508. package/dist/Pagination-Ffv6IFIU.cjs.map +0 -1
  509. package/dist/PaletteField-ChG2VQtS.js +0 -54
  510. package/dist/PaletteField-ChG2VQtS.js.map +0 -1
  511. package/dist/PaletteField-DQ1OvXqe.cjs +0 -2
  512. package/dist/PaletteField-DQ1OvXqe.cjs.map +0 -1
  513. package/dist/QrCode-B9YbQNVc.js +0 -80
  514. package/dist/QrCode-B9YbQNVc.js.map +0 -1
  515. package/dist/QrCode-CNVYpz9j.cjs +0 -2
  516. package/dist/QrCode-CNVYpz9j.cjs.map +0 -1
  517. package/dist/RichTextEditor-DSvSaszc.cjs +0 -2
  518. package/dist/RichTextEditor-DSvSaszc.cjs.map +0 -1
  519. package/dist/RichTextEditor-itYD1PfE.js.map +0 -1
  520. package/dist/RootLayout-BlYjYAYk.js +0 -582
  521. package/dist/RootLayout-BlYjYAYk.js.map +0 -1
  522. package/dist/RootLayout-D5nlzYlH.cjs +0 -2
  523. package/dist/RootLayout-D5nlzYlH.cjs.map +0 -1
  524. package/dist/Sidebar-C3-u3Agj.cjs +0 -2
  525. package/dist/Slider-0joKXhPo.cjs +0 -2
  526. package/dist/Slider-0joKXhPo.cjs.map +0 -1
  527. package/dist/Slider-CwZYxDO0.js +0 -184
  528. package/dist/Slider-CwZYxDO0.js.map +0 -1
  529. package/dist/Stepper-BN0GsRZW.js.map +0 -1
  530. package/dist/Stepper-wPPs57uZ.cjs.map +0 -1
  531. package/dist/Table-CFl3OYlo.cjs.map +0 -1
  532. package/dist/Table-DChIfjqj.js.map +0 -1
  533. package/dist/TagsField-5mbyaFQZ.cjs +0 -2
  534. package/dist/TagsField-5mbyaFQZ.cjs.map +0 -1
  535. package/dist/TagsField-CoBRqcjW.js.map +0 -1
  536. package/dist/ThemeToggle-_SUmLxmU.js +0 -28
  537. package/dist/TimePicker-6nHQx0P5.cjs +0 -2
  538. package/dist/TranslatedFields-CVc0NvXa.cjs +0 -2
  539. package/dist/TranslatedFields-CVc0NvXa.cjs.map +0 -1
  540. package/dist/TranslatedFields-CmRhRGC_.js +0 -86
  541. package/dist/TranslatedFields-CmRhRGC_.js.map +0 -1
  542. package/dist/UserCard-1ubnvBV6.cjs.map +0 -1
  543. package/dist/UserCard-DcTLEHFu.js.map +0 -1
  544. package/dist/messages-CMgYU5p6.js.map +0 -1
  545. package/dist/messages-h22vS9zn.cjs +0 -36
  546. package/dist/messages-h22vS9zn.cjs.map +0 -1
@@ -32,9 +32,9 @@ export interface ThemeConfig {
32
32
  /** Initial color mode. */
33
33
  mode?: ThemeMode;
34
34
  /**
35
- * Default font family — the app-wide default the user's Settings choice overrides (persisted). One of
36
- * the pre-imported presets (`Inter` / `Roboto` / `Lato`) or any Google Font family name. Defaults to
37
- * `Inter`. A non-preset family is loaded on demand at runtime.
35
+ * Default font family — the app-wide default the user's Settings choice overrides (persisted). The
36
+ * pre-imported `Inter` (the only preset) or any Google Font family name. Defaults to `Inter`. Any other
37
+ * family is loaded on demand at runtime.
38
38
  */
39
39
  fontFamily?: string;
40
40
  /**
@@ -283,8 +283,9 @@ export interface HeaderConfig {
283
283
  /**
284
284
  * UI-language config for the admin panel's **own** static strings (labels, placeholders, aria-labels).
285
285
  * Distinct from `locales` (which is content-translation locales for `<TranslatedFields>`). The library
286
- * ships built-in translations (English + Georgian), so listing `languages` here is enough to get a
287
- * localized panel — no per-app setup. Any language the library doesn't ship is supplied via `messages`.
286
+ * ships built-in translations (English, Georgian, Spanish, German, Italian, French and Russian), so
287
+ * listing `languages` here is enough to get a localized panel — no per-app setup. Any language the
288
+ * library doesn't ship is supplied via `messages`.
288
289
  */
289
290
  export interface I18nConfig {
290
291
  /**
@@ -339,9 +340,34 @@ export interface Config {
339
340
  * `header` prop is merged over this (the prop wins), so a specific shell can override.
340
341
  */
341
342
  header?: HeaderConfig;
343
+ /**
344
+ * `RootLayout` sidebar config, app-wide — its default look (`sidebar.variant`), which each user can change in
345
+ * the Settings drawer, and whether the sidebar shows a `UserCard` (`sidebar.userCard`, default `false`). A
346
+ * `RootLayout` / `AdminRoot` `sidebarVariant` / `showUserCard` prop wins over them. See `SidebarConfig`.
347
+ */
348
+ sidebar?: SidebarConfig;
342
349
  /** Google Maps settings for `LocationPicker` (the API key etc.), app-wide. See `MapsConfig`. */
343
350
  maps?: MapsConfig;
344
351
  }
352
+ /** How the shell sidebar sits: a floating rounded card, or docked flush to the window edges. */
353
+ export type SidebarVariant = 'floating' | 'docked';
354
+ /** `RootLayout` sidebar config, app-wide (`config.sidebar`). */
355
+ export interface SidebarConfig {
356
+ /**
357
+ * The sidebar's **default** look. `'floating'` (default): a rounded, bordered card inset from the window
358
+ * edges. `'docked'`: on desktop (≥1280px) flush against the top, left and bottom edges, no radius, a single
359
+ * border on its right; below 1280px (the overlay drawer) it looks exactly like `'floating'`.
360
+ * Each user can change it in the Settings drawer (`useTheme().sidebarVariant`, persisted; Reset brings this
361
+ * back). A `RootLayout` / `AdminRoot` `sidebarVariant` prop wins over both.
362
+ */
363
+ variant?: SidebarVariant;
364
+ /**
365
+ * Show a **`UserCard`** at the bottom of the sidebar — the signed-in user (`header.user`) with a **Sign Out**
366
+ * button (`header.onLogout`). Default **`false`** (hidden). A `RootLayout` / `AdminRoot` `showUserCard` prop
367
+ * wins over it.
368
+ */
369
+ userCard?: boolean;
370
+ }
345
371
  /**
346
372
  * Google Maps settings, app-wide — read by `LocationPicker` (its own `apiKey` / `mapId` props win). The key is the
347
373
  * app's **browser** key (restrict it by HTTP referrer in the Google Cloud console); the Maps JavaScript API is
@@ -379,12 +405,18 @@ interface ThemeContextValue {
379
405
  tableQuery: TableQueryConfig;
380
406
  /** App-wide `RootLayout` header config (`config.header` ?? `{}`); the `RootLayout` prop merges over it. */
381
407
  header: HeaderConfig;
408
+ /** App-wide `RootLayout` sidebar config (`config.sidebar` ?? `{}`). */
409
+ sidebar: SidebarConfig;
382
410
  /** App-wide Google Maps settings (`config.maps` ?? `{}`). */
383
411
  maps: MapsConfig;
384
412
  /** Whether the shell header sticks to the top on scroll (fixed) vs scrolls away (static). Persisted. */
385
413
  headerSticky: boolean;
386
414
  /** Set + persist the header sticky/static preference (overrides `config.header.sticky`). */
387
415
  setHeaderSticky: (sticky: boolean) => void;
416
+ /** The shell sidebar's look (`floating` / `docked`). Persisted; seeded from `config.sidebar.variant`. */
417
+ sidebarVariant: SidebarVariant;
418
+ /** Set + persist the sidebar look (overrides `config.sidebar.variant`). */
419
+ setSidebarVariant: (variant: SidebarVariant) => void;
388
420
  /** The active font family (drives `--tz-font-family`). Persisted; seeded from `config.theme.fontFamily`. */
389
421
  fontFamily: string;
390
422
  /** Set + persist the font family (a preset or any Google Font name; loaded on demand). */
@@ -395,12 +427,14 @@ interface ThemeContextValue {
395
427
  setShape: (shape: ThemeShape) => void;
396
428
  /**
397
429
  * `true` while any appearance preference differs from the app's configured default — the mode, either
398
- * mode's accent, the font, the header sticky choice or the shape. Drives the Settings drawer's Reset.
430
+ * mode's accent, the font, the header sticky choice, the sidebar look or the shape. Drives the Settings
431
+ * drawer's Reset.
399
432
  */
400
433
  hasCustomPreferences: boolean;
401
434
  /**
402
435
  * Reset every appearance preference to the app's configured default (`config.theme.mode` / `fontFamily` /
403
- * `shape`, `config.header.sticky`, no accent override) and forget the saved choices, so the configured
436
+ * `shape`, `config.header.sticky`, `config.sidebar.variant`, no accent override) and forget the saved
437
+ * choices, so the configured
404
438
  * defaults apply again on the next visit. The UI language is not touched (it isn't an appearance setting).
405
439
  */
406
440
  resetPreferences: () => void;
@@ -505,6 +539,12 @@ export declare function useTableQueryConfig(): TableQueryConfig;
505
539
  * a specific shell can override the app-wide defaults.
506
540
  */
507
541
  export declare function useHeaderConfig(): HeaderConfig;
542
+ /**
543
+ * The app-wide `RootLayout` sidebar config set on `<ConfigProvider config={{ sidebar }}>` (`{}` when unset /
544
+ * outside a provider). A `RootLayout` / `AdminRoot` `sidebarVariant` prop wins over its `variant`, a
545
+ * `showUserCard` prop over its `userCard`.
546
+ */
547
+ export declare function useSidebarConfig(): SidebarConfig;
508
548
  /** The app-wide Google Maps settings (`config.maps`; `{}` when unset / outside a provider). */
509
549
  export declare function useMapsConfig(): MapsConfig;
510
550
  /** The active light / dark mode — lenient (`'light'` outside a provider), for components that only read it. */
@@ -2,6 +2,6 @@ export { applyTheme } from './applyTheme';
2
2
  export type { ThemePalette, ThemeColor } from './applyTheme';
3
3
  export { BREAKPOINTS, BREAKPOINT_ORDER, breakpointQuery, resolveResponsive } from './breakpoints';
4
4
  export type { Breakpoint, Responsive } from './breakpoints';
5
- export { ConfigProvider, useTheme, useLocales, useTranslationsNamespace, useTabsQueryKey, useNestedTabQueryKey, useStepQueryKey, useTableQueryConfig, useHeaderConfig, useMapsConfig, useColorMode, useT, useTranslations, useLanguage, DEFAULT_TABS_QUERY_KEY, DEFAULT_NESTED_TAB_QUERY_KEY, DEFAULT_STEP_QUERY_KEY, DEFAULT_FONT_FAMILY, } from './ConfigProvider';
6
- export type { Config, ThemeConfig, ThemeColors, ThemeMode, ThemeShape, ConfigProviderProps, LocaleConfig, KeysConfig, TableConfig, TableQueryConfig, HeaderConfig, HeaderUser, HeaderMenuItem, HeaderEnvironment, HeaderAction, MapsConfig, I18nConfig, } from './ConfigProvider';
5
+ export { ConfigProvider, useTheme, useLocales, useTranslationsNamespace, useTabsQueryKey, useNestedTabQueryKey, useStepQueryKey, useTableQueryConfig, useHeaderConfig, useSidebarConfig, useMapsConfig, useColorMode, useT, useTranslations, useLanguage, DEFAULT_TABS_QUERY_KEY, DEFAULT_NESTED_TAB_QUERY_KEY, DEFAULT_STEP_QUERY_KEY, DEFAULT_FONT_FAMILY, } from './ConfigProvider';
6
+ export type { Config, ThemeConfig, ThemeColors, ThemeMode, ThemeShape, ConfigProviderProps, LocaleConfig, KeysConfig, TableConfig, TableQueryConfig, HeaderConfig, HeaderUser, HeaderMenuItem, HeaderEnvironment, HeaderAction, SidebarConfig, SidebarVariant, MapsConfig, I18nConfig, } from './ConfigProvider';
7
7
  export type { Messages, MessageKey, MessageCatalog, MessageOverrides, Translator, AppMessages, AppTranslator, } from '../i18n/messages';
@@ -2,6 +2,6 @@ export { applyTheme } from './applyTheme';
2
2
  export type { ThemePalette, ThemeColor } from './applyTheme';
3
3
  export { BREAKPOINTS, BREAKPOINT_ORDER, breakpointQuery, resolveResponsive } from './breakpoints';
4
4
  export type { Breakpoint, Responsive } from './breakpoints';
5
- export { ConfigProvider, useTheme, useLocales, useTranslationsNamespace, useTabsQueryKey, useNestedTabQueryKey, useStepQueryKey, useTableQueryConfig, useHeaderConfig, useMapsConfig, useColorMode, useT, useTranslations, useLanguage, DEFAULT_TABS_QUERY_KEY, DEFAULT_NESTED_TAB_QUERY_KEY, DEFAULT_STEP_QUERY_KEY, DEFAULT_FONT_FAMILY, } from './ConfigProvider';
6
- export type { Config, ThemeConfig, ThemeColors, ThemeMode, ThemeShape, ConfigProviderProps, LocaleConfig, KeysConfig, TableConfig, TableQueryConfig, HeaderConfig, HeaderUser, HeaderMenuItem, HeaderEnvironment, HeaderAction, MapsConfig, I18nConfig, } from './ConfigProvider';
5
+ export { ConfigProvider, useTheme, useLocales, useTranslationsNamespace, useTabsQueryKey, useNestedTabQueryKey, useStepQueryKey, useTableQueryConfig, useHeaderConfig, useSidebarConfig, useMapsConfig, useColorMode, useT, useTranslations, useLanguage, DEFAULT_TABS_QUERY_KEY, DEFAULT_NESTED_TAB_QUERY_KEY, DEFAULT_STEP_QUERY_KEY, DEFAULT_FONT_FAMILY, } from './ConfigProvider';
6
+ export type { Config, ThemeConfig, ThemeColors, ThemeMode, ThemeShape, ConfigProviderProps, LocaleConfig, KeysConfig, TableConfig, TableQueryConfig, HeaderConfig, HeaderUser, HeaderMenuItem, HeaderEnvironment, HeaderAction, SidebarConfig, SidebarVariant, MapsConfig, I18nConfig, } from './ConfigProvider';
7
7
  export type { Messages, MessageKey, MessageCatalog, MessageOverrides, Translator, AppMessages, AppTranslator, } from '../i18n/messages';
@@ -1 +1 @@
1
- {"version":3,"file":"useForm-CGbJ44Gp.js","sources":["../src/hooks/useDisclosure.ts","../src/hooks/useTableQuery.ts","../src/hooks/useQueryModal.ts","../src/form/useForm.ts"],"sourcesContent":["import { useCallback, useState } from 'react'\n\nexport interface UseDisclosureReturn {\n isOpen: boolean\n open: () => void\n close: () => void\n toggle: () => void\n}\n\nexport function useDisclosure(initial = false): UseDisclosureReturn {\n const [isOpen, setIsOpen] = useState(initial)\n const open = useCallback(() => setIsOpen(true), [])\n const close = useCallback(() => setIsOpen(false), [])\n const toggle = useCallback(() => setIsOpen((v) => !v), [])\n return { isOpen, open, close, toggle }\n}\n","import { useCallback, useState } from 'react'\nimport type { TableChangeState } from '../components/Table'\n\n/** A page of rows + the total the server counted (after filters, before paging). */\nexport interface TablePage<T> {\n items: T[]\n totalCount: number\n}\n\n/**\n * The slice of a data-fetching result a server-driven table needs — matches TanStack Query's\n * `useQuery` result (`data`, `isFetching`), SWR's (`data`, `isValidating` → pass it as `isFetching`), or\n * any hand-rolled state.\n */\nexport interface TableQueryResult<T> {\n data?: TablePage<T> | null\n /** A request is in flight (the first load or a refetch). */\n isFetching?: boolean\n}\n\nexport interface UseTableQueryReturn {\n /**\n * The request's query string the table built from its page / size / search / sort / filters (via the\n * app's `config.table.query` mapping + the table's `queryMapping`) — `null` until the table has reported\n * its first state. Put it in the query key and gate the request on it: `enabled: query !== null`.\n */\n query: string | null\n /** The full state from the table's last `onChange` (page, size, search, sort, filters, params). */\n state: TableChangeState | null\n /**\n * The server-mode `<Table>` props for a fetch result — spread them on: `manualPagination`, `data`,\n * `rowCount`, `loading` and `onChange`.\n */\n props: <T>(result: TableQueryResult<T>) => {\n manualPagination: true\n data: T[]\n rowCount: number\n loading: boolean\n onChange: (state: TableChangeState) => void\n }\n}\n\n/**\n * Removes the boilerplate from a **server-driven `<Table>`**: it holds the request query string the table\n * builds on every change, and maps a fetch result back onto the table's server-mode props. The fetch stays\n * yours (TanStack Query, SWR, …) — call it at the top level with `query`:\n *\n * ```tsx\n * const table = useTableQuery()\n * const users = useQuery({\n * queryKey: ['users', table.query],\n * queryFn: () => api.users(table.query!), // → { items, totalCount }\n * enabled: table.query !== null, // wait for the table's first state — no unparameterised request\n * placeholderData: (previous) => previous, // keep the old page on screen while the next loads\n * })\n * <Table {...table.props(users)} columns={columns} searchable getRowId={(u) => u.id} />\n * ```\n *\n * `totalCount` must be the **server's** total (never `items.length`), or the pager shows a single page.\n */\nexport function useTableQuery(): UseTableQueryReturn {\n const [state, setState] = useState<TableChangeState | null>(null)\n const onChange = useCallback((next: TableChangeState) => setState(next), [])\n return {\n query: state ? state.query : null,\n state,\n props: <T>(result: TableQueryResult<T>) => ({\n manualPagination: true as const,\n data: result.data?.items ?? [],\n rowCount: result.data?.totalCount ?? 0,\n loading: Boolean(result.isFetching),\n onChange,\n }),\n }\n}\n","import { useCallback, useSyncExternalStore } from 'react'\nimport { removeQueryParam, useClearUrlOnUnmount } from './useClearUrlOnUnmount'\n\n/** Fired after every `useQueryModal` URL write, so other instances watching the same key re-read the URL. */\nconst QUERY_EVENT = 'tz:querymodal'\n/** Marker stored in `history.state` on the entry an `open()` pushed — lets `close()` step Back over it. */\nconst STATE_MARKER = '__tzQueryModal'\n\n/**\n * Identifies THIS document's pushes. `history.state` survives a reload, but the entry before a pushed one then\n * belongs to the discarded document — stepping Back into it would be a full page load, so a marker from another\n * document is treated like no marker (close just drops the param).\n */\nconst DOCUMENT_ID = Math.random().toString(36).slice(2)\n/** Keys whose `close()` has stepped Back and is waiting for the popstate — a second close is a no-op. */\nconst closing = new Set<string>()\n\n/** The value an `open()` without an argument writes (`?create=1`). */\nconst FLAG_VALUE = '1'\n\nexport interface UseQueryModalOptions {\n /**\n * Push a browser-history entry when the modal opens, so **Back closes it** (instead of leaving the page).\n * Defaults to `true`; `false` replaces the current entry instead (no history step).\n */\n push?: boolean\n /**\n * Remove the param when the component using the hook unmounts **on the same page** (the pathname it was\n * opened on is still showing) — so a modal that goes away with its page section doesn't leave a stale\n * `?customer=…` behind. After a navigation to another pathname nothing is touched. Defaults to `true`.\n */\n clearUrlOnUnmount?: boolean\n}\n\nexport interface UseQueryModalReturn {\n /** Whether the param is in the URL — pass it as the modal's `open`. */\n isOpen: boolean\n /** The param's value (e.g. the record id from `open(id)`), or `null` while closed. `'1'` for `open()`. */\n value: string | null\n /** Open: write `?<key>=<value>` (value defaults to `'1'`). Re-opening with another value swaps it in place. */\n open: (value?: string) => void\n /** Close: step Back over the entry `open()` pushed, else remove the param (e.g. after a shared link). */\n close: () => void\n}\n\nconst readParam = (key: string): string | null =>\n typeof window === 'undefined' ? null : new URLSearchParams(window.location.search).get(key)\n\nconst subscribe = (onChange: () => void) => {\n window.addEventListener('popstate', onChange)\n window.addEventListener(QUERY_EVENT, onChange)\n return () => {\n window.removeEventListener('popstate', onChange)\n window.removeEventListener(QUERY_EVENT, onChange)\n }\n}\n\n/** Write `params` into the current URL (keeping the path + hash), via push or replace, then notify. */\nfunction writeUrl(params: URLSearchParams, mode: 'push' | 'replace', state: unknown) {\n const query = params.toString()\n const url = `${window.location.pathname}${query ? `?${query}` : ''}${window.location.hash}`\n window.history[mode === 'push' ? 'pushState' : 'replaceState'](state, '', url)\n window.dispatchEvent(new Event(QUERY_EVENT))\n}\n\nconst markerFor = (key: string) => `${DOCUMENT_ID}:${key}`\nconst markedFor = (state: unknown, key: string) =>\n state != null &&\n typeof state === 'object' &&\n (state as Record<string, unknown>)[STATE_MARKER] === markerFor(key)\n\nconst withoutMarker = (state: unknown) => {\n if (state == null || typeof state !== 'object' || !(STATE_MARKER in state)) return state\n const rest = { ...(state as Record<string, unknown>) }\n delete rest[STATE_MARKER]\n return rest\n}\n\n/**\n * A modal / drawer / dialog whose **open state lives in the URL query** — `?customer=242a…` — so the page can\n * be shared or reloaded, or opened in a new tab, with the modal already open (and showing the right record).\n * Pair it with any overlay: `<Modal open={m.isOpen} onClose={m.close}>…{m.value}</Modal>`. Opening pushes a\n * history entry (Back closes the modal); closing steps back over it, or just removes the param when the modal\n * was opened from a link. Other params (`?tab=…`, a `Table`'s page / size) and the hash are kept; every\n * instance using the same `key` stays in sync. Purely opt-in — a plain `Modal` is unaffected.\n *\n * ```tsx\n * const sheet = useQueryModal('customer')\n * <Button onClick={() => sheet.open(row.id)}>View</Button>\n * <Modal open={sheet.isOpen} onClose={sheet.close} placement=\"right\" title=\"Customer\">\n * {sheet.value && <CustomerDetails id={sheet.value} />}\n * </Modal>\n * ```\n */\nexport function useQueryModal(\n key: string,\n options: UseQueryModalOptions = {},\n): UseQueryModalReturn {\n const { push = true, clearUrlOnUnmount = true } = options\n const value = useSyncExternalStore(\n subscribe,\n () => readParam(key),\n () => null,\n )\n\n const open = useCallback(\n (next: string = FLAG_VALUE) => {\n if (typeof window === 'undefined') return\n const params = new URLSearchParams(window.location.search)\n const current = params.get(key)\n if (current === next) return\n params.set(key, next)\n // already open (another record): swap in place; otherwise a new entry (Back closes) unless push=false\n if (current == null && push) {\n writeUrl(params, 'push', {\n ...((window.history.state as object | null) ?? {}),\n [STATE_MARKER]: markerFor(key),\n })\n } else {\n writeUrl(params, 'replace', window.history.state)\n }\n },\n [key, push],\n )\n\n const close = useCallback(() => {\n if (typeof window === 'undefined' || closing.has(key)) return\n const params = new URLSearchParams(window.location.search)\n if (!params.has(key)) return\n // we pushed this entry (in this document) → step Back over it (the popstate re-reads the URL); else (a\n // shared link, a reload, push=false) there is nothing of ours to go back to — just drop the param\n if (markedFor(window.history.state, key)) {\n // …and if the entry we land on still carries the param (something inside the modal — e.g. its own\n // Tabs — pushed further entries), drop it there, so Close always closes. `closing` makes a second\n // close() before the popstate a no-op (it would step Back twice and leave the page).\n closing.add(key)\n const settle = () => {\n window.removeEventListener('popstate', settle)\n closing.delete(key)\n const landed = new URLSearchParams(window.location.search)\n if (!landed.has(key)) return\n landed.delete(key)\n writeUrl(landed, 'replace', withoutMarker(window.history.state))\n }\n window.addEventListener('popstate', settle)\n window.history.back()\n return\n }\n params.delete(key)\n writeUrl(params, 'replace', withoutMarker(window.history.state))\n }, [key])\n\n // unmount on the same page → drop the param (the shared rule; deferred so StrictMode keeps a deep link)\n useClearUrlOnUnmount(key, clearUrlOnUnmount, () => {\n if (removeQueryParam(key, withoutMarker(window.history.state))) {\n window.dispatchEvent(new Event(QUERY_EVENT))\n }\n })\n\n return { isOpen: value != null, value, open, close }\n}\n","import {\n useCallback,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type Dispatch,\n type FocusEvent,\n type SetStateAction,\n type SyntheticEvent,\n} from 'react'\nimport type { TypeOf, ZodType } from 'zod'\n\n/**\n * When validation errors start showing for a field:\n * - `blurThenLive` (default) — after the field is blurred (or the form is submitted), then live on every change.\n * - `change` — from the very first keystroke.\n * - `submit` — only after a submit attempt.\n */\nexport type FormValidationMode = 'blurThenLive' | 'change' | 'submit'\n\nexport interface UseFormOptions<S extends ZodType> {\n /** Zod schema describing the whole form. Field names match the schema's top-level keys. */\n schema: S\n /** Initial values — the controlled source of truth for every field. */\n defaultValues: TypeOf<S>\n /**\n * Called with the parsed (schema-validated) values when a submit passes validation. The second\n * argument carries helpers — e.g. `reset` to clear the form on success: `(values, { reset }) => {…}`.\n */\n onSubmit?: (values: TypeOf<S>, helpers: FormHelpers<TypeOf<S>>) => void | Promise<void>\n /** When errors begin to show per field. Defaults to `blurThenLive`. */\n mode?: FormValidationMode\n /**\n * On a failed submit, smooth-scroll to (and focus) the first invalid field — the one that sits\n * **highest** on the page. Needs the submit event's form element (works with `<Form>` or any\n * `<form onSubmit={form.handleSubmit}>`). Defaults to `true`.\n */\n scrollToError?: boolean\n}\n\n/** Helpers handed to `onSubmit` (Formik-style), so you can clear or tweak the form on success. */\nexport interface FormHelpers<Values> {\n /** Reset to `defaultValues` (or the given values), clearing touched/submitted state. */\n reset: (next?: Values) => void\n /** Set one field's value. */\n setValue: <K extends keyof Values & string>(name: K, value: Values[K]) => void\n /** Replace all values. */\n setValues: Dispatch<SetStateAction<Values>>\n}\n\n/** Props returned by `field(name)` — spread directly onto a `<TextField />`. */\nexport interface FieldProps {\n name: string\n value: string\n onChange: (event: ChangeEvent<HTMLInputElement>) => void\n onBlur: (event: FocusEvent<HTMLInputElement>) => void\n error: boolean\n helperText?: string\n}\n\n/** Everything `useForm` returns — also the value carried by `<Form>`'s context. */\nexport interface FormApi<Values> {\n /** Current form values. */\n values: Values\n /** `{ field: firstErrorMessage }` for every invalid field (regardless of visibility). */\n errors: Record<string, string>\n /** Which fields have been blurred. */\n touched: Record<string, boolean>\n /** True when the whole form passes the schema. */\n isValid: boolean\n /** True once a submit has been attempted. */\n isSubmitted: boolean\n /** Number of submit attempts (increments on every `handleSubmit`) — watch it to react to each submit. */\n submitCount: number\n /** True while an async `onSubmit` is in flight. */\n isSubmitting: boolean\n /** Spread onto a `<TextField />` (or let `<Form>` + a `name` prop wire it for you). */\n field: (name: keyof Values & string) => FieldProps\n /** Imperatively set one field's value. */\n setValue: <K extends keyof Values & string>(name: K, value: Values[K]) => void\n /** Replace all values. */\n setValues: Dispatch<SetStateAction<Values>>\n /** Reset to `defaultValues` (or the given values) and clear touched/submitted state. */\n reset: (next?: Values) => void\n /** Form `onSubmit` handler — validates, then calls `onSubmit` with parsed values when valid. */\n handleSubmit: (event?: SyntheticEvent) => void\n}\n\n/**\n * Smooth-scroll to (and focus) the highest invalid field inside `scope`, matched by its `name`\n * attribute. \"Highest\" = smallest viewport `top`, so it lands on the first red field regardless of\n * DOM vs. visual order. No-op if none of the names resolve to an element.\n */\nfunction scrollToFirstError(scope: Element, names: string[]) {\n let target: HTMLElement | null = null\n let top = Number.POSITIVE_INFINITY\n for (const name of names) {\n const selector = typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(name) : name\n const el = scope.querySelector<HTMLElement>(`[name=\"${selector}\"]`)\n if (!el) continue\n const elTop = el.getBoundingClientRect().top\n if (elTop < top) {\n top = elTop\n target = el\n }\n }\n if (!target) return\n if (typeof target.scrollIntoView === 'function') {\n target.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n target.focus({ preventScroll: true })\n}\n\n/** Runs the schema and reduces Zod issues to a `{ field: firstMessage }` map. */\nfunction collectErrors(schema: ZodType, values: unknown): Record<string, string> {\n const result = schema.safeParse(values)\n if (result.success) return {}\n const errors: Record<string, string> = {}\n for (const issue of result.error.issues) {\n // path-less issues (a root `.refine()` / `.superRefine()`, e.g. password-confirm) land under a\n // reserved `_form` key so `isValid` reflects them and the message is surfaceable — instead of\n // being silently dropped (which made the form look valid while submit no-op'd).\n const key = String(issue.path[0] ?? '_form')\n if (!(key in errors)) errors[key] = issue.message // keep the first issue per field\n }\n return errors\n}\n\n/**\n * A tiny, Zod-powered form helper — the dependency-light alternative to bundling Formik in\n * every app. Give it a schema and initial values; spread `field(name)` onto a `<TextField />`\n * and it wires up `value`/`onChange`/`onBlur` and surfaces the field's validation error as\n * `error` + `helperText`. Validation follows `mode` (default: validate on blur, then live).\n * `handleSubmit` validates the whole form and calls `onSubmit` with the parsed values only when valid.\n */\nexport function useForm<S extends ZodType>({\n schema,\n defaultValues,\n onSubmit,\n mode = 'blurThenLive',\n scrollToError = true,\n}: UseFormOptions<S>): FormApi<TypeOf<S>> {\n type Values = TypeOf<S>\n\n const [values, setValues] = useState<Values>(defaultValues)\n // hold the initial values in a first-render ref so `reset`'s identity doesn't churn when the caller\n // passes an inline `defaultValues` literal (a fresh object every render)\n const defaultValuesRef = useRef(defaultValues)\n const [touched, setTouched] = useState<Record<string, boolean>>({})\n const [submitted, setSubmitted] = useState(false)\n const [submitCount, setSubmitCount] = useState(0)\n const [isSubmitting, setIsSubmitting] = useState(false)\n // synchronous re-entrancy guard — blocks a double-click before the `isSubmitting` re-render lands\n const submittingRef = useRef(false)\n\n const errors = useMemo(() => collectErrors(schema, values), [schema, values])\n const isValid = Object.keys(errors).length === 0\n\n /** Whether a field's error should currently be visible, per the chosen mode. */\n const isShown = useCallback(\n (name: string) => {\n if (mode === 'change') return true\n if (mode === 'submit') return submitted\n return submitted || touched[name] === true // blurThenLive\n },\n [mode, submitted, touched],\n )\n\n const setValue = useCallback(<K extends keyof Values & string>(name: K, value: Values[K]) => {\n setValues((prev) => ({ ...prev, [name]: value }))\n }, [])\n\n const field = useCallback(\n (name: keyof Values & string): FieldProps => {\n const raw = values[name]\n return {\n name,\n value: raw == null ? '' : String(raw),\n onChange: (event) => setValue(name, event.target.value as Values[typeof name]),\n onBlur: () => {\n // always record touched (so `FormApi.touched` is accurate in every mode); when a field's\n // error becomes *visible* is governed separately by `isShown`/`mode`\n setTouched((prev) => (prev[name] ? prev : { ...prev, [name]: true }))\n },\n error: isShown(name) && Boolean(errors[name]),\n helperText: isShown(name) ? errors[name] : undefined,\n }\n },\n [values, errors, isShown, setValue, mode],\n )\n\n const reset = useCallback((next?: Values) => {\n setValues(next ?? defaultValuesRef.current)\n setTouched({})\n setSubmitted(false)\n setSubmitCount(0)\n }, [])\n\n const handleSubmit = useCallback(\n (event?: SyntheticEvent) => {\n event?.preventDefault()\n if (submittingRef.current) return // ignore re-entrant submits while an async onSubmit is in flight\n setSubmitted(true)\n setSubmitCount((c) => c + 1)\n\n const result = schema.safeParse(values)\n if (!result.success) {\n // errors are derived + now shown (submitted); jump to the first red field if we have the form\n const scope = event?.currentTarget\n if (scrollToError && scope instanceof Element) {\n const names = result.error.issues\n .map((issue) => String(issue.path[0] ?? ''))\n .filter(Boolean)\n scrollToFirstError(scope, names)\n }\n return\n }\n\n const outcome = onSubmit?.(result.data as Values, { reset, setValue, setValues })\n if (outcome instanceof Promise) {\n submittingRef.current = true\n setIsSubmitting(true)\n const done = () => {\n submittingRef.current = false\n setIsSubmitting(false)\n }\n // clear on resolve OR reject — `.then(done, done)` also marks the rejection handled\n // (a bare `.finally` would re-throw into a discarded chain → unhandled promise rejection)\n outcome.then(done, done)\n }\n },\n [schema, values, onSubmit, reset, setValue, scrollToError],\n )\n\n // memoized so `<Form>` (which feeds this straight into context) doesn't re-render every bound field\n // on each render of the form-owning component — only when a real piece of state/identity changes\n return useMemo(\n () => ({\n /** Current form values. */\n values,\n /** `{ field: firstErrorMessage }` for every invalid field (regardless of visibility). */\n errors,\n /** Which fields have been blurred. */\n touched,\n /** True when the whole form passes the schema. */\n isValid,\n /** True once a submit has been attempted. */\n isSubmitted: submitted,\n /** Number of submit attempts (increments on every `handleSubmit`). */\n submitCount,\n /** True while an async `onSubmit` is in flight. */\n isSubmitting,\n /** Spread onto a `<TextField />`: wires value/onChange/onBlur and shows the field's error. */\n field,\n /** Imperatively set one field's value. */\n setValue,\n /** Replace all values. */\n setValues,\n /** Reset to `defaultValues` (or the given values) and clear touched/submitted state. */\n reset,\n /** Form `onSubmit` handler — validates, then calls `onSubmit` with parsed values when valid. */\n handleSubmit,\n }),\n [\n values,\n errors,\n touched,\n isValid,\n submitted,\n submitCount,\n isSubmitting,\n field,\n setValue,\n setValues,\n reset,\n handleSubmit,\n ],\n )\n}\n"],"names":["useDisclosure","initial","isOpen","setIsOpen","useState","open","useCallback","close","toggle","v","useTableQuery","state","setState","onChange","next","result","_a","_b","QUERY_EVENT","STATE_MARKER","DOCUMENT_ID","closing","FLAG_VALUE","readParam","key","subscribe","writeUrl","params","mode","query","url","markerFor","markedFor","withoutMarker","rest","useQueryModal","options","push","clearUrlOnUnmount","value","useSyncExternalStore","current","settle","landed","useClearUrlOnUnmount","removeQueryParam","scrollToFirstError","scope","names","target","top","name","selector","el","elTop","collectErrors","schema","values","errors","issue","useForm","defaultValues","onSubmit","scrollToError","setValues","defaultValuesRef","useRef","touched","setTouched","submitted","setSubmitted","submitCount","setSubmitCount","isSubmitting","setIsSubmitting","submittingRef","useMemo","isValid","isShown","setValue","prev","field","raw","event","reset","handleSubmit","c","outcome","done"],"mappings":"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"}
1
+ {"version":3,"file":"useForm-CGbJ44Gp.js","sources":["../src/hooks/useDisclosure.ts","../src/hooks/useTableQuery.ts","../src/hooks/useQueryModal.ts","../src/form/useForm.ts"],"sourcesContent":["import { useCallback, useState } from 'react'\n\nexport interface UseDisclosureReturn {\n isOpen: boolean\n open: () => void\n close: () => void\n toggle: () => void\n}\n\nexport function useDisclosure(initial = false): UseDisclosureReturn {\n const [isOpen, setIsOpen] = useState(initial)\n const open = useCallback(() => setIsOpen(true), [])\n const close = useCallback(() => setIsOpen(false), [])\n const toggle = useCallback(() => setIsOpen((v) => !v), [])\n return { isOpen, open, close, toggle }\n}\n","import { useCallback, useState } from 'react'\nimport type { TableChangeState } from '../components/Table'\n\n/** A page of rows + the total the server counted (after filters, before paging). */\nexport interface TablePage<T> {\n items: T[]\n totalCount: number\n}\n\n/**\n * The slice of a data-fetching result a server-driven table needs — matches TanStack Query's\n * `useQuery` result (`data`, `isFetching`), SWR's (`data`, `isValidating` → pass it as `isFetching`), or\n * any hand-rolled state.\n */\nexport interface TableQueryResult<T> {\n data?: TablePage<T> | null\n /** A request is in flight (the first load or a refetch). */\n isFetching?: boolean\n}\n\nexport interface UseTableQueryReturn {\n /**\n * The request's query string the table built from its page / size / search / sort / filters (via the\n * app's `config.table.query` mapping + the table's `queryMapping`) — `null` until the table has reported\n * its first state. Put it in the query key and gate the request on it: `enabled: query !== null`.\n */\n query: string | null\n /** The full state from the table's last `onChange` (page, size, search, sort, filters, params). */\n state: TableChangeState | null\n /**\n * The server-mode `<Table>` props for a fetch result — spread them on: `manualPagination`, `data`,\n * `rowCount`, `loading` and `onChange`.\n */\n props: <T>(result: TableQueryResult<T>) => {\n manualPagination: true\n data: T[]\n rowCount: number\n loading: boolean\n onChange: (state: TableChangeState) => void\n }\n}\n\n/**\n * Removes the boilerplate from a **server-driven `<Table>`**: it holds the request query string the table\n * builds on every change, and maps a fetch result back onto the table's server-mode props. The fetch stays\n * yours (TanStack Query, SWR, …) — call it at the top level with `query`:\n *\n * ```tsx\n * const table = useTableQuery()\n * const users = useQuery({\n * queryKey: ['users', table.query],\n * queryFn: () => api.users(table.query!), // → { items, totalCount }\n * enabled: table.query !== null, // wait for the table's first state — no unparameterised request\n * placeholderData: (previous) => previous, // keep the old page on screen while the next loads\n * })\n * <Table {...table.props(users)} columns={columns} searchable getRowId={(u) => u.id} />\n * ```\n *\n * `totalCount` must be the **server's** total (never `items.length`), or the pager shows a single page.\n */\nexport function useTableQuery(): UseTableQueryReturn {\n const [state, setState] = useState<TableChangeState | null>(null)\n const onChange = useCallback((next: TableChangeState) => setState(next), [])\n return {\n query: state ? state.query : null,\n state,\n props: <T>(result: TableQueryResult<T>) => ({\n manualPagination: true as const,\n data: result.data?.items ?? [],\n rowCount: result.data?.totalCount ?? 0,\n loading: Boolean(result.isFetching),\n onChange,\n }),\n }\n}\n","import { useCallback, useSyncExternalStore } from 'react'\nimport { removeQueryParam, useClearUrlOnUnmount } from './useClearUrlOnUnmount'\n\n/** Fired after every `useQueryModal` URL write, so other instances watching the same key re-read the URL. */\nconst QUERY_EVENT = 'tz:querymodal'\n/** Marker stored in `history.state` on the entry an `open()` pushed — lets `close()` step Back over it. */\nconst STATE_MARKER = '__tzQueryModal'\n\n/**\n * Identifies THIS document's pushes. `history.state` survives a reload, but the entry before a pushed one then\n * belongs to the discarded document — stepping Back into it would be a full page load, so a marker from another\n * document is treated like no marker (close just drops the param).\n */\nconst DOCUMENT_ID = Math.random().toString(36).slice(2)\n/** Keys whose `close()` has stepped Back and is waiting for the popstate — a second close is a no-op. */\nconst closing = new Set<string>()\n\n/** The value an `open()` without an argument writes (`?create=1`). */\nconst FLAG_VALUE = '1'\n\nexport interface UseQueryModalOptions {\n /**\n * Push a browser-history entry when the modal opens, so **Back closes it** (instead of leaving the page).\n * Defaults to `true`; `false` replaces the current entry instead (no history step).\n */\n push?: boolean\n /**\n * Remove the param when the component using the hook unmounts **on the same page** (the pathname it was\n * opened on is still showing) — so a modal that goes away with its page section doesn't leave a stale\n * `?customer=…` behind. After a navigation to another pathname nothing is touched. Defaults to `true`.\n */\n clearUrlOnUnmount?: boolean\n}\n\nexport interface UseQueryModalReturn {\n /** Whether the param is in the URL — pass it as the modal's `open`. */\n isOpen: boolean\n /** The param's value (e.g. the record id from `open(id)`), or `null` while closed. `'1'` for `open()`. */\n value: string | null\n /** Open: write `?<key>=<value>` (value defaults to `'1'`). Re-opening with another value swaps it in place. */\n open: (value?: string) => void\n /** Close: step Back over the entry `open()` pushed, else remove the param (e.g. after a shared link). */\n close: () => void\n}\n\nconst readParam = (key: string): string | null =>\n typeof window === 'undefined' ? null : new URLSearchParams(window.location.search).get(key)\n\nconst subscribe = (onChange: () => void) => {\n window.addEventListener('popstate', onChange)\n window.addEventListener(QUERY_EVENT, onChange)\n return () => {\n window.removeEventListener('popstate', onChange)\n window.removeEventListener(QUERY_EVENT, onChange)\n }\n}\n\n/** Write `params` into the current URL (keeping the path + hash), via push or replace, then notify. */\nfunction writeUrl(params: URLSearchParams, mode: 'push' | 'replace', state: unknown) {\n const query = params.toString()\n const url = `${window.location.pathname}${query ? `?${query}` : ''}${window.location.hash}`\n window.history[mode === 'push' ? 'pushState' : 'replaceState'](state, '', url)\n window.dispatchEvent(new Event(QUERY_EVENT))\n}\n\nconst markerFor = (key: string) => `${DOCUMENT_ID}:${key}`\nconst markedFor = (state: unknown, key: string) =>\n state != null &&\n typeof state === 'object' &&\n (state as Record<string, unknown>)[STATE_MARKER] === markerFor(key)\n\nconst withoutMarker = (state: unknown) => {\n if (state == null || typeof state !== 'object' || !(STATE_MARKER in state)) return state\n const rest = { ...(state as Record<string, unknown>) }\n delete rest[STATE_MARKER]\n return rest\n}\n\n/**\n * A modal / drawer / dialog whose **open state lives in the URL query** — `?customer=242a…` — so the page can\n * be shared or reloaded, or opened in a new tab, with the modal already open (and showing the right record).\n * Pair it with any overlay: `<Modal open={m.isOpen} onClose={m.close}>…{m.value}</Modal>`. Opening pushes a\n * history entry (Back closes the modal); closing steps back over it, or just removes the param when the modal\n * was opened from a link. Other params (`?tab=…`, a `Table`'s page / size) and the hash are kept; every\n * instance using the same `key` stays in sync. Purely opt-in — a plain `Modal` is unaffected.\n *\n * ```tsx\n * const sheet = useQueryModal('customer')\n * <Button onClick={() => sheet.open(row.id)}>View</Button>\n * <Modal open={sheet.isOpen} onClose={sheet.close} placement=\"right\" title=\"Customer\">\n * {sheet.value && <CustomerDetails id={sheet.value} />}\n * </Modal>\n * ```\n */\nexport function useQueryModal(\n key: string,\n options: UseQueryModalOptions = {},\n): UseQueryModalReturn {\n const { push = true, clearUrlOnUnmount = true } = options\n const value = useSyncExternalStore(\n subscribe,\n () => readParam(key),\n () => null,\n )\n\n const open = useCallback(\n (next: string = FLAG_VALUE) => {\n if (typeof window === 'undefined') return\n const params = new URLSearchParams(window.location.search)\n const current = params.get(key)\n if (current === next) return\n params.set(key, next)\n // already open (another record): swap in place; otherwise a new entry (Back closes) unless push=false\n if (current == null && push) {\n writeUrl(params, 'push', {\n ...((window.history.state as object | null) ?? {}),\n [STATE_MARKER]: markerFor(key),\n })\n } else {\n writeUrl(params, 'replace', window.history.state)\n }\n },\n [key, push],\n )\n\n const close = useCallback(() => {\n if (typeof window === 'undefined' || closing.has(key)) return\n const params = new URLSearchParams(window.location.search)\n if (!params.has(key)) return\n // we pushed this entry (in this document) → step Back over it (the popstate re-reads the URL); else (a\n // shared link, a reload, push=false) there is nothing of ours to go back to — just drop the param\n if (markedFor(window.history.state, key)) {\n // …and if the entry we land on still carries the param (something inside the modal — e.g. its own\n // Tabs — pushed further entries), drop it there, so Close always closes. `closing` makes a second\n // close() before the popstate a no-op (it would step Back twice and leave the page).\n closing.add(key)\n const settle = () => {\n window.removeEventListener('popstate', settle)\n closing.delete(key)\n const landed = new URLSearchParams(window.location.search)\n if (!landed.has(key)) return\n landed.delete(key)\n writeUrl(landed, 'replace', withoutMarker(window.history.state))\n }\n window.addEventListener('popstate', settle)\n window.history.back()\n return\n }\n params.delete(key)\n writeUrl(params, 'replace', withoutMarker(window.history.state))\n }, [key])\n\n // unmount on the same page → drop the param (the shared rule; deferred so StrictMode keeps a deep link)\n useClearUrlOnUnmount(key, clearUrlOnUnmount, () => {\n if (removeQueryParam(key, withoutMarker(window.history.state))) {\n window.dispatchEvent(new Event(QUERY_EVENT))\n }\n })\n\n return { isOpen: value != null, value, open, close }\n}\n","import {\n useCallback,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type Dispatch,\n type FocusEvent,\n type SetStateAction,\n type SyntheticEvent,\n} from 'react'\nimport type { TypeOf, ZodType } from 'zod'\n\n/**\n * When validation errors start showing for a field:\n * - `blurThenLive` (default) — after the field is blurred (or the form is submitted), then live on every change.\n * - `change` — from the first render (an untouched invalid field shows its error at once).\n * - `submit` — only after a submit attempt.\n */\nexport type FormValidationMode = 'blurThenLive' | 'change' | 'submit'\n\nexport interface UseFormOptions<S extends ZodType> {\n /** Zod schema describing the whole form. Field names match the schema's top-level keys. */\n schema: S\n /** Initial values — the controlled source of truth for every field. */\n defaultValues: TypeOf<S>\n /**\n * Called with the parsed (schema-validated) values when a submit passes validation. The second\n * argument carries helpers — e.g. `reset` to clear the form on success: `(values, { reset }) => {…}`.\n */\n onSubmit?: (values: TypeOf<S>, helpers: FormHelpers<TypeOf<S>>) => void | Promise<void>\n /** When errors begin to show per field. Defaults to `blurThenLive`. */\n mode?: FormValidationMode\n /**\n * On a failed submit, smooth-scroll to (and focus) the first invalid field — the one that sits\n * **highest** on the page. Needs the submit event's form element (works with `<Form>` or any\n * `<form onSubmit={form.handleSubmit}>`). Defaults to `true`.\n */\n scrollToError?: boolean\n}\n\n/** Helpers handed to `onSubmit` (Formik-style), so you can clear or tweak the form on success. */\nexport interface FormHelpers<Values> {\n /** Reset to `defaultValues` (or the given values), clearing touched/submitted state. */\n reset: (next?: Values) => void\n /** Set one field's value. */\n setValue: <K extends keyof Values & string>(name: K, value: Values[K]) => void\n /** Replace all values. */\n setValues: Dispatch<SetStateAction<Values>>\n}\n\n/** Props returned by `field(name)` — spread directly onto a `<TextField />`. */\nexport interface FieldProps {\n name: string\n value: string\n onChange: (event: ChangeEvent<HTMLInputElement>) => void\n onBlur: (event: FocusEvent<HTMLInputElement>) => void\n error: boolean\n helperText?: string\n}\n\n/** Everything `useForm` returns — also the value carried by `<Form>`'s context. */\nexport interface FormApi<Values> {\n /** Current form values. */\n values: Values\n /** `{ field: firstErrorMessage }` for every invalid field (regardless of visibility). */\n errors: Record<string, string>\n /** Which fields have been blurred. */\n touched: Record<string, boolean>\n /** True when the whole form passes the schema. */\n isValid: boolean\n /** True once a submit has been attempted. */\n isSubmitted: boolean\n /** Number of submit attempts (increments on every `handleSubmit`) — watch it to react to each submit. */\n submitCount: number\n /** True while an async `onSubmit` is in flight. */\n isSubmitting: boolean\n /** Spread onto a `<TextField />` (or let `<Form>` + a `name` prop wire it for you). */\n field: (name: keyof Values & string) => FieldProps\n /** Imperatively set one field's value. */\n setValue: <K extends keyof Values & string>(name: K, value: Values[K]) => void\n /** Replace all values. */\n setValues: Dispatch<SetStateAction<Values>>\n /** Reset to `defaultValues` (or the given values) and clear touched/submitted state. */\n reset: (next?: Values) => void\n /** Form `onSubmit` handler — validates, then calls `onSubmit` with parsed values when valid. */\n handleSubmit: (event?: SyntheticEvent) => void\n}\n\n/**\n * Smooth-scroll to (and focus) the highest invalid field inside `scope`, matched by its `name`\n * attribute. \"Highest\" = smallest viewport `top`, so it lands on the first red field regardless of\n * DOM vs. visual order. No-op if none of the names resolve to an element.\n */\nfunction scrollToFirstError(scope: Element, names: string[]) {\n let target: HTMLElement | null = null\n let top = Number.POSITIVE_INFINITY\n for (const name of names) {\n const selector = typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(name) : name\n const el = scope.querySelector<HTMLElement>(`[name=\"${selector}\"]`)\n if (!el) continue\n const elTop = el.getBoundingClientRect().top\n if (elTop < top) {\n top = elTop\n target = el\n }\n }\n if (!target) return\n if (typeof target.scrollIntoView === 'function') {\n target.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n target.focus({ preventScroll: true })\n}\n\n/** Runs the schema and reduces Zod issues to a `{ field: firstMessage }` map. */\nfunction collectErrors(schema: ZodType, values: unknown): Record<string, string> {\n const result = schema.safeParse(values)\n if (result.success) return {}\n const errors: Record<string, string> = {}\n for (const issue of result.error.issues) {\n // path-less issues (a root `.refine()` / `.superRefine()`, e.g. password-confirm) land under a\n // reserved `_form` key so `isValid` reflects them and the message is surfaceable — instead of\n // being silently dropped (which made the form look valid while submit no-op'd).\n const key = String(issue.path[0] ?? '_form')\n if (!(key in errors)) errors[key] = issue.message // keep the first issue per field\n }\n return errors\n}\n\n/**\n * A tiny, Zod-powered form helper — the dependency-light alternative to bundling Formik in\n * every app. Give it a schema and initial values; spread `field(name)` onto a `<TextField />`\n * and it wires up `value`/`onChange`/`onBlur` and surfaces the field's validation error as\n * `error` + `helperText`. Validation follows `mode` (default: validate on blur, then live).\n * `handleSubmit` validates the whole form and calls `onSubmit` with the parsed values only when valid.\n */\nexport function useForm<S extends ZodType>({\n schema,\n defaultValues,\n onSubmit,\n mode = 'blurThenLive',\n scrollToError = true,\n}: UseFormOptions<S>): FormApi<TypeOf<S>> {\n type Values = TypeOf<S>\n\n const [values, setValues] = useState<Values>(defaultValues)\n // hold the initial values in a first-render ref so `reset`'s identity doesn't churn when the caller\n // passes an inline `defaultValues` literal (a fresh object every render)\n const defaultValuesRef = useRef(defaultValues)\n const [touched, setTouched] = useState<Record<string, boolean>>({})\n const [submitted, setSubmitted] = useState(false)\n const [submitCount, setSubmitCount] = useState(0)\n const [isSubmitting, setIsSubmitting] = useState(false)\n // synchronous re-entrancy guard — blocks a double-click before the `isSubmitting` re-render lands\n const submittingRef = useRef(false)\n\n const errors = useMemo(() => collectErrors(schema, values), [schema, values])\n const isValid = Object.keys(errors).length === 0\n\n /** Whether a field's error should currently be visible, per the chosen mode. */\n const isShown = useCallback(\n (name: string) => {\n if (mode === 'change') return true\n if (mode === 'submit') return submitted\n return submitted || touched[name] === true // blurThenLive\n },\n [mode, submitted, touched],\n )\n\n const setValue = useCallback(<K extends keyof Values & string>(name: K, value: Values[K]) => {\n setValues((prev) => ({ ...prev, [name]: value }))\n }, [])\n\n const field = useCallback(\n (name: keyof Values & string): FieldProps => {\n const raw = values[name]\n return {\n name,\n value: raw == null ? '' : String(raw),\n onChange: (event) => setValue(name, event.target.value as Values[typeof name]),\n onBlur: () => {\n // always record touched (so `FormApi.touched` is accurate in every mode); when a field's\n // error becomes *visible* is governed separately by `isShown`/`mode`\n setTouched((prev) => (prev[name] ? prev : { ...prev, [name]: true }))\n },\n error: isShown(name) && Boolean(errors[name]),\n helperText: isShown(name) ? errors[name] : undefined,\n }\n },\n [values, errors, isShown, setValue, mode],\n )\n\n const reset = useCallback((next?: Values) => {\n setValues(next ?? defaultValuesRef.current)\n setTouched({})\n setSubmitted(false)\n setSubmitCount(0)\n }, [])\n\n const handleSubmit = useCallback(\n (event?: SyntheticEvent) => {\n event?.preventDefault()\n if (submittingRef.current) return // ignore re-entrant submits while an async onSubmit is in flight\n setSubmitted(true)\n setSubmitCount((c) => c + 1)\n\n const result = schema.safeParse(values)\n if (!result.success) {\n // errors are derived + now shown (submitted); jump to the first red field if we have the form\n const scope = event?.currentTarget\n if (scrollToError && scope instanceof Element) {\n const names = result.error.issues\n .map((issue) => String(issue.path[0] ?? ''))\n .filter(Boolean)\n scrollToFirstError(scope, names)\n }\n return\n }\n\n const outcome = onSubmit?.(result.data as Values, { reset, setValue, setValues })\n if (outcome instanceof Promise) {\n submittingRef.current = true\n setIsSubmitting(true)\n const done = () => {\n submittingRef.current = false\n setIsSubmitting(false)\n }\n // clear on resolve OR reject — `.then(done, done)` also marks the rejection handled\n // (a bare `.finally` would re-throw into a discarded chain → unhandled promise rejection)\n outcome.then(done, done)\n }\n },\n [schema, values, onSubmit, reset, setValue, scrollToError],\n )\n\n // memoized so `<Form>` (which feeds this straight into context) doesn't re-render every bound field\n // on each render of the form-owning component — only when a real piece of state/identity changes\n return useMemo(\n () => ({\n /** Current form values. */\n values,\n /** `{ field: firstErrorMessage }` for every invalid field (regardless of visibility). */\n errors,\n /** Which fields have been blurred. */\n touched,\n /** True when the whole form passes the schema. */\n isValid,\n /** True once a submit has been attempted. */\n isSubmitted: submitted,\n /** Number of submit attempts (increments on every `handleSubmit`). */\n submitCount,\n /** True while an async `onSubmit` is in flight. */\n isSubmitting,\n /** Spread onto a `<TextField />`: wires value/onChange/onBlur and shows the field's error. */\n field,\n /** Imperatively set one field's value. */\n setValue,\n /** Replace all values. */\n setValues,\n /** Reset to `defaultValues` (or the given values) and clear touched/submitted state. */\n reset,\n /** Form `onSubmit` handler — validates, then calls `onSubmit` with parsed values when valid. */\n handleSubmit,\n }),\n [\n values,\n errors,\n touched,\n isValid,\n submitted,\n submitCount,\n isSubmitting,\n field,\n setValue,\n setValues,\n reset,\n handleSubmit,\n ],\n )\n}\n"],"names":["useDisclosure","initial","isOpen","setIsOpen","useState","open","useCallback","close","toggle","v","useTableQuery","state","setState","onChange","next","result","_a","_b","QUERY_EVENT","STATE_MARKER","DOCUMENT_ID","closing","FLAG_VALUE","readParam","key","subscribe","writeUrl","params","mode","query","url","markerFor","markedFor","withoutMarker","rest","useQueryModal","options","push","clearUrlOnUnmount","value","useSyncExternalStore","current","settle","landed","useClearUrlOnUnmount","removeQueryParam","scrollToFirstError","scope","names","target","top","name","selector","el","elTop","collectErrors","schema","values","errors","issue","useForm","defaultValues","onSubmit","scrollToError","setValues","defaultValuesRef","useRef","touched","setTouched","submitted","setSubmitted","submitCount","setSubmitCount","isSubmitting","setIsSubmitting","submittingRef","useMemo","isValid","isShown","setValue","prev","field","raw","event","reset","handleSubmit","c","outcome","done"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useForm-CSw6r1n1.cjs","sources":["../src/hooks/useDisclosure.ts","../src/hooks/useTableQuery.ts","../src/hooks/useQueryModal.ts","../src/form/useForm.ts"],"sourcesContent":["import { useCallback, useState } from 'react'\n\nexport interface UseDisclosureReturn {\n isOpen: boolean\n open: () => void\n close: () => void\n toggle: () => void\n}\n\nexport function useDisclosure(initial = false): UseDisclosureReturn {\n const [isOpen, setIsOpen] = useState(initial)\n const open = useCallback(() => setIsOpen(true), [])\n const close = useCallback(() => setIsOpen(false), [])\n const toggle = useCallback(() => setIsOpen((v) => !v), [])\n return { isOpen, open, close, toggle }\n}\n","import { useCallback, useState } from 'react'\nimport type { TableChangeState } from '../components/Table'\n\n/** A page of rows + the total the server counted (after filters, before paging). */\nexport interface TablePage<T> {\n items: T[]\n totalCount: number\n}\n\n/**\n * The slice of a data-fetching result a server-driven table needs — matches TanStack Query's\n * `useQuery` result (`data`, `isFetching`), SWR's (`data`, `isValidating` → pass it as `isFetching`), or\n * any hand-rolled state.\n */\nexport interface TableQueryResult<T> {\n data?: TablePage<T> | null\n /** A request is in flight (the first load or a refetch). */\n isFetching?: boolean\n}\n\nexport interface UseTableQueryReturn {\n /**\n * The request's query string the table built from its page / size / search / sort / filters (via the\n * app's `config.table.query` mapping + the table's `queryMapping`) — `null` until the table has reported\n * its first state. Put it in the query key and gate the request on it: `enabled: query !== null`.\n */\n query: string | null\n /** The full state from the table's last `onChange` (page, size, search, sort, filters, params). */\n state: TableChangeState | null\n /**\n * The server-mode `<Table>` props for a fetch result — spread them on: `manualPagination`, `data`,\n * `rowCount`, `loading` and `onChange`.\n */\n props: <T>(result: TableQueryResult<T>) => {\n manualPagination: true\n data: T[]\n rowCount: number\n loading: boolean\n onChange: (state: TableChangeState) => void\n }\n}\n\n/**\n * Removes the boilerplate from a **server-driven `<Table>`**: it holds the request query string the table\n * builds on every change, and maps a fetch result back onto the table's server-mode props. The fetch stays\n * yours (TanStack Query, SWR, …) — call it at the top level with `query`:\n *\n * ```tsx\n * const table = useTableQuery()\n * const users = useQuery({\n * queryKey: ['users', table.query],\n * queryFn: () => api.users(table.query!), // → { items, totalCount }\n * enabled: table.query !== null, // wait for the table's first state — no unparameterised request\n * placeholderData: (previous) => previous, // keep the old page on screen while the next loads\n * })\n * <Table {...table.props(users)} columns={columns} searchable getRowId={(u) => u.id} />\n * ```\n *\n * `totalCount` must be the **server's** total (never `items.length`), or the pager shows a single page.\n */\nexport function useTableQuery(): UseTableQueryReturn {\n const [state, setState] = useState<TableChangeState | null>(null)\n const onChange = useCallback((next: TableChangeState) => setState(next), [])\n return {\n query: state ? state.query : null,\n state,\n props: <T>(result: TableQueryResult<T>) => ({\n manualPagination: true as const,\n data: result.data?.items ?? [],\n rowCount: result.data?.totalCount ?? 0,\n loading: Boolean(result.isFetching),\n onChange,\n }),\n }\n}\n","import { useCallback, useSyncExternalStore } from 'react'\nimport { removeQueryParam, useClearUrlOnUnmount } from './useClearUrlOnUnmount'\n\n/** Fired after every `useQueryModal` URL write, so other instances watching the same key re-read the URL. */\nconst QUERY_EVENT = 'tz:querymodal'\n/** Marker stored in `history.state` on the entry an `open()` pushed — lets `close()` step Back over it. */\nconst STATE_MARKER = '__tzQueryModal'\n\n/**\n * Identifies THIS document's pushes. `history.state` survives a reload, but the entry before a pushed one then\n * belongs to the discarded document — stepping Back into it would be a full page load, so a marker from another\n * document is treated like no marker (close just drops the param).\n */\nconst DOCUMENT_ID = Math.random().toString(36).slice(2)\n/** Keys whose `close()` has stepped Back and is waiting for the popstate — a second close is a no-op. */\nconst closing = new Set<string>()\n\n/** The value an `open()` without an argument writes (`?create=1`). */\nconst FLAG_VALUE = '1'\n\nexport interface UseQueryModalOptions {\n /**\n * Push a browser-history entry when the modal opens, so **Back closes it** (instead of leaving the page).\n * Defaults to `true`; `false` replaces the current entry instead (no history step).\n */\n push?: boolean\n /**\n * Remove the param when the component using the hook unmounts **on the same page** (the pathname it was\n * opened on is still showing) — so a modal that goes away with its page section doesn't leave a stale\n * `?customer=…` behind. After a navigation to another pathname nothing is touched. Defaults to `true`.\n */\n clearUrlOnUnmount?: boolean\n}\n\nexport interface UseQueryModalReturn {\n /** Whether the param is in the URL — pass it as the modal's `open`. */\n isOpen: boolean\n /** The param's value (e.g. the record id from `open(id)`), or `null` while closed. `'1'` for `open()`. */\n value: string | null\n /** Open: write `?<key>=<value>` (value defaults to `'1'`). Re-opening with another value swaps it in place. */\n open: (value?: string) => void\n /** Close: step Back over the entry `open()` pushed, else remove the param (e.g. after a shared link). */\n close: () => void\n}\n\nconst readParam = (key: string): string | null =>\n typeof window === 'undefined' ? null : new URLSearchParams(window.location.search).get(key)\n\nconst subscribe = (onChange: () => void) => {\n window.addEventListener('popstate', onChange)\n window.addEventListener(QUERY_EVENT, onChange)\n return () => {\n window.removeEventListener('popstate', onChange)\n window.removeEventListener(QUERY_EVENT, onChange)\n }\n}\n\n/** Write `params` into the current URL (keeping the path + hash), via push or replace, then notify. */\nfunction writeUrl(params: URLSearchParams, mode: 'push' | 'replace', state: unknown) {\n const query = params.toString()\n const url = `${window.location.pathname}${query ? `?${query}` : ''}${window.location.hash}`\n window.history[mode === 'push' ? 'pushState' : 'replaceState'](state, '', url)\n window.dispatchEvent(new Event(QUERY_EVENT))\n}\n\nconst markerFor = (key: string) => `${DOCUMENT_ID}:${key}`\nconst markedFor = (state: unknown, key: string) =>\n state != null &&\n typeof state === 'object' &&\n (state as Record<string, unknown>)[STATE_MARKER] === markerFor(key)\n\nconst withoutMarker = (state: unknown) => {\n if (state == null || typeof state !== 'object' || !(STATE_MARKER in state)) return state\n const rest = { ...(state as Record<string, unknown>) }\n delete rest[STATE_MARKER]\n return rest\n}\n\n/**\n * A modal / drawer / dialog whose **open state lives in the URL query** — `?customer=242a…` — so the page can\n * be shared or reloaded, or opened in a new tab, with the modal already open (and showing the right record).\n * Pair it with any overlay: `<Modal open={m.isOpen} onClose={m.close}>…{m.value}</Modal>`. Opening pushes a\n * history entry (Back closes the modal); closing steps back over it, or just removes the param when the modal\n * was opened from a link. Other params (`?tab=…`, a `Table`'s page / size) and the hash are kept; every\n * instance using the same `key` stays in sync. Purely opt-in — a plain `Modal` is unaffected.\n *\n * ```tsx\n * const sheet = useQueryModal('customer')\n * <Button onClick={() => sheet.open(row.id)}>View</Button>\n * <Modal open={sheet.isOpen} onClose={sheet.close} placement=\"right\" title=\"Customer\">\n * {sheet.value && <CustomerDetails id={sheet.value} />}\n * </Modal>\n * ```\n */\nexport function useQueryModal(\n key: string,\n options: UseQueryModalOptions = {},\n): UseQueryModalReturn {\n const { push = true, clearUrlOnUnmount = true } = options\n const value = useSyncExternalStore(\n subscribe,\n () => readParam(key),\n () => null,\n )\n\n const open = useCallback(\n (next: string = FLAG_VALUE) => {\n if (typeof window === 'undefined') return\n const params = new URLSearchParams(window.location.search)\n const current = params.get(key)\n if (current === next) return\n params.set(key, next)\n // already open (another record): swap in place; otherwise a new entry (Back closes) unless push=false\n if (current == null && push) {\n writeUrl(params, 'push', {\n ...((window.history.state as object | null) ?? {}),\n [STATE_MARKER]: markerFor(key),\n })\n } else {\n writeUrl(params, 'replace', window.history.state)\n }\n },\n [key, push],\n )\n\n const close = useCallback(() => {\n if (typeof window === 'undefined' || closing.has(key)) return\n const params = new URLSearchParams(window.location.search)\n if (!params.has(key)) return\n // we pushed this entry (in this document) → step Back over it (the popstate re-reads the URL); else (a\n // shared link, a reload, push=false) there is nothing of ours to go back to — just drop the param\n if (markedFor(window.history.state, key)) {\n // …and if the entry we land on still carries the param (something inside the modal — e.g. its own\n // Tabs — pushed further entries), drop it there, so Close always closes. `closing` makes a second\n // close() before the popstate a no-op (it would step Back twice and leave the page).\n closing.add(key)\n const settle = () => {\n window.removeEventListener('popstate', settle)\n closing.delete(key)\n const landed = new URLSearchParams(window.location.search)\n if (!landed.has(key)) return\n landed.delete(key)\n writeUrl(landed, 'replace', withoutMarker(window.history.state))\n }\n window.addEventListener('popstate', settle)\n window.history.back()\n return\n }\n params.delete(key)\n writeUrl(params, 'replace', withoutMarker(window.history.state))\n }, [key])\n\n // unmount on the same page → drop the param (the shared rule; deferred so StrictMode keeps a deep link)\n useClearUrlOnUnmount(key, clearUrlOnUnmount, () => {\n if (removeQueryParam(key, withoutMarker(window.history.state))) {\n window.dispatchEvent(new Event(QUERY_EVENT))\n }\n })\n\n return { isOpen: value != null, value, open, close }\n}\n","import {\n useCallback,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type Dispatch,\n type FocusEvent,\n type SetStateAction,\n type SyntheticEvent,\n} from 'react'\nimport type { TypeOf, ZodType } from 'zod'\n\n/**\n * When validation errors start showing for a field:\n * - `blurThenLive` (default) — after the field is blurred (or the form is submitted), then live on every change.\n * - `change` — from the very first keystroke.\n * - `submit` — only after a submit attempt.\n */\nexport type FormValidationMode = 'blurThenLive' | 'change' | 'submit'\n\nexport interface UseFormOptions<S extends ZodType> {\n /** Zod schema describing the whole form. Field names match the schema's top-level keys. */\n schema: S\n /** Initial values — the controlled source of truth for every field. */\n defaultValues: TypeOf<S>\n /**\n * Called with the parsed (schema-validated) values when a submit passes validation. The second\n * argument carries helpers — e.g. `reset` to clear the form on success: `(values, { reset }) => {…}`.\n */\n onSubmit?: (values: TypeOf<S>, helpers: FormHelpers<TypeOf<S>>) => void | Promise<void>\n /** When errors begin to show per field. Defaults to `blurThenLive`. */\n mode?: FormValidationMode\n /**\n * On a failed submit, smooth-scroll to (and focus) the first invalid field — the one that sits\n * **highest** on the page. Needs the submit event's form element (works with `<Form>` or any\n * `<form onSubmit={form.handleSubmit}>`). Defaults to `true`.\n */\n scrollToError?: boolean\n}\n\n/** Helpers handed to `onSubmit` (Formik-style), so you can clear or tweak the form on success. */\nexport interface FormHelpers<Values> {\n /** Reset to `defaultValues` (or the given values), clearing touched/submitted state. */\n reset: (next?: Values) => void\n /** Set one field's value. */\n setValue: <K extends keyof Values & string>(name: K, value: Values[K]) => void\n /** Replace all values. */\n setValues: Dispatch<SetStateAction<Values>>\n}\n\n/** Props returned by `field(name)` — spread directly onto a `<TextField />`. */\nexport interface FieldProps {\n name: string\n value: string\n onChange: (event: ChangeEvent<HTMLInputElement>) => void\n onBlur: (event: FocusEvent<HTMLInputElement>) => void\n error: boolean\n helperText?: string\n}\n\n/** Everything `useForm` returns — also the value carried by `<Form>`'s context. */\nexport interface FormApi<Values> {\n /** Current form values. */\n values: Values\n /** `{ field: firstErrorMessage }` for every invalid field (regardless of visibility). */\n errors: Record<string, string>\n /** Which fields have been blurred. */\n touched: Record<string, boolean>\n /** True when the whole form passes the schema. */\n isValid: boolean\n /** True once a submit has been attempted. */\n isSubmitted: boolean\n /** Number of submit attempts (increments on every `handleSubmit`) — watch it to react to each submit. */\n submitCount: number\n /** True while an async `onSubmit` is in flight. */\n isSubmitting: boolean\n /** Spread onto a `<TextField />` (or let `<Form>` + a `name` prop wire it for you). */\n field: (name: keyof Values & string) => FieldProps\n /** Imperatively set one field's value. */\n setValue: <K extends keyof Values & string>(name: K, value: Values[K]) => void\n /** Replace all values. */\n setValues: Dispatch<SetStateAction<Values>>\n /** Reset to `defaultValues` (or the given values) and clear touched/submitted state. */\n reset: (next?: Values) => void\n /** Form `onSubmit` handler — validates, then calls `onSubmit` with parsed values when valid. */\n handleSubmit: (event?: SyntheticEvent) => void\n}\n\n/**\n * Smooth-scroll to (and focus) the highest invalid field inside `scope`, matched by its `name`\n * attribute. \"Highest\" = smallest viewport `top`, so it lands on the first red field regardless of\n * DOM vs. visual order. No-op if none of the names resolve to an element.\n */\nfunction scrollToFirstError(scope: Element, names: string[]) {\n let target: HTMLElement | null = null\n let top = Number.POSITIVE_INFINITY\n for (const name of names) {\n const selector = typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(name) : name\n const el = scope.querySelector<HTMLElement>(`[name=\"${selector}\"]`)\n if (!el) continue\n const elTop = el.getBoundingClientRect().top\n if (elTop < top) {\n top = elTop\n target = el\n }\n }\n if (!target) return\n if (typeof target.scrollIntoView === 'function') {\n target.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n target.focus({ preventScroll: true })\n}\n\n/** Runs the schema and reduces Zod issues to a `{ field: firstMessage }` map. */\nfunction collectErrors(schema: ZodType, values: unknown): Record<string, string> {\n const result = schema.safeParse(values)\n if (result.success) return {}\n const errors: Record<string, string> = {}\n for (const issue of result.error.issues) {\n // path-less issues (a root `.refine()` / `.superRefine()`, e.g. password-confirm) land under a\n // reserved `_form` key so `isValid` reflects them and the message is surfaceable — instead of\n // being silently dropped (which made the form look valid while submit no-op'd).\n const key = String(issue.path[0] ?? '_form')\n if (!(key in errors)) errors[key] = issue.message // keep the first issue per field\n }\n return errors\n}\n\n/**\n * A tiny, Zod-powered form helper — the dependency-light alternative to bundling Formik in\n * every app. Give it a schema and initial values; spread `field(name)` onto a `<TextField />`\n * and it wires up `value`/`onChange`/`onBlur` and surfaces the field's validation error as\n * `error` + `helperText`. Validation follows `mode` (default: validate on blur, then live).\n * `handleSubmit` validates the whole form and calls `onSubmit` with the parsed values only when valid.\n */\nexport function useForm<S extends ZodType>({\n schema,\n defaultValues,\n onSubmit,\n mode = 'blurThenLive',\n scrollToError = true,\n}: UseFormOptions<S>): FormApi<TypeOf<S>> {\n type Values = TypeOf<S>\n\n const [values, setValues] = useState<Values>(defaultValues)\n // hold the initial values in a first-render ref so `reset`'s identity doesn't churn when the caller\n // passes an inline `defaultValues` literal (a fresh object every render)\n const defaultValuesRef = useRef(defaultValues)\n const [touched, setTouched] = useState<Record<string, boolean>>({})\n const [submitted, setSubmitted] = useState(false)\n const [submitCount, setSubmitCount] = useState(0)\n const [isSubmitting, setIsSubmitting] = useState(false)\n // synchronous re-entrancy guard — blocks a double-click before the `isSubmitting` re-render lands\n const submittingRef = useRef(false)\n\n const errors = useMemo(() => collectErrors(schema, values), [schema, values])\n const isValid = Object.keys(errors).length === 0\n\n /** Whether a field's error should currently be visible, per the chosen mode. */\n const isShown = useCallback(\n (name: string) => {\n if (mode === 'change') return true\n if (mode === 'submit') return submitted\n return submitted || touched[name] === true // blurThenLive\n },\n [mode, submitted, touched],\n )\n\n const setValue = useCallback(<K extends keyof Values & string>(name: K, value: Values[K]) => {\n setValues((prev) => ({ ...prev, [name]: value }))\n }, [])\n\n const field = useCallback(\n (name: keyof Values & string): FieldProps => {\n const raw = values[name]\n return {\n name,\n value: raw == null ? '' : String(raw),\n onChange: (event) => setValue(name, event.target.value as Values[typeof name]),\n onBlur: () => {\n // always record touched (so `FormApi.touched` is accurate in every mode); when a field's\n // error becomes *visible* is governed separately by `isShown`/`mode`\n setTouched((prev) => (prev[name] ? prev : { ...prev, [name]: true }))\n },\n error: isShown(name) && Boolean(errors[name]),\n helperText: isShown(name) ? errors[name] : undefined,\n }\n },\n [values, errors, isShown, setValue, mode],\n )\n\n const reset = useCallback((next?: Values) => {\n setValues(next ?? defaultValuesRef.current)\n setTouched({})\n setSubmitted(false)\n setSubmitCount(0)\n }, [])\n\n const handleSubmit = useCallback(\n (event?: SyntheticEvent) => {\n event?.preventDefault()\n if (submittingRef.current) return // ignore re-entrant submits while an async onSubmit is in flight\n setSubmitted(true)\n setSubmitCount((c) => c + 1)\n\n const result = schema.safeParse(values)\n if (!result.success) {\n // errors are derived + now shown (submitted); jump to the first red field if we have the form\n const scope = event?.currentTarget\n if (scrollToError && scope instanceof Element) {\n const names = result.error.issues\n .map((issue) => String(issue.path[0] ?? ''))\n .filter(Boolean)\n scrollToFirstError(scope, names)\n }\n return\n }\n\n const outcome = onSubmit?.(result.data as Values, { reset, setValue, setValues })\n if (outcome instanceof Promise) {\n submittingRef.current = true\n setIsSubmitting(true)\n const done = () => {\n submittingRef.current = false\n setIsSubmitting(false)\n }\n // clear on resolve OR reject — `.then(done, done)` also marks the rejection handled\n // (a bare `.finally` would re-throw into a discarded chain → unhandled promise rejection)\n outcome.then(done, done)\n }\n },\n [schema, values, onSubmit, reset, setValue, scrollToError],\n )\n\n // memoized so `<Form>` (which feeds this straight into context) doesn't re-render every bound field\n // on each render of the form-owning component — only when a real piece of state/identity changes\n return useMemo(\n () => ({\n /** Current form values. */\n values,\n /** `{ field: firstErrorMessage }` for every invalid field (regardless of visibility). */\n errors,\n /** Which fields have been blurred. */\n touched,\n /** True when the whole form passes the schema. */\n isValid,\n /** True once a submit has been attempted. */\n isSubmitted: submitted,\n /** Number of submit attempts (increments on every `handleSubmit`). */\n submitCount,\n /** True while an async `onSubmit` is in flight. */\n isSubmitting,\n /** Spread onto a `<TextField />`: wires value/onChange/onBlur and shows the field's error. */\n field,\n /** Imperatively set one field's value. */\n setValue,\n /** Replace all values. */\n setValues,\n /** Reset to `defaultValues` (or the given values) and clear touched/submitted state. */\n reset,\n /** Form `onSubmit` handler — validates, then calls `onSubmit` with parsed values when valid. */\n handleSubmit,\n }),\n [\n values,\n errors,\n touched,\n isValid,\n submitted,\n submitCount,\n isSubmitting,\n field,\n setValue,\n setValues,\n reset,\n handleSubmit,\n ],\n )\n}\n"],"names":["useDisclosure","initial","isOpen","setIsOpen","useState","open","useCallback","close","toggle","v","useTableQuery","state","setState","onChange","next","result","_a","_b","QUERY_EVENT","STATE_MARKER","DOCUMENT_ID","closing","FLAG_VALUE","readParam","key","subscribe","writeUrl","params","mode","query","url","markerFor","markedFor","withoutMarker","rest","useQueryModal","options","push","clearUrlOnUnmount","value","useSyncExternalStore","current","settle","landed","useClearUrlOnUnmount","removeQueryParam","scrollToFirstError","scope","names","target","top","name","selector","el","elTop","collectErrors","schema","values","errors","issue","useForm","defaultValues","onSubmit","scrollToError","setValues","defaultValuesRef","useRef","touched","setTouched","submitted","setSubmitted","submitCount","setSubmitCount","isSubmitting","setIsSubmitting","submittingRef","useMemo","isValid","isShown","setValue","prev","field","raw","event","reset","handleSubmit","c","outcome","done"],"mappings":"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"}
1
+ {"version":3,"file":"useForm-CSw6r1n1.cjs","sources":["../src/hooks/useDisclosure.ts","../src/hooks/useTableQuery.ts","../src/hooks/useQueryModal.ts","../src/form/useForm.ts"],"sourcesContent":["import { useCallback, useState } from 'react'\n\nexport interface UseDisclosureReturn {\n isOpen: boolean\n open: () => void\n close: () => void\n toggle: () => void\n}\n\nexport function useDisclosure(initial = false): UseDisclosureReturn {\n const [isOpen, setIsOpen] = useState(initial)\n const open = useCallback(() => setIsOpen(true), [])\n const close = useCallback(() => setIsOpen(false), [])\n const toggle = useCallback(() => setIsOpen((v) => !v), [])\n return { isOpen, open, close, toggle }\n}\n","import { useCallback, useState } from 'react'\nimport type { TableChangeState } from '../components/Table'\n\n/** A page of rows + the total the server counted (after filters, before paging). */\nexport interface TablePage<T> {\n items: T[]\n totalCount: number\n}\n\n/**\n * The slice of a data-fetching result a server-driven table needs — matches TanStack Query's\n * `useQuery` result (`data`, `isFetching`), SWR's (`data`, `isValidating` → pass it as `isFetching`), or\n * any hand-rolled state.\n */\nexport interface TableQueryResult<T> {\n data?: TablePage<T> | null\n /** A request is in flight (the first load or a refetch). */\n isFetching?: boolean\n}\n\nexport interface UseTableQueryReturn {\n /**\n * The request's query string the table built from its page / size / search / sort / filters (via the\n * app's `config.table.query` mapping + the table's `queryMapping`) — `null` until the table has reported\n * its first state. Put it in the query key and gate the request on it: `enabled: query !== null`.\n */\n query: string | null\n /** The full state from the table's last `onChange` (page, size, search, sort, filters, params). */\n state: TableChangeState | null\n /**\n * The server-mode `<Table>` props for a fetch result — spread them on: `manualPagination`, `data`,\n * `rowCount`, `loading` and `onChange`.\n */\n props: <T>(result: TableQueryResult<T>) => {\n manualPagination: true\n data: T[]\n rowCount: number\n loading: boolean\n onChange: (state: TableChangeState) => void\n }\n}\n\n/**\n * Removes the boilerplate from a **server-driven `<Table>`**: it holds the request query string the table\n * builds on every change, and maps a fetch result back onto the table's server-mode props. The fetch stays\n * yours (TanStack Query, SWR, …) — call it at the top level with `query`:\n *\n * ```tsx\n * const table = useTableQuery()\n * const users = useQuery({\n * queryKey: ['users', table.query],\n * queryFn: () => api.users(table.query!), // → { items, totalCount }\n * enabled: table.query !== null, // wait for the table's first state — no unparameterised request\n * placeholderData: (previous) => previous, // keep the old page on screen while the next loads\n * })\n * <Table {...table.props(users)} columns={columns} searchable getRowId={(u) => u.id} />\n * ```\n *\n * `totalCount` must be the **server's** total (never `items.length`), or the pager shows a single page.\n */\nexport function useTableQuery(): UseTableQueryReturn {\n const [state, setState] = useState<TableChangeState | null>(null)\n const onChange = useCallback((next: TableChangeState) => setState(next), [])\n return {\n query: state ? state.query : null,\n state,\n props: <T>(result: TableQueryResult<T>) => ({\n manualPagination: true as const,\n data: result.data?.items ?? [],\n rowCount: result.data?.totalCount ?? 0,\n loading: Boolean(result.isFetching),\n onChange,\n }),\n }\n}\n","import { useCallback, useSyncExternalStore } from 'react'\nimport { removeQueryParam, useClearUrlOnUnmount } from './useClearUrlOnUnmount'\n\n/** Fired after every `useQueryModal` URL write, so other instances watching the same key re-read the URL. */\nconst QUERY_EVENT = 'tz:querymodal'\n/** Marker stored in `history.state` on the entry an `open()` pushed — lets `close()` step Back over it. */\nconst STATE_MARKER = '__tzQueryModal'\n\n/**\n * Identifies THIS document's pushes. `history.state` survives a reload, but the entry before a pushed one then\n * belongs to the discarded document — stepping Back into it would be a full page load, so a marker from another\n * document is treated like no marker (close just drops the param).\n */\nconst DOCUMENT_ID = Math.random().toString(36).slice(2)\n/** Keys whose `close()` has stepped Back and is waiting for the popstate — a second close is a no-op. */\nconst closing = new Set<string>()\n\n/** The value an `open()` without an argument writes (`?create=1`). */\nconst FLAG_VALUE = '1'\n\nexport interface UseQueryModalOptions {\n /**\n * Push a browser-history entry when the modal opens, so **Back closes it** (instead of leaving the page).\n * Defaults to `true`; `false` replaces the current entry instead (no history step).\n */\n push?: boolean\n /**\n * Remove the param when the component using the hook unmounts **on the same page** (the pathname it was\n * opened on is still showing) — so a modal that goes away with its page section doesn't leave a stale\n * `?customer=…` behind. After a navigation to another pathname nothing is touched. Defaults to `true`.\n */\n clearUrlOnUnmount?: boolean\n}\n\nexport interface UseQueryModalReturn {\n /** Whether the param is in the URL — pass it as the modal's `open`. */\n isOpen: boolean\n /** The param's value (e.g. the record id from `open(id)`), or `null` while closed. `'1'` for `open()`. */\n value: string | null\n /** Open: write `?<key>=<value>` (value defaults to `'1'`). Re-opening with another value swaps it in place. */\n open: (value?: string) => void\n /** Close: step Back over the entry `open()` pushed, else remove the param (e.g. after a shared link). */\n close: () => void\n}\n\nconst readParam = (key: string): string | null =>\n typeof window === 'undefined' ? null : new URLSearchParams(window.location.search).get(key)\n\nconst subscribe = (onChange: () => void) => {\n window.addEventListener('popstate', onChange)\n window.addEventListener(QUERY_EVENT, onChange)\n return () => {\n window.removeEventListener('popstate', onChange)\n window.removeEventListener(QUERY_EVENT, onChange)\n }\n}\n\n/** Write `params` into the current URL (keeping the path + hash), via push or replace, then notify. */\nfunction writeUrl(params: URLSearchParams, mode: 'push' | 'replace', state: unknown) {\n const query = params.toString()\n const url = `${window.location.pathname}${query ? `?${query}` : ''}${window.location.hash}`\n window.history[mode === 'push' ? 'pushState' : 'replaceState'](state, '', url)\n window.dispatchEvent(new Event(QUERY_EVENT))\n}\n\nconst markerFor = (key: string) => `${DOCUMENT_ID}:${key}`\nconst markedFor = (state: unknown, key: string) =>\n state != null &&\n typeof state === 'object' &&\n (state as Record<string, unknown>)[STATE_MARKER] === markerFor(key)\n\nconst withoutMarker = (state: unknown) => {\n if (state == null || typeof state !== 'object' || !(STATE_MARKER in state)) return state\n const rest = { ...(state as Record<string, unknown>) }\n delete rest[STATE_MARKER]\n return rest\n}\n\n/**\n * A modal / drawer / dialog whose **open state lives in the URL query** — `?customer=242a…` — so the page can\n * be shared or reloaded, or opened in a new tab, with the modal already open (and showing the right record).\n * Pair it with any overlay: `<Modal open={m.isOpen} onClose={m.close}>…{m.value}</Modal>`. Opening pushes a\n * history entry (Back closes the modal); closing steps back over it, or just removes the param when the modal\n * was opened from a link. Other params (`?tab=…`, a `Table`'s page / size) and the hash are kept; every\n * instance using the same `key` stays in sync. Purely opt-in — a plain `Modal` is unaffected.\n *\n * ```tsx\n * const sheet = useQueryModal('customer')\n * <Button onClick={() => sheet.open(row.id)}>View</Button>\n * <Modal open={sheet.isOpen} onClose={sheet.close} placement=\"right\" title=\"Customer\">\n * {sheet.value && <CustomerDetails id={sheet.value} />}\n * </Modal>\n * ```\n */\nexport function useQueryModal(\n key: string,\n options: UseQueryModalOptions = {},\n): UseQueryModalReturn {\n const { push = true, clearUrlOnUnmount = true } = options\n const value = useSyncExternalStore(\n subscribe,\n () => readParam(key),\n () => null,\n )\n\n const open = useCallback(\n (next: string = FLAG_VALUE) => {\n if (typeof window === 'undefined') return\n const params = new URLSearchParams(window.location.search)\n const current = params.get(key)\n if (current === next) return\n params.set(key, next)\n // already open (another record): swap in place; otherwise a new entry (Back closes) unless push=false\n if (current == null && push) {\n writeUrl(params, 'push', {\n ...((window.history.state as object | null) ?? {}),\n [STATE_MARKER]: markerFor(key),\n })\n } else {\n writeUrl(params, 'replace', window.history.state)\n }\n },\n [key, push],\n )\n\n const close = useCallback(() => {\n if (typeof window === 'undefined' || closing.has(key)) return\n const params = new URLSearchParams(window.location.search)\n if (!params.has(key)) return\n // we pushed this entry (in this document) → step Back over it (the popstate re-reads the URL); else (a\n // shared link, a reload, push=false) there is nothing of ours to go back to — just drop the param\n if (markedFor(window.history.state, key)) {\n // …and if the entry we land on still carries the param (something inside the modal — e.g. its own\n // Tabs — pushed further entries), drop it there, so Close always closes. `closing` makes a second\n // close() before the popstate a no-op (it would step Back twice and leave the page).\n closing.add(key)\n const settle = () => {\n window.removeEventListener('popstate', settle)\n closing.delete(key)\n const landed = new URLSearchParams(window.location.search)\n if (!landed.has(key)) return\n landed.delete(key)\n writeUrl(landed, 'replace', withoutMarker(window.history.state))\n }\n window.addEventListener('popstate', settle)\n window.history.back()\n return\n }\n params.delete(key)\n writeUrl(params, 'replace', withoutMarker(window.history.state))\n }, [key])\n\n // unmount on the same page → drop the param (the shared rule; deferred so StrictMode keeps a deep link)\n useClearUrlOnUnmount(key, clearUrlOnUnmount, () => {\n if (removeQueryParam(key, withoutMarker(window.history.state))) {\n window.dispatchEvent(new Event(QUERY_EVENT))\n }\n })\n\n return { isOpen: value != null, value, open, close }\n}\n","import {\n useCallback,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type Dispatch,\n type FocusEvent,\n type SetStateAction,\n type SyntheticEvent,\n} from 'react'\nimport type { TypeOf, ZodType } from 'zod'\n\n/**\n * When validation errors start showing for a field:\n * - `blurThenLive` (default) — after the field is blurred (or the form is submitted), then live on every change.\n * - `change` — from the first render (an untouched invalid field shows its error at once).\n * - `submit` — only after a submit attempt.\n */\nexport type FormValidationMode = 'blurThenLive' | 'change' | 'submit'\n\nexport interface UseFormOptions<S extends ZodType> {\n /** Zod schema describing the whole form. Field names match the schema's top-level keys. */\n schema: S\n /** Initial values — the controlled source of truth for every field. */\n defaultValues: TypeOf<S>\n /**\n * Called with the parsed (schema-validated) values when a submit passes validation. The second\n * argument carries helpers — e.g. `reset` to clear the form on success: `(values, { reset }) => {…}`.\n */\n onSubmit?: (values: TypeOf<S>, helpers: FormHelpers<TypeOf<S>>) => void | Promise<void>\n /** When errors begin to show per field. Defaults to `blurThenLive`. */\n mode?: FormValidationMode\n /**\n * On a failed submit, smooth-scroll to (and focus) the first invalid field — the one that sits\n * **highest** on the page. Needs the submit event's form element (works with `<Form>` or any\n * `<form onSubmit={form.handleSubmit}>`). Defaults to `true`.\n */\n scrollToError?: boolean\n}\n\n/** Helpers handed to `onSubmit` (Formik-style), so you can clear or tweak the form on success. */\nexport interface FormHelpers<Values> {\n /** Reset to `defaultValues` (or the given values), clearing touched/submitted state. */\n reset: (next?: Values) => void\n /** Set one field's value. */\n setValue: <K extends keyof Values & string>(name: K, value: Values[K]) => void\n /** Replace all values. */\n setValues: Dispatch<SetStateAction<Values>>\n}\n\n/** Props returned by `field(name)` — spread directly onto a `<TextField />`. */\nexport interface FieldProps {\n name: string\n value: string\n onChange: (event: ChangeEvent<HTMLInputElement>) => void\n onBlur: (event: FocusEvent<HTMLInputElement>) => void\n error: boolean\n helperText?: string\n}\n\n/** Everything `useForm` returns — also the value carried by `<Form>`'s context. */\nexport interface FormApi<Values> {\n /** Current form values. */\n values: Values\n /** `{ field: firstErrorMessage }` for every invalid field (regardless of visibility). */\n errors: Record<string, string>\n /** Which fields have been blurred. */\n touched: Record<string, boolean>\n /** True when the whole form passes the schema. */\n isValid: boolean\n /** True once a submit has been attempted. */\n isSubmitted: boolean\n /** Number of submit attempts (increments on every `handleSubmit`) — watch it to react to each submit. */\n submitCount: number\n /** True while an async `onSubmit` is in flight. */\n isSubmitting: boolean\n /** Spread onto a `<TextField />` (or let `<Form>` + a `name` prop wire it for you). */\n field: (name: keyof Values & string) => FieldProps\n /** Imperatively set one field's value. */\n setValue: <K extends keyof Values & string>(name: K, value: Values[K]) => void\n /** Replace all values. */\n setValues: Dispatch<SetStateAction<Values>>\n /** Reset to `defaultValues` (or the given values) and clear touched/submitted state. */\n reset: (next?: Values) => void\n /** Form `onSubmit` handler — validates, then calls `onSubmit` with parsed values when valid. */\n handleSubmit: (event?: SyntheticEvent) => void\n}\n\n/**\n * Smooth-scroll to (and focus) the highest invalid field inside `scope`, matched by its `name`\n * attribute. \"Highest\" = smallest viewport `top`, so it lands on the first red field regardless of\n * DOM vs. visual order. No-op if none of the names resolve to an element.\n */\nfunction scrollToFirstError(scope: Element, names: string[]) {\n let target: HTMLElement | null = null\n let top = Number.POSITIVE_INFINITY\n for (const name of names) {\n const selector = typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(name) : name\n const el = scope.querySelector<HTMLElement>(`[name=\"${selector}\"]`)\n if (!el) continue\n const elTop = el.getBoundingClientRect().top\n if (elTop < top) {\n top = elTop\n target = el\n }\n }\n if (!target) return\n if (typeof target.scrollIntoView === 'function') {\n target.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n target.focus({ preventScroll: true })\n}\n\n/** Runs the schema and reduces Zod issues to a `{ field: firstMessage }` map. */\nfunction collectErrors(schema: ZodType, values: unknown): Record<string, string> {\n const result = schema.safeParse(values)\n if (result.success) return {}\n const errors: Record<string, string> = {}\n for (const issue of result.error.issues) {\n // path-less issues (a root `.refine()` / `.superRefine()`, e.g. password-confirm) land under a\n // reserved `_form` key so `isValid` reflects them and the message is surfaceable — instead of\n // being silently dropped (which made the form look valid while submit no-op'd).\n const key = String(issue.path[0] ?? '_form')\n if (!(key in errors)) errors[key] = issue.message // keep the first issue per field\n }\n return errors\n}\n\n/**\n * A tiny, Zod-powered form helper — the dependency-light alternative to bundling Formik in\n * every app. Give it a schema and initial values; spread `field(name)` onto a `<TextField />`\n * and it wires up `value`/`onChange`/`onBlur` and surfaces the field's validation error as\n * `error` + `helperText`. Validation follows `mode` (default: validate on blur, then live).\n * `handleSubmit` validates the whole form and calls `onSubmit` with the parsed values only when valid.\n */\nexport function useForm<S extends ZodType>({\n schema,\n defaultValues,\n onSubmit,\n mode = 'blurThenLive',\n scrollToError = true,\n}: UseFormOptions<S>): FormApi<TypeOf<S>> {\n type Values = TypeOf<S>\n\n const [values, setValues] = useState<Values>(defaultValues)\n // hold the initial values in a first-render ref so `reset`'s identity doesn't churn when the caller\n // passes an inline `defaultValues` literal (a fresh object every render)\n const defaultValuesRef = useRef(defaultValues)\n const [touched, setTouched] = useState<Record<string, boolean>>({})\n const [submitted, setSubmitted] = useState(false)\n const [submitCount, setSubmitCount] = useState(0)\n const [isSubmitting, setIsSubmitting] = useState(false)\n // synchronous re-entrancy guard — blocks a double-click before the `isSubmitting` re-render lands\n const submittingRef = useRef(false)\n\n const errors = useMemo(() => collectErrors(schema, values), [schema, values])\n const isValid = Object.keys(errors).length === 0\n\n /** Whether a field's error should currently be visible, per the chosen mode. */\n const isShown = useCallback(\n (name: string) => {\n if (mode === 'change') return true\n if (mode === 'submit') return submitted\n return submitted || touched[name] === true // blurThenLive\n },\n [mode, submitted, touched],\n )\n\n const setValue = useCallback(<K extends keyof Values & string>(name: K, value: Values[K]) => {\n setValues((prev) => ({ ...prev, [name]: value }))\n }, [])\n\n const field = useCallback(\n (name: keyof Values & string): FieldProps => {\n const raw = values[name]\n return {\n name,\n value: raw == null ? '' : String(raw),\n onChange: (event) => setValue(name, event.target.value as Values[typeof name]),\n onBlur: () => {\n // always record touched (so `FormApi.touched` is accurate in every mode); when a field's\n // error becomes *visible* is governed separately by `isShown`/`mode`\n setTouched((prev) => (prev[name] ? prev : { ...prev, [name]: true }))\n },\n error: isShown(name) && Boolean(errors[name]),\n helperText: isShown(name) ? errors[name] : undefined,\n }\n },\n [values, errors, isShown, setValue, mode],\n )\n\n const reset = useCallback((next?: Values) => {\n setValues(next ?? defaultValuesRef.current)\n setTouched({})\n setSubmitted(false)\n setSubmitCount(0)\n }, [])\n\n const handleSubmit = useCallback(\n (event?: SyntheticEvent) => {\n event?.preventDefault()\n if (submittingRef.current) return // ignore re-entrant submits while an async onSubmit is in flight\n setSubmitted(true)\n setSubmitCount((c) => c + 1)\n\n const result = schema.safeParse(values)\n if (!result.success) {\n // errors are derived + now shown (submitted); jump to the first red field if we have the form\n const scope = event?.currentTarget\n if (scrollToError && scope instanceof Element) {\n const names = result.error.issues\n .map((issue) => String(issue.path[0] ?? ''))\n .filter(Boolean)\n scrollToFirstError(scope, names)\n }\n return\n }\n\n const outcome = onSubmit?.(result.data as Values, { reset, setValue, setValues })\n if (outcome instanceof Promise) {\n submittingRef.current = true\n setIsSubmitting(true)\n const done = () => {\n submittingRef.current = false\n setIsSubmitting(false)\n }\n // clear on resolve OR reject — `.then(done, done)` also marks the rejection handled\n // (a bare `.finally` would re-throw into a discarded chain → unhandled promise rejection)\n outcome.then(done, done)\n }\n },\n [schema, values, onSubmit, reset, setValue, scrollToError],\n )\n\n // memoized so `<Form>` (which feeds this straight into context) doesn't re-render every bound field\n // on each render of the form-owning component — only when a real piece of state/identity changes\n return useMemo(\n () => ({\n /** Current form values. */\n values,\n /** `{ field: firstErrorMessage }` for every invalid field (regardless of visibility). */\n errors,\n /** Which fields have been blurred. */\n touched,\n /** True when the whole form passes the schema. */\n isValid,\n /** True once a submit has been attempted. */\n isSubmitted: submitted,\n /** Number of submit attempts (increments on every `handleSubmit`). */\n submitCount,\n /** True while an async `onSubmit` is in flight. */\n isSubmitting,\n /** Spread onto a `<TextField />`: wires value/onChange/onBlur and shows the field's error. */\n field,\n /** Imperatively set one field's value. */\n setValue,\n /** Replace all values. */\n setValues,\n /** Reset to `defaultValues` (or the given values) and clear touched/submitted state. */\n reset,\n /** Form `onSubmit` handler — validates, then calls `onSubmit` with parsed values when valid. */\n handleSubmit,\n }),\n [\n values,\n errors,\n touched,\n isValid,\n submitted,\n submitCount,\n isSubmitting,\n field,\n setValue,\n setValues,\n reset,\n handleSubmit,\n ],\n )\n}\n"],"names":["useDisclosure","initial","isOpen","setIsOpen","useState","open","useCallback","close","toggle","v","useTableQuery","state","setState","onChange","next","result","_a","_b","QUERY_EVENT","STATE_MARKER","DOCUMENT_ID","closing","FLAG_VALUE","readParam","key","subscribe","writeUrl","params","mode","query","url","markerFor","markedFor","withoutMarker","rest","useQueryModal","options","push","clearUrlOnUnmount","value","useSyncExternalStore","current","settle","landed","useClearUrlOnUnmount","removeQueryParam","scrollToFirstError","scope","names","target","top","name","selector","el","elTop","collectErrors","schema","values","errors","issue","useForm","defaultValues","onSubmit","scrollToError","setValues","defaultValuesRef","useRef","touched","setTouched","submitted","setSubmitted","submitCount","setSubmitCount","isSubmitting","setIsSubmitting","submittingRef","useMemo","isValid","isShown","setValue","prev","field","raw","event","reset","handleSubmit","c","outcome","done"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";const n=require("react"),l=require("@tanstack/react-router"),c=require("./access-DPUHbE-S.cjs"),o=require("./Sidebar-C3-u3Agj.cjs");function f(r){const s=l.useRouter({warn:!1}),a=c.useAccessKeys(),u=n.useMemo(()=>{if(r!=null)return r;if(!s)return;const i=o.buildNavTree(Object.values(s.looseRoutesById).map(t=>{var e;return{fullPath:t.fullPath,staticData:(e=t.options)==null?void 0:e.staticData}}).filter(t=>{var e;return c.hasAccess((e=t.staticData)==null?void 0:e.roles)}));return o.firstNavTo(i)??"/"},[s,r,a]);return{router:s,homeTo:u}}exports.useHomeTo=f;
2
- //# sourceMappingURL=useHomeTo-MfvJxziQ.cjs.map
1
+ "use strict";const n=require("react"),l=require("@tanstack/react-router"),c=require("./access-DPUHbE-S.cjs"),o=require("./Sidebar-wK1_xaY_.cjs");function f(r){const s=l.useRouter({warn:!1}),a=c.useAccessKeys(),u=n.useMemo(()=>{if(r!=null)return r;if(!s)return;const i=o.buildNavTree(Object.values(s.looseRoutesById).map(t=>{var e;return{fullPath:t.fullPath,staticData:(e=t.options)==null?void 0:e.staticData}}).filter(t=>{var e;return c.hasAccess((e=t.staticData)==null?void 0:e.roles)}));return o.firstNavTo(i)??"/"},[s,r,a]);return{router:s,homeTo:u}}exports.useHomeTo=f;
2
+ //# sourceMappingURL=useHomeTo-BaM7kBDh.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useHomeTo-MfvJxziQ.cjs","sources":["../src/components/PageNotFound/useHomeTo.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport { useRouter } from '@tanstack/react-router'\nimport { hasAccess, useAccessKeys } from '../../helpers/access'\nimport { buildNavTree, firstNavTo } from '../Sidebar/Sidebar'\n\n/**\n * Internal: the \"home\" a full-page state sends the user back to — the **first allowed menu page** (RBAC-aware,\n * the same target as `FirstRouteRedirect`), falling back to `/`; `to` overrides it. Also returns the router\n * (lenient: `undefined` outside a `<RouterProvider>`, so the page renders without its home action). Shared by\n * `PageNotFound` and `PageError`.\n */\nexport function useHomeTo(to?: string) {\n const router = useRouter({ warn: false })\n const accessKeys = useAccessKeys()\n const homeTo = useMemo(() => {\n if (to != null) return to\n if (!router) return undefined\n const tree = buildNavTree(\n Object.values(router.looseRoutesById)\n .map((route) => ({ fullPath: route.fullPath, staticData: route.options?.staticData }))\n .filter((route) => hasAccess(route.staticData?.roles)),\n )\n return firstNavTo(tree) ?? '/'\n // accessKeys: recompute when the user's roles change\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, to, accessKeys])\n return { router, homeTo }\n}\n"],"names":["useHomeTo","to","router","useRouter","accessKeys","useAccessKeys","homeTo","useMemo","tree","buildNavTree","route","_a","hasAccess","firstNavTo"],"mappings":"iJAWO,SAASA,EAAUC,EAAa,CACrC,MAAMC,EAASC,EAAAA,UAAU,CAAE,KAAM,GAAO,EAClCC,EAAaC,EAAAA,cAAA,EACbC,EAASC,EAAAA,QAAQ,IAAM,CAC3B,GAAIN,GAAM,KAAM,OAAOA,EACvB,GAAI,CAACC,EAAQ,OACb,MAAMM,EAAOC,EAAAA,aACX,OAAO,OAAOP,EAAO,eAAe,EACjC,IAAKQ,UAAW,OAAE,SAAUA,EAAM,SAAU,YAAYC,EAAAD,EAAM,UAAN,YAAAC,EAAe,YAAa,EACpF,OAAQD,GAAA,OAAUE,OAAAA,aAAUD,EAAAD,EAAM,aAAN,YAAAC,EAAkB,KAAK,EAAC,CAAA,EAEzD,OAAOE,EAAAA,WAAWL,CAAI,GAAK,GAG7B,EAAG,CAACN,EAAQD,EAAIG,CAAU,CAAC,EAC3B,MAAO,CAAE,OAAAF,EAAQ,OAAAI,CAAA,CACnB"}
1
+ {"version":3,"file":"useHomeTo-BaM7kBDh.cjs","sources":["../src/components/PageNotFound/useHomeTo.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport { useRouter } from '@tanstack/react-router'\nimport { hasAccess, useAccessKeys } from '../../helpers/access'\nimport { buildNavTree, firstNavTo } from '../Sidebar/Sidebar'\n\n/**\n * Internal: the \"home\" a full-page state sends the user back to — the **first allowed menu page** (RBAC-aware,\n * the same target as `FirstRouteRedirect`), falling back to `/`; `to` overrides it. Also returns the router\n * (lenient: `undefined` outside a `<RouterProvider>`, so the page renders without its home action). Shared by\n * `PageNotFound` and `PageError`.\n */\nexport function useHomeTo(to?: string) {\n const router = useRouter({ warn: false })\n const accessKeys = useAccessKeys()\n const homeTo = useMemo(() => {\n if (to != null) return to\n if (!router) return undefined\n const tree = buildNavTree(\n Object.values(router.looseRoutesById)\n .map((route) => ({ fullPath: route.fullPath, staticData: route.options?.staticData }))\n .filter((route) => hasAccess(route.staticData?.roles)),\n )\n return firstNavTo(tree) ?? '/'\n // accessKeys: recompute when the user's roles change\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, to, accessKeys])\n return { router, homeTo }\n}\n"],"names":["useHomeTo","to","router","useRouter","accessKeys","useAccessKeys","homeTo","useMemo","tree","buildNavTree","route","_a","hasAccess","firstNavTo"],"mappings":"iJAWO,SAASA,EAAUC,EAAa,CACrC,MAAMC,EAASC,EAAAA,UAAU,CAAE,KAAM,GAAO,EAClCC,EAAaC,EAAAA,cAAA,EACbC,EAASC,EAAAA,QAAQ,IAAM,CAC3B,GAAIN,GAAM,KAAM,OAAOA,EACvB,GAAI,CAACC,EAAQ,OACb,MAAMM,EAAOC,EAAAA,aACX,OAAO,OAAOP,EAAO,eAAe,EACjC,IAAKQ,UAAW,OAAE,SAAUA,EAAM,SAAU,YAAYC,EAAAD,EAAM,UAAN,YAAAC,EAAe,YAAa,EACpF,OAAQD,GAAA,OAAUE,OAAAA,aAAUD,EAAAD,EAAM,aAAN,YAAAC,EAAkB,KAAK,EAAC,CAAA,EAEzD,OAAOE,EAAAA,WAAWL,CAAI,GAAK,GAG7B,EAAG,CAACN,EAAQD,EAAIG,CAAU,CAAC,EAC3B,MAAO,CAAE,OAAAF,EAAQ,OAAAI,CAAA,CACnB"}
@@ -1,7 +1,7 @@
1
1
  import { useMemo as c } from "react";
2
2
  import { useRouter as i } from "@tanstack/react-router";
3
3
  import { u as f, h as n } from "./access-Db4knwyR.js";
4
- import { b as l, f as m } from "./Sidebar-Dg15hPpM.js";
4
+ import { b as l, f as m } from "./Sidebar-_pcwxdd8.js";
5
5
  function b(o) {
6
6
  const t = i({ warn: !1 }), r = f(), a = c(() => {
7
7
  if (o != null) return o;
@@ -22,4 +22,4 @@ function b(o) {
22
22
  export {
23
23
  b as u
24
24
  };
25
- //# sourceMappingURL=useHomeTo-Ckq7scIY.js.map
25
+ //# sourceMappingURL=useHomeTo-DQj9tVZI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useHomeTo-Ckq7scIY.js","sources":["../src/components/PageNotFound/useHomeTo.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport { useRouter } from '@tanstack/react-router'\nimport { hasAccess, useAccessKeys } from '../../helpers/access'\nimport { buildNavTree, firstNavTo } from '../Sidebar/Sidebar'\n\n/**\n * Internal: the \"home\" a full-page state sends the user back to — the **first allowed menu page** (RBAC-aware,\n * the same target as `FirstRouteRedirect`), falling back to `/`; `to` overrides it. Also returns the router\n * (lenient: `undefined` outside a `<RouterProvider>`, so the page renders without its home action). Shared by\n * `PageNotFound` and `PageError`.\n */\nexport function useHomeTo(to?: string) {\n const router = useRouter({ warn: false })\n const accessKeys = useAccessKeys()\n const homeTo = useMemo(() => {\n if (to != null) return to\n if (!router) return undefined\n const tree = buildNavTree(\n Object.values(router.looseRoutesById)\n .map((route) => ({ fullPath: route.fullPath, staticData: route.options?.staticData }))\n .filter((route) => hasAccess(route.staticData?.roles)),\n )\n return firstNavTo(tree) ?? '/'\n // accessKeys: recompute when the user's roles change\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, to, accessKeys])\n return { router, homeTo }\n}\n"],"names":["useHomeTo","to","router","useRouter","accessKeys","useAccessKeys","homeTo","useMemo","tree","buildNavTree","route","_a","hasAccess","firstNavTo"],"mappings":";;;;AAWO,SAASA,EAAUC,GAAa;AACrC,QAAMC,IAASC,EAAU,EAAE,MAAM,IAAO,GAClCC,IAAaC,EAAA,GACbC,IAASC,EAAQ,MAAM;AAC3B,QAAIN,KAAM,KAAM,QAAOA;AACvB,QAAI,CAACC,EAAQ;AACb,UAAMM,IAAOC;AAAA,MACX,OAAO,OAAOP,EAAO,eAAe,EACjC,IAAI,CAACQ;;AAAW,iBAAE,UAAUA,EAAM,UAAU,aAAYC,IAAAD,EAAM,YAAN,gBAAAC,EAAe;OAAa,EACpF,OAAO,CAACD,MAAA;;AAAU,eAAAE,GAAUD,IAAAD,EAAM,eAAN,gBAAAC,EAAkB,KAAK;AAAA,OAAC;AAAA,IAAA;AAEzD,WAAOE,EAAWL,CAAI,KAAK;AAAA,EAG7B,GAAG,CAACN,GAAQD,GAAIG,CAAU,CAAC;AAC3B,SAAO,EAAE,QAAAF,GAAQ,QAAAI,EAAA;AACnB;"}
1
+ {"version":3,"file":"useHomeTo-DQj9tVZI.js","sources":["../src/components/PageNotFound/useHomeTo.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport { useRouter } from '@tanstack/react-router'\nimport { hasAccess, useAccessKeys } from '../../helpers/access'\nimport { buildNavTree, firstNavTo } from '../Sidebar/Sidebar'\n\n/**\n * Internal: the \"home\" a full-page state sends the user back to — the **first allowed menu page** (RBAC-aware,\n * the same target as `FirstRouteRedirect`), falling back to `/`; `to` overrides it. Also returns the router\n * (lenient: `undefined` outside a `<RouterProvider>`, so the page renders without its home action). Shared by\n * `PageNotFound` and `PageError`.\n */\nexport function useHomeTo(to?: string) {\n const router = useRouter({ warn: false })\n const accessKeys = useAccessKeys()\n const homeTo = useMemo(() => {\n if (to != null) return to\n if (!router) return undefined\n const tree = buildNavTree(\n Object.values(router.looseRoutesById)\n .map((route) => ({ fullPath: route.fullPath, staticData: route.options?.staticData }))\n .filter((route) => hasAccess(route.staticData?.roles)),\n )\n return firstNavTo(tree) ?? '/'\n // accessKeys: recompute when the user's roles change\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [router, to, accessKeys])\n return { router, homeTo }\n}\n"],"names":["useHomeTo","to","router","useRouter","accessKeys","useAccessKeys","homeTo","useMemo","tree","buildNavTree","route","_a","hasAccess","firstNavTo"],"mappings":";;;;AAWO,SAASA,EAAUC,GAAa;AACrC,QAAMC,IAASC,EAAU,EAAE,MAAM,IAAO,GAClCC,IAAaC,EAAA,GACbC,IAASC,EAAQ,MAAM;AAC3B,QAAIN,KAAM,KAAM,QAAOA;AACvB,QAAI,CAACC,EAAQ;AACb,UAAMM,IAAOC;AAAA,MACX,OAAO,OAAOP,EAAO,eAAe,EACjC,IAAI,CAACQ;;AAAW,iBAAE,UAAUA,EAAM,UAAU,aAAYC,IAAAD,EAAM,YAAN,gBAAAC,EAAe;OAAa,EACpF,OAAO,CAACD,MAAA;;AAAU,eAAAE,GAAUD,IAAAD,EAAM,eAAN,gBAAAC,EAAkB,KAAK;AAAA,OAAC;AAAA,IAAA;AAEzD,WAAOE,EAAWL,CAAI,KAAK;AAAA,EAG7B,GAAG,CAACN,GAAQD,GAAIG,CAAU,CAAC;AAC3B,SAAO,EAAE,QAAAF,GAAQ,QAAAI,EAAA;AACnB;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useMediaQuery-CHMrI6Dy.cjs","sources":["../src/hooks/useMediaQuery.ts"],"sourcesContent":["import { useCallback, useSyncExternalStore } from 'react'\nimport {\n BREAKPOINTS,\n breakpointQuery,\n getBreakpointsVersion,\n subscribeBreakpoints,\n type Breakpoint,\n} from '../theme/breakpoints'\n\nconst isBreakpoint = (value: string): value is Breakpoint => value in BREAKPOINTS\n\n/**\n * Subscribe to a media query and get whether it currently matches, re-rendering when it flips. Built on\n * `useSyncExternalStore`, so on the client the first render already has the correct value (no flash),\n * and it's **SSR-safe** — returns `false` on the server / where `matchMedia` is unavailable. Use this\n * instead of hand-rolling `window.matchMedia` + effects.\n *\n * Pass either a **raw media query** (`'(max-width: 640px)'`, `'(prefers-color-scheme: dark)'`) **or a\n * shared `Breakpoint` token** — a token resolves against the library's breakpoints (§ `BREAKPOINTS`),\n * defaulting to **`down`** (max-width): `useMediaQuery('sm')` → `(max-width: 959.98px)` = tablet-and-down.\n * Pass `direction: 'up'` for the min-width side.\n *\n * @example\n * const isMobile = useMediaQuery('xs') // ≤ 767.98px\n * const isTablet = useMediaQuery('sm') // ≤ 959.98px\n * const isDesktopUp = useMediaQuery('md', 'up') // ≥ 1280px\n * const isDark = useMediaQuery('(prefers-color-scheme: dark)')\n */\nexport function useMediaQuery(query: string, direction: 'down' | 'up' = 'down'): boolean {\n // re-render when the active breakpoints change (a `config.theme.breakpoints` override) so a token\n // query re-resolves; harmless for raw-string queries (the store only fires on an actual override)\n useSyncExternalStore(subscribeBreakpoints, getBreakpointsVersion, () => 0)\n const resolved = isBreakpoint(query) ? breakpointQuery(query, direction) : query\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {}\n const mql = window.matchMedia(resolved)\n mql.addEventListener('change', onStoreChange)\n return () => mql.removeEventListener('change', onStoreChange)\n },\n [resolved],\n )\n const getSnapshot = () =>\n typeof window !== 'undefined' && window.matchMedia ? window.matchMedia(resolved).matches : false\n // the server can't know the viewport — assume the query doesn't match (matches the CSR-first default)\n const getServerSnapshot = () => false\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n}\n\n/**\n * The current **max-width match** for every breakpoint — `{ xs, sm, md, lg, xl }` where each is `true`\n * when the viewport is at most that breakpoint's bound. Feeds `resolveResponsive` so components can\n * turn a responsive prop map into a concrete value. A fixed set of `useMediaQuery` calls (stable hook\n * order), each SSR-safe.\n */\nexport function useBreakpointMatches(): Record<Breakpoint, boolean> {\n // explicit, fixed set of calls (stable hook order) — one per breakpoint, all max-width (\"down\")\n return {\n xxs: useMediaQuery('xxs'),\n xs: useMediaQuery('xs'),\n sm: useMediaQuery('sm'),\n md: useMediaQuery('md'),\n lg: useMediaQuery('lg'),\n xl: useMediaQuery('xl'),\n xxl: useMediaQuery('xxl'),\n }\n}\n"],"names":["isBreakpoint","value","BREAKPOINTS","useMediaQuery","query","direction","useSyncExternalStore","subscribeBreakpoints","getBreakpointsVersion","resolved","breakpointQuery","subscribe","useCallback","onStoreChange","mql","getSnapshot","getServerSnapshot","useBreakpointMatches"],"mappings":"8EASMA,EAAgBC,GAAuCA,KAASC,EAAAA,YAmB/D,SAASC,EAAcC,EAAeC,EAA2B,OAAiB,CAGvFC,EAAAA,qBAAqBC,EAAAA,qBAAsBC,wBAAuB,IAAM,CAAC,EACzE,MAAMC,EAAWT,EAAaI,CAAK,EAAIM,EAAAA,gBAAgBN,EAAOC,CAAS,EAAID,EAErEO,EAAYC,EAAAA,YACfC,GAA8B,CAC7B,GAAI,OAAO,OAAW,KAAe,CAAC,OAAO,iBAAmB,IAAM,CAAC,EACvE,MAAMC,EAAM,OAAO,WAAWL,CAAQ,EACtC,OAAAK,EAAI,iBAAiB,SAAUD,CAAa,EACrC,IAAMC,EAAI,oBAAoB,SAAUD,CAAa,CAC9D,EACA,CAACJ,CAAQ,CAAA,EAELM,EAAc,IAClB,OAAO,OAAW,KAAe,OAAO,WAAa,OAAO,WAAWN,CAAQ,EAAE,QAAU,GAEvFO,EAAoB,IAAM,GAChC,OAAOV,uBAAqBK,EAAWI,EAAaC,CAAiB,CACvE,CAQO,SAASC,GAAoD,CAElE,MAAO,CACL,IAAKd,EAAc,KAAK,EACxB,GAAIA,EAAc,IAAI,EACtB,GAAIA,EAAc,IAAI,EACtB,GAAIA,EAAc,IAAI,EACtB,GAAIA,EAAc,IAAI,EACtB,GAAIA,EAAc,IAAI,EACtB,IAAKA,EAAc,KAAK,CAAA,CAE5B"}
1
+ {"version":3,"file":"useMediaQuery-CHMrI6Dy.cjs","sources":["../src/hooks/useMediaQuery.ts"],"sourcesContent":["import { useCallback, useSyncExternalStore } from 'react'\nimport {\n BREAKPOINTS,\n breakpointQuery,\n getBreakpointsVersion,\n subscribeBreakpoints,\n type Breakpoint,\n} from '../theme/breakpoints'\n\nconst isBreakpoint = (value: string): value is Breakpoint => value in BREAKPOINTS\n\n/**\n * Subscribe to a media query and get whether it currently matches, re-rendering when it flips. Built on\n * `useSyncExternalStore`, so on the client the first render already has the correct value (no flash),\n * and it's **SSR-safe** — returns `false` on the server / where `matchMedia` is unavailable. Use this\n * instead of hand-rolling `window.matchMedia` + effects.\n *\n * Pass either a **raw media query** (`'(max-width: 640px)'`, `'(prefers-color-scheme: dark)'`) **or a\n * shared `Breakpoint` token** — a token resolves against the library's breakpoints (§ `BREAKPOINTS`),\n * defaulting to **`down`** (max-width): `useMediaQuery('sm')` → `(max-width: 1023.98px)` = tablet-and-down.\n * Pass `direction: 'up'` for the min-width side.\n *\n * @example\n * const isMobile = useMediaQuery('xs') // ≤ 767.98px\n * const isTablet = useMediaQuery('sm') // ≤ 1023.98px\n * const isDesktopUp = useMediaQuery('md', 'up') // ≥ 1280px\n * const isDark = useMediaQuery('(prefers-color-scheme: dark)')\n */\nexport function useMediaQuery(query: string, direction: 'down' | 'up' = 'down'): boolean {\n // re-render when the active breakpoints change (a `config.theme.breakpoints` override) so a token\n // query re-resolves; harmless for raw-string queries (the store only fires on an actual override)\n useSyncExternalStore(subscribeBreakpoints, getBreakpointsVersion, () => 0)\n const resolved = isBreakpoint(query) ? breakpointQuery(query, direction) : query\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {}\n const mql = window.matchMedia(resolved)\n mql.addEventListener('change', onStoreChange)\n return () => mql.removeEventListener('change', onStoreChange)\n },\n [resolved],\n )\n const getSnapshot = () =>\n typeof window !== 'undefined' && window.matchMedia ? window.matchMedia(resolved).matches : false\n // the server can't know the viewport — assume the query doesn't match (matches the CSR-first default)\n const getServerSnapshot = () => false\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n}\n\n/**\n * The current **max-width match** for every breakpoint — `{ xxs, xs, sm, md, lg, xl, xxl }` where each is `true`\n * when the viewport is at most that breakpoint's bound. Feeds `resolveResponsive` so components can\n * turn a responsive prop map into a concrete value. A fixed set of `useMediaQuery` calls (stable hook\n * order), each SSR-safe.\n */\nexport function useBreakpointMatches(): Record<Breakpoint, boolean> {\n // explicit, fixed set of calls (stable hook order) — one per breakpoint, all max-width (\"down\")\n return {\n xxs: useMediaQuery('xxs'),\n xs: useMediaQuery('xs'),\n sm: useMediaQuery('sm'),\n md: useMediaQuery('md'),\n lg: useMediaQuery('lg'),\n xl: useMediaQuery('xl'),\n xxl: useMediaQuery('xxl'),\n }\n}\n"],"names":["isBreakpoint","value","BREAKPOINTS","useMediaQuery","query","direction","useSyncExternalStore","subscribeBreakpoints","getBreakpointsVersion","resolved","breakpointQuery","subscribe","useCallback","onStoreChange","mql","getSnapshot","getServerSnapshot","useBreakpointMatches"],"mappings":"8EASMA,EAAgBC,GAAuCA,KAASC,EAAAA,YAmB/D,SAASC,EAAcC,EAAeC,EAA2B,OAAiB,CAGvFC,EAAAA,qBAAqBC,EAAAA,qBAAsBC,wBAAuB,IAAM,CAAC,EACzE,MAAMC,EAAWT,EAAaI,CAAK,EAAIM,EAAAA,gBAAgBN,EAAOC,CAAS,EAAID,EAErEO,EAAYC,EAAAA,YACfC,GAA8B,CAC7B,GAAI,OAAO,OAAW,KAAe,CAAC,OAAO,iBAAmB,IAAM,CAAC,EACvE,MAAMC,EAAM,OAAO,WAAWL,CAAQ,EACtC,OAAAK,EAAI,iBAAiB,SAAUD,CAAa,EACrC,IAAMC,EAAI,oBAAoB,SAAUD,CAAa,CAC9D,EACA,CAACJ,CAAQ,CAAA,EAELM,EAAc,IAClB,OAAO,OAAW,KAAe,OAAO,WAAa,OAAO,WAAWN,CAAQ,EAAE,QAAU,GAEvFO,EAAoB,IAAM,GAChC,OAAOV,uBAAqBK,EAAWI,EAAaC,CAAiB,CACvE,CAQO,SAASC,GAAoD,CAElE,MAAO,CACL,IAAKd,EAAc,KAAK,EACxB,GAAIA,EAAc,IAAI,EACtB,GAAIA,EAAc,IAAI,EACtB,GAAIA,EAAc,IAAI,EACtB,GAAIA,EAAc,IAAI,EACtB,GAAIA,EAAc,IAAI,EACtB,IAAKA,EAAc,KAAK,CAAA,CAE5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"useMediaQuery-DrDUrkmJ.js","sources":["../src/hooks/useMediaQuery.ts"],"sourcesContent":["import { useCallback, useSyncExternalStore } from 'react'\nimport {\n BREAKPOINTS,\n breakpointQuery,\n getBreakpointsVersion,\n subscribeBreakpoints,\n type Breakpoint,\n} from '../theme/breakpoints'\n\nconst isBreakpoint = (value: string): value is Breakpoint => value in BREAKPOINTS\n\n/**\n * Subscribe to a media query and get whether it currently matches, re-rendering when it flips. Built on\n * `useSyncExternalStore`, so on the client the first render already has the correct value (no flash),\n * and it's **SSR-safe** — returns `false` on the server / where `matchMedia` is unavailable. Use this\n * instead of hand-rolling `window.matchMedia` + effects.\n *\n * Pass either a **raw media query** (`'(max-width: 640px)'`, `'(prefers-color-scheme: dark)'`) **or a\n * shared `Breakpoint` token** — a token resolves against the library's breakpoints (§ `BREAKPOINTS`),\n * defaulting to **`down`** (max-width): `useMediaQuery('sm')` → `(max-width: 959.98px)` = tablet-and-down.\n * Pass `direction: 'up'` for the min-width side.\n *\n * @example\n * const isMobile = useMediaQuery('xs') // ≤ 767.98px\n * const isTablet = useMediaQuery('sm') // ≤ 959.98px\n * const isDesktopUp = useMediaQuery('md', 'up') // ≥ 1280px\n * const isDark = useMediaQuery('(prefers-color-scheme: dark)')\n */\nexport function useMediaQuery(query: string, direction: 'down' | 'up' = 'down'): boolean {\n // re-render when the active breakpoints change (a `config.theme.breakpoints` override) so a token\n // query re-resolves; harmless for raw-string queries (the store only fires on an actual override)\n useSyncExternalStore(subscribeBreakpoints, getBreakpointsVersion, () => 0)\n const resolved = isBreakpoint(query) ? breakpointQuery(query, direction) : query\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {}\n const mql = window.matchMedia(resolved)\n mql.addEventListener('change', onStoreChange)\n return () => mql.removeEventListener('change', onStoreChange)\n },\n [resolved],\n )\n const getSnapshot = () =>\n typeof window !== 'undefined' && window.matchMedia ? window.matchMedia(resolved).matches : false\n // the server can't know the viewport — assume the query doesn't match (matches the CSR-first default)\n const getServerSnapshot = () => false\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n}\n\n/**\n * The current **max-width match** for every breakpoint — `{ xs, sm, md, lg, xl }` where each is `true`\n * when the viewport is at most that breakpoint's bound. Feeds `resolveResponsive` so components can\n * turn a responsive prop map into a concrete value. A fixed set of `useMediaQuery` calls (stable hook\n * order), each SSR-safe.\n */\nexport function useBreakpointMatches(): Record<Breakpoint, boolean> {\n // explicit, fixed set of calls (stable hook order) — one per breakpoint, all max-width (\"down\")\n return {\n xxs: useMediaQuery('xxs'),\n xs: useMediaQuery('xs'),\n sm: useMediaQuery('sm'),\n md: useMediaQuery('md'),\n lg: useMediaQuery('lg'),\n xl: useMediaQuery('xl'),\n xxl: useMediaQuery('xxl'),\n }\n}\n"],"names":["isBreakpoint","value","BREAKPOINTS","useMediaQuery","query","direction","useSyncExternalStore","subscribeBreakpoints","getBreakpointsVersion","resolved","breakpointQuery","subscribe","useCallback","onStoreChange","mql","useBreakpointMatches"],"mappings":";;AASA,MAAMA,IAAe,CAACC,MAAuCA,KAASC;AAmB/D,SAASC,EAAcC,GAAeC,IAA2B,QAAiB;AAGvF,EAAAC,EAAqBC,GAAsBC,GAAuB,MAAM,CAAC;AACzE,QAAMC,IAAWT,EAAaI,CAAK,IAAIM,EAAgBN,GAAOC,CAAS,IAAID,GAErEO,IAAYC;AAAA,IAChB,CAACC,MAA8B;AAC7B,UAAI,OAAO,SAAW,OAAe,CAAC,OAAO,mBAAmB,MAAM;AAAA,MAAC;AACvE,YAAMC,IAAM,OAAO,WAAWL,CAAQ;AACtC,aAAAK,EAAI,iBAAiB,UAAUD,CAAa,GACrC,MAAMC,EAAI,oBAAoB,UAAUD,CAAa;AAAA,IAC9D;AAAA,IACA,CAACJ,CAAQ;AAAA,EAAA;AAMX,SAAOH,EAAqBK,GAJR,MAClB,OAAO,SAAW,OAAe,OAAO,aAAa,OAAO,WAAWF,CAAQ,EAAE,UAAU,IAEnE,MAAM,EACqC;AACvE;AAQO,SAASM,IAAoD;AAElE,SAAO;AAAA,IACL,KAAKZ,EAAc,KAAK;AAAA,IACxB,IAAIA,EAAc,IAAI;AAAA,IACtB,IAAIA,EAAc,IAAI;AAAA,IACtB,IAAIA,EAAc,IAAI;AAAA,IACtB,IAAIA,EAAc,IAAI;AAAA,IACtB,IAAIA,EAAc,IAAI;AAAA,IACtB,KAAKA,EAAc,KAAK;AAAA,EAAA;AAE5B;"}
1
+ {"version":3,"file":"useMediaQuery-DrDUrkmJ.js","sources":["../src/hooks/useMediaQuery.ts"],"sourcesContent":["import { useCallback, useSyncExternalStore } from 'react'\nimport {\n BREAKPOINTS,\n breakpointQuery,\n getBreakpointsVersion,\n subscribeBreakpoints,\n type Breakpoint,\n} from '../theme/breakpoints'\n\nconst isBreakpoint = (value: string): value is Breakpoint => value in BREAKPOINTS\n\n/**\n * Subscribe to a media query and get whether it currently matches, re-rendering when it flips. Built on\n * `useSyncExternalStore`, so on the client the first render already has the correct value (no flash),\n * and it's **SSR-safe** — returns `false` on the server / where `matchMedia` is unavailable. Use this\n * instead of hand-rolling `window.matchMedia` + effects.\n *\n * Pass either a **raw media query** (`'(max-width: 640px)'`, `'(prefers-color-scheme: dark)'`) **or a\n * shared `Breakpoint` token** — a token resolves against the library's breakpoints (§ `BREAKPOINTS`),\n * defaulting to **`down`** (max-width): `useMediaQuery('sm')` → `(max-width: 1023.98px)` = tablet-and-down.\n * Pass `direction: 'up'` for the min-width side.\n *\n * @example\n * const isMobile = useMediaQuery('xs') // ≤ 767.98px\n * const isTablet = useMediaQuery('sm') // ≤ 1023.98px\n * const isDesktopUp = useMediaQuery('md', 'up') // ≥ 1280px\n * const isDark = useMediaQuery('(prefers-color-scheme: dark)')\n */\nexport function useMediaQuery(query: string, direction: 'down' | 'up' = 'down'): boolean {\n // re-render when the active breakpoints change (a `config.theme.breakpoints` override) so a token\n // query re-resolves; harmless for raw-string queries (the store only fires on an actual override)\n useSyncExternalStore(subscribeBreakpoints, getBreakpointsVersion, () => 0)\n const resolved = isBreakpoint(query) ? breakpointQuery(query, direction) : query\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {}\n const mql = window.matchMedia(resolved)\n mql.addEventListener('change', onStoreChange)\n return () => mql.removeEventListener('change', onStoreChange)\n },\n [resolved],\n )\n const getSnapshot = () =>\n typeof window !== 'undefined' && window.matchMedia ? window.matchMedia(resolved).matches : false\n // the server can't know the viewport — assume the query doesn't match (matches the CSR-first default)\n const getServerSnapshot = () => false\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n}\n\n/**\n * The current **max-width match** for every breakpoint — `{ xxs, xs, sm, md, lg, xl, xxl }` where each is `true`\n * when the viewport is at most that breakpoint's bound. Feeds `resolveResponsive` so components can\n * turn a responsive prop map into a concrete value. A fixed set of `useMediaQuery` calls (stable hook\n * order), each SSR-safe.\n */\nexport function useBreakpointMatches(): Record<Breakpoint, boolean> {\n // explicit, fixed set of calls (stable hook order) — one per breakpoint, all max-width (\"down\")\n return {\n xxs: useMediaQuery('xxs'),\n xs: useMediaQuery('xs'),\n sm: useMediaQuery('sm'),\n md: useMediaQuery('md'),\n lg: useMediaQuery('lg'),\n xl: useMediaQuery('xl'),\n xxl: useMediaQuery('xxl'),\n }\n}\n"],"names":["isBreakpoint","value","BREAKPOINTS","useMediaQuery","query","direction","useSyncExternalStore","subscribeBreakpoints","getBreakpointsVersion","resolved","breakpointQuery","subscribe","useCallback","onStoreChange","mql","useBreakpointMatches"],"mappings":";;AASA,MAAMA,IAAe,CAACC,MAAuCA,KAASC;AAmB/D,SAASC,EAAcC,GAAeC,IAA2B,QAAiB;AAGvF,EAAAC,EAAqBC,GAAsBC,GAAuB,MAAM,CAAC;AACzE,QAAMC,IAAWT,EAAaI,CAAK,IAAIM,EAAgBN,GAAOC,CAAS,IAAID,GAErEO,IAAYC;AAAA,IAChB,CAACC,MAA8B;AAC7B,UAAI,OAAO,SAAW,OAAe,CAAC,OAAO,mBAAmB,MAAM;AAAA,MAAC;AACvE,YAAMC,IAAM,OAAO,WAAWL,CAAQ;AACtC,aAAAK,EAAI,iBAAiB,UAAUD,CAAa,GACrC,MAAMC,EAAI,oBAAoB,UAAUD,CAAa;AAAA,IAC9D;AAAA,IACA,CAACJ,CAAQ;AAAA,EAAA;AAMX,SAAOH,EAAqBK,GAJR,MAClB,OAAO,SAAW,OAAe,OAAO,aAAa,OAAO,WAAWF,CAAQ,EAAE,UAAU,IAEnE,MAAM,EACqC;AACvE;AAQO,SAASM,IAAoD;AAElE,SAAO;AAAA,IACL,KAAKZ,EAAc,KAAK;AAAA,IACxB,IAAIA,EAAc,IAAI;AAAA,IACtB,IAAIA,EAAc,IAAI;AAAA,IACtB,IAAIA,EAAc,IAAI;AAAA,IACtB,IAAIA,EAAc,IAAI;AAAA,IACtB,IAAIA,EAAc,IAAI;AAAA,IACtB,KAAKA,EAAc,KAAK;AAAA,EAAA;AAE5B;"}
@@ -1,2 +1,2 @@
1
- "use strict";const c=require("react/jsx-runtime"),Q=require("clsx"),W=require("./FloatingPanel-tGCG2nhA.cjs"),$=require("./Icon-B6lz-V0A.cjs"),U=require("./List-B5Ppe9R1.cjs"),V=require("./ListItem-Qo1Tt6Fi.cjs"),G=require("./Loader-B5Pm8AaT.cjs"),C=require("./Typography-d97DdbNd.cjs"),J=require("./ConfigProvider-B_Bb6pk1.cjs"),l=require("react"),X="_popover_rf9kn_3",Y="_search_rf9kn_11",Z="_searchIcon_rf9kn_20",B="_searchInput_rf9kn_24",ee="_listbox_rf9kn_40",te="_active_rf9kn_48",re="_noOptions_rf9kn_52",se="_loading_rf9kn_58",oe="_group_rf9kn_68",ne="_groupLabel_rf9kn_80",ae="_trailing_rf9kn_86",h={popover:X,search:Y,searchIcon:Z,searchInput:B,listbox:ee,active:te,noOptions:re,loading:se,group:oe,groupLabel:ne,trailing:ae};function ie({menu:t,anchorRef:m,size:g,searchPlaceholder:_,loading:O=!1,loadingText:E,noOptionsText:d,showSelectedTick:x=!0,multiselectable:M=!1,labelledBy:j,ariaLabel:N,onSearchKeyDown:R,className:y}){const r=J.useT(),L=_??r("common.search"),{filteredOptions:I,highlightedIndex:q}=t,f=({opt:o,index:p})=>{const n=t.isSelected(o),u=n&&x;return c.jsx(V.ListItem,{id:t.optionId(p),role:"option",tabIndex:-1,"aria-selected":n,"aria-current":void 0,clickable:!0,selected:n,disabled:o.disabled,icon:o.icon,className:Q.clsx(p===q&&h.active),trailing:o.trailing!=null||u?c.jsxs("span",{className:h.trailing,children:[o.trailing,u&&c.jsx($.Icon,{name:"TickCircle",size:"sm"})]}):void 0,onMouseEnter:()=>!o.disabled&&t.setHighlightedIndex(p),onMouseDown:a=>a.preventDefault(),onClick:()=>t.pick(o),children:o.label},o.value)},b=o=>{if(!o.some(n=>n.opt.group!=null))return o.map(f);const p=[];for(const n of o){const u=p[p.length-1];u&&u.group===n.opt.group?u.rows.push(n):p.push({group:n.opt.group,rows:[n]})}return p.map((n,u)=>{if(n.group==null)return n.rows.map(f);const a=`${t.listboxId}-group-${u}`;return c.jsxs("div",{role:"group","aria-labelledby":a,className:h.group,children:[c.jsx(C.Typography,{as:"div",id:a,role:"presentation",variant:"caption",color:"muted",uppercase:!0,className:h.groupLabel,children:n.group}),n.rows.map(f)]},`group-${u}`)})};return c.jsxs(W.FloatingPanel,{ref:t.popoverRef,open:t.open,triggerRef:m,onClose:t.closeMenu,matchTriggerWidth:!0,className:Q.clsx(h.popover,y),children:[t.searchable&&c.jsxs("div",{className:h.search,children:[c.jsx($.Icon,{name:"SearchNormal",size:"sm",className:h.searchIcon,"aria-hidden":"true"}),c.jsx("input",{ref:t.searchInputRef,className:h.searchInput,type:"text",role:"combobox","aria-expanded":"true","aria-controls":t.listboxId,"aria-activedescendant":t.activeId,"aria-autocomplete":"list","aria-label":L,placeholder:L,value:t.searchQuery,spellCheck:!1,autoComplete:"off",onChange:o=>t.setSearchQuery(o.target.value),onKeyDown:R??t.handleKeyDown})]}),c.jsx(U.List,{role:"listbox",id:t.listboxId,"aria-labelledby":j,"aria-label":j?void 0:N,"aria-multiselectable":M||void 0,size:g,className:h.listbox,onMouseLeave:()=>t.setHighlightedIndex(-1),children:O?c.jsxs("div",{className:h.loading,children:[c.jsx(G.Loader,{size:"sm"}),c.jsx(C.Typography,{as:"span",variant:"bodySmall",color:"muted",children:E??r("common.loading")})]}):I.length===0?c.jsx("div",{className:h.noOptions,children:c.jsx(C.Typography,{as:"span",variant:"bodySmall",color:"muted",children:d==null?r("select.noOptions"):typeof d=="function"?d(t.searchQuery):d})}):b(I.map((o,p)=>({opt:o,index:p})))})]})}function ce(t){if(!t.some(g=>g.group!=null))return t;const m=new Map;for(const g of t){const _=m.get(g.group);_?_.push(g):m.set(g.group,[g])}return[...m.values()].flat()}function le({idBase:t,options:m,isSelected:g,onPick:_,closeOnPick:O=!0,highlightSelected:E=!0,searchable:d=!1,onSearchChange:x,disabled:M=!1,focusRef:j,onClose:N}){const R=`${t}-listbox`,y=l.useCallback(e=>`${t}-opt-${e}`,[t]),[r,L]=l.useState(!1),[I,q]=l.useState(""),[f,b]=l.useState(-1),o=l.useRef(null),p=l.useRef(null),n=l.useRef({buffer:"",timer:0}),u=l.useRef(N);u.current=N;const a=l.useMemo(()=>{const e=I.trim().toLowerCase(),s=!d||x||!e?m:m.filter(i=>{var k;return i.label.toLowerCase().includes(e)||((k=i.keywords)==null?void 0:k.some(F=>F.toLowerCase().includes(e)))});return ce(s)},[d,x,I,m]),v=l.useCallback((e,s)=>{let i=e;for(;i>=0&&i<a.length;){if(!a[i].disabled)return i;i+=s}return-1},[a]),D=l.useCallback(e=>{var s,i;L(!1),q(""),window.clearTimeout(n.current.timer),n.current.buffer="",(s=u.current)==null||s.call(u),e&&((i=j.current)==null||i.focus())},[j]);l.useEffect(()=>{if(!r)return;const e=E?a.findIndex(g):-1;b(e>=0&&!a[e].disabled?e:v(0,1)),d&&requestAnimationFrame(()=>{var s;return(s=o.current)==null?void 0:s.focus()})},[r]),l.useEffect(()=>{var e,s;!r||f<0||(s=(e=document.getElementById(y(f)))==null?void 0:e.scrollIntoView)==null||s.call(e,{block:"nearest"})},[r,f,y]),l.useEffect(()=>{r&&d&&b(v(0,1))},[I]),l.useEffect(()=>{r&&b(e=>e<a.length?e:v(0,1))},[a.length]);const w=()=>{M||L(!0)},H=()=>r?D(!1):w(),P=e=>{q(e),x==null||x(e)},T=e=>{!e||e.disabled||(_(e),O&&D(!0))},K=e=>{b(s=>{const i=s<0?e>0?0:a.length-1:s+e,k=v(i,e);return k===-1?s:k})},S=e=>{const s=n.current;window.clearTimeout(s.timer),s.buffer+=e.toLowerCase(),s.timer=window.setTimeout(()=>s.buffer="",500);const i=a.findIndex(k=>!k.disabled&&k.label.toLowerCase().startsWith(s.buffer));i>=0&&b(i)},z=e=>{if(!M)switch(e.key){case"ArrowDown":e.preventDefault(),r?K(1):w();break;case"ArrowUp":e.preventDefault(),r?K(-1):w();break;case"Enter":e.preventDefault(),r?T(a[f]):w();break;case" ":r?d||(e.preventDefault(),T(a[f])):(e.preventDefault(),w());break;case"Escape":r&&(e.preventDefault(),e.stopPropagation(),D(!0));break;case"Tab":r&&D(!0);break;case"Home":r&&(e.preventDefault(),b(v(0,1)));break;case"End":r&&(e.preventDefault(),b(v(a.length-1,-1)));break;default:!d&&r&&e.key.length===1&&!e.metaKey&&!e.ctrlKey&&!e.altKey&&S(e.key)}},A=r&&f>=0?y(f):void 0;return{open:r,openMenu:w,closeMenu:D,toggleMenu:H,searchable:d,searchQuery:I,setSearchQuery:P,filteredOptions:a,highlightedIndex:f,setHighlightedIndex:b,isSelected:g,pick:T,handleKeyDown:z,listboxId:R,optionId:y,activeId:A,searchInputRef:o,popoverRef:p}}exports.OptionMenu=ie;exports.useOptionMenu=le;
2
- //# sourceMappingURL=useOptionMenu-3YlvxPAM.cjs.map
1
+ "use strict";const c=require("react/jsx-runtime"),Q=require("clsx"),W=require("./FloatingPanel-tGCG2nhA.cjs"),$=require("./Icon-B6lz-V0A.cjs"),U=require("./List-CKoNx21F.cjs"),V=require("./ListItem-DkCYXucd.cjs"),G=require("./Loader-5zp2MPm5.cjs"),C=require("./Typography-d97DdbNd.cjs"),J=require("./ConfigProvider-BaiTKZKC.cjs"),l=require("react"),X="_popover_rf9kn_3",Y="_search_rf9kn_11",Z="_searchIcon_rf9kn_20",B="_searchInput_rf9kn_24",ee="_listbox_rf9kn_40",te="_active_rf9kn_48",re="_noOptions_rf9kn_52",se="_loading_rf9kn_58",oe="_group_rf9kn_68",ne="_groupLabel_rf9kn_80",ae="_trailing_rf9kn_86",h={popover:X,search:Y,searchIcon:Z,searchInput:B,listbox:ee,active:te,noOptions:re,loading:se,group:oe,groupLabel:ne,trailing:ae};function ie({menu:t,anchorRef:m,size:g,searchPlaceholder:_,loading:O=!1,loadingText:E,noOptionsText:d,showSelectedTick:x=!0,multiselectable:M=!1,labelledBy:j,ariaLabel:N,onSearchKeyDown:R,className:y}){const r=J.useT(),L=_??r("common.search"),{filteredOptions:I,highlightedIndex:q}=t,f=({opt:o,index:p})=>{const n=t.isSelected(o),u=n&&x;return c.jsx(V.ListItem,{id:t.optionId(p),role:"option",tabIndex:-1,"aria-selected":n,"aria-current":void 0,clickable:!0,selected:n,disabled:o.disabled,icon:o.icon,className:Q.clsx(p===q&&h.active),trailing:o.trailing!=null||u?c.jsxs("span",{className:h.trailing,children:[o.trailing,u&&c.jsx($.Icon,{name:"TickCircle",size:"sm"})]}):void 0,onMouseEnter:()=>!o.disabled&&t.setHighlightedIndex(p),onMouseDown:a=>a.preventDefault(),onClick:()=>t.pick(o),children:o.label},o.value)},b=o=>{if(!o.some(n=>n.opt.group!=null))return o.map(f);const p=[];for(const n of o){const u=p[p.length-1];u&&u.group===n.opt.group?u.rows.push(n):p.push({group:n.opt.group,rows:[n]})}return p.map((n,u)=>{if(n.group==null)return n.rows.map(f);const a=`${t.listboxId}-group-${u}`;return c.jsxs("div",{role:"group","aria-labelledby":a,className:h.group,children:[c.jsx(C.Typography,{as:"div",id:a,role:"presentation",variant:"caption",color:"muted",uppercase:!0,className:h.groupLabel,children:n.group}),n.rows.map(f)]},`group-${u}`)})};return c.jsxs(W.FloatingPanel,{ref:t.popoverRef,open:t.open,triggerRef:m,onClose:t.closeMenu,matchTriggerWidth:!0,className:Q.clsx(h.popover,y),children:[t.searchable&&c.jsxs("div",{className:h.search,children:[c.jsx($.Icon,{name:"SearchNormal",size:"sm",className:h.searchIcon,"aria-hidden":"true"}),c.jsx("input",{ref:t.searchInputRef,className:h.searchInput,type:"text",role:"combobox","aria-expanded":"true","aria-controls":t.listboxId,"aria-activedescendant":t.activeId,"aria-autocomplete":"list","aria-label":L,placeholder:L,value:t.searchQuery,spellCheck:!1,autoComplete:"off",onChange:o=>t.setSearchQuery(o.target.value),onKeyDown:R??t.handleKeyDown})]}),c.jsx(U.List,{role:"listbox",id:t.listboxId,"aria-labelledby":j,"aria-label":j?void 0:N,"aria-multiselectable":M||void 0,size:g,className:h.listbox,onMouseLeave:()=>t.setHighlightedIndex(-1),children:O?c.jsxs("div",{className:h.loading,children:[c.jsx(G.Loader,{size:"sm"}),c.jsx(C.Typography,{as:"span",variant:"bodySmall",color:"muted",children:E??r("common.loading")})]}):I.length===0?c.jsx("div",{className:h.noOptions,children:c.jsx(C.Typography,{as:"span",variant:"bodySmall",color:"muted",children:d==null?r("select.noOptions"):typeof d=="function"?d(t.searchQuery):d})}):b(I.map((o,p)=>({opt:o,index:p})))})]})}function ce(t){if(!t.some(g=>g.group!=null))return t;const m=new Map;for(const g of t){const _=m.get(g.group);_?_.push(g):m.set(g.group,[g])}return[...m.values()].flat()}function le({idBase:t,options:m,isSelected:g,onPick:_,closeOnPick:O=!0,highlightSelected:E=!0,searchable:d=!1,onSearchChange:x,disabled:M=!1,focusRef:j,onClose:N}){const R=`${t}-listbox`,y=l.useCallback(e=>`${t}-opt-${e}`,[t]),[r,L]=l.useState(!1),[I,q]=l.useState(""),[f,b]=l.useState(-1),o=l.useRef(null),p=l.useRef(null),n=l.useRef({buffer:"",timer:0}),u=l.useRef(N);u.current=N;const a=l.useMemo(()=>{const e=I.trim().toLowerCase(),s=!d||x||!e?m:m.filter(i=>{var k;return i.label.toLowerCase().includes(e)||((k=i.keywords)==null?void 0:k.some(F=>F.toLowerCase().includes(e)))});return ce(s)},[d,x,I,m]),v=l.useCallback((e,s)=>{let i=e;for(;i>=0&&i<a.length;){if(!a[i].disabled)return i;i+=s}return-1},[a]),D=l.useCallback(e=>{var s,i;L(!1),q(""),window.clearTimeout(n.current.timer),n.current.buffer="",(s=u.current)==null||s.call(u),e&&((i=j.current)==null||i.focus())},[j]);l.useEffect(()=>{if(!r)return;const e=E?a.findIndex(g):-1;b(e>=0&&!a[e].disabled?e:v(0,1)),d&&requestAnimationFrame(()=>{var s;return(s=o.current)==null?void 0:s.focus()})},[r]),l.useEffect(()=>{var e,s;!r||f<0||(s=(e=document.getElementById(y(f)))==null?void 0:e.scrollIntoView)==null||s.call(e,{block:"nearest"})},[r,f,y]),l.useEffect(()=>{r&&d&&b(v(0,1))},[I]),l.useEffect(()=>{r&&b(e=>e<a.length?e:v(0,1))},[a.length]);const w=()=>{M||L(!0)},H=()=>r?D(!1):w(),P=e=>{q(e),x==null||x(e)},T=e=>{!e||e.disabled||(_(e),O&&D(!0))},K=e=>{b(s=>{const i=s<0?e>0?0:a.length-1:s+e,k=v(i,e);return k===-1?s:k})},S=e=>{const s=n.current;window.clearTimeout(s.timer),s.buffer+=e.toLowerCase(),s.timer=window.setTimeout(()=>s.buffer="",500);const i=a.findIndex(k=>!k.disabled&&k.label.toLowerCase().startsWith(s.buffer));i>=0&&b(i)},z=e=>{if(!M)switch(e.key){case"ArrowDown":e.preventDefault(),r?K(1):w();break;case"ArrowUp":e.preventDefault(),r?K(-1):w();break;case"Enter":e.preventDefault(),r?T(a[f]):w();break;case" ":r?d||(e.preventDefault(),T(a[f])):(e.preventDefault(),w());break;case"Escape":r&&(e.preventDefault(),e.stopPropagation(),D(!0));break;case"Tab":r&&D(!0);break;case"Home":r&&(e.preventDefault(),b(v(0,1)));break;case"End":r&&(e.preventDefault(),b(v(a.length-1,-1)));break;default:!d&&r&&e.key.length===1&&!e.metaKey&&!e.ctrlKey&&!e.altKey&&S(e.key)}},A=r&&f>=0?y(f):void 0;return{open:r,openMenu:w,closeMenu:D,toggleMenu:H,searchable:d,searchQuery:I,setSearchQuery:P,filteredOptions:a,highlightedIndex:f,setHighlightedIndex:b,isSelected:g,pick:T,handleKeyDown:z,listboxId:R,optionId:y,activeId:A,searchInputRef:o,popoverRef:p}}exports.OptionMenu=ie;exports.useOptionMenu=le;
2
+ //# sourceMappingURL=useOptionMenu-BKC1y6oj.cjs.map