@techzyapp/ui-library 1.0.45 → 1.0.47

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 (392) hide show
  1. package/README.md +1 -1
  2. package/dist/AdminRoot-BRN_MlHp.cjs +2 -0
  3. package/dist/AdminRoot-BRN_MlHp.cjs.map +1 -0
  4. package/dist/AdminRoot-CtqPtYxo.js +107 -0
  5. package/dist/AdminRoot-CtqPtYxo.js.map +1 -0
  6. package/dist/{Alert-BU7GlQna.js → Alert-Bo_XgY-A.js} +3 -3
  7. package/dist/{Alert-BU7GlQna.js.map → Alert-Bo_XgY-A.js.map} +1 -1
  8. package/dist/{Alert-CVQOjuEq.cjs → Alert-QvfNBhlU.cjs} +2 -2
  9. package/dist/{Alert-CVQOjuEq.cjs.map → Alert-QvfNBhlU.cjs.map} +1 -1
  10. package/dist/AuthGuard-CAaQZ2y7.cjs +2 -0
  11. package/dist/AuthGuard-CAaQZ2y7.cjs.map +1 -0
  12. package/dist/AuthGuard-vqKf2PF9.js +102 -0
  13. package/dist/AuthGuard-vqKf2PF9.js.map +1 -0
  14. package/dist/{Breadcrumbs-BMz_YVPa.js → Breadcrumbs-BEv57tuJ.js} +3 -3
  15. package/dist/{Breadcrumbs-BMz_YVPa.js.map → Breadcrumbs-BEv57tuJ.js.map} +1 -1
  16. package/dist/{Breadcrumbs-BbC0o4JE.cjs → Breadcrumbs-CqGS32x5.cjs} +2 -2
  17. package/dist/{Breadcrumbs-BbC0o4JE.cjs.map → Breadcrumbs-CqGS32x5.cjs.map} +1 -1
  18. package/dist/{Button-mBZOvgyZ.cjs → Button-BtiFpRie.cjs} +2 -2
  19. package/dist/{Button-mBZOvgyZ.cjs.map → Button-BtiFpRie.cjs.map} +1 -1
  20. package/dist/{Button-C415LPw_.js → Button-DZWYeAno.js} +2 -2
  21. package/dist/{Button-C415LPw_.js.map → Button-DZWYeAno.js.map} +1 -1
  22. package/dist/{Calendar-B0f6h9-A.js → Calendar-7W9xNVBZ.js} +3 -3
  23. package/dist/{Calendar-B0f6h9-A.js.map → Calendar-7W9xNVBZ.js.map} +1 -1
  24. package/dist/{Calendar-hO051hfk.cjs → Calendar-Bgh_3Vk2.cjs} +2 -2
  25. package/dist/{Calendar-hO051hfk.cjs.map → Calendar-Bgh_3Vk2.cjs.map} +1 -1
  26. package/dist/{Card-BdNr5row.cjs → Card-KfmWG9Uz.cjs} +2 -2
  27. package/dist/{Card-BdNr5row.cjs.map → Card-KfmWG9Uz.cjs.map} +1 -1
  28. package/dist/{Card-ssUNaOF_.js → Card-ckOd617g.js} +3 -3
  29. package/dist/{Card-ssUNaOF_.js.map → Card-ckOd617g.js.map} +1 -1
  30. package/dist/{Chip-BpJN4rzY.cjs → Chip-BDUsue_R.cjs} +2 -2
  31. package/dist/{Chip-BpJN4rzY.cjs.map → Chip-BDUsue_R.cjs.map} +1 -1
  32. package/dist/{Chip-C0x-6g2h.js → Chip-Crzm7Eux.js} +2 -2
  33. package/dist/{Chip-C0x-6g2h.js.map → Chip-Crzm7Eux.js.map} +1 -1
  34. package/dist/{CodeBlock-DKnWINdV.js → CodeBlock-CX8_dMPD.js} +3 -3
  35. package/dist/{CodeBlock-DKnWINdV.js.map → CodeBlock-CX8_dMPD.js.map} +1 -1
  36. package/dist/{CodeBlock-DTrzN95i.cjs → CodeBlock-rnGAu2DQ.cjs} +2 -2
  37. package/dist/{CodeBlock-DTrzN95i.cjs.map → CodeBlock-rnGAu2DQ.cjs.map} +1 -1
  38. package/dist/{ColorPicker-Doaegll4.cjs → ColorPicker-BaAdcqR9.cjs} +2 -2
  39. package/dist/{ColorPicker-Doaegll4.cjs.map → ColorPicker-BaAdcqR9.cjs.map} +1 -1
  40. package/dist/{ColorPicker-Bidev2DJ.js → ColorPicker-CwLivdAt.js} +3 -3
  41. package/dist/{ColorPicker-Bidev2DJ.js.map → ColorPicker-CwLivdAt.js.map} +1 -1
  42. package/dist/{ColorPickerPanel-DThSuUoz.js → ColorPickerPanel-CkrSIf35.js} +2 -2
  43. package/dist/{ColorPickerPanel-DThSuUoz.js.map → ColorPickerPanel-CkrSIf35.js.map} +1 -1
  44. package/dist/{ColorPickerPanel-048Fj7wv.cjs → ColorPickerPanel-IOhJJF1R.cjs} +2 -2
  45. package/dist/{ColorPickerPanel-048Fj7wv.cjs.map → ColorPickerPanel-IOhJJF1R.cjs.map} +1 -1
  46. package/dist/{ColorRamp-CGw4D9bf.cjs → ColorRamp-BCy8a7ks.cjs} +2 -2
  47. package/dist/{ColorRamp-CGw4D9bf.cjs.map → ColorRamp-BCy8a7ks.cjs.map} +1 -1
  48. package/dist/{ColorRamp-Reb0q69d.js → ColorRamp-DbFOsspz.js} +2 -2
  49. package/dist/{ColorRamp-Reb0q69d.js.map → ColorRamp-DbFOsspz.js.map} +1 -1
  50. package/dist/ConfigProvider-CYSpuSMJ.cjs +2 -0
  51. package/dist/ConfigProvider-CYSpuSMJ.cjs.map +1 -0
  52. package/dist/ConfigProvider-DtyUlWk6.js +394 -0
  53. package/dist/ConfigProvider-DtyUlWk6.js.map +1 -0
  54. package/dist/{CopyButton-Cnab62vt.cjs → CopyButton-DUG5s3TM.cjs} +2 -2
  55. package/dist/{CopyButton-Cnab62vt.cjs.map → CopyButton-DUG5s3TM.cjs.map} +1 -1
  56. package/dist/{CopyButton-Dm8-V4ku.js → CopyButton-LURMuaYw.js} +3 -3
  57. package/dist/{CopyButton-Dm8-V4ku.js.map → CopyButton-LURMuaYw.js.map} +1 -1
  58. package/dist/{DatePicker-CaGeW_-j.cjs → DatePicker-Bw9gLB8o.cjs} +2 -2
  59. package/dist/{DatePicker-CaGeW_-j.cjs.map → DatePicker-Bw9gLB8o.cjs.map} +1 -1
  60. package/dist/{DatePicker-C4MTCmDn.js → DatePicker-CSIBYSZt.js} +4 -4
  61. package/dist/{DatePicker-C4MTCmDn.js.map → DatePicker-CSIBYSZt.js.map} +1 -1
  62. package/dist/{DateTimePicker-B0CjHKPV.js → DateTimePicker-C9F2yJMf.js} +7 -7
  63. package/dist/{DateTimePicker-B0CjHKPV.js.map → DateTimePicker-C9F2yJMf.js.map} +1 -1
  64. package/dist/{DateTimePicker-DXKaAYey.cjs → DateTimePicker-kikKdt0F.cjs} +2 -2
  65. package/dist/{DateTimePicker-DXKaAYey.cjs.map → DateTimePicker-kikKdt0F.cjs.map} +1 -1
  66. package/dist/{DescriptionList-BSDwobDc.cjs → DescriptionList-DnGkHdzT.cjs} +2 -2
  67. package/dist/{DescriptionList-BSDwobDc.cjs.map → DescriptionList-DnGkHdzT.cjs.map} +1 -1
  68. package/dist/{DescriptionList-BkUS5egS.js → DescriptionList-kfNXbf_D.js} +4 -4
  69. package/dist/{DescriptionList-BkUS5egS.js.map → DescriptionList-kfNXbf_D.js.map} +1 -1
  70. package/dist/{EmptyState-CkkFHKrh.cjs → EmptyState-BM5LrRLq.cjs} +2 -2
  71. package/dist/{EmptyState-CkkFHKrh.cjs.map → EmptyState-BM5LrRLq.cjs.map} +1 -1
  72. package/dist/{EmptyState-DXoaPC7o.js → EmptyState-DrSj2XV_.js} +2 -2
  73. package/dist/{EmptyState-DXoaPC7o.js.map → EmptyState-DrSj2XV_.js.map} +1 -1
  74. package/dist/{ErrorBoundary-CSP_Ctg6.js → ErrorBoundary-DsP4hO_V.js} +3 -3
  75. package/dist/{ErrorBoundary-CSP_Ctg6.js.map → ErrorBoundary-DsP4hO_V.js.map} +1 -1
  76. package/dist/{ErrorBoundary-tZjKtO28.cjs → ErrorBoundary-yz669VEu.cjs} +2 -2
  77. package/dist/{ErrorBoundary-tZjKtO28.cjs.map → ErrorBoundary-yz669VEu.cjs.map} +1 -1
  78. package/dist/{ErrorState-JH4JdrTI.cjs → ErrorState-BThPIYaM.cjs} +2 -2
  79. package/dist/{ErrorState-JH4JdrTI.cjs.map → ErrorState-BThPIYaM.cjs.map} +1 -1
  80. package/dist/{ErrorState-WYsly5-i.js → ErrorState-DEngucdq.js} +7 -7
  81. package/dist/{ErrorState-WYsly5-i.js.map → ErrorState-DEngucdq.js.map} +1 -1
  82. package/dist/{FileCard-D4TB3qGG.js → FileCard-CmCESTQd.js} +3 -3
  83. package/dist/{FileCard-D4TB3qGG.js.map → FileCard-CmCESTQd.js.map} +1 -1
  84. package/dist/{FileCard-BIfPqeek.cjs → FileCard-wxDT2rj9.cjs} +2 -2
  85. package/dist/{FileCard-BIfPqeek.cjs.map → FileCard-wxDT2rj9.cjs.map} +1 -1
  86. package/dist/{FileUploader-YE_DfTNC.cjs → FileUploader-DBNRp5eT.cjs} +2 -2
  87. package/dist/{FileUploader-YE_DfTNC.cjs.map → FileUploader-DBNRp5eT.cjs.map} +1 -1
  88. package/dist/{FileUploader-DPVF76Ha.js → FileUploader-Dp1r4Sxc.js} +29 -29
  89. package/dist/{FileUploader-DPVF76Ha.js.map → FileUploader-Dp1r4Sxc.js.map} +1 -1
  90. package/dist/{FullscreenToggle-ipX55Nj4.cjs → FullscreenToggle-DVdQriWB.cjs} +2 -2
  91. package/dist/{FullscreenToggle-ipX55Nj4.cjs.map → FullscreenToggle-DVdQriWB.cjs.map} +1 -1
  92. package/dist/{FullscreenToggle-CxwGPLdd.js → FullscreenToggle-WGsbE3Op.js} +3 -3
  93. package/dist/{FullscreenToggle-CxwGPLdd.js.map → FullscreenToggle-WGsbE3Op.js.map} +1 -1
  94. package/dist/{IconButton-U_sr2Ahy.cjs → IconButton-DSPdv-oI.cjs} +2 -2
  95. package/dist/{IconButton-U_sr2Ahy.cjs.map → IconButton-DSPdv-oI.cjs.map} +1 -1
  96. package/dist/{IconButton-re6xITGO.js → IconButton-iWbUJAz7.js} +2 -2
  97. package/dist/{IconButton-re6xITGO.js.map → IconButton-iWbUJAz7.js.map} +1 -1
  98. package/dist/{ImageEditor-BwrG1fk7.js → ImageEditor-BDNys8pq.js} +5 -5
  99. package/dist/{ImageEditor-BwrG1fk7.js.map → ImageEditor-BDNys8pq.js.map} +1 -1
  100. package/dist/{ImageEditor-1n50vo_v.cjs → ImageEditor-C40dp2-V.cjs} +2 -2
  101. package/dist/{ImageEditor-1n50vo_v.cjs.map → ImageEditor-C40dp2-V.cjs.map} +1 -1
  102. package/dist/{Loader-7v1QBvHY.js → Loader-DD1vfqmN.js} +2 -2
  103. package/dist/{Loader-7v1QBvHY.js.map → Loader-DD1vfqmN.js.map} +1 -1
  104. package/dist/{Loader-BE3SQr7W.cjs → Loader-RyFTP2X5.cjs} +2 -2
  105. package/dist/{Loader-BE3SQr7W.cjs.map → Loader-RyFTP2X5.cjs.map} +1 -1
  106. package/dist/{LocationPicker-CVJ4jVn2.cjs → LocationPicker-B594f0bz.cjs} +2 -2
  107. package/dist/{LocationPicker-CVJ4jVn2.cjs.map → LocationPicker-B594f0bz.cjs.map} +1 -1
  108. package/dist/{LocationPicker-BvKtZFq0.js → LocationPicker-DpmYaYyd.js} +6 -6
  109. package/dist/{LocationPicker-BvKtZFq0.js.map → LocationPicker-DpmYaYyd.js.map} +1 -1
  110. package/dist/{Modal-CxODxl81.cjs → Modal-7cCok6fV.cjs} +2 -2
  111. package/dist/{Modal-CxODxl81.cjs.map → Modal-7cCok6fV.cjs.map} +1 -1
  112. package/dist/{Modal-DpoiMMM3.js → Modal-DVGTD2Ck.js} +3 -3
  113. package/dist/{Modal-DpoiMMM3.js.map → Modal-DVGTD2Ck.js.map} +1 -1
  114. package/dist/{MultiSelect-B7KwEhL5.js → MultiSelect-D-X833xt.js} +4 -4
  115. package/dist/{MultiSelect-B7KwEhL5.js.map → MultiSelect-D-X833xt.js.map} +1 -1
  116. package/dist/{MultiSelect-2GouMRTl.cjs → MultiSelect-DTKNjUDH.cjs} +2 -2
  117. package/dist/{MultiSelect-2GouMRTl.cjs.map → MultiSelect-DTKNjUDH.cjs.map} +1 -1
  118. package/dist/{NumberField-ThojS4K3.js → NumberField-OPOl0Yph.js} +3 -3
  119. package/dist/{NumberField-ThojS4K3.js.map → NumberField-OPOl0Yph.js.map} +1 -1
  120. package/dist/{NumberField-o2z2QNK1.cjs → NumberField-Xz4yQMlm.cjs} +2 -2
  121. package/dist/{NumberField-o2z2QNK1.cjs.map → NumberField-Xz4yQMlm.cjs.map} +1 -1
  122. package/dist/{OtpField-C3MlMZ2F.js → OtpField-CLrDMNtS.js} +2 -2
  123. package/dist/{OtpField-C3MlMZ2F.js.map → OtpField-CLrDMNtS.js.map} +1 -1
  124. package/dist/{OtpField-BhZq44vV.cjs → OtpField-kd0YghZq.cjs} +2 -2
  125. package/dist/{OtpField-BhZq44vV.cjs.map → OtpField-kd0YghZq.cjs.map} +1 -1
  126. package/dist/{PageError-63Gk6fVC.js → PageError-BIiZDzey.js} +5 -5
  127. package/dist/{PageError-63Gk6fVC.js.map → PageError-BIiZDzey.js.map} +1 -1
  128. package/dist/{PageError-CCKWbrc5.cjs → PageError-v6MAH_OL.cjs} +2 -2
  129. package/dist/{PageError-CCKWbrc5.cjs.map → PageError-v6MAH_OL.cjs.map} +1 -1
  130. package/dist/{PageLayout-BekkDBtT.js → PageLayout-BjaPfXvb.js} +4 -4
  131. package/dist/{PageLayout-BekkDBtT.js.map → PageLayout-BjaPfXvb.js.map} +1 -1
  132. package/dist/{PageLayout-CDPUYu6A.cjs → PageLayout-DH3jochw.cjs} +2 -2
  133. package/dist/{PageLayout-CDPUYu6A.cjs.map → PageLayout-DH3jochw.cjs.map} +1 -1
  134. package/dist/{PageNotFound-BD3zX3cd.js → PageNotFound-C1oSsMG-.js} +5 -5
  135. package/dist/{PageNotFound-BD3zX3cd.js.map → PageNotFound-C1oSsMG-.js.map} +1 -1
  136. package/dist/{PageNotFound-CTR6htwa.cjs → PageNotFound-Cse4bROv.cjs} +2 -2
  137. package/dist/{PageNotFound-CTR6htwa.cjs.map → PageNotFound-Cse4bROv.cjs.map} +1 -1
  138. package/dist/{Pagination-qKjISBJ9.js → Pagination-BNJdqcu4.js} +2 -2
  139. package/dist/{Pagination-qKjISBJ9.js.map → Pagination-BNJdqcu4.js.map} +1 -1
  140. package/dist/{Pagination-BJvLUjQ0.cjs → Pagination-DkmfEmgK.cjs} +2 -2
  141. package/dist/{Pagination-BJvLUjQ0.cjs.map → Pagination-DkmfEmgK.cjs.map} +1 -1
  142. package/dist/{PaletteField-y8KpR4Ap.js → PaletteField-Cdky6Zka.js} +3 -3
  143. package/dist/{PaletteField-y8KpR4Ap.js.map → PaletteField-Cdky6Zka.js.map} +1 -1
  144. package/dist/{PaletteField-CDS9CJW9.cjs → PaletteField-DqZl1mK0.cjs} +2 -2
  145. package/dist/{PaletteField-CDS9CJW9.cjs.map → PaletteField-DqZl1mK0.cjs.map} +1 -1
  146. package/dist/{PhoneField-OjsuevPx.js → PhoneField-DmFaJJEa.js} +4 -4
  147. package/dist/{PhoneField-OjsuevPx.js.map → PhoneField-DmFaJJEa.js.map} +1 -1
  148. package/dist/{PhoneField-Df3J6Hhg.cjs → PhoneField-jq-3_i_b.cjs} +2 -2
  149. package/dist/{PhoneField-Df3J6Hhg.cjs.map → PhoneField-jq-3_i_b.cjs.map} +1 -1
  150. package/dist/{Popconfirm-aCyniPnH.js → Popconfirm-D-8ZG2WR.js} +3 -3
  151. package/dist/{Popconfirm-aCyniPnH.js.map → Popconfirm-D-8ZG2WR.js.map} +1 -1
  152. package/dist/{Popconfirm-BKzJ_EZy.cjs → Popconfirm-KOE9gGi6.cjs} +2 -2
  153. package/dist/{Popconfirm-BKzJ_EZy.cjs.map → Popconfirm-KOE9gGi6.cjs.map} +1 -1
  154. package/dist/{Progress-DWOoLd8u.cjs → Progress-7EyhPtnu.cjs} +2 -2
  155. package/dist/{Progress-DWOoLd8u.cjs.map → Progress-7EyhPtnu.cjs.map} +1 -1
  156. package/dist/{Progress-DzxbkcaD.js → Progress-CdX666FP.js} +2 -2
  157. package/dist/{Progress-DzxbkcaD.js.map → Progress-CdX666FP.js.map} +1 -1
  158. package/dist/{QrCode-C8uAPiHq.cjs → QrCode-ClIJjjvF.cjs} +2 -2
  159. package/dist/{QrCode-C8uAPiHq.cjs.map → QrCode-ClIJjjvF.cjs.map} +1 -1
  160. package/dist/{QrCode-DaJYqBc1.js → QrCode-D7ocSDi7.js} +2 -2
  161. package/dist/{QrCode-DaJYqBc1.js.map → QrCode-D7ocSDi7.js.map} +1 -1
  162. package/dist/{RemoveDialog-MhEU5Zl3.js → RemoveDialog-DTzRPLaT.js} +5 -5
  163. package/dist/{RemoveDialog-MhEU5Zl3.js.map → RemoveDialog-DTzRPLaT.js.map} +1 -1
  164. package/dist/{RemoveDialog-BnOtR6-q.cjs → RemoveDialog-UsSX5z8Y.cjs} +2 -2
  165. package/dist/{RemoveDialog-BnOtR6-q.cjs.map → RemoveDialog-UsSX5z8Y.cjs.map} +1 -1
  166. package/dist/{RichTextEditor-zkoxujnO.js → RichTextEditor-BMctlkVC.js} +7 -7
  167. package/dist/{RichTextEditor-zkoxujnO.js.map → RichTextEditor-BMctlkVC.js.map} +1 -1
  168. package/dist/{RichTextEditor-Cnrnvv1f.cjs → RichTextEditor-Bh0Q3dIW.cjs} +2 -2
  169. package/dist/{RichTextEditor-Cnrnvv1f.cjs.map → RichTextEditor-Bh0Q3dIW.cjs.map} +1 -1
  170. package/dist/{RootLayout-Z9PuRfsa.cjs → RootLayout-BztZetpk.cjs} +2 -2
  171. package/dist/{RootLayout-Z9PuRfsa.cjs.map → RootLayout-BztZetpk.cjs.map} +1 -1
  172. package/dist/{RootLayout-C4r9i5Go.js → RootLayout-CTkv4iQJ.js} +14 -14
  173. package/dist/{RootLayout-C4r9i5Go.js.map → RootLayout-CTkv4iQJ.js.map} +1 -1
  174. package/dist/{Select-CylqFHce.cjs → Select-BzVyK6Ne.cjs} +2 -2
  175. package/dist/{Select-CylqFHce.cjs.map → Select-BzVyK6Ne.cjs.map} +1 -1
  176. package/dist/{Select-jT94L1vq.js → Select-CmonDIIU.js} +3 -3
  177. package/dist/{Select-jT94L1vq.js.map → Select-CmonDIIU.js.map} +1 -1
  178. package/dist/{Sidebar-B1O2RsbR.js → Sidebar-CLr-DyQ_.js} +3 -3
  179. package/dist/{Sidebar-B1O2RsbR.js.map → Sidebar-CLr-DyQ_.js.map} +1 -1
  180. package/dist/{Sidebar-Bcm0fgVm.cjs → Sidebar-CM-jZfj5.cjs} +2 -2
  181. package/dist/{Sidebar-Bcm0fgVm.cjs.map → Sidebar-CM-jZfj5.cjs.map} +1 -1
  182. package/dist/{Slider-DC-ugZwT.js → Slider-C7Wb3q_F.js} +2 -2
  183. package/dist/{Slider-DC-ugZwT.js.map → Slider-C7Wb3q_F.js.map} +1 -1
  184. package/dist/{Slider-CV7ug0WF.cjs → Slider-Oe9VSAdy.cjs} +2 -2
  185. package/dist/{Slider-CV7ug0WF.cjs.map → Slider-Oe9VSAdy.cjs.map} +1 -1
  186. package/dist/{SpeedDial-C6yiMUe8.js → SpeedDial-CCGQlwn2.js} +2 -2
  187. package/dist/{SpeedDial-C6yiMUe8.js.map → SpeedDial-CCGQlwn2.js.map} +1 -1
  188. package/dist/{SpeedDial-DOgm2DDX.cjs → SpeedDial-DpIXoYHB.cjs} +2 -2
  189. package/dist/{SpeedDial-DOgm2DDX.cjs.map → SpeedDial-DpIXoYHB.cjs.map} +1 -1
  190. package/dist/{Stepper-BZdYGpBN.js → Stepper-D_WKS1RG.js} +2 -2
  191. package/dist/{Stepper-BZdYGpBN.js.map → Stepper-D_WKS1RG.js.map} +1 -1
  192. package/dist/{Stepper-DqM86TGV.cjs → Stepper-PBDU60G_.cjs} +2 -2
  193. package/dist/{Stepper-DqM86TGV.cjs.map → Stepper-PBDU60G_.cjs.map} +1 -1
  194. package/dist/{Table-BgaCwRDQ.cjs → Table-CZ4n4-TN.cjs} +2 -2
  195. package/dist/{Table-BgaCwRDQ.cjs.map → Table-CZ4n4-TN.cjs.map} +1 -1
  196. package/dist/{Table-FZlVWoYi.js → Table-DZQVa_PE.js} +16 -16
  197. package/dist/{Table-FZlVWoYi.js.map → Table-DZQVa_PE.js.map} +1 -1
  198. package/dist/{Tabs-BqQPkorY.js → Tabs-B063mP-v.js} +12 -12
  199. package/dist/{Tabs-BqQPkorY.js.map → Tabs-B063mP-v.js.map} +1 -1
  200. package/dist/{Tabs-kGeyFhJ6.cjs → Tabs-Byhqm-TE.cjs} +2 -2
  201. package/dist/{Tabs-kGeyFhJ6.cjs.map → Tabs-Byhqm-TE.cjs.map} +1 -1
  202. package/dist/{TagsField-B_sjp48X.cjs → TagsField-g_LtwYgz.cjs} +2 -2
  203. package/dist/{TagsField-B_sjp48X.cjs.map → TagsField-g_LtwYgz.cjs.map} +1 -1
  204. package/dist/{TagsField-ByTx9JXK.js → TagsField-hQFYyNcM.js} +4 -4
  205. package/dist/{TagsField-ByTx9JXK.js.map → TagsField-hQFYyNcM.js.map} +1 -1
  206. package/dist/{TextField-CBYJIfau.cjs → TextField-D4s2hGSd.cjs} +2 -2
  207. package/dist/{TextField-CBYJIfau.cjs.map → TextField-D4s2hGSd.cjs.map} +1 -1
  208. package/dist/{TextField-CyKIx-d-.js → TextField-Dfpk0jOg.js} +3 -3
  209. package/dist/{TextField-CyKIx-d-.js.map → TextField-Dfpk0jOg.js.map} +1 -1
  210. package/dist/{ThemeToggle-Dg6IishB.js → ThemeToggle-BQQ3eswr.js} +7 -7
  211. package/dist/{ThemeToggle-Dg6IishB.js.map → ThemeToggle-BQQ3eswr.js.map} +1 -1
  212. package/dist/{ThemeToggle-D2dIqiBa.cjs → ThemeToggle-BTTI7Jz0.cjs} +2 -2
  213. package/dist/{ThemeToggle-D2dIqiBa.cjs.map → ThemeToggle-BTTI7Jz0.cjs.map} +1 -1
  214. package/dist/{TimeColumns-Cx8J5qzW.js → TimeColumns-BpjhrNCq.js} +2 -2
  215. package/dist/{TimeColumns-Cx8J5qzW.js.map → TimeColumns-BpjhrNCq.js.map} +1 -1
  216. package/dist/{TimeColumns-DVmK_T_P.cjs → TimeColumns-DZYGWWG_.cjs} +2 -2
  217. package/dist/{TimeColumns-DVmK_T_P.cjs.map → TimeColumns-DZYGWWG_.cjs.map} +1 -1
  218. package/dist/{TimePicker-0nZOPRKp.cjs → TimePicker-DChtZgBs.cjs} +2 -2
  219. package/dist/{TimePicker-0nZOPRKp.cjs.map → TimePicker-DChtZgBs.cjs.map} +1 -1
  220. package/dist/{TimePicker-sAhtvqQ4.js → TimePicker-mzoMIlpq.js} +5 -5
  221. package/dist/{TimePicker-sAhtvqQ4.js.map → TimePicker-mzoMIlpq.js.map} +1 -1
  222. package/dist/{Toaster-BOW9rzLq.js → Toaster-79DvOW80.js} +8 -8
  223. package/dist/{Toaster-BOW9rzLq.js.map → Toaster-79DvOW80.js.map} +1 -1
  224. package/dist/{Toaster-DYGo92ke.cjs → Toaster-lonArt-H.cjs} +2 -2
  225. package/dist/{Toaster-DYGo92ke.cjs.map → Toaster-lonArt-H.cjs.map} +1 -1
  226. package/dist/{TranslatedFields-C_DuLotV.cjs → TranslatedFields-BYpMrYaw.cjs} +2 -2
  227. package/dist/{TranslatedFields-C_DuLotV.cjs.map → TranslatedFields-BYpMrYaw.cjs.map} +1 -1
  228. package/dist/{TranslatedFields-CcE0td9p.js → TranslatedFields-CHHtXO_n.js} +9 -9
  229. package/dist/{TranslatedFields-CcE0td9p.js.map → TranslatedFields-CHHtXO_n.js.map} +1 -1
  230. package/dist/{UserCard-DeONbaKj.js → UserCard-BJFNP_nl.js} +3 -3
  231. package/dist/{UserCard-DeONbaKj.js.map → UserCard-BJFNP_nl.js.map} +1 -1
  232. package/dist/{UserCard-DLVptkLr.cjs → UserCard-SlkCgZS9.cjs} +2 -2
  233. package/dist/{UserCard-DLVptkLr.cjs.map → UserCard-SlkCgZS9.cjs.map} +1 -1
  234. package/dist/app/AdminRoot.d.cts +9 -4
  235. package/dist/app/AdminRoot.d.ts +9 -4
  236. package/dist/auth/AuthGuard.d.cts +9 -3
  237. package/dist/auth/AuthGuard.d.ts +9 -3
  238. package/dist/auth/authLayoutRoute.d.cts +11 -3
  239. package/dist/auth/authLayoutRoute.d.ts +11 -3
  240. package/dist/auth/authRedirect.d.cts +64 -0
  241. package/dist/auth/authRedirect.d.ts +64 -0
  242. package/dist/authLayoutRoute-DCG9gCZ8.cjs +2 -0
  243. package/dist/authLayoutRoute-DCG9gCZ8.cjs.map +1 -0
  244. package/dist/authLayoutRoute-TuEqVizw.js +15 -0
  245. package/dist/authLayoutRoute-TuEqVizw.js.map +1 -0
  246. package/dist/components/Alert/index.cjs +1 -1
  247. package/dist/components/Alert/index.js +1 -1
  248. package/dist/components/Breadcrumbs/index.cjs +1 -1
  249. package/dist/components/Breadcrumbs/index.js +1 -1
  250. package/dist/components/Button/index.cjs +1 -1
  251. package/dist/components/Button/index.js +1 -1
  252. package/dist/components/Card/index.cjs +1 -1
  253. package/dist/components/Card/index.js +1 -1
  254. package/dist/components/Chip/index.cjs +1 -1
  255. package/dist/components/Chip/index.js +1 -1
  256. package/dist/components/CodeBlock/index.cjs +1 -1
  257. package/dist/components/CodeBlock/index.js +1 -1
  258. package/dist/components/ColorPicker/index.cjs +1 -1
  259. package/dist/components/ColorPicker/index.js +1 -1
  260. package/dist/components/ColorRamp/index.cjs +1 -1
  261. package/dist/components/ColorRamp/index.js +1 -1
  262. package/dist/components/CopyButton/index.cjs +1 -1
  263. package/dist/components/CopyButton/index.js +1 -1
  264. package/dist/components/DatePicker/index.cjs +1 -1
  265. package/dist/components/DatePicker/index.js +1 -1
  266. package/dist/components/DateTimePicker/index.cjs +1 -1
  267. package/dist/components/DateTimePicker/index.js +1 -1
  268. package/dist/components/DescriptionList/index.cjs +1 -1
  269. package/dist/components/DescriptionList/index.js +1 -1
  270. package/dist/components/EmptyState/index.cjs +1 -1
  271. package/dist/components/EmptyState/index.js +1 -1
  272. package/dist/components/ErrorState/index.cjs +1 -1
  273. package/dist/components/ErrorState/index.js +2 -2
  274. package/dist/components/FileCard/index.cjs +1 -1
  275. package/dist/components/FileCard/index.js +1 -1
  276. package/dist/components/FileUploader/index.cjs +1 -1
  277. package/dist/components/FileUploader/index.js +1 -1
  278. package/dist/components/FullscreenToggle/index.cjs +1 -1
  279. package/dist/components/FullscreenToggle/index.js +1 -1
  280. package/dist/components/IconButton/index.cjs +1 -1
  281. package/dist/components/IconButton/index.js +1 -1
  282. package/dist/components/ImageEditor/index.cjs +1 -1
  283. package/dist/components/ImageEditor/index.js +1 -1
  284. package/dist/components/Loader/index.cjs +1 -1
  285. package/dist/components/Loader/index.js +1 -1
  286. package/dist/components/LocationPicker/index.cjs +1 -1
  287. package/dist/components/LocationPicker/index.js +1 -1
  288. package/dist/components/Modal/index.cjs +1 -1
  289. package/dist/components/Modal/index.js +1 -1
  290. package/dist/components/MultiSelect/index.cjs +1 -1
  291. package/dist/components/MultiSelect/index.js +1 -1
  292. package/dist/components/NumberField/index.cjs +1 -1
  293. package/dist/components/NumberField/index.js +1 -1
  294. package/dist/components/OtpField/index.cjs +1 -1
  295. package/dist/components/OtpField/index.js +1 -1
  296. package/dist/components/PageError/index.cjs +1 -1
  297. package/dist/components/PageError/index.js +1 -1
  298. package/dist/components/PageLayout/index.cjs +1 -1
  299. package/dist/components/PageLayout/index.js +1 -1
  300. package/dist/components/PageNotFound/index.cjs +1 -1
  301. package/dist/components/PageNotFound/index.js +1 -1
  302. package/dist/components/Pagination/index.cjs +1 -1
  303. package/dist/components/Pagination/index.js +1 -1
  304. package/dist/components/PaletteField/index.cjs +1 -1
  305. package/dist/components/PaletteField/index.js +1 -1
  306. package/dist/components/PhoneField/index.cjs +1 -1
  307. package/dist/components/PhoneField/index.js +1 -1
  308. package/dist/components/Popconfirm/index.cjs +1 -1
  309. package/dist/components/Popconfirm/index.js +1 -1
  310. package/dist/components/Progress/index.cjs +1 -1
  311. package/dist/components/Progress/index.js +1 -1
  312. package/dist/components/QrCode/index.cjs +1 -1
  313. package/dist/components/QrCode/index.js +1 -1
  314. package/dist/components/RemoveDialog/index.cjs +1 -1
  315. package/dist/components/RemoveDialog/index.js +1 -1
  316. package/dist/components/RichTextEditor/index.cjs +1 -1
  317. package/dist/components/RichTextEditor/index.js +1 -1
  318. package/dist/components/RootLayout/index.cjs +1 -1
  319. package/dist/components/RootLayout/index.js +1 -1
  320. package/dist/components/Select/index.cjs +1 -1
  321. package/dist/components/Select/index.js +1 -1
  322. package/dist/components/Sidebar/index.cjs +1 -1
  323. package/dist/components/Sidebar/index.js +1 -1
  324. package/dist/components/Slider/index.cjs +1 -1
  325. package/dist/components/Slider/index.js +1 -1
  326. package/dist/components/SpeedDial/index.cjs +1 -1
  327. package/dist/components/SpeedDial/index.js +1 -1
  328. package/dist/components/Stepper/index.cjs +1 -1
  329. package/dist/components/Stepper/index.js +1 -1
  330. package/dist/components/Table/index.cjs +1 -1
  331. package/dist/components/Table/index.js +1 -1
  332. package/dist/components/Tabs/index.cjs +1 -1
  333. package/dist/components/Tabs/index.js +1 -1
  334. package/dist/components/TagsField/index.cjs +1 -1
  335. package/dist/components/TagsField/index.js +1 -1
  336. package/dist/components/TextField/index.cjs +1 -1
  337. package/dist/components/TextField/index.js +1 -1
  338. package/dist/components/ThemeToggle/index.cjs +1 -1
  339. package/dist/components/ThemeToggle/index.js +1 -1
  340. package/dist/components/TimePicker/index.cjs +1 -1
  341. package/dist/components/TimePicker/index.js +1 -1
  342. package/dist/components/Toast/index.cjs +1 -1
  343. package/dist/components/Toast/index.js +1 -1
  344. package/dist/components/TranslatedFields/index.cjs +1 -1
  345. package/dist/components/TranslatedFields/index.js +1 -1
  346. package/dist/components/UserCard/index.cjs +1 -1
  347. package/dist/components/UserCard/index.js +1 -1
  348. package/dist/entries/app.cjs +1 -1
  349. package/dist/entries/app.js +1 -1
  350. package/dist/entries/auth.cjs +1 -1
  351. package/dist/entries/auth.d.cts +1 -0
  352. package/dist/entries/auth.d.ts +1 -0
  353. package/dist/entries/auth.js +7 -4
  354. package/dist/entries/components.cjs +1 -1
  355. package/dist/entries/components.js +52 -52
  356. package/dist/entries/i18n.cjs +1 -1
  357. package/dist/entries/i18n.js +1 -1
  358. package/dist/entries/theme.cjs +1 -1
  359. package/dist/entries/theme.d.cts +1 -1
  360. package/dist/entries/theme.d.ts +1 -1
  361. package/dist/entries/theme.js +20 -18
  362. package/dist/index.cjs +1 -1
  363. package/dist/index.js +259 -254
  364. package/dist/theme/ConfigProvider.d.cts +17 -0
  365. package/dist/theme/ConfigProvider.d.ts +17 -0
  366. package/dist/theme/index.d.cts +1 -1
  367. package/dist/theme/index.d.ts +1 -1
  368. package/dist/{useHomeTo-BL3e8Sc6.js → useHomeTo-BLSvhJd5.js} +2 -2
  369. package/dist/{useHomeTo-BL3e8Sc6.js.map → useHomeTo-BLSvhJd5.js.map} +1 -1
  370. package/dist/{useHomeTo-W1PDW5CU.cjs → useHomeTo-cXCg1tf0.cjs} +2 -2
  371. package/dist/{useHomeTo-W1PDW5CU.cjs.map → useHomeTo-cXCg1tf0.cjs.map} +1 -1
  372. package/dist/{useOptionMenu-CVl7VHXl.cjs → useOptionMenu-6ZffgbYG.cjs} +2 -2
  373. package/dist/{useOptionMenu-CVl7VHXl.cjs.map → useOptionMenu-6ZffgbYG.cjs.map} +1 -1
  374. package/dist/{useOptionMenu-BkKiZ6Ax.js → useOptionMenu-CxM6FHXL.js} +3 -3
  375. package/dist/{useOptionMenu-BkKiZ6Ax.js.map → useOptionMenu-CxM6FHXL.js.map} +1 -1
  376. package/package.json +1 -1
  377. package/dist/AdminRoot-BZ1v5vN9.js +0 -101
  378. package/dist/AdminRoot-BZ1v5vN9.js.map +0 -1
  379. package/dist/AdminRoot-DJ4-UMAB.cjs +0 -2
  380. package/dist/AdminRoot-DJ4-UMAB.cjs.map +0 -1
  381. package/dist/AuthGuard-CVklwDbj.js +0 -7
  382. package/dist/AuthGuard-CVklwDbj.js.map +0 -1
  383. package/dist/AuthGuard-kfOZviar.cjs +0 -2
  384. package/dist/AuthGuard-kfOZviar.cjs.map +0 -1
  385. package/dist/ConfigProvider-DBU6rOIA.cjs +0 -2
  386. package/dist/ConfigProvider-DBU6rOIA.cjs.map +0 -1
  387. package/dist/ConfigProvider-DVDGtCUc.js +0 -386
  388. package/dist/ConfigProvider-DVDGtCUc.js.map +0 -1
  389. package/dist/authLayoutRoute-B10sXioW.js +0 -11
  390. package/dist/authLayoutRoute-B10sXioW.js.map +0 -1
  391. package/dist/authLayoutRoute-BVQ4LhuU.cjs +0 -2
  392. package/dist/authLayoutRoute-BVQ4LhuU.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"NumberField-o2z2QNK1.cjs","sources":["../src/components/NumberField/NumberField.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type ChangeEvent,\n type CSSProperties,\n type FocusEvent,\n type InputHTMLAttributes,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { useFormContext } from '../../form/formContext'\nimport { useT } from '../../theme'\nimport { Icon } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { Typography } from '../Typography'\n// shared field chrome (label/control/helper) AND the `.control .iconButton` styling for the steppers\nimport fieldStyles from '../TextField/TextField.module.css'\n\nexport type NumberFieldSize = 'sm' | 'md' | 'lg'\n\n/** Allowed while typing — digits, an optional leading `-`, and one decimal point. */\nconst NUMERIC_RE = /^-?\\d*\\.?\\d*$/\n\n/** Parses the display string to a number, treating empty / in-progress input (`\"\"`, `\"-\"`, `\".\"`) as null. */\nfunction parseValue(raw: string): number | null {\n if (raw === '' || raw === '-' || raw === '.' || raw === '-.') return null\n const n = Number(raw)\n return Number.isNaN(n) ? null : n\n}\n\nfunction clampValue(n: number, min?: number, max?: number): number {\n if (min != null && n < min) return min\n if (max != null && n > max) return max\n return n\n}\n\n/** Kills binary float drift from repeated stepping (e.g. 0.1 + 0.2). */\nfunction roundStep(n: number): number {\n return Math.round(n * 1e6) / 1e6\n}\n\n/** Groups the integer part with `separator` for display (e.g. 32345345 → \"32.345.345\"). */\nfunction groupThousands(value: number, separator: string): string {\n const [intPart, decPart] = String(value).split('.')\n const sign = intPart.startsWith('-') ? '-' : ''\n const digits = sign ? intPart.slice(1) : intPart\n const grouped = digits.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator)\n return decPart != null ? `${sign}${grouped}.${decPart}` : `${sign}${grouped}`\n}\n\n/** Counts the \"significant\" (non-separator) chars — used to keep the caret stable across regrouping. */\nfunction countExcept(s: string, sep: string): number {\n let n = 0\n for (const c of s) if (c !== sep) n++\n return n\n}\n\n/** Index just after the `n`-th non-separator char in `str` (where the caret should land after regrouping). */\nfunction positionAfterExcept(str: string, sep: string, n: number): number {\n if (n <= 0) return 0\n let count = 0\n for (let i = 0; i < str.length; i++) {\n if (str[i] !== sep) {\n count += 1\n if (count === n) return i + 1\n }\n }\n return str.length\n}\n\nexport interface NumberFieldProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'value' | 'defaultValue' | 'onChange' | 'type' | 'min' | 'max' | 'step' | 'prefix'\n> {\n /** Label rendered above the field. */\n label?: ReactNode\n /** Preset size — drives the control height, font size and padding. */\n size?: NumberFieldSize\n /** Marks the field invalid: red border/focus ring + the `helperText` in the error color. */\n error?: boolean\n /** Helper / validation text under the field. Adopts the error color while `error`. */\n helperText?: ReactNode\n /** Adds a red asterisk after the label. */\n required?: boolean\n /** Stretches the field to fill its container width. Defaults to `true`. */\n fullWidth?: boolean\n /** Controlled numeric value (`null` = empty). */\n value?: number | null\n /** Initial value for uncontrolled use (`null` = empty). Defaults to `null`. */\n defaultValue?: number | null\n /** Fires with the parsed numeric value (or `null` when the field is empty). */\n onChange?: (value: number | null) => void\n /** Minimum value — clamps on blur and on the stepper, and disables `−` at the floor. Defaults to `0`; pass a negative `min` to allow negatives. */\n min?: number\n /** Maximum value — clamps on blur and on the stepper, and disables `+` at the ceiling. */\n max?: number\n /** Amount the `+`/`−` buttons add or subtract. Defaults to `1`. */\n step?: number\n /** Hides the `+`/`−` stepper buttons (keyboard entry only). */\n hideStepper?: boolean\n /**\n * Thousands-group separator shown **live** as you type, e.g. `\".\"` displays `32345345` as\n * `32.345.345` (or `\",\"`). The caret is preserved across regrouping; the `value`/`onChange`/form\n * value stay a plain `number`. Best for integers — with `\".\"` decimals aren't supported (the dot is\n * the group separator).\n */\n thousandSeparator?: string\n}\n\n/**\n * A numeric input with `+`/`−` stepper buttons. Supports `min`/`max` clamping, a `step` amount,\n * controlled (`value` + `onChange`) or uncontrolled (`defaultValue`) use, optional live thousands\n * grouping, and — like `TextField` — binds to a surrounding `<Form>` by `name` (its form value is a\n * real `number`, validated by the Zod schema). `onChange` emits a `number` or `null` (empty). Shares\n * `TextField`'s field chrome, so label, sizing, error and focus styling are identical.\n */\nexport const NumberField = forwardRef<HTMLInputElement, NumberFieldProps>(function NumberField(\n {\n label,\n size = 'md',\n error,\n helperText,\n required = false,\n fullWidth = true,\n value,\n defaultValue = null,\n onChange,\n min = 0,\n max,\n step = 1,\n hideStepper = false,\n thousandSeparator,\n name,\n onBlur,\n disabled = false,\n id: idProp,\n className,\n style,\n ...props\n },\n ref,\n) {\n const t = useT()\n const reactId = useId()\n const id = idProp ?? reactId\n const helperId = `${id}-helper`\n\n // Auto-bind to a surrounding <Form> by `name`. The form stores a real number; we use field() for\n // touched/error/helper and read/write the numeric value through values/setValue.\n const form = useFormContext()\n const isFormBound = Boolean(form && name)\n const bound = form && name ? form.field(name) : undefined\n\n const externalValue: number | null | undefined =\n value !== undefined\n ? value\n : isFormBound\n ? ((form!.values[name!] as number | null | undefined) ?? null)\n : undefined\n const isControlled = externalValue !== undefined\n const [internal, setInternal] = useState<number | null>(defaultValue)\n const numValue: number | null = isControlled ? externalValue! : internal\n\n // number <-> display string, applying live thousands grouping when `thousandSeparator` is set.\n const toDisplay = (v: number | null): string =>\n v == null ? '' : thousandSeparator != null ? groupThousands(v, thousandSeparator) : String(v)\n const fromDisplay = (raw: string): number | null =>\n parseValue(thousandSeparator != null ? raw.split(thousandSeparator).join('') : raw)\n\n // The display string mirrors `numValue` but tolerates in-progress input (\"-\", \"1.\" …).\n const [text, setText] = useState<string>(() => toDisplay(numValue))\n useEffect(() => {\n if (fromDisplay(text) !== numValue) setText(toDisplay(numValue))\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [numValue]) // re-sync only when the value changes from the outside (stepper, form, reset)\n\n // Caret restoration after regrouping (the formatted string length changes as separators move).\n const innerRef = useRef<HTMLInputElement>(null)\n const pendingCaret = useRef<number | null>(null)\n const setInputRef = useCallback(\n (node: HTMLInputElement | null) => {\n innerRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n },\n [ref],\n )\n useLayoutEffect(() => {\n const pos = pendingCaret.current\n if (pos == null) return\n pendingCaret.current = null\n innerRef.current?.setSelectionRange(pos, pos)\n })\n\n const resolvedError = error ?? bound?.error ?? false\n const resolvedHelperText = helperText ?? bound?.helperText\n\n const commit = (next: number | null) => {\n if (!isControlled) setInternal(next)\n if (isFormBound) form!.setValue(name!, next)\n onChange?.(next)\n }\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const el = event.target\n const raw = el.value\n\n if (thousandSeparator == null) {\n if (raw !== '' && !NUMERIC_RE.test(raw)) return // reject non-numeric keystrokes\n setText(raw)\n commit(parseValue(raw))\n return\n }\n\n // Live grouping: strip separators, validate, regroup, and remember where the caret should land.\n const sep = thousandSeparator\n const cleaned = raw.split(sep).join('')\n if (cleaned !== '' && !NUMERIC_RE.test(cleaned)) return\n const caret = el.selectionStart ?? raw.length\n const significantBefore = countExcept(raw.slice(0, caret), sep)\n const next = parseValue(cleaned)\n const formatted = next == null ? cleaned : groupThousands(next, sep)\n setText(formatted)\n commit(next)\n pendingCaret.current = positionAfterExcept(formatted, sep, significantBefore)\n }\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n if (numValue != null) {\n const clamped = clampValue(numValue, min, max)\n if (clamped !== numValue) commit(clamped)\n }\n bound?.onBlur(event)\n onBlur?.(event)\n }\n\n const stepBy = (direction: 1 | -1) => {\n const base = numValue ?? min ?? 0\n commit(clampValue(roundStep(base + direction * step), min, max))\n }\n\n const atMax = max != null && numValue != null && numValue >= max\n const atMin = min != null && numValue != null && numValue <= min\n\n return (\n <div\n className={clsx(\n fieldStyles.field,\n fieldStyles[size],\n fullWidth && fieldStyles.fullWidth,\n resolvedError && fieldStyles.error,\n disabled && fieldStyles.disabled,\n className,\n )}\n style={style as CSSProperties}\n >\n {label != null && (\n <label htmlFor={id} className={fieldStyles.label}>\n <Typography as=\"span\" variant=\"bodySmall\" color=\"muted\">\n {label}\n </Typography>\n {required && (\n <span className={fieldStyles.required} aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <div className={clsx(fieldStyles.control, !hideStepper && fieldStyles.hasRightAdornment)}>\n <input\n ref={setInputRef}\n id={id}\n name={name}\n type=\"text\"\n inputMode=\"decimal\"\n className={fieldStyles.input}\n value={text}\n onChange={handleChange}\n onBlur={handleBlur}\n disabled={disabled}\n aria-invalid={resolvedError || undefined}\n aria-describedby={resolvedHelperText != null ? helperId : undefined}\n {...props}\n />\n {!hideStepper && (\n <>\n {/* Filled icon buttons, sized via the shared `.control .iconButton` rule (flush square,\n stretched to the control height, scaled). The minus glyph is nudged for optical centering. */}\n <IconButton\n variant=\"filled\"\n color=\"primary\"\n className={fieldStyles.iconButton}\n style={{ marginRight: -2 }}\n disabled={disabled || atMin}\n aria-label={t('numberField.decrease')}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => stepBy(-1)}\n >\n <Icon name=\"Minus\" />\n </IconButton>\n <IconButton\n variant=\"filled\"\n color=\"primary\"\n className={fieldStyles.iconButton}\n disabled={disabled || atMax}\n aria-label={t('numberField.increase')}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => stepBy(1)}\n >\n <Icon name=\"Add\" />\n </IconButton>\n </>\n )}\n </div>\n\n {resolvedHelperText != null && (\n <Typography\n as=\"span\"\n id={helperId}\n variant=\"bodySmall\"\n color={resolvedError ? 'error' : 'muted'}\n className={fieldStyles.helper}\n >\n {resolvedHelperText}\n </Typography>\n )}\n </div>\n )\n})\n"],"names":["NUMERIC_RE","parseValue","raw","n","clampValue","min","max","roundStep","groupThousands","value","separator","intPart","decPart","sign","grouped","countExcept","s","sep","c","positionAfterExcept","str","count","i","NumberField","forwardRef","label","size","error","helperText","required","fullWidth","defaultValue","onChange","step","hideStepper","thousandSeparator","name","onBlur","disabled","idProp","className","style","props","ref","t","useT","reactId","useId","id","helperId","form","useFormContext","isFormBound","bound","externalValue","isControlled","internal","setInternal","useState","numValue","toDisplay","v","fromDisplay","text","setText","useEffect","innerRef","useRef","pendingCaret","setInputRef","useCallback","node","useLayoutEffect","pos","_a","resolvedError","resolvedHelperText","commit","next","handleChange","event","el","cleaned","caret","significantBefore","formatted","handleBlur","clamped","stepBy","direction","atMax","atMin","jsxs","clsx","fieldStyles","jsx","Typography","Fragment","IconButton","Icon"],"mappings":"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"}
1
+ {"version":3,"file":"NumberField-Xz4yQMlm.cjs","sources":["../src/components/NumberField/NumberField.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type ChangeEvent,\n type CSSProperties,\n type FocusEvent,\n type InputHTMLAttributes,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { useFormContext } from '../../form/formContext'\nimport { useT } from '../../theme'\nimport { Icon } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { Typography } from '../Typography'\n// shared field chrome (label/control/helper) AND the `.control .iconButton` styling for the steppers\nimport fieldStyles from '../TextField/TextField.module.css'\n\nexport type NumberFieldSize = 'sm' | 'md' | 'lg'\n\n/** Allowed while typing — digits, an optional leading `-`, and one decimal point. */\nconst NUMERIC_RE = /^-?\\d*\\.?\\d*$/\n\n/** Parses the display string to a number, treating empty / in-progress input (`\"\"`, `\"-\"`, `\".\"`) as null. */\nfunction parseValue(raw: string): number | null {\n if (raw === '' || raw === '-' || raw === '.' || raw === '-.') return null\n const n = Number(raw)\n return Number.isNaN(n) ? null : n\n}\n\nfunction clampValue(n: number, min?: number, max?: number): number {\n if (min != null && n < min) return min\n if (max != null && n > max) return max\n return n\n}\n\n/** Kills binary float drift from repeated stepping (e.g. 0.1 + 0.2). */\nfunction roundStep(n: number): number {\n return Math.round(n * 1e6) / 1e6\n}\n\n/** Groups the integer part with `separator` for display (e.g. 32345345 → \"32.345.345\"). */\nfunction groupThousands(value: number, separator: string): string {\n const [intPart, decPart] = String(value).split('.')\n const sign = intPart.startsWith('-') ? '-' : ''\n const digits = sign ? intPart.slice(1) : intPart\n const grouped = digits.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator)\n return decPart != null ? `${sign}${grouped}.${decPart}` : `${sign}${grouped}`\n}\n\n/** Counts the \"significant\" (non-separator) chars — used to keep the caret stable across regrouping. */\nfunction countExcept(s: string, sep: string): number {\n let n = 0\n for (const c of s) if (c !== sep) n++\n return n\n}\n\n/** Index just after the `n`-th non-separator char in `str` (where the caret should land after regrouping). */\nfunction positionAfterExcept(str: string, sep: string, n: number): number {\n if (n <= 0) return 0\n let count = 0\n for (let i = 0; i < str.length; i++) {\n if (str[i] !== sep) {\n count += 1\n if (count === n) return i + 1\n }\n }\n return str.length\n}\n\nexport interface NumberFieldProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'value' | 'defaultValue' | 'onChange' | 'type' | 'min' | 'max' | 'step' | 'prefix'\n> {\n /** Label rendered above the field. */\n label?: ReactNode\n /** Preset size — drives the control height, font size and padding. */\n size?: NumberFieldSize\n /** Marks the field invalid: red border/focus ring + the `helperText` in the error color. */\n error?: boolean\n /** Helper / validation text under the field. Adopts the error color while `error`. */\n helperText?: ReactNode\n /** Adds a red asterisk after the label. */\n required?: boolean\n /** Stretches the field to fill its container width. Defaults to `true`. */\n fullWidth?: boolean\n /** Controlled numeric value (`null` = empty). */\n value?: number | null\n /** Initial value for uncontrolled use (`null` = empty). Defaults to `null`. */\n defaultValue?: number | null\n /** Fires with the parsed numeric value (or `null` when the field is empty). */\n onChange?: (value: number | null) => void\n /** Minimum value — clamps on blur and on the stepper, and disables `−` at the floor. Defaults to `0`; pass a negative `min` to allow negatives. */\n min?: number\n /** Maximum value — clamps on blur and on the stepper, and disables `+` at the ceiling. */\n max?: number\n /** Amount the `+`/`−` buttons add or subtract. Defaults to `1`. */\n step?: number\n /** Hides the `+`/`−` stepper buttons (keyboard entry only). */\n hideStepper?: boolean\n /**\n * Thousands-group separator shown **live** as you type, e.g. `\".\"` displays `32345345` as\n * `32.345.345` (or `\",\"`). The caret is preserved across regrouping; the `value`/`onChange`/form\n * value stay a plain `number`. Best for integers — with `\".\"` decimals aren't supported (the dot is\n * the group separator).\n */\n thousandSeparator?: string\n}\n\n/**\n * A numeric input with `+`/`−` stepper buttons. Supports `min`/`max` clamping, a `step` amount,\n * controlled (`value` + `onChange`) or uncontrolled (`defaultValue`) use, optional live thousands\n * grouping, and — like `TextField` — binds to a surrounding `<Form>` by `name` (its form value is a\n * real `number`, validated by the Zod schema). `onChange` emits a `number` or `null` (empty). Shares\n * `TextField`'s field chrome, so label, sizing, error and focus styling are identical.\n */\nexport const NumberField = forwardRef<HTMLInputElement, NumberFieldProps>(function NumberField(\n {\n label,\n size = 'md',\n error,\n helperText,\n required = false,\n fullWidth = true,\n value,\n defaultValue = null,\n onChange,\n min = 0,\n max,\n step = 1,\n hideStepper = false,\n thousandSeparator,\n name,\n onBlur,\n disabled = false,\n id: idProp,\n className,\n style,\n ...props\n },\n ref,\n) {\n const t = useT()\n const reactId = useId()\n const id = idProp ?? reactId\n const helperId = `${id}-helper`\n\n // Auto-bind to a surrounding <Form> by `name`. The form stores a real number; we use field() for\n // touched/error/helper and read/write the numeric value through values/setValue.\n const form = useFormContext()\n const isFormBound = Boolean(form && name)\n const bound = form && name ? form.field(name) : undefined\n\n const externalValue: number | null | undefined =\n value !== undefined\n ? value\n : isFormBound\n ? ((form!.values[name!] as number | null | undefined) ?? null)\n : undefined\n const isControlled = externalValue !== undefined\n const [internal, setInternal] = useState<number | null>(defaultValue)\n const numValue: number | null = isControlled ? externalValue! : internal\n\n // number <-> display string, applying live thousands grouping when `thousandSeparator` is set.\n const toDisplay = (v: number | null): string =>\n v == null ? '' : thousandSeparator != null ? groupThousands(v, thousandSeparator) : String(v)\n const fromDisplay = (raw: string): number | null =>\n parseValue(thousandSeparator != null ? raw.split(thousandSeparator).join('') : raw)\n\n // The display string mirrors `numValue` but tolerates in-progress input (\"-\", \"1.\" …).\n const [text, setText] = useState<string>(() => toDisplay(numValue))\n useEffect(() => {\n if (fromDisplay(text) !== numValue) setText(toDisplay(numValue))\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [numValue]) // re-sync only when the value changes from the outside (stepper, form, reset)\n\n // Caret restoration after regrouping (the formatted string length changes as separators move).\n const innerRef = useRef<HTMLInputElement>(null)\n const pendingCaret = useRef<number | null>(null)\n const setInputRef = useCallback(\n (node: HTMLInputElement | null) => {\n innerRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n },\n [ref],\n )\n useLayoutEffect(() => {\n const pos = pendingCaret.current\n if (pos == null) return\n pendingCaret.current = null\n innerRef.current?.setSelectionRange(pos, pos)\n })\n\n const resolvedError = error ?? bound?.error ?? false\n const resolvedHelperText = helperText ?? bound?.helperText\n\n const commit = (next: number | null) => {\n if (!isControlled) setInternal(next)\n if (isFormBound) form!.setValue(name!, next)\n onChange?.(next)\n }\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const el = event.target\n const raw = el.value\n\n if (thousandSeparator == null) {\n if (raw !== '' && !NUMERIC_RE.test(raw)) return // reject non-numeric keystrokes\n setText(raw)\n commit(parseValue(raw))\n return\n }\n\n // Live grouping: strip separators, validate, regroup, and remember where the caret should land.\n const sep = thousandSeparator\n const cleaned = raw.split(sep).join('')\n if (cleaned !== '' && !NUMERIC_RE.test(cleaned)) return\n const caret = el.selectionStart ?? raw.length\n const significantBefore = countExcept(raw.slice(0, caret), sep)\n const next = parseValue(cleaned)\n const formatted = next == null ? cleaned : groupThousands(next, sep)\n setText(formatted)\n commit(next)\n pendingCaret.current = positionAfterExcept(formatted, sep, significantBefore)\n }\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n if (numValue != null) {\n const clamped = clampValue(numValue, min, max)\n if (clamped !== numValue) commit(clamped)\n }\n bound?.onBlur(event)\n onBlur?.(event)\n }\n\n const stepBy = (direction: 1 | -1) => {\n const base = numValue ?? min ?? 0\n commit(clampValue(roundStep(base + direction * step), min, max))\n }\n\n const atMax = max != null && numValue != null && numValue >= max\n const atMin = min != null && numValue != null && numValue <= min\n\n return (\n <div\n className={clsx(\n fieldStyles.field,\n fieldStyles[size],\n fullWidth && fieldStyles.fullWidth,\n resolvedError && fieldStyles.error,\n disabled && fieldStyles.disabled,\n className,\n )}\n style={style as CSSProperties}\n >\n {label != null && (\n <label htmlFor={id} className={fieldStyles.label}>\n <Typography as=\"span\" variant=\"bodySmall\" color=\"muted\">\n {label}\n </Typography>\n {required && (\n <span className={fieldStyles.required} aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <div className={clsx(fieldStyles.control, !hideStepper && fieldStyles.hasRightAdornment)}>\n <input\n ref={setInputRef}\n id={id}\n name={name}\n type=\"text\"\n inputMode=\"decimal\"\n className={fieldStyles.input}\n value={text}\n onChange={handleChange}\n onBlur={handleBlur}\n disabled={disabled}\n aria-invalid={resolvedError || undefined}\n aria-describedby={resolvedHelperText != null ? helperId : undefined}\n {...props}\n />\n {!hideStepper && (\n <>\n {/* Filled icon buttons, sized via the shared `.control .iconButton` rule (flush square,\n stretched to the control height, scaled). The minus glyph is nudged for optical centering. */}\n <IconButton\n variant=\"filled\"\n color=\"primary\"\n className={fieldStyles.iconButton}\n style={{ marginRight: -2 }}\n disabled={disabled || atMin}\n aria-label={t('numberField.decrease')}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => stepBy(-1)}\n >\n <Icon name=\"Minus\" />\n </IconButton>\n <IconButton\n variant=\"filled\"\n color=\"primary\"\n className={fieldStyles.iconButton}\n disabled={disabled || atMax}\n aria-label={t('numberField.increase')}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => stepBy(1)}\n >\n <Icon name=\"Add\" />\n </IconButton>\n </>\n )}\n </div>\n\n {resolvedHelperText != null && (\n <Typography\n as=\"span\"\n id={helperId}\n variant=\"bodySmall\"\n color={resolvedError ? 'error' : 'muted'}\n className={fieldStyles.helper}\n >\n {resolvedHelperText}\n </Typography>\n )}\n </div>\n )\n})\n"],"names":["NUMERIC_RE","parseValue","raw","n","clampValue","min","max","roundStep","groupThousands","value","separator","intPart","decPart","sign","grouped","countExcept","s","sep","c","positionAfterExcept","str","count","i","NumberField","forwardRef","label","size","error","helperText","required","fullWidth","defaultValue","onChange","step","hideStepper","thousandSeparator","name","onBlur","disabled","idProp","className","style","props","ref","t","useT","reactId","useId","id","helperId","form","useFormContext","isFormBound","bound","externalValue","isControlled","internal","setInternal","useState","numValue","toDisplay","v","fromDisplay","text","setText","useEffect","innerRef","useRef","pendingCaret","setInputRef","useCallback","node","useLayoutEffect","pos","_a","resolvedError","resolvedHelperText","commit","next","handleChange","event","el","cleaned","caret","significantBefore","formatted","handleBlur","clamped","stepBy","direction","atMax","atMin","jsxs","clsx","fieldStyles","jsx","Typography","Fragment","IconButton","Icon"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { clsx as T } from "clsx";
4
4
  import { u as lt } from "./formContext-B7ln1Miy.js";
5
5
  import { T as S } from "./Typography-ChSuxgkc.js";
6
6
  import { f as u } from "./TextField.module-6gYcR9TL.js";
7
- import { a as at } from "./ConfigProvider-DVDGtCUc.js";
7
+ import { a as at } from "./ConfigProvider-DtyUlWk6.js";
8
8
  const it = "_row_u40i0_2", ct = "_center_u40i0_14", nt = "_end_u40i0_15", ft = "_sm_u40i0_27", ut = "_md_u40i0_31", dt = "_lg_u40i0_35", mt = "_box_u40i0_41", pt = "_filled_u40i0_65", _t = "_invalid_u40i0_84", d = {
9
9
  row: it,
10
10
  center: ct,
@@ -171,4 +171,4 @@ const Bt = tt(function({
171
171
  export {
172
172
  Bt as O
173
173
  };
174
- //# sourceMappingURL=OtpField-C3MlMZ2F.js.map
174
+ //# sourceMappingURL=OtpField-CLrDMNtS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OtpField-C3MlMZ2F.js","sources":["../src/components/OtpField/OtpField.tsx"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type ClipboardEvent,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { useFormContext } from '../../form/formContext'\nimport { useT, type ThemeColor } from '../../theme'\nimport { Typography } from '../Typography'\nimport fieldStyles from '../TextField/TextField.module.css'\nimport styles from './OtpField.module.css'\n\nexport type OtpFieldSize = 'sm' | 'md' | 'lg'\n/** Which characters the code accepts. */\nexport type OtpFieldType = 'numeric' | 'alphabetic' | 'alphanumeric'\n\nexport type OtpFieldAlign = 'start' | 'center' | 'end'\n\n/** Allowed-character matcher per `type`. */\nconst PATTERN: Record<OtpFieldType, RegExp> = {\n numeric: /[0-9]/,\n alphabetic: /[A-Za-z]/,\n alphanumeric: /[A-Za-z0-9]/,\n}\n\n/** Split a code string into exactly `length` single-char slots, padded with empties. */\nfunction toChars(value: string, length: number): string[] {\n const out = [...value].slice(0, length)\n while (out.length < length) out.push('')\n return out\n}\n\nexport interface OtpFieldProps {\n /** Number of input boxes (the code length). Defaults to `4`. */\n length?: number\n /** Which characters are accepted (also drives the mobile keyboard). Defaults to `'numeric'`. */\n type?: OtpFieldType\n /** Controlled value — the concatenated code string. */\n value?: string\n /** Initial value for uncontrolled use. */\n defaultValue?: string\n /** Fires with the full code string on every change. */\n onChange?: (value: string) => void\n /** Fires with the code once every box is filled. */\n onComplete?: (value: string) => void\n /** Field name — the `<Form>` binding key (form value is the code `string`). */\n name?: string\n /** Label rendered above the boxes. */\n label?: ReactNode\n /** Helper / error text under the boxes (shown in the error color while `error`). */\n helperText?: ReactNode\n /** Marks the field invalid — reddens the boxes + helper. */\n error?: boolean\n /** Adds a red asterisk after the label. */\n required?: boolean\n /** Disables every box. */\n disabled?: boolean\n /** Focus the first box on mount. */\n autoFocus?: boolean\n /** Placeholder character shown in empty boxes (e.g. `'•'`). */\n placeholder?: string\n /** Preset size. Defaults to `'md'`. */\n size?: OtpFieldSize\n /** Horizontal alignment of the boxes within the field. Defaults to `'start'` (left). */\n align?: OtpFieldAlign\n /** Theme palette token for the focus ring / active box. Defaults to `'primary'`. */\n color?: ThemeColor\n className?: string\n style?: CSSProperties\n}\n\n/**\n * A one-time-passcode input — a row of single-character boxes for verification codes. **`length`**\n * (default `4`) sets the box count; **`type`** (`'numeric'` default · `'alphabetic'` · `'alphanumeric'`)\n * restricts the accepted characters and the mobile keyboard. Typing advances to the next box, Backspace\n * clears the box (in an empty box: clears the previous one and steps back), Arrows navigate, and **paste / SMS autofill** (`autocomplete=\"one-time-code\"`)\n * distributes the whole code across the boxes. The value is the concatenated string — controlled\n * (`value` + `onChange`) or uncontrolled (`defaultValue`); **`onComplete`** fires when all boxes are\n * filled. Shares the field-family chrome (`label` · `error` + `helperText` · `required` · `disabled` ·\n * `size`) and binds to a surrounding `<Form>` by **`name`** (form value = the code string; validate with\n * e.g. `z.string().length(4)` or a `type`-matching regex). Tinted by `color` via the shared\n * `--tz-btn-rgb` pattern; `role=\"group\"` with per-box `aria-label`s. Own CSS module (+ TextField's for\n * the label/helper chrome).\n */\nexport const OtpField = forwardRef<HTMLDivElement, OtpFieldProps>(function OtpField(\n {\n length = 4,\n type = 'numeric',\n value,\n defaultValue,\n onChange,\n onComplete,\n name,\n label,\n helperText,\n error,\n required = false,\n disabled = false,\n autoFocus = false,\n placeholder,\n size = 'md',\n align = 'start',\n color = 'primary',\n className,\n style,\n },\n ref,\n) {\n const t = useT()\n const reactId = useId()\n const helperId = `${reactId}-helper`\n const allowed = PATTERN[type]\n\n // bind to a surrounding <Form> by `name` — form value is the code string; error/touched via field()\n const form = useFormContext()\n const isFormBound = Boolean(form && name)\n const bound = form && name ? form.field(name) : undefined\n\n const externalValue =\n value !== undefined ? value : isFormBound ? (form!.values[name!] as string) : undefined\n const isControlled = value !== undefined || isFormBound\n const [internal, setInternal] = useState<string>(defaultValue ?? '')\n const currentValue = isControlled ? (externalValue ?? '') : internal\n\n const resolvedError = error ?? bound?.error ?? false\n const resolvedHelperText = helperText ?? bound?.helperText\n\n // the code split into exactly `length` single-char slots (padded with empties)\n const chars = toChars(currentValue, length)\n\n const inputsRef = useRef<(HTMLInputElement | null)[]>([])\n\n useEffect(() => {\n if (autoFocus) inputsRef.current[0]?.focus()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const focusBox = (i: number) => {\n const el = inputsRef.current[Math.max(0, Math.min(i, length - 1))]\n el?.focus()\n el?.select()\n }\n\n const commit = (nextChars: string[]) => {\n const next = nextChars.join('')\n if (!isControlled) setInternal(next)\n if (isFormBound) form!.setValue(name!, next)\n onChange?.(next)\n if (nextChars.every((c) => c !== '')) onComplete?.(next)\n }\n\n const handleChange = (index: number, raw: string) => {\n const filtered = [...raw].filter((c) => allowed.test(c))\n // a disallowed keystroke (raw non-empty but nothing survives the filter) is ignored\n if (raw !== '' && filtered.length === 0) return\n const nextChars = [...chars]\n if (filtered.length <= 1) {\n // a single typed char (boxes select-on-focus, so this replaces) — or a clear ('')\n nextChars[index] = filtered[0] ?? ''\n commit(nextChars)\n if (filtered[0]) focusBox(index + 1)\n } else {\n // multiple chars (SMS autofill dumps the whole code into one box) → distribute from here\n let k = index\n for (const ch of filtered) {\n if (k >= length) break\n nextChars[k] = ch\n k++\n }\n commit(nextChars)\n focusBox(k)\n }\n }\n\n const handleKeyDown = (index: number, event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Backspace') {\n if (chars[index] === '' && index > 0) {\n // empty box → step back and clear the previous one\n event.preventDefault()\n const nextChars = [...chars]\n nextChars[index - 1] = ''\n commit(nextChars)\n focusBox(index - 1)\n }\n // a non-empty box lets the native delete run → onChange fires with '' (stays put)\n } else if (event.key === 'ArrowLeft') {\n event.preventDefault()\n focusBox(index - 1)\n } else if (event.key === 'ArrowRight') {\n event.preventDefault()\n focusBox(index + 1)\n } else if (event.key === 'Delete') {\n event.preventDefault()\n const nextChars = [...chars]\n nextChars[index] = ''\n commit(nextChars)\n }\n }\n\n const handlePaste = (index: number, event: ClipboardEvent<HTMLInputElement>) => {\n event.preventDefault()\n const filtered = [...event.clipboardData.getData('text')].filter((c) => allowed.test(c))\n if (filtered.length === 0) return\n const nextChars = [...chars]\n let k = index\n for (const ch of filtered) {\n if (k >= length) break\n nextChars[k] = ch\n k++\n }\n commit(nextChars)\n focusBox(k)\n }\n\n // mark the field touched when focus leaves the whole widget (not when it hops between boxes)\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n bound?.onBlur(event as unknown as FocusEvent<HTMLInputElement>)\n }\n }\n\n return (\n <div\n ref={ref}\n className={clsx(\n fieldStyles.field,\n resolvedError && fieldStyles.error,\n disabled && fieldStyles.disabled,\n className,\n )}\n style={\n {\n '--tz-btn-rgb': `var(--tz-color-${color}-rgb)`,\n ...style,\n } as CSSProperties\n }\n >\n {label != null && (\n <span className={fieldStyles.label}>\n <Typography as=\"span\" variant=\"bodySmall\" color=\"muted\">\n {label}\n </Typography>\n {required && (\n <span className={fieldStyles.required} aria-hidden=\"true\">\n *\n </span>\n )}\n </span>\n )}\n\n <div\n role=\"group\"\n aria-label={typeof label === 'string' ? label : t('otpField.label')}\n aria-invalid={resolvedError || undefined}\n aria-describedby={resolvedHelperText != null ? helperId : undefined}\n className={clsx(styles.row, styles[size], styles[align], resolvedError && styles.invalid)}\n onBlur={handleBlur}\n >\n {chars.map((char, i) => (\n <input\n key={i}\n ref={(el) => {\n inputsRef.current[i] = el\n }}\n // the name goes on the first box only, so the form's scroll-to-error can target it\n name={i === 0 ? name : undefined}\n type=\"text\"\n inputMode={type === 'numeric' ? 'numeric' : 'text'}\n autoComplete={i === 0 ? 'one-time-code' : 'off'}\n aria-label={t('otpField.digit', { index: i + 1, total: length })}\n className={clsx(styles.box, char !== '' && styles.filled)}\n value={char}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(e) => handleChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={(e) => handlePaste(i, e)}\n onFocus={(e) => e.target.select()}\n />\n ))}\n </div>\n\n {resolvedHelperText != null && (\n <Typography\n as=\"span\"\n id={helperId}\n variant=\"bodySmall\"\n color={resolvedError ? 'error' : 'muted'}\n className={fieldStyles.helper}\n >\n {resolvedHelperText}\n </Typography>\n )}\n </div>\n )\n})\n"],"names":["PATTERN","toChars","value","length","out","OtpField","forwardRef","type","defaultValue","onChange","onComplete","name","label","helperText","error","required","disabled","autoFocus","placeholder","size","align","color","className","style","ref","t","useT","helperId","useId","allowed","form","useFormContext","isFormBound","bound","externalValue","isControlled","internal","setInternal","useState","currentValue","resolvedError","resolvedHelperText","chars","inputsRef","useRef","useEffect","_a","focusBox","i","el","commit","nextChars","next","c","handleChange","index","raw","filtered","k","ch","handleKeyDown","event","handlePaste","handleBlur","jsxs","clsx","fieldStyles","jsx","Typography","styles","char","e"],"mappings":"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"}
1
+ {"version":3,"file":"OtpField-CLrDMNtS.js","sources":["../src/components/OtpField/OtpField.tsx"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type ClipboardEvent,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { useFormContext } from '../../form/formContext'\nimport { useT, type ThemeColor } from '../../theme'\nimport { Typography } from '../Typography'\nimport fieldStyles from '../TextField/TextField.module.css'\nimport styles from './OtpField.module.css'\n\nexport type OtpFieldSize = 'sm' | 'md' | 'lg'\n/** Which characters the code accepts. */\nexport type OtpFieldType = 'numeric' | 'alphabetic' | 'alphanumeric'\n\nexport type OtpFieldAlign = 'start' | 'center' | 'end'\n\n/** Allowed-character matcher per `type`. */\nconst PATTERN: Record<OtpFieldType, RegExp> = {\n numeric: /[0-9]/,\n alphabetic: /[A-Za-z]/,\n alphanumeric: /[A-Za-z0-9]/,\n}\n\n/** Split a code string into exactly `length` single-char slots, padded with empties. */\nfunction toChars(value: string, length: number): string[] {\n const out = [...value].slice(0, length)\n while (out.length < length) out.push('')\n return out\n}\n\nexport interface OtpFieldProps {\n /** Number of input boxes (the code length). Defaults to `4`. */\n length?: number\n /** Which characters are accepted (also drives the mobile keyboard). Defaults to `'numeric'`. */\n type?: OtpFieldType\n /** Controlled value — the concatenated code string. */\n value?: string\n /** Initial value for uncontrolled use. */\n defaultValue?: string\n /** Fires with the full code string on every change. */\n onChange?: (value: string) => void\n /** Fires with the code once every box is filled. */\n onComplete?: (value: string) => void\n /** Field name — the `<Form>` binding key (form value is the code `string`). */\n name?: string\n /** Label rendered above the boxes. */\n label?: ReactNode\n /** Helper / error text under the boxes (shown in the error color while `error`). */\n helperText?: ReactNode\n /** Marks the field invalid — reddens the boxes + helper. */\n error?: boolean\n /** Adds a red asterisk after the label. */\n required?: boolean\n /** Disables every box. */\n disabled?: boolean\n /** Focus the first box on mount. */\n autoFocus?: boolean\n /** Placeholder character shown in empty boxes (e.g. `'•'`). */\n placeholder?: string\n /** Preset size. Defaults to `'md'`. */\n size?: OtpFieldSize\n /** Horizontal alignment of the boxes within the field. Defaults to `'start'` (left). */\n align?: OtpFieldAlign\n /** Theme palette token for the focus ring / active box. Defaults to `'primary'`. */\n color?: ThemeColor\n className?: string\n style?: CSSProperties\n}\n\n/**\n * A one-time-passcode input — a row of single-character boxes for verification codes. **`length`**\n * (default `4`) sets the box count; **`type`** (`'numeric'` default · `'alphabetic'` · `'alphanumeric'`)\n * restricts the accepted characters and the mobile keyboard. Typing advances to the next box, Backspace\n * clears the box (in an empty box: clears the previous one and steps back), Arrows navigate, and **paste / SMS autofill** (`autocomplete=\"one-time-code\"`)\n * distributes the whole code across the boxes. The value is the concatenated string — controlled\n * (`value` + `onChange`) or uncontrolled (`defaultValue`); **`onComplete`** fires when all boxes are\n * filled. Shares the field-family chrome (`label` · `error` + `helperText` · `required` · `disabled` ·\n * `size`) and binds to a surrounding `<Form>` by **`name`** (form value = the code string; validate with\n * e.g. `z.string().length(4)` or a `type`-matching regex). Tinted by `color` via the shared\n * `--tz-btn-rgb` pattern; `role=\"group\"` with per-box `aria-label`s. Own CSS module (+ TextField's for\n * the label/helper chrome).\n */\nexport const OtpField = forwardRef<HTMLDivElement, OtpFieldProps>(function OtpField(\n {\n length = 4,\n type = 'numeric',\n value,\n defaultValue,\n onChange,\n onComplete,\n name,\n label,\n helperText,\n error,\n required = false,\n disabled = false,\n autoFocus = false,\n placeholder,\n size = 'md',\n align = 'start',\n color = 'primary',\n className,\n style,\n },\n ref,\n) {\n const t = useT()\n const reactId = useId()\n const helperId = `${reactId}-helper`\n const allowed = PATTERN[type]\n\n // bind to a surrounding <Form> by `name` — form value is the code string; error/touched via field()\n const form = useFormContext()\n const isFormBound = Boolean(form && name)\n const bound = form && name ? form.field(name) : undefined\n\n const externalValue =\n value !== undefined ? value : isFormBound ? (form!.values[name!] as string) : undefined\n const isControlled = value !== undefined || isFormBound\n const [internal, setInternal] = useState<string>(defaultValue ?? '')\n const currentValue = isControlled ? (externalValue ?? '') : internal\n\n const resolvedError = error ?? bound?.error ?? false\n const resolvedHelperText = helperText ?? bound?.helperText\n\n // the code split into exactly `length` single-char slots (padded with empties)\n const chars = toChars(currentValue, length)\n\n const inputsRef = useRef<(HTMLInputElement | null)[]>([])\n\n useEffect(() => {\n if (autoFocus) inputsRef.current[0]?.focus()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const focusBox = (i: number) => {\n const el = inputsRef.current[Math.max(0, Math.min(i, length - 1))]\n el?.focus()\n el?.select()\n }\n\n const commit = (nextChars: string[]) => {\n const next = nextChars.join('')\n if (!isControlled) setInternal(next)\n if (isFormBound) form!.setValue(name!, next)\n onChange?.(next)\n if (nextChars.every((c) => c !== '')) onComplete?.(next)\n }\n\n const handleChange = (index: number, raw: string) => {\n const filtered = [...raw].filter((c) => allowed.test(c))\n // a disallowed keystroke (raw non-empty but nothing survives the filter) is ignored\n if (raw !== '' && filtered.length === 0) return\n const nextChars = [...chars]\n if (filtered.length <= 1) {\n // a single typed char (boxes select-on-focus, so this replaces) — or a clear ('')\n nextChars[index] = filtered[0] ?? ''\n commit(nextChars)\n if (filtered[0]) focusBox(index + 1)\n } else {\n // multiple chars (SMS autofill dumps the whole code into one box) → distribute from here\n let k = index\n for (const ch of filtered) {\n if (k >= length) break\n nextChars[k] = ch\n k++\n }\n commit(nextChars)\n focusBox(k)\n }\n }\n\n const handleKeyDown = (index: number, event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Backspace') {\n if (chars[index] === '' && index > 0) {\n // empty box → step back and clear the previous one\n event.preventDefault()\n const nextChars = [...chars]\n nextChars[index - 1] = ''\n commit(nextChars)\n focusBox(index - 1)\n }\n // a non-empty box lets the native delete run → onChange fires with '' (stays put)\n } else if (event.key === 'ArrowLeft') {\n event.preventDefault()\n focusBox(index - 1)\n } else if (event.key === 'ArrowRight') {\n event.preventDefault()\n focusBox(index + 1)\n } else if (event.key === 'Delete') {\n event.preventDefault()\n const nextChars = [...chars]\n nextChars[index] = ''\n commit(nextChars)\n }\n }\n\n const handlePaste = (index: number, event: ClipboardEvent<HTMLInputElement>) => {\n event.preventDefault()\n const filtered = [...event.clipboardData.getData('text')].filter((c) => allowed.test(c))\n if (filtered.length === 0) return\n const nextChars = [...chars]\n let k = index\n for (const ch of filtered) {\n if (k >= length) break\n nextChars[k] = ch\n k++\n }\n commit(nextChars)\n focusBox(k)\n }\n\n // mark the field touched when focus leaves the whole widget (not when it hops between boxes)\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n bound?.onBlur(event as unknown as FocusEvent<HTMLInputElement>)\n }\n }\n\n return (\n <div\n ref={ref}\n className={clsx(\n fieldStyles.field,\n resolvedError && fieldStyles.error,\n disabled && fieldStyles.disabled,\n className,\n )}\n style={\n {\n '--tz-btn-rgb': `var(--tz-color-${color}-rgb)`,\n ...style,\n } as CSSProperties\n }\n >\n {label != null && (\n <span className={fieldStyles.label}>\n <Typography as=\"span\" variant=\"bodySmall\" color=\"muted\">\n {label}\n </Typography>\n {required && (\n <span className={fieldStyles.required} aria-hidden=\"true\">\n *\n </span>\n )}\n </span>\n )}\n\n <div\n role=\"group\"\n aria-label={typeof label === 'string' ? label : t('otpField.label')}\n aria-invalid={resolvedError || undefined}\n aria-describedby={resolvedHelperText != null ? helperId : undefined}\n className={clsx(styles.row, styles[size], styles[align], resolvedError && styles.invalid)}\n onBlur={handleBlur}\n >\n {chars.map((char, i) => (\n <input\n key={i}\n ref={(el) => {\n inputsRef.current[i] = el\n }}\n // the name goes on the first box only, so the form's scroll-to-error can target it\n name={i === 0 ? name : undefined}\n type=\"text\"\n inputMode={type === 'numeric' ? 'numeric' : 'text'}\n autoComplete={i === 0 ? 'one-time-code' : 'off'}\n aria-label={t('otpField.digit', { index: i + 1, total: length })}\n className={clsx(styles.box, char !== '' && styles.filled)}\n value={char}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(e) => handleChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={(e) => handlePaste(i, e)}\n onFocus={(e) => e.target.select()}\n />\n ))}\n </div>\n\n {resolvedHelperText != null && (\n <Typography\n as=\"span\"\n id={helperId}\n variant=\"bodySmall\"\n color={resolvedError ? 'error' : 'muted'}\n className={fieldStyles.helper}\n >\n {resolvedHelperText}\n </Typography>\n )}\n </div>\n )\n})\n"],"names":["PATTERN","toChars","value","length","out","OtpField","forwardRef","type","defaultValue","onChange","onComplete","name","label","helperText","error","required","disabled","autoFocus","placeholder","size","align","color","className","style","ref","t","useT","helperId","useId","allowed","form","useFormContext","isFormBound","bound","externalValue","isControlled","internal","setInternal","useState","currentValue","resolvedError","resolvedHelperText","chars","inputsRef","useRef","useEffect","_a","focusBox","i","el","commit","nextChars","next","c","handleChange","index","raw","filtered","k","ch","handleKeyDown","event","handlePaste","handleBlur","jsxs","clsx","fieldStyles","jsx","Typography","styles","char","e"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";const i=require("react/jsx-runtime"),y=require("react"),k=require("clsx"),ee=require("./formContext-bTWrqdEV.cjs"),A=require("./Typography-d97DdbNd.cjs"),f=require("./TextField.module-DsNCo8vN.cjs"),te=require("./ConfigProvider-DBU6rOIA.cjs"),re="_row_u40i0_2",se="_center_u40i0_14",oe="_end_u40i0_15",le="_sm_u40i0_27",ce="_md_u40i0_31",ie="_lg_u40i0_35",ne="_box_u40i0_41",ae="_filled_u40i0_65",ue="_invalid_u40i0_84",p={row:re,center:se,end:oe,sm:le,md:ce,lg:ie,box:ne,filled:ae,invalid:ue},de={numeric:/[0-9]/,alphabetic:/[A-Za-z]/,alphanumeric:/[A-Za-z0-9]/};function fe(F,l){const n=[...F].slice(0,l);for(;n.length<l;)n.push("");return n}const pe=y.forwardRef(function({length:l=4,type:n="numeric",value:g,defaultValue:I,onChange:b,onComplete:T,name:a,label:x,helperText:z,error:P,required:C=!1,disabled:S=!1,autoFocus:E=!1,placeholder:M,size:O="md",align:V="start",color:K="primary",className:Z,style:$},H){const q=te.useT(),B=`${y.useId()}-helper`,N=de[n],h=ee.useFormContext(),w=!!(h&&a),o=h&&a?h.field(a):void 0,L=g!==void 0?g:w?h.values[a]:void 0,R=g!==void 0||w,[G,J]=y.useState(I??""),Q=R?L??"":G,v=P??(o==null?void 0:o.error)??!1,D=z??(o==null?void 0:o.helperText),u=fe(Q,l),j=y.useRef([]);y.useEffect(()=>{var t;E&&((t=j.current[0])==null||t.focus())},[]);const d=t=>{const e=j.current[Math.max(0,Math.min(t,l-1))];e==null||e.focus(),e==null||e.select()},m=t=>{const e=t.join("");R||J(e),w&&h.setValue(a,e),b==null||b(e),t.every(r=>r!=="")&&(T==null||T(e))},U=(t,e)=>{const r=[...e].filter(s=>N.test(s));if(e!==""&&r.length===0)return;const c=[...u];if(r.length<=1)c[t]=r[0]??"",m(c),r[0]&&d(t+1);else{let s=t;for(const _ of r){if(s>=l)break;c[s]=_,s++}m(c),d(s)}},W=(t,e)=>{if(e.key==="Backspace"){if(u[t]===""&&t>0){e.preventDefault();const r=[...u];r[t-1]="",m(r),d(t-1)}}else if(e.key==="ArrowLeft")e.preventDefault(),d(t-1);else if(e.key==="ArrowRight")e.preventDefault(),d(t+1);else if(e.key==="Delete"){e.preventDefault();const r=[...u];r[t]="",m(r)}},X=(t,e)=>{e.preventDefault();const r=[...e.clipboardData.getData("text")].filter(_=>N.test(_));if(r.length===0)return;const c=[...u];let s=t;for(const _ of r){if(s>=l)break;c[s]=_,s++}m(c),d(s)},Y=t=>{t.currentTarget.contains(t.relatedTarget)||o==null||o.onBlur(t)};return i.jsxs("div",{ref:H,className:k.clsx(f.fieldStyles.field,v&&f.fieldStyles.error,S&&f.fieldStyles.disabled,Z),style:{"--tz-btn-rgb":`var(--tz-color-${K}-rgb)`,...$},children:[x!=null&&i.jsxs("span",{className:f.fieldStyles.label,children:[i.jsx(A.Typography,{as:"span",variant:"bodySmall",color:"muted",children:x}),C&&i.jsx("span",{className:f.fieldStyles.required,"aria-hidden":"true",children:"*"})]}),i.jsx("div",{role:"group","aria-label":typeof x=="string"?x:q("otpField.label"),"aria-invalid":v||void 0,"aria-describedby":D!=null?B:void 0,className:k.clsx(p.row,p[O],p[V],v&&p.invalid),onBlur:Y,children:u.map((t,e)=>i.jsx("input",{ref:r=>{j.current[e]=r},name:e===0?a:void 0,type:"text",inputMode:n==="numeric"?"numeric":"text",autoComplete:e===0?"one-time-code":"off","aria-label":q("otpField.digit",{index:e+1,total:l}),className:k.clsx(p.box,t!==""&&p.filled),value:t,placeholder:M,disabled:S,onChange:r=>U(e,r.target.value),onKeyDown:r=>W(e,r),onPaste:r=>X(e,r),onFocus:r=>r.target.select()},e))}),D!=null&&i.jsx(A.Typography,{as:"span",id:B,variant:"bodySmall",color:v?"error":"muted",className:f.fieldStyles.helper,children:D})]})});exports.OtpField=pe;
2
- //# sourceMappingURL=OtpField-BhZq44vV.cjs.map
1
+ "use strict";const i=require("react/jsx-runtime"),y=require("react"),k=require("clsx"),ee=require("./formContext-bTWrqdEV.cjs"),A=require("./Typography-d97DdbNd.cjs"),f=require("./TextField.module-DsNCo8vN.cjs"),te=require("./ConfigProvider-CYSpuSMJ.cjs"),re="_row_u40i0_2",se="_center_u40i0_14",oe="_end_u40i0_15",le="_sm_u40i0_27",ce="_md_u40i0_31",ie="_lg_u40i0_35",ne="_box_u40i0_41",ae="_filled_u40i0_65",ue="_invalid_u40i0_84",p={row:re,center:se,end:oe,sm:le,md:ce,lg:ie,box:ne,filled:ae,invalid:ue},de={numeric:/[0-9]/,alphabetic:/[A-Za-z]/,alphanumeric:/[A-Za-z0-9]/};function fe(F,l){const n=[...F].slice(0,l);for(;n.length<l;)n.push("");return n}const pe=y.forwardRef(function({length:l=4,type:n="numeric",value:g,defaultValue:I,onChange:b,onComplete:T,name:a,label:x,helperText:z,error:P,required:C=!1,disabled:S=!1,autoFocus:E=!1,placeholder:M,size:O="md",align:V="start",color:K="primary",className:Z,style:$},H){const q=te.useT(),B=`${y.useId()}-helper`,N=de[n],h=ee.useFormContext(),w=!!(h&&a),o=h&&a?h.field(a):void 0,L=g!==void 0?g:w?h.values[a]:void 0,R=g!==void 0||w,[G,J]=y.useState(I??""),Q=R?L??"":G,v=P??(o==null?void 0:o.error)??!1,D=z??(o==null?void 0:o.helperText),u=fe(Q,l),j=y.useRef([]);y.useEffect(()=>{var t;E&&((t=j.current[0])==null||t.focus())},[]);const d=t=>{const e=j.current[Math.max(0,Math.min(t,l-1))];e==null||e.focus(),e==null||e.select()},m=t=>{const e=t.join("");R||J(e),w&&h.setValue(a,e),b==null||b(e),t.every(r=>r!=="")&&(T==null||T(e))},U=(t,e)=>{const r=[...e].filter(s=>N.test(s));if(e!==""&&r.length===0)return;const c=[...u];if(r.length<=1)c[t]=r[0]??"",m(c),r[0]&&d(t+1);else{let s=t;for(const _ of r){if(s>=l)break;c[s]=_,s++}m(c),d(s)}},W=(t,e)=>{if(e.key==="Backspace"){if(u[t]===""&&t>0){e.preventDefault();const r=[...u];r[t-1]="",m(r),d(t-1)}}else if(e.key==="ArrowLeft")e.preventDefault(),d(t-1);else if(e.key==="ArrowRight")e.preventDefault(),d(t+1);else if(e.key==="Delete"){e.preventDefault();const r=[...u];r[t]="",m(r)}},X=(t,e)=>{e.preventDefault();const r=[...e.clipboardData.getData("text")].filter(_=>N.test(_));if(r.length===0)return;const c=[...u];let s=t;for(const _ of r){if(s>=l)break;c[s]=_,s++}m(c),d(s)},Y=t=>{t.currentTarget.contains(t.relatedTarget)||o==null||o.onBlur(t)};return i.jsxs("div",{ref:H,className:k.clsx(f.fieldStyles.field,v&&f.fieldStyles.error,S&&f.fieldStyles.disabled,Z),style:{"--tz-btn-rgb":`var(--tz-color-${K}-rgb)`,...$},children:[x!=null&&i.jsxs("span",{className:f.fieldStyles.label,children:[i.jsx(A.Typography,{as:"span",variant:"bodySmall",color:"muted",children:x}),C&&i.jsx("span",{className:f.fieldStyles.required,"aria-hidden":"true",children:"*"})]}),i.jsx("div",{role:"group","aria-label":typeof x=="string"?x:q("otpField.label"),"aria-invalid":v||void 0,"aria-describedby":D!=null?B:void 0,className:k.clsx(p.row,p[O],p[V],v&&p.invalid),onBlur:Y,children:u.map((t,e)=>i.jsx("input",{ref:r=>{j.current[e]=r},name:e===0?a:void 0,type:"text",inputMode:n==="numeric"?"numeric":"text",autoComplete:e===0?"one-time-code":"off","aria-label":q("otpField.digit",{index:e+1,total:l}),className:k.clsx(p.box,t!==""&&p.filled),value:t,placeholder:M,disabled:S,onChange:r=>U(e,r.target.value),onKeyDown:r=>W(e,r),onPaste:r=>X(e,r),onFocus:r=>r.target.select()},e))}),D!=null&&i.jsx(A.Typography,{as:"span",id:B,variant:"bodySmall",color:v?"error":"muted",className:f.fieldStyles.helper,children:D})]})});exports.OtpField=pe;
2
+ //# sourceMappingURL=OtpField-kd0YghZq.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"OtpField-BhZq44vV.cjs","sources":["../src/components/OtpField/OtpField.tsx"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type ClipboardEvent,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { useFormContext } from '../../form/formContext'\nimport { useT, type ThemeColor } from '../../theme'\nimport { Typography } from '../Typography'\nimport fieldStyles from '../TextField/TextField.module.css'\nimport styles from './OtpField.module.css'\n\nexport type OtpFieldSize = 'sm' | 'md' | 'lg'\n/** Which characters the code accepts. */\nexport type OtpFieldType = 'numeric' | 'alphabetic' | 'alphanumeric'\n\nexport type OtpFieldAlign = 'start' | 'center' | 'end'\n\n/** Allowed-character matcher per `type`. */\nconst PATTERN: Record<OtpFieldType, RegExp> = {\n numeric: /[0-9]/,\n alphabetic: /[A-Za-z]/,\n alphanumeric: /[A-Za-z0-9]/,\n}\n\n/** Split a code string into exactly `length` single-char slots, padded with empties. */\nfunction toChars(value: string, length: number): string[] {\n const out = [...value].slice(0, length)\n while (out.length < length) out.push('')\n return out\n}\n\nexport interface OtpFieldProps {\n /** Number of input boxes (the code length). Defaults to `4`. */\n length?: number\n /** Which characters are accepted (also drives the mobile keyboard). Defaults to `'numeric'`. */\n type?: OtpFieldType\n /** Controlled value — the concatenated code string. */\n value?: string\n /** Initial value for uncontrolled use. */\n defaultValue?: string\n /** Fires with the full code string on every change. */\n onChange?: (value: string) => void\n /** Fires with the code once every box is filled. */\n onComplete?: (value: string) => void\n /** Field name — the `<Form>` binding key (form value is the code `string`). */\n name?: string\n /** Label rendered above the boxes. */\n label?: ReactNode\n /** Helper / error text under the boxes (shown in the error color while `error`). */\n helperText?: ReactNode\n /** Marks the field invalid — reddens the boxes + helper. */\n error?: boolean\n /** Adds a red asterisk after the label. */\n required?: boolean\n /** Disables every box. */\n disabled?: boolean\n /** Focus the first box on mount. */\n autoFocus?: boolean\n /** Placeholder character shown in empty boxes (e.g. `'•'`). */\n placeholder?: string\n /** Preset size. Defaults to `'md'`. */\n size?: OtpFieldSize\n /** Horizontal alignment of the boxes within the field. Defaults to `'start'` (left). */\n align?: OtpFieldAlign\n /** Theme palette token for the focus ring / active box. Defaults to `'primary'`. */\n color?: ThemeColor\n className?: string\n style?: CSSProperties\n}\n\n/**\n * A one-time-passcode input — a row of single-character boxes for verification codes. **`length`**\n * (default `4`) sets the box count; **`type`** (`'numeric'` default · `'alphabetic'` · `'alphanumeric'`)\n * restricts the accepted characters and the mobile keyboard. Typing advances to the next box, Backspace\n * clears the box (in an empty box: clears the previous one and steps back), Arrows navigate, and **paste / SMS autofill** (`autocomplete=\"one-time-code\"`)\n * distributes the whole code across the boxes. The value is the concatenated string — controlled\n * (`value` + `onChange`) or uncontrolled (`defaultValue`); **`onComplete`** fires when all boxes are\n * filled. Shares the field-family chrome (`label` · `error` + `helperText` · `required` · `disabled` ·\n * `size`) and binds to a surrounding `<Form>` by **`name`** (form value = the code string; validate with\n * e.g. `z.string().length(4)` or a `type`-matching regex). Tinted by `color` via the shared\n * `--tz-btn-rgb` pattern; `role=\"group\"` with per-box `aria-label`s. Own CSS module (+ TextField's for\n * the label/helper chrome).\n */\nexport const OtpField = forwardRef<HTMLDivElement, OtpFieldProps>(function OtpField(\n {\n length = 4,\n type = 'numeric',\n value,\n defaultValue,\n onChange,\n onComplete,\n name,\n label,\n helperText,\n error,\n required = false,\n disabled = false,\n autoFocus = false,\n placeholder,\n size = 'md',\n align = 'start',\n color = 'primary',\n className,\n style,\n },\n ref,\n) {\n const t = useT()\n const reactId = useId()\n const helperId = `${reactId}-helper`\n const allowed = PATTERN[type]\n\n // bind to a surrounding <Form> by `name` — form value is the code string; error/touched via field()\n const form = useFormContext()\n const isFormBound = Boolean(form && name)\n const bound = form && name ? form.field(name) : undefined\n\n const externalValue =\n value !== undefined ? value : isFormBound ? (form!.values[name!] as string) : undefined\n const isControlled = value !== undefined || isFormBound\n const [internal, setInternal] = useState<string>(defaultValue ?? '')\n const currentValue = isControlled ? (externalValue ?? '') : internal\n\n const resolvedError = error ?? bound?.error ?? false\n const resolvedHelperText = helperText ?? bound?.helperText\n\n // the code split into exactly `length` single-char slots (padded with empties)\n const chars = toChars(currentValue, length)\n\n const inputsRef = useRef<(HTMLInputElement | null)[]>([])\n\n useEffect(() => {\n if (autoFocus) inputsRef.current[0]?.focus()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const focusBox = (i: number) => {\n const el = inputsRef.current[Math.max(0, Math.min(i, length - 1))]\n el?.focus()\n el?.select()\n }\n\n const commit = (nextChars: string[]) => {\n const next = nextChars.join('')\n if (!isControlled) setInternal(next)\n if (isFormBound) form!.setValue(name!, next)\n onChange?.(next)\n if (nextChars.every((c) => c !== '')) onComplete?.(next)\n }\n\n const handleChange = (index: number, raw: string) => {\n const filtered = [...raw].filter((c) => allowed.test(c))\n // a disallowed keystroke (raw non-empty but nothing survives the filter) is ignored\n if (raw !== '' && filtered.length === 0) return\n const nextChars = [...chars]\n if (filtered.length <= 1) {\n // a single typed char (boxes select-on-focus, so this replaces) — or a clear ('')\n nextChars[index] = filtered[0] ?? ''\n commit(nextChars)\n if (filtered[0]) focusBox(index + 1)\n } else {\n // multiple chars (SMS autofill dumps the whole code into one box) → distribute from here\n let k = index\n for (const ch of filtered) {\n if (k >= length) break\n nextChars[k] = ch\n k++\n }\n commit(nextChars)\n focusBox(k)\n }\n }\n\n const handleKeyDown = (index: number, event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Backspace') {\n if (chars[index] === '' && index > 0) {\n // empty box → step back and clear the previous one\n event.preventDefault()\n const nextChars = [...chars]\n nextChars[index - 1] = ''\n commit(nextChars)\n focusBox(index - 1)\n }\n // a non-empty box lets the native delete run → onChange fires with '' (stays put)\n } else if (event.key === 'ArrowLeft') {\n event.preventDefault()\n focusBox(index - 1)\n } else if (event.key === 'ArrowRight') {\n event.preventDefault()\n focusBox(index + 1)\n } else if (event.key === 'Delete') {\n event.preventDefault()\n const nextChars = [...chars]\n nextChars[index] = ''\n commit(nextChars)\n }\n }\n\n const handlePaste = (index: number, event: ClipboardEvent<HTMLInputElement>) => {\n event.preventDefault()\n const filtered = [...event.clipboardData.getData('text')].filter((c) => allowed.test(c))\n if (filtered.length === 0) return\n const nextChars = [...chars]\n let k = index\n for (const ch of filtered) {\n if (k >= length) break\n nextChars[k] = ch\n k++\n }\n commit(nextChars)\n focusBox(k)\n }\n\n // mark the field touched when focus leaves the whole widget (not when it hops between boxes)\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n bound?.onBlur(event as unknown as FocusEvent<HTMLInputElement>)\n }\n }\n\n return (\n <div\n ref={ref}\n className={clsx(\n fieldStyles.field,\n resolvedError && fieldStyles.error,\n disabled && fieldStyles.disabled,\n className,\n )}\n style={\n {\n '--tz-btn-rgb': `var(--tz-color-${color}-rgb)`,\n ...style,\n } as CSSProperties\n }\n >\n {label != null && (\n <span className={fieldStyles.label}>\n <Typography as=\"span\" variant=\"bodySmall\" color=\"muted\">\n {label}\n </Typography>\n {required && (\n <span className={fieldStyles.required} aria-hidden=\"true\">\n *\n </span>\n )}\n </span>\n )}\n\n <div\n role=\"group\"\n aria-label={typeof label === 'string' ? label : t('otpField.label')}\n aria-invalid={resolvedError || undefined}\n aria-describedby={resolvedHelperText != null ? helperId : undefined}\n className={clsx(styles.row, styles[size], styles[align], resolvedError && styles.invalid)}\n onBlur={handleBlur}\n >\n {chars.map((char, i) => (\n <input\n key={i}\n ref={(el) => {\n inputsRef.current[i] = el\n }}\n // the name goes on the first box only, so the form's scroll-to-error can target it\n name={i === 0 ? name : undefined}\n type=\"text\"\n inputMode={type === 'numeric' ? 'numeric' : 'text'}\n autoComplete={i === 0 ? 'one-time-code' : 'off'}\n aria-label={t('otpField.digit', { index: i + 1, total: length })}\n className={clsx(styles.box, char !== '' && styles.filled)}\n value={char}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(e) => handleChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={(e) => handlePaste(i, e)}\n onFocus={(e) => e.target.select()}\n />\n ))}\n </div>\n\n {resolvedHelperText != null && (\n <Typography\n as=\"span\"\n id={helperId}\n variant=\"bodySmall\"\n color={resolvedError ? 'error' : 'muted'}\n className={fieldStyles.helper}\n >\n {resolvedHelperText}\n </Typography>\n )}\n </div>\n )\n})\n"],"names":["PATTERN","toChars","value","length","out","OtpField","forwardRef","type","defaultValue","onChange","onComplete","name","label","helperText","error","required","disabled","autoFocus","placeholder","size","align","color","className","style","ref","t","useT","helperId","useId","allowed","form","useFormContext","isFormBound","bound","externalValue","isControlled","internal","setInternal","useState","currentValue","resolvedError","resolvedHelperText","chars","inputsRef","useRef","useEffect","_a","focusBox","i","el","commit","nextChars","next","c","handleChange","index","raw","filtered","k","ch","handleKeyDown","event","handlePaste","handleBlur","jsxs","clsx","fieldStyles","jsx","Typography","styles","char","e"],"mappings":"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"}
1
+ {"version":3,"file":"OtpField-kd0YghZq.cjs","sources":["../src/components/OtpField/OtpField.tsx"],"sourcesContent":["import {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type ClipboardEvent,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\nimport { clsx } from 'clsx'\nimport { useFormContext } from '../../form/formContext'\nimport { useT, type ThemeColor } from '../../theme'\nimport { Typography } from '../Typography'\nimport fieldStyles from '../TextField/TextField.module.css'\nimport styles from './OtpField.module.css'\n\nexport type OtpFieldSize = 'sm' | 'md' | 'lg'\n/** Which characters the code accepts. */\nexport type OtpFieldType = 'numeric' | 'alphabetic' | 'alphanumeric'\n\nexport type OtpFieldAlign = 'start' | 'center' | 'end'\n\n/** Allowed-character matcher per `type`. */\nconst PATTERN: Record<OtpFieldType, RegExp> = {\n numeric: /[0-9]/,\n alphabetic: /[A-Za-z]/,\n alphanumeric: /[A-Za-z0-9]/,\n}\n\n/** Split a code string into exactly `length` single-char slots, padded with empties. */\nfunction toChars(value: string, length: number): string[] {\n const out = [...value].slice(0, length)\n while (out.length < length) out.push('')\n return out\n}\n\nexport interface OtpFieldProps {\n /** Number of input boxes (the code length). Defaults to `4`. */\n length?: number\n /** Which characters are accepted (also drives the mobile keyboard). Defaults to `'numeric'`. */\n type?: OtpFieldType\n /** Controlled value — the concatenated code string. */\n value?: string\n /** Initial value for uncontrolled use. */\n defaultValue?: string\n /** Fires with the full code string on every change. */\n onChange?: (value: string) => void\n /** Fires with the code once every box is filled. */\n onComplete?: (value: string) => void\n /** Field name — the `<Form>` binding key (form value is the code `string`). */\n name?: string\n /** Label rendered above the boxes. */\n label?: ReactNode\n /** Helper / error text under the boxes (shown in the error color while `error`). */\n helperText?: ReactNode\n /** Marks the field invalid — reddens the boxes + helper. */\n error?: boolean\n /** Adds a red asterisk after the label. */\n required?: boolean\n /** Disables every box. */\n disabled?: boolean\n /** Focus the first box on mount. */\n autoFocus?: boolean\n /** Placeholder character shown in empty boxes (e.g. `'•'`). */\n placeholder?: string\n /** Preset size. Defaults to `'md'`. */\n size?: OtpFieldSize\n /** Horizontal alignment of the boxes within the field. Defaults to `'start'` (left). */\n align?: OtpFieldAlign\n /** Theme palette token for the focus ring / active box. Defaults to `'primary'`. */\n color?: ThemeColor\n className?: string\n style?: CSSProperties\n}\n\n/**\n * A one-time-passcode input — a row of single-character boxes for verification codes. **`length`**\n * (default `4`) sets the box count; **`type`** (`'numeric'` default · `'alphabetic'` · `'alphanumeric'`)\n * restricts the accepted characters and the mobile keyboard. Typing advances to the next box, Backspace\n * clears the box (in an empty box: clears the previous one and steps back), Arrows navigate, and **paste / SMS autofill** (`autocomplete=\"one-time-code\"`)\n * distributes the whole code across the boxes. The value is the concatenated string — controlled\n * (`value` + `onChange`) or uncontrolled (`defaultValue`); **`onComplete`** fires when all boxes are\n * filled. Shares the field-family chrome (`label` · `error` + `helperText` · `required` · `disabled` ·\n * `size`) and binds to a surrounding `<Form>` by **`name`** (form value = the code string; validate with\n * e.g. `z.string().length(4)` or a `type`-matching regex). Tinted by `color` via the shared\n * `--tz-btn-rgb` pattern; `role=\"group\"` with per-box `aria-label`s. Own CSS module (+ TextField's for\n * the label/helper chrome).\n */\nexport const OtpField = forwardRef<HTMLDivElement, OtpFieldProps>(function OtpField(\n {\n length = 4,\n type = 'numeric',\n value,\n defaultValue,\n onChange,\n onComplete,\n name,\n label,\n helperText,\n error,\n required = false,\n disabled = false,\n autoFocus = false,\n placeholder,\n size = 'md',\n align = 'start',\n color = 'primary',\n className,\n style,\n },\n ref,\n) {\n const t = useT()\n const reactId = useId()\n const helperId = `${reactId}-helper`\n const allowed = PATTERN[type]\n\n // bind to a surrounding <Form> by `name` — form value is the code string; error/touched via field()\n const form = useFormContext()\n const isFormBound = Boolean(form && name)\n const bound = form && name ? form.field(name) : undefined\n\n const externalValue =\n value !== undefined ? value : isFormBound ? (form!.values[name!] as string) : undefined\n const isControlled = value !== undefined || isFormBound\n const [internal, setInternal] = useState<string>(defaultValue ?? '')\n const currentValue = isControlled ? (externalValue ?? '') : internal\n\n const resolvedError = error ?? bound?.error ?? false\n const resolvedHelperText = helperText ?? bound?.helperText\n\n // the code split into exactly `length` single-char slots (padded with empties)\n const chars = toChars(currentValue, length)\n\n const inputsRef = useRef<(HTMLInputElement | null)[]>([])\n\n useEffect(() => {\n if (autoFocus) inputsRef.current[0]?.focus()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const focusBox = (i: number) => {\n const el = inputsRef.current[Math.max(0, Math.min(i, length - 1))]\n el?.focus()\n el?.select()\n }\n\n const commit = (nextChars: string[]) => {\n const next = nextChars.join('')\n if (!isControlled) setInternal(next)\n if (isFormBound) form!.setValue(name!, next)\n onChange?.(next)\n if (nextChars.every((c) => c !== '')) onComplete?.(next)\n }\n\n const handleChange = (index: number, raw: string) => {\n const filtered = [...raw].filter((c) => allowed.test(c))\n // a disallowed keystroke (raw non-empty but nothing survives the filter) is ignored\n if (raw !== '' && filtered.length === 0) return\n const nextChars = [...chars]\n if (filtered.length <= 1) {\n // a single typed char (boxes select-on-focus, so this replaces) — or a clear ('')\n nextChars[index] = filtered[0] ?? ''\n commit(nextChars)\n if (filtered[0]) focusBox(index + 1)\n } else {\n // multiple chars (SMS autofill dumps the whole code into one box) → distribute from here\n let k = index\n for (const ch of filtered) {\n if (k >= length) break\n nextChars[k] = ch\n k++\n }\n commit(nextChars)\n focusBox(k)\n }\n }\n\n const handleKeyDown = (index: number, event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Backspace') {\n if (chars[index] === '' && index > 0) {\n // empty box → step back and clear the previous one\n event.preventDefault()\n const nextChars = [...chars]\n nextChars[index - 1] = ''\n commit(nextChars)\n focusBox(index - 1)\n }\n // a non-empty box lets the native delete run → onChange fires with '' (stays put)\n } else if (event.key === 'ArrowLeft') {\n event.preventDefault()\n focusBox(index - 1)\n } else if (event.key === 'ArrowRight') {\n event.preventDefault()\n focusBox(index + 1)\n } else if (event.key === 'Delete') {\n event.preventDefault()\n const nextChars = [...chars]\n nextChars[index] = ''\n commit(nextChars)\n }\n }\n\n const handlePaste = (index: number, event: ClipboardEvent<HTMLInputElement>) => {\n event.preventDefault()\n const filtered = [...event.clipboardData.getData('text')].filter((c) => allowed.test(c))\n if (filtered.length === 0) return\n const nextChars = [...chars]\n let k = index\n for (const ch of filtered) {\n if (k >= length) break\n nextChars[k] = ch\n k++\n }\n commit(nextChars)\n focusBox(k)\n }\n\n // mark the field touched when focus leaves the whole widget (not when it hops between boxes)\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n bound?.onBlur(event as unknown as FocusEvent<HTMLInputElement>)\n }\n }\n\n return (\n <div\n ref={ref}\n className={clsx(\n fieldStyles.field,\n resolvedError && fieldStyles.error,\n disabled && fieldStyles.disabled,\n className,\n )}\n style={\n {\n '--tz-btn-rgb': `var(--tz-color-${color}-rgb)`,\n ...style,\n } as CSSProperties\n }\n >\n {label != null && (\n <span className={fieldStyles.label}>\n <Typography as=\"span\" variant=\"bodySmall\" color=\"muted\">\n {label}\n </Typography>\n {required && (\n <span className={fieldStyles.required} aria-hidden=\"true\">\n *\n </span>\n )}\n </span>\n )}\n\n <div\n role=\"group\"\n aria-label={typeof label === 'string' ? label : t('otpField.label')}\n aria-invalid={resolvedError || undefined}\n aria-describedby={resolvedHelperText != null ? helperId : undefined}\n className={clsx(styles.row, styles[size], styles[align], resolvedError && styles.invalid)}\n onBlur={handleBlur}\n >\n {chars.map((char, i) => (\n <input\n key={i}\n ref={(el) => {\n inputsRef.current[i] = el\n }}\n // the name goes on the first box only, so the form's scroll-to-error can target it\n name={i === 0 ? name : undefined}\n type=\"text\"\n inputMode={type === 'numeric' ? 'numeric' : 'text'}\n autoComplete={i === 0 ? 'one-time-code' : 'off'}\n aria-label={t('otpField.digit', { index: i + 1, total: length })}\n className={clsx(styles.box, char !== '' && styles.filled)}\n value={char}\n placeholder={placeholder}\n disabled={disabled}\n onChange={(e) => handleChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={(e) => handlePaste(i, e)}\n onFocus={(e) => e.target.select()}\n />\n ))}\n </div>\n\n {resolvedHelperText != null && (\n <Typography\n as=\"span\"\n id={helperId}\n variant=\"bodySmall\"\n color={resolvedError ? 'error' : 'muted'}\n className={fieldStyles.helper}\n >\n {resolvedHelperText}\n </Typography>\n )}\n </div>\n )\n})\n"],"names":["PATTERN","toChars","value","length","out","OtpField","forwardRef","type","defaultValue","onChange","onComplete","name","label","helperText","error","required","disabled","autoFocus","placeholder","size","align","color","className","style","ref","t","useT","helperId","useId","allowed","form","useFormContext","isFormBound","bound","externalValue","isControlled","internal","setInternal","useState","currentValue","resolvedError","resolvedHelperText","chars","inputsRef","useRef","useEffect","_a","focusBox","i","el","commit","nextChars","next","c","handleChange","index","raw","filtered","k","ch","handleKeyDown","event","handlePaste","handleBlur","jsxs","clsx","fieldStyles","jsx","Typography","styles","char","e"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { jsx as s } from "react/jsx-runtime";
2
2
  import { forwardRef as j, useState as w, useRef as u, useEffect as l } from "react";
3
- import { B as z } from "./Button-C415LPw_.js";
4
- import { E as C } from "./ErrorState-WYsly5-i.js";
3
+ import { B as z } from "./Button-DZWYeAno.js";
4
+ import { E as C } from "./ErrorState-DEngucdq.js";
5
5
  import { f as p, e as D } from "./errorMessage-C83fB2h5.js";
6
- import { u as H } from "./useHomeTo-BL3e8Sc6.js";
7
- import { a as _ } from "./ConfigProvider-DVDGtCUc.js";
6
+ import { u as H } from "./useHomeTo-BLSvhJd5.js";
7
+ import { a as _ } from "./ConfigProvider-DtyUlWk6.js";
8
8
  const O = j(function({
9
9
  error: t,
10
10
  reset: o,
@@ -67,4 +67,4 @@ const O = j(function({
67
67
  export {
68
68
  O as P
69
69
  };
70
- //# sourceMappingURL=PageError-63Gk6fVC.js.map
70
+ //# sourceMappingURL=PageError-BIiZDzey.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageError-63Gk6fVC.js","sources":["../src/components/PageError/PageError.tsx"],"sourcesContent":["import { forwardRef, useEffect, useRef, useState, type HTMLAttributes, type ReactNode } from 'react'\nimport { type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport type { IconName } from '../../icons/names'\nimport { Button } from '../Button'\nimport type { EmptyStateSize } from '../EmptyState'\nimport { ErrorState } from '../ErrorState/ErrorState'\nimport { isDev, isServerError } from '../ErrorState/errorMessage'\nimport { useHomeTo } from '../PageNotFound/useHomeTo'\n\nexport interface PageErrorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'color'> {\n /** What the route threw (TanStack Router's `ErrorComponentProps.error`). */\n error: unknown\n /** Resets the route's error boundary (TanStack Router's `ErrorComponentProps.reset`). */\n reset?: () => void\n /** The React component stack (TanStack Router's `ErrorComponentProps.info`) — unused, accepted for typing. */\n info?: { componentStack: string }\n /**\n * Runs **before** the reset on \"Try Again\" (may be async) — where an app drops cached data, e.g.\n * `() => queryClient.resetQueries({ predicate: (q) => q.queryKey[0] !== 'session' })`. Without it, `reset()`\n * re-renders against the same cached response and throws on the same data again.\n */\n onRetry?: () => void | Promise<void>\n /**\n * Show the error's own message. Default: when it looks **server-originated** (a `traceId` or a numeric\n * `status` — written for people) or in development; otherwise the localized generic sentence (a render\n * crash's message is a developer's). `true` / `false` force it; `'dev'` = development only; a function decides\n * per error.\n */\n showMessage?: boolean | 'dev' | ((error: unknown) => boolean)\n /** A secondary \"Go to Home\" button to the first allowed menu page (RBAC-aware). Defaults to `true`. */\n showHome?: boolean\n /** Heading. Defaults to the localized \"This Page Could Not Be Shown\". */\n title?: ReactNode\n /** Overrides the description (the message / the generic sentence). */\n description?: ReactNode\n /** Leading icon — passed to `ErrorState` (`Danger` / `CloudCross` by default; `false` hides it). */\n icon?: IconName | ReactNode | false\n /** Size — passed to `ErrorState`. Defaults to `md`. */\n size?: EmptyStateSize\n /** Faded-grid hero backdrop — passed to `ErrorState`. Defaults to `true`. */\n pattern?: boolean\n /** The developer details panel (stack) — passed to `ErrorState`. Defaults to `'dev'`. */\n showDetails?: boolean | 'dev'\n}\n\n/**\n * The shared **route error page** — the twin of `PageNotFound`. Drop it into TanStack Router as the\n * `defaultErrorComponent`: TanStack wraps every route in its own error boundary (inside the shell's `<Outlet/>`),\n * so without it a crashing page shows the router's bare \"Something went wrong!\". Renders the full `ErrorState`\n * hero inside the shell with **Try Again** (`await onRetry?.()` → `reset()` → `router.invalidate()`, which re-runs\n * a throwing loader / `beforeLoad`), a **Go to Home** button, the server's `traceId`, and the error's message only\n * when it was written for people (`showMessage`). Every error is `console.error`ed once — in production the\n * screen hides the message, so the console is the record.\n *\n * @example\n * createRouter({ routeTree, defaultNotFoundComponent: PageNotFound, defaultErrorComponent: PageError })\n */\nexport const PageError = forwardRef<HTMLDivElement, PageErrorProps>(function PageError(\n {\n error,\n reset,\n info: _info,\n onRetry,\n showMessage,\n showHome = true,\n title,\n description,\n icon,\n size,\n pattern,\n showDetails,\n ...props\n },\n ref,\n) {\n const t = useT()\n const { router, homeTo } = useHomeTo()\n const [retrying, setRetrying] = useState(false)\n const mounted = useRef(true)\n useEffect(() => {\n mounted.current = true\n return () => {\n mounted.current = false\n }\n }, [])\n\n // log each distinct error once (StrictMode re-runs effects; a re-render with the same error isn't new)\n const logged = useRef<unknown>(undefined)\n useEffect(() => {\n if (logged.current === error) return\n logged.current = error\n console.error('[PageError]', error)\n }, [error])\n\n const messageShown =\n typeof showMessage === 'function'\n ? showMessage(error)\n : showMessage === 'dev'\n ? isDev()\n : (showMessage ?? (isServerError(error) || isDev()))\n\n const retry = async () => {\n setRetrying(true)\n try {\n await onRetry?.()\n reset?.()\n await router?.invalidate()\n } finally {\n if (mounted.current) setRetrying(false)\n }\n }\n\n const home =\n showHome && router && homeTo != null ? (\n <Button\n size=\"sm\"\n variant=\"text\"\n color=\"primary\"\n onClick={() => router.navigate({ to: homeTo as LinkProps['to'] })}\n >\n {t('pageError.home')}\n </Button>\n ) : undefined\n\n return (\n <ErrorState\n ref={ref}\n variant=\"block\"\n error={error}\n title={title ?? t('pageError.title')}\n // hidden message → the generic sentence (the trace id still shows: it's for support, not a leak)\n description={description ?? (messageShown ? undefined : t('pageError.description'))}\n icon={icon}\n size={size}\n pattern={pattern}\n showDetails={showDetails}\n onRetry={reset || onRetry || router ? () => void retry() : undefined}\n retrying={retrying}\n action={home}\n {...props}\n />\n )\n})\n"],"names":["PageError","forwardRef","error","reset","_info","onRetry","showMessage","showHome","title","description","icon","size","pattern","showDetails","props","ref","t","useT","router","homeTo","useHomeTo","retrying","setRetrying","useState","mounted","useRef","useEffect","logged","messageShown","isDev","isServerError","retry","home","jsx","Button","ErrorState"],"mappings":";;;;;;;AA0DO,MAAMA,IAAYC,EAA2C,SAClE;AAAA,EACE,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA,MAAMC;AAAA,EACN,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,MAAAC;AAAA,EACA,MAAAC;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,QAAMC,IAAIC,EAAA,GACJ,EAAE,QAAAC,GAAQ,QAAAC,EAAA,IAAWC,EAAA,GACrB,CAACC,GAAUC,CAAW,IAAIC,EAAS,EAAK,GACxCC,IAAUC,EAAO,EAAI;AAC3B,EAAAC,EAAU,OACRF,EAAQ,UAAU,IACX,MAAM;AACX,IAAAA,EAAQ,UAAU;AAAA,EACpB,IACC,CAAA,CAAE;AAGL,QAAMG,IAASF,EAAgB,MAAS;AACxC,EAAAC,EAAU,MAAM;AACd,IAAIC,EAAO,YAAYzB,MACvByB,EAAO,UAAUzB,GACjB,QAAQ,MAAM,eAAeA,CAAK;AAAA,EACpC,GAAG,CAACA,CAAK,CAAC;AAEV,QAAM0B,IACJ,OAAOtB,KAAgB,aACnBA,EAAYJ,CAAK,IACjBI,MAAgB,QACduB,MACCvB,MAAgBwB,EAAc5B,CAAK,KAAK2B,MAE3CE,IAAQ,YAAY;AACxB,IAAAT,EAAY,EAAI;AAChB,QAAI;AACF,aAAMjB,KAAA,gBAAAA,MACNF,KAAA,QAAAA,KACA,OAAMe,KAAA,gBAAAA,EAAQ;AAAA,IAChB,UAAA;AACE,MAAIM,EAAQ,WAASF,EAAY,EAAK;AAAA,IACxC;AAAA,EACF,GAEMU,IACJzB,KAAYW,KAAUC,KAAU,OAC9B,gBAAAc;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAQ;AAAA,MACR,OAAM;AAAA,MACN,SAAS,MAAMhB,EAAO,SAAS,EAAE,IAAIC,GAA2B;AAAA,MAE/D,YAAE,gBAAgB;AAAA,IAAA;AAAA,EAAA,IAEnB;AAEN,SACE,gBAAAc;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,KAAApB;AAAA,MACA,SAAQ;AAAA,MACR,OAAAb;AAAA,MACA,OAAOM,KAASQ,EAAE,iBAAiB;AAAA,MAEnC,aAAaP,MAAgBmB,IAAe,SAAYZ,EAAE,uBAAuB;AAAA,MACjF,MAAAN;AAAA,MACA,MAAAC;AAAA,MACA,SAAAC;AAAA,MACA,aAAAC;AAAA,MACA,SAASV,KAASE,KAAWa,IAAS,MAAM,KAAKa,MAAU;AAAA,MAC3D,UAAAV;AAAA,MACA,QAAQW;AAAA,MACP,GAAGlB;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;"}
1
+ {"version":3,"file":"PageError-BIiZDzey.js","sources":["../src/components/PageError/PageError.tsx"],"sourcesContent":["import { forwardRef, useEffect, useRef, useState, type HTMLAttributes, type ReactNode } from 'react'\nimport { type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport type { IconName } from '../../icons/names'\nimport { Button } from '../Button'\nimport type { EmptyStateSize } from '../EmptyState'\nimport { ErrorState } from '../ErrorState/ErrorState'\nimport { isDev, isServerError } from '../ErrorState/errorMessage'\nimport { useHomeTo } from '../PageNotFound/useHomeTo'\n\nexport interface PageErrorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'color'> {\n /** What the route threw (TanStack Router's `ErrorComponentProps.error`). */\n error: unknown\n /** Resets the route's error boundary (TanStack Router's `ErrorComponentProps.reset`). */\n reset?: () => void\n /** The React component stack (TanStack Router's `ErrorComponentProps.info`) — unused, accepted for typing. */\n info?: { componentStack: string }\n /**\n * Runs **before** the reset on \"Try Again\" (may be async) — where an app drops cached data, e.g.\n * `() => queryClient.resetQueries({ predicate: (q) => q.queryKey[0] !== 'session' })`. Without it, `reset()`\n * re-renders against the same cached response and throws on the same data again.\n */\n onRetry?: () => void | Promise<void>\n /**\n * Show the error's own message. Default: when it looks **server-originated** (a `traceId` or a numeric\n * `status` — written for people) or in development; otherwise the localized generic sentence (a render\n * crash's message is a developer's). `true` / `false` force it; `'dev'` = development only; a function decides\n * per error.\n */\n showMessage?: boolean | 'dev' | ((error: unknown) => boolean)\n /** A secondary \"Go to Home\" button to the first allowed menu page (RBAC-aware). Defaults to `true`. */\n showHome?: boolean\n /** Heading. Defaults to the localized \"This Page Could Not Be Shown\". */\n title?: ReactNode\n /** Overrides the description (the message / the generic sentence). */\n description?: ReactNode\n /** Leading icon — passed to `ErrorState` (`Danger` / `CloudCross` by default; `false` hides it). */\n icon?: IconName | ReactNode | false\n /** Size — passed to `ErrorState`. Defaults to `md`. */\n size?: EmptyStateSize\n /** Faded-grid hero backdrop — passed to `ErrorState`. Defaults to `true`. */\n pattern?: boolean\n /** The developer details panel (stack) — passed to `ErrorState`. Defaults to `'dev'`. */\n showDetails?: boolean | 'dev'\n}\n\n/**\n * The shared **route error page** — the twin of `PageNotFound`. Drop it into TanStack Router as the\n * `defaultErrorComponent`: TanStack wraps every route in its own error boundary (inside the shell's `<Outlet/>`),\n * so without it a crashing page shows the router's bare \"Something went wrong!\". Renders the full `ErrorState`\n * hero inside the shell with **Try Again** (`await onRetry?.()` → `reset()` → `router.invalidate()`, which re-runs\n * a throwing loader / `beforeLoad`), a **Go to Home** button, the server's `traceId`, and the error's message only\n * when it was written for people (`showMessage`). Every error is `console.error`ed once — in production the\n * screen hides the message, so the console is the record.\n *\n * @example\n * createRouter({ routeTree, defaultNotFoundComponent: PageNotFound, defaultErrorComponent: PageError })\n */\nexport const PageError = forwardRef<HTMLDivElement, PageErrorProps>(function PageError(\n {\n error,\n reset,\n info: _info,\n onRetry,\n showMessage,\n showHome = true,\n title,\n description,\n icon,\n size,\n pattern,\n showDetails,\n ...props\n },\n ref,\n) {\n const t = useT()\n const { router, homeTo } = useHomeTo()\n const [retrying, setRetrying] = useState(false)\n const mounted = useRef(true)\n useEffect(() => {\n mounted.current = true\n return () => {\n mounted.current = false\n }\n }, [])\n\n // log each distinct error once (StrictMode re-runs effects; a re-render with the same error isn't new)\n const logged = useRef<unknown>(undefined)\n useEffect(() => {\n if (logged.current === error) return\n logged.current = error\n console.error('[PageError]', error)\n }, [error])\n\n const messageShown =\n typeof showMessage === 'function'\n ? showMessage(error)\n : showMessage === 'dev'\n ? isDev()\n : (showMessage ?? (isServerError(error) || isDev()))\n\n const retry = async () => {\n setRetrying(true)\n try {\n await onRetry?.()\n reset?.()\n await router?.invalidate()\n } finally {\n if (mounted.current) setRetrying(false)\n }\n }\n\n const home =\n showHome && router && homeTo != null ? (\n <Button\n size=\"sm\"\n variant=\"text\"\n color=\"primary\"\n onClick={() => router.navigate({ to: homeTo as LinkProps['to'] })}\n >\n {t('pageError.home')}\n </Button>\n ) : undefined\n\n return (\n <ErrorState\n ref={ref}\n variant=\"block\"\n error={error}\n title={title ?? t('pageError.title')}\n // hidden message → the generic sentence (the trace id still shows: it's for support, not a leak)\n description={description ?? (messageShown ? undefined : t('pageError.description'))}\n icon={icon}\n size={size}\n pattern={pattern}\n showDetails={showDetails}\n onRetry={reset || onRetry || router ? () => void retry() : undefined}\n retrying={retrying}\n action={home}\n {...props}\n />\n )\n})\n"],"names":["PageError","forwardRef","error","reset","_info","onRetry","showMessage","showHome","title","description","icon","size","pattern","showDetails","props","ref","t","useT","router","homeTo","useHomeTo","retrying","setRetrying","useState","mounted","useRef","useEffect","logged","messageShown","isDev","isServerError","retry","home","jsx","Button","ErrorState"],"mappings":";;;;;;;AA0DO,MAAMA,IAAYC,EAA2C,SAClE;AAAA,EACE,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA,MAAMC;AAAA,EACN,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,MAAAC;AAAA,EACA,MAAAC;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,QAAMC,IAAIC,EAAA,GACJ,EAAE,QAAAC,GAAQ,QAAAC,EAAA,IAAWC,EAAA,GACrB,CAACC,GAAUC,CAAW,IAAIC,EAAS,EAAK,GACxCC,IAAUC,EAAO,EAAI;AAC3B,EAAAC,EAAU,OACRF,EAAQ,UAAU,IACX,MAAM;AACX,IAAAA,EAAQ,UAAU;AAAA,EACpB,IACC,CAAA,CAAE;AAGL,QAAMG,IAASF,EAAgB,MAAS;AACxC,EAAAC,EAAU,MAAM;AACd,IAAIC,EAAO,YAAYzB,MACvByB,EAAO,UAAUzB,GACjB,QAAQ,MAAM,eAAeA,CAAK;AAAA,EACpC,GAAG,CAACA,CAAK,CAAC;AAEV,QAAM0B,IACJ,OAAOtB,KAAgB,aACnBA,EAAYJ,CAAK,IACjBI,MAAgB,QACduB,MACCvB,MAAgBwB,EAAc5B,CAAK,KAAK2B,MAE3CE,IAAQ,YAAY;AACxB,IAAAT,EAAY,EAAI;AAChB,QAAI;AACF,aAAMjB,KAAA,gBAAAA,MACNF,KAAA,QAAAA,KACA,OAAMe,KAAA,gBAAAA,EAAQ;AAAA,IAChB,UAAA;AACE,MAAIM,EAAQ,WAASF,EAAY,EAAK;AAAA,IACxC;AAAA,EACF,GAEMU,IACJzB,KAAYW,KAAUC,KAAU,OAC9B,gBAAAc;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAQ;AAAA,MACR,OAAM;AAAA,MACN,SAAS,MAAMhB,EAAO,SAAS,EAAE,IAAIC,GAA2B;AAAA,MAE/D,YAAE,gBAAgB;AAAA,IAAA;AAAA,EAAA,IAEnB;AAEN,SACE,gBAAAc;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,KAAApB;AAAA,MACA,SAAQ;AAAA,MACR,OAAAb;AAAA,MACA,OAAOM,KAASQ,EAAE,iBAAiB;AAAA,MAEnC,aAAaP,MAAgBmB,IAAe,SAAYZ,EAAE,uBAAuB;AAAA,MACjF,MAAAN;AAAA,MACA,MAAAC;AAAA,MACA,SAAAC;AAAA,MACA,aAAAC;AAAA,MACA,SAASV,KAASE,KAAWa,IAAS,MAAM,KAAKa,MAAU;AAAA,MAC3D,UAAAV;AAAA,MACA,QAAQW;AAAA,MACP,GAAGlB;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;"}
@@ -1,2 +1,2 @@
1
- "use strict";const d=require("react/jsx-runtime"),t=require("react"),k=require("./Button-mBZOvgyZ.cjs"),B=require("./ErrorState-JH4JdrTI.cjs"),s=require("./errorMessage-C7N4KvUS.cjs"),C=require("./useHomeTo-W1PDW5CU.cjs"),D=require("./ConfigProvider-DBU6rOIA.cjs"),H=t.forwardRef(function({error:r,reset:o,info:w,onRetry:n,showMessage:i,showHome:v=!0,title:g,description:E,icon:m,size:p,pattern:q,showDetails:P,...S},x){const c=D.useT(),{router:e,homeTo:a}=C.useHomeTo(),[y,f]=t.useState(!1),u=t.useRef(!0);t.useEffect(()=>(u.current=!0,()=>{u.current=!1}),[]);const l=t.useRef(void 0);t.useEffect(()=>{l.current!==r&&(l.current=r,console.error("[PageError]",r))},[r]);const T=typeof i=="function"?i(r):i==="dev"?s.isDev():i??(s.isServerError(r)||s.isDev()),j=async()=>{f(!0);try{await(n==null?void 0:n()),o==null||o(),await(e==null?void 0:e.invalidate())}finally{u.current&&f(!1)}},h=v&&e&&a!=null?d.jsx(k.Button,{size:"sm",variant:"text",color:"primary",onClick:()=>e.navigate({to:a}),children:c("pageError.home")}):void 0;return d.jsx(B.ErrorState,{ref:x,variant:"block",error:r,title:g??c("pageError.title"),description:E??(T?void 0:c("pageError.description")),icon:m,size:p,pattern:q,showDetails:P,onRetry:o||n||e?()=>void j():void 0,retrying:y,action:h,...S})});exports.PageError=H;
2
- //# sourceMappingURL=PageError-CCKWbrc5.cjs.map
1
+ "use strict";const d=require("react/jsx-runtime"),t=require("react"),k=require("./Button-BtiFpRie.cjs"),B=require("./ErrorState-BThPIYaM.cjs"),s=require("./errorMessage-C7N4KvUS.cjs"),C=require("./useHomeTo-cXCg1tf0.cjs"),D=require("./ConfigProvider-CYSpuSMJ.cjs"),H=t.forwardRef(function({error:r,reset:o,info:w,onRetry:n,showMessage:i,showHome:v=!0,title:g,description:E,icon:m,size:p,pattern:q,showDetails:P,...S},x){const c=D.useT(),{router:e,homeTo:a}=C.useHomeTo(),[y,f]=t.useState(!1),u=t.useRef(!0);t.useEffect(()=>(u.current=!0,()=>{u.current=!1}),[]);const l=t.useRef(void 0);t.useEffect(()=>{l.current!==r&&(l.current=r,console.error("[PageError]",r))},[r]);const T=typeof i=="function"?i(r):i==="dev"?s.isDev():i??(s.isServerError(r)||s.isDev()),j=async()=>{f(!0);try{await(n==null?void 0:n()),o==null||o(),await(e==null?void 0:e.invalidate())}finally{u.current&&f(!1)}},h=v&&e&&a!=null?d.jsx(k.Button,{size:"sm",variant:"text",color:"primary",onClick:()=>e.navigate({to:a}),children:c("pageError.home")}):void 0;return d.jsx(B.ErrorState,{ref:x,variant:"block",error:r,title:g??c("pageError.title"),description:E??(T?void 0:c("pageError.description")),icon:m,size:p,pattern:q,showDetails:P,onRetry:o||n||e?()=>void j():void 0,retrying:y,action:h,...S})});exports.PageError=H;
2
+ //# sourceMappingURL=PageError-v6MAH_OL.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageError-CCKWbrc5.cjs","sources":["../src/components/PageError/PageError.tsx"],"sourcesContent":["import { forwardRef, useEffect, useRef, useState, type HTMLAttributes, type ReactNode } from 'react'\nimport { type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport type { IconName } from '../../icons/names'\nimport { Button } from '../Button'\nimport type { EmptyStateSize } from '../EmptyState'\nimport { ErrorState } from '../ErrorState/ErrorState'\nimport { isDev, isServerError } from '../ErrorState/errorMessage'\nimport { useHomeTo } from '../PageNotFound/useHomeTo'\n\nexport interface PageErrorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'color'> {\n /** What the route threw (TanStack Router's `ErrorComponentProps.error`). */\n error: unknown\n /** Resets the route's error boundary (TanStack Router's `ErrorComponentProps.reset`). */\n reset?: () => void\n /** The React component stack (TanStack Router's `ErrorComponentProps.info`) — unused, accepted for typing. */\n info?: { componentStack: string }\n /**\n * Runs **before** the reset on \"Try Again\" (may be async) — where an app drops cached data, e.g.\n * `() => queryClient.resetQueries({ predicate: (q) => q.queryKey[0] !== 'session' })`. Without it, `reset()`\n * re-renders against the same cached response and throws on the same data again.\n */\n onRetry?: () => void | Promise<void>\n /**\n * Show the error's own message. Default: when it looks **server-originated** (a `traceId` or a numeric\n * `status` — written for people) or in development; otherwise the localized generic sentence (a render\n * crash's message is a developer's). `true` / `false` force it; `'dev'` = development only; a function decides\n * per error.\n */\n showMessage?: boolean | 'dev' | ((error: unknown) => boolean)\n /** A secondary \"Go to Home\" button to the first allowed menu page (RBAC-aware). Defaults to `true`. */\n showHome?: boolean\n /** Heading. Defaults to the localized \"This Page Could Not Be Shown\". */\n title?: ReactNode\n /** Overrides the description (the message / the generic sentence). */\n description?: ReactNode\n /** Leading icon — passed to `ErrorState` (`Danger` / `CloudCross` by default; `false` hides it). */\n icon?: IconName | ReactNode | false\n /** Size — passed to `ErrorState`. Defaults to `md`. */\n size?: EmptyStateSize\n /** Faded-grid hero backdrop — passed to `ErrorState`. Defaults to `true`. */\n pattern?: boolean\n /** The developer details panel (stack) — passed to `ErrorState`. Defaults to `'dev'`. */\n showDetails?: boolean | 'dev'\n}\n\n/**\n * The shared **route error page** — the twin of `PageNotFound`. Drop it into TanStack Router as the\n * `defaultErrorComponent`: TanStack wraps every route in its own error boundary (inside the shell's `<Outlet/>`),\n * so without it a crashing page shows the router's bare \"Something went wrong!\". Renders the full `ErrorState`\n * hero inside the shell with **Try Again** (`await onRetry?.()` → `reset()` → `router.invalidate()`, which re-runs\n * a throwing loader / `beforeLoad`), a **Go to Home** button, the server's `traceId`, and the error's message only\n * when it was written for people (`showMessage`). Every error is `console.error`ed once — in production the\n * screen hides the message, so the console is the record.\n *\n * @example\n * createRouter({ routeTree, defaultNotFoundComponent: PageNotFound, defaultErrorComponent: PageError })\n */\nexport const PageError = forwardRef<HTMLDivElement, PageErrorProps>(function PageError(\n {\n error,\n reset,\n info: _info,\n onRetry,\n showMessage,\n showHome = true,\n title,\n description,\n icon,\n size,\n pattern,\n showDetails,\n ...props\n },\n ref,\n) {\n const t = useT()\n const { router, homeTo } = useHomeTo()\n const [retrying, setRetrying] = useState(false)\n const mounted = useRef(true)\n useEffect(() => {\n mounted.current = true\n return () => {\n mounted.current = false\n }\n }, [])\n\n // log each distinct error once (StrictMode re-runs effects; a re-render with the same error isn't new)\n const logged = useRef<unknown>(undefined)\n useEffect(() => {\n if (logged.current === error) return\n logged.current = error\n console.error('[PageError]', error)\n }, [error])\n\n const messageShown =\n typeof showMessage === 'function'\n ? showMessage(error)\n : showMessage === 'dev'\n ? isDev()\n : (showMessage ?? (isServerError(error) || isDev()))\n\n const retry = async () => {\n setRetrying(true)\n try {\n await onRetry?.()\n reset?.()\n await router?.invalidate()\n } finally {\n if (mounted.current) setRetrying(false)\n }\n }\n\n const home =\n showHome && router && homeTo != null ? (\n <Button\n size=\"sm\"\n variant=\"text\"\n color=\"primary\"\n onClick={() => router.navigate({ to: homeTo as LinkProps['to'] })}\n >\n {t('pageError.home')}\n </Button>\n ) : undefined\n\n return (\n <ErrorState\n ref={ref}\n variant=\"block\"\n error={error}\n title={title ?? t('pageError.title')}\n // hidden message → the generic sentence (the trace id still shows: it's for support, not a leak)\n description={description ?? (messageShown ? undefined : t('pageError.description'))}\n icon={icon}\n size={size}\n pattern={pattern}\n showDetails={showDetails}\n onRetry={reset || onRetry || router ? () => void retry() : undefined}\n retrying={retrying}\n action={home}\n {...props}\n />\n )\n})\n"],"names":["PageError","forwardRef","error","reset","_info","onRetry","showMessage","showHome","title","description","icon","size","pattern","showDetails","props","ref","t","useT","router","homeTo","useHomeTo","retrying","setRetrying","useState","mounted","useRef","useEffect","logged","messageShown","isDev","isServerError","retry","home","jsx","Button","ErrorState"],"mappings":"yQA0DaA,EAAYC,EAAAA,WAA2C,SAClE,CACE,MAAAC,EACA,MAAAC,EACA,KAAMC,EACN,QAAAC,EACA,YAAAC,EACA,SAAAC,EAAW,GACX,MAAAC,EACA,YAAAC,EACA,KAAAC,EACA,KAAAC,EACA,QAAAC,EACA,YAAAC,EACA,GAAGC,CACL,EACAC,EACA,CACA,MAAMC,EAAIC,EAAAA,KAAA,EACJ,CAAE,OAAAC,EAAQ,OAAAC,CAAA,EAAWC,YAAA,EACrB,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAS,EAAK,EACxCC,EAAUC,EAAAA,OAAO,EAAI,EAC3BC,EAAAA,UAAU,KACRF,EAAQ,QAAU,GACX,IAAM,CACXA,EAAQ,QAAU,EACpB,GACC,CAAA,CAAE,EAGL,MAAMG,EAASF,EAAAA,OAAgB,MAAS,EACxCC,EAAAA,UAAU,IAAM,CACVC,EAAO,UAAYzB,IACvByB,EAAO,QAAUzB,EACjB,QAAQ,MAAM,cAAeA,CAAK,EACpC,EAAG,CAACA,CAAK,CAAC,EAEV,MAAM0B,EACJ,OAAOtB,GAAgB,WACnBA,EAAYJ,CAAK,EACjBI,IAAgB,MACduB,EAAAA,QACCvB,IAAgBwB,EAAAA,cAAc5B,CAAK,GAAK2B,EAAAA,SAE3CE,EAAQ,SAAY,CACxBT,EAAY,EAAI,EAChB,GAAI,CACF,MAAMjB,GAAA,YAAAA,KACNF,GAAA,MAAAA,IACA,MAAMe,GAAA,YAAAA,EAAQ,aAChB,QAAA,CACMM,EAAQ,SAASF,EAAY,EAAK,CACxC,CACF,EAEMU,EACJzB,GAAYW,GAAUC,GAAU,KAC9Bc,EAAAA,IAACC,EAAAA,OAAA,CACC,KAAK,KACL,QAAQ,OACR,MAAM,UACN,QAAS,IAAMhB,EAAO,SAAS,CAAE,GAAIC,EAA2B,EAE/D,WAAE,gBAAgB,CAAA,CAAA,EAEnB,OAEN,OACEc,EAAAA,IAACE,EAAAA,WAAA,CACC,IAAApB,EACA,QAAQ,QACR,MAAAb,EACA,MAAOM,GAASQ,EAAE,iBAAiB,EAEnC,YAAaP,IAAgBmB,EAAe,OAAYZ,EAAE,uBAAuB,GACjF,KAAAN,EACA,KAAAC,EACA,QAAAC,EACA,YAAAC,EACA,QAASV,GAASE,GAAWa,EAAS,IAAM,KAAKa,IAAU,OAC3D,SAAAV,EACA,OAAQW,EACP,GAAGlB,CAAA,CAAA,CAGV,CAAC"}
1
+ {"version":3,"file":"PageError-v6MAH_OL.cjs","sources":["../src/components/PageError/PageError.tsx"],"sourcesContent":["import { forwardRef, useEffect, useRef, useState, type HTMLAttributes, type ReactNode } from 'react'\nimport { type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport type { IconName } from '../../icons/names'\nimport { Button } from '../Button'\nimport type { EmptyStateSize } from '../EmptyState'\nimport { ErrorState } from '../ErrorState/ErrorState'\nimport { isDev, isServerError } from '../ErrorState/errorMessage'\nimport { useHomeTo } from '../PageNotFound/useHomeTo'\n\nexport interface PageErrorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'color'> {\n /** What the route threw (TanStack Router's `ErrorComponentProps.error`). */\n error: unknown\n /** Resets the route's error boundary (TanStack Router's `ErrorComponentProps.reset`). */\n reset?: () => void\n /** The React component stack (TanStack Router's `ErrorComponentProps.info`) — unused, accepted for typing. */\n info?: { componentStack: string }\n /**\n * Runs **before** the reset on \"Try Again\" (may be async) — where an app drops cached data, e.g.\n * `() => queryClient.resetQueries({ predicate: (q) => q.queryKey[0] !== 'session' })`. Without it, `reset()`\n * re-renders against the same cached response and throws on the same data again.\n */\n onRetry?: () => void | Promise<void>\n /**\n * Show the error's own message. Default: when it looks **server-originated** (a `traceId` or a numeric\n * `status` — written for people) or in development; otherwise the localized generic sentence (a render\n * crash's message is a developer's). `true` / `false` force it; `'dev'` = development only; a function decides\n * per error.\n */\n showMessage?: boolean | 'dev' | ((error: unknown) => boolean)\n /** A secondary \"Go to Home\" button to the first allowed menu page (RBAC-aware). Defaults to `true`. */\n showHome?: boolean\n /** Heading. Defaults to the localized \"This Page Could Not Be Shown\". */\n title?: ReactNode\n /** Overrides the description (the message / the generic sentence). */\n description?: ReactNode\n /** Leading icon — passed to `ErrorState` (`Danger` / `CloudCross` by default; `false` hides it). */\n icon?: IconName | ReactNode | false\n /** Size — passed to `ErrorState`. Defaults to `md`. */\n size?: EmptyStateSize\n /** Faded-grid hero backdrop — passed to `ErrorState`. Defaults to `true`. */\n pattern?: boolean\n /** The developer details panel (stack) — passed to `ErrorState`. Defaults to `'dev'`. */\n showDetails?: boolean | 'dev'\n}\n\n/**\n * The shared **route error page** — the twin of `PageNotFound`. Drop it into TanStack Router as the\n * `defaultErrorComponent`: TanStack wraps every route in its own error boundary (inside the shell's `<Outlet/>`),\n * so without it a crashing page shows the router's bare \"Something went wrong!\". Renders the full `ErrorState`\n * hero inside the shell with **Try Again** (`await onRetry?.()` → `reset()` → `router.invalidate()`, which re-runs\n * a throwing loader / `beforeLoad`), a **Go to Home** button, the server's `traceId`, and the error's message only\n * when it was written for people (`showMessage`). Every error is `console.error`ed once — in production the\n * screen hides the message, so the console is the record.\n *\n * @example\n * createRouter({ routeTree, defaultNotFoundComponent: PageNotFound, defaultErrorComponent: PageError })\n */\nexport const PageError = forwardRef<HTMLDivElement, PageErrorProps>(function PageError(\n {\n error,\n reset,\n info: _info,\n onRetry,\n showMessage,\n showHome = true,\n title,\n description,\n icon,\n size,\n pattern,\n showDetails,\n ...props\n },\n ref,\n) {\n const t = useT()\n const { router, homeTo } = useHomeTo()\n const [retrying, setRetrying] = useState(false)\n const mounted = useRef(true)\n useEffect(() => {\n mounted.current = true\n return () => {\n mounted.current = false\n }\n }, [])\n\n // log each distinct error once (StrictMode re-runs effects; a re-render with the same error isn't new)\n const logged = useRef<unknown>(undefined)\n useEffect(() => {\n if (logged.current === error) return\n logged.current = error\n console.error('[PageError]', error)\n }, [error])\n\n const messageShown =\n typeof showMessage === 'function'\n ? showMessage(error)\n : showMessage === 'dev'\n ? isDev()\n : (showMessage ?? (isServerError(error) || isDev()))\n\n const retry = async () => {\n setRetrying(true)\n try {\n await onRetry?.()\n reset?.()\n await router?.invalidate()\n } finally {\n if (mounted.current) setRetrying(false)\n }\n }\n\n const home =\n showHome && router && homeTo != null ? (\n <Button\n size=\"sm\"\n variant=\"text\"\n color=\"primary\"\n onClick={() => router.navigate({ to: homeTo as LinkProps['to'] })}\n >\n {t('pageError.home')}\n </Button>\n ) : undefined\n\n return (\n <ErrorState\n ref={ref}\n variant=\"block\"\n error={error}\n title={title ?? t('pageError.title')}\n // hidden message → the generic sentence (the trace id still shows: it's for support, not a leak)\n description={description ?? (messageShown ? undefined : t('pageError.description'))}\n icon={icon}\n size={size}\n pattern={pattern}\n showDetails={showDetails}\n onRetry={reset || onRetry || router ? () => void retry() : undefined}\n retrying={retrying}\n action={home}\n {...props}\n />\n )\n})\n"],"names":["PageError","forwardRef","error","reset","_info","onRetry","showMessage","showHome","title","description","icon","size","pattern","showDetails","props","ref","t","useT","router","homeTo","useHomeTo","retrying","setRetrying","useState","mounted","useRef","useEffect","logged","messageShown","isDev","isServerError","retry","home","jsx","Button","ErrorState"],"mappings":"yQA0DaA,EAAYC,EAAAA,WAA2C,SAClE,CACE,MAAAC,EACA,MAAAC,EACA,KAAMC,EACN,QAAAC,EACA,YAAAC,EACA,SAAAC,EAAW,GACX,MAAAC,EACA,YAAAC,EACA,KAAAC,EACA,KAAAC,EACA,QAAAC,EACA,YAAAC,EACA,GAAGC,CACL,EACAC,EACA,CACA,MAAMC,EAAIC,EAAAA,KAAA,EACJ,CAAE,OAAAC,EAAQ,OAAAC,CAAA,EAAWC,YAAA,EACrB,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAS,EAAK,EACxCC,EAAUC,EAAAA,OAAO,EAAI,EAC3BC,EAAAA,UAAU,KACRF,EAAQ,QAAU,GACX,IAAM,CACXA,EAAQ,QAAU,EACpB,GACC,CAAA,CAAE,EAGL,MAAMG,EAASF,EAAAA,OAAgB,MAAS,EACxCC,EAAAA,UAAU,IAAM,CACVC,EAAO,UAAYzB,IACvByB,EAAO,QAAUzB,EACjB,QAAQ,MAAM,cAAeA,CAAK,EACpC,EAAG,CAACA,CAAK,CAAC,EAEV,MAAM0B,EACJ,OAAOtB,GAAgB,WACnBA,EAAYJ,CAAK,EACjBI,IAAgB,MACduB,EAAAA,QACCvB,IAAgBwB,EAAAA,cAAc5B,CAAK,GAAK2B,EAAAA,SAE3CE,EAAQ,SAAY,CACxBT,EAAY,EAAI,EAChB,GAAI,CACF,MAAMjB,GAAA,YAAAA,KACNF,GAAA,MAAAA,IACA,MAAMe,GAAA,YAAAA,EAAQ,aAChB,QAAA,CACMM,EAAQ,SAASF,EAAY,EAAK,CACxC,CACF,EAEMU,EACJzB,GAAYW,GAAUC,GAAU,KAC9Bc,EAAAA,IAACC,EAAAA,OAAA,CACC,KAAK,KACL,QAAQ,OACR,MAAM,UACN,QAAS,IAAMhB,EAAO,SAAS,CAAE,GAAIC,EAA2B,EAE/D,WAAE,gBAAgB,CAAA,CAAA,EAEnB,OAEN,OACEc,EAAAA,IAACE,EAAAA,WAAA,CACC,IAAApB,EACA,QAAQ,QACR,MAAAb,EACA,MAAOM,GAASQ,EAAE,iBAAiB,EAEnC,YAAaP,IAAgBmB,EAAe,OAAYZ,EAAE,uBAAuB,GACjF,KAAAN,EACA,KAAAC,EACA,QAAAC,EACA,YAAAC,EACA,QAASV,GAASE,GAAWa,EAAS,IAAM,KAAKa,IAAU,OAC3D,SAAAV,EACA,OAAQW,EACP,GAAGlB,CAAA,CAAA,CAGV,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { jsxs as m, Fragment as p, jsx as t } from "react/jsx-runtime";
2
2
  import { forwardRef as w } from "react";
3
3
  import { useRouter as y } from "@tanstack/react-router";
4
- import { C as _ } from "./Card-ssUNaOF_.js";
4
+ import { C as _ } from "./Card-ckOd617g.js";
5
5
  import { b as v } from "./Icon-B7DJn8Tw.js";
6
- import { I as T } from "./IconButton-re6xITGO.js";
6
+ import { I as T } from "./IconButton-iWbUJAz7.js";
7
7
  import { T as x } from "./Typography-ChSuxgkc.js";
8
- import { a as C } from "./ConfigProvider-DVDGtCUc.js";
8
+ import { a as C } from "./ConfigProvider-DtyUlWk6.js";
9
9
  const I = "_heading_100i8_4", L = "_title_100i8_12", N = "_actions_100i8_19", s = {
10
10
  heading: I,
11
11
  title: L,
@@ -34,4 +34,4 @@ const I = "_heading_100i8_4", L = "_title_100i8_12", N = "_actions_100i8_19", s
34
34
  export {
35
35
  F as P
36
36
  };
37
- //# sourceMappingURL=PageLayout-BekkDBtT.js.map
37
+ //# sourceMappingURL=PageLayout-BjaPfXvb.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageLayout-BekkDBtT.js","sources":["../src/components/PageLayout/PageLayout.tsx"],"sourcesContent":["import { forwardRef, type ReactNode } from 'react'\nimport { useRouter, type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport { Card, type CardProps } from '../Card'\nimport { Icon } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { Typography } from '../Typography'\nimport styles from './PageLayout.module.css'\n\n/** Something React would actually render — `null` / `undefined` / booleans / `''` render nothing (e.g. the\n * `pageActions={isDirty && <Button…/>}` pattern), so they mustn't produce an empty heading row. */\nconst renders = (node: ReactNode): boolean =>\n node != null && typeof node !== 'boolean' && node !== ''\n\n/** PageLayout is a flat `Card`, so it gains all of Card's slots minus the `flat` toggle (always flat). */\nexport interface PageLayoutProps extends Omit<CardProps, 'flat'> {\n /**\n * The page heading — an `h2` in the row **above** the card (the card's own header — `icon` / `title` /\n * `subtitle` / `actions` — is separate and unchanged). Shown only when given.\n */\n pageTitle?: ReactNode\n /**\n * Anything for the right end of the heading row — usually a few `size=\"sm\"` `Button`s, built in the page with\n * its own state. Rendered as given (no automatic phone collapse); on a narrow screen the row wraps, so they\n * drop below the title.\n */\n pageActions?: ReactNode\n /**\n * A back button left of the heading. `true` → the browser history back; a **path** string → navigates there\n * (deterministic on a deep link / refresh, e.g. `back={`/users/${id}`}`). Omitted / `false` → none.\n */\n back?: boolean | string\n}\n\n/**\n * The container a page's body sits in — a **flat `Card`**: an ordinary bordered `surface` panel with no\n * shadow, floating on the shell's `background` canvas (`flat` is only a styling hook). Being a Card, it has the full\n * Card anatomy: an optional card header (`icon` + `title` + `subtitle` + `actions`), the body (`children`), a\n * `footer` / `footerStart` (`stickyFooter`), and `collapsible`. Above the card, an optional **page heading row**\n * — `back` (button) + `pageTitle` (`h2`) + `pageActions` (right) — shown only when one of them is given; the\n * shell itself renders no page title. Rendered by the consumer inside each route, below the shell's breadcrumbs:\n * `<PageLayout pageTitle=\"Users\" pageActions={<Button size=\"sm\">Add New</Button>}>…</PageLayout>`. The ref\n * points at the card. Styling uses `--tz-*` tokens only.\n */\nexport const PageLayout = forwardRef<HTMLDivElement, PageLayoutProps>(function PageLayout(\n { pageTitle, pageActions, back, ...props },\n ref,\n) {\n const t = useT()\n // lenient: outside a RouterProvider the back button falls back to the browser's own history / location\n const router = useRouter({ warn: false })\n const goBack =\n back === true\n ? () => (router ? router.history.back() : window.history.back())\n : typeof back === 'string' && back\n ? () =>\n router\n ? void router.navigate({ to: back as LinkProps['to'] })\n : window.location.assign(back)\n : undefined\n const showTitle = renders(pageTitle)\n const showActions = renders(pageActions)\n const hasHeading = showTitle || showActions || goBack != null\n\n return (\n <>\n {hasHeading ? (\n <div className={styles.heading}>\n {goBack ? (\n <IconButton\n aria-label={t('pageTitle.back')}\n variant=\"filled\"\n color=\"accent\"\n size=\"sm\"\n onClick={goBack}\n >\n <Icon name=\"ArrowLeft\" />\n </IconButton>\n ) : null}\n {showTitle ? (\n <Typography variant=\"h2\" className={styles.title}>\n {pageTitle}\n </Typography>\n ) : null}\n {showActions ? <div className={styles.actions}>{pageActions}</div> : null}\n </div>\n ) : null}\n <Card ref={ref} flat {...props} />\n </>\n )\n})\n"],"names":["renders","node","PageLayout","forwardRef","pageTitle","pageActions","back","props","ref","t","useT","router","useRouter","goBack","showTitle","showActions","hasHeading","jsxs","Fragment","styles","jsx","IconButton","Icon","Typography","Card"],"mappings":";;;;;;;;;;;;GAWMA,IAAU,CAACC,MACfA,KAAQ,QAAQ,OAAOA,KAAS,aAAaA,MAAS,IAgC3CC,IAAaC,EAA4C,SACpE,EAAE,WAAAC,GAAW,aAAAC,GAAa,MAAAC,GAAM,GAAGC,EAAA,GACnCC,GACA;AACA,QAAMC,IAAIC,EAAA,GAEJC,IAASC,EAAU,EAAE,MAAM,IAAO,GAClCC,IACJP,MAAS,KACL,MAAOK,IAASA,EAAO,QAAQ,KAAA,IAAS,OAAO,QAAQ,KAAA,IACvD,OAAOL,KAAS,YAAYA,IAC1B,MACEK,IACI,KAAKA,EAAO,SAAS,EAAE,IAAIL,EAAA,CAAyB,IACpD,OAAO,SAAS,OAAOA,CAAI,IACjC,QACFQ,IAAYd,EAAQI,CAAS,GAC7BW,IAAcf,EAAQK,CAAW,GACjCW,IAAaF,KAAaC,KAAeF,KAAU;AAEzD,SACE,gBAAAI,EAAAC,GAAA,EACG,UAAA;AAAA,IAAAF,IACC,gBAAAC,EAAC,OAAA,EAAI,WAAWE,EAAO,SACpB,UAAA;AAAA,MAAAN,IACC,gBAAAO;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,cAAYZ,EAAE,gBAAgB;AAAA,UAC9B,SAAQ;AAAA,UACR,OAAM;AAAA,UACN,MAAK;AAAA,UACL,SAASI;AAAA,UAET,UAAA,gBAAAO,EAACE,GAAA,EAAK,MAAK,YAAA,CAAY;AAAA,QAAA;AAAA,MAAA,IAEvB;AAAA,MACHR,sBACES,GAAA,EAAW,SAAQ,MAAK,WAAWJ,EAAO,OACxC,UAAAf,EAAA,CACH,IACE;AAAA,MACHW,IAAc,gBAAAK,EAAC,OAAA,EAAI,WAAWD,EAAO,SAAU,aAAY,IAAS;AAAA,IAAA,EAAA,CACvE,IACE;AAAA,sBACHK,GAAA,EAAK,KAAAhB,GAAU,MAAI,IAAE,GAAGD,EAAA,CAAO;AAAA,EAAA,GAClC;AAEJ,CAAC;"}
1
+ {"version":3,"file":"PageLayout-BjaPfXvb.js","sources":["../src/components/PageLayout/PageLayout.tsx"],"sourcesContent":["import { forwardRef, type ReactNode } from 'react'\nimport { useRouter, type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport { Card, type CardProps } from '../Card'\nimport { Icon } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { Typography } from '../Typography'\nimport styles from './PageLayout.module.css'\n\n/** Something React would actually render — `null` / `undefined` / booleans / `''` render nothing (e.g. the\n * `pageActions={isDirty && <Button…/>}` pattern), so they mustn't produce an empty heading row. */\nconst renders = (node: ReactNode): boolean =>\n node != null && typeof node !== 'boolean' && node !== ''\n\n/** PageLayout is a flat `Card`, so it gains all of Card's slots minus the `flat` toggle (always flat). */\nexport interface PageLayoutProps extends Omit<CardProps, 'flat'> {\n /**\n * The page heading — an `h2` in the row **above** the card (the card's own header — `icon` / `title` /\n * `subtitle` / `actions` — is separate and unchanged). Shown only when given.\n */\n pageTitle?: ReactNode\n /**\n * Anything for the right end of the heading row — usually a few `size=\"sm\"` `Button`s, built in the page with\n * its own state. Rendered as given (no automatic phone collapse); on a narrow screen the row wraps, so they\n * drop below the title.\n */\n pageActions?: ReactNode\n /**\n * A back button left of the heading. `true` → the browser history back; a **path** string → navigates there\n * (deterministic on a deep link / refresh, e.g. `back={`/users/${id}`}`). Omitted / `false` → none.\n */\n back?: boolean | string\n}\n\n/**\n * The container a page's body sits in — a **flat `Card`**: an ordinary bordered `surface` panel with no\n * shadow, floating on the shell's `background` canvas (`flat` is only a styling hook). Being a Card, it has the full\n * Card anatomy: an optional card header (`icon` + `title` + `subtitle` + `actions`), the body (`children`), a\n * `footer` / `footerStart` (`stickyFooter`), and `collapsible`. Above the card, an optional **page heading row**\n * — `back` (button) + `pageTitle` (`h2`) + `pageActions` (right) — shown only when one of them is given; the\n * shell itself renders no page title. Rendered by the consumer inside each route, below the shell's breadcrumbs:\n * `<PageLayout pageTitle=\"Users\" pageActions={<Button size=\"sm\">Add New</Button>}>…</PageLayout>`. The ref\n * points at the card. Styling uses `--tz-*` tokens only.\n */\nexport const PageLayout = forwardRef<HTMLDivElement, PageLayoutProps>(function PageLayout(\n { pageTitle, pageActions, back, ...props },\n ref,\n) {\n const t = useT()\n // lenient: outside a RouterProvider the back button falls back to the browser's own history / location\n const router = useRouter({ warn: false })\n const goBack =\n back === true\n ? () => (router ? router.history.back() : window.history.back())\n : typeof back === 'string' && back\n ? () =>\n router\n ? void router.navigate({ to: back as LinkProps['to'] })\n : window.location.assign(back)\n : undefined\n const showTitle = renders(pageTitle)\n const showActions = renders(pageActions)\n const hasHeading = showTitle || showActions || goBack != null\n\n return (\n <>\n {hasHeading ? (\n <div className={styles.heading}>\n {goBack ? (\n <IconButton\n aria-label={t('pageTitle.back')}\n variant=\"filled\"\n color=\"accent\"\n size=\"sm\"\n onClick={goBack}\n >\n <Icon name=\"ArrowLeft\" />\n </IconButton>\n ) : null}\n {showTitle ? (\n <Typography variant=\"h2\" className={styles.title}>\n {pageTitle}\n </Typography>\n ) : null}\n {showActions ? <div className={styles.actions}>{pageActions}</div> : null}\n </div>\n ) : null}\n <Card ref={ref} flat {...props} />\n </>\n )\n})\n"],"names":["renders","node","PageLayout","forwardRef","pageTitle","pageActions","back","props","ref","t","useT","router","useRouter","goBack","showTitle","showActions","hasHeading","jsxs","Fragment","styles","jsx","IconButton","Icon","Typography","Card"],"mappings":";;;;;;;;;;;;GAWMA,IAAU,CAACC,MACfA,KAAQ,QAAQ,OAAOA,KAAS,aAAaA,MAAS,IAgC3CC,IAAaC,EAA4C,SACpE,EAAE,WAAAC,GAAW,aAAAC,GAAa,MAAAC,GAAM,GAAGC,EAAA,GACnCC,GACA;AACA,QAAMC,IAAIC,EAAA,GAEJC,IAASC,EAAU,EAAE,MAAM,IAAO,GAClCC,IACJP,MAAS,KACL,MAAOK,IAASA,EAAO,QAAQ,KAAA,IAAS,OAAO,QAAQ,KAAA,IACvD,OAAOL,KAAS,YAAYA,IAC1B,MACEK,IACI,KAAKA,EAAO,SAAS,EAAE,IAAIL,EAAA,CAAyB,IACpD,OAAO,SAAS,OAAOA,CAAI,IACjC,QACFQ,IAAYd,EAAQI,CAAS,GAC7BW,IAAcf,EAAQK,CAAW,GACjCW,IAAaF,KAAaC,KAAeF,KAAU;AAEzD,SACE,gBAAAI,EAAAC,GAAA,EACG,UAAA;AAAA,IAAAF,IACC,gBAAAC,EAAC,OAAA,EAAI,WAAWE,EAAO,SACpB,UAAA;AAAA,MAAAN,IACC,gBAAAO;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,cAAYZ,EAAE,gBAAgB;AAAA,UAC9B,SAAQ;AAAA,UACR,OAAM;AAAA,UACN,MAAK;AAAA,UACL,SAASI;AAAA,UAET,UAAA,gBAAAO,EAACE,GAAA,EAAK,MAAK,YAAA,CAAY;AAAA,QAAA;AAAA,MAAA,IAEvB;AAAA,MACHR,sBACES,GAAA,EAAW,SAAQ,MAAK,WAAWJ,EAAO,OACxC,UAAAf,EAAA,CACH,IACE;AAAA,MACHW,IAAc,gBAAAK,EAAC,OAAA,EAAI,WAAWD,EAAO,SAAU,aAAY,IAAS;AAAA,IAAA,EAAA,CACvE,IACE;AAAA,sBACHK,GAAA,EAAK,KAAAhB,GAAU,MAAI,IAAE,GAAGD,EAAA,CAAO;AAAA,EAAA,GAClC;AAEJ,CAAC;"}
@@ -1,2 +1,2 @@
1
- "use strict";const t=require("react/jsx-runtime"),f=require("react"),w=require("@tanstack/react-router"),_=require("./Card-BdNr5row.cjs"),j=require("./Icon-CBg21lKA.cjs"),q=require("./IconButton-U_sr2Ahy.cjs"),v=require("./Typography-d97DdbNd.cjs"),x=require("./ConfigProvider-DBU6rOIA.cjs"),m="_heading_100i8_4",p="_title_100i8_12",C="_actions_100i8_19",i={heading:m,title:p,actions:C},u=e=>e!=null&&typeof e!="boolean"&&e!=="",I=f.forwardRef(function({pageTitle:r,pageActions:a,back:n,...d},h){const g=x.useT(),o=w.useRouter({warn:!1}),s=n===!0?()=>o?o.history.back():window.history.back():typeof n=="string"&&n?()=>o?void o.navigate({to:n}):window.location.assign(n):void 0,c=u(r),l=u(a),y=c||l||s!=null;return t.jsxs(t.Fragment,{children:[y?t.jsxs("div",{className:i.heading,children:[s?t.jsx(q.IconButton,{"aria-label":g("pageTitle.back"),variant:"filled",color:"accent",size:"sm",onClick:s,children:t.jsx(j.Icon,{name:"ArrowLeft"})}):null,c?t.jsx(v.Typography,{variant:"h2",className:i.title,children:r}):null,l?t.jsx("div",{className:i.actions,children:a}):null]}):null,t.jsx(_.Card,{ref:h,flat:!0,...d})]})});exports.PageLayout=I;
2
- //# sourceMappingURL=PageLayout-CDPUYu6A.cjs.map
1
+ "use strict";const t=require("react/jsx-runtime"),f=require("react"),w=require("@tanstack/react-router"),_=require("./Card-KfmWG9Uz.cjs"),j=require("./Icon-CBg21lKA.cjs"),q=require("./IconButton-DSPdv-oI.cjs"),v=require("./Typography-d97DdbNd.cjs"),x=require("./ConfigProvider-CYSpuSMJ.cjs"),m="_heading_100i8_4",p="_title_100i8_12",C="_actions_100i8_19",i={heading:m,title:p,actions:C},u=e=>e!=null&&typeof e!="boolean"&&e!=="",I=f.forwardRef(function({pageTitle:r,pageActions:a,back:n,...d},h){const g=x.useT(),o=w.useRouter({warn:!1}),s=n===!0?()=>o?o.history.back():window.history.back():typeof n=="string"&&n?()=>o?void o.navigate({to:n}):window.location.assign(n):void 0,c=u(r),l=u(a),y=c||l||s!=null;return t.jsxs(t.Fragment,{children:[y?t.jsxs("div",{className:i.heading,children:[s?t.jsx(q.IconButton,{"aria-label":g("pageTitle.back"),variant:"filled",color:"accent",size:"sm",onClick:s,children:t.jsx(j.Icon,{name:"ArrowLeft"})}):null,c?t.jsx(v.Typography,{variant:"h2",className:i.title,children:r}):null,l?t.jsx("div",{className:i.actions,children:a}):null]}):null,t.jsx(_.Card,{ref:h,flat:!0,...d})]})});exports.PageLayout=I;
2
+ //# sourceMappingURL=PageLayout-DH3jochw.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageLayout-CDPUYu6A.cjs","sources":["../src/components/PageLayout/PageLayout.tsx"],"sourcesContent":["import { forwardRef, type ReactNode } from 'react'\nimport { useRouter, type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport { Card, type CardProps } from '../Card'\nimport { Icon } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { Typography } from '../Typography'\nimport styles from './PageLayout.module.css'\n\n/** Something React would actually render — `null` / `undefined` / booleans / `''` render nothing (e.g. the\n * `pageActions={isDirty && <Button…/>}` pattern), so they mustn't produce an empty heading row. */\nconst renders = (node: ReactNode): boolean =>\n node != null && typeof node !== 'boolean' && node !== ''\n\n/** PageLayout is a flat `Card`, so it gains all of Card's slots minus the `flat` toggle (always flat). */\nexport interface PageLayoutProps extends Omit<CardProps, 'flat'> {\n /**\n * The page heading — an `h2` in the row **above** the card (the card's own header — `icon` / `title` /\n * `subtitle` / `actions` — is separate and unchanged). Shown only when given.\n */\n pageTitle?: ReactNode\n /**\n * Anything for the right end of the heading row — usually a few `size=\"sm\"` `Button`s, built in the page with\n * its own state. Rendered as given (no automatic phone collapse); on a narrow screen the row wraps, so they\n * drop below the title.\n */\n pageActions?: ReactNode\n /**\n * A back button left of the heading. `true` → the browser history back; a **path** string → navigates there\n * (deterministic on a deep link / refresh, e.g. `back={`/users/${id}`}`). Omitted / `false` → none.\n */\n back?: boolean | string\n}\n\n/**\n * The container a page's body sits in — a **flat `Card`**: an ordinary bordered `surface` panel with no\n * shadow, floating on the shell's `background` canvas (`flat` is only a styling hook). Being a Card, it has the full\n * Card anatomy: an optional card header (`icon` + `title` + `subtitle` + `actions`), the body (`children`), a\n * `footer` / `footerStart` (`stickyFooter`), and `collapsible`. Above the card, an optional **page heading row**\n * — `back` (button) + `pageTitle` (`h2`) + `pageActions` (right) — shown only when one of them is given; the\n * shell itself renders no page title. Rendered by the consumer inside each route, below the shell's breadcrumbs:\n * `<PageLayout pageTitle=\"Users\" pageActions={<Button size=\"sm\">Add New</Button>}>…</PageLayout>`. The ref\n * points at the card. Styling uses `--tz-*` tokens only.\n */\nexport const PageLayout = forwardRef<HTMLDivElement, PageLayoutProps>(function PageLayout(\n { pageTitle, pageActions, back, ...props },\n ref,\n) {\n const t = useT()\n // lenient: outside a RouterProvider the back button falls back to the browser's own history / location\n const router = useRouter({ warn: false })\n const goBack =\n back === true\n ? () => (router ? router.history.back() : window.history.back())\n : typeof back === 'string' && back\n ? () =>\n router\n ? void router.navigate({ to: back as LinkProps['to'] })\n : window.location.assign(back)\n : undefined\n const showTitle = renders(pageTitle)\n const showActions = renders(pageActions)\n const hasHeading = showTitle || showActions || goBack != null\n\n return (\n <>\n {hasHeading ? (\n <div className={styles.heading}>\n {goBack ? (\n <IconButton\n aria-label={t('pageTitle.back')}\n variant=\"filled\"\n color=\"accent\"\n size=\"sm\"\n onClick={goBack}\n >\n <Icon name=\"ArrowLeft\" />\n </IconButton>\n ) : null}\n {showTitle ? (\n <Typography variant=\"h2\" className={styles.title}>\n {pageTitle}\n </Typography>\n ) : null}\n {showActions ? <div className={styles.actions}>{pageActions}</div> : null}\n </div>\n ) : null}\n <Card ref={ref} flat {...props} />\n </>\n )\n})\n"],"names":["renders","node","PageLayout","forwardRef","pageTitle","pageActions","back","props","ref","t","useT","router","useRouter","goBack","showTitle","showActions","hasHeading","jsxs","Fragment","styles","jsx","IconButton","Icon","Typography","Card"],"mappings":"mYAWMA,EAAWC,GACfA,GAAQ,MAAQ,OAAOA,GAAS,WAAaA,IAAS,GAgC3CC,EAAaC,EAAAA,WAA4C,SACpE,CAAE,UAAAC,EAAW,YAAAC,EAAa,KAAAC,EAAM,GAAGC,CAAA,EACnCC,EACA,CACA,MAAMC,EAAIC,EAAAA,KAAA,EAEJC,EAASC,EAAAA,UAAU,CAAE,KAAM,GAAO,EAClCC,EACJP,IAAS,GACL,IAAOK,EAASA,EAAO,QAAQ,KAAA,EAAS,OAAO,QAAQ,KAAA,EACvD,OAAOL,GAAS,UAAYA,EAC1B,IACEK,EACI,KAAKA,EAAO,SAAS,CAAE,GAAIL,CAAA,CAAyB,EACpD,OAAO,SAAS,OAAOA,CAAI,EACjC,OACFQ,EAAYd,EAAQI,CAAS,EAC7BW,EAAcf,EAAQK,CAAW,EACjCW,EAAaF,GAAaC,GAAeF,GAAU,KAEzD,OACEI,EAAAA,KAAAC,WAAA,CACG,SAAA,CAAAF,EACCC,EAAAA,KAAC,MAAA,CAAI,UAAWE,EAAO,QACpB,SAAA,CAAAN,EACCO,EAAAA,IAACC,EAAAA,WAAA,CACC,aAAYZ,EAAE,gBAAgB,EAC9B,QAAQ,SACR,MAAM,SACN,KAAK,KACL,QAASI,EAET,SAAAO,EAAAA,IAACE,EAAAA,KAAA,CAAK,KAAK,WAAA,CAAY,CAAA,CAAA,EAEvB,KACHR,QACES,aAAA,CAAW,QAAQ,KAAK,UAAWJ,EAAO,MACxC,SAAAf,CAAA,CACH,EACE,KACHW,EAAcK,EAAAA,IAAC,MAAA,CAAI,UAAWD,EAAO,QAAU,WAAY,EAAS,IAAA,CAAA,CACvE,EACE,WACHK,EAAAA,KAAA,CAAK,IAAAhB,EAAU,KAAI,GAAE,GAAGD,CAAA,CAAO,CAAA,EAClC,CAEJ,CAAC"}
1
+ {"version":3,"file":"PageLayout-DH3jochw.cjs","sources":["../src/components/PageLayout/PageLayout.tsx"],"sourcesContent":["import { forwardRef, type ReactNode } from 'react'\nimport { useRouter, type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport { Card, type CardProps } from '../Card'\nimport { Icon } from '../Icon'\nimport { IconButton } from '../IconButton'\nimport { Typography } from '../Typography'\nimport styles from './PageLayout.module.css'\n\n/** Something React would actually render — `null` / `undefined` / booleans / `''` render nothing (e.g. the\n * `pageActions={isDirty && <Button…/>}` pattern), so they mustn't produce an empty heading row. */\nconst renders = (node: ReactNode): boolean =>\n node != null && typeof node !== 'boolean' && node !== ''\n\n/** PageLayout is a flat `Card`, so it gains all of Card's slots minus the `flat` toggle (always flat). */\nexport interface PageLayoutProps extends Omit<CardProps, 'flat'> {\n /**\n * The page heading — an `h2` in the row **above** the card (the card's own header — `icon` / `title` /\n * `subtitle` / `actions` — is separate and unchanged). Shown only when given.\n */\n pageTitle?: ReactNode\n /**\n * Anything for the right end of the heading row — usually a few `size=\"sm\"` `Button`s, built in the page with\n * its own state. Rendered as given (no automatic phone collapse); on a narrow screen the row wraps, so they\n * drop below the title.\n */\n pageActions?: ReactNode\n /**\n * A back button left of the heading. `true` → the browser history back; a **path** string → navigates there\n * (deterministic on a deep link / refresh, e.g. `back={`/users/${id}`}`). Omitted / `false` → none.\n */\n back?: boolean | string\n}\n\n/**\n * The container a page's body sits in — a **flat `Card`**: an ordinary bordered `surface` panel with no\n * shadow, floating on the shell's `background` canvas (`flat` is only a styling hook). Being a Card, it has the full\n * Card anatomy: an optional card header (`icon` + `title` + `subtitle` + `actions`), the body (`children`), a\n * `footer` / `footerStart` (`stickyFooter`), and `collapsible`. Above the card, an optional **page heading row**\n * — `back` (button) + `pageTitle` (`h2`) + `pageActions` (right) — shown only when one of them is given; the\n * shell itself renders no page title. Rendered by the consumer inside each route, below the shell's breadcrumbs:\n * `<PageLayout pageTitle=\"Users\" pageActions={<Button size=\"sm\">Add New</Button>}>…</PageLayout>`. The ref\n * points at the card. Styling uses `--tz-*` tokens only.\n */\nexport const PageLayout = forwardRef<HTMLDivElement, PageLayoutProps>(function PageLayout(\n { pageTitle, pageActions, back, ...props },\n ref,\n) {\n const t = useT()\n // lenient: outside a RouterProvider the back button falls back to the browser's own history / location\n const router = useRouter({ warn: false })\n const goBack =\n back === true\n ? () => (router ? router.history.back() : window.history.back())\n : typeof back === 'string' && back\n ? () =>\n router\n ? void router.navigate({ to: back as LinkProps['to'] })\n : window.location.assign(back)\n : undefined\n const showTitle = renders(pageTitle)\n const showActions = renders(pageActions)\n const hasHeading = showTitle || showActions || goBack != null\n\n return (\n <>\n {hasHeading ? (\n <div className={styles.heading}>\n {goBack ? (\n <IconButton\n aria-label={t('pageTitle.back')}\n variant=\"filled\"\n color=\"accent\"\n size=\"sm\"\n onClick={goBack}\n >\n <Icon name=\"ArrowLeft\" />\n </IconButton>\n ) : null}\n {showTitle ? (\n <Typography variant=\"h2\" className={styles.title}>\n {pageTitle}\n </Typography>\n ) : null}\n {showActions ? <div className={styles.actions}>{pageActions}</div> : null}\n </div>\n ) : null}\n <Card ref={ref} flat {...props} />\n </>\n )\n})\n"],"names":["renders","node","PageLayout","forwardRef","pageTitle","pageActions","back","props","ref","t","useT","router","useRouter","goBack","showTitle","showActions","hasHeading","jsxs","Fragment","styles","jsx","IconButton","Icon","Typography","Card"],"mappings":"mYAWMA,EAAWC,GACfA,GAAQ,MAAQ,OAAOA,GAAS,WAAaA,IAAS,GAgC3CC,EAAaC,EAAAA,WAA4C,SACpE,CAAE,UAAAC,EAAW,YAAAC,EAAa,KAAAC,EAAM,GAAGC,CAAA,EACnCC,EACA,CACA,MAAMC,EAAIC,EAAAA,KAAA,EAEJC,EAASC,EAAAA,UAAU,CAAE,KAAM,GAAO,EAClCC,EACJP,IAAS,GACL,IAAOK,EAASA,EAAO,QAAQ,KAAA,EAAS,OAAO,QAAQ,KAAA,EACvD,OAAOL,GAAS,UAAYA,EAC1B,IACEK,EACI,KAAKA,EAAO,SAAS,CAAE,GAAIL,CAAA,CAAyB,EACpD,OAAO,SAAS,OAAOA,CAAI,EACjC,OACFQ,EAAYd,EAAQI,CAAS,EAC7BW,EAAcf,EAAQK,CAAW,EACjCW,EAAaF,GAAaC,GAAeF,GAAU,KAEzD,OACEI,EAAAA,KAAAC,WAAA,CACG,SAAA,CAAAF,EACCC,EAAAA,KAAC,MAAA,CAAI,UAAWE,EAAO,QACpB,SAAA,CAAAN,EACCO,EAAAA,IAACC,EAAAA,WAAA,CACC,aAAYZ,EAAE,gBAAgB,EAC9B,QAAQ,SACR,MAAM,SACN,KAAK,KACL,QAASI,EAET,SAAAO,EAAAA,IAACE,EAAAA,KAAA,CAAK,KAAK,WAAA,CAAY,CAAA,CAAA,EAEvB,KACHR,QACES,aAAA,CAAW,QAAQ,KAAK,UAAWJ,EAAO,MACxC,SAAAf,CAAA,CACH,EACE,KACHW,EAAcK,EAAAA,IAAC,MAAA,CAAI,UAAWD,EAAO,QAAU,WAAY,EAAS,IAAA,CAAA,CACvE,EACE,WACHK,EAAAA,KAAA,CAAK,IAAAhB,EAAU,KAAI,GAAE,GAAGD,CAAA,CAAO,CAAA,EAClC,CAEJ,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as r } from "react/jsx-runtime";
2
2
  import { forwardRef as l } from "react";
3
- import { E as F } from "./EmptyState-DXoaPC7o.js";
4
- import { B as N } from "./Button-C415LPw_.js";
5
- import { u as g } from "./useHomeTo-BL3e8Sc6.js";
6
- import { a as v } from "./ConfigProvider-DVDGtCUc.js";
3
+ import { E as F } from "./EmptyState-DrSj2XV_.js";
4
+ import { B as N } from "./Button-DZWYeAno.js";
5
+ import { u as g } from "./useHomeTo-BLSvhJd5.js";
6
+ import { a as v } from "./ConfigProvider-DtyUlWk6.js";
7
7
  const k = l(function({
8
8
  icon: e = "SearchStatus",
9
9
  title: a,
@@ -33,4 +33,4 @@ const k = l(function({
33
33
  export {
34
34
  k as P
35
35
  };
36
- //# sourceMappingURL=PageNotFound-BD3zX3cd.js.map
36
+ //# sourceMappingURL=PageNotFound-C1oSsMG-.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageNotFound-BD3zX3cd.js","sources":["../src/components/PageNotFound/PageNotFound.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react'\nimport { type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport { EmptyState, type EmptyStateSize } from '../EmptyState'\nimport { Button } from '../Button'\nimport type { IconName } from '../../icons/names'\nimport { useHomeTo } from './useHomeTo'\n\nexport interface PageNotFoundProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'color'> {\n /** Hero glyph — an `IconName`, any node, or `false` to hide it. Defaults to `SearchStatus`. */\n icon?: IconName | ReactNode | false\n /** Heading. Defaults to the localized `notFound.title`. */\n title?: ReactNode\n /** Muted description. Defaults to the localized `notFound.description`. */\n description?: ReactNode\n /** Action button label. Defaults to the localized `notFound.action`. */\n actionLabel?: ReactNode\n /** Where the action navigates. Defaults to the first allowed menu page (RBAC-aware), else `/`. */\n to?: string\n /** Show the \"back home\" action button. Defaults to `true` (hidden anyway when there's no router). */\n showAction?: boolean\n /** Faded-grid hero backdrop — passed to `EmptyState`. Defaults to `true` (its default). */\n pattern?: boolean\n /** Size — passed to `EmptyState`. Defaults to `md`. */\n size?: EmptyStateSize\n /*\n * The router's `NotFoundRouteProps`, declared so `defaultNotFoundComponent: PageNotFound` type-checks (an\n * all-optional props type that shares no field with the router's props fails TypeScript's weak-type check —\n * `data` / `isNotFound` alone satisfy it), and destructured away so they never reach the DOM.\n * `routeId` is `unknown` ON PURPOSE: the router types it `RouteIds<RegisteredRouter['routeTree']>`, and any\n * narrower type here (1.0.36 had `string`) makes the assignability check resolve that — i.e. `typeof router`\n * through the app's `Register` block — while `createRouter` is still inferring `router`: a cycle (TS7022 /\n * TS2502). `unknown` accepts it without looking. Guarded by `routerDefaults.registered.test-d.ts`.\n */\n /** Passed by TanStack Router when used as `defaultNotFoundComponent`; ignored. */\n data?: unknown\n /** Passed by TanStack Router when used as `defaultNotFoundComponent`; ignored. */\n isNotFound?: boolean\n /** Passed by TanStack Router when used as `defaultNotFoundComponent`; ignored (`unknown` — see above). */\n routeId?: unknown\n}\n\n/**\n * The shared **404** page. Drop it straight into TanStack Router as the\n * `defaultNotFoundComponent` — zero props needed: the title/description/action strings come from the\n * built-in i18n (`useT`), so they translate with the panel language, and the action navigates to the\n * **first allowed menu page** (the same RBAC-aware target as `FirstRouteRedirect`), falling back to\n * `/`. Built on `EmptyState` (hero glyph + title + description + action, `pattern` on by default), so\n * it renders inside the `RootLayout` content area with the shell/sidebar intact. Lenient: with no\n * router context the `EmptyState` still renders, just without the action button. Token-only styling.\n *\n * @example\n * const router = createRouter({\n * routeTree,\n * defaultNotFoundComponent: PageNotFound,\n * defaultErrorComponent: PageError,\n * })\n */\nexport const PageNotFound = forwardRef<HTMLDivElement, PageNotFoundProps>(function PageNotFound(\n {\n icon = 'SearchStatus',\n title,\n description,\n actionLabel,\n to,\n showAction = true,\n // the router's props — kept off the DOM\n data: _data,\n isNotFound: _isNotFound,\n routeId: _routeId,\n ...props\n },\n ref,\n) {\n const t = useT()\n // the first allowed menu page (RBAC-aware, `/` fallback); router is undefined outside a <RouterProvider>\n const { router, homeTo: resolvedTo } = useHomeTo(to)\n\n const canNavigate = !!router && resolvedTo != null\n const action =\n showAction && canNavigate ? (\n <Button size=\"sm\" onClick={() => router.navigate({ to: resolvedTo as LinkProps['to'] })}>\n {actionLabel ?? t('notFound.action')}\n </Button>\n ) : undefined\n\n return (\n <EmptyState\n ref={ref}\n icon={icon}\n title={title ?? t('notFound.title')}\n description={description ?? t('notFound.description')}\n action={action}\n {...props}\n />\n )\n})\n"],"names":["PageNotFound","forwardRef","icon","title","description","actionLabel","to","showAction","_data","_isNotFound","_routeId","props","ref","t","useT","router","resolvedTo","useHomeTo","canNavigate","action","jsx","Button","EmptyState"],"mappings":";;;;;;AA0DO,MAAMA,IAAeC,EAA8C,SACxE;AAAA,EACE,MAAAC,IAAO;AAAA,EACP,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,IAAAC;AAAA,EACA,YAAAC,IAAa;AAAA;AAAA,EAEb,MAAMC;AAAA,EACN,YAAYC;AAAA,EACZ,SAASC;AAAA,EACT,GAAGC;AACL,GACAC,GACA;AACA,QAAMC,IAAIC,EAAA,GAEJ,EAAE,QAAAC,GAAQ,QAAQC,EAAA,IAAeC,EAAUX,CAAE,GAE7CY,IAAc,CAAC,CAACH,KAAUC,KAAc,MACxCG,IACJZ,KAAcW,IACZ,gBAAAE,EAACC,KAAO,MAAK,MAAK,SAAS,MAAMN,EAAO,SAAS,EAAE,IAAIC,GAA+B,GACnF,eAAeH,EAAE,iBAAiB,GACrC,IACE;AAEN,SACE,gBAAAO;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,KAAAV;AAAA,MACA,MAAAV;AAAA,MACA,OAAOC,KAASU,EAAE,gBAAgB;AAAA,MAClC,aAAaT,KAAeS,EAAE,sBAAsB;AAAA,MACpD,QAAAM;AAAA,MACC,GAAGR;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;"}
1
+ {"version":3,"file":"PageNotFound-C1oSsMG-.js","sources":["../src/components/PageNotFound/PageNotFound.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react'\nimport { type LinkProps } from '@tanstack/react-router'\nimport { useT } from '../../theme'\nimport { EmptyState, type EmptyStateSize } from '../EmptyState'\nimport { Button } from '../Button'\nimport type { IconName } from '../../icons/names'\nimport { useHomeTo } from './useHomeTo'\n\nexport interface PageNotFoundProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'color'> {\n /** Hero glyph — an `IconName`, any node, or `false` to hide it. Defaults to `SearchStatus`. */\n icon?: IconName | ReactNode | false\n /** Heading. Defaults to the localized `notFound.title`. */\n title?: ReactNode\n /** Muted description. Defaults to the localized `notFound.description`. */\n description?: ReactNode\n /** Action button label. Defaults to the localized `notFound.action`. */\n actionLabel?: ReactNode\n /** Where the action navigates. Defaults to the first allowed menu page (RBAC-aware), else `/`. */\n to?: string\n /** Show the \"back home\" action button. Defaults to `true` (hidden anyway when there's no router). */\n showAction?: boolean\n /** Faded-grid hero backdrop — passed to `EmptyState`. Defaults to `true` (its default). */\n pattern?: boolean\n /** Size — passed to `EmptyState`. Defaults to `md`. */\n size?: EmptyStateSize\n /*\n * The router's `NotFoundRouteProps`, declared so `defaultNotFoundComponent: PageNotFound` type-checks (an\n * all-optional props type that shares no field with the router's props fails TypeScript's weak-type check —\n * `data` / `isNotFound` alone satisfy it), and destructured away so they never reach the DOM.\n * `routeId` is `unknown` ON PURPOSE: the router types it `RouteIds<RegisteredRouter['routeTree']>`, and any\n * narrower type here (1.0.36 had `string`) makes the assignability check resolve that — i.e. `typeof router`\n * through the app's `Register` block — while `createRouter` is still inferring `router`: a cycle (TS7022 /\n * TS2502). `unknown` accepts it without looking. Guarded by `routerDefaults.registered.test-d.ts`.\n */\n /** Passed by TanStack Router when used as `defaultNotFoundComponent`; ignored. */\n data?: unknown\n /** Passed by TanStack Router when used as `defaultNotFoundComponent`; ignored. */\n isNotFound?: boolean\n /** Passed by TanStack Router when used as `defaultNotFoundComponent`; ignored (`unknown` — see above). */\n routeId?: unknown\n}\n\n/**\n * The shared **404** page. Drop it straight into TanStack Router as the\n * `defaultNotFoundComponent` — zero props needed: the title/description/action strings come from the\n * built-in i18n (`useT`), so they translate with the panel language, and the action navigates to the\n * **first allowed menu page** (the same RBAC-aware target as `FirstRouteRedirect`), falling back to\n * `/`. Built on `EmptyState` (hero glyph + title + description + action, `pattern` on by default), so\n * it renders inside the `RootLayout` content area with the shell/sidebar intact. Lenient: with no\n * router context the `EmptyState` still renders, just without the action button. Token-only styling.\n *\n * @example\n * const router = createRouter({\n * routeTree,\n * defaultNotFoundComponent: PageNotFound,\n * defaultErrorComponent: PageError,\n * })\n */\nexport const PageNotFound = forwardRef<HTMLDivElement, PageNotFoundProps>(function PageNotFound(\n {\n icon = 'SearchStatus',\n title,\n description,\n actionLabel,\n to,\n showAction = true,\n // the router's props — kept off the DOM\n data: _data,\n isNotFound: _isNotFound,\n routeId: _routeId,\n ...props\n },\n ref,\n) {\n const t = useT()\n // the first allowed menu page (RBAC-aware, `/` fallback); router is undefined outside a <RouterProvider>\n const { router, homeTo: resolvedTo } = useHomeTo(to)\n\n const canNavigate = !!router && resolvedTo != null\n const action =\n showAction && canNavigate ? (\n <Button size=\"sm\" onClick={() => router.navigate({ to: resolvedTo as LinkProps['to'] })}>\n {actionLabel ?? t('notFound.action')}\n </Button>\n ) : undefined\n\n return (\n <EmptyState\n ref={ref}\n icon={icon}\n title={title ?? t('notFound.title')}\n description={description ?? t('notFound.description')}\n action={action}\n {...props}\n />\n )\n})\n"],"names":["PageNotFound","forwardRef","icon","title","description","actionLabel","to","showAction","_data","_isNotFound","_routeId","props","ref","t","useT","router","resolvedTo","useHomeTo","canNavigate","action","jsx","Button","EmptyState"],"mappings":";;;;;;AA0DO,MAAMA,IAAeC,EAA8C,SACxE;AAAA,EACE,MAAAC,IAAO;AAAA,EACP,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,IAAAC;AAAA,EACA,YAAAC,IAAa;AAAA;AAAA,EAEb,MAAMC;AAAA,EACN,YAAYC;AAAA,EACZ,SAASC;AAAA,EACT,GAAGC;AACL,GACAC,GACA;AACA,QAAMC,IAAIC,EAAA,GAEJ,EAAE,QAAAC,GAAQ,QAAQC,EAAA,IAAeC,EAAUX,CAAE,GAE7CY,IAAc,CAAC,CAACH,KAAUC,KAAc,MACxCG,IACJZ,KAAcW,IACZ,gBAAAE,EAACC,KAAO,MAAK,MAAK,SAAS,MAAMN,EAAO,SAAS,EAAE,IAAIC,GAA+B,GACnF,eAAeH,EAAE,iBAAiB,GACrC,IACE;AAEN,SACE,gBAAAO;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,KAAAV;AAAA,MACA,MAAAV;AAAA,MACA,OAAOC,KAASU,EAAE,gBAAgB;AAAA,MAClC,aAAaT,KAAeS,EAAE,sBAAsB;AAAA,MACpD,QAAAM;AAAA,MACC,GAAGR;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;"}