@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.
- package/dist/admin/assets/{AssetTile-BrMzsUZD.js → AssetTile-DecaDqjj.js} +2 -2
- package/dist/admin/assets/{AssetTile-BrMzsUZD.js.map → AssetTile-DecaDqjj.js.map} +1 -1
- package/dist/admin/assets/AssistError-rslPtgWB.js +2 -0
- package/dist/admin/assets/{AssistError-Cs-r9Ssc.js.map → AssistError-rslPtgWB.js.map} +1 -1
- package/dist/admin/assets/{BlockMenuItems-DsccXMc_.js → BlockMenuItems-JHFue7Qt.js} +2 -2
- package/dist/admin/assets/{BlockMenuItems-DsccXMc_.js.map → BlockMenuItems-JHFue7Qt.js.map} +1 -1
- package/dist/admin/assets/Body-7NgJl9Pi.js +2 -0
- package/dist/admin/assets/Body-7NgJl9Pi.js.map +1 -0
- package/dist/admin/assets/Builder-DmlYcgiP.js +2 -0
- package/dist/admin/assets/Builder-DmlYcgiP.js.map +1 -0
- package/dist/admin/assets/{CodeEditor-CBCR73Wd.js → CodeEditor-Dv1FtkvI.js} +2 -2
- package/dist/admin/assets/{CodeEditor-CBCR73Wd.js.map → CodeEditor-Dv1FtkvI.js.map} +1 -1
- package/dist/admin/assets/{CopyButton-CxFsBHfF.js → CopyButton-Brnpfqe0.js} +2 -2
- package/dist/admin/assets/{CopyButton-CxFsBHfF.js.map → CopyButton-Brnpfqe0.js.map} +1 -1
- package/dist/admin/assets/{CursorPager-BW2U3v6l.js → CursorPager-C7cAK5Qe.js} +2 -2
- package/dist/admin/assets/{CursorPager-BW2U3v6l.js.map → CursorPager-C7cAK5Qe.js.map} +1 -1
- package/dist/admin/assets/{ExternalLink-BITMgS1K.js → ExternalLink-D80sb5Jj.js} +2 -2
- package/dist/admin/assets/{ExternalLink-BITMgS1K.js.map → ExternalLink-D80sb5Jj.js.map} +1 -1
- package/dist/admin/assets/{FocalPoint-CpZTve1E.js → FocalPoint-Bhtb1gUa.js} +2 -2
- package/dist/admin/assets/{FocalPoint-CpZTve1E.js.map → FocalPoint-Bhtb1gUa.js.map} +1 -1
- package/dist/admin/assets/Form-Cf1ephPH.js +2 -0
- package/dist/admin/assets/Form-Cf1ephPH.js.map +1 -0
- package/dist/admin/assets/FormCheckboxGroup-BzVZFR3W.js +2 -0
- package/dist/admin/assets/FormCheckboxGroup-BzVZFR3W.js.map +1 -0
- package/dist/admin/assets/{FormRadioGroup-Cfx5pvzU.js → FormRadioGroup-BzmLzRnI.js} +2 -2
- package/dist/admin/assets/{FormRadioGroup-Cfx5pvzU.js.map → FormRadioGroup-BzmLzRnI.js.map} +1 -1
- package/dist/admin/assets/FormSelectField-Cl7EjXc3.js +2 -0
- package/dist/admin/assets/FormSelectField-Cl7EjXc3.js.map +1 -0
- package/dist/admin/assets/FormSheet-CLZpd_7B.js +2 -0
- package/dist/admin/assets/FormSheet-CLZpd_7B.js.map +1 -0
- package/dist/admin/assets/{FormSwitchField-BLOh7qei.js → FormSwitchField-BbqQ3tx_.js} +2 -2
- package/dist/admin/assets/{FormSwitchField-BLOh7qei.js.map → FormSwitchField-BbqQ3tx_.js.map} +1 -1
- package/dist/admin/assets/{FormTextareaField-CO115n_u.js → FormTextareaField-9RN5Pt3B.js} +2 -2
- package/dist/admin/assets/{FormTextareaField-CO115n_u.js.map → FormTextareaField-9RN5Pt3B.js.map} +1 -1
- package/dist/admin/assets/{HintedLabel-DzHnEdIK.js → HintedLabel-D9IVF0EE.js} +2 -2
- package/dist/admin/assets/{HintedLabel-DzHnEdIK.js.map → HintedLabel-D9IVF0EE.js.map} +1 -1
- package/dist/admin/assets/{InfoHint-CSEtcHjL.js → InfoHint-tlSeZB9U.js} +2 -2
- package/dist/admin/assets/{InfoHint-CSEtcHjL.js.map → InfoHint-tlSeZB9U.js.map} +1 -1
- package/dist/admin/assets/{InlineConfirm-yW-iUKFC.js → InlineConfirm-Kj9AOIFO.js} +2 -2
- package/dist/admin/assets/{InlineConfirm-yW-iUKFC.js.map → InlineConfirm-Kj9AOIFO.js.map} +1 -1
- package/dist/admin/assets/{InsertMenuItem-CCr9e0qY.js → InsertMenuItem-CHAp2tH7.js} +2 -2
- package/dist/admin/assets/{InsertMenuItem-CCr9e0qY.js.map → InsertMenuItem-CHAp2tH7.js.map} +1 -1
- package/dist/admin/assets/{LinkTabs-8SmS1vCd.js → LinkTabs-oQXsy1I3.js} +2 -2
- package/dist/admin/assets/{LinkTabs-8SmS1vCd.js.map → LinkTabs-oQXsy1I3.js.map} +1 -1
- package/dist/admin/assets/{Match-CcD9KxHH.js → Match-BfNRwPfR.js} +2 -2
- package/dist/admin/assets/{Match-CcD9KxHH.js.map → Match-BfNRwPfR.js.map} +1 -1
- package/dist/admin/assets/{NoAccess-C8RLPN0I.js → NoAccess-DnEpYj9l.js} +2 -2
- package/dist/admin/assets/{NoAccess-C8RLPN0I.js.map → NoAccess-DnEpYj9l.js.map} +1 -1
- package/dist/admin/assets/Panel-Bcl09TtM.js.map +1 -1
- package/dist/admin/assets/{QueryView-xMP_uJ_t.js → QueryView-B86NcRt5.js} +2 -2
- package/dist/admin/assets/{QueryView-xMP_uJ_t.js.map → QueryView-B86NcRt5.js.map} +1 -1
- package/dist/admin/assets/{RadioTile-DQFmni5A.js → RadioTile-Bwd2Pmlk.js} +2 -2
- package/dist/admin/assets/RadioTile-Bwd2Pmlk.js.map +1 -0
- package/dist/admin/assets/{RichTextField-CVHRIbnu.js → RichTextField-Dou79MHF.js} +4 -4
- package/dist/admin/assets/RichTextField-Dou79MHF.js.map +1 -0
- package/dist/admin/assets/{RowTitle-Bqt6evG9.js → RowTitle-DH9OZs3g.js} +2 -2
- package/dist/admin/assets/{RowTitle-Bqt6evG9.js.map → RowTitle-DH9OZs3g.js.map} +1 -1
- package/dist/admin/assets/{SecretReveal-Bm6nYg5J.js → SecretReveal-D95oACLj.js} +2 -2
- package/dist/admin/assets/{SecretReveal-Bm6nYg5J.js.map → SecretReveal-D95oACLj.js.map} +1 -1
- package/dist/admin/assets/{SharedGlyph-cUmTh0_C.js → SharedGlyph-Chwb1EIS.js} +2 -2
- package/dist/admin/assets/{SharedGlyph-cUmTh0_C.js.map → SharedGlyph-Chwb1EIS.js.map} +1 -1
- package/dist/admin/assets/StepList-D9iHsUZJ.js +2 -0
- package/dist/admin/assets/StepList-D9iHsUZJ.js.map +1 -0
- package/dist/admin/assets/Structure-CewJL1b3.js +2 -0
- package/dist/admin/assets/{Structure-D8csgrIt.js.map → Structure-CewJL1b3.js.map} +1 -1
- package/dist/admin/assets/{SubNavLink-CiCaVV8U.js → SubNavLink-7Cs1LqMv.js} +2 -2
- package/dist/admin/assets/SubNavLink-7Cs1LqMv.js.map +1 -0
- package/dist/admin/assets/{SuggestAltButton-CvIoirnz.js → SuggestAltButton-BK1uo4yC.js} +2 -2
- package/dist/admin/assets/{SuggestAltButton-CvIoirnz.js.map → SuggestAltButton-BK1uo4yC.js.map} +1 -1
- package/dist/admin/assets/{TextLink-HRn66VL1.js → TextLink-Dfs5wsc5.js} +2 -2
- package/dist/admin/assets/{TextLink-HRn66VL1.js.map → TextLink-Dfs5wsc5.js.map} +1 -1
- package/dist/admin/assets/{Thumbnail-DNj5TRBI.js → Thumbnail-C2A_Ub77.js} +2 -2
- package/dist/admin/assets/{Thumbnail-DNj5TRBI.js.map → Thumbnail-C2A_Ub77.js.map} +1 -1
- package/dist/admin/assets/Trans-CPoNNUK1.js +2 -0
- package/dist/admin/assets/Trans-CPoNNUK1.js.map +1 -0
- package/dist/admin/assets/{UnsavedChangesGuard-CUiuMklN.js → UnsavedChangesGuard-BsEyn9oH.js} +2 -2
- package/dist/admin/assets/{UnsavedChangesGuard-CUiuMklN.js.map → UnsavedChangesGuard-BsEyn9oH.js.map} +1 -1
- package/dist/admin/assets/{UserAvatar-p-jV-LoD.js → UserAvatar-CgGKOFfP.js} +2 -2
- package/dist/admin/assets/{UserAvatar-p-jV-LoD.js.map → UserAvatar-CgGKOFfP.js.map} +1 -1
- package/dist/admin/assets/auth-BFSvtV59.js +2 -0
- package/dist/admin/assets/{auth-CQO4MBUj.js.map → auth-BFSvtV59.js.map} +1 -1
- package/dist/admin/assets/{badge-CqKF1pwz.js → badge-DGqA_yr_.js} +2 -2
- package/dist/admin/assets/{badge-CqKF1pwz.js.map → badge-DGqA_yr_.js.map} +1 -1
- package/dist/admin/assets/baseExtensions-TVKN1UwW.js.map +1 -1
- package/dist/admin/assets/{boxes-CAygw8zF.js → boxes-_5klpWNM.js} +2 -2
- package/dist/admin/assets/{boxes-CAygw8zF.js.map → boxes-_5klpWNM.js.map} +1 -1
- package/dist/admin/assets/{calendar-clock-BZGtAvWR.js → calendar-clock-VXok22Xj.js} +2 -2
- package/dist/admin/assets/{calendar-clock-BZGtAvWR.js.map → calendar-clock-VXok22Xj.js.map} +1 -1
- package/dist/admin/assets/changeSets-B6HxCJ4A.js +2 -0
- package/dist/admin/assets/{changeSets-8EburmT0.js.map → changeSets-B6HxCJ4A.js.map} +1 -1
- package/dist/admin/assets/chevron-left-CkRxDtvO.js +2 -0
- package/dist/admin/assets/{chevron-left-DGU3HGYG.js.map → chevron-left-CkRxDtvO.js.map} +1 -1
- package/dist/admin/assets/{circle-check-C37MSJqX.js → circle-check-DtDq7QMo.js} +2 -2
- package/dist/admin/assets/{circle-check-C37MSJqX.js.map → circle-check-DtDq7QMo.js.map} +1 -1
- package/dist/admin/assets/{clock-2arjsgZ4.js → clock-BtvZR9KD.js} +2 -2
- package/dist/admin/assets/{clock-2arjsgZ4.js.map → clock-BtvZR9KD.js.map} +1 -1
- package/dist/admin/assets/cn-DVhJ55Mo.js.map +1 -1
- package/dist/admin/assets/{constants-a_15vqOh.js → constants-DY3YJAKH.js} +2 -2
- package/dist/admin/assets/{constants-a_15vqOh.js.map → constants-DY3YJAKH.js.map} +1 -1
- package/dist/admin/assets/content-BNZF26Ve.js +3 -0
- package/dist/admin/assets/content-BNZF26Ve.js.map +1 -0
- package/dist/admin/assets/{contentCounts-DP7YYeZZ.js → contentCounts-BzC7IQqP.js} +2 -2
- package/dist/admin/assets/{contentCounts-DP7YYeZZ.js.map → contentCounts-BzC7IQqP.js.map} +1 -1
- package/dist/admin/assets/{contentTypes-84uc0bjR.js → contentTypes-Bz2xpqGf.js} +2 -2
- package/dist/admin/assets/{contentTypes-84uc0bjR.js.map → contentTypes-Bz2xpqGf.js.map} +1 -1
- package/dist/admin/assets/{context-IKYdzQJ-.js → context-CEVKblBl.js} +2 -2
- package/dist/admin/assets/{context-IKYdzQJ-.js.map → context-CEVKblBl.js.map} +1 -1
- package/dist/admin/assets/{copy-CsSRHgKZ.js → copy-B7vIq8DS.js} +2 -2
- package/dist/admin/assets/{copy-CsSRHgKZ.js.map → copy-B7vIq8DS.js.map} +1 -1
- package/dist/admin/assets/createLucideIcon-BOsNKleB.js +2 -0
- package/dist/admin/assets/createLucideIcon-BOsNKleB.js.map +1 -0
- package/dist/admin/assets/develop-D6CtwuYj.js +11 -0
- package/dist/admin/assets/develop-D6CtwuYj.js.map +1 -0
- package/dist/admin/assets/{dropdown-menu-_xfaEp5C.js → dropdown-menu-Bz7CLcRK.js} +2 -2
- package/dist/admin/assets/{dropdown-menu-_xfaEp5C.js.map → dropdown-menu-Bz7CLcRK.js.map} +1 -1
- package/dist/admin/assets/{ellipsis-F91991on.js → ellipsis-Ci0rsbCJ.js} +2 -2
- package/dist/admin/assets/{ellipsis-F91991on.js.map → ellipsis-Ci0rsbCJ.js.map} +1 -1
- package/dist/admin/assets/{entryLink-CVB-TdIn.js → entryLink-B0hSb_dN.js} +2 -2
- package/dist/admin/assets/{entryLink-CVB-TdIn.js.map → entryLink-B0hSb_dN.js.map} +1 -1
- package/dist/admin/assets/es2015-Cv57ynE1.js +42 -0
- package/dist/admin/assets/es2015-Cv57ynE1.js.map +1 -0
- package/dist/admin/assets/{external-link-CdG6kHfA.js → external-link-Bs9YRzvY.js} +2 -2
- package/dist/admin/assets/{external-link-CdG6kHfA.js.map → external-link-Bs9YRzvY.js.map} +1 -1
- package/dist/admin/assets/{field-COOzRptX.js → field-D-xWW2E7.js} +2 -2
- package/dist/admin/assets/{field-COOzRptX.js.map → field-D-xWW2E7.js.map} +1 -1
- package/dist/admin/assets/{file-stack-28ZtO1xW.js → file-stack-X4OGmkLA.js} +2 -2
- package/dist/admin/assets/{file-stack-28ZtO1xW.js.map → file-stack-X4OGmkLA.js.map} +1 -1
- package/dist/admin/assets/{fileRoute-s7mCMYUJ.js → fileRoute-DMal-zYL.js} +2 -2
- package/dist/admin/assets/{fileRoute-s7mCMYUJ.js.map → fileRoute-DMal-zYL.js.map} +1 -1
- package/dist/admin/assets/{folder-plus-DIk0pWkP.js → folder-plus-De2GNvry.js} +2 -2
- package/dist/admin/assets/{folder-plus-DIk0pWkP.js.map → folder-plus-De2GNvry.js.map} +1 -1
- package/dist/admin/assets/followPlural-CsgeALTW.js +2 -0
- package/dist/admin/assets/followPlural-CsgeALTW.js.map +1 -0
- package/dist/admin/assets/{globe-DFr3Gd2w.js → globe-DBw84s8Z.js} +2 -2
- package/dist/admin/assets/{globe-DFr3Gd2w.js.map → globe-DBw84s8Z.js.map} +1 -1
- package/dist/admin/assets/{image-DT79QFa_.js → image-CX4mT-_R.js} +2 -2
- package/dist/admin/assets/{image-DT79QFa_.js.map → image-CX4mT-_R.js.map} +1 -1
- package/dist/admin/assets/{image-off-DFs5upyX.js → image-off-CVaH_qKf.js} +2 -2
- package/dist/admin/assets/{image-off-DFs5upyX.js.map → image-off-CVaH_qKf.js.map} +1 -1
- package/dist/admin/assets/inbox-C0PVc6UI.js +2 -0
- package/dist/admin/assets/inbox-C0PVc6UI.js.map +1 -0
- package/dist/admin/assets/{inbox-CySnQydm.js → inbox-D9SmWt5L.js} +2 -2
- package/dist/admin/assets/{inbox-CySnQydm.js.map → inbox-D9SmWt5L.js.map} +1 -1
- package/dist/admin/assets/index-BqtCXB0u.js +4 -0
- package/dist/admin/assets/index-BqtCXB0u.js.map +1 -0
- package/dist/admin/assets/index-DZsQq6fY.css +2 -0
- package/dist/admin/assets/{key-round-D36CePnN.js → key-round-C8sd9CLN.js} +2 -2
- package/dist/admin/assets/{key-round-D36CePnN.js.map → key-round-C8sd9CLN.js.map} +1 -1
- package/dist/admin/assets/{labels-DQckbLGW.js → labels-BtktCNGw.js} +2 -2
- package/dist/admin/assets/{labels-DQckbLGW.js.map → labels-BtktCNGw.js.map} +1 -1
- package/dist/admin/assets/{languages-CzbTaQv9.js → languages-DLjdz6gb.js} +2 -2
- package/dist/admin/assets/{languages-CzbTaQv9.js.map → languages-DLjdz6gb.js.map} +1 -1
- package/dist/admin/assets/{layers-BmcodiaH.js → layers-swLuw-3a.js} +2 -2
- package/dist/admin/assets/{layers-BmcodiaH.js.map → layers-swLuw-3a.js.map} +1 -1
- package/dist/admin/assets/{link-2-off-CoJNwrxm.js → link-2-off-CEsI5T8h.js} +2 -2
- package/dist/admin/assets/{link-2-off-CoJNwrxm.js.map → link-2-off-CEsI5T8h.js.map} +1 -1
- package/dist/admin/assets/{link-Pyr2Y35S.js → link-C98FG_p5.js} +2 -2
- package/dist/admin/assets/{link-Pyr2Y35S.js.map → link-C98FG_p5.js.map} +1 -1
- package/dist/admin/assets/locales-CkuC7TJ1.js +2 -0
- package/dist/admin/assets/{locales-Bg3htKo8.js.map → locales-CkuC7TJ1.js.map} +1 -1
- package/dist/admin/assets/media-CbGSd_Mw.js +2 -0
- package/dist/admin/assets/{media-BCnVhaDH.js.map → media-CbGSd_Mw.js.map} +1 -1
- package/dist/admin/assets/{media-CURizGns.js → media-CeZGDGh7.js} +2 -2
- package/dist/admin/assets/{media-CURizGns.js.map → media-CeZGDGh7.js.map} +1 -1
- package/dist/admin/assets/network-BflLSKFO.js +2 -0
- package/dist/admin/assets/network-BflLSKFO.js.map +1 -0
- package/dist/admin/assets/{plus-BoDtdLCo.js → plus-cr9ZfO6j.js} +2 -2
- package/dist/admin/assets/{plus-BoDtdLCo.js.map → plus-cr9ZfO6j.js.map} +1 -1
- package/dist/admin/assets/publishing-BkxBplUZ.js +2 -0
- package/dist/admin/assets/publishing-BkxBplUZ.js.map +1 -0
- package/dist/admin/assets/{radio-group-4ok5evXq.js → radio-group-CRuWQnuV.js} +2 -2
- package/dist/admin/assets/{radio-group-4ok5evXq.js.map → radio-group-CRuWQnuV.js.map} +1 -1
- package/dist/admin/assets/{rotate-ccw-DL6TzcZh.js → rotate-ccw-BP8Ba-mY.js} +2 -2
- package/dist/admin/assets/{rotate-ccw-DL6TzcZh.js.map → rotate-ccw-BP8Ba-mY.js.map} +1 -1
- package/dist/admin/assets/schedules-BIyBlsYZ.js +2 -0
- package/dist/admin/assets/{schedules-BmB9Y73z.js.map → schedules-BIyBlsYZ.js.map} +1 -1
- package/dist/admin/assets/schema-6eUoC8fJ.js +2 -0
- package/dist/admin/assets/schema-6eUoC8fJ.js.map +1 -0
- package/dist/admin/assets/{scroll-text-PqeZm472.js → scroll-text-B5vfi9fD.js} +2 -2
- package/dist/admin/assets/{scroll-text-PqeZm472.js.map → scroll-text-B5vfi9fD.js.map} +1 -1
- package/dist/admin/assets/{search-BdwIwOzC.js → search-wj7zbkx1.js} +2 -2
- package/dist/admin/assets/{search-BdwIwOzC.js.map → search-wj7zbkx1.js.map} +1 -1
- package/dist/admin/assets/{searchSchemas-CSScloG8.js → searchSchemas-DAnwh3I3.js} +2 -2
- package/dist/admin/assets/{searchSchemas-CSScloG8.js.map → searchSchemas-DAnwh3I3.js.map} +1 -1
- package/dist/admin/assets/{sections-DqBzSKMP.js → sections-CWL-XD6m.js} +2 -2
- package/dist/admin/assets/sections-CWL-XD6m.js.map +1 -0
- package/dist/admin/assets/{sections-BTS683ur.js → sections-DBQpB0uv.js} +2 -2
- package/dist/admin/assets/{sections-BTS683ur.js.map → sections-DBQpB0uv.js.map} +1 -1
- package/dist/admin/assets/{select-C0USI-Ox.js → select-DVrPV1b3.js} +2 -2
- package/dist/admin/assets/{select-C0USI-Ox.js.map → select-DVrPV1b3.js.map} +1 -1
- package/dist/admin/assets/{send-XPWo3m4u.js → send-CzFdgUc_.js} +2 -2
- package/dist/admin/assets/{send-XPWo3m4u.js.map → send-CzFdgUc_.js.map} +1 -1
- package/dist/admin/assets/seo-Bd0sWQMo.js +2 -0
- package/dist/admin/assets/{seo-CceGYTIX.js.map → seo-Bd0sWQMo.js.map} +1 -1
- package/dist/admin/assets/settings-CqnrPmzR.js +2 -0
- package/dist/admin/assets/{settings-B60vHpZd.js.map → settings-CqnrPmzR.js.map} +1 -1
- package/dist/admin/assets/shapes-ZAkMBB-Z.js +6 -0
- package/dist/admin/assets/shapes-ZAkMBB-Z.js.map +1 -0
- package/dist/admin/assets/{skeleton-B5MP72Kw.js → skeleton-CiX26LnL.js} +2 -2
- package/dist/admin/assets/{skeleton-B5MP72Kw.js.map → skeleton-CiX26LnL.js.map} +1 -1
- package/dist/admin/assets/{snapshots-DUI2t-qF.js → snapshots-DbFQNJgN.js} +2 -2
- package/dist/admin/assets/{snapshots-DUI2t-qF.js.map → snapshots-DbFQNJgN.js.map} +1 -1
- package/dist/admin/assets/{sparkles-CvT-jxrW.js → sparkles-D_kmZJVd.js} +2 -2
- package/dist/admin/assets/{sparkles-CvT-jxrW.js.map → sparkles-D_kmZJVd.js.map} +1 -1
- package/dist/admin/assets/src-CMor9izq.js +7 -0
- package/dist/admin/assets/src-CMor9izq.js.map +1 -0
- package/dist/admin/assets/{stableId-BrtQedPy.js → stableId-g1uxJGSz.js} +2 -2
- package/dist/admin/assets/{stableId-BrtQedPy.js.map → stableId-g1uxJGSz.js.map} +1 -1
- package/dist/admin/assets/{store-CdIFG90N.js → store-CznhNKEi.js} +2 -2
- package/dist/admin/assets/{store-CdIFG90N.js.map → store-CznhNKEi.js.map} +1 -1
- package/dist/admin/assets/{switch-Dp6WYNam.js → switch-CiVf05NF.js} +2 -2
- package/dist/admin/assets/{switch-Dp6WYNam.js.map → switch-CiVf05NF.js.map} +1 -1
- package/dist/admin/assets/{theme-65PB8uAu.js → theme-Cv-MfOv8.js} +2 -2
- package/dist/admin/assets/theme-Cv-MfOv8.js.map +1 -0
- package/dist/admin/assets/titles-DrQhW8z3.js +2 -0
- package/dist/admin/assets/titles-DrQhW8z3.js.map +1 -0
- package/dist/admin/assets/tokens-B1S81Epe.js +2 -0
- package/dist/admin/assets/{tokens-ixHjAkDK.js.map → tokens-B1S81Epe.js.map} +1 -1
- package/dist/admin/assets/{tooltip-BGP1DVBt.js → tooltip-Bqf3oyqC.js} +2 -2
- package/dist/admin/assets/{tooltip-BGP1DVBt.js.map → tooltip-Bqf3oyqC.js.map} +1 -1
- package/dist/admin/assets/{undo-2-BiTANHFz.js → undo-2-DpwwRQTf.js} +2 -2
- package/dist/admin/assets/{undo-2-BiTANHFz.js.map → undo-2-DpwwRQTf.js.map} +1 -1
- package/dist/admin/assets/useContentSchema-B_q1rMrG.js +2 -0
- package/dist/admin/assets/useContentSchema-B_q1rMrG.js.map +1 -0
- package/dist/admin/assets/useCursorPager-BHYqHb3M.js +2 -0
- package/dist/admin/assets/{useCursorPager-0zHjlm-7.js.map → useCursorPager-BHYqHb3M.js.map} +1 -1
- package/dist/admin/assets/{useDiscardGuard-BskWSlbT.js → useDiscardGuard-C4QTfiU4.js} +2 -2
- package/dist/admin/assets/{useDiscardGuard-BskWSlbT.js.map → useDiscardGuard-C4QTfiU4.js.map} +1 -1
- package/dist/admin/assets/{useMediaPickerDialog-CU-ekPqX.js → useMediaPickerDialog-BLrVV1Kn.js} +2 -2
- package/dist/admin/assets/{useMediaPickerDialog-CU-ekPqX.js.map → useMediaPickerDialog-BLrVV1Kn.js.map} +1 -1
- package/dist/admin/assets/{useMediaUploader-CBcq1ICg.js → useMediaUploader-CFy6lasO.js} +2 -2
- package/dist/admin/assets/useMediaUploader-CFy6lasO.js.map +1 -0
- package/dist/admin/assets/useModelIndex-NU-WlHQY.js +2 -0
- package/dist/admin/assets/useModelIndex-NU-WlHQY.js.map +1 -0
- package/dist/admin/assets/useNetworkPermission-DehDln-U.js +2 -0
- package/dist/admin/assets/{useNetworkPermission-Cts98h9d.js.map → useNetworkPermission-DehDln-U.js.map} +1 -1
- package/dist/admin/assets/{usePaletteItems-DtReWmkd.js → usePaletteItems-CFpNlSOs.js} +2 -2
- package/dist/admin/assets/{usePaletteItems-DtReWmkd.js.map → usePaletteItems-CFpNlSOs.js.map} +1 -1
- package/dist/admin/assets/usePlaces-BA4x6503.js +2 -0
- package/dist/admin/assets/usePlaces-BA4x6503.js.map +1 -0
- package/dist/admin/assets/useResolvedDefinitions-30lnwFQ1.js +2 -0
- package/dist/admin/assets/useResolvedDefinitions-30lnwFQ1.js.map +1 -0
- package/dist/admin/assets/{useResolvedScheme-C8vcQVko.js → useResolvedScheme-BVM4qLct.js} +2 -2
- package/dist/admin/assets/{useResolvedScheme-C8vcQVko.js.map → useResolvedScheme-BVM4qLct.js.map} +1 -1
- package/dist/admin/assets/useSaveShortcut-DQuNL1uJ.js +2 -0
- package/dist/admin/assets/useSaveShortcut-DQuNL1uJ.js.map +1 -0
- package/dist/admin/assets/{useSchemaScopeAccess-ByrxIdKM.js → useSchemaScopeAccess-JXOMx51q.js} +2 -2
- package/dist/admin/assets/{useSchemaScopeAccess-ByrxIdKM.js.map → useSchemaScopeAccess-JXOMx51q.js.map} +1 -1
- package/dist/admin/assets/users-38jLQ7zr.js +2 -0
- package/dist/admin/assets/users-38jLQ7zr.js.map +1 -0
- package/dist/admin/assets/{users-DM7CXUBJ.js → users-DYwcVDqp.js} +2 -2
- package/dist/admin/assets/{users-DM7CXUBJ.js.map → users-DYwcVDqp.js.map} +1 -1
- package/dist/admin/assets/{zod-Cry7YvLY.js → zod-ZaQjjiAq.js} +2 -2
- package/dist/admin/assets/{zod-Cry7YvLY.js.map → zod-ZaQjjiAq.js.map} +1 -1
- package/dist/admin/index.html +60 -58
- package/dist/cli.js +1 -1
- package/dist/{cliMain-papyXJDd.js → cliMain-CTntiVc2.js} +107 -30
- package/dist/cliMain-CTntiVc2.js.map +1 -0
- package/dist/config.d.ts +2 -2
- package/dist/config.js +1 -1
- package/dist/{contentDisposition-DOL2Xt0l.js → contentDisposition-DzhPhncr.js} +2 -2
- package/dist/{contentDisposition-DOL2Xt0l.js.map → contentDisposition-DzhPhncr.js.map} +1 -1
- package/dist/index.d.ts +43 -6
- package/dist/index.js +2 -2
- package/dist/{public-COKbHR-N.d.ts → public-CMFaGDyf.d.ts} +50 -8
- package/dist/{public-B57h4F7Y.js → public-sJCQaNaP.js} +2 -2
- package/dist/public-sJCQaNaP.js.map +1 -0
- package/dist/{s3Adapter-U01iEAcK.js → s3Adapter-CZcCl0sy.js} +2 -2
- package/dist/{s3Adapter-U01iEAcK.js.map → s3Adapter-CZcCl0sy.js.map} +1 -1
- package/dist/{worker-B-sC-eY2.js → worker-DHm2JwMZ.js} +3140 -1292
- package/dist/worker-DHm2JwMZ.js.map +1 -0
- package/package.json +5 -5
- package/dist/admin/assets/AssistError-Cs-r9Ssc.js +0 -2
- package/dist/admin/assets/Body-BzZD-TZT.js +0 -2
- package/dist/admin/assets/Body-BzZD-TZT.js.map +0 -1
- package/dist/admin/assets/Builder-DW-GJA_q.js +0 -2
- package/dist/admin/assets/Builder-DW-GJA_q.js.map +0 -1
- package/dist/admin/assets/Form-lNrRHc0I.js +0 -2
- package/dist/admin/assets/Form-lNrRHc0I.js.map +0 -1
- package/dist/admin/assets/FormCheckboxGroup-DeeaYnzB.js +0 -2
- package/dist/admin/assets/FormCheckboxGroup-DeeaYnzB.js.map +0 -1
- package/dist/admin/assets/FormSelectField-BzE9Lq9i.js +0 -2
- package/dist/admin/assets/FormSelectField-BzE9Lq9i.js.map +0 -1
- package/dist/admin/assets/RadioTile-DQFmni5A.js.map +0 -1
- package/dist/admin/assets/RichTextField-CVHRIbnu.js.map +0 -1
- package/dist/admin/assets/StepList-BXGYD9eJ.js +0 -2
- package/dist/admin/assets/StepList-BXGYD9eJ.js.map +0 -1
- package/dist/admin/assets/Structure-D8csgrIt.js +0 -2
- package/dist/admin/assets/SubNavLink-CiCaVV8U.js.map +0 -1
- package/dist/admin/assets/auth-CQO4MBUj.js +0 -2
- package/dist/admin/assets/changeSets-8EburmT0.js +0 -2
- package/dist/admin/assets/chevron-left-DGU3HGYG.js +0 -2
- package/dist/admin/assets/content-CAjkbZEY.js +0 -3
- package/dist/admin/assets/content-CAjkbZEY.js.map +0 -1
- package/dist/admin/assets/createLucideIcon-CLmh7Go-.js +0 -2
- package/dist/admin/assets/createLucideIcon-CLmh7Go-.js.map +0 -1
- package/dist/admin/assets/develop-BOqvnlgt.js +0 -11
- package/dist/admin/assets/develop-BOqvnlgt.js.map +0 -1
- package/dist/admin/assets/es2015-BHmI7wjK.js +0 -42
- package/dist/admin/assets/es2015-BHmI7wjK.js.map +0 -1
- package/dist/admin/assets/followPlural-Cm7v_Udv.js +0 -2
- package/dist/admin/assets/followPlural-Cm7v_Udv.js.map +0 -1
- package/dist/admin/assets/inbox-DGO2D8fa.js +0 -2
- package/dist/admin/assets/inbox-DGO2D8fa.js.map +0 -1
- package/dist/admin/assets/index-BIIU9ZI6.js +0 -4
- package/dist/admin/assets/index-BIIU9ZI6.js.map +0 -1
- package/dist/admin/assets/index-lxe7WimO.css +0 -2
- package/dist/admin/assets/locales-Bg3htKo8.js +0 -2
- package/dist/admin/assets/media-BCnVhaDH.js +0 -2
- package/dist/admin/assets/network-BixABr0o.js +0 -2
- package/dist/admin/assets/network-BixABr0o.js.map +0 -1
- package/dist/admin/assets/publishing-Dke9bSKp.js +0 -2
- package/dist/admin/assets/publishing-Dke9bSKp.js.map +0 -1
- package/dist/admin/assets/schedules-BmB9Y73z.js +0 -2
- package/dist/admin/assets/schema-D-qo7XSF.js +0 -2
- package/dist/admin/assets/schema-D-qo7XSF.js.map +0 -1
- package/dist/admin/assets/sections-DqBzSKMP.js.map +0 -1
- package/dist/admin/assets/seo-CceGYTIX.js +0 -2
- package/dist/admin/assets/settings-B60vHpZd.js +0 -2
- package/dist/admin/assets/shapes-B5twqZcp.js +0 -6
- package/dist/admin/assets/shapes-B5twqZcp.js.map +0 -1
- package/dist/admin/assets/src-ndgTSYLX.js +0 -7
- package/dist/admin/assets/src-ndgTSYLX.js.map +0 -1
- package/dist/admin/assets/theme-65PB8uAu.js.map +0 -1
- package/dist/admin/assets/titles-CQiqqDw-.js +0 -2
- package/dist/admin/assets/titles-CQiqqDw-.js.map +0 -1
- package/dist/admin/assets/tokens-ixHjAkDK.js +0 -2
- package/dist/admin/assets/useContentSchema-DtYfhsd2.js +0 -2
- package/dist/admin/assets/useContentSchema-DtYfhsd2.js.map +0 -1
- package/dist/admin/assets/useCursorPager-0zHjlm-7.js +0 -2
- package/dist/admin/assets/useMediaUploader-CBcq1ICg.js.map +0 -1
- package/dist/admin/assets/useNetworkPermission-Cts98h9d.js +0 -2
- package/dist/admin/assets/usePlaces-DC47wVeU.js +0 -2
- package/dist/admin/assets/usePlaces-DC47wVeU.js.map +0 -1
- package/dist/admin/assets/useQueries-CirW3Mvp.js +0 -2
- package/dist/admin/assets/useQueries-CirW3Mvp.js.map +0 -1
- package/dist/admin/assets/useSaveShortcut-rKtp1qK7.js +0 -2
- package/dist/admin/assets/useSaveShortcut-rKtp1qK7.js.map +0 -1
- package/dist/admin/assets/users-2iJYwlJb.js +0 -2
- package/dist/admin/assets/users-2iJYwlJb.js.map +0 -1
- package/dist/cliMain-papyXJDd.js.map +0 -1
- package/dist/public-B57h4F7Y.js.map +0 -1
- package/dist/worker-B-sC-eY2.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"mappings":"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","names":["__iconData","ArrowDownWideNarrow","createLucideIcon","ArrowUpDown","ArrowUpNarrowWide","ArrowUpRight","CloudOff","Columns3","Eye","FileQuestionMark","Funnel","ListPlus","PanelRight","RotateCw","Rows3","Save","ShieldAlert","SquarePen","usePlacePermissions","me","useMe","useSchemaScopeAccess","shared","useDefinitions","definition","model","scope","canManageSchema","canOnModel","canCreateOnSite","TAB_LABEL_KEYS","Tabs","useTranslation","navigate","useNavigate","useSearch","open","next","value","entryPage","previous","import_jsx_runtime","TabsRoot","tab","TabsList","t","placeLabel","PLACE_TABS","TabsTrigger","key","TabsContent","cn","document","EntryFrame","canSeeStructure","children","useContentLocales","locales","useLocales","list","defaultLocale","locale","known","requested","code","DrawerSection","id","title","CoverSettings","altId","useId","useFieldsEnvironment","useMediaPermissions","useTopLevelValue","field","asset","useMediaAsset","update","useUpdateMediaAsset","alt","setAlt","useState","current","editable","canWrite","readOnly","event","Label","Input","SubmitButton","SuggestAltButton","FocalPoint","FormError","DangerZone","onUnpublish","onDuplicate","onDelete","InlineConfirm","Button","Undo2","Copy","Trash2","CanvasBlock","memo","control","useFieldControl","custom","LabelElement","path","_Fragment","showScope","ScopeIcon","FieldEditor","FieldMessages","GroupLabel","DropdownMenuLabel","BoundaryInserter","menu","useDeferredMenuAction","usable","targets","insertions","several","final","DropdownMenu","DropdownMenuTrigger","Plus","DropdownMenuContent","DropdownMenuGroup","index","DropdownMenuSeparator","BlockMenuItems","actions","type","edge","InsertMenuItem","Boxes","component","ImagePlus","listMax","useCanvasInsertions","store","useEntryFormStore","handles","useCanvasHandles","insertionsOf","useCallback","disabled","isCanvasEligible","count","toList","max","full","allowedComponentsOf","components","putInList","added","item","newComponentItem","allowedKinds","picked","pickMedia","error","reportError","CanvasField","Canvas","CanvasHandlesContext","CanvasFields","useEntryForm","state","fields","Fragment","COVER_VARIANTS","PERCENT","coverId","Cover","dropping","setDropping","uploading","setUploading","focusReplace","setFocusReplace","replaceRef","useRef","import_react","url","variant","name","choose","first","onChange","drop","file","candidate","uploadMedia","logError","toast","dropProps","focal","Skeleton","RefreshCw","onEditDetails","Crosshair","Loader2","stripFieldsFor","stripFieldsOf","layout","isSeoField","isEmptyValue","values","isSummarizable","effectiveTitleField","richTextBodyOf","SHOWN_LINKS","RelationValue","target","models","ids","labels","useEntryLabels","names","entryTitle","shortId","shown","MediaValue","PropertyValue","formatDateTime","summarizeValue","SAVE_BEFORE_ASSIST_KEYS","AssistDocumentContext","createContext","useAssistDocument","saveIfDirty","dirtyKeysOf","baseline","outcome","save","useMemo","mode","useAssistTarget","environment","assistDocument","useContext","entryId","useSummarizeIntoField","summarize","useSummarizeField","preparing","setPreparing","blocked","setBlocked","truncated","setTruncated","run","prepared","result","SummarizeAction","AssistButton","InfoHint","AssistError","PropertyChip","setOpen","problems","countIssuesUnder","issuesByPath","assistEnabled","useAssistEnabled","summarizable","Popover","PopoverTrigger","CircleAlert","PopoverContent","TopLevelField","PropertiesStrip","more","onMore","PropertyGrid","groups","group","headingClasses","Title","InlineTitle","heading","invalid","textValue","text","DocumentBody","hasBlocks","onOpenSettings","Section","headingId","section","spaced","EntryFields","FormBody","effectiveFormLayout","KIND_ORDER","revisionRowKey","revisionId","historyTimeline","liveIds","publications","items","revision","published","publication","b","a","diffRevision","toFormValues","revisionData","liveFields","now","then","isSameContent","REASON_KEYS","reasonKey","reason","useRowText","meta","extra","row","by","ICONS","History","Send","Row","Icon","body","StatusChip","selected","onSelect","revisionIdOf","CHANGE_KEYS","HistorySheet","history","useEntryHistory","rows","selectedKey","setSelectedKey","initialRevisionId","selectedRow","selectedId","newestRevision","useRevision","changes","restoreButton","restoring","confirmRestore","onRestore","RotateCcw","Sheet","SheetContent","SheetHeader","SheetTitle","SheetBody","LoadingState","ErrorState","change","usePaletteActions","usePaletteItems","useDocumentPaletteActions","latest","canPublish","onPublish","canSwitch","onLocaleChange","entry","Languages","SHORTCUTS","handlers","useDocumentShortcuts","enabled","onKeyDown","slugPairsOf","slug","source","useFollowingSlugs","pairs","before","after","slugify","useAutosave","latestSave","timer","unsubscribe","AUTOSAVE_DELAY_MS","newLocaleValues","fromSource","collect","defaults","defaultFormValues","localizedValuesOf","useEntryLifecycle","queryClient","useQueryClient","createMutation","useCreateEntry","deleteMutation","useDeleteEntry","duplicateMutation","useDuplicateEntry","restoreMutation","useRestoreRevision","referrers","setReferrers","markClean","flushSync","openEntry","buildCreateData","issues","contentIssuesOf","found","referrersOf","copy","exclusive","versionRef","onRestored","isEditConflict","onConflict","entryQueryOptions","onAsset","useEntryPermissions","can","action","sendableChanges","held","containsUnparsed","useEntrySaver","useSaveEntry","queue","setState","failedSignedOut","runSave","kind","refuseUnparsed","keys","mutateAsync","buildPatch","sent","isUnauthorized","task","resumed","useSessionStore","session","useEntrySetup","runtime","useRuntimeEditors","mediaDialog","useMediaPickerDialog","canUpload","useMediaUploader","queryKeys","initial","schema","created","createEntryFormStore","carry","setEntry","uploadOne","usePublishing","publishMutation","usePublishEntry","modelKey","unpublishMutation","useUnpublishEntry","othersDismissed","setOthersDismissed","autosaved","expectedVersion","onEntry","expectedVersions","entryLocales","others","EDIT_CONFLICT","useRemoteDraftChange","server","drafts","draft","moved","busy","conflict","shownVersion","raise","dirty","useEntryDocument","permissions","setConflict","reloading","setReloading","setup","useStore","selectDirtyKeys","hasLocalizedValues","saver","saved","onReload","lifecycle","publishing","local","keepChanges","silent","PRESENCE_HEARTBEAT_MS","usePreflight","useQuery","withCsrf","adminApi","useEntryPresenceQuery","input","leavePresence","tabId","leavePresenceOnUnload","token","ADMIN_PATHS","apiBaseUrl","CSRF_HEADER","subscribeVisibility","isVisible","NO_PEOPLE","NO_DRAFTS","useEntryHeartbeat","visible","useSyncExternalStore","presence","onPageHide","usePreflightFlow","ready","setReady","start","FOCUSABLE","elementFor","segments","length","useRevealField","apiKey","focus","assetId","fieldDomId","idPrefix","openProperty","XL_QUERY","useMediaQuery","subscribe","query","getSnapshot","serverValue","useSettingsDrawer","wide","remembered","useUiStore","remember","narrowOpen","setNarrowOpen","hidden","setHidden","touched","setTouched","setFocus","expanded","setExpanded","wasWide","setWasWide","openAt","property","toggleProperty","withEntryLayout","display","isQuietPlan","plan","SWITCHED_KEYS","NeedsReviewError","useLayoutSwitch","usePlanChange","ship","useShipDraftNow","shipLayout","detail","definitionQueryOptions","entryLayoutOf","notifyFailure","describeError","hasErrorCode","undoable","SECTION_ID","SWITCH_ID","wordClasses","LayoutSection","form","word","side","pending","Switch","checked","NoFields","EmptyState","Link","proposalKey","useAssistProposalsStore","create","set","proposal","_dismissed","rest","AssistProposalBanner","dismiss","labelOfPath","Alert","Sparkles","AlertTitle","AlertDescription","labelOf","issue","ConflictBanner","reloadRef","TriangleAlert","onReloadKeepingChanges","onDiscard","PublishOthersAlert","onDismiss","ReferencedAlert","ref","unique","other","referrer","Link2","Notices","newLocaleLabel","newLocaleAction","onDismissReferrers","outdated","onPublishOthers","onDismissOthers","useAddEntryToChangeSet","addEntry","useAddChangeSetEntry","createChangeSet","useCreateChangeSet","addTo","AddToChangeSet","titleId","inputId","newTitle","setNewTitle","sets","useChangeSets","onAdded","cause","reset","FolderPlus","createAndAdd","decode","segment","resolveFieldPath","topLevel","trail","zoneKey","isRecord","PREFLIGHT_RULE_KEYS","ENTRY_LOCALE_MISSING_KEY","param","check","sentenceOf","context","describeIssue","PreflightCheckItem","sentence","onFix","ScheduleForm","setValue","defaultScheduleValue","setInvalid","useCreateSchedule","runAt","dateTimeLocalToIso","onScheduled","CalendarClock","PreflightSheet","preflight","scheduling","setScheduling","pendingFix","localeChecks","entryChecks","fixOf","onOpenChange","fix","SheetDescription","CircleCheck","canSchedule","SheetFooter","canUseChangeSets","SHOWN","Presence","people","label","person","Tooltip","TooltipTrigger","UserAvatar","TooltipContent","Frame","frameRef","SdkNotice","Info","ExternalLink","VISUAL_EDITING_DOCS_URL","Body","preview","siteUrl","frameUrl","frameTitle","Link2Off","TOP_BAR_SELECTOR","useTopBarHeight","height","setHeight","bar","observer","IconAction","icon","Toolbar","Select","onChooseTarget","SelectTrigger","SelectValue","SelectContent","SelectItem","onShowDocument","FileText","onClose","X","PreviewPane","topBarHeight","VISUAL_QUERY_PARAM","MAX_PATH_LENGTH","MAX_PATH_SEGMENTS","SEGMENT","ENTRY_ID","LOCALE","normalizeFieldPath","parseSiteMessage","data","usePreviewTargets","openPreview","revokePreviewToken","framedPreviewUrl","framed","httpOriginOf","parsed","canFramePreview","origin","adminOrigin","useFrameBlocked","blockedOrigin","setBlockedOrigin","onViolation","resolvePreviewFocus","message","usePreviewFocus","reveal","acceptSiteMessage","frame","previewOrigin","usePreviewMessages","latestFocus","onFocus","onMessage","onFrameLoad","PREVIEW_READY_TIMEOUT_MS","usePreviewRefresh","status","latestRefresh","refresh","settled","MIN_REFRESH_DELAY_MS","release","usePreviewSession","connectionId","attempt","setAttempt","cancelled","tokenId","mint","opened","delay","PREVIEW_TOKEN_REFRESH_MARGIN_MS","REFRESH","useEntryPreview","options","mobile","useIsMobile","documentShown","setDocumentShown","chosen","setChosen","active","focusField","messages","saveStatus","PreviewButton","available","pressed","onToggle","MOMENT_MS","changedWhen","savedAt","momentAgo","formatRelativeTime","RemoteChange","when","savedBy","compact","SaveState","short","AlertCircle","Pencil","Check","brief","PropertyRow","bodyId","ChevronRight","focusTargetOf","SettingsDrawer","automatic","properties","onToggleProperty","cover","onOpenHistory","danger","EntryStatusChip","ENTRY_STATUS_TONES","ENTRY_STATUS_LABEL_KEYS","LocaleStatusList","states","useTranslateLocale","translate","useTranslateEntry","saveEntry","propose","setTarget","to","prepare","onOpen","from","TranslateLocale","className","fromLabel","term","StatusSection","assistTarget","canCopy","onCopyFromDefault","notStarted","copyButton","confirmCopy","spinnerOr","TopBar","saveState","onSave","saving","settingsOpen","onToggleSettings","primary","EntryDocument","entryDocument","effectiveLayout","drawer","linkedRevision","historyOpen","setHistoryOpen","titleValue","useSaveShortcut","showSave","live","hasFields","FieldsProvider","EntrySiblings","Page","LocaleSelect","UnsavedChangesGuard","existingLocalesOf","ShapioApiError","useEntryForLocale","useEntry","existing","sourceLocale","sourceEnabled","EntryLoader","loaded","generation","setGeneration","reload","useModelRoute","schemaError","useContentSchema","findModelByKey","ModelMissing","FileQuestion","EntryEditor","useParams","search","ContentHome","Navigate","PageHeader","CREATE","NewEntry","linkOptions","NoAccess","EndpointList","Panel","endpoints","Badge","endpoint","CopyButton","Api","lookup","restEndpoints","routeKeyOf","graphqlSdl","PagePager","pageCount","total","pageSize","page","pageSizes","onPageSizeChange","size","onPageChange","ChevronLeft","BulkBar","running","onAction","canDelete","onClear","SelectAll","all","some","Checkbox","onSelectChange","coverAssetOf","AvatarGroup","AvatarGroupCount","RowActions","confirming","setConfirming","confirmOpen","setConfirmOpen","ask","handingOff","handOff","inline","publishConfirm","localeLabel","deleteConfirm","editLink","PublishIcon","moreId","MoreHorizontal","DropdownMenuItem","onQuickEdit","onPreview","Card","Thumbnail","ImageOff","RowTitle","NOBODY","Cards","familyOf","EQUALITY","RANGE","TEXT_MATCH","BY_FAMILY","SYSTEM_FILTER_FIELDS","SYSTEM_OPERATORS","operatorsFor","operator","isSortableField","OPERATOR_LABEL_KEYS","isValueless","toContentFilter","filters","conditions","filter","fromDateTimeInput","Author","author","Cell","EntryTitle","rowMoreId","fixedColumnCount","rowActionsProps","quickEdit","FLAG_CLASSES","LocaleFlags","description","DOCUMENT_ONLY_TYPES","quickEditFieldsOf","placed","Form","setError","formRef","onDraftChange","submit","failure","cancel","QuickEdit","Updated","at","TableRow","TableCell","titleColumn","columns","SortHeader","sort","ArrowUp","ArrowDown","onSortChange","EntryTable","allSelected","someSelected","ariaSort","header","sortable","Table","TableHeader","TableHead","TableBody","FilterChip","onRemove","isSystemField","filterFieldOf","isEntryFilter","relationFilterFields","useFilterLabel","subject","SYSTEM_LABEL_KEYS","condition","rawValue","ActiveFilter","AddChip","props","AuthorFilter","choices","onPick","choice","meId","useAuthorChoices","canListUsers","useHasGlobalPermission","users","byId","add","user","SEARCH_DEBOUNCE_MS","RelationFilter","setText","q","useDebouncedValue","searchable","isSearchable","useEntryList","Search","StatusFilter","ENTRY_STATUSES","Chip","FilterChips","used","adders","applied","onSearchChange","nameOf","expectedVersionOf","SUCCESS_KEYS","FAILURE_KEYS","useBulkEntryActions","setRunning","failed","firstError","expectedOf","succeeded","i18next","MAX_DEFAULT_COLUMNS","LISTABLE_TYPES","UNLISTABLE_TYPES","columnChoicesFor","titleFieldOf","columnsFor","configured","useListColumnsStore","persist","modelId","_previous","fieldIds","view","persistentStorage","useListColumns","chosenIds","setColumns","fieldId","useListView","stored","setStored","useModelPresence","PRESENCE_POLL_MS","usePreviewEntry","useMutation","useQuickEditRow","openId","setOpenId","useRowActions","publishEntry","unpublishEntry","duplicateEntry","deleteEntry","refreshCounts","useSelection","setSelected","NewButton","Item","Stacked","ColumnsMenu","DropdownMenuCheckboxItem","onColumnChange","customized","onReset","FilterBuilder","setDraft","operatorsOf","Filter","operators","fieldLabel","SortMenu","DirectionIcon","DropdownMenuRadioGroup","DropdownMenuRadioItem","direction","SegmentedToggle","ariaLabel","ariaLabelledBy","option","iconOnly","ViewToggle","onViewChange","LayoutGrid","useSearchInput","onQueryChange","onFiltersChange","chips","Entries","placeSearch","bulk","quickEditRow","useIsMdUp","quickEditable","filtered","setFilters","setSearch","setSort","pagination","TableCard","columnChoices","setColumnVisible","resetColumns","setView","CONTENT_PAGE_SIZES","FileStack","changeSelection","replaceSelection","Header","canCreate","usePlaceCount","counts","useContentCounts","unfilteredTotal","parseSort","defaultSortOf","usePlaceSearch","resetPage","Singleton","Structure","lazy","module","PlaceScreen","collection","content","Suspense","contentLazyRoutes","createLazyRoute"],"ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],"sources":["../../../../node_modules/.pnpm/lucide-react@1.49.0_@types+react@19.3.0_react@19.3.0/node_modules/lucide-react/dist/esm/icons/arrow-down-wide-narrow.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/arrow-up-down.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/arrow-up-narrow-wide.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/arrow-up-right.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/cloud-off.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/columns-3.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/eye.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/file-question-mark.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/funnel.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/list-plus.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/panel-right.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/rotate-cw.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/rows-3.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/save.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/shield-alert.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/square-pen.mjs","../../src/features/Content/Place/hooks/usePlacePermissions.ts","../../src/features/Content/Place/Tabs/index.tsx","../../src/features/Content/EntryFrame/index.tsx","../../src/features/Content/hooks/useContentLocales.ts","../../src/features/Content/Entry/DrawerSection/index.tsx","../../src/features/Content/Entry/CoverSettings/index.tsx","../../src/features/Content/Entry/DangerZone/index.tsx","../../src/fields/CanvasBlock/index.tsx","../../src/features/Content/Entry/BoundaryInserter/index.tsx","../../src/features/Content/Entry/hooks/useCanvasInsertions.ts","../../src/features/Content/Entry/Canvas/index.tsx","../../src/features/Content/Entry/Cover/index.tsx","../../src/features/Content/Entry/helpers/stripFields.ts","../../src/features/Content/Entry/helpers/assistEligibility.ts","../../src/features/Content/Entry/PropertyValue/index.tsx","../../src/features/Content/Entry/helpers/assistMessages.ts","../../src/features/Content/Entry/hooks/useAssistTarget.ts","../../src/features/Content/Entry/hooks/useSummarizeIntoField.ts","../../src/features/Content/Entry/SummarizeAction/index.tsx","../../src/features/Content/Entry/PropertyChip/index.tsx","../../src/features/Content/Entry/PropertiesStrip/index.tsx","../../src/features/Content/Entry/PropertyGrid/index.tsx","../../src/features/Content/Entry/Title/index.tsx","../../src/features/Content/Entry/Document/index.tsx","../../src/features/Content/Entry/Form/Section/index.tsx","../../src/features/Content/Entry/Form/index.tsx","../../src/features/Content/Entry/helpers/historyTimeline.ts","../../src/features/Content/Entry/helpers/revisionDiff.ts","../../src/features/Content/Entry/HistorySheet/Row/index.tsx","../../src/features/Content/Entry/HistorySheet/index.tsx","../../src/components/CommandPalette/hooks/usePaletteActions.ts","../../src/features/Content/Entry/hooks/useDocumentPaletteActions.ts","../../src/features/Content/Entry/hooks/useDocumentShortcuts.ts","../../src/fields/hooks/useFollowingSlugs.ts","../../src/features/Content/Entry/hooks/useAutosave.ts","../../src/features/Content/Entry/helpers/initialValues.ts","../../src/features/Content/Entry/hooks/useEntryLifecycle.ts","../../src/features/Content/Entry/hooks/useEntryPermissions.ts","../../src/features/Content/Entry/hooks/useEntrySaver.ts","../../src/features/Content/Entry/hooks/useEntrySetup.ts","../../src/features/Content/Entry/hooks/usePublishing.ts","../../src/features/Content/Entry/hooks/useRemoteDraftChange.ts","../../src/features/Content/Entry/hooks/useEntryDocument.ts","../../src/api/entryDocument.ts","../../src/features/Content/Entry/hooks/useEntryHeartbeat.ts","../../src/features/Content/Entry/hooks/usePreflightFlow.ts","../../src/features/Content/Entry/hooks/useRevealField.ts","../../src/hooks/useMediaQuery.ts","../../src/features/Content/Entry/hooks/useSettingsDrawer.ts","../../src/features/Content/Entry/helpers/layoutSwitch.ts","../../src/features/Content/Entry/hooks/useLayoutSwitch.ts","../../src/features/Content/Entry/LayoutSection/index.tsx","../../src/features/Content/Entry/NoFields/index.tsx","../../src/stores/assistProposals.ts","../../src/features/Content/Entry/AssistProposalBanner/index.tsx","../../src/features/Content/Entry/ConflictBanner/index.tsx","../../src/features/Content/Entry/PublishOthersAlert/index.tsx","../../src/features/Content/Entry/ReferencedAlert/index.tsx","../../src/features/Content/Entry/Notices/index.tsx","../../src/features/Content/Entry/hooks/useAddEntryToChangeSet.ts","../../src/features/Content/Entry/AddToChangeSet/index.tsx","../../src/features/Content/Entry/helpers/fieldPath.ts","../../src/features/Content/Entry/helpers/preflightSentences.ts","../../src/features/Content/Entry/PreflightCheckItem/index.tsx","../../src/features/Content/Entry/ScheduleForm/index.tsx","../../src/features/Content/Entry/PreflightSheet/index.tsx","../../src/features/Content/Entry/Presence/index.tsx","../../src/features/Content/Entry/Preview/Frame/index.tsx","../../src/features/Content/Entry/Preview/SdkNotice/index.tsx","../../src/features/Content/Entry/Preview/Body/index.tsx","../../src/features/Content/Entry/Preview/hooks/useTopBarHeight.ts","../../src/features/Content/Entry/Preview/Toolbar/IconAction/index.tsx","../../src/features/Content/Entry/Preview/Toolbar/index.tsx","../../src/features/Content/Entry/Preview/index.tsx","../../../../packages/visual/src/messages.ts","../../src/api/preview.ts","../../src/features/Content/Entry/Preview/helpers/previewFrame.ts","../../src/features/Content/Entry/Preview/hooks/useFrameBlocked.ts","../../src/features/Content/Entry/Preview/helpers/focusTarget.ts","../../src/features/Content/Entry/Preview/hooks/usePreviewFocus.ts","../../src/features/Content/Entry/Preview/helpers/previewMessages.ts","../../src/features/Content/Entry/Preview/hooks/usePreviewMessages.ts","../../src/features/Content/Entry/Preview/hooks/usePreviewRefresh.ts","../../src/features/Content/Entry/Preview/hooks/usePreviewSession.ts","../../src/features/Content/Entry/Preview/hooks/useEntryPreview.ts","../../src/features/Content/Entry/PreviewButton/index.tsx","../../src/features/Content/Entry/helpers/changedWhen.ts","../../src/features/Content/Entry/RemoteChange/index.tsx","../../src/features/Content/Entry/SaveState/index.tsx","../../src/features/Content/Entry/PropertyRow/index.tsx","../../src/features/Content/Entry/SettingsDrawer/index.tsx","../../src/features/Content/EntryStatusChip/index.tsx","../../src/features/Content/Entry/LocaleStatusList/index.tsx","../../src/features/Content/Entry/hooks/useTranslateLocale.ts","../../src/features/Content/Entry/TranslateLocale/index.tsx","../../src/features/Content/Entry/StatusSection/index.tsx","../../src/features/Content/Entry/TopBar/index.tsx","../../src/features/Content/Entry/index.tsx","../../src/features/Content/hooks/useEntryForLocale.ts","../../src/features/Content/EntryLoader/index.tsx","../../src/features/Content/hooks/useModelRoute.ts","../../src/features/Content/ModelMissing/index.tsx","../../src/features/Content/EntryEditor/index.tsx","../../src/features/Content/Home/index.tsx","../../src/features/Content/NewEntry/index.tsx","../../src/features/Content/Place/Api/index.tsx","../../src/components/PagePager/index.tsx","../../src/features/Content/Place/BulkBar/index.tsx","../../src/features/Content/Place/SelectAll/index.tsx","../../src/features/Content/Place/helpers/cover.ts","../../src/features/Content/Place/Presence/index.tsx","../../src/features/Content/Place/RowActions/index.tsx","../../src/features/Content/Place/Cards/Card/index.tsx","../../src/features/Content/Place/Cards/index.tsx","../../src/features/Content/helpers/filterOperators.ts","../../src/features/Content/Place/Author/index.tsx","../../src/features/Content/Place/Cell/index.tsx","../../src/features/Content/Place/EntryTitle/index.tsx","../../src/features/Content/Place/helpers/rowIds.ts","../../src/features/Content/Place/helpers/rowContext.ts","../../src/features/Content/Place/LocaleFlags/index.tsx","../../src/features/Content/Place/helpers/quickEditFields.ts","../../src/features/Content/Place/QuickEdit/Form/index.tsx","../../src/features/Content/Place/QuickEdit/index.tsx","../../src/features/Content/Place/Updated/index.tsx","../../src/features/Content/Place/Row/index.tsx","../../src/features/Content/Place/EntryTable/SortHeader/index.tsx","../../src/features/Content/Place/EntryTable/index.tsx","../../src/features/Content/Place/FilterChip/index.tsx","../../src/features/Content/Place/helpers/filterLabels.ts","../../src/features/Content/Place/hooks/useFilterLabel.ts","../../src/features/Content/Place/ActiveFilter/index.tsx","../../src/features/Content/Place/AddChip/index.tsx","../../src/features/Content/Place/AuthorFilter/index.tsx","../../src/features/Content/Place/hooks/useAuthorChoices.ts","../../src/features/Content/Place/RelationFilter/index.tsx","../../src/features/Content/Place/StatusFilter/index.tsx","../../src/features/Content/Place/FilterChips/index.tsx","../../src/features/Content/Place/helpers/expectedVersion.ts","../../src/features/Content/Place/hooks/useBulkEntryActions.ts","../../src/features/Content/Place/columns.ts","../../src/features/Content/Place/stores/listColumns.ts","../../src/features/Content/Place/hooks/useListColumns.ts","../../src/features/Content/Place/hooks/useListView.ts","../../src/features/Content/Place/hooks/useModelPresence.ts","../../src/features/Content/Place/hooks/usePreviewEntry.ts","../../src/features/Content/Place/hooks/useQuickEditRow.ts","../../src/features/Content/Place/hooks/useRowActions.ts","../../src/features/Content/Place/hooks/useSelection.ts","../../src/features/Content/Place/NewButton/index.tsx","../../src/features/Content/Place/Stacked/Item/index.tsx","../../src/features/Content/Place/Stacked/index.tsx","../../src/features/Content/Place/ColumnsMenu/index.tsx","../../src/features/Content/Place/FilterBuilder/index.tsx","../../src/features/Content/Place/SortMenu/index.tsx","../../src/components/SegmentedToggle/index.tsx","../../src/features/Content/Place/ViewToggle/index.tsx","../../src/features/Content/Place/Toolbar/index.tsx","../../src/features/Content/Place/Entries/index.tsx","../../src/features/Content/Place/Header/index.tsx","../../src/features/Content/Place/hooks/usePlaceCount.ts","../../src/features/Content/Place/hooks/usePlaceSearch.ts","../../src/features/Content/Place/Singleton/index.tsx","../../src/features/Content/Place/index.tsx","../../src/app/lazyRoutes/content.tsx"],"sourcesContent":["/**\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: \"arrow-down-wide-narrow\",\n size: 24,\n node: [\n [\"path\", { d: \"m3 16 4 4 4-4\", key: \"1co6wj\" }],\n [\"path\", { d: \"M7 20V4\", key: \"1yoxec\" }],\n [\"path\", { d: \"M11 4h10\", key: \"1w87gc\" }],\n [\"path\", { d: \"M11 8h7\", key: \"djye34\" }],\n [\"path\", { d: \"M11 12h4\", key: \"q8tih4\" }]\n ],\n aliases: [\"sort-desc\"]\n};\n__iconData.node;\nconst ArrowDownWideNarrow = createLucideIcon(__iconData);\n\nexport { __iconData, ArrowDownWideNarrow as default };\n//# sourceMappingURL=arrow-down-wide-narrow.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: \"arrow-up-down\",\n size: 24,\n node: [\n [\"path\", { d: \"m21 16-4 4-4-4\", key: \"f6ql7i\" }],\n [\"path\", { d: \"M17 20V4\", key: \"1ejh1v\" }],\n [\"path\", { d: \"m3 8 4-4 4 4\", key: \"11wl7u\" }],\n [\"path\", { d: \"M7 4v16\", key: \"1glfcx\" }]\n ]\n};\n__iconData.node;\nconst ArrowUpDown = createLucideIcon(__iconData);\n\nexport { __iconData, ArrowUpDown as default };\n//# sourceMappingURL=arrow-up-down.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: \"arrow-up-narrow-wide\",\n size: 24,\n node: [\n [\"path\", { d: \"m3 8 4-4 4 4\", key: \"11wl7u\" }],\n [\"path\", { d: \"M7 4v16\", key: \"1glfcx\" }],\n [\"path\", { d: \"M11 12h4\", key: \"q8tih4\" }],\n [\"path\", { d: \"M11 16h7\", key: \"uosisv\" }],\n [\"path\", { d: \"M11 20h10\", key: \"jvxblo\" }]\n ],\n aliases: [\"sort-asc\"]\n};\n__iconData.node;\nconst ArrowUpNarrowWide = createLucideIcon(__iconData);\n\nexport { __iconData, ArrowUpNarrowWide as default };\n//# sourceMappingURL=arrow-up-narrow-wide.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: \"arrow-up-right\",\n size: 24,\n node: [\n [\"path\", { d: \"M7 7h10v10\", key: \"1tivn9\" }],\n [\"path\", { d: \"M7 17 17 7\", key: \"1vkiza\" }]\n ]\n};\n__iconData.node;\nconst ArrowUpRight = createLucideIcon(__iconData);\n\nexport { __iconData, ArrowUpRight as default };\n//# sourceMappingURL=arrow-up-right.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: \"cloud-off\",\n size: 24,\n node: [\n [\n \"path\",\n { d: \"M10.94 5.274A7 7 0 0 1 15.71 10h1.79a4.5 4.5 0 0 1 4.222 6.057\", key: \"1uxyv8\" }\n ],\n [\"path\", { d: \"M18.796 18.81A4.5 4.5 0 0 1 17.5 19H9A7 7 0 0 1 5.79 5.78\", key: \"99tcn7\" }],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n ]\n};\n__iconData.node;\nconst CloudOff = createLucideIcon(__iconData);\n\nexport { __iconData, CloudOff as default };\n//# sourceMappingURL=cloud-off.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: \"columns-3\",\n size: 24,\n node: [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }]\n ],\n aliases: [\"panels-left-right\"]\n};\n__iconData.node;\nconst Columns3 = createLucideIcon(__iconData);\n\nexport { __iconData, Columns3 as default };\n//# sourceMappingURL=columns-3.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: \"eye\",\n size: 24,\n node: [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n ]\n};\n__iconData.node;\nconst Eye = createLucideIcon(__iconData);\n\nexport { __iconData, Eye as default };\n//# sourceMappingURL=eye.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: \"file-question-mark\",\n size: 24,\n node: [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }],\n [\"path\", { d: \"M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3\", key: \"mhlwft\" }]\n ],\n aliases: [\"file-question\"]\n};\n__iconData.node;\nconst FileQuestionMark = createLucideIcon(__iconData);\n\nexport { __iconData, FileQuestionMark as default };\n//# sourceMappingURL=file-question-mark.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: \"funnel\",\n size: 24,\n node: [\n [\n \"path\",\n {\n d: \"M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z\",\n key: \"sc7q7i\"\n }\n ]\n ],\n aliases: [\"filter\"]\n};\n__iconData.node;\nconst Funnel = createLucideIcon(__iconData);\n\nexport { __iconData, Funnel as default };\n//# sourceMappingURL=funnel.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: \"list-plus\",\n size: 24,\n node: [\n [\"path\", { d: \"M16 5H3\", key: \"m91uny\" }],\n [\"path\", { d: \"M11 12H3\", key: \"51ecnj\" }],\n [\"path\", { d: \"M16 19H3\", key: \"zzsher\" }],\n [\"path\", { d: \"M18 9v6\", key: \"1twb98\" }],\n [\"path\", { d: \"M21 12h-6\", key: \"bt1uis\" }]\n ]\n};\n__iconData.node;\nconst ListPlus = createLucideIcon(__iconData);\n\nexport { __iconData, ListPlus as default };\n//# sourceMappingURL=list-plus.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: \"panel-right\",\n size: 24,\n node: [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }]\n ]\n};\n__iconData.node;\nconst PanelRight = createLucideIcon(__iconData);\n\nexport { __iconData, PanelRight as default };\n//# sourceMappingURL=panel-right.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: \"rotate-cw\",\n size: 24,\n node: [\n [\"path\", { d: \"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\", key: \"1p45f6\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }]\n ]\n};\n__iconData.node;\nconst RotateCw = createLucideIcon(__iconData);\n\nexport { __iconData, RotateCw as default };\n//# sourceMappingURL=rotate-cw.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: \"rows-3\",\n size: 24,\n node: [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M21 9H3\", key: \"1338ky\" }],\n [\"path\", { d: \"M21 15H3\", key: \"9uk58r\" }]\n ],\n aliases: [\"panels-top-bottom\"]\n};\n__iconData.node;\nconst Rows3 = createLucideIcon(__iconData);\n\nexport { __iconData, Rows3 as default };\n//# sourceMappingURL=rows-3.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: \"save\",\n size: 24,\n node: [\n [\n \"path\",\n {\n d: \"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\",\n key: \"1c8476\"\n }\n ],\n [\"path\", { d: \"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\", key: \"1ydtos\" }],\n [\"path\", { d: \"M7 3v4a1 1 0 0 0 1 1h7\", key: \"t51u73\" }]\n ]\n};\n__iconData.node;\nconst Save = createLucideIcon(__iconData);\n\nexport { __iconData, Save as default };\n//# sourceMappingURL=save.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: \"shield-alert\",\n size: 24,\n node: [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"M12 8v4\", key: \"1got3b\" }],\n [\"path\", { d: \"M12 16h.01\", key: \"1drbdi\" }]\n ]\n};\n__iconData.node;\nconst ShieldAlert = createLucideIcon(__iconData);\n\nexport { __iconData, ShieldAlert as default };\n//# sourceMappingURL=shield-alert.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: \"square-pen\",\n size: 24,\n node: [\n [\"path\", { d: \"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\", key: \"1m0v6g\" }],\n [\n \"path\",\n {\n d: \"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\",\n key: \"ohrbg2\"\n }\n ]\n ],\n aliases: [\"pen-box\", \"edit\", \"pen-square\"]\n};\n__iconData.node;\nconst SquarePen = createLucideIcon(__iconData);\n\nexport { __iconData, SquarePen as default };\n//# sourceMappingURL=square-pen.mjs.map\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useMe } from '@/api/auth';\nimport { useDefinitions } from '@/api/schema';\nimport { canOnModel } from '@/helpers/modelPermissions';\nimport { useSchemaScopeAccess } from '@/hooks/useSchemaScopeAccess';\n\n/** What the signed-in admin may do in this place (the server checks every request again). */\nexport const usePlacePermissions = (model: ModelDefinition) => {\n const me = useMe().data;\n const { canCreateOnSite } = useSchemaScopeAccess();\n const shared = useDefinitions('model').data?.some(\n ({ definition, scope }) => definition.id === model.id && scope === 'network',\n );\n const canManageSchema = canOnModel(me, model.id, 'schemaManage');\n return {\n canCreate: canOnModel(me, model.id, 'create'),\n canUpdate: canOnModel(me, model.id, 'update'),\n canDelete: canOnModel(me, model.id, 'delete'),\n canPublish: model.draftAndPublish && canOnModel(me, model.id, 'publish'),\n canManageSchema,\n /**\n * The Structure and API tabs: for whoever manages the schema, and read-only for a site's schema admin\n * on a type shared with all sites (changing it needs a role on every site).\n */\n canSeeStructure: canManageSchema || (shared === true && canCreateOnSite),\n };\n};\n","import { useNavigate, useSearch } from '@tanstack/react-router';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Tabs as TabsRoot, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';\nimport { cn } from '@/helpers/cn';\nimport { PLACE_TABS, type PlaceTab } from '../constants';\n\nconst TAB_LABEL_KEYS = {\n entries: 'place.tabs.entries',\n structure: 'place.tabs.structure',\n api: 'place.tabs.api',\n} as const satisfies Record<PlaceTab, string>;\n\ntype TabsProps = {\n tab: PlaceTab;\n placeLabel: string;\n /** The place's key as it appears in the URL (`/content/$modelKey`). */\n modelKey: string;\n /** Each tab is a whole screen with its own header (the list, the builder, the document). */\n children: ReactNode;\n /**\n * The tab shows an entry document: its sticky top bar pulls itself up into the page gutter, so the panel\n * makes room for it under the tabs (the tabs scroll away; only the document's bar sticks).\n */\n document?: boolean;\n /**\n * Shown above one entry of a collection (`/content/$modelKey/$entryId` or `/new`): Entries goes back to\n * the list, and the other tabs open on the place without the entry's search.\n */\n entryPage?: boolean;\n};\n\n/**\n * Entries · Structure · API, for admins who manage the place's schema, above the place and above each of a\n * collection's entries. The tabs sit above each tab's own header because every tab is a full screen (the\n * builder and the document bring their own headers). The tab\n * lives in the URL (`?tab=`), so it is bookmarkable and the back button works.\n */\nexport const Tabs = ({\n tab,\n placeLabel,\n modelKey,\n children,\n document = false,\n entryPage = false,\n}: TabsProps) => {\n const { t } = useTranslation();\n const navigate = useNavigate({ from: '/content/$modelKey' });\n const { locale } = useSearch({ strict: false });\n const open = (value: PlaceTab) => {\n const next = value === 'entries' ? undefined : value;\n if (entryPage) {\n // From an entry: the place route itself, keeping only the locale.\n void navigate({ to: '/content/$modelKey', params: { modelKey }, search: { locale, tab: next } });\n return;\n }\n void navigate({ search: (previous) => ({ ...previous, tab: next }) });\n };\n return (\n <TabsRoot value={tab} onValueChange={(value) => open(value as PlaceTab)} className=\"gap-6\">\n <TabsList variant=\"underline\" aria-label={t('place.tabs.label', { place: placeLabel })}>\n {PLACE_TABS.map((key) => (\n <TabsTrigger\n key={key}\n value={key}\n // On an entry page Entries is the selected tab: selecting it again goes back to the list.\n onClick={entryPage && key === tab ? () => open(key) : undefined}\n >\n {t(TAB_LABEL_KEYS[key])}\n </TabsTrigger>\n ))}\n </TabsList>\n <TabsContent value={tab} className={cn('min-w-0', document && 'pt-7')}>\n {children}\n </TabsContent>\n </TabsRoot>\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport type { ReactNode } from 'react';\nimport { usePlacePermissions } from '../Place/hooks/usePlacePermissions';\nimport { Tabs } from '../Place/Tabs';\n\ntype EntryFrameProps = {\n model: ModelDefinition;\n /** The place's key as it appears in the URL. */\n modelKey: string;\n children: ReactNode;\n};\n\n/**\n * One entry of a collection inside its place: for admins who see the place's Structure, the Entries ·\n * Structure · API tabs sit above the entry, as they do above a single type's document. Everyone else gets\n * the entry alone.\n */\nexport const EntryFrame = ({ model, modelKey, children }: EntryFrameProps) => {\n const { canSeeStructure } = usePlacePermissions(model);\n return canSeeStructure ? (\n <Tabs tab=\"entries\" placeLabel={model.label} modelKey={modelKey} document entryPage>\n {children}\n </Tabs>\n ) : (\n children\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useLocales } from '@/api/locales';\n\n/**\n * The instance's locales, the default one, and the locale a screen edits (null for non-localized models).\n * `error` only when nothing loaded: a failed refetch keeps the list (and the screen) it had.\n */\nexport const useContentLocales = (model: ModelDefinition | undefined, requested: string | undefined) => {\n const locales = useLocales();\n const list = locales.data ?? [];\n const defaultLocale = list.find((locale) => locale.isDefault)?.code;\n const known = requested && list.some((locale) => locale.code === requested) ? requested : undefined;\n const current = model?.localized ? (known ?? defaultLocale ?? null) : null;\n const labelOf = (code: string) => list.find((locale) => locale.code === code)?.label ?? code;\n return {\n locales: list,\n defaultLocale,\n current,\n labelOf,\n isPending: locales.isPending,\n error: locales.data ? null : locales.error,\n };\n};\n","import type { ReactNode } from 'react';\n\ntype DrawerSectionProps = { id: string; title: string; children: ReactNode };\n\n/** A section of the settings drawer: a 12px uppercase heading and compact rows. */\nexport const DrawerSection = ({ id, title, children }: DrawerSectionProps) => (\n <section aria-labelledby={id} className=\"scroll-mt-4 space-y-2\" data-drawer-section={id}>\n <h3 id={id} className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n {title}\n </h3>\n {children}\n </section>\n);\n","import type { FieldDefinition } from '@shapio/schema';\nimport { useId, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useMediaAsset, useUpdateMediaAsset } from '@/api/media';\nimport { FocalPoint } from '@/components/FocalPoint';\nimport { FormError } from '@/components/FormError';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { SuggestAltButton } from '@/components/SuggestAltButton';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { useFieldsEnvironment } from '@/fields/form/context';\nimport { useTopLevelValue } from '@/fields/hooks/useTopLevelValue';\nimport { useMediaPermissions } from '@/hooks/useMediaPermissions';\nimport { DrawerSection } from '../DrawerSection';\n\ntype CoverSettingsProps = { field: FieldDefinition };\n\n/**\n * The cover's alt text and focal point. Both belong to the file in the library (shared by every use), so\n * they save to the asset at once, not with the entry.\n */\nexport const CoverSettings = ({ field }: CoverSettingsProps) => {\n const { t } = useTranslation();\n const altId = useId();\n const { readOnly, locale } = useFieldsEnvironment();\n const { canWrite } = useMediaPermissions();\n const { value } = useTopLevelValue(field);\n const asset = useMediaAsset(typeof value === 'string' ? value : undefined);\n const update = useUpdateMediaAsset();\n const [alt, setAlt] = useState<string | undefined>();\n if (!asset.data) {\n return null;\n }\n const current = asset.data;\n const editable = canWrite && !readOnly;\n return (\n <DrawerSection id=\"entry-settings-cover\" title={t('entry.settings.cover', { field: field.label })}>\n <form\n className=\"space-y-2\"\n onSubmit={(event) => {\n event.preventDefault();\n if (alt !== undefined) {\n update.mutate(\n { id: current.id, input: { expectedVersion: current.version, alt } },\n { onSuccess: () => setAlt(undefined) },\n );\n }\n }}\n >\n <Label htmlFor={altId}>{t('content.media.altLabel')}</Label>\n <div className=\"flex gap-2\">\n <Input\n id={altId}\n value={alt ?? current.alt}\n readOnly={!editable}\n placeholder={t('content.richText.altPlaceholder')}\n aria-describedby={`${altId}-hint`}\n onChange={(event) => setAlt(event.target.value)}\n />\n {editable ? (\n <SubmitButton\n size=\"default\"\n pending={update.isPending}\n pendingLabel={t('common.saving')}\n disabled={alt === undefined || alt === current.alt}\n >\n {t('content.form.save')}\n </SubmitButton>\n ) : null}\n </div>\n <p id={`${altId}-hint`} className=\"text-meta text-muted-foreground\">\n {t('content.media.altHint')}\n </p>\n {editable ? (\n <SuggestAltButton\n assetId={current.id}\n mimeType={current.mimeType}\n locale={locale}\n onSuggest={setAlt}\n />\n ) : null}\n </form>\n {editable && current.mimeType.startsWith('image/') ? (\n <FocalPoint\n imageUrl={current.url}\n value={current.focalPoint}\n onChange={(focalPoint) =>\n update.mutate({ id: current.id, input: { expectedVersion: current.version, focalPoint } })\n }\n />\n ) : null}\n <FormError error={update.error} />\n </DrawerSection>\n );\n};\n","import { Copy, Trash2, Undo2 } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { Button } from '@/components/ui/button';\nimport { DrawerSection } from '../DrawerSection';\n\ntype DangerZoneProps = {\n title: string;\n /** Present while this locale is live. */\n onUnpublish?: () => Promise<unknown>;\n onDuplicate?: () => void;\n onDelete?: () => Promise<unknown>;\n};\n\n/** Taking the entry offline, copying it, deleting it: each consequential one confirmed in place. */\nexport const DangerZone = ({ title, onUnpublish, onDuplicate, onDelete }: DangerZoneProps) => {\n const { t } = useTranslation();\n if (!onUnpublish && !onDuplicate && !onDelete) {\n return null;\n }\n return (\n <DrawerSection id=\"entry-settings-danger\" title={t('entry.settings.danger')}>\n <div className=\"flex flex-wrap gap-2\">\n {onUnpublish ? (\n <InlineConfirm\n tone=\"default\"\n align=\"start\"\n title={t('entry.settings.unpublishTitle')}\n description={t('entry.settings.unpublishDescription')}\n confirmLabel={t('content.actions.unpublish')}\n onConfirm={onUnpublish}\n trigger={\n <Button type=\"button\" variant=\"outline\" size=\"sm\">\n <Undo2 aria-hidden=\"true\" />\n {t('content.actions.unpublish')}\n </Button>\n }\n />\n ) : null}\n {onDuplicate ? (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={onDuplicate}>\n <Copy aria-hidden=\"true\" />\n {t('content.actions.duplicate')}\n </Button>\n ) : null}\n {onDelete ? (\n <InlineConfirm\n tone=\"danger\"\n align=\"start\"\n title={t('content.form.deleteTitle', { title })}\n description={t('content.form.deleteDescription')}\n confirmLabel={t('common.delete')}\n onConfirm={onDelete}\n trigger={\n <Button type=\"button\" variant=\"destructive-ghost\" size=\"sm\">\n <Trash2 aria-hidden=\"true\" />\n {t('content.actions.delete')}\n </Button>\n }\n />\n ) : null}\n </div>\n </DrawerSection>\n );\n};\n","import type { FieldDefinition, SchemaDefinition } from '@shapio/schema';\nimport { memo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Label } from '@/components/ui/label';\nimport { cn } from '@/helpers/cn';\nimport { FieldEditor } from '../FieldEditor';\nimport { FieldMessages } from '../FieldMessages';\nimport { useFieldControl } from '../hooks/useFieldControl';\nimport { ScopeIcon } from '../ScopeIcon';\n\ntype CanvasBlockProps = {\n field: FieldDefinition;\n owner: SchemaDefinition;\n value: unknown;\n onChange: (value: unknown) => void;\n path: string;\n /** The model is localized: show whether this field is per locale or shared. */\n showScope: boolean;\n};\n\n/**\n * One canvas field of the entry document. Never a form label: a heading (the field's name in small caps\n * and a hairline) always sits above it, so people see where Body ends and Sections begin, two lists of the\n * same component tell apart, and an empty field is still there to fill; it also names the editor for\n * assistive technology. Built-in editors render in `canvas` appearance; a project's custom editor keeps its\n * contract inside a card.\n */\nexport const CanvasBlock = memo(({ field, owner, value, onChange, path, showScope }: CanvasBlockProps) => {\n const { t } = useTranslation();\n const control = useFieldControl({ field, owner, value, onChange, path, appearance: 'canvas' });\n const custom = control.resolved.kind === 'runtime';\n const LabelElement = control.labelling === 'input' ? Label : 'span';\n return (\n <div\n role=\"group\"\n aria-labelledby={control.labelId}\n id={`${control.inputId}-section`}\n data-field-path={path}\n data-canvas-field={field.type}\n className=\"relative min-w-0 scroll-mt-24 space-y-2\"\n >\n <div\n className=\"flex items-center gap-2 text-xs font-semibold text-muted-foreground\"\n data-canvas-heading\n >\n <LabelElement\n id={control.labelId}\n {...(control.labelling === 'input' ? { htmlFor: control.inputId } : {})}\n className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\"\n >\n {field.label}\n {field.required ? (\n <>\n <span aria-hidden=\"true\" className=\"ml-0.5 text-destructive\">\n *\n </span>\n <span className=\"sr-only\">{t('content.fields.required')}</span>\n </>\n ) : null}\n </LabelElement>\n {showScope ? <ScopeIcon localized={field.localized} /> : null}\n <span aria-hidden=\"true\" className=\"h-px flex-1 bg-border\" />\n </div>\n <div className={cn(custom && 'rounded-xl border bg-card p-4')}>\n <FieldEditor control={control} />\n </div>\n <FieldMessages field={field} control={control} />\n </div>\n );\n});\n\nCanvasBlock.displayName = 'CanvasBlock';\n","import { Boxes, ImagePlus, Plus } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { useDeferredMenuAction } from '@/fields/hooks/useDeferredMenuAction';\nimport { InsertMenuItem } from '@/fields/InsertMenuItem';\nimport { BlockMenuItems } from '@/fields/RichTextField/canvas/BlockMenuItems';\nimport { cn } from '@/helpers/cn';\nimport type { Edge, FieldInsertions, useCanvasInsertions } from '../hooks/useCanvasInsertions';\n\ntype Target = { insertions: FieldInsertions; edge: Edge };\n\ntype BoundaryInserterProps = {\n /** The end of the field above and the start of the field below (either may be missing). */\n targets: readonly Target[];\n actions: ReturnType<typeof useCanvasInsertions>;\n /** The last one: always visible (\"Add a block, or just keep writing\"), not only on hover. */\n final: boolean;\n};\n\nconst GroupLabel = ({ children }: { children: string }) => (\n <DropdownMenuLabel className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n {children}\n </DropdownMenuLabel>\n);\n\n/**\n * The `+` between two canvas fields (and after the last): offers exactly what can be stored there, the\n * block types of a rich-text field and the components of a zone or list, labelled by field when both meet.\n */\nexport const BoundaryInserter = ({ targets, actions, final }: BoundaryInserterProps) => {\n const { t } = useTranslation();\n const menu = useDeferredMenuAction();\n const usable = targets.filter(({ insertions }) => insertions.kind !== 'none');\n if (usable.length === 0) {\n return null;\n }\n const several = usable.length > 1;\n return (\n <div\n className={cn('group/boundary relative flex items-center font-sans', final ? 'pt-2' : 'h-6')}\n data-boundary\n >\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n {final ? (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" className=\"-ml-2 text-muted-foreground\">\n <Plus aria-hidden=\"true\" />\n {t('entry.blocks.addBlock')}\n </Button>\n ) : (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon-xs\"\n className=\"relative z-10 rounded-full bg-background opacity-0 transition-opacity group-hover/boundary:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100\"\n aria-label={t('entry.blocks.addBetween', {\n fields: usable.map(({ insertions }) => insertions.field.label).join(', '),\n })}\n >\n <Plus aria-hidden=\"true\" />\n </Button>\n )}\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"start\"\n className=\"max-h-96 w-80 overflow-y-auto\"\n onCloseAutoFocus={menu.onCloseAutoFocus}\n >\n {usable.map(({ insertions, edge }, index) => (\n <DropdownMenuGroup key={`${insertions.field.id}-${edge}`}>\n {index > 0 ? <DropdownMenuSeparator /> : null}\n {insertions.kind === 'richText' ? (\n <BlockMenuItems\n heading={several ? insertions.field.label : undefined}\n onSelect={(type) => menu.defer(() => actions.insertBlock(insertions.field, type, edge))}\n />\n ) : insertions.kind === 'components' ? (\n <>\n <GroupLabel>\n {several\n ? t('entry.blocks.groupIn', {\n group: t('entry.blocks.groupComponents'),\n field: insertions.field.label,\n })\n : t('entry.blocks.groupComponents')}\n </GroupLabel>\n {insertions.components.map((component) => (\n <InsertMenuItem\n key={component.id}\n icon={Boxes}\n label={component.label}\n onSelect={() =>\n menu.defer(() => actions.insertComponent(insertions.field, component, edge))\n }\n />\n ))}\n </>\n ) : insertions.kind === 'files' ? (\n <>\n <GroupLabel>{insertions.field.label}</GroupLabel>\n <InsertMenuItem\n icon={ImagePlus}\n label={t('entry.blocks.addFiles', { field: insertions.field.label })}\n onSelect={() => menu.defer(() => void actions.insertFiles(insertions.field, edge))}\n />\n </>\n ) : null}\n </DropdownMenuGroup>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n {final ? null : (\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-x-0 top-1/2 h-px bg-border opacity-0 transition-opacity group-hover/boundary:opacity-100\"\n />\n )}\n </div>\n );\n};\n","import { isCanvasEligible, type ComponentDefinition, type FieldDefinition } from '@shapio/schema';\nimport { useCallback } from 'react';\nimport { useCanvasHandles } from '@/fields/form/canvasHandles';\nimport { useEntryFormStore, useFieldsEnvironment } from '@/fields/form/context';\nimport { newComponentItem } from '@/fields/helpers/formValues';\nimport { toList, type ItemValues } from '@/fields/helpers/values';\nimport { allowedComponentsOf } from '@/fields/hooks/useAllowedComponents';\nimport type { BlockType } from '@/fields/RichTextField/canvas/blocks';\nimport { reportError } from '@/helpers/reportError';\n\nexport type Edge = 'start' | 'end';\n\n/** What a canvas field can take at its start or end. */\nexport type FieldInsertions =\n | { kind: 'richText'; field: FieldDefinition }\n | { kind: 'components'; field: FieldDefinition; components: ComponentDefinition[] }\n | { kind: 'files'; field: FieldDefinition }\n | { kind: 'none'; field: FieldDefinition };\n\nconst listMax = (field: FieldDefinition) =>\n field.type === 'dynamiczone' || field.type === 'component' || field.type === 'media'\n ? 'max' in field.settings\n ? field.settings.max\n : undefined\n : undefined;\n\n/**\n * The canvas's boundary inserters: what each field can store at its start or end (rich-text blocks,\n * allowed components, files), and doing it, through the field's registered editor (rich text) or the value\n * itself (lists). A full list offers nothing.\n */\nexport const useCanvasInsertions = () => {\n const store = useEntryFormStore();\n const handles = useCanvasHandles();\n const { components, pickMedia, readOnly, disabled } = useFieldsEnvironment();\n\n const insertionsOf = useCallback(\n (field: FieldDefinition): FieldInsertions => {\n // Only block fields take blocks: a single component or file placed in the document holds one value.\n if (readOnly || disabled || !isCanvasEligible(field)) {\n return { kind: 'none', field };\n }\n const count = toList(store.getState().values[field.apiKey]).length;\n const max = listMax(field);\n const full = max !== undefined && count >= max;\n if (field.type === 'richtext') {\n return { kind: 'richText', field };\n }\n if ((field.type === 'dynamiczone' || field.type === 'component') && !full) {\n return { kind: 'components', field, components: allowedComponentsOf(field, components) };\n }\n if (field.type === 'media' && !full) {\n return { kind: 'files', field };\n }\n return { kind: 'none', field };\n },\n [store, components, readOnly, disabled],\n );\n\n const putInList = useCallback(\n (field: FieldDefinition, edge: Edge, added: unknown[]) => {\n const current = toList(store.getState().values[field.apiKey]);\n store\n .getState()\n .setValue(field.apiKey, edge === 'start' ? [...added, ...current] : [...current, ...added]);\n },\n [store],\n );\n\n const insertBlock = useCallback(\n (field: FieldDefinition, type: BlockType, edge: Edge) =>\n void handles?.get(`/${field.apiKey}`)?.insertBlock(type, edge),\n [handles],\n );\n\n const insertComponent = useCallback(\n (field: FieldDefinition, component: ComponentDefinition, edge: Edge) => {\n const item: ItemValues = newComponentItem(component, field.type === 'dynamiczone');\n putInList(field, edge, [item]);\n },\n [putInList],\n );\n\n const insertFiles = useCallback(\n async (field: FieldDefinition, edge: Edge) => {\n try {\n const allowedKinds = field.type === 'media' ? field.settings.allowedKinds : undefined;\n const picked = await pickMedia({ multiple: true, ...(allowedKinds ? { allowedKinds } : {}) });\n const current = toList<string>(store.getState().values[field.apiKey]);\n const added = (picked ?? []).map((asset) => asset.id).filter((id) => !current.includes(id));\n if (added.length > 0) {\n putInList(field, edge, added);\n }\n } catch (error) {\n reportError(error, 'adding files to the canvas');\n }\n },\n [pickMedia, putInList, store],\n );\n\n return { insertionsOf, insertBlock, insertComponent, insertFiles };\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { Fragment, memo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { CanvasBlock } from '@/fields/CanvasBlock';\nimport { CanvasHandlesContext, type CanvasHandles } from '@/fields/form/canvasHandles';\nimport { useEntryForm, useFieldsEnvironment } from '@/fields/form/context';\nimport { useTopLevelValue } from '@/fields/hooks/useTopLevelValue';\nimport { BoundaryInserter } from '../BoundaryInserter';\nimport { useCanvasInsertions } from '../hooks/useCanvasInsertions';\n\ntype CanvasProps = { fields: readonly FieldDefinition[] };\n\nconst CanvasField = memo(({ field }: { field: FieldDefinition }) => {\n const { model } = useFieldsEnvironment();\n const { value, onChange } = useTopLevelValue(field);\n return (\n <CanvasBlock\n field={field}\n owner={model}\n value={value}\n onChange={onChange}\n path={`/${field.apiKey}`}\n showScope={model.localized}\n />\n );\n});\n\nCanvasField.displayName = 'CanvasField';\n\n/**\n * The writing surface: the model's canvas fields in order, each owning its blocks (stored formats are\n * unchanged, and blocks never move between fields). Between fields, and after the last, a `+` offers what\n * can be stored there.\n */\nexport const Canvas = ({ fields }: CanvasProps) => {\n const { t } = useTranslation();\n const [handles] = useState<CanvasHandles>(() => new Map());\n return (\n <CanvasHandlesContext.Provider value={handles}>\n <section aria-label={t('entry.canvas.label')} className=\"space-y-2\" data-canvas>\n <CanvasFields fields={fields} />\n </section>\n </CanvasHandlesContext.Provider>\n );\n};\n\nconst CanvasFields = ({ fields }: CanvasProps) => {\n const actions = useCanvasInsertions();\n // Re-read what fits whenever values change (a list reaching its max offers nothing more).\n useEntryForm((state) => state.values);\n return fields.map((field, index) => {\n const next = fields[index + 1];\n return (\n <Fragment key={field.id}>\n <CanvasField field={field} />\n <BoundaryInserter\n actions={actions}\n final={next === undefined}\n targets={[\n { insertions: actions.insertionsOf(field), edge: 'end' },\n ...(next ? [{ insertions: actions.insertionsOf(next), edge: 'start' as const }] : []),\n ]}\n />\n </Fragment>\n );\n });\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { Crosshair, ImagePlus, Loader2, RefreshCw, Trash2 } from 'lucide-react';\nimport { useEffect, useRef, useState, type CSSProperties, type DragEvent } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useMediaAsset } from '@/api/media';\nimport { Button } from '@/components/ui/button';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport { FieldMessages } from '@/fields/FieldMessages';\nimport { useFieldsEnvironment } from '@/fields/form/context';\nimport { useFieldControl } from '@/fields/hooks/useFieldControl';\nimport { useTopLevelValue } from '@/fields/hooks/useTopLevelValue';\nimport { cn } from '@/helpers/cn';\nimport { logError, reportError } from '@/helpers/reportError';\n\ntype CoverProps = {\n field: FieldDefinition;\n /** Opens the settings drawer at the cover's alt text and focal point. */\n onEditDetails: () => void;\n};\n\nconst COVER_VARIANTS = ['w1280', 'w640'];\nconst PERCENT = 100;\n\nconst coverId = (value: unknown) => (typeof value === 'string' ? value : undefined);\n\n/**\n * The cover image above the title: full width, cropped around its focal point, with Replace / Focal point /\n * Remove on hover or focus. A file dropped onto it replaces it (uploaded to the library). Empty: a dashed\n * \"Add a cover\" band that also takes a drop.\n */\nexport const Cover = ({ field, onEditDetails }: CoverProps) => {\n const { t } = useTranslation();\n const { model, readOnly, disabled, pickMedia, uploadMedia } = useFieldsEnvironment();\n const { value, onChange } = useTopLevelValue(field);\n const path = `/${field.apiKey}`;\n const control = useFieldControl({ field, owner: model, value, onChange, path });\n const id = coverId(value);\n const asset = useMediaAsset(id);\n const [dropping, setDropping] = useState(false);\n const [uploading, setUploading] = useState(false);\n // After choosing from the band, focus lands on Replace (the band itself is gone).\n const [focusReplace, setFocusReplace] = useState(false);\n const replaceRef = useRef<HTMLButtonElement>(null);\n useEffect(() => {\n if (focusReplace && id && replaceRef.current) {\n replaceRef.current.focus();\n setFocusReplace(false);\n }\n }, [focusReplace, id]);\n const editable = !readOnly && !disabled;\n const url =\n COVER_VARIANTS.map(\n (name) => asset.data?.variants.find((variant) => variant.name === name && variant.url)?.url,\n ).find(Boolean) ?? asset.data?.url;\n const choose = async () => {\n try {\n const picked = await pickMedia({ multiple: false, allowedKinds: ['image'] });\n const first = picked?.[0];\n if (first) {\n onChange(first.id);\n control.builtInProps.onBlur();\n setFocusReplace(true);\n }\n } catch (error) {\n reportError(error, 'choosing a cover');\n }\n };\n const drop = async (event: DragEvent) => {\n setDropping(false);\n const file = [...event.dataTransfer.files].find((candidate) => candidate.type.startsWith('image/'));\n if (!file || !uploadMedia || !editable) {\n return;\n }\n event.preventDefault();\n setUploading(true);\n try {\n onChange((await uploadMedia(file)).id);\n } catch (error) {\n logError(error, `uploading ${file.name} as a cover`);\n toast.error(t('entry.upload.failed', { name: file.name }));\n } finally {\n setUploading(false);\n }\n };\n const dropProps = {\n onDragOver: (event: DragEvent) => {\n if (editable && uploadMedia && event.dataTransfer.types.includes('Files')) {\n event.preventDefault();\n setDropping(true);\n }\n },\n onDragLeave: () => setDropping(false),\n onDrop: (event: DragEvent) => void drop(event),\n };\n const focal = asset.data?.focalPoint ?? { x: 0.5, y: 0.5 };\n return (\n <div className=\"space-y-1\" data-field-path={path} id={`${control.inputId}-section`}>\n <span id={control.labelId} className=\"sr-only\">\n {field.label}\n </span>\n {id ? (\n <div\n role=\"group\"\n aria-labelledby={control.labelId}\n className={cn(\n 'group/cover relative overflow-hidden rounded-xl bg-muted',\n dropping && 'ring-[3px] ring-ring/50',\n )}\n {...dropProps}\n >\n {asset.isPending || uploading ? (\n <Skeleton className=\"h-56 w-full sm:h-72\" />\n ) : url ? (\n <img\n src={url}\n alt={asset.data?.alt ?? ''}\n className=\"h-56 w-full object-cover object-(--focal) sm:h-72\"\n style={{ '--focal': `${focal.x * PERCENT}% ${focal.y * PERCENT}%` } as CSSProperties}\n />\n ) : (\n <div className=\"flex h-56 items-center justify-center text-sm text-muted-foreground sm:h-72\">\n {t('content.media.missing')}\n </div>\n )}\n {editable ? (\n <div className=\"absolute right-3 bottom-3 flex flex-wrap gap-1.5 opacity-0 transition-opacity group-focus-within/cover:opacity-100 group-hover/cover:opacity-100 max-lg:opacity-100\">\n <Button\n ref={replaceRef}\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => void choose()}\n >\n <RefreshCw aria-hidden=\"true\" />\n {t('entry.cover.replace')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"secondary\" onClick={onEditDetails}>\n <Crosshair aria-hidden=\"true\" />\n {t('entry.cover.details')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"secondary\" onClick={() => onChange(null)}>\n <Trash2 aria-hidden=\"true\" />\n {t('entry.cover.remove')}\n </Button>\n </div>\n ) : null}\n </div>\n ) : editable ? (\n <button\n id={control.inputId}\n type=\"button\"\n aria-describedby={control.builtInProps.describedBy}\n onClick={() => void choose()}\n {...dropProps}\n className={cn(\n 'flex h-20 w-full items-center justify-center gap-2 rounded-xl border border-dashed text-sm text-muted-foreground outline-none hover:bg-muted/50 hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50',\n dropping && 'bg-muted/50 ring-[3px] ring-ring/50',\n )}\n >\n {uploading ? (\n <Loader2 aria-hidden=\"true\" className=\"size-4 animate-spin\" />\n ) : (\n <ImagePlus aria-hidden=\"true\" className=\"size-4\" />\n )}\n {uploadMedia\n ? t('entry.cover.addOrDrop', { field: field.label })\n : t('entry.cover.add', { field: field.label })}\n </button>\n ) : null}\n <FieldMessages field={field} control={control} />\n </div>\n );\n};\n","import { isSeoField, stripFieldsOf, type DocumentLayout, type FieldDefinition } from '@shapio/schema';\nimport { isEmptyValue } from '@/fields/helpers/values';\n\n/**\n * The strip's properties for these values: the configured ones, or the first five worth seeing at once —\n * required ones (what blocks publishing), ones with a value, and the SEO group even while empty, which\n * otherwise only showed behind \"+N more\" and read as missing.\n */\nexport const stripFieldsFor = (\n layout: DocumentLayout,\n values: Readonly<Record<string, unknown>>,\n): FieldDefinition[] =>\n stripFieldsOf(\n layout,\n (field) => field.required || isSeoField(field) || !isEmptyValue(values[field.apiKey]),\n );\n","import {\n effectiveTitleField,\n richTextBodyOf,\n type FieldDefinition,\n type ModelDefinition,\n} from '@shapio/schema';\n\n/**\n * A field \"Summarize from body\" can fill (the server's rule, services/assist/summarize.ts): a live string or\n * text field, not the title, of a model with a rich-text body (`richTextBodyOf`: the document's rich-text\n * canvas fields, or every rich-text field of a form).\n */\nexport const isSummarizable = (model: ModelDefinition, field: FieldDefinition) =>\n (field.type === 'string' || field.type === 'text') &&\n !field.deprecated &&\n effectiveTitleField(model)?.apiKey !== field.apiKey &&\n richTextBodyOf(model).length > 0;\n","import type { FieldDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { useMediaAsset } from '@/api/media';\nimport { useFieldsEnvironment } from '@/fields/form/context';\nimport { summarizeValue } from '@/fields/helpers/summary';\nimport { entryTitle, shortId } from '@/fields/helpers/titles';\nimport { isEmptyValue, toList } from '@/fields/helpers/values';\nimport { useEntryLabels } from '@/fields/hooks/useEntryLabels';\nimport { formatDateTime } from '@/helpers/formatDate';\n\ntype PropertyValueProps = { field: FieldDefinition; value: unknown };\n\nconst SHOWN_LINKS = 2;\n\nconst RelationValue = ({ field, value }: PropertyValueProps) => {\n const { t } = useTranslation();\n const { models, locale } = useFieldsEnvironment();\n const target = field.type === 'relation' ? models.get(field.settings.target) : undefined;\n const ids = toList<string>(value).filter((id): id is string => typeof id === 'string');\n const labels = useEntryLabels(target, ids, locale);\n if (!target) {\n // A target missing from the readable registry is one this role can't read (see RelationField).\n return (\n <span className=\"text-muted-foreground\">\n {t('content.relation.unreadableLinks', { count: ids.length })}\n </span>\n );\n }\n const names = ids.map((id) => {\n const item = labels.byId.get(id);\n return (item ? entryTitle(target, item.data) : undefined) ?? `${t('content.untitled')} · ${shortId(id)}`;\n });\n const shown = names.slice(0, SHOWN_LINKS).join(', ');\n return (\n <>\n {names.length > SHOWN_LINKS\n ? t('entry.properties.andMore', { list: shown, count: names.length - SHOWN_LINKS })\n : shown}\n </>\n );\n};\n\nconst MediaValue = ({ value }: { value: unknown }) => {\n const ids = toList<string>(value).filter((id): id is string => typeof id === 'string');\n const first = useMediaAsset(ids[0]);\n const name = first.data?.filename ?? '';\n return <>{ids.length > 1 ? `${name} +${ids.length - 1}` : name}</>;\n};\n\n/**\n * A property's value as one short line (strip chips, drawer rows): titles of linked entries, file names,\n * dates in the viewer's time, choice labels, Yes/No. Empty shows a muted \"Empty\".\n */\nexport const PropertyValue = ({ field, value }: PropertyValueProps) => {\n const { t } = useTranslation();\n if (isEmptyValue(value)) {\n return <span className=\"text-muted-foreground\">{t('entry.properties.empty')}</span>;\n }\n switch (field.type) {\n case 'relation':\n return <RelationValue field={field} value={value} />;\n case 'media':\n return <MediaValue value={value} />;\n case 'boolean':\n return <>{value === true ? t('content.fields.yes') : t('content.fields.no')}</>;\n case 'datetime':\n return <>{typeof value === 'string' ? formatDateTime(value) : ''}</>;\n case 'component':\n case 'dynamiczone':\n return <>{t('entry.properties.items', { count: toList(value).length })}</>;\n default:\n return <>{summarizeValue(field, value)}</>;\n }\n};\n","import type { SaveBeforeAssist } from '../hooks/useAssistTarget';\n\n/** Why an entry assist didn't run: the changes have to be saved first, or saving them failed. */\nexport const SAVE_BEFORE_ASSIST_KEYS = {\n saveFirst: 'assist.saveFirst',\n failed: 'assist.saveFailed',\n} as const satisfies Record<Exclude<SaveBeforeAssist, 'ready'>, string>;\n","import type { ModelDefinition } from '@shapio/schema';\nimport { createContext, useCallback, useContext, useMemo } from 'react';\nimport { useFieldsEnvironment } from '@/fields/form/context';\nimport type { EntryFormStore } from '@/fields/form/store';\nimport { dirtyKeysOf } from '@/fields/helpers/formValues';\nimport type { EntryMode } from '../types';\nimport type { SaveKind, SaveOutcome } from './useEntrySaver';\n\n/**\n * Whether the server's copy is current before an assist reads it (summarize and translate read the saved\n * draft): `ready`, `saveFirst` (unsaved changes on a model without drafts, where saving publishes, so the\n * person saves), or `failed` (the save didn't go through).\n */\nexport type SaveBeforeAssist = 'ready' | 'saveFirst' | 'failed';\n\ntype AssistDocument = { saveIfDirty: () => Promise<SaveBeforeAssist> };\n\n/** Provided by the entry document (Entry/index.tsx) only for an entry whose locale exists (edit mode). */\nexport const AssistDocumentContext = createContext<AssistDocument | null>(null);\n\ntype AssistDocumentOptions = {\n model: ModelDefinition;\n mode: EntryMode;\n store: EntryFormStore;\n save: (kind: SaveKind) => Promise<SaveOutcome>;\n};\n\n/**\n * The entry document's side of the assist target: unsaved changes are saved as a draft (the autosave\n * path: no revision, no `required` check) before an assist reads the entry. Null outside edit mode.\n */\nexport const useAssistDocument = ({ model, mode, store, save }: AssistDocumentOptions) => {\n const saveIfDirty = useCallback(async (): Promise<SaveBeforeAssist> => {\n const { values, baseline } = store.getState();\n if (dirtyKeysOf(values, baseline).length === 0) {\n return 'ready';\n }\n if (!model.draftAndPublish) {\n return 'saveFirst';\n }\n const outcome = await save('autosave');\n return outcome === 'saved' || outcome === 'unchanged' ? 'ready' : 'failed';\n }, [model.draftAndPublish, store, save]);\n return useMemo(() => (mode.kind === 'edit' ? { saveIfDirty } : null), [mode.kind, saveIfDirty]);\n};\n\nexport type AssistTarget = {\n modelKey: string;\n entryId: string;\n locale: string | null;\n saveIfDirty: () => Promise<SaveBeforeAssist>;\n};\n\n/**\n * What an entry-scoped assist (summarize, translate) acts on: the entry open in the document, in its\n * locale. Null outside an editable, existing entry (a new entry, a locale not started, read-only).\n */\nexport const useAssistTarget = (): AssistTarget | null => {\n const environment = useFieldsEnvironment();\n const assistDocument = useContext(AssistDocumentContext);\n const { model, entryId, locale, readOnly } = environment;\n return useMemo(\n () =>\n assistDocument && entryId && !readOnly\n ? { modelKey: model.apiKey, entryId, locale, saveIfDirty: assistDocument.saveIfDirty }\n : null,\n [assistDocument, entryId, readOnly, model.apiKey, locale],\n );\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { useState } from 'react';\nimport { useSummarizeField } from '@/api/assist';\nimport { useTopLevelValue } from '@/fields/hooks/useTopLevelValue';\nimport { useAssistTarget, type SaveBeforeAssist } from './useAssistTarget';\n\n/**\n * \"Summarize from body\" for one property: saves unsaved changes first (the server reads the saved draft),\n * then fills the field with the summary as an ordinary edit the person reviews and saves.\n */\nexport const useSummarizeIntoField = (field: FieldDefinition) => {\n const target = useAssistTarget();\n const { onChange } = useTopLevelValue(field);\n const summarize = useSummarizeField();\n const [preparing, setPreparing] = useState(false);\n const [blocked, setBlocked] = useState<Exclude<SaveBeforeAssist, 'ready'> | null>(null);\n const [truncated, setTruncated] = useState(false);\n const run = async () => {\n if (!target) {\n return;\n }\n setBlocked(null);\n setTruncated(false);\n summarize.reset();\n setPreparing(true);\n const prepared = await target.saveIfDirty().finally(() => setPreparing(false));\n if (prepared !== 'ready') {\n setBlocked(prepared);\n return;\n }\n summarize.mutate(\n {\n modelKey: target.modelKey,\n entryId: target.entryId,\n fieldApiKey: field.apiKey,\n ...(target.locale ? { locale: target.locale } : {}),\n },\n {\n onSuccess: (result) => {\n onChange(result.text);\n setTruncated(result.truncated);\n },\n },\n );\n };\n return {\n available: target !== null,\n run: () => void run(),\n pending: preparing || summarize.isPending,\n error: summarize.error,\n blocked,\n truncated,\n };\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { AssistButton } from '@/components/AssistButton';\nimport { AssistError } from '@/components/AssistError';\nimport { InfoHint } from '@/components/InfoHint';\nimport { SAVE_BEFORE_ASSIST_KEYS } from '../helpers/assistMessages';\nimport { useSummarizeIntoField } from '../hooks/useSummarizeIntoField';\n\ntype SummarizeActionProps = { field: FieldDefinition };\n\n/** \"Summarize from body\" under a summarizable property's editor: fills it with a proposal to review. */\nexport const SummarizeAction = ({ field }: SummarizeActionProps) => {\n const { t } = useTranslation();\n const summarize = useSummarizeIntoField(field);\n if (!summarize.available) {\n return null;\n }\n return (\n <div className=\"mt-3 space-y-1 border-t pt-3\">\n <div className=\"flex items-center gap-1\">\n <AssistButton pending={summarize.pending} pendingLabel={t('assist.working')} onClick={summarize.run}>\n {t('assist.summarize.run')}\n </AssistButton>\n <InfoHint about={t('assist.summarize.run')}>{t('assist.summarize.hint')}</InfoHint>\n </div>\n {summarize.blocked ? (\n <p role=\"alert\" className=\"text-meta text-destructive\">\n {t(SAVE_BEFORE_ASSIST_KEYS[summarize.blocked])}\n </p>\n ) : null}\n <AssistError error={summarize.error} />\n {summarize.truncated ? (\n <p className=\"text-meta text-muted-foreground\">{t('assist.truncated')}</p>\n ) : null}\n </div>\n );\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { CircleAlert } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useAssistEnabled } from '@/api/assist';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { useEntryForm, useFieldsEnvironment } from '@/fields/form/context';\nimport { TopLevelField } from '@/fields/form/TopLevelField';\nimport { countIssuesUnder, issuesByPath } from '@/fields/helpers/issues';\nimport { useTopLevelValue } from '@/fields/hooks/useTopLevelValue';\nimport { ScopeIcon } from '@/fields/ScopeIcon';\nimport { cn } from '@/helpers/cn';\nimport { isSummarizable } from '../helpers/assistEligibility';\nimport { PropertyValue } from '../PropertyValue';\nimport { SummarizeAction } from '../SummarizeAction';\n\ntype PropertyChipProps = { field: FieldDefinition };\n\n/**\n * One property in the strip under the title: its name and value as a quiet chip. Clicking edits it in\n * place, in a popover anchored to the chip with the field's own editor. Problems mark the chip.\n */\nexport const PropertyChip = ({ field }: PropertyChipProps) => {\n const { t } = useTranslation();\n const { model } = useFieldsEnvironment();\n const { value } = useTopLevelValue(field);\n const [open, setOpen] = useState(false);\n const path = `/${field.apiKey}`;\n const problems = useEntryForm((state) => countIssuesUnder(issuesByPath(state.issues), path));\n const assistEnabled = useAssistEnabled();\n const summarizable = useMemo(() => isSummarizable(model, field), [model, field]);\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n type=\"button\"\n data-property={field.apiKey}\n className={cn(\n '-mx-1.5 inline-flex max-w-full min-w-0 items-center gap-1.5 rounded-md px-1.5 py-0.5 text-meta outline-none hover:bg-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 data-[state=open]:bg-muted',\n problems > 0 && 'text-destructive',\n )}\n >\n <span className=\"shrink-0 text-muted-foreground\">{field.label}</span>\n <span className=\"min-w-0 truncate font-medium text-foreground\">\n <PropertyValue field={field} value={value} />\n </span>\n {model.localized ? <ScopeIcon localized={field.localized} /> : null}\n {problems > 0 ? (\n <CircleAlert\n aria-label={t('content.items.problems', { count: problems })}\n className=\"size-3.5 shrink-0\"\n />\n ) : null}\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-[min(24rem,calc(100vw-2rem))]\">\n <TopLevelField field={field} />\n {assistEnabled && summarizable ? <SummarizeAction field={field} /> : null}\n </PopoverContent>\n </Popover>\n );\n};\n","import type { DocumentLayout } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { useEntryForm } from '@/fields/form/context';\nimport { stripFieldsFor } from '../helpers/stripFields';\nimport { PropertyChip } from '../PropertyChip';\n\ntype PropertiesStripProps = {\n layout: DocumentLayout;\n /** Opens the settings drawer at the properties. */\n onMore: () => void;\n};\n\n/**\n * Notion-style properties under the title: the configured ones, or the first five that have a value\n * (required ones and the SEO group too, see `stripFieldsFor`). \"+N more\" opens the drawer with all of them.\n */\nexport const PropertiesStrip = ({ layout, onMore }: PropertiesStripProps) => {\n const { t } = useTranslation();\n const values = useEntryForm((state) => state.values);\n const shown = stripFieldsFor(layout, values);\n const more = layout.properties.length - shown.length;\n if (layout.properties.length === 0) {\n return null;\n }\n return (\n <div\n role=\"group\"\n aria-label={t('entry.properties.title')}\n className=\"flex flex-wrap items-center gap-x-4 gap-y-1.5 border-b pb-4\"\n >\n {shown.map((field) => (\n <PropertyChip key={field.id} field={field} />\n ))}\n {more > 0 ? (\n <button\n type=\"button\"\n onClick={onMore}\n className=\"-mx-1.5 rounded-md px-1.5 py-0.5 text-meta text-muted-foreground outline-none hover:bg-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n >\n {shown.length === 0\n ? t('entry.properties.add', { count: more })\n : t('entry.properties.more', { count: more })}\n </button>\n ) : null}\n </div>\n );\n};\n","import type { PropertyGroup } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { TopLevelField } from '@/fields/form/TopLevelField';\n\ntype PropertyGridProps = { groups: readonly PropertyGroup[] };\n\n/**\n * A model without canvas fields (an author, a tag) is still a document: under the title, its properties as\n * a two-column grid of name and value (Notion-style), grouped by the model's display groups.\n */\nexport const PropertyGrid = ({ groups }: PropertyGridProps) => {\n const { t } = useTranslation();\n return (\n <section aria-label={t('entry.properties.title')} className=\"space-y-8\" data-property-grid>\n {groups.map((group) => (\n <div key={group.id} className=\"space-y-4\">\n {group.label ? (\n <h2 className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n {group.label}\n </h2>\n ) : null}\n <div className=\"space-y-4\">\n {group.fields.map((field) => (\n <TopLevelField key={field.id} field={field} layout=\"inline\" />\n ))}\n </div>\n </div>\n ))}\n </section>\n );\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { FieldMessages } from '@/fields/FieldMessages';\nimport { useFieldsEnvironment } from '@/fields/form/context';\nimport { textValue } from '@/fields/helpers/props';\nimport { useFieldControl } from '@/fields/hooks/useFieldControl';\nimport { useTopLevelValue } from '@/fields/hooks/useTopLevelValue';\nimport { cn } from '@/helpers/cn';\n\ntype TitleProps = {\n /** The title field when it is edited inline (string/text); otherwise the title is read-only. */\n field: FieldDefinition | undefined;\n /** The entry's heading: its title, \"New Article\", or \"Untitled\". */\n heading: string;\n /** `form`: a smaller read-only heading over a form-layout entry, whose title is a field of the form. */\n variant?: TitleVariant;\n};\n\ntype TitleVariant = 'document' | 'form';\n\nconst headingClasses = {\n document: 'text-display',\n form: 'text-title',\n} satisfies Record<TitleVariant, string>;\n\n/**\n * The entry's H1. In a document, a text title is typed straight into the page (one line that wraps, 44px, no\n * border); the heading itself is for assistive technology and the outline. Any other title type, and every\n * form's title, is shown read-only and edited as a field.\n */\nexport const Title = ({ field, heading, variant = 'document' }: TitleProps) => {\n if (!field) {\n return <h1 className={cn('break-words', headingClasses[variant])}>{heading}</h1>;\n }\n return <InlineTitle field={field} heading={heading} />;\n};\n\ntype InlineTitleProps = { field: FieldDefinition; heading: string };\n\nconst InlineTitle = ({ field, heading }: InlineTitleProps) => {\n const { t } = useTranslation();\n const { model, readOnly, disabled } = useFieldsEnvironment();\n const { value, onChange } = useTopLevelValue(field);\n const path = `/${field.apiKey}`;\n const control = useFieldControl({ field, owner: model, value, onChange, path });\n const invalid = control.messages.length > 0;\n return (\n <div className=\"space-y-1\" data-field-path={path} id={`${control.inputId}-section`}>\n <h1 className=\"sr-only\">{heading}</h1>\n <textarea\n id={control.inputId}\n rows={1}\n value={textValue(value)}\n aria-label={field.label}\n aria-describedby={control.builtInProps.describedBy}\n aria-invalid={invalid || undefined}\n aria-required={field.required || undefined}\n readOnly={readOnly}\n disabled={disabled}\n placeholder={t('entry.title.placeholder', { field: field.label })}\n autoComplete=\"off\"\n // One line that wraps on narrow screens: Enter doesn't break it, pasted line breaks become spaces.\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n }\n }}\n onChange={(event) => {\n const text = event.target.value.replace(/\\s*\\n\\s*/g, ' ');\n onChange(text === '' ? null : text);\n }}\n onBlur={control.builtInProps.onBlur}\n className={cn(\n 'field-sizing-content w-full min-w-0 resize-none bg-transparent text-display outline-none placeholder:text-muted-foreground/60',\n // A textarea clips what leaves its box; at the display line height, descenders (g, j, p, q, y) would.\n '-mx-2 rounded-lg px-2 pb-[0.2em] focus-visible:ring-[3px] focus-visible:ring-ring/50',\n invalid && 'underline decoration-destructive decoration-2 underline-offset-8',\n )}\n />\n <FieldMessages field={field} control={control} />\n </div>\n );\n};\n","import { isCanvasEligible, type DocumentLayout } from '@shapio/schema';\nimport { Canvas } from '../Canvas';\nimport { Cover } from '../Cover';\nimport { PropertiesStrip } from '../PropertiesStrip';\nimport { PropertyGrid } from '../PropertyGrid';\nimport type { DrawerFocus } from '../SettingsDrawer';\nimport { Title } from '../Title';\n\ntype DocumentBodyProps = {\n layout: DocumentLayout;\n heading: string;\n /** Opens the settings drawer at a section (the cover's details, every property). */\n onOpenSettings: (focus: DrawerFocus) => void;\n};\n\n/**\n * A document-layout entry's page: the cover, the title typed into the page, a strip of properties and the\n * canvas of blocks. A model without block fields shows its properties as a grid under the title and any\n * field placed in the document, and no strip.\n */\nexport const DocumentBody = ({ layout, heading, onOpenSettings }: DocumentBodyProps) => {\n // Rich text, zones, lists or galleries: the page is a document with a strip; otherwise the grid stays.\n const hasBlocks = layout.canvas.some(isCanvasEligible);\n return (\n <>\n {layout.cover ? (\n <Cover field={layout.cover} onEditDetails={() => onOpenSettings({ section: 'cover' })} />\n ) : null}\n <Title field={layout.titleInline ? layout.title : undefined} heading={heading} />\n {hasBlocks ? (\n <PropertiesStrip layout={layout} onMore={() => onOpenSettings({ section: 'properties' })} />\n ) : null}\n {layout.canvas.length > 0 ? <Canvas fields={layout.canvas} /> : null}\n {/* Without blocks the document is a form: the properties stay on the page, under its fields. */}\n {hasBlocks || layout.properties.length === 0 ? null : <PropertyGrid groups={layout.propertyGroups} />}\n </>\n );\n};\n","import type { FieldSection } from '@shapio/schema';\nimport { EntryFields } from '@/fields/form/EntryFields';\nimport { cn } from '@/helpers/cn';\n\ntype SectionProps = {\n section: FieldSection;\n /** An unlabelled section after a group: extra space above, so its fields don't read as part of the group. */\n spaced?: boolean;\n};\n\n/**\n * One section of a form-layout entry: a display group's fields under its name in the group-label style and\n * a hairline, or a run of ungrouped fields with no heading (extra space above when it follows a group). Fields\n * span their `width` on the six-column grid.\n */\nexport const Section = ({ section, spaced = false }: SectionProps) => {\n const headingId = `entry-form-section-${section.id}`;\n return (\n <section\n aria-labelledby={section.label ? headingId : undefined}\n // pt-8: a heading row and its gap, so the rhythm matches a labelled section without a line.\n className={cn('space-y-4', spaced && 'pt-8')}\n data-form-section={section.id}\n >\n {section.label ? (\n <div className=\"flex items-center gap-2\">\n <h2 id={headingId} className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n {section.label}\n </h2>\n <span aria-hidden=\"true\" className=\"h-px flex-1 bg-border\" />\n </div>\n ) : null}\n <EntryFields fields={section.fields} mode=\"widths\" />\n </section>\n );\n};\n","import { effectiveFormLayout, type ModelDefinition } from '@shapio/schema';\nimport { useMemo } from 'react';\nimport { Title } from '../Title';\nimport { Section } from './Section';\n\ntype FormBodyProps = {\n model: ModelDefinition;\n heading: string;\n};\n\n/**\n * A form-layout entry's page (`display.layout: 'form'`): the title as a read-only heading, then every field\n * on the page at its width, in sections from the display groups (`effectiveFormLayout`). The title is one of\n * the fields. No cover, strip, canvas or property grid.\n */\nexport const FormBody = ({ model, heading }: FormBodyProps) => {\n const layout = useMemo(() => effectiveFormLayout(model), [model]);\n return (\n <>\n <Title field={undefined} heading={heading} variant=\"form\" />\n {layout.sections.map((section, index) => (\n <Section\n key={section.id}\n section={section}\n // Runs of ungrouped fields never touch, so a section after the first follows a group or is one.\n spaced={index > 0 && section.label === undefined}\n />\n ))}\n </>\n );\n};\n","import type { EntryHistory, EntryPublication } from '@shapio/client';\n\nexport type HistoryRevision = EntryHistory['items'][number];\n\n/** One row of an entry's history: a revision, or a publication going live or ending. */\nexport type HistoryRow =\n | { kind: 'revision'; key: string; at: string; revision: HistoryRevision; live: boolean }\n | { kind: 'published' | 'unpublished'; key: string; at: string; publication: EntryPublication };\n\n/** Within the same instant, the later step of a write first: unpublish, publish, then the revision saved. */\nconst KIND_ORDER = { unpublished: 0, published: 1, revision: 2 } as const;\n\nexport const revisionRowKey = (revisionId: string) => `revision:${revisionId}`;\n\n/**\n * Revisions and publications as one list, newest first. A revision that is live now is marked; a publication\n * that ended without being replaced adds an \"unpublished\" row.\n */\nexport const historyTimeline = ({ items, publications }: EntryHistory): HistoryRow[] => {\n const liveIds = new Set(publications.filter((item) => item.live).map((item) => item.revisionId));\n const rows: HistoryRow[] = [\n ...items.map((revision) => ({\n kind: 'revision' as const,\n key: revisionRowKey(revision.id),\n at: revision.createdAt,\n revision,\n live: liveIds.has(revision.id),\n })),\n ...publications.flatMap((publication, index) => {\n const published: HistoryRow = {\n kind: 'published',\n key: `published:${index}`,\n at: publication.publishedAt,\n publication,\n };\n return publication.unpublishedAt\n ? [\n published,\n {\n kind: 'unpublished' as const,\n key: `unpublished:${index}`,\n at: publication.unpublishedAt,\n publication,\n },\n ]\n : [published];\n }),\n ];\n return rows.sort((a, b) => Date.parse(b.at) - Date.parse(a.at) || KIND_ORDER[a.kind] - KIND_ORDER[b.kind]);\n};\n","import type { ComponentDefinition, FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { liveFields, toFormValues } from '@/fields/helpers/formValues';\nimport { summarizeValue } from '@/fields/helpers/summary';\nimport { isEmptyValue, isSameContent, type FormValues } from '@/fields/helpers/values';\n\nexport type FieldChange = {\n field: FieldDefinition;\n kind: 'added' | 'removed' | 'changed';\n /** Short readable values (empty for structured values, which show their kind of change only). */\n before: string;\n after: string;\n};\n\n/**\n * What restoring a revision would change, field by field: the revision's values compared with the form's\n * current values. Text-like values show before/after summaries; structured ones (components, lists, rich\n * text) are reported as changed.\n */\nexport const diffRevision = (\n model: ModelDefinition,\n components: ReadonlyMap<string, ComponentDefinition>,\n revisionData: Readonly<Record<string, unknown>>,\n current: FormValues,\n): FieldChange[] => {\n const revision = toFormValues(model.fields, revisionData, components);\n return liveFields(model.fields).flatMap((field): FieldChange[] => {\n const now = current[field.apiKey];\n const then = revision[field.apiKey];\n if (isSameContent(now, then)) {\n return [];\n }\n const kind = isEmptyValue(now) ? 'added' : isEmptyValue(then) ? 'removed' : 'changed';\n return [{ field, kind, before: summarizeValue(field, now), after: summarizeValue(field, then) }];\n });\n};\n","import { CloudOff, History, Send } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { StatusChip } from '@/components/StatusChip';\nimport { cn } from '@/helpers/cn';\nimport { formatDateTime } from '@/helpers/formatDate';\nimport type { HistoryRow } from '../../helpers/historyTimeline';\n\ntype RowProps = {\n row: HistoryRow;\n selected: boolean;\n /** The newest revision (the draft the form started from). */\n current: boolean;\n onSelect: () => void;\n};\n\nconst REASON_KEYS = {\n create: 'content.history.reasons.create',\n save: 'content.history.reasons.save',\n publish: 'content.history.reasons.publish',\n restore: 'content.history.reasons.restore',\n duplicate: 'content.history.reasons.duplicate',\n localize: 'content.history.reasons.localize',\n} as const;\n\nconst reasonKey = (reason: string) =>\n Object.hasOwn(REASON_KEYS, reason) ? REASON_KEYS[reason as keyof typeof REASON_KEYS] : undefined;\n\nconst useRowText = (row: HistoryRow, current: boolean) => {\n const { t } = useTranslation();\n const meta = (by: string | null, ...extra: string[]) =>\n [formatDateTime(row.at), ...(by ? [by] : []), ...extra].join(' · ');\n switch (row.kind) {\n case 'revision': {\n const key = reasonKey(row.revision.reason);\n return {\n title: key ? t(key) : row.revision.reason,\n meta: meta(row.revision.authorName, ...(current ? [t('content.history.latest')] : [])),\n };\n }\n case 'published':\n return {\n title:\n row.publication.via === 'changeSet'\n ? t('content.history.events.publishedWithChangeSet', { title: row.publication.changeSetTitle })\n : row.publication.via === 'schedule'\n ? t('content.history.events.publishedOnSchedule')\n : t('content.history.events.published'),\n meta: meta(row.publication.publishedBy),\n };\n case 'unpublished':\n return { title: t('content.history.events.unpublished'), meta: meta(row.publication.unpublishedBy) };\n }\n};\n\nconst ICONS = { revision: History, published: Send, unpublished: CloudOff } as const;\n\n/**\n * One history row. Revisions and publications select a version to compare (a publication selects the\n * revision it put live); an unpublish is a plain line.\n */\nexport const Row = ({ row, selected, current, onSelect }: RowProps) => {\n const { t } = useTranslation();\n const { title, meta } = useRowText(row, current);\n const Icon = ICONS[row.kind];\n const body = (\n <>\n <Icon aria-hidden=\"true\" className=\"size-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block font-semibold\">{title}</span>\n <span className=\"block text-meta text-muted-foreground\">{meta}</span>\n </span>\n {row.kind === 'revision' && row.live ? (\n <StatusChip tone=\"success\" size=\"sm\" label={t('content.history.live')} />\n ) : null}\n </>\n );\n if (row.kind === 'unpublished') {\n return <div className=\"flex w-full items-center gap-3 px-3 py-2 text-sm\">{body}</div>;\n }\n return (\n <button\n type=\"button\"\n aria-pressed={selected}\n onClick={onSelect}\n className={cn(\n 'flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left text-sm outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/50',\n selected && 'bg-accent text-accent-foreground',\n )}\n >\n {body}\n </button>\n );\n};\n","import type { ComponentDefinition, ModelDefinition } from '@shapio/schema';\nimport { RotateCcw } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useEntryHistory, useRevision } from '@/api/content';\nimport { ErrorState } from '@/components/ErrorState';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Button } from '@/components/ui/button';\nimport { Sheet, SheetBody, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';\nimport { useEntryForm } from '@/fields/form/context';\nimport { historyTimeline, revisionRowKey, type HistoryRow } from '../helpers/historyTimeline';\nimport { diffRevision } from '../helpers/revisionDiff';\nimport { Row } from './Row';\n\ntype HistorySheetProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n model: ModelDefinition;\n components: ReadonlyMap<string, ComponentDefinition>;\n entryId: string;\n locale: string | null;\n restoring: boolean;\n /** The form has unsaved changes, which restoring replaces: ask first. */\n confirmRestore: boolean;\n /** Restores a revision; a confirmation stays open (with a spinner) until it settles. */\n onRestore: (revisionId: string) => Promise<unknown>;\n /** The revision selected when the sheet first opens (a link to one version). */\n initialRevisionId?: string;\n};\n\nconst revisionIdOf = (row: HistoryRow) =>\n row.kind === 'revision' ? row.revision.id : row.publication.revisionId;\n\nconst CHANGE_KEYS = {\n added: 'content.history.changes.added',\n removed: 'content.history.changes.removed',\n changed: 'content.history.changes.changed',\n} as const;\n\n/**\n * The entry's history in this locale: revisions (explicit saves, restores; autosaves are not history) with\n * who made them, and when it was published or unpublished, by whom. Choosing a revision (or a publication,\n * which picks the revision it put live) shows which fields differ from the form now; restoring brings it back\n * as a new revision.\n */\nexport const HistorySheet = ({\n open,\n onOpenChange,\n model,\n components,\n entryId,\n locale,\n restoring,\n confirmRestore,\n onRestore,\n initialRevisionId,\n}: HistorySheetProps) => {\n const { t } = useTranslation();\n const current = useEntryForm((state) => state.values);\n const history = useEntryHistory(model.apiKey, entryId, locale ?? undefined, open);\n const rows = useMemo(() => (history.data ? historyTimeline(history.data) : []), [history.data]);\n const [selectedKey, setSelectedKey] = useState<string | undefined>(\n initialRevisionId === undefined ? undefined : revisionRowKey(initialRevisionId),\n );\n const selectedRow = rows.find((row) => row.key === selectedKey);\n const selectedId = selectedRow\n ? revisionIdOf(selectedRow)\n : selectedKey === undefined\n ? undefined\n : initialRevisionId;\n const newestRevision = rows.find((row) => row.kind === 'revision')?.key;\n const revision = useRevision(model.apiKey, entryId, selectedId);\n const changes = revision.data ? diffRevision(model, components, revision.data.data, current) : [];\n const restoreButton = (\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={restoring || revision.isPending}\n onClick={confirmRestore || !selectedId ? undefined : () => void onRestore(selectedId)}\n >\n <RotateCcw aria-hidden=\"true\" />\n {t('content.history.restore')}\n </Button>\n );\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent size=\"md\" aria-describedby={undefined}>\n <SheetHeader>\n <SheetTitle>{t('content.history.title')}</SheetTitle>\n </SheetHeader>\n <SheetBody className=\"space-y-4\">\n {history.isPending ? (\n <LoadingState rows={4} />\n ) : history.isError ? (\n <ErrorState error={history.error} onRetry={() => void history.refetch()} />\n ) : rows.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">{t('content.history.empty')}</p>\n ) : (\n <ol aria-label={t('content.history.list')} className=\"space-y-1\">\n {rows.map((row) => (\n <li key={row.key}>\n <Row\n row={row}\n selected={row.key === selectedKey}\n current={row.key === newestRevision}\n onSelect={() => setSelectedKey(row.key)}\n />\n </li>\n ))}\n </ol>\n )}\n {selectedId ? (\n <section aria-labelledby=\"revision-diff-title\" className=\"space-y-3 rounded-xl border p-4\">\n <h3 id=\"revision-diff-title\" className=\"text-sm font-semibold\">\n {t('content.history.diffTitle')}\n </h3>\n {revision.isPending ? (\n <LoadingState rows={2} />\n ) : revision.isError ? (\n <ErrorState error={revision.error} onRetry={() => void revision.refetch()} />\n ) : changes.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">{t('content.history.noChanges')}</p>\n ) : (\n <ul className=\"space-y-2 text-sm\">\n {changes.map((change) => (\n <li key={change.field.id}>\n <span className=\"font-medium\">{change.field.label}</span>{' '}\n <span className=\"text-muted-foreground\">{t(CHANGE_KEYS[change.kind])}</span>\n {change.before || change.after ? (\n <span className=\"mt-0.5 block text-meta text-muted-foreground\">\n {t('content.history.beforeAfter', {\n before: change.before || '—',\n after: change.after || '—',\n })}\n </span>\n ) : null}\n </li>\n ))}\n </ul>\n )}\n {confirmRestore ? (\n <InlineConfirm\n tone=\"default\"\n align=\"start\"\n title={t('content.history.restoreTitle')}\n description={t('content.history.restoreDescription')}\n confirmLabel={t('content.history.restoreConfirm')}\n onConfirm={() => onRestore(selectedId)}\n trigger={restoreButton}\n />\n ) : (\n restoreButton\n )}\n </section>\n ) : null}\n </SheetBody>\n </SheetContent>\n </Sheet>\n );\n};\n","import type { PaletteItem } from '../types';\nimport { usePaletteItems } from './usePaletteItems';\n\n/**\n * Actions on the current page, listed first in the palette while the screen is mounted (Publish, Open\n * settings, Start French…). Memoize the array; give each action a `run`, and a `hint` with its shortcut\n * when it has one.\n *\n * ```tsx\n * const actions = useMemo(() => [{ id: 'publish', label: t('entry.publish'), icon: Send, hint: '⌘⇧P', run: openPublish }], [t, openPublish]);\n * usePaletteActions(actions);\n * ```\n */\nexport const usePaletteActions = (actions: readonly PaletteItem[]) => usePaletteItems('page', actions);\n","import type { AdminEntry, Locale } from '@shapio/client';\nimport { Languages, PanelRight, Send } from 'lucide-react';\nimport { useEffect, useMemo, useRef } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { usePaletteActions } from '@/components/CommandPalette/hooks/usePaletteActions';\nimport type { PaletteItem } from '@/components/CommandPalette/types';\n\ntype DocumentPaletteOptions = {\n onPublish: (() => void) | undefined;\n onOpenSettings: () => void;\n /** Locales of a localized entry, with \"Start French\" for the ones it doesn't have yet. */\n locales: readonly Locale[];\n entry: AdminEntry | null;\n onLocaleChange: ((code: string) => void) | undefined;\n};\n\n/** The document's actions in the ⌘K palette: Publish, Settings, and switching or starting a locale. */\nexport const useDocumentPaletteActions = ({\n onPublish,\n onOpenSettings,\n locales,\n entry,\n onLocaleChange,\n}: DocumentPaletteOptions) => {\n const { t } = useTranslation();\n // The latest handlers, so the registered actions change only when what they offer changes.\n const latest = useRef({ onPublish, onOpenSettings, onLocaleChange });\n useEffect(() => {\n latest.current = { onPublish, onOpenSettings, onLocaleChange };\n });\n const canPublish = onPublish !== undefined;\n const canSwitch = onLocaleChange !== undefined;\n const actions = useMemo<PaletteItem[]>(\n () => [\n ...(canPublish\n ? [\n {\n id: 'publish',\n label: t('content.actions.publish'),\n icon: Send,\n hint: '⌘⇧P',\n run: () => latest.current.onPublish?.(),\n },\n ]\n : []),\n {\n id: 'settings',\n label: t('entry.settings.open'),\n icon: PanelRight,\n hint: '⌘/',\n run: () => latest.current.onOpenSettings(),\n },\n ...(canSwitch && entry\n ? locales.map((locale) => ({\n id: `locale-${locale.code}`,\n label: entry.locales.some((state) => state.locale === locale.code)\n ? t('entry.palette.switchLocale', { locale: locale.label })\n : t('entry.settings.startLocale', { locale: locale.label }),\n icon: Languages,\n run: () => latest.current.onLocaleChange?.(locale.code),\n }))\n : []),\n ],\n [t, canPublish, canSwitch, locales, entry],\n );\n usePaletteActions(actions);\n};\n","import { useEffect, useRef } from 'react';\n\ntype DocumentShortcuts = {\n /** ⌘⇧P: open the publish pre-flight. */\n onPublish?: () => void;\n /** ⌘/: open or close the settings drawer. */\n onToggleSettings: () => void;\n /** ⌘⇧L: the next locale. */\n onCycleLocale?: () => void;\n};\n\ntype Shortcut = {\n key: string;\n shift: boolean;\n run: (handlers: DocumentShortcuts) => (() => void) | undefined;\n};\n\nconst SHORTCUTS: readonly Shortcut[] = [\n { key: 'p', shift: true, run: (handlers) => handlers.onPublish },\n { key: '/', shift: false, run: (handlers) => handlers.onToggleSettings },\n { key: 'l', shift: true, run: (handlers) => handlers.onCycleLocale },\n];\n\n/**\n * The document's keyboard shortcuts besides ⌘S (`useSaveShortcut`): ⌘⇧P publish, ⌘/ settings, ⌘⇧L next\n * locale. ⌘K stays the command palette; the rich-text link shortcut is ⌘⇧K.\n */\nexport const useDocumentShortcuts = (handlers: DocumentShortcuts, enabled: boolean) => {\n const latest = useRef(handlers);\n useEffect(() => {\n latest.current = handlers;\n });\n useEffect(() => {\n if (!enabled) {\n return undefined;\n }\n const onKeyDown = (event: KeyboardEvent) => {\n if (!(event.metaKey || event.ctrlKey) || event.altKey) {\n return;\n }\n const shortcut = SHORTCUTS.find(\n (candidate) => candidate.key === event.key.toLowerCase() && candidate.shift === event.shiftKey,\n );\n const run = shortcut?.run(latest.current);\n if (run) {\n event.preventDefault();\n run();\n }\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [enabled]);\n};\n","import type { FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { useEffect } from 'react';\nimport type { EntryFormStore } from '../form/store';\nimport { textValue } from '../helpers/props';\nimport { slugify } from '../helpers/slugify';\n\ntype SlugPair = { slug: FieldDefinition; source: FieldDefinition };\n\nconst slugPairsOf = (model: ModelDefinition): SlugPair[] =>\n model.fields.flatMap((slug) => {\n if (slug.type !== 'slug' || slug.deprecated || !slug.settings.sourceFieldId) {\n return [];\n }\n const source = model.fields.find((field) => field.id === slug.settings.sourceFieldId);\n return source ? [{ slug, source }] : [];\n });\n\n/**\n * Top-level slugs follow their source field (usually the title) even when their editor isn't on screen: in\n * the entry document a slug is a property, often only in the settings drawer. A slug still follows while\n * it is empty or equal to what the previous source text generated; once edited by hand it stays. (The\n * slug editor does the same while it is shown; both write the same value.)\n */\nexport const useFollowingSlugs = (store: EntryFormStore, model: ModelDefinition, enabled: boolean) => {\n useEffect(() => {\n const pairs = slugPairsOf(model);\n if (!enabled || pairs.length === 0) {\n return undefined;\n }\n return store.subscribe((state, previous) => {\n for (const { slug, source } of pairs) {\n const before = previous.values[source.apiKey];\n const after = state.values[source.apiKey];\n if (before === after) {\n continue;\n }\n const current = textValue(state.values[slug.apiKey]);\n if (current === '' || current === slugify(textValue(before))) {\n const next = slugify(textValue(after));\n if (next !== current) {\n state.setValue(slug.apiKey, next === '' ? null : next);\n }\n }\n }\n });\n }, [store, model, enabled]);\n};\n","import { useEffect, useRef } from 'react';\nimport type { EntryFormStore } from '@/fields/form/store';\nimport { AUTOSAVE_DELAY_MS } from '../../constants';\nimport type { SaveKind, SaveOutcome } from './useEntrySaver';\n\n/**\n * Autosave: a short while after the last change, the draft is saved with the API's `autosave` flag (no\n * revision, `required` not enforced), so work survives a closed tab without filling the history.\n */\nexport const useAutosave = (\n store: EntryFormStore,\n enabled: boolean,\n save: (kind: SaveKind) => Promise<SaveOutcome>,\n) => {\n // The latest save function, so re-renders never restart (and so cancel) a pending autosave.\n const latestSave = useRef(save);\n useEffect(() => {\n latestSave.current = save;\n });\n useEffect(() => {\n if (!enabled) {\n return undefined;\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const unsubscribe = store.subscribe((state, previous) => {\n if (state.values === previous.values) {\n return;\n }\n clearTimeout(timer);\n timer = setTimeout(() => void latestSave.current('autosave'), AUTOSAVE_DELAY_MS);\n });\n return () => {\n clearTimeout(timer);\n unsubscribe();\n };\n }, [store, enabled]);\n};\n","import type { AdminEntry, MediaAsset } from '@shapio/client';\nimport type { ComponentDefinition, ModelDefinition } from '@shapio/schema';\nimport { defaultFormValues, liveFields, toFormValues } from '@/fields/helpers/formValues';\nimport type { FormValues } from '@/fields/helpers/values';\n\ntype Collect = (asset: MediaAsset) => void;\n\n/**\n * Values for a locale that has no version of the entry yet: shared fields come from an existing locale\n * (they are the same in every locale, ADR 0004), localized fields start from their defaults.\n */\nexport const newLocaleValues = (\n model: ModelDefinition,\n source: AdminEntry,\n components: ReadonlyMap<string, ComponentDefinition>,\n collect: Collect,\n): FormValues => {\n const fromSource = toFormValues(model.fields, source.data, components, collect);\n const defaults = defaultFormValues(model.fields);\n return Object.fromEntries(\n liveFields(model.fields).map((field) => [\n field.apiKey,\n field.localized ? defaults[field.apiKey] : fromSource[field.apiKey],\n ]),\n );\n};\n\n/** Localized fields' values of another locale (for \"copy from the default locale\"). */\nexport const localizedValuesOf = (\n model: ModelDefinition,\n source: AdminEntry,\n components: ReadonlyMap<string, ComponentDefinition>,\n collect: Collect,\n): FormValues => {\n const values = toFormValues(model.fields, source.data, components, collect);\n return Object.fromEntries(\n liveFields(model.fields)\n .filter((field) => field.localized)\n .map((field) => [field.apiKey, values[field.apiKey]]),\n );\n};\n","import type { AdminEntry, EntryReferrer, MediaAsset } from '@shapio/client';\nimport type { ComponentDefinition, ModelDefinition } from '@shapio/schema';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useNavigate } from '@tanstack/react-router';\nimport { useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport {\n entryQueryOptions,\n useCreateEntry,\n useDeleteEntry,\n useDuplicateEntry,\n useRestoreRevision,\n} from '@/api/content';\nimport { refuseUnparsed } from '@/fields/form/refuseUnparsed';\nimport type { EntryFormStore } from '@/fields/form/store';\nimport { contentIssuesOf, isEditConflict, referrersOf } from '@/fields/helpers/apiErrors';\nimport { buildCreateData } from '@/fields/helpers/formValues';\nimport { reportError } from '@/helpers/reportError';\nimport { localizedValuesOf } from '../helpers/initialValues';\n\ntype LifecycleOptions = {\n model: ModelDefinition;\n components: ReadonlyMap<string, ComponentDefinition>;\n store: EntryFormStore;\n entryId: string | null;\n locale: string | null;\n defaultLocale: string | undefined;\n versionRef: { current: number | null };\n exclusive: <T>(task: () => Promise<T>) => Promise<T>;\n onAsset: (asset: MediaAsset) => void;\n onConflict: (code: string) => void;\n onRestored: () => void;\n};\n\n/**\n * Creating, deleting, duplicating, restoring and copying between locales. Before leaving the form the\n * store is marked clean synchronously, so the unsaved-changes guard doesn't ask about work that was saved.\n */\nexport const useEntryLifecycle = ({\n model,\n components,\n store,\n entryId,\n locale,\n defaultLocale,\n versionRef,\n exclusive,\n onAsset,\n onConflict,\n onRestored,\n}: LifecycleOptions) => {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const createMutation = useCreateEntry(model.apiKey);\n const deleteMutation = useDeleteEntry(model.apiKey);\n const duplicateMutation = useDuplicateEntry(model.apiKey);\n const restoreMutation = useRestoreRevision(model.apiKey);\n const [referrers, setReferrers] = useState<EntryReferrer[]>([]);\n const markClean = () => flushSync(() => store.getState().load(store.getState().values));\n const openEntry = (entry: AdminEntry) =>\n void navigate({\n to: '/content/$modelKey/$entryId',\n params: { modelKey: model.apiKey, entryId: entry.id },\n search: model.localized ? { locale: entry.locale } : {},\n replace: true,\n });\n\n const create = async () => {\n if (refuseUnparsed(store)) {\n return;\n }\n store.getState().reveal();\n try {\n const entry = await createMutation.mutateAsync({\n ...(locale ? { locale } : {}),\n data: buildCreateData(store.getState().values),\n });\n markClean();\n toast.success(t('content.form.createdToast'));\n openEntry(entry);\n } catch (error) {\n const issues = contentIssuesOf(error);\n if (issues.length > 0) {\n store.getState().setIssues(issues);\n toast.error(t('content.form.fixProblems', { count: issues.length }));\n return;\n }\n reportError(error, 'creating an entry');\n }\n };\n\n const remove = async () => {\n if (!entryId) {\n return;\n }\n try {\n await deleteMutation.mutateAsync(entryId);\n markClean();\n toast.success(t('content.form.deletedToast'));\n void navigate({ to: '/content/$modelKey', params: { modelKey: model.apiKey } });\n } catch (error) {\n const found = referrersOf(error);\n if (found.length > 0) {\n setReferrers(found);\n return;\n }\n reportError(error, 'deleting an entry');\n }\n };\n\n const duplicate = async () => {\n if (!entryId) {\n return;\n }\n const copy = await duplicateMutation.mutateAsync(entryId).catch(() => undefined);\n if (copy) {\n toast.success(t('content.form.duplicatedToast'));\n openEntry(copy);\n }\n };\n\n const restore = (revisionId: string) =>\n exclusive(async () => {\n if (!entryId || versionRef.current === null) {\n return;\n }\n try {\n await restoreMutation.mutateAsync({ id: entryId, revisionId, expectedVersion: versionRef.current });\n markClean();\n toast.success(t('content.history.restoredToast'));\n onRestored();\n } catch (error) {\n if (isEditConflict(error)) {\n onConflict(error.code);\n return;\n }\n reportError(error, 'restoring a revision');\n }\n });\n\n const copyFromDefault = async () => {\n if (!entryId || !defaultLocale) {\n return;\n }\n try {\n const source = await queryClient.fetchQuery({\n ...entryQueryOptions(model.apiKey, entryId, defaultLocale),\n staleTime: 0,\n });\n store.getState().patchValues(localizedValuesOf(model, source, components, onAsset));\n toast.success(t('content.locales.copiedToast'));\n } catch (error) {\n reportError(error, 'copying from the default locale');\n }\n };\n\n return {\n create,\n creating: createMutation.isPending,\n remove,\n duplicate,\n restore,\n restoring: restoreMutation.isPending,\n copyFromDefault,\n referrers,\n clearReferrers: () => setReferrers([]),\n };\n};\n","import type { ContentAction } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { useMe } from '@/api/auth';\n\n/**\n * What the signed-in admin may do with this model's entries (`me.modelPermissions`), so the document\n * offers only what will work. The server checks every action again.\n */\nexport const useEntryPermissions = (model: ModelDefinition) => {\n const me = useMe().data;\n const actions: readonly ContentAction[] | undefined = me?.modelPermissions?.[model.id];\n // Until `me` has loaded (or from a server without per-model permissions) nothing is hidden.\n const can = (action: ContentAction) => actions === undefined || actions.includes(action);\n return {\n canCreate: can('create'),\n canUpdate: can('update'),\n canDelete: can('delete'),\n canPublish: can('publish'),\n canManageSchema: can('schemaManage'),\n // Compared as a string: `changes.manage` came with D0 and may be missing from older client types.\n canUseChangeSets:\n (me?.globalPermissions as readonly string[] | undefined)?.includes('changes.manage') ?? false,\n canSchedule: (me?.globalPermissions ?? []).includes('publishing.manage') || can('publish'),\n };\n};\n","import type { AdminEntry, MediaAsset, ShapioApiError } from '@shapio/client';\nimport type { ComponentDefinition, ModelDefinition } from '@shapio/schema';\nimport { useCallback, useEffect, useRef, useState, type MutableRefObject } from 'react';\nimport { useSaveEntry } from '@/api/content';\nimport { isUnauthorized } from '@/api/errors';\nimport { refuseUnparsed } from '@/fields/form/refuseUnparsed';\nimport type { EntryFormStore } from '@/fields/form/store';\nimport { contentIssuesOf, isEditConflict } from '@/fields/helpers/apiErrors';\nimport { buildPatch, dirtyKeysOf, toFormValues } from '@/fields/helpers/formValues';\nimport { containsUnparsed } from '@/fields/helpers/unparsed';\nimport type { FormValues } from '@/fields/helpers/values';\nimport { logError, reportError } from '@/helpers/reportError';\nimport { useSessionStore } from '@/stores/session';\n\nexport type SaveKind = 'autosave' | 'save';\nexport type SaveOutcome = 'saved' | 'unchanged' | 'invalid' | 'conflict' | 'failed';\nexport type SaveState = {\n status: 'idle' | 'saving' | 'saved' | 'failed';\n kind: SaveKind | undefined;\n at: string | undefined;\n};\n\ntype EntrySaverOptions = {\n model: ModelDefinition;\n components: ReadonlyMap<string, ComponentDefinition>;\n entryId: string;\n locale: string | null;\n store: EntryFormStore;\n /** The draft version last seen; null while this locale has no version yet. */\n versionRef: MutableRefObject<number | null>;\n onSaved: (entry: AdminEntry, kind: SaveKind) => void;\n onConflict: (error: ShapioApiError) => void;\n onAsset: (asset: MediaAsset) => void;\n};\n\n/**\n * The changed fields a save sends. Fields still holding text an editor couldn't parse are held back (only\n * autosave gets this far with them): they are left out of `sent`, so the save's result doesn't overwrite them\n * and they stay unsaved changes.\n */\nconst sendableChanges = (values: FormValues, baseline: FormValues) => {\n const held = new Set(Object.keys(values).filter((key) => containsUnparsed(values[key])));\n return {\n keys: dirtyKeysOf(values, baseline).filter((key) => !held.has(key)),\n sent: Object.fromEntries(Object.entries(values).filter(([key]) => !held.has(key))),\n };\n};\n\n/**\n * Saving one locale's draft. Saves run one at a time (an explicit save waits for a running autosave), so\n * every request carries the latest version and nothing races. Only changed fields are sent (the API takes\n * a patch). Autosave moves the draft without a revision and skips `required`; Save creates a revision and\n * validates everything. 422 issues land on the fields; 409 conflicts go to the conflict dialog. A save that\n * failed because the session ended runs again once it is resumed in place (the edits never left the page).\n */\nexport const useEntrySaver = ({\n model,\n components,\n entryId,\n locale,\n store,\n versionRef,\n onSaved,\n onConflict,\n onAsset,\n}: EntrySaverOptions) => {\n const { mutateAsync } = useSaveEntry(model.apiKey);\n const queue = useRef<Promise<unknown>>(Promise.resolve());\n const [state, setState] = useState<SaveState>({ status: 'idle', kind: undefined, at: undefined });\n /** The save that failed with a 401, if any: Save wins over autosave. */\n const failedSignedOut = useRef<SaveKind | undefined>(undefined);\n const latest = useRef({ onSaved, onConflict, onAsset });\n useEffect(() => {\n latest.current = { onSaved, onConflict, onAsset };\n });\n\n const runSave = useCallback(\n async (kind: SaveKind): Promise<SaveOutcome> => {\n if (kind === 'save' && refuseUnparsed(store)) {\n return 'invalid';\n }\n const { values, baseline } = store.getState();\n const { keys, sent } = sendableChanges(values, baseline);\n if (kind === 'autosave' && keys.length === 0) {\n return 'unchanged';\n }\n if (kind === 'save') {\n store.getState().reveal();\n }\n setState({ status: 'saving', kind, at: undefined });\n try {\n const entry = await mutateAsync({\n id: entryId,\n input: {\n ...(locale ? { locale } : {}),\n expectedVersion: versionRef.current,\n data: buildPatch(values, keys),\n ...(kind === 'autosave' ? { autosave: true } : {}),\n },\n });\n versionRef.current = entry.version;\n store\n .getState()\n .acceptSaved(sent, toFormValues(model.fields, entry.data, components, latest.current.onAsset));\n if (kind === 'save') {\n store.getState().setIssues([]);\n }\n latest.current.onSaved(entry, kind);\n setState({ status: 'saved', kind, at: entry.updatedAt });\n return 'saved';\n } catch (error) {\n setState({ status: 'failed', kind, at: undefined });\n const issues = contentIssuesOf(error);\n if (issues.length > 0) {\n store.getState().setIssues(issues);\n store.getState().reveal();\n return 'invalid';\n }\n if (isEditConflict(error)) {\n latest.current.onConflict(error);\n return 'conflict';\n }\n if (isUnauthorized(error)) {\n // The sign-in panel says what happened; the save runs again after it.\n failedSignedOut.current = failedSignedOut.current === 'save' ? 'save' : kind;\n logError(error, 'saving an entry after the session ended');\n return 'failed';\n }\n (kind === 'save' ? reportError : logError)(\n error,\n kind === 'save' ? 'saving an entry' : 'autosaving an entry',\n );\n return 'failed';\n }\n },\n [mutateAsync, store, entryId, locale, versionRef, model.fields, components],\n );\n\n /** Runs `task` after any save in progress, so publish/restore never overlap a save. */\n const exclusive = useCallback(<T>(task: () => Promise<T>): Promise<T> => {\n const next = queue.current.then(task);\n queue.current = next.catch(() => undefined);\n return next;\n }, []);\n\n const save = useCallback((kind: SaveKind) => exclusive(() => runSave(kind)), [exclusive, runSave]);\n\n const resumed = useSessionStore((session) => session.resumed);\n const latestSave = useRef(save);\n useEffect(() => {\n latestSave.current = save;\n });\n useEffect(() => {\n const kind = failedSignedOut.current;\n if (kind === undefined) {\n return;\n }\n failedSignedOut.current = undefined;\n void latestSave.current(kind);\n }, [resumed]);\n\n return { save, exclusive, state };\n};\n","import type { AdminEntry, MediaAsset } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useMemo, useRef, useState } from 'react';\nimport { queryKeys } from '@/api/queryKeys';\nimport type { FieldsEnvironment } from '@/fields/form/context';\nimport { createEntryFormStore } from '@/fields/form/store';\nimport { defaultFormValues, toFormValues } from '@/fields/helpers/formValues';\nimport type { FormValues } from '@/fields/helpers/values';\nimport { useMediaPickerDialog } from '@/fields/hooks/useMediaPickerDialog';\nimport { useRuntimeEditors } from '@/fields/runtime/useRuntimeEditors';\nimport { useMediaPermissions } from '@/hooks/useMediaPermissions';\nimport { useMediaUploader } from '@/hooks/useMediaUploader';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\nimport { newLocaleValues } from '../helpers/initialValues';\nimport type { EntryMode } from '../types';\n\ntype SetupOptions = {\n schema: ContentSchema;\n model: ModelDefinition;\n mode: EntryMode;\n locale: string | null;\n carry: FormValues | undefined;\n disabled: boolean;\n /** The admin may not change this entry (no `update`, or no `create` for a new one). */\n readOnly: boolean;\n};\n\n/**\n * Everything one open entry document owns: its value store (seeded from the loaded entry, a new locale's\n * shared values, or defaults), the server's latest view of the entry and its version, and the environment\n * every field editor sees (schema, locale, custom editors, the media picker).\n */\nexport const useEntrySetup = ({ schema, model, mode, locale, carry, disabled, readOnly }: SetupOptions) => {\n const queryClient = useQueryClient();\n const runtime = useRuntimeEditors();\n const { pickMedia, dialog: mediaDialog } = useMediaPickerDialog();\n const { canWrite: canUpload } = useMediaPermissions();\n const { uploadOne } = useMediaUploader();\n const onAsset = useCallback(\n (asset: MediaAsset) => queryClient.setQueryData(queryKeys.media.asset(asset.id), asset),\n [queryClient],\n );\n const [store] = useState(() => {\n const initial =\n mode.kind === 'edit'\n ? toFormValues(model.fields, mode.entry.data, schema.components, onAsset)\n : mode.kind === 'newLocale'\n ? newLocaleValues(model, mode.source, schema.components, onAsset)\n : defaultFormValues(model.fields);\n const created = createEntryFormStore(initial);\n if (carry) {\n created.getState().patchValues(carry);\n }\n return created;\n });\n const [entry, setEntry] = useState<AdminEntry | null>(mode.kind === 'edit' ? mode.entry : null);\n const versionRef = useRef<number | null>(mode.kind === 'edit' ? mode.entry.version : null);\n const entryId = mode.kind === 'edit' ? mode.entry.id : mode.kind === 'newLocale' ? mode.entryId : null;\n const environment = useMemo<FieldsEnvironment>(\n () => ({\n idPrefix: 'entry-',\n model,\n components: schema.components,\n models: schema.models,\n locale,\n entryId,\n readOnly,\n disabled,\n runtimeEditors: runtime.editors,\n pickMedia,\n ...(canUpload && !readOnly ? { uploadMedia: uploadOne } : {}),\n }),\n [model, schema, locale, entryId, readOnly, disabled, runtime.editors, pickMedia, canUpload, uploadOne],\n );\n return {\n store,\n entry,\n setEntry,\n versionRef,\n entryId,\n environment,\n mediaDialog,\n onAsset,\n runtimeLoading: runtime.isLoading,\n };\n};\n","import type { AdminEntry, ShapioApiError } from '@shapio/client';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useState, type MutableRefObject } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { entryQueryOptions, usePublishEntry, useUnpublishEntry } from '@/api/content';\nimport type { EntryFormStore } from '@/fields/form/store';\nimport { contentIssuesOf, isEditConflict } from '@/fields/helpers/apiErrors';\nimport { dirtyKeysOf } from '@/fields/helpers/formValues';\nimport { reportError } from '@/helpers/reportError';\nimport type { SaveKind, SaveOutcome } from './useEntrySaver';\n\ntype PublishingOptions = {\n modelKey: string;\n /** Null while the entry is not created yet (nothing to publish). */\n entryId: string | null;\n /** The draft holds autosaved work that has not been validated by a Save. */\n autosaved: boolean;\n locale: string | null;\n /** The draft version this document shows; publish sends it so a draft saved elsewhere since is refused. */\n versionRef: MutableRefObject<number | null>;\n /** Every locale's state as last read (its draft version guards \"publish the other locales too\"). */\n entryLocales: AdminEntry['locales'];\n store: EntryFormStore;\n save: (kind: SaveKind) => Promise<SaveOutcome>;\n exclusive: <T>(task: () => Promise<T>) => Promise<T>;\n onEntry: (entry: AdminEntry) => void;\n /** Someone else saved since this document loaded: the conflict banner takes over, nothing is published. */\n onConflict: (error: ShapioApiError) => void;\n};\n\n/**\n * Publishing is per locale (ADR 0004): publishing this locale never changes another locale's live content.\n * Unsaved or autosaved changes are saved first (fully validated). When other published locales still serve\n * older shared values the document offers to publish them too; `othersDismissed` hides that notice until\n * the next publish. Every publish carries the draft versions this document saw, so a stale tab gets the\n * conflict banner instead of publishing a draft it never showed.\n */\nexport const usePublishing = ({\n modelKey,\n entryId,\n autosaved,\n locale,\n versionRef,\n entryLocales,\n store,\n save,\n exclusive,\n onEntry,\n onConflict,\n}: PublishingOptions) => {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const publishMutation = usePublishEntry(modelKey);\n const unpublishMutation = useUnpublishEntry(modelKey);\n const [othersDismissed, setOthersDismissed] = useState(false);\n // A non-localized model has no locale: omit `locales` so the API uses its default.\n const locales = locale ? [locale] : undefined;\n\n /** Resolves true when the pre-flight should close: this locale went live, or the conflict banner took over. */\n const publish = async (): Promise<boolean> => {\n if (!entryId) {\n return false;\n }\n const { values, baseline } = store.getState();\n if (dirtyKeysOf(values, baseline).length > 0 || autosaved) {\n const outcome = await save('save');\n if (outcome !== 'saved') {\n return outcome === 'conflict';\n }\n }\n return exclusive(async () => {\n try {\n const expectedVersion = versionRef.current;\n const published = await publishMutation.mutateAsync({\n id: entryId,\n locales,\n ...(expectedVersion !== null ? { expectedVersion } : {}),\n });\n onEntry(published);\n toast.success(t('content.form.publishedToast'));\n setOthersDismissed(false);\n return true;\n } catch (error) {\n const issues = contentIssuesOf(error);\n if (issues.length > 0) {\n store.getState().setIssues(issues);\n store.getState().reveal();\n toast.error(t('content.form.fixProblems', { count: issues.length }));\n return false;\n }\n if (isEditConflict(error)) {\n onConflict(error);\n return true;\n }\n reportError(error, 'publishing an entry');\n return false;\n }\n });\n };\n\n const publishOthers = async (others: string[]) => {\n if (!entryId) {\n return;\n }\n await exclusive(async () => {\n try {\n // The response describes the first published locale; re-read the one being edited.\n const expectedVersions = Object.fromEntries(\n entryLocales\n .filter((state) => others.includes(state.locale))\n .map((state) => [state.locale, state.version]),\n );\n await publishMutation.mutateAsync({ id: entryId, locales: others, expectedVersions });\n onEntry(\n await queryClient.fetchQuery({\n ...entryQueryOptions(modelKey, entryId, locale ?? undefined),\n staleTime: 0,\n }),\n );\n toast.success(t('content.form.publishedOthersToast', { count: others.length }));\n } catch (error) {\n if (isEditConflict(error)) {\n onConflict(error);\n return;\n }\n reportError(error, 'publishing other locales');\n }\n });\n };\n\n const unpublish = () =>\n exclusive(async () => {\n if (!entryId) {\n return;\n }\n try {\n onEntry(await unpublishMutation.mutateAsync({ id: entryId, locales }));\n toast.success(t('content.form.unpublishedToast'));\n } catch (error) {\n reportError(error, 'unpublishing an entry');\n }\n });\n\n return {\n publish,\n publishOthers,\n unpublish,\n othersDismissed,\n dismissOthers: () => setOthersDismissed(true),\n publishing: publishMutation.isPending,\n unpublishing: unpublishMutation.isPending,\n };\n};\n","import type { DraftState } from '@shapio/client';\nimport { useEffect } from 'react';\n\n/** CONTENT_VERSION_CONFLICT: the code a 409 on save or publish carries, so the same banner shows. */\nconst EDIT_CONFLICT = 'CONTENT_VERSION_CONFLICT';\n\nexport type RemoteChange = Pick<DraftState, 'savedAt' | 'savedBy'>;\n\ntype RemoteDraftChangeOptions = {\n /** Every locale's draft as the last heartbeat saw it. */\n drafts: readonly DraftState[];\n /** The locale of the draft this document shows (the entry's own, also for a model without locales). */\n locale: string | undefined;\n /** The draft version this document shows (kept with `versionRef` by every save and publish). */\n shownVersion: number | undefined;\n dirty: boolean;\n /** A save, publish or restore of this tab is under way: its own new version may not be shown yet. */\n busy: boolean;\n conflict: string | undefined;\n onConflict: (code: string) => void;\n};\n\n/**\n * Notices a draft that moved on the server past the version this document shows (another tab or person\n * saved it). With no unsaved edits it returns the change, for a quiet \"Changed by … Reload\" notice; with\n * unsaved edits it raises the conflict banner a save would have raised, so nothing is lost or overwritten.\n */\nexport const useRemoteDraftChange = ({\n drafts,\n locale,\n shownVersion,\n dirty,\n busy,\n conflict,\n onConflict,\n}: RemoteDraftChangeOptions): { remoteChange: RemoteChange | null } => {\n const server = drafts.find((draft) => draft.locale === locale);\n // Only newer counts: this tab's own saves raise the version it shows and never look like someone else's.\n const moved =\n !busy &&\n conflict === undefined &&\n server !== undefined &&\n shownVersion !== undefined &&\n server.version > shownVersion;\n const raise = moved && dirty;\n useEffect(() => {\n if (raise) {\n onConflict(EDIT_CONFLICT);\n }\n }, [raise, onConflict]);\n return { remoteChange: moved && !dirty ? { savedAt: server.savedAt, savedBy: server.savedBy } : null };\n};\n","import type { DraftState } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { useState } from 'react';\nimport { useStore } from 'zustand';\nimport { selectDirtyKeys } from '@/fields/form/store';\nimport { isEmptyValue, type FormValues } from '@/fields/helpers/values';\nimport { useFollowingSlugs } from '@/fields/hooks/useFollowingSlugs';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\nimport type { EntryMode, ReloadEntry } from '../types';\nimport { useAutosave } from './useAutosave';\nimport { useEntryLifecycle } from './useEntryLifecycle';\nimport { useEntryPermissions } from './useEntryPermissions';\nimport { useEntrySaver } from './useEntrySaver';\nimport { useEntrySetup } from './useEntrySetup';\nimport { usePublishing } from './usePublishing';\nimport { useRemoteDraftChange } from './useRemoteDraftChange';\n\ntype EntryDocumentOptions = {\n schema: ContentSchema;\n model: ModelDefinition;\n mode: EntryMode;\n locale: string | null;\n defaultLocale: string | undefined;\n carry: FormValues | undefined;\n onReload: ReloadEntry;\n /** Every locale's draft as the presence heartbeat last saw it (saves made elsewhere). */\n drafts: readonly DraftState[];\n};\n\n/**\n * Everything one open entry document does, composed: its value store and field environment, saving\n * (autosave, Save, the version guard and conflicts), creating, deleting, duplicating, restoring, copying\n * between locales, publishing per locale, noticing saves made elsewhere, and what the admin is allowed to do.\n */\nexport const useEntryDocument = ({\n schema,\n model,\n mode,\n locale,\n defaultLocale,\n carry,\n onReload,\n drafts,\n}: EntryDocumentOptions) => {\n const permissions = useEntryPermissions(model);\n const [conflict, setConflict] = useState<string | undefined>();\n const [reloading, setReloading] = useState(false);\n const setup = useEntrySetup({\n schema,\n model,\n mode,\n locale,\n carry,\n disabled: conflict !== undefined || reloading,\n readOnly: mode.kind === 'create' ? !permissions.canCreate : !permissions.canUpdate,\n });\n const { store, entry, setEntry, versionRef, entryId } = setup;\n const dirty = useStore(store, (state) => selectDirtyKeys(state).length > 0);\n // Copying from the default locale replaces localized values: it asks first when there are some.\n const hasLocalizedValues = useStore(store, (state) =>\n model.fields.some((field) => field.localized && !isEmptyValue(state.values[field.apiKey])),\n );\n const saver = useEntrySaver({\n model,\n components: schema.components,\n entryId: entryId ?? '',\n locale,\n store,\n versionRef,\n onAsset: setup.onAsset,\n onConflict: (error) => setConflict(error.code),\n onSaved: (saved) => {\n setEntry(saved);\n if (mode.kind === 'newLocale') {\n onReload(null);\n }\n },\n });\n const lifecycle = useEntryLifecycle({\n model,\n components: schema.components,\n store,\n entryId,\n locale,\n defaultLocale,\n versionRef,\n exclusive: saver.exclusive,\n onAsset: setup.onAsset,\n onConflict: setConflict,\n onRestored: () => onReload(null),\n });\n const publishing = usePublishing({\n modelKey: model.apiKey,\n entryId,\n autosaved: entry?.autosaved ?? false,\n locale,\n versionRef,\n entryLocales: entry?.locales ?? [],\n store,\n save: saver.save,\n exclusive: saver.exclusive,\n onEntry: (next) => {\n setEntry(next);\n versionRef.current = next.version;\n },\n onConflict: (error) => setConflict(error.code),\n });\n const { remoteChange } = useRemoteDraftChange({\n drafts,\n locale: entry?.locale,\n shownVersion: entry?.version,\n dirty,\n busy:\n saver.state.status === 'saving' ||\n publishing.publishing ||\n publishing.unpublishing ||\n lifecycle.restoring,\n conflict,\n onConflict: setConflict,\n });\n const editable = !setup.environment.readOnly;\n useFollowingSlugs(store, model, editable && mode.kind !== 'newLocale');\n useAutosave(\n store,\n mode.kind === 'edit' && model.draftAndPublish && conflict === undefined && editable,\n saver.save,\n );\n const save = () => (mode.kind === 'create' ? void lifecycle.create() : void saver.save('save'));\n const reload = (keepChanges: boolean) => {\n setReloading(true);\n const { values: current, baseline } = store.getState();\n const local = Object.fromEntries(\n selectDirtyKeys({ values: current, baseline }).map((key) => [key, current[key]]),\n );\n onReload(keepChanges ? local : null);\n };\n return {\n setup,\n permissions,\n conflict,\n remoteChange,\n reloading,\n dirty,\n hasLocalizedValues,\n saver,\n lifecycle,\n publishing,\n save,\n reload,\n editable,\n };\n};\n","import type { PresenceHeartbeatInput } from '@shapio/client';\nimport { ADMIN_PATHS } from '@shapio/client';\nimport { useQuery } from '@tanstack/react-query';\nimport { useSessionStore } from '@/stores/session';\nimport { adminApi, apiBaseUrl, CSRF_HEADER } from './client';\nimport { withCsrf } from './csrf';\nimport { queryKeys } from './queryKeys';\n\nconst silent = { silent: true } as const;\n\n/** Heartbeat interval while the document is visible (the server forgets a tab after 45s without one). */\nexport const PRESENCE_HEARTBEAT_MS = 15_000;\n\n/**\n * What publishing would run into, for the pre-flight sheet: read fresh every time it opens (the caller\n * saves first), never retried silently.\n */\nexport const usePreflight = (modelKey: string, id: string, locale: string | undefined, enabled: boolean) =>\n useQuery({\n queryKey: queryKeys.entryDocument.preflight(modelKey, id, locale),\n queryFn: () => withCsrf(() => adminApi.preflight.run(modelKey, id, locale ? { locales: [locale] } : {})),\n enabled,\n staleTime: 0,\n gcTime: 0,\n retry: false,\n meta: silent,\n });\n\n/**\n * Presence: a heartbeat every 15s while this tab shows the entry (paused while hidden); each answer lists\n * who else has it open. Presence is information only: entries lock nothing.\n */\nexport const useEntryPresenceQuery = (\n modelKey: string,\n id: string | null,\n input: PresenceHeartbeatInput,\n enabled: boolean,\n) =>\n useQuery({\n queryKey: queryKeys.presence(modelKey, id ?? ''),\n queryFn: () => withCsrf(() => adminApi.presence.heartbeat(modelKey, id ?? '', input)),\n enabled: enabled && id !== null,\n refetchInterval: PRESENCE_HEARTBEAT_MS,\n refetchIntervalInBackground: false,\n staleTime: 0,\n gcTime: 0,\n retry: false,\n meta: silent,\n });\n\n/** Leaves on a normal unmount (navigating away inside the admin). */\nexport const leavePresence = (modelKey: string, id: string, tabId: string) =>\n withCsrf(() => adminApi.presence.leave(modelKey, id, tabId));\n\n/**\n * Leaves while the page itself goes away (tab closed, reload): a keepalive request outlives the page,\n * which an ordinary fetch would not.\n */\nexport const leavePresenceOnUnload = (modelKey: string, id: string, tabId: string) => {\n const token = useSessionStore.getState().csrfToken;\n const path = `${ADMIN_PATHS.presence}/${encodeURIComponent(modelKey)}/${encodeURIComponent(id)}`;\n const url = new URL(`${path.replace(/^\\//, '')}?tabId=${encodeURIComponent(tabId)}`, apiBaseUrl());\n void fetch(url, {\n method: 'DELETE',\n keepalive: true,\n credentials: 'same-origin',\n headers: token ? { [CSRF_HEADER]: token } : {},\n }).catch(() => undefined);\n};\n","import type { DraftState, PresencePerson } from '@shapio/client';\nimport { useEffect, useState, useSyncExternalStore } from 'react';\nimport { leavePresence, leavePresenceOnUnload, useEntryPresenceQuery } from '@/api/entryDocument';\nimport { logError } from '@/helpers/reportError';\n\nconst subscribeVisibility = (onChange: () => void) => {\n document.addEventListener('visibilitychange', onChange);\n return () => document.removeEventListener('visibilitychange', onChange);\n};\n\nconst isVisible = () => document.visibilityState === 'visible';\n\nconst NO_PEOPLE: PresencePerson[] = [];\nconst NO_DRAFTS: DraftState[] = [];\n\n/**\n * This tab's heartbeat while it is visible: who else has this entry open, and every locale's draft version\n * as the server has it (so the document learns about saves made elsewhere). The tab leaves when the\n * document closes (a keepalive request when the page itself goes away). Information only; nothing locks.\n */\nexport const useEntryHeartbeat = (modelKey: string, entryId: string | null, locale: string | null) => {\n const [tabId] = useState(() => crypto.randomUUID());\n const visible = useSyncExternalStore(subscribeVisibility, isVisible, () => true);\n const presence = useEntryPresenceQuery(modelKey, entryId, { tabId, locale }, visible);\n useEffect(() => {\n if (!entryId) {\n return undefined;\n }\n const onPageHide = () => leavePresenceOnUnload(modelKey, entryId, tabId);\n window.addEventListener('pagehide', onPageHide);\n return () => {\n window.removeEventListener('pagehide', onPageHide);\n leavePresence(modelKey, entryId, tabId).catch((error: unknown) =>\n logError(error, 'leaving an entry (presence)'),\n );\n };\n }, [modelKey, entryId, tabId]);\n return { people: presence.data?.people ?? NO_PEOPLE, drafts: presence.data?.drafts ?? NO_DRAFTS };\n};\n","import { useState } from 'react';\nimport type { SaveKind, SaveOutcome } from './useEntrySaver';\n\n/**\n * Opening the pre-flight: unsaved changes are autosaved first (no revision, nothing validated beyond the\n * format), so the checks are about what is on screen. A conflict closes it again (the banner takes over).\n */\nexport const usePreflightFlow = (save: (kind: SaveKind) => Promise<SaveOutcome>) => {\n const [open, setOpen] = useState(false);\n const [ready, setReady] = useState(false);\n const start = async () => {\n setReady(false);\n setOpen(true);\n const outcome = await save('autosave');\n if (outcome === 'conflict') {\n setOpen(false);\n return;\n }\n setReady(true);\n };\n return {\n open,\n ready,\n start: () => void start(),\n setOpen: (next: boolean) => (next ? void start() : setOpen(false)),\n };\n};\n","import { useCallback } from 'react';\nimport { fieldDomId } from '@/fields/helpers/domIds';\n\nconst FOCUSABLE =\n 'input:not([type=\"hidden\"]), textarea, select, [contenteditable=\"true\"], button[aria-expanded], button';\n\n/** The element for a path, or the closest ancestor path that is on the page (a collapsed item's block). */\nconst elementFor = (path: string) => {\n const segments = path.split('/');\n for (let length = segments.length; length > 1; length -= 1) {\n const candidate = document.querySelector<HTMLElement>(\n `[data-field-path=\"${CSS.escape(segments.slice(0, length).join('/'))}\"]`,\n );\n if (candidate) {\n return candidate;\n }\n }\n return null;\n};\n\n/**\n * Takes a person to a value (a pre-flight \"Fix\" link): opens the settings drawer when the field is a\n * property that isn't on the page, then scrolls to it and focuses its control. An image without alt text\n * focuses that image's alt input.\n */\nexport const useRevealField = (idPrefix: string, openProperty: (apiKey: string) => void) =>\n useCallback(\n (path: string, assetId?: string) => {\n const apiKey = path.split('/')[1] ?? '';\n const focus = () => {\n const target = elementFor(path);\n if (!target) {\n return false;\n }\n target.scrollIntoView({ behavior: 'smooth', block: 'center' });\n const image = assetId\n ? target.querySelector<HTMLElement>(`[data-media-id=\"${CSS.escape(assetId)}\"] [data-alt-input]`)\n : null;\n const control =\n image ??\n document.getElementById(fieldDomId(idPrefix, path)) ??\n target.querySelector<HTMLElement>(FOCUSABLE);\n control?.focus({ preventScroll: true });\n return true;\n };\n if (!focus()) {\n openProperty(apiKey);\n // The drawer renders the row on the next frames.\n window.setTimeout(focus, 150);\n }\n },\n [idPrefix, openProperty],\n );\n","import { useCallback, useSyncExternalStore } from 'react';\n\n/** Tailwind's `xl` (80rem): the entry's Settings panel sits beside the document from here up. */\nexport const XL_QUERY = '(min-width: 80rem)';\n\n/**\n * Whether a media query matches, kept current as the viewport changes. `serverValue` is what it reports\n * where there is no `window` (tests without a DOM).\n */\nexport const useMediaQuery = (query: string, serverValue = false): boolean => {\n const subscribe = useCallback(\n (onChange: () => void) => {\n const list = window.matchMedia(query);\n list.addEventListener('change', onChange);\n return () => list.removeEventListener('change', onChange);\n },\n [query],\n );\n const getSnapshot = useCallback(() => window.matchMedia(query).matches, [query]);\n return useSyncExternalStore(subscribe, getSnapshot, () => serverValue);\n};\n","import { useCallback, useState } from 'react';\nimport { useMediaQuery, XL_QUERY } from '@/hooks/useMediaQuery';\nimport { useUiStore } from '@/stores/ui';\nimport type { DrawerFocus } from '../SettingsDrawer';\n\n/**\n * The settings drawer's state: open, where it opened, which property rows are expanded. On wide screens\n * (`xl`, where it sits beside the document) it is open unless the person closed it, and every open or close\n * there is remembered per browser; narrower, it overlays the document and starts closed (a window narrowed\n * while it is open keeps it open). `automatic` is true\n * while it is open only because of that default, so it doesn't take focus from the document.\n */\nexport const useSettingsDrawer = () => {\n const wide = useMediaQuery(XL_QUERY);\n const remembered = useUiStore((state) => state.entrySettingsOpen);\n const remember = useUiStore((state) => state.setEntrySettingsOpen);\n const [narrowOpen, setNarrowOpen] = useState(false);\n // Closed for the preview without changing the remembered choice; any open or close clears it.\n const [hidden, setHidden] = useState(false);\n const [touched, setTouched] = useState(false);\n const [focus, setFocus] = useState<DrawerFocus>({ section: 'status' });\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(new Set());\n const open = wide ? remembered && !hidden : narrowOpen;\n // Narrowing the window (a resized window, a rotated tablet) keeps the drawer as it was; only a narrow\n // start is closed. Adjusted while rendering, React's pattern for state that follows a changed input.\n const [wasWide, setWasWide] = useState(wide);\n if (wasWide !== wide) {\n setWasWide(wide);\n if (!wide) {\n setNarrowOpen(remembered && !hidden);\n }\n }\n\n // Stable, and reads the viewport when called: Radix can keep an `onOpenChange` from before a resize.\n const setOpen = useCallback(\n (next: boolean) => {\n setTouched(true);\n setHidden(false);\n if (window.matchMedia(XL_QUERY).matches) {\n remember(next);\n } else {\n setNarrowOpen(next);\n }\n },\n [remember],\n );\n const openAt = useCallback(\n (next: DrawerFocus) => {\n setFocus(next);\n if (next.property) {\n const property = next.property;\n setExpanded((current) => new Set([...current, property]));\n }\n setOpen(true);\n },\n [setOpen],\n );\n const toggleProperty = useCallback(\n (apiKey: string) =>\n setExpanded((current) => {\n const next = new Set(current);\n if (next.has(apiKey)) {\n next.delete(apiKey);\n } else {\n next.add(apiKey);\n }\n return next;\n }),\n [],\n );\n return {\n open,\n automatic: open && !touched,\n setOpen,\n focus,\n expanded,\n openAt,\n toggle: useCallback(() => setOpen(!open), [setOpen, open]),\n /** Makes room for the preview: closes the drawer without changing the remembered choice. */\n hideForPreview: useCallback(() => setHidden(true), []),\n toggleProperty,\n };\n};\n","import type { PlanPreview } from '@shapio/client';\nimport type { EntryLayout, ModelDefinition } from '@shapio/schema';\n\n/** The definition with `display.layout` set; Document is the default, so it is written as unset. */\nexport const withEntryLayout = (definition: ModelDefinition, layout: EntryLayout): ModelDefinition => {\n const display = { ...definition.display };\n delete display.layout;\n return { ...definition, display: layout === 'form' ? { ...display, layout } : display };\n};\n\n/**\n * Whether a plan can ship from the entry's drawer without a review: metadata only, nothing to check first,\n * no validation issues. A layout change always is; anything else goes through the builder's review.\n */\nexport const isQuietPlan = (plan: PlanPreview['plan']): boolean =>\n plan.summary.metadataOnly &&\n !plan.summary.breaking &&\n !plan.summary.destructive &&\n plan.prerequisites.length === 0 &&\n plan.issues.length === 0;\n","import { entryLayoutOf, type EntryLayout, type ModelDefinition } from '@shapio/schema';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useShipDraftNow } from '@/api/changeSets';\nimport { hasErrorCode } from '@/api/errors';\nimport { queryKeys } from '@/api/queryKeys';\nimport { definitionQueryOptions, usePlanChange } from '@/api/schema';\nimport { describeError } from '@/helpers/describeError';\nimport { logError } from '@/helpers/reportError';\nimport { isQuietPlan, withEntryLayout } from '../helpers/layoutSwitch';\n\nconst SWITCHED_KEYS = {\n document: 'entry.layout.switchedDocument',\n form: 'entry.layout.switchedForm',\n} as const satisfies Record<EntryLayout, string>;\n\n/** The plan asked for more than a metadata change: the drawer never ships that without a review. */\nclass NeedsReviewError extends Error {}\n\n/**\n * Switches how the model's entries open (`display.layout`) from the entry's Settings, at once: loads the\n * active definition, plans the change (it must be metadata only), and ships it as a one-item change set,\n * like the builder's Ship now without the review. The toast offers Undo, which ships the previous layout\n * the same way. The schema queries refresh, so the open entry re-renders in the new layout.\n */\nexport const useLayoutSwitch = (model: ModelDefinition) => {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const plan = usePlanChange();\n const ship = useShipDraftNow();\n\n /** Ships `layout`; resolves with the layout it replaced. */\n const shipLayout = async (layout: EntryLayout): Promise<EntryLayout> => {\n const detail = await queryClient.fetchQuery({\n ...definitionQueryOptions('model', model.id),\n staleTime: 0,\n });\n const current = detail.definition as ModelDefinition;\n const definition = withEntryLayout(current, layout);\n const preview = await plan.mutateAsync({\n category: 'model',\n id: model.id,\n definition,\n expectedVersion: detail.version,\n });\n if (!isQuietPlan(preview.plan)) {\n throw new NeedsReviewError();\n }\n await ship.mutateAsync({\n definitionId: model.id,\n input: { category: 'model', definition, baseVersion: detail.version },\n acknowledgement: {},\n title: t('entry.layout.setTitle', { model: current.label }),\n });\n // The detail fetched above is the old version, and nothing observes it to refetch after the ship's\n // invalidation: drop it, so the builder (which starts from the cached detail) loads the new one.\n queryClient.removeQueries({ queryKey: queryKeys.schema.definition('model', model.id), exact: true });\n return entryLayoutOf(current);\n };\n\n const notifyFailure = (error: unknown) => {\n if (error instanceof NeedsReviewError) {\n toast.error(t('entry.layout.needsReview'));\n return;\n }\n logError(error, 'switching the entry layout');\n toast.error(describeError(error));\n if (hasErrorCode(error, 'SCHEMA_VERSION_CONFLICT')) {\n void queryClient.invalidateQueries({ queryKey: queryKeys.schema.all });\n }\n };\n\n const change = async (layout: EntryLayout, undoable: boolean): Promise<void> => {\n try {\n const previous = await shipLayout(layout);\n toast.success(\n t(SWITCHED_KEYS[layout], { model: model.label }),\n undoable && previous !== layout\n ? { action: { label: t('entry.layout.undo'), onClick: () => void change(previous, false) } }\n : undefined,\n );\n } catch (error) {\n notifyFailure(error);\n }\n };\n\n return {\n layout: entryLayoutOf(model),\n /** Ships the layout; the toast offers Undo. Failures show as a toast. */\n change: (layout: EntryLayout) => change(layout, true),\n pending: plan.isPending || ship.isPending,\n };\n};\n","import type { EntryLayout, ModelDefinition } from '@shapio/schema';\nimport type { MouseEvent } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Switch } from '@/components/ui/switch';\nimport { cn } from '@/helpers/cn';\nimport { DrawerSection } from '../DrawerSection';\nimport { useLayoutSwitch } from '../hooks/useLayoutSwitch';\n\ntype LayoutSectionProps = { model: ModelDefinition };\n\nconst SECTION_ID = 'entry-settings-layout';\nconst SWITCH_ID = `${SECTION_ID}-switch`;\n\nconst wordClasses = {\n chosen: 'text-foreground',\n other: 'text-muted-foreground hover:text-foreground',\n} as const;\n\n/**\n * How the type's entries open, switched from the entry itself (for whoever manages the schema): a switch\n * between the words Document and Form, on for Form. Either word picks its side. The change ships at once,\n * live, and the toast offers Undo.\n */\nexport const LayoutSection = ({ model }: LayoutSectionProps) => {\n const { t } = useTranslation();\n const { layout, change, pending } = useLayoutSwitch(model);\n const form = layout === 'form';\n // A word is a label of the switch; the chosen side's word does nothing instead of toggling it away.\n const word = (side: EntryLayout, text: string) => (\n <label\n htmlFor={SWITCH_ID}\n onClick={(event: MouseEvent) => {\n if (side === layout) {\n event.preventDefault();\n }\n }}\n className={cn(\n 'cursor-pointer text-sm font-medium transition-colors',\n side === layout ? wordClasses.chosen : wordClasses.other,\n pending && 'pointer-events-none opacity-50',\n )}\n >\n {text}\n </label>\n );\n return (\n <DrawerSection id={SECTION_ID} title={t('models.builder.layout')}>\n <div className=\"flex h-9 items-center gap-3\">\n {word('document', t('models.builder.layoutDocument'))}\n <Switch\n id={SWITCH_ID}\n aria-label={t('entry.layout.switchLabel')}\n checked={form}\n disabled={pending}\n onCheckedChange={(checked) => void change(checked ? 'form' : 'document')}\n />\n {word('form', t('models.builder.layoutForm'))}\n </div>\n </DrawerSection>\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { Link } from '@tanstack/react-router';\nimport { ListPlus } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Button } from '@/components/ui/button';\n\ntype NoFieldsProps = { model: ModelDefinition; canManageSchema: boolean };\n\n/** A content type without fields has nothing to write yet: point people who can add fields to Structure. */\nexport const NoFields = ({ model, canManageSchema }: NoFieldsProps) => {\n const { t } = useTranslation();\n return (\n <EmptyState\n size=\"panel\"\n icon={ListPlus}\n title={t('entry.noFields.title')}\n description={canManageSchema ? undefined : t('entry.noFields.ask')}\n action={\n canManageSchema ? (\n <Button asChild>\n <Link to=\"/content/$modelKey\" params={{ modelKey: model.apiKey }} search={{ tab: 'structure' }}>\n {t('entry.noFields.addFields')}\n </Link>\n </Button>\n ) : undefined\n }\n />\n );\n};\n","import type { AssistIssue } from '@shapio/client';\nimport { create } from 'zustand';\n\n/** A locale draft an assist wrote (translate): shown with \"Proposed by {model}\" until dismissed. */\nexport type AssistProposal = { model: string; from: string; issues: readonly AssistIssue[] };\n\ntype AssistProposalsState = {\n proposals: Readonly<Record<string, AssistProposal>>;\n propose: (key: string, proposal: AssistProposal) => void;\n dismiss: (key: string) => void;\n};\n\n/** One entry locale (the document's locale; `-` for non-localized models). */\nexport const proposalKey = (modelKey: string, entryId: string, locale: string | null) =>\n `${modelKey}/${entryId}/${locale ?? '-'}`;\n\n/**\n * Proposals awaiting review, by entry locale (client-only, for this page load). Kept outside the document\n * because opening the new locale reloads it.\n */\nexport const useAssistProposalsStore = create<AssistProposalsState>()((set) => ({\n proposals: {},\n propose: (key, proposal) => set((state) => ({ proposals: { ...state.proposals, [key]: proposal } })),\n dismiss: (key) =>\n set((state) => {\n const { [key]: _dismissed, ...rest } = state.proposals;\n return { proposals: rest };\n }),\n}));\n","import { Sparkles } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { useFieldsEnvironment } from '@/fields/form/context';\nimport { proposalKey, useAssistProposalsStore } from '@/stores/assistProposals';\n\ntype AssistProposalBannerProps = { labelOf: (code: string) => string };\n\n/**\n * \"Proposed by {model}\" over a locale draft an assist just wrote (translate): review before publishing.\n * The translation's issues (values cut to a limit, segments left untranslated) are listed by field.\n */\nexport const AssistProposalBanner = ({ labelOf }: AssistProposalBannerProps) => {\n const { t } = useTranslation();\n const { model, entryId, locale } = useFieldsEnvironment();\n const key = entryId ? proposalKey(model.apiKey, entryId, locale) : '';\n const proposal = useAssistProposalsStore((state) => state.proposals[key]);\n const dismiss = useAssistProposalsStore((state) => state.dismiss);\n if (!proposal) {\n return null;\n }\n const labelOfPath = (path: string) => {\n const apiKey = path.split('/')[1] ?? '';\n return model.fields.find((field) => field.apiKey === apiKey)?.label ?? apiKey;\n };\n return (\n <Alert variant=\"info\" role=\"status\">\n <Sparkles aria-hidden=\"true\" />\n <AlertTitle>{t('assist.proposal.title', { model: proposal.model })}</AlertTitle>\n <AlertDescription className=\"space-y-2\">\n <p>{t('assist.proposal.description', { from: labelOf(proposal.from) })}</p>\n {proposal.issues.length > 0 ? (\n <ul aria-label={t('assist.proposal.issues')} className=\"list-disc space-y-0.5 pl-5\">\n {proposal.issues.map((issue) => (\n <li key={`${issue.path}:${issue.code}`}>\n <span className=\"font-semibold\">{labelOfPath(issue.path)}</span>: {issue.message}\n </li>\n ))}\n </ul>\n ) : null}\n <div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => dismiss(key)}>\n {t('assist.proposal.dismiss')}\n </Button>\n </div>\n </AlertDescription>\n </Alert>\n );\n};\n","import { RefreshCw, TriangleAlert } from 'lucide-react';\nimport { useEffect, useRef } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\n\ntype ConflictBannerProps = {\n /** CONTENT_VERSION_CONFLICT (someone else saved) or SCHEMA_CHANGED (the model changed). */\n code: string;\n busy: boolean;\n onReloadKeepingChanges: () => void;\n onDiscard: () => void;\n};\n\n/**\n * A save lost a race: the draft or the model changed since this form loaded. Nothing is overwritten\n * silently: reload the latest version and reapply this person's changes on top, or discard them. The form\n * is read-only meanwhile, so focus moves to the banner (the field being typed in was just disabled).\n */\nexport const ConflictBanner = ({ code, busy, onReloadKeepingChanges, onDiscard }: ConflictBannerProps) => {\n const { t } = useTranslation();\n const reloadRef = useRef<HTMLButtonElement>(null);\n useEffect(() => {\n reloadRef.current?.focus();\n }, []);\n return (\n <Alert variant=\"warning\">\n <TriangleAlert aria-hidden=\"true\" />\n <AlertTitle>\n {code === 'SCHEMA_CHANGED' ? t('content.conflict.schemaTitle') : t('content.conflict.title')}\n </AlertTitle>\n <AlertDescription className=\"space-y-3\">\n <p>{t('content.conflict.description')}</p>\n <div className=\"flex flex-wrap gap-2\">\n <Button ref={reloadRef} type=\"button\" size=\"sm\" disabled={busy} onClick={onReloadKeepingChanges}>\n <RefreshCw aria-hidden=\"true\" />\n {t('content.conflict.reload')}\n </Button>\n <InlineConfirm\n tone=\"danger\"\n align=\"start\"\n title={t('content.conflict.discardTitle')}\n description={t('content.conflict.discardDescription')}\n confirmLabel={t('content.conflict.discardConfirm')}\n onConfirm={onDiscard}\n trigger={\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={busy}>\n {t('content.conflict.discard')}\n </Button>\n }\n />\n </div>\n </AlertDescription>\n </Alert>\n );\n};\n","import { Send } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Alert, AlertDescription } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\n\ntype PublishOthersAlertProps = {\n /** Other published locales that still serve older shared (non-localized) values. */\n locales: readonly string[];\n labelOf: (code: string) => string;\n /** A publish is running: the action waits for it. */\n publishing: boolean;\n onPublish: (locales: string[]) => void;\n onDismiss: () => void;\n};\n\n/**\n * Publishing is per locale (ADR 0004), so other published locales keep their older shared values until\n * they are published too: one action publishes them all, \"Not now\" hides the notice until the next publish.\n */\nexport const PublishOthersAlert = ({\n locales,\n labelOf,\n publishing,\n onPublish,\n onDismiss,\n}: PublishOthersAlertProps) => {\n const { t } = useTranslation();\n return (\n <Alert variant=\"warning\">\n <AlertDescription className=\"space-y-2\">\n <p>\n {t('content.publishOthers.notice', {\n count: locales.length,\n locales: locales.map(labelOf).join(', '),\n })}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n disabled={publishing}\n onClick={() => onPublish([...locales])}\n >\n <Send aria-hidden=\"true\" />\n {t('content.publishOthers.confirm', { count: locales.length })}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={onDismiss}>\n {t('content.publishOthers.notNow')}\n </Button>\n </div>\n </AlertDescription>\n </Alert>\n );\n};\n","import type { EntryReferrer } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { Link } from '@tanstack/react-router';\nimport { Link2 } from 'lucide-react';\nimport { useEffect, useRef } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { shortId } from '@/fields/helpers/titles';\n\ntype ReferencedAlertProps = {\n referrers: readonly EntryReferrer[];\n models: ReadonlyMap<string, ModelDefinition>;\n onDismiss: () => void;\n};\n\n/**\n * Why an entry can't be deleted (409 ENTRY_REFERENCED): the entries that still link to it, as links. It\n * scrolls into view when it appears, since the side panel sits below the fields on narrow screens.\n */\nexport const ReferencedAlert = ({ referrers, models, onDismiss }: ReferencedAlertProps) => {\n const { t } = useTranslation();\n const ref = useRef<HTMLDivElement>(null);\n useEffect(() => {\n ref.current?.scrollIntoView({ block: 'nearest' });\n }, []);\n const unique = referrers.filter(\n (referrer, index) => referrers.findIndex((other) => other.entryId === referrer.entryId) === index,\n );\n return (\n <Alert ref={ref} variant=\"destructive\">\n <Link2 aria-hidden=\"true\" />\n <AlertTitle>{t('content.referenced.title')}</AlertTitle>\n <AlertDescription className=\"space-y-2\">\n <p>{t('content.referenced.description')}</p>\n <ul className=\"space-y-1\">\n {unique.map((referrer) => {\n const model = models.get(referrer.modelId);\n return (\n <li key={referrer.entryId}>\n {model ? (\n <Link\n to=\"/content/$modelKey/$entryId\"\n params={{ modelKey: model.apiKey, entryId: referrer.entryId }}\n search={model.localized ? { locale: referrer.locale } : {}}\n className=\"font-semibold underline underline-offset-4\"\n >\n {t('content.referenced.entry', { model: model.label, id: shortId(referrer.entryId) })}\n </Link>\n ) : (\n t('content.referenced.unknown', { id: shortId(referrer.entryId) })\n )}\n </li>\n );\n })}\n </ul>\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={onDismiss}>\n {t('common.close')}\n </Button>\n </AlertDescription>\n </Alert>\n );\n};\n","import type { EntryReferrer } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Alert, AlertDescription } from '@/components/ui/alert';\nimport { AssistProposalBanner } from '../AssistProposalBanner';\nimport { ConflictBanner } from '../ConflictBanner';\nimport { PublishOthersAlert } from '../PublishOthersAlert';\nimport { ReferencedAlert } from '../ReferencedAlert';\n\ntype NoticesProps = {\n conflict: string | undefined;\n reloading: boolean;\n onReload: (keepChanges: boolean) => void;\n /** The locale being started (this entry has no version in it yet). */\n newLocaleLabel: string | undefined;\n /** An action for the locale being started (\"Translate from English\", when assist is on). */\n newLocaleAction?: ReactNode;\n referrers: readonly EntryReferrer[];\n models: ReadonlyMap<string, ModelDefinition>;\n onDismissReferrers: () => void;\n /** Other published locales still serving older shared values. */\n outdated: readonly string[];\n labelOf: (code: string) => string;\n publishing: boolean;\n onPublishOthers: (locales: string[]) => void;\n onDismissOthers: () => void;\n};\n\n/** What the document needs to tell before anything else: conflicts, a new locale, why it can't be deleted. */\nexport const Notices = ({\n conflict,\n reloading,\n onReload,\n newLocaleLabel,\n newLocaleAction,\n referrers,\n models,\n onDismissReferrers,\n outdated,\n labelOf,\n publishing,\n onPublishOthers,\n onDismissOthers,\n}: NoticesProps) => {\n const { t } = useTranslation();\n return (\n <>\n {conflict !== undefined ? (\n <ConflictBanner\n code={conflict}\n busy={reloading}\n onReloadKeepingChanges={() => onReload(true)}\n onDiscard={() => onReload(false)}\n />\n ) : null}\n {newLocaleLabel ? (\n <Alert variant=\"info\">\n <AlertDescription className=\"space-y-2\">\n <p>{t('content.locales.missing', { locale: newLocaleLabel })}</p>\n {newLocaleAction}\n </AlertDescription>\n </Alert>\n ) : null}\n <AssistProposalBanner labelOf={labelOf} />\n {referrers.length > 0 ? (\n <ReferencedAlert referrers={referrers} models={models} onDismiss={onDismissReferrers} />\n ) : null}\n {outdated.length > 0 ? (\n <PublishOthersAlert\n locales={outdated}\n labelOf={labelOf}\n publishing={publishing}\n onPublish={onPublishOthers}\n onDismiss={onDismissOthers}\n />\n ) : null}\n </>\n );\n};\n","import { useNavigate } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useAddChangeSetEntry, useCreateChangeSet } from '@/api/changeSets';\nimport { useFieldsEnvironment } from '@/fields/form/context';\n\n/**\n * Adds this entry's locale to a change set (published when the set ships), or to a new set created with\n * `title` first; the toast links to the set. Errors stay with the mutations for the popover to show.\n */\nexport const useAddEntryToChangeSet = (entryId: string, locale: string | null) => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { model } = useFieldsEnvironment();\n const addEntry = useAddChangeSetEntry();\n const createChangeSet = useCreateChangeSet();\n const addTo = async (id: string) => {\n const set = await addEntry.mutateAsync({\n id,\n input: { modelKey: model.apiKey, entryId, ...(locale ? { locale } : {}), action: 'publish' },\n });\n toast.success(t('entry.changeSet.added', { title: set.title }), {\n action: {\n label: t('entry.changeSet.open'),\n onClick: () => void navigate({ to: '/changes/$changeSetId', params: { changeSetId: set.id } }),\n },\n });\n };\n return {\n addTo,\n createAndAdd: async (title: string) => {\n const set = await createChangeSet.mutateAsync({ title });\n await addTo(set.id);\n },\n pending: addEntry.isPending || createChangeSet.isPending,\n error: addEntry.error ?? createChangeSet.error,\n reset: () => {\n addEntry.reset();\n createChangeSet.reset();\n },\n };\n};\n","import { FolderPlus } from 'lucide-react';\nimport { useId, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useChangeSets } from '@/api/changeSets';\nimport { FormError } from '@/components/FormError';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { logError } from '@/helpers/reportError';\nimport { useAddEntryToChangeSet } from '../hooks/useAddEntryToChangeSet';\n\ntype AddToChangeSetProps = {\n entryId: string;\n /** The locale being edited (null for a non-localized model). */\n locale: string | null;\n disabled: boolean;\n /** Runs once the entry is in a set (the pre-flight closes). */\n onAdded: () => void;\n};\n\n/**\n * \"Add to change set…\" in the pre-flight: publish this locale when a change set ships, instead of now.\n * Pick an open set, or name a new one.\n */\nexport const AddToChangeSet = ({ entryId, locale, disabled, onAdded }: AddToChangeSetProps) => {\n const { t } = useTranslation();\n const titleId = useId();\n const inputId = useId();\n const [open, setOpen] = useState(false);\n const [newTitle, setNewTitle] = useState('');\n const sets = useChangeSets('open');\n const { addTo, createAndAdd, pending, error, reset } = useAddEntryToChangeSet(entryId, locale);\n const run = (action: () => Promise<void>) =>\n void action().then(\n () => {\n setOpen(false);\n onAdded();\n },\n (cause: unknown) => logError(cause, 'adding an entry to a change set'),\n );\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n if (pending) {\n return;\n }\n setOpen(next);\n if (next) {\n reset();\n setNewTitle('');\n }\n }}\n >\n <PopoverTrigger asChild>\n <Button type=\"button\" variant=\"outline\" disabled={disabled}>\n <FolderPlus aria-hidden=\"true\" />\n {t('entry.changeSet.add')}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" side=\"top\" aria-labelledby={titleId} className=\"w-80 space-y-3\">\n <p id={titleId} className=\"text-sm font-semibold\">\n {t('entry.changeSet.title')}\n </p>\n {sets.data && sets.data.items.length > 0 ? (\n <ul aria-label={t('entry.changeSet.openSets')} className=\"max-h-56 space-y-1 overflow-y-auto\">\n {sets.data.items.map((set) => (\n <li key={set.id}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"w-full justify-start truncate\"\n disabled={pending}\n onClick={() => run(() => addTo(set.id))}\n >\n {set.title}\n </Button>\n </li>\n ))}\n </ul>\n ) : (\n <p className=\"text-meta text-muted-foreground\">{t('entry.changeSet.none')}</p>\n )}\n <form\n noValidate\n className=\"space-y-2 border-t pt-3\"\n onSubmit={(event) => {\n event.preventDefault();\n const title = newTitle.trim();\n if (title) {\n run(() => createAndAdd(title));\n }\n }}\n >\n <label htmlFor={inputId} className=\"text-sm font-semibold\">\n {t('entry.changeSet.newTitle')}\n </label>\n <div className=\"flex gap-2\">\n <Input\n id={inputId}\n inputSize=\"sm\"\n value={newTitle}\n maxLength={200}\n autoComplete=\"off\"\n onChange={(event) => setNewTitle(event.target.value)}\n />\n <SubmitButton\n size=\"sm\"\n pending={pending}\n pendingLabel={t('common.saving')}\n disabled={!newTitle.trim()}\n >\n {t('common.create')}\n </SubmitButton>\n </div>\n </form>\n <FormError error={error} />\n </PopoverContent>\n </Popover>\n );\n};\n","import type { ComponentDefinition, FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { isRecord, toList } from '@/fields/helpers/values';\n\nexport type PathTarget = {\n /** The entry's own field the path starts in (what the document can reveal). */\n topLevel: FieldDefinition;\n /** Readable trail: field labels, with list positions (\"Sections › 3 › Title\"). */\n trail: string[];\n /** The deepest field the path reached. */\n field: FieldDefinition;\n};\n\nconst decode = (segment: string) => segment.replace(/~1/g, '/').replace(/~0/g, '~');\n\n/**\n * Where a JSON pointer (API keys, `/sections/2/title`) points in the document: the top-level field to\n * reveal and a readable trail of labels for sentences. Unknown segments end the trail.\n */\nexport const resolveFieldPath = (\n model: ModelDefinition,\n components: ReadonlyMap<string, ComponentDefinition>,\n values: Readonly<Record<string, unknown>>,\n path: string,\n): PathTarget | undefined => {\n const segments = path.split('/').slice(1).map(decode);\n const topLevel = model.fields.find((field) => field.apiKey === segments[0]);\n if (!topLevel) {\n return undefined;\n }\n const trail = [topLevel.label];\n let field: FieldDefinition = topLevel;\n let value: unknown = values[topLevel.apiKey];\n for (const segment of segments.slice(1)) {\n if (/^\\d+$/.test(segment)) {\n trail.push(String(Number(segment) + 1));\n value = toList(value)[Number(segment)];\n continue;\n }\n const zoneKey = isRecord(value) ? value.__component : undefined;\n const owner: ComponentDefinition | undefined =\n field.type === 'component'\n ? components.get(field.settings.component)\n : field.type === 'dynamiczone'\n ? [...components.values()].find((component) => component.apiKey === zoneKey)\n : undefined;\n const next = owner?.fields.find((candidate) => candidate.apiKey === segment);\n if (!next) {\n break;\n }\n trail.push(next.label);\n field = next;\n value = isRecord(value) ? value[segment] : undefined;\n }\n return { topLevel, trail, field };\n};\n","import type { ContentIssue, PreflightCheck, PreflightRule } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { describeIssue } from '@/fields/helpers/issues';\n\n/** One sentence per rule (`entry.preflight.rules.*`), built from the check's params by the admin. */\nexport const PREFLIGHT_RULE_KEYS = {\n requiredEmpty: 'entry.preflight.rules.requiredEmpty',\n invalid: 'entry.preflight.rules.invalid',\n mediaMissing: 'entry.preflight.rules.mediaMissing',\n altMissing: 'entry.preflight.rules.altMissing',\n localeMissing: 'entry.preflight.rules.localeMissing',\n relationMissing: 'entry.preflight.rules.relationMissing',\n relationUnpublished: 'entry.preflight.rules.relationUnpublished',\n uniqueConflict: 'entry.preflight.rules.uniqueConflict',\n staleDraft: 'entry.preflight.rules.staleDraft',\n unpublishedChanges: 'entry.preflight.rules.unpublishedChanges',\n} as const satisfies Record<PreflightRule, string>;\n\n/** A locale not started yet, as a whole-entry warning (\"French hasn't been started\"). */\nexport const ENTRY_LOCALE_MISSING_KEY = 'entry.preflight.rules.localeNotStarted';\n\nexport type SentenceParts = {\n key: (typeof PREFLIGHT_RULE_KEYS)[PreflightRule] | typeof ENTRY_LOCALE_MISSING_KEY;\n values: Record<string, string | number>;\n};\n\ntype SentenceContext = {\n /** The readable trail of the check's path (\"Sections › 2 › Title\"), when it has one. */\n fieldLabel: string | undefined;\n /** The field at the end of the path, for the validator's message. */\n field: FieldDefinition | undefined;\n localeLabel: (code: string) => string;\n /** Whole-entry checks (other locales) read differently from this locale's. */\n entryLevel: boolean;\n};\n\nconst param = (check: PreflightCheck, name: string) => {\n const value = check.params[name];\n return typeof value === 'string' || typeof value === 'number' ? value : '';\n};\n\n/** The translation key and values that turn a check into a plain sentence. */\nexport const sentenceOf = (check: PreflightCheck, context: SentenceContext): SentenceParts => {\n const field = context.fieldLabel ?? '';\n if (check.rule === 'localeMissing') {\n const locale = context.localeLabel(String(param(check, 'locale')));\n return context.entryLevel\n ? { key: ENTRY_LOCALE_MISSING_KEY, values: { locale } }\n : { key: PREFLIGHT_RULE_KEYS.localeMissing, values: { locale } };\n }\n if (check.rule === 'invalid') {\n const issue: ContentIssue = { path: check.path ?? '', code: check.code ?? '', message: '' };\n return {\n key: PREFLIGHT_RULE_KEYS.invalid,\n values: { field, problem: describeIssue(issue, context.field) },\n };\n }\n if (check.rule === 'staleDraft' || check.rule === 'unpublishedChanges') {\n return {\n key: PREFLIGHT_RULE_KEYS[check.rule],\n values: { days: param(check, 'days'), count: Number(param(check, 'days')) },\n };\n }\n return { key: PREFLIGHT_RULE_KEYS[check.rule], values: { field } };\n};\n","import type { PreflightCheck } from '@shapio/client';\nimport { CircleAlert, TriangleAlert } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/helpers/cn';\nimport type { SentenceParts } from '../helpers/preflightSentences';\n\ntype PreflightCheckItemProps = {\n check: PreflightCheck;\n sentence: SentenceParts;\n /** Takes the person to the value to fix (absent when the check has no place in the document). */\n onFix?: () => void;\n};\n\n/** One pre-flight finding as a plain sentence: an error blocks publishing, a warning only informs. */\nexport const PreflightCheckItem = ({ check, sentence, onFix }: PreflightCheckItemProps) => {\n const { t } = useTranslation();\n const error = check.severity === 'error';\n const Icon = error ? CircleAlert : TriangleAlert;\n return (\n <li className=\"flex items-start gap-3 border-t py-3 first:border-t-0\" data-check-rule={check.rule}>\n <Icon\n aria-hidden=\"true\"\n className={cn('mt-0.5 size-4 shrink-0', error ? 'text-destructive' : 'text-warning')}\n />\n <div className=\"min-w-0 flex-1 space-y-0.5 text-sm\">\n <p>\n <span className=\"sr-only\">\n {error ? t('entry.preflight.error') : t('entry.preflight.warning')}{' '}\n </span>\n {t(sentence.key, sentence.values)}\n </p>\n {error ? null : <p className=\"text-meta text-muted-foreground\">{t('entry.preflight.warningHint')}</p>}\n </div>\n {onFix ? (\n <Button type=\"button\" variant=\"link\" size=\"sm\" className=\"h-auto shrink-0 p-0\" onClick={onFix}>\n {t('entry.preflight.fix')}\n </Button>\n ) : null}\n </li>\n );\n};\n","import { CalendarClock } from 'lucide-react';\nimport { useId, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useCreateSchedule } from '@/api/schedules';\nimport { FormError } from '@/components/FormError';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { dateTimeLocalToIso, defaultScheduleValue } from '@/features/Publishing/helpers/dateTimeLocal';\n\ntype ScheduleFormProps = {\n modelKey: string;\n entryId: string;\n locale: string | null;\n onScheduled: (runAt: string) => void;\n};\n\n/** \"Schedule…\": publish this locale at a time (the browser's time zone), inline in the pre-flight. */\nexport const ScheduleForm = ({ modelKey, entryId, locale, onScheduled }: ScheduleFormProps) => {\n const { t } = useTranslation();\n const id = useId();\n const [value, setValue] = useState(defaultScheduleValue);\n const [invalid, setInvalid] = useState(false);\n const create = useCreateSchedule();\n return (\n <form\n noValidate\n className=\"space-y-2 rounded-xl border p-4\"\n onSubmit={(event) => {\n event.preventDefault();\n const runAt = dateTimeLocalToIso(value);\n if (!runAt) {\n setInvalid(true);\n return;\n }\n create.mutate(\n { modelKey, entryId, ...(locale ? { locale } : {}), action: 'publish', runAt },\n { onSuccess: () => onScheduled(runAt) },\n );\n }}\n >\n <Label htmlFor={id}>{t('entry.preflight.scheduleAt')}</Label>\n <div className=\"flex flex-wrap gap-2\">\n <Input\n id={id}\n type=\"datetime-local\"\n className=\"w-auto\"\n value={value}\n aria-invalid={invalid || undefined}\n aria-describedby={`${id}-hint`}\n onChange={(event) => {\n setValue(event.target.value);\n setInvalid(false);\n }}\n />\n <SubmitButton pending={create.isPending} pendingLabel={t('common.saving')} variant=\"outline\">\n <CalendarClock aria-hidden=\"true\" />\n {t('entry.preflight.scheduleConfirm')}\n </SubmitButton>\n </div>\n <p\n id={`${id}-hint`}\n className={invalid ? 'text-meta text-destructive' : 'text-meta text-muted-foreground'}\n >\n {invalid\n ? t('validation.dateTime')\n : t('publishing.fields.localTimeHint', {\n timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n })}\n </p>\n <FormError error={create.error} />\n </form>\n );\n};\n","import type { PreflightCheck } from '@shapio/client';\nimport { CalendarClock, CircleCheck, Loader2, Send } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { usePreflight } from '@/api/entryDocument';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Button } from '@/components/ui/button';\nimport {\n Sheet,\n SheetBody,\n SheetContent,\n SheetDescription,\n SheetFooter,\n SheetHeader,\n SheetTitle,\n} from '@/components/ui/sheet';\nimport { useEntryForm, useFieldsEnvironment } from '@/fields/form/context';\nimport { formatDateTime } from '@/helpers/formatDate';\nimport { AddToChangeSet } from '../AddToChangeSet';\nimport { resolveFieldPath } from '../helpers/fieldPath';\nimport { sentenceOf } from '../helpers/preflightSentences';\nimport { PreflightCheckItem } from '../PreflightCheckItem';\nimport { ScheduleForm } from '../ScheduleForm';\n\ntype PreflightSheetProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n entryId: string;\n /** The draft has been saved (autosaved) since it was last changed: the checks see what is on screen. */\n ready: boolean;\n labelOf: (code: string) => string;\n canSchedule: boolean;\n /** Offer \"Add to change set…\" (the admin manages change sets). */\n canUseChangeSets: boolean;\n publishing: boolean;\n onPublish: () => Promise<boolean>;\n /** Takes the person to a value, once the sheet has closed. */\n onFix: (path: string, assetId?: string) => void;\n};\n\n/**\n * Publishing as a pre-flight (Ghost-style): one plain sentence per thing publishing would run into, each\n * with a way to fix it. Errors (required fields, invalid values, a slug already live elsewhere) disable\n * \"Publish now\"; warnings (missing alt text, a locale not started) only inform. Schedule… publishes later.\n */\nexport const PreflightSheet = ({\n open,\n onOpenChange,\n entryId,\n ready,\n labelOf,\n canSchedule,\n canUseChangeSets,\n publishing,\n onPublish,\n onFix,\n}: PreflightSheetProps) => {\n const { t } = useTranslation();\n const { model, components, locale } = useFieldsEnvironment();\n const values = useEntryForm((state) => state.values);\n const preflight = usePreflight(model.apiKey, entryId, locale ?? undefined, open && ready);\n const [scheduling, setScheduling] = useState(false);\n // A Fix waits for the sheet to close, then moves focus to the value instead of back to Publish.\n const pendingFix = useRef<(() => void) | null>(null);\n const localeChecks = preflight.data?.locales.flatMap((item) => item.checks) ?? [];\n const entryChecks = preflight.data?.entry ?? [];\n const blocked = localeChecks.some((check) => check.severity === 'error');\n const sentence = (check: PreflightCheck, entryLevel: boolean) => {\n const target = check.path ? resolveFieldPath(model, components, values, check.path) : undefined;\n return sentenceOf(check, {\n fieldLabel: target?.trail.join(' › '),\n field: target?.field,\n localeLabel: labelOf,\n entryLevel,\n });\n };\n const fixOf = (check: PreflightCheck) => {\n const path = check.path;\n if (!path) {\n return undefined;\n }\n const assetId = typeof check.params.assetId === 'string' ? check.params.assetId : undefined;\n return () => {\n pendingFix.current = () => onFix(path, assetId);\n onOpenChange(false);\n };\n };\n return (\n <Sheet\n open={open}\n onOpenChange={(next) => {\n onOpenChange(next);\n if (!next) {\n setScheduling(false);\n }\n }}\n >\n <SheetContent\n size=\"md\"\n onCloseAutoFocus={(event) => {\n const fix = pendingFix.current;\n if (fix) {\n event.preventDefault();\n pendingFix.current = null;\n fix();\n }\n }}\n >\n <SheetHeader>\n <SheetTitle>{t('entry.preflight.title')}</SheetTitle>\n <SheetDescription>\n {locale\n ? t('entry.preflight.descriptionLocale', { locale: labelOf(locale) })\n : t('entry.preflight.description')}\n </SheetDescription>\n </SheetHeader>\n <SheetBody className=\"space-y-5\">\n {!ready || preflight.isPending ? (\n <LoadingState rows={3} />\n ) : preflight.isError ? (\n <ErrorState error={preflight.error} onRetry={() => void preflight.refetch()} />\n ) : (\n <>\n {localeChecks.length === 0 && entryChecks.length === 0 ? (\n <p className=\"flex items-center gap-2 text-sm\" role=\"status\">\n <CircleCheck aria-hidden=\"true\" className=\"size-4 text-success\" />\n {t('entry.preflight.allClear')}\n </p>\n ) : (\n <ul aria-label={t('entry.preflight.checks')} className=\"rounded-xl border px-4\">\n {localeChecks.map((check, index) => (\n <PreflightCheckItem\n key={`${check.rule}-${check.path ?? ''}-${index}`}\n check={check}\n sentence={sentence(check, false)}\n onFix={fixOf(check)}\n />\n ))}\n {entryChecks.map((check, index) => (\n <PreflightCheckItem\n key={`entry-${check.rule}-${index}`}\n check={check}\n sentence={sentence(check, true)}\n />\n ))}\n </ul>\n )}\n {scheduling && canSchedule ? (\n <ScheduleForm\n modelKey={model.apiKey}\n entryId={entryId}\n locale={locale}\n onScheduled={(runAt) => {\n toast.success(t('entry.preflight.scheduledToast', { time: formatDateTime(runAt) }));\n onOpenChange(false);\n }}\n />\n ) : null}\n </>\n )}\n </SheetBody>\n <SheetFooter className=\"justify-between\">\n <div className=\"flex flex-wrap gap-2\">\n {canSchedule ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n aria-expanded={scheduling}\n disabled={blocked || !preflight.data}\n onClick={() => setScheduling((current) => !current)}\n >\n <CalendarClock aria-hidden=\"true\" />\n {t('entry.preflight.schedule')}\n </Button>\n ) : null}\n {canUseChangeSets ? (\n <AddToChangeSet\n entryId={entryId}\n locale={locale}\n disabled={blocked || !preflight.data}\n onAdded={() => onOpenChange(false)}\n />\n ) : null}\n </div>\n <div className=\"flex gap-2\">\n <Button type=\"button\" variant=\"ghost\" onClick={() => onOpenChange(false)}>\n {t('entry.preflight.notYet')}\n </Button>\n <Button\n type=\"button\"\n disabled={blocked || !preflight.data || publishing}\n onClick={() =>\n void onPublish().then((published) => (published ? onOpenChange(false) : undefined))\n }\n >\n {publishing ? (\n <Loader2 aria-hidden=\"true\" className=\"animate-spin\" />\n ) : (\n <Send aria-hidden=\"true\" />\n )}\n {t('entry.preflight.publishNow')}\n </Button>\n </div>\n </SheetFooter>\n </SheetContent>\n </Sheet>\n );\n};\n","import type { PresencePerson } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { UserAvatar } from '@/components/UserAvatar';\n\ntype PresenceProps = { people: readonly PresencePerson[] };\n\nconst SHOWN = 3;\n\n/** Who else has this entry open right now: overlapping initials, names in the tooltip and for readers. */\nexport const Presence = ({ people }: PresenceProps) => {\n const { t } = useTranslation();\n if (people.length === 0) {\n return null;\n }\n const names = [\n ...new Set(people.map((person) => (person.you ? t('entry.presence.youElsewhere') : person.name))),\n ];\n const label = t('entry.presence.label', { names: names.join(', ') });\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span role=\"img\" aria-label={label} className=\"flex items-center\" data-presence>\n {people.slice(0, SHOWN).map((person) => (\n <UserAvatar\n key={`${person.userId}-${person.since}`}\n name={person.name}\n size=\"sm\"\n className=\"-ml-1.5 ring-2 ring-background first:ml-0\"\n />\n ))}\n {people.length > SHOWN ? (\n <span className=\"ml-1 text-meta text-muted-foreground\">+{people.length - SHOWN}</span>\n ) : null}\n </span>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n );\n};\n","import type { RefObject } from 'react';\n\ntype FrameProps = {\n frameRef: RefObject<HTMLIFrameElement | null>;\n src: string;\n title: string;\n onLoad: () => void;\n};\n\n/**\n * The site, framed. Its origin is never the admin's (checked before it renders), so `allow-same-origin` only\n * gives the site its own origin back (its fetches to Shapio need one); it can't reach the admin.\n */\nexport const Frame = ({ frameRef, src, title, onLoad }: FrameProps) => (\n <iframe\n ref={frameRef}\n src={src}\n title={title}\n onLoad={onLoad}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups\"\n referrerPolicy=\"no-referrer\"\n className=\"block size-full min-h-0 flex-1 border-0 bg-background\"\n />\n);\n","import { Info } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';\nimport { VISUAL_EDITING_DOCS_URL } from '@/constants/publishing';\nimport { ExternalLink } from '@/features/Publishing/ExternalLink';\n\n/** Shown in the pane when the framed page never said it runs @shapio/visual. */\nexport const SdkNotice = () => {\n const { t } = useTranslation();\n return (\n <Alert variant=\"info\" className=\"rounded-none border-x-0 border-t-0\">\n <Info aria-hidden=\"true\" />\n <AlertTitle>{t('entry.preview.sdkMissingTitle')}</AlertTitle>\n <AlertDescription>\n <p>\n {t('entry.preview.sdkMissingDescription')}{' '}\n <ExternalLink href={VISUAL_EDITING_DOCS_URL}>{t('entry.preview.setupGuide')}</ExternalLink>\n </p>\n </AlertDescription>\n </Alert>\n );\n};\n","import { ExternalLink, Link2Off, RotateCw, ShieldAlert } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { EmptyState } from '@/components/EmptyState';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';\nimport { Button } from '@/components/ui/button';\nimport { Frame } from '../Frame';\nimport type { EntryPreview } from '../hooks/useEntryPreview';\nimport { SdkNotice } from '../SdkNotice';\n\ntype BodyProps = { preview: EntryPreview; frameTitle: string };\n\n/** What the pane shows: the framed site, or why it can't (opening, failed, new-tab only, blocked by CSP). */\nexport const Body = ({ preview, frameTitle }: BodyProps) => {\n const { t } = useTranslation();\n const { session, siteUrl, frameUrl } = preview;\n if (session.status === 'loading') {\n return <LoadingState rows={6} className=\"p-5\" />;\n }\n if (session.status === 'error') {\n return <ErrorState size=\"panel\" className=\"p-5\" error={session.error} onRetry={session.retry} />;\n }\n if (!siteUrl) {\n return (\n <EmptyState\n size=\"panel\"\n icon={Link2Off}\n title={t('entry.preview.noUrlTitle')}\n description={t('entry.preview.noUrlDescription')}\n />\n );\n }\n if (!frameUrl) {\n return (\n <EmptyState\n size=\"panel\"\n icon={ExternalLink}\n title={t('entry.preview.notFramableTitle')}\n description={t('entry.preview.notFramableDescription')}\n action={\n <Button asChild>\n <a href={siteUrl} target=\"_blank\" rel=\"noopener noreferrer\" referrerPolicy=\"no-referrer\">\n <ExternalLink aria-hidden=\"true\" />\n {t('entry.preview.openInTab')}\n </a>\n </Button>\n }\n />\n );\n }\n return (\n <>\n {preview.blocked ? (\n <Alert variant=\"warning\" className=\"rounded-none border-x-0 border-t-0\">\n <ShieldAlert aria-hidden=\"true\" />\n <AlertTitle>{t('entry.preview.blockedTitle')}</AlertTitle>\n <AlertDescription>\n <p>{t('entry.preview.blockedDescription')}</p>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"mt-2\"\n onClick={() => window.location.reload()}\n >\n <RotateCw aria-hidden=\"true\" />\n {t('entry.preview.reloadAdmin')}\n </Button>\n </AlertDescription>\n </Alert>\n ) : preview.missing ? (\n <SdkNotice />\n ) : null}\n <Frame frameRef={preview.frameRef} src={frameUrl} title={frameTitle} onLoad={preview.onFrameLoad} />\n </>\n );\n};\n","import { useEffect, useState } from 'react';\n\n/** The document's top bar; the preview pane starts under it on lg and up so its actions stay in view. */\nconst TOP_BAR_SELECTOR = '[data-slot=\"entry-top-bar\"]';\n\n/** The top bar's current height in pixels (it wraps on narrow screens), while `enabled`. */\nexport const useTopBarHeight = (enabled: boolean): number => {\n const [height, setHeight] = useState(0);\n useEffect(() => {\n const bar = enabled ? document.querySelector(TOP_BAR_SELECTOR) : null;\n if (!bar) {\n return undefined;\n }\n const observer = new ResizeObserver(() => setHeight(bar.getBoundingClientRect().height));\n observer.observe(bar);\n return () => observer.disconnect();\n }, [enabled]);\n return height;\n};\n","import type { ReactNode } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\n\ntype IconActionProps = { label: string; icon: ReactNode; onClick: () => void };\n\n/** A small icon button of the preview pane's toolbar, named by its label (also its tooltip). */\nexport const IconAction = ({ label, icon, onClick }: IconActionProps) => (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button type=\"button\" variant=\"ghost\" size=\"icon-sm\" aria-label={label} onClick={onClick}>\n {icon}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n);\n","import type { PreviewTarget } from '@shapio/client';\nimport { ExternalLink, FileText, RotateCw, X } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { IconAction } from './IconAction';\n\ntype ToolbarProps = {\n headingId: string;\n targets: readonly PreviewTarget[];\n target: PreviewTarget | undefined;\n onChooseTarget: (connectionId: string) => void;\n /** The site's URL for this preview (opened in a new tab without the visual-editing flag). */\n siteUrl: string | undefined;\n onReload: (() => void) | undefined;\n onShowDocument: () => void;\n onClose: () => void;\n};\n\n/** The preview pane's header: which site, and reload, open in a new tab, the document (phones), close. */\nexport const Toolbar = ({\n headingId,\n targets,\n target,\n onChooseTarget,\n siteUrl,\n onReload,\n onShowDocument,\n onClose,\n}: ToolbarProps) => {\n const { t } = useTranslation();\n return (\n <div className=\"flex items-center gap-2 border-b px-3 py-2\">\n <h2 id={headingId} className=\"text-sm font-semibold max-sm:sr-only\">\n {t('content.form.preview')}\n </h2>\n {targets.length > 1 ? (\n <Select value={target?.connectionId ?? ''} onValueChange={onChooseTarget}>\n <SelectTrigger size=\"sm\" aria-label={t('entry.preview.site')} className=\"max-w-48 min-w-0\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {targets.map((item) => (\n <SelectItem key={item.connectionId} value={item.connectionId}>\n {item.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : null}\n <div className=\"ml-auto flex items-center gap-1\">\n {onReload ? (\n <IconAction\n label={t('entry.preview.reload')}\n onClick={onReload}\n icon={<RotateCw aria-hidden=\"true\" />}\n />\n ) : null}\n {siteUrl ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon-sm\" asChild>\n <a\n href={siteUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n referrerPolicy=\"no-referrer\"\n aria-label={t('entry.preview.openInTab')}\n >\n <ExternalLink aria-hidden=\"true\" />\n </a>\n </Button>\n </TooltipTrigger>\n <TooltipContent>{t('entry.preview.openInTab')}</TooltipContent>\n </Tooltip>\n ) : null}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"lg:hidden\" onClick={onShowDocument}>\n <FileText aria-hidden=\"true\" />\n {t('entry.preview.showDocument')}\n </Button>\n <IconAction label={t('entry.preview.close')} onClick={onClose} icon={<X aria-hidden=\"true\" />} />\n </div>\n </div>\n );\n};\n","import { useId, type CSSProperties } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cn } from '@/helpers/cn';\nimport { Body } from './Body';\nimport type { EntryPreview } from './hooks/useEntryPreview';\nimport { useTopBarHeight } from './hooks/useTopBarHeight';\nimport { Toolbar } from './Toolbar';\n\ntype PreviewPaneProps = { preview: EntryPreview; title: string };\n\n/**\n * The site's preview beside the document: the right half of the screen under the top bar on lg and up, the\n * whole screen below it, where \"Document\" slides the document back in over it (the frame stays loaded). Clicking a field in the\n * frame focuses it in the document; saves re-render the frame.\n */\nexport const PreviewPane = ({ preview, title }: PreviewPaneProps) => {\n const { t } = useTranslation();\n const headingId = useId();\n const topBarHeight = useTopBarHeight(preview.open);\n if (!preview.open) {\n return null;\n }\n return (\n <section\n aria-labelledby={headingId}\n data-preview-pane\n style={{ '--preview-top': `${topBarHeight}px` } as CSSProperties}\n className={cn(\n 'fixed inset-x-0 top-12 bottom-0 z-30 flex flex-col bg-card transition-transform md:bottom-(--statusbar-h)',\n 'lg:top-(--preview-top) lg:left-auto lg:w-1/2 lg:border-l',\n preview.documentShown && 'invisible translate-x-full',\n )}\n >\n <Toolbar\n headingId={headingId}\n targets={preview.targets}\n target={preview.target}\n onChooseTarget={preview.chooseTarget}\n siteUrl={preview.siteUrl}\n onReload={preview.frameUrl ? preview.refresh : undefined}\n onShowDocument={preview.showDocument}\n onClose={preview.close}\n />\n <div className=\"flex min-h-0 flex-1 flex-col overflow-auto\">\n <Body\n preview={preview}\n frameTitle={t('entry.preview.frameTitle', { title, site: preview.target?.name ?? '' })}\n />\n </div>\n </section>\n );\n};\n","/**\n * The messages between a site in Shapio's preview frame and the admin around it. Every message carries the\n * protocol version; anything that does not parse is ignored. Who may send a message (the frame's window from\n * the preview origin, the parent from the Shapio origin) is checked by each side before parsing.\n */\nexport const VISUAL_PROTOCOL_VERSION = 1;\n/** The query parameter the admin adds to a preview URL it frames (`?shapio-visual=1`). */\nexport const VISUAL_QUERY_PARAM = 'shapio-visual';\n\nexport type VisualReadyMessage = { type: 'shapio:ready'; v: typeof VISUAL_PROTOCOL_VERSION };\nexport type VisualFocusMessage = {\n type: 'shapio:focus';\n v: typeof VISUAL_PROTOCOL_VERSION;\n entryId: string;\n /** A JSON pointer of API IDs (`/title`, `/sections/2/heading`). */\n path: string;\n locale?: string;\n};\nexport type VisualRefreshMessage = { type: 'shapio:refresh'; v: typeof VISUAL_PROTOCOL_VERSION };\n\n/** What the site posts to the admin. */\nexport type SiteMessage = VisualReadyMessage | VisualFocusMessage;\n/** What the admin posts to the site. */\nexport type AdminMessage = VisualRefreshMessage;\n\nconst MAX_PATH_LENGTH = 512;\nconst MAX_PATH_SEGMENTS = 32;\nconst SEGMENT = /^[A-Za-z0-9_~-]+$/;\nconst ENTRY_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst LOCALE = /^[A-Za-z0-9-]{1,35}$/;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/** `title`, `/title` or `sections/2/heading` → a JSON pointer (`/sections/2/heading`); undefined if malformed. */\nexport const normalizeFieldPath = (path: unknown): string | undefined => {\n if (typeof path !== 'string' || path.length === 0 || path.length > MAX_PATH_LENGTH) {\n return undefined;\n }\n const segments = path.replace(/^\\//, '').split('/');\n if (segments.length > MAX_PATH_SEGMENTS || !segments.every((segment) => SEGMENT.test(segment))) {\n return undefined;\n }\n return `/${segments.join('/')}`;\n};\n\n/** A message from the site, or undefined when the data is not one. */\nexport const parseSiteMessage = (data: unknown): SiteMessage | undefined => {\n if (!isRecord(data) || data.v !== VISUAL_PROTOCOL_VERSION) {\n return undefined;\n }\n if (data.type === 'shapio:ready') {\n return { type: 'shapio:ready', v: VISUAL_PROTOCOL_VERSION };\n }\n if (data.type !== 'shapio:focus') {\n return undefined;\n }\n const path = normalizeFieldPath(data.path);\n if (typeof data.entryId !== 'string' || !ENTRY_ID.test(data.entryId) || !path) {\n return undefined;\n }\n if (data.locale !== undefined && (typeof data.locale !== 'string' || !LOCALE.test(data.locale))) {\n return undefined;\n }\n return {\n type: 'shapio:focus',\n v: VISUAL_PROTOCOL_VERSION,\n entryId: data.entryId,\n path,\n ...(typeof data.locale === 'string' ? { locale: data.locale } : {}),\n };\n};\n\n/** A message from the admin, or undefined when the data is not one. */\nexport const parseAdminMessage = (data: unknown): AdminMessage | undefined =>\n isRecord(data) && data.v === VISUAL_PROTOCOL_VERSION && data.type === 'shapio:refresh'\n ? { type: 'shapio:refresh', v: VISUAL_PROTOCOL_VERSION }\n : undefined;\n","import type { OpenPreviewInput } from '@shapio/client';\nimport { useQuery } from '@tanstack/react-query';\nimport { adminApi } from './client';\nimport { withCsrf } from './csrf';\nimport { queryKeys } from './queryKeys';\n\n/** The site's connections with a preview URL: whether the entry document can show a preview, and where. */\nexport const usePreviewTargets = () =>\n useQuery({\n queryKey: queryKeys.publishing.deployments.previewTargets,\n queryFn: () => adminApi.preview.targets(),\n staleTime: 60_000,\n meta: { silent: true },\n });\n\n/** A fresh one-hour preview token for an entry and the URL that opens it on the site. */\nexport const openPreview = (input: OpenPreviewInput) => withCsrf(() => adminApi.preview.open(input));\n\n/** Revokes a preview token the pane no longer uses (replaced or closed). */\nexport const revokePreviewToken = (id: string) => withCsrf(() => adminApi.preview.tokens.revoke(id));\n","import { VISUAL_QUERY_PARAM } from '@shapio/visual';\n\n/** The preview URL the pane frames: the site's URL with `?shapio-visual=1` (a `#token=` fragment survives). */\nexport const framedPreviewUrl = (url: string): string => {\n const framed = new URL(url);\n framed.searchParams.set(VISUAL_QUERY_PARAM, '1');\n return framed.href;\n};\n\n/** The origin of an http(s) URL, or undefined. */\nexport const httpOriginOf = (url: string): string | undefined => {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:' ? parsed.origin : undefined;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Whether the admin may frame a preview URL: http(s), and never on the admin's own origin (a framed page on it\n * could script the admin; the API refuses such templates and the CSP never lists the origin).\n */\nexport const canFramePreview = (url: string, adminOrigin: string): boolean => {\n const origin = httpOriginOf(url);\n return origin !== undefined && origin !== adminOrigin;\n};\n","import { useEffect, useState } from 'react';\nimport { httpOriginOf } from '../helpers/previewFrame';\n\n/**\n * Whether the admin's CSP blocked the preview frame: the page's `frame-src` was set when the admin loaded, so a\n * site connected since then needs a reload of the admin before it can be shown.\n */\nexport const useFrameBlocked = (origin: string | undefined): boolean => {\n const [blockedOrigin, setBlockedOrigin] = useState<string | undefined>();\n useEffect(() => {\n if (!origin) {\n return undefined;\n }\n const onViolation = (event: SecurityPolicyViolationEvent) => {\n if (/^(frame|child)-src/.test(event.effectiveDirective) && httpOriginOf(event.blockedURI) === origin) {\n setBlockedOrigin(origin);\n }\n };\n document.addEventListener('securitypolicyviolation', onViolation);\n return () => document.removeEventListener('securitypolicyviolation', onViolation);\n }, [origin]);\n return origin !== undefined && blockedOrigin === origin;\n};\n","import type { ComponentDefinition, ModelDefinition } from '@shapio/schema';\nimport type { VisualFocusMessage } from '@shapio/visual';\nimport { resolveFieldPath } from '../../helpers/fieldPath';\n\n/** What a click in the preview asks the document to do. */\nexport type PreviewFocus =\n | { kind: 'field'; path: string }\n | { kind: 'otherEntry' }\n | { kind: 'otherLocale'; locale: string }\n | { kind: 'unknownField' };\n\ntype OpenDocument = {\n entryId: string;\n /** The document's locale; null for a model that isn't localized. */\n locale: string | null;\n model: ModelDefinition;\n components: ReadonlyMap<string, ComponentDefinition>;\n values: Readonly<Record<string, unknown>>;\n};\n\n/**\n * Maps a clicked element (entry, API ID path, locale) to a field of the open document. Another entry (a\n * populated relation) or another locale is reported, not followed; a path that names no field of the model is\n * unknown.\n */\nexport const resolvePreviewFocus = (message: VisualFocusMessage, open: OpenDocument): PreviewFocus => {\n if (message.entryId !== open.entryId) {\n return { kind: 'otherEntry' };\n }\n if (open.locale !== null && message.locale !== undefined && message.locale !== open.locale) {\n return { kind: 'otherLocale', locale: message.locale };\n }\n return resolveFieldPath(open.model, open.components, open.values, message.path)\n ? { kind: 'field', path: message.path }\n : { kind: 'unknownField' };\n};\n","import type { ComponentDefinition, ModelDefinition } from '@shapio/schema';\nimport type { VisualFocusMessage } from '@shapio/visual';\nimport { useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport type { EntryFormStore } from '@/fields/form/store';\nimport { resolvePreviewFocus } from '../helpers/focusTarget';\n\ntype PreviewFocusOptions = {\n entryId: string;\n locale: string | null;\n model: ModelDefinition;\n components: ReadonlyMap<string, ComponentDefinition>;\n store: EntryFormStore;\n /** Scrolls to a field and focuses its control (the document's reveal). */\n reveal: (path: string) => void;\n};\n\n/**\n * A click in the preview → the field it shows: focused in the document. A click on something of another entry\n * or locale, or on a path the model doesn't have, says so in a toast instead.\n */\nexport const usePreviewFocus = ({\n entryId,\n locale,\n model,\n components,\n store,\n reveal,\n}: PreviewFocusOptions) => {\n const { t } = useTranslation();\n return useCallback(\n (message: VisualFocusMessage) => {\n const target = resolvePreviewFocus(message, {\n entryId,\n locale,\n model,\n components,\n values: store.getState().values,\n });\n if (target.kind === 'field') {\n reveal(target.path);\n } else if (target.kind === 'otherEntry') {\n toast.info(t('entry.preview.otherEntry'));\n } else if (target.kind === 'otherLocale') {\n toast.info(t('entry.preview.otherLocale', { locale: target.locale }));\n } else {\n toast.info(t('entry.preview.unknownField'));\n }\n },\n [entryId, locale, model, components, store, reveal, t],\n );\n};\n","import { parseSiteMessage, type SiteMessage } from '@shapio/visual';\n\ntype IncomingMessage = Pick<MessageEvent, 'source' | 'origin' | 'data'>;\n\n/**\n * A message from the preview frame, or undefined. Only the framed window itself, on the preview URL's origin,\n * is heard: another window, frame or origin (the admin's own included) is ignored before the data is read.\n */\nexport const acceptSiteMessage = (\n event: IncomingMessage,\n frame: Window | null | undefined,\n previewOrigin: string | undefined,\n): SiteMessage | undefined =>\n frame && previewOrigin && event.source === frame && event.origin === previewOrigin\n ? parseSiteMessage(event.data)\n : undefined;\n","import type { VisualFocusMessage } from '@shapio/visual';\nimport { useCallback, useEffect, useRef, useState, type RefObject } from 'react';\nimport { PREVIEW_READY_TIMEOUT_MS } from '@/constants/publishing';\nimport { acceptSiteMessage } from '../helpers/previewMessages';\n\ntype FrameState = { url: string | undefined; ready: boolean; missing: boolean };\n\n/**\n * Listens to the preview frame: `shapio:ready` (the site runs @shapio/visual) and `shapio:focus` (a click on\n * a field). Only the frame's own window on the preview origin is heard. When the page has loaded and no ready\n * message arrives in time, `missing` is set (the pane explains how to add the SDK).\n */\nexport const usePreviewMessages = (\n frameRef: RefObject<HTMLIFrameElement | null>,\n url: string | undefined,\n origin: string | undefined,\n onFocus: (message: VisualFocusMessage) => void,\n) => {\n const [state, setState] = useState<FrameState>({ url: undefined, ready: false, missing: false });\n const latestFocus = useRef(onFocus);\n const timer = useRef<ReturnType<typeof setTimeout>>(undefined);\n useEffect(() => {\n latestFocus.current = onFocus;\n });\n\n useEffect(() => {\n const onMessage = (event: MessageEvent) => {\n const message = acceptSiteMessage(event, frameRef.current?.contentWindow, origin);\n if (message?.type === 'shapio:ready') {\n clearTimeout(timer.current);\n setState({ url, ready: true, missing: false });\n } else if (message?.type === 'shapio:focus') {\n latestFocus.current(message);\n }\n };\n window.addEventListener('message', onMessage);\n return () => {\n window.removeEventListener('message', onMessage);\n clearTimeout(timer.current);\n };\n }, [frameRef, url, origin]);\n\n /** The frame's `load`: start waiting for the site's ready message. */\n const onFrameLoad = useCallback(() => {\n clearTimeout(timer.current);\n timer.current = setTimeout(\n () =>\n setState((current) =>\n current.url === url && current.ready ? current : { url, ready: false, missing: true },\n ),\n PREVIEW_READY_TIMEOUT_MS,\n );\n }, [url]);\n\n const current = state.url === url ? state : { url, ready: false, missing: false };\n return { ready: current.ready, missing: current.missing, onFrameLoad };\n};\n","import { useEffect, useRef } from 'react';\nimport { PREVIEW_REFRESH_DEBOUNCE_MS } from '@/constants/publishing';\nimport type { SaveState } from '../../hooks/useEntrySaver';\n\n/**\n * Re-renders the preview after the draft is saved (autosave, Save, Publish): when a save settles, `refresh`\n * runs once after a short quiet period, so a burst of saves refreshes the frame once.\n */\nexport const usePreviewRefresh = (status: SaveState['status'], enabled: boolean, refresh: () => void) => {\n const previous = useRef(status);\n const latestRefresh = useRef(refresh);\n const timer = useRef<ReturnType<typeof setTimeout>>(undefined);\n useEffect(() => {\n latestRefresh.current = refresh;\n });\n useEffect(() => {\n const settled = previous.current === 'saving' && status === 'saved';\n previous.current = status;\n if (enabled && settled) {\n clearTimeout(timer.current);\n timer.current = setTimeout(() => latestRefresh.current(), PREVIEW_REFRESH_DEBOUNCE_MS);\n }\n }, [status, enabled]);\n useEffect(() => () => clearTimeout(timer.current), []);\n};\n","import { useEffect, useState } from 'react';\nimport { openPreview, revokePreviewToken } from '@/api/preview';\nimport { PREVIEW_TOKEN_REFRESH_MARGIN_MS } from '@/constants/publishing';\nimport { logError } from '@/helpers/reportError';\n\ntype PreviewSessionInput = {\n modelKey: string;\n entryId: string;\n locale: string | null;\n connectionId: string | undefined;\n};\n\nexport type PreviewSession =\n | { status: 'loading' }\n | { status: 'ready'; url: string | null }\n | { status: 'error'; error: unknown; retry: () => void };\n\n/** Never schedule a refresh sooner than this, whatever the token's expiry says. */\nconst MIN_REFRESH_DELAY_MS = 30_000;\n\nconst release = (id: string) => {\n revokePreviewToken(id).catch((error: unknown) => logError(error, 'preview.revokeToken'));\n};\n\n/**\n * A preview token for the open entry while `enabled`: minted on open, replaced shortly before its hour is up\n * (the replaced token is revoked), and revoked when the preview closes or the entry, locale or connection\n * changes. Returns the URL the site opens it on.\n */\nexport const usePreviewSession = (input: PreviewSessionInput, enabled: boolean): PreviewSession => {\n const { modelKey, entryId, locale, connectionId } = input;\n const key = [modelKey, entryId, locale ?? '', connectionId ?? '', enabled].join('|');\n // The state belongs to one key: a stale key reads as loading, so nothing is set during render or effects.\n const [state, setState] = useState<{ key: string; session: PreviewSession } | undefined>();\n const [attempt, setAttempt] = useState(0);\n\n useEffect(() => {\n if (!enabled) {\n return undefined;\n }\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let tokenId: string | undefined;\n const mint = async () => {\n try {\n const opened = await openPreview({\n modelKey,\n entryId,\n ...(locale ? { locale } : {}),\n ...(connectionId ? { connectionId } : {}),\n });\n if (cancelled) {\n release(opened.id);\n return;\n }\n if (tokenId) {\n release(tokenId);\n }\n tokenId = opened.id;\n setState({ key, session: { status: 'ready', url: opened.url } });\n const delay = Date.parse(opened.expiresAt) - Date.now() - PREVIEW_TOKEN_REFRESH_MARGIN_MS;\n timer = setTimeout(() => void mint(), Math.max(MIN_REFRESH_DELAY_MS, delay));\n } catch (error) {\n if (!cancelled) {\n logError(error, 'preview.open');\n setState({\n key,\n session: { status: 'error', error, retry: () => setAttempt((count) => count + 1) },\n });\n }\n }\n };\n void mint();\n return () => {\n cancelled = true;\n clearTimeout(timer);\n if (tokenId) {\n release(tokenId);\n }\n };\n }, [enabled, key, modelKey, entryId, locale, connectionId, attempt]);\n\n return state?.key === key ? state.session : { status: 'loading' };\n};\n","import type { ComponentDefinition, ModelDefinition } from '@shapio/schema';\nimport { VISUAL_PROTOCOL_VERSION, type AdminMessage } from '@shapio/visual';\nimport { useCallback, useMemo, useRef, useState } from 'react';\nimport { usePreviewTargets } from '@/api/preview';\nimport type { EntryFormStore } from '@/fields/form/store';\nimport { useIsMobile } from '@/hooks/use-mobile';\nimport type { SaveState } from '../../hooks/useEntrySaver';\nimport { canFramePreview, framedPreviewUrl, httpOriginOf } from '../helpers/previewFrame';\nimport { useFrameBlocked } from './useFrameBlocked';\nimport { usePreviewFocus } from './usePreviewFocus';\nimport { usePreviewMessages } from './usePreviewMessages';\nimport { usePreviewRefresh } from './usePreviewRefresh';\nimport { usePreviewSession } from './usePreviewSession';\n\ntype EntryPreviewOptions = {\n model: ModelDefinition;\n components: ReadonlyMap<string, ComponentDefinition>;\n /** null until the entry exists (creating): no preview then. */\n entryId: string | null;\n locale: string | null;\n store: EntryFormStore;\n saveStatus: SaveState['status'];\n reveal: (path: string) => void;\n};\n\nconst REFRESH: AdminMessage = { type: 'shapio:refresh', v: VISUAL_PROTOCOL_VERSION };\n\n/**\n * The entry document's preview: which connection it opens on, its token (refreshed before expiry), the framed\n * URL, the conversation with the site (ready, focus, refresh after saves), and, on phones, whether the\n * document is slid in over it.\n */\nexport const useEntryPreview = (options: EntryPreviewOptions) => {\n const { model, entryId, locale, saveStatus } = options;\n const targets = usePreviewTargets();\n const mobile = useIsMobile();\n const [open, setOpen] = useState(false);\n const [documentShown, setDocumentShown] = useState(false);\n const [chosen, setChosen] = useState<string | undefined>();\n const list = useMemo(() => targets.data ?? [], [targets.data]);\n const target =\n list.find((item) => item.connectionId === chosen) ?? list.find((item) => item.framable) ?? list[0];\n const active = open && entryId !== null && target !== undefined;\n const session = usePreviewSession(\n { modelKey: model.apiKey, entryId: entryId ?? '', locale, connectionId: target?.connectionId },\n active,\n );\n const siteUrl = session.status === 'ready' ? (session.url ?? undefined) : undefined;\n const framable = siteUrl !== undefined && canFramePreview(siteUrl, window.location.origin);\n const frameUrl = framable ? framedPreviewUrl(siteUrl) : undefined;\n const origin = frameUrl ? httpOriginOf(frameUrl) : undefined;\n const frameRef = useRef<HTMLIFrameElement>(null);\n\n const reveal = options.reveal;\n const focusField = useCallback(\n (path: string) => {\n if (!mobile) {\n reveal(path);\n return;\n }\n // On phones the document slides in over the preview first; reveal once it is on screen.\n setDocumentShown(true);\n window.setTimeout(() => reveal(path), 200);\n },\n [mobile, reveal],\n );\n const onFocus = usePreviewFocus({ ...options, entryId: entryId ?? '', reveal: focusField });\n const messages = usePreviewMessages(frameRef, frameUrl, origin, onFocus);\n const blocked = useFrameBlocked(origin);\n // With @shapio/visual the site re-renders itself; without it the frame is simply loaded again.\n const refresh = useCallback(() => {\n const frame = frameRef.current;\n if (!frame || !origin || !frameUrl) {\n return;\n }\n if (messages.ready) {\n frame.contentWindow?.postMessage(REFRESH, origin);\n } else {\n frame.setAttribute('src', frameUrl);\n }\n }, [origin, frameUrl, messages.ready]);\n usePreviewRefresh(saveStatus, frameUrl !== undefined, refresh);\n\n return {\n available: entryId !== null && list.length > 0,\n open: active,\n toggle: () => {\n setDocumentShown(false);\n setOpen((current) => !(current && (!mobile || !documentShown)));\n },\n close: () => setOpen(false),\n targets: list,\n target,\n chooseTarget: setChosen,\n session,\n siteUrl,\n frameUrl,\n frameRef,\n ready: messages.ready,\n missing: messages.missing,\n onFrameLoad: messages.onFrameLoad,\n blocked,\n refresh,\n documentShown: mobile && documentShown,\n showDocument: () => setDocumentShown(true),\n };\n};\n\nexport type EntryPreview = ReturnType<typeof useEntryPreview>;\n","import { Eye } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\n\ntype PreviewButtonProps = {\n /** The site has a deployment connection with a preview URL. */\n available: boolean;\n /** The preview is on screen. */\n pressed: boolean;\n onToggle: () => void;\n};\n\n/**\n * Shows or hides the draft on the site beside the document. Without a connection that has a preview URL it\n * stays visible but explains what's missing.\n */\nexport const PreviewButton = ({ available, pressed, onToggle }: PreviewButtonProps) => {\n const { t } = useTranslation();\n if (available) {\n return (\n <Button\n type=\"button\"\n variant={pressed ? 'secondary' : 'ghost'}\n size=\"sm\"\n aria-pressed={pressed}\n onClick={onToggle}\n >\n <Eye aria-hidden=\"true\" />\n {t('content.form.preview')}\n </Button>\n );\n }\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-disabled=\"true\"\n aria-description={t('content.form.previewUnavailable')}\n className=\"aria-disabled:cursor-not-allowed aria-disabled:opacity-60\"\n onClick={(event) => event.preventDefault()}\n >\n <Eye aria-hidden=\"true\" />\n {t('content.form.preview')}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{t('content.form.previewUnavailable')}</TooltipContent>\n </Tooltip>\n );\n};\n","import { formatRelativeTime } from '@/helpers/formatDate';\n\n/** Under a minute (or a little ahead, a clock difference) reads as `momentAgo`. */\nconst MOMENT_MS = 60_000;\n\n/** When a draft was changed elsewhere, as the notice says it: \"a moment ago\", then \"5 min. ago\". */\nexport const changedWhen = (savedAt: string, momentAgo: string, now = Date.now()): string =>\n now - new Date(savedAt).getTime() < MOMENT_MS ? momentAgo : formatRelativeTime(savedAt, { now });\n","import { RefreshCw } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { formatDateTime } from '@/helpers/formatDate';\nimport { changedWhen } from '../helpers/changedWhen';\nimport type { RemoteChange as RemoteChangeValue } from '../hooks/useRemoteDraftChange';\n\ntype RemoteChangeProps = {\n change: RemoteChangeValue;\n busy: boolean;\n onReload: () => void;\n /** \"Changed elsewhere\" and an icon-only Reload: the bar is narrow (drawer or preview open). */\n compact?: boolean;\n};\n\n/**\n * In place of the save state when the draft moved on the server and this tab has no edits of its own:\n * who changed it and when, and Reload to show it. Announced politely; the full sentence is the `title` (and\n * the only place the name shows while the bar is narrow).\n */\nexport const RemoteChange = ({ change, busy, onReload, compact = false }: RemoteChangeProps) => {\n const { t } = useTranslation();\n const when = changedWhen(change.savedAt, t('entry.remoteChange.momentAgo'));\n const { savedBy } = change;\n const full = savedBy\n ? savedBy.you\n ? t('entry.remoteChange.byYou', { when })\n : t('entry.remoteChange.by', { name: savedBy.name, when })\n : t('entry.remoteChange.unknown', { when });\n return (\n <div className=\"flex min-w-0 items-center gap-2\">\n <p\n role=\"status\"\n aria-live=\"polite\"\n title={`${full} (${formatDateTime(change.savedAt)})`}\n className=\"min-w-0 truncate text-foreground\"\n >\n {compact ? t('entry.remoteChange.short') : full}\n </p>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button type=\"button\" variant=\"outline\" size=\"xs\" disabled={busy} onClick={onReload}>\n <RefreshCw aria-hidden=\"true\" />\n <span className={compact ? 'sr-only' : undefined}>{t('entry.remoteChange.reload')}</span>\n </Button>\n </TooltipTrigger>\n {compact ? <TooltipContent>{t('entry.remoteChange.reload')}</TooltipContent> : null}\n </Tooltip>\n </div>\n );\n};\n","import { AlertCircle, Check, Loader2, Pencil } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { cn } from '@/helpers/cn';\nimport { formatDateTime } from '@/helpers/formatDate';\nimport type { SaveState as SaveStateValue } from '../hooks/useEntrySaver';\n\ntype SaveStateProps = {\n state: SaveStateValue;\n dirty: boolean;\n autosaved: boolean;\n /** Short text only (\"Saved\", not \"Saved Oct 10, 9:01 PM\"): the bar is narrow (drawer or preview open). */\n compact?: boolean;\n};\n\n/**\n * Where the draft stands: saving, unsaved changes, autosaved, saved, or a failed save. Announced politely.\n * The time of the last save shows from `xl` when there is room; the full sentence is always the `title`.\n */\nexport const SaveState = ({ state, dirty, autosaved, compact = false }: SaveStateProps) => {\n const { t } = useTranslation();\n const [Icon, full, short] =\n state.status === 'saving'\n ? [Loader2, t('content.save.saving')]\n : state.status === 'failed'\n ? [AlertCircle, t('content.save.failed')]\n : dirty\n ? [Pencil, t('content.save.unsaved')]\n : state.status === 'saved'\n ? state.kind === 'autosave'\n ? [\n Check,\n t('content.save.autosavedAt', { time: formatDateTime(state.at) }),\n t('content.save.autosaved'),\n ]\n : [\n Check,\n t('content.save.savedAt', { time: formatDateTime(state.at) }),\n t('content.save.saved'),\n ]\n : autosaved\n ? [Check, t('content.save.draftAutosaved')]\n : [Check, t('content.save.allSaved')];\n const brief = short ?? full;\n return (\n <p\n role=\"status\"\n aria-live=\"polite\"\n title={full}\n className={cn('flex min-w-0 items-center gap-1.5', state.status === 'failed' && 'text-destructive')}\n >\n <Icon\n aria-hidden=\"true\"\n className={cn('size-3.5 shrink-0', state.status === 'saving' && 'animate-spin')}\n />\n {compact || brief === full ? (\n <span className=\"truncate\">{brief}</span>\n ) : (\n <>\n <span className=\"truncate xl:hidden\">{brief}</span>\n <span className=\"truncate max-xl:hidden\">{full}</span>\n </>\n )}\n </p>\n );\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { ChevronRight } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useEntryForm } from '@/fields/form/context';\nimport { TopLevelField } from '@/fields/form/TopLevelField';\nimport { countIssuesUnder, issuesByPath } from '@/fields/helpers/issues';\nimport { useTopLevelValue } from '@/fields/hooks/useTopLevelValue';\nimport { cn } from '@/helpers/cn';\nimport { PropertyValue } from '../PropertyValue';\n\ntype PropertyRowProps = {\n field: FieldDefinition;\n expanded: boolean;\n onToggle: () => void;\n};\n\n/**\n * A property in the settings drawer: one compact line (name, value) that expands to the field's editor on\n * click. A property with problems is always open, so its error is never hidden.\n */\nexport const PropertyRow = ({ field, expanded, onToggle }: PropertyRowProps) => {\n const { t } = useTranslation();\n const { value } = useTopLevelValue(field);\n const path = `/${field.apiKey}`;\n const problems = useEntryForm((state) => countIssuesUnder(issuesByPath(state.issues), path));\n const open = expanded || problems > 0;\n const bodyId = `entry-property-${field.id}`;\n return (\n <div className=\"border-b last:border-b-0\" data-property-row={field.apiKey}>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={bodyId}\n onClick={onToggle}\n className=\"flex min-h-10 w-full items-center gap-3 rounded-md px-1 text-left text-sm outline-none hover:bg-muted/60 focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn('size-3.5 shrink-0 text-muted-foreground transition-transform', open && 'rotate-90')}\n />\n <span className={cn('shrink-0 text-muted-foreground', problems > 0 && 'text-destructive')}>\n {field.label}\n {field.required ? <span className=\"sr-only\"> {t('content.fields.required')}</span> : null}\n </span>\n <span className=\"ml-auto min-w-0 truncate text-right\">\n <PropertyValue field={field} value={value} />\n </span>\n </button>\n {open ? (\n <div id={bodyId} className=\"px-1 pt-1 pb-4\">\n <TopLevelField field={field} layout=\"bare\" />\n </div>\n ) : null}\n </div>\n );\n};\n","import type { PropertyGroup } from '@shapio/schema';\nimport { History } from 'lucide-react';\nimport { useEffect, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Sheet, SheetBody, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';\nimport { useIsMobile } from '@/hooks/use-mobile';\nimport { DrawerSection } from '../DrawerSection';\nimport { PropertyRow } from '../PropertyRow';\n\n/** Where the drawer opens: its top, the properties (one of them expanded) or the cover. */\nexport type DrawerFocus = { section: 'status' | 'properties' | 'cover'; property?: string };\n\ntype SettingsDrawerProps = {\n open: boolean;\n /** Open only because wide screens show it by default: focus and scroll stay in the document. */\n automatic: boolean;\n onOpenChange: (open: boolean) => void;\n focus: DrawerFocus;\n /** The document's properties by group; none for a form, whose fields are all on the page. */\n properties?: readonly PropertyGroup[];\n /** Properties whose rows are expanded (by API key). */\n expanded: ReadonlySet<string>;\n onToggleProperty: (apiKey: string) => void;\n /** How the type's entries open (Document or Form), for whoever manages its schema; first, before Status. */\n layout?: ReactNode;\n status: ReactNode;\n cover: ReactNode;\n onOpenHistory?: () => void;\n danger: ReactNode;\n};\n\nconst focusTargetOf = (focus: DrawerFocus) =>\n document.querySelector<HTMLElement>(\n focus.property\n ? `[data-property-row=\"${CSS.escape(focus.property)}\"] > button`\n : `[data-drawer-section=\"entry-settings-${focus.section}\"] :is(button, input, [href])`,\n );\n\n/**\n * The entry's settings beside the document (360px on the right, a bottom sheet on phones): the type's\n * layout (schema managers), status and locales, every property as a compact row, the cover's alt text and focal point, history, and the danger\n * zone. A form has no properties or cover here: its fields are all on the page. Non-modal: the document\n * stays editable while it is open; Escape or ⌘/ closes it.\n */\nexport const SettingsDrawer = ({\n open,\n automatic,\n onOpenChange,\n focus,\n properties = [],\n expanded,\n onToggleProperty,\n layout,\n status,\n cover,\n onOpenHistory,\n danger,\n}: SettingsDrawerProps) => {\n const { t } = useTranslation();\n const mobile = useIsMobile();\n useEffect(() => {\n if (open && !automatic) {\n document\n .querySelector(`[data-drawer-section=\"entry-settings-${focus.section}\"]`)\n ?.scrollIntoView({ block: 'start' });\n }\n }, [open, automatic, focus]);\n return (\n <Sheet open={open} onOpenChange={onOpenChange} modal={false}>\n <SheetContent\n id=\"entry-settings\"\n nonModal\n side={mobile ? 'bottom' : 'right'}\n size=\"xs\"\n // Focus goes to what the drawer was opened for: a property's row, a section, or its first control.\n onOpenAutoFocus={(event) => {\n if (automatic) {\n event.preventDefault();\n return;\n }\n const target = focusTargetOf(focus);\n if (target) {\n event.preventDefault();\n target.focus();\n }\n }}\n >\n <SheetHeader className=\"pb-2\">\n <SheetTitle className=\"text-base\">{t('entry.settings.title')}</SheetTitle>\n </SheetHeader>\n {/* pt-5: the first section sits as far under the title as the sections sit apart. */}\n <SheetBody className=\"space-y-7 pt-5\">\n {layout}\n {status}\n {properties.length > 0 ? (\n <DrawerSection id=\"entry-settings-properties\" title={t('entry.properties.title')}>\n {properties.map((group) => (\n <div key={group.id} className=\"space-y-1\">\n {group.label ? <h4 className=\"pt-2 text-sm font-semibold\">{group.label}</h4> : null}\n {group.fields.map((field) => (\n <PropertyRow\n key={field.id}\n field={field}\n expanded={expanded.has(field.apiKey)}\n onToggle={() => onToggleProperty(field.apiKey)}\n />\n ))}\n </div>\n ))}\n </DrawerSection>\n ) : null}\n {cover}\n {onOpenHistory ? (\n <DrawerSection id=\"entry-settings-history\" title={t('content.history.title')}>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={onOpenHistory}>\n <History aria-hidden=\"true\" />\n {t('entry.settings.allVersions')}\n </Button>\n </DrawerSection>\n ) : null}\n {danger}\n </SheetBody>\n </SheetContent>\n </Sheet>\n );\n};\n","import type { EntryStatus } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { StatusChip } from '@/components/StatusChip';\nimport { ENTRY_STATUS_LABEL_KEYS, ENTRY_STATUS_TONES } from '../helpers/entryStatus';\n\ntype EntryStatusChipProps = { status: EntryStatus; size?: 'default' | 'sm'; className?: string };\n\n/** Draft, published, or published with newer draft changes (\"Changed\"). */\nexport const EntryStatusChip = ({ status, size, className }: EntryStatusChipProps) => {\n const { t } = useTranslation();\n return (\n <StatusChip\n tone={ENTRY_STATUS_TONES[status]}\n label={t(ENTRY_STATUS_LABEL_KEYS[status])}\n size={size}\n className={className}\n />\n );\n};\n","import type { EntryLocaleState, Locale } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { cn } from '@/helpers/cn';\nimport { EntryStatusChip } from '../../EntryStatusChip';\n\ntype LocaleStatusListProps = {\n locales: readonly Locale[];\n states: readonly EntryLocaleState[];\n current: string;\n};\n\n/** Every locale's status for this entry (publishing is per locale, so each has its own). */\nexport const LocaleStatusList = ({ locales, states, current }: LocaleStatusListProps) => {\n const { t } = useTranslation();\n return (\n <ul aria-label={t('content.locales.statuses')} className=\"space-y-2\">\n {locales.map((locale) => {\n const state = states.find((item) => item.locale === locale.code);\n return (\n <li key={locale.code} className=\"flex min-h-5 items-center justify-between gap-2 text-sm\">\n <span className={cn('min-w-0 truncate', locale.code === current && 'font-semibold')}>\n {locale.label} <span className=\"font-mono text-xs text-muted-foreground\">{locale.code}</span>\n </span>\n {state ? (\n <EntryStatusChip status={state.status} size=\"sm\" />\n ) : (\n <span className=\"text-xs text-muted-foreground\">{t('content.locales.notCreated')}</span>\n )}\n </li>\n );\n })}\n </ul>\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useState } from 'react';\nimport { useTranslateEntry } from '@/api/assist';\nimport { useSaveEntry } from '@/api/content';\nimport { proposalKey, useAssistProposalsStore } from '@/stores/assistProposals';\nimport type { SaveBeforeAssist } from './useAssistTarget';\n\ntype TranslateLocaleOptions = {\n model: ModelDefinition;\n entryId: string;\n /** Saves the document first when it is the source locale; omit when the source isn't open. */\n prepare?: () => Promise<SaveBeforeAssist>;\n /** Opens the new locale's draft. */\n onOpen: (locale: string) => void;\n};\n\n/**\n * \"Translate from {locale}\": the model translates the source locale's saved draft, the result is saved as\n * the target locale's first draft (nothing publishes), and the document opens it with the proposal banner.\n */\nexport const useTranslateLocale = ({ model, entryId, prepare, onOpen }: TranslateLocaleOptions) => {\n const translate = useTranslateEntry();\n const saveEntry = useSaveEntry(model.apiKey);\n const propose = useAssistProposalsStore((state) => state.propose);\n const [preparing, setPreparing] = useState(false);\n const [blocked, setBlocked] = useState<Exclude<SaveBeforeAssist, 'ready'> | null>(null);\n const [target, setTarget] = useState<string | null>(null);\n\n const run = async (from: string, to: string) => {\n setBlocked(null);\n translate.reset();\n saveEntry.reset();\n setTarget(to);\n if (prepare) {\n setPreparing(true);\n const prepared = await prepare().finally(() => setPreparing(false));\n if (prepared !== 'ready') {\n setBlocked(prepared);\n return;\n }\n }\n try {\n const result = await translate.mutateAsync({ modelKey: model.apiKey, entryId, from, to });\n await saveEntry.mutateAsync({\n id: entryId,\n input: { locale: to, expectedVersion: null, data: result.data },\n });\n propose(proposalKey(model.apiKey, entryId, to), { model: result.model, from, issues: result.issues });\n onOpen(to);\n } catch {\n // Shown inline from the mutations' errors (both are silent: no toast, logged by the query client).\n }\n };\n return {\n run: (from: string, to: string) => void run(from, to),\n /** The locale being (or last) translated into. */\n target,\n pending: preparing || translate.isPending || saveEntry.isPending,\n error: translate.error ?? saveEntry.error,\n blocked,\n };\n};\n","import type { Locale } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { useAssistEnabled } from '@/api/assist';\nimport { AssistButton } from '@/components/AssistButton';\nimport { AssistError } from '@/components/AssistError';\nimport { cn } from '@/helpers/cn';\nimport { SAVE_BEFORE_ASSIST_KEYS } from '../helpers/assistMessages';\nimport type { SaveBeforeAssist } from '../hooks/useAssistTarget';\nimport { useTranslateLocale } from '../hooks/useTranslateLocale';\n\ntype TranslateLocaleProps = {\n model: ModelDefinition;\n entryId: string;\n /** The locale to translate from, and its label. */\n from: string;\n fromLabel: string;\n /** Locales this entry doesn't have yet. */\n targets: readonly Pick<Locale, 'code' | 'label'>[];\n /** Saves the open document first when it is `from`. */\n prepare?: () => Promise<SaveBeforeAssist>;\n onOpen: (locale: string) => void;\n className?: string;\n};\n\n/** \"Translate {locale} from {from}\" for each locale not started: a draft to review, opened with a banner. */\nexport const TranslateLocale = ({\n model,\n entryId,\n from,\n fromLabel,\n targets,\n prepare,\n onOpen,\n className,\n}: TranslateLocaleProps) => {\n const { t } = useTranslation();\n const enabled = useAssistEnabled();\n const translate = useTranslateLocale({ model, entryId, prepare, onOpen });\n if (!enabled || targets.length === 0) {\n return null;\n }\n return (\n <div className={cn('space-y-1', className)}>\n <div className=\"flex flex-wrap gap-1\">\n {targets.map((locale) => (\n <AssistButton\n key={locale.code}\n pending={translate.pending && translate.target === locale.code}\n pendingLabel={t('assist.translate.pending', { locale: locale.label })}\n disabled={translate.pending}\n onClick={() => translate.run(from, locale.code)}\n >\n {t('assist.translate.run', { locale: locale.label, from: fromLabel })}\n </AssistButton>\n ))}\n </div>\n {translate.blocked ? (\n <p role=\"alert\" className=\"text-meta text-destructive\">\n {t(SAVE_BEFORE_ASSIST_KEYS[translate.blocked])}\n </p>\n ) : null}\n <AssistError error={translate.error} />\n </div>\n );\n};\n","import type { AdminEntry, Locale } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { Copy, Plus } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { Button } from '@/components/ui/button';\nimport { formatDateTime } from '@/helpers/formatDate';\nimport { EntryStatusChip } from '../../EntryStatusChip';\nimport { DrawerSection } from '../DrawerSection';\nimport { useAssistTarget } from '../hooks/useAssistTarget';\nimport { LocaleStatusList } from '../LocaleStatusList';\nimport { TranslateLocale } from '../TranslateLocale';\n\ntype StatusSectionProps = {\n model: ModelDefinition;\n entry: AdminEntry | null;\n locales: readonly Locale[];\n locale: string | null;\n defaultLocale: string | undefined;\n labelOf: (code: string) => string;\n onLocaleChange: (code: string) => void;\n /** Copies the default locale's localized values into the document. */\n onCopyFromDefault?: () => void | Promise<unknown>;\n /** Copying would replace localized values: ask first. */\n confirmCopy: boolean;\n};\n\ntype RowProps = { term: string; children: ReactNode };\n\nconst Row = ({ term, children }: RowProps) => (\n <div className=\"flex min-h-8 items-center justify-between gap-3 border-b text-sm last:border-b-0\">\n <dt className=\"text-muted-foreground\">{term}</dt>\n <dd className=\"min-w-0 text-right\">{children}</dd>\n </div>\n);\n\n/** Where the entry stands: status, when it went live, its locales (with \"Start French\"), dates. */\nexport const StatusSection = ({\n model,\n entry,\n locales,\n locale,\n defaultLocale,\n labelOf,\n onLocaleChange,\n onCopyFromDefault,\n confirmCopy,\n}: StatusSectionProps) => {\n const { t } = useTranslation();\n const assistTarget = useAssistTarget();\n const canCopy = Boolean(onCopyFromDefault && defaultLocale);\n const notStarted = entry\n ? locales.filter((item) => !entry.locales.some((state) => state.locale === item.code))\n : [];\n const copyButton = (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={confirmCopy || !onCopyFromDefault ? undefined : () => void onCopyFromDefault()}\n >\n <Copy aria-hidden=\"true\" />\n {t('content.locales.copyFrom', { locale: labelOf(defaultLocale ?? '') })}\n </Button>\n );\n // A new entry has no status, dates or locales yet: no section rather than an empty heading.\n if (!entry && !canCopy) {\n return null;\n }\n return (\n <DrawerSection id=\"entry-settings-status\" title={t('entry.settings.status')}>\n <dl>\n {entry ? (\n <Row term={t('entry.settings.now')}>\n <EntryStatusChip status={entry.status} size=\"sm\" />\n </Row>\n ) : null}\n {entry && model.draftAndPublish ? (\n <Row term={t('entry.settings.liveSince')}>\n {entry.publishedAt ? formatDateTime(entry.publishedAt) : t('content.form.notPublished')}\n </Row>\n ) : null}\n {entry ? <Row term={t('content.form.created')}>{formatDateTime(entry.createdAt)}</Row> : null}\n {entry ? <Row term={t('content.form.updated')}>{formatDateTime(entry.updatedAt)}</Row> : null}\n </dl>\n {model.localized && locale && entry && locales.length > 1 ? (\n <div className=\"space-y-2 pt-2\">\n <h4 className=\"text-sm font-semibold\">{t('content.locales.statuses')}</h4>\n <LocaleStatusList locales={locales} states={entry.locales} current={locale} />\n {notStarted.map((item) => (\n <Button\n key={item.code}\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onLocaleChange(item.code)}\n >\n <Plus aria-hidden=\"true\" />\n {t('entry.settings.startLocale', { locale: item.label })}\n </Button>\n ))}\n {assistTarget ? (\n <TranslateLocale\n model={model}\n entryId={assistTarget.entryId}\n from={locale}\n fromLabel={labelOf(locale)}\n targets={notStarted}\n prepare={assistTarget.saveIfDirty}\n onOpen={onLocaleChange}\n />\n ) : null}\n </div>\n ) : null}\n {onCopyFromDefault && defaultLocale ? (\n confirmCopy ? (\n <InlineConfirm\n tone=\"default\"\n title={t('content.locales.copyTitle', { locale: labelOf(defaultLocale) })}\n description={t('content.locales.copyDescription')}\n confirmLabel={t('content.locales.copyConfirm')}\n onConfirm={onCopyFromDefault}\n trigger={copyButton}\n />\n ) : (\n copyButton\n )\n ) : null}\n </DrawerSection>\n );\n};\n","import type { EntryStatus } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { Link } from '@tanstack/react-router';\nimport { Check, Loader2, PanelRight, Save, Send } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';\nimport { EntryStatusChip } from '../../EntryStatusChip';\n\n/** The one primary action of the document, by state. */\nexport type PrimaryAction =\n | { kind: 'publish'; upToDate: boolean; onClick: () => void }\n | { kind: 'create' | 'save'; label: string; pending: boolean; onClick: () => void }\n | { kind: 'none' };\n\ntype TopBarProps = {\n model: ModelDefinition;\n title: string;\n status: EntryStatus | undefined;\n saveState: ReactNode;\n presence: ReactNode;\n /** The locale switch, for localized models. */\n locale: ReactNode;\n preview: ReactNode;\n /** Shown while the draft has changes a Save would validate and record (plus ⌘S). */\n onSave: (() => void) | undefined;\n saving: boolean;\n /** A save conflict waits for a decision: nothing can be saved or published. */\n blocked: boolean;\n settingsOpen: boolean;\n onToggleSettings: () => void;\n primary: PrimaryAction;\n};\n\nconst spinnerOr = (busy: boolean, icon: ReactNode) =>\n busy ? <Loader2 aria-hidden=\"true\" className=\"animate-spin\" /> : icon;\n\n/**\n * The document's thin sticky bar: where you are (place / title), its state (status, save state, who else\n * is here) and its actions (locale, Preview, Settings, then the primary: Publish, Create or Save).\n */\nexport const TopBar = ({\n model,\n title,\n status,\n saveState,\n presence,\n locale,\n preview,\n onSave,\n saving,\n blocked,\n settingsOpen,\n onToggleSettings,\n primary,\n}: TopBarProps) => {\n const { t } = useTranslation();\n return (\n <div\n data-slot=\"entry-top-bar\"\n className=\"sticky top-12 z-20 -mx-4 -mt-7 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b bg-background/95 px-4 py-2.5 backdrop-blur supports-[backdrop-filter]:bg-background/80 sm:-mx-8 sm:px-8 lg:top-0\"\n >\n {/* min-w-72: below that the actions wrap to a row of their own rather than squeeze or overlap it. */}\n <div className=\"flex min-w-72 flex-1 items-center gap-x-3 gap-y-1 text-meta text-muted-foreground max-sm:min-w-0 max-sm:flex-wrap\">\n {/* The breadcrumb gives way first, and in it only the title truncates (the place name never shrinks). */}\n <nav aria-label={t('common.breadcrumb')} className=\"min-w-0 shrink-10 overflow-hidden\">\n <ol className=\"flex min-w-0 items-center gap-1.5 font-medium\">\n <li className=\"shrink-0\">\n {model.kind === 'collection' ? (\n <Link\n to=\"/content/$modelKey\"\n params={{ modelKey: model.apiKey }}\n className=\"rounded-sm outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n >\n {model.label}\n </Link>\n ) : (\n model.label\n )}\n </li>\n <li aria-hidden=\"true\" className=\"text-muted-foreground/70\">\n /\n </li>\n <li aria-current=\"page\" className=\"min-w-0 truncate font-semibold text-foreground\">\n {title}\n </li>\n </ol>\n </nav>\n {status ? (\n <div className=\"shrink-0\">\n <EntryStatusChip status={status} size=\"sm\" />\n </div>\n ) : null}\n {/* Short on a narrow bar (`compact`), so it keeps its width; the title truncates instead. */}\n <div className=\"shrink-0 whitespace-nowrap\">{saveState}</div>\n </div>\n <div className=\"flex shrink-0 flex-wrap items-center gap-2\">\n {presence}\n {locale}\n {onSave ? (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" disabled={saving || blocked} onClick={onSave}>\n {spinnerOr(saving, <Save aria-hidden=\"true\" />)}\n {t('content.form.save')}\n </Button>\n ) : null}\n {preview}\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n aria-expanded={settingsOpen}\n aria-controls=\"entry-settings\"\n onClick={onToggleSettings}\n >\n <PanelRight aria-hidden=\"true\" />\n {/* Icon only while the drawer is open: the bar is narrow then, and the open drawer says what it is. */}\n <span className={settingsOpen ? 'sr-only' : 'max-sm:sr-only'}>{t('entry.settings.open')}</span>\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n {t('entry.shortcutHint', { action: t('entry.settings.open'), keys: '⌘/' })}\n </TooltipContent>\n </Tooltip>\n {primary.kind === 'publish' ? (\n primary.upToDate ? (\n <Button type=\"button\" size=\"sm\" disabled>\n <Check aria-hidden=\"true\" />\n {t('content.actions.published')}\n </Button>\n ) : (\n <Button type=\"button\" size=\"sm\" disabled={saving || blocked} onClick={primary.onClick}>\n <Send aria-hidden=\"true\" />\n {t('content.actions.publish')}\n </Button>\n )\n ) : primary.kind === 'none' ? null : (\n <Button type=\"button\" size=\"sm\" disabled={primary.pending || blocked} onClick={primary.onClick}>\n {spinnerOr(primary.pending, <Save aria-hidden=\"true\" />)}\n {primary.label}\n </Button>\n )}\n </div>\n </div>\n );\n};\n","import { effectiveLayout, entryLayoutOf, type ModelDefinition } from '@shapio/schema';\nimport { useSearch } from '@tanstack/react-router';\nimport { useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useStore } from 'zustand';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Page } from '@/components/Page';\nimport { UnsavedChangesGuard } from '@/components/UnsavedChangesGuard';\nimport { EntrySiblings } from '@/fields/form/EntrySiblings';\nimport { FieldsProvider } from '@/fields/form/FieldsProvider';\nimport { entryTitle } from '@/fields/helpers/titles';\nimport type { FormValues } from '@/fields/helpers/values';\nimport { cn } from '@/helpers/cn';\nimport { useSaveShortcut } from '@/hooks/useSaveShortcut';\nimport { useContentLocales } from '../hooks/useContentLocales';\nimport type { ContentSchema } from '../hooks/useContentSchema';\nimport { LocaleSelect } from '../LocaleSelect';\nimport { CoverSettings } from './CoverSettings';\nimport { DangerZone } from './DangerZone';\nimport { DocumentBody } from './Document';\nimport { FormBody } from './Form';\nimport { HistorySheet } from './HistorySheet';\nimport { AssistDocumentContext, useAssistDocument } from './hooks/useAssistTarget';\nimport { useDocumentPaletteActions } from './hooks/useDocumentPaletteActions';\nimport { useDocumentShortcuts } from './hooks/useDocumentShortcuts';\nimport { useEntryDocument } from './hooks/useEntryDocument';\nimport { useEntryHeartbeat } from './hooks/useEntryHeartbeat';\nimport { usePreflightFlow } from './hooks/usePreflightFlow';\nimport { useRevealField } from './hooks/useRevealField';\nimport { useSettingsDrawer } from './hooks/useSettingsDrawer';\nimport { LayoutSection } from './LayoutSection';\nimport { NoFields } from './NoFields';\nimport { Notices } from './Notices';\nimport { PreflightSheet } from './PreflightSheet';\nimport { Presence } from './Presence';\nimport { PreviewPane } from './Preview';\nimport { useEntryPreview } from './Preview/hooks/useEntryPreview';\nimport { PreviewButton } from './PreviewButton';\nimport { RemoteChange } from './RemoteChange';\nimport { SaveState } from './SaveState';\nimport { SettingsDrawer } from './SettingsDrawer';\nimport { StatusSection } from './StatusSection';\nimport { TopBar, type PrimaryAction } from './TopBar';\nimport { TranslateLocale } from './TranslateLocale';\nimport type { EntryMode, ReloadEntry } from './types';\n\ntype EntryDocumentProps = {\n schema: ContentSchema;\n model: ModelDefinition;\n mode: EntryMode;\n locale: string | null;\n /** Local values to reapply over the loaded ones (after \"reload and keep my changes\"). */\n carry?: FormValues;\n onReload: ReloadEntry;\n onLocaleChange: (code: string) => void;\n};\n\n/**\n * An entry, opened the way its model says (`display.layout`). A document you write (plan\n * editor-experience §3, `DocumentBody`): the cover, the title typed into the page, a strip of properties and\n * the canvas of blocks, everything else in a settings drawer beside it. A form you fill (`FormBody`): every\n * field on the page at its width, in sections. Around either: a thin top bar, the drawer, publishing through\n * a pre-flight, the preview, history and presence. Autosave keeps drafts safe; ⌘S records a version.\n */\nexport const EntryDocument = ({\n schema,\n model,\n mode,\n locale,\n carry,\n onReload,\n onLocaleChange,\n}: EntryDocumentProps) => {\n const { t } = useTranslation();\n const { locales, defaultLocale, labelOf } = useContentLocales(model, locale ?? undefined);\n const { people, drafts } = useEntryHeartbeat(\n model.apiKey,\n mode.kind === 'edit' ? mode.entry.id : null,\n locale,\n );\n const entryDocument = useEntryDocument({\n schema,\n model,\n mode,\n locale,\n defaultLocale,\n carry,\n onReload,\n drafts,\n });\n const { setup, saver, lifecycle, publishing, permissions, conflict, dirty } = entryDocument;\n const { store, entry, entryId, environment } = setup;\n const layout = useMemo(() => effectiveLayout(model), [model]);\n // A form has every field on the page: its drawer holds no properties or cover.\n const form = entryLayoutOf(model) === 'form';\n const assistDocument = useAssistDocument({ model, mode, store, save: saver.save });\n const drawer = useSettingsDrawer();\n const preflight = usePreflightFlow(saver.save);\n // `?revision=` (Snapshots → Timeline, \"Open this version\") opens the history at that revision.\n const { revision: linkedRevision } = useSearch({ strict: false });\n const [historyOpen, setHistoryOpen] = useState(linkedRevision !== undefined);\n const reveal = useRevealField(environment.idPrefix, (apiKey) =>\n drawer.openAt(form ? { section: 'status' } : { section: 'properties', property: apiKey }),\n );\n const preview = useEntryPreview({\n model,\n components: schema.components,\n entryId: mode.kind === 'edit' ? entryId : null,\n locale,\n store,\n saveStatus: saver.state.status,\n reveal,\n });\n const titleValue = useStore(store, (state) =>\n layout.title ? state.values[layout.title.apiKey] : undefined,\n );\n const blocked = conflict !== undefined;\n const canPublish = mode.kind === 'edit' && model.draftAndPublish && permissions.canPublish;\n useSaveShortcut(entryDocument.save, !blocked && entryDocument.editable);\n useDocumentShortcuts(\n {\n onPublish: canPublish && !blocked ? preflight.start : undefined,\n onToggleSettings: drawer.toggle,\n onCycleLocale:\n model.localized && locale && locales.length > 1\n ? () => {\n const index = locales.findIndex((item) => item.code === locale);\n const next = locales[(index + 1) % locales.length];\n if (next) {\n onLocaleChange(next.code);\n }\n }\n : undefined,\n },\n true,\n );\n\n useDocumentPaletteActions({\n onPublish: canPublish && !blocked ? preflight.start : undefined,\n onOpenSettings: () => drawer.openAt({ section: 'status' }),\n locales,\n entry,\n onLocaleChange: model.localized && locales.length > 1 ? onLocaleChange : undefined,\n });\n\n if (setup.runtimeLoading) {\n return <LoadingState rows={6} />;\n }\n const heading =\n entryTitle(model, layout.title ? { [layout.title.apiKey]: titleValue } : {}) ??\n (mode.kind === 'create' ? t('content.form.newTitle', { model: model.label }) : t('content.untitled'));\n const autosaved = entry?.autosaved ?? false;\n const primary: PrimaryAction =\n mode.kind === 'create'\n ? permissions.canCreate\n ? {\n kind: 'create',\n label: t('content.form.create'),\n pending: lifecycle.creating,\n onClick: entryDocument.save,\n }\n : { kind: 'none' }\n : mode.kind === 'newLocale'\n ? {\n kind: 'create',\n label: t('content.form.createLocale', { locale: labelOf(locale ?? '') }),\n pending: saver.state.status === 'saving',\n onClick: entryDocument.save,\n }\n : canPublish\n ? {\n kind: 'publish',\n upToDate: entry?.status === 'published' && !dirty && !autosaved,\n onClick: preflight.start,\n }\n : model.draftAndPublish || !entryDocument.editable\n ? { kind: 'none' }\n : {\n kind: 'save',\n label: t('content.form.save'),\n pending: saver.state.status === 'saving',\n onClick: entryDocument.save,\n };\n // With Publish as the primary action, Save (a validated version) shows while there is something to record.\n const showSave = primary.kind === 'publish' && entryDocument.editable && (dirty || autosaved);\n const live = entry !== null && entry.status !== 'draft';\n const hasFields =\n layout.title !== undefined ||\n layout.cover !== undefined ||\n layout.canvas.length > 0 ||\n layout.properties.length > 0;\n return (\n <FieldsProvider environment={environment} store={store}>\n <AssistDocumentContext.Provider value={assistDocument}>\n <EntrySiblings>\n <Page\n width=\"full\"\n className={cn(\n 'space-y-0 transition-[padding]',\n // The settings drawer overlays the preview when both are open.\n !preview.open && drawer.open && 'xl:pr-90',\n )}\n >\n <TopBar\n model={model}\n title={heading}\n status={entry?.status}\n saveState={\n mode.kind === 'edit' && entryDocument.remoteChange ? (\n <RemoteChange\n change={entryDocument.remoteChange}\n busy={entryDocument.reloading}\n onReload={() => entryDocument.reload(false)}\n compact={drawer.open || preview.open}\n />\n ) : mode.kind === 'edit' ? (\n <SaveState\n state={saver.state}\n dirty={dirty}\n autosaved={autosaved}\n // The bar shares the screen with the drawer or the preview: the short form only.\n compact={drawer.open || preview.open}\n />\n ) : null\n }\n presence={<Presence people={people} />}\n locale={\n model.localized && locale ? (\n <LocaleSelect\n locales={locales}\n value={locale}\n onChange={onLocaleChange}\n states={entry?.locales ?? []}\n size=\"sm\"\n className=\"w-auto\"\n />\n ) : null\n }\n preview={\n mode.kind === 'edit' ? (\n <PreviewButton\n available={preview.available}\n pressed={preview.open && !preview.documentShown}\n onToggle={() => {\n // The preview takes the right half: the drawer makes room, its remembered choice kept.\n if (!preview.open) {\n drawer.hideForPreview();\n }\n preview.toggle();\n }}\n />\n ) : null\n }\n onSave={showSave ? entryDocument.save : undefined}\n saving={saver.state.status === 'saving' || lifecycle.creating}\n blocked={blocked}\n settingsOpen={drawer.open}\n onToggleSettings={drawer.toggle}\n primary={primary}\n />\n {/* The preview takes the right half of the screen under the top bar on lg and up. */}\n <div className={cn(preview.open && 'lg:pr-[calc(50vw-2rem)]')}>\n <article\n aria-label={heading}\n className={cn(\n 'mx-auto w-full space-y-6 pt-8 pb-40 lg:px-16',\n form ? 'max-w-4xl' : 'max-w-3xl',\n )}\n data-entry-document\n data-entry-layout={form ? 'form' : 'document'}\n >\n <Notices\n conflict={conflict}\n reloading={entryDocument.reloading}\n onReload={entryDocument.reload}\n newLocaleLabel={mode.kind === 'newLocale' ? labelOf(locale ?? '') : undefined}\n newLocaleAction={\n mode.kind === 'newLocale' && locale && mode.source.locale && entryDocument.editable ? (\n <TranslateLocale\n model={model}\n entryId={mode.entryId}\n from={mode.source.locale}\n fromLabel={labelOf(mode.source.locale)}\n targets={[{ code: locale, label: labelOf(locale) }]}\n onOpen={onLocaleChange}\n />\n ) : null\n }\n referrers={lifecycle.referrers}\n models={schema.models}\n onDismissReferrers={lifecycle.clearReferrers}\n outdated={\n model.draftAndPublish && !publishing.othersDismissed\n ? (entry?.sharedOutdatedLocales ?? [])\n : []\n }\n labelOf={labelOf}\n publishing={publishing.publishing}\n onPublishOthers={(others) => void publishing.publishOthers(others)}\n onDismissOthers={publishing.dismissOthers}\n />\n {hasFields ? null : <NoFields model={model} canManageSchema={permissions.canManageSchema} />}\n {form ? (\n <FormBody model={model} heading={heading} />\n ) : (\n <DocumentBody layout={layout} heading={heading} onOpenSettings={drawer.openAt} />\n )}\n </article>\n </div>\n </Page>\n <PreviewPane preview={preview} title={heading} />\n <SettingsDrawer\n open={drawer.open}\n automatic={drawer.automatic}\n onOpenChange={drawer.setOpen}\n focus={drawer.focus}\n properties={form ? undefined : layout.propertyGroups}\n expanded={drawer.expanded}\n onToggleProperty={drawer.toggleProperty}\n layout={permissions.canManageSchema ? <LayoutSection model={model} /> : null}\n status={\n <StatusSection\n model={model}\n entry={entry}\n locales={locales}\n locale={locale}\n defaultLocale={defaultLocale}\n labelOf={labelOf}\n onLocaleChange={onLocaleChange}\n onCopyFromDefault={\n model.localized &&\n entryId !== null &&\n defaultLocale !== undefined &&\n locale !== defaultLocale\n ? lifecycle.copyFromDefault\n : undefined\n }\n confirmCopy={entryDocument.hasLocalizedValues}\n />\n }\n cover={layout.cover && !form ? <CoverSettings field={layout.cover} /> : null}\n onOpenHistory={mode.kind === 'edit' ? () => setHistoryOpen(true) : undefined}\n danger={\n mode.kind === 'edit' ? (\n <DangerZone\n title={heading}\n onUnpublish={canPublish && live ? publishing.unpublish : undefined}\n onDuplicate={\n model.kind === 'collection' && permissions.canCreate\n ? () => void lifecycle.duplicate()\n : undefined\n }\n onDelete={permissions.canDelete ? lifecycle.remove : undefined}\n />\n ) : null\n }\n />\n {entryId && canPublish ? (\n <PreflightSheet\n open={preflight.open}\n onOpenChange={preflight.setOpen}\n entryId={entryId}\n ready={preflight.ready}\n labelOf={labelOf}\n canSchedule={permissions.canSchedule}\n canUseChangeSets={permissions.canUseChangeSets}\n publishing={publishing.publishing || saver.state.status === 'saving'}\n onPublish={publishing.publish}\n onFix={reveal}\n />\n ) : null}\n {setup.mediaDialog}\n {entryId && mode.kind === 'edit' ? (\n <HistorySheet\n open={historyOpen}\n onOpenChange={setHistoryOpen}\n model={model}\n components={schema.components}\n entryId={entryId}\n locale={locale}\n restoring={lifecycle.restoring}\n confirmRestore={dirty}\n onRestore={lifecycle.restore}\n initialRevisionId={linkedRevision}\n />\n ) : null}\n <UnsavedChangesGuard when={dirty && !blocked} />\n </EntrySiblings>\n </AssistDocumentContext.Provider>\n </FieldsProvider>\n );\n};\n","import { ShapioApiError } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { useEntry } from '@/api/content';\nimport { isRecord } from '@/fields/helpers/values';\nimport type { EntryMode } from '../Entry/types';\n\n/** The locales an entry has, from a 404 ENTRY_LOCALE_NOT_FOUND answer. */\nconst existingLocalesOf = (error: unknown): string[] => {\n if (\n !(error instanceof ShapioApiError) ||\n error.code !== 'ENTRY_LOCALE_NOT_FOUND' ||\n !isRecord(error.details)\n ) {\n return [];\n }\n const locales = error.details.locales;\n return Array.isArray(locales) ? locales.filter((code): code is string => typeof code === 'string') : [];\n};\n\n/**\n * The entry in the requested locale, or, when it has no version in that locale yet, another locale's\n * version to start one from (its shared fields carry over).\n */\nexport const useEntryForLocale = (model: ModelDefinition, entryId: string, locale: string | null) => {\n const entry = useEntry(model.apiKey, entryId, locale ?? undefined);\n const existing = existingLocalesOf(entry.error);\n const sourceLocale = model.localized ? existing[0] : undefined;\n const sourceEnabled = sourceLocale !== undefined;\n const source = useEntry(model.apiKey, entryId, sourceLocale, sourceEnabled);\n if (entry.data) {\n return {\n mode: { kind: 'edit', entry: entry.data } as EntryMode,\n error: undefined,\n pending: false,\n refetch: entry.refetch,\n };\n }\n if (sourceEnabled && source.data) {\n return {\n mode: { kind: 'newLocale', entryId, source: source.data } as EntryMode,\n error: undefined,\n pending: false,\n refetch: entry.refetch,\n };\n }\n const error = sourceEnabled ? source.error : entry.error;\n return { mode: undefined, error: error ?? undefined, pending: !error, refetch: entry.refetch };\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useState } from 'react';\nimport { entryQueryOptions } from '@/api/content';\nimport { queryKeys } from '@/api/queryKeys';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport type { FormValues } from '@/fields/helpers/values';\nimport { reportError } from '@/helpers/reportError';\nimport { EntryDocument } from '../Entry';\nimport type { ContentSchema } from '../hooks/useContentSchema';\nimport { useEntryForLocale } from '../hooks/useEntryForLocale';\n\ntype EntryLoaderProps = {\n schema: ContentSchema;\n model: ModelDefinition;\n entryId: string;\n locale: string | null;\n onLocaleChange: (code: string) => void;\n};\n\n/**\n * Loads an entry in one locale and opens the form. \"Reload\" (after a conflict, a restore or creating a\n * locale) refetches the entry, and the schema when it changed, then starts the form again.\n */\nexport const EntryLoader = ({ schema, model, entryId, locale, onLocaleChange }: EntryLoaderProps) => {\n const queryClient = useQueryClient();\n const loaded = useEntryForLocale(model, entryId, locale);\n const [generation, setGeneration] = useState<{ token: number; carry: FormValues | undefined }>({\n token: 0,\n carry: undefined,\n });\n const reload = async (carry: FormValues | null) => {\n try {\n await queryClient.invalidateQueries({ queryKey: queryKeys.schema.all });\n await queryClient.fetchQuery({\n ...entryQueryOptions(model.apiKey, entryId, locale ?? undefined),\n staleTime: 0,\n });\n } catch (error) {\n reportError(error, 'reloading an entry');\n }\n setGeneration((current) => ({ token: current.token + 1, carry: carry ?? undefined }));\n };\n if (loaded.error) {\n return <ErrorState error={loaded.error} onRetry={() => void loaded.refetch()} />;\n }\n if (!loaded.mode) {\n return <LoadingState rows={6} />;\n }\n return (\n <EntryDocument\n key={`${entryId}:${locale ?? ''}:${loaded.mode.kind}:${generation.token}`}\n schema={schema}\n model={model}\n mode={loaded.mode}\n locale={locale}\n carry={generation.carry}\n onReload={(carry) => void reload(carry)}\n onLocaleChange={onLocaleChange}\n />\n );\n};\n","import { findModelByKey, useContentSchema } from './useContentSchema';\n\n/**\n * Resolves a route's `modelKey` against the live schema (models are data, looked up at render time). A\n * failed refetch keeps the schema already loaded: the error only counts when there is none, so an open\n * editor never unmounts over a background request (e.g. while the session is resumed in place).\n */\nexport const useModelRoute = (modelKey: string) => {\n const { schema, error: schemaError } = useContentSchema();\n const model = schema ? findModelByKey(schema, modelKey) : undefined;\n const error = schema ? undefined : schemaError;\n return { schema, model, error, pending: !schema && !error };\n};\n","import { Link } from '@tanstack/react-router';\nimport { FileQuestion } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Button } from '@/components/ui/button';\n\ntype ModelMissingProps = { modelKey: string };\n\n/** The URL names a model that doesn't exist (renamed, deleted, or not readable by this person). */\nexport const ModelMissing = ({ modelKey }: ModelMissingProps) => {\n const { t } = useTranslation();\n return (\n <EmptyState\n icon={FileQuestion}\n title={t('content.missingModel.title', { key: modelKey })}\n action={\n <Button asChild variant=\"outline\">\n <Link to=\"/content\">{t('content.missingModel.back')}</Link>\n </Button>\n }\n />\n );\n};\n","import { useNavigate, useParams, useSearch } from '@tanstack/react-router';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { EntryFrame } from '../EntryFrame';\nimport { EntryLoader } from '../EntryLoader';\nimport { useContentLocales } from '../hooks/useContentLocales';\nimport { useModelRoute } from '../hooks/useModelRoute';\nimport { ModelMissing } from '../ModelMissing';\n\n/** `/content/$modelKey/$entryId?locale=`: edit one entry in one locale. */\nexport const EntryEditor = () => {\n const { modelKey, entryId } = useParams({ from: '/app/content/$modelKey/$entryId' });\n const search = useSearch({ from: '/app/content/$modelKey/$entryId' });\n const navigate = useNavigate({ from: '/content/$modelKey/$entryId' });\n const { schema, model, error, pending } = useModelRoute(modelKey);\n const locales = useContentLocales(model, search.locale);\n if (error || locales.error) {\n return <ErrorState error={error ?? locales.error} />;\n }\n if (pending || locales.isPending || !schema) {\n return <LoadingState rows={6} />;\n }\n if (!model) {\n return <ModelMissing modelKey={modelKey} />;\n }\n return (\n <EntryFrame model={model} modelKey={modelKey}>\n <EntryLoader\n schema={schema}\n model={model}\n entryId={entryId}\n locale={locales.current}\n onLocaleChange={(locale) => void navigate({ search: { locale } })}\n />\n </EntryFrame>\n );\n};\n","import { Link, Navigate } from '@tanstack/react-router';\nimport { Boxes } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { EmptyState } from '@/components/EmptyState';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { Button } from '@/components/ui/button';\nimport { useContentSchema } from '../hooks/useContentSchema';\n\n/** `/content`: opens the first model's content, or explains that a model comes first. */\nexport const ContentHome = () => {\n const { t } = useTranslation();\n const { schema, error } = useContentSchema();\n if (error) {\n return <ErrorState error={error} />;\n }\n if (!schema) {\n return <LoadingState />;\n }\n const [first] = schema.sortedModels\n .filter((model) => model.kind === 'collection')\n .concat(schema.sortedModels);\n if (first) {\n return <Navigate to=\"/content/$modelKey\" params={{ modelKey: first.apiKey }} replace />;\n }\n return (\n <Page>\n <PageHeader title={t('content.title')} />\n <EmptyState\n icon={Boxes}\n title={t('content.empty.title')}\n action={\n <Button asChild>\n <Link to=\"/content/new\">{t('content.empty.action')}</Link>\n </Button>\n }\n />\n </Page>\n );\n};\n","import { linkOptions, useNavigate, useParams, useSearch } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { useMe } from '@/api/auth';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { NoAccess } from '@/components/NoAccess';\nimport { Page } from '@/components/Page';\nimport { PageHeader } from '@/components/PageHeader';\nimport { canOnModel } from '@/helpers/modelPermissions';\nimport { EntryDocument } from '../Entry';\nimport { EntryFrame } from '../EntryFrame';\nimport { useContentLocales } from '../hooks/useContentLocales';\nimport { useModelRoute } from '../hooks/useModelRoute';\nimport { ModelMissing } from '../ModelMissing';\n\nconst CREATE = { kind: 'create' } as const;\n\n/** `/content/$modelKey/new?locale=`: a new entry, created on the first Save (fully validated). */\nexport const NewEntry = () => {\n const { modelKey } = useParams({ from: '/app/content/$modelKey/new' });\n const search = useSearch({ from: '/app/content/$modelKey/new' });\n const navigate = useNavigate({ from: '/content/$modelKey/new' });\n const { t } = useTranslation();\n const me = useMe().data;\n const { schema, model, error, pending } = useModelRoute(modelKey);\n const locales = useContentLocales(model, search.locale);\n if (error || locales.error) {\n return <ErrorState error={error ?? locales.error} />;\n }\n if (pending || locales.isPending || !schema) {\n return <LoadingState rows={6} />;\n }\n if (!model) {\n return <ModelMissing modelKey={modelKey} />;\n }\n if (!canOnModel(me, model.id, 'create')) {\n return (\n <Page>\n <PageHeader\n breadcrumb={[\n { label: model.label, link: linkOptions({ to: '/content/$modelKey', params: { modelKey } }) },\n ]}\n title={t('content.form.newTitle', { model: model.label })}\n />\n <NoAccess />\n </Page>\n );\n }\n return (\n <EntryFrame model={model} modelKey={modelKey}>\n <EntryDocument\n key={locales.current ?? ''}\n schema={schema}\n model={model}\n mode={CREATE}\n locale={locales.current}\n onReload={() => undefined}\n onLocaleChange={(locale) => void navigate({ search: { locale } })}\n />\n </EntryFrame>\n );\n};\n","import { routeKeyOf, type ModelDefinition, type SchemaDefinition } from '@shapio/schema';\nimport { Link } from '@tanstack/react-router';\nimport { ArrowUpRight } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { CopyButton } from '@/components/CopyButton';\nimport { PageHeader } from '@/components/PageHeader';\nimport { Panel } from '@/components/Panel';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { graphqlSdl, restEndpoints, type RestEndpoint } from '@/features/Develop/Schema/helpers/shapes';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\n\ntype ApiProps = { schema: ContentSchema; model: ModelDefinition };\n\ntype EndpointListProps = { title: string; endpoints: readonly RestEndpoint[] };\n\nconst EndpointList = ({ title, endpoints }: EndpointListProps) => (\n <Panel title={title} flush>\n <ul className=\"divide-y\">\n {endpoints.map((endpoint) => (\n <li key={`${endpoint.method} ${endpoint.path}`} className=\"flex items-center gap-3 px-5 py-2.5\">\n <Badge variant=\"outline\" className=\"w-16 justify-center font-mono\">\n {endpoint.method}\n </Badge>\n <code className=\"min-w-0 flex-1 truncate font-mono text-sm\">{endpoint.path}</code>\n <CopyButton value={endpoint.path} />\n </li>\n ))}\n </ul>\n </Panel>\n);\n\n/** What the place looks like to code: its REST endpoints and GraphQL type, from the live registry. */\nexport const Api = ({ schema, model }: ApiProps) => {\n const { t } = useTranslation();\n const lookup = useMemo(\n () => new Map<string, SchemaDefinition>([...schema.models, ...schema.components]),\n [schema],\n );\n const endpoints = restEndpoints(model);\n return (\n <>\n <PageHeader\n title={model.label}\n meta={t('place.api.meta', { apiKey: model.apiKey, routeKey: routeKeyOf(model) })}\n actions={\n <Button asChild variant=\"outline\">\n <Link to=\"/api-explorer\">\n {t('place.api.explorer')}\n <ArrowUpRight aria-hidden=\"true\" />\n </Link>\n </Button>\n }\n />\n <div className=\"grid min-w-0 gap-6 xl:grid-cols-2 xl:items-start\">\n <div className=\"min-w-0 space-y-6\">\n <EndpointList\n title={t('place.api.delivery')}\n endpoints={endpoints.filter((endpoint) => endpoint.scope === 'delivery')}\n />\n <EndpointList\n title={t('place.api.admin')}\n endpoints={endpoints.filter((endpoint) => endpoint.scope === 'admin')}\n />\n </div>\n <Panel title={t('place.api.graphql')} actions={<CopyButton value={graphqlSdl(model, lookup)} />}>\n <pre\n // Wide SDL scrolls sideways: the block is a Tab stop so the keyboard can scroll it too.\n tabIndex={0}\n aria-label={t('place.api.graphqlSchema', { place: model.label })}\n className=\"overflow-x-auto rounded-lg bg-muted p-4 font-mono text-xs leading-relaxed outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n >\n {graphqlSdl(model, lookup)}\n </pre>\n </Panel>\n </div>\n </>\n );\n};\n","import { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport { cn } from '@/helpers/cn';\n\ntype PagePagerProps = {\n /** 1-based. */\n page: number;\n pageSize: number;\n total: number;\n /** Choices for the page-size select; omit to hide it. */\n pageSizes?: readonly number[];\n onPageChange: (page: number) => void;\n onPageSizeChange?: (pageSize: number) => void;\n className?: string;\n};\n\n/** Paging for page-numbered lists with a known total: \"26–50 of 112\", page size, previous/next. */\nexport const PagePager = ({\n page,\n pageSize,\n total,\n pageSizes,\n onPageChange,\n onPageSizeChange,\n className,\n}: PagePagerProps) => {\n const { t } = useTranslation();\n const pageCount = Math.max(Math.ceil(total / pageSize), 1);\n const from = total === 0 ? 0 : (page - 1) * pageSize + 1;\n const to = Math.min(page * pageSize, total);\n return (\n <nav\n aria-label={t('common.pagination')}\n className={cn('flex flex-wrap items-center justify-between gap-3 text-sm', className)}\n >\n <p className=\"text-muted-foreground tabular-nums\" aria-live=\"polite\">\n {t('common.pageRange', { from, to, total })}\n </p>\n <div className=\"flex items-center gap-2\">\n {pageSizes && onPageSizeChange ? (\n <Select value={String(pageSize)} onValueChange={(value) => onPageSizeChange(Number(value))}>\n <SelectTrigger size=\"sm\" className=\"h-8 w-32\" aria-label={t('common.rowsPerPage')}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {pageSizes.map((size) => (\n <SelectItem key={size} value={String(size)}>\n {t('common.perPage', { count: size })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : null}\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t('common.previous')}\n disabled={page <= 1}\n onClick={() => onPageChange(page - 1)}\n >\n <ChevronLeft aria-hidden=\"true\" />\n </Button>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={t('common.next')}\n disabled={page >= pageCount}\n onClick={() => onPageChange(page + 1)}\n >\n <ChevronRight aria-hidden=\"true\" />\n </Button>\n </div>\n </nav>\n );\n};\n","import { Loader2, Send, Trash2, Undo2, X } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { Button } from '@/components/ui/button';\nimport type { BulkAction } from '../hooks/useBulkEntryActions';\n\ntype BulkBarProps = {\n count: number;\n canPublish: boolean;\n canDelete: boolean;\n running: BulkAction | null;\n onAction: (action: BulkAction) => void;\n onClear: () => void;\n};\n\n/**\n * Actions for the selected entries (publish, unpublish in the list's locale, delete) as a pill that floats\n * at the bottom of the list while it scrolls, above the status bar. Delete asks first, above its button.\n */\nexport const BulkBar = ({ count, canPublish, canDelete, running, onAction, onClear }: BulkBarProps) => {\n const { t } = useTranslation();\n const busy = running !== null;\n const icon = (action: BulkAction, Icon: typeof Send) =>\n running === action ? (\n <Loader2 aria-hidden=\"true\" className=\"animate-spin\" />\n ) : (\n <Icon aria-hidden=\"true\" />\n );\n return (\n <div className=\"pointer-events-none sticky bottom-4 z-20 flex justify-center md:bottom-[calc(var(--statusbar-h)+1rem)]\">\n <div\n role=\"region\"\n aria-label={t('place.bulk.label')}\n className=\"pointer-events-auto flex max-w-full flex-wrap items-center justify-center gap-2 rounded-3xl border bg-card py-1.5 pr-1.5 pl-4 shadow-lg\"\n >\n <span className=\"text-sm font-semibold whitespace-nowrap\" aria-live=\"polite\">\n {t('place.bulk.selected', { count })}\n </span>\n {canPublish ? (\n <>\n <Button size=\"sm\" disabled={busy} onClick={() => onAction('publish')}>\n {icon('publish', Send)}\n {t('content.actions.publish')}\n </Button>\n <Button size=\"sm\" variant=\"outline\" disabled={busy} onClick={() => onAction('unpublish')}>\n {icon('unpublish', Undo2)}\n {t('content.actions.unpublish')}\n </Button>\n </>\n ) : null}\n {canDelete ? (\n <InlineConfirm\n tone=\"danger\"\n side=\"top\"\n align=\"center\"\n title={t('place.bulk.deleteTitle', { count })}\n description={t('place.bulk.deleteDescription')}\n confirmLabel={t('common.delete')}\n onConfirm={() => onAction('delete')}\n trigger={\n <Button size=\"sm\" variant=\"destructive-ghost\" disabled={busy}>\n {icon('delete', Trash2)}\n {t('common.delete')}\n </Button>\n }\n />\n ) : null}\n <Button\n size=\"icon-sm\"\n variant=\"ghost\"\n disabled={busy}\n aria-label={t('place.bulk.clear')}\n onClick={onClear}\n >\n <X aria-hidden=\"true\" />\n </Button>\n </div>\n </div>\n );\n};\n","import { useTranslation } from 'react-i18next';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { cn } from '@/helpers/cn';\n\ntype SelectAllProps = {\n ids: readonly string[];\n selected: ReadonlySet<string>;\n onSelectChange: (ids: string[], checked: boolean) => void;\n className?: string;\n};\n\n/** \"Select all entries on this page\" above a list without a table header (cards, phone rows). */\nexport const SelectAll = ({ ids, selected, onSelectChange, className }: SelectAllProps) => {\n const { t } = useTranslation();\n const all = ids.length > 0 && ids.every((id) => selected.has(id));\n const some = ids.some((id) => selected.has(id));\n return (\n <label className={cn('flex w-fit items-center gap-2 text-sm font-medium', className)}>\n <Checkbox\n checked={all ? true : some ? 'indeterminate' : false}\n onCheckedChange={(checked) => onSelectChange([...ids], checked === true)}\n />\n {t('place.list.selectAll')}\n </label>\n );\n};\n","import type { MediaAsset } from '@shapio/client';\nimport { isRecord } from '@/fields/helpers/values';\n\n/** A cover field's value in an admin list row: the asset view, or undefined when empty or not readable. */\nexport const coverAssetOf = (value: unknown): MediaAsset | undefined =>\n isRecord(value) &&\n typeof value.id === 'string' &&\n typeof value.mimeType === 'string' &&\n Array.isArray(value.variants)\n ? (value as MediaAsset)\n : undefined;\n","import type { PresencePerson } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { AvatarGroup, AvatarGroupCount } from '@/components/ui/avatar';\nimport { UserAvatar } from '@/components/UserAvatar';\nimport { MAX_ROW_PRESENCE } from '../constants';\n\ntype PresenceProps = { people: readonly PresencePerson[] };\n\n/** Small avatars of the people editing an entry right now (information only; nothing is locked). */\nexport const Presence = ({ people }: PresenceProps) => {\n const { t } = useTranslation();\n if (people.length === 0) {\n return null;\n }\n const names = [...new Set(people.map((person) => person.name))];\n const label = t('place.presence.editing', { names: names.join(', '), count: names.length });\n const shown = names.slice(0, MAX_ROW_PRESENCE);\n return (\n <span className=\"inline-flex shrink-0 items-center\" title={label}>\n <AvatarGroup aria-hidden=\"true\">\n {shown.map((name) => (\n <UserAvatar key={name} name={name} size=\"sm\" />\n ))}\n {names.length > shown.length ? (\n <AvatarGroupCount className=\"text-2xs\">+{names.length - shown.length}</AvatarGroupCount>\n ) : null}\n </AvatarGroup>\n <span className=\"sr-only\">{label}</span>\n </span>\n );\n};\n","import type { EntryStatus } from '@shapio/client';\nimport { Link } from '@tanstack/react-router';\nimport { Copy, Eye, MoreHorizontal, Pencil, Send, SquarePen, Trash2, Undo2 } from 'lucide-react';\nimport { useRef, 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 DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { cn } from '@/helpers/cn';\nimport type { usePlacePermissions } from '../hooks/usePlacePermissions';\nimport type { useRowActions } from '../hooks/useRowActions';\n\ntype RowActionsProps = {\n modelKey: string;\n entry: { id: string; status: EntryStatus; locale: string; version: number };\n /** The entry's title, for the buttons' names and the confirmations. */\n label: string;\n locale: string | null;\n /** The locale's name for \"Goes live in English\"; null for models that aren't localized. */\n localeLabel: string | null;\n permissions: ReturnType<typeof usePlacePermissions>;\n actions: ReturnType<typeof useRowActions>;\n onPreview: (entryId: string) => void;\n /** Opens the row's quick edit (models with properties, with the update permission). */\n onQuickEdit?: () => void;\n /** DOM id of the menu button (focus returns there when the row's quick edit closes). */\n moreId?: string;\n /**\n * `inline`: Edit and Publish as buttons beside the menu, revealed on hover/focus from md up. `menu`: one\n * always-visible menu button holding every action (phone rows).\n */\n layout?: 'inline' | 'menu';\n className?: string;\n};\n\ntype Confirming = 'publish' | 'delete';\n\n/**\n * A row's quick actions: Edit, Publish or Unpublish (asks inline), Quick edit, Preview, Duplicate and Delete\n * (asks inline). Confirmations opened from the menu are anchored to the menu button.\n */\nexport const RowActions = ({\n modelKey,\n entry,\n label,\n locale,\n localeLabel,\n permissions,\n actions,\n onPreview,\n onQuickEdit,\n moreId,\n layout = 'inline',\n className,\n}: RowActionsProps) => {\n const { t } = useTranslation();\n // The last confirmation asked for stays as `confirming` while it animates out, so its text doesn't change.\n const [confirming, setConfirming] = useState<Confirming>('delete');\n const [confirmOpen, setConfirmOpen] = useState(false);\n const ask = (kind: Confirming) => {\n setConfirming(kind);\n setConfirmOpen(true);\n };\n // Confirmations and Quick edit move focus elsewhere (the popover, the first field): the menu must not\n // take it back to its button as it closes.\n const handingOff = useRef(false);\n const handOff = (run: () => void) => () => {\n handingOff.current = true;\n run();\n };\n const inline = layout === 'inline';\n const live = entry.status === 'published';\n const publishConfirm = {\n tone: 'default' as const,\n title: t(live ? 'place.actions.unpublishTitle' : 'place.actions.publishTitle', { entry: label }),\n description: localeLabel\n ? t(live ? 'place.actions.unpublishLocaleDescription' : 'place.actions.publishLocaleDescription', {\n locale: localeLabel,\n })\n : t(live ? 'place.actions.unpublishDescription' : 'place.actions.publishDescription'),\n confirmLabel: t(live ? 'content.actions.unpublish' : 'content.actions.publish'),\n pendingLabel: t(live ? 'place.actions.unpublishing' : 'place.actions.publishing'),\n onConfirm: () => (live ? actions.unpublish(entry.id, label) : actions.publish(entry, label)),\n };\n const deleteConfirm = {\n tone: 'danger' as const,\n title: t('place.actions.deleteTitle', { entry: label }),\n description: t('place.actions.deleteDescription'),\n confirmLabel: t('common.delete'),\n onConfirm: () => actions.remove(entry.id, label),\n };\n const editLink = {\n to: '/content/$modelKey/$entryId',\n params: { modelKey, entryId: entry.id },\n search: locale ? { locale } : {},\n } as const;\n const PublishIcon = live ? Undo2 : Send;\n return (\n <div\n className={cn(\n 'flex items-center justify-end gap-0.5',\n inline &&\n 'md:opacity-0 md:group-focus-within/row:opacity-100 md:group-hover/row:opacity-100 md:has-[[aria-expanded=true]]:opacity-100',\n className,\n )}\n >\n {inline ? (\n <Button asChild variant=\"ghost\" size=\"icon-sm\" aria-label={t('place.actions.edit', { entry: label })}>\n <Link {...editLink}>\n <Pencil aria-hidden=\"true\" />\n </Link>\n </Button>\n ) : null}\n {inline && permissions.canPublish ? (\n <InlineConfirm\n {...publishConfirm}\n trigger={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t(live ? 'place.actions.unpublish' : 'place.actions.publish', { entry: label })}\n >\n <PublishIcon aria-hidden=\"true\" />\n </Button>\n }\n />\n ) : null}\n <DropdownMenu>\n <InlineConfirm\n {...(confirming === 'publish' ? publishConfirm : deleteConfirm)}\n open={confirmOpen}\n onOpenChange={setConfirmOpen}\n >\n <DropdownMenuTrigger asChild>\n <Button\n id={moreId}\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('place.actions.more', { entry: label })}\n >\n <MoreHorizontal aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n </InlineConfirm>\n <DropdownMenuContent\n align=\"end\"\n onCloseAutoFocus={(event) => {\n if (handingOff.current) {\n handingOff.current = false;\n event.preventDefault();\n }\n }}\n >\n {inline ? null : (\n <DropdownMenuItem asChild>\n <Link {...editLink}>\n <Pencil aria-hidden=\"true\" />\n {t('common.edit')}\n </Link>\n </DropdownMenuItem>\n )}\n {!inline && permissions.canPublish ? (\n <DropdownMenuItem onSelect={handOff(() => ask('publish'))}>\n <PublishIcon aria-hidden=\"true\" />\n {t(live ? 'content.actions.unpublish' : 'content.actions.publish')}\n </DropdownMenuItem>\n ) : null}\n {onQuickEdit ? (\n <DropdownMenuItem onSelect={handOff(onQuickEdit)}>\n <SquarePen aria-hidden=\"true\" />\n {t('place.actions.quickEdit')}\n </DropdownMenuItem>\n ) : null}\n <DropdownMenuItem onSelect={() => onPreview(entry.id)}>\n <Eye aria-hidden=\"true\" />\n {t('place.actions.preview')}\n </DropdownMenuItem>\n {permissions.canCreate ? (\n <DropdownMenuItem\n disabled={actions.duplicating}\n onSelect={() => actions.duplicate(entry.id, label)}\n >\n <Copy aria-hidden=\"true\" />\n {t('content.actions.duplicate')}\n </DropdownMenuItem>\n ) : null}\n {permissions.canDelete ? (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\" onSelect={handOff(() => ask('delete'))}>\n <Trash2 aria-hidden=\"true\" />\n {t('common.delete')}\n </DropdownMenuItem>\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n};\n","import type { AdminEntryListItem, PresencePerson } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { Link } from '@tanstack/react-router';\nimport { ImageOff } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { RowTitle } from '@/components/RowTitle';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Thumbnail } from '@/features/Media/Thumbnail';\nimport { cn } from '@/helpers/cn';\nimport { formatDateTime, formatRelativeTime } from '@/helpers/formatDate';\nimport { EntryStatusChip } from '../../../EntryStatusChip';\nimport { coverAssetOf } from '../../helpers/cover';\nimport { Presence } from '../../Presence';\nimport type { RowContext } from '../../Row';\nimport { RowActions } from '../../RowActions';\n\ntype CardProps = {\n context: RowContext;\n cover: FieldDefinition;\n item: AdminEntryListItem;\n label: string;\n selected: boolean;\n people: readonly PresencePerson[];\n onSelectChange: (checked: boolean) => void;\n};\n\n/** One entry as a tile: its cover, title, status and last update; tick box and actions on hover. */\nexport const Card = ({ context, cover, item, label, selected, people, onSelectChange }: CardProps) => {\n const { t } = useTranslation();\n const { model, locale } = context;\n const asset = coverAssetOf(item.data[cover.apiKey]);\n return (\n <li\n className={cn(\n 'group/row relative flex min-w-0 flex-col overflow-hidden rounded-xl border bg-card transition-colors focus-within:border-input hover:border-input',\n selected && 'border-primary focus-within:border-primary hover:border-primary',\n )}\n >\n {asset ? (\n <Thumbnail asset={asset} className=\"aspect-video w-full\" />\n ) : (\n <div className=\"flex aspect-video w-full items-center justify-center bg-muted text-muted-foreground\">\n <ImageOff aria-hidden=\"true\" className=\"size-6\" />\n </div>\n )}\n <Checkbox\n checked={selected}\n aria-label={t('place.list.select', { entry: label })}\n className={cn(\n 'absolute top-3 left-3 bg-card',\n !selected && 'md:opacity-0 md:group-focus-within/row:opacity-100 md:group-hover/row:opacity-100',\n )}\n onCheckedChange={(checked) => onSelectChange(checked === true)}\n />\n <div className=\"flex min-w-0 flex-1 flex-col gap-2 p-4\">\n <div className=\"flex min-w-0 items-start justify-between gap-2\">\n <RowTitle asChild className=\"line-clamp-2 min-w-0\">\n <Link\n to=\"/content/$modelKey/$entryId\"\n params={{ modelKey: model.apiKey, entryId: item.id }}\n search={locale ? { locale } : {}}\n >\n {label}\n </Link>\n </RowTitle>\n <Presence people={people} />\n </div>\n <div className=\"mt-auto flex flex-wrap items-center justify-between gap-2\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <EntryStatusChip status={item.status} size=\"sm\" />\n <time\n dateTime={item.updatedAt}\n title={formatDateTime(item.updatedAt)}\n className=\"truncate text-meta text-muted-foreground\"\n >\n {formatRelativeTime(item.updatedAt)}\n </time>\n </div>\n <RowActions\n modelKey={model.apiKey}\n entry={item}\n label={label}\n locale={locale}\n localeLabel={locale ? context.localeLabelOf(locale) : null}\n permissions={context.permissions}\n actions={context.actions}\n onPreview={context.onPreview}\n />\n </div>\n </div>\n </li>\n );\n};\n","import type { AdminEntryListItem, PresencePerson } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { labelOf } from '@/fields/helpers/titles';\nimport type { RowContext } from '../Row';\nimport { SelectAll } from '../SelectAll';\nimport { Card } from './Card';\n\ntype CardsProps = {\n context: RowContext;\n cover: FieldDefinition;\n items: readonly AdminEntryListItem[];\n selected: ReadonlySet<string>;\n presence: ReadonlyMap<string, readonly PresencePerson[]>;\n onSelectChange: (ids: string[], checked: boolean) => void;\n};\n\nconst NOBODY: readonly PresencePerson[] = [];\n\n/** A place's entries as cover tiles (models with a cover field). */\nexport const Cards = ({ context, cover, items, selected, presence, onSelectChange }: CardsProps) => {\n const { t } = useTranslation();\n return (\n <div>\n <SelectAll\n ids={items.map((item) => item.id)}\n selected={selected}\n onSelectChange={onSelectChange}\n className=\"px-4 pt-4\"\n />\n <ul\n aria-label={t('place.view.cardsLabel', { place: context.model.label })}\n className=\"grid grid-cols-1 gap-4 p-4 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4\"\n >\n {items.map((item) => (\n <Card\n key={item.id}\n context={context}\n cover={cover}\n item={item}\n label={labelOf(context.model, item, t('content.untitled'))}\n selected={selected.has(item.id)}\n people={presence.get(item.id) ?? NOBODY}\n onSelectChange={(checked) => onSelectChange([item.id], checked)}\n />\n ))}\n </ul>\n </div>\n );\n};\n","import type { ContentFilter, ContentFilterOperator } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { fromDateTimeInput } from '@/fields/helpers/dates';\n\n/**\n * Which filter operators the list offers per field. Mirrors the content compiler's allowlist\n * (`apps/api/src/content/compiler/operators.ts`), which stays the enforcement: equality on every scalar\n * type; ranges only on filterable or sortable fields (they need an index); text matches only on\n * filterable ones.\n */\ntype Family = 'text' | 'temporal' | 'number' | 'boolean' | 'list' | 'reference' | 'none';\n\nconst familyOf = (field: FieldDefinition): Family => {\n switch (field.type) {\n case 'string':\n case 'text':\n case 'slug':\n case 'email':\n case 'url':\n case 'uid':\n return 'text';\n case 'enum':\n return field.settings.multiple ? 'list' : 'text';\n case 'date':\n case 'datetime':\n case 'time':\n return 'temporal';\n case 'number':\n case 'integer':\n case 'decimal':\n case 'biginteger':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'relation':\n case 'media':\n return 'reference';\n default:\n return 'none';\n }\n};\n\nconst EQUALITY: readonly ContentFilterOperator[] = ['$eq', '$ne', '$in', '$nin', '$null', '$notNull'];\nconst RANGE: readonly ContentFilterOperator[] = ['$lt', '$lte', '$gt', '$gte'];\nconst TEXT_MATCH: readonly ContentFilterOperator[] = [\n '$containsi',\n '$contains',\n '$notContains',\n '$startsWith',\n '$endsWith',\n];\n\nconst BY_FAMILY: Readonly<Record<Family, readonly ContentFilterOperator[]>> = {\n text: [...EQUALITY, ...RANGE, ...TEXT_MATCH],\n temporal: [...EQUALITY, ...RANGE],\n number: [...EQUALITY, ...RANGE],\n boolean: ['$eq', '$ne', '$null', '$notNull'],\n list: EQUALITY,\n reference: EQUALITY,\n none: [],\n};\n\n/** System attributes every entry can be filtered and sorted by. */\nexport const SYSTEM_FILTER_FIELDS = ['createdAt', 'updatedAt'] as const;\nconst SYSTEM_OPERATORS: readonly ContentFilterOperator[] = ['$eq', '$ne', '$lt', '$lte', '$gt', '$gte'];\n\nexport const operatorsFor = (\n field: FieldDefinition | 'createdAt' | 'updatedAt',\n): readonly ContentFilterOperator[] => {\n if (typeof field === 'string') {\n return SYSTEM_OPERATORS;\n }\n return BY_FAMILY[familyOf(field)].filter(\n (operator) =>\n (!RANGE.includes(operator) || field.filterable || field.sortable) &&\n (!TEXT_MATCH.includes(operator) || field.filterable),\n );\n};\n\n/** Fields that can be sorted by: sortable scalars (an expression index exists for them). */\nexport const isSortableField = (field: FieldDefinition) =>\n field.sortable && !['none', 'list', 'reference'].includes(familyOf(field));\n\nexport const OPERATOR_LABEL_KEYS = {\n $eq: 'content.filters.operators.eq',\n $ne: 'content.filters.operators.ne',\n $in: 'content.filters.operators.in',\n $nin: 'content.filters.operators.nin',\n $lt: 'content.filters.operators.lt',\n $lte: 'content.filters.operators.lte',\n $gt: 'content.filters.operators.gt',\n $gte: 'content.filters.operators.gte',\n $contains: 'content.filters.operators.contains',\n $notContains: 'content.filters.operators.notContains',\n $containsi: 'content.filters.operators.containsi',\n $startsWith: 'content.filters.operators.startsWith',\n $endsWith: 'content.filters.operators.endsWith',\n $null: 'content.filters.operators.null',\n $notNull: 'content.filters.operators.notNull',\n} as const satisfies Record<ContentFilterOperator, string>;\n\n/** Operators that need no value. */\nexport const isValueless = (operator: ContentFilterOperator) =>\n operator === '$null' || operator === '$notNull';\n\nexport type ListFilter = { field: string; operator: ContentFilterOperator; value?: string };\n\n/** The list's filter rows → the API's filter tree (rows on the same field are combined with `$and`). */\nexport const toContentFilter = (filters: readonly ListFilter[]): ContentFilter | undefined => {\n if (filters.length === 0) {\n return undefined;\n }\n const conditions = filters.map((filter): ContentFilter => {\n const value = isValueless(filter.operator)\n ? true\n : filter.operator === '$in' || filter.operator === '$nin'\n ? (filter.value ?? '')\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean)\n : (SYSTEM_FILTER_FIELDS as readonly string[]).includes(filter.field)\n ? // System timestamps are typed in local time and compared as UTC instants.\n (fromDateTimeInput(filter.value ?? '', false) ?? filter.value ?? '')\n : (filter.value ?? '');\n return { [filter.field]: { [filter.operator]: value } };\n });\n return conditions.length === 1 ? conditions[0] : { $and: conditions };\n};\n","import type { EntryAuthor } from '@shapio/client';\nimport { UserAvatar } from '@/components/UserAvatar';\nimport { cn } from '@/helpers/cn';\n\ntype AuthorProps = { author: EntryAuthor | null | undefined; className?: string };\n\n/** Who created the entry: avatar and name (nothing for entries made by tokens, app users or imports). */\nexport const Author = ({ author, className }: AuthorProps) =>\n author ? (\n <span className={cn('inline-flex min-w-0 items-center gap-2', className)}>\n <UserAvatar name={author.name} size=\"sm\" />\n <span className=\"truncate\">{author.name}</span>\n </span>\n ) : null;\n","import type { FieldDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { summarizeValue } from '@/fields/helpers/summary';\nimport { isEmptyValue, toList } from '@/fields/helpers/values';\nimport { formatDateTime } from '@/helpers/formatDate';\n\ntype CellProps = { field: FieldDefinition; value: unknown };\n\n/** One field's value in the list, as short readable text (counts for lists, Yes/No for booleans). */\nexport const Cell = ({ field, value }: CellProps) => {\n const { t } = useTranslation();\n if (isEmptyValue(value)) {\n return <span className=\"text-muted-foreground\">{t('place.list.emptyValue')}</span>;\n }\n switch (field.type) {\n case 'boolean':\n return <>{value === true ? t('content.fields.yes') : t('content.fields.no')}</>;\n case 'datetime':\n return <>{formatDateTime(typeof value === 'string' ? value : null)}</>;\n case 'media':\n case 'relation':\n case 'component':\n case 'dynamiczone':\n return <>{t('place.list.itemCount', { count: toList(value).length })}</>;\n default:\n return <span className=\"line-clamp-2\">{summarizeValue(field, value)}</span>;\n }\n};\n","import type { PresencePerson } from '@shapio/client';\nimport { Link } from '@tanstack/react-router';\nimport { RowTitle } from '@/components/RowTitle';\nimport { cn } from '@/helpers/cn';\nimport { Presence } from '../Presence';\n\ntype EntryTitleProps = {\n modelKey: string;\n entryId: string;\n label: string;\n /** Carried into the document link; null for models that aren't localized. */\n locale: string | null;\n people: readonly PresencePerson[];\n className?: string;\n};\n\n/** A row's title: the link to the document, then who is editing it right now. */\nexport const EntryTitle = ({ modelKey, entryId, label, locale, people, className }: EntryTitleProps) => (\n <span className={cn('flex min-w-0 items-center gap-2', className)}>\n <RowTitle asChild className=\"min-w-0 truncate\">\n <Link to=\"/content/$modelKey/$entryId\" params={{ modelKey, entryId }} search={locale ? { locale } : {}}>\n {label}\n </Link>\n </RowTitle>\n <Presence people={people} />\n </span>\n);\n","/** The menu button's DOM id for a row (quick edit returns focus there). */\nexport const rowMoreId = (entryId: string) => `row-more-${entryId}`;\n","import type { AdminEntryListItem } from '@shapio/client';\nimport type { RowContext } from '../Row';\nimport { rowMoreId } from './rowIds';\n\n/** The table's columns besides the field columns: tick box, status, author, (locale), updated, actions. */\nexport const fixedColumnCount = (context: RowContext) =>\n 5 + (context.titleColumn ? 0 : 1) + (context.locale ? 1 : 0);\n\n/** The row's quick actions (shared by table rows and phone rows). */\nexport const rowActionsProps = (context: RowContext, item: AdminEntryListItem, label: string) => {\n const { model, locale, quickEdit } = context;\n // A row read from a fallback locale has no version in this locale yet: the document creates it.\n const editable = quickEdit !== null && (locale === null || item.locale === locale);\n return {\n modelKey: model.apiKey,\n entry: item,\n label,\n locale,\n localeLabel: locale ? context.localeLabelOf(locale) : null,\n permissions: context.permissions,\n actions: context.actions,\n onPreview: context.onPreview,\n onQuickEdit: editable ? () => quickEdit.open(item.id) : undefined,\n moreId: rowMoreId(item.id),\n };\n};\n","import type { AdminEntryListItem, EntryStatus } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { cn } from '@/helpers/cn';\nimport { ENTRY_STATUS_LABEL_KEYS } from '../../helpers/entryStatus';\nimport { MAX_ROW_LOCALES } from '../constants';\n\nconst FLAG_CLASSES = {\n draft: 'bg-muted text-muted-foreground',\n modified: 'bg-warning-muted text-warning',\n published: 'bg-success-muted text-success',\n} as const satisfies Record<EntryStatus, string>;\n\ntype LocaleFlagsProps = {\n item: Pick<AdminEntryListItem, 'id' | 'locale' | 'status' | 'locales'>;\n /** The locale the list is read in (outlined). */\n current: string;\n labelOf: (code: string) => string;\n};\n\n/**\n * The locales an entry has, each tinted by its state (published, changed, draft) and named with it for\n * assistive technology. The list's locale is outlined; a row read from a fallback locale shows that one.\n */\nexport const LocaleFlags = ({ item, current, labelOf }: LocaleFlagsProps) => {\n const { t } = useTranslation();\n const locales = item.locales ?? [{ locale: item.locale, status: item.status }];\n const shown = locales.slice(0, MAX_ROW_LOCALES);\n return (\n <ul aria-label={t('place.list.localesOf')} className=\"flex items-center gap-1\">\n {shown.map(({ locale, status }) => {\n const description = t('place.list.localeState', {\n locale: labelOf(locale),\n status: t(ENTRY_STATUS_LABEL_KEYS[status]),\n });\n return (\n <li\n key={locale}\n title={description}\n className={cn(\n 'inline-flex h-5 items-center rounded-full px-1.5 font-mono text-2xs font-semibold',\n FLAG_CLASSES[status],\n locale === current && 'ring-1 ring-input',\n )}\n >\n <span aria-hidden=\"true\">{locale}</span>\n <span className=\"sr-only\">{description}</span>\n </li>\n );\n })}\n {locales.length > shown.length ? (\n <li className=\"text-2xs font-semibold text-muted-foreground\">+{locales.length - shown.length}</li>\n ) : null}\n </ul>\n );\n};\n","import {\n effectiveFormLayout,\n effectiveLayout,\n entryLayoutOf,\n isCanvasEligible,\n type FieldDefinition,\n type ModelDefinition,\n} from '@shapio/schema';\n\n/** Values too large for a row's quick edit; they are edited in the document. */\nconst DOCUMENT_ONLY_TYPES: ReadonlySet<string> = new Set([\n 'richtext',\n 'component',\n 'dynamiczone',\n 'json',\n 'code',\n]);\n\n/**\n * What a row's quick edit offers, without the values that need the whole entry. A document: the inline title,\n * then the properties strip (the configured one, else every property and every non-block field placed in the\n * document). A form: every live field in form order.\n */\nexport const quickEditFieldsOf = (model: ModelDefinition): FieldDefinition[] => {\n if (entryLayoutOf(model) === 'form') {\n return effectiveFormLayout(model)\n .sections.flatMap((section) => section.fields)\n .filter((field) => !DOCUMENT_ONLY_TYPES.has(field.type));\n }\n const layout = effectiveLayout(model);\n const title = layout.titleInline && layout.title ? [layout.title] : [];\n const placed = layout.canvas.filter((field) => !isCanvasEligible(field));\n return [...title, ...(layout.strip ?? [...layout.properties, ...placed])].filter(\n (field) => !DOCUMENT_ONLY_TYPES.has(field.type),\n );\n};\n","import type { AdminEntry } from '@shapio/client';\nimport type { FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useStore } from 'zustand';\nimport { useSaveEntry } from '@/api/content';\nimport { FormError } from '@/components/FormError';\nimport { InlineConfirm } from '@/components/InlineConfirm';\nimport { SubmitButton } from '@/components/SubmitButton';\nimport { Button } from '@/components/ui/button';\nimport { UnsavedChangesGuard } from '@/components/UnsavedChangesGuard';\nimport { EntryFields } from '@/fields/form/EntryFields';\nimport { FieldsProvider } from '@/fields/form/FieldsProvider';\nimport { refuseUnparsed } from '@/fields/form/refuseUnparsed';\nimport { selectDirtyKeys } from '@/fields/form/store';\nimport { contentIssuesOf } from '@/fields/helpers/apiErrors';\nimport { buildPatch } from '@/fields/helpers/formValues';\nimport type { FormValues } from '@/fields/helpers/values';\nimport { useEntrySetup } from '../../../Entry/hooks/useEntrySetup';\nimport type { ContentSchema } from '../../../hooks/useContentSchema';\n\ntype FormProps = {\n schema: ContentSchema;\n model: ModelDefinition;\n entry: AdminEntry;\n fields: readonly FieldDefinition[];\n label: string;\n locale: string | null;\n /** Unsaved changes from before a remount (the list switched layouts). */\n carry: FormValues | undefined;\n onDraftChange: (values: FormValues | undefined) => void;\n onClose: () => void;\n};\n\n/**\n * The quick edit form: the row's properties with the same field editors as the document, saved as one\n * revision (fully validated, with the version guard). Leaving with changes asks first.\n */\nexport const Form = ({\n schema,\n model,\n entry,\n fields,\n label,\n locale,\n carry,\n onDraftChange,\n onClose,\n}: FormProps) => {\n const { t } = useTranslation();\n const save = useSaveEntry(model.apiKey);\n const [error, setError] = useState<unknown>(null);\n const setup = useEntrySetup({\n schema,\n model,\n mode: { kind: 'edit', entry },\n locale,\n carry,\n disabled: save.isPending,\n readOnly: false,\n });\n const { store } = setup;\n const environment = useMemo(() => ({ ...setup.environment, idPrefix: 'quick-' }), [setup.environment]);\n const dirty = useStore(store, (state) => selectDirtyKeys(state).length > 0);\n const formRef = useRef<HTMLFormElement>(null);\n useEffect(\n () =>\n store.subscribe((state) => {\n const keys = selectDirtyKeys(state);\n onDraftChange(\n keys.length > 0 ? Object.fromEntries(keys.map((key) => [key, state.values[key]])) : undefined,\n );\n }),\n [store, onDraftChange],\n );\n useEffect(() => {\n formRef.current?.querySelector<HTMLElement>('input, textarea, [role=\"combobox\"], button')?.focus();\n }, []);\n\n const submit = async () => {\n if (refuseUnparsed(store)) {\n return;\n }\n store.getState().reveal();\n const state = store.getState();\n const keys = selectDirtyKeys(state);\n if (keys.length === 0) {\n onClose();\n return;\n }\n setError(null);\n try {\n await save.mutateAsync({\n id: entry.id,\n input: {\n ...(locale ? { locale } : {}),\n expectedVersion: entry.version,\n data: buildPatch(state.values, keys),\n },\n });\n toast.success(t('place.quickEdit.saved', { entry: label }));\n onClose();\n } catch (failure) {\n // Logged by the mutation cache; field issues show on the fields, anything else above the buttons.\n const issues = contentIssuesOf(failure);\n store.getState().setIssues(issues);\n setError(issues.length > 0 ? null : failure);\n }\n };\n const cancel = (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={dirty ? undefined : onClose}>\n {t('common.cancel')}\n </Button>\n );\n return (\n <form\n ref={formRef}\n noValidate\n aria-label={t('place.quickEdit.label', { entry: label })}\n className=\"space-y-5\"\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape' && !dirty && !event.defaultPrevented) {\n onClose();\n }\n }}\n >\n <UnsavedChangesGuard when={dirty} />\n <FieldsProvider environment={environment} store={store}>\n <EntryFields fields={fields} />\n </FieldsProvider>\n {error ? <FormError error={error} /> : null}\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {dirty ? (\n <InlineConfirm\n tone=\"danger\"\n side=\"top\"\n title={t('place.quickEdit.discardTitle')}\n description={t('place.quickEdit.discardDescription')}\n confirmLabel={t('place.quickEdit.discard')}\n onConfirm={onClose}\n trigger={cancel}\n />\n ) : (\n cancel\n )}\n <SubmitButton size=\"sm\" pending={save.isPending} pendingLabel={t('common.saving')}>\n {t('place.quickEdit.save')}\n </SubmitButton>\n </div>\n {setup.mediaDialog}\n </form>\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useMemo } from 'react';\nimport { useEntry } from '@/api/content';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { quickEditFieldsOf } from '../helpers/quickEditFields';\nimport type { RowContext } from '../Row';\nimport { Form } from './Form';\n\ntype QuickEditProps = {\n quickEdit: NonNullable<RowContext['quickEdit']>;\n model: ModelDefinition;\n entryId: string;\n label: string;\n locale: string | null;\n onClose: () => void;\n};\n\n/**\n * A row's quick edit, shown right under the row (a table row or a phone row): the entry's properties with\n * the document's field editors, without opening the document.\n */\nexport const QuickEdit = ({ quickEdit, model, entryId, label, locale, onClose }: QuickEditProps) => {\n const entry = useEntry(model.apiKey, entryId, locale ?? undefined);\n const fields = useMemo(() => quickEditFieldsOf(model), [model]);\n if (entry.isPending) {\n return <LoadingState rows={2} />;\n }\n if (entry.isError) {\n return <ErrorState size=\"panel\" error={entry.error} onRetry={() => void entry.refetch()} />;\n }\n return (\n <Form\n schema={quickEdit.schema}\n carry={quickEdit.getDraft()}\n onDraftChange={quickEdit.setDraft}\n model={model}\n entry={entry.data}\n fields={fields}\n label={label}\n locale={locale}\n onClose={onClose}\n />\n );\n};\n","import { cn } from '@/helpers/cn';\nimport { formatDateTime, formatRelativeTime } from '@/helpers/formatDate';\n\ntype UpdatedProps = { at: string; className?: string };\n\n/** \"2 hr. ago\", with the full date and time on hover. */\nexport const Updated = ({ at, className }: UpdatedProps) => (\n <time dateTime={at} title={formatDateTime(at)} className={cn('text-muted-foreground', className)}>\n {formatRelativeTime(at)}\n </time>\n);\n","import type { AdminEntryListItem, PresencePerson } from '@shapio/client';\nimport type { FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { Fragment } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { TableCell, TableRow } from '@/components/ui/table';\nimport type { FormValues } from '@/fields/helpers/values';\nimport { EntryStatusChip } from '../../EntryStatusChip';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\nimport { Author } from '../Author';\nimport { Cell } from '../Cell';\nimport { EntryTitle } from '../EntryTitle';\nimport { fixedColumnCount, rowActionsProps } from '../helpers/rowContext';\nimport type { usePlacePermissions } from '../hooks/usePlacePermissions';\nimport type { useRowActions } from '../hooks/useRowActions';\nimport { LocaleFlags } from '../LocaleFlags';\nimport { QuickEdit } from '../QuickEdit';\nimport { RowActions } from '../RowActions';\nimport { Updated } from '../Updated';\n\nexport type RowContext = {\n model: ModelDefinition;\n columns: readonly FieldDefinition[];\n /** The title field, when it is one of the columns (it then carries the link). */\n titleColumn: FieldDefinition | undefined;\n /** The locale the list asked for, carried into the editor link; null for models that aren't localized. */\n locale: string | null;\n localeLabelOf: (code: string) => string;\n permissions: ReturnType<typeof usePlacePermissions>;\n actions: ReturnType<typeof useRowActions>;\n onPreview: (entryId: string) => void;\n /** The row whose quick edit is open, and its switches; null where quick edit isn't offered. */\n quickEdit: {\n schema: ContentSchema;\n openId: string | null;\n open: (id: string) => void;\n close: (id: string) => void;\n getDraft: () => FormValues | undefined;\n setDraft: (values: FormValues | undefined) => void;\n } | null;\n};\n\nexport type RowProps = {\n context: RowContext;\n item: AdminEntryListItem;\n label: string;\n selected: boolean;\n people: readonly PresencePerson[];\n onSelectChange: (checked: boolean) => void;\n};\n\n/** One entry: tick box, title link with presence, field columns, status, author, locales, updated, actions. */\nexport const Row = ({ context, item, label, selected, people, onSelectChange }: RowProps) => {\n const { t } = useTranslation();\n const { model, columns, titleColumn, locale, quickEdit } = context;\n const title = (\n <EntryTitle modelKey={model.apiKey} entryId={item.id} label={label} locale={locale} people={people} />\n );\n return (\n <Fragment>\n <TableRow className=\"group/row\" data-state={selected ? 'selected' : undefined}>\n <TableCell className=\"pl-4\">\n <Checkbox\n checked={selected}\n aria-label={t('place.list.select', { entry: label })}\n onCheckedChange={(checked) => onSelectChange(checked === true)}\n />\n </TableCell>\n {titleColumn ? null : <TableCell className=\"max-w-96\">{title}</TableCell>}\n {columns.map((field) => (\n <TableCell key={field.id} className=\"max-w-72 whitespace-normal\">\n {field === titleColumn ? title : <Cell field={field} value={item.data[field.apiKey]} />}\n </TableCell>\n ))}\n <TableCell>\n <EntryStatusChip status={item.status} />\n </TableCell>\n <TableCell className=\"max-w-48\">\n <Author author={item.author} />\n </TableCell>\n {locale ? (\n <TableCell>\n <LocaleFlags item={item} current={locale} labelOf={context.localeLabelOf} />\n </TableCell>\n ) : null}\n <TableCell>\n <Updated at={item.updatedAt} />\n </TableCell>\n <TableCell className=\"pr-4\">\n <RowActions {...rowActionsProps(context, item, label)} />\n </TableCell>\n </TableRow>\n {quickEdit?.openId === item.id ? (\n <TableRow>\n <TableCell\n colSpan={fixedColumnCount(context) + columns.length}\n className=\"h-auto px-4 py-5 whitespace-normal\"\n >\n <QuickEdit\n quickEdit={quickEdit}\n model={model}\n entryId={item.id}\n label={label}\n locale={locale}\n onClose={() => quickEdit.close(item.id)}\n />\n </TableCell>\n </TableRow>\n ) : null}\n </Fragment>\n );\n};\n","import type { ContentSort } from '@shapio/client';\nimport { ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { cn } from '@/helpers/cn';\n\ntype SortHeaderProps = {\n label: string;\n field: string;\n sort: ContentSort | undefined;\n onSortChange: (sort: ContentSort) => void;\n};\n\n/** A column label that sorts by its column (keeps the header's 12px uppercase style). */\nexport const SortHeader = ({ label, field, sort, onSortChange }: SortHeaderProps) => {\n const { t } = useTranslation();\n const active = sort?.field === field ? sort.direction : undefined;\n const Icon = active === 'asc' ? ArrowUp : active === 'desc' ? ArrowDown : ArrowUpDown;\n return (\n <button\n type=\"button\"\n aria-label={t('place.list.sortBy', { field: label })}\n className={cn(\n '-ml-1.5 inline-flex h-7 items-center gap-1 rounded-md px-1.5 tracking-wide uppercase outline-none hover:bg-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50',\n active && 'text-foreground',\n )}\n onClick={() => onSortChange({ field, direction: active === 'asc' ? 'desc' : 'asc' })}\n >\n {label}\n <Icon aria-hidden=\"true\" className={cn('size-3.5', !active && 'opacity-50')} />\n </button>\n );\n};\n","import type { AdminEntryListItem, ContentSort, PresencePerson } from '@shapio/client';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Table, TableBody, TableHead, TableHeader, TableRow } from '@/components/ui/table';\nimport { labelOf } from '@/fields/helpers/titles';\nimport { isSortableField } from '../../helpers/filterOperators';\nimport { Row, type RowContext } from '../Row';\nimport { SortHeader } from './SortHeader';\n\ntype EntryTableProps = {\n context: RowContext;\n items: readonly AdminEntryListItem[];\n sort: ContentSort | undefined;\n selected: ReadonlySet<string>;\n presence: ReadonlyMap<string, readonly PresencePerson[]>;\n onSortChange: (sort: ContentSort) => void;\n onSelectChange: (ids: string[], checked: boolean) => void;\n};\n\nconst NOBODY: readonly PresencePerson[] = [];\n\n/** A place's entries as a table: selectable rows, the chosen field columns, status, locale, last update. */\nexport const EntryTable = ({\n context,\n items,\n sort,\n selected,\n presence,\n onSortChange,\n onSelectChange,\n}: EntryTableProps) => {\n const { t } = useTranslation();\n const { model, columns, titleColumn, locale } = context;\n const allSelected = items.length > 0 && items.every((item) => selected.has(item.id));\n const someSelected = items.some((item) => selected.has(item.id));\n const ariaSort = (field: string) =>\n sort?.field === field ? (sort.direction === 'asc' ? 'ascending' : 'descending') : undefined;\n const header = (field: string, label: string, sortable: boolean): ReactNode =>\n sortable ? <SortHeader label={label} field={field} sort={sort} onSortChange={onSortChange} /> : label;\n return (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-10 pl-4\">\n <Checkbox\n checked={allSelected ? true : someSelected ? 'indeterminate' : false}\n aria-label={t('place.list.selectAll')}\n onCheckedChange={(checked) =>\n onSelectChange(\n items.map((item) => item.id),\n checked === true,\n )\n }\n />\n </TableHead>\n {titleColumn ? null : <TableHead>{t('place.list.entry')}</TableHead>}\n {columns.map((field) => (\n <TableHead key={field.id} aria-sort={ariaSort(field.apiKey)}>\n {header(field.apiKey, field.label, isSortableField(field))}\n </TableHead>\n ))}\n <TableHead>{t('place.list.status')}</TableHead>\n <TableHead>{t('place.list.author')}</TableHead>\n {locale ? <TableHead>{t('place.list.locale')}</TableHead> : null}\n <TableHead aria-sort={ariaSort('updatedAt')}>\n {header('updatedAt', t('place.list.updatedAt'), true)}\n </TableHead>\n <TableHead className=\"w-0 pr-4\">\n <span className=\"sr-only\">{t('common.actions')}</span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {items.map((item) => (\n <Row\n key={item.id}\n context={context}\n item={item}\n label={labelOf(model, item, t('content.untitled'))}\n selected={selected.has(item.id)}\n people={presence.get(item.id) ?? NOBODY}\n onSelectChange={(checked) => onSelectChange([item.id], checked)}\n />\n ))}\n </TableBody>\n </Table>\n );\n};\n","import { X } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\n\ntype FilterChipProps = {\n /** What the chip filters by, e.g. \"Title starts with Co\". */\n children: ReactNode;\n /** Plain text of the chip for the remove button's name. */\n label: string;\n onRemove: () => void;\n};\n\n/** One active filter as a pill with a remove button. */\nexport const FilterChip = ({ children, label, onRemove }: FilterChipProps) => {\n const { t } = useTranslation();\n return (\n <li className=\"inline-flex h-7 max-w-full items-center gap-0.5 rounded-full border bg-muted/60 pr-0.5 pl-3 text-xs font-medium\">\n <span className=\"truncate\">{children}</span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={t('place.filters.removeChip', { filter: label })}\n onClick={onRemove}\n >\n <X aria-hidden=\"true\" />\n </Button>\n </li>\n );\n};\n","import type { FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { SYSTEM_FILTER_FIELDS, type ListFilter } from '../../helpers/filterOperators';\n\nexport const isSystemField = (key: string): key is (typeof SYSTEM_FILTER_FIELDS)[number] =>\n (SYSTEM_FILTER_FIELDS as readonly string[]).includes(key);\n\n/** The live field a filter row targets, or undefined for a system attribute (createdAt, updatedAt). */\nexport const filterFieldOf = (model: ModelDefinition, filter: ListFilter): FieldDefinition | undefined =>\n isSystemField(filter.field)\n ? undefined\n : model.fields.find((field) => !field.deprecated && field.apiKey === filter.field);\n\n/** A relation filter that names one entry (`author is <id>`): its chip shows the entry's title. */\nexport const isEntryFilter = (field: FieldDefinition | undefined, filter: ListFilter) =>\n field?.type === 'relation' && (filter.operator === '$eq' || filter.operator === '$ne');\n\n/** Filters the quick relation chips manage: relation fields that take an equality condition. */\nexport const relationFilterFields = (model: ModelDefinition): FieldDefinition[] =>\n model.fields.filter((field) => !field.deprecated && field.type === 'relation');\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { useEntry } from '@/api/content';\nimport { entryTitle, shortId } from '@/fields/helpers/titles';\nimport { isValueless, OPERATOR_LABEL_KEYS, type ListFilter } from '../../helpers/filterOperators';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\nimport { SYSTEM_LABEL_KEYS } from '../constants';\nimport { filterFieldOf, isEntryFilter, isSystemField } from '../helpers/filterLabels';\n\n/**\n * A filter row in words, split for the chip: \"Title\" \"starts with\" \"Co\". A relation filter naming one entry\n * shows that entry's title (its short ID until it loads).\n */\nexport const useFilterLabel = (schema: ContentSchema, model: ModelDefinition, filter: ListFilter) => {\n const { t } = useTranslation();\n const field = filterFieldOf(model, filter);\n const target =\n field?.type === 'relation' && isEntryFilter(field, filter)\n ? schema.models.get(field.settings.target)\n : undefined;\n const entry = useEntry(\n target?.apiKey ?? '',\n filter.value ?? '',\n undefined,\n target !== undefined && Boolean(filter.value),\n );\n const subject = isSystemField(filter.field)\n ? t(SYSTEM_LABEL_KEYS[filter.field])\n : (field?.label ?? filter.field);\n const condition = t(OPERATOR_LABEL_KEYS[filter.operator]);\n const rawValue = isValueless(filter.operator) ? '' : (filter.value ?? '');\n const value =\n target && rawValue\n ? entry.data\n ? (entryTitle(target, entry.data.data) ?? t('content.untitled'))\n : shortId(rawValue)\n : rawValue;\n return { subject, condition, value, text: [subject, condition, value].filter(Boolean).join(' ') };\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport type { ListFilter } from '../../helpers/filterOperators';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\nimport { FilterChip } from '../FilterChip';\nimport { useFilterLabel } from '../hooks/useFilterLabel';\n\ntype ActiveFilterProps = {\n schema: ContentSchema;\n model: ModelDefinition;\n filter: ListFilter;\n onRemove: () => void;\n};\n\n/** One applied filter as a chip: \"Title starts with Co ×\". */\nexport const ActiveFilter = ({ schema, model, filter, onRemove }: ActiveFilterProps) => {\n const { subject, condition, value, text } = useFilterLabel(schema, model, filter);\n return (\n <FilterChip label={text} onRemove={onRemove}>\n <span className=\"text-muted-foreground\">\n {subject} {condition}\n </span>\n {value ? ` ${value}` : null}\n </FilterChip>\n );\n};\n","import { Plus } from 'lucide-react';\nimport type { ComponentProps } from 'react';\nimport { cn } from '@/helpers/cn';\n\ntype AddChipProps = Omit<ComponentProps<'button'>, 'type'>;\n\n/** A dashed \"+ Status\" chip that opens a quick filter (a menu or picker as its trigger). */\nexport const AddChip = ({ className, children, ...props }: AddChipProps) => (\n <button\n type=\"button\"\n className={cn(\n 'inline-flex h-7 items-center gap-1 rounded-full border border-dashed border-input px-3 text-xs font-medium text-muted-foreground outline-none hover:bg-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50',\n className,\n )}\n {...props}\n >\n <Plus aria-hidden=\"true\" className=\"size-3.5\" />\n {children}\n </button>\n);\n","import type { EntryAuthor } from '@shapio/client';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { UserAvatar } from '@/components/UserAvatar';\nimport { AddChip } from '../AddChip';\n\ntype AuthorFilterProps = {\n choices: readonly EntryAuthor[];\n meId: string | undefined;\n onPick: (authorId: string) => void;\n};\n\n/** \"+ Created by\": only entries a given admin created (you, an author on this page, or anyone listed). */\nexport const AuthorFilter = ({ choices, meId, onPick }: AuthorFilterProps) => {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n return (\n <li>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <AddChip>{t('place.filters.author')}</AddChip>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-2\">\n <ul aria-label={t('place.filters.authors')} className=\"max-h-72 space-y-0.5 overflow-y-auto\">\n {choices.map((choice) => (\n <li key={choice.id}>\n <button\n type=\"button\"\n className=\"flex h-9 w-full items-center gap-2 rounded-md px-2 text-left text-sm outline-none hover:bg-accent focus-visible:bg-accent focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n onClick={() => {\n onPick(choice.id);\n setOpen(false);\n }}\n >\n <UserAvatar name={choice.name} size=\"sm\" />\n <span className=\"truncate\">\n {choice.id === meId ? t('place.filters.you', { name: choice.name }) : choice.name}\n </span>\n </button>\n </li>\n ))}\n </ul>\n </PopoverContent>\n </Popover>\n </li>\n );\n};\n","import type { AdminEntryListItem, EntryAuthor } from '@shapio/client';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { useMe, useHasGlobalPermission } from '@/api/auth';\nimport { adminApi } from '@/api/client';\nimport { queryKeys } from '@/api/queryKeys';\n\n/**\n * Who the \"Created by\" filter offers: you first, then the authors on this page, then every admin when\n * you may list them (`users.manage`). Also names the author an active filter points at.\n */\nexport const useAuthorChoices = (items: readonly AdminEntryListItem[] | undefined) => {\n const me = useMe().data?.user;\n const canListUsers = useHasGlobalPermission('users.manage');\n const users = useQuery({\n queryKey: queryKeys.users,\n queryFn: () => adminApi.users.list(),\n enabled: canListUsers,\n meta: { silent: true },\n });\n const choices = useMemo(() => {\n const byId = new Map<string, EntryAuthor>();\n const add = (author: EntryAuthor | null | undefined) => {\n if (author && !byId.has(author.id)) {\n byId.set(author.id, author);\n }\n };\n add(me ? { id: me.id, name: me.name } : undefined);\n items?.forEach((item) => add(item.author));\n users.data?.forEach((user) => add({ id: user.id, name: user.name }));\n return [...byId.values()];\n }, [me, items, users.data]);\n return { choices, meId: me?.id, nameOf: (id: string) => choices.find((choice) => choice.id === id)?.name };\n};\n","import type { FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { Search } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useEntryList } from '@/api/content';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Input } from '@/components/ui/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { labelOf, isSearchable } from '@/fields/helpers/titles';\nimport { useDebouncedValue } from '@/hooks/useDebouncedValue';\nimport { AddChip } from '../AddChip';\nimport { RELATION_PICKER_SIZE } from '../constants';\n\ntype RelationFilterProps = {\n field: FieldDefinition;\n /** The model the relation points at (undefined when it is gone or not readable). */\n target: ModelDefinition | undefined;\n onPick: (entryId: string) => void;\n};\n\nconst SEARCH_DEBOUNCE_MS = 250;\n\n/** A dashed \"+ Author\" chip: pick one entry of the related model to show only entries linked to it. */\nexport const RelationFilter = ({ field, target, onPick }: RelationFilterProps) => {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [text, setText] = useState('');\n const q = useDebouncedValue(text, SEARCH_DEBOUNCE_MS).trim();\n const searchable = target ? isSearchable(target) : false;\n const options = useEntryList(\n target?.apiKey ?? '',\n { pageSize: RELATION_PICKER_SIZE, ...(searchable && q ? { q } : {}) },\n open && target !== undefined,\n );\n if (!target) {\n return null;\n }\n return (\n <li>\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n setText('');\n }}\n >\n <PopoverTrigger asChild>\n <AddChip>{field.label}</AddChip>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-72 space-y-2 p-2\">\n {searchable ? (\n <div className=\"relative\">\n <Search\n aria-hidden=\"true\"\n className=\"absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n type=\"search\"\n inputSize=\"sm\"\n value={text}\n className=\"pl-9\"\n aria-label={t('place.filters.findEntry', { model: target.label })}\n placeholder={t('place.filters.findEntry', { model: target.label })}\n onChange={(event) => setText(event.target.value)}\n />\n </div>\n ) : null}\n {options.isPending ? (\n <LoadingState rows={3} className=\"p-1\" />\n ) : options.isError ? (\n <p className=\"px-2 py-1.5 text-sm text-destructive\">{t('place.filters.entriesFailed')}</p>\n ) : options.data.items.length === 0 ? (\n <p className=\"px-2 py-1.5 text-sm text-muted-foreground\">{t('place.filters.noEntries')}</p>\n ) : (\n <ul aria-label={t('place.filters.entriesOf', { model: target.label })} className=\"space-y-0.5\">\n {options.data.items.map((item) => (\n <li key={item.id}>\n <button\n type=\"button\"\n className=\"flex h-8 w-full items-center rounded-md px-2 text-left text-sm outline-none hover:bg-accent focus-visible:bg-accent focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n onClick={() => {\n onPick(item.id);\n setOpen(false);\n }}\n >\n <span className=\"truncate\">{labelOf(target, item, t('content.untitled'))}</span>\n </button>\n </li>\n ))}\n </ul>\n )}\n </PopoverContent>\n </Popover>\n </li>\n );\n};\n","import type { EntryStatus } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { ENTRY_STATUS_LABEL_KEYS } from '../../helpers/entryStatus';\nimport { AddChip } from '../AddChip';\nimport { ENTRY_STATUSES } from '../constants';\n\ntype StatusFilterProps = { onPick: (status: EntryStatus) => void };\n\n/** \"+ Status\": only drafts, changed or published entries (in the list's locale). */\nexport const StatusFilter = ({ onPick }: StatusFilterProps) => {\n const { t } = useTranslation();\n return (\n <li>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <AddChip>{t('place.filters.status')}</AddChip>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n {ENTRY_STATUSES.map((status) => (\n <DropdownMenuItem key={status} onSelect={() => onPick(status)}>\n {t(ENTRY_STATUS_LABEL_KEYS[status])}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n </li>\n );\n};\n","import type { AdminEntryListItem, EntryStatus } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport { shortId } from '@/fields/helpers/titles';\nimport { ENTRY_STATUS_LABEL_KEYS } from '../../helpers/entryStatus';\nimport type { ListFilter } from '../../helpers/filterOperators';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\nimport { ActiveFilter } from '../ActiveFilter';\nimport { AuthorFilter } from '../AuthorFilter';\nimport { FilterChip } from '../FilterChip';\nimport { relationFilterFields } from '../helpers/filterLabels';\nimport { useAuthorChoices } from '../hooks/useAuthorChoices';\nimport { RelationFilter } from '../RelationFilter';\nimport { StatusFilter } from '../StatusFilter';\n\ntype FilterChipsProps = {\n schema: ContentSchema;\n model: ModelDefinition;\n filters: readonly ListFilter[];\n status: EntryStatus | undefined;\n author: string | undefined;\n /** Changes some of the list's filters at once (one URL update). */\n onSearchChange: (changes: FilterChanges) => void;\n /** The page's entries (their authors are offered by \"Created by\"). */\n items: readonly AdminEntryListItem[] | undefined;\n};\n\nexport type FilterChanges = {\n filters?: ListFilter[];\n status?: EntryStatus | undefined;\n author?: string | undefined;\n};\n\ntype ChipProps = { subject: string; value: string; onRemove: () => void };\n\nconst Chip = ({ subject, value, onRemove }: ChipProps) => (\n <FilterChip label={`${subject} ${value}`} onRemove={onRemove}>\n <span className=\"text-muted-foreground\">{subject}</span> {value}\n </FilterChip>\n);\n\n/**\n * The list's filters as chips: status and \"created by\" (quick filters), every applied condition (removable),\n * and a dashed chip per relation (\"+ Author\") that filters by one related entry. Other conditions are added\n * with the Filters button.\n */\nexport const FilterChips = ({\n schema,\n model,\n filters,\n status,\n author,\n onSearchChange,\n items,\n}: FilterChipsProps) => {\n const { t } = useTranslation();\n const { choices, meId, nameOf } = useAuthorChoices(items);\n const used = new Set(filters.map((filter) => filter.field));\n const adders = relationFilterFields(model).filter((field) => !used.has(field.apiKey));\n const applied = filters.length + (status ? 1 : 0) + (author ? 1 : 0);\n return (\n <div className=\"flex w-full flex-wrap items-center gap-2\">\n <ul aria-label={t('place.filters.active')} className=\"flex flex-wrap items-center gap-2\">\n {status ? (\n <Chip\n subject={t('place.filters.statusIs')}\n value={t(ENTRY_STATUS_LABEL_KEYS[status])}\n onRemove={() => onSearchChange({ status: undefined })}\n />\n ) : null}\n {author ? (\n <Chip\n subject={t('place.filters.createdBy')}\n value={nameOf(author) ?? shortId(author)}\n onRemove={() => onSearchChange({ author: undefined })}\n />\n ) : null}\n {filters.map((filter, index) => (\n <ActiveFilter\n key={`${filter.field}-${index}`}\n schema={schema}\n model={model}\n filter={filter}\n onRemove={() => onSearchChange({ filters: filters.filter((_, at) => at !== index) })}\n />\n ))}\n {status ? null : <StatusFilter onPick={(next) => onSearchChange({ status: next })} />}\n {author ? null : (\n <AuthorFilter choices={choices} meId={meId} onPick={(next) => onSearchChange({ author: next })} />\n )}\n {adders.map((field) =>\n field.type === 'relation' ? (\n <RelationFilter\n key={field.id}\n field={field}\n target={schema.models.get(field.settings.target)}\n onPick={(entryId) =>\n onSearchChange({\n filters: [...filters, { field: field.apiKey, operator: '$eq', value: entryId }],\n })\n }\n />\n ) : null,\n )}\n </ul>\n {applied > 1 ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => onSearchChange({ filters: [], status: undefined, author: undefined })}\n >\n {t('place.filters.clearChips')}\n </Button>\n ) : null}\n </div>\n );\n};\n","/** A list row's draft as the list read it. */\nexport type VersionedRow = { id: string; locale: string; version: number };\n\n/**\n * The draft version a list row shows for the locale being published (null: a model that isn't localized),\n * sent with the publish so a draft saved since the list loaded is refused. Undefined when the row was read\n * from another locale (a fallback): the list never showed that draft's version, so nothing guards it.\n */\nexport const expectedVersionOf = (row: VersionedRow, locale: string | null): number | undefined =>\n locale === null || row.locale === locale ? row.version : undefined;\n","import { useQueryClient } from '@tanstack/react-query';\nimport { useState } from 'react';\nimport { toast } from 'sonner';\nimport { adminApi } from '@/api/client';\nimport { withCsrf } from '@/api/csrf';\nimport { queryKeys } from '@/api/queryKeys';\nimport { i18next } from '@/app/i18n';\nimport { describeError } from '@/helpers/describeError';\nimport { logError } from '@/helpers/reportError';\nimport { expectedVersionOf, type VersionedRow } from '../helpers/expectedVersion';\n\nexport type BulkAction = 'publish' | 'unpublish' | 'delete';\n\nconst SUCCESS_KEYS = {\n publish: 'place.bulk.published',\n unpublish: 'place.bulk.unpublished',\n delete: 'place.bulk.deleted',\n} as const satisfies Record<BulkAction, string>;\n\nconst FAILURE_KEYS = {\n publish: 'place.bulk.publishFailed',\n unpublish: 'place.bulk.unpublishFailed',\n delete: 'place.bulk.deleteFailed',\n} as const satisfies Record<BulkAction, string>;\n\n/**\n * Publish, unpublish or delete several entries, one request each (so one failure, e.g. an entry still\n * referenced or invalid, does not stop the rest), then a summary with the first reason for any failures.\n * Publishing sends each loaded row's draft version, so a draft saved since the list loaded fails (409);\n * rows ticked on another page are not in `rows` and publish unguarded.\n */\nexport const useBulkEntryActions = (modelKey: string, locale: string | null) => {\n const queryClient = useQueryClient();\n const [running, setRunning] = useState<BulkAction | null>(null);\n const run = async (\n action: BulkAction,\n ids: readonly string[],\n rows: readonly VersionedRow[] = [],\n ): Promise<string[]> => {\n setRunning(action);\n const failed: string[] = [];\n let firstError: unknown;\n const locales = locale ? { locales: [locale] } : {};\n const expectedOf = (id: string) => {\n const row = rows.find((candidate) => candidate.id === id);\n const expectedVersion = row ? expectedVersionOf(row, locale) : undefined;\n return expectedVersion !== undefined ? { expectedVersion } : {};\n };\n for (const id of ids) {\n try {\n await withCsrf<unknown>(() =>\n action === 'delete'\n ? adminApi.content.remove(modelKey, id)\n : action === 'publish'\n ? adminApi.content.publish(modelKey, id, { ...locales, ...expectedOf(id) })\n : adminApi.content.unpublish(modelKey, id, locales),\n );\n } catch (error) {\n logError(error, `bulk ${action} of ${modelKey}/${id}`);\n failed.push(id);\n firstError ??= error;\n }\n }\n setRunning(null);\n await queryClient.invalidateQueries({ queryKey: queryKeys.content.model(modelKey) });\n if (action === 'delete') {\n await queryClient.invalidateQueries({ queryKey: queryKeys.contentCounts });\n }\n const succeeded = ids.length - failed.length;\n if (succeeded > 0) {\n toast.success(i18next.t(SUCCESS_KEYS[action], { count: succeeded }));\n }\n if (failed.length > 0) {\n toast.error(\n i18next.t(FAILURE_KEYS[action], { count: failed.length, reason: describeError(firstError) }),\n );\n }\n return failed;\n };\n return { run, running };\n};\n","import type { FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { liveFields } from '@/fields/helpers/formValues';\nimport { titleFieldOf } from '@/fields/helpers/titles';\n\nconst MAX_DEFAULT_COLUMNS = 3;\nconst LISTABLE_TYPES: ReadonlySet<string> = new Set([\n 'string',\n 'slug',\n 'email',\n 'url',\n 'uid',\n 'number',\n 'integer',\n 'decimal',\n 'biginteger',\n 'boolean',\n 'date',\n 'datetime',\n 'time',\n 'enum',\n]);\n/** Values too large or nested to read in a table cell. */\nconst UNLISTABLE_TYPES: ReadonlySet<string> = new Set([\n 'richtext',\n 'json',\n 'code',\n 'component',\n 'dynamiczone',\n]);\n\n/** Fields the column chooser offers: the title first, then every field with a readable cell. */\nexport const columnChoicesFor = (model: ModelDefinition): FieldDefinition[] => {\n const title = titleFieldOf(model);\n const rest = liveFields(model.fields).filter(\n (field) => field !== title && !UNLISTABLE_TYPES.has(field.type),\n );\n return [...(title ? [title] : []), ...rest];\n};\n\n/** The list's default columns: the model's `display.listFieldIds`, else its title and a few short fields. */\nexport const columnsFor = (model: ModelDefinition): FieldDefinition[] => {\n const fields = liveFields(model.fields);\n const configured = (model.display.listFieldIds ?? [])\n .map((id) => fields.find((field) => field.id === id))\n .filter((field): field is FieldDefinition => field !== undefined);\n if (configured.length > 0) {\n return configured;\n }\n const title = titleFieldOf(model);\n const rest = fields.filter((field) => field !== title && LISTABLE_TYPES.has(field.type));\n return [...(title ? [title] : []), ...rest].slice(0, MAX_DEFAULT_COLUMNS);\n};\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport { persistentStorage } from '@/helpers/safeStorage';\nimport type { ListView } from '../constants';\n\ntype ListColumnsState = {\n /** Field IDs shown as columns, per model ID. A model without an entry uses its default columns. */\n byModel: Readonly<Record<string, readonly string[]>>;\n /** Table or cards, per model ID. A model without an entry shows the table. */\n viewByModel: Readonly<Record<string, ListView>>;\n setColumns: (modelId: string, fieldIds: readonly string[] | undefined) => void;\n setView: (modelId: string, view: ListView) => void;\n};\n\n/** A place's column choice and view (this browser only; a per-person convenience, not shared state). */\nexport const useListColumnsStore = create<ListColumnsState>()(\n persist(\n (set) => ({\n byModel: {},\n viewByModel: {},\n setColumns: (modelId, fieldIds) =>\n set((state) => {\n const { [modelId]: _previous, ...rest } = state.byModel;\n return { byModel: fieldIds ? { ...rest, [modelId]: fieldIds } : rest };\n }),\n setView: (modelId, view) =>\n set((state) => ({ viewByModel: { ...state.viewByModel, [modelId]: view } })),\n }),\n // Version 1 stored only `byModel`; the persisted state is merged over the defaults, so it still loads.\n { name: 'shapio.contentColumns', storage: persistentStorage, version: 1 },\n ),\n);\n","import type { FieldDefinition, ModelDefinition } from '@shapio/schema';\nimport { useMemo } from 'react';\nimport { columnChoicesFor, columnsFor } from '../columns';\nimport { useListColumnsStore } from '../stores/listColumns';\n\n/**\n * The list's field columns (the person's choice, else the model's defaults), the fields that can be\n * chosen, and the setters. Field IDs, not API keys, so a renamed field stays chosen.\n */\nexport const useListColumns = (model: ModelDefinition) => {\n const chosenIds = useListColumnsStore((state) => state.byModel[model.id]);\n const setColumns = useListColumnsStore((state) => state.setColumns);\n const choices = useMemo(() => columnChoicesFor(model), [model]);\n const columns = useMemo<FieldDefinition[]>(() => {\n const chosen = chosenIds ? choices.filter((field) => chosenIds.includes(field.id)) : [];\n return chosen.length > 0 ? chosen : columnsFor(model);\n }, [chosenIds, choices, model]);\n const setColumnVisible = (fieldId: string, visible: boolean) => {\n const current = columns.map((field) => field.id);\n const next = visible ? [...current, fieldId] : current.filter((id) => id !== fieldId);\n setColumns(model.id, next.length > 0 ? next : undefined);\n };\n return {\n columns,\n columnChoices: choices,\n customized: chosenIds !== undefined,\n setColumnVisible,\n resetColumns: () => setColumns(model.id, undefined),\n };\n};\n","import { effectiveLayout, type ModelDefinition } from '@shapio/schema';\nimport { useMemo } from 'react';\nimport type { ListView } from '../constants';\nimport { useListColumnsStore } from '../stores/listColumns';\n\n/**\n * Table or cards for this model, remembered per model in this browser. Cards need a cover field (the\n * document layout's cover); without one the list is always a table.\n */\nexport const useListView = (model: ModelDefinition) => {\n const cover = useMemo(() => effectiveLayout(model).cover, [model]);\n const stored = useListColumnsStore((state) => state.viewByModel[model.id]);\n const setStored = useListColumnsStore((state) => state.setView);\n const view: ListView = cover && stored === 'cards' ? 'cards' : 'table';\n return { view, cover, setView: (next: ListView) => setStored(model.id, next) };\n};\n","import type { PresencePerson } from '@shapio/client';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { adminApi } from '@/api/client';\nimport { queryKeys } from '@/api/queryKeys';\nimport { PRESENCE_POLL_MS } from '../constants';\n\nconst NOBODY: ReadonlyMap<string, readonly PresencePerson[]> = new Map();\n\n/**\n * Who is editing which entry of the model right now (`GET /api/admin/presence/:modelKey`), refreshed every\n * 15s while the tab is visible. Information only: entries lock nothing.\n */\nexport const useModelPresence = (modelKey: string) => {\n const presence = useQuery({\n queryKey: queryKeys.presence(modelKey),\n queryFn: () => adminApi.presence.model(modelKey),\n refetchInterval: PRESENCE_POLL_MS,\n retry: false,\n meta: { silent: true },\n });\n const byEntry = useMemo(\n () =>\n presence.data\n ? new Map(\n presence.data.entries.map((row) => [row.entryId, row.people.filter((person) => !person.you)]),\n )\n : NOBODY,\n [presence.data],\n );\n return { byEntry };\n};\n","import { useMutation } from '@tanstack/react-query';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { adminApi } from '@/api/client';\nimport { withCsrf } from '@/api/csrf';\nimport { describeError } from '@/helpers/describeError';\nimport { logError } from '@/helpers/reportError';\n\n/**\n * Opens an entry's draft on the site (the first connection with a preview URL template). The tab opens on\n * the click, so browsers don't block it, and is pointed at the preview once the token exists.\n */\nexport const usePreviewEntry = (modelKey: string, locale: string | null) => {\n const { t } = useTranslation();\n const open = useMutation({\n mutationKey: ['preview', 'open', modelKey],\n meta: { silent: true },\n mutationFn: (entryId: string) =>\n withCsrf(() => adminApi.preview.open({ modelKey, entryId, ...(locale ? { locale } : {}) })),\n });\n const preview = (entryId: string) => {\n const tab = window.open('about:blank', '_blank');\n open.mutate(entryId, {\n onSuccess: (result) => {\n if (result.url && tab) {\n tab.opener = null;\n tab.location.href = result.url;\n return;\n }\n tab?.close();\n toast.info(t('place.actions.previewUnavailable'));\n },\n onError: (error) => {\n tab?.close();\n logError(error, `preview of ${modelKey}/${entryId}`);\n toast.error(describeError(error));\n },\n });\n };\n return { preview, pending: open.isPending };\n};\n","import { useCallback, useRef, useState } from 'react';\nimport type { FormValues } from '@/fields/helpers/values';\nimport { rowMoreId } from '../helpers/rowIds';\n\n/**\n * Which row's quick edit is open (one at a time), and its unsaved changes: the editor remounts when the list\n * switches between the table and phone rows (a rotated tablet), and picks them up again. Closing it puts\n * focus back on that row's menu button.\n */\nexport const useQuickEditRow = () => {\n const [openId, setOpenId] = useState<string | null>(null);\n const draft = useRef<FormValues | undefined>(undefined);\n const getDraft = useCallback(() => draft.current, []);\n const setDraft = useCallback((values: FormValues | undefined) => {\n draft.current = values;\n }, []);\n return {\n openId,\n open: (id: string) => {\n draft.current = undefined;\n setOpenId(id);\n },\n close: (id: string) => {\n draft.current = undefined;\n setOpenId(null);\n requestAnimationFrame(() => document.getElementById(rowMoreId(id))?.focus());\n },\n /** The open editor's changed values, to carry over a remount. */\n getDraft,\n setDraft,\n };\n};\n","import { useQueryClient } from '@tanstack/react-query';\nimport { useNavigate } from '@tanstack/react-router';\nimport { useTranslation } from 'react-i18next';\nimport { toast } from 'sonner';\nimport { useDeleteEntry, useDuplicateEntry, usePublishEntry, useUnpublishEntry } from '@/api/content';\nimport { queryKeys } from '@/api/queryKeys';\nimport { expectedVersionOf, type VersionedRow } from '../helpers/expectedVersion';\n\n/**\n * A list row's quick actions on one entry, in the list's locale. Each returns the request's promise, so an\n * `InlineConfirm` keeps its spinner until it settles and shows the reason when it fails (an invalid entry,\n * one still linked from others, a draft saved since the list loaded). Successes are announced with a toast.\n */\nexport const useRowActions = (modelKey: string, locale: string | null) => {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const publishEntry = usePublishEntry(modelKey);\n const unpublishEntry = useUnpublishEntry(modelKey);\n const duplicateEntry = useDuplicateEntry(modelKey);\n const deleteEntry = useDeleteEntry(modelKey);\n const locales = locale ? [locale] : undefined;\n const refreshCounts = () => queryClient.invalidateQueries({ queryKey: queryKeys.contentCounts });\n\n const publish = async (row: VersionedRow, label: string) => {\n const expectedVersion = expectedVersionOf(row, locale);\n await publishEntry.mutateAsync({\n id: row.id,\n locales,\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n });\n toast.success(t('place.actions.publishedToast', { entry: label }));\n };\n const unpublish = async (id: string, label: string) => {\n await unpublishEntry.mutateAsync({ id, locales });\n toast.success(t('place.actions.unpublishedToast', { entry: label }));\n };\n const duplicate = (id: string, label: string) =>\n duplicateEntry.mutate(id, {\n onSuccess: (copy) => {\n void refreshCounts();\n toast.success(t('place.actions.duplicatedToast', { entry: label }), {\n action: {\n label: t('place.actions.openCopy'),\n onClick: () =>\n void navigate({\n to: '/content/$modelKey/$entryId',\n params: { modelKey, entryId: copy.id },\n search: locale ? { locale } : {},\n }),\n },\n });\n },\n });\n const remove = async (id: string, label: string) => {\n await deleteEntry.mutateAsync(id);\n void refreshCounts();\n toast.success(t('place.actions.deletedToast', { entry: label }));\n };\n return { publish, unpublish, duplicate, remove, duplicating: duplicateEntry.isPending };\n};\n","import { useState } from 'react';\n\n/** The entries ticked for bulk actions (kept across pages until cleared). */\nexport const useSelection = () => {\n const [selected, setSelected] = useState<ReadonlySet<string>>(new Set());\n const changeSelection = (ids: readonly string[], checked: boolean) =>\n setSelected((current) => {\n const next = new Set(current);\n ids.forEach((id) => (checked ? next.add(id) : next.delete(id)));\n return next;\n });\n const replaceSelection = (ids: readonly string[]) => setSelected(new Set(ids));\n return { selected, changeSelection, replaceSelection };\n};\n","import { Link } from '@tanstack/react-router';\nimport { Plus } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\n\ntype NewButtonProps = { modelKey: string; locale: string | null };\n\n/** \"New\" for a place: opens a new entry in the list's locale. */\nexport const NewButton = ({ modelKey, locale }: NewButtonProps) => {\n const { t } = useTranslation();\n return (\n <Button asChild>\n <Link to=\"/content/$modelKey/new\" params={{ modelKey }} search={locale ? { locale } : {}}>\n <Plus aria-hidden=\"true\" />\n {t('place.new')}\n </Link>\n </Button>\n );\n};\n","import { useTranslation } from 'react-i18next';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { cn } from '@/helpers/cn';\nimport { EntryStatusChip } from '../../../EntryStatusChip';\nimport { Author } from '../../Author';\nimport { EntryTitle } from '../../EntryTitle';\nimport { rowActionsProps } from '../../helpers/rowContext';\nimport { LocaleFlags } from '../../LocaleFlags';\nimport { QuickEdit } from '../../QuickEdit';\nimport type { RowProps } from '../../Row';\nimport { RowActions } from '../../RowActions';\nimport { Updated } from '../../Updated';\n\n/**\n * One entry on a phone: tick box, title with presence, then status, author, locales and last update on one\n * wrapping line, and every action in the \"…\" menu. Quick edit opens underneath.\n */\nexport const Item = ({ context, item, label, selected, people, onSelectChange }: RowProps) => {\n const { t } = useTranslation();\n const { model, locale, quickEdit } = context;\n return (\n <li className={cn('border-b last:border-b-0', selected && 'bg-accent/40')}>\n <div className=\"flex items-start gap-3 px-4 py-3\">\n <Checkbox\n checked={selected}\n aria-label={t('place.list.select', { entry: label })}\n className=\"mt-0.5\"\n onCheckedChange={(checked) => onSelectChange(checked === true)}\n />\n <div className=\"min-w-0 flex-1 space-y-1.5\">\n <EntryTitle\n modelKey={model.apiKey}\n entryId={item.id}\n label={label}\n locale={locale}\n people={people}\n />\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1.5 text-meta\">\n <EntryStatusChip status={item.status} size=\"sm\" />\n <Author author={item.author} className=\"max-w-40\" />\n {locale ? <LocaleFlags item={item} current={locale} labelOf={context.localeLabelOf} /> : null}\n <Updated at={item.updatedAt} />\n </div>\n </div>\n <RowActions {...rowActionsProps(context, item, label)} layout=\"menu\" />\n </div>\n {quickEdit?.openId === item.id ? (\n <div className=\"border-t px-4 py-5\">\n <QuickEdit\n quickEdit={quickEdit}\n model={model}\n entryId={item.id}\n label={label}\n locale={locale}\n onClose={() => quickEdit.close(item.id)}\n />\n </div>\n ) : null}\n </li>\n );\n};\n","import type { AdminEntryListItem, PresencePerson } from '@shapio/client';\nimport { useTranslation } from 'react-i18next';\nimport { labelOf } from '@/fields/helpers/titles';\nimport type { RowContext } from '../Row';\nimport { SelectAll } from '../SelectAll';\nimport { Item } from './Item';\n\ntype StackedProps = {\n context: RowContext;\n items: readonly AdminEntryListItem[];\n selected: ReadonlySet<string>;\n presence: ReadonlyMap<string, readonly PresencePerson[]>;\n onSelectChange: (ids: string[], checked: boolean) => void;\n};\n\nconst NOBODY: readonly PresencePerson[] = [];\n\n/** A place's entries on a phone: one stacked row each, nothing scrolls sideways (sorting is in Sort). */\nexport const Stacked = ({ context, items, selected, presence, onSelectChange }: StackedProps) => {\n const { t } = useTranslation();\n return (\n <div>\n <SelectAll\n ids={items.map((item) => item.id)}\n selected={selected}\n onSelectChange={onSelectChange}\n className=\"border-b px-4 py-3\"\n />\n <ul aria-label={t('place.list.rowsLabel', { place: context.model.label })}>\n {items.map((item) => (\n <Item\n key={item.id}\n context={context}\n item={item}\n label={labelOf(context.model, item, t('content.untitled'))}\n selected={selected.has(item.id)}\n people={presence.get(item.id) ?? NOBODY}\n onSelectChange={(checked) => onSelectChange([item.id], checked)}\n />\n ))}\n </ul>\n </div>\n );\n};\n","import type { FieldDefinition } from '@shapio/schema';\nimport { Columns3 } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\n\ntype ColumnsMenuProps = {\n choices: readonly FieldDefinition[];\n columns: readonly FieldDefinition[];\n customized: boolean;\n onColumnChange: (fieldId: string, visible: boolean) => void;\n onReset: () => void;\n};\n\n/** Which fields the list shows as columns (at least one stays). */\nexport const ColumnsMenu = ({ choices, columns, customized, onColumnChange, onReset }: ColumnsMenuProps) => {\n const { t } = useTranslation();\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\">\n <Columns3 aria-hidden=\"true\" />\n {t('place.list.columns')}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"max-h-80 w-56 overflow-y-auto\">\n <DropdownMenuLabel>{t('place.list.columnsTitle')}</DropdownMenuLabel>\n {choices.map((field) => {\n const visible = columns.includes(field);\n return (\n <DropdownMenuCheckboxItem\n key={field.id}\n checked={visible}\n disabled={visible && columns.length === 1}\n onSelect={(event) => event.preventDefault()}\n onCheckedChange={(checked) => onColumnChange(field.id, checked === true)}\n >\n {field.label}\n </DropdownMenuCheckboxItem>\n );\n })}\n {customized ? (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={onReset}>{t('place.list.resetColumns')}</DropdownMenuItem>\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n","import type { ContentFilterOperator } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { Filter, Plus, X } from 'lucide-react';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport {\n isValueless,\n OPERATOR_LABEL_KEYS,\n operatorsFor,\n SYSTEM_FILTER_FIELDS,\n type ListFilter,\n} from '../../helpers/filterOperators';\nimport { SYSTEM_LABEL_KEYS } from '../constants';\n\ntype FilterBuilderProps = {\n fields: readonly FieldDefinition[];\n filters: readonly ListFilter[];\n onChange: (filters: ListFilter[]) => void;\n};\n\nconst isSystemField = (key: string): key is (typeof SYSTEM_FILTER_FIELDS)[number] =>\n (SYSTEM_FILTER_FIELDS as readonly string[]).includes(key);\n\n/**\n * Filter rows (field, operator, value) using the operators the content API allows for each field. Edits\n * apply when the person presses Apply, so typing doesn't reload the list on every key.\n */\nexport const FilterBuilder = ({ fields, filters, onChange }: FilterBuilderProps) => {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [draft, setDraft] = useState<ListFilter[]>([...filters]);\n const filterable = fields.filter((field) => operatorsFor(field).length > 0);\n const choices = [\n ...filterable.map((field) => ({ key: field.apiKey, label: field.label, operators: operatorsFor(field) })),\n ...SYSTEM_FILTER_FIELDS.map((key) => ({\n key,\n label: t(SYSTEM_LABEL_KEYS[key]),\n operators: operatorsFor(key),\n })),\n ];\n const operatorsOf = (key: string) => choices.find((choice) => choice.key === key)?.operators ?? [];\n const update = (index: number, change: Partial<ListFilter>) =>\n setDraft((current) => current.map((row, at) => (at === index ? { ...row, ...change } : row)));\n const first = choices[0];\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (next) {\n setDraft([...filters]);\n }\n }}\n >\n <PopoverTrigger asChild>\n <Button variant=\"outline\">\n <Filter aria-hidden=\"true\" />\n {t('place.filters.button')}\n {filters.length > 0 ? <Badge variant=\"secondary\">{filters.length}</Badge> : null}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-[min(36rem,calc(100vw-2rem))] space-y-3\">\n <p className=\"text-sm font-semibold\">{t('place.filters.title')}</p>\n {draft.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">{t('place.filters.none')}</p>\n ) : null}\n <ul className=\"space-y-2\">\n {draft.map((row, index) => {\n const operators = operatorsOf(row.field);\n const fieldLabel = choices.find((choice) => choice.key === row.field)?.label ?? row.field;\n return (\n <li key={index} className=\"flex flex-wrap items-center gap-2\">\n <Select\n value={row.field}\n onValueChange={(field) =>\n update(index, { field, operator: operatorsOf(field)[0] ?? '$eq', value: '' })\n }\n >\n <SelectTrigger\n size=\"sm\"\n className=\"w-40\"\n aria-label={t('place.filters.field', { index: index + 1 })}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {choices.map((choice) => (\n <SelectItem key={choice.key} value={choice.key}>\n {choice.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select\n value={row.operator}\n onValueChange={(operator) => update(index, { operator: operator as ContentFilterOperator })}\n >\n <SelectTrigger\n size=\"sm\"\n className=\"w-40\"\n aria-label={t('place.filters.operator', { field: fieldLabel })}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {operators.map((operator) => (\n <SelectItem key={operator} value={operator}>\n {t(OPERATOR_LABEL_KEYS[operator])}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {isValueless(row.operator) ? null : (\n <Input\n value={row.value ?? ''}\n inputSize=\"sm\"\n className=\"min-w-32 flex-1\"\n type={isSystemField(row.field) ? 'datetime-local' : 'text'}\n aria-label={t('place.filters.value', { field: fieldLabel })}\n placeholder={\n row.operator === '$in' || row.operator === '$nin'\n ? t('place.filters.listPlaceholder')\n : undefined\n }\n onChange={(event) => update(index, { value: event.target.value })}\n />\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={t('place.filters.remove', { field: fieldLabel })}\n onClick={() => setDraft((current) => current.filter((_, at) => at !== index))}\n >\n <X aria-hidden=\"true\" />\n </Button>\n </li>\n );\n })}\n </ul>\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n disabled={!first}\n onClick={() =>\n first &&\n setDraft((current) => [\n ...current,\n { field: first.key, operator: first.operators[0] ?? '$eq', value: '' },\n ])\n }\n >\n <Plus aria-hidden=\"true\" />\n {t('place.filters.add')}\n </Button>\n <div className=\"flex gap-2\">\n {filters.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n onChange([]);\n setOpen(false);\n }}\n >\n {t('place.filters.clear')}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => {\n onChange(draft.filter((row) => isValueless(row.operator) || (row.value ?? '').trim() !== ''));\n setOpen(false);\n }}\n >\n {t('place.filters.apply')}\n </Button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n};\n","import type { ContentSort } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { ArrowDownWideNarrow, ArrowUpNarrowWide, ArrowUpDown } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { isSortableField, SYSTEM_FILTER_FIELDS } from '../../helpers/filterOperators';\nimport { SYSTEM_LABEL_KEYS } from '../constants';\n\ntype SortMenuProps = {\n fields: readonly FieldDefinition[];\n sort: ContentSort | undefined;\n onSortChange: (sort: ContentSort) => void;\n};\n\n/** Sort by any sortable field or a system date, in either direction (the column headers do the same). */\nexport const SortMenu = ({ fields, sort, onSortChange }: SortMenuProps) => {\n const { t } = useTranslation();\n const choices = [\n ...fields.filter(isSortableField).map((field) => ({ key: field.apiKey, label: field.label })),\n ...SYSTEM_FILTER_FIELDS.map((key) => ({ key, label: t(SYSTEM_LABEL_KEYS[key]) })),\n ];\n const DirectionIcon =\n sort?.direction === 'asc' ? ArrowUpNarrowWide : sort ? ArrowDownWideNarrow : ArrowUpDown;\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\">\n <DirectionIcon aria-hidden=\"true\" />\n {t('place.list.sort')}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-56\">\n <DropdownMenuLabel>{t('place.list.sortField')}</DropdownMenuLabel>\n <DropdownMenuRadioGroup\n value={sort?.field ?? ''}\n onValueChange={(field) => onSortChange({ field, direction: sort?.direction ?? 'asc' })}\n >\n {choices.map((choice) => (\n <DropdownMenuRadioItem key={choice.key} value={choice.key}>\n {choice.label}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n <DropdownMenuSeparator />\n <DropdownMenuRadioGroup\n value={sort?.direction ?? ''}\n onValueChange={(direction) =>\n onSortChange({\n field: sort?.field ?? 'updatedAt',\n direction: direction === 'asc' ? 'asc' : 'desc',\n })\n }\n >\n <DropdownMenuRadioItem value=\"asc\">{t('place.list.ascending')}</DropdownMenuRadioItem>\n <DropdownMenuRadioItem value=\"desc\">{t('place.list.descending')}</DropdownMenuRadioItem>\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n","import type { LucideIcon } from 'lucide-react';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/helpers/cn';\n\nexport type SegmentedToggleOption<TValue extends string> = {\n value: TValue;\n label: string;\n icon?: LucideIcon;\n};\n\ntype SegmentedToggleProps<TValue extends string> = {\n value: TValue;\n options: readonly SegmentedToggleOption<TValue>[];\n onChange: (value: TValue) => void;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n /** Icons only, each label as its button's accessible name (the options must have icons). */\n iconOnly?: boolean;\n disabled?: boolean;\n className?: string;\n};\n\n/**\n * A switch between a few options as one rounded pill: the chosen option is a `secondary` button, the others\n * `ghost`, each with `aria-pressed`. Pressing the chosen option does nothing. 36px tall, like an `sm` control\n * row. Used for the place's table/cards view.\n */\nexport const SegmentedToggle = <TValue extends string>({\n value,\n options,\n onChange,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n iconOnly = false,\n disabled = false,\n className,\n}: SegmentedToggleProps<TValue>) => (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={cn('flex h-9 w-fit items-center gap-0.5 rounded-lg border border-input px-px', className)}\n >\n {options.map(({ value: option, label, icon: Icon }) => {\n const pressed = option === value;\n return (\n <Button\n key={option}\n type=\"button\"\n variant={pressed ? 'secondary' : 'ghost'}\n size={iconOnly ? 'icon-sm' : 'sm'}\n aria-pressed={pressed}\n aria-label={iconOnly ? label : undefined}\n disabled={disabled}\n onClick={pressed ? undefined : () => onChange(option)}\n >\n {Icon ? <Icon aria-hidden=\"true\" /> : null}\n {iconOnly ? null : label}\n </Button>\n );\n })}\n </div>\n);\n","import { LayoutGrid, Rows3 } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { SegmentedToggle } from '@/components/SegmentedToggle';\nimport type { ListView } from '../constants';\n\ntype ViewToggleProps = { view: ListView; onViewChange: (view: ListView) => void };\n\n/** Table or cover tiles (shown only for models with a cover field). */\nexport const ViewToggle = ({ view, onViewChange }: ViewToggleProps) => {\n const { t } = useTranslation();\n return (\n <SegmentedToggle\n aria-label={t('place.view.label')}\n iconOnly\n value={view}\n onChange={onViewChange}\n options={[\n { value: 'table', label: t('place.view.table'), icon: Rows3 },\n { value: 'cards', label: t('place.view.cards'), icon: LayoutGrid },\n ]}\n />\n );\n};\n","import type { ContentSort } from '@shapio/client';\nimport type { FieldDefinition } from '@shapio/schema';\nimport { Search } from 'lucide-react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Input } from '@/components/ui/input';\nimport { useSearchInput } from '@/hooks/useSearchInput';\nimport type { ListFilter } from '../../helpers/filterOperators';\nimport { ColumnsMenu } from '../ColumnsMenu';\nimport type { ListView } from '../constants';\nimport { FilterBuilder } from '../FilterBuilder';\nimport { SortMenu } from '../SortMenu';\nimport { ViewToggle } from '../ViewToggle';\n\ntype ToolbarProps = {\n /** Null when the model has no text title field to search. */\n query: string | undefined | null;\n onQueryChange: (query: string | undefined) => void;\n fields: readonly FieldDefinition[];\n filters: readonly ListFilter[];\n onFiltersChange: (filters: ListFilter[]) => void;\n sort: ContentSort | undefined;\n onSortChange: (sort: ContentSort) => void;\n /** The column chooser (table view only). */\n columns: ComponentProps<typeof ColumnsMenu> | null;\n /** The table/cards switch (models with a cover only). */\n view: { view: ListView; onViewChange: (view: ListView) => void } | null;\n /** The filter chips row, full width under the controls. */\n chips: ReactNode;\n};\n\n/** Search by title (grows), then filters, sort, columns and the view switch; the filter chips below. */\nexport const Toolbar = ({\n query,\n onQueryChange,\n fields,\n filters,\n onFiltersChange,\n sort,\n onSortChange,\n columns,\n view,\n chips,\n}: ToolbarProps) => {\n const { t } = useTranslation();\n const { text, setText } = useSearchInput(query ?? undefined, onQueryChange);\n return (\n <>\n {query !== null ? (\n <div className=\"relative min-w-48 flex-1\">\n <Search\n aria-hidden=\"true\"\n className=\"absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n type=\"search\"\n inputSize=\"sm\"\n value={text}\n aria-label={t('place.list.search')}\n placeholder={t('place.list.searchPlaceholder')}\n className=\"pl-9\"\n onChange={(event) => setText(event.target.value)}\n />\n </div>\n ) : (\n <div className=\"flex-1\" />\n )}\n <div className=\"flex flex-wrap items-center gap-2\">\n <FilterBuilder fields={fields} filters={filters} onChange={onFiltersChange} />\n <SortMenu fields={fields} sort={sort} onSortChange={onSortChange} />\n {columns ? <ColumnsMenu {...columns} /> : null}\n {view ? <ViewToggle {...view} /> : null}\n </div>\n {chips}\n </>\n );\n};\n","import type { AdminEntryPage } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { FileStack } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { EmptyState } from '@/components/EmptyState';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { PagePager } from '@/components/PagePager';\nimport { TableCard } from '@/components/TableCard';\nimport { liveFields } from '@/fields/helpers/formValues';\nimport { isSearchable, titleFieldOf } from '@/fields/helpers/titles';\nimport { useIsMdUp } from '@/fields/hooks/useIsMdUp';\nimport { CONTENT_PAGE_SIZES } from '../../constants';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\nimport { BulkBar } from '../BulkBar';\nimport { Cards } from '../Cards';\nimport { EntryTable } from '../EntryTable';\nimport { FilterChips } from '../FilterChips';\nimport { quickEditFieldsOf } from '../helpers/quickEditFields';\nimport { useBulkEntryActions } from '../hooks/useBulkEntryActions';\nimport { useListColumns } from '../hooks/useListColumns';\nimport { useListView } from '../hooks/useListView';\nimport { useModelPresence } from '../hooks/useModelPresence';\nimport type { usePlacePermissions } from '../hooks/usePlacePermissions';\nimport type { usePlaceSearch } from '../hooks/usePlaceSearch';\nimport { usePreviewEntry } from '../hooks/usePreviewEntry';\nimport { useQuickEditRow } from '../hooks/useQuickEditRow';\nimport { useRowActions } from '../hooks/useRowActions';\nimport { useSelection } from '../hooks/useSelection';\nimport { NewButton } from '../NewButton';\nimport type { RowContext } from '../Row';\nimport { Stacked } from '../Stacked';\nimport { Toolbar } from '../Toolbar';\n\ntype EntriesProps = {\n schema: ContentSchema;\n model: ModelDefinition;\n locale: string | null;\n localeLabelOf: (code: string) => string;\n placeSearch: ReturnType<typeof usePlaceSearch>;\n list: UseQueryResult<AdminEntryPage>;\n permissions: ReturnType<typeof usePlacePermissions>;\n};\n\n/**\n * A collection's entries: search, filter chips, sort, columns, table or cards, pages, presence, quick\n * actions per row and bulk actions for the selection.\n */\nexport const Entries = ({\n schema,\n model,\n locale,\n localeLabelOf,\n placeSearch,\n list,\n permissions,\n}: EntriesProps) => {\n const { t } = useTranslation();\n const { search, setSearch, sort } = placeSearch;\n const { selected, changeSelection, replaceSelection } = useSelection();\n const bulk = useBulkEntryActions(model.apiKey, locale);\n const { columns, columnChoices, customized, setColumnVisible, resetColumns } = useListColumns(model);\n const { view, cover, setView } = useListView(model);\n const { byEntry: presence } = useModelPresence(model.apiKey);\n const actions = useRowActions(model.apiKey, locale);\n const { preview } = usePreviewEntry(model.apiKey, locale);\n const fields = useMemo(() => liveFields(model.fields), [model]);\n const quickEditRow = useQuickEditRow();\n const wide = useIsMdUp();\n const quickEditable = useMemo(() => quickEditFieldsOf(model).length > 0, [model]);\n const filters = search.filters ?? [];\n const filtered = Boolean(search.q || search.status || search.author || filters.length > 0);\n const title = titleFieldOf(model);\n const context: RowContext = {\n model,\n columns,\n titleColumn: title && columns.includes(title) ? title : undefined,\n locale,\n localeLabelOf,\n permissions,\n actions,\n onPreview: preview,\n quickEdit: permissions.canUpdate && quickEditable ? { schema, ...quickEditRow } : null,\n };\n const setFilters = (next: typeof filters) => setSearch({ filters: next.length > 0 ? next : undefined });\n const setSort = (next: NonNullable<typeof sort>) => setSearch({ sort: `${next.field}:${next.direction}` });\n const pagination = list.data?.pagination;\n const body = () => {\n if (list.isPending) {\n return <LoadingState rows={5} className=\"p-4\" />;\n }\n if (list.isError) {\n return <ErrorState size=\"panel\" error={list.error} onRetry={() => void list.refetch()} />;\n }\n if (list.data.items.length === 0) {\n return (\n <EmptyState\n size=\"panel\"\n icon={FileStack}\n title={filtered ? t('place.list.emptyFiltered') : t('place.list.empty', { place: model.label })}\n action={\n filtered || !permissions.canCreate ? undefined : (\n <NewButton modelKey={model.apiKey} locale={locale} />\n )\n }\n />\n );\n }\n const shared = { context, items: list.data.items, selected, presence, onSelectChange: changeSelection };\n if (view === 'cards' && cover) {\n return <Cards {...shared} cover={cover} />;\n }\n return wide ? <EntryTable {...shared} sort={sort} onSortChange={setSort} /> : <Stacked {...shared} />;\n };\n return (\n <>\n <TableCard\n toolbar={\n <Toolbar\n query={isSearchable(model) ? search.q : null}\n onQueryChange={(q) => setSearch({ q }, { replace: true })}\n fields={fields}\n filters={filters}\n onFiltersChange={setFilters}\n sort={sort}\n onSortChange={setSort}\n columns={\n view === 'table' && wide\n ? {\n choices: columnChoices,\n columns,\n customized,\n onColumnChange: setColumnVisible,\n onReset: resetColumns,\n }\n : null\n }\n view={cover ? { view, onViewChange: setView } : null}\n chips={\n <FilterChips\n schema={schema}\n model={model}\n filters={filters}\n status={search.status}\n author={search.author}\n items={list.data?.items}\n onSearchChange={({ filters: next, ...rest }) =>\n setSearch({\n ...rest,\n ...(next === undefined ? {} : { filters: next.length > 0 ? next : undefined }),\n })\n }\n />\n }\n />\n }\n footer={\n pagination && pagination.total > 0 ? (\n <PagePager\n page={pagination.page}\n pageSize={pagination.pageSize}\n total={pagination.total}\n pageSizes={CONTENT_PAGE_SIZES}\n onPageChange={(page) => setSearch({ page }, { resetPage: false })}\n onPageSizeChange={(pageSize) => setSearch({ pageSize })}\n />\n ) : undefined\n }\n >\n {body()}\n </TableCard>\n {selected.size > 0 ? (\n <BulkBar\n count={selected.size}\n canPublish={permissions.canPublish}\n canDelete={permissions.canDelete}\n running={bulk.running}\n onClear={() => replaceSelection([])}\n onAction={(action) => void bulk.run(action, [...selected], list.data?.items).then(replaceSelection)}\n />\n ) : null}\n </>\n );\n};\n","import type { Locale } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { useTranslation } from 'react-i18next';\nimport { PageHeader } from '@/components/PageHeader';\nimport { LocaleSelect } from '../../LocaleSelect';\nimport { NewButton } from '../NewButton';\n\ntype HeaderProps = {\n model: ModelDefinition;\n /** Entries in the place; undefined while unknown. */\n count: number | undefined;\n locales: readonly Locale[];\n /** The list's locale; null for models that aren't localized. */\n locale: string | null;\n onLocaleChange: (code: string) => void;\n canCreate: boolean;\n};\n\n/** A collection's header: its name and entry count, the content locale and New. */\nexport const Header = ({ model, count, locales, locale, onLocaleChange, canCreate }: HeaderProps) => {\n const { t } = useTranslation();\n return (\n <PageHeader\n title={model.label}\n meta={count === undefined ? undefined : t('place.count', { count })}\n actions={\n <>\n {locale ? (\n <LocaleSelect\n locales={locales}\n value={locale}\n size=\"sm\"\n className=\"w-auto min-w-40\"\n onChange={onLocaleChange}\n />\n ) : null}\n {canCreate ? <NewButton modelKey={model.apiKey} locale={locale} /> : null}\n </>\n }\n />\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useContentCounts } from '@/api/contentCounts';\n\n/**\n * How many entries the place has. An unfiltered page of the list knows its live total, so it wins; the\n * counts endpoint (cached up to 60s) covers a filtered list, other tabs and the first paint.\n */\nexport const usePlaceCount = (model: ModelDefinition, unfilteredTotal: number | undefined) => {\n const counts = useContentCounts();\n return { count: unfilteredTotal ?? counts?.get(model.id) };\n};\n","import type { ContentListQuery, ContentSort } from '@shapio/client';\nimport type { ModelDefinition } from '@shapio/schema';\nimport { useNavigate, useSearch } from '@tanstack/react-router';\nimport type { ContentListSearch } from '@/app/searchSchemas';\nimport { DEFAULT_CONTENT_PAGE_SIZE } from '../../constants';\nimport { toContentFilter } from '../../helpers/filterOperators';\n\nconst parseSort = (sort: string | undefined): ContentSort | undefined => {\n const [field, direction] = sort?.split(':') ?? [];\n return field && (direction === 'asc' || direction === 'desc') ? { field, direction } : undefined;\n};\n\n/** The model's configured default sort, as the API's sort (by API key). */\nconst defaultSortOf = (model: ModelDefinition): ContentSort | undefined => {\n const configured = model.display.defaultSort;\n const field = configured\n ? model.fields.find((candidate) => candidate.id === configured.fieldId)\n : undefined;\n return field && configured ? { field: field.apiKey, direction: configured.direction } : undefined;\n};\n\nexport type SetPlaceSearch = (\n changes: Partial<ContentListSearch>,\n options?: { resetPage?: boolean; replace?: boolean },\n) => void;\n\n/** The list's search, filters, sort, page and locale live in the URL (bookmarkable, back-button friendly). */\nexport const usePlaceSearch = (model: ModelDefinition, locale: string | null) => {\n const search = useSearch({ from: '/app/content/$modelKey' });\n const navigate = useNavigate({ from: '/content/$modelKey' });\n const setSearch: SetPlaceSearch = (changes, { resetPage = true, replace = false } = {}) =>\n void navigate({\n search: (previous) => ({ ...previous, ...(resetPage ? { page: undefined } : {}), ...changes }),\n replace,\n });\n const sort = parseSort(search.sort) ?? defaultSortOf(model);\n const filter = toContentFilter(search.filters ?? []);\n const query: ContentListQuery = {\n page: search.page ?? 1,\n pageSize: search.pageSize ?? DEFAULT_CONTENT_PAGE_SIZE,\n ...(search.q ? { q: search.q } : {}),\n ...(sort ? { sort: [sort] } : {}),\n ...(filter ? { filters: filter } : {}),\n ...(locale ? { locale } : {}),\n ...(search.status ? { status: search.status } : {}),\n ...(search.author ? { author: search.author } : {}),\n };\n return { search, setSearch, query, sort };\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useEntryList } from '@/api/content';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { EntryDocument } from '../../Entry';\nimport { EntryLoader } from '../../EntryLoader';\nimport type { ContentSchema } from '../../hooks/useContentSchema';\n\nconst CREATE = { kind: 'create' } as const;\n\ntype SingletonProps = {\n schema: ContentSchema;\n model: ModelDefinition;\n locale: string | null;\n onLocaleChange: (code: string) => void;\n};\n\n/** A single type has one entry: its document opens directly (or a new one, before it exists). */\nexport const Singleton = ({ schema, model, locale, onLocaleChange }: SingletonProps) => {\n const list = useEntryList(model.apiKey, { pageSize: 1 });\n if (list.isError) {\n return <ErrorState error={list.error} onRetry={() => void list.refetch()} />;\n }\n if (list.isPending) {\n return <LoadingState rows={6} />;\n }\n const [entry] = list.data.items;\n return entry ? (\n <EntryLoader\n schema={schema}\n model={model}\n entryId={entry.id}\n locale={locale}\n onLocaleChange={onLocaleChange}\n />\n ) : (\n <EntryDocument\n key={locale ?? ''}\n schema={schema}\n model={model}\n mode={CREATE}\n locale={locale}\n onReload={() => undefined}\n onLocaleChange={onLocaleChange}\n />\n );\n};\n","import type { ModelDefinition } from '@shapio/schema';\nimport { useNavigate, useParams, useSearch } from '@tanstack/react-router';\nimport { lazy, Suspense } from 'react';\nimport { useEntryList } from '@/api/content';\nimport { ErrorState } from '@/components/ErrorState';\nimport { LoadingState } from '@/components/LoadingState';\nimport { Page } from '@/components/Page';\nimport { useContentLocales } from '../hooks/useContentLocales';\nimport type { ContentSchema } from '../hooks/useContentSchema';\nimport { useModelRoute } from '../hooks/useModelRoute';\nimport { ModelMissing } from '../ModelMissing';\nimport { Api } from './Api';\nimport type { PlaceTab } from './constants';\nimport { Entries } from './Entries';\nimport { Header } from './Header';\nimport { usePlaceCount } from './hooks/usePlaceCount';\nimport { usePlacePermissions } from './hooks/usePlacePermissions';\nimport { usePlaceSearch } from './hooks/usePlaceSearch';\nimport { Singleton } from './Singleton';\nimport { Tabs } from './Tabs';\n\n// The builder (and @shapio/schema's validators) load only when the Structure tab opens.\nconst Structure = lazy(() => import('./Structure').then((module) => ({ default: module.Structure })));\n\ntype PlaceScreenProps = {\n schema: ContentSchema;\n model: ModelDefinition;\n locales: ReturnType<typeof useContentLocales>;\n /** The place's key as it appears in the URL. */\n modelKey: string;\n};\n\nconst PlaceScreen = ({ schema, model, locales, modelKey }: PlaceScreenProps) => {\n const navigate = useNavigate({ from: '/content/$modelKey' });\n const permissions = usePlacePermissions(model);\n const placeSearch = usePlaceSearch(model, locales.current);\n const requested = placeSearch.search.tab ?? 'entries';\n const tab: PlaceTab = permissions.canSeeStructure ? requested : 'entries';\n const collection = model.kind === 'collection';\n const list = useEntryList(model.apiKey, placeSearch.query, collection && tab === 'entries');\n const search = placeSearch.search;\n const unfiltered = !search.q && !search.status && !search.author && !(search.filters?.length ?? 0);\n const { count } = usePlaceCount(model, unfiltered ? list.data?.pagination.total : undefined);\n const onLocaleChange = (code: string) => placeSearch.setSearch({ locale: code });\n const content = () => {\n switch (tab) {\n case 'structure':\n return (\n <Suspense fallback={<LoadingState rows={6} />}>\n <Structure model={model} />\n </Suspense>\n );\n case 'api':\n return (\n <Page width=\"full\">\n <Api schema={schema} model={model} />\n </Page>\n );\n case 'entries':\n return collection ? (\n <Page width=\"full\">\n <Header\n model={model}\n count={count}\n locales={locales.locales}\n locale={locales.current}\n onLocaleChange={onLocaleChange}\n canCreate={permissions.canCreate}\n />\n <Entries\n schema={schema}\n model={model}\n locale={locales.current}\n localeLabelOf={locales.labelOf}\n placeSearch={placeSearch}\n list={list}\n permissions={permissions}\n />\n </Page>\n ) : (\n <Singleton\n schema={schema}\n model={model}\n locale={locales.current}\n onLocaleChange={(code) =>\n void navigate({ search: (previous) => ({ ...previous, locale: code }) })\n }\n />\n );\n }\n };\n return permissions.canSeeStructure ? (\n <Tabs tab={tab} placeLabel={model.label} modelKey={modelKey} document={tab === 'entries' && !collection}>\n {content()}\n </Tabs>\n ) : (\n content()\n );\n};\n\n/**\n * `/content/$modelKey?tab=`: a place. A collection's entries (or a single type's document), and for admins\n * who manage its schema, its Structure (the builder) and API tabs. The model is resolved from the live\n * registry at render time (models are data), so a place created a moment ago opens at once.\n */\nexport const Place = () => {\n const { modelKey } = useParams({ from: '/app/content/$modelKey' });\n const search = useSearch({ from: '/app/content/$modelKey' });\n const { schema, model, error, pending } = useModelRoute(modelKey);\n const locales = useContentLocales(model, search.locale);\n if (error || locales.error) {\n return <ErrorState error={error ?? locales.error} />;\n }\n if (pending || !schema || locales.isPending) {\n return <LoadingState rows={6} />;\n }\n if (!model) {\n return (\n <Page>\n <ModelMissing modelKey={modelKey} />\n </Page>\n );\n }\n return <PlaceScreen key={model.id} schema={schema} model={model} locales={locales} modelKey={modelKey} />;\n};\n","import { createLazyRoute } from '@tanstack/react-router';\nimport { EntryEditor } from '@/features/Content/EntryEditor';\nimport { ContentHome } from '@/features/Content/Home';\nimport { NewEntry } from '@/features/Content/NewEntry';\nimport { Place } from '@/features/Content/Place';\n\n/** Content screens (and the editors with Tiptap), loaded together on the first visit to Content. */\nexport const contentLazyRoutes = {\n home: createLazyRoute('/app/content')({ component: ContentHome }),\n model: createLazyRoute('/app/content/$modelKey')({ component: Place }),\n newEntry: createLazyRoute('/app/content/$modelKey/new')({ component: NewEntry }),\n entry: createLazyRoute('/app/content/$modelKey/$entryId')({ component: EntryEditor }),\n};\n"],"file":"content-CAjkbZEY.js"}
|