@shapio/cms 0.5.0 → 0.5.1

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 (270) hide show
  1. package/dist/admin/assets/{AssetTile-zOf0K0nN.js → AssetTile-B8ftUG4s.js} +2 -2
  2. package/dist/admin/assets/{AssetTile-zOf0K0nN.js.map → AssetTile-B8ftUG4s.js.map} +1 -1
  3. package/dist/admin/assets/{AssistError-D_vY2CO0.js → AssistError-BidlzaBY.js} +2 -2
  4. package/dist/admin/assets/{AssistError-D_vY2CO0.js.map → AssistError-BidlzaBY.js.map} +1 -1
  5. package/dist/admin/assets/{BlockMenuItems-BEnSpClj.js → BlockMenuItems-DfNBHqVM.js} +2 -2
  6. package/dist/admin/assets/{BlockMenuItems-BEnSpClj.js.map → BlockMenuItems-DfNBHqVM.js.map} +1 -1
  7. package/dist/admin/assets/{Body-B_IVN5wp.js → Body-C0oQSX6L.js} +2 -2
  8. package/dist/admin/assets/{Body-B_IVN5wp.js.map → Body-C0oQSX6L.js.map} +1 -1
  9. package/dist/admin/assets/{Builder-CnEtRudv.js → Builder-Z_hcyzNW.js} +2 -2
  10. package/dist/admin/assets/{Builder-CnEtRudv.js.map → Builder-Z_hcyzNW.js.map} +1 -1
  11. package/dist/admin/assets/{ConfirmDialog-BW-l3Whg.js → ConfirmDialog-DVN-n-tE.js} +2 -2
  12. package/dist/admin/assets/{ConfirmDialog-BW-l3Whg.js.map → ConfirmDialog-DVN-n-tE.js.map} +1 -1
  13. package/dist/admin/assets/{CopyButton-CyoUMStc.js → CopyButton--tHegXQr.js} +2 -2
  14. package/dist/admin/assets/{CopyButton-CyoUMStc.js.map → CopyButton--tHegXQr.js.map} +1 -1
  15. package/dist/admin/assets/{CursorPager-BW2Dl_hn.js → CursorPager-Cb94mITn.js} +2 -2
  16. package/dist/admin/assets/{CursorPager-BW2Dl_hn.js.map → CursorPager-Cb94mITn.js.map} +1 -1
  17. package/dist/admin/assets/{ExternalLink-BCI0q9ib.js → ExternalLink-M1cb1n2n.js} +2 -2
  18. package/dist/admin/assets/{ExternalLink-BCI0q9ib.js.map → ExternalLink-M1cb1n2n.js.map} +1 -1
  19. package/dist/admin/assets/{FocalPoint-CxicvlJO.js → FocalPoint-pTq17ngi.js} +2 -2
  20. package/dist/admin/assets/{FocalPoint-CxicvlJO.js.map → FocalPoint-pTq17ngi.js.map} +1 -1
  21. package/dist/admin/assets/{Form-DB03drS9.js → Form-4zah109J.js} +2 -2
  22. package/dist/admin/assets/{Form-DB03drS9.js.map → Form-4zah109J.js.map} +1 -1
  23. package/dist/admin/assets/FormCheckboxGroup-DAeuGKAU.js +2 -0
  24. package/dist/admin/assets/FormCheckboxGroup-DAeuGKAU.js.map +1 -0
  25. package/dist/admin/assets/{FormRadioGroup-BvSC8SRm.js → FormRadioGroup--xx08rw6.js} +2 -2
  26. package/dist/admin/assets/{FormRadioGroup-BvSC8SRm.js.map → FormRadioGroup--xx08rw6.js.map} +1 -1
  27. package/dist/admin/assets/{FormSelectField-BDIVhZh6.js → FormSelectField-DNOCQKqc.js} +2 -2
  28. package/dist/admin/assets/{FormSelectField-BDIVhZh6.js.map → FormSelectField-DNOCQKqc.js.map} +1 -1
  29. package/dist/admin/assets/{FormSwitchField-OM4F8ln4.js → FormSwitchField-BECl-pzH.js} +2 -2
  30. package/dist/admin/assets/{FormSwitchField-OM4F8ln4.js.map → FormSwitchField-BECl-pzH.js.map} +1 -1
  31. package/dist/admin/assets/{FormTextareaField-Bw7EkC4H.js → FormTextareaField-DmRuKDJ_.js} +2 -2
  32. package/dist/admin/assets/{FormTextareaField-Bw7EkC4H.js.map → FormTextareaField-DmRuKDJ_.js.map} +1 -1
  33. package/dist/admin/assets/{HintedLabel-BGidukgy.js → HintedLabel-DIEBvftx.js} +2 -2
  34. package/dist/admin/assets/{HintedLabel-BGidukgy.js.map → HintedLabel-DIEBvftx.js.map} +1 -1
  35. package/dist/admin/assets/{InfoHint-D3uwei-E.js → InfoHint-BdAadb9U.js} +2 -2
  36. package/dist/admin/assets/{InfoHint-D3uwei-E.js.map → InfoHint-BdAadb9U.js.map} +1 -1
  37. package/dist/admin/assets/{InsertMenuItem-DAihGvbw.js → InsertMenuItem-oh0NJrhB.js} +2 -2
  38. package/dist/admin/assets/{InsertMenuItem-DAihGvbw.js.map → InsertMenuItem-oh0NJrhB.js.map} +1 -1
  39. package/dist/admin/assets/{LinkTabs-DBXbfzME.js → LinkTabs-EBgHX4Uh.js} +2 -2
  40. package/dist/admin/assets/{LinkTabs-DBXbfzME.js.map → LinkTabs-EBgHX4Uh.js.map} +1 -1
  41. package/dist/admin/assets/{Match-CgfZTzqs.js → Match-CvpSNEfi.js} +2 -2
  42. package/dist/admin/assets/{Match-CgfZTzqs.js.map → Match-CvpSNEfi.js.map} +1 -1
  43. package/dist/admin/assets/{Panel-DDky5_x9.js → Panel-BV1BpNCn.js} +2 -2
  44. package/dist/admin/assets/{Panel-DDky5_x9.js.map → Panel-BV1BpNCn.js.map} +1 -1
  45. package/dist/admin/assets/{QueryView-C2d392ly.js → QueryView-Bbw1eiV2.js} +2 -2
  46. package/dist/admin/assets/{QueryView-C2d392ly.js.map → QueryView-Bbw1eiV2.js.map} +1 -1
  47. package/dist/admin/assets/{RadioTile-CcP78eb_.js → RadioTile-CSYW-8gL.js} +2 -2
  48. package/dist/admin/assets/{RadioTile-CcP78eb_.js.map → RadioTile-CSYW-8gL.js.map} +1 -1
  49. package/dist/admin/assets/{RichTextField-CeztaFET.js → RichTextField-BDb67rCi.js} +2 -2
  50. package/dist/admin/assets/{RichTextField-CeztaFET.js.map → RichTextField-BDb67rCi.js.map} +1 -1
  51. package/dist/admin/assets/{RowTitle-mkKp4yfl.js → RowTitle-Cted2GP8.js} +2 -2
  52. package/dist/admin/assets/{RowTitle-mkKp4yfl.js.map → RowTitle-Cted2GP8.js.map} +1 -1
  53. package/dist/admin/assets/SecretReveal-Ccaul96d.js +2 -0
  54. package/dist/admin/assets/SecretReveal-Ccaul96d.js.map +1 -0
  55. package/dist/admin/assets/{SharedGlyph-CuDT7OUU.js → SharedGlyph-BrLi3Hug.js} +2 -2
  56. package/dist/admin/assets/{SharedGlyph-CuDT7OUU.js.map → SharedGlyph-BrLi3Hug.js.map} +1 -1
  57. package/dist/admin/assets/{StepList-BDO0Q3Wc.js → StepList-BLvElvPV.js} +2 -2
  58. package/dist/admin/assets/{StepList-BDO0Q3Wc.js.map → StepList-BLvElvPV.js.map} +1 -1
  59. package/dist/admin/assets/Structure-CRNAuVY7.js +2 -0
  60. package/dist/admin/assets/{Structure-CL_0hVci.js.map → Structure-CRNAuVY7.js.map} +1 -1
  61. package/dist/admin/assets/{SubNavLink-C4eSybWd.js → SubNavLink-biGV5ozd.js} +2 -2
  62. package/dist/admin/assets/{SubNavLink-C4eSybWd.js.map → SubNavLink-biGV5ozd.js.map} +1 -1
  63. package/dist/admin/assets/{SuggestAltButton-CxYlhwyd.js → SuggestAltButton-CrFiRWGr.js} +2 -2
  64. package/dist/admin/assets/{SuggestAltButton-CxYlhwyd.js.map → SuggestAltButton-CrFiRWGr.js.map} +1 -1
  65. package/dist/admin/assets/{TextLink-DzNaAft6.js → TextLink-BPLbXw2n.js} +2 -2
  66. package/dist/admin/assets/{TextLink-DzNaAft6.js.map → TextLink-BPLbXw2n.js.map} +1 -1
  67. package/dist/admin/assets/{Thumbnail-DSPArZ9h.js → Thumbnail-B_TWlgEz.js} +2 -2
  68. package/dist/admin/assets/{Thumbnail-DSPArZ9h.js.map → Thumbnail-B_TWlgEz.js.map} +1 -1
  69. package/dist/admin/assets/{UnsavedChangesGuard-BPOCBD5T.js → UnsavedChangesGuard-CrzR2boF.js} +2 -2
  70. package/dist/admin/assets/{UnsavedChangesGuard-BPOCBD5T.js.map → UnsavedChangesGuard-CrzR2boF.js.map} +1 -1
  71. package/dist/admin/assets/{UserAvatar-BHNWHDVb.js → UserAvatar-W-S3st7E.js} +2 -2
  72. package/dist/admin/assets/{UserAvatar-BHNWHDVb.js.map → UserAvatar-W-S3st7E.js.map} +1 -1
  73. package/dist/admin/assets/{auth-BzCgJtgr.js → auth-cXFFyABE.js} +2 -2
  74. package/dist/admin/assets/{auth-BzCgJtgr.js.map → auth-cXFFyABE.js.map} +1 -1
  75. package/dist/admin/assets/{badge-DBoaS0nQ.js → badge-DrPwivGk.js} +2 -2
  76. package/dist/admin/assets/{badge-DBoaS0nQ.js.map → badge-DrPwivGk.js.map} +1 -1
  77. package/dist/admin/assets/{boxes-DhN0ctLo.js → boxes-CKJ6P9VA.js} +2 -2
  78. package/dist/admin/assets/{boxes-DhN0ctLo.js.map → boxes-CKJ6P9VA.js.map} +1 -1
  79. package/dist/admin/assets/{calendar-clock-BEA3tG17.js → calendar-clock-DPyjti63.js} +2 -2
  80. package/dist/admin/assets/{calendar-clock-BEA3tG17.js.map → calendar-clock-DPyjti63.js.map} +1 -1
  81. package/dist/admin/assets/{changeSets-C54Ku-X9.js → changeSets-DYGm5j1A.js} +2 -2
  82. package/dist/admin/assets/{changeSets-C54Ku-X9.js.map → changeSets-DYGm5j1A.js.map} +1 -1
  83. package/dist/admin/assets/chevron-left-DIp5sJuv.js +2 -0
  84. package/dist/admin/assets/{chevron-left-BeJdUVAX.js.map → chevron-left-DIp5sJuv.js.map} +1 -1
  85. package/dist/admin/assets/{circle-check-ktACw37r.js → circle-check-VXPKg4cE.js} +2 -2
  86. package/dist/admin/assets/{circle-check-ktACw37r.js.map → circle-check-VXPKg4cE.js.map} +1 -1
  87. package/dist/admin/assets/{clock-BKNNASKp.js → clock-DNhupIko.js} +2 -2
  88. package/dist/admin/assets/{clock-BKNNASKp.js.map → clock-DNhupIko.js.map} +1 -1
  89. package/dist/admin/assets/cn-CEPUgFbZ.js +2 -0
  90. package/dist/admin/assets/cn-CEPUgFbZ.js.map +1 -0
  91. package/dist/admin/assets/coerce-BxuBjZdf.js +2 -0
  92. package/dist/admin/assets/{coerce-DDQ1vGLx.js.map → coerce-BxuBjZdf.js.map} +1 -1
  93. package/dist/admin/assets/{constants-DH7oqfO_.js → constants-B9cNrCXV.js} +2 -2
  94. package/dist/admin/assets/{constants-DH7oqfO_.js.map → constants-B9cNrCXV.js.map} +1 -1
  95. package/dist/admin/assets/{content-BptqQO8c.js → content-DjyCdi4c.js} +3 -3
  96. package/dist/admin/assets/{content-BptqQO8c.js.map → content-DjyCdi4c.js.map} +1 -1
  97. package/dist/admin/assets/{contentCounts-BpGlmyeZ.js → contentCounts-CX15iYcR.js} +2 -2
  98. package/dist/admin/assets/{contentCounts-BpGlmyeZ.js.map → contentCounts-CX15iYcR.js.map} +1 -1
  99. package/dist/admin/assets/{contentTypes-B_mAlIcH.js → contentTypes-FgyxLhlk.js} +2 -2
  100. package/dist/admin/assets/{contentTypes-B_mAlIcH.js.map → contentTypes-FgyxLhlk.js.map} +1 -1
  101. package/dist/admin/assets/{context-DyyMW7Md.js → context-FqJXjS5k.js} +2 -2
  102. package/dist/admin/assets/{context-DyyMW7Md.js.map → context-FqJXjS5k.js.map} +1 -1
  103. package/dist/admin/assets/{copy-DjzlFY9u.js → copy-CoHbtS-Y.js} +2 -2
  104. package/dist/admin/assets/{copy-DjzlFY9u.js.map → copy-CoHbtS-Y.js.map} +1 -1
  105. package/dist/admin/assets/{dateTimeLocal-DFXY779D.js → dateTimeLocal-BxmDLO_H.js} +2 -2
  106. package/dist/admin/assets/{dateTimeLocal-DFXY779D.js.map → dateTimeLocal-BxmDLO_H.js.map} +1 -1
  107. package/dist/admin/assets/{develop-DJap_z-1.js → develop-gx8WeWv4.js} +2 -2
  108. package/dist/admin/assets/{develop-DJap_z-1.js.map → develop-gx8WeWv4.js.map} +1 -1
  109. package/dist/admin/assets/{dropdown-menu-DGSMTf23.js → dropdown-menu-BG1rctRQ.js} +2 -2
  110. package/dist/admin/assets/{dropdown-menu-DGSMTf23.js.map → dropdown-menu-BG1rctRQ.js.map} +1 -1
  111. package/dist/admin/assets/{ellipsis-BMP-j3yO.js → ellipsis-DHfP1Ah2.js} +2 -2
  112. package/dist/admin/assets/{ellipsis-BMP-j3yO.js.map → ellipsis-DHfP1Ah2.js.map} +1 -1
  113. package/dist/admin/assets/{external-link-DzOkt97S.js → external-link-itxcNtaX.js} +2 -2
  114. package/dist/admin/assets/{external-link-DzOkt97S.js.map → external-link-itxcNtaX.js.map} +1 -1
  115. package/dist/admin/assets/{fileRoute-CG0Dufvt.js → fileRoute-BZ0pGGsh.js} +2 -2
  116. package/dist/admin/assets/{fileRoute-CG0Dufvt.js.map → fileRoute-BZ0pGGsh.js.map} +1 -1
  117. package/dist/admin/assets/{folder-plus-C-LhI4a2.js → folder-plus-BgsfY_6i.js} +2 -2
  118. package/dist/admin/assets/{folder-plus-C-LhI4a2.js.map → folder-plus-BgsfY_6i.js.map} +1 -1
  119. package/dist/admin/assets/{followPlural-D-8kzFOe.js → followPlural-BqjqhHmz.js} +2 -2
  120. package/dist/admin/assets/{followPlural-D-8kzFOe.js.map → followPlural-BqjqhHmz.js.map} +1 -1
  121. package/dist/admin/assets/{globe-DOoGBy23.js → globe-RjXj4P-A.js} +2 -2
  122. package/dist/admin/assets/{globe-DOoGBy23.js.map → globe-RjXj4P-A.js.map} +1 -1
  123. package/dist/admin/assets/{image-D9p_gGE2.js → image-4itB4TLl.js} +2 -2
  124. package/dist/admin/assets/{image-D9p_gGE2.js.map → image-4itB4TLl.js.map} +1 -1
  125. package/dist/admin/assets/{image-off-G0M2Nh1I.js → image-off-CokIymyg.js} +2 -2
  126. package/dist/admin/assets/{image-off-G0M2Nh1I.js.map → image-off-CokIymyg.js.map} +1 -1
  127. package/dist/admin/assets/{inbox-XaM-nvsM.js → inbox-8AAyyM0T.js} +2 -2
  128. package/dist/admin/assets/{inbox-XaM-nvsM.js.map → inbox-8AAyyM0T.js.map} +1 -1
  129. package/dist/admin/assets/{inbox-CMzYVMZo.js → inbox-97pzmuus.js} +2 -2
  130. package/dist/admin/assets/{inbox-CMzYVMZo.js.map → inbox-97pzmuus.js.map} +1 -1
  131. package/dist/admin/assets/{index-DHmfMpqz.js → index-cpiZvLck.js} +4 -4
  132. package/dist/admin/assets/{index-DHmfMpqz.js.map → index-cpiZvLck.js.map} +1 -1
  133. package/dist/admin/assets/{key-round-HBvMrmMo.js → key-round-Dc4_SOi-.js} +2 -2
  134. package/dist/admin/assets/{key-round-HBvMrmMo.js.map → key-round-Dc4_SOi-.js.map} +1 -1
  135. package/dist/admin/assets/{languages-BOv0jYhe.js → languages-DR2K97A5.js} +2 -2
  136. package/dist/admin/assets/{languages-BOv0jYhe.js.map → languages-DR2K97A5.js.map} +1 -1
  137. package/dist/admin/assets/{layers-CkZyCaeb.js → layers-ZPmcbieN.js} +2 -2
  138. package/dist/admin/assets/{layers-CkZyCaeb.js.map → layers-ZPmcbieN.js.map} +1 -1
  139. package/dist/admin/assets/{link-2-off-UUkSmPIL.js → link-2-off-D_5_hkT7.js} +2 -2
  140. package/dist/admin/assets/{link-2-off-UUkSmPIL.js.map → link-2-off-D_5_hkT7.js.map} +1 -1
  141. package/dist/admin/assets/{link-Bvqcg7db.js → link-BnDFFyvi.js} +2 -2
  142. package/dist/admin/assets/{link-Bvqcg7db.js.map → link-BnDFFyvi.js.map} +1 -1
  143. package/dist/admin/assets/{locales-DbrcdhZi.js → locales-D-21t-l-.js} +2 -2
  144. package/dist/admin/assets/{locales-DbrcdhZi.js.map → locales-D-21t-l-.js.map} +1 -1
  145. package/dist/admin/assets/{media-ugEyLgwN.js → media-D7aimjyy.js} +2 -2
  146. package/dist/admin/assets/{media-ugEyLgwN.js.map → media-D7aimjyy.js.map} +1 -1
  147. package/dist/admin/assets/{media-CO0HSS3b.js → media-Db0cHYNY.js} +2 -2
  148. package/dist/admin/assets/{media-CO0HSS3b.js.map → media-Db0cHYNY.js.map} +1 -1
  149. package/dist/admin/assets/network-l_oLT5fa.js +2 -0
  150. package/dist/admin/assets/network-l_oLT5fa.js.map +1 -0
  151. package/dist/admin/assets/{pencil-BLNGNJmL.js → pencil-Cn8c_gtv.js} +2 -2
  152. package/dist/admin/assets/{pencil-BLNGNJmL.js.map → pencil-Cn8c_gtv.js.map} +1 -1
  153. package/dist/admin/assets/{plus-BXMBYPoB.js → plus-yxvf4aAT.js} +2 -2
  154. package/dist/admin/assets/{plus-BXMBYPoB.js.map → plus-yxvf4aAT.js.map} +1 -1
  155. package/dist/admin/assets/{preload-helper-DEbJbZwX.js → preload-helper-pwSesV5P.js} +2 -2
  156. package/dist/admin/assets/{preload-helper-DEbJbZwX.js.map → preload-helper-pwSesV5P.js.map} +1 -1
  157. package/dist/admin/assets/{publishing-DKrATBaj.js → publishing-PQLCOnvu.js} +2 -2
  158. package/dist/admin/assets/{publishing-DKrATBaj.js.map → publishing-PQLCOnvu.js.map} +1 -1
  159. package/dist/admin/assets/{radio-group-BIhT_uEK.js → radio-group-Fc2ENIMO.js} +2 -2
  160. package/dist/admin/assets/{radio-group-BIhT_uEK.js.map → radio-group-Fc2ENIMO.js.map} +1 -1
  161. package/dist/admin/assets/{rotate-ccw-DqbffhiC.js → rotate-ccw-BHa0BHug.js} +2 -2
  162. package/dist/admin/assets/{rotate-ccw-DqbffhiC.js.map → rotate-ccw-BHa0BHug.js.map} +1 -1
  163. package/dist/admin/assets/{schedules-CETl2eLe.js → schedules-B8y_GnqX.js} +2 -2
  164. package/dist/admin/assets/{schedules-CETl2eLe.js.map → schedules-B8y_GnqX.js.map} +1 -1
  165. package/dist/admin/assets/{schema-CWHuez0q.js → schema-BJHcYshf.js} +2 -2
  166. package/dist/admin/assets/{schema-CWHuez0q.js.map → schema-BJHcYshf.js.map} +1 -1
  167. package/dist/admin/assets/{scroll-text-DlcDEi2k.js → scroll-text-BHLmZpBB.js} +2 -2
  168. package/dist/admin/assets/{scroll-text-DlcDEi2k.js.map → scroll-text-BHLmZpBB.js.map} +1 -1
  169. package/dist/admin/assets/{search-Dy2dtwyR.js → search-D3GGSaSL.js} +2 -2
  170. package/dist/admin/assets/{search-Dy2dtwyR.js.map → search-D3GGSaSL.js.map} +1 -1
  171. package/dist/admin/assets/{searchSchemas-Cz4P1iku.js → searchSchemas-C4dnYI9a.js} +2 -2
  172. package/dist/admin/assets/{searchSchemas-Cz4P1iku.js.map → searchSchemas-C4dnYI9a.js.map} +1 -1
  173. package/dist/admin/assets/{sections-BfG6DTFr.js → sections-BWoTaw2B.js} +2 -2
  174. package/dist/admin/assets/{sections-BfG6DTFr.js.map → sections-BWoTaw2B.js.map} +1 -1
  175. package/dist/admin/assets/{sections-EgXyXN3-.js → sections-eeTU636D.js} +2 -2
  176. package/dist/admin/assets/{sections-EgXyXN3-.js.map → sections-eeTU636D.js.map} +1 -1
  177. package/dist/admin/assets/{select--mePTdz8.js → select-BMi4G1Ib.js} +2 -2
  178. package/dist/admin/assets/{select--mePTdz8.js.map → select-BMi4G1Ib.js.map} +1 -1
  179. package/dist/admin/assets/{send-DVgq5Iwg.js → send-Bqhmg9HP.js} +2 -2
  180. package/dist/admin/assets/{send-DVgq5Iwg.js.map → send-Bqhmg9HP.js.map} +1 -1
  181. package/dist/admin/assets/{seo-Zhb62Ojz.js → seo-BL9C7Yt3.js} +2 -2
  182. package/dist/admin/assets/{seo-Zhb62Ojz.js.map → seo-BL9C7Yt3.js.map} +1 -1
  183. package/dist/admin/assets/settings-D-nW3wQb.js +2 -0
  184. package/dist/admin/assets/settings-D-nW3wQb.js.map +1 -0
  185. package/dist/admin/assets/skeleton-BPLAzyDo.js +42 -0
  186. package/dist/admin/assets/skeleton-BPLAzyDo.js.map +1 -0
  187. package/dist/admin/assets/{snapshots-BpLhILlt.js → snapshots-COSUeZBP.js} +2 -2
  188. package/dist/admin/assets/{snapshots-BpLhILlt.js.map → snapshots-COSUeZBP.js.map} +1 -1
  189. package/dist/admin/assets/{sparkles-Dd6S_roX.js → sparkles-CykwtKTd.js} +2 -2
  190. package/dist/admin/assets/{sparkles-Dd6S_roX.js.map → sparkles-CykwtKTd.js.map} +1 -1
  191. package/dist/admin/assets/{stableId-DFVM13gJ.js → stableId-DfJkQUV3.js} +2 -2
  192. package/dist/admin/assets/{stableId-DFVM13gJ.js.map → stableId-DfJkQUV3.js.map} +1 -1
  193. package/dist/admin/assets/{store-BP-xStwU.js → store-GOGeP63I.js} +2 -2
  194. package/dist/admin/assets/{store-BP-xStwU.js.map → store-GOGeP63I.js.map} +1 -1
  195. package/dist/admin/assets/{switch-skVypg5O.js → switch-XRU_EOoM.js} +2 -2
  196. package/dist/admin/assets/{switch-skVypg5O.js.map → switch-XRU_EOoM.js.map} +1 -1
  197. package/dist/admin/assets/{table-BMbbRUK9.js → table-CLVW6uJB.js} +2 -2
  198. package/dist/admin/assets/{table-BMbbRUK9.js.map → table-CLVW6uJB.js.map} +1 -1
  199. package/dist/admin/assets/{tabs-C1lgOg1B.js → tabs-DB42Xljn.js} +3 -3
  200. package/dist/admin/assets/{tabs-C1lgOg1B.js.map → tabs-DB42Xljn.js.map} +1 -1
  201. package/dist/admin/assets/{textarea-CffBBxoQ.js → textarea-DcsLGCkq.js} +2 -2
  202. package/dist/admin/assets/{textarea-CffBBxoQ.js.map → textarea-DcsLGCkq.js.map} +1 -1
  203. package/dist/admin/assets/{theme-RHTVnR9j.js → theme-CnSar6tt.js} +2 -2
  204. package/dist/admin/assets/{theme-RHTVnR9j.js.map → theme-CnSar6tt.js.map} +1 -1
  205. package/dist/admin/assets/{titles-DWiPmNvn.js → titles-DluirfBO.js} +2 -2
  206. package/dist/admin/assets/{titles-DWiPmNvn.js.map → titles-DluirfBO.js.map} +1 -1
  207. package/dist/admin/assets/{tokens-BqyeN1D-.js → tokens-CQooB8Sf.js} +2 -2
  208. package/dist/admin/assets/{tokens-BqyeN1D-.js.map → tokens-CQooB8Sf.js.map} +1 -1
  209. package/dist/admin/assets/{tooltip-BfSF6EyR.js → tooltip-xfZn0Fla.js} +2 -2
  210. package/dist/admin/assets/{tooltip-BfSF6EyR.js.map → tooltip-xfZn0Fla.js.map} +1 -1
  211. package/dist/admin/assets/{undo-2-p4YlNhBp.js → undo-2-B_QjuGmR.js} +2 -2
  212. package/dist/admin/assets/{undo-2-p4YlNhBp.js.map → undo-2-B_QjuGmR.js.map} +1 -1
  213. package/dist/admin/assets/{useAuditLabels-DV5gcaaG.js → useAuditLabels-BZPAj3wG.js} +2 -2
  214. package/dist/admin/assets/{useAuditLabels-DV5gcaaG.js.map → useAuditLabels-BZPAj3wG.js.map} +1 -1
  215. package/dist/admin/assets/{useConfirmTarget-DCvnxNVg.js → useConfirmTarget-B7iLg66j.js} +2 -2
  216. package/dist/admin/assets/{useConfirmTarget-DCvnxNVg.js.map → useConfirmTarget-B7iLg66j.js.map} +1 -1
  217. package/dist/admin/assets/{useContentSchema-z6tNif86.js → useContentSchema-BTyBYURX.js} +2 -2
  218. package/dist/admin/assets/{useContentSchema-z6tNif86.js.map → useContentSchema-BTyBYURX.js.map} +1 -1
  219. package/dist/admin/assets/{useCursorPager-CQGX41_L.js → useCursorPager-CTGOzl69.js} +2 -2
  220. package/dist/admin/assets/{useCursorPager-CQGX41_L.js.map → useCursorPager-CTGOzl69.js.map} +1 -1
  221. package/dist/admin/assets/{useDiscardGuard-Dhbif7VL.js → useDiscardGuard-CSkPw8iq.js} +2 -2
  222. package/dist/admin/assets/{useDiscardGuard-Dhbif7VL.js.map → useDiscardGuard-CSkPw8iq.js.map} +1 -1
  223. package/dist/admin/assets/{useMediaPickerDialog-D-5uKsMG.js → useMediaPickerDialog-W0jhN-hi.js} +2 -2
  224. package/dist/admin/assets/{useMediaPickerDialog-D-5uKsMG.js.map → useMediaPickerDialog-W0jhN-hi.js.map} +1 -1
  225. package/dist/admin/assets/{useMediaUploader-BtLoimmQ.js → useMediaUploader-BC5zCkQt.js} +2 -2
  226. package/dist/admin/assets/{useMediaUploader-BtLoimmQ.js.map → useMediaUploader-BC5zCkQt.js.map} +1 -1
  227. package/dist/admin/assets/{usePaletteItems-D3PZsW0Q.js → usePaletteItems-CqcKndUT.js} +2 -2
  228. package/dist/admin/assets/{usePaletteItems-D3PZsW0Q.js.map → usePaletteItems-CqcKndUT.js.map} +1 -1
  229. package/dist/admin/assets/{usePlaces-Cj5PljTy.js → usePlaces-o4Os5Nbv.js} +2 -2
  230. package/dist/admin/assets/{usePlaces-Cj5PljTy.js.map → usePlaces-o4Os5Nbv.js.map} +1 -1
  231. package/dist/admin/assets/{useQueries-CeDzli4Z.js → useQueries-BTnSD0k5.js} +2 -2
  232. package/dist/admin/assets/{useQueries-CeDzli4Z.js.map → useQueries-BTnSD0k5.js.map} +1 -1
  233. package/dist/admin/assets/{useResolvedScheme-DHD-zisP.js → useResolvedScheme-SoI-2Faf.js} +2 -2
  234. package/dist/admin/assets/{useResolvedScheme-DHD-zisP.js.map → useResolvedScheme-SoI-2Faf.js.map} +1 -1
  235. package/dist/admin/assets/{useSchemaScopeAccess-BNeVslcv.js → useSchemaScopeAccess-B4-31q7m.js} +2 -2
  236. package/dist/admin/assets/{useSchemaScopeAccess-BNeVslcv.js.map → useSchemaScopeAccess-B4-31q7m.js.map} +1 -1
  237. package/dist/admin/assets/{users-BRefbzuS.js → users-BVuapb3u.js} +2 -2
  238. package/dist/admin/assets/{users-BRefbzuS.js.map → users-BVuapb3u.js.map} +1 -1
  239. package/dist/admin/assets/{users-CppI8ctO.js → users-Oj5V5za_.js} +2 -2
  240. package/dist/admin/assets/{users-CppI8ctO.js.map → users-Oj5V5za_.js.map} +1 -1
  241. package/dist/admin/assets/{zod-Dcwk-m8X.js → zod-cTJwCa4E.js} +2 -2
  242. package/dist/admin/assets/{zod-Dcwk-m8X.js.map → zod-cTJwCa4E.js.map} +1 -1
  243. package/dist/admin/index.html +55 -55
  244. package/dist/cli.js +33 -18
  245. package/dist/cli.js.map +1 -1
  246. package/dist/config.d.ts +1 -1
  247. package/dist/index.d.ts +1 -1
  248. package/dist/index.js +1 -1
  249. package/dist/{public-DYR4mtVQ.d.ts → public-C027OJX6.d.ts} +12 -2
  250. package/dist/{s3Adapter-C8AgFVYw.js → s3Adapter-BipoQiwQ.js} +2 -2
  251. package/dist/{s3Adapter-C8AgFVYw.js.map → s3Adapter-BipoQiwQ.js.map} +1 -1
  252. package/dist/{worker-jz_0yAmS.js → worker-BU-V4qbH.js} +174 -60
  253. package/dist/worker-BU-V4qbH.js.map +1 -0
  254. package/package.json +5 -5
  255. package/dist/admin/assets/FormCheckboxGroup-JP1xzReQ.js +0 -2
  256. package/dist/admin/assets/FormCheckboxGroup-JP1xzReQ.js.map +0 -1
  257. package/dist/admin/assets/SecretReveal-mYCzxF96.js +0 -2
  258. package/dist/admin/assets/SecretReveal-mYCzxF96.js.map +0 -1
  259. package/dist/admin/assets/Structure-CL_0hVci.js +0 -2
  260. package/dist/admin/assets/chevron-left-BeJdUVAX.js +0 -2
  261. package/dist/admin/assets/cn-h5ORT3LK.js +0 -2
  262. package/dist/admin/assets/cn-h5ORT3LK.js.map +0 -1
  263. package/dist/admin/assets/coerce-DDQ1vGLx.js +0 -2
  264. package/dist/admin/assets/network-BfDaUb7D.js +0 -2
  265. package/dist/admin/assets/network-BfDaUb7D.js.map +0 -1
  266. package/dist/admin/assets/settings-Mscp6tN5.js +0 -2
  267. package/dist/admin/assets/settings-Mscp6tN5.js.map +0 -1
  268. package/dist/admin/assets/skeleton-DJVukcn6.js +0 -42
  269. package/dist/admin/assets/skeleton-DJVukcn6.js.map +0 -1
  270. package/dist/worker-jz_0yAmS.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"network-BfDaUb7D.js","names":["__iconData","Form","useMemo","i18next","Form","z.object","zodResolver","i18next","_Fragment","z.object","z.string","EMPTY","zodResolver","CreateSheet","Table","TableRoot","useState","Globe2","Table","CreateSheet","useState","useState","Table","TableRoot","_Fragment","Table","z.object","z.string","z.enum","z.array","z.custom","zodResolver","i18next","Table","TableRoot","MoreHorizontal","Trash2","useState","Table","z.object","z.string","zodResolver","i18next","i18next","useState","MoreHorizontal","Trash2","Table","TableRoot","useState","Table","z.object","z.string","zodResolver","useState","useMemo","i18next","_Fragment","Row","useState","Table","Fragment","Row","useState","Table","Link","z.array","z.object","z.string","useMemo","useMemo","z.object","zodResolver","useMemo","z.object","zodResolver","i18next","useState","MoreHorizontal","Trash2","TableRoot","useState","UsersIcon","NewContentType","AppRoleEditor","__toESM","require_jsx_runtime","useQuery","queryKeys","useMutation","currentSite","useQueryClient","createLucideIcon","useTranslation","adminApi","withCsrf","cn","goToSite","leaveDeletedSite","linkOptions","useNavigate","useMe","Link","X","SubmitButton","Page","PageHeader","useParams","StatusChip","EmptyState","ErrorState","Badge","formatRelativeTime","formatDateTime","useSearch","RowTitle","createLazyRoute","UnsavedChangesGuard","FormCheckboxGroup","isModelDefinition","Info","toast","Trash","FieldLabel","FieldLegend","Field","FieldSet","FieldGroup","instance","Button","describeError","Input","Label","List","Form$2","Earth","Boxes","SelectValue","SelectTrigger","SelectContent","SelectItem","ChevronDown","Select","CursorPager","Alert","FormError","Checkbox","AlertDescription","InlineConfirm","ConfirmDialog","Ellipsis","Search","Link$1","DropdownMenuItem","DropdownMenuSeparator","DropdownMenuTrigger","DropdownMenuContent","DropdownMenu","Pencil","Plus","ScrollText","useDeleteAppRole","UserCheck","AUDIT_ACTOR_TYPES","Person","useCreateAppRole","useAppRoles","useAppRole","useUpdateAppRole","ShieldCheck","UserX","UserPlus","auditTargetName","useAuditEvents","useAuditLabels","Users$1","UserAvatar","RadioGroupItem","RadioGroup","Switch","useFormState","useWatch","emailField","useFieldArray","FormTextField","requiredText","FormFieldError","u","useForm","settle","TableHeader","custom","object","TableHead","_enum","TableBody","TableRow","TableCell","TableCard","Table$5","array","string","HintedLabel","useSharedDefinitions","useDefinitions","QueryView","FormRadioGroup","Panel","useSchemaLock","LockNotice","FormTextareaField","FormSheet","FormSelectField","useRevokeInvitation","useUsers","useRemoveUser","useInviteUser","useSetUserStatus","useIssueInvitationLink","useUpdateUser","useInvitations","useNetworkPermission","useConfirmTarget","useRoles","useRoleNames","useCreateRole","useUpdateRole","useDeleteRole","SecretReveal","LinkTabs","CONTENT_ACTIONS","GLOBAL_ACTIONS","APP_CONTENT_ACTIONS","__iconData$1","BookOpen","__iconData","SlidersHorizontal","import_jsx_runtime","ContentTypes","shared","createAction","locked","t","data","KINDS","New","import_react","require_react","refreshSites","queryClient","useSites","useSite","id","useSiteNames","sites","site","useCreateSite","input","useUpdateSite","useDeleteSite","useSiteAppRoles","useSetSiteAppRoles","result","useAppRoleBindingsForm","setBindings","form","bindings","formState","reset","saved","values","Form$1","options","roles","role","onSubmit","event","canManage","isDirty","AppRoleBindings","siteId","appRoles","DangerZone","navigate","deleteSite","renameSchema","useRenameSiteForm","updateSite","KEY_ID","KEY_HINT_ID","Details","Site","canManageRoles","createSiteSchema","EMPTY$1","useCreateSiteForm","createSite","open","created","onCreated","CreateSheet$1","Table$4","Sites","creating","setCreating","ALL","isActorType","value","Filters","actionDraft","setActionDraft","action","hasFilters","actorType","onChange","type","useAuditLogSearch","search","previousCursors","setPreviousCursors","go","previous","changes","cursors","nextCursor","filters","targetReference","Table$3","events","name","detail","actionLabel","reference","targetName","targetLabel","AuditLog","setFilters","goFirst","goPrevious","goNext","EDITABLE_ACTIONS","ACTION_LABEL_KEYS","ROLE_KINDS","ROLE_KEY_PATTERN","roleSchema","isEveryModelGrant","permission","valuesFor","toGrant","useRoleForm","createRole","updateRole","narrower","actions","onDone","mutation","KIND_LABEL_KEYS","RoleSheet","onOpenChange","isEdit","kind","Table$2","onEdit","onDelete","Tabs","Roles","deleteRole","confirmDelete","sheet","setSheet","current","createAppRoleSchema","EMPTY","useCreateAppRoleForm","createAppRole","CreateSheet","readsAllModels","useGrantReadAll","updateAppRole","error","Actions","deleting","setDeleting","BUILT_IN_HOLDER_KEYS","builtInHolderKey","key","Table$1","holderKey","pendingRoleId","onGrantReadAll","AppRoles","deleteAppRole","grantReadAll","OWN_ONLY_ACTIONS","FIELD_SCOPED_ACTIONS","ACTION_COLUMN_KEYS","toMatrix","matrix","permissions","toPermissions","a","b","grant","withGrant","row","setGranted","granted","updateGrant","hasOptions","grants","setColumn","keys","next","columnState","detailsSchema","useAppRoleEditor","setMatrix","initial","permissionsDirty","detailsDirty","details","SCOPE_ALL","SCOPE_SELECTED","Options","liveFields","fields","field","ownOnly","fieldScoped","rowKey","base","checked","selected","checkboxId","fieldId","Row$1","label","onToggle","canExpand","expanded","optionsId","onToggleExpanded","Matrix","setExpanded","toggleExpanded","rows","models","item","definition","isExpanded","BUILT_IN_DESCRIPTION_KEYS","builtInDescriptionKey","Form","editor","explanation","breadcrumb","Editor","roleId","loaded","definitions","useInvitationLinkReveal","emailDelivery","issueLink","revealed","setRevealed","reveal","link","invitation","InvitationLink","expires","AssignmentBadges","showSites","siteNames","assignments","roleNames","Invitations","invitations","revoke","onCopyLink","siteValue","toAssignmentRows","bySite","ownerRoleId","toAssignments","assignmentRowsSchema","seen","context","index","nextAssignmentRow","used","siteIds","candidate","AssignmentsField","path","multiSite","roleOptions","defaultRoleId","rootError","errors","siteOptions","remove","append","SYSTEM_ADMIN_ROLE_KEYS","useAdminRoleOptionsAndDefaults","adminRoles","isOwnerRole","includeOwner","heldRoleIds","useAssignmentOptions","emptyValues","useInviteForm","invite","schema","onInvited","InviteSheet","useAccessForm","updateUser","user","useIsOwner","AccessSheet","assignment","Row","editingAccess","setEditingAccess","removing","setRemoving","displayName","isSelf","onRemove","onToggleStatus","Table","users","currentUserId","networkLazyRoutes","me","setStatus","removeUser","inviting","setInviting","invitationLink"],"sources":["../../../../packages/client/src/admin/types.ts","../../../../packages/client/src/admin/appUsersTypes.ts","../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/book-open.mjs","../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.mjs","../../src/features/Network/ContentTypes/index.tsx","../../src/features/Network/ContentTypes/New/index.tsx","../../src/api/sites.ts","../../src/features/Network/Site/hooks/useAppRoleBindingsForm.ts","../../src/features/Network/Site/AppRoleBindings/index.tsx","../../src/features/Network/Site/DangerZone/index.tsx","../../src/features/Network/Site/hooks/useRenameSiteForm.ts","../../src/features/Network/Site/Details/index.tsx","../../src/features/Network/Site/index.tsx","../../src/features/Network/constants.ts","../../src/features/Network/Sites/hooks/useCreateSiteForm.ts","../../src/features/Network/Sites/CreateSheet/index.tsx","../../src/features/Network/Sites/Table/index.tsx","../../src/features/Network/Sites/index.tsx","../../src/features/Settings/AuditLog/Filters/index.tsx","../../src/features/Settings/AuditLog/hooks/useAuditLogSearch.ts","../../src/features/Settings/AuditLog/Table/index.tsx","../../src/features/Settings/AuditLog/index.tsx","../../src/features/Settings/Roles/constants.ts","../../src/features/Settings/Roles/hooks/useRoleForm.ts","../../src/features/Settings/Roles/RoleSheet/index.tsx","../../src/features/Settings/Roles/Table/index.tsx","../../src/features/Settings/Roles/Tabs/index.tsx","../../src/features/Settings/Roles/index.tsx","../../src/features/Settings/Roles/AppRoles/hooks/useCreateAppRoleForm.ts","../../src/features/Settings/Roles/AppRoles/CreateSheet/index.tsx","../../src/features/Settings/Roles/AppRoles/hooks/useGrantReadAll.ts","../../src/features/Settings/Roles/AppRoles/Table/Actions/index.tsx","../../src/features/Settings/Roles/AppRoles/Table/index.tsx","../../src/features/Settings/Roles/AppRoles/index.tsx","../../src/features/Settings/Roles/AppRoles/constants.ts","../../src/features/Settings/Roles/AppRoles/helpers/permissionMatrix.ts","../../src/features/Settings/Roles/AppRoles/Editor/hooks/useAppRoleEditor.ts","../../src/features/Settings/Roles/AppRoles/Editor/Matrix/Options/index.tsx","../../src/features/Settings/Roles/AppRoles/Editor/Matrix/Row/index.tsx","../../src/features/Settings/Roles/AppRoles/Editor/Matrix/index.tsx","../../src/features/Settings/Roles/AppRoles/Editor/index.tsx","../../src/features/Users/hooks/useInvitationLinkReveal.ts","../../src/features/Users/InvitationLink/index.tsx","../../src/features/Users/AssignmentBadges/index.tsx","../../src/features/Users/Invitations/index.tsx","../../src/features/Users/helpers/assignments.ts","../../src/features/Users/AssignmentsField/index.tsx","../../src/constants/roles.ts","../../src/features/Users/hooks/useAdminRoleOptionsAndDefaults.ts","../../src/features/Users/hooks/useAssignmentOptions.ts","../../src/features/Users/hooks/useInviteForm.ts","../../src/features/Users/InviteSheet/index.tsx","../../src/features/Users/hooks/useAccessForm.ts","../../src/features/Users/hooks/useIsOwner.ts","../../src/features/Users/AccessSheet/index.tsx","../../src/features/Users/Table/Row/index.tsx","../../src/features/Users/Table/index.tsx","../../src/features/Users/index.tsx","../../src/app/lazyRoutes/network.tsx"],"sourcesContent":["import type { SiteSummary } from './sitesTypes.js';\n/**\n * Admin identity API shapes (package B, build plan §4.B), mirroring the TypeBox route schemas in\n * apps/api/src/routes/admin/** and routes/schemas/adminIdentity.ts. JSON is camelCase; timestamps are ISO-8601.\n */\n\nexport type AdminUserStatus = 'active' | 'disabled';\n\n/** A role held on one site, or on every site (`siteId` null). */\nexport type RoleAssignment = { roleId: string; siteId: string | null };\n\nexport type AdminUser = {\n id: string;\n email: string;\n name: string;\n status: AdminUserStatus;\n /** Where each role applies. */\n assignments: RoleAssignment[];\n /** Deprecated: the distinct roles of `assignments`, on any site. */\n roleIds: string[];\n lastLoginAt: string | null;\n createdAt: string;\n updatedAt: string;\n};\n\nexport const CONTENT_ACTIONS = ['read', 'create', 'update', 'delete', 'publish', 'schemaManage'] as const;\nexport type ContentAction = (typeof CONTENT_ACTIONS)[number];\n\n/**\n * Network actions: about the whole instance. Only roles assigned on every site grant them, so a role held\n * on one site never reaches the network.\n */\nexport const NETWORK_ACTIONS = [\n 'schema.create',\n 'users.manage',\n 'roles.manage',\n 'audit.read',\n 'sites.manage',\n] as const;\nexport type NetworkAction = (typeof NETWORK_ACTIONS)[number];\n\n/** Site actions: about one site's library, tokens and publishing. */\nexport const SITE_ACTIONS = [\n 'tokens.manage',\n 'media.read',\n 'media.write',\n 'media.manage',\n 'publishing.manage',\n 'webhooks.manage',\n 'deployments.manage',\n 'deployments.trigger',\n 'changes.manage',\n 'changes.ship',\n] as const;\nexport type SiteAction = (typeof SITE_ACTIONS)[number];\n\n/** Actions not scoped to a model: network actions and site actions. */\nexport const GLOBAL_ACTIONS = [\n 'schema.create',\n 'users.manage',\n 'roles.manage',\n 'tokens.manage',\n 'audit.read',\n 'sites.manage',\n 'media.read',\n 'media.write',\n 'media.manage',\n 'publishing.manage',\n 'webhooks.manage',\n 'deployments.manage',\n 'deployments.trigger',\n 'changes.manage',\n 'changes.ship',\n 'site.settings',\n] as const;\nexport type GlobalAction = (typeof GLOBAL_ACTIONS)[number];\n\nexport type PermissionAction = ContentAction | GlobalAction;\n\nexport type RoleSummary = { id: string; key: string; name: string };\n\n/** Returned whenever a session starts (setup, login, accepting an invitation). */\nexport type SessionStarted = { user: AdminUser; csrfToken: string };\n\nexport type MeResponse = {\n user: AdminUser;\n roles: RoleSummary[];\n /** The site this response is about: the request's `Shapio-Site`, else the primary site. */\n site: SiteSummary;\n /** Every site this admin holds a role on (all of them for a role assigned on every site). */\n sites: SiteSummary[];\n /** Sites on this instance (whether or not the admin holds a role on them); scope is shown only above 1. */\n siteCount: number;\n /** Network actions (roles assigned on every site only). */\n networkPermissions: NetworkAction[];\n /**\n * Site actions on the request's site, plus `schema.create` when a role on the site grants it for the\n * site's own definitions (`networkPermissions` lists it when shared definitions may be created too).\n */\n sitePermissions: Array<SiteAction | 'schema.create'>;\n /** `networkPermissions` and `sitePermissions` together. */\n globalPermissions: GlobalAction[];\n /** Content actions per model ID on the request's site (models without any action are left out). */\n modelPermissions: Record<string, ContentAction[]>;\n /** How the server sends email: `console` writes it to the server log (no real delivery is set up). */\n emailDelivery: EmailDelivery;\n csrfToken: string;\n};\n\nexport type EmailDelivery = 'console' | 'smtp';\n\nexport type SetupStatusResponse = {\n /** No admin exists yet. */\n required: boolean;\n /** SETUP_REQUIRE_TOKEN is set: setup also needs the one-time token from the server log. */\n requiresToken: boolean;\n};\n\n/** `token` is needed only when the server requires it (`requiresToken`); otherwise it is ignored. */\nexport type SetupInput = { token?: string; email: string; name: string; password: string };\n\nexport type LoginInput = { email: string; password: string };\n\nexport type CsrfResponse = { csrfToken: string };\n\nexport type UpdateProfileInput = { name: string };\n\nexport type ChangePasswordInput = { currentPassword: string; newPassword: string };\n\nexport type PasswordResetRequestInput = { email: string };\n\nexport type PasswordResetConfirmInput = { token: string; password: string };\n\nexport type AcceptInvitationInput = { token: string; name: string; password: string };\n\nexport type InspectInvitationResponse = { email: string; expiresAt: string };\n\nexport type AdminSession = {\n id: string;\n current: boolean;\n ip: string | null;\n userAgent: string | null;\n createdAt: string;\n lastSeenAt: string;\n expiresAt: string;\n};\n\nexport type Invitation = {\n id: string;\n email: string;\n /** The role assignments the invitee gets on accepting. */\n assignments: RoleAssignment[];\n /** Deprecated: the distinct roles of `assignments`. */\n roleIds: string[];\n invitedBy: string | null;\n expiresAt: string;\n createdAt: string;\n};\n\n/** A fresh accept link, shown once; issuing it makes earlier links (emailed or copied) stop working. */\nexport type InvitationLink = { acceptUrl: string; expiresAt: string };\n\n/**\n * Either `assignments` or (deprecated) `roleIds`, meaning those roles on every site; never both. Updating\n * either replaces every assignment.\n */\ntype AssignmentsInput =\n { assignments: RoleAssignment[]; roleIds?: never } | { roleIds: string[]; assignments?: never };\n\nexport type InviteUserInput = { email: string } & AssignmentsInput;\n\nexport type UpdateAdminUserInput = { name?: string; status?: AdminUserStatus } & (\n AssignmentsInput | { assignments?: never; roleIds?: never }\n);\n\nexport type RoleKind = 'admin' | 'delivery';\n\nexport type RoleCondition = 'ownedByPrincipal';\n\nexport type RolePermission = {\n action: PermissionAction;\n /** `null` grants the action on every model (and is required for global actions). */\n modelId: string | null;\n condition: RoleCondition | null;\n /** `null` = every field; otherwise only these stable field IDs. */\n fieldIds: string[] | null;\n};\n\nexport type Role = {\n id: string;\n key: string;\n name: string;\n description: string;\n kind: RoleKind;\n isSystem: boolean;\n /** Optimistic-concurrency version: send it back as `expectedVersion` on update. */\n version: number;\n permissions: RolePermission[];\n createdAt: string;\n updatedAt: string;\n};\n\nexport type CreateRoleInput = {\n key: string;\n name: string;\n description?: string;\n kind?: RoleKind;\n permissions: RolePermission[];\n};\n\nexport type UpdateRoleInput = {\n expectedVersion: number;\n name?: string;\n description?: string;\n permissions?: RolePermission[];\n};\n\nexport type ApiToken = {\n id: string;\n name: string;\n /** First characters of the token (`shp_` + 6), for telling tokens apart. */\n tokenPrefix: string;\n roleId: string;\n scope: RoleKind;\n /** The token's site; null for a network admin token (its role applies on every site). */\n siteId: string | null;\n createdBy: string | null;\n expiresAt: string | null;\n lastUsedAt: string | null;\n revokedAt: string | null;\n createdAt: string;\n};\n\nexport type CreateApiTokenInput = {\n name: string;\n roleId: string;\n expiresAt?: string | null;\n /**\n * A network admin token (every site and network actions; needs `users.manage`). Omitted: a network token\n * when the creator may create one, else a token of the request's site. Delivery tokens are always per site.\n */\n network?: boolean;\n};\n\n/** `token` is the plain secret, returned once at creation and never again. */\nexport type CreatedApiToken = { token: string; apiToken: ApiToken };\n\nexport type AuditActorType = 'admin' | 'app_user' | 'token' | 'anonymous' | 'system';\n\nexport type AuditEvent = {\n id: string;\n occurredAt: string;\n actorType: AuditActorType;\n actorId: string | null;\n /** The acting admin's (or app user's) display name, when the actor is a known account. */\n actorName: string | null;\n actorEmail: string | null;\n action: string;\n targetType: string | null;\n targetId: string | null;\n outcome: 'success' | 'failure';\n requestId: string | null;\n ip: string | null;\n metadata: unknown;\n};\n\n/** Newest first, cursor-paginated. */\nexport type AuditQuery = {\n cursor?: string;\n limit?: number;\n actorType?: AuditActorType;\n actorId?: string;\n action?: string;\n actionPrefix?: string;\n targetType?: string;\n targetId?: string;\n outcome?: 'success' | 'failure';\n from?: string;\n to?: string;\n};\n\nexport type AuditPage = { items: AuditEvent[]; nextCursor: string | null };\n","/**\n * App users and app roles as administrators manage them (package I), mirroring the TypeBox route schemas in\n * apps/api/src/routes/admin/{appUsers,appRoles}. JSON is camelCase; timestamps are ISO-8601.\n */\nimport type { RoleCondition } from './types.js';\n\nexport type AdminAppUser = {\n id: string;\n email: string;\n name: string;\n confirmed: boolean;\n blocked: boolean;\n /** False for accounts that only sign in with an OAuth provider. */\n hasPassword: boolean;\n /** OAuth providers linked to the account (`google`, `github`). */\n providers: string[];\n /** Custom app roles; `authenticated` applies to every app user implicitly. */\n roleIds: string[];\n lastLoginAt: string | null;\n createdAt: string;\n updatedAt: string;\n};\n\n/** Newest first, cursor-paginated; `search` matches email or name. */\nexport type AppUserQuery = { search?: string; cursor?: string; limit?: number };\n\nexport type AppUserPage = { items: AdminAppUser[]; nextCursor: string | null };\n\nexport type UpdateAppUserInput = { blocked?: boolean; roleIds?: string[] };\n\n/** What app roles may grant: content actions only. */\nexport const APP_CONTENT_ACTIONS = ['read', 'create', 'update', 'delete', 'publish'] as const;\nexport type AppContentAction = (typeof APP_CONTENT_ACTIONS)[number];\n\n/** Built-in app role keys: `public` applies to anonymous callers, `authenticated` to every app user. */\nexport const BUILT_IN_APP_ROLE_KEYS = ['public', 'authenticated'] as const;\n\nexport type AppRolePermission = {\n action: AppContentAction;\n /** `null` grants the action on every model, including ones created later. */\n modelId: string | null;\n condition: RoleCondition | null;\n /** `null` = every public field; otherwise exactly these stable field IDs (non-public ones included). */\n fieldIds: string[] | null;\n};\n\nexport type AppRole = {\n id: string;\n key: string;\n name: string;\n description: string;\n isSystem: boolean;\n version: number;\n permissions: AppRolePermission[];\n userCount: number;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type CreateAppRoleInput = {\n key: string;\n name: string;\n description?: string;\n permissions: AppRolePermission[];\n};\n\n/** Built-in roles accept `permissions` only. */\nexport type UpdateAppRoleInput = {\n expectedVersion: number;\n name?: string;\n description?: string;\n permissions?: AppRolePermission[];\n};\n","/**\n * @license lucide-react v1.49.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 __iconData = {\n name: \"book-open\",\n size: 24,\n node: [\n [\"path\", { d: \"M12 5v16\", key: \"1f6ucr\" }],\n [\n \"path\",\n {\n d: \"M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z\",\n key: \"1fyvmf\"\n }\n ]\n ]\n};\n__iconData.node;\nconst BookOpen = createLucideIcon(__iconData);\n\nexport { __iconData, BookOpen as default };\n//# sourceMappingURL=book-open.mjs.map\n","/**\n * @license lucide-react v1.49.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 __iconData = {\n name: \"sliders-horizontal\",\n size: 24,\n node: [\n [\"path\", { d: \"M10 5H3\", key: \"1qgfaw\" }],\n [\"path\", { d: \"M12 19H3\", key: \"yhmn1j\" }],\n [\"path\", { d: \"M14 3v4\", key: \"1sua03\" }],\n [\"path\", { d: \"M16 17v4\", key: \"1q0r14\" }],\n [\"path\", { d: \"M21 12h-9\", key: \"1o4lsq\" }],\n [\"path\", { d: \"M21 19h-5\", key: \"1rlt1p\" }],\n [\"path\", { d: \"M21 5h-7\", key: \"1oszz2\" }],\n [\"path\", { d: \"M8 10v4\", key: \"tgpxqk\" }],\n [\"path\", { d: \"M8 12H3\", key: \"a7s4jb\" }]\n ]\n};\n__iconData.node;\nconst SlidersHorizontal = createLucideIcon(__iconData);\n\nexport { __iconData, SlidersHorizontal as default };\n//# sourceMappingURL=sliders-horizontal.mjs.map\n","import { Link } from '@tanstack/react-router';\nimport { Boxes, Plus } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useSharedDefinitions } from '@/api/schema';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { QueryView } from '@/components/QueryView';\nimport { Button } from '@/components/ui/button';\nimport { useSchemaLock } from '@/features/Models/hooks/useSchemaLock';\nimport { List } from '@/features/Models/List';\nimport { LockNotice } from '@/features/Models/LockNotice';\n\n/**\n * Network → Content types: the content types and components shared with all sites (each site has them,\n * with its own content). Rows open the builder; New creates a shared one. The network route guard and the\n * nav item need `schema.create` on every site; the server enforces it either way.\n */\nexport const ContentTypes = () => {\n const { t } = useTranslation();\n const shared = useSharedDefinitions();\n const { locked, reason } = useSchemaLock();\n const createAction = locked ? null : (\n <Button asChild>\n <Link to=\"/network/content-types/new\">\n <Plus aria-hidden=\"true\" />\n {t('contentTypes.network.create')}\n </Link>\n </Button>\n );\n return (\n <Page>\n <PageHeader\n title={t('contentTypes.network.title')}\n meta={shared.data ? t('contentTypes.network.count', { count: shared.data.length }) : undefined}\n actions={createAction}\n />\n {locked ? <LockNotice reason={reason} /> : null}\n <QueryView\n query={shared}\n isEmpty={(data) => data.length === 0}\n empty={\n <EmptyState\n icon={Boxes}\n title={t('contentTypes.network.empty')}\n description={t('contentTypes.network.emptyDescription')}\n action={createAction}\n />\n }\n >\n {(data) => <List items={data} showKind markShared={false} />}\n </QueryView>\n </Page>\n );\n};\n","import { linkOptions } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { Form } from '@/features/Content/New/Form';\n\nconst KINDS = ['collection', 'singleton', 'component'] as const;\n\n/** `/network/content-types/new`: a content type or component shared with all sites, live once created. */\nexport const New = () => {\n const { t } = useTranslation();\n return (\n <Form\n title={t('contentTypes.network.newTitle')}\n kinds={KINDS}\n back={linkOptions({ to: '/network/content-types' })}\n backLabel={t('contentTypes.network.title')}\n scope=\"network\"\n />\n );\n};\n","import type { CreateSiteInput, SetSiteAppRolesInput, Site, UpdateSiteInput } from '@shapio/client';\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { currentSite, leaveDeletedSite } from '@/app/currentSite';\nimport { adminApi } from './client';\nimport { withCsrf } from './csrf';\nimport { queryKeys } from './queryKeys';\n\n/** The sites list and `me` (whose `sites` feed the switcher) after a site is created, renamed or deleted. */\nconst refreshSites = (queryClient: QueryClient) =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: queryKeys.sites.all }),\n queryClient.invalidateQueries({ queryKey: queryKeys.me }),\n ]);\n\n/** Every site the admin works on (all of them with a role on every site). */\nexport const useSites = () =>\n useQuery({ queryKey: queryKeys.sites.all, queryFn: () => adminApi.sites.list(), meta: { silent: true } });\n\nexport const useSite = (id: string) =>\n useQuery({\n queryKey: queryKeys.sites.site(id),\n queryFn: () => adminApi.sites.get(id),\n meta: { silent: true },\n });\n\n/** Site names by ID, for the role assignments and webhooks that name a site. */\nexport const useSiteNames = () => {\n const sites = useSites();\n const names = useMemo(() => new Map((sites.data ?? []).map((site) => [site.id, site.name])), [sites.data]);\n return { names, error: sites.error };\n};\n\nexport const useCreateSite = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationKey: ['sites', 'create'],\n meta: { silent: true },\n mutationFn: (input: CreateSiteInput) => withCsrf(() => adminApi.sites.create(input)),\n onSuccess: () => refreshSites(queryClient),\n });\n};\n\nexport const useUpdateSite = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationKey: ['sites', 'update'],\n meta: { silent: true },\n mutationFn: ({ id, input }: { id: string; input: UpdateSiteInput }) =>\n withCsrf(() => adminApi.sites.update(id, input)),\n onSettled: () => refreshSites(queryClient),\n });\n};\n\n/**\n * Shows its own error (`SITE_NOT_EMPTY`, `SITE_IS_PRIMARY`) where the delete was asked for. Deleting the site\n * this page load works on leaves it (a full navigation to the sites list): every request names that site.\n */\nexport const useDeleteSite = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationKey: ['sites', 'delete'],\n meta: { silent: true },\n mutationFn: (site: Pick<Site, 'id' | 'key'>) => withCsrf(() => adminApi.sites.remove(site.id)),\n onSuccess: (_result, site) => {\n if (site.key === currentSite().key) {\n leaveDeletedSite();\n return undefined;\n }\n queryClient.removeQueries({ queryKey: queryKeys.sites.site(site.id) });\n return refreshSites(queryClient);\n },\n });\n};\n\nexport const useSiteAppRoles = (id: string) =>\n useQuery({\n queryKey: queryKeys.sites.appRoles(id),\n queryFn: () => adminApi.sites.appRoles.get(id),\n meta: { silent: true },\n });\n\nexport const useSetSiteAppRoles = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationKey: ['sites', 'appRoles', 'set'],\n meta: { silent: true },\n mutationFn: ({ id, input }: { id: string; input: SetSiteAppRolesInput }) =>\n withCsrf(() => adminApi.sites.appRoles.set(id, input)),\n onSuccess: (result) => queryClient.setQueryData(queryKeys.sites.appRoles(result.siteId), result),\n });\n};\n","import type { SiteAppRoles } from '@shapio/client';\nimport { useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { useSetSiteAppRoles } from '@/api/sites';\nimport { i18next } from '@/app/i18n';\nimport { settle } from '@/helpers/settle';\n\nexport type AppRoleBindingsValues = { public: string[]; authenticated: string[] };\n\n/** Which app roles apply on this site to anonymous callers and to every signed-in app user. */\nexport const useAppRoleBindingsForm = (bindings: SiteAppRoles) => {\n const setBindings = useSetSiteAppRoles();\n const form = useForm<AppRoleBindingsValues>({\n defaultValues: { public: bindings.public, authenticated: bindings.authenticated },\n });\n const { reset, formState } = form;\n useEffect(() => {\n if (!formState.isDirty) {\n reset({ public: bindings.public, authenticated: bindings.authenticated });\n }\n }, [bindings, reset, formState.isDirty]);\n const onSubmit = form.handleSubmit(async (values) => {\n const saved = await settle(setBindings.mutateAsync({ id: bindings.siteId, input: values }));\n if (!saved.ok) {\n return;\n }\n reset({ public: saved.value.public, authenticated: saved.value.authenticated });\n toast.success(i18next.t('sites.appRoles.saved'));\n });\n return { form, onSubmit, setBindings };\n};\n","import type { AppRole, SiteAppRoles } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { useAppRoles } from '@/api/appRoles';\nimport { useSiteAppRoles } from '@/api/sites';\nimport { FormCheckboxGroup } from '@/components/FormCheckboxGroup';\nimport { FormError } from '@/components/FormError';\nimport { Panel } from '@/components/Panel';\nimport { QueryView } from '@/components/QueryView';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { FieldGroup } from '@/components/ui/field';\nimport { UnsavedChangesGuard } from '@/components/UnsavedChangesGuard';\nimport { useAppRoleBindingsForm } from '../hooks/useAppRoleBindingsForm';\n\ntype FormProps = { bindings: SiteAppRoles; roles: readonly AppRole[]; canManage: boolean };\n\nconst Form = ({ bindings, roles, canManage }: FormProps) => {\n const { t } = useTranslation();\n const { form, onSubmit, setBindings } = useAppRoleBindingsForm(bindings);\n const options = roles.map((role) => ({ value: role.id, label: role.name }));\n const { isDirty } = form.formState;\n return (\n <form noValidate onSubmit={(event) => void onSubmit(event)}>\n <FieldGroup>\n <FormCheckboxGroup\n control={form.control}\n name=\"public\"\n legend={t('sites.appRoles.public')}\n options={options}\n disabled={!canManage}\n />\n <FormCheckboxGroup\n control={form.control}\n name=\"authenticated\"\n legend={t('sites.appRoles.authenticated')}\n options={options}\n disabled={!canManage}\n />\n <FormError error={setBindings.error} />\n {canManage ? (\n <div>\n <SubmitButton\n pending={setBindings.isPending}\n pendingLabel={t('common.saving')}\n disabled={!isDirty}\n >\n {t('common.saveChanges')}\n </SubmitButton>\n </div>\n ) : null}\n </FieldGroup>\n <UnsavedChangesGuard when={isDirty} />\n </form>\n );\n};\n\ntype AppRoleBindingsProps = { siteId: string; canManage: boolean };\n\n/**\n * The app roles this site grants (sites plan §H): `public` to anonymous delivery callers, `authenticated` to\n * every signed-in app user of the site. A new site binds nothing, so it shows nothing until bound here.\n */\nexport const AppRoleBindings = ({ siteId, canManage }: AppRoleBindingsProps) => {\n const { t } = useTranslation();\n const bindings = useSiteAppRoles(siteId);\n const roles = useAppRoles();\n return (\n <Panel title={t('sites.appRoles.title')} description={t('sites.appRoles.description')}>\n <QueryView query={bindings}>\n {(data) => (\n <QueryView query={roles}>\n {(appRoles) => <Form bindings={data} roles={appRoles} canManage={canManage} />}\n </QueryView>\n )}\n </QueryView>\n </Panel>\n );\n};\n","import type { Site } from '@shapio/client';\nimport { useNavigate } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useDeleteSite } from '@/api/sites';\nimport { currentSite } from '@/app/currentSite';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { Panel } from '@/components/Panel';\nimport { Button } from '@/components/ui/button';\n\ntype DangerZoneProps = { site: Site };\n\n/**\n * Deleting a site: only an empty one (no entries, media, folders, change sets or app users), never the\n * primary one. The server says which (`SITE_NOT_EMPTY`, `SITE_IS_PRIMARY`); the confirmation shows it.\n */\nexport const DangerZone = ({ site }: DangerZoneProps) => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const deleteSite = useDeleteSite();\n const remove = async () => {\n await deleteSite.mutateAsync(site);\n // Deleting this page load's own site reloads the sites list instead (see useDeleteSite).\n if (site.key !== currentSite().key) {\n toast.success(t('sites.deleted', { name: site.name }));\n void navigate({ to: '/network/sites' });\n }\n };\n return (\n <Panel title={t('sites.danger')} description={t('sites.deleteDescription')}>\n <InlineConfirm\n tone=\"danger\"\n title={t('sites.deleteTitle', { name: site.name })}\n description={t('sites.deleteConsequence')}\n confirmLabel={t('common.delete')}\n onConfirm={remove}\n trigger={<Button variant=\"destructive-ghost\">{t('sites.delete')}</Button>}\n />\n </Panel>\n );\n};\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { Site } from '@shapio/client';\nimport { useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useUpdateSite } from '@/api/sites';\nimport { i18next } from '@/app/i18n';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\n\nconst renameSchema = z.object({ name: requiredText().max(200, 'validation.tooLong') });\n\nexport type RenameSiteValues = z.infer<typeof renameSchema>;\n\n/** A site's name, saved with the version it was loaded at (a stale save is refused, 409). */\nexport const useRenameSiteForm = (site: Site) => {\n const updateSite = useUpdateSite();\n const form = useForm<RenameSiteValues>({\n resolver: zodResolver(renameSchema),\n defaultValues: { name: site.name },\n });\n const { reset, formState } = form;\n // Follow the server's value when it changes elsewhere, unless the admin is mid-edit.\n useEffect(() => {\n if (!formState.isDirty) {\n reset({ name: site.name });\n }\n }, [site.name, reset, formState.isDirty]);\n const onSubmit = form.handleSubmit(async ({ name }) => {\n const saved = await settle(\n updateSite.mutateAsync({ id: site.id, input: { expectedVersion: site.version, name } }),\n );\n if (!saved.ok) {\n return;\n }\n reset({ name: saved.value.name });\n toast.success(i18next.t('sites.renamed'));\n });\n return { form, onSubmit, updateSite };\n};\n","import type { Site } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { FormError } from '@/components/FormError';\nimport { FormTextField } from '@/components/FormTextField';\nimport { HintedLabel } from '@/components/HintedLabel';\nimport { Panel } from '@/components/Panel';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { Field, FieldGroup } from '@/components/ui/field';\nimport { Input } from '@/components/ui/input';\nimport { UnsavedChangesGuard } from '@/components/UnsavedChangesGuard';\nimport { useRenameSiteForm } from '../hooks/useRenameSiteForm';\n\ntype DetailsProps = { site: Site; canManage: boolean };\n\nconst KEY_ID = 'site-key';\nconst KEY_HINT_ID = 'site-key-hint';\n\n/** The site's name (renamed with `sites.manage`) and its fixed key. */\nexport const Details = ({ site, canManage }: DetailsProps) => {\n const { t } = useTranslation();\n const { form, onSubmit, updateSite } = useRenameSiteForm(site);\n const { isDirty } = form.formState;\n return (\n <Panel title={t('sites.details')}>\n <form noValidate onSubmit={(event) => void onSubmit(event)} className=\"max-w-md\">\n <FieldGroup>\n <FormTextField\n control={form.control}\n name=\"name\"\n label={t('sites.name')}\n autoComplete=\"off\"\n readOnly={!canManage}\n />\n <Field>\n <HintedLabel\n htmlFor={KEY_ID}\n label={t('sites.key')}\n hint={t('sites.keyHint')}\n hintId={KEY_HINT_ID}\n />\n <Input\n id={KEY_ID}\n value={site.key}\n readOnly\n className=\"font-mono\"\n aria-describedby={KEY_HINT_ID}\n />\n </Field>\n <FormError error={updateSite.error} />\n {canManage ? (\n <div>\n <SubmitButton\n pending={updateSite.isPending}\n pendingLabel={t('common.saving')}\n disabled={!isDirty}\n >\n {t('common.saveChanges')}\n </SubmitButton>\n </div>\n ) : null}\n </FieldGroup>\n </form>\n <UnsavedChangesGuard when={isDirty} />\n </Panel>\n );\n};\n","import { linkOptions, useParams } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { useSite } from '@/api/sites';\nimport { goToSite } from '@/app/currentSite';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { QueryView } from '@/components/QueryView';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { useNetworkPermission } from '../hooks/useNetworkPermission';\nimport { AppRoleBindings } from './AppRoleBindings';\nimport { DangerZone } from './DangerZone';\nimport { Details } from './Details';\n\n/** Network → Sites → one site: its name and key, the app roles it grants, and deleting it. */\nexport const Site = () => {\n const { t } = useTranslation();\n const { siteId } = useParams({ from: '/app/network/sites/$siteId' });\n const site = useSite(siteId);\n const canManage = useNetworkPermission('sites.manage');\n const canManageRoles = useNetworkPermission('roles.manage');\n return (\n <Page width=\"narrow\">\n <QueryView query={site}>\n {(data) => (\n <>\n <PageHeader\n breadcrumb={[{ label: t('sites.title'), link: linkOptions({ to: '/network/sites' }) }]}\n title={data.name}\n badge={data.isPrimary ? <Badge variant=\"secondary\">{t('sites.primary')}</Badge> : null}\n meta={data.key}\n actions={\n <Button variant=\"outline\" onClick={() => goToSite(data.key)}>\n {t('sites.open')}\n </Button>\n }\n />\n <Details key={data.id} site={data} canManage={canManage} />\n <AppRoleBindings siteId={data.id} canManage={canManageRoles} />\n {canManage && !data.isPrimary ? <DangerZone site={data} /> : null}\n </>\n )}\n </QueryView>\n </Page>\n );\n};\n","/** A site key: lower case, starts with a letter (the API's `SITE_KEY_PATTERN`). Fixed once created. */\nexport const SITE_KEY_PATTERN = /^[a-z][a-z0-9-]{0,62}$/;\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { Site } from '@shapio/client';\nimport { useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport { useCreateSite } from '@/api/sites';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\nimport { SITE_KEY_PATTERN } from '../../constants';\n\nconst createSiteSchema = z.object({\n name: requiredText().max(200, 'validation.tooLong'),\n key: z.string().trim().regex(SITE_KEY_PATTERN, 'validation.siteKey'),\n});\n\nexport type CreateSiteValues = z.infer<typeof createSiteSchema>;\n\nconst EMPTY: CreateSiteValues = { name: '', key: '' };\n\n/** The new-site sheet's form: a name and the fixed key its URLs use. */\nexport const useCreateSiteForm = (open: boolean, onCreated: (site: Site) => void) => {\n const createSite = useCreateSite();\n const form = useForm<CreateSiteValues>({ resolver: zodResolver(createSiteSchema), defaultValues: EMPTY });\n const { reset } = form;\n useEffect(() => {\n if (open) {\n reset(EMPTY);\n }\n }, [open, reset]);\n const onSubmit = form.handleSubmit(async (values) => {\n const created = await settle(createSite.mutateAsync(values));\n if (!created.ok) {\n return;\n }\n reset(EMPTY);\n onCreated(created.value);\n });\n return { form, onSubmit, createSite };\n};\n","import type { Site } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { FormError } from '@/components/FormError';\nimport { FormSheet } from '@/components/FormSheet';\nimport { FormTextField } from '@/components/FormTextField';\nimport { useCreateSiteForm } from '../hooks/useCreateSiteForm';\n\ntype CreateSheetProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreated: (site: Site) => void;\n};\n\n/** A new site: its name, and the key that its URLs and API calls use (fixed once created). */\nexport const CreateSheet = ({ open, onOpenChange, onCreated }: CreateSheetProps) => {\n const { t } = useTranslation();\n const { form, onSubmit, createSite } = useCreateSiteForm(open, onCreated);\n return (\n <FormSheet\n open={open}\n onOpenChange={onOpenChange}\n size=\"md\"\n title={t('sites.createTitle')}\n dirty={form.formState.isDirty}\n pending={createSite.isPending}\n submitLabel={t('common.create')}\n pendingLabel={t('common.saving')}\n onSubmit={(event) => void onSubmit(event)}\n >\n <FormTextField control={form.control} name=\"name\" label={t('sites.name')} autoComplete=\"off\" />\n <FormTextField\n control={form.control}\n name=\"key\"\n label={t('sites.key')}\n autoComplete=\"off\"\n spellCheck={false}\n hint={t('sites.keyHint')}\n description={t('sites.keyFixed')}\n />\n <FormError error={createSite.error} />\n </FormSheet>\n );\n};\n","import type { Site } from '@shapio/client';\nimport { Link } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { goToSite } from '@/app/currentSite';\nimport { RowTitle } from '@/components/RowTitle';\nimport { TableCard } from '@/components/TableCard';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport {\n Table as TableRoot,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table';\nimport { formatDateTime, formatRelativeTime } from '@/helpers/formatDate';\n\ntype TableProps = { sites: readonly Site[] };\n\n/** Every site: name (to its page), key, created; \"Open\" switches the admin to the site. */\nexport const Table = ({ sites }: TableProps) => {\n const { t } = useTranslation();\n return (\n <TableCard>\n <TableRoot>\n <TableHeader>\n <TableRow>\n <TableHead>{t('sites.name')}</TableHead>\n <TableHead>{t('sites.key')}</TableHead>\n <TableHead>{t('sites.createdAt')}</TableHead>\n <TableHead>\n <span className=\"sr-only\">{t('common.actions')}</span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {sites.map((site) => (\n <TableRow key={site.id}>\n <TableCell>\n <div className=\"flex items-center gap-2\">\n <RowTitle asChild>\n <Link to=\"/network/sites/$siteId\" params={{ siteId: site.id }}>\n {site.name}\n </Link>\n </RowTitle>\n {site.isPrimary ? <Badge variant=\"secondary\">{t('sites.primary')}</Badge> : null}\n </div>\n </TableCell>\n <TableCell className=\"font-mono text-xs\">{site.key}</TableCell>\n <TableCell title={formatDateTime(site.createdAt)}>\n {formatRelativeTime(site.createdAt)}\n </TableCell>\n <TableCell className=\"text-right\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={t('sites.openNamed', { name: site.name })}\n onClick={() => goToSite(site.key)}\n >\n {t('sites.open')}\n </Button>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </TableRoot>\n </TableCard>\n );\n};\n","import type { Site } from '@shapio/client';\nimport { useNavigate } from '@tanstack/react-router';\nimport { Globe2, Plus } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useSites } from '@/api/sites';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { QueryView } from '@/components/QueryView';\nimport { Button } from '@/components/ui/button';\nimport { useNetworkPermission } from '../hooks/useNetworkPermission';\nimport { CreateSheet } from './CreateSheet';\nimport { Table } from './Table';\n\n/** Network → Sites: every site on this instance; one login, each with its own content types and content. */\nexport const Sites = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const sites = useSites();\n const canManage = useNetworkPermission('sites.manage');\n const [creating, setCreating] = useState(false);\n const onCreated = (site: Site) => {\n setCreating(false);\n toast.success(t('sites.created', { name: site.name }));\n void navigate({ to: '/network/sites/$siteId', params: { siteId: site.id } });\n };\n return (\n <Page>\n <PageHeader\n title={t('sites.title')}\n meta={sites.data ? t('sites.count', { count: sites.data.length }) : undefined}\n actions={\n canManage ? (\n <Button onClick={() => setCreating(true)}>\n <Plus aria-hidden=\"true\" />\n {t('sites.create')}\n </Button>\n ) : null\n }\n />\n <QueryView\n query={sites}\n isEmpty={(data) => data.length === 0}\n empty={<EmptyState icon={Globe2} title={t('sites.empty')} />}\n >\n {(data) => <Table sites={data} />}\n </QueryView>\n {canManage ? <CreateSheet open={creating} onOpenChange={setCreating} onCreated={onCreated} /> : null}\n </Page>\n );\n};\n","import type { AuditActorType } from '@shapio/client';\nimport { Search } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { AUDIT_ACTOR_TYPES } from '@/constants/audit';\n\ntype FiltersProps = {\n action: string | undefined;\n actorType: AuditActorType | undefined;\n onChange: (filters: { action: string | undefined; actorType: AuditActorType | undefined }) => void;\n};\n\nconst ALL = 'all';\n\nconst isActorType = (value: string): value is AuditActorType =>\n (AUDIT_ACTOR_TYPES as readonly string[]).includes(value);\n\n/** The audit table's filter row: action (applied on Enter or blur) and actor type. */\nexport const Filters = ({ action, actorType, onChange }: FiltersProps) => {\n const { t } = useTranslation();\n const [actionDraft, setActionDraft] = useState(action ?? '');\n const hasFilters = Boolean(action) || Boolean(actorType);\n return (\n <form\n role=\"search\"\n className=\"flex w-full flex-wrap items-center gap-2\"\n onSubmit={(event) => {\n event.preventDefault();\n onChange({ action: actionDraft.trim() || undefined, actorType });\n }}\n >\n <Label htmlFor=\"audit-action\" className=\"sr-only\">\n {t('audit.filterAction')}\n </Label>\n <div className=\"relative w-full sm:w-80\">\n <Search\n aria-hidden=\"true\"\n className=\"absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n id=\"audit-action\"\n inputSize=\"sm\"\n value={actionDraft}\n placeholder={t('audit.filterActionPlaceholder')}\n onChange={(event) => setActionDraft(event.target.value)}\n onBlur={() => onChange({ action: actionDraft.trim() || undefined, actorType })}\n className=\"pl-8\"\n />\n </div>\n <Label htmlFor=\"audit-actor-type\" className=\"sr-only\">\n {t('audit.filterActor')}\n </Label>\n <Select\n value={actorType ?? ALL}\n onValueChange={(value) => onChange({ action, actorType: isActorType(value) ? value : undefined })}\n >\n <SelectTrigger id=\"audit-actor-type\" size=\"sm\" className=\"w-44\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>{t('audit.allActors')}</SelectItem>\n {AUDIT_ACTOR_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {t(`audit.actorTypes.${type}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {hasFilters ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n setActionDraft('');\n onChange({ action: undefined, actorType: undefined });\n }}\n >\n {t('audit.clearFilters')}\n </Button>\n ) : null}\n </form>\n );\n};\n","import { useNavigate, useSearch } from '@tanstack/react-router';\nimport { useState } from 'react';\nimport type { AuditSearch } from '@/app/searchSchemas';\n\n/**\n * Filters and the current cursor live in the URL (bookmarkable, back-button friendly). The cursors of the\n * pages before this one are kept in memory, since the API pages forward only (newest first).\n */\nexport const useAuditLogSearch = () => {\n const search = useSearch({ from: '/app/network/audit-log' });\n const navigate = useNavigate({ from: '/network/audit-log' });\n const [previousCursors, setPreviousCursors] = useState<(string | undefined)[]>([]);\n const go = (changes: Partial<AuditSearch>) =>\n void navigate({ search: (previous) => ({ ...previous, ...changes }) });\n const atFirst = search.cursor === undefined;\n return {\n search,\n goFirst: atFirst\n ? undefined\n : () => {\n setPreviousCursors([]);\n go({ cursor: undefined });\n },\n goPrevious:\n previousCursors.length === 0\n ? undefined\n : () => {\n go({ cursor: previousCursors.at(-1) });\n setPreviousCursors((cursors) => cursors.slice(0, -1));\n },\n goNext: (nextCursor: string) => {\n setPreviousCursors((cursors) => [...cursors, search.cursor]);\n go({ cursor: nextCursor });\n },\n setFilters: (filters: Pick<AuditSearch, 'action' | 'actorType'>) => {\n setPreviousCursors([]);\n go({ ...filters, cursor: undefined });\n },\n };\n};\n","import type { AuditEvent } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { StatusChip } from '@/components/StatusChip';\nimport { Badge } from '@/components/ui/badge';\nimport {\n Table as TableRoot,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table';\nimport { UserAvatar } from '@/components/UserAvatar';\nimport { auditTargetName } from '@/helpers/auditTargetName';\nimport { formatDateTime, formatRelativeTime } from '@/helpers/formatDate';\nimport { useAuditLabels } from '@/hooks/useAuditLabels';\n\ntype TableProps = { events: AuditEvent[] };\n\n/** `admin_role:1f2e…`: the raw reference, kept in a title for support and log searches. */\nconst targetReference = (event: AuditEvent) =>\n event.targetType ? `${event.targetType}:${event.targetId ?? ''}` : undefined;\n\nexport const Table = ({ events }: TableProps) => {\n const { t } = useTranslation();\n const { actionLabel, targetLabel } = useAuditLabels();\n return (\n <TableRoot>\n <TableHeader>\n <TableRow>\n <TableHead>{t('audit.actor')}</TableHead>\n <TableHead>{t('audit.action')}</TableHead>\n <TableHead>{t('audit.target')}</TableHead>\n <TableHead>{t('audit.outcome')}</TableHead>\n <TableHead>{t('audit.ipAddress')}</TableHead>\n <TableHead>{t('audit.when')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {events.map((event) => {\n const actorType = t(`audit.actorTypes.${event.actorType}`);\n const name = event.actorName ?? event.actorEmail ?? actorType;\n const detail =\n event.actorName && event.actorEmail\n ? event.actorEmail\n : event.actorName || event.actorEmail\n ? actorType\n : (event.actorId ?? undefined);\n const action = actionLabel(event.action);\n const reference = targetReference(event);\n const targetName = auditTargetName(event.metadata);\n return (\n <TableRow key={event.id}>\n <TableCell>\n <span className=\"flex items-center gap-2.5\">\n <UserAvatar name={name} size=\"sm\" />\n <span className=\"min-w-0\">\n <span className=\"block max-w-48 truncate text-sm font-semibold\">{name}</span>\n {detail ? (\n <span className=\"block max-w-48 truncate text-xs text-muted-foreground\" title={detail}>\n {detail}\n </span>\n ) : null}\n </span>\n </span>\n </TableCell>\n <TableCell title={event.action}>\n {action ? (\n <Badge variant=\"secondary\">{action}</Badge>\n ) : (\n <Badge variant=\"secondary\" className=\"font-mono\">\n {event.action}\n </Badge>\n )}\n </TableCell>\n <TableCell className=\"max-w-64\" title={reference}>\n {event.targetType ? (\n <>\n <span className=\"block truncate text-sm\">\n {targetLabel(event.targetType) ?? (\n <span className=\"font-mono text-xs\">{event.targetType}</span>\n )}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground\">\n {targetName ?? <span className=\"font-mono\">{event.targetId}</span>}\n </span>\n </>\n ) : (\n <span className=\"text-muted-foreground\">{t('common.none')}</span>\n )}\n </TableCell>\n <TableCell>\n <StatusChip\n tone={event.outcome === 'success' ? 'success' : 'danger'}\n label={event.outcome === 'success' ? t('audit.success') : t('audit.failure')}\n />\n </TableCell>\n <TableCell className=\"font-mono text-xs\">{event.ip ?? t('common.unknown')}</TableCell>\n <TableCell className=\"whitespace-nowrap\" title={formatDateTime(event.occurredAt)}>\n {formatRelativeTime(event.occurredAt)}\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </TableRoot>\n );\n};\n","import { ScrollText } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useAuditEvents } from '@/api/audit';\nimport { AUDIT_PAGE_SIZE } from '@/app/searchSchemas';\nimport { CursorPager } from '@/components/CursorPager';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { QueryView } from '@/components/QueryView';\nimport { TableCard } from '@/components/TableCard';\nimport { Filters } from './Filters';\nimport { useAuditLogSearch } from './hooks/useAuditLogSearch';\nimport { Table } from './Table';\n\nexport const AuditLog = () => {\n const { t } = useTranslation();\n const { search, goFirst, goPrevious, goNext, setFilters } = useAuditLogSearch();\n const events = useAuditEvents({\n cursor: search.cursor,\n limit: AUDIT_PAGE_SIZE,\n action: search.action,\n actorType: search.actorType,\n });\n const nextCursor = events.data?.nextCursor;\n return (\n <Page width=\"full\">\n <PageHeader title={t('audit.title')} />\n <TableCard\n toolbar={\n <Filters\n key={`${search.action ?? ''}|${search.actorType ?? ''}`}\n action={search.action}\n actorType={search.actorType}\n onChange={setFilters}\n />\n }\n footer={\n <CursorPager\n onFirst={goFirst}\n onPrevious={goPrevious}\n onNext={nextCursor ? () => goNext(nextCursor) : undefined}\n />\n }\n >\n <QueryView\n query={events}\n loadingRows={8}\n isEmpty={(data) => data.items.length === 0 && search.cursor === undefined}\n empty={<EmptyState size=\"panel\" icon={ScrollText} title={t('audit.empty')} />}\n >\n {(data) => <Table events={data.items} />}\n </QueryView>\n </TableCard>\n </Page>\n );\n};\n","import { CONTENT_ACTIONS, GLOBAL_ACTIONS, type PermissionAction, type RoleKind } from '@shapio/client';\n\nexport { CONTENT_ACTIONS, GLOBAL_ACTIONS };\n\n/** Every action this form edits. Content grants made here apply to every model (`modelId: null`). */\nexport const EDITABLE_ACTIONS: readonly PermissionAction[] = [...CONTENT_ACTIONS, ...GLOBAL_ACTIONS];\n\n/** Translation keys per action (action names contain dots, which i18next reads as nesting). */\nexport const ACTION_LABEL_KEYS = {\n read: 'roles.actions.read',\n create: 'roles.actions.create',\n update: 'roles.actions.update',\n delete: 'roles.actions.delete',\n publish: 'roles.actions.publish',\n schemaManage: 'roles.actions.schemaManage',\n 'schema.create': 'roles.actions.schemaCreate',\n 'users.manage': 'roles.actions.usersManage',\n 'roles.manage': 'roles.actions.rolesManage',\n 'tokens.manage': 'roles.actions.tokensManage',\n 'audit.read': 'roles.actions.auditRead',\n 'sites.manage': 'roles.actions.sitesManage',\n 'media.read': 'roles.actions.mediaRead',\n 'media.write': 'roles.actions.mediaWrite',\n 'media.manage': 'roles.actions.mediaManage',\n 'publishing.manage': 'roles.actions.publishingManage',\n 'webhooks.manage': 'roles.actions.webhooksManage',\n 'deployments.manage': 'roles.actions.deploymentsManage',\n 'deployments.trigger': 'roles.actions.deploymentsTrigger',\n 'changes.manage': 'roles.actions.changesManage',\n 'changes.ship': 'roles.actions.changesShip',\n 'site.settings': 'roles.actions.siteSettings',\n} as const satisfies Record<PermissionAction, string>;\n\nexport const ROLE_KINDS: readonly RoleKind[] = ['admin', 'delivery'];\n\n/** Same rule as the server (admin_roles.key check constraint). */\nexport const ROLE_KEY_PATTERN = /^[a-z][a-z0-9-]{0,62}$/;\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { PermissionAction, Role, RolePermission } from '@shapio/client';\nimport { useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useCreateRole, useUpdateRole } from '@/api/roles';\nimport { i18next } from '@/app/i18n';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\nimport { EDITABLE_ACTIONS, ROLE_KEY_PATTERN } from '../constants';\n\nconst roleSchema = z.object({\n key: z.string().trim().regex(ROLE_KEY_PATTERN, 'validation.roleKey'),\n name: requiredText(),\n description: z.string().trim(),\n kind: z.enum(['admin', 'delivery']),\n actions: z.array(\n z.custom<PermissionAction>((value) => EDITABLE_ACTIONS.includes(value as PermissionAction)),\n ),\n});\n\nexport type RoleValues = z.infer<typeof roleSchema>;\n\n/** A grant this form owns: on every model, unconditional, every field. Anything narrower is left alone. */\nconst isEveryModelGrant = (permission: RolePermission) =>\n permission.modelId === null && permission.condition === null && permission.fieldIds === null;\n\nconst valuesFor = (role: Role | undefined): RoleValues => ({\n key: role?.key ?? '',\n name: role?.name ?? '',\n description: role?.description ?? '',\n kind: role?.kind ?? 'admin',\n actions: (role?.permissions ?? []).filter(isEveryModelGrant).map((permission) => permission.action),\n});\n\nconst toGrant = (action: PermissionAction): RolePermission => ({\n action,\n modelId: null,\n condition: null,\n fieldIds: null,\n});\n\n/**\n * Create or edit a role. Editing replaces only the every-model grants shown in the form and keeps any\n * model-, field- or condition-specific grants untouched. Updates send the version the form was opened with\n * (optimistic concurrency: a concurrent change is a VERSION_CONFLICT, not a silent overwrite).\n */\nexport const useRoleForm = (open: boolean, role: Role | undefined, onDone: () => void) => {\n const createRole = useCreateRole();\n const updateRole = useUpdateRole();\n const form = useForm<RoleValues>({ resolver: zodResolver(roleSchema), defaultValues: valuesFor(role) });\n const { reset } = form;\n // Each time the dialog opens it starts from the role's current values (or a blank role).\n useEffect(() => {\n if (open) {\n reset(valuesFor(role));\n }\n }, [open, role, reset]);\n const onSubmit = form.handleSubmit(async ({ key, name, description, kind, actions }) => {\n if (role) {\n const narrower = role.permissions.filter((permission) => !isEveryModelGrant(permission));\n const updated = await settle(\n updateRole.mutateAsync({\n id: role.id,\n input: {\n expectedVersion: role.version,\n name,\n description,\n permissions: [...narrower, ...actions.map(toGrant)],\n },\n }),\n );\n if (!updated.ok) {\n return;\n }\n toast.success(i18next.t('roles.saved'));\n } else {\n const created = await settle(\n createRole.mutateAsync({ key, name, description, kind, permissions: actions.map(toGrant) }),\n );\n if (!created.ok) {\n return;\n }\n toast.success(i18next.t('roles.created'));\n }\n onDone();\n });\n const mutation = role ? updateRole : createRole;\n return { form, onSubmit, pending: mutation.isPending, error: mutation.error };\n};\n","import type { Role } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { FormCheckboxGroup } from '@/components/FormCheckboxGroup';\nimport { FormError } from '@/components/FormError';\nimport { FormSelectField } from '@/components/FormSelectField';\nimport { FormSheet } from '@/components/FormSheet';\nimport { FormTextareaField } from '@/components/FormTextareaField';\nimport { FormTextField } from '@/components/FormTextField';\nimport { ACTION_LABEL_KEYS, CONTENT_ACTIONS, GLOBAL_ACTIONS, ROLE_KINDS } from '../constants';\nimport { useRoleForm } from '../hooks/useRoleForm';\n\ntype RoleSheetProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Edit this role; create a new one when undefined. */\n role: Role | undefined;\n};\n\nconst KIND_LABEL_KEYS = { admin: 'roles.kindAdmin', delivery: 'roles.kindDelivery' } as const;\n\nexport const RoleSheet = ({ open, onOpenChange, role }: RoleSheetProps) => {\n const { t } = useTranslation();\n const { form, onSubmit, pending, error } = useRoleForm(open, role, () => onOpenChange(false));\n const isEdit = role !== undefined;\n const kind = form.watch('kind');\n return (\n <FormSheet\n open={open}\n onOpenChange={onOpenChange}\n size=\"md\"\n title={isEdit ? t('roles.editTitle') : t('roles.createTitle')}\n dirty={form.formState.isDirty}\n pending={pending}\n submitLabel={isEdit ? t('common.saveChanges') : t('common.create')}\n pendingLabel={t('common.saving')}\n onSubmit={(event) => void onSubmit(event)}\n >\n <FormTextField control={form.control} name=\"name\" label={t('roles.name')} autoComplete=\"off\" />\n <FormTextField\n control={form.control}\n name=\"key\"\n label={t('roles.key')}\n hint={t('roles.keyHint')}\n autoComplete=\"off\"\n spellCheck={false}\n className=\"font-mono\"\n disabled={isEdit}\n />\n <FormTextareaField\n control={form.control}\n name=\"description\"\n label={t('roles.roleDescription')}\n rows={2}\n />\n <FormSelectField\n control={form.control}\n name=\"kind\"\n label={t('roles.kind')}\n hint={t('roles.kindHint')}\n options={ROLE_KINDS.map((value) => ({ value, label: t(KIND_LABEL_KEYS[value]) }))}\n disabled={isEdit}\n />\n <FormCheckboxGroup\n control={form.control}\n name=\"actions\"\n legend={t('roles.contentPermissions')}\n options={CONTENT_ACTIONS.map((action) => ({ value: action, label: t(ACTION_LABEL_KEYS[action]) }))}\n />\n {kind === 'admin' ? (\n <FormCheckboxGroup\n control={form.control}\n name=\"actions\"\n legend={t('roles.instancePermissions')}\n options={GLOBAL_ACTIONS.map((action) => ({ value: action, label: t(ACTION_LABEL_KEYS[action]) }))}\n />\n ) : null}\n <FormError error={error} />\n </FormSheet>\n );\n};\n","import type { Role } from '@shapio/client';\nimport { MoreHorizontal, Pencil, Trash2 } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { RowTitle } from '@/components/RowTitle';\nimport { TableCard } from '@/components/TableCard';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport {\n Table as TableRoot,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table';\n\ntype TableProps = { roles: Role[]; onEdit: (role: Role) => void; onDelete: (role: Role) => void };\n\nexport const Table = ({ roles, onEdit, onDelete }: TableProps) => {\n const { t } = useTranslation();\n return (\n <TableCard>\n <TableRoot>\n <TableHeader>\n <TableRow>\n <TableHead>{t('roles.name')}</TableHead>\n <TableHead>{t('roles.key')}</TableHead>\n <TableHead>{t('roles.kind')}</TableHead>\n <TableHead>{t('roles.permissions')}</TableHead>\n <TableHead>\n <span className=\"sr-only\">{t('common.actions')}</span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {roles.map((role) => (\n <TableRow key={role.id}>\n <TableCell className=\"max-w-xs\">\n <span className=\"flex items-center gap-2\">\n <RowTitle>{role.name}</RowTitle>\n <Badge variant={role.isSystem ? 'secondary' : 'outline'}>\n {role.isSystem ? t('roles.builtIn') : t('roles.custom')}\n </Badge>\n </span>\n {role.description ? (\n <span className=\"block truncate text-meta whitespace-normal text-muted-foreground\">\n {role.description}\n </span>\n ) : null}\n </TableCell>\n <TableCell className=\"font-mono text-xs\">{role.key}</TableCell>\n <TableCell>{role.kind === 'admin' ? t('roles.kindAdmin') : t('roles.kindDelivery')}</TableCell>\n <TableCell>{t('roles.permissionsCount', { count: role.permissions.length })}</TableCell>\n <TableCell className=\"text-right\">\n {role.isSystem ? null : (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={`${t('common.actions')}: ${role.name}`}\n >\n <MoreHorizontal aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onSelect={() => onEdit(role)}>\n <Pencil aria-hidden=\"true\" />\n {t('common.edit')}\n </DropdownMenuItem>\n <DropdownMenuItem variant=\"destructive\" onSelect={() => onDelete(role)}>\n <Trash2 aria-hidden=\"true\" />\n {t('common.delete')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </TableRoot>\n </TableCard>\n );\n};\n","import { useTranslation } from 'react-i18next';\nimport { LinkTabs } from '@/components/LinkTabs';\n\n/** Admin and token roles, and app roles (for the end users of the sites built on Shapio). */\nexport const Tabs = () => {\n const { t } = useTranslation();\n return (\n <LinkTabs\n label={t('roles.sections')}\n tabs={[\n { to: '/network/roles', label: t('roles.tabAdmin') },\n { to: '/network/roles/app', label: t('roles.tabApp') },\n ]}\n />\n );\n};\n","import type { Role } from '@shapio/client';\nimport { Plus, ShieldCheck } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useDeleteRole, useRoles } from '@/api/roles';\nimport { ConfirmDialog } from '@/components/ConfirmDialog';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { QueryView } from '@/components/QueryView';\nimport { Button } from '@/components/ui/button';\nimport { useConfirmTarget } from '@/hooks/useConfirmTarget';\nimport { RoleSheet } from './RoleSheet';\nimport { Table } from './Table';\nimport { Tabs } from './Tabs';\n\nexport const Roles = () => {\n const { t } = useTranslation();\n const roles = useRoles();\n const deleteRole = useDeleteRole();\n const confirmDelete = useConfirmTarget<Role>();\n const [sheet, setSheet] = useState<{ open: boolean; role: Role | undefined }>({\n open: false,\n role: undefined,\n });\n return (\n <Page width=\"full\">\n <PageHeader\n title={t('roles.title')}\n tabs={<Tabs />}\n actions={\n <Button onClick={() => setSheet({ open: true, role: undefined })}>\n <Plus aria-hidden=\"true\" />\n {t('roles.create')}\n </Button>\n }\n />\n <QueryView\n query={roles}\n isEmpty={(data) => data.length === 0}\n empty={<EmptyState icon={ShieldCheck} title={t('roles.empty')} />}\n >\n {(data) => (\n <Table\n roles={data}\n onEdit={(role) => setSheet({ open: true, role })}\n onDelete={(role) => confirmDelete.ask(role)}\n />\n )}\n </QueryView>\n <RoleSheet\n open={sheet.open}\n onOpenChange={(open) => setSheet((current) => ({ ...current, open }))}\n role={sheet.role}\n />\n <ConfirmDialog\n open={confirmDelete.open}\n onOpenChange={confirmDelete.onOpenChange}\n title={t('roles.deleteTitle', { name: confirmDelete.target?.name ?? '' })}\n description={t('roles.deleteDescription')}\n confirmLabel={t('common.delete')}\n destructive\n onConfirm={() => {\n if (confirmDelete.target) {\n deleteRole.mutate(confirmDelete.target.id, {\n onSuccess: () => toast.success(t('roles.deleted')),\n });\n }\n }}\n />\n </Page>\n );\n};\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { AppRole } from '@shapio/client';\nimport { useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useCreateAppRole } from '@/api/appRoles';\nimport { i18next } from '@/app/i18n';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\nimport { ROLE_KEY_PATTERN } from '../../constants';\n\nconst createAppRoleSchema = z.object({\n key: z.string().trim().regex(ROLE_KEY_PATTERN, 'validation.roleKey'),\n name: requiredText(),\n description: z.string().trim(),\n});\n\nexport type CreateAppRoleValues = z.infer<typeof createAppRoleSchema>;\n\nconst EMPTY: CreateAppRoleValues = { key: '', name: '', description: '' };\n\n/** Creates a custom app role with no permissions; the caller opens its permission editor next. */\nexport const useCreateAppRoleForm = (open: boolean, onCreated: (role: AppRole) => void) => {\n const createAppRole = useCreateAppRole();\n const form = useForm<CreateAppRoleValues>({\n resolver: zodResolver(createAppRoleSchema),\n defaultValues: EMPTY,\n });\n const { reset } = form;\n useEffect(() => {\n if (open) {\n reset(EMPTY);\n }\n }, [open, reset]);\n const onSubmit = form.handleSubmit(async (values) => {\n const created = await settle(createAppRole.mutateAsync({ ...values, permissions: [] }));\n if (!created.ok) {\n return;\n }\n toast.success(i18next.t('appRoles.created'));\n onCreated(created.value);\n });\n return { form, onSubmit, createAppRole };\n};\n","import type { AppRole } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { FormError } from '@/components/FormError';\nimport { FormSheet } from '@/components/FormSheet';\nimport { FormTextareaField } from '@/components/FormTextareaField';\nimport { FormTextField } from '@/components/FormTextField';\nimport { useCreateAppRoleForm } from '../hooks/useCreateAppRoleForm';\n\ntype CreateSheetProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreated: (role: AppRole) => void;\n};\n\nexport const CreateSheet = ({ open, onOpenChange, onCreated }: CreateSheetProps) => {\n const { t } = useTranslation();\n const { form, onSubmit, createAppRole } = useCreateAppRoleForm(open, onCreated);\n return (\n <FormSheet\n open={open}\n onOpenChange={onOpenChange}\n size=\"md\"\n title={t('appRoles.createTitle')}\n dirty={form.formState.isDirty}\n pending={createAppRole.isPending}\n submitLabel={t('common.create')}\n pendingLabel={t('common.saving')}\n onSubmit={(event) => void onSubmit(event)}\n >\n <FormTextField control={form.control} name=\"name\" label={t('roles.name')} autoComplete=\"off\" />\n <FormTextField\n control={form.control}\n name=\"key\"\n label={t('roles.key')}\n hint={t('roles.keyHint')}\n autoComplete=\"off\"\n spellCheck={false}\n className=\"font-mono\"\n />\n <FormTextareaField\n control={form.control}\n name=\"description\"\n label={t('roles.roleDescription')}\n rows={2}\n />\n <FormError error={createAppRole.error} />\n </FormSheet>\n );\n};\n","import type { AppRole } from '@shapio/client';\nimport { toast } from 'sonner';\nimport { useUpdateAppRole } from '@/api/appRoles';\nimport { i18next } from '@/app/i18n';\nimport { describeError } from '@/helpers/describeError';\n\n/** Whether the role already reads every model (published content, public fields). */\nexport const readsAllModels = (role: AppRole) =>\n role.permissions.some(\n (permission) =>\n permission.action === 'read' && permission.modelId === null && permission.condition === null,\n );\n\n/**\n * The one-click preset for the built-in roles: add \"read on all models\" (published content, public fields)\n * to the role's grants, keeping the others. Built-in roles start with nothing (brief §8: deliberate enable).\n */\nexport const useGrantReadAll = () => {\n const updateAppRole = useUpdateAppRole();\n const grantReadAll = (role: AppRole) =>\n updateAppRole.mutate(\n {\n id: role.id,\n input: {\n expectedVersion: role.version,\n permissions: [\n ...role.permissions.filter(\n (permission) => !(permission.action === 'read' && permission.modelId === null),\n ),\n { action: 'read', modelId: null, condition: null, fieldIds: null },\n ],\n },\n },\n {\n onSuccess: () => toast.success(i18next.t('appRoles.readAllGranted', { name: role.name })),\n // The shared mutation is silent (forms show their own errors); this button has no form.\n onError: (error) => toast.error(describeError(error)),\n },\n );\n return { grantReadAll, pendingRoleId: updateAppRole.isPending ? updateAppRole.variables?.id : undefined };\n};\n","import type { AppRole } from '@shapio/client';\nimport { Link } from '@tanstack/react-router';\nimport { MoreHorizontal, SlidersHorizontal, Trash2 } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\n\ntype ActionsProps = {\n role: AppRole;\n /** Resolves once the role is deleted (the confirmation waits for it). */\n onDelete: (role: AppRole) => Promise<unknown>;\n};\n\n/** An app role's row menu; Delete asks inline, anchored to the menu button. */\nexport const Actions = ({ role, onDelete }: ActionsProps) => {\n const { t } = useTranslation();\n const [deleting, setDeleting] = useState(false);\n return (\n <DropdownMenu>\n <InlineConfirm\n tone=\"danger\"\n open={deleting}\n onOpenChange={setDeleting}\n title={t('roles.deleteTitle', { name: role.name })}\n description={t('appRoles.deleteDescription')}\n confirmLabel={t('common.delete')}\n onConfirm={() => onDelete(role)}\n >\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={`${t('common.actions')}: ${role.name}`}>\n <MoreHorizontal aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n </InlineConfirm>\n <DropdownMenuContent align=\"end\" onCloseAutoFocus={(event) => deleting && event.preventDefault()}>\n <DropdownMenuItem asChild>\n <Link to=\"/network/roles/app/$roleId\" params={{ roleId: role.id }}>\n <SlidersHorizontal aria-hidden=\"true\" />\n {t('appRoles.editPermissions')}\n </Link>\n </DropdownMenuItem>\n {role.isSystem ? null : (\n <DropdownMenuItem variant=\"destructive\" onSelect={() => setDeleting(true)}>\n <Trash2 aria-hidden=\"true\" />\n {t('common.delete')}\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n","import type { AppRole } from '@shapio/client';\nimport { Link } from '@tanstack/react-router';\nimport { BookOpen } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { RowTitle } from '@/components/RowTitle';\nimport { TableCard } from '@/components/TableCard';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport {\n Table as TableRoot,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table';\nimport { readsAllModels } from '../hooks/useGrantReadAll';\nimport { Actions } from './Actions';\n\ntype TableProps = {\n roles: AppRole[];\n onDelete: (role: AppRole) => Promise<unknown>;\n /** The one-click preset offered on built-in roles that don't read every model yet. */\n onGrantReadAll: (role: AppRole) => void;\n pendingRoleId: string | undefined;\n};\n\nconst BUILT_IN_HOLDER_KEYS = {\n public: 'appRoles.holdersPublic',\n authenticated: 'appRoles.holdersAuthenticated',\n} as const;\n\nconst builtInHolderKey = (key: string) =>\n Object.hasOwn(BUILT_IN_HOLDER_KEYS, key)\n ? BUILT_IN_HOLDER_KEYS[key as keyof typeof BUILT_IN_HOLDER_KEYS]\n : undefined;\n\nexport const Table = ({ roles, onDelete, onGrantReadAll, pendingRoleId }: TableProps) => {\n const { t } = useTranslation();\n return (\n <TableCard>\n <TableRoot>\n <TableHeader>\n <TableRow>\n <TableHead>{t('roles.name')}</TableHead>\n <TableHead>{t('roles.key')}</TableHead>\n <TableHead>{t('appRoles.heldBy')}</TableHead>\n <TableHead>{t('roles.permissions')}</TableHead>\n <TableHead>\n <span className=\"sr-only\">{t('common.actions')}</span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {roles.map((role) => {\n const holderKey = role.isSystem ? builtInHolderKey(role.key) : undefined;\n return (\n <TableRow key={role.id}>\n <TableCell className=\"max-w-xs\">\n <span className=\"flex items-center gap-2\">\n <RowTitle asChild>\n <Link to=\"/network/roles/app/$roleId\" params={{ roleId: role.id }}>\n {role.name}\n </Link>\n </RowTitle>\n <Badge variant={role.isSystem ? 'secondary' : 'outline'}>\n {role.isSystem ? t('roles.builtIn') : t('roles.custom')}\n </Badge>\n </span>\n {role.description ? (\n <span className=\"block text-meta whitespace-normal text-muted-foreground\">\n {role.description}\n </span>\n ) : null}\n </TableCell>\n <TableCell className=\"font-mono text-xs\">{role.key}</TableCell>\n <TableCell>\n {holderKey ? t(holderKey) : t('appRoles.userCount', { count: role.userCount })}\n </TableCell>\n <TableCell>\n <span className=\"flex flex-wrap items-center gap-2\">\n {t('roles.permissionsCount', { count: role.permissions.length })}\n {role.isSystem && !readsAllModels(role) ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={pendingRoleId === role.id}\n aria-label={`${t('appRoles.grantReadAll')}: ${role.name}`}\n onClick={() => onGrantReadAll(role)}\n >\n <BookOpen aria-hidden=\"true\" />\n {t('appRoles.grantReadAll')}\n </Button>\n ) : null}\n </span>\n </TableCell>\n <TableCell className=\"text-right\">\n <Actions role={role} onDelete={onDelete} />\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </TableRoot>\n </TableCard>\n );\n};\n","import type { AppRole } from '@shapio/client';\nimport { useNavigate } from '@tanstack/react-router';\nimport { Info, Plus, ShieldCheck } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useAppRoles, useDeleteAppRole } from '@/api/appRoles';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { QueryView } from '@/components/QueryView';\nimport { Alert, AlertDescription } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { Tabs } from '../Tabs';\nimport { CreateSheet } from './CreateSheet';\nimport { readsAllModels, useGrantReadAll } from './hooks/useGrantReadAll';\nimport { Table } from './Table';\n\n/** Settings → Roles → App roles: what anonymous callers and signed-in app users may do with content. */\nexport const AppRoles = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const roles = useAppRoles();\n const deleteAppRole = useDeleteAppRole();\n const [creating, setCreating] = useState(false);\n const { grantReadAll, pendingRoleId } = useGrantReadAll();\n const deleteRole = async (role: AppRole) => {\n await deleteAppRole.mutateAsync(role.id);\n toast.success(t('roles.deleted'));\n };\n return (\n <Page width=\"full\">\n <PageHeader\n title={t('appRoles.title')}\n tabs={<Tabs />}\n actions={\n <Button onClick={() => setCreating(true)}>\n <Plus aria-hidden=\"true\" />\n {t('appRoles.create')}\n </Button>\n }\n />\n <QueryView\n query={roles}\n isEmpty={(data) => data.length === 0}\n empty={<EmptyState icon={ShieldCheck} title={t('roles.empty')} />}\n >\n {(data) => (\n <div className=\"space-y-4\">\n {data.some((role) => role.isSystem && !readsAllModels(role)) ? (\n <Alert variant=\"info\" role=\"note\">\n <Info aria-hidden=\"true\" />\n <AlertDescription>{t('appRoles.denyByDefault')}</AlertDescription>\n </Alert>\n ) : null}\n <Table\n roles={data}\n onDelete={deleteRole}\n onGrantReadAll={grantReadAll}\n pendingRoleId={pendingRoleId}\n />\n </div>\n )}\n </QueryView>\n <CreateSheet\n open={creating}\n onOpenChange={setCreating}\n onCreated={(role) => {\n setCreating(false);\n void navigate({ to: '/network/roles/app/$roleId', params: { roleId: role.id } });\n }}\n />\n </Page>\n );\n};\n","import { APP_CONTENT_ACTIONS, type AppContentAction } from '@shapio/client';\n\nexport { APP_CONTENT_ACTIONS };\n\n/** The matrix row that grants on every model, including models created later (`modelId: null`). */\nexport const ALL_MODELS = '*';\n\n/** Actions a row filter means something for: \"only entries the app user owns\". */\nexport const OWN_ONLY_ACTIONS: ReadonlySet<AppContentAction> = new Set([\n 'read',\n 'update',\n 'delete',\n 'publish',\n]);\n\n/** Actions a field list applies to (what the user may see or write). */\nexport const FIELD_SCOPED_ACTIONS: ReadonlySet<AppContentAction> = new Set(['read', 'create', 'update']);\n\n/** Column headings: short verbs. */\nexport const ACTION_COLUMN_KEYS = {\n read: 'appRoles.actions.read',\n create: 'appRoles.actions.create',\n update: 'appRoles.actions.update',\n delete: 'appRoles.actions.delete',\n publish: 'appRoles.actions.publish',\n} as const satisfies Record<AppContentAction, string>;\n","import type { AppContentAction, AppRolePermission } from '@shapio/client';\nimport { ALL_MODELS, APP_CONTENT_ACTIONS, FIELD_SCOPED_ACTIONS, OWN_ONLY_ACTIONS } from '../constants';\n\n/**\n * The permission matrix the editor works on: model (or every model) × action → grant options. It converts\n * losslessly to and from the API's grant list, so grants the editor does not show are never dropped.\n */\nexport type ActionGrant = {\n /** `ownedByPrincipal`: only entries the app user created. */\n ownOnly: boolean;\n /** `null` = every public field; otherwise exactly these field IDs (non-public ones included). */\n fieldIds: string[] | null;\n};\n\nexport type ModelGrants = Partial<Record<AppContentAction, ActionGrant>>;\n\n/** Keyed by model ID, or `ALL_MODELS`. */\nexport type PermissionMatrix = Readonly<Record<string, ModelGrants>>;\n\nexport const toMatrix = (permissions: readonly AppRolePermission[]): PermissionMatrix => {\n const matrix: Record<string, ModelGrants> = {};\n for (const permission of permissions) {\n const key = permission.modelId ?? ALL_MODELS;\n matrix[key] = {\n ...matrix[key],\n [permission.action]: {\n ownOnly: permission.condition === 'ownedByPrincipal',\n fieldIds: permission.fieldIds === null ? null : [...permission.fieldIds].sort(),\n },\n };\n }\n return matrix;\n};\n\n/** Grants in a stable order (every-model row first, then by model ID and action), so dirty checks compare. */\nexport const toPermissions = (matrix: PermissionMatrix): AppRolePermission[] =>\n Object.keys(matrix)\n .sort((a, b) => (a === ALL_MODELS ? -1 : b === ALL_MODELS ? 1 : a.localeCompare(b)))\n .flatMap((key) =>\n APP_CONTENT_ACTIONS.flatMap((action) => {\n const grant = matrix[key]?.[action];\n if (!grant) {\n return [];\n }\n return [\n {\n action,\n modelId: key === ALL_MODELS ? null : key,\n condition: grant.ownOnly && OWN_ONLY_ACTIONS.has(action) ? ('ownedByPrincipal' as const) : null,\n fieldIds: FIELD_SCOPED_ACTIONS.has(action) ? grant.fieldIds : null,\n },\n ];\n }),\n );\n\nconst withGrant = (\n matrix: PermissionMatrix,\n key: string,\n action: AppContentAction,\n grant: ActionGrant | undefined,\n): PermissionMatrix => {\n const row: ModelGrants = { ...matrix[key] };\n if (grant) {\n row[action] = grant;\n } else {\n delete row[action];\n }\n return { ...matrix, [key]: row };\n};\n\nexport const setGranted = (\n matrix: PermissionMatrix,\n key: string,\n action: AppContentAction,\n granted: boolean,\n): PermissionMatrix =>\n withGrant(\n matrix,\n key,\n action,\n granted ? (matrix[key]?.[action] ?? { ownOnly: false, fieldIds: null }) : undefined,\n );\n\nexport const updateGrant = (\n matrix: PermissionMatrix,\n key: string,\n action: AppContentAction,\n changes: Partial<ActionGrant>,\n): PermissionMatrix => {\n const current = matrix[key]?.[action];\n return current ? withGrant(matrix, key, action, { ...current, ...changes }) : matrix;\n};\n\n/** Whether a row has any granted action with options to set (own entries, or fields on a model row). */\nexport const hasOptions = (key: string, grants: ModelGrants | undefined): boolean =>\n APP_CONTENT_ACTIONS.some(\n (action) =>\n grants?.[action] !== undefined &&\n (OWN_ONLY_ACTIONS.has(action) || (key !== ALL_MODELS && FIELD_SCOPED_ACTIONS.has(action))),\n );\n\n/** Grants or revokes one action on every given row (a column's header checkbox). Granted rows keep options. */\nexport const setColumn = (\n matrix: PermissionMatrix,\n keys: readonly string[],\n action: AppContentAction,\n granted: boolean,\n): PermissionMatrix => keys.reduce((next, key) => setGranted(next, key, action, granted), matrix);\n\n/** A column header checkbox: every row holds the action (true), some do ('indeterminate'), or none (false). */\nexport const columnState = (\n matrix: PermissionMatrix,\n keys: readonly string[],\n action: AppContentAction,\n): boolean | 'indeterminate' => {\n const granted = keys.filter((key) => matrix[key]?.[action] !== undefined).length;\n if (granted === 0) {\n return false;\n }\n return granted === keys.length ? true : 'indeterminate';\n};\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { AppRole } from '@shapio/client';\nimport { useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useUpdateAppRole } from '@/api/appRoles';\nimport { i18next } from '@/app/i18n';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\nimport { toMatrix, toPermissions, type PermissionMatrix } from '../../helpers/permissionMatrix';\n\nconst detailsSchema = z.object({ name: requiredText(), description: z.string().trim() });\n\nexport type AppRoleDetails = z.infer<typeof detailsSchema>;\n\n/**\n * Editing one app role: its details (custom roles only) in a form, its permission matrix in state. Saving\n * sends only what changed, with the version the page loaded (a concurrent edit is a VERSION_CONFLICT).\n */\nexport const useAppRoleEditor = (role: AppRole) => {\n const updateAppRole = useUpdateAppRole();\n const form = useForm<AppRoleDetails>({\n resolver: zodResolver(detailsSchema),\n defaultValues: { name: role.name, description: role.description },\n });\n const [matrix, setMatrix] = useState<PermissionMatrix>(() => toMatrix(role.permissions));\n const initial = useMemo(\n () => JSON.stringify(toPermissions(toMatrix(role.permissions))),\n [role.permissions],\n );\n const permissions = useMemo(() => toPermissions(matrix), [matrix]);\n const permissionsDirty = JSON.stringify(permissions) !== initial;\n const detailsDirty = !role.isSystem && form.formState.isDirty;\n\n const onSubmit = form.handleSubmit(async (details) => {\n const saved = await settle(\n updateAppRole.mutateAsync({\n id: role.id,\n input: {\n expectedVersion: role.version,\n ...(detailsDirty ? details : {}),\n ...(permissionsDirty ? { permissions } : {}),\n },\n }),\n );\n if (saved.ok) {\n toast.success(i18next.t('roles.saved'));\n }\n });\n\n return {\n form,\n matrix,\n setMatrix,\n dirty: permissionsDirty || detailsDirty,\n onSubmit,\n pending: updateAppRole.isPending,\n error: updateAppRole.error,\n };\n};\n","import type { AppContentAction } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '@/components/ui/badge';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Field, FieldLabel, FieldLegend, FieldSet } from '@/components/ui/field';\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';\nimport { Switch } from '@/components/ui/switch';\nimport {\n ACTION_COLUMN_KEYS,\n ALL_MODELS,\n APP_CONTENT_ACTIONS,\n FIELD_SCOPED_ACTIONS,\n OWN_ONLY_ACTIONS,\n} from '../../../constants';\nimport type { ActionGrant, ModelGrants } from '../../../helpers/permissionMatrix';\n\ntype OptionsProps = {\n id: string;\n rowKey: string;\n /** The model's fields; undefined for the every-model row (no field lists there). */\n fields: readonly FieldDefinition[] | undefined;\n grants: ModelGrants;\n onChange: (action: AppContentAction, changes: Partial<ActionGrant>) => void;\n};\n\nconst SCOPE_ALL = 'all';\nconst SCOPE_SELECTED = 'selected';\n\n/** Per granted action: \"only their own entries\" and, on a model, which fields it covers. */\nexport const Options = ({ id, rowKey, fields, grants, onChange }: OptionsProps) => {\n const { t } = useTranslation();\n const liveFields = (fields ?? []).filter((field) => !field.deprecated);\n return (\n <div id={id} className=\"grid gap-6 border-t bg-muted/40 px-5 py-4 md:grid-cols-2\">\n {APP_CONTENT_ACTIONS.map((action) => {\n const grant = grants[action];\n const ownOnly = OWN_ONLY_ACTIONS.has(action);\n const fieldScoped = rowKey !== ALL_MODELS && FIELD_SCOPED_ACTIONS.has(action);\n if (!grant || (!ownOnly && !fieldScoped)) {\n return null;\n }\n const base = `${id}-${action}`;\n return (\n <FieldSet key={action} className=\"gap-3\">\n <FieldLegend variant=\"label\">{t(ACTION_COLUMN_KEYS[action])}</FieldLegend>\n {ownOnly ? (\n <Field orientation=\"horizontal\">\n <FieldLabel htmlFor={`${base}-own`}>{t('appRoles.ownOnly')}</FieldLabel>\n <Switch\n id={`${base}-own`}\n checked={grant.ownOnly}\n onCheckedChange={(checked) => onChange(action, { ownOnly: checked })}\n />\n </Field>\n ) : null}\n {fieldScoped ? (\n <>\n <RadioGroup\n aria-label={t('appRoles.fieldScope')}\n value={grant.fieldIds === null ? SCOPE_ALL : SCOPE_SELECTED}\n onValueChange={(value) =>\n onChange(action, {\n fieldIds:\n value === SCOPE_ALL\n ? null\n : liveFields.filter((field) => field.public).map((field) => field.id),\n })\n }\n >\n <Field orientation=\"horizontal\">\n <RadioGroupItem id={`${base}-all`} value={SCOPE_ALL} />\n <FieldLabel htmlFor={`${base}-all`} className=\"font-normal\">\n {t('appRoles.allPublicFields')}\n </FieldLabel>\n </Field>\n <Field orientation=\"horizontal\">\n <RadioGroupItem id={`${base}-selected`} value={SCOPE_SELECTED} />\n <FieldLabel htmlFor={`${base}-selected`} className=\"font-normal\">\n {t('appRoles.selectedFields')}\n </FieldLabel>\n </Field>\n </RadioGroup>\n {grant.fieldIds === null ? null : (\n <div className=\"grid gap-2 pl-6 sm:grid-cols-2\">\n {liveFields.map((field) => {\n const selected = grant.fieldIds ?? [];\n const checkboxId = `${base}-field-${field.id}`;\n return (\n <Field key={field.id} orientation=\"horizontal\">\n <Checkbox\n id={checkboxId}\n checked={selected.includes(field.id)}\n onCheckedChange={(checked) =>\n onChange(action, {\n fieldIds:\n checked === true\n ? [...selected, field.id].sort()\n : selected.filter((fieldId) => fieldId !== field.id),\n })\n }\n />\n <FieldLabel htmlFor={checkboxId} className=\"font-normal\">\n {field.label}\n {field.public ? null : (\n <Badge variant=\"secondary\">{t('appRoles.notPublic')}</Badge>\n )}\n </FieldLabel>\n </Field>\n );\n })}\n </div>\n )}\n </>\n ) : null}\n </FieldSet>\n );\n })}\n </div>\n );\n};\n","import type { AppContentAction } from '@shapio/client';\nimport { ChevronDown } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { TableCell, TableRow } from '@/components/ui/table';\nimport { cn } from '@/helpers/cn';\nimport { ACTION_COLUMN_KEYS, APP_CONTENT_ACTIONS } from '../../../constants';\nimport type { ModelGrants } from '../../../helpers/permissionMatrix';\n\ntype RowProps = {\n label: string;\n /** API key or a hint beside the label. */\n detail: string;\n grants: ModelGrants;\n optionsId: string;\n expanded: boolean;\n /** False when no granted action on this row has options. */\n canExpand: boolean;\n onToggle: (action: AppContentAction, granted: boolean) => void;\n onToggleExpanded: () => void;\n};\n\n/** One model (or every model): a 36px row with a checkbox per action and the button that shows its options. */\nexport const Row = ({\n label,\n detail,\n grants,\n optionsId,\n expanded,\n canExpand,\n onToggle,\n onToggleExpanded,\n}: RowProps) => {\n const { t } = useTranslation();\n return (\n <TableRow className=\"hover:bg-transparent has-aria-expanded:bg-transparent\">\n <TableCell className=\"sticky left-0 z-10 h-9 bg-card py-0\">\n <span className=\"flex items-baseline gap-2\">\n <span className=\"font-semibold\">{label}</span>\n <span className=\"truncate text-xs text-muted-foreground\">{detail}</span>\n </span>\n </TableCell>\n {APP_CONTENT_ACTIONS.map((action) => (\n <TableCell key={action} className=\"h-9 py-0 text-center\">\n <Checkbox\n checked={grants[action] !== undefined}\n onCheckedChange={(checked) => onToggle(action, checked === true)}\n aria-label={`${t(ACTION_COLUMN_KEYS[action])}: ${label}`}\n className=\"align-middle\"\n />\n </TableCell>\n ))}\n <TableCell className=\"h-9 py-0 text-right\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n disabled={!canExpand}\n aria-expanded={expanded}\n aria-controls={expanded ? optionsId : undefined}\n aria-label={`${t('appRoles.options')}: ${label}`}\n onClick={onToggleExpanded}\n >\n {t('appRoles.options')}\n <ChevronDown aria-hidden=\"true\" className={cn('transition-transform', expanded && 'rotate-180')} />\n </Button>\n </TableCell>\n </TableRow>\n );\n};\n","import type { DefinitionListItem } from '@shapio/client';\nimport { isModelDefinition } from '@shapio/schema';\nimport { Fragment, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';\nimport { ACTION_COLUMN_KEYS, ALL_MODELS, APP_CONTENT_ACTIONS } from '../../constants';\nimport {\n columnState,\n hasOptions,\n setColumn,\n setGranted,\n updateGrant,\n type PermissionMatrix,\n} from '../../helpers/permissionMatrix';\nimport { Options } from './Options';\nimport { Row } from './Row';\n\ntype MatrixProps = {\n matrix: PermissionMatrix;\n models: readonly DefinitionListItem[];\n onChange: (matrix: PermissionMatrix) => void;\n};\n\n/**\n * Models × actions. The first row grants on every model, including ones created later; each column's header\n * checkbox grants or revokes that action on every row. The model column stays put while the table scrolls.\n */\nexport const Matrix = ({ matrix, models, onChange }: MatrixProps) => {\n const { t } = useTranslation();\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(new Set());\n const toggleExpanded = (key: string) =>\n setExpanded((current) => {\n const next = new Set(current);\n if (!next.delete(key)) {\n next.add(key);\n }\n return next;\n });\n const rows = [\n {\n key: ALL_MODELS,\n label: t('appRoles.allModels'),\n detail: t('appRoles.allModelsHint'),\n fields: undefined,\n },\n ...models\n .map((item) => item.definition)\n .filter(isModelDefinition)\n .map((definition) => ({\n key: definition.id,\n label: definition.label,\n detail: definition.apiKey,\n fields: definition.fields,\n })),\n ];\n const keys = rows.map((row) => row.key);\n return (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"sticky left-0 z-10 min-w-60 bg-muted\">{t('appRoles.model')}</TableHead>\n {APP_CONTENT_ACTIONS.map((action) => {\n const label = t(ACTION_COLUMN_KEYS[action]);\n return (\n <TableHead key={action} className=\"w-24 bg-muted\">\n <span className=\"flex items-center justify-center gap-2\">\n <Checkbox\n checked={columnState(matrix, keys, action)}\n onCheckedChange={(checked) => onChange(setColumn(matrix, keys, action, checked === true))}\n aria-label={t('appRoles.everyRow', { action: label })}\n />\n {label}\n </span>\n </TableHead>\n );\n })}\n <TableHead className=\"bg-muted\">\n <span className=\"sr-only\">{t('appRoles.options')}</span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((row) => {\n const grants = matrix[row.key] ?? {};\n const canExpand = hasOptions(row.key, grants);\n const isExpanded = canExpand && expanded.has(row.key);\n const optionsId = `app-role-options-${row.key === ALL_MODELS ? 'all' : row.key}`;\n return (\n <Fragment key={row.key}>\n <Row\n label={row.label}\n detail={row.detail}\n grants={grants}\n optionsId={optionsId}\n expanded={isExpanded}\n canExpand={canExpand}\n onToggle={(action, granted) => onChange(setGranted(matrix, row.key, action, granted))}\n onToggleExpanded={() => toggleExpanded(row.key)}\n />\n {isExpanded ? (\n <TableRow className=\"hover:bg-transparent\">\n <TableCell\n colSpan={APP_CONTENT_ACTIONS.length + 2}\n className=\"h-auto p-0 whitespace-normal\"\n >\n <Options\n id={optionsId}\n rowKey={row.key}\n fields={row.fields}\n grants={grants}\n onChange={(action, changes) => onChange(updateGrant(matrix, row.key, action, changes))}\n />\n </TableCell>\n </TableRow>\n ) : null}\n </Fragment>\n );\n })}\n </TableBody>\n </Table>\n );\n};\n","import type { AppRole, DefinitionListItem } from '@shapio/client';\nimport { linkOptions, useParams } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { useAppRole } from '@/api/appRoles';\nimport { useDefinitions } from '@/api/schema';\nimport { FormError } from '@/components/FormError';\nimport { FormTextareaField } from '@/components/FormTextareaField';\nimport { FormTextField } from '@/components/FormTextField';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { Panel } from '@/components/Panel';\nimport { QueryView } from '@/components/QueryView';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { Badge } from '@/components/ui/badge';\nimport { FieldGroup } from '@/components/ui/field';\nimport { UnsavedChangesGuard } from '@/components/UnsavedChangesGuard';\nimport { useAppRoleEditor } from './hooks/useAppRoleEditor';\nimport { Matrix } from './Matrix';\n\ntype FormProps = { role: AppRole; models: readonly DefinitionListItem[] };\n\nconst BUILT_IN_DESCRIPTION_KEYS = {\n public: 'appRoles.publicExplained',\n authenticated: 'appRoles.authenticatedExplained',\n} as const;\n\nconst builtInDescriptionKey = (key: string) =>\n Object.hasOwn(BUILT_IN_DESCRIPTION_KEYS, key)\n ? BUILT_IN_DESCRIPTION_KEYS[key as keyof typeof BUILT_IN_DESCRIPTION_KEYS]\n : undefined;\n\nconst Form = ({ role, models }: FormProps) => {\n const { t } = useTranslation();\n const editor = useAppRoleEditor(role);\n const explanation = role.isSystem ? builtInDescriptionKey(role.key) : undefined;\n const breadcrumb = [\n { label: t('roles.title'), link: linkOptions({ to: '/network/roles' }) },\n { label: t('appRoles.title'), link: linkOptions({ to: '/network/roles/app' }) },\n ];\n return (\n <form noValidate className=\"space-y-6\" onSubmit={(event) => void editor.onSubmit(event)}>\n <PageHeader\n sticky\n breadcrumb={breadcrumb}\n title={role.name}\n badge={role.isSystem ? <Badge variant=\"secondary\">{t('roles.builtIn')}</Badge> : null}\n meta={explanation ? t(explanation) : role.description || undefined}\n actions={\n <SubmitButton pending={editor.pending} pendingLabel={t('common.saving')} disabled={!editor.dirty}>\n {t('common.saveChanges')}\n </SubmitButton>\n }\n />\n {role.isSystem ? null : (\n <Panel title={t('appRoles.details')}>\n <FieldGroup className=\"max-w-xl\">\n <FormTextField\n control={editor.form.control}\n name=\"name\"\n label={t('roles.name')}\n autoComplete=\"off\"\n />\n <FormTextareaField\n control={editor.form.control}\n name=\"description\"\n label={t('roles.roleDescription')}\n rows={2}\n />\n </FieldGroup>\n </Panel>\n )}\n <Panel title={t('roles.permissions')} description={t('appRoles.permissionsHint')} flush>\n <Matrix matrix={editor.matrix} models={models} onChange={editor.setMatrix} />\n </Panel>\n <FormError error={editor.error} />\n <UnsavedChangesGuard when={editor.dirty && !editor.pending} />\n </form>\n );\n};\n\n/** Settings → Roles → App roles → one role: its permission matrix (models × actions, own entries, fields). */\nexport const Editor = () => {\n const { roleId } = useParams({ from: '/app/network/roles/app/$roleId' });\n const role = useAppRole(roleId);\n const models = useDefinitions('model');\n return (\n <Page width=\"full\">\n <QueryView query={role} loadingRows={6}>\n {(loaded) => (\n <QueryView query={models} loadingRows={6}>\n {(definitions) => (\n <Form key={`${loaded.id}:${loaded.version}`} role={loaded} models={definitions} />\n )}\n </QueryView>\n )}\n </QueryView>\n </Page>\n );\n};\n","import type { EmailDelivery, Invitation, InvitationLink } from '@shapio/client';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useMe } from '@/api/auth';\nimport { useIssueInvitationLink } from '@/api/users';\nimport { settle } from '@/helpers/settle';\n\nexport type RevealedInvitationLink = InvitationLink & { email: string };\n\n/**\n * Copyable invitation links, shown once in a `SecretReveal` (never in a URL). Without real email delivery\n * the link is issued right after inviting, since it is the only way the invitee can join; with email, the\n * \"Invitation sent\" toast offers it instead. Issuing a link makes earlier ones stop working.\n */\nexport const useInvitationLinkReveal = () => {\n const { t } = useTranslation();\n const emailDelivery: EmailDelivery | undefined = useMe().data?.emailDelivery;\n const issueLink = useIssueInvitationLink();\n const [revealed, setRevealed] = useState<RevealedInvitationLink | undefined>(undefined);\n const reveal = async ({ id, email }: Pick<Invitation, 'id' | 'email'>) => {\n const link = await issueLink.mutateAsync(id);\n setRevealed({ ...link, email });\n };\n const announceInvitation = async (invitation: Invitation) => {\n if (emailDelivery === 'console') {\n await reveal(invitation);\n return;\n }\n toast.success(t('users.invited', { email: invitation.email }), {\n action: { label: t('users.copyLink'), onClick: () => void settle(reveal(invitation)) },\n });\n };\n return {\n revealed,\n emailDelivery,\n reveal,\n announceInvitation,\n dismiss: () => setRevealed(undefined),\n /** For the invite sheet's `onCloseAutoFocus`: focus stays on the reveal's copy button. */\n keepFocusOnReveal: (event: Event) => {\n if (revealed) {\n event.preventDefault();\n }\n },\n };\n};\n","import type { EmailDelivery } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { SecretReveal } from '@/components/SecretReveal';\nimport { formatDateTime } from '@/helpers/formatDate';\nimport type { RevealedInvitationLink } from '../hooks/useInvitationLinkReveal';\n\ntype InvitationLinkProps = {\n link: RevealedInvitationLink;\n emailDelivery: EmailDelivery | undefined;\n onDismiss: () => void;\n};\n\n/** A copyable invitation link, shown once above the pending invitations. */\nexport const InvitationLink = ({ link, emailDelivery, onDismiss }: InvitationLinkProps) => {\n const { t } = useTranslation();\n const expires = formatDateTime(link.expiresAt);\n return (\n <SecretReveal\n title={t('users.invitationLink.title', { email: link.email })}\n description={\n emailDelivery === 'console'\n ? t('users.invitationLink.noEmailDescription', { date: expires })\n : t('users.invitationLink.description', { date: expires })\n }\n label={t('users.invitationLink.label')}\n secret={link.acceptUrl}\n dismissLabel={t('users.invitationLink.done')}\n onDismiss={onDismiss}\n />\n );\n};\n","import type { RoleAssignment } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '@/components/ui/badge';\n\ntype AssignmentBadgesProps = {\n assignments: readonly RoleAssignment[];\n roleNames: ReadonlyMap<string, string>;\n /** Site names by ID; with one site or none, only the role is shown (there is no other site). */\n siteNames: ReadonlyMap<string, string>;\n};\n\n/** A user's or invitation's role assignments: \"Editor · All sites\", \"Viewer · Blog\". */\nexport const AssignmentBadges = ({ assignments, roleNames, siteNames }: AssignmentBadgesProps) => {\n const { t } = useTranslation();\n const showSites = siteNames.size > 1;\n return assignments.map(({ roleId, siteId }) => {\n const role = roleNames.get(roleId) ?? t('common.unknown');\n const site =\n siteId === null ? t('sites.switcher.allSites') : (siteNames.get(siteId) ?? t('common.unknown'));\n return (\n <Badge key={`${roleId}:${siteId ?? ''}`} variant=\"outline\">\n {showSites ? t('users.access.badge', { role, site }) : role}\n </Badge>\n );\n });\n};\n","import type { Invitation } from '@shapio/client';\nimport { Link } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useRoleNames } from '@/api/roles';\nimport { useInvitations, useRevokeInvitation } from '@/api/users';\nimport { ErrorState } from '@/components/ErrorState';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { Panel } from '@/components/Panel';\nimport { RowTitle } from '@/components/RowTitle';\nimport { Button } from '@/components/ui/button';\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';\nimport { formatDateTime, formatRelativeTime } from '@/helpers/formatDate';\nimport { AssignmentBadges } from '../AssignmentBadges';\n\ntype InvitationsProps = {\n siteNames: ReadonlyMap<string, string>;\n /** Issues a fresh link for the invitation and shows it; resolves once it is shown. */\n onCopyLink: (invitation: Invitation) => Promise<unknown>;\n /** Keeps focus on a link that just appeared instead of returning it to the row's button. */\n onCloseAutoFocus: (event: Event) => void;\n};\n\n/**\n * Invitations not yet accepted; the panel only appears while there are some. Each row can issue a new link\n * to send by hand (the earlier one stops working) or revoke the invitation.\n */\nexport const Invitations = ({ siteNames, onCopyLink, onCloseAutoFocus }: InvitationsProps) => {\n const { t } = useTranslation();\n const invitations = useInvitations();\n const { names: roleNames } = useRoleNames();\n const revoke = useRevokeInvitation();\n if (invitations.isError) {\n return <ErrorState error={invitations.error} onRetry={() => void invitations.refetch()} />;\n }\n if (!invitations.data || invitations.data.length === 0) {\n return null;\n }\n return (\n <Panel title={t('users.invitationsTitle')} flush>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('users.email')}</TableHead>\n <TableHead>{t('users.roles')}</TableHead>\n <TableHead>{t('users.invitationExpires')}</TableHead>\n <TableHead>\n <span className=\"sr-only\">{t('common.actions')}</span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {invitations.data.map((invitation) => (\n <TableRow key={invitation.id}>\n <TableCell>\n <RowTitle>{invitation.email}</RowTitle>\n </TableCell>\n <TableCell>\n <span className=\"flex flex-wrap gap-1\">\n <AssignmentBadges\n assignments={invitation.assignments}\n roleNames={roleNames}\n siteNames={siteNames}\n />\n </span>\n </TableCell>\n <TableCell title={formatDateTime(invitation.expiresAt)}>\n {formatRelativeTime(invitation.expiresAt)}\n </TableCell>\n <TableCell>\n <div className=\"flex justify-end gap-2\">\n <InlineConfirm\n tone=\"default\"\n title={t('users.invitationLink.confirmTitle', { email: invitation.email })}\n description={t('users.invitationLink.confirmDescription')}\n confirmLabel={t('users.invitationLink.create')}\n onConfirm={() => onCopyLink(invitation)}\n onCloseAutoFocus={onCloseAutoFocus}\n trigger={\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`${t('users.copyLink')}: ${invitation.email}`}\n >\n <Link aria-hidden=\"true\" />\n {t('users.copyLink')}\n </Button>\n }\n />\n <InlineConfirm\n tone=\"danger\"\n title={t('users.revokeInvitationTitle', { email: invitation.email })}\n description={t('users.revokeInvitationDescription')}\n confirmLabel={t('common.revoke')}\n onConfirm={async () => {\n await revoke.mutateAsync(invitation.id);\n toast.success(t('users.invitationRevoked'));\n }}\n trigger={\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`${t('common.revoke')}: ${invitation.email}`}\n >\n {t('common.revoke')}\n </Button>\n }\n />\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Panel>\n );\n};\n","import type { RoleAssignment } from '@shapio/client';\nimport { z } from 'zod';\n\n/**\n * Role assignments as the admin edits them (sites plan §H): one row per site, each a role on that site or on\n * every site. The server allows several roles per site; the admin keeps one, like the one-role rule.\n */\n\n/** The select value for \"All sites\" (`siteId: null`). */\nexport const ALL_SITES = 'all';\n\nexport type AssignmentRow = { site: string; roleId: string };\n\nexport type AssignmentsValues = { rows: AssignmentRow[] };\n\nconst siteValue = (siteId: string | null) => siteId ?? ALL_SITES;\n\n/**\n * The rows for a user's assignments: one per site, in the order the server gave them. Where a site holds\n * several roles, the owner role wins (it can only be held on every site), else the first.\n */\nexport const toAssignmentRows = (\n assignments: readonly RoleAssignment[],\n ownerRoleId: string | undefined,\n): AssignmentRow[] => {\n const bySite = new Map<string, string>();\n for (const { roleId, siteId } of assignments) {\n const site = siteValue(siteId);\n if (!bySite.has(site) || roleId === ownerRoleId) {\n bySite.set(site, roleId);\n }\n }\n return [...bySite].map(([site, roleId]) => ({ site, roleId }));\n};\n\nexport const toAssignments = (rows: readonly AssignmentRow[]): RoleAssignment[] =>\n rows.map(({ site, roleId }) => ({ roleId, siteId: site === ALL_SITES ? null : site }));\n\n/**\n * At least one row, a role on each, a site at most once, and the owner role only on every site (the server\n * refuses it otherwise, 400 `OWNER_ALL_SITES`).\n */\nexport const assignmentRowsSchema = (ownerRoleId: string | undefined) =>\n z\n .array(z.object({ site: z.string().min(1), roleId: z.string().min(1, 'validation.selectRole') }))\n .min(1)\n .superRefine((rows, context) => {\n const seen = new Set<string>();\n rows.forEach((row, index) => {\n if (seen.has(row.site)) {\n context.addIssue({ code: 'custom', path: [index, 'site'], message: 'validation.siteTwice' });\n }\n seen.add(row.site);\n if (ownerRoleId !== undefined && row.roleId === ownerRoleId && row.site !== ALL_SITES) {\n context.addIssue({ code: 'custom', path: [index, 'roleId'], message: 'validation.ownerAllSites' });\n }\n });\n });\n\n/** The next row \"Add a site\" adds: the first site no row names yet, with the given role. */\nexport const nextAssignmentRow = (\n rows: readonly AssignmentRow[],\n siteIds: readonly string[],\n roleId: string,\n): AssignmentRow | undefined => {\n const used = new Set(rows.map((row) => row.site));\n const site = [ALL_SITES, ...siteIds].find((candidate) => !used.has(candidate));\n return site === undefined ? undefined : { site, roleId };\n};\n","import { Plus, X } from 'lucide-react';\nimport {\n useFieldArray,\n useFormState,\n useWatch,\n type ArrayPath,\n type Control,\n type FieldArray,\n type FieldPath,\n} from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport { FormFieldError } from '@/components/FormFieldError';\nimport type { RadioOption } from '@/components/FormRadioGroup';\nimport { FormRadioGroup } from '@/components/FormRadioGroup';\nimport { FormSelectField, type SelectOption } from '@/components/FormSelectField';\nimport { Button } from '@/components/ui/button';\nimport { FieldLegend, FieldSet } from '@/components/ui/field';\nimport { nextAssignmentRow, type AssignmentsValues } from '../helpers/assignments';\n\ntype AssignmentsFieldProps<TValues extends AssignmentsValues> = {\n control: Control<TValues>;\n roleOptions: readonly RadioOption[];\n siteOptions: readonly SelectOption[];\n siteIds: readonly string[];\n /** One site on the instance: just the role (on every site), as before there were sites. */\n multiSite: boolean;\n /** The role a new row starts with. */\n defaultRoleId: string | undefined;\n};\n\n/**\n * Where an admin works (sites plan §H): one row per site, each a role on that site or on all sites. With a\n * single site there is nothing to choose but the role, so it is the role alone.\n */\nexport const AssignmentsField = <TValues extends AssignmentsValues>({\n control,\n roleOptions,\n siteOptions,\n siteIds,\n multiSite,\n defaultRoleId,\n}: AssignmentsFieldProps<TValues>) => {\n const { t } = useTranslation();\n const { fields, append, remove } = useFieldArray({ control, name: 'rows' as ArrayPath<TValues> });\n const { errors } = useFormState({ control, name: 'rows' as FieldPath<TValues> });\n const rows = useWatch({ control, name: 'rows' as FieldPath<TValues> }) as\n AssignmentsValues['rows'] | undefined;\n const path = (index: number, key: 'site' | 'roleId') => `rows.${index}.${key}` as FieldPath<TValues>;\n if (!multiSite) {\n return (\n <FormRadioGroup\n control={control}\n name={path(0, 'roleId')}\n legend={t('users.role')}\n options={roleOptions}\n />\n );\n }\n const next = nextAssignmentRow(rows ?? [], siteIds, defaultRoleId ?? '');\n const rootError = (errors as { rows?: { root?: { message?: string }; message?: string } }).rows;\n return (\n <FieldSet>\n <FieldLegend variant=\"label\">{t('users.access.title')}</FieldLegend>\n <div className=\"space-y-3\">\n {fields.map((field, index) => (\n <fieldset\n key={field.id}\n aria-label={t('users.access.row', { n: index + 1 })}\n className=\"grid grid-cols-[1fr_1fr_auto] items-start gap-3\"\n >\n <FormSelectField\n control={control}\n name={path(index, 'site')}\n label={t('users.access.site')}\n options={siteOptions}\n />\n <FormSelectField\n control={control}\n name={path(index, 'roleId')}\n label={t('users.role')}\n options={roleOptions}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"mt-7\"\n disabled={fields.length === 1}\n aria-label={t('users.access.remove', { n: index + 1 })}\n onClick={() => remove(index)}\n >\n <X aria-hidden=\"true\" />\n </Button>\n </fieldset>\n ))}\n </div>\n <FormFieldError message={rootError?.root?.message ?? rootError?.message} />\n <div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!next}\n onClick={() => next && append(next as FieldArray<TValues, ArrayPath<TValues>>)}\n >\n <Plus aria-hidden=\"true\" />\n {t('users.access.add')}\n </Button>\n </div>\n </FieldSet>\n );\n};\n","/** Keys of the built-in admin roles the admin UI treats specially (apps/api permissions/seedRoles.ts). */\nexport const SYSTEM_ADMIN_ROLE_KEYS = {\n owner: 'owner',\n editor: 'editor',\n} as const;\n","import { useRoles } from '@/api/roles';\nimport type { RadioOption } from '@/components/FormRadioGroup';\nimport { SYSTEM_ADMIN_ROLE_KEYS } from '@/constants/roles';\n\ntype AdminRoleOptionsInput = {\n /** Offer the owner role (owners only; the server refuses anyone else). */\n includeOwner: boolean;\n /** The roles the user being edited holds: owner is offered when they hold it. */\n heldRoleIds?: readonly string[];\n};\n\n/**\n * Roles an admin user can hold (delivery roles are for tokens only), as single-choice options: an admin user\n * has one role per site. Also returns the default choice for a new user (Editor) and the owner role's ID\n * (which can only be held on every site).\n */\nexport const useAdminRoleOptionsAndDefaults = ({ includeOwner, heldRoleIds = [] }: AdminRoleOptionsInput) => {\n const roles = useRoles();\n const adminRoles = (roles.data ?? []).filter((role) => role.kind === 'admin');\n const isOwnerRole = (key: string) => key === SYSTEM_ADMIN_ROLE_KEYS.owner;\n const offered = adminRoles.filter(\n (role) => !isOwnerRole(role.key) || includeOwner || heldRoleIds.includes(role.id),\n );\n const options: RadioOption[] = offered.map((role) => ({\n value: role.id,\n label: role.name,\n ...(role.description ? { description: role.description } : {}),\n }));\n return {\n options,\n editorRoleId: adminRoles.find((role) => role.key === SYSTEM_ADMIN_ROLE_KEYS.editor)?.id,\n ownerRoleId: adminRoles.find((role) => isOwnerRole(role.key))?.id,\n isPending: roles.isPending,\n error: roles.error,\n };\n};\n","import { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useSites } from '@/api/sites';\nimport type { SelectOption } from '@/components/FormSelectField';\nimport { ALL_SITES } from '../helpers/assignments';\nimport { useAdminRoleOptionsAndDefaults } from './useAdminRoleOptionsAndDefaults';\n\ntype AssignmentOptionsInput = {\n /** Offer the owner role (owners only; the server refuses anyone else). */\n includeOwner: boolean;\n heldRoleIds?: readonly string[];\n};\n\n/**\n * What an assignment row can name: the admin roles, and the sites (\"All sites\" first). `multiSite` is false\n * on an instance with one site, where the site isn't a choice and the form is just the role.\n */\nexport const useAssignmentOptions = ({ includeOwner, heldRoleIds }: AssignmentOptionsInput) => {\n const { t } = useTranslation();\n const roles = useAdminRoleOptionsAndDefaults({ includeOwner, ...(heldRoleIds ? { heldRoleIds } : {}) });\n const sites = useSites();\n const siteOptions = useMemo<SelectOption[]>(\n () => [\n { value: ALL_SITES, label: t('sites.switcher.allSites') },\n ...(sites.data ?? []).map((site) => ({ value: site.id, label: site.name })),\n ],\n [sites.data, t],\n );\n const siteIds = useMemo(() => (sites.data ?? []).map((site) => site.id), [sites.data]);\n return {\n roleOptions: roles.options,\n siteOptions,\n siteIds,\n multiSite: siteIds.length > 1,\n editorRoleId: roles.editorRoleId,\n ownerRoleId: roles.ownerRoleId,\n error: roles.error ?? sites.error,\n };\n};\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { Invitation } from '@shapio/client';\nimport { useEffect, useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport { useInviteUser } from '@/api/users';\nimport { settle } from '@/helpers/settle';\nimport { emailField } from '@/helpers/validation';\nimport { ALL_SITES, assignmentRowsSchema, toAssignments, type AssignmentRow } from '../helpers/assignments';\n\nexport type InviteValues = { email: string; rows: AssignmentRow[] };\n\nconst emptyValues = (roleId: string): InviteValues => ({ email: '', rows: [{ site: ALL_SITES, roleId }] });\n\ntype InviteFormOptions = {\n open: boolean;\n /** Preselected role (Editor, on all sites), once the roles have loaded. */\n defaultRoleId: string | undefined;\n ownerRoleId: string | undefined;\n /** Runs after the invitation is created, before the sheet closes (it stays pending meanwhile). */\n onInvited: (invitation: Invitation) => Promise<unknown>;\n onDone: () => void;\n};\n\n/** The invite sheet's form: an email and the invitee's role assignments (one row per site). */\nexport const useInviteForm = ({ open, defaultRoleId, ownerRoleId, onInvited, onDone }: InviteFormOptions) => {\n const invite = useInviteUser();\n const schema = useMemo(\n () => z.object({ email: emailField(), rows: assignmentRowsSchema(ownerRoleId) }),\n [ownerRoleId],\n );\n const form = useForm<InviteValues>({ resolver: zodResolver(schema), defaultValues: emptyValues('') });\n const { reset } = form;\n // Roles are already loaded by the Users screen (role names), so the default is there when the sheet opens.\n useEffect(() => {\n if (open) {\n reset(emptyValues(defaultRoleId ?? ''));\n }\n }, [open, defaultRoleId, reset]);\n const onSubmit = form.handleSubmit(async ({ email, rows }) => {\n const created = await settle(invite.mutateAsync({ email, assignments: toAssignments(rows) }));\n if (!created.ok) {\n return;\n }\n // A failure here (the copyable link) is reported by the mutation; the invitation itself exists.\n await settle(onInvited(created.value));\n reset(emptyValues(defaultRoleId ?? ''));\n onDone();\n });\n return { form, onSubmit, invite };\n};\n","import type { Invitation } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { FormError } from '@/components/FormError';\nimport { FormSheet } from '@/components/FormSheet';\nimport { FormTextField } from '@/components/FormTextField';\nimport { AssignmentsField } from '../AssignmentsField';\nimport { useAssignmentOptions } from '../hooks/useAssignmentOptions';\nimport { useInviteForm } from '../hooks/useInviteForm';\n\ntype InviteSheetProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Runs once the invitation exists, while the sheet is still pending (e.g. to fetch its link). */\n onInvited: (invitation: Invitation) => Promise<unknown>;\n /** Keeps focus where it is when the sheet closes (on a link that just appeared). */\n onCloseAutoFocus: (event: Event) => void;\n};\n\n/**\n * Invites someone by email with a role on all sites, or one role per site where there are several (Editor\n * on all sites preselected; Owner isn't offered).\n */\nexport const InviteSheet = ({ open, onOpenChange, onInvited, onCloseAutoFocus }: InviteSheetProps) => {\n const { t } = useTranslation();\n const options = useAssignmentOptions({ includeOwner: false });\n const { form, onSubmit, invite } = useInviteForm({\n open,\n defaultRoleId: options.editorRoleId,\n ownerRoleId: options.ownerRoleId,\n onInvited,\n onDone: () => onOpenChange(false),\n });\n return (\n <FormSheet\n open={open}\n onOpenChange={onOpenChange}\n size=\"md\"\n title={t('users.inviteTitle')}\n dirty={form.formState.isDirty}\n pending={form.formState.isSubmitting}\n submitLabel={t('users.invite')}\n pendingLabel={t('common.saving')}\n onSubmit={(event) => void onSubmit(event)}\n onCloseAutoFocus={onCloseAutoFocus}\n >\n <FormTextField\n control={form.control}\n name=\"email\"\n label={t('users.email')}\n type=\"email\"\n autoComplete=\"off\"\n />\n <AssignmentsField\n control={form.control}\n roleOptions={options.roleOptions}\n siteOptions={options.siteOptions}\n siteIds={options.siteIds}\n multiSite={options.multiSite}\n defaultRoleId={options.editorRoleId}\n />\n <FormError error={invite.error ?? options.error} />\n </FormSheet>\n );\n};\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { AdminUser } from '@shapio/client';\nimport { useEffect, useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useUpdateUser } from '@/api/users';\nimport { i18next } from '@/app/i18n';\nimport { settle } from '@/helpers/settle';\nimport {\n assignmentRowsSchema,\n toAssignmentRows,\n toAssignments,\n type AssignmentsValues,\n} from '../helpers/assignments';\n\n/** An admin user's role assignments, replaced as a whole (`assignments`). */\nexport const useAccessForm = (\n open: boolean,\n user: AdminUser,\n ownerRoleId: string | undefined,\n onDone: () => void,\n) => {\n const updateUser = useUpdateUser();\n const schema = useMemo(() => z.object({ rows: assignmentRowsSchema(ownerRoleId) }), [ownerRoleId]);\n const form = useForm<AssignmentsValues>({ resolver: zodResolver(schema), defaultValues: { rows: [] } });\n const { reset } = form;\n useEffect(() => {\n if (open) {\n reset({ rows: toAssignmentRows(user.assignments, ownerRoleId) });\n }\n }, [open, user.assignments, ownerRoleId, reset]);\n const onSubmit = form.handleSubmit(async ({ rows }) => {\n const saved = await settle(\n updateUser.mutateAsync({ id: user.id, input: { assignments: toAssignments(rows) } }),\n );\n if (!saved.ok) {\n return;\n }\n toast.success(i18next.t('users.rolesSaved'));\n onDone();\n });\n return { form, onSubmit, updateUser };\n};\n","import { useMe } from '@/api/auth';\nimport { SYSTEM_ADMIN_ROLE_KEYS } from '@/constants/roles';\n\n/** Whether the signed-in admin holds the owner role (the server checks again). */\nexport const useIsOwner = () =>\n useMe().data?.roles.some((role) => role.key === SYSTEM_ADMIN_ROLE_KEYS.owner) ?? false;\n","import type { AdminUser } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { FormError } from '@/components/FormError';\nimport { FormSheet } from '@/components/FormSheet';\nimport { AssignmentsField } from '../AssignmentsField';\nimport { useAccessForm } from '../hooks/useAccessForm';\nimport { useAssignmentOptions } from '../hooks/useAssignmentOptions';\nimport { useIsOwner } from '../hooks/useIsOwner';\n\ntype AccessSheetProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n user: AdminUser;\n};\n\n/**\n * Changes where an admin user works and with which role (sites plan §H). Owner is offered only to owners,\n * or when the user already holds it, and only on all sites.\n */\nexport const AccessSheet = ({ open, onOpenChange, user }: AccessSheetProps) => {\n const { t } = useTranslation();\n const isOwner = useIsOwner();\n const options = useAssignmentOptions({\n includeOwner: isOwner,\n heldRoleIds: user.assignments.map((assignment) => assignment.roleId),\n });\n const { form, onSubmit, updateUser } = useAccessForm(open, user, options.ownerRoleId, () =>\n onOpenChange(false),\n );\n return (\n <FormSheet\n open={open}\n onOpenChange={onOpenChange}\n size=\"md\"\n title={t('users.accessTitle', { name: user.name || user.email })}\n dirty={form.formState.isDirty}\n pending={updateUser.isPending}\n submitLabel={t('common.saveChanges')}\n pendingLabel={t('common.saving')}\n onSubmit={(event) => void onSubmit(event)}\n >\n <AssignmentsField\n control={form.control}\n roleOptions={options.roleOptions}\n siteOptions={options.siteOptions}\n siteIds={options.siteIds}\n multiSite={options.multiSite}\n defaultRoleId={options.editorRoleId}\n />\n <FormError error={updateUser.error ?? options.error} />\n </FormSheet>\n );\n};\n","import type { AdminUser } from '@shapio/client';\nimport { MoreHorizontal, ShieldCheck, Trash2, UserCheck, UserX } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { StatusChip } from '@/components/StatusChip';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { TableCell, TableRow } from '@/components/ui/table';\nimport { formatDateTime, formatRelativeTime } from '@/helpers/formatDate';\nimport { AccessSheet } from '../../AccessSheet';\nimport { AssignmentBadges } from '../../AssignmentBadges';\nimport { Person } from '../../Person';\n\ntype RowProps = {\n user: AdminUser;\n roleNames: ReadonlyMap<string, string>;\n siteNames: ReadonlyMap<string, string>;\n isSelf: boolean;\n onToggleStatus: (user: AdminUser) => void;\n /** Resolves once the user is removed (the confirmation waits for it). */\n onRemove: (user: AdminUser) => Promise<unknown>;\n};\n\n/**\n * One admin user. Its menu hands off to the access sheet (role per site), or to an inline confirmation\n * anchored to the menu button.\n */\nexport const Row = ({ user, roleNames, siteNames, isSelf, onToggleStatus, onRemove }: RowProps) => {\n const { t } = useTranslation();\n // Undefined until first opened, so rows that are never edited don't each hold a form.\n const [editingAccess, setEditingAccess] = useState<boolean | undefined>(undefined);\n const [removing, setRemoving] = useState(false);\n const displayName = user.name || user.email;\n return (\n <TableRow>\n <TableCell>\n <Person\n name={displayName}\n email={user.email}\n badge={isSelf ? <Badge variant=\"secondary\">{t('users.you')}</Badge> : null}\n />\n </TableCell>\n <TableCell>\n <span className=\"flex flex-wrap gap-1\">\n <AssignmentBadges assignments={user.assignments} roleNames={roleNames} siteNames={siteNames} />\n </span>\n {editingAccess === undefined ? null : (\n <AccessSheet open={editingAccess} onOpenChange={setEditingAccess} user={user} />\n )}\n </TableCell>\n <TableCell>\n {user.status === 'active' ? (\n <StatusChip tone=\"success\" label={t('users.active')} />\n ) : (\n <StatusChip tone=\"muted\" label={t('users.disabled')} />\n )}\n </TableCell>\n <TableCell title={formatDateTime(user.lastLoginAt) || undefined}>\n {user.lastLoginAt ? formatRelativeTime(user.lastLoginAt) : t('common.never')}\n </TableCell>\n <TableCell className=\"text-right\">\n {isSelf ? null : (\n <DropdownMenu>\n <InlineConfirm\n tone=\"danger\"\n open={removing}\n onOpenChange={setRemoving}\n title={t('users.removeTitle', { name: displayName })}\n description={t('users.removeDescription')}\n confirmLabel={t('common.remove')}\n onConfirm={() => onRemove(user)}\n >\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={`${t('common.actions')}: ${displayName}`}>\n <MoreHorizontal aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n </InlineConfirm>\n <DropdownMenuContent\n align=\"end\"\n onCloseAutoFocus={(event) => (removing || editingAccess) && event.preventDefault()}\n >\n <DropdownMenuItem onSelect={() => setEditingAccess(true)}>\n <ShieldCheck aria-hidden=\"true\" />\n {t('users.editAccess')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => onToggleStatus(user)}>\n {user.status === 'active' ? <UserX aria-hidden=\"true\" /> : <UserCheck aria-hidden=\"true\" />}\n {user.status === 'active' ? t('users.disable') : t('users.enable')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\" onSelect={() => setRemoving(true)}>\n <Trash2 aria-hidden=\"true\" />\n {t('common.remove')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </TableCell>\n </TableRow>\n );\n};\n","import type { AdminUser } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { TableCard } from '@/components/TableCard';\nimport { Table as TableRoot, TableBody, TableHead, TableHeader, TableRow } from '@/components/ui/table';\nimport { Row } from './Row';\n\ntype TableProps = {\n users: AdminUser[];\n roleNames: ReadonlyMap<string, string>;\n siteNames: ReadonlyMap<string, string>;\n currentUserId: string | undefined;\n onToggleStatus: (user: AdminUser) => void;\n onRemove: (user: AdminUser) => Promise<unknown>;\n};\n\nexport const Table = ({\n users,\n roleNames,\n siteNames,\n currentUserId,\n onToggleStatus,\n onRemove,\n}: TableProps) => {\n const { t } = useTranslation();\n return (\n <TableCard>\n <TableRoot>\n <TableHeader>\n <TableRow>\n <TableHead>{t('users.name')}</TableHead>\n <TableHead>{t('users.roles')}</TableHead>\n <TableHead>{t('users.status')}</TableHead>\n <TableHead>{t('users.lastLogin')}</TableHead>\n <TableHead>\n <span className=\"sr-only\">{t('common.actions')}</span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {users.map((user) => (\n <Row\n key={user.id}\n user={user}\n roleNames={roleNames}\n siteNames={siteNames}\n isSelf={user.id === currentUserId}\n onToggleStatus={onToggleStatus}\n onRemove={onRemove}\n />\n ))}\n </TableBody>\n </TableRoot>\n </TableCard>\n );\n};\n","import type { AdminUser } from '@shapio/client';\nimport { UserPlus, Users as UsersIcon } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useMe } from '@/api/auth';\nimport { useRoleNames } from '@/api/roles';\nimport { useSiteNames } from '@/api/sites';\nimport { useRemoveUser, useSetUserStatus, useUsers } from '@/api/users';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { QueryView } from '@/components/QueryView';\nimport { Button } from '@/components/ui/button';\nimport { useInvitationLinkReveal } from './hooks/useInvitationLinkReveal';\nimport { InvitationLink } from './InvitationLink';\nimport { Invitations } from './Invitations';\nimport { InviteSheet } from './InviteSheet';\nimport { Table } from './Table';\n\n/** Network → Users: the admins who sign in to this instance, where each works, and invitations. */\nexport const Users = () => {\n const { t } = useTranslation();\n const { data: me } = useMe();\n const users = useUsers();\n const { names: roleNames } = useRoleNames();\n const { names: siteNames } = useSiteNames();\n const setStatus = useSetUserStatus();\n const removeUser = useRemoveUser();\n const [inviting, setInviting] = useState(false);\n const invitationLink = useInvitationLinkReveal();\n const remove = async (user: AdminUser) => {\n await removeUser.mutateAsync(user.id);\n toast.success(t('users.removed'));\n };\n return (\n <Page>\n <PageHeader\n title={t('users.title')}\n actions={\n <Button onClick={() => setInviting(true)}>\n <UserPlus aria-hidden=\"true\" />\n {t('users.invite')}\n </Button>\n }\n />\n <QueryView\n query={users}\n isEmpty={(data) => data.length === 0}\n empty={<EmptyState icon={UsersIcon} title={t('users.empty')} />}\n >\n {(data) => (\n <Table\n users={data}\n roleNames={roleNames}\n siteNames={siteNames}\n currentUserId={me?.user.id}\n onToggleStatus={(user) =>\n setStatus.mutate(\n { id: user.id, status: user.status === 'active' ? 'disabled' : 'active' },\n { onSuccess: () => toast.success(t('users.statusChanged')) },\n )\n }\n onRemove={remove}\n />\n )}\n </QueryView>\n {invitationLink.revealed ? (\n <InvitationLink\n key={invitationLink.revealed.acceptUrl}\n link={invitationLink.revealed}\n emailDelivery={invitationLink.emailDelivery}\n onDismiss={invitationLink.dismiss}\n />\n ) : null}\n <Invitations\n siteNames={siteNames}\n onCopyLink={invitationLink.reveal}\n onCloseAutoFocus={invitationLink.keepFocusOnReveal}\n />\n <InviteSheet\n open={inviting}\n onOpenChange={setInviting}\n onInvited={invitationLink.announceInvitation}\n onCloseAutoFocus={invitationLink.keepFocusOnReveal}\n />\n </Page>\n );\n};\n","import { createLazyRoute } from '@tanstack/react-router';\nimport { ContentTypes } from '@/features/Network/ContentTypes';\nimport { New as NewContentType } from '@/features/Network/ContentTypes/New';\nimport { Site } from '@/features/Network/Site';\nimport { Sites } from '@/features/Network/Sites';\nimport { AuditLog } from '@/features/Settings/AuditLog';\nimport { Roles } from '@/features/Settings/Roles';\nimport { AppRoles } from '@/features/Settings/Roles/AppRoles';\nimport { Editor as AppRoleEditor } from '@/features/Settings/Roles/AppRoles/Editor';\nimport { Users } from '@/features/Users';\n\n/** The network view's screens (sites plan §H), loaded together on the first visit. */\nexport const networkLazyRoutes = {\n sites: createLazyRoute('/app/network/sites')({ component: Sites }),\n site: createLazyRoute('/app/network/sites/$siteId')({ component: Site }),\n contentTypes: createLazyRoute('/app/network/content-types/')({ component: ContentTypes }),\n newContentType: createLazyRoute('/app/network/content-types/new')({ component: NewContentType }),\n users: createLazyRoute('/app/network/users')({ component: Users }),\n roles: createLazyRoute('/app/network/roles')({ component: Roles }),\n appRoles: createLazyRoute('/app/network/roles/app')({ component: AppRoles }),\n appRole: createLazyRoute('/app/network/roles/app/$roleId')({ component: AppRoleEditor }),\n auditLog: createLazyRoute('/app/network/audit-log')({ component: AuditLog }),\n};\n"],"ignoreList":[2,3],"mappings":"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"}