@tinyrack/issuary-server 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. package/dist/entities/terms-content.entity.d.ts +9 -0
  2. package/dist/entities/terms-content.entity.d.ts.map +1 -1
  3. package/dist/entities/terms.entity.d.ts +9 -0
  4. package/dist/entities/terms.entity.d.ts.map +1 -1
  5. package/dist/entities/terms.entity.js +4 -0
  6. package/dist/entities/terms.entity.js.map +1 -1
  7. package/dist/entities/user-terms-consent.entity.d.ts +9 -0
  8. package/dist/entities/user-terms-consent.entity.d.ts.map +1 -1
  9. package/dist/entrypoints/app.d.ts +598 -3
  10. package/dist/entrypoints/app.d.ts.map +1 -1
  11. package/dist/entrypoints/database/postgres/compiled-functions.d.ts +19 -16
  12. package/dist/entrypoints/database/postgres/compiled-functions.d.ts.map +1 -1
  13. package/dist/entrypoints/database/postgres/compiled-functions.js +133 -76
  14. package/dist/entrypoints/database/postgres/compiled-functions.js.map +1 -1
  15. package/dist/entrypoints/database/sqlite/compiled-functions.d.ts +19 -16
  16. package/dist/entrypoints/database/sqlite/compiled-functions.d.ts.map +1 -1
  17. package/dist/entrypoints/database/sqlite/compiled-functions.js +133 -76
  18. package/dist/entrypoints/database/sqlite/compiled-functions.js.map +1 -1
  19. package/dist/lib/config/branding.d.ts +5 -0
  20. package/dist/lib/config/branding.d.ts.map +1 -1
  21. package/dist/lib/config/branding.js +23 -1
  22. package/dist/lib/config/branding.js.map +1 -1
  23. package/dist/lib/config/resolved.d.ts +3 -0
  24. package/dist/lib/config/resolved.d.ts.map +1 -1
  25. package/dist/lib/interpolate-html.d.ts +3 -3
  26. package/dist/lib/interpolate-html.js +3 -3
  27. package/dist/lib/interpolate-html.js.map +1 -1
  28. package/dist/migrations/postgres/Migration20260827090000_archive_terms.d.ts +6 -0
  29. package/dist/migrations/postgres/Migration20260827090000_archive_terms.d.ts.map +1 -0
  30. package/dist/migrations/postgres/Migration20260827090000_archive_terms.js +12 -0
  31. package/dist/migrations/postgres/Migration20260827090000_archive_terms.js.map +1 -0
  32. package/dist/migrations/postgres/index.d.ts.map +1 -1
  33. package/dist/migrations/postgres/index.js +2 -0
  34. package/dist/migrations/postgres/index.js.map +1 -1
  35. package/dist/migrations/sqlite/Migration20260827090000_archive_terms.d.ts +6 -0
  36. package/dist/migrations/sqlite/Migration20260827090000_archive_terms.d.ts.map +1 -0
  37. package/dist/migrations/sqlite/Migration20260827090000_archive_terms.js +12 -0
  38. package/dist/migrations/sqlite/Migration20260827090000_archive_terms.js.map +1 -0
  39. package/dist/migrations/sqlite/index.d.ts.map +1 -1
  40. package/dist/migrations/sqlite/index.js +2 -0
  41. package/dist/migrations/sqlite/index.js.map +1 -1
  42. package/dist/repositories/terms.repository.d.ts.map +1 -1
  43. package/dist/repositories/terms.repository.js +1 -1
  44. package/dist/repositories/terms.repository.js.map +1 -1
  45. package/dist/routes/api/admin/console/index.d.ts +523 -0
  46. package/dist/routes/api/admin/console/index.d.ts.map +1 -0
  47. package/dist/routes/api/admin/console/index.js +212 -0
  48. package/dist/routes/api/admin/console/index.js.map +1 -0
  49. package/dist/routes/api/admin/index.d.ts +584 -0
  50. package/dist/routes/api/admin/index.d.ts.map +1 -1
  51. package/dist/routes/api/admin/index.js +3 -1
  52. package/dist/routes/api/admin/index.js.map +1 -1
  53. package/dist/routes/api/admin/users/index.d.ts +64 -0
  54. package/dist/routes/api/admin/users/index.d.ts.map +1 -1
  55. package/dist/routes/api/admin/users/index.js +47 -0
  56. package/dist/routes/api/admin/users/index.js.map +1 -1
  57. package/dist/routes/api/config/get.d.ts +10 -3
  58. package/dist/routes/api/config/get.d.ts.map +1 -1
  59. package/dist/routes/api/config/get.js +3 -0
  60. package/dist/routes/api/config/get.js.map +1 -1
  61. package/dist/routes/api/config/index.d.ts +10 -3
  62. package/dist/routes/api/config/index.d.ts.map +1 -1
  63. package/dist/routes/api/index.d.ts +594 -3
  64. package/dist/routes/api/index.d.ts.map +1 -1
  65. package/dist/routes/index.d.ts +594 -3
  66. package/dist/routes/index.d.ts.map +1 -1
  67. package/dist/schemas/response.d.ts +4 -1
  68. package/dist/schemas/response.d.ts.map +1 -1
  69. package/dist/schemas/response.js +11 -2
  70. package/dist/schemas/response.js.map +1 -1
  71. package/dist/services/admin-console.service.d.ts +407 -0
  72. package/dist/services/admin-console.service.d.ts.map +1 -0
  73. package/dist/services/admin-console.service.js +377 -0
  74. package/dist/services/admin-console.service.js.map +1 -0
  75. package/dist/services/container.d.ts +5 -0
  76. package/dist/services/container.d.ts.map +1 -1
  77. package/dist/services/container.js +3 -0
  78. package/dist/services/container.js.map +1 -1
  79. package/dist/services/user.service.d.ts +21 -0
  80. package/dist/services/user.service.d.ts.map +1 -1
  81. package/dist/services/user.service.js +65 -1
  82. package/dist/services/user.service.js.map +1 -1
  83. package/package.json +1 -1
  84. package/public/assets/2fa-BowFczF7.js +2 -0
  85. package/public/assets/2fa-BowFczF7.js.map +1 -0
  86. package/public/assets/2fa-C_pA-n2i.js +2 -0
  87. package/public/assets/{2fa-DFTcWEMb.js.map → 2fa-C_pA-n2i.js.map} +1 -1
  88. package/public/assets/2fa-Cpfhakvn.js +2 -0
  89. package/public/assets/{2fa-huNZDYU9.js.map → 2fa-Cpfhakvn.js.map} +1 -1
  90. package/public/assets/2fa-o1a13VHx.js +2 -0
  91. package/public/assets/2fa-o1a13VHx.js.map +1 -0
  92. package/public/assets/FieldControl-ShLuCjvG.js +2 -0
  93. package/public/assets/FieldControl-ShLuCjvG.js.map +1 -0
  94. package/public/assets/Separator-C6MmGAmP.js +2 -0
  95. package/public/assets/Separator-C6MmGAmP.js.map +1 -0
  96. package/public/assets/admin-_jFLs8Ve.js +2 -0
  97. package/public/assets/admin-_jFLs8Ve.js.map +1 -0
  98. package/public/assets/admin-shell-B91U4-Ro.js +2 -0
  99. package/public/assets/admin-shell-B91U4-Ro.js.map +1 -0
  100. package/public/assets/alert-D3aaK-_3.js +2 -0
  101. package/public/assets/alert-D3aaK-_3.js.map +1 -0
  102. package/public/assets/alert-kRxM1xsM.js +2 -0
  103. package/public/assets/alert-kRxM1xsM.js.map +1 -0
  104. package/public/assets/auth-choice-row-h4heOMHs.js +2 -0
  105. package/public/assets/auth-choice-row-h4heOMHs.js.map +1 -0
  106. package/public/assets/auth-field-BpJ4AHtU.js +2 -0
  107. package/public/assets/{auth-field-CWyXGKoC.js.map → auth-field-BpJ4AHtU.js.map} +1 -1
  108. package/public/assets/auth-footer-Du6S-oDG.js +2 -0
  109. package/public/assets/auth-footer-Du6S-oDG.js.map +1 -0
  110. package/public/assets/auth-layout-BdRRr0vT.js +2 -0
  111. package/public/assets/auth-layout-BdRRr0vT.js.map +1 -0
  112. package/public/assets/auth-page-header-ChaCNNrn.js +2 -0
  113. package/public/assets/{auth-page-header-DgGAaIiP.js.map → auth-page-header-ChaCNNrn.js.map} +1 -1
  114. package/public/assets/authorization-context-banner-zVxGX5e8.js +2 -0
  115. package/public/assets/{authorization-context-banner-DznMDPOX.js.map → authorization-context-banner-zVxGX5e8.js.map} +1 -1
  116. package/public/assets/avatar-BxTPQIDp.js +2 -0
  117. package/public/assets/{avatar-D-FRGa1m.js.map → avatar-BxTPQIDp.js.map} +1 -1
  118. package/public/assets/badge-B8D0Q2qq.js +2 -0
  119. package/public/assets/{badge-CsOfUji0.js.map → badge-B8D0Q2qq.js.map} +1 -1
  120. package/public/assets/checkbox-DTPGfvmq.js +2 -0
  121. package/public/assets/{checkbox-C90dDDza.js.map → checkbox-DTPGfvmq.js.map} +1 -1
  122. package/public/assets/{circle-check-6QTLhwM_.js → circle-check-Cnzuu7xR.js} +2 -2
  123. package/public/assets/{circle-check-6QTLhwM_.js.map → circle-check-Cnzuu7xR.js.map} +1 -1
  124. package/public/assets/clients-DLqy7K3N.js +5 -0
  125. package/public/assets/clients-DLqy7K3N.js.map +1 -0
  126. package/public/assets/config-C18-l7z7.js +2 -0
  127. package/public/assets/config-C18-l7z7.js.map +1 -0
  128. package/public/assets/{consent-RtCi_85E.js → consent-BWniDzI3.js} +2 -2
  129. package/public/assets/{consent-RtCi_85E.js.map → consent-BWniDzI3.js.map} +1 -1
  130. package/public/assets/consent-r_tX8DTb.js +2 -0
  131. package/public/assets/{consent-B9sQEyO8.js.map → consent-r_tX8DTb.js.map} +1 -1
  132. package/public/assets/{createLucideIcon-BPpAIXR_.js → createLucideIcon-D-yizrWN.js} +2 -2
  133. package/public/assets/{createLucideIcon-BPpAIXR_.js.map → createLucideIcon-D-yizrWN.js.map} +1 -1
  134. package/public/assets/design-system-rich-text-B3NzIRoJ.js +2 -0
  135. package/public/assets/design-system-rich-text-B3NzIRoJ.js.map +1 -0
  136. package/public/assets/email-Bx9JlWp3.js +2 -0
  137. package/public/assets/email-Bx9JlWp3.js.map +1 -0
  138. package/public/assets/email-Cpfhakvn.js +2 -0
  139. package/public/assets/email-Cpfhakvn.js.map +1 -0
  140. package/public/assets/error-DDY8m_Px.js +2 -0
  141. package/public/assets/error-DDY8m_Px.js.map +1 -0
  142. package/public/assets/field-CsrUbl__.js +3 -0
  143. package/public/assets/field-CsrUbl__.js.map +1 -0
  144. package/public/assets/{fingerprint-pattern-DP62Vk8x.js → fingerprint-pattern-BwUoN1_w.js} +2 -2
  145. package/public/assets/{fingerprint-pattern-DP62Vk8x.js.map → fingerprint-pattern-BwUoN1_w.js.map} +1 -1
  146. package/public/assets/forgot-Cpfhakvn.js +2 -0
  147. package/public/assets/forgot-Cpfhakvn.js.map +1 -0
  148. package/public/assets/forgot-u52JMu6e.js +2 -0
  149. package/public/assets/forgot-u52JMu6e.js.map +1 -0
  150. package/public/assets/form-sJw-V9wb.js +2 -0
  151. package/public/assets/form-sJw-V9wb.js.map +1 -0
  152. package/public/assets/index-8mX6CKcW.css +2 -0
  153. package/public/assets/index-lTEyHSus.js +11 -0
  154. package/public/assets/index-lTEyHSus.js.map +1 -0
  155. package/public/assets/initial-avatar-WMjxW3Zz.js +2 -0
  156. package/public/assets/initial-avatar-WMjxW3Zz.js.map +1 -0
  157. package/public/assets/input-QvBxPgy5.js +2 -0
  158. package/public/assets/{input-CxVeC8Pn.js.map → input-QvBxPgy5.js.map} +1 -1
  159. package/public/assets/{key-round-CdvHb8vT.js → key-round-BxWppK6h.js} +2 -2
  160. package/public/assets/{key-round-CdvHb8vT.js.map → key-round-BxWppK6h.js.map} +1 -1
  161. package/public/assets/labeled-separator-DdkyYDWH.js +2 -0
  162. package/public/assets/labeled-separator-DdkyYDWH.js.map +1 -0
  163. package/public/assets/link-BHmn75Zo.js +2 -0
  164. package/public/assets/{link-C-WdTj3F.js.map → link-BHmn75Zo.js.map} +1 -1
  165. package/public/assets/{lock-7NRyvXBS.js → lock-8wpR2C78.js} +2 -2
  166. package/public/assets/{lock-7NRyvXBS.js.map → lock-8wpR2C78.js.map} +1 -1
  167. package/public/assets/login-Cpfhakvn.js +2 -0
  168. package/public/assets/login-Cpfhakvn.js.map +1 -0
  169. package/public/assets/login-DRcHjJ2-.js +2 -0
  170. package/public/assets/login-DRcHjJ2-.js.map +1 -0
  171. package/public/assets/logout-Dphj1d_0.js +2 -0
  172. package/public/assets/logout-Dphj1d_0.js.map +1 -0
  173. package/public/assets/{mail-D0B_1Dzd.js → mail-DVP_XMUi.js} +2 -2
  174. package/public/assets/{mail-D0B_1Dzd.js.map → mail-DVP_XMUi.js.map} +1 -1
  175. package/public/assets/modal-JuaLVSyx.js +2 -0
  176. package/public/assets/modal-JuaLVSyx.js.map +1 -0
  177. package/public/assets/mutationOptions-Cv_vJkJn.js +2 -0
  178. package/public/assets/{mutationOptions-DyYFUbyn.js.map → mutationOptions-Cv_vJkJn.js.map} +1 -1
  179. package/public/assets/passkey-CObBlfKK.js +2 -0
  180. package/public/assets/passkey-CObBlfKK.js.map +1 -0
  181. package/public/assets/{passkey-J1qnYp9A.js → passkey-CWTjw19S.js} +2 -2
  182. package/public/assets/{passkey-J1qnYp9A.js.map → passkey-CWTjw19S.js.map} +1 -1
  183. package/public/assets/passkey-CavITajY.js +2 -0
  184. package/public/assets/passkey-CavITajY.js.map +1 -0
  185. package/public/assets/passkey-Cpfhakvn.js +2 -0
  186. package/public/assets/passkey-Cpfhakvn.js.map +1 -0
  187. package/public/assets/{passkey-error-ZqqPQUta.js → passkey-error-CZ26Ss-I.js} +2 -2
  188. package/public/assets/{passkey-error-ZqqPQUta.js.map → passkey-error-CZ26Ss-I.js.map} +1 -1
  189. package/public/assets/password-Cpfhakvn.js +2 -0
  190. package/public/assets/password-Cpfhakvn.js.map +1 -0
  191. package/public/assets/password-Dk8PwtZN.js +2 -0
  192. package/public/assets/password-Dk8PwtZN.js.map +1 -0
  193. package/public/assets/password-reset-BcFpGOop.js +2 -0
  194. package/public/assets/{password-reset-sU5KkBKi.js.map → password-reset-BcFpGOop.js.map} +1 -1
  195. package/public/assets/password-strength-Bgvy7kz6.js +2 -0
  196. package/public/assets/{password-strength-BIPcWiM_.js.map → password-strength-Bgvy7kz6.js.map} +1 -1
  197. package/public/assets/pin-input-DhsRO4Ei.js +2 -0
  198. package/public/assets/{pin-input-CITrr-Yc.js.map → pin-input-DhsRO4Ei.js.map} +1 -1
  199. package/public/assets/profile-PjXEnzA-.js +2 -0
  200. package/public/assets/profile-PjXEnzA-.js.map +1 -0
  201. package/public/assets/profile-k66ruDWl.js +2 -0
  202. package/public/assets/{profile-BHPL9Px_.js.map → profile-k66ruDWl.js.map} +1 -1
  203. package/public/assets/provider-mark-CeYazOfu.js +2 -0
  204. package/public/assets/provider-mark-CeYazOfu.js.map +1 -0
  205. package/public/assets/recovery-hdRyezmb.js +2 -0
  206. package/public/assets/recovery-hdRyezmb.js.map +1 -0
  207. package/public/assets/register-Cpfhakvn.js +2 -0
  208. package/public/assets/register-Cpfhakvn.js.map +1 -0
  209. package/public/assets/register-DMgKT_fm.js +2 -0
  210. package/public/assets/register-DMgKT_fm.js.map +1 -0
  211. package/public/assets/reset-Cpfhakvn.js +2 -0
  212. package/public/assets/reset-Cpfhakvn.js.map +1 -0
  213. package/public/assets/reset-DBu3wYpE.js +2 -0
  214. package/public/assets/reset-DBu3wYpE.js.map +1 -0
  215. package/public/assets/select-5LheSsRl.js +2 -0
  216. package/public/assets/select-5LheSsRl.js.map +1 -0
  217. package/public/assets/select-Cpfhakvn.js +2 -0
  218. package/public/assets/{select-huNZDYU9.js.map → select-Cpfhakvn.js.map} +1 -1
  219. package/public/assets/separator-CMGc2Y1q.js +2 -0
  220. package/public/assets/separator-CMGc2Y1q.js.map +1 -0
  221. package/public/assets/settings-BVe4k3kJ.js +2 -0
  222. package/public/assets/settings-BVe4k3kJ.js.map +1 -0
  223. package/public/assets/shell-header-bar-CdOEWmCT.js +2 -0
  224. package/public/assets/shell-header-bar-CdOEWmCT.js.map +1 -0
  225. package/public/assets/{shield-check-D_p8H0ni.js → shield-check-DpYF8yeI.js} +2 -2
  226. package/public/assets/{shield-check-D_p8H0ni.js.map → shield-check-DpYF8yeI.js.map} +1 -1
  227. package/public/assets/standard-schema-C50nwAaQ.js +2 -0
  228. package/public/assets/{standard-schema-e8gtSzGE.js.map → standard-schema-C50nwAaQ.js.map} +1 -1
  229. package/public/assets/system-BoUqxc5h.js +2 -0
  230. package/public/assets/system-BoUqxc5h.js.map +1 -0
  231. package/public/assets/table-Dl89o43x.js +2 -0
  232. package/public/assets/table-Dl89o43x.js.map +1 -0
  233. package/public/assets/terms-B2wWfx1d.js +2 -0
  234. package/public/assets/terms-B2wWfx1d.js.map +1 -0
  235. package/public/assets/terms-COr3cDw5.js +2 -0
  236. package/public/assets/terms-COr3cDw5.js.map +1 -0
  237. package/public/assets/terms-checkbox-list-C9TkDC8Y.js +2 -0
  238. package/public/assets/terms-checkbox-list-C9TkDC8Y.js.map +1 -0
  239. package/public/assets/terms-k66ruDWl.js +2 -0
  240. package/public/assets/terms-k66ruDWl.js.map +1 -0
  241. package/public/assets/totp-BJycMMTC.js +2 -0
  242. package/public/assets/totp-BJycMMTC.js.map +1 -0
  243. package/public/assets/{totp-BNZ904Zm.js → totp-BhElob6P.js} +2 -2
  244. package/public/assets/{totp-BNZ904Zm.js.map → totp-BhElob6P.js.map} +1 -1
  245. package/public/assets/totp-C1ba10Is.js +2 -0
  246. package/public/assets/totp-C1ba10Is.js.map +1 -0
  247. package/public/assets/{trash-2-DZdKBLvC.js → trash-2-B3NVE8pR.js} +2 -2
  248. package/public/assets/{trash-2-DZdKBLvC.js.map → trash-2-B3NVE8pR.js.map} +1 -1
  249. package/public/assets/{triangle-alert-CqNn0kPs.js → triangle-alert-DATO9o3k.js} +2 -2
  250. package/public/assets/{triangle-alert-CqNn0kPs.js.map → triangle-alert-DATO9o3k.js.map} +1 -1
  251. package/public/assets/use-admin-selection-D2b7jnym.js +2 -0
  252. package/public/assets/use-admin-selection-D2b7jnym.js.map +1 -0
  253. package/public/assets/use-totp-setup-KOVNS2DC.js +3 -0
  254. package/public/assets/use-totp-setup-KOVNS2DC.js.map +1 -0
  255. package/public/assets/useAriaLabelledBy-CF3crxLc.js +2 -0
  256. package/public/assets/{useAriaLabelledBy-IIwdHUss.js.map → useAriaLabelledBy-CF3crxLc.js.map} +1 -1
  257. package/public/assets/useMutation-DqIIIiBW.js +2 -0
  258. package/public/assets/{useMutation-BWZ0G4Td.js.map → useMutation-DqIIIiBW.js.map} +1 -1
  259. package/public/assets/useQuery-CLr9TaKA.js +2 -0
  260. package/public/assets/{useQuery-Ccv_nzQl.js.map → useQuery-CLr9TaKA.js.map} +1 -1
  261. package/public/assets/users-BQQQm353.js +2 -0
  262. package/public/assets/users-BQQQm353.js.map +1 -0
  263. package/public/assets/{zod-C87S6Tec.js → zod-Dszyrytb.js} +2 -2
  264. package/public/assets/{zod-C87S6Tec.js.map → zod-Dszyrytb.js.map} +1 -1
  265. package/public/index.html +6 -6
  266. package/public/issuary-app-icon-512.png +0 -0
  267. package/public/issuary-app-icon.svg +8 -0
  268. package/public/assets/2fa-C9wUlSBS.js +0 -2
  269. package/public/assets/2fa-C9wUlSBS.js.map +0 -1
  270. package/public/assets/2fa-DFTcWEMb.js +0 -2
  271. package/public/assets/2fa-TtshNxXv.js +0 -2
  272. package/public/assets/2fa-TtshNxXv.js.map +0 -1
  273. package/public/assets/2fa-huNZDYU9.js +0 -2
  274. package/public/assets/DialogHandle-DICBMcjK.js +0 -2
  275. package/public/assets/DialogHandle-DICBMcjK.js.map +0 -1
  276. package/public/assets/FieldItemContext-BeNfhOsU.js +0 -2
  277. package/public/assets/FieldItemContext-BeNfhOsU.js.map +0 -1
  278. package/public/assets/admin-CFZaO1bM.js +0 -2
  279. package/public/assets/admin-CFZaO1bM.js.map +0 -1
  280. package/public/assets/admin-users-BK_BN8jm.js +0 -2
  281. package/public/assets/admin-users-BK_BN8jm.js.map +0 -1
  282. package/public/assets/alert-leqyvHOp.js +0 -2
  283. package/public/assets/alert-leqyvHOp.js.map +0 -1
  284. package/public/assets/auth-choice-row-CXuyJgkR.js +0 -2
  285. package/public/assets/auth-choice-row-CXuyJgkR.js.map +0 -1
  286. package/public/assets/auth-field-CWyXGKoC.js +0 -2
  287. package/public/assets/auth-footer-Cz5ivsDc.js +0 -2
  288. package/public/assets/auth-footer-Cz5ivsDc.js.map +0 -1
  289. package/public/assets/auth-layout-CiNn2-Nb.js +0 -2
  290. package/public/assets/auth-layout-CiNn2-Nb.js.map +0 -1
  291. package/public/assets/auth-page-header-DgGAaIiP.js +0 -2
  292. package/public/assets/authorization-context-banner-DznMDPOX.js +0 -2
  293. package/public/assets/avatar-D-FRGa1m.js +0 -2
  294. package/public/assets/badge-CsOfUji0.js +0 -2
  295. package/public/assets/checkbox-C90dDDza.js +0 -2
  296. package/public/assets/chevron-right-CN0jUyV0.js +0 -2
  297. package/public/assets/chevron-right-CN0jUyV0.js.map +0 -1
  298. package/public/assets/config-DTQCUlfZ.js +0 -2
  299. package/public/assets/config-DTQCUlfZ.js.map +0 -1
  300. package/public/assets/consent-B9sQEyO8.js +0 -2
  301. package/public/assets/email-8RKQzeig.js +0 -2
  302. package/public/assets/email-8RKQzeig.js.map +0 -1
  303. package/public/assets/email-huNZDYU9.js +0 -2
  304. package/public/assets/email-huNZDYU9.js.map +0 -1
  305. package/public/assets/error-BYe3gUMO.js +0 -2
  306. package/public/assets/error-BYe3gUMO.js.map +0 -1
  307. package/public/assets/field-BMT214_m.js +0 -3
  308. package/public/assets/field-BMT214_m.js.map +0 -1
  309. package/public/assets/forgot-BenoOUxC.js +0 -2
  310. package/public/assets/forgot-BenoOUxC.js.map +0 -1
  311. package/public/assets/forgot-huNZDYU9.js +0 -2
  312. package/public/assets/forgot-huNZDYU9.js.map +0 -1
  313. package/public/assets/index-CKpnrw9M.js +0 -11
  314. package/public/assets/index-CKpnrw9M.js.map +0 -1
  315. package/public/assets/index-Ct9o0oCZ.css +0 -2
  316. package/public/assets/initial-avatar-E5DK9Igm.js +0 -2
  317. package/public/assets/initial-avatar-E5DK9Igm.js.map +0 -1
  318. package/public/assets/input-CxVeC8Pn.js +0 -2
  319. package/public/assets/labeled-separator-CV7nb0XW.js +0 -2
  320. package/public/assets/labeled-separator-CV7nb0XW.js.map +0 -1
  321. package/public/assets/link-C-WdTj3F.js +0 -2
  322. package/public/assets/login-1YuiZD30.js +0 -2
  323. package/public/assets/login-1YuiZD30.js.map +0 -1
  324. package/public/assets/login-huNZDYU9.js +0 -2
  325. package/public/assets/login-huNZDYU9.js.map +0 -1
  326. package/public/assets/logout-B5T52P8u.js +0 -2
  327. package/public/assets/logout-B5T52P8u.js.map +0 -1
  328. package/public/assets/modal-tByFpy18.js +0 -2
  329. package/public/assets/modal-tByFpy18.js.map +0 -1
  330. package/public/assets/mutationOptions-DyYFUbyn.js +0 -2
  331. package/public/assets/passkey-CgAHaQ1p.js +0 -2
  332. package/public/assets/passkey-CgAHaQ1p.js.map +0 -1
  333. package/public/assets/passkey-huNZDYU9.js +0 -2
  334. package/public/assets/passkey-huNZDYU9.js.map +0 -1
  335. package/public/assets/passkey-v9Pzv-4A.js +0 -2
  336. package/public/assets/passkey-v9Pzv-4A.js.map +0 -1
  337. package/public/assets/password-Cuh9Hnjp.js +0 -2
  338. package/public/assets/password-Cuh9Hnjp.js.map +0 -1
  339. package/public/assets/password-huNZDYU9.js +0 -2
  340. package/public/assets/password-huNZDYU9.js.map +0 -1
  341. package/public/assets/password-reset-sU5KkBKi.js +0 -2
  342. package/public/assets/password-strength-BIPcWiM_.js +0 -2
  343. package/public/assets/pin-input-CITrr-Yc.js +0 -2
  344. package/public/assets/plus-DSBBSrgj.js +0 -2
  345. package/public/assets/plus-DSBBSrgj.js.map +0 -1
  346. package/public/assets/profile-BHPL9Px_.js +0 -2
  347. package/public/assets/profile-C8KaELVe.js +0 -2
  348. package/public/assets/profile-C8KaELVe.js.map +0 -1
  349. package/public/assets/provider-logos-u1YURWQr.js +0 -2
  350. package/public/assets/provider-logos-u1YURWQr.js.map +0 -1
  351. package/public/assets/recovery-CVROV9nj.js +0 -2
  352. package/public/assets/recovery-CVROV9nj.js.map +0 -1
  353. package/public/assets/register-cpxjX3qr.js +0 -2
  354. package/public/assets/register-cpxjX3qr.js.map +0 -1
  355. package/public/assets/register-huNZDYU9.js +0 -2
  356. package/public/assets/register-huNZDYU9.js.map +0 -1
  357. package/public/assets/reset-huNZDYU9.js +0 -2
  358. package/public/assets/reset-huNZDYU9.js.map +0 -1
  359. package/public/assets/reset-iNqYdsoa.js +0 -2
  360. package/public/assets/reset-iNqYdsoa.js.map +0 -1
  361. package/public/assets/select-DdjQtcLJ.js +0 -2
  362. package/public/assets/select-DdjQtcLJ.js.map +0 -1
  363. package/public/assets/select-huNZDYU9.js +0 -2
  364. package/public/assets/separator-B0Bvh1he.js +0 -2
  365. package/public/assets/separator-B0Bvh1he.js.map +0 -1
  366. package/public/assets/shell-header-bar-JcFhS7mb.js +0 -2
  367. package/public/assets/shell-header-bar-JcFhS7mb.js.map +0 -1
  368. package/public/assets/standard-schema-e8gtSzGE.js +0 -2
  369. package/public/assets/terms-BHPL9Px_.js +0 -2
  370. package/public/assets/terms-BHPL9Px_.js.map +0 -1
  371. package/public/assets/terms-BjwMWDFp.js +0 -2
  372. package/public/assets/terms-BjwMWDFp.js.map +0 -1
  373. package/public/assets/terms-checkbox-list-DNOq4Pb2.js +0 -2
  374. package/public/assets/terms-checkbox-list-DNOq4Pb2.js.map +0 -1
  375. package/public/assets/totp-D_EWG1h8.js +0 -2
  376. package/public/assets/totp-D_EWG1h8.js.map +0 -1
  377. package/public/assets/totp-DetFwOkk.js +0 -2
  378. package/public/assets/totp-DetFwOkk.js.map +0 -1
  379. package/public/assets/use-totp-setup-DtlgPUPJ.js +0 -3
  380. package/public/assets/use-totp-setup-DtlgPUPJ.js.map +0 -1
  381. package/public/assets/useAriaLabelledBy-IIwdHUss.js +0 -2
  382. package/public/assets/useMutation-BWZ0G4Td.js +0 -2
  383. package/public/assets/useQuery-Ccv_nzQl.js +0 -2
  384. package/public/assets/users-B1gvPM_x.js +0 -2
  385. package/public/assets/users-B1gvPM_x.js.map +0 -1
  386. package/public/vite.svg +0 -1
@@ -0,0 +1,2 @@
1
+ import{X as e,i as t,n}from"./createLucideIcon-D-yizrWN.js";import{t as r}from"./config-C18-l7z7.js";import{Dt as i}from"./shell-header-bar-CdOEWmCT.js";import{h as a,i as o,t as s}from"./admin-shell-B91U4-Ro.js";import{c}from"./index-lTEyHSus.js";import{t as l}from"./badge-B8D0Q2qq.js";import{t as u}from"./table-Dl89o43x.js";var d=e();function f(){let e=c.useRouteContext({select:e=>e.user});return e?.role===`admin`?(0,d.jsx)(p,{user:e}):(0,d.jsx)(a,{reason:`access-required`})}function p({user:e}){let{data:t}=i(r);return t.admin.enabled?(0,d.jsx)(m,{user:e}):(0,d.jsx)(a,{reason:`console-disabled`})}function m({user:e}){let{t:r}=t(),{data:a}=i(o);return(0,d.jsxs)(s,{current:`system`,title:r(`admin.system.title`),user:e,children:[(0,d.jsxs)(`div`,{className:`flex flex-col items-start justify-between gap-tinyrack-md bg-tinyrack-surface px-tinyrack-lg py-tinyrack-md sm:flex-row sm:items-center`,children:[(0,d.jsxs)(`div`,{children:[(0,d.jsx)(n,{as:`h1`,variant:`headingMd`,children:r(`admin.system.title`)}),(0,d.jsx)(n,{as:`p`,color:`muted`,variant:`bodySm`,children:r(`admin.system.readonly`)})]}),(0,d.jsxs)(`div`,{className:`flex shrink-0 gap-tinyrack-sm`,children:[(0,d.jsx)(l,{variant:`success`,children:r(`admin.statusValue.${a.health.database}`)}),(0,d.jsx)(l,{variant:a.health.email===`disabled`?`neutral`:`success`,children:r(`admin.statusValue.${a.health.email}`)})]})]}),(0,d.jsx)(`div`,{className:`grid gap-tinyrack-lg xl:grid-cols-2`,children:a.sections.map(e=>(0,d.jsxs)(`section`,{children:[(0,d.jsx)(`header`,{className:`bg-tinyrack-surface px-tinyrack-lg py-tinyrack-md`,children:(0,d.jsx)(n,{as:`h2`,variant:`headingSm`,children:r(`admin.system.section.${e.id}`)})}),(0,d.jsx)(u.Root,{density:`compact`,children:(0,d.jsx)(u.Body,{children:Object.entries(e.values).map(([e,t])=>(0,d.jsxs)(u.Row,{children:[(0,d.jsx)(u.Cell,{className:`text-tinyrack-text-muted`,children:r(`admin.system.key.${e}`)}),(0,d.jsx)(u.Cell,{className:`text-right`,children:(0,d.jsx)(h,{value:t})})]},e))})})]},e.id))})]})}function h({value:e}){let{t:r}=t();return typeof e==`boolean`?(0,d.jsx)(l,{variant:e?`success`:`neutral`,children:r(e?`common.on`:`common.off`)}):Array.isArray(e)?(0,d.jsx)(n,{as:`span`,variant:`bodySm`,children:e.length>0?e.join(`, `):r(`common.none`)}):(0,d.jsx)(n,{as:`span`,variant:`bodySm`,children:e})}export{f as component};
2
+ //# sourceMappingURL=system-BoUqxc5h.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-BoUqxc5h.js","names":["useSuspenseQuery","TRBadge","TRTable","TRText","useTranslation","AdminGateScreen","AdminShell","adminSystemQueryOptions","appConfigQueryOptions","Route","AdminSystemPage","user","useRouteContext","select","context","role","AdminSystemGate","SessionUser","data","config","admin","enabled","AdminSystemContent","t","health","database","email","sections","map","section","id","Object","entries","values","key","value","SystemValue","Array","isArray","length","join","component"],"sources":["../../../frontend/src/routes/admin/system/index.tsx?tsr-split=component"],"sourcesContent":["import { useSuspenseQuery } from '@tanstack/react-query';\nimport { createFileRoute, redirect } from '@tanstack/react-router';\nimport { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRTable } from '@tinyrack/ui/components/table';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { useTranslation } from 'react-i18next';\nimport { AdminGateScreen } from '#frontend/features/admin/admin-gate-screen.tsx';\nimport { AdminShell } from '#frontend/features/admin/admin-shell.tsx';\nimport { adminSystemQueryOptions } from '#frontend/queries/admin-console.ts';\nimport { appConfigQueryOptions } from '#frontend/queries/config.ts';\nimport type { SessionUser } from '#frontend/queries/session.ts';\n\nexport const Route = createFileRoute('/admin/system/')({\n component: AdminSystemPage,\n beforeLoad: async ({ context }) => {\n if (!context.user) throw redirect({ to: '/login' });\n },\n});\nfunction AdminSystemPage() {\n const user = Route.useRouteContext({ select: (context) => context.user });\n if (user?.role !== 'admin')\n return <AdminGateScreen reason=\"access-required\" />;\n return <AdminSystemGate user={user} />;\n}\nfunction AdminSystemGate({ user }: { user: SessionUser }) {\n const { data: config } = useSuspenseQuery(appConfigQueryOptions);\n if (!config.admin.enabled)\n return <AdminGateScreen reason=\"console-disabled\" />;\n return <AdminSystemContent user={user} />;\n}\n\nfunction AdminSystemContent({ user }: { user: SessionUser }) {\n const { t } = useTranslation();\n const { data } = useSuspenseQuery(adminSystemQueryOptions);\n return (\n <AdminShell current=\"system\" title={t('admin.system.title')} user={user}>\n <div className=\"flex flex-col items-start justify-between gap-tinyrack-md bg-tinyrack-surface px-tinyrack-lg py-tinyrack-md sm:flex-row sm:items-center\">\n <div>\n <TRText as=\"h1\" variant=\"headingMd\">\n {t('admin.system.title')}\n </TRText>\n <TRText as=\"p\" color=\"muted\" variant=\"bodySm\">\n {t('admin.system.readonly')}\n </TRText>\n </div>\n <div className=\"flex shrink-0 gap-tinyrack-sm\">\n <TRBadge variant=\"success\">\n {t(`admin.statusValue.${data.health.database}`)}\n </TRBadge>\n <TRBadge\n variant={data.health.email === 'disabled' ? 'neutral' : 'success'}\n >\n {t(`admin.statusValue.${data.health.email}`)}\n </TRBadge>\n </div>\n </div>\n {/* tinyrack-check-ignore-next-line components/no-native-text -- Structural system-card grid; cards own visible typography. */}\n <div className=\"grid gap-tinyrack-lg xl:grid-cols-2\">\n {data.sections.map((section) => (\n <section key={section.id}>\n <header className=\"bg-tinyrack-surface px-tinyrack-lg py-tinyrack-md\">\n <TRText as=\"h2\" variant=\"headingSm\">\n {t(`admin.system.section.${section.id}`)}\n </TRText>\n </header>\n <TRTable.Root density=\"compact\">\n <TRTable.Body>\n {Object.entries(section.values).map(([key, value]) => (\n <TRTable.Row key={key}>\n <TRTable.Cell className=\"text-tinyrack-text-muted\">\n {t(`admin.system.key.${key}`)}\n </TRTable.Cell>\n <TRTable.Cell className=\"text-right\">\n <SystemValue value={value} />\n </TRTable.Cell>\n </TRTable.Row>\n ))}\n </TRTable.Body>\n </TRTable.Root>\n </section>\n ))}\n </div>\n </AdminShell>\n );\n}\n\nfunction SystemValue({\n value,\n}: {\n value: boolean | number | string | string[];\n}) {\n const { t } = useTranslation();\n if (typeof value === 'boolean')\n return (\n <TRBadge variant={value ? 'success' : 'neutral'}>\n {t(value ? 'common.on' : 'common.off')}\n </TRBadge>\n );\n if (Array.isArray(value))\n return (\n <TRText as=\"span\" variant=\"bodySm\">\n {value.length > 0 ? value.join(', ') : t('common.none')}\n </TRText>\n );\n return (\n <TRText as=\"span\" variant=\"bodySm\">\n {value}\n </TRText>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{X as e,q as t}from"./createLucideIcon-D-yizrWN.js";var n=e();function r({className:e,...r}){return(0,n.jsx)(`tbody`,{...r,className:t(`tr-table-body`,e)})}function i({className:e,...r}){return(0,n.jsx)(`caption`,{...r,className:t(`tr-table-caption`,e)})}function a({className:e,...r}){return(0,n.jsx)(`td`,{...r,className:t(`tr-table-cell`,e)})}function o({className:e,...r}){return(0,n.jsx)(`tfoot`,{...r,className:t(`tr-table-footer`,e)})}function s({className:e,...r}){return(0,n.jsx)(`th`,{...r,className:t(`tr-table-head`,e)})}function c({className:e,...r}){return(0,n.jsx)(`thead`,{...r,className:t(`tr-table-header`,e)})}function l({className:e,containerClassName:r,containerProps:i,containerRef:a,density:o=`comfortable`,layout:s=`auto`,striped:c=!1,...l}){let{className:u,ref:d,...f}=i??{};return(0,n.jsx)(`div`,{...f,className:t(`tr-table-container`,r,u),ref:a??d,children:(0,n.jsx)(`table`,{...l,className:t(`tr-table`,e),"data-density":o,"data-layout":s,"data-striped":c?`true`:void 0})})}function u({className:e,...r}){return(0,n.jsx)(`tr`,{...r,className:t(`tr-table-row`,e)})}var d={Root:l,Caption:i,Header:c,Body:r,Footer:o,Row:u,Head:s,Cell:a};export{d as t};
2
+ //# sourceMappingURL=table-Dl89o43x.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-Dl89o43x.js","names":[],"sources":["../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-body.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-caption.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-cell.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-footer.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-head.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-header.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-root.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-row.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/index.js"],"sourcesContent":["import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-body.tsx\nfunction TRTableBody({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tbody\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-body\", className)\n\t});\n}\n//#endregion\nexport { TRTableBody };\n\n//# sourceMappingURL=table-body.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-caption.tsx\nfunction TRTableCaption({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"caption\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-caption\", className)\n\t});\n}\n//#endregion\nexport { TRTableCaption };\n\n//# sourceMappingURL=table-caption.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-cell.tsx\nfunction TRTableCell({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"td\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-cell\", className)\n\t});\n}\n//#endregion\nexport { TRTableCell };\n\n//# sourceMappingURL=table-cell.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-footer.tsx\nfunction TRTableFooter({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tfoot\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-footer\", className)\n\t});\n}\n//#endregion\nexport { TRTableFooter };\n\n//# sourceMappingURL=table-footer.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-head.tsx\nfunction TRTableHead({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"th\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-head\", className)\n\t});\n}\n//#endregion\nexport { TRTableHead };\n\n//# sourceMappingURL=table-head.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-header.tsx\nfunction TRTableHeader({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"thead\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-header\", className)\n\t});\n}\n//#endregion\nexport { TRTableHeader };\n\n//# sourceMappingURL=table-header.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-root.tsx\nfunction TRTableRoot({ className, containerClassName, containerProps, containerRef, density = \"comfortable\", layout = \"auto\", striped = false, ...props }) {\n\tconst { className: containerPropsClassName, ref: containerPropsRef, ...restContainerProps } = containerProps ?? {};\n\treturn /* @__PURE__ */ jsx(\"div\", {\n\t\t...restContainerProps,\n\t\tclassName: mergeClassNames(\"tr-table-container\", containerClassName, containerPropsClassName),\n\t\tref: containerRef ?? containerPropsRef,\n\t\tchildren: /* @__PURE__ */ jsx(\"table\", {\n\t\t\t...props,\n\t\t\tclassName: mergeClassNames(\"tr-table\", className),\n\t\t\t\"data-density\": density,\n\t\t\t\"data-layout\": layout,\n\t\t\t\"data-striped\": striped ? \"true\" : void 0\n\t\t})\n\t});\n}\n//#endregion\nexport { TRTableRoot };\n\n//# sourceMappingURL=table-root.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-row.tsx\nfunction TRTableRow({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tr\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-row\", className)\n\t});\n}\n//#endregion\nexport { TRTableRow };\n\n//# sourceMappingURL=table-row.js.map","import { TRTableBody } from \"./table-body.js\";\nimport { TRTableCaption } from \"./table-caption.js\";\nimport { TRTableCell } from \"./table-cell.js\";\nimport { TRTableFooter } from \"./table-footer.js\";\nimport { TRTableHead } from \"./table-head.js\";\nimport { TRTableHeader } from \"./table-header.js\";\nimport { TRTableRoot } from \"./table-root.js\";\nimport { TRTableRow } from \"./table-row.js\";\n//#region src/components/table/index.tsx\nconst TRTable = {\n\tRoot: TRTableRoot,\n\tCaption: TRTableCaption,\n\tHeader: TRTableHeader,\n\tBody: TRTableBody,\n\tFooter: TRTableFooter,\n\tRow: TRTableRow,\n\tHead: TRTableHead,\n\tCell: TRTableCell\n};\n//#endregion\nexport { TRTable, TRTableBody, TRTableCaption, TRTableCell, TRTableFooter, TRTableHead, TRTableHeader, TRTableRoot, TRTableRow };\n\n//# sourceMappingURL=index.js.map"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8],"mappings":"oEAGA,SAAS,EAAY,CAAE,YAAW,GAAG,GAAS,CAC7C,OAAuB,EAAA,EAAA,IAAA,CAAI,QAAS,CACnC,GAAG,EACH,UAAW,EAAgB,gBAAiB,CAAS,CACtD,CAAC,CACF,CCLA,SAAS,EAAe,CAAE,YAAW,GAAG,GAAS,CAChD,OAAuB,EAAA,EAAA,IAAA,CAAI,UAAW,CACrC,GAAG,EACH,UAAW,EAAgB,mBAAoB,CAAS,CACzD,CAAC,CACF,CCLA,SAAS,EAAY,CAAE,YAAW,GAAG,GAAS,CAC7C,OAAuB,EAAA,EAAA,IAAA,CAAI,KAAM,CAChC,GAAG,EACH,UAAW,EAAgB,gBAAiB,CAAS,CACtD,CAAC,CACF,CCLA,SAAS,EAAc,CAAE,YAAW,GAAG,GAAS,CAC/C,OAAuB,EAAA,EAAA,IAAA,CAAI,QAAS,CACnC,GAAG,EACH,UAAW,EAAgB,kBAAmB,CAAS,CACxD,CAAC,CACF,CCLA,SAAS,EAAY,CAAE,YAAW,GAAG,GAAS,CAC7C,OAAuB,EAAA,EAAA,IAAA,CAAI,KAAM,CAChC,GAAG,EACH,UAAW,EAAgB,gBAAiB,CAAS,CACtD,CAAC,CACF,CCLA,SAAS,EAAc,CAAE,YAAW,GAAG,GAAS,CAC/C,OAAuB,EAAA,EAAA,IAAA,CAAI,QAAS,CACnC,GAAG,EACH,UAAW,EAAgB,kBAAmB,CAAS,CACxD,CAAC,CACF,CCLA,SAAS,EAAY,CAAE,YAAW,qBAAoB,iBAAgB,eAAc,UAAU,cAAe,SAAS,OAAQ,UAAU,GAAO,GAAG,GAAS,CAC1J,GAAM,CAAE,UAAW,EAAyB,IAAK,EAAmB,GAAG,GAAuB,GAAkB,CAAC,EACjH,OAAuB,EAAA,EAAA,IAAA,CAAI,MAAO,CACjC,GAAG,EACH,UAAW,EAAgB,qBAAsB,EAAoB,CAAuB,EAC5F,IAAK,GAAgB,EACrB,UAA0B,EAAA,EAAA,IAAA,CAAI,QAAS,CACtC,GAAG,EACH,UAAW,EAAgB,WAAY,CAAS,EAChD,eAAgB,EAChB,cAAe,EACf,eAAgB,EAAU,OAAS,IAAK,EACzC,CAAC,CACF,CAAC,CACF,CCdA,SAAS,EAAW,CAAE,YAAW,GAAG,GAAS,CAC5C,OAAuB,EAAA,EAAA,IAAA,CAAI,KAAM,CAChC,GAAG,EACH,UAAW,EAAgB,eAAgB,CAAS,CACrD,CAAC,CACF,CCCA,IAAM,EAAU,CACf,KAAM,EACN,QAAS,EACT,OAAQ,EACR,KAAM,EACN,OAAQ,EACR,IAAK,EACL,KAAM,EACN,KAAM,CACP"}
@@ -0,0 +1,2 @@
1
+ import{X as e,Z as t,c as n,et as r,i,n as a,q as o,s}from"./createLucideIcon-D-yizrWN.js";import{Ar as c,On as l,kn as u,t as d}from"./config-C18-l7z7.js";import{t as f}from"./useMutation-DqIIIiBW.js";import{Dt as p,c as m,k as h}from"./shell-header-bar-CdOEWmCT.js";import{a as ee,c as g,d as _,f as v,i as y,l as b,n as te,o as ne,p as re,r as x,s as S,t as C,u as w}from"./use-admin-selection-D2b7jnym.js";import{a as T,f as E,h as D,l as O,s as k,t as A}from"./admin-shell-B91U4-Ro.js";import{l as j}from"./index-lTEyHSus.js";import{t as ie}from"./badge-B8D0Q2qq.js";import{t as M}from"./checkbox-DTPGfvmq.js";import{t as N}from"./form-sJw-V9wb.js";import{n as P,r as F,t as I}from"./field-CsrUbl__.js";import{t as L}from"./FieldControl-ShLuCjvG.js";import{t as R}from"./input-QvBxPgy5.js";import{t as z}from"./table-Dl89o43x.js";import{n as B,t as V}from"./modal-JuaLVSyx.js";var H=r(t(),1),U=e(),W=H.forwardRef(function(e,t){let{render:r,className:i,style:a,disabled:o=!1,...s}=e,[c,l]=H.useState(void 0),u=F(!0)?.disabled||o,d=n(`fieldset`,e,{ref:t,state:{disabled:u},props:[{"aria-labelledby":c,disabled:u},s]}),f=H.useMemo(()=>({legendId:c,setLegendId:l,disabled:u}),[c,l,u]);return(0,U.jsx)(P.Provider,{value:f,children:d})}),G=H.forwardRef(function(e,t){let{render:r,className:i,style:a,id:o,...s}=e,{disabled:c,setLegendId:l}=F(),u=h(o,l);return n(`div`,e,{state:{disabled:c},ref:t,props:[{id:u},s]})});function K({ref:e,render:t=(0,U.jsx)(`legend`,{}),...n}){return(0,U.jsx)(G,{...n,ref:e,render:t})}var q=l(K,`tr-fieldset-legend`),J={Root:l(W,`tr-fieldset`),Legend:q};function ae({className:e,uiSize:t=`md`,appearance:n=`solid`,...r}){return u(),(0,U.jsx)(L,{...r,className:o(`tr-textarea`,e),"data-appearance":n,"data-ui-size":t,render:(0,U.jsx)(`textarea`,{})})}function oe(){let e=j.useRouteContext({select:e=>e.user});return e?.role===`admin`?(0,U.jsx)(se,{user:e}):(0,U.jsx)(D,{reason:`access-required`})}function se({user:e}){let{data:t}=p(d);return t.admin.enabled?(0,U.jsx)(ce,{user:e}):(0,U.jsx)(D,{reason:`console-disabled`})}function ce({user:e}){let{t}=i(),n=c(),[r,o]=(0,H.useState)(``),[l,u]=(0,H.useState)({page:1,pageSize:20}),[d,m]=(0,H.useState)(null),[h,D]=(0,H.useState)(null),{data:j}=p(T(l)),M=C(j.terms.map(e=>e.id)),N=()=>n.invalidateQueries({queryKey:[`admin`]}),P=f({mutationFn:O,onSuccess:()=>{N(),m(null)}}),F=f({mutationFn:({id:e,input:t})=>E(e,t),onSuccess:()=>{N(),m(null)}}),I=f({mutationFn:k,onSuccess:()=>{N(),M.clear(),D(null)}}),L=l.page??1,R=l.pageSize??20,B=M.selection.kind===`filter`?j.pagination.total:M.selectedCount??0,V=M.selection.kind===`filter`?{kind:`filter`,filter:{query:l.query,managed_by:l.managedBy,archived:l.archived}}:{kind:`ids`,ids:[...M.selection.ids]},W=e=>{M.clear(),u(e)};return(0,U.jsxs)(A,{current:`terms`,title:t(`admin.terms.title`),user:e,children:[(0,U.jsxs)(`div`,{className:`flex min-h-0 min-w-0 flex-1 flex-col`,children:[(0,U.jsxs)(y,{onCreate:()=>m(`create`),onQueryChange:o,onSearch:()=>W({...l,query:r.trim(),page:1}),query:r,title:t(`admin.terms.title`),total:j.pagination.total,children:[(0,U.jsx)(x,{label:t(`admin.terms.required`),onChange:e=>W({...l,required:e===`all`?void 0:e===`required`,page:1}),options:[[`all`,t(`admin.filter.allRequirements`)],[`required`,t(`admin.terms.required`)],[`optional`,t(`admin.terms.optional`)]],value:l.required===void 0?`all`:l.required?`required`:`optional`}),(0,U.jsx)(x,{label:t(`admin.terms.consentMode`),onChange:e=>W({...l,consentMode:e===`explicit`?`explicit`:e===`implicit`?`implicit`:void 0,page:1}),options:[[`all`,t(`admin.filter.allModes`)],[`explicit`,t(`admin.terms.explicit`)],[`implicit`,t(`admin.terms.implicit`)]],value:l.consentMode??`all`}),(0,U.jsx)(x,{label:t(`admin.table.status`),onChange:e=>W({...l,archived:e===`all`?void 0:e===`archived`,page:1}),options:[[`all`,t(`admin.filter.allStatuses`)],[`active`,t(`admin.status.active`)],[`archived`,t(`admin.status.archived`)]],value:l.archived===void 0?`all`:l.archived?`archived`:`active`})]}),(0,U.jsxs)(re,{children:[(0,U.jsxs)(v,{label:t(`admin.terms.title`),children:[(0,U.jsx)(z.Header,{className:`sticky top-0 z-tinyrack-component-raised`,children:(0,U.jsxs)(z.Row,{children:[(0,U.jsx)(_,{header:!0,children:(0,U.jsx)(S,{checked:M.allOnPage,indeterminate:M.someOnPage,onChange:M.togglePage})}),(0,U.jsx)(w,{header:!0,children:(0,U.jsx)(g,{direction:l.direction??`asc`,label:t(`admin.terms.id`),onClick:()=>W({...l,direction:l.direction===`desc`?`asc`:`desc`,page:1})})}),(0,U.jsx)(z.Head,{children:t(`admin.terms.titleLabel`)}),(0,U.jsx)(z.Head,{children:t(`admin.terms.version`)}),(0,U.jsx)(z.Head,{children:t(`admin.terms.required`)}),(0,U.jsx)(z.Head,{children:t(`admin.terms.consentMode`)}),(0,U.jsx)(z.Head,{children:t(`admin.terms.languages`)}),(0,U.jsx)(z.Head,{children:t(`admin.terms.source`)}),(0,U.jsx)(z.Head,{children:t(`admin.table.status`)}),(0,U.jsx)(b,{header:!0,children:t(`admin.table.actions`)})]})}),(0,U.jsx)(z.Body,{children:j.terms.length===0?(0,U.jsx)(z.Row,{children:(0,U.jsx)(z.Cell,{className:`py-tinyrack-3xl text-center`,colSpan:10,children:t(`admin.table.empty`)})}):j.terms.map(e=>(0,U.jsxs)(z.Row,{className:M.isSelected(e.id)?`bg-tinyrack-surface-selected`:void 0,"data-selected":M.isSelected(e.id)?``:void 0,children:[(0,U.jsx)(_,{selected:M.isSelected(e.id),children:(0,U.jsx)(ne,{checked:M.isSelected(e.id),label:t(`admin.selection.row`,{name:e.id}),onChange:t=>M.toggleOne(e.id,t)})}),(0,U.jsx)(w,{selected:M.isSelected(e.id),children:(0,U.jsx)(a,{as:`span`,variant:`code`,children:e.id})}),(0,U.jsx)(z.Cell,{children:e.contents[0]?.title??e.id}),(0,U.jsx)(z.Cell,{children:e.version}),(0,U.jsx)(z.Cell,{children:t(e.required?`common.yes`:`common.no`)}),(0,U.jsx)(z.Cell,{children:t(`admin.terms.${e.consent_mode}`)}),(0,U.jsx)(z.Cell,{children:e.contents.map(e=>e.lang.toUpperCase()).join(`, `)}),(0,U.jsx)(z.Cell,{children:t(`admin.source.${e.managed_by}`)}),(0,U.jsx)(z.Cell,{children:(0,U.jsx)(ie,{className:`whitespace-nowrap`,variant:e.archived_at?`neutral`:`success`,children:t(e.archived_at?`admin.status.archived`:`admin.status.active`)})}),(0,U.jsx)(b,{selected:M.isSelected(e.id),children:(0,U.jsxs)(`div`,{className:`flex justify-end gap-tinyrack-xs`,children:[(0,U.jsx)(s,{appearance:`ghost`,disabled:e.managed_by===`config`,onClick:()=>m(e),type:`button`,uiSize:`sm`,children:t(`admin.actions.edit`)}),(0,U.jsx)(s,{appearance:`ghost`,disabled:e.managed_by===`config`,onClick:()=>I.mutate({target:{kind:`ids`,ids:[e.id]},active:!!e.archived_at}),type:`button`,uiSize:`sm`,children:t(e.archived_at?`admin.actions.restore`:`admin.actions.archive`)})]})})]},e.id))})]}),(0,U.jsx)(ee,{onPageChange:e=>W({...l,page:e}),onPageSizeChange:e=>W({...l,page:1,pageSize:e}),page:L,pageSize:R,total:j.pagination.total})]})]}),B>0?(0,U.jsx)(te,{canExpand:M.allOnPage&&j.pagination.total>j.terms.length,filterSelected:M.selection.kind===`filter`,onActivate:()=>D(!0),onClear:M.clear,onDeactivate:()=>D(!1),onExpand:M.selectFilter,pending:I.isPending,selected:B,total:j.pagination.total}):null,(0,U.jsx)(le,{active:h,count:B,filterSelected:M.selection.kind===`filter`,onClose:()=>D(null),onRun:()=>I.mutate({target:V,active:h??!0})}),(0,U.jsx)(Z,{isOpen:d!==null,onClose:()=>m(null),onSubmit:e=>{if(d&&d!==`create`){let{id:t,...n}=e;F.mutate({id:d.id,input:n})}else P.mutate(e)},pending:P.isPending||F.isPending,term:d===`create`?void 0:d??void 0})]})}function Y(e,t){let n=e.get(t);return typeof n==`string`?n.trim():``}var X=[`ko`,`en`,`ja`];function Z({isOpen:e,term:t,pending:n,onClose:r,onSubmit:o}){let{t:c}=i();return(0,U.jsx)(V,{description:c(t?`admin.terms.editDescription`:`admin.terms.createDescription`),isOpen:e,onClose:r,title:c(t?`admin.terms.editTitle`:`admin.terms.createTitle`),children:(0,U.jsxs)(N,{className:`flex flex-col gap-tinyrack-md pt-tinyrack-lg`,onSubmit:e=>{e.preventDefault();let t=new FormData(e.currentTarget),n=Y(t,`consent_mode`),r=[];for(let e of X){let n=Y(t,`${e}_title`),i=Y(t,`${e}_content`),a=Y(t,`${e}_type`);n&&i&&r.push({lang:e,title:n,type:a===`text`?`text`:`link`,content:i})}o({id:Y(t,`id`),required:t.get(`required`)===`on`,consent_mode:n===`implicit`?`implicit`:`explicit`,version:Y(t,`version`),contents:r})},children:[(0,U.jsxs)(`div`,{className:`grid gap-tinyrack-md sm:grid-cols-2`,children:[(0,U.jsx)(Q,{defaultValue:t?.id,disabled:!!t,label:c(`admin.terms.id`),name:`id`}),(0,U.jsx)(Q,{defaultValue:t?.version??`1.0.0`,label:c(`admin.terms.version`),name:`version`}),(0,U.jsx)($,{defaultValue:t?.consent_mode??`explicit`,label:c(`admin.terms.consentMode`),name:`consent_mode`,options:[[`explicit`,c(`admin.terms.explicit`)],[`implicit`,c(`admin.terms.implicit`)]]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-tinyrack-sm`,children:[(0,U.jsx)(M.Root,{"aria-label":c(`admin.terms.required`),defaultChecked:t?.required??!0,name:`required`,value:`on`,children:(0,U.jsx)(M.Indicator,{})}),(0,U.jsx)(a,{variant:`caption`,children:c(`admin.terms.required`)})]})]}),t?(0,U.jsx)(a,{color:`warning`,variant:`bodySm`,children:c(`admin.terms.versionWarning`)}):null,X.map(e=>{let n=t?.contents.find(t=>t.lang===e);return(0,U.jsxs)(J.Root,{className:`grid gap-tinyrack-sm pt-tinyrack-md sm:grid-cols-2`,children:[(0,U.jsx)(J.Legend,{children:e.toUpperCase()}),(0,U.jsx)(Q,{defaultValue:n?.title,label:c(`admin.terms.titleLabel`),name:`${e}_title`}),(0,U.jsx)($,{defaultValue:n?.type??`link`,label:c(`admin.terms.contentType`),name:`${e}_type`,options:[[`link`,c(`admin.terms.link`)],[`text`,c(`admin.terms.text`)]]}),(0,U.jsx)(ae,{className:`sm:col-span-2`,defaultValue:n?.content,name:`${e}_content`,placeholder:c(`admin.terms.content`)})]},e)}),(0,U.jsxs)(B,{children:[(0,U.jsx)(s,{disabled:n,onClick:r,type:`button`,children:c(`common.dismiss`)}),(0,U.jsx)(s,{disabled:n,intent:`primary`,type:`submit`,children:c(`admin.actions.save`)})]})]})})}function Q({label:e,name:t,defaultValue:n,disabled:r}){return(0,U.jsxs)(I.Root,{children:[(0,U.jsx)(I.Label,{children:e}),(0,U.jsx)(R,{defaultValue:n,disabled:r,name:t,required:!0,uiSize:`sm`})]})}function $({label:e,name:t,defaultValue:n,options:r}){return(0,U.jsxs)(`div`,{className:`flex flex-col gap-tinyrack-xs text-tinyrack-xs`,children:[(0,U.jsx)(a,{as:`span`,variant:`caption`,children:e}),(0,U.jsxs)(m.Root,{defaultValue:n,name:t,children:[(0,U.jsx)(m.Trigger,{"aria-label":e,uiSize:`sm`,children:(0,U.jsx)(m.Value,{children:r.find(([e])=>e===n)?.[1]??n})}),(0,U.jsx)(m.Positioner,{children:(0,U.jsx)(m.Popup,{children:(0,U.jsx)(m.List,{children:r.map(([e,t])=>(0,U.jsx)(m.Item,{value:e,children:(0,U.jsx)(m.ItemText,{children:t})},e))})})})]})]})}function le({active:e,count:t,filterSelected:n,onClose:r,onRun:o}){let{t:c}=i();return(0,U.jsx)(V,{isOpen:e!==null,onClose:r,title:c(e?`admin.bulk.restoreTitle`:`admin.bulk.archiveTitle`),children:(0,U.jsxs)(`div`,{className:`pt-tinyrack-lg`,children:[(0,U.jsx)(a,{color:`muted`,variant:`bodySm`,children:c(`admin.bulk.confirm`,{count:t,scope:c(n?`admin.selection.filterScope`:`admin.selection.pageScope`)})}),(0,U.jsxs)(B,{children:[(0,U.jsx)(s,{onClick:r,type:`button`,children:c(`common.dismiss`)}),(0,U.jsx)(s,{intent:e?`primary`:`danger`,onClick:o,type:`button`,children:c(`admin.bulk.run`)})]})]})})}export{oe as component};
2
+ //# sourceMappingURL=terms-B2wWfx1d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terms-B2wWfx1d.js","names":["FieldsetLegend","Fieldset.Legend","Fieldset.Root","Field.Control","useMutation","useQueryClient","useSuspenseQuery","TRBadge","TRButton","TRCheckbox","TRField","TRFieldset","TRForm","TRInput","TRSelect","TRTable","TRText","TRTextarea","useState","useTranslation","Modal","ModalActions","AdminBulkBar","AdminFilterSelect","AdminListToolbar","AdminPagination","AdminRowCheckbox","AdminSelectAll","AdminSortButton","AdminStickyActionCell","AdminStickyIdentityCell","AdminStickySelectCell","AdminTable","AdminTableFrame","AdminGateScreen","AdminShell","useAdminSelection","adminTermsQueryOptions","bulkSetAdminTermsActive","createAdminTerm","updateAdminTerm","appConfigQueryOptions","Route","AdminTermsPage","user","useRouteContext","select","context","role","AdminTermsGate","SessionUser","data","config","admin","enabled","AdminTermsContent","t","queryClient","draftQuery","setDraftQuery","filters","setFilters","AdminTermsQuery","page","pageSize","editing","setEditing","AdminTerm","bulkActive","setBulkActive","selection","terms","map","term","id","invalidate","invalidateQueries","queryKey","createMutation","mutationFn","onSuccess","updateMutation","input","Omit","AdminTermInput","bulkMutation","clear","selected","kind","pagination","total","selectedCount","target","AdminTermBulkTarget","filter","query","managed_by","managedBy","archived","ids","setFilter","next","trim","value","required","undefined","consentMode","allOnPage","someOnPage","togglePage","direction","length","isSelected","name","checked","toggleOne","contents","title","version","consent_mode","content","lang","toUpperCase","join","archived_at","mutate","active","Boolean","selectFilter","isPending","ignoredId","update","formString","FormData","get","TERM_LANGUAGES","Array","TermModal","isOpen","pending","onClose","onSubmit","submit","event","FormEvent","HTMLFormElement","preventDefault","currentTarget","contentType","push","type","find","item","TermField","label","defaultValue","disabled","TermFormSelect","options","text","TermsBulkConfirm","count","filterSelected","onRun","scope","component"],"sources":["../../../../node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@base-ui/react/fieldset/root/FieldsetRoot.mjs","../../../../node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7/node_modules/@base-ui/react/fieldset/legend/FieldsetLegend.mjs","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/fieldset/fieldset-legend.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/fieldset/fieldset-root.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/fieldset/index.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/textarea/textarea.js","../../../frontend/src/routes/admin/terms/index.tsx?tsr-split=component"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { FieldsetRootContext, useFieldsetRootContext } from \"./FieldsetRootContext.mjs\";\nimport { useRenderElement } from \"../../internals/useRenderElement.mjs\";\n\n/**\n * Groups a shared legend with related controls.\n * Renders a `<fieldset>` element.\n *\n * Documentation: [Base UI Fieldset](https://base-ui.com/react/components/fieldset)\n */\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport const FieldsetRoot = /*#__PURE__*/React.forwardRef(function FieldsetRoot(componentProps, forwardedRef) {\n const {\n render,\n className,\n style,\n disabled: disabledProp = false,\n ...elementProps\n } = componentProps;\n const [legendId, setLegendId] = React.useState(undefined);\n const parentDisabled = useFieldsetRootContext(true)?.disabled;\n const disabled = parentDisabled || disabledProp;\n const state = {\n disabled\n };\n const element = useRenderElement('fieldset', componentProps, {\n ref: forwardedRef,\n state,\n props: [{\n 'aria-labelledby': legendId,\n disabled\n }, elementProps]\n });\n const contextValue = React.useMemo(() => ({\n legendId,\n setLegendId,\n disabled\n }), [legendId, setLegendId, disabled]);\n return /*#__PURE__*/_jsx(FieldsetRootContext.Provider, {\n value: contextValue,\n children: element\n });\n});\nif (process.env.NODE_ENV !== \"production\") FieldsetRoot.displayName = \"FieldsetRoot\";","'use client';\n\nimport * as React from 'react';\nimport { useRenderElement } from \"../../internals/useRenderElement.mjs\";\nimport { useFieldsetRootContext } from \"../root/FieldsetRootContext.mjs\";\nimport { useRegisteredLabelId } from \"../../utils/useRegisteredLabelId.mjs\";\n\n/**\n * An accessible label that is automatically associated with the fieldset.\n * Renders a `<div>` element.\n *\n * Documentation: [Base UI Fieldset](https://base-ui.com/react/components/fieldset)\n */\nexport const FieldsetLegend = /*#__PURE__*/React.forwardRef(function FieldsetLegend(componentProps, forwardedRef) {\n const {\n render,\n className,\n style,\n id: idProp,\n ...elementProps\n } = componentProps;\n const {\n disabled,\n setLegendId\n } = useFieldsetRootContext();\n const id = useRegisteredLabelId(idProp, setLegendId);\n const state = {\n disabled\n };\n const element = useRenderElement('div', componentProps, {\n state,\n ref: forwardedRef,\n props: [{\n id\n }, elementProps]\n });\n return element;\n});\nif (process.env.NODE_ENV !== \"production\") FieldsetLegend.displayName = \"FieldsetLegend\";","\"use client\";\nimport { createComponentPart } from \"../../internal/component-part.js\";\nimport { jsx } from \"react/jsx-runtime\";\nimport { Fieldset } from \"@base-ui/react/fieldset\";\n//#region src/components/fieldset/fieldset-legend.tsx\nfunction FieldsetLegend({ ref, render = /* @__PURE__ */ jsx(\"legend\", {}), ...props }) {\n\treturn /* @__PURE__ */ jsx(Fieldset.Legend, {\n\t\t...props,\n\t\tref,\n\t\trender\n\t});\n}\nconst TRFieldsetLegend = createComponentPart(FieldsetLegend, \"tr-fieldset-legend\");\n//#endregion\nexport { TRFieldsetLegend };\n\n//# sourceMappingURL=fieldset-legend.js.map","\"use client\";\nimport { createComponentPart } from \"../../internal/component-part.js\";\nimport { Fieldset } from \"@base-ui/react/fieldset\";\n//#region src/components/fieldset/fieldset-root.tsx\nconst TRFieldsetRoot = createComponentPart(Fieldset.Root, \"tr-fieldset\");\n//#endregion\nexport { TRFieldsetRoot };\n\n//# sourceMappingURL=fieldset-root.js.map","import { TRFieldsetLegend } from \"./fieldset-legend.js\";\nimport { TRFieldsetRoot } from \"./fieldset-root.js\";\n//#region src/components/fieldset/index.tsx\nconst TRFieldset = {\n\tRoot: TRFieldsetRoot,\n\tLegend: TRFieldsetLegend\n};\n//#endregion\nexport { TRFieldset, TRFieldsetLegend, TRFieldsetRoot };\n\n//# sourceMappingURL=index.js.map","\"use client\";\nimport { useTinyrackFocusModality } from \"../../providers/focus-modality/focus-modality-provider.js\";\nimport { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\nimport { Field } from \"@base-ui/react/field\";\n//#region src/components/textarea/textarea.tsx\nfunction TRTextarea({ className, uiSize = \"md\", appearance = \"solid\", ...props }) {\n\tuseTinyrackFocusModality();\n\treturn /* @__PURE__ */ jsx(Field.Control, {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-textarea\", className),\n\t\t\"data-appearance\": appearance,\n\t\t\"data-ui-size\": uiSize,\n\t\trender: /* @__PURE__ */ jsx(\"textarea\", {})\n\t});\n}\n//#endregion\nexport { TRTextarea };\n\n//# sourceMappingURL=textarea.js.map","import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from '@tanstack/react-query';\nimport { createFileRoute, redirect } from '@tanstack/react-router';\nimport { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCheckbox } from '@tinyrack/ui/components/checkbox';\nimport { TRField } from '@tinyrack/ui/components/field';\nimport { TRFieldset } from '@tinyrack/ui/components/fieldset';\nimport { TRForm } from '@tinyrack/ui/components/form';\nimport { TRInput } from '@tinyrack/ui/components/input';\nimport { TRSelect } from '@tinyrack/ui/components/select';\nimport { TRTable } from '@tinyrack/ui/components/table';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { TRTextarea } from '@tinyrack/ui/components/textarea';\nimport { type FormEvent, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Modal, ModalActions } from '#frontend/components/ui/modal.tsx';\nimport {\n AdminBulkBar,\n AdminFilterSelect,\n AdminListToolbar,\n AdminPagination,\n AdminRowCheckbox,\n AdminSelectAll,\n AdminSortButton,\n AdminStickyActionCell,\n AdminStickyIdentityCell,\n AdminStickySelectCell,\n AdminTable,\n AdminTableFrame,\n} from '#frontend/features/admin/admin-data-table.tsx';\nimport { AdminGateScreen } from '#frontend/features/admin/admin-gate-screen.tsx';\nimport { AdminShell } from '#frontend/features/admin/admin-shell.tsx';\nimport { useAdminSelection } from '#frontend/features/admin/use-admin-selection.ts';\nimport {\n type AdminTerm,\n type AdminTermBulkTarget,\n type AdminTermInput,\n type AdminTermsQuery,\n adminTermsQueryOptions,\n bulkSetAdminTermsActive,\n createAdminTerm,\n updateAdminTerm,\n} from '#frontend/queries/admin-console.ts';\nimport { appConfigQueryOptions } from '#frontend/queries/config.ts';\nimport type { SessionUser } from '#frontend/queries/session.ts';\n\nexport const Route = createFileRoute('/admin/terms/')({\n component: AdminTermsPage,\n beforeLoad: async ({ context }) => {\n if (!context.user) throw redirect({ to: '/login' });\n },\n});\n\nfunction AdminTermsPage() {\n const user = Route.useRouteContext({ select: (context) => context.user });\n if (user?.role !== 'admin')\n return <AdminGateScreen reason=\"access-required\" />;\n return <AdminTermsGate user={user} />;\n}\nfunction AdminTermsGate({ user }: { user: SessionUser }) {\n const { data: config } = useSuspenseQuery(appConfigQueryOptions);\n if (!config.admin.enabled)\n return <AdminGateScreen reason=\"console-disabled\" />;\n return <AdminTermsContent user={user} />;\n}\n\nfunction AdminTermsContent({ user }: { user: SessionUser }) {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const [draftQuery, setDraftQuery] = useState('');\n const [filters, setFilters] = useState<AdminTermsQuery>({\n page: 1,\n pageSize: 20,\n });\n const [editing, setEditing] = useState<AdminTerm | 'create' | null>(null);\n const [bulkActive, setBulkActive] = useState<boolean | null>(null);\n const { data } = useSuspenseQuery(adminTermsQueryOptions(filters));\n const selection = useAdminSelection(data.terms.map((term) => term.id));\n const invalidate = () =>\n queryClient.invalidateQueries({ queryKey: ['admin'] });\n const createMutation = useMutation({\n mutationFn: createAdminTerm,\n onSuccess: () => {\n void invalidate();\n setEditing(null);\n },\n });\n const updateMutation = useMutation({\n mutationFn: ({\n id,\n input,\n }: {\n id: string;\n input: Omit<AdminTermInput, 'id'>;\n }) => updateAdminTerm(id, input),\n onSuccess: () => {\n void invalidate();\n setEditing(null);\n },\n });\n const bulkMutation = useMutation({\n mutationFn: bulkSetAdminTermsActive,\n onSuccess: () => {\n void invalidate();\n selection.clear();\n setBulkActive(null);\n },\n });\n const page = filters.page ?? 1;\n const pageSize = filters.pageSize ?? 20;\n const selected =\n selection.selection.kind === 'filter'\n ? data.pagination.total\n : (selection.selectedCount ?? 0);\n const target: AdminTermBulkTarget =\n selection.selection.kind === 'filter'\n ? {\n kind: 'filter',\n filter: {\n query: filters.query,\n managed_by: filters.managedBy,\n archived: filters.archived,\n },\n }\n : { kind: 'ids', ids: [...selection.selection.ids] };\n const setFilter = (next: AdminTermsQuery) => {\n selection.clear();\n setFilters(next);\n };\n return (\n <AdminShell current=\"terms\" title={t('admin.terms.title')} user={user}>\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col\">\n <AdminListToolbar\n onCreate={() => setEditing('create')}\n onQueryChange={setDraftQuery}\n onSearch={() =>\n setFilter({ ...filters, query: draftQuery.trim(), page: 1 })\n }\n query={draftQuery}\n title={t('admin.terms.title')}\n total={data.pagination.total}\n >\n <AdminFilterSelect\n label={t('admin.terms.required')}\n onChange={(value) =>\n setFilter({\n ...filters,\n required: value === 'all' ? undefined : value === 'required',\n page: 1,\n })\n }\n options={[\n ['all', t('admin.filter.allRequirements')],\n ['required', t('admin.terms.required')],\n ['optional', t('admin.terms.optional')],\n ]}\n value={\n filters.required === undefined\n ? 'all'\n : filters.required\n ? 'required'\n : 'optional'\n }\n />\n <AdminFilterSelect\n label={t('admin.terms.consentMode')}\n onChange={(value) =>\n setFilter({\n ...filters,\n consentMode:\n value === 'explicit'\n ? 'explicit'\n : value === 'implicit'\n ? 'implicit'\n : undefined,\n page: 1,\n })\n }\n options={[\n ['all', t('admin.filter.allModes')],\n ['explicit', t('admin.terms.explicit')],\n ['implicit', t('admin.terms.implicit')],\n ]}\n value={filters.consentMode ?? 'all'}\n />\n <AdminFilterSelect\n label={t('admin.table.status')}\n onChange={(value) =>\n setFilter({\n ...filters,\n archived: value === 'all' ? undefined : value === 'archived',\n page: 1,\n })\n }\n options={[\n ['all', t('admin.filter.allStatuses')],\n ['active', t('admin.status.active')],\n ['archived', t('admin.status.archived')],\n ]}\n value={\n filters.archived === undefined\n ? 'all'\n : filters.archived\n ? 'archived'\n : 'active'\n }\n />\n </AdminListToolbar>\n <AdminTableFrame>\n <AdminTable label={t('admin.terms.title')}>\n <TRTable.Header className=\"sticky top-0 z-tinyrack-component-raised\">\n <TRTable.Row>\n <AdminStickySelectCell header>\n <AdminSelectAll\n checked={selection.allOnPage}\n indeterminate={selection.someOnPage}\n onChange={selection.togglePage}\n />\n </AdminStickySelectCell>\n <AdminStickyIdentityCell header>\n <AdminSortButton\n direction={filters.direction ?? 'asc'}\n label={t('admin.terms.id')}\n onClick={() =>\n setFilter({\n ...filters,\n direction:\n filters.direction === 'desc' ? 'asc' : 'desc',\n page: 1,\n })\n }\n />\n </AdminStickyIdentityCell>\n <TRTable.Head>{t('admin.terms.titleLabel')}</TRTable.Head>\n <TRTable.Head>{t('admin.terms.version')}</TRTable.Head>\n <TRTable.Head>{t('admin.terms.required')}</TRTable.Head>\n <TRTable.Head>{t('admin.terms.consentMode')}</TRTable.Head>\n <TRTable.Head>{t('admin.terms.languages')}</TRTable.Head>\n <TRTable.Head>{t('admin.terms.source')}</TRTable.Head>\n <TRTable.Head>{t('admin.table.status')}</TRTable.Head>\n <AdminStickyActionCell header>\n {t('admin.table.actions')}\n </AdminStickyActionCell>\n </TRTable.Row>\n </TRTable.Header>\n <TRTable.Body>\n {data.terms.length === 0 ? (\n <TRTable.Row>\n <TRTable.Cell\n className=\"py-tinyrack-3xl text-center\"\n colSpan={10}\n >\n {t('admin.table.empty')}\n </TRTable.Cell>\n </TRTable.Row>\n ) : (\n data.terms.map((term) => (\n <TRTable.Row\n className={\n selection.isSelected(term.id)\n ? 'bg-tinyrack-surface-selected'\n : undefined\n }\n data-selected={\n selection.isSelected(term.id) ? '' : undefined\n }\n key={term.id}\n >\n <AdminStickySelectCell\n selected={selection.isSelected(term.id)}\n >\n <AdminRowCheckbox\n checked={selection.isSelected(term.id)}\n label={t('admin.selection.row', { name: term.id })}\n onChange={(checked) =>\n selection.toggleOne(term.id, checked)\n }\n />\n </AdminStickySelectCell>\n <AdminStickyIdentityCell\n selected={selection.isSelected(term.id)}\n >\n <TRText as=\"span\" variant=\"code\">\n {term.id}\n </TRText>\n </AdminStickyIdentityCell>\n <TRTable.Cell>\n {term.contents[0]?.title ?? term.id}\n </TRTable.Cell>\n <TRTable.Cell>{term.version}</TRTable.Cell>\n <TRTable.Cell>\n {t(term.required ? 'common.yes' : 'common.no')}\n </TRTable.Cell>\n <TRTable.Cell>\n {t(`admin.terms.${term.consent_mode}`)}\n </TRTable.Cell>\n <TRTable.Cell>\n {term.contents\n .map((content) => content.lang.toUpperCase())\n .join(', ')}\n </TRTable.Cell>\n <TRTable.Cell>\n {t(`admin.source.${term.managed_by}`)}\n </TRTable.Cell>\n <TRTable.Cell>\n <TRBadge\n className=\"whitespace-nowrap\"\n variant={term.archived_at ? 'neutral' : 'success'}\n >\n {t(\n term.archived_at\n ? 'admin.status.archived'\n : 'admin.status.active',\n )}\n </TRBadge>\n </TRTable.Cell>\n <AdminStickyActionCell\n selected={selection.isSelected(term.id)}\n >\n <div className=\"flex justify-end gap-tinyrack-xs\">\n <TRButton\n appearance=\"ghost\"\n disabled={term.managed_by === 'config'}\n onClick={() => setEditing(term)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.actions.edit')}\n </TRButton>\n <TRButton\n appearance=\"ghost\"\n disabled={term.managed_by === 'config'}\n onClick={() =>\n bulkMutation.mutate({\n target: { kind: 'ids', ids: [term.id] },\n active: Boolean(term.archived_at),\n })\n }\n type=\"button\"\n uiSize=\"sm\"\n >\n {t(\n term.archived_at\n ? 'admin.actions.restore'\n : 'admin.actions.archive',\n )}\n </TRButton>\n </div>\n </AdminStickyActionCell>\n </TRTable.Row>\n ))\n )}\n </TRTable.Body>\n </AdminTable>\n <AdminPagination\n onPageChange={(next) => setFilter({ ...filters, page: next })}\n onPageSizeChange={(next) =>\n setFilter({ ...filters, page: 1, pageSize: next })\n }\n page={page}\n pageSize={pageSize}\n total={data.pagination.total}\n />\n </AdminTableFrame>\n </div>\n {selected > 0 ? (\n <AdminBulkBar\n canExpand={\n selection.allOnPage && data.pagination.total > data.terms.length\n }\n filterSelected={selection.selection.kind === 'filter'}\n onActivate={() => setBulkActive(true)}\n onClear={selection.clear}\n onDeactivate={() => setBulkActive(false)}\n onExpand={selection.selectFilter}\n pending={bulkMutation.isPending}\n selected={selected}\n total={data.pagination.total}\n />\n ) : null}\n <TermsBulkConfirm\n active={bulkActive}\n count={selected}\n filterSelected={selection.selection.kind === 'filter'}\n onClose={() => setBulkActive(null)}\n onRun={() =>\n bulkMutation.mutate({ target, active: bulkActive ?? true })\n }\n />\n <TermModal\n isOpen={editing !== null}\n onClose={() => setEditing(null)}\n onSubmit={(input) => {\n if (editing && editing !== 'create') {\n const { id: ignoredId, ...update } = input;\n void ignoredId;\n updateMutation.mutate({ id: editing.id, input: update });\n } else createMutation.mutate(input);\n }}\n pending={createMutation.isPending || updateMutation.isPending}\n term={editing === 'create' ? undefined : (editing ?? undefined)}\n />\n </AdminShell>\n );\n}\n\nfunction formString(data: FormData, name: string) {\n const value = data.get(name);\n return typeof value === 'string' ? value.trim() : '';\n}\nconst TERM_LANGUAGES: Array<'ko' | 'en' | 'ja'> = ['ko', 'en', 'ja'];\n\nfunction TermModal({\n isOpen,\n term,\n pending,\n onClose,\n onSubmit,\n}: {\n isOpen: boolean;\n term?: AdminTerm | undefined;\n pending: boolean;\n onClose: () => void;\n onSubmit: (input: AdminTermInput) => void;\n}) {\n const { t } = useTranslation();\n const submit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const data = new FormData(event.currentTarget);\n const consentMode = formString(data, 'consent_mode');\n const contents: AdminTermInput['contents'] = [];\n for (const lang of TERM_LANGUAGES) {\n const title = formString(data, `${lang}_title`);\n const content = formString(data, `${lang}_content`);\n const contentType = formString(data, `${lang}_type`);\n if (title && content)\n contents.push({\n lang,\n title,\n type: contentType === 'text' ? 'text' : 'link',\n content,\n });\n }\n onSubmit({\n id: formString(data, 'id'),\n required: data.get('required') === 'on',\n consent_mode: consentMode === 'implicit' ? 'implicit' : 'explicit',\n version: formString(data, 'version'),\n contents,\n });\n };\n return (\n <Modal\n description={t(\n term ? 'admin.terms.editDescription' : 'admin.terms.createDescription',\n )}\n isOpen={isOpen}\n onClose={onClose}\n title={t(term ? 'admin.terms.editTitle' : 'admin.terms.createTitle')}\n >\n <TRForm\n className=\"flex flex-col gap-tinyrack-md pt-tinyrack-lg\"\n onSubmit={submit}\n >\n {/* tinyrack-check-ignore-next-line components/no-native-text -- Structural form grid; fields own visible typography. */}\n <div className=\"grid gap-tinyrack-md sm:grid-cols-2\">\n <TermField\n defaultValue={term?.id}\n disabled={Boolean(term)}\n label={t('admin.terms.id')}\n name=\"id\"\n />\n <TermField\n defaultValue={term?.version ?? '1.0.0'}\n label={t('admin.terms.version')}\n name=\"version\"\n />\n <TermFormSelect\n defaultValue={term?.consent_mode ?? 'explicit'}\n label={t('admin.terms.consentMode')}\n name=\"consent_mode\"\n options={[\n ['explicit', t('admin.terms.explicit')],\n ['implicit', t('admin.terms.implicit')],\n ]}\n />\n {/* tinyrack-check-ignore-next-line components/no-native-text -- Structural checkbox row; visible label uses TRText. */}\n <div className=\"flex items-center gap-tinyrack-sm\">\n <TRCheckbox.Root\n aria-label={t('admin.terms.required')}\n defaultChecked={term?.required ?? true}\n name=\"required\"\n value=\"on\"\n >\n <TRCheckbox.Indicator />\n </TRCheckbox.Root>\n <TRText variant=\"caption\">{t('admin.terms.required')}</TRText>\n </div>\n </div>\n {term ? (\n <TRText color=\"warning\" variant=\"bodySm\">\n {t('admin.terms.versionWarning')}\n </TRText>\n ) : null}\n {TERM_LANGUAGES.map((lang) => {\n const content = term?.contents.find((item) => item.lang === lang);\n return (\n <TRFieldset.Root\n className=\"grid gap-tinyrack-sm pt-tinyrack-md sm:grid-cols-2\"\n key={lang}\n >\n <TRFieldset.Legend>{lang.toUpperCase()}</TRFieldset.Legend>\n <TermField\n defaultValue={content?.title}\n label={t('admin.terms.titleLabel')}\n name={`${lang}_title`}\n />\n <TermFormSelect\n defaultValue={content?.type ?? 'link'}\n label={t('admin.terms.contentType')}\n name={`${lang}_type`}\n options={[\n ['link', t('admin.terms.link')],\n ['text', t('admin.terms.text')],\n ]}\n />\n <TRTextarea\n className=\"sm:col-span-2\"\n defaultValue={content?.content}\n name={`${lang}_content`}\n placeholder={t('admin.terms.content')}\n />\n </TRFieldset.Root>\n );\n })}\n <ModalActions>\n <TRButton disabled={pending} onClick={onClose} type=\"button\">\n {t('common.dismiss')}\n </TRButton>\n <TRButton disabled={pending} intent=\"primary\" type=\"submit\">\n {t('admin.actions.save')}\n </TRButton>\n </ModalActions>\n </TRForm>\n </Modal>\n );\n}\nfunction TermField({\n label,\n name,\n defaultValue,\n disabled,\n}: {\n label: string;\n name: string;\n defaultValue?: string | undefined;\n disabled?: boolean | undefined;\n}) {\n return (\n <TRField.Root>\n <TRField.Label>{label}</TRField.Label>\n <TRInput\n defaultValue={defaultValue}\n disabled={disabled}\n name={name}\n required\n uiSize=\"sm\"\n />\n </TRField.Root>\n );\n}\nfunction TermFormSelect({\n label,\n name,\n defaultValue,\n options,\n}: {\n label: string;\n name: string;\n defaultValue: string;\n options: Array<[string, string]>;\n}) {\n return (\n <div className=\"flex flex-col gap-tinyrack-xs text-tinyrack-xs\">\n <TRText as=\"span\" variant=\"caption\">\n {label}\n </TRText>\n <TRSelect.Root defaultValue={defaultValue} name={name}>\n <TRSelect.Trigger aria-label={label} uiSize=\"sm\">\n <TRSelect.Value>\n {options.find(([value]) => value === defaultValue)?.[1] ??\n defaultValue}\n </TRSelect.Value>\n </TRSelect.Trigger>\n <TRSelect.Positioner>\n <TRSelect.Popup>\n <TRSelect.List>\n {options.map(([value, text]) => (\n <TRSelect.Item key={value} value={value}>\n <TRSelect.ItemText>{text}</TRSelect.ItemText>\n </TRSelect.Item>\n ))}\n </TRSelect.List>\n </TRSelect.Popup>\n </TRSelect.Positioner>\n </TRSelect.Root>\n </div>\n );\n}\nfunction TermsBulkConfirm({\n active,\n count,\n filterSelected,\n onClose,\n onRun,\n}: {\n active: boolean | null;\n count: number;\n filterSelected: boolean;\n onClose: () => void;\n onRun: () => void;\n}) {\n const { t } = useTranslation();\n return (\n <Modal\n isOpen={active !== null}\n onClose={onClose}\n title={t(active ? 'admin.bulk.restoreTitle' : 'admin.bulk.archiveTitle')}\n >\n <div className=\"pt-tinyrack-lg\">\n <TRText color=\"muted\" variant=\"bodySm\">\n {t('admin.bulk.confirm', {\n count,\n scope: t(\n filterSelected\n ? 'admin.selection.filterScope'\n : 'admin.selection.pageScope',\n ),\n })}\n </TRText>\n <ModalActions>\n <TRButton onClick={onClose} type=\"button\">\n {t('common.dismiss')}\n </TRButton>\n <TRButton\n intent={active ? 'primary' : 'danger'}\n onClick={onRun}\n type=\"button\"\n >\n {t('admin.bulk.run')}\n </TRButton>\n </ModalActions>\n </div>\n </Modal>\n );\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{X as e,Z as t,et as n,i as r,s as i}from"./createLucideIcon-D-yizrWN.js";import{Ar as a,In as o,t as s}from"./config-C18-l7z7.js";import{t as c}from"./useMutation-DqIIIiBW.js";import{Dt as l}from"./shell-header-bar-CdOEWmCT.js";import{t as u}from"./triangle-alert-DATO9o3k.js";import{a as d,o as f,r as p}from"./zod-Dszyrytb.js";import{E as m,M as h,N as g,P as _}from"./index-lTEyHSus.js";import{t as v}from"./auth-page-header-ChaCNNrn.js";import{t as y}from"./alert-D3aaK-_3.js";import{t as b}from"./auth-layout-BdRRr0vT.js";import{t as x}from"./form-sJw-V9wb.js";import{t as S}from"./promise-OpBtq8tG.js";import{t as C}from"./design-system-rich-text-B3NzIRoJ.js";import{r as w,t as T}from"./standard-schema-C50nwAaQ.js";import{t as E}from"./terms-checkbox-list-C9TkDC8Y.js";import{t as D}from"./labeled-separator-DdkyYDWH.js";var O=n(t()),k=e();function A(){let{t:e,i18n:t}=r(),n=o(),A=a(),j=h.useSearch(),{data:M}=l(s),N=j.lang??t.language,P=l(g(N)),F=M.registration.signup_notice?.[N]??M.registration.signup_notice?.[M.i18n.fallback_language],I=(0,O.useMemo)(()=>P.data.terms.filter(e=>e.consentMode===`explicit`),[P.data.terms]),L=(0,O.useMemo)(()=>P.data.terms.filter(e=>e.consentMode===`implicit`),[P.data.terms]),R=I.length>0,z=(0,O.useMemo)(()=>f({termsConsents:f(Object.fromEntries(I.map(t=>[t.id,t.required?d(!0,{message:e(`validation.terms.required`)}):p()])))}),[e,I]),{handleSubmit:B,control:V,setValue:H,formState:{errors:U}}=w({defaultValues:{termsConsents:Object.fromEntries(I.map(e=>[e.id,!!(e.userConsent?.agreed&&!e.userConsent.requiresUpdate)]))},resolver:T(z),mode:`onChange`}),W=c({..._,onSuccess:async()=>{await A.invalidateQueries({queryKey:m.queryKey}),await A.fetchQuery(m),await S(),j.redirect?window.location.href=j.redirect:n.navigate({to:`/profile`})}});return(0,k.jsxs)(b,{width:`wide`,children:[(0,k.jsx)(v,{title:e(`terms.title`)}),F&&(0,k.jsx)(C,{html:F,variant:`notice`}),F&&R&&(0,k.jsx)(D,{label:e(`terms.additionalOptionalConsent`)}),(0,k.jsxs)(x,{className:`flex flex-col gap-tinyrack-lg`,onSubmit:B(e=>{let t=Object.entries(e.termsConsents).map(([e,t])=>({termsId:e,agreed:t,consentType:`explicit`})),n=L.map(e=>({termsId:e.id,agreed:!0,consentType:`implicit`}));W.mutate({consents:[...t,...n],...j.registration_token&&{registrationToken:j.registration_token}})}),children:[R&&(0,k.jsx)(E,{control:V,disabled:W.isPending,errors:U,setValue:H,terms:I}),W.isError&&(0,k.jsx)(y,{icon:u,type:`error`,children:e(`terms.error.submitFailed`)}),(0,k.jsx)(`div`,{className:`sticky bottom-0 flex gap-tinyrack-sm border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface py-tinyrack-md`,children:(0,k.jsx)(i,{className:`w-full`,intent:`primary`,loading:W.isPending,loadingLabel:e(`terms.submit`),type:`submit`,uiSize:`lg`,children:e(`terms.submit`)})})]})]})}export{A as component};
2
+ //# sourceMappingURL=terms-COr3cDw5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terms-COr3cDw5.js","names":["standardSchemaResolver","useMutation","useQueryClient","useSuspenseQuery","useRouter","TRButton","TRForm","TriangleAlertIcon","useMemo","useForm","useTranslation","z","AuthPageHeader","TermsCheckboxList","Alert","DesignSystemRichText","LabeledSeparator","AuthLayout","tick","appConfigQueryOptions","getSessionQueryOptions","getTermsQueryOptions","termsConsentMutationOptions","Route","Terms","t","i18n","router","queryClient","search","useSearch","data","configData","lang","language","termsQuery","implicitNotice","registration","signup_notice","fallback_language","explicitTerms","terms","filter","term","consentMode","implicitTerms","hasExplicitTerms","length","termsSchema","object","termsConsents","Object","fromEntries","map","id","required","literal","message","boolean","TermsFormValues","TermsConsentsField","handleSubmit","control","setValue","formState","errors","defaultValues","userConsent","agreed","requiresUpdate","resolver","mode","consentMutation","onSuccess","invalidateQueries","queryKey","fetchQuery","redirect","window","location","href","navigate","to","onSubmit","values","explicitConsents","entries","TermsConsentItem","termsId","consentType","implicitConsents","mutate","consents","registration_token","registrationToken","isPending","isError","component"],"sources":["../../../frontend/src/routes/terms/index.tsx?tsr-split=component"],"sourcesContent":["import { standardSchemaResolver } from '@hookform/resolvers/standard-schema';\nimport {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from '@tanstack/react-query';\nimport {\n createFileRoute,\n type ErrorComponentProps,\n redirect,\n useRouter,\n} from '@tanstack/react-router';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRForm } from '@tinyrack/ui/components/form';\nimport { TriangleAlertIcon } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport { z } from 'zod';\nimport { AuthPageHeader } from '#frontend/components/auth/auth-page-header.tsx';\nimport {\n TermsCheckboxList,\n type TermsConsentsField,\n} from '#frontend/components/terms/terms-checkbox-list.tsx';\nimport { Alert } from '#frontend/components/ui/alert.tsx';\nimport { DesignSystemRichText } from '#frontend/components/ui/design-system-rich-text.tsx';\nimport { LabeledSeparator } from '#frontend/components/ui/labeled-separator.tsx';\nimport { RouteErrorFallback } from '#frontend/components/ui/route-error-fallback.tsx';\nimport { AuthLayout } from '#frontend/features/layout/auth-layout.tsx';\nimport { OAuthSearchSchema } from '#frontend/libs/oauth-search.ts';\nimport { tick } from '#frontend/libs/promise.ts';\nimport { appConfigQueryOptions } from '#frontend/queries/config.ts';\nimport { getSessionQueryOptions } from '#frontend/queries/session.ts';\nimport {\n getTermsQueryOptions,\n type TermsConsentItem,\n termsConsentMutationOptions,\n} from '#frontend/queries/terms.ts';\n\nconst TermsSearchSchema = OAuthSearchSchema.extend({\n redirect: z.string().optional(),\n lang: z.string().optional(),\n mode: z.enum(['normal', 'complete_registration']).optional(),\n registration_token: z.string().optional(),\n});\n\nfunction TermsError(props: ErrorComponentProps) {\n return (\n <RouteErrorFallback\n {...props}\n onUnauthorized={() => {\n window.location.href = '/login';\n }}\n />\n );\n}\n\nexport const Route = createFileRoute('/terms/')({\n component: Terms,\n errorComponent: TermsError,\n validateSearch: TermsSearchSchema,\n beforeLoad: async ({ context, search }) => {\n // When mode=complete_registration, user is completing OAuth signup.\n // The registration_token in the URL references a DB record with OAuth data.\n // Skip auth check — backend will validate the token on consent submission.\n if (search.mode === 'complete_registration') {\n return;\n }\n\n // Standard mode: requires authentication\n // Users are redirected here after OAuth login when they need to agree to terms\n if (!context.user) {\n throw redirect({\n to: '/login',\n });\n }\n },\n loaderDeps: ({ search }) => ({\n lang: search.lang,\n }),\n loader: async ({ context, deps }) => {\n const lang = deps.lang ?? context.i18n.language;\n await Promise.all([\n context.queryClient.ensureQueryData(getTermsQueryOptions(lang)),\n context.queryClient.ensureQueryData(appConfigQueryOptions),\n ]);\n },\n});\n\nfunction Terms() {\n const { t, i18n } = useTranslation();\n const router = useRouter();\n const queryClient = useQueryClient();\n const search = Route.useSearch();\n\n const { data: configData } = useSuspenseQuery(appConfigQueryOptions);\n const lang = search.lang ?? i18n.language;\n const termsQuery = useSuspenseQuery(getTermsQueryOptions(lang));\n const implicitNotice =\n configData.registration.signup_notice?.[lang] ??\n configData.registration.signup_notice?.[configData.i18n.fallback_language];\n\n // Separate explicit and implicit terms\n const explicitTerms = useMemo(\n () =>\n termsQuery.data.terms.filter((term) => term.consentMode === 'explicit'),\n [termsQuery.data.terms],\n );\n\n const implicitTerms = useMemo(\n () =>\n termsQuery.data.terms.filter((term) => term.consentMode === 'implicit'),\n [termsQuery.data.terms],\n );\n\n const hasExplicitTerms = explicitTerms.length > 0;\n\n // Schema only validates explicit terms (implicit are auto-agreed)\n const termsSchema = useMemo(\n () =>\n z.object({\n termsConsents: z.object(\n Object.fromEntries(\n explicitTerms.map((term) => [\n term.id,\n term.required\n ? z.literal(true, {\n message: t('validation.terms.required'),\n })\n : z.boolean(),\n ]),\n ),\n ),\n }),\n [t, explicitTerms],\n );\n\n type TermsFormValues = TermsConsentsField;\n\n const {\n handleSubmit,\n control,\n setValue,\n formState: { errors },\n } = useForm<TermsFormValues>({\n defaultValues: {\n termsConsents: Object.fromEntries(\n explicitTerms.map((term) => [\n term.id,\n !!(term.userConsent?.agreed && !term.userConsent.requiresUpdate),\n ]),\n ),\n },\n resolver: standardSchemaResolver(termsSchema),\n mode: 'onChange',\n });\n\n const consentMutation = useMutation({\n ...termsConsentMutationOptions,\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: getSessionQueryOptions.queryKey,\n });\n await queryClient.fetchQuery(getSessionQueryOptions);\n await tick();\n\n // Redirect after successful consent\n if (search.redirect) {\n window.location.href = search.redirect;\n } else {\n router.navigate({ to: '/profile' });\n }\n },\n });\n\n const onSubmit = (values: TermsFormValues) => {\n const explicitConsents = Object.entries(\n values.termsConsents,\n ).map<TermsConsentItem>(([termsId, agreed]) => ({\n termsId,\n agreed,\n consentType: 'explicit',\n }));\n\n const implicitConsents = implicitTerms.map<TermsConsentItem>((term) => ({\n termsId: term.id,\n agreed: true,\n consentType: 'implicit',\n }));\n\n consentMutation.mutate({\n consents: [...explicitConsents, ...implicitConsents],\n ...(search.registration_token && {\n registrationToken: search.registration_token,\n }),\n });\n };\n\n return (\n <AuthLayout width=\"wide\">\n <AuthPageHeader title={t('terms.title')} />\n\n {implicitNotice && (\n <DesignSystemRichText html={implicitNotice} variant=\"notice\" />\n )}\n\n {implicitNotice && hasExplicitTerms && (\n <LabeledSeparator label={t('terms.additionalOptionalConsent')} />\n )}\n\n <TRForm\n className=\"flex flex-col gap-tinyrack-lg\"\n onSubmit={handleSubmit(onSubmit)}\n >\n {/* Explicit terms with checkboxes */}\n {hasExplicitTerms && (\n <TermsCheckboxList\n control={control}\n disabled={consentMutation.isPending}\n errors={errors}\n setValue={setValue}\n terms={explicitTerms}\n />\n )}\n\n {/* Error message */}\n {consentMutation.isError && (\n <Alert icon={TriangleAlertIcon} type=\"error\">\n {t('terms.error.submitFailed')}\n </Alert>\n )}\n\n {/*\n Sticky, like consent: a long list of terms would otherwise push the\n only action off the bottom of the screen.\n */}\n <div className=\"sticky bottom-0 flex gap-tinyrack-sm border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface py-tinyrack-md\">\n <TRButton\n className=\"w-full\"\n intent=\"primary\"\n loading={consentMutation.isPending}\n loadingLabel={t('terms.submit')}\n type=\"submit\"\n uiSize=\"lg\"\n >\n {t('terms.submit')}\n </TRButton>\n </div>\n </TRForm>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{X as e,Z as t,et as n,i as r,n as i,s as a}from"./createLucideIcon-D-yizrWN.js";import{t as o}from"./badge-B8D0Q2qq.js";import{t as s}from"./checkbox-DTPGfvmq.js";import{t as c}from"./modal-JuaLVSyx.js";import{t as l}from"./link-BHmn75Zo.js";import{t as u}from"./design-system-rich-text-B3NzIRoJ.js";import{i as d,n as f}from"./standard-schema-C50nwAaQ.js";var p=n(t(),1),m=e();function h({isOpen:e,onClose:t,title:n,content:r}){return(0,m.jsx)(c,{isOpen:e,onClose:t,size:`lg`,title:n,children:(0,m.jsx)(u,{className:`mt-tinyrack-md max-h-dvh overflow-y-auto`,html:r})})}function g({terms:e,control:t,setValue:n,errors:c,disabled:u=!1}){let{t:g}=r(),[v,y]=(0,p.useState)(null),b=d({control:t,name:`termsConsents`}),x=t=>{for(let r of e)n(`termsConsents.${r.id}`,t,{shouldValidate:!0})},S=e.every(e=>b?.[e.id]),C=e.some(e=>!e.required),w=c?.termsConsents,T=e=>e.title===e.id?_(e.id):e.title;return(0,m.jsxs)(m.Fragment,{children:[(0,m.jsxs)(`div`,{className:`space-y-tinyrack-xs`,children:[e.length>1&&(0,m.jsxs)(`div`,{className:`flex cursor-pointer items-center gap-tinyrack-sm py-tinyrack-2xs`,children:[(0,m.jsx)(s.Root,{"aria-labelledby":`terms-all-label`,checked:S,"data-testid":`terms-checkbox`,disabled:u,onCheckedChange:x,uiSize:`lg`,children:(0,m.jsx)(s.Indicator,{})}),(0,m.jsx)(i,{id:`terms-all-label`,variant:`caption`,weight:`medium`,children:g(`terms.agreeAll`)}),C&&(0,m.jsx)(i,{color:`muted`,variant:`caption`,children:g(`terms.agreeAllOptionalIncluded`)})]}),e.map(e=>(0,m.jsx)(f,{control:t,name:`termsConsents.${e.id}`,render:({field:t})=>(0,m.jsxs)(`div`,{children:[(0,m.jsxs)(`div`,{className:`flex items-center gap-tinyrack-sm py-tinyrack-2xs`,children:[(0,m.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-tinyrack-sm`,children:[(0,m.jsx)(s.Root,{"aria-labelledby":`term-label-${e.id}`,checked:t.value===!0,"data-testid":`terms-checkbox`,disabled:u,onCheckedChange:e=>t.onChange(e===!0),uiSize:`lg`,children:(0,m.jsx)(s.Indicator,{})}),(0,m.jsx)(i,{id:`term-label-${e.id}`,truncate:!0,variant:`caption`,children:T(e)}),(0,m.jsx)(o,{"data-testid":e.required?`terms-badge-required`:`terms-badge-optional`,uiSize:`md`,variant:e.required?`danger`:`neutral`,children:e.required?g(`terms.required`):g(`terms.optional`)})]}),e.type===`link`&&e.content&&(0,m.jsx)(l,{"aria-label":g(`terms.viewSpecific`,{title:T(e)}),className:`shrink-0 text-tinyrack-xs`,href:e.content,rel:`noopener noreferrer`,target:`_blank`,children:g(`terms.view`)}),e.type===`text`&&e.content&&(0,m.jsx)(a,{appearance:`ghost`,"aria-label":g(`terms.viewSpecific`,{title:T(e)}),className:`shrink-0 text-tinyrack-xs`,onClick:()=>y(e),type:`button`,uiSize:`sm`,children:g(`terms.view`)})]}),e.userConsent?.requiresUpdate&&(0,m.jsx)(i,{as:`p`,className:`ml-tinyrack-xl`,color:`warning`,variant:`caption`,children:g(`terms.versionUpdated`)}),w?.[e.id]&&(0,m.jsx)(i,{as:`p`,className:`ml-tinyrack-xl`,color:`danger`,"data-testid":`terms-field-error`,variant:`caption`,children:w[e.id]?.message})]})},e.id))]}),(0,m.jsx)(h,{content:v?.content??``,isOpen:v!==null,onClose:()=>y(null),title:v?.title??``})]})}function _(e){return e.replaceAll(`-`,` `).replaceAll(`_`,` `).replace(/([a-zA-Z])(\d)/g,`$1 $2`).split(` `).filter(e=>e.length>0).map(e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`).join(` `)}export{g as t};
2
+ //# sourceMappingURL=terms-checkbox-list-C9TkDC8Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terms-checkbox-list-C9TkDC8Y.js","names":[],"sources":["../../../frontend/src/components/terms/terms-content-modal.tsx","../../../frontend/src/components/terms/terms-checkbox-list.tsx"],"sourcesContent":["import { DesignSystemRichText } from '#frontend/components/ui/design-system-rich-text.tsx';\nimport { Modal } from '#frontend/components/ui/modal.tsx';\n\ntype TermsContentModalProps = {\n isOpen: boolean;\n onClose: () => void;\n title: string;\n content: string;\n};\n\nexport function TermsContentModal({\n isOpen,\n onClose,\n title,\n content,\n}: TermsContentModalProps) {\n return (\n <Modal isOpen={isOpen} onClose={onClose} size=\"lg\" title={title}>\n <DesignSystemRichText\n className=\"mt-tinyrack-md max-h-dvh overflow-y-auto\"\n html={content}\n />\n </Modal>\n );\n}\n","import { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCheckbox } from '@tinyrack/ui/components/checkbox';\nimport { TRLink } from '@tinyrack/ui/components/link';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { useState } from 'react';\nimport {\n type Control,\n Controller,\n type FieldErrors,\n type FieldValues,\n type Path,\n type PathValue,\n type UseFormSetValue,\n useWatch,\n} from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\n\nimport type { TermItem } from '#frontend/queries/terms.ts';\nimport { TermsContentModal } from './terms-content-modal.tsx';\n\nexport type TermsConsentsField = {\n termsConsents: Record<string, boolean>;\n};\n\ntype TermsCheckboxListProps<T extends FieldValues & TermsConsentsField> = {\n terms: TermItem[];\n control: Control<T>;\n setValue: UseFormSetValue<T>;\n errors?: FieldErrors<T>;\n disabled?: boolean;\n};\n\nexport function TermsCheckboxList<T extends FieldValues & TermsConsentsField>({\n terms,\n control,\n setValue,\n errors,\n disabled = false,\n}: TermsCheckboxListProps<T>) {\n const { t } = useTranslation();\n const [modalTerm, setModalTerm] = useState<TermItem | null>(null);\n\n const termsConsents = useWatch({\n control,\n name: 'termsConsents' as Path<T>,\n }) as Record<string, boolean> | undefined;\n\n const handleAllChange = (checked: boolean) => {\n for (const term of terms) {\n setValue(\n `termsConsents.${term.id}` as Path<T>,\n checked as PathValue<T, Path<T>>,\n { shouldValidate: true },\n );\n }\n };\n\n const allChecked = terms.every((term) => termsConsents?.[term.id]);\n\n const hasOptionalTerms = terms.some((term) => !term.required);\n\n const termsConsentsErrors = errors?.termsConsents as\n | Record<string, { message?: string }>\n | undefined;\n\n const getTermTitle = (term: TermItem) => {\n if (term.title !== term.id) {\n return term.title;\n }\n\n return humanizeTermId(term.id);\n };\n\n return (\n <>\n {/* tinyrack-check-ignore-next-line components/no-native-text -- Structural terms list; all labels and errors use TRText. */}\n <div className=\"space-y-tinyrack-xs\">\n {terms.length > 1 && (\n /* tinyrack-check-ignore-next-line components/no-native-text -- Structural checkbox row containing DS controls and TRText. */\n <div className=\"flex cursor-pointer items-center gap-tinyrack-sm py-tinyrack-2xs\">\n <TRCheckbox.Root\n aria-labelledby=\"terms-all-label\"\n checked={allChecked}\n data-testid=\"terms-checkbox\"\n disabled={disabled}\n onCheckedChange={handleAllChange}\n uiSize=\"lg\"\n >\n <TRCheckbox.Indicator />\n </TRCheckbox.Root>\n <TRText id=\"terms-all-label\" variant=\"caption\" weight=\"medium\">\n {t('terms.agreeAll')}\n </TRText>\n {hasOptionalTerms && (\n <TRText color=\"muted\" variant=\"caption\">\n {t('terms.agreeAllOptionalIncluded')}\n </TRText>\n )}\n </div>\n )}\n\n {terms.map((term) => (\n <Controller\n control={control}\n key={term.id}\n name={`termsConsents.${term.id}` as Path<T>}\n render={({ field }) => (\n /* tinyrack-check-ignore-next-line components/no-native-text -- Structural term state wrapper. */\n <div>\n {/* tinyrack-check-ignore-next-line components/no-native-text -- Structural term row containing DS controls and TRText. */}\n <div className=\"flex items-center gap-tinyrack-sm py-tinyrack-2xs\">\n {/* tinyrack-check-ignore-next-line components/no-native-text -- Structural label group. */}\n <div className=\"flex min-w-0 flex-1 items-center gap-tinyrack-sm\">\n <TRCheckbox.Root\n aria-labelledby={`term-label-${term.id}`}\n checked={field.value === true}\n data-testid=\"terms-checkbox\"\n disabled={disabled}\n onCheckedChange={(checked) =>\n field.onChange(checked === true)\n }\n uiSize=\"lg\"\n >\n <TRCheckbox.Indicator />\n </TRCheckbox.Root>\n <TRText\n id={`term-label-${term.id}`}\n truncate\n variant=\"caption\"\n >\n {getTermTitle(term)}\n </TRText>\n <TRBadge\n data-testid={\n term.required\n ? 'terms-badge-required'\n : 'terms-badge-optional'\n }\n uiSize=\"md\"\n variant={term.required ? 'danger' : 'neutral'}\n >\n {term.required\n ? t('terms.required')\n : t('terms.optional')}\n </TRBadge>\n </div>\n {term.type === 'link' && term.content && (\n <TRLink\n aria-label={t('terms.viewSpecific', {\n title: getTermTitle(term),\n })}\n className=\"shrink-0 text-tinyrack-xs\"\n href={term.content}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n {t('terms.view')}\n </TRLink>\n )}\n {term.type === 'text' && term.content && (\n <TRButton\n appearance=\"ghost\"\n aria-label={t('terms.viewSpecific', {\n title: getTermTitle(term),\n })}\n className=\"shrink-0 text-tinyrack-xs\"\n onClick={() => setModalTerm(term)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('terms.view')}\n </TRButton>\n )}\n </div>\n {term.userConsent?.requiresUpdate && (\n <TRText\n as=\"p\"\n className=\"ml-tinyrack-xl\"\n color=\"warning\"\n variant=\"caption\"\n >\n {t('terms.versionUpdated')}\n </TRText>\n )}\n {termsConsentsErrors?.[term.id] && (\n <TRText\n as=\"p\"\n className=\"ml-tinyrack-xl\"\n color=\"danger\"\n data-testid=\"terms-field-error\"\n variant=\"caption\"\n >\n {termsConsentsErrors[term.id]?.message}\n </TRText>\n )}\n </div>\n )}\n />\n ))}\n </div>\n\n <TermsContentModal\n content={modalTerm?.content ?? ''}\n isOpen={modalTerm !== null}\n onClose={() => setModalTerm(null)}\n title={modalTerm?.title ?? ''}\n />\n </>\n );\n}\n\nfunction humanizeTermId(id: string): string {\n const words = id\n .replaceAll('-', ' ')\n .replaceAll('_', ' ')\n .replace(/([a-zA-Z])(\\d)/g, '$1 $2')\n .split(' ')\n .filter((word) => word.length > 0);\n\n return words\n .map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`)\n .join(' ');\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{X as e}from"./createLucideIcon-D-yizrWN.js";import{B as t}from"./index-lTEyHSus.js";var n=e();function r(e){return(0,n.jsx)(t,{...e,onUnauthorized:()=>{window.location.href=`/login`}})}export{r as errorComponent};
2
+ //# sourceMappingURL=terms-k66ruDWl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terms-k66ruDWl.js","names":["RouteErrorFallback","TermsError","props","ErrorComponentProps","window","location","href","errorComponent"],"sources":["../../../frontend/src/routes/terms/index.tsx?tsr-split=errorComponent"],"sourcesContent":["import { standardSchemaResolver } from '@hookform/resolvers/standard-schema';\nimport {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from '@tanstack/react-query';\nimport {\n createFileRoute,\n type ErrorComponentProps,\n redirect,\n useRouter,\n} from '@tanstack/react-router';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRForm } from '@tinyrack/ui/components/form';\nimport { TriangleAlertIcon } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport { z } from 'zod';\nimport { AuthPageHeader } from '#frontend/components/auth/auth-page-header.tsx';\nimport {\n TermsCheckboxList,\n type TermsConsentsField,\n} from '#frontend/components/terms/terms-checkbox-list.tsx';\nimport { Alert } from '#frontend/components/ui/alert.tsx';\nimport { DesignSystemRichText } from '#frontend/components/ui/design-system-rich-text.tsx';\nimport { LabeledSeparator } from '#frontend/components/ui/labeled-separator.tsx';\nimport { RouteErrorFallback } from '#frontend/components/ui/route-error-fallback.tsx';\nimport { AuthLayout } from '#frontend/features/layout/auth-layout.tsx';\nimport { OAuthSearchSchema } from '#frontend/libs/oauth-search.ts';\nimport { tick } from '#frontend/libs/promise.ts';\nimport { appConfigQueryOptions } from '#frontend/queries/config.ts';\nimport { getSessionQueryOptions } from '#frontend/queries/session.ts';\nimport {\n getTermsQueryOptions,\n type TermsConsentItem,\n termsConsentMutationOptions,\n} from '#frontend/queries/terms.ts';\n\nconst TermsSearchSchema = OAuthSearchSchema.extend({\n redirect: z.string().optional(),\n lang: z.string().optional(),\n mode: z.enum(['normal', 'complete_registration']).optional(),\n registration_token: z.string().optional(),\n});\n\nfunction TermsError(props: ErrorComponentProps) {\n return (\n <RouteErrorFallback\n {...props}\n onUnauthorized={() => {\n window.location.href = '/login';\n }}\n />\n );\n}\n\nexport const Route = createFileRoute('/terms/')({\n component: Terms,\n errorComponent: TermsError,\n validateSearch: TermsSearchSchema,\n beforeLoad: async ({ context, search }) => {\n // When mode=complete_registration, user is completing OAuth signup.\n // The registration_token in the URL references a DB record with OAuth data.\n // Skip auth check — backend will validate the token on consent submission.\n if (search.mode === 'complete_registration') {\n return;\n }\n\n // Standard mode: requires authentication\n // Users are redirected here after OAuth login when they need to agree to terms\n if (!context.user) {\n throw redirect({\n to: '/login',\n });\n }\n },\n loaderDeps: ({ search }) => ({\n lang: search.lang,\n }),\n loader: async ({ context, deps }) => {\n const lang = deps.lang ?? context.i18n.language;\n await Promise.all([\n context.queryClient.ensureQueryData(getTermsQueryOptions(lang)),\n context.queryClient.ensureQueryData(appConfigQueryOptions),\n ]);\n },\n});\n\nfunction Terms() {\n const { t, i18n } = useTranslation();\n const router = useRouter();\n const queryClient = useQueryClient();\n const search = Route.useSearch();\n\n const { data: configData } = useSuspenseQuery(appConfigQueryOptions);\n const lang = search.lang ?? i18n.language;\n const termsQuery = useSuspenseQuery(getTermsQueryOptions(lang));\n const implicitNotice =\n configData.registration.signup_notice?.[lang] ??\n configData.registration.signup_notice?.[configData.i18n.fallback_language];\n\n // Separate explicit and implicit terms\n const explicitTerms = useMemo(\n () =>\n termsQuery.data.terms.filter((term) => term.consentMode === 'explicit'),\n [termsQuery.data.terms],\n );\n\n const implicitTerms = useMemo(\n () =>\n termsQuery.data.terms.filter((term) => term.consentMode === 'implicit'),\n [termsQuery.data.terms],\n );\n\n const hasExplicitTerms = explicitTerms.length > 0;\n\n // Schema only validates explicit terms (implicit are auto-agreed)\n const termsSchema = useMemo(\n () =>\n z.object({\n termsConsents: z.object(\n Object.fromEntries(\n explicitTerms.map((term) => [\n term.id,\n term.required\n ? z.literal(true, {\n message: t('validation.terms.required'),\n })\n : z.boolean(),\n ]),\n ),\n ),\n }),\n [t, explicitTerms],\n );\n\n type TermsFormValues = TermsConsentsField;\n\n const {\n handleSubmit,\n control,\n setValue,\n formState: { errors },\n } = useForm<TermsFormValues>({\n defaultValues: {\n termsConsents: Object.fromEntries(\n explicitTerms.map((term) => [\n term.id,\n !!(term.userConsent?.agreed && !term.userConsent.requiresUpdate),\n ]),\n ),\n },\n resolver: standardSchemaResolver(termsSchema),\n mode: 'onChange',\n });\n\n const consentMutation = useMutation({\n ...termsConsentMutationOptions,\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: getSessionQueryOptions.queryKey,\n });\n await queryClient.fetchQuery(getSessionQueryOptions);\n await tick();\n\n // Redirect after successful consent\n if (search.redirect) {\n window.location.href = search.redirect;\n } else {\n router.navigate({ to: '/profile' });\n }\n },\n });\n\n const onSubmit = (values: TermsFormValues) => {\n const explicitConsents = Object.entries(\n values.termsConsents,\n ).map<TermsConsentItem>(([termsId, agreed]) => ({\n termsId,\n agreed,\n consentType: 'explicit',\n }));\n\n const implicitConsents = implicitTerms.map<TermsConsentItem>((term) => ({\n termsId: term.id,\n agreed: true,\n consentType: 'implicit',\n }));\n\n consentMutation.mutate({\n consents: [...explicitConsents, ...implicitConsents],\n ...(search.registration_token && {\n registrationToken: search.registration_token,\n }),\n });\n };\n\n return (\n <AuthLayout width=\"wide\">\n <AuthPageHeader title={t('terms.title')} />\n\n {implicitNotice && (\n <DesignSystemRichText html={implicitNotice} variant=\"notice\" />\n )}\n\n {implicitNotice && hasExplicitTerms && (\n <LabeledSeparator label={t('terms.additionalOptionalConsent')} />\n )}\n\n <TRForm\n className=\"flex flex-col gap-tinyrack-lg\"\n onSubmit={handleSubmit(onSubmit)}\n >\n {/* Explicit terms with checkboxes */}\n {hasExplicitTerms && (\n <TermsCheckboxList\n control={control}\n disabled={consentMutation.isPending}\n errors={errors}\n setValue={setValue}\n terms={explicitTerms}\n />\n )}\n\n {/* Error message */}\n {consentMutation.isError && (\n <Alert icon={TriangleAlertIcon} type=\"error\">\n {t('terms.error.submitFailed')}\n </Alert>\n )}\n\n {/*\n Sticky, like consent: a long list of terms would otherwise push the\n only action off the bottom of the screen.\n */}\n <div className=\"sticky bottom-0 flex gap-tinyrack-sm border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface py-tinyrack-md\">\n <TRButton\n className=\"w-full\"\n intent=\"primary\"\n loading={consentMutation.isPending}\n loadingLabel={t('terms.submit')}\n type=\"submit\"\n uiSize=\"lg\"\n >\n {t('terms.submit')}\n </TRButton>\n </div>\n </TRForm>\n </AuthLayout>\n );\n}\n"],"mappings":"qGA8CA,SAASC,EAAWC,EAA4B,CAC9C,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,GAAIA,EACJ,mBAAsB,CACpBE,OAAOC,SAASC,KAAO,QACzB,CAAE,CAAA,CAGR"}
@@ -0,0 +1,2 @@
1
+ import{K as e,X as t,Z as n,et as r,i,n as a,q as o,r as s,s as c,t as l}from"./createLucideIcon-D-yizrWN.js";import{An as u,Ar as ee,In as te}from"./config-C18-l7z7.js";import{a as d,i as f,n as p,r as m,t as h}from"./use-totp-setup-KOVNS2DC.js";import{t as g}from"./shield-check-DpYF8yeI.js";import{E as _,F as v,H as ne,L as y,h as re,z as ie}from"./index-lTEyHSus.js";import{t as b}from"./auth-page-header-ChaCNNrn.js";import{t as x}from"./alert-kRxM1xsM.js";import{t as S}from"./alert-D3aaK-_3.js";import{t as ae}from"./auth-layout-BdRRr0vT.js";import{t as C}from"./promise-OpBtq8tG.js";import{n as w,t as T}from"./auth-footer-Du6S-oDG.js";var oe=l(`circle-x`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m15 9-6 6`,key:`1uzhvr`}],[`path`,{d:`m9 9 6 6`,key:`z0biqf`}]]),E=r(n()),D=t();function O({className:e,role:t=`list`,...n}){return(0,D.jsx)(`ol`,{...n,className:o(`tr-steps`,e),role:t})}function k({className:e,...t}){return(0,D.jsx)(`li`,{...t,className:o(`tr-steps-item`,e)})}function A({className:e,current:t,total:n,...r}){let i=Math.max(1,n),a=Math.min(Math.max(1,t),i);return(0,D.jsx)(`div`,{...r,"aria-valuemax":i,"aria-valuemin":1,"aria-valuenow":a,className:o(`tr-steps-progress`,e),role:`progressbar`,children:Array.from({length:i},(e,t)=>String(t+1)).map(e=>(0,D.jsx)(`span`,{"aria-hidden":`true`,className:`tr-steps-progress-segment`,"data-complete":Number(e)<=a?`true`:void 0},e))})}var j={Item:k,Progress:A,Root:O};function M({steps:e,current:t,progressLabel:n}){return(0,D.jsxs)(`div`,{className:`flex w-full flex-col gap-tinyrack-xs`,children:[(0,D.jsxs)(`div`,{className:`flex items-baseline justify-between gap-tinyrack-sm`,children:[(0,D.jsx)(a,{color:`muted`,variant:`label`,children:n}),(0,D.jsx)(a,{color:`muted`,variant:`caption`,children:e[t]})]}),(0,D.jsx)(j.Progress,{"aria-label":n,current:t+1,total:e.length})]})}var N={TOTP_ALREADY_ENABLED:`TOTP_ALREADY_ENABLED`,TOTP_NOT_SETUP:`TOTP_NOT_SETUP`,INVALID_TOTP_CODE:`INVALID_TOTP_CODE`,UNAUTHORIZED:`UNAUTHORIZED`,SECOND_FACTOR_SESSION_EXPIRED:`SECOND_FACTOR_SESSION_EXPIRED`},P=5;function F(){let{t}=i(),n=te(),r=ee(),a=re.useSearch(),[o,l]=(0,E.useState)(`generic`),[O,k]=(0,E.useState)(P),A=(0,E.useCallback)(()=>{n.navigate({to:`/login`,search:y(a)})},[n,a]),j=(0,E.useCallback)(()=>{n.navigate({to:`/profile`})},[n]),{step:F,setupData:I,recoveryCodes:L,isSetupPending:R,isVerifyPending:z,isConfirmPending:B,startSetup:V,verify:H,goToQr:U,goToVerify:W,confirmRecoveryCodes:G}=h({autoStart:!0,onSetupError:(0,E.useCallback)(e=>{if(e instanceof s)switch(e.code){case N.TOTP_ALREADY_ENABLED:l(`already_enabled`);break;case N.UNAUTHORIZED:case N.SECOND_FACTOR_SESSION_EXPIRED:l(`session_expired`),k(P);break;default:l(`generic`)}else l(`generic`)},[]),onVerifySuccess:(0,E.useCallback)(async e=>{await C()},[]),onConfirmSuccess:(0,E.useCallback)(async e=>{r.setQueryData(_.queryKey,{user:e.user}),await C(),ie(a)?window.location.href=v(a):n.navigate({to:`/profile`})},[r,n,a]),onVerifyError:e=>{if(e instanceof s)switch(e.code){case N.TOTP_ALREADY_ENABLED:j();break;case N.UNAUTHORIZED:case N.SECOND_FACTOR_SESSION_EXPIRED:l(`session_expired`),k(P);break;case N.TOTP_NOT_SETUP:V();break}}});(0,E.useEffect)(()=>{if(o!==`session_expired`||F!==`error`)return;let e=setInterval(()=>{k(t=>t<=1?(clearInterval(e),A(),0):t-1)},1e3);return()=>clearInterval(e)},[o,F,A]);let K=(0,E.useCallback)(async e=>{await H(e)},[H]),q=F===`recovery`&&L.length>0,J=F===`qr`&&I!==null,Y=F!==`loading`&&F!==`error`,X=1;q?X=2:J&&(X=0);let Z=t(`setupTotp.title`),Q=t(`setupTotp.subtitle`);q?Z=t(`setupTotp.recoveryCodes.title`):Y&&!J&&(Z=t(`setupTotp.verifyTitle`),Q=t(`setupTotp.verifySubtitle`));let se=F===`error`||J,$;return $=F===`loading`?(0,D.jsx)(`div`,{className:`flex justify-center py-tinyrack-xl`,"data-testid":`totp-setup-loading`,children:(0,D.jsx)(e,{uiSize:`lg`,variant:`primary`})}):F===`error`&&o===`session_expired`?(0,D.jsxs)(x.Root,{"data-testid":`totp-setup-session-expired`,variant:`warning`,children:[(0,D.jsx)(ne,{"aria-hidden":!0,className:`size-tinyrack-xl`}),(0,D.jsx)(x.Title,{children:t(`setupTotp.error.expired`)}),(0,D.jsx)(x.Description,{children:t(`setupTotp.redirecting`,{seconds:O})}),(0,D.jsx)(x.Actions,{children:(0,D.jsx)(c,{appearance:`ghost`,intent:`neutral`,onClick:A,type:`button`,uiSize:`sm`,children:t(`setupTotp.redirectNow`)})})]}):F===`error`&&o===`already_enabled`?(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(S,{icon:d,type:`info`,children:t(`setupTotp.error.alreadyEnabled`)}),(0,D.jsx)(c,{className:`w-full`,intent:`primary`,onClick:j,type:`button`,uiSize:`lg`,children:t(`setupTotp.goToProfile`)})]}):F===`error`?(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(S,{icon:oe,type:`error`,children:t(`setupTotp.error.setupFailed`)}),(0,D.jsx)(c,{className:`w-full`,disabled:R,intent:`primary`,loading:R,onClick:V,type:`button`,uiSize:`lg`,children:t(`setupTotp.retry`)})]}):q?(0,D.jsx)(f,{isLoading:B,onConfirm:G,recoveryCodes:L}):J&&I?(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(S,{icon:g,type:`info`,children:t(`setupTotp.required`)}),(0,D.jsx)(p,{onNext:W,setupData:I})]}):(0,D.jsx)(m,{isPending:z,onBack:U,onSubmit:K}),(0,D.jsxs)(ae,{width:q?`wide`:`form`,children:[(0,D.jsx)(b,{eyebrow:Y?(0,D.jsx)(M,{current:X,progressLabel:t(`setupTotp.stepProgress`,{current:X+1,total:3}),steps:[t(`setupTotp.steps.scan`),t(`setupTotp.steps.verify`),t(`setupTotp.steps.saveCodes`)]}):void 0,subtitle:Q,title:Z}),(0,D.jsx)(`div`,{className:`auth-enter flex flex-col gap-tinyrack-lg`,children:$},F),se&&(0,D.jsx)(T,{children:(0,D.jsx)(w,{link:(0,D.jsx)(u,{search:y(a),to:`/login`,children:t(`setupTotp.backToLogin`)})})})]})}export{F as component};
2
+ //# sourceMappingURL=totp-BJycMMTC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"totp-BJycMMTC.js","names":["useQueryClient","Link","useRouter","TRAlert","TRButton","TRSpinner","CircleAlertIcon","CircleXIcon","InfoIcon","ShieldCheckIcon","useCallback","useEffect","useState","useTranslation","AuthFooter","AuthFooterLink","AuthPageHeader","AuthSteps","QrStep","RecoveryCodesStep","VerifyStep","Alert","AuthLayout","useTotpSetup","IssuaryError","buildAuthenticatedAuthorizeUrl","extractOAuthParams","isOAuthFlow","tick","getSessionQueryOptions","ERROR_CODES","TOTP_ALREADY_ENABLED","TOTP_NOT_SETUP","INVALID_TOTP_CODE","UNAUTHORIZED","SECOND_FACTOR_SESSION_EXPIRED","const","Route","ErrorType","REDIRECT_COUNTDOWN_SECONDS","SetupTotp","t","router","queryClient","search","useSearch","errorType","setErrorType","redirectCountdown","setRedirectCountdown","redirectToLogin","navigate","to","redirectToProfile","handleSetupError","error","Error","code","handleVerifySuccess","_data","TotpSetupVerifyResponse","handleConfirmSuccess","data","TotpConfirmResponse","setQueryData","queryKey","user","window","location","href","step","setupData","recoveryCodes","isSetupPending","isVerifyPending","isConfirmPending","startSetup","verify","goToQr","goToVerify","confirmRecoveryCodes","autoStart","onSetupError","onVerifySuccess","onConfirmSuccess","onVerifyError","timer","setInterval","prev","clearInterval","handleVerify","isRecoveryStep","length","isQrStep","isWizardStep","wizardIndex","title","subtitle","showFooter","body","React","ReactNode","seconds","current","total","undefined","component"],"sources":["../../../../node_modules/.pnpm/lucide-react@1.25.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/circle-x.mjs","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/steps/steps.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.31.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.4.2_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/steps/index.js","../../../frontend/src/components/auth/auth-steps.tsx","../../../frontend/src/routes/setup/totp/index.tsx?tsr-split=component"],"sourcesContent":["/**\n * @license lucide-react v1.25.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n];\nconst CircleX = createLucideIcon(\"circle-x\", __iconNode);\n\nexport { __iconNode, CircleX as default };\n//# sourceMappingURL=circle-x.mjs.map\n","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/steps/steps.tsx\nfunction TRStepsRoot({ className, role = \"list\", ...props }) {\n\treturn /* @__PURE__ */ jsx(\"ol\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-steps\", className),\n\t\trole\n\t});\n}\nfunction TRStepsItem({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"li\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-steps-item\", className)\n\t});\n}\nfunction TRStepsProgress({ className, current, total, ...props }) {\n\tconst safeTotal = Math.max(1, total);\n\tconst safeCurrent = Math.min(Math.max(1, current), safeTotal);\n\treturn /* @__PURE__ */ jsx(\"div\", {\n\t\t...props,\n\t\t\"aria-valuemax\": safeTotal,\n\t\t\"aria-valuemin\": 1,\n\t\t\"aria-valuenow\": safeCurrent,\n\t\tclassName: mergeClassNames(\"tr-steps-progress\", className),\n\t\trole: \"progressbar\",\n\t\tchildren: Array.from({ length: safeTotal }, (_, index) => String(index + 1)).map((step) => /* @__PURE__ */ jsx(\"span\", {\n\t\t\t\"aria-hidden\": \"true\",\n\t\t\tclassName: \"tr-steps-progress-segment\",\n\t\t\t\"data-complete\": Number(step) <= safeCurrent ? \"true\" : void 0\n\t\t}, step))\n\t});\n}\n//#endregion\nexport { TRStepsItem, TRStepsProgress, TRStepsRoot };\n\n//# sourceMappingURL=steps.js.map","import { TRStepsItem, TRStepsProgress, TRStepsRoot } from \"./steps.js\";\n//#region src/components/steps/index.tsx\nconst TRSteps = {\n\tItem: TRStepsItem,\n\tProgress: TRStepsProgress,\n\tRoot: TRStepsRoot\n};\n//#endregion\nexport { TRSteps, TRStepsItem, TRStepsProgress, TRStepsRoot };\n\n//# sourceMappingURL=index.js.map","import { TRSteps } from '@tinyrack/ui/components/steps';\nimport { TRText } from '@tinyrack/ui/components/text';\n\ntype AuthStepsProps = {\n /** Ordered step labels. The current one is announced to assistive tech. */\n steps: string[];\n /** Zero-based index of the step being shown. */\n current: number;\n /** e.g. \"Step {{current}} of {{total}}\" — already interpolated by the caller. */\n progressLabel: string;\n};\n\nexport function AuthSteps({ steps, current, progressLabel }: AuthStepsProps) {\n return (\n <div className=\"flex w-full flex-col gap-tinyrack-xs\">\n <div className=\"flex items-baseline justify-between gap-tinyrack-sm\">\n <TRText color=\"muted\" variant=\"label\">\n {progressLabel}\n </TRText>\n <TRText color=\"muted\" variant=\"caption\">\n {steps[current]}\n </TRText>\n </div>\n <TRSteps.Progress\n aria-label={progressLabel}\n current={current + 1}\n total={steps.length}\n />\n </div>\n );\n}\n","import { useQueryClient } from '@tanstack/react-query';\nimport { createFileRoute, Link, useRouter } from '@tanstack/react-router';\nimport { TRAlert } from '@tinyrack/ui/components/alert';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRSpinner } from '@tinyrack/ui/components/spinner';\nimport {\n CircleAlertIcon,\n CircleXIcon,\n InfoIcon,\n ShieldCheckIcon,\n} from 'lucide-react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n AuthFooter,\n AuthFooterLink,\n} from '#frontend/components/auth/auth-footer.tsx';\nimport { AuthPageHeader } from '#frontend/components/auth/auth-page-header.tsx';\nimport { AuthSteps } from '#frontend/components/auth/auth-steps.tsx';\nimport { QrStep } from '#frontend/components/totp/qr-step.tsx';\nimport { RecoveryCodesStep } from '#frontend/components/totp/recovery-codes-step.tsx';\nimport { VerifyStep } from '#frontend/components/totp/verify-step.tsx';\nimport { Alert } from '#frontend/components/ui/alert.tsx';\nimport { AuthLayout } from '#frontend/features/layout/auth-layout.tsx';\nimport { useTotpSetup } from '#frontend/features/totp/use-totp-setup.ts';\nimport { IssuaryError } from '#frontend/libs/error.ts';\nimport {\n buildAuthenticatedAuthorizeUrl,\n extractOAuthParams,\n isOAuthFlow,\n OAuthSearchSchema,\n} from '#frontend/libs/oauth-search.ts';\nimport { tick } from '#frontend/libs/promise.ts';\nimport { getSessionQueryOptions } from '#frontend/queries/session.ts';\nimport type {\n TotpConfirmResponse,\n TotpSetupVerifyResponse,\n} from '#frontend/queries/totp.ts';\n\n/** Error codes from backend */\nconst ERROR_CODES = {\n TOTP_ALREADY_ENABLED: 'TOTP_ALREADY_ENABLED',\n TOTP_NOT_SETUP: 'TOTP_NOT_SETUP',\n INVALID_TOTP_CODE: 'INVALID_TOTP_CODE',\n UNAUTHORIZED: 'UNAUTHORIZED',\n SECOND_FACTOR_SESSION_EXPIRED: 'SECOND_FACTOR_SESSION_EXPIRED',\n} as const;\n\nconst SearchSchema = OAuthSearchSchema;\n\nexport const Route = createFileRoute('/setup/totp/')({\n component: SetupTotp,\n validateSearch: SearchSchema,\n});\n\ntype ErrorType = 'generic' | 'already_enabled' | 'session_expired';\n\n/** Auto redirect countdown seconds */\nconst REDIRECT_COUNTDOWN_SECONDS = 5;\n\nfunction SetupTotp() {\n const { t } = useTranslation();\n const router = useRouter();\n const queryClient = useQueryClient();\n const search = Route.useSearch();\n\n const [errorType, setErrorType] = useState<ErrorType>('generic');\n const [redirectCountdown, setRedirectCountdown] = useState(\n REDIRECT_COUNTDOWN_SECONDS,\n );\n\n const redirectToLogin = useCallback(() => {\n router.navigate({\n to: '/login',\n search: extractOAuthParams(search),\n });\n }, [router, search]);\n\n const redirectToProfile = useCallback(() => {\n router.navigate({ to: '/profile' });\n }, [router]);\n\n const handleSetupError = useCallback((error: Error) => {\n if (error instanceof IssuaryError) {\n switch (error.code) {\n case ERROR_CODES.TOTP_ALREADY_ENABLED:\n setErrorType('already_enabled');\n break;\n case ERROR_CODES.UNAUTHORIZED:\n case ERROR_CODES.SECOND_FACTOR_SESSION_EXPIRED:\n setErrorType('session_expired');\n setRedirectCountdown(REDIRECT_COUNTDOWN_SECONDS);\n break;\n default:\n setErrorType('generic');\n }\n } else {\n setErrorType('generic');\n }\n }, []);\n\n const handleVerifySuccess = useCallback(\n async (_data: TotpSetupVerifyResponse) => {\n // Recovery codes step is handled by useTotpSetup hook\n // (step transitions to 'recovery' automatically)\n // Session update happens after confirm, not here\n await tick();\n },\n [],\n );\n\n const handleConfirmSuccess = useCallback(\n async (data: TotpConfirmResponse) => {\n queryClient.setQueryData(getSessionQueryOptions.queryKey, {\n user: data.user,\n });\n await tick();\n // Navigate after successful confirm\n if (isOAuthFlow(search)) {\n window.location.href = buildAuthenticatedAuthorizeUrl(search);\n } else {\n router.navigate({ to: '/profile' });\n }\n },\n [queryClient, router, search],\n );\n\n const {\n step,\n setupData,\n recoveryCodes,\n isSetupPending,\n isVerifyPending,\n isConfirmPending,\n startSetup,\n verify,\n goToQr,\n goToVerify,\n confirmRecoveryCodes,\n } = useTotpSetup({\n autoStart: true,\n onSetupError: handleSetupError,\n onVerifySuccess: handleVerifySuccess,\n onConfirmSuccess: handleConfirmSuccess,\n onVerifyError: (error) => {\n if (error instanceof IssuaryError) {\n switch (error.code) {\n case ERROR_CODES.TOTP_ALREADY_ENABLED:\n redirectToProfile();\n break;\n case ERROR_CODES.UNAUTHORIZED:\n case ERROR_CODES.SECOND_FACTOR_SESSION_EXPIRED:\n setErrorType('session_expired');\n setRedirectCountdown(REDIRECT_COUNTDOWN_SECONDS);\n break;\n case ERROR_CODES.TOTP_NOT_SETUP:\n startSetup();\n break;\n }\n }\n },\n });\n\n // Auto redirect when session expires\n useEffect(() => {\n if (errorType !== 'session_expired' || step !== 'error') return;\n\n const timer = setInterval(() => {\n setRedirectCountdown((prev) => {\n if (prev <= 1) {\n clearInterval(timer);\n redirectToLogin();\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(timer);\n }, [errorType, step, redirectToLogin]);\n\n const handleVerify = useCallback(\n async (code: string) => {\n await verify(code);\n },\n [verify],\n );\n\n const isRecoveryStep = step === 'recovery' && recoveryCodes.length > 0;\n const isQrStep = step === 'qr' && setupData !== null;\n // `loading` and `error` are not points on the journey, so the wizard's\n // progress is hidden there rather than showing a misleading step.\n const isWizardStep = step !== 'loading' && step !== 'error';\n\n let wizardIndex = 1;\n if (isRecoveryStep) {\n wizardIndex = 2;\n } else if (isQrStep) {\n wizardIndex = 0;\n }\n\n let title = t('setupTotp.title');\n let subtitle: string | undefined = t('setupTotp.subtitle');\n if (isRecoveryStep) {\n title = t('setupTotp.recoveryCodes.title');\n } else if (isWizardStep && !isQrStep) {\n title = t('setupTotp.verifyTitle');\n subtitle = t('setupTotp.verifySubtitle');\n }\n\n // Where the original screens offered a way out: the wizard's later steps\n // deliberately do not, so nobody leaves before saving their codes.\n const showFooter = step === 'error' || isQrStep;\n\n let body: React.ReactNode;\n if (step === 'loading') {\n body = (\n <div\n className=\"flex justify-center py-tinyrack-xl\"\n data-testid=\"totp-setup-loading\"\n >\n <TRSpinner uiSize=\"lg\" variant=\"primary\" />\n </div>\n );\n } else if (step === 'error' && errorType === 'session_expired') {\n body = (\n <TRAlert.Root data-testid=\"totp-setup-session-expired\" variant=\"warning\">\n <CircleAlertIcon aria-hidden className=\"size-tinyrack-xl\" />\n <TRAlert.Title>{t('setupTotp.error.expired')}</TRAlert.Title>\n <TRAlert.Description>\n {t('setupTotp.redirecting', {\n seconds: redirectCountdown,\n })}\n </TRAlert.Description>\n <TRAlert.Actions>\n <TRButton\n appearance=\"ghost\"\n intent=\"neutral\"\n onClick={redirectToLogin}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('setupTotp.redirectNow')}\n </TRButton>\n </TRAlert.Actions>\n </TRAlert.Root>\n );\n } else if (step === 'error' && errorType === 'already_enabled') {\n body = (\n <>\n <Alert icon={InfoIcon} type=\"info\">\n {t('setupTotp.error.alreadyEnabled')}\n </Alert>\n <TRButton\n className=\"w-full\"\n intent=\"primary\"\n onClick={redirectToProfile}\n type=\"button\"\n uiSize=\"lg\"\n >\n {t('setupTotp.goToProfile')}\n </TRButton>\n </>\n );\n } else if (step === 'error') {\n body = (\n <>\n <Alert icon={CircleXIcon} type=\"error\">\n {t('setupTotp.error.setupFailed')}\n </Alert>\n <TRButton\n className=\"w-full\"\n disabled={isSetupPending}\n intent=\"primary\"\n loading={isSetupPending}\n onClick={startSetup}\n type=\"button\"\n uiSize=\"lg\"\n >\n {t('setupTotp.retry')}\n </TRButton>\n </>\n );\n } else if (isRecoveryStep) {\n body = (\n <RecoveryCodesStep\n isLoading={isConfirmPending}\n onConfirm={confirmRecoveryCodes}\n recoveryCodes={recoveryCodes}\n />\n );\n } else if (isQrStep && setupData) {\n body = (\n <>\n <Alert icon={ShieldCheckIcon} type=\"info\">\n {t('setupTotp.required')}\n </Alert>\n <QrStep onNext={goToVerify} setupData={setupData} />\n </>\n );\n } else {\n body = (\n <VerifyStep\n isPending={isVerifyPending}\n onBack={goToQr}\n onSubmit={handleVerify}\n />\n );\n }\n\n /*\n One shell, one header. The seven `AuthLayout` blocks this replaced meant\n the header remounted on every transition, so the title flashed and the\n progress had nowhere to live.\n */\n return (\n <AuthLayout width={isRecoveryStep ? 'wide' : 'form'}>\n <AuthPageHeader\n eyebrow={\n isWizardStep ? (\n <AuthSteps\n current={wizardIndex}\n progressLabel={t('setupTotp.stepProgress', {\n current: wizardIndex + 1,\n total: 3,\n })}\n steps={[\n t('setupTotp.steps.scan'),\n t('setupTotp.steps.verify'),\n t('setupTotp.steps.saveCodes'),\n ]}\n />\n ) : undefined\n }\n subtitle={subtitle}\n title={title}\n />\n\n {/* Keyed so each step animates in rather than swapping in place. */}\n {/* tinyrack-check-ignore-next-line components/no-native-text -- Structural animated step host; each step owns visible typography. */}\n <div className=\"auth-enter flex flex-col gap-tinyrack-lg\" key={step}>\n {body}\n </div>\n\n {showFooter && (\n <AuthFooter>\n <AuthFooterLink\n link={\n <Link search={extractOAuthParams(search)} to=\"/login\">\n {t('setupTotp.backToLogin')}\n </Link>\n }\n />\n </AuthFooter>\n )}\n </AuthLayout>\n );\n}\n"],"x_google_ignoreList":[0,1,2],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{i as e,r as t}from"./config-DTQCUlfZ.js";import{t as n}from"./mutationOptions-DyYFUbyn.js";var r=n({mutationFn:async()=>e(await t.api.user.totp.setup.$post())}),i=n({mutationFn:async n=>e(await t.api.user.totp.verify.$post({json:n}))}),a=n({mutationFn:async()=>e(await t.api.user.totp.confirm.$post({json:{}}))}),o=n({mutationFn:async n=>e(await t.api.user.totp.$delete({json:n}))}),s=n({mutationFn:async n=>e(await t.api.user.totp.recovery.regenerate.$post({json:n}))}),c=n({mutationFn:async n=>e(await t.api.auth.totp.verify.$post({json:n}))}),l=n({mutationFn:async n=>e(await t.api.auth.totp.recovery.verify.$post({json:n}))});export{l as a,r as i,o as n,c as o,s as r,i as s,a as t};
2
- //# sourceMappingURL=totp-BNZ904Zm.js.map
1
+ import{i as e,r as t}from"./config-C18-l7z7.js";import{t as n}from"./mutationOptions-Cv_vJkJn.js";var r=n({mutationFn:async()=>e(await t.api.user.totp.setup.$post())}),i=n({mutationFn:async n=>e(await t.api.user.totp.verify.$post({json:n}))}),a=n({mutationFn:async()=>e(await t.api.user.totp.confirm.$post({json:{}}))}),o=n({mutationFn:async n=>e(await t.api.user.totp.$delete({json:n}))}),s=n({mutationFn:async n=>e(await t.api.user.totp.recovery.regenerate.$post({json:n}))}),c=n({mutationFn:async n=>e(await t.api.auth.totp.verify.$post({json:n}))}),l=n({mutationFn:async n=>e(await t.api.auth.totp.recovery.verify.$post({json:n}))});export{l as a,r as i,o as n,c as o,s as r,i as s,a as t};
2
+ //# sourceMappingURL=totp-BhElob6P.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"totp-BNZ904Zm.js","names":[],"sources":["../../../frontend/src/queries/totp.ts"],"sourcesContent":["import { mutationOptions } from '@tanstack/react-query';\nimport type { InferRequestType, InferResponseType } from 'hono/client';\nimport { client, jsonOk } from '#frontend/libs/api.ts';\n\nexport type TotpSetupResponse = InferResponseType<\n (typeof client.api.user.totp.setup)['$post'],\n 200\n>;\n\nexport type TotpSetupVerifyResponse = InferResponseType<\n (typeof client.api.user.totp.verify)['$post'],\n 200\n>;\n\nexport type TotpConfirmResponse = InferResponseType<\n (typeof client.api.user.totp.confirm)['$post'],\n 200\n>;\n\nexport type RegenerateTotpRecoveryCodesResponse = InferResponseType<\n (typeof client.api.user.totp.recovery.regenerate)['$post'],\n 200\n>;\n\nexport type TotpLoginVerifyResponse = InferResponseType<\n (typeof client.api.auth.totp.verify)['$post'],\n 200\n>;\n\n/**\n * Start TOTP setup - generates secret and QR code\n */\nexport const startTotpSetupMutationOptions = mutationOptions({\n mutationFn: async () => {\n const res = await client.api.user.totp.setup.$post();\n return jsonOk(res);\n },\n});\n\n/**\n * Verify TOTP code during setup (returns recovery codes)\n */\nexport type VerifyTotpParams = InferRequestType<\n (typeof client.api.user.totp.verify)['$post']\n>['json'];\n\nexport const verifyTotpMutationOptions = mutationOptions({\n mutationFn: async (values: VerifyTotpParams) => {\n const res = await client.api.user.totp.verify.$post({\n json: values,\n });\n return jsonOk(res);\n },\n});\n\n/**\n * Confirm TOTP setup after user acknowledges recovery\n * codes\n */\nexport const confirmTotpSetupMutationOptions = mutationOptions({\n mutationFn: async () => {\n const res = await client.api.user.totp.confirm.$post({\n json: {},\n });\n return jsonOk(res);\n },\n});\n\n/**\n * Disable TOTP authentication\n */\nexport type DisableTotpParams = InferRequestType<\n (typeof client.api.user.totp)['$delete']\n>['json'];\n\nexport const disableTotpMutationOptions = mutationOptions({\n mutationFn: async (values: DisableTotpParams) => {\n const res = await client.api.user.totp.$delete({\n json: values,\n });\n return jsonOk(res);\n },\n});\n\nexport type RegenerateTotpRecoveryCodesParams = InferRequestType<\n (typeof client.api.user.totp.recovery.regenerate)['$post']\n>['json'];\n\nexport const regenerateTotpRecoveryCodesMutationOptions = mutationOptions({\n mutationFn: async (values: RegenerateTotpRecoveryCodesParams) => {\n const res = await client.api.user.totp.recovery.regenerate.$post({\n json: values,\n });\n return jsonOk(res);\n },\n});\n\n/**\n * Verify TOTP code during login (complete 2FA login)\n */\nexport type VerifyTotpLoginParams = InferRequestType<\n (typeof client.api.auth.totp.verify)['$post']\n>['json'];\n\nexport const verifyTotpLoginMutationOptions = mutationOptions({\n mutationFn: async (values: VerifyTotpLoginParams) => {\n const res = await client.api.auth.totp.verify.$post({\n json: values,\n });\n return jsonOk(res);\n },\n});\n\n/**\n * Verify recovery code during login (complete 2FA login)\n */\nexport type VerifyRecoveryCodeParams = InferRequestType<\n (typeof client.api.auth.totp.recovery.verify)['$post']\n>['json'];\n\nexport type VerifyRecoveryCodeResponse = InferResponseType<\n (typeof client.api.auth.totp.recovery.verify)['$post'],\n 200\n>;\n\nexport const verifyRecoveryCodeMutationOptions = mutationOptions({\n mutationFn: async (values: VerifyRecoveryCodeParams) => {\n const res = await client.api.auth.totp.recovery.verify.$post({\n json: values,\n });\n return jsonOk(res);\n },\n});\n"],"mappings":"kGAgCA,IAAa,EAAgC,EAAgB,CAC3D,WAAY,SAEH,EAAO,MADI,EAAO,IAAI,KAAK,KAAK,MAAM,MAAM,CAClC,CAErB,CAAC,EASY,EAA4B,EAAgB,CACvD,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,OAAO,MAAM,CAClD,KAAM,CACR,CAAC,CACgB,CAErB,CAAC,EAMY,EAAkC,EAAgB,CAC7D,WAAY,SAIH,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,QAAQ,MAAM,CACnD,KAAM,CAAC,CACT,CAAC,CACgB,CAErB,CAAC,EASY,EAA6B,EAAgB,CACxD,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,QAAQ,CAC7C,KAAM,CACR,CAAC,CACgB,CAErB,CAAC,EAMY,EAA6C,EAAgB,CACxE,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,SAAS,WAAW,MAAM,CAC/D,KAAM,CACR,CAAC,CACgB,CAErB,CAAC,EASY,EAAiC,EAAgB,CAC5D,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,OAAO,MAAM,CAClD,KAAM,CACR,CAAC,CACgB,CAErB,CAAC,EAcY,EAAoC,EAAgB,CAC/D,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,SAAS,OAAO,MAAM,CAC3D,KAAM,CACR,CAAC,CACgB,CAErB,CAAC"}
1
+ {"version":3,"file":"totp-BhElob6P.js","names":[],"sources":["../../../frontend/src/queries/totp.ts"],"sourcesContent":["import { mutationOptions } from '@tanstack/react-query';\nimport type { InferRequestType, InferResponseType } from 'hono/client';\nimport { client, jsonOk } from '#frontend/libs/api.ts';\n\nexport type TotpSetupResponse = InferResponseType<\n (typeof client.api.user.totp.setup)['$post'],\n 200\n>;\n\nexport type TotpSetupVerifyResponse = InferResponseType<\n (typeof client.api.user.totp.verify)['$post'],\n 200\n>;\n\nexport type TotpConfirmResponse = InferResponseType<\n (typeof client.api.user.totp.confirm)['$post'],\n 200\n>;\n\nexport type RegenerateTotpRecoveryCodesResponse = InferResponseType<\n (typeof client.api.user.totp.recovery.regenerate)['$post'],\n 200\n>;\n\nexport type TotpLoginVerifyResponse = InferResponseType<\n (typeof client.api.auth.totp.verify)['$post'],\n 200\n>;\n\n/**\n * Start TOTP setup - generates secret and QR code\n */\nexport const startTotpSetupMutationOptions = mutationOptions({\n mutationFn: async () => {\n const res = await client.api.user.totp.setup.$post();\n return jsonOk(res);\n },\n});\n\n/**\n * Verify TOTP code during setup (returns recovery codes)\n */\nexport type VerifyTotpParams = InferRequestType<\n (typeof client.api.user.totp.verify)['$post']\n>['json'];\n\nexport const verifyTotpMutationOptions = mutationOptions({\n mutationFn: async (values: VerifyTotpParams) => {\n const res = await client.api.user.totp.verify.$post({\n json: values,\n });\n return jsonOk(res);\n },\n});\n\n/**\n * Confirm TOTP setup after user acknowledges recovery\n * codes\n */\nexport const confirmTotpSetupMutationOptions = mutationOptions({\n mutationFn: async () => {\n const res = await client.api.user.totp.confirm.$post({\n json: {},\n });\n return jsonOk(res);\n },\n});\n\n/**\n * Disable TOTP authentication\n */\nexport type DisableTotpParams = InferRequestType<\n (typeof client.api.user.totp)['$delete']\n>['json'];\n\nexport const disableTotpMutationOptions = mutationOptions({\n mutationFn: async (values: DisableTotpParams) => {\n const res = await client.api.user.totp.$delete({\n json: values,\n });\n return jsonOk(res);\n },\n});\n\nexport type RegenerateTotpRecoveryCodesParams = InferRequestType<\n (typeof client.api.user.totp.recovery.regenerate)['$post']\n>['json'];\n\nexport const regenerateTotpRecoveryCodesMutationOptions = mutationOptions({\n mutationFn: async (values: RegenerateTotpRecoveryCodesParams) => {\n const res = await client.api.user.totp.recovery.regenerate.$post({\n json: values,\n });\n return jsonOk(res);\n },\n});\n\n/**\n * Verify TOTP code during login (complete 2FA login)\n */\nexport type VerifyTotpLoginParams = InferRequestType<\n (typeof client.api.auth.totp.verify)['$post']\n>['json'];\n\nexport const verifyTotpLoginMutationOptions = mutationOptions({\n mutationFn: async (values: VerifyTotpLoginParams) => {\n const res = await client.api.auth.totp.verify.$post({\n json: values,\n });\n return jsonOk(res);\n },\n});\n\n/**\n * Verify recovery code during login (complete 2FA login)\n */\nexport type VerifyRecoveryCodeParams = InferRequestType<\n (typeof client.api.auth.totp.recovery.verify)['$post']\n>['json'];\n\nexport type VerifyRecoveryCodeResponse = InferResponseType<\n (typeof client.api.auth.totp.recovery.verify)['$post'],\n 200\n>;\n\nexport const verifyRecoveryCodeMutationOptions = mutationOptions({\n mutationFn: async (values: VerifyRecoveryCodeParams) => {\n const res = await client.api.auth.totp.recovery.verify.$post({\n json: values,\n });\n return jsonOk(res);\n },\n});\n"],"mappings":"kGAgCA,IAAa,EAAgC,EAAgB,CAC3D,WAAY,SAEH,EAAO,MADI,EAAO,IAAI,KAAK,KAAK,MAAM,MAAM,CAClC,CAErB,CAAC,EASY,EAA4B,EAAgB,CACvD,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,OAAO,MAAM,CAClD,KAAM,CACR,CAAC,CACgB,CAErB,CAAC,EAMY,EAAkC,EAAgB,CAC7D,WAAY,SAIH,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,QAAQ,MAAM,CACnD,KAAM,CAAC,CACT,CAAC,CACgB,CAErB,CAAC,EASY,EAA6B,EAAgB,CACxD,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,QAAQ,CAC7C,KAAM,CACR,CAAC,CACgB,CAErB,CAAC,EAMY,EAA6C,EAAgB,CACxE,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,SAAS,WAAW,MAAM,CAC/D,KAAM,CACR,CAAC,CACgB,CAErB,CAAC,EASY,EAAiC,EAAgB,CAC5D,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,OAAO,MAAM,CAClD,KAAM,CACR,CAAC,CACgB,CAErB,CAAC,EAcY,EAAoC,EAAgB,CAC/D,WAAY,KAAO,IAIV,EAAO,MAHI,EAAO,IAAI,KAAK,KAAK,SAAS,OAAO,MAAM,CAC3D,KAAM,CACR,CAAC,CACgB,CAErB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import{X as e,Z as t,et as n,i as r,n as i,r as a,s as o}from"./createLucideIcon-D-yizrWN.js";import{An as s,Ar as c,In as l}from"./config-C18-l7z7.js";import{t as u}from"./useMutation-DqIIIiBW.js";import{c as d,o as f}from"./zod-Dszyrytb.js";import{E as p,F as m,H as h,L as g,y as _,z as v}from"./index-lTEyHSus.js";import{t as y}from"./auth-page-header-ChaCNNrn.js";import{t as b}from"./alert-D3aaK-_3.js";import{t as x}from"./auth-layout-BdRRr0vT.js";import{t as S}from"./form-sJw-V9wb.js";import{t as C}from"./promise-OpBtq8tG.js";import{n as w,t as T}from"./auth-footer-Du6S-oDG.js";import{r as E,t as D}from"./standard-schema-C50nwAaQ.js";import{o as O}from"./totp-BhElob6P.js";import{t as k}from"./pin-input-DhsRO4Ei.js";import{t as A}from"./labeled-separator-DdkyYDWH.js";var j=n(t()),M=e(),N={SECOND_FACTOR_SESSION_EXPIRED:`SECOND_FACTOR_SESSION_EXPIRED`,INVALID_TOTP_CODE:`INVALID_TOTP_CODE`,TOTP_NOT_ENABLED:`TOTP_NOT_ENABLED`},P=5;function F(){let{t:e}=r(),t=l(),n=c(),F=_.useSearch(),I=(0,j.useRef)(null),[L,R]=(0,j.useState)(!1),[z,B]=(0,j.useState)(P),V=(0,j.useMemo)(()=>f({code:d().length(6,e(`validation.totp.length`)).regex(/^\d{6}$/,e(`validation.totp.digits`))}),[e]),H=u({...O,onSuccess:async e=>{n.setQueryData(p.queryKey,{user:e.user}),await C(),v(F)?window.location.href=m(F):t.navigate({to:`/profile`})},onSettled:()=>{n.invalidateQueries({queryKey:p.queryKey})}}),{setValue:U,setError:W,handleSubmit:G,watch:K,formState:{errors:q}}=E({defaultValues:{code:``},resolver:D(V)}),J=K(`code`),Y=(0,j.useCallback)(()=>{t.navigate({to:`/login`,search:g(F)})},[t,F]);(0,j.useEffect)(()=>{if(!L)return;let e=setInterval(()=>{B(t=>t<=1?(clearInterval(e),Y(),0):t-1)},1e3);return()=>clearInterval(e)},[L,Y]);let X=async t=>{try{await H.mutateAsync(t)}catch(t){if(t instanceof a)switch(t.code){case N.SECOND_FACTOR_SESSION_EXPIRED:R(!0),B(P);return;case N.TOTP_NOT_ENABLED:Y();return;case N.INVALID_TOTP_CODE:W(`code`,{type:`manual`,message:e(`verifyTotp.error.invalid`)}),U(`code`,``),I.current?.focus();return}W(`code`,{type:`manual`,message:e(`verifyTotp.error.invalid`)}),U(`code`,``),I.current?.focus()}};return(0,M.jsxs)(x,{children:[(0,M.jsx)(y,{subtitle:e(`verifyTotp.subtitle`),title:e(`verifyTotp.title`)}),L&&(0,M.jsx)(b,{"data-testid":`totp-verify-session-expired`,icon:h,type:`warning`,children:(0,M.jsxs)(`div`,{className:`flex flex-col items-start gap-tinyrack-3xs`,children:[(0,M.jsx)(i,{as:`span`,variant:`bodySm`,children:e(`verifyTotp.error.expired`)}),(0,M.jsx)(i,{as:`span`,color:`muted`,variant:`caption`,children:e(`verifyTotp.redirecting`,{seconds:z})}),(0,M.jsx)(o,{appearance:`ghost`,intent:`neutral`,onClick:Y,type:`button`,uiSize:`sm`,children:e(`verifyTotp.redirectNow`)})]})}),(0,M.jsxs)(S,{className:`flex flex-col gap-tinyrack-lg`,onSubmit:G(X),children:[(0,M.jsx)(k,{autoFocus:!0,disabled:L,error:q.code,length:6,onChange:e=>U(`code`,e),onComplete:()=>G(X)(),ref:I,value:J}),L?(0,M.jsx)(o,{className:`w-full`,disabled:!0,intent:`primary`,type:`button`,uiSize:`lg`,children:e(`verifyTotp.submit`)}):(0,M.jsx)(o,{className:`w-full`,intent:`primary`,loading:H.isPending,loadingLabel:e(`verifyTotp.submitting`),type:`submit`,uiSize:`lg`,children:e(`verifyTotp.submit`)})]}),(0,M.jsxs)(`div`,{className:`flex flex-col gap-tinyrack-md`,children:[(0,M.jsx)(A,{label:e(`common.or`)}),(0,M.jsx)(o,{appearance:`ghost`,className:`w-full`,"data-testid":`totp-verify-recovery-link`,intent:`neutral`,onClick:()=>t.navigate({to:`/verify/totp/recovery`,search:g(F)}),type:`button`,uiSize:`lg`,children:e(`verifyTotp.useRecoveryCode`)})]}),(0,M.jsx)(T,{children:(0,M.jsx)(w,{link:(0,M.jsx)(s,{search:g(F),to:`/login`,children:e(`verifyTotp.backToLogin`)})})})]})}export{F as component};
2
+ //# sourceMappingURL=totp-C1ba10Is.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"totp-C1ba10Is.js","names":["standardSchemaResolver","useMutation","useQueryClient","Link","useRouter","TRButton","TRForm","TRText","CircleAlertIcon","useCallback","useEffect","useMemo","useRef","useState","useForm","useTranslation","z","AuthFooter","AuthFooterLink","AuthPageHeader","Alert","LabeledSeparator","PinInput","AuthLayout","IssuaryError","buildAuthenticatedAuthorizeUrl","extractOAuthParams","isOAuthFlow","tick","getSessionQueryOptions","verifyTotpLoginMutationOptions","ERROR_CODES","SECOND_FACTOR_SESSION_EXPIRED","INVALID_TOTP_CODE","TOTP_NOT_ENABLED","const","Route","VerifyTotpFormValues","code","REDIRECT_COUNTDOWN_SECONDS","VerifyTotp","t","router","queryClient","search","useSearch","pinInputRef","PinInputRef","sessionExpired","setSessionExpired","redirectCountdown","setRedirectCountdown","verifySchema","object","string","length","regex","verifyMutation","onSuccess","data","setQueryData","queryKey","user","window","location","href","navigate","to","onSettled","invalidateQueries","setValue","setError","handleSubmit","watch","formState","errors","defaultValues","resolver","codeValue","redirectToLogin","timer","setInterval","prev","clearInterval","onSubmit","values","mutateAsync","error","type","message","current","focus","seconds","value","isPending","component"],"sources":["../../../frontend/src/routes/verify/totp/index.tsx?tsr-split=component"],"sourcesContent":["import { standardSchemaResolver } from '@hookform/resolvers/standard-schema';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { createFileRoute, Link, useRouter } from '@tanstack/react-router';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRForm } from '@tinyrack/ui/components/form';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { CircleAlertIcon } from 'lucide-react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport { z } from 'zod';\nimport {\n AuthFooter,\n AuthFooterLink,\n} from '#frontend/components/auth/auth-footer.tsx';\nimport { AuthPageHeader } from '#frontend/components/auth/auth-page-header.tsx';\nimport { Alert } from '#frontend/components/ui/alert.tsx';\nimport { LabeledSeparator } from '#frontend/components/ui/labeled-separator.tsx';\nimport {\n PinInput,\n type PinInputRef,\n} from '#frontend/components/ui/pin-input.tsx';\nimport { AuthLayout } from '#frontend/features/layout/auth-layout.tsx';\nimport { IssuaryError } from '#frontend/libs/error.ts';\nimport {\n buildAuthenticatedAuthorizeUrl,\n extractOAuthParams,\n isOAuthFlow,\n OAuthSearchSchema,\n} from '#frontend/libs/oauth-search.ts';\nimport { tick } from '#frontend/libs/promise.ts';\nimport { getSessionQueryOptions } from '#frontend/queries/session.ts';\nimport { verifyTotpLoginMutationOptions } from '#frontend/queries/totp.ts';\n\n/** Error codes from backend */\nconst ERROR_CODES = {\n SECOND_FACTOR_SESSION_EXPIRED: 'SECOND_FACTOR_SESSION_EXPIRED',\n INVALID_TOTP_CODE: 'INVALID_TOTP_CODE',\n TOTP_NOT_ENABLED: 'TOTP_NOT_ENABLED',\n} as const;\n\nconst SearchSchema = OAuthSearchSchema;\n\nexport const Route = createFileRoute('/verify/totp/')({\n component: VerifyTotp,\n validateSearch: SearchSchema,\n});\n\ntype VerifyTotpFormValues = {\n code: string;\n};\n\n/** Auto redirect countdown seconds */\nconst REDIRECT_COUNTDOWN_SECONDS = 5;\n\nfunction VerifyTotp() {\n const { t } = useTranslation();\n const router = useRouter();\n const queryClient = useQueryClient();\n const search = Route.useSearch();\n const pinInputRef = useRef<PinInputRef>(null);\n\n const [sessionExpired, setSessionExpired] = useState(false);\n const [redirectCountdown, setRedirectCountdown] = useState(\n REDIRECT_COUNTDOWN_SECONDS,\n );\n\n const verifySchema = useMemo(\n () =>\n z.object({\n code: z\n .string()\n .length(6, t('validation.totp.length'))\n .regex(/^\\d{6}$/, t('validation.totp.digits')),\n }),\n [t],\n );\n\n const verifyMutation = useMutation({\n ...verifyTotpLoginMutationOptions,\n onSuccess: async (data) => {\n queryClient.setQueryData(getSessionQueryOptions.queryKey, {\n user: data.user,\n });\n await tick();\n\n if (isOAuthFlow(search)) {\n window.location.href = buildAuthenticatedAuthorizeUrl(search);\n } else {\n router.navigate({ to: '/profile' });\n }\n },\n onSettled: () => {\n queryClient.invalidateQueries({\n queryKey: getSessionQueryOptions.queryKey,\n });\n },\n });\n\n const {\n setValue,\n setError,\n handleSubmit,\n watch,\n formState: { errors },\n } = useForm<VerifyTotpFormValues>({\n defaultValues: {\n code: '',\n },\n resolver: standardSchemaResolver(verifySchema),\n });\n\n const codeValue = watch('code');\n\n // Auto redirect when session expires\n const redirectToLogin = useCallback(() => {\n router.navigate({\n to: '/login',\n search: extractOAuthParams(search),\n });\n }, [router, search]);\n\n useEffect(() => {\n if (!sessionExpired) return;\n\n const timer = setInterval(() => {\n setRedirectCountdown((prev) => {\n if (prev <= 1) {\n clearInterval(timer);\n redirectToLogin();\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(timer);\n }, [sessionExpired, redirectToLogin]);\n\n const onSubmit = async (values: VerifyTotpFormValues) => {\n try {\n await verifyMutation.mutateAsync(values);\n } catch (error) {\n if (error instanceof IssuaryError) {\n switch (error.code) {\n case ERROR_CODES.SECOND_FACTOR_SESSION_EXPIRED:\n // Session expired - show alert and start auto redirect\n setSessionExpired(true);\n setRedirectCountdown(REDIRECT_COUNTDOWN_SECONDS);\n return;\n\n case ERROR_CODES.TOTP_NOT_ENABLED:\n // TOTP not enabled - redirect to login\n redirectToLogin();\n return;\n\n case ERROR_CODES.INVALID_TOTP_CODE:\n // Invalid code - show specific error and clear input\n setError('code', {\n type: 'manual',\n message: t('verifyTotp.error.invalid'),\n });\n setValue('code', '');\n pinInputRef.current?.focus();\n return;\n }\n }\n\n // Generic error fallback\n setError('code', {\n type: 'manual',\n message: t('verifyTotp.error.invalid'),\n });\n setValue('code', '');\n pinInputRef.current?.focus();\n }\n };\n\n return (\n <AuthLayout>\n <AuthPageHeader\n subtitle={t('verifyTotp.subtitle')}\n title={t('verifyTotp.title')}\n />\n\n {sessionExpired && (\n <Alert\n data-testid=\"totp-verify-session-expired\"\n icon={CircleAlertIcon}\n type=\"warning\"\n >\n {/* tinyrack-check-ignore-next-line components/no-native-text -- Structural alert content; visible copy uses TRText and TRButton. */}\n <div className=\"flex flex-col items-start gap-tinyrack-3xs\">\n <TRText as=\"span\" variant=\"bodySm\">\n {t('verifyTotp.error.expired')}\n </TRText>\n <TRText as=\"span\" color=\"muted\" variant=\"caption\">\n {t('verifyTotp.redirecting', { seconds: redirectCountdown })}\n </TRText>\n <TRButton\n appearance=\"ghost\"\n intent=\"neutral\"\n onClick={redirectToLogin}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('verifyTotp.redirectNow')}\n </TRButton>\n </div>\n </Alert>\n )}\n\n <TRForm\n className=\"flex flex-col gap-tinyrack-lg\"\n onSubmit={handleSubmit(onSubmit)}\n >\n <PinInput\n autoFocus\n disabled={sessionExpired}\n error={errors.code}\n length={6}\n onChange={(value) => setValue('code', value)}\n onComplete={() => handleSubmit(onSubmit)()}\n ref={pinInputRef}\n value={codeValue}\n />\n\n {sessionExpired ? (\n <TRButton\n className=\"w-full\"\n disabled\n intent=\"primary\"\n type=\"button\"\n uiSize=\"lg\"\n >\n {t('verifyTotp.submit')}\n </TRButton>\n ) : (\n <TRButton\n className=\"w-full\"\n intent=\"primary\"\n loading={verifyMutation.isPending}\n loadingLabel={t('verifyTotp.submitting')}\n type=\"submit\"\n uiSize=\"lg\"\n >\n {t('verifyTotp.submit')}\n </TRButton>\n )}\n </TRForm>\n\n {/*\n The recovery code is the way out when the authenticator is gone, so it\n sits below the rule rather than in the footer with the navigation.\n */}\n <div className=\"flex flex-col gap-tinyrack-md\">\n <LabeledSeparator label={t('common.or')} />\n <TRButton\n appearance=\"ghost\"\n className=\"w-full\"\n data-testid=\"totp-verify-recovery-link\"\n intent=\"neutral\"\n onClick={() =>\n router.navigate({\n to: '/verify/totp/recovery',\n search: extractOAuthParams(search),\n })\n }\n type=\"button\"\n uiSize=\"lg\"\n >\n {t('verifyTotp.useRecoveryCode')}\n </TRButton>\n </div>\n\n <AuthFooter>\n <AuthFooterLink\n link={\n <Link search={extractOAuthParams(search)} to=\"/login\">\n {t('verifyTotp.backToLogin')}\n </Link>\n }\n />\n </AuthFooter>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./createLucideIcon-BPpAIXR_.js";var t=e(`trash-2`,[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]]);export{t};
2
- //# sourceMappingURL=trash-2-DZdKBLvC.js.map
1
+ import{t as e}from"./createLucideIcon-D-yizrWN.js";var t=e(`trash-2`,[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]]);export{t};
2
+ //# sourceMappingURL=trash-2-B3NVE8pR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"trash-2-DZdKBLvC.js","names":[],"sources":["../../../../node_modules/.pnpm/lucide-react@1.25.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/trash-2.mjs"],"sourcesContent":["/**\n * @license lucide-react v1.25.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 11v6\", key: \"nco0om\" }],\n [\"path\", { d: \"M14 11v6\", key: \"outv1u\" }],\n [\"path\", { d: \"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\", key: \"miytrc\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\", key: \"e791ji\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.mjs.map\n"],"x_google_ignoreList":[0],"mappings":"mDAgBA,IAAM,EAAS,EAAiB,UAAW,CANzC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAS,CAAC,EACzC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAS,CAAC,EACzC,CAAC,OAAQ,CAAE,EAAG,2CAA4C,IAAK,QAAS,CAAC,EACzE,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAS,CAAC,EACxC,CAAC,OAAQ,CAAE,EAAG,yCAA0C,IAAK,QAAS,CAAC,CAE9B,CAAU"}
1
+ {"version":3,"file":"trash-2-B3NVE8pR.js","names":[],"sources":["../../../../node_modules/.pnpm/lucide-react@1.25.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/trash-2.mjs"],"sourcesContent":["/**\n * @license lucide-react v1.25.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 11v6\", key: \"nco0om\" }],\n [\"path\", { d: \"M14 11v6\", key: \"outv1u\" }],\n [\"path\", { d: \"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\", key: \"miytrc\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\", key: \"e791ji\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.mjs.map\n"],"x_google_ignoreList":[0],"mappings":"mDAgBA,IAAM,EAAS,EAAiB,UAAW,CANzC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAS,CAAC,EACzC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAS,CAAC,EACzC,CAAC,OAAQ,CAAE,EAAG,2CAA4C,IAAK,QAAS,CAAC,EACzE,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAS,CAAC,EACxC,CAAC,OAAQ,CAAE,EAAG,yCAA0C,IAAK,QAAS,CAAC,CAE9B,CAAU"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./createLucideIcon-BPpAIXR_.js";var t=e(`triangle-alert`,[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]);export{t};
2
- //# sourceMappingURL=triangle-alert-CqNn0kPs.js.map
1
+ import{t as e}from"./createLucideIcon-D-yizrWN.js";var t=e(`triangle-alert`,[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]);export{t};
2
+ //# sourceMappingURL=triangle-alert-DATO9o3k.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"triangle-alert-CqNn0kPs.js","names":[],"sources":["../../../../node_modules/.pnpm/lucide-react@1.25.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/triangle-alert.mjs"],"sourcesContent":["/**\n * @license lucide-react v1.25.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\",\n key: \"wmoenq\"\n }\n ],\n [\"path\", { d: \"M12 9v4\", key: \"juzpu7\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n];\nconst TriangleAlert = createLucideIcon(\"triangle-alert\", __iconNode);\n\nexport { __iconNode, TriangleAlert as default };\n//# sourceMappingURL=triangle-alert.mjs.map\n"],"x_google_ignoreList":[0],"mappings":"mDAoBA,IAAM,EAAgB,EAAiB,iBAAkB,CAVvD,CACE,OACA,CACE,EAAG,2EACH,IAAK,QACP,CACF,EACA,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAS,CAAC,EACxC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAS,CAAC,CAEY,CAAU"}
1
+ {"version":3,"file":"triangle-alert-DATO9o3k.js","names":[],"sources":["../../../../node_modules/.pnpm/lucide-react@1.25.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/triangle-alert.mjs"],"sourcesContent":["/**\n * @license lucide-react v1.25.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\",\n key: \"wmoenq\"\n }\n ],\n [\"path\", { d: \"M12 9v4\", key: \"juzpu7\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n];\nconst TriangleAlert = createLucideIcon(\"triangle-alert\", __iconNode);\n\nexport { __iconNode, TriangleAlert as default };\n//# sourceMappingURL=triangle-alert.mjs.map\n"],"x_google_ignoreList":[0],"mappings":"mDAoBA,IAAM,EAAgB,EAAiB,iBAAkB,CAVvD,CACE,OACA,CACE,EAAG,2EACH,IAAK,QACP,CACF,EACA,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAS,CAAC,EACxC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAS,CAAC,CAEY,CAAU"}
@@ -0,0 +1,2 @@
1
+ import{X as e,Z as t,et as n,i as r,n as i,s as a,t as o}from"./createLucideIcon-D-yizrWN.js";import{Q as s,X as c,Z as l,c as u}from"./shell-header-bar-CdOEWmCT.js";import{_ as d}from"./admin-shell-B91U4-Ro.js";import{t as f}from"./checkbox-DTPGfvmq.js";import{t as p}from"./form-sJw-V9wb.js";import{t as m}from"./input-QvBxPgy5.js";import{t as h}from"./table-Dl89o43x.js";var g=o(`arrow-down`,[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]),_=o(`arrow-up`,[[`path`,{d:`m5 12 7-7 7 7`,key:`hav0vg`}],[`path`,{d:`M12 19V5`,key:`x0mq9r`}]]),v=e();function y({title:e,total:t,query:n,onQueryChange:o,onSearch:s,onCreate:c,children:l}){let{t:u}=r();return(0,v.jsxs)(`div`,{className:`flex shrink-0 flex-col bg-tinyrack-surface`,"data-testid":`admin-list-toolbar`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-tinyrack-md py-tinyrack-md`,children:[(0,v.jsxs)(`div`,{className:`flex min-w-0 items-baseline gap-tinyrack-sm`,children:[(0,v.jsx)(i,{as:`h1`,variant:`headingMd`,weight:`heading`,children:e}),(0,v.jsx)(i,{color:`muted`,variant:`caption`,children:u(`admin.table.total`,{count:t})})]}),c?(0,v.jsx)(a,{intent:`primary`,onClick:c,type:`button`,uiSize:`sm`,children:u(`admin.table.create`)}):null]}),(0,v.jsxs)(p,{className:`flex flex-wrap items-center gap-tinyrack-sm py-tinyrack-sm`,onSubmit:e=>{e.preventDefault(),s()},children:[(0,v.jsxs)(m.Group,{className:`w-full flex-none sm:w-auto sm:min-w-tinyrack-measure-sm sm:flex-1`,children:[(0,v.jsx)(m.Adornment,{children:(0,v.jsx)(d,{"aria-hidden":!0})}),(0,v.jsx)(m,{"aria-label":u(`admin.table.search`),onChange:e=>o(e.target.value),placeholder:u(`admin.table.searchPlaceholder`),uiSize:`sm`,value:n})]}),l,(0,v.jsx)(a,{appearance:`outline`,type:`submit`,uiSize:`sm`,children:u(`admin.table.search`)})]})]})}function b({children:e}){return(0,v.jsx)(`div`,{className:`flex min-h-0 w-full min-w-0 flex-1 flex-col`,"data-layout":`table`,children:e})}function x({children:e,label:t}){return(0,v.jsx)(h.Root,{"aria-label":t,containerClassName:`min-h-0 max-w-full flex-1 overflow-auto`,density:`compact`,layout:`wide`,children:e})}function S({checked:e,indeterminate:t,onChange:n}){let{t:i}=r();return(0,v.jsx)(f.Root,{"aria-label":i(`admin.selection.page`),checked:e,indeterminate:t,onCheckedChange:e=>n(e===!0),uiSize:`md`,children:(0,v.jsx)(f.Indicator,{})})}function C({checked:e,label:t,onChange:n}){return(0,v.jsx)(f.Root,{"aria-label":t,checked:e,onCheckedChange:e=>n(e===!0),uiSize:`md`,children:(0,v.jsx)(f.Indicator,{})})}function w({children:e,header:t=!1,selected:n=!1}){return(0,v.jsx)(t?h.Head:h.Cell,{className:`sticky left-0 z-tinyrack-component-raised w-tinyrack-measure-xs ${n?`admin-sticky-selected`:t?`bg-tinyrack-surface-muted`:`bg-tinyrack-surface`}`,children:e})}function T({children:e,header:t=!1,selected:n=!1}){return(0,v.jsx)(t?h.Head:h.Cell,{className:`sticky left-tinyrack-measure-xs z-tinyrack-component-raised min-w-tinyrack-measure-lg ${n?`admin-sticky-selected`:t?`bg-tinyrack-surface-muted`:`bg-tinyrack-surface`}`,children:e})}function E({children:e,header:t=!1,selected:n=!1}){return(0,v.jsx)(t?h.Head:h.Cell,{className:`sticky right-0 z-tinyrack-component-raised text-right ${n?`admin-sticky-selected`:t?`bg-tinyrack-surface-muted`:`bg-tinyrack-surface`}`,children:e})}function D({label:e,direction:t,onClick:n}){return(0,v.jsxs)(a,{appearance:`ghost`,onClick:n,type:`button`,uiSize:`sm`,children:[e,t?(0,v.jsx)(t===`desc`?g:_,{"aria-hidden":!0,className:`size-tinyrack-md`}):null]})}function O({label:e,value:t,options:n,onChange:r}){return(0,v.jsxs)(u.Root,{onValueChange:e=>{typeof e==`string`&&r(e)},value:t,children:[(0,v.jsxs)(u.Trigger,{"aria-label":e,uiSize:`sm`,children:[(0,v.jsx)(u.Value,{children:n.find(([e])=>e===t)?.[1]??t}),(0,v.jsx)(u.Icon,{children:(0,v.jsx)(l,{"aria-hidden":!0})})]}),(0,v.jsx)(u.Positioner,{children:(0,v.jsx)(u.Popup,{children:(0,v.jsx)(u.List,{children:n.map(([e,t])=>(0,v.jsxs)(u.Item,{value:e,children:[(0,v.jsx)(u.ItemText,{children:t}),(0,v.jsx)(u.ItemIndicator,{children:(0,v.jsx)(s,{"aria-hidden":!0})})]},e))})})})]})}function k({page:e,pageSize:t,total:n,onPageChange:o,onPageSizeChange:s}){let{t:c}=r(),l=Math.max(Math.ceil(n/t),1);return(0,v.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-tinyrack-md py-tinyrack-sm`,children:[(0,v.jsx)(O,{label:c(`admin.table.pageSize`),onChange:e=>s(Number(e)),options:[`20`,`50`,`100`].map(e=>[e,e]),value:String(t)}),(0,v.jsxs)(`div`,{className:`flex items-center gap-tinyrack-sm`,children:[(0,v.jsx)(a,{appearance:`ghost`,disabled:e<=1,onClick:()=>o(e-1),type:`button`,uiSize:`sm`,children:c(`admin.table.previous`)}),(0,v.jsx)(i,{color:`muted`,variant:`caption`,children:c(`admin.table.page`,{page:e,total:l})}),(0,v.jsx)(a,{appearance:`ghost`,disabled:e>=l,onClick:()=>o(e+1),type:`button`,uiSize:`sm`,children:c(`admin.table.next`)})]})]})}function A({selected:e,total:t,filterSelected:n,canExpand:o,onExpand:s,onClear:l,onActivate:u,onDeactivate:d,pending:f}){let{t:p}=r();return(0,v.jsxs)(`div`,{className:`fixed right-tinyrack-lg bottom-tinyrack-lg z-tinyrack-dropdown flex max-w-[calc(100vw-var(--tinyrack-space-lg)*2)] flex-wrap items-center gap-tinyrack-sm rounded-tinyrack-lg bg-tinyrack-surface px-tinyrack-lg py-tinyrack-sm shadow-tinyrack-overlay`,"data-testid":`admin-bulk-bar`,children:[(0,v.jsx)(i,{variant:`bodySm`,weight:`strong`,children:p(`admin.selection.selected`,{count:n?t:e})}),(0,v.jsx)(i,{color:`muted`,variant:`caption`,children:p(n?`admin.selection.filterScope`:`admin.selection.pageScope`)}),o&&!n?(0,v.jsx)(a,{appearance:`ghost`,onClick:s,type:`button`,uiSize:`sm`,children:p(`admin.selection.selectAll`,{count:t})}):null,(0,v.jsx)(a,{disabled:f,onClick:u,type:`button`,uiSize:`sm`,children:p(`admin.selection.activate`)}),(0,v.jsx)(a,{disabled:f,intent:`danger`,onClick:d,type:`button`,uiSize:`sm`,children:p(`admin.selection.deactivate`)}),(0,v.jsx)(a,{appearance:`ghost`,"aria-label":p(`admin.selection.clear`),onClick:l,type:`button`,uiSize:`sm`,children:(0,v.jsx)(c,{"aria-hidden":!0})})]})}var j=n(t(),1);function M(e){let[t,n]=(0,j.useState)(()=>({kind:`ids`,ids:new Set})),r=(0,j.useMemo)(()=>t.kind===`filter`?e.length:e.filter(e=>t.ids.has(e)).length,[e,t]);return{selection:t,selectedOnPage:r,allOnPage:e.length>0&&r===e.length,someOnPage:r>0&&r<e.length,selectedCount:t.kind===`ids`?t.ids.size:void 0,isSelected:e=>t.kind===`filter`||t.ids.has(e),selectFilter:()=>n({kind:`filter`}),clear:()=>n({kind:`ids`,ids:new Set}),togglePage:t=>{n({kind:`ids`,ids:t?new Set(e):new Set})},toggleOne:(t,r)=>{n(n=>{let i=n.kind===`filter`?new Set(e):new Set(n.ids);return r?i.add(t):i.delete(t),{kind:`ids`,ids:i}})}}}export{k as a,D as c,w as d,x as f,y as i,E as l,A as n,C as o,b as p,O as r,S as s,M as t,T as u};
2
+ //# sourceMappingURL=use-admin-selection-D2b7jnym.js.map