@shapio/cms 0.5.8 → 0.5.10

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 (343) hide show
  1. package/dist/admin/assets/{AssetTile-BrMzsUZD.js → AssetTile-DecaDqjj.js} +2 -2
  2. package/dist/admin/assets/{AssetTile-BrMzsUZD.js.map → AssetTile-DecaDqjj.js.map} +1 -1
  3. package/dist/admin/assets/AssistError-rslPtgWB.js +2 -0
  4. package/dist/admin/assets/{AssistError-Cs-r9Ssc.js.map → AssistError-rslPtgWB.js.map} +1 -1
  5. package/dist/admin/assets/{BlockMenuItems-DsccXMc_.js → BlockMenuItems-JHFue7Qt.js} +2 -2
  6. package/dist/admin/assets/{BlockMenuItems-DsccXMc_.js.map → BlockMenuItems-JHFue7Qt.js.map} +1 -1
  7. package/dist/admin/assets/Body-7NgJl9Pi.js +2 -0
  8. package/dist/admin/assets/Body-7NgJl9Pi.js.map +1 -0
  9. package/dist/admin/assets/Builder-DmlYcgiP.js +2 -0
  10. package/dist/admin/assets/Builder-DmlYcgiP.js.map +1 -0
  11. package/dist/admin/assets/{CodeEditor-CBCR73Wd.js → CodeEditor-Dv1FtkvI.js} +2 -2
  12. package/dist/admin/assets/{CodeEditor-CBCR73Wd.js.map → CodeEditor-Dv1FtkvI.js.map} +1 -1
  13. package/dist/admin/assets/{CopyButton-CxFsBHfF.js → CopyButton-Brnpfqe0.js} +2 -2
  14. package/dist/admin/assets/{CopyButton-CxFsBHfF.js.map → CopyButton-Brnpfqe0.js.map} +1 -1
  15. package/dist/admin/assets/{CursorPager-BW2U3v6l.js → CursorPager-C7cAK5Qe.js} +2 -2
  16. package/dist/admin/assets/{CursorPager-BW2U3v6l.js.map → CursorPager-C7cAK5Qe.js.map} +1 -1
  17. package/dist/admin/assets/{ExternalLink-BITMgS1K.js → ExternalLink-D80sb5Jj.js} +2 -2
  18. package/dist/admin/assets/{ExternalLink-BITMgS1K.js.map → ExternalLink-D80sb5Jj.js.map} +1 -1
  19. package/dist/admin/assets/{FocalPoint-CpZTve1E.js → FocalPoint-Bhtb1gUa.js} +2 -2
  20. package/dist/admin/assets/{FocalPoint-CpZTve1E.js.map → FocalPoint-Bhtb1gUa.js.map} +1 -1
  21. package/dist/admin/assets/Form-Cf1ephPH.js +2 -0
  22. package/dist/admin/assets/Form-Cf1ephPH.js.map +1 -0
  23. package/dist/admin/assets/FormCheckboxGroup-BzVZFR3W.js +2 -0
  24. package/dist/admin/assets/FormCheckboxGroup-BzVZFR3W.js.map +1 -0
  25. package/dist/admin/assets/{FormRadioGroup-Cfx5pvzU.js → FormRadioGroup-BzmLzRnI.js} +2 -2
  26. package/dist/admin/assets/{FormRadioGroup-Cfx5pvzU.js.map → FormRadioGroup-BzmLzRnI.js.map} +1 -1
  27. package/dist/admin/assets/FormSelectField-Cl7EjXc3.js +2 -0
  28. package/dist/admin/assets/FormSelectField-Cl7EjXc3.js.map +1 -0
  29. package/dist/admin/assets/FormSheet-CLZpd_7B.js +2 -0
  30. package/dist/admin/assets/FormSheet-CLZpd_7B.js.map +1 -0
  31. package/dist/admin/assets/{FormSwitchField-BLOh7qei.js → FormSwitchField-BbqQ3tx_.js} +2 -2
  32. package/dist/admin/assets/{FormSwitchField-BLOh7qei.js.map → FormSwitchField-BbqQ3tx_.js.map} +1 -1
  33. package/dist/admin/assets/{FormTextareaField-CO115n_u.js → FormTextareaField-9RN5Pt3B.js} +2 -2
  34. package/dist/admin/assets/{FormTextareaField-CO115n_u.js.map → FormTextareaField-9RN5Pt3B.js.map} +1 -1
  35. package/dist/admin/assets/{HintedLabel-DzHnEdIK.js → HintedLabel-D9IVF0EE.js} +2 -2
  36. package/dist/admin/assets/{HintedLabel-DzHnEdIK.js.map → HintedLabel-D9IVF0EE.js.map} +1 -1
  37. package/dist/admin/assets/{InfoHint-CSEtcHjL.js → InfoHint-tlSeZB9U.js} +2 -2
  38. package/dist/admin/assets/{InfoHint-CSEtcHjL.js.map → InfoHint-tlSeZB9U.js.map} +1 -1
  39. package/dist/admin/assets/{InlineConfirm-yW-iUKFC.js → InlineConfirm-Kj9AOIFO.js} +2 -2
  40. package/dist/admin/assets/{InlineConfirm-yW-iUKFC.js.map → InlineConfirm-Kj9AOIFO.js.map} +1 -1
  41. package/dist/admin/assets/{InsertMenuItem-CCr9e0qY.js → InsertMenuItem-CHAp2tH7.js} +2 -2
  42. package/dist/admin/assets/{InsertMenuItem-CCr9e0qY.js.map → InsertMenuItem-CHAp2tH7.js.map} +1 -1
  43. package/dist/admin/assets/{LinkTabs-8SmS1vCd.js → LinkTabs-oQXsy1I3.js} +2 -2
  44. package/dist/admin/assets/{LinkTabs-8SmS1vCd.js.map → LinkTabs-oQXsy1I3.js.map} +1 -1
  45. package/dist/admin/assets/{Match-CcD9KxHH.js → Match-BfNRwPfR.js} +2 -2
  46. package/dist/admin/assets/{Match-CcD9KxHH.js.map → Match-BfNRwPfR.js.map} +1 -1
  47. package/dist/admin/assets/{NoAccess-C8RLPN0I.js → NoAccess-DnEpYj9l.js} +2 -2
  48. package/dist/admin/assets/{NoAccess-C8RLPN0I.js.map → NoAccess-DnEpYj9l.js.map} +1 -1
  49. package/dist/admin/assets/Panel-Bcl09TtM.js.map +1 -1
  50. package/dist/admin/assets/{QueryView-xMP_uJ_t.js → QueryView-B86NcRt5.js} +2 -2
  51. package/dist/admin/assets/{QueryView-xMP_uJ_t.js.map → QueryView-B86NcRt5.js.map} +1 -1
  52. package/dist/admin/assets/{RadioTile-DQFmni5A.js → RadioTile-Bwd2Pmlk.js} +2 -2
  53. package/dist/admin/assets/RadioTile-Bwd2Pmlk.js.map +1 -0
  54. package/dist/admin/assets/{RichTextField-CVHRIbnu.js → RichTextField-Dou79MHF.js} +4 -4
  55. package/dist/admin/assets/RichTextField-Dou79MHF.js.map +1 -0
  56. package/dist/admin/assets/{RowTitle-Bqt6evG9.js → RowTitle-DH9OZs3g.js} +2 -2
  57. package/dist/admin/assets/{RowTitle-Bqt6evG9.js.map → RowTitle-DH9OZs3g.js.map} +1 -1
  58. package/dist/admin/assets/{SecretReveal-Bm6nYg5J.js → SecretReveal-D95oACLj.js} +2 -2
  59. package/dist/admin/assets/{SecretReveal-Bm6nYg5J.js.map → SecretReveal-D95oACLj.js.map} +1 -1
  60. package/dist/admin/assets/{SharedGlyph-cUmTh0_C.js → SharedGlyph-Chwb1EIS.js} +2 -2
  61. package/dist/admin/assets/{SharedGlyph-cUmTh0_C.js.map → SharedGlyph-Chwb1EIS.js.map} +1 -1
  62. package/dist/admin/assets/StepList-D9iHsUZJ.js +2 -0
  63. package/dist/admin/assets/StepList-D9iHsUZJ.js.map +1 -0
  64. package/dist/admin/assets/Structure-CewJL1b3.js +2 -0
  65. package/dist/admin/assets/{Structure-D8csgrIt.js.map → Structure-CewJL1b3.js.map} +1 -1
  66. package/dist/admin/assets/{SubNavLink-CiCaVV8U.js → SubNavLink-7Cs1LqMv.js} +2 -2
  67. package/dist/admin/assets/SubNavLink-7Cs1LqMv.js.map +1 -0
  68. package/dist/admin/assets/{SuggestAltButton-CvIoirnz.js → SuggestAltButton-BK1uo4yC.js} +2 -2
  69. package/dist/admin/assets/{SuggestAltButton-CvIoirnz.js.map → SuggestAltButton-BK1uo4yC.js.map} +1 -1
  70. package/dist/admin/assets/{TextLink-HRn66VL1.js → TextLink-Dfs5wsc5.js} +2 -2
  71. package/dist/admin/assets/{TextLink-HRn66VL1.js.map → TextLink-Dfs5wsc5.js.map} +1 -1
  72. package/dist/admin/assets/{Thumbnail-DNj5TRBI.js → Thumbnail-C2A_Ub77.js} +2 -2
  73. package/dist/admin/assets/{Thumbnail-DNj5TRBI.js.map → Thumbnail-C2A_Ub77.js.map} +1 -1
  74. package/dist/admin/assets/Trans-CPoNNUK1.js +2 -0
  75. package/dist/admin/assets/Trans-CPoNNUK1.js.map +1 -0
  76. package/dist/admin/assets/{UnsavedChangesGuard-CUiuMklN.js → UnsavedChangesGuard-BsEyn9oH.js} +2 -2
  77. package/dist/admin/assets/{UnsavedChangesGuard-CUiuMklN.js.map → UnsavedChangesGuard-BsEyn9oH.js.map} +1 -1
  78. package/dist/admin/assets/{UserAvatar-p-jV-LoD.js → UserAvatar-CgGKOFfP.js} +2 -2
  79. package/dist/admin/assets/{UserAvatar-p-jV-LoD.js.map → UserAvatar-CgGKOFfP.js.map} +1 -1
  80. package/dist/admin/assets/auth-BFSvtV59.js +2 -0
  81. package/dist/admin/assets/{auth-CQO4MBUj.js.map → auth-BFSvtV59.js.map} +1 -1
  82. package/dist/admin/assets/{badge-CqKF1pwz.js → badge-DGqA_yr_.js} +2 -2
  83. package/dist/admin/assets/{badge-CqKF1pwz.js.map → badge-DGqA_yr_.js.map} +1 -1
  84. package/dist/admin/assets/baseExtensions-TVKN1UwW.js.map +1 -1
  85. package/dist/admin/assets/{boxes-CAygw8zF.js → boxes-_5klpWNM.js} +2 -2
  86. package/dist/admin/assets/{boxes-CAygw8zF.js.map → boxes-_5klpWNM.js.map} +1 -1
  87. package/dist/admin/assets/{calendar-clock-BZGtAvWR.js → calendar-clock-VXok22Xj.js} +2 -2
  88. package/dist/admin/assets/{calendar-clock-BZGtAvWR.js.map → calendar-clock-VXok22Xj.js.map} +1 -1
  89. package/dist/admin/assets/changeSets-B6HxCJ4A.js +2 -0
  90. package/dist/admin/assets/{changeSets-8EburmT0.js.map → changeSets-B6HxCJ4A.js.map} +1 -1
  91. package/dist/admin/assets/chevron-left-CkRxDtvO.js +2 -0
  92. package/dist/admin/assets/{chevron-left-DGU3HGYG.js.map → chevron-left-CkRxDtvO.js.map} +1 -1
  93. package/dist/admin/assets/{circle-check-C37MSJqX.js → circle-check-DtDq7QMo.js} +2 -2
  94. package/dist/admin/assets/{circle-check-C37MSJqX.js.map → circle-check-DtDq7QMo.js.map} +1 -1
  95. package/dist/admin/assets/{clock-2arjsgZ4.js → clock-BtvZR9KD.js} +2 -2
  96. package/dist/admin/assets/{clock-2arjsgZ4.js.map → clock-BtvZR9KD.js.map} +1 -1
  97. package/dist/admin/assets/cn-DVhJ55Mo.js.map +1 -1
  98. package/dist/admin/assets/{constants-a_15vqOh.js → constants-DY3YJAKH.js} +2 -2
  99. package/dist/admin/assets/{constants-a_15vqOh.js.map → constants-DY3YJAKH.js.map} +1 -1
  100. package/dist/admin/assets/content-BNZF26Ve.js +3 -0
  101. package/dist/admin/assets/content-BNZF26Ve.js.map +1 -0
  102. package/dist/admin/assets/{contentCounts-DP7YYeZZ.js → contentCounts-BzC7IQqP.js} +2 -2
  103. package/dist/admin/assets/{contentCounts-DP7YYeZZ.js.map → contentCounts-BzC7IQqP.js.map} +1 -1
  104. package/dist/admin/assets/{contentTypes-84uc0bjR.js → contentTypes-Bz2xpqGf.js} +2 -2
  105. package/dist/admin/assets/{contentTypes-84uc0bjR.js.map → contentTypes-Bz2xpqGf.js.map} +1 -1
  106. package/dist/admin/assets/{context-IKYdzQJ-.js → context-CEVKblBl.js} +2 -2
  107. package/dist/admin/assets/{context-IKYdzQJ-.js.map → context-CEVKblBl.js.map} +1 -1
  108. package/dist/admin/assets/{copy-CsSRHgKZ.js → copy-B7vIq8DS.js} +2 -2
  109. package/dist/admin/assets/{copy-CsSRHgKZ.js.map → copy-B7vIq8DS.js.map} +1 -1
  110. package/dist/admin/assets/createLucideIcon-BOsNKleB.js +2 -0
  111. package/dist/admin/assets/createLucideIcon-BOsNKleB.js.map +1 -0
  112. package/dist/admin/assets/develop-D6CtwuYj.js +11 -0
  113. package/dist/admin/assets/develop-D6CtwuYj.js.map +1 -0
  114. package/dist/admin/assets/{dropdown-menu-_xfaEp5C.js → dropdown-menu-Bz7CLcRK.js} +2 -2
  115. package/dist/admin/assets/{dropdown-menu-_xfaEp5C.js.map → dropdown-menu-Bz7CLcRK.js.map} +1 -1
  116. package/dist/admin/assets/{ellipsis-F91991on.js → ellipsis-Ci0rsbCJ.js} +2 -2
  117. package/dist/admin/assets/{ellipsis-F91991on.js.map → ellipsis-Ci0rsbCJ.js.map} +1 -1
  118. package/dist/admin/assets/{entryLink-CVB-TdIn.js → entryLink-B0hSb_dN.js} +2 -2
  119. package/dist/admin/assets/{entryLink-CVB-TdIn.js.map → entryLink-B0hSb_dN.js.map} +1 -1
  120. package/dist/admin/assets/es2015-Cv57ynE1.js +42 -0
  121. package/dist/admin/assets/es2015-Cv57ynE1.js.map +1 -0
  122. package/dist/admin/assets/{external-link-CdG6kHfA.js → external-link-Bs9YRzvY.js} +2 -2
  123. package/dist/admin/assets/{external-link-CdG6kHfA.js.map → external-link-Bs9YRzvY.js.map} +1 -1
  124. package/dist/admin/assets/{field-COOzRptX.js → field-D-xWW2E7.js} +2 -2
  125. package/dist/admin/assets/{field-COOzRptX.js.map → field-D-xWW2E7.js.map} +1 -1
  126. package/dist/admin/assets/{file-stack-28ZtO1xW.js → file-stack-X4OGmkLA.js} +2 -2
  127. package/dist/admin/assets/{file-stack-28ZtO1xW.js.map → file-stack-X4OGmkLA.js.map} +1 -1
  128. package/dist/admin/assets/{fileRoute-s7mCMYUJ.js → fileRoute-DMal-zYL.js} +2 -2
  129. package/dist/admin/assets/{fileRoute-s7mCMYUJ.js.map → fileRoute-DMal-zYL.js.map} +1 -1
  130. package/dist/admin/assets/{folder-plus-DIk0pWkP.js → folder-plus-De2GNvry.js} +2 -2
  131. package/dist/admin/assets/{folder-plus-DIk0pWkP.js.map → folder-plus-De2GNvry.js.map} +1 -1
  132. package/dist/admin/assets/followPlural-CsgeALTW.js +2 -0
  133. package/dist/admin/assets/followPlural-CsgeALTW.js.map +1 -0
  134. package/dist/admin/assets/{globe-DFr3Gd2w.js → globe-DBw84s8Z.js} +2 -2
  135. package/dist/admin/assets/{globe-DFr3Gd2w.js.map → globe-DBw84s8Z.js.map} +1 -1
  136. package/dist/admin/assets/{image-DT79QFa_.js → image-CX4mT-_R.js} +2 -2
  137. package/dist/admin/assets/{image-DT79QFa_.js.map → image-CX4mT-_R.js.map} +1 -1
  138. package/dist/admin/assets/{image-off-DFs5upyX.js → image-off-CVaH_qKf.js} +2 -2
  139. package/dist/admin/assets/{image-off-DFs5upyX.js.map → image-off-CVaH_qKf.js.map} +1 -1
  140. package/dist/admin/assets/inbox-C0PVc6UI.js +2 -0
  141. package/dist/admin/assets/inbox-C0PVc6UI.js.map +1 -0
  142. package/dist/admin/assets/{inbox-CySnQydm.js → inbox-D9SmWt5L.js} +2 -2
  143. package/dist/admin/assets/{inbox-CySnQydm.js.map → inbox-D9SmWt5L.js.map} +1 -1
  144. package/dist/admin/assets/index-BqtCXB0u.js +4 -0
  145. package/dist/admin/assets/index-BqtCXB0u.js.map +1 -0
  146. package/dist/admin/assets/index-DZsQq6fY.css +2 -0
  147. package/dist/admin/assets/{key-round-D36CePnN.js → key-round-C8sd9CLN.js} +2 -2
  148. package/dist/admin/assets/{key-round-D36CePnN.js.map → key-round-C8sd9CLN.js.map} +1 -1
  149. package/dist/admin/assets/{labels-DQckbLGW.js → labels-BtktCNGw.js} +2 -2
  150. package/dist/admin/assets/{labels-DQckbLGW.js.map → labels-BtktCNGw.js.map} +1 -1
  151. package/dist/admin/assets/{languages-CzbTaQv9.js → languages-DLjdz6gb.js} +2 -2
  152. package/dist/admin/assets/{languages-CzbTaQv9.js.map → languages-DLjdz6gb.js.map} +1 -1
  153. package/dist/admin/assets/{layers-BmcodiaH.js → layers-swLuw-3a.js} +2 -2
  154. package/dist/admin/assets/{layers-BmcodiaH.js.map → layers-swLuw-3a.js.map} +1 -1
  155. package/dist/admin/assets/{link-2-off-CoJNwrxm.js → link-2-off-CEsI5T8h.js} +2 -2
  156. package/dist/admin/assets/{link-2-off-CoJNwrxm.js.map → link-2-off-CEsI5T8h.js.map} +1 -1
  157. package/dist/admin/assets/{link-Pyr2Y35S.js → link-C98FG_p5.js} +2 -2
  158. package/dist/admin/assets/{link-Pyr2Y35S.js.map → link-C98FG_p5.js.map} +1 -1
  159. package/dist/admin/assets/locales-CkuC7TJ1.js +2 -0
  160. package/dist/admin/assets/{locales-Bg3htKo8.js.map → locales-CkuC7TJ1.js.map} +1 -1
  161. package/dist/admin/assets/media-CbGSd_Mw.js +2 -0
  162. package/dist/admin/assets/{media-BCnVhaDH.js.map → media-CbGSd_Mw.js.map} +1 -1
  163. package/dist/admin/assets/{media-CURizGns.js → media-CeZGDGh7.js} +2 -2
  164. package/dist/admin/assets/{media-CURizGns.js.map → media-CeZGDGh7.js.map} +1 -1
  165. package/dist/admin/assets/network-BflLSKFO.js +2 -0
  166. package/dist/admin/assets/network-BflLSKFO.js.map +1 -0
  167. package/dist/admin/assets/{plus-BoDtdLCo.js → plus-cr9ZfO6j.js} +2 -2
  168. package/dist/admin/assets/{plus-BoDtdLCo.js.map → plus-cr9ZfO6j.js.map} +1 -1
  169. package/dist/admin/assets/publishing-BkxBplUZ.js +2 -0
  170. package/dist/admin/assets/publishing-BkxBplUZ.js.map +1 -0
  171. package/dist/admin/assets/{radio-group-4ok5evXq.js → radio-group-CRuWQnuV.js} +2 -2
  172. package/dist/admin/assets/{radio-group-4ok5evXq.js.map → radio-group-CRuWQnuV.js.map} +1 -1
  173. package/dist/admin/assets/{rotate-ccw-DL6TzcZh.js → rotate-ccw-BP8Ba-mY.js} +2 -2
  174. package/dist/admin/assets/{rotate-ccw-DL6TzcZh.js.map → rotate-ccw-BP8Ba-mY.js.map} +1 -1
  175. package/dist/admin/assets/schedules-BIyBlsYZ.js +2 -0
  176. package/dist/admin/assets/{schedules-BmB9Y73z.js.map → schedules-BIyBlsYZ.js.map} +1 -1
  177. package/dist/admin/assets/schema-6eUoC8fJ.js +2 -0
  178. package/dist/admin/assets/schema-6eUoC8fJ.js.map +1 -0
  179. package/dist/admin/assets/{scroll-text-PqeZm472.js → scroll-text-B5vfi9fD.js} +2 -2
  180. package/dist/admin/assets/{scroll-text-PqeZm472.js.map → scroll-text-B5vfi9fD.js.map} +1 -1
  181. package/dist/admin/assets/{search-BdwIwOzC.js → search-wj7zbkx1.js} +2 -2
  182. package/dist/admin/assets/{search-BdwIwOzC.js.map → search-wj7zbkx1.js.map} +1 -1
  183. package/dist/admin/assets/{searchSchemas-CSScloG8.js → searchSchemas-DAnwh3I3.js} +2 -2
  184. package/dist/admin/assets/{searchSchemas-CSScloG8.js.map → searchSchemas-DAnwh3I3.js.map} +1 -1
  185. package/dist/admin/assets/{sections-DqBzSKMP.js → sections-CWL-XD6m.js} +2 -2
  186. package/dist/admin/assets/sections-CWL-XD6m.js.map +1 -0
  187. package/dist/admin/assets/{sections-BTS683ur.js → sections-DBQpB0uv.js} +2 -2
  188. package/dist/admin/assets/{sections-BTS683ur.js.map → sections-DBQpB0uv.js.map} +1 -1
  189. package/dist/admin/assets/{select-C0USI-Ox.js → select-DVrPV1b3.js} +2 -2
  190. package/dist/admin/assets/{select-C0USI-Ox.js.map → select-DVrPV1b3.js.map} +1 -1
  191. package/dist/admin/assets/{send-XPWo3m4u.js → send-CzFdgUc_.js} +2 -2
  192. package/dist/admin/assets/{send-XPWo3m4u.js.map → send-CzFdgUc_.js.map} +1 -1
  193. package/dist/admin/assets/seo-Bd0sWQMo.js +2 -0
  194. package/dist/admin/assets/{seo-CceGYTIX.js.map → seo-Bd0sWQMo.js.map} +1 -1
  195. package/dist/admin/assets/settings-CqnrPmzR.js +2 -0
  196. package/dist/admin/assets/{settings-B60vHpZd.js.map → settings-CqnrPmzR.js.map} +1 -1
  197. package/dist/admin/assets/shapes-ZAkMBB-Z.js +6 -0
  198. package/dist/admin/assets/shapes-ZAkMBB-Z.js.map +1 -0
  199. package/dist/admin/assets/{skeleton-B5MP72Kw.js → skeleton-CiX26LnL.js} +2 -2
  200. package/dist/admin/assets/{skeleton-B5MP72Kw.js.map → skeleton-CiX26LnL.js.map} +1 -1
  201. package/dist/admin/assets/{snapshots-DUI2t-qF.js → snapshots-DbFQNJgN.js} +2 -2
  202. package/dist/admin/assets/{snapshots-DUI2t-qF.js.map → snapshots-DbFQNJgN.js.map} +1 -1
  203. package/dist/admin/assets/{sparkles-CvT-jxrW.js → sparkles-D_kmZJVd.js} +2 -2
  204. package/dist/admin/assets/{sparkles-CvT-jxrW.js.map → sparkles-D_kmZJVd.js.map} +1 -1
  205. package/dist/admin/assets/src-CMor9izq.js +7 -0
  206. package/dist/admin/assets/src-CMor9izq.js.map +1 -0
  207. package/dist/admin/assets/{stableId-BrtQedPy.js → stableId-g1uxJGSz.js} +2 -2
  208. package/dist/admin/assets/{stableId-BrtQedPy.js.map → stableId-g1uxJGSz.js.map} +1 -1
  209. package/dist/admin/assets/{store-CdIFG90N.js → store-CznhNKEi.js} +2 -2
  210. package/dist/admin/assets/{store-CdIFG90N.js.map → store-CznhNKEi.js.map} +1 -1
  211. package/dist/admin/assets/{switch-Dp6WYNam.js → switch-CiVf05NF.js} +2 -2
  212. package/dist/admin/assets/{switch-Dp6WYNam.js.map → switch-CiVf05NF.js.map} +1 -1
  213. package/dist/admin/assets/{theme-65PB8uAu.js → theme-Cv-MfOv8.js} +2 -2
  214. package/dist/admin/assets/theme-Cv-MfOv8.js.map +1 -0
  215. package/dist/admin/assets/titles-DrQhW8z3.js +2 -0
  216. package/dist/admin/assets/titles-DrQhW8z3.js.map +1 -0
  217. package/dist/admin/assets/tokens-B1S81Epe.js +2 -0
  218. package/dist/admin/assets/{tokens-ixHjAkDK.js.map → tokens-B1S81Epe.js.map} +1 -1
  219. package/dist/admin/assets/{tooltip-BGP1DVBt.js → tooltip-Bqf3oyqC.js} +2 -2
  220. package/dist/admin/assets/{tooltip-BGP1DVBt.js.map → tooltip-Bqf3oyqC.js.map} +1 -1
  221. package/dist/admin/assets/{undo-2-BiTANHFz.js → undo-2-DpwwRQTf.js} +2 -2
  222. package/dist/admin/assets/{undo-2-BiTANHFz.js.map → undo-2-DpwwRQTf.js.map} +1 -1
  223. package/dist/admin/assets/useContentSchema-B_q1rMrG.js +2 -0
  224. package/dist/admin/assets/useContentSchema-B_q1rMrG.js.map +1 -0
  225. package/dist/admin/assets/useCursorPager-BHYqHb3M.js +2 -0
  226. package/dist/admin/assets/{useCursorPager-0zHjlm-7.js.map → useCursorPager-BHYqHb3M.js.map} +1 -1
  227. package/dist/admin/assets/{useDiscardGuard-BskWSlbT.js → useDiscardGuard-C4QTfiU4.js} +2 -2
  228. package/dist/admin/assets/{useDiscardGuard-BskWSlbT.js.map → useDiscardGuard-C4QTfiU4.js.map} +1 -1
  229. package/dist/admin/assets/{useMediaPickerDialog-CU-ekPqX.js → useMediaPickerDialog-BLrVV1Kn.js} +2 -2
  230. package/dist/admin/assets/{useMediaPickerDialog-CU-ekPqX.js.map → useMediaPickerDialog-BLrVV1Kn.js.map} +1 -1
  231. package/dist/admin/assets/{useMediaUploader-CBcq1ICg.js → useMediaUploader-CFy6lasO.js} +2 -2
  232. package/dist/admin/assets/useMediaUploader-CFy6lasO.js.map +1 -0
  233. package/dist/admin/assets/useModelIndex-NU-WlHQY.js +2 -0
  234. package/dist/admin/assets/useModelIndex-NU-WlHQY.js.map +1 -0
  235. package/dist/admin/assets/useNetworkPermission-DehDln-U.js +2 -0
  236. package/dist/admin/assets/{useNetworkPermission-Cts98h9d.js.map → useNetworkPermission-DehDln-U.js.map} +1 -1
  237. package/dist/admin/assets/{usePaletteItems-DtReWmkd.js → usePaletteItems-CFpNlSOs.js} +2 -2
  238. package/dist/admin/assets/{usePaletteItems-DtReWmkd.js.map → usePaletteItems-CFpNlSOs.js.map} +1 -1
  239. package/dist/admin/assets/usePlaces-BA4x6503.js +2 -0
  240. package/dist/admin/assets/usePlaces-BA4x6503.js.map +1 -0
  241. package/dist/admin/assets/useResolvedDefinitions-30lnwFQ1.js +2 -0
  242. package/dist/admin/assets/useResolvedDefinitions-30lnwFQ1.js.map +1 -0
  243. package/dist/admin/assets/{useResolvedScheme-C8vcQVko.js → useResolvedScheme-BVM4qLct.js} +2 -2
  244. package/dist/admin/assets/{useResolvedScheme-C8vcQVko.js.map → useResolvedScheme-BVM4qLct.js.map} +1 -1
  245. package/dist/admin/assets/useSaveShortcut-DQuNL1uJ.js +2 -0
  246. package/dist/admin/assets/useSaveShortcut-DQuNL1uJ.js.map +1 -0
  247. package/dist/admin/assets/{useSchemaScopeAccess-ByrxIdKM.js → useSchemaScopeAccess-JXOMx51q.js} +2 -2
  248. package/dist/admin/assets/{useSchemaScopeAccess-ByrxIdKM.js.map → useSchemaScopeAccess-JXOMx51q.js.map} +1 -1
  249. package/dist/admin/assets/users-38jLQ7zr.js +2 -0
  250. package/dist/admin/assets/users-38jLQ7zr.js.map +1 -0
  251. package/dist/admin/assets/{users-DM7CXUBJ.js → users-DYwcVDqp.js} +2 -2
  252. package/dist/admin/assets/{users-DM7CXUBJ.js.map → users-DYwcVDqp.js.map} +1 -1
  253. package/dist/admin/assets/{zod-Cry7YvLY.js → zod-ZaQjjiAq.js} +2 -2
  254. package/dist/admin/assets/{zod-Cry7YvLY.js.map → zod-ZaQjjiAq.js.map} +1 -1
  255. package/dist/admin/index.html +60 -58
  256. package/dist/cli.js +1 -1
  257. package/dist/{cliMain-papyXJDd.js → cliMain-CTntiVc2.js} +107 -30
  258. package/dist/cliMain-CTntiVc2.js.map +1 -0
  259. package/dist/config.d.ts +2 -2
  260. package/dist/config.js +1 -1
  261. package/dist/{contentDisposition-DOL2Xt0l.js → contentDisposition-DzhPhncr.js} +2 -2
  262. package/dist/{contentDisposition-DOL2Xt0l.js.map → contentDisposition-DzhPhncr.js.map} +1 -1
  263. package/dist/index.d.ts +43 -6
  264. package/dist/index.js +2 -2
  265. package/dist/{public-COKbHR-N.d.ts → public-CMFaGDyf.d.ts} +50 -8
  266. package/dist/{public-B57h4F7Y.js → public-sJCQaNaP.js} +2 -2
  267. package/dist/public-sJCQaNaP.js.map +1 -0
  268. package/dist/{s3Adapter-U01iEAcK.js → s3Adapter-CZcCl0sy.js} +2 -2
  269. package/dist/{s3Adapter-U01iEAcK.js.map → s3Adapter-CZcCl0sy.js.map} +1 -1
  270. package/dist/{worker-B-sC-eY2.js → worker-DHm2JwMZ.js} +3140 -1292
  271. package/dist/worker-DHm2JwMZ.js.map +1 -0
  272. package/package.json +5 -5
  273. package/dist/admin/assets/AssistError-Cs-r9Ssc.js +0 -2
  274. package/dist/admin/assets/Body-BzZD-TZT.js +0 -2
  275. package/dist/admin/assets/Body-BzZD-TZT.js.map +0 -1
  276. package/dist/admin/assets/Builder-DW-GJA_q.js +0 -2
  277. package/dist/admin/assets/Builder-DW-GJA_q.js.map +0 -1
  278. package/dist/admin/assets/Form-lNrRHc0I.js +0 -2
  279. package/dist/admin/assets/Form-lNrRHc0I.js.map +0 -1
  280. package/dist/admin/assets/FormCheckboxGroup-DeeaYnzB.js +0 -2
  281. package/dist/admin/assets/FormCheckboxGroup-DeeaYnzB.js.map +0 -1
  282. package/dist/admin/assets/FormSelectField-BzE9Lq9i.js +0 -2
  283. package/dist/admin/assets/FormSelectField-BzE9Lq9i.js.map +0 -1
  284. package/dist/admin/assets/RadioTile-DQFmni5A.js.map +0 -1
  285. package/dist/admin/assets/RichTextField-CVHRIbnu.js.map +0 -1
  286. package/dist/admin/assets/StepList-BXGYD9eJ.js +0 -2
  287. package/dist/admin/assets/StepList-BXGYD9eJ.js.map +0 -1
  288. package/dist/admin/assets/Structure-D8csgrIt.js +0 -2
  289. package/dist/admin/assets/SubNavLink-CiCaVV8U.js.map +0 -1
  290. package/dist/admin/assets/auth-CQO4MBUj.js +0 -2
  291. package/dist/admin/assets/changeSets-8EburmT0.js +0 -2
  292. package/dist/admin/assets/chevron-left-DGU3HGYG.js +0 -2
  293. package/dist/admin/assets/content-CAjkbZEY.js +0 -3
  294. package/dist/admin/assets/content-CAjkbZEY.js.map +0 -1
  295. package/dist/admin/assets/createLucideIcon-CLmh7Go-.js +0 -2
  296. package/dist/admin/assets/createLucideIcon-CLmh7Go-.js.map +0 -1
  297. package/dist/admin/assets/develop-BOqvnlgt.js +0 -11
  298. package/dist/admin/assets/develop-BOqvnlgt.js.map +0 -1
  299. package/dist/admin/assets/es2015-BHmI7wjK.js +0 -42
  300. package/dist/admin/assets/es2015-BHmI7wjK.js.map +0 -1
  301. package/dist/admin/assets/followPlural-Cm7v_Udv.js +0 -2
  302. package/dist/admin/assets/followPlural-Cm7v_Udv.js.map +0 -1
  303. package/dist/admin/assets/inbox-DGO2D8fa.js +0 -2
  304. package/dist/admin/assets/inbox-DGO2D8fa.js.map +0 -1
  305. package/dist/admin/assets/index-BIIU9ZI6.js +0 -4
  306. package/dist/admin/assets/index-BIIU9ZI6.js.map +0 -1
  307. package/dist/admin/assets/index-lxe7WimO.css +0 -2
  308. package/dist/admin/assets/locales-Bg3htKo8.js +0 -2
  309. package/dist/admin/assets/media-BCnVhaDH.js +0 -2
  310. package/dist/admin/assets/network-BixABr0o.js +0 -2
  311. package/dist/admin/assets/network-BixABr0o.js.map +0 -1
  312. package/dist/admin/assets/publishing-Dke9bSKp.js +0 -2
  313. package/dist/admin/assets/publishing-Dke9bSKp.js.map +0 -1
  314. package/dist/admin/assets/schedules-BmB9Y73z.js +0 -2
  315. package/dist/admin/assets/schema-D-qo7XSF.js +0 -2
  316. package/dist/admin/assets/schema-D-qo7XSF.js.map +0 -1
  317. package/dist/admin/assets/sections-DqBzSKMP.js.map +0 -1
  318. package/dist/admin/assets/seo-CceGYTIX.js +0 -2
  319. package/dist/admin/assets/settings-B60vHpZd.js +0 -2
  320. package/dist/admin/assets/shapes-B5twqZcp.js +0 -6
  321. package/dist/admin/assets/shapes-B5twqZcp.js.map +0 -1
  322. package/dist/admin/assets/src-ndgTSYLX.js +0 -7
  323. package/dist/admin/assets/src-ndgTSYLX.js.map +0 -1
  324. package/dist/admin/assets/theme-65PB8uAu.js.map +0 -1
  325. package/dist/admin/assets/titles-CQiqqDw-.js +0 -2
  326. package/dist/admin/assets/titles-CQiqqDw-.js.map +0 -1
  327. package/dist/admin/assets/tokens-ixHjAkDK.js +0 -2
  328. package/dist/admin/assets/useContentSchema-DtYfhsd2.js +0 -2
  329. package/dist/admin/assets/useContentSchema-DtYfhsd2.js.map +0 -1
  330. package/dist/admin/assets/useCursorPager-0zHjlm-7.js +0 -2
  331. package/dist/admin/assets/useMediaUploader-CBcq1ICg.js.map +0 -1
  332. package/dist/admin/assets/useNetworkPermission-Cts98h9d.js +0 -2
  333. package/dist/admin/assets/usePlaces-DC47wVeU.js +0 -2
  334. package/dist/admin/assets/usePlaces-DC47wVeU.js.map +0 -1
  335. package/dist/admin/assets/useQueries-CirW3Mvp.js +0 -2
  336. package/dist/admin/assets/useQueries-CirW3Mvp.js.map +0 -1
  337. package/dist/admin/assets/useSaveShortcut-rKtp1qK7.js +0 -2
  338. package/dist/admin/assets/useSaveShortcut-rKtp1qK7.js.map +0 -1
  339. package/dist/admin/assets/users-2iJYwlJb.js +0 -2
  340. package/dist/admin/assets/users-2iJYwlJb.js.map +0 -1
  341. package/dist/cliMain-papyXJDd.js.map +0 -1
  342. package/dist/public-B57h4F7Y.js.map +0 -1
  343. package/dist/worker-B-sC-eY2.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"network-BixABr0o.js","names":["__iconData","Form","useMemo","i18next","Form","z.object","zodResolver","i18next","_Fragment","z.object","z.string","EMPTY","zodResolver","useCallback","CreateSheet","Table","TableRoot","useState","Globe2","Table","CreateSheet","useState","useState","Table","TableRoot","_Fragment","Table","z.object","z.string","z.enum","EMPTY","zodResolver","useCallback","i18next","KIND_LABEL_KEYS","CreateSheet","Table","TableRoot","MoreHorizontal","Trash2","useState","Table","CreateSheet","z.object","z.string","zodResolver","useCallback","i18next","i18next","useState","MoreHorizontal","Trash2","Table","TableRoot","useState","Table","_Fragment","Row","useState","Table","Fragment","Row","detailsSchema","z.object","z.string","zodResolver","useState","useMemo","i18next","Form","Editor","z.object","z.string","z.array","z.custom","useMemo","zodResolver","useState","i18next","useState","Table","Link","z.array","z.object","z.string","useMemo","useMemo","z.object","zodResolver","useMemo","z.object","zodResolver","i18next","useState","useState","MoreHorizontal","Trash2","TableRoot","useState","UsersIcon","NewContentType","RoleEditor","AppRoleEditor","__toESM","require_jsx_runtime","useQuery","queryKeys","useMutation","leaveDeletedSite","useQueryClient","withCsrf","goToSite","currentSite","adminApi","useNavigate","Link","useMe","linkOptions","X","SubmitButton","Page","PageHeader","useParams","StatusChip","EmptyState","ErrorState","Badge","useTranslation","createLucideIcon","formatRelativeTime","formatDateTime","useSearch","RowTitle","createLazyRoute","UnsavedChangesGuard","FormCheckboxGroup","toast","Info","instance","describeError","useValueFromSource","List","Form$3","Earth","Boxes","Button","Input","Label","SelectValue","SelectTrigger","SelectContent","SelectItem","ChevronDown","Select","CursorPager","FormError","Checkbox","Alert","ConfirmDialog","AlertDescription","InlineConfirm","Trash","FieldGroup","FieldSet","FieldLabel","FieldLegend","Field","Link$1","Ellipsis","Search","DropdownMenuItem","DropdownMenuSeparator","DropdownMenuTrigger","DropdownMenuContent","DropdownMenu","Plus","ScrollText","useDeleteAppRole","UserCheck","AUDIT_ACTOR_TYPES","Person","useCreateAppRole","useAppRoles","useAppRole","useUpdateAppRole","ShieldCheck","UserX","useRevokeInvitation","useUsers","useAuditEvents","UserPlus","useRemoveUser","useAuditLabels","useInviteUser","useSetUserStatus","useIssueInvitationLink","useUpdateUser","useInvitations","auditTargetName","Users$1","cn","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","SharedGlyph","useSharedDefinitions","useEverySiteModels","QueryView","FormRadioGroup","useNetworkPermission","slugify","Panel","useSchemaLock","LockNotice","FormTextareaField","FormSheet","FormSelectField","useRole","useUpdateRole","useCreateRole","useRoleNames","useDeleteRole","useRoles","SecretReveal","useConfirmTarget","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$2","options","roles","role","onSubmit","event","canManage","isDirty","AppRoleBindings","siteId","appRoles","DangerZone","navigate","deleteSite","renameSchema","useRenameSiteForm","updateSite","KEY_ID","KEY_HINT_ID","Details","Site","canManageRoles","MAX_KEY_LENGTH","deriveKey","name","createSiteSchema","EMPTY$2","useCreateSiteForm","createSite","getValues","setValue","key","open","created","onCreated","CreateSheet$2","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","detail","actionLabel","reference","targetName","targetLabel","AuditLog","setFilters","goFirst","goPrevious","goNext","MATRIX_RULES_BY_KIND","CHECKBOX_ACTIONS_BY_KIND","ACTION_LABEL_KEYS","ROLE_KINDS","ROLE_KEY_PATTERN","createRoleSchema","EMPTY$1","useCreateRoleForm","createRole","KIND_LABEL_KEYS$1","CreateSheet$1","Table$2","onDelete","Tabs","Roles","deleteRole","confirmDelete","createAppRoleSchema","EMPTY","useCreateAppRoleForm","createAppRole","CreateSheet","readsAllModels","permission","useGrantReadAll","updateAppRole","error","Actions","deleting","setDeleting","BUILT_IN_HOLDER_KEYS","builtInHolderKey","Table$1","holderKey","pendingRoleId","onGrantReadAll","AppRoles","deleteAppRole","grantReadAll","ACTION_COLUMN_KEYS","toMatrix","matrix","permissions","toPermissions","a","b","rules","grant","withGrant","row","setGranted","granted","updateGrant","current","canSetOwnOnly","canSetFields","fixedOptions","actionHasOptions","fixed","hasOptions","grants","unlistedGrants","listedKeys","modelId","setColumn","keys","next","columnState","fieldChoices","live","fields","field","choices","audience","liveIds","fieldId","fieldIds","candidate","SCOPE_ALL","SCOPE_SELECTED","FieldScope","selected","readOnly","defaultSelection","checkboxId","choice","checked","OwnOnly","Options","rowKey","base","Row$1","label","siteName","actions","onToggle","canExpand","expanded","optionsId","onToggleExpanded","Unlisted","onRemove","PermissionMatrix","setExpanded","toggleExpanded","rows","models","definition","showSites","isExpanded","APP_ROLE_MATRIX_RULES","detailsSchema$1","useAppRoleEditor","setMatrix","initial","permissionsDirty","detailsDirty","details","BUILT_IN_DESCRIPTION_KEYS","builtInDescriptionKey","Form$1","editor","explanation","breadcrumb","Editor$1","roleId","siteModels","loaded","siteCount","isContentGrant","isCheckboxGrant","kind","splitGrants","inMatrix","p","joinGrants","checkboxActions","detailsSchema","useRoleEditor","updateRole","initialPermissions","dirtyFields","KIND_LABEL_KEYS","CONTENT_HINT_KEYS","CHECKBOX_LEGEND_KEYS","Form","Editor","useInvitationLinkReveal","emailDelivery","issueLink","revealed","setRevealed","reveal","link","invitation","InvitationLink","expires","AssignmentBadges","siteNames","assignments","roleNames","Invitations","invitations","revoke","onCopyLink","siteValue","toAssignmentRows","bySite","ownerRoleId","toAssignments","assignmentRowsSchema","seen","context","index","nextAssignmentRow","used","siteIds","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","onDone","InviteSheet","onOpenChange","useAccessForm","updateUser","user","useIsOwner","AccessSheet","assignment","formatTokenNames","language","tokens","token","useAccountConfirmKindAndCopy","setKindState","shown","setShown","setKind","displayName","names","i18n","Row","editingAccess","setEditingAccess","confirm","isSelf","onToggleStatus","Table","users","currentUserId","networkLazyRoutes","me","setStatus","removeUser","inviting","setInviting","invitationLink","toggleStatus"],"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/helpers/deriveKey.ts","../../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/useCreateRoleForm.ts","../../src/features/Settings/Roles/CreateSheet/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/PermissionMatrix/constants.ts","../../src/features/Settings/Roles/PermissionMatrix/helpers/permissionMatrix.ts","../../src/features/Settings/Roles/PermissionMatrix/Options/FieldScope/index.tsx","../../src/features/Settings/Roles/PermissionMatrix/Options/OwnOnly/index.tsx","../../src/features/Settings/Roles/PermissionMatrix/Options/index.tsx","../../src/features/Settings/Roles/PermissionMatrix/Row/index.tsx","../../src/features/Settings/Roles/PermissionMatrix/Unlisted/index.tsx","../../src/features/Settings/Roles/PermissionMatrix/index.tsx","../../src/features/Settings/Roles/AppRoles/constants.ts","../../src/features/Settings/Roles/AppRoles/Editor/hooks/useAppRoleEditor.ts","../../src/features/Settings/Roles/AppRoles/Editor/index.tsx","../../src/features/Settings/Roles/Editor/helpers/roleGrants.ts","../../src/features/Settings/Roles/Editor/hooks/useRoleEditor.ts","../../src/features/Settings/Roles/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/helpers/tokenNames.ts","../../src/features/Users/hooks/useAccountConfirm.ts","../../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 /** Usable API tokens this admin created: refused while the account is disabled, revoked when it is deleted. */\n apiTokens: AdminUserApiToken[];\n};\n\n/** An API token listed with the admin who created it. */\nexport type AdminUserApiToken = { id: string; name: string; siteId: string | null };\n\nexport const CONTENT_ACTIONS = ['read', 'create', 'update', 'delete', 'publish', 'schemaManage'] as const;\nexport type ContentAction = (typeof CONTENT_ACTIONS)[number];\n\n/**\n * What a delivery role grants: `read`, and `readDrafts` (drafts mode: the token's site may read drafts with\n * `publicationState=draft`). `readDrafts` always covers every model and is never granted to admin roles.\n */\nexport const DELIVERY_ACTIONS = ['read', 'readDrafts'] as const;\nexport type DeliveryAction = (typeof DELIVERY_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 | DeliveryAction | 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 /** The creator's account is disabled: the token is refused until it is enabled again. */\n creatorDisabled: boolean;\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","import { slugify } from '@/fields/helpers/slugify';\n\nconst MAX_KEY_LENGTH = 63;\n\n/**\n * Suggests a site or role key for a name: lower-case words joined by hyphens, starting with a letter, at\n * most 63 characters (`Marketing team` → `marketing-team`). The form still validates it; this only proposes\n * a value the user can edit.\n */\nexport const deriveKey = (name: string): string =>\n slugify(name)\n .replace(/^[^a-z]+/, '')\n .slice(0, MAX_KEY_LENGTH)\n .replace(/-+$/, '');\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 { useCallback, useEffect } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\nimport { z } from 'zod';\nimport { useCreateSite } from '@/api/sites';\nimport { deriveKey } from '@/helpers/deriveKey';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\nimport { useValueFromSource } from '@/hooks/useValueFromSource';\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, getValues, setValue } = form;\n // The key follows the name until the user types one of their own, as a model's API ID follows its label.\n useValueFromSource(\n useWatch({ control: form.control, name: 'name' }),\n useCallback(() => getValues('key'), [getValues]),\n useCallback((key: string) => setValue('key', key, { shouldValidate: false }), [setValue]),\n deriveKey,\n );\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 {\n CONTENT_ACTIONS,\n GLOBAL_ACTIONS,\n type ContentAction,\n type PermissionAction,\n type RoleKind,\n} from '@shapio/client';\nimport type { MatrixRules } from './PermissionMatrix/helpers/permissionMatrix';\n\nexport { GLOBAL_ACTIONS };\n\n/**\n * The permission matrix per role kind. Admin roles: every content action per model, \"own entries\" (entries\n * the admin created) and field lists where they mean something. Delivery roles: read per model, with field\n * lists (tokens own no entries).\n */\nexport const MATRIX_RULES_BY_KIND: Record<RoleKind, MatrixRules<ContentAction>> = {\n admin: {\n actions: CONTENT_ACTIONS,\n ownOnlyActions: new Set<ContentAction>(['read', 'update', 'delete', 'publish']),\n fieldScopedActions: new Set<ContentAction>(['read', 'create', 'update']),\n },\n delivery: {\n actions: ['read'],\n ownOnlyActions: new Set<ContentAction>(),\n fieldScopedActions: new Set<ContentAction>(['read']),\n },\n};\n\n/** The every-model checkboxes per role kind: instance actions; read drafts (delivery roles only). */\nexport const CHECKBOX_ACTIONS_BY_KIND = {\n admin: GLOBAL_ACTIONS,\n delivery: ['readDrafts'],\n} as const satisfies Record<RoleKind, readonly PermissionAction[]>;\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 readDrafts: 'roles.actions.readDrafts',\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 { Role } from '@shapio/client';\nimport { useCallback, useEffect } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useCreateRole } from '@/api/roles';\nimport { i18next } from '@/app/i18n';\nimport { deriveKey } from '@/helpers/deriveKey';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\nimport { useValueFromSource } from '@/hooks/useValueFromSource';\nimport { ROLE_KEY_PATTERN } from '../constants';\n\nconst createRoleSchema = 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});\n\nexport type CreateRoleValues = z.infer<typeof createRoleSchema>;\n\nconst EMPTY: CreateRoleValues = { key: '', name: '', description: '', kind: 'admin' };\n\n/** Creates an admin or delivery role with no permissions; the caller opens its editor next. */\nexport const useCreateRoleForm = (open: boolean, onCreated: (role: Role) => void) => {\n const createRole = useCreateRole();\n const form = useForm<CreateRoleValues>({ resolver: zodResolver(createRoleSchema), defaultValues: EMPTY });\n const { reset, getValues, setValue } = form;\n // The key follows the name until the user types one of their own, as a model's API ID follows its label.\n useValueFromSource(\n useWatch({ control: form.control, name: 'name' }),\n useCallback(() => getValues('key'), [getValues]),\n useCallback((key: string) => setValue('key', key, { shouldValidate: false }), [setValue]),\n deriveKey,\n );\n useEffect(() => {\n if (open) {\n reset(EMPTY);\n }\n }, [open, reset]);\n const onSubmit = form.handleSubmit(async (values) => {\n const created = await settle(createRole.mutateAsync({ ...values, permissions: [] }));\n if (!created.ok) {\n return;\n }\n toast.success(i18next.t('roles.created'));\n onCreated(created.value);\n });\n return { form, onSubmit, createRole };\n};\n","import type { Role } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\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 { ROLE_KINDS } from '../constants';\nimport { useCreateRoleForm } from '../hooks/useCreateRoleForm';\n\ntype CreateSheetProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreated: (role: Role) => void;\n};\n\nconst KIND_LABEL_KEYS = { admin: 'roles.kindAdmin', delivery: 'roles.kindDelivery' } as const;\n\n/** A new admin or delivery role: name, key and kind; its permissions are set on its page next. */\nexport const CreateSheet = ({ open, onOpenChange, onCreated }: CreateSheetProps) => {\n const { t } = useTranslation();\n const { form, onSubmit, createRole } = useCreateRoleForm(open, onCreated);\n return (\n <FormSheet\n open={open}\n onOpenChange={onOpenChange}\n size=\"md\"\n title={t('roles.createTitle')}\n dirty={form.formState.isDirty}\n pending={createRole.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 <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 />\n <FormError error={createRole.error} />\n </FormSheet>\n );\n};\n","import type { Role } from '@shapio/client';\nimport { Link } from '@tanstack/react-router';\nimport { MoreHorizontal, SlidersHorizontal, 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[]; onDelete: (role: Role) => void };\n\nexport const Table = ({ roles, 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 asChild>\n <Link to=\"/network/roles/$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 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 asChild>\n <Link to=\"/network/roles/$roleId\" params={{ roleId: role.id }}>\n <SlidersHorizontal aria-hidden=\"true\" />\n {t('roles.editPermissions')}\n </Link>\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 { useNavigate } from '@tanstack/react-router';\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 { CreateSheet } from './CreateSheet';\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 navigate = useNavigate();\n const [creating, setCreating] = useState(false);\n return (\n <Page width=\"full\">\n <PageHeader\n title={t('roles.title')}\n tabs={<Tabs />}\n actions={\n <Button onClick={() => setCreating(true)}>\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) => <Table roles={data} onDelete={(role) => confirmDelete.ask(role)} />}\n </QueryView>\n <CreateSheet\n open={creating}\n onOpenChange={setCreating}\n onCreated={(role) => {\n setCreating(false);\n void navigate({ to: '/network/roles/$roleId', params: { roleId: role.id } });\n }}\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 { useCallback, useEffect } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useCreateAppRole } from '@/api/appRoles';\nimport { i18next } from '@/app/i18n';\nimport { deriveKey } from '@/helpers/deriveKey';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\nimport { useValueFromSource } from '@/hooks/useValueFromSource';\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, getValues, setValue } = form;\n // The key follows the name until the user types one of their own, as a model's API ID follows its label.\n useValueFromSource(\n useWatch({ control: form.control, name: 'name' }),\n useCallback(() => getValues('key'), [getValues]),\n useCallback((key: string) => setValue('key', key, { shouldValidate: false }), [setValue]),\n deriveKey,\n );\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('roles.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 everyone, and signed-in app users on top, 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 type { ContentAction } from '@shapio/client';\n\n/** The matrix row that grants on every model, including models created later (`modelId: null`). */\nexport const ALL_MODELS = '*';\n\n/** Column headings: short verbs. */\nexport const ACTION_COLUMN_KEYS = {\n read: 'roles.matrix.actions.read',\n create: 'roles.matrix.actions.create',\n update: 'roles.matrix.actions.update',\n delete: 'roles.matrix.actions.delete',\n publish: 'roles.matrix.actions.publish',\n schemaManage: 'roles.matrix.actions.schemaManage',\n} as const satisfies Record<ContentAction, string>;\n","import type { ContentAction, RoleCondition } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { ALL_MODELS } from '../constants';\n\n/** One grant in the API's shape, for the content actions a matrix edits. */\nexport type MatrixPermission<A extends ContentAction> = {\n action: A;\n modelId: string | null;\n condition: RoleCondition | null;\n fieldIds: string[] | null;\n};\n\n/**\n * Which actions a matrix shows (its columns, in order), which take \"only their own entries\" (a row\n * filter), and which take a field list (what the holder may see or write).\n */\nexport type MatrixRules<A extends ContentAction> = {\n actions: readonly A[];\n ownOnlyActions: ReadonlySet<A>;\n fieldScopedActions: ReadonlySet<A>;\n};\n\n/**\n * The permission matrix an 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 holder created. */\n ownOnly: boolean;\n /** `null` = every field the holder's audience may see; otherwise exactly these field IDs. */\n fieldIds: string[] | null;\n};\n\nexport type ModelGrants<A extends ContentAction> = Partial<Record<A, ActionGrant>>;\n\n/**\n * Whose field rules a matrix follows: admin roles see every field without a field list; app users and\n * delivery tokens only public ones (non-public fields only when a list names them).\n */\nexport type MatrixAudience = 'admin' | 'delivery';\n\n/** Keyed by model ID, or `ALL_MODELS`. */\nexport type PermissionMatrix<A extends ContentAction> = Readonly<Record<string, ModelGrants<A>>>;\n\nexport const toMatrix = <A extends ContentAction>(\n permissions: readonly MatrixPermission<A>[],\n): PermissionMatrix<A> => {\n const matrix: Record<string, ModelGrants<A>> = {};\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/**\n * Grants in a stable order (every-model row first, then by model ID and action), so dirty checks compare.\n * Options the rules don't let the editor change (a condition on create, a field list on the every-model\n * row) are kept as they were loaded: the matrix shows them read-only and never drops them.\n */\nexport const toPermissions = <A extends ContentAction>(\n matrix: PermissionMatrix<A>,\n rules: Pick<MatrixRules<A>, 'actions'>,\n): MatrixPermission<A>[] =>\n Object.keys(matrix)\n .sort((a, b) => (a === ALL_MODELS ? -1 : b === ALL_MODELS ? 1 : a.localeCompare(b)))\n .flatMap((key) =>\n rules.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 ? ('ownedByPrincipal' as const) : null,\n fieldIds: grant.fieldIds,\n },\n ];\n }),\n );\n\nconst withGrant = <A extends ContentAction>(\n matrix: PermissionMatrix<A>,\n key: string,\n action: A,\n grant: ActionGrant | undefined,\n): PermissionMatrix<A> => {\n const row: ModelGrants<A> = { ...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 = <A extends ContentAction>(\n matrix: PermissionMatrix<A>,\n key: string,\n action: A,\n granted: boolean,\n): PermissionMatrix<A> =>\n withGrant(\n matrix,\n key,\n action,\n granted ? (matrix[key]?.[action] ?? { ownOnly: false, fieldIds: null }) : undefined,\n );\n\nexport const updateGrant = <A extends ContentAction>(\n matrix: PermissionMatrix<A>,\n key: string,\n action: A,\n changes: Partial<ActionGrant>,\n): PermissionMatrix<A> => {\n const current = matrix[key]?.[action];\n return current ? withGrant(matrix, key, action, { ...current, ...changes }) : matrix;\n};\n\n/** Whether an action's \"own entries\" switch can be changed on this row. */\nexport const canSetOwnOnly = <A extends ContentAction>(action: A, rules: MatrixRules<A>): boolean =>\n rules.ownOnlyActions.has(action);\n\n/** Whether an action's field list can be changed on this row (model rows only: fields belong to a model). */\nexport const canSetFields = <A extends ContentAction>(\n key: string,\n action: A,\n rules: MatrixRules<A>,\n): boolean => key !== ALL_MODELS && rules.fieldScopedActions.has(action);\n\n/** Options a grant carries that this row can't change (loaded from the API), shown read-only. */\nexport const fixedOptions = <A extends ContentAction>(\n key: string,\n action: A,\n grant: ActionGrant,\n rules: MatrixRules<A>,\n): ActionGrant => ({\n ownOnly: grant.ownOnly && !canSetOwnOnly(action, rules),\n fieldIds: canSetFields(key, action, rules) ? null : grant.fieldIds,\n});\n\n/** Whether a granted action has options to set or to show on this row. */\nexport const actionHasOptions = <A extends ContentAction>(\n key: string,\n action: A,\n grant: ActionGrant,\n rules: MatrixRules<A>,\n): boolean => {\n const fixed = fixedOptions(key, action, grant, rules);\n return (\n canSetOwnOnly(action, rules) ||\n canSetFields(key, action, rules) ||\n fixed.ownOnly ||\n fixed.fieldIds !== null\n );\n};\n\n/** Whether a row has any granted action with options (own entries, fields on a model row, or fixed ones). */\nexport const hasOptions = <A extends ContentAction>(\n key: string,\n grants: ModelGrants<A> | undefined,\n rules: MatrixRules<A>,\n): boolean =>\n rules.actions.some((action) => {\n const grant = grants?.[action];\n return grant !== undefined && actionHasOptions(key, action, grant, rules);\n });\n\n/** Granted rows of the matrix whose model is not among `listedKeys` (deleted models): one entry per grant. */\nexport const unlistedGrants = <A extends ContentAction>(\n matrix: PermissionMatrix<A>,\n listedKeys: ReadonlySet<string>,\n rules: Pick<MatrixRules<A>, 'actions'>,\n): Array<{ modelId: string; action: A; grant: ActionGrant }> =>\n Object.keys(matrix)\n .filter((key) => key !== ALL_MODELS && !listedKeys.has(key))\n .sort()\n .flatMap((modelId) =>\n rules.actions.flatMap((action) => {\n const grant = matrix[modelId]?.[action];\n return grant ? [{ modelId, action, grant }] : [];\n }),\n );\n\n/** Grants or revokes one action on every given row (a column's header checkbox). Granted rows keep options. */\nexport const setColumn = <A extends ContentAction>(\n matrix: PermissionMatrix<A>,\n keys: readonly string[],\n action: A,\n granted: boolean,\n): PermissionMatrix<A> => 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 = <A extends ContentAction>(\n matrix: PermissionMatrix<A>,\n keys: readonly string[],\n action: A,\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\n/** One checkbox of a field list: a live field, or a ticked one the model no longer shows. */\nexport type FieldChoice = {\n id: string;\n /** Undefined for an ID that is not a field of the model. */\n label: string | undefined;\n note: 'notPublic' | 'deprecated' | 'unknown' | undefined;\n};\n\n/**\n * The checkboxes of a field list (live fields, then ticked deprecated or unknown IDs so they can be\n * cleared) and what \"only selected fields\" starts from: every live field the audience sees without a list.\n */\nexport const fieldChoices = (\n fields: readonly FieldDefinition[],\n fieldIds: readonly string[] | null,\n audience: MatrixAudience,\n): { choices: FieldChoice[]; defaultSelection: string[] } => {\n const live = fields.filter((field) => !field.deprecated);\n const choices: FieldChoice[] = live.map((field) => ({\n id: field.id,\n label: field.label,\n note: audience === 'delivery' && !field.public ? 'notPublic' : undefined,\n }));\n const liveIds = new Set(live.map((field) => field.id));\n for (const fieldId of fieldIds ?? []) {\n if (!liveIds.has(fieldId)) {\n const field = fields.find((candidate) => candidate.id === fieldId);\n choices.push({ id: fieldId, label: field?.label, note: field ? 'deprecated' : 'unknown' });\n }\n }\n const visible = audience === 'admin' ? live : live.filter((field) => field.public);\n return { choices, defaultSelection: visible.map((field) => field.id) };\n};\n","import 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 } from '@/components/ui/field';\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';\nimport { fieldChoices, type MatrixAudience } from '../../helpers/permissionMatrix';\n\ntype FieldScopeProps = {\n id: string;\n fields: readonly FieldDefinition[];\n /** `null`: every field the audience may see. */\n fieldIds: string[] | null;\n audience: MatrixAudience;\n readOnly: boolean;\n onChange: (fieldIds: string[] | null) => void;\n};\n\nconst SCOPE_ALL = 'all';\nconst SCOPE_SELECTED = 'selected';\n\n/**\n * Which fields one granted action covers: all of them (public ones only for app users and delivery tokens),\n * or the ones ticked. A ticked field the model no longer shows (deprecated, or gone) stays listed so it\n * can be cleared.\n */\nexport const FieldScope = ({ id, fields, fieldIds, audience, readOnly, onChange }: FieldScopeProps) => {\n const { t } = useTranslation();\n const { choices, defaultSelection } = fieldChoices(fields, fieldIds, audience);\n const selected = fieldIds ?? [];\n return (\n <>\n <RadioGroup\n aria-label={t('roles.matrix.fieldScope')}\n value={fieldIds === null ? SCOPE_ALL : SCOPE_SELECTED}\n disabled={readOnly}\n onValueChange={(value) => onChange(value === SCOPE_ALL ? null : defaultSelection)}\n >\n <Field orientation=\"horizontal\">\n <RadioGroupItem id={`${id}-all`} value={SCOPE_ALL} />\n <FieldLabel htmlFor={`${id}-all`} className=\"font-normal\">\n {audience === 'admin' ? t('roles.matrix.allFields') : t('roles.matrix.allPublicFields')}\n </FieldLabel>\n </Field>\n <Field orientation=\"horizontal\">\n <RadioGroupItem id={`${id}-selected`} value={SCOPE_SELECTED} />\n <FieldLabel htmlFor={`${id}-selected`} className=\"font-normal\">\n {t('roles.matrix.selectedFields')}\n </FieldLabel>\n </Field>\n </RadioGroup>\n {fieldIds === null ? null : (\n <div className=\"grid gap-2 pl-6 sm:grid-cols-2\">\n {choices.map((choice) => {\n const checkboxId = `${id}-field-${choice.id}`;\n return (\n <Field key={choice.id} orientation=\"horizontal\">\n <Checkbox\n id={checkboxId}\n checked={selected.includes(choice.id)}\n disabled={readOnly}\n onCheckedChange={(checked) =>\n onChange(\n checked === true\n ? [...selected, choice.id].sort()\n : selected.filter((fieldId) => fieldId !== choice.id),\n )\n }\n />\n <FieldLabel htmlFor={checkboxId} className=\"font-normal\">\n {choice.label ?? <span className=\"font-mono text-xs\">{choice.id}</span>}\n {choice.note === 'notPublic' ? (\n <Badge variant=\"secondary\">{t('roles.matrix.notPublic')}</Badge>\n ) : null}\n {choice.note === 'deprecated' ? (\n <Badge variant=\"secondary\">{t('roles.matrix.deprecatedField')}</Badge>\n ) : null}\n {choice.note === 'unknown' ? (\n <Badge variant=\"secondary\">{t('roles.matrix.unknownField')}</Badge>\n ) : null}\n </FieldLabel>\n </Field>\n );\n })}\n </div>\n )}\n </>\n );\n};\n","import { useTranslation } from 'react-i18next';\nimport { Field, FieldLabel } from '@/components/ui/field';\nimport { Switch } from '@/components/ui/switch';\n\ntype OwnOnlyProps = {\n id: string;\n checked: boolean;\n disabled: boolean;\n onCheckedChange: (checked: boolean) => void;\n};\n\n/** The \"only their own entries\" switch of one granted action. */\nexport const OwnOnly = ({ id, checked, disabled, onCheckedChange }: OwnOnlyProps) => {\n const { t } = useTranslation();\n return (\n <Field orientation=\"horizontal\">\n <FieldLabel htmlFor={id}>{t('roles.matrix.ownOnly')}</FieldLabel>\n <Switch id={id} checked={checked} disabled={disabled} onCheckedChange={onCheckedChange} />\n </Field>\n );\n};\n","import type { ContentAction } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { Field, FieldLegend, FieldSet } from '@/components/ui/field';\nimport { ACTION_COLUMN_KEYS } from '../constants';\nimport {\n actionHasOptions,\n canSetFields,\n canSetOwnOnly,\n fixedOptions,\n type ActionGrant,\n type MatrixAudience,\n type MatrixRules,\n type ModelGrants,\n} from '../helpers/permissionMatrix';\nimport { FieldScope } from './FieldScope';\nimport { OwnOnly } from './OwnOnly';\n\ntype OptionsProps<A extends ContentAction> = {\n id: string;\n rules: MatrixRules<A>;\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<A>;\n audience: MatrixAudience;\n readOnly: boolean;\n onChange: (action: A, changes: Partial<ActionGrant>) => void;\n};\n\n/**\n * Per granted action: \"only their own entries\" and, on a model, which fields it covers. Options the row\n * can't change (loaded from the API) are shown as they are.\n */\nexport const Options = <A extends ContentAction>({\n id,\n rules,\n rowKey,\n fields,\n grants,\n audience,\n readOnly,\n onChange,\n}: OptionsProps<A>) => {\n const { t } = useTranslation();\n return (\n <div\n id={id}\n className=\"sticky left-0 grid max-w-[100cqw] gap-6 border-t bg-muted/40 px-5 py-4 @3xl:grid-cols-2\"\n >\n {rules.actions.map((action) => {\n const grant = grants[action];\n if (!grant || !actionHasOptions(rowKey, action, grant, rules)) {\n return null;\n }\n const base = `${id}-${action}`;\n const fixed = fixedOptions(rowKey, action, grant, rules);\n return (\n <FieldSet key={action} className=\"gap-3\">\n <FieldLegend variant=\"label\">{t(ACTION_COLUMN_KEYS[action])}</FieldLegend>\n {canSetOwnOnly(action, rules) ? (\n <OwnOnly\n id={`${base}-own`}\n checked={grant.ownOnly}\n disabled={readOnly}\n onCheckedChange={(ownOnly) => onChange(action, { ownOnly })}\n />\n ) : null}\n {canSetFields(rowKey, action, rules) ? (\n <FieldScope\n id={base}\n fields={fields ?? []}\n fieldIds={grant.fieldIds}\n audience={audience}\n readOnly={readOnly}\n onChange={(fieldIds) => onChange(action, { fieldIds })}\n />\n ) : null}\n {fixed.ownOnly ? (\n <Field>\n <p className=\"text-meta text-muted-foreground\">{t('roles.matrix.fixedOwnOnly')}</p>\n </Field>\n ) : null}\n {fixed.fieldIds !== null ? (\n <Field>\n <p className=\"text-meta text-muted-foreground\">\n {t('roles.matrix.fixedFields', { fields: fixed.fieldIds.join(', ') || '–' })}\n </p>\n </Field>\n ) : null}\n </FieldSet>\n );\n })}\n </div>\n );\n};\n","import type { ContentAction } from '@shapio/client';\nimport { ChevronDown } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { SharedGlyph } from '@/components/SharedGlyph';\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 } from '../constants';\nimport type { ModelGrants } from '../helpers/permissionMatrix';\n\ntype RowProps<A extends ContentAction> = {\n /** The matrix's columns, in order. */\n actions: readonly A[];\n label: string;\n /** API key or a hint beside the label. */\n detail: string;\n /** Shared with all sites: a globe beside the label. */\n shared: boolean;\n /** The site a site's own model belongs to, when there are several sites. */\n siteName: string | undefined;\n readOnly: boolean;\n grants: ModelGrants<A>;\n optionsId: string;\n expanded: boolean;\n /** False when no granted action on this row has options. */\n canExpand: boolean;\n onToggle: (action: A, 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 = <A extends ContentAction>({\n actions,\n label,\n detail,\n shared,\n siteName,\n readOnly,\n grants,\n optionsId,\n expanded,\n canExpand,\n onToggle,\n onToggleExpanded,\n}: RowProps<A>) => {\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 {shared ? <SharedGlyph className=\"self-center\" /> : null}\n <span className=\"truncate text-xs text-muted-foreground\">\n {siteName ? `${siteName} · ${detail}` : detail}\n </span>\n </span>\n </TableCell>\n {actions.map((action) => (\n <TableCell key={action} className=\"h-9 py-0 text-center\">\n <Checkbox\n checked={grants[action] !== undefined}\n disabled={readOnly}\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('roles.matrix.options')}: ${label}`}\n onClick={onToggleExpanded}\n >\n {t('roles.matrix.options')}\n <ChevronDown aria-hidden=\"true\" className={cn('transition-transform', expanded && 'rotate-180')} />\n </Button>\n </TableCell>\n </TableRow>\n );\n};\n","import type { ContentAction } from '@shapio/client';\nimport { X } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { ACTION_COLUMN_KEYS } from '../constants';\nimport { unlistedGrants, type MatrixRules, type PermissionMatrix } from '../helpers/permissionMatrix';\n\ntype UnlistedProps<A extends ContentAction> = {\n matrix: PermissionMatrix<A>;\n /** The rows the table shows (the every-model row and every site's models). */\n listedKeys: ReadonlySet<string>;\n rules: MatrixRules<A>;\n readOnly: boolean;\n onRemove: (modelId: string, action: A) => void;\n};\n\n/**\n * Grants on models no site has any more (a deleted model keeps its grants), as stored: the server refuses\n * to save them, so each can be removed here.\n */\nexport const Unlisted = <A extends ContentAction>({\n matrix,\n listedKeys,\n rules,\n readOnly,\n onRemove,\n}: UnlistedProps<A>) => {\n const { t } = useTranslation();\n const grants = unlistedGrants(matrix, listedKeys, rules);\n if (grants.length === 0) {\n return null;\n }\n return (\n <section aria-labelledby=\"unlisted-grants-title\" className=\"space-y-3 border-t px-5 py-4\">\n <h3 id=\"unlisted-grants-title\" className=\"text-sm font-semibold\">\n {t('roles.matrix.unlistedTitle')}\n </h3>\n <ul className=\"space-y-2\">\n {grants.map(({ modelId, action, grant }) => {\n const actionLabel = t(ACTION_COLUMN_KEYS[action]);\n return (\n <li key={`${modelId}:${action}`} className=\"flex items-center justify-between gap-3\">\n <span className=\"min-w-0 text-sm\">\n <span className=\"font-semibold\">{actionLabel}</span>{' '}\n <span className=\"font-mono text-xs break-all text-muted-foreground\">{modelId}</span>\n {grant.ownOnly ? (\n <span className=\"block text-meta text-muted-foreground\">{t('roles.matrix.ownOnly')}</span>\n ) : null}\n {grant.fieldIds === null ? null : (\n <span className=\"block text-meta text-muted-foreground\">\n {t('roles.matrix.fixedFields', { fields: grant.fieldIds.join(', ') || '–' })}\n </span>\n )}\n </span>\n {readOnly ? null : (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n aria-label={t('roles.matrix.removeGrant', { action: actionLabel, model: modelId })}\n onClick={() => onRemove(modelId, action)}\n >\n <X aria-hidden=\"true\" />\n {t('common.remove')}\n </Button>\n )}\n </li>\n );\n })}\n </ul>\n </section>\n );\n};\n","import type { ContentAction } from '@shapio/client';\nimport { Fragment, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { SiteModel } from '@/api/schema';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';\nimport { ACTION_COLUMN_KEYS, ALL_MODELS } from './constants';\nimport {\n columnState,\n hasOptions,\n setColumn,\n setGranted,\n updateGrant,\n type MatrixAudience,\n type MatrixRules,\n type PermissionMatrix as Matrix,\n} from './helpers/permissionMatrix';\nimport { Options } from './Options';\nimport { Row } from './Row';\nimport { Unlisted } from './Unlisted';\n\ntype PermissionMatrixProps<A extends ContentAction> = {\n matrix: Matrix<A>;\n /** Every site's models (shared ones once). */\n models: readonly SiteModel[];\n /** Name each site's own models (more than one site). */\n showSites: boolean;\n rules: MatrixRules<A>;\n audience: MatrixAudience;\n /** Shown, not changed (built-in admin roles). */\n readOnly?: boolean;\n onChange: (matrix: Matrix<A>) => 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 * Grants on models no site has any more are listed under the table, to remove.\n */\nexport const PermissionMatrix = <A extends ContentAction>({\n matrix,\n models,\n showSites,\n rules,\n audience,\n readOnly = false,\n onChange,\n}: PermissionMatrixProps<A>) => {\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('roles.matrix.allModels'),\n detail: t('roles.matrix.allModelsHint'),\n shared: false,\n siteName: undefined,\n fields: undefined,\n },\n ...models.map(({ definition, site }) => ({\n key: definition.id,\n label: definition.label,\n detail: definition.apiKey,\n shared: site === null,\n siteName: showSites ? site?.name : undefined,\n fields: definition.fields,\n })),\n ];\n const keys = rows.map((row) => row.key);\n // The panel's width: options stay in view (sticky, as wide as the panel) when the table scrolls sideways.\n return (\n <div className=\"@container\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"sticky left-0 z-10 min-w-60 bg-muted\">{t('roles.matrix.model')}</TableHead>\n {rules.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 disabled={readOnly}\n onCheckedChange={(checked) =>\n onChange(setColumn(matrix, keys, action, checked === true))\n }\n aria-label={t('roles.matrix.everyRow', { action: label })}\n />\n {label}\n </span>\n </TableHead>\n );\n })}\n <TableHead className=\"bg-muted\">\n <span className=\"sr-only\">{t('roles.matrix.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, rules);\n const isExpanded = canExpand && expanded.has(row.key);\n const optionsId = `permission-options-${row.key === ALL_MODELS ? 'all' : row.key}`;\n return (\n <Fragment key={row.key}>\n <Row\n actions={rules.actions}\n label={row.label}\n detail={row.detail}\n shared={row.shared}\n siteName={row.siteName}\n readOnly={readOnly}\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 colSpan={rules.actions.length + 2} className=\"h-auto p-0 whitespace-normal\">\n <Options\n id={optionsId}\n rules={rules}\n rowKey={row.key}\n fields={row.fields}\n grants={grants}\n audience={audience}\n readOnly={readOnly}\n onChange={(action, changes) =>\n onChange(updateGrant(matrix, row.key, action, changes))\n }\n />\n </TableCell>\n </TableRow>\n ) : null}\n </Fragment>\n );\n })}\n </TableBody>\n </Table>\n <Unlisted\n matrix={matrix}\n listedKeys={new Set(keys)}\n rules={rules}\n readOnly={readOnly}\n onRemove={(modelId, action) => onChange(setGranted(matrix, modelId, action, false))}\n />\n </div>\n );\n};\n","import { APP_CONTENT_ACTIONS, type AppContentAction } from '@shapio/client';\nimport type { MatrixRules } from '../PermissionMatrix/helpers/permissionMatrix';\n\n/** What an app role's matrix edits: content actions; \"own entries\" and field lists where they mean something. */\nexport const APP_ROLE_MATRIX_RULES: MatrixRules<AppContentAction> = {\n actions: APP_CONTENT_ACTIONS,\n ownOnlyActions: new Set(['read', 'update', 'delete', 'publish']),\n fieldScopedActions: new Set(['read', 'create', 'update']),\n};\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { AppContentAction, 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 {\n toMatrix,\n toPermissions,\n type PermissionMatrix,\n} from '../../../PermissionMatrix/helpers/permissionMatrix';\nimport { APP_ROLE_MATRIX_RULES } from '../../constants';\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<AppContentAction>>(() => toMatrix(role.permissions));\n const initial = useMemo(\n () => JSON.stringify(toPermissions(toMatrix(role.permissions), APP_ROLE_MATRIX_RULES)),\n [role.permissions],\n );\n const permissions = useMemo(() => toPermissions(matrix, APP_ROLE_MATRIX_RULES), [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 { AppRole } from '@shapio/client';\nimport { linkOptions, useParams } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { useAppRole } from '@/api/appRoles';\nimport { useEverySiteModels, type SiteModel } 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 { PermissionMatrix } from '../../PermissionMatrix';\nimport { APP_ROLE_MATRIX_RULES } from '../constants';\nimport { useAppRoleEditor } from './hooks/useAppRoleEditor';\n\ntype FormProps = { role: AppRole; models: readonly SiteModel[]; showSites: boolean };\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, showSites }: 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 <PermissionMatrix\n matrix={editor.matrix}\n models={models}\n showSites={showSites}\n rules={APP_ROLE_MATRIX_RULES}\n audience=\"delivery\"\n onChange={editor.setMatrix}\n />\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 = useEverySiteModels();\n return (\n <Page width=\"full\">\n <QueryView query={role} loadingRows={6}>\n {(loaded) => (\n <QueryView query={models} loadingRows={6}>\n {({ models: siteModels, siteCount }) => (\n <Form\n key={`${loaded.id}:${loaded.version}`}\n role={loaded}\n models={siteModels}\n showSites={siteCount > 1}\n />\n )}\n </QueryView>\n )}\n </QueryView>\n </Page>\n );\n};\n","import {\n CONTENT_ACTIONS,\n type ContentAction,\n type PermissionAction,\n type RoleKind,\n type RolePermission,\n} from '@shapio/client';\nimport { CHECKBOX_ACTIONS_BY_KIND, MATRIX_RULES_BY_KIND } from '../../constants';\nimport {\n toMatrix,\n toPermissions,\n type MatrixPermission,\n type PermissionMatrix,\n} from '../../PermissionMatrix/helpers/permissionMatrix';\n\n/** A role's grants as its editor shows them. */\nexport type RoleGrants = {\n /** Content actions per model (or every model). */\n matrix: PermissionMatrix<ContentAction>;\n /** Every-model checkboxes: instance actions, or read drafts. */\n actions: PermissionAction[];\n /** Anything else, kept as loaded (the server allows nothing else today). */\n others: RolePermission[];\n};\n\nconst isContentGrant = (permission: RolePermission): permission is MatrixPermission<ContentAction> =>\n (CONTENT_ACTIONS as readonly string[]).includes(permission.action);\n\nconst isCheckboxGrant = (kind: RoleKind, permission: RolePermission) =>\n (CHECKBOX_ACTIONS_BY_KIND[kind] as readonly PermissionAction[]).includes(permission.action) &&\n permission.modelId === null &&\n permission.condition === null &&\n permission.fieldIds === null;\n\n/** Splits a role's grants into the matrix, the checkboxes, and the rest. Nothing is dropped. */\nexport const splitGrants = (kind: RoleKind, permissions: readonly RolePermission[]): RoleGrants => {\n const actions = MATRIX_RULES_BY_KIND[kind].actions;\n const inMatrix = permissions.filter(\n (permission): permission is MatrixPermission<ContentAction> =>\n isContentGrant(permission) && actions.includes(permission.action),\n );\n return {\n matrix: toMatrix(inMatrix),\n actions: permissions.filter((permission) => isCheckboxGrant(kind, permission)).map((p) => p.action),\n others: permissions.filter(\n (permission) =>\n !inMatrix.includes(permission as MatrixPermission<ContentAction>) &&\n !isCheckboxGrant(kind, permission),\n ),\n };\n};\n\n/** The full grant list to save: matrix grants in a stable order, then the checkboxes, then the rest. */\nexport const joinGrants = (kind: RoleKind, grants: RoleGrants): RolePermission[] => {\n const checkboxActions: readonly PermissionAction[] = CHECKBOX_ACTIONS_BY_KIND[kind];\n return [\n ...toPermissions(grants.matrix, MATRIX_RULES_BY_KIND[kind]),\n ...checkboxActions\n .filter((action) => grants.actions.includes(action))\n .map((action) => ({ action, modelId: null, condition: null, fieldIds: null })),\n ...grants.others,\n ];\n};\n","import { zodResolver } from '@hookform/resolvers/zod';\nimport type { ContentAction, PermissionAction, Role } from '@shapio/client';\nimport { useMemo, useState } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useUpdateRole } from '@/api/roles';\nimport { i18next } from '@/app/i18n';\nimport { settle } from '@/helpers/settle';\nimport { requiredText } from '@/helpers/validation';\nimport type { PermissionMatrix } from '../../PermissionMatrix/helpers/permissionMatrix';\nimport { joinGrants, splitGrants } from '../helpers/roleGrants';\n\nconst detailsSchema = z.object({\n name: requiredText(),\n description: z.string().trim(),\n actions: z.array(z.custom<PermissionAction>((value) => typeof value === 'string')),\n});\n\nexport type RoleDetails = z.infer<typeof detailsSchema>;\n\n/**\n * Editing one admin or delivery role: details and every-model checkboxes in a form, the permission matrix\n * in state. Saving sends only what changed, with the version the page loaded (a concurrent edit is a\n * VERSION_CONFLICT, not a silent overwrite). Every grant the role holds is shown somewhere, and sent back.\n */\nexport const useRoleEditor = (role: Role) => {\n const updateRole = useUpdateRole();\n const initial = useMemo(() => splitGrants(role.kind, role.permissions), [role.kind, role.permissions]);\n const form = useForm<RoleDetails>({\n resolver: zodResolver(detailsSchema),\n defaultValues: { name: role.name, description: role.description, actions: initial.actions },\n });\n const [matrix, setMatrix] = useState<PermissionMatrix<ContentAction>>(initial.matrix);\n const actions = useWatch({ control: form.control, name: 'actions' });\n const initialPermissions = useMemo(\n () => JSON.stringify(joinGrants(role.kind, initial)),\n [role.kind, initial],\n );\n const permissions = useMemo(\n () => joinGrants(role.kind, { matrix, actions, others: initial.others }),\n [role.kind, matrix, actions, initial.others],\n );\n const permissionsDirty = JSON.stringify(permissions) !== initialPermissions;\n const { dirtyFields } = form.formState;\n const detailsDirty = Boolean(dirtyFields.name ?? dirtyFields.description);\n\n const onSubmit = form.handleSubmit(async ({ name, description }) => {\n const saved = await settle(\n updateRole.mutateAsync({\n id: role.id,\n input: {\n expectedVersion: role.version,\n ...(detailsDirty ? { name, description } : {}),\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: updateRole.isPending,\n error: updateRole.error,\n };\n};\n","import type { Role } from '@shapio/client';\nimport { linkOptions, useParams } from '@tanstack/react-router';\nimport { Info } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useRole } from '@/api/roles';\nimport { useEverySiteModels, type SiteModel } from '@/api/schema';\nimport { FormCheckboxGroup } from '@/components/FormCheckboxGroup';\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 { Alert, AlertDescription } from '@/components/ui/alert';\nimport { Badge } from '@/components/ui/badge';\nimport { FieldGroup } from '@/components/ui/field';\nimport { UnsavedChangesGuard } from '@/components/UnsavedChangesGuard';\nimport { ACTION_LABEL_KEYS, CHECKBOX_ACTIONS_BY_KIND, MATRIX_RULES_BY_KIND } from '../constants';\nimport { PermissionMatrix } from '../PermissionMatrix';\nimport { useRoleEditor } from './hooks/useRoleEditor';\n\ntype FormProps = { role: Role; models: readonly SiteModel[]; showSites: boolean };\n\nconst KIND_LABEL_KEYS = { admin: 'roles.kindAdmin', delivery: 'roles.kindDelivery' } as const;\nconst CONTENT_HINT_KEYS = { admin: 'roles.contentHintAdmin', delivery: 'roles.contentHintDelivery' } as const;\nconst CHECKBOX_LEGEND_KEYS = { admin: 'roles.instancePermissions', delivery: 'roles.drafts' } as const;\n\nconst Form = ({ role, models, showSites }: FormProps) => {\n const { t } = useTranslation();\n const editor = useRoleEditor(role);\n const readOnly = role.isSystem;\n const breadcrumb = [{ label: t('roles.title'), link: linkOptions({ to: '/network/roles' }) }];\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={\n <Badge variant={role.isSystem ? 'secondary' : 'outline'}>\n {role.isSystem ? t('roles.builtIn') : t('roles.custom')}\n </Badge>\n }\n meta={`${t(KIND_LABEL_KEYS[role.kind])} · ${role.key}`}\n actions={\n readOnly ? null : (\n <SubmitButton pending={editor.pending} pendingLabel={t('common.saving')} disabled={!editor.dirty}>\n {t('common.saveChanges')}\n </SubmitButton>\n )\n }\n />\n {readOnly ? (\n <Alert variant=\"info\" role=\"note\">\n <Info aria-hidden=\"true\" />\n <AlertDescription>{t('roles.builtInReadOnly')}</AlertDescription>\n </Alert>\n ) : (\n <Panel title={t('roles.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.contentPermissions')} description={t(CONTENT_HINT_KEYS[role.kind])} flush>\n <PermissionMatrix\n matrix={editor.matrix}\n models={models}\n showSites={showSites}\n rules={MATRIX_RULES_BY_KIND[role.kind]}\n audience={role.kind === 'admin' ? 'admin' : 'delivery'}\n readOnly={readOnly}\n onChange={editor.setMatrix}\n />\n </Panel>\n <Panel>\n <FormCheckboxGroup\n control={editor.form.control}\n name=\"actions\"\n legend={t(CHECKBOX_LEGEND_KEYS[role.kind])}\n disabled={readOnly}\n options={CHECKBOX_ACTIONS_BY_KIND[role.kind].map((action) => ({\n value: action,\n label: t(ACTION_LABEL_KEYS[action]),\n ...(action === 'readDrafts' ? { hint: t('roles.actions.readDraftsHint') } : {}),\n }))}\n />\n </Panel>\n <FormError error={editor.error} />\n <UnsavedChangesGuard when={editor.dirty && !editor.pending} />\n </form>\n );\n};\n\n/** Network → Roles → one admin or delivery role: details, its permission matrix, and every-model actions. */\nexport const Editor = () => {\n const { roleId } = useParams({ from: '/app/network/roles/$roleId' });\n const role = useRole(roleId);\n const models = useEverySiteModels();\n return (\n <Page width=\"full\">\n <QueryView query={role} loadingRows={6}>\n {(loaded) => (\n <QueryView query={models} loadingRows={6}>\n {({ models: siteModels, siteCount }) => (\n <Form\n key={`${loaded.id}:${loaded.version}`}\n role={loaded}\n models={siteModels}\n showSites={siteCount > 1}\n />\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 { AdminUserApiToken } from '@shapio/client';\n\n/** The tokens' names as one quoted list in the UI language (\"“Build” and “Preview”\"). */\nexport const formatTokenNames = (tokens: readonly AdminUserApiToken[], language: string): string =>\n new Intl.ListFormat(language, { type: 'conjunction' }).format(tokens.map((token) => `“${token.name}”`));\n","import type { AdminUser } from '@shapio/client';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { formatTokenNames } from '../helpers/tokenNames';\n\n/** What the row's confirmation is asking about: removing the user, or disabling one who has API tokens. */\ntype ConfirmKind = 'remove' | 'disable';\n\ntype AccountConfirmCopy = { title: string; description: string; confirmLabel: string };\n\n/**\n * The row's one confirmation (remove, or disable when the person has API tokens) and its copy. Both name the\n * API tokens the person created, since disabling pauses them and removing revokes them.\n */\nexport const useAccountConfirmKindAndCopy = (user: AdminUser) => {\n const { t, i18n } = useTranslation();\n const [kind, setKindState] = useState<ConfirmKind | null>(null);\n // The copy of the last confirmation asked for, kept while the popover closes so it does not flicker.\n const [shown, setShown] = useState<ConfirmKind>('remove');\n const setKind = (next: ConfirmKind | null) => {\n if (next) {\n setShown(next);\n }\n setKindState(next);\n };\n const displayName = user.name || user.email;\n const tokens = user.apiTokens;\n const names = formatTokenNames(tokens, i18n.language);\n const copy: Record<ConfirmKind, AccountConfirmCopy> = {\n remove: {\n title: t('users.removeTitle', { name: displayName }),\n description:\n tokens.length > 0\n ? t('users.removeDescriptionWithTokens', { count: tokens.length, names })\n : t('users.removeDescription'),\n confirmLabel: t('common.remove'),\n },\n disable: {\n title: t('users.disableTitle', { name: displayName }),\n description: t('users.disableDescriptionWithTokens', { count: tokens.length, names }),\n confirmLabel: t('users.disable'),\n },\n };\n return {\n kind,\n setKind,\n copy: copy[shown],\n /** Disabling pauses the person's API tokens, so it is confirmed only when they have some. */\n disableNeedsConfirm: user.status === 'active' && tokens.length > 0,\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 { settle } from '@/helpers/settle';\nimport { AccessSheet } from '../../AccessSheet';\nimport { AssignmentBadges } from '../../AssignmentBadges';\nimport { useAccountConfirmKindAndCopy } from '../../hooks/useAccountConfirm';\nimport { Person } from '../../Person';\n\ntype RowProps = {\n user: AdminUser;\n roleNames: ReadonlyMap<string, string>;\n siteNames: ReadonlyMap<string, string>;\n isSelf: boolean;\n /** Resolves once the status is changed (a confirmation waits for it). */\n onToggleStatus: (user: AdminUser) => Promise<unknown>;\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: for removing, and for disabling someone whose API tokens would stop working.\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 confirm = useAccountConfirmKindAndCopy(user);\n const displayName = user.name || user.email;\n const toggleStatus = () => {\n if (confirm.disableNeedsConfirm) {\n confirm.setKind('disable');\n return;\n }\n // A failure is reported by the mutation cache.\n void settle(onToggleStatus(user));\n };\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={confirm.kind !== null}\n onOpenChange={(open) => !open && confirm.setKind(null)}\n title={confirm.copy.title}\n description={confirm.copy.description}\n confirmLabel={confirm.copy.confirmLabel}\n onConfirm={() => (confirm.kind === 'disable' ? onToggleStatus(user) : 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) => (confirm.kind !== null || editingAccess) && event.preventDefault()}\n >\n <DropdownMenuItem onSelect={() => setEditingAccess(true)}>\n <ShieldCheck aria-hidden=\"true\" />\n {t('users.editAccess')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={toggleStatus}>\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={() => confirm.setKind('remove')}>\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) => Promise<unknown>;\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 toggleStatus = async (user: AdminUser) => {\n await setStatus.mutateAsync({ id: user.id, status: user.status === 'active' ? 'disabled' : 'active' });\n toast.success(t('users.statusChanged'));\n };\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={toggleStatus}\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 { Editor as RoleEditor } from '@/features/Settings/Roles/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 role: createLazyRoute('/app/network/roles/$roleId')({ component: RoleEditor }),\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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"}