@panphora/clayjs 1.15.2 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -5
- package/THIRD-PARTY-NOTICES.md +16 -0
- package/compat/highlight-11.9.0.min.js +1213 -0
- package/compat/highlight-LICENSE +29 -0
- package/compat/journal-assets.lock.json +22 -0
- package/compat/overtype-2.6.1.min.js +116 -0
- package/compat/overtype-LICENSE +21 -0
- package/dist/all.js +90 -0
- package/dist/clay-dom.js +84 -0
- package/dist/clay-events.js +103 -0
- package/dist/clay-internals.js +85 -0
- package/dist/clay-options.js +93 -0
- package/dist/clay-router.js +98 -0
- package/dist/clay-ui.js +95 -0
- package/dist/clay-utils.js +84 -0
- package/dist/clay.js +146 -0
- package/dist/clay.standalone.js +84291 -57611
- package/dist/m/attrs/add-from-T5LJXFFI.js +1 -0
- package/dist/m/attrs/onaftersave-OKSWEJQF.js +1 -0
- package/dist/m/attrs/refetch-on-save-ZUE7PSCI.js +1 -0
- package/dist/m/attrs/save-freeze-MYNVXREN.js +1 -0
- package/dist/m/c-2AZDZWCK.js +1 -0
- package/dist/m/c-2SPVQSHC.js +1 -0
- package/dist/m/c-2YYDMLNZ.js +1 -0
- package/dist/m/c-336SGU5W.js +1 -0
- package/dist/m/c-33JJ6CBX.js +2 -0
- package/dist/m/c-3GJ4SDE2.js +1 -0
- package/dist/m/c-3H6BZDNJ.js +6 -0
- package/dist/m/c-3OWDMNJR.js +2 -0
- package/dist/m/c-3RUU4TPX.js +91 -0
- package/dist/m/c-3XIRD4NU.js +1 -0
- package/dist/m/c-46XYM55L.js +1 -0
- package/dist/m/c-4DFEJ2PO.js +3 -0
- package/dist/m/c-4JZDZFF6.js +1 -0
- package/dist/m/c-4L3BTFRK.js +1 -0
- package/dist/m/c-4Q2XTQ2N.js +2 -0
- package/dist/m/c-4WKFKEKF.js +1 -0
- package/dist/m/c-56QRZTZH.js +1 -0
- package/dist/m/c-5J4E7O4Y.js +4 -0
- package/dist/m/c-5LKDWQTL.js +19 -0
- package/dist/m/c-5QWQ7A5L.js +1 -0
- package/dist/m/c-5RJFTLSF.js +1 -0
- package/dist/m/c-5V3MOVJT.js +1 -0
- package/dist/m/c-5VYOWDTI.js +1 -0
- package/dist/m/c-5YIHJ3TJ.js +1 -0
- package/dist/m/c-6AZOGAPE.js +1 -0
- package/dist/m/c-6CRUUXOX.js +5 -0
- package/dist/m/c-6HMB24EV.js +1 -0
- package/dist/m/c-6KEVEQ7L.js +1 -0
- package/dist/m/c-6NC5I2TV.js +1 -0
- package/dist/m/c-74MGYWZF.js +1 -0
- package/dist/m/c-7DJDKPGL.js +1 -0
- package/dist/m/c-7OLLJPWP.js +1 -0
- package/dist/m/c-7SWMYKAI.js +1 -0
- package/dist/m/c-A3E3NIMC.js +1 -0
- package/dist/m/c-A7LS5UZW.js +1 -0
- package/dist/m/c-AMSNPOCX.js +1 -0
- package/dist/m/c-AQLFEATB.js +1 -0
- package/dist/m/c-B3JM5ZXC.js +1 -0
- package/dist/m/c-BBVGTQG7.js +1 -0
- package/dist/m/c-BPF2NSPV.js +1 -0
- package/dist/m/c-BQ6LOBEE.js +1 -0
- package/dist/m/c-BTDI4Y23.js +1 -0
- package/dist/m/c-BWFVSBDF.js +1 -0
- package/dist/m/c-BYTKL6UX.js +1 -0
- package/dist/m/c-CFHW5AMY.js +6 -0
- package/dist/m/c-CJ3A7ZKE.js +1 -0
- package/dist/m/c-CQHPGKX2.js +1 -0
- package/dist/m/c-CYWLPPUS.js +1 -0
- package/dist/m/c-CZUSOB7V.js +1 -0
- package/dist/m/c-DCFSEJZG.js +1 -0
- package/dist/m/c-DCXOXBF3.js +1 -0
- package/dist/m/c-DFS4XZJV.js +2 -0
- package/dist/m/c-DNENWY4O.js +1 -0
- package/dist/m/c-DNZ5IFM6.js +1 -0
- package/dist/m/c-E4LIR5X5.js +1 -0
- package/dist/m/c-EJTGYSLN.js +1 -0
- package/dist/m/c-EVCQ3BKA.js +1 -0
- package/dist/m/c-EZU56NQV.js +34 -0
- package/dist/m/c-FDNHHZY5.js +1 -0
- package/dist/m/c-FILLTJA7.js +1 -0
- package/dist/m/c-FRLHSY7E.js +1 -0
- package/dist/m/c-FROJUZMV.js +1 -0
- package/dist/m/c-G2JPKCTP.js +1 -0
- package/dist/m/c-GB6TU7WV.js +1 -0
- package/dist/m/c-GFJJEBTU.js +1 -0
- package/dist/m/c-GJAEGGXY.js +1 -0
- package/dist/m/c-GOWBDM6J.js +1 -0
- package/dist/m/c-GQ6F6IDK.js +1 -0
- package/dist/m/c-GSFIGKOP.js +1 -0
- package/dist/m/c-GY422N3Q.js +1 -0
- package/dist/m/c-H4LG442Q.js +1 -0
- package/dist/m/c-HA6INT6J.js +1 -0
- package/dist/m/c-HAWFNBYG.js +1 -0
- package/dist/m/c-HDDEEL77.js +1 -0
- package/dist/m/c-HFKUVACH.js +1 -0
- package/dist/m/c-HHDFCNHV.js +1 -0
- package/dist/m/c-HPURYVZS.js +2 -0
- package/dist/m/c-I2ZATQCD.js +2 -0
- package/dist/m/c-IEM4NTCS.js +1 -0
- package/dist/m/c-IJUK2GPW.js +1 -0
- package/dist/m/c-IW6GGOU2.js +1 -0
- package/dist/m/c-JAX2667S.js +6 -0
- package/dist/m/c-JDCX26UP.js +25 -0
- package/dist/m/c-JRKY44DK.js +1 -0
- package/dist/m/c-JU3NK25H.js +1 -0
- package/dist/m/c-KAU6E43D.js +1 -0
- package/dist/m/c-KBS3UV6B.js +1 -0
- package/dist/m/c-KGVGROZT.js +1 -0
- package/dist/m/c-KI7M4AY3.js +1 -0
- package/dist/m/c-KIPQJX4B.js +1 -0
- package/dist/m/c-KQ6TYJAP.js +135 -0
- package/dist/m/c-KU3ZFADW.js +1 -0
- package/dist/m/c-L4WQSC27.js +1 -0
- package/dist/m/c-LFPHCXY3.js +1 -0
- package/dist/m/c-LRPUO2MX.js +1 -0
- package/dist/m/c-LWLBHLVC.js +3 -0
- package/dist/m/c-LZJPNR2W.js +1 -0
- package/dist/m/c-M2L47S2X.js +7 -0
- package/dist/m/c-MFP2ZWD4.js +1 -0
- package/dist/m/c-MKSQ4Y57.js +1 -0
- package/dist/m/c-MTQHWQC3.js +1 -0
- package/dist/m/c-N326R2JD.js +1 -0
- package/dist/m/c-N7JPUPGC.js +1 -0
- package/dist/m/c-NRPJEVJS.js +1 -0
- package/dist/m/c-NUFFJVVJ.js +1 -0
- package/dist/m/c-NUHP2XDB.js +1 -0
- package/dist/m/c-NUHSPT5P.js +1 -0
- package/dist/m/c-O72HVYSA.js +1 -0
- package/dist/m/c-OCSZ4QGN.js +1 -0
- package/dist/m/c-OIBUTDXI.js +1 -0
- package/dist/m/c-OIDRZKAF.js +1 -0
- package/dist/m/c-OW5QIGG3.js +1 -0
- package/dist/m/c-P7KNDG34.js +1 -0
- package/dist/m/c-PGRCK73F.js +1 -0
- package/dist/m/c-PQ5LK6QE.js +993 -0
- package/dist/m/c-PS5ARVWR.js +9 -0
- package/dist/m/c-PZ4XEPUP.js +2 -0
- package/dist/m/c-Q622NS2Y.js +1 -0
- package/dist/m/c-Q7NQD65V.js +1 -0
- package/dist/m/c-QH63LQOS.js +1 -0
- package/dist/m/c-QHIWXHRO.js +1 -0
- package/dist/m/c-QHWJ5ZIJ.js +1 -0
- package/dist/m/c-QICP2YR5.js +1 -0
- package/dist/m/c-QJ4OM3G6.js +1 -0
- package/dist/m/c-QNKREOL6.js +1 -0
- package/dist/m/c-R3L7ZJGB.js +2 -0
- package/dist/m/c-R7IWVINQ.js +1 -0
- package/dist/m/c-RM7J7BV2.js +1 -0
- package/dist/m/c-RSMOODDU.js +1 -0
- package/dist/m/c-RVMWGXEJ.js +1 -0
- package/dist/m/c-RYUXUUBX.js +1 -0
- package/dist/m/c-S4ZEH46B.js +9 -0
- package/dist/m/c-S7H2DRCB.js +1 -0
- package/dist/m/c-S7LK4KUE.js +1 -0
- package/dist/m/c-SDAXDM2D.js +1 -0
- package/dist/m/c-SGIA4IEQ.js +188 -0
- package/dist/m/c-SMBZG5X4.js +1 -0
- package/dist/m/c-SMGU7RT3.js +235 -0
- package/dist/m/c-SPIORRYS.js +1 -0
- package/dist/m/c-SWLRT66R.js +1 -0
- package/dist/m/c-SZGYW5HT.js +1 -0
- package/dist/m/c-TCCA5BZN.js +2 -0
- package/dist/m/c-TCJTVAFN.js +1 -0
- package/dist/m/c-TJ6WOJL3.js +67 -0
- package/dist/m/c-TQEMVJCS.js +1 -0
- package/dist/m/c-TRS6TM6O.js +1 -0
- package/dist/m/c-TYLXX4NF.js +21 -0
- package/dist/m/c-U62OB4BT.js +1 -0
- package/dist/m/c-U6YWUAR3.js +8 -0
- package/dist/m/c-UDCSU5G5.js +2 -0
- package/dist/m/c-UDUUJPFZ.js +1 -0
- package/dist/m/c-UGHH4MB3.js +1 -0
- package/dist/m/c-UL2YUY52.js +1 -0
- package/dist/m/c-VAK7SG37.js +1 -0
- package/dist/m/c-VDSS4K3Z.js +1 -0
- package/dist/m/c-VE6ZMYMC.js +1 -0
- package/dist/m/c-VG5XIN4T.js +1 -0
- package/dist/m/c-VHM5XQHK.js +1 -0
- package/dist/m/c-VHNSBD2M.js +1 -0
- package/dist/m/c-VI5RMSVY.js +1 -0
- package/dist/m/c-VKEDWYDF.js +1 -0
- package/dist/m/c-VRZN56XY.js +1 -0
- package/dist/m/c-W5MCHEGA.js +1 -0
- package/dist/m/c-WDC5GVKU.js +1 -0
- package/dist/m/c-WN5AY3OZ.js +1 -0
- package/dist/m/c-WNYBLIOZ.js +1 -0
- package/dist/m/c-WRBKEJD4.js +1 -0
- package/dist/m/c-WWXIDH4O.js +28 -0
- package/dist/m/c-WYFDLITL.js +1 -0
- package/dist/m/c-XCNTK76U.js +1 -0
- package/dist/m/c-XMS6DPBR.js +1 -0
- package/dist/m/c-XN6MBKI6.js +67 -0
- package/dist/m/c-XPELB6E5.js +1 -0
- package/dist/m/c-XQXZAO7N.js +1 -0
- package/dist/m/c-Y5HBBIQ4.js +1 -0
- package/dist/m/c-ZE46QDIH.js +1 -0
- package/dist/m/c-ZUCOKOHT.js +1 -0
- package/dist/m/c-ZVPVXTJF.js +4 -0
- package/dist/m/c-ZVRKXKM7.js +1 -0
- package/dist/m/c-ZWIOJGMT.js +1 -0
- package/dist/m/core/admin-attrs-QHOKPJ7W.js +1 -0
- package/dist/m/core/autosave-HRYGUWV6.js +1 -0
- package/dist/m/core/conflict-notice-6MROJN2L.js +1 -0
- package/dist/m/core/draft-mode-WSQAT67S.js +1 -0
- package/dist/m/core/host-permission-FNXVEFNE.js +1 -0
- package/dist/m/core/is-edit-mode-KTWA3O5N.js +1 -0
- package/dist/m/core/persist-JFYRHMRJ.js +3 -0
- package/dist/m/core/recovery-FLTCC2OC.js +1 -0
- package/dist/m/core/save-HQZ4S667.js +1 -0
- package/dist/m/core/save-core-KGQWFUNH.js +1 -0
- package/dist/m/core/snapshot-EGQZNT45.js +1 -0
- package/dist/m/core/unsaved-warning-IDJLD66H.js +1 -0
- package/dist/m/dom/all-APS5ZSKP.js +1 -0
- package/dist/m/dom/dom-helpers-L7OSR6S4.js +1 -0
- package/dist/m/events/index-RN2JNGBV.js +1 -0
- package/dist/m/internals/index-PVXGPUDA.js +1 -0
- package/dist/m/lib/cache-bust-MUMFXZK6.js +1 -0
- package/dist/m/lib/region-policy-SB2AWVG5.js +1 -0
- package/dist/m/loader-S4I7GKXR.js +1 -0
- package/dist/m/manifest-4C419D67.js +1 -0
- package/dist/m/manifest-edit-B077F288.js +1 -0
- package/dist/m/manifest.json +3988 -0
- package/dist/m/options/options-EJMS3K24.js +1 -0
- package/dist/m/page/editor-NNJA4OKD.js +202 -0
- package/dist/m/plugins/ai-edit-QN4PMMNL.js +6 -0
- package/dist/m/plugins/bind-text-NX46N5UV.js +1 -0
- package/dist/m/plugins/cms-HP3LSTPN.js +2293 -0
- package/dist/m/plugins/demo-RM5IR6AO.js +1 -0
- package/dist/m/plugins/derive-UAAA4V4S.js +1 -0
- package/dist/m/plugins/indicator-URDBBOQO.js +1 -0
- package/dist/m/plugins/live-HFWD4OIH.js +1 -0
- package/dist/m/plugins/menu-3HIEQSI6.js +138 -0
- package/dist/m/plugins/message-LQ6EDH4V.js +1 -0
- package/dist/m/plugins/page-JOKB6XPR.js +2 -0
- package/dist/m/plugins/page-view-NXOJHNW6.js +1 -0
- package/dist/m/plugins/people-SGPJKANK.js +1 -0
- package/dist/m/plugins/quickcrop-QNY3PKLD.js +26 -0
- package/dist/m/plugins/quickcrop-QNY3PKLD.js.LEGAL.txt +7 -0
- package/dist/m/plugins/richclay-NRQDSWX6.js +517 -0
- package/dist/m/plugins/richclay-NRQDSWX6.js.LEGAL.txt +1 -0
- package/dist/m/plugins/sortable-GWT4PWDV.js +1 -0
- package/dist/m/plugins/source-4ZRSAIYM.js +1 -0
- package/dist/m/plugins/undo-VDA5P7FH.js +1 -0
- package/dist/m/plugins/unsent-HJFLQJ2O.js +1 -0
- package/dist/m/plugins/upgrade-W7FG5VFG.js +1 -0
- package/dist/m/plugins/upload-WLYKK6TL.js +1 -0
- package/dist/m/plugins/visitor-drafts-LIDY7NH6.js +21 -0
- package/dist/m/plugins/visitor-drafts-owner-ZXCKBZE7.js +1 -0
- package/dist/m/plugins/wire-4N6GYAF6.js +1 -0
- package/dist/m/reader-core-DXYCURFF.js +68 -0
- package/dist/m/route/route-KOCZSEGN.js +1 -0
- package/dist/m/sync/live-sync-J7VMYTKS.js +1 -0
- package/dist/m/ui/index-3JLVI27O.js +1 -0
- package/dist/m/utils/index-4TJCVLT7.js +1 -0
- package/dist/m/vendor/Sortable.vendor-A755ITLN.js +3 -0
- package/dist/m/vendor/Sortable.vendor-A755ITLN.js.LEGAL.txt +1 -0
- package/dist/m/vendor/sap-core.vendor-A7BMUYZT.js +6 -0
- package/dist/offline-manifest.json +4034 -0
- package/dist/page/themes/light-1.css +430 -0
- package/dist/server/core.cjs +23748 -22855
- package/dist/server/offline-runtime.cjs +4954 -0
- package/dist/server/offline-runtime.mjs +4923 -0
- package/dist/server/rooms.mjs +9 -0
- package/docs/guide.md +1078 -669
- package/entries/all.js +2 -0
- package/entries/clay-data.js +1 -1
- package/entries/clay-dom.js +2 -0
- package/entries/clay-events.js +2 -0
- package/entries/clay-internals.js +2 -0
- package/entries/clay-options.js +2 -0
- package/entries/clay-router.js +2 -0
- package/entries/clay-ui.js +2 -0
- package/entries/clay-utils.js +2 -0
- package/entries/clay.js +2 -0
- package/entries/sap.js +6 -6
- package/fonts/ibm-plex-mono-LICENSE +93 -0
- package/fonts/ibm-plex-mono-latin-300-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-400-italic.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-LICENSE +93 -0
- package/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex.css +71 -0
- package/fonts/inter-LICENSE +93 -0
- package/fonts/inter-cyrillic-ext-wght-normal.woff2 +0 -0
- package/fonts/inter-cyrillic-wght-normal.woff2 +0 -0
- package/fonts/inter-greek-ext-wght-normal.woff2 +0 -0
- package/fonts/inter-greek-wght-normal.woff2 +0 -0
- package/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
- package/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/fonts/inter-vietnamese-wght-normal.woff2 +0 -0
- package/fonts/inter.css +62 -0
- package/fonts/newsreader-LICENSE +93 -0
- package/fonts/newsreader-latin-ext-opsz-normal.woff2 +0 -0
- package/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/fonts/newsreader-vietnamese-opsz-normal.woff2 +0 -0
- package/fonts/newsreader.css +26 -0
- package/fonts/work-sans-LICENSE +93 -0
- package/fonts/work-sans-latin-wght-normal.woff2 +0 -0
- package/fonts/work-sans.css +8 -0
- package/package.json +20 -3
- package/packed-contract.json +1 -0
- package/src/attrs/add-from.js +27 -4
- package/src/attrs/save-freeze.js +7 -52
- package/src/core/admin-attrs.js +119 -12
- package/src/core/admin-contenteditable.js +12 -10
- package/src/core/admin-inputs.js +14 -15
- package/src/core/admin-onclick.js +2 -0
- package/src/core/autosave.js +74 -21
- package/src/core/boot-phase.js +2 -1
- package/src/core/conflict-download.js +19 -23
- package/src/core/conflict-notice-ui.js +1173 -0
- package/src/core/conflict-notice.js +140 -697
- package/src/core/download.js +32 -0
- package/src/core/edit-mode.js +147 -14
- package/src/core/etag.js +30 -12
- package/src/core/host-meta.js +90 -8
- package/src/core/host-permission.js +29 -0
- package/src/core/is-edit-mode.js +145 -12
- package/src/core/mode-key.js +125 -0
- package/src/core/mode-lifecycle.js +544 -0
- package/src/core/mode-receipt.js +30 -0
- package/src/core/mode-refusal.js +13 -0
- package/src/core/mode-resources.js +52 -0
- package/src/core/mode-support.js +82 -0
- package/src/core/mode-switch.js +259 -0
- package/src/core/mode-transition.js +112 -0
- package/src/core/page-data-write.js +305 -0
- package/src/core/page-data.js +26 -227
- package/src/core/page-format-wire.js +4 -0
- package/src/core/page-format.js +58 -0
- package/src/core/persist.js +37 -9
- package/src/core/preserve-authored.js +114 -0
- package/src/core/recovery.js +772 -0
- package/src/core/runtime-url.js +105 -0
- package/src/core/save-core.js +113 -12
- package/src/core/save-replace.js +72 -0
- package/src/core/save-size-notice.js +134 -0
- package/src/core/save-size.js +140 -0
- package/src/core/save.js +806 -119
- package/src/core/snapshot.js +159 -11
- package/src/core/source-map.js +157 -9
- package/src/core/unsaved-warning.js +14 -4
- package/src/core/upgrade-run.js +408 -0
- package/src/core/version.js +18 -0
- package/src/lib/assets.js +30 -0
- package/src/lib/autosave-debug-gate.js +50 -0
- package/src/lib/autosave-scheduler.js +140 -0
- package/src/lib/boot-imports.js +8 -0
- package/src/lib/derived.js +3 -1
- package/src/lib/dirty-gate.js +15 -0
- package/src/lib/doc-storage.js +33 -0
- package/src/lib/effect.js +9 -4
- package/src/lib/mutation.js +4 -2
- package/src/lib/offline-runtime.js +226 -0
- package/src/lib/preload.js +48 -0
- package/src/lib/root-attrs.js +1 -1
- package/src/lib/trash.js +18 -0
- package/src/lib/undo/capture-move.js +152 -0
- package/src/live/local-channel.js +61 -0
- package/src/live/local-lane.js +60 -9
- package/src/live/server-lane.js +6 -3
- package/src/loader-logic.js +76 -15
- package/src/loader.js +218 -30
- package/src/page/adopt-boot.js +76 -22
- package/src/page/adopt.js +25 -4
- package/src/page/awareness.js +230 -0
- package/src/page/blocks.js +113 -6
- package/src/page/blocksel.js +20 -4
- package/src/page/board-face.js +13 -0
- package/src/page/board-panel.js +5 -17
- package/src/page/board-style.js +2 -13
- package/src/page/board-view.js +1 -11
- package/src/page/board-views.js +3 -0
- package/src/page/board.js +2 -2
- package/src/page/boot-pack.js +26 -0
- package/src/page/boot.js +237 -0
- package/src/page/chart-tables.js +11 -0
- package/src/page/chart.js +6 -10
- package/src/page/checklist.js +1 -1
- package/src/page/checkpoint-proof.js +289 -0
- package/src/page/chrome.js +431 -63
- package/src/page/csv-import.js +17 -2
- package/src/page/document-title-dom.js +52 -0
- package/src/page/document-title-runtime.js +90 -0
- package/src/page/document-title.js +12 -0
- package/src/page/drag.js +48 -13
- package/src/page/drop.js +2 -1
- package/src/page/editor.js +399 -90
- package/src/page/emoji-data.js +162 -0
- package/src/page/feature-loader.js +72 -0
- package/src/page/features/board.js +21 -0
- package/src/page/features/chart.js +11 -0
- package/src/page/features/code.js +13 -0
- package/src/page/features/dates.js +180 -0
- package/src/page/features/emoji.js +187 -0
- package/src/page/features/media.js +290 -0
- package/src/page/features/mentions.js +188 -0
- package/src/page/features/registry.js +28 -0
- package/src/page/features/table.js +383 -0
- package/src/page/{tool-view.js → features/tool.js} +33 -2
- package/src/page/format-codec.js +215 -0
- package/src/page/format-command.js +9 -0
- package/src/page/format-gate.js +179 -0
- package/src/page/format-host.js +54 -0
- package/src/page/format-level.js +157 -0
- package/src/page/format-native-commands.js +142 -0
- package/src/page/format-native.js +42 -0
- package/src/page/highlight-slot.js +23 -0
- package/src/page/highlight.js +30 -16
- package/src/page/history-intent.js +78 -0
- package/src/page/inline.js +45 -28
- package/src/page/items.js +67 -14
- package/src/page/link.js +1 -0
- package/src/page/markdown.js +112 -3
- package/src/page/media-views.js +3 -0
- package/src/page/media.js +33 -245
- package/src/page/mention-picker.js +99 -0
- package/src/page/merge.js +1 -1
- package/src/page/outline-cache.js +11 -0
- package/src/page/placeholder.js +27 -7
- package/src/page/projection.js +240 -51
- package/src/page/reader-patch.js +306 -0
- package/src/page/recover.js +1 -1
- package/src/page/rich/page-tool.js +1 -4
- package/src/page/runtime-owner.js +27 -0
- package/src/page/save-projection.js +46 -4
- package/src/page/save-states.js +1 -1
- package/src/page/schema.js +47 -0
- package/src/page/table-rect-key.js +3 -0
- package/src/page/table-select.js +4 -3
- package/src/page/table-style.js +1 -1
- package/src/page/table-views.js +3 -0
- package/src/page/table.js +8 -293
- package/src/page/themes/content.css +25 -1
- package/src/page/themes/light-1.css +163 -2
- package/src/page/themes/light-1.source.css +269 -0
- package/src/page/tool-capability.js +3 -0
- package/src/page/tool-views.js +3 -0
- package/src/page/view-hooks.js +32 -0
- package/src/page/view.js +390 -107
- package/src/page/ybind/awareness.js +172 -0
- package/src/page/ybind/binding.js +40 -5
- package/src/page/ybind/bridge.js +50 -47
- package/src/page/ybind/decode.js +52 -19
- package/src/page/ybind/doc.js +27 -2
- package/src/page/ybind/group.js +12 -3
- package/src/page/ybind/index.js +2 -0
- package/src/page/ybind/lineage.js +71 -0
- package/src/page/ybind/marks.js +26 -1
- package/src/page/ybind/migrate.js +48 -13
- package/src/page/ybind/moves.js +32 -21
- package/src/page/ybind/positions.js +50 -0
- package/src/page/ybind/provider.js +97 -24
- package/src/page/ybind/recovery-proof.js +191 -0
- package/src/page/ybind/recovery-replay.js +488 -0
- package/src/page/ybind/tokens.js +15 -6
- package/src/page/ybind/walk.js +10 -3
- package/src/page/ybind/writer.js +48 -4
- package/src/plugins/ai-edit.js +167 -32
- package/src/plugins/bind-text.js +218 -0
- package/src/plugins/cms.js +93 -0
- package/src/plugins/indicator.js +57 -5
- package/src/plugins/live.js +319 -35
- package/src/plugins/menu/claygoo.svg.js +1 -0
- package/src/plugins/menu/seo-head.js +323 -0
- package/src/plugins/menu/seo.js +849 -0
- package/src/plugins/menu.js +425 -0
- package/src/plugins/page-view.js +131 -0
- package/src/plugins/page.js +1131 -270
- package/src/plugins/people.js +158 -31
- package/src/plugins/richclay.js +119 -9
- package/src/plugins/sortable.js +370 -60
- package/src/plugins/source.js +189 -366
- package/src/plugins/undo.js +289 -19
- package/src/plugins/unsent.js +132 -0
- package/src/plugins/upgrade-run.js +1 -0
- package/src/plugins/upgrade.js +210 -0
- package/src/plugins/upload-task.js +571 -0
- package/src/plugins/upload-ui.js +265 -0
- package/src/plugins/upload.js +34 -153
- package/src/plugins/visitor-drafts/inert.js +32 -0
- package/src/plugins/visitor-drafts/intro.js +2 -1
- package/src/plugins/visitor-drafts/owner-chip.js +3 -0
- package/src/plugins/visitor-drafts/prompt.js +2 -2
- package/src/plugins/visitor-drafts-owner.js +85 -0
- package/src/plugins/visitor-drafts.js +31 -42
- package/src/plugins/wire.js +82 -1
- package/src/reader-core.js +26 -0
- package/src/recovery/conflicts.js +287 -0
- package/src/recovery/identity.js +154 -0
- package/src/recovery/store.js +792 -0
- package/src/recovery/undo.js +257 -0
- package/src/server/checkpoint/index.js +68 -4
- package/src/server/offline-runtime/index.js +214 -0
- package/src/server/rooms/index.js +2 -1
- package/src/server/rooms/live-data-rooms.js +2 -2
- package/src/server/rooms/page-admission.js +33 -0
- package/src/server/rooms/page-lineage.js +56 -0
- package/src/server/rooms/page-rebase.js +11 -5
- package/src/server/rooms/page-state.js +2 -0
- package/src/server/rooms/page-write-admission.js +9 -3
- package/src/source/session.js +705 -0
- package/src/sync/conflict-revert.js +5 -4
- package/src/sync/conflicts-edit.js +119 -0
- package/src/sync/conflicts-facade.js +49 -0
- package/src/sync/conflicts.js +99 -1
- package/src/sync/editing-marker.js +37 -6
- package/src/sync/editing-sender.js +8 -1
- package/src/sync/live-sync-edit.js +63 -0
- package/src/sync/live-sync.js +364 -119
- package/src/sync/local-presence.js +187 -0
- package/src/sync/merge-declarations.js +10 -0
- package/src/sync/merge-engine.js +12 -0
- package/src/sync/presence-store.js +412 -0
- package/src/sync/presence-target.js +243 -0
- package/src/sync/presence.js +72 -41
- package/src/sync/saved-handoff.js +200 -0
- package/src/sync/saved-stream.js +544 -0
- package/src/sync/version-guard.js +92 -0
- package/src/sync/wire-profile.js +81 -0
- package/src/ui/bevel-controls.js +2 -8
- package/src/ui/page-scheme.js +7 -0
- package/src/ui/skins/cms.js +1 -1
- package/src/ui/theme-config.js +150 -0
- package/src/ui/theme.js +6 -138
- package/src/ui/toast-lazy.js +11 -0
- package/src/vendor/LICENSES-optional.md +253 -0
- package/src/vendor/highlight.vendor.js +3 -0
- package/src/vendor/hljs-bash.vendor.js +2 -0
- package/src/vendor/hljs-css.vendor.js +2 -0
- package/src/vendor/hljs-javascript.vendor.js +2 -0
- package/src/vendor/hljs-json.vendor.js +2 -0
- package/src/vendor/hljs-python.vendor.js +2 -0
- package/src/vendor/hljs-xml.vendor.js +2 -0
- package/src/vendor/hyper-html-api-data.vendor.js +1 -1
- package/src/vendor/hyper-html-api-upgrade.vendor.js +5 -0
- package/src/vendor/hyper-morph-identity.vendor.js +2 -0
- package/src/vendor/hyper-morph-json.vendor.js +3 -0
- package/src/vendor/hyper-morph.vendor.js +6 -6
- package/src/vendor/hyper-undo.vendor.js +1 -1
- package/src/vendor/hypercms.vendor.js +169 -84
- package/src/vendor/marked.vendor.js +68 -0
- package/src/vendor/overtype.vendor.js +994 -0
- package/src/vendor/richclay.vendor.js +17 -17
- package/src/vendor/sap-core.vendor.js +5 -5
- package/src/vendor/sap-ownership.vendor.js +11 -7
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* clay.bindText — an editor textarea that lives outside the saved records.
|
|
3
|
+
*
|
|
4
|
+
* The textarea sits in a `clay="freeze"` region and edits one record's text
|
|
5
|
+
* element (for example `<pre><code class="entry-body">`). Every input is
|
|
6
|
+
* written into the record at once, so a save captures it as the record's text
|
|
7
|
+
* and a peer's merge of another paragraph keeps both edits. A change to the
|
|
8
|
+
* record from elsewhere (a peer's merge, a restored draft, a JSON API write) is
|
|
9
|
+
* shown in the textarea with the caret kept. During an IME composition nothing
|
|
10
|
+
* is written or shown, and when it ends both edits apply unless they touch the
|
|
11
|
+
* same stretch of text. Nothing here is Journal-specific: OverType, the
|
|
12
|
+
* timestamps and the note arrive as callbacks.
|
|
13
|
+
*
|
|
14
|
+
* The binding answers for its own lifecycle too: `flush()` reports whether the
|
|
15
|
+
* record now holds the text and refuses while a composition is running, `open()`
|
|
16
|
+
* and `close()` honor that refusal, and `dispose()` only detaches once the exit
|
|
17
|
+
* barrier has landed.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// Applies two edits to one text when each is one stretch of it (an IME composition always is) and the
|
|
21
|
+
// stretches do not overlap (two inserts at one point keep both); null when they do.
|
|
22
|
+
export function spliceMerge(base, local, remote) {
|
|
23
|
+
const span = (text) => {
|
|
24
|
+
let pre = 0;
|
|
25
|
+
const max = Math.min(base.length, text.length);
|
|
26
|
+
while (pre < max && base[pre] === text[pre]) pre++;
|
|
27
|
+
let suf = 0;
|
|
28
|
+
while (suf < max - pre && base[base.length - 1 - suf] === text[text.length - 1 - suf]) suf++;
|
|
29
|
+
return { start: pre, end: base.length - suf, text: text.slice(pre, text.length - suf) };
|
|
30
|
+
};
|
|
31
|
+
const l = span(local);
|
|
32
|
+
const r = span(remote);
|
|
33
|
+
if (l.end <= r.start) return base.slice(0, l.start) + l.text + base.slice(l.end, r.start) + r.text + base.slice(r.end);
|
|
34
|
+
if (r.end <= l.start) return base.slice(0, r.start) + r.text + base.slice(r.end, l.start) + l.text + base.slice(l.end);
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Where an offset in `before` lands in `after`, when the two differ in one stretch.
|
|
39
|
+
export function mapCaret(before, after, offset) {
|
|
40
|
+
let pre = 0;
|
|
41
|
+
const max = Math.min(before.length, after.length);
|
|
42
|
+
while (pre < max && before[pre] === after[pre]) pre++;
|
|
43
|
+
if (offset <= pre) return offset;
|
|
44
|
+
let suf = 0;
|
|
45
|
+
while (suf < max - pre && before[before.length - 1 - suf] === after[after.length - 1 - suf]) suf++;
|
|
46
|
+
return offset >= before.length - suf ? after.length - (before.length - offset) : after.length - suf;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function bindText(textarea, { onWrite, onShow, onConflict, onGone } = {}) {
|
|
50
|
+
const OBSERVE = { characterData: true, childList: true, subtree: true };
|
|
51
|
+
let field = textarea;
|
|
52
|
+
const ta = () => field;
|
|
53
|
+
let s = null; // { key, code, seen, composing, resolve }
|
|
54
|
+
let disposed = false;
|
|
55
|
+
const observer = new MutationObserver(() => {
|
|
56
|
+
observer.takeRecords();
|
|
57
|
+
if (s && !s.composing && s.code.textContent !== s.seen) reconcile(s.code.textContent);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// New durable input is the lifecycle's to admit, not the binding's: while a transition
|
|
61
|
+
// runs, a keystroke is not new input and is refused. A standalone page has no lifecycle
|
|
62
|
+
// and always admits.
|
|
63
|
+
const admitted = () => window.clay?.modeLifecycle?.canWrite?.() !== false;
|
|
64
|
+
|
|
65
|
+
// The record holds what the textarea holds. That is the only proof a flush landed: a
|
|
66
|
+
// callback that staged a conflict or a gone record has not made the text represented.
|
|
67
|
+
const represented = () => !!(s && s.code.isConnected && s.code.textContent === ta().value);
|
|
68
|
+
|
|
69
|
+
function write(value) {
|
|
70
|
+
const t = s.code.firstChild;
|
|
71
|
+
if (t && t.nodeType === 3 && !t.nextSibling) t.data = value;
|
|
72
|
+
else s.code.textContent = value;
|
|
73
|
+
observer.takeRecords();
|
|
74
|
+
s.seen = value;
|
|
75
|
+
onWrite?.(s.code);
|
|
76
|
+
}
|
|
77
|
+
function show(value) {
|
|
78
|
+
const el = ta();
|
|
79
|
+
const before = el.value;
|
|
80
|
+
const [a, b] = [mapCaret(before, value, el.selectionStart), mapCaret(before, value, el.selectionEnd)];
|
|
81
|
+
el.value = value;
|
|
82
|
+
if (document.activeElement === el) el.setSelectionRange(a, b);
|
|
83
|
+
s.seen = value;
|
|
84
|
+
onShow?.();
|
|
85
|
+
}
|
|
86
|
+
// The record changed while the textarea held text the record had not taken yet.
|
|
87
|
+
// `base` is the text both sides were editing, read before show() moves `seen`: a
|
|
88
|
+
// caller staging the losing side needs what the clash was measured against, not
|
|
89
|
+
// what the textarea holds afterwards. The second argument is additive, so a
|
|
90
|
+
// caller that only wants the typed string ignores it.
|
|
91
|
+
function reconcile(now) {
|
|
92
|
+
const typed = ta().value;
|
|
93
|
+
const base = s.seen;
|
|
94
|
+
const merged = typed === base ? now : spliceMerge(base, typed, now);
|
|
95
|
+
if (merged == null) {
|
|
96
|
+
onConflict?.(typed, { key: s.key, base, remote: now });
|
|
97
|
+
show(now);
|
|
98
|
+
return { ok: false, code: "conflict" };
|
|
99
|
+
}
|
|
100
|
+
if (merged !== now) write(merged);
|
|
101
|
+
show(merged);
|
|
102
|
+
return { ok: true };
|
|
103
|
+
}
|
|
104
|
+
// A record that cannot be resolved hands its text to `onGone` and is released: there is
|
|
105
|
+
// nothing left here that a later write could land in, and holding the detached element
|
|
106
|
+
// would refuse every record switch after it.
|
|
107
|
+
function rebind() {
|
|
108
|
+
const code = s.resolve ? s.resolve() : null;
|
|
109
|
+
if (!code) {
|
|
110
|
+
onGone?.(ta().value, { key: s.key, base: s.seen });
|
|
111
|
+
observer.disconnect();
|
|
112
|
+
s = null;
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
s.code = code;
|
|
116
|
+
observer.disconnect();
|
|
117
|
+
observer.observe(s.code, OBSERVE);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
// `captured` is the composition this binding already holds: it finishes through its own
|
|
121
|
+
// operation, so a closed admission does not throw away what the person was typing.
|
|
122
|
+
function input(captured = false) {
|
|
123
|
+
if (!s) return { ok: true };
|
|
124
|
+
if (s.composing) return { ok: false, code: "composition" };
|
|
125
|
+
if (!captured && !admitted()) return { ok: false, code: "busy" };
|
|
126
|
+
if (!s.code.isConnected && !rebind()) return { ok: false, code: "gone" };
|
|
127
|
+
const now = s.code.textContent;
|
|
128
|
+
if (now !== s.seen) return reconcile(now);
|
|
129
|
+
const value = ta().value;
|
|
130
|
+
if (value !== s.seen) write(value);
|
|
131
|
+
return { ok: true };
|
|
132
|
+
}
|
|
133
|
+
// A composition in progress is not something a flush may end on the person's behalf: it
|
|
134
|
+
// is refused, and `s.composing` stays exactly as it was. Everything else runs the input
|
|
135
|
+
// path above, and its answer says whether the record now holds the text.
|
|
136
|
+
function flush() {
|
|
137
|
+
if (!s) return { ok: true };
|
|
138
|
+
if (s.composing) return { ok: false, code: "composition" };
|
|
139
|
+
const result = input();
|
|
140
|
+
if (!result.ok) return result;
|
|
141
|
+
return represented() ? { ok: true } : { ok: false, code: "conflict" };
|
|
142
|
+
}
|
|
143
|
+
function open(textEl, options = {}) {
|
|
144
|
+
if (disposed) return { ok: false, code: "disposed" };
|
|
145
|
+
const key = options.key;
|
|
146
|
+
if (s && s.key === key) {
|
|
147
|
+
s.resolve = options.resolve;
|
|
148
|
+
if (s.code !== textEl || !s.code.isConnected) {
|
|
149
|
+
if (!rebind()) return { ok: false, code: "gone" };
|
|
150
|
+
return input();
|
|
151
|
+
}
|
|
152
|
+
return { ok: true };
|
|
153
|
+
}
|
|
154
|
+
// A refused flush keeps the open record and its observer: nothing was written, so
|
|
155
|
+
// switching records here would drop the text the refusal was protecting. A record that
|
|
156
|
+
// was gone has already handed its text over and released itself, so there is nothing
|
|
157
|
+
// left to protect and the switch goes ahead.
|
|
158
|
+
const flushed = flush();
|
|
159
|
+
if (!flushed.ok && s) return flushed;
|
|
160
|
+
observer.disconnect();
|
|
161
|
+
s = { key, code: textEl, seen: textEl.textContent, composing: false, resolve: options.resolve };
|
|
162
|
+
observer.observe(textEl, OBSERVE);
|
|
163
|
+
const el = ta();
|
|
164
|
+
el.value = s.seen;
|
|
165
|
+
el.setSelectionRange(0, 0);
|
|
166
|
+
onShow?.();
|
|
167
|
+
return { ok: true };
|
|
168
|
+
}
|
|
169
|
+
function close() {
|
|
170
|
+
const flushed = flush();
|
|
171
|
+
if (!flushed.ok && s) return flushed;
|
|
172
|
+
observer.disconnect();
|
|
173
|
+
s = null;
|
|
174
|
+
return { ok: true };
|
|
175
|
+
}
|
|
176
|
+
// Detaching only. The barrier has already succeeded when a lease disposes the binding, so
|
|
177
|
+
// this never flushes: a composition still in progress or text the record never took keeps
|
|
178
|
+
// the listeners where they are, and the caller is told why.
|
|
179
|
+
function dispose() {
|
|
180
|
+
if (disposed) return { ok: true };
|
|
181
|
+
if (s?.composing) return { ok: false, code: "composition" };
|
|
182
|
+
if (s && !represented()) return { ok: false, code: "pending-input" };
|
|
183
|
+
disposed = true;
|
|
184
|
+
observer.disconnect();
|
|
185
|
+
detach();
|
|
186
|
+
s = null;
|
|
187
|
+
return { ok: true };
|
|
188
|
+
}
|
|
189
|
+
function attach(next) {
|
|
190
|
+
if (disposed || !next || next === field) return;
|
|
191
|
+
detach();
|
|
192
|
+
field = next;
|
|
193
|
+
listen();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function onInput() { input(); }
|
|
197
|
+
function onCompositionStart() { if (s) s.composing = true; }
|
|
198
|
+
function onCompositionEnd() { if (s) { s.composing = false; input(true); } }
|
|
199
|
+
function listen() {
|
|
200
|
+
field.addEventListener("input", onInput);
|
|
201
|
+
field.addEventListener("compositionstart", onCompositionStart);
|
|
202
|
+
field.addEventListener("compositionend", onCompositionEnd);
|
|
203
|
+
}
|
|
204
|
+
function detach() {
|
|
205
|
+
field.removeEventListener("input", onInput);
|
|
206
|
+
field.removeEventListener("compositionstart", onCompositionStart);
|
|
207
|
+
field.removeEventListener("compositionend", onCompositionEnd);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
listen();
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
open, close, flush, dispose,
|
|
214
|
+
current: () => s && s.code,
|
|
215
|
+
attach,
|
|
216
|
+
composing: () => !!(s && s.composing),
|
|
217
|
+
};
|
|
218
|
+
}
|
package/src/plugins/cms.js
CHANGED
|
@@ -4,9 +4,102 @@
|
|
|
4
4
|
import { installSkin } from "../ui/vendor-skin.js";
|
|
5
5
|
import { CSS } from "../ui/skins/cms.js";
|
|
6
6
|
import { CSS as TOGGLE_CSS, ROOTS as TOGGLE_ROOTS } from "../ui/skins/cms-toggle.js";
|
|
7
|
+
import { cms as hypercms } from "../vendor/hypercms.vendor.js";
|
|
7
8
|
|
|
8
9
|
export { cms, default } from "../vendor/hypercms.vendor.js";
|
|
9
10
|
|
|
10
11
|
installSkin("cms", CSS);
|
|
11
12
|
// The toggle takes the page's scheme, so Bevel's face and ink resolve the way the page reads.
|
|
12
13
|
installSkin("cms-toggle", TOGGLE_CSS, { roots: TOGGLE_ROOTS });
|
|
14
|
+
|
|
15
|
+
const fault = (message, code) => Object.assign(new Error(`clay:cms: ${message}`), { code });
|
|
16
|
+
|
|
17
|
+
const isStale = (context) => {
|
|
18
|
+
if (!context) return false;
|
|
19
|
+
if (context.signal?.aborted) return true;
|
|
20
|
+
return typeof context.isCurrent === "function" && !context.isCurrent();
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// One edit session over the page the CMS edits, as a ClayJS lease. The source owns the
|
|
24
|
+
// session itself, so every method here is the source's own lifecycle call: `enable`
|
|
25
|
+
// opens and mounts, `resume` is the refused exit over the same session, and `dispose`
|
|
26
|
+
// goes through the CMS's teardown after the barrier.
|
|
27
|
+
//
|
|
28
|
+
// `quiesce` is the one call the lease shapes. The source answers for the work it still
|
|
29
|
+
// holds, an upload in flight or a painted preview, with `{ok:false}` rather than by
|
|
30
|
+
// tearing that work down: an exit refused there keeps the session, its buffers and the
|
|
31
|
+
// upload, and the controller resumes the same lease once the person finishes or
|
|
32
|
+
// discards it. The lease contract carries a refusal as the `code` a controller reports,
|
|
33
|
+
// so the non-ok answer is thrown as `pending-input`.
|
|
34
|
+
function cmsLease(source) {
|
|
35
|
+
let disposed = false;
|
|
36
|
+
return {
|
|
37
|
+
ready: source.ready,
|
|
38
|
+
enable() {
|
|
39
|
+
if (disposed) return;
|
|
40
|
+
source.enable();
|
|
41
|
+
},
|
|
42
|
+
quiesce() {
|
|
43
|
+
if (disposed) return;
|
|
44
|
+
const result = source.quiesce();
|
|
45
|
+
if (result && result.ok === false) {
|
|
46
|
+
throw Object.assign(fault("the CMS still has work to finish", result.code || "pending-input"), {
|
|
47
|
+
pending: result.pending,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
},
|
|
52
|
+
resume() {
|
|
53
|
+
if (disposed) return;
|
|
54
|
+
source.resume();
|
|
55
|
+
},
|
|
56
|
+
dispose() {
|
|
57
|
+
if (disposed) return;
|
|
58
|
+
disposed = true;
|
|
59
|
+
source.dispose();
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The boot this tab made, adopted instead of prepared. A page that opened the CMS itself
|
|
65
|
+
// (`?cms=true`) holds a session the source hands no lease out for, so it cannot be
|
|
66
|
+
// quiesced or torn down through the adapter and the caller keeps its reload instead;
|
|
67
|
+
// a boot that opened nothing has nothing to hand back, and this lease starts nothing.
|
|
68
|
+
function adopt() {
|
|
69
|
+
if (hypercms.isOpen) throw fault("the CMS this boot opened cannot be taken back", "unsupported-plugin");
|
|
70
|
+
const lease = cmsLease(hypercms.prepareModeLease({}));
|
|
71
|
+
return {
|
|
72
|
+
enable() {},
|
|
73
|
+
quiesce: () => lease.quiesce(),
|
|
74
|
+
resume: () => lease.resume(),
|
|
75
|
+
dispose: () => lease.dispose(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The CMS as a mode participant: the session the commit that enters edit opens, and the
|
|
81
|
+
* one the exit destroys.
|
|
82
|
+
*
|
|
83
|
+
* `prepare` is inert by construction, because the source's lease mounts nothing until
|
|
84
|
+
* `enable`; a vendor build without that lifecycle is refused here rather than opened
|
|
85
|
+
* beside the controller, where an exit would have no session to quiesce and no teardown
|
|
86
|
+
* to run. `order` is the source's: the CMS edits the page's own attributes and content,
|
|
87
|
+
* so it enters after the modules that prepare that page for editing, and it leaves
|
|
88
|
+
* first, while its session can still refuse an exit over an upload or a preview.
|
|
89
|
+
*/
|
|
90
|
+
export function cmsParticipant(options = {}) {
|
|
91
|
+
return {
|
|
92
|
+
id: "clay:cms",
|
|
93
|
+
order: 1000,
|
|
94
|
+
async prepare(context = {}) {
|
|
95
|
+
if (typeof hypercms.prepareModeLease !== "function") {
|
|
96
|
+
throw fault("this vendor build has no quiescable session", "unsupported-plugin");
|
|
97
|
+
}
|
|
98
|
+
if (isStale(context)) throw fault("prepared for a stale generation", "stale-document");
|
|
99
|
+
if (context.initial === true) return adopt();
|
|
100
|
+
return cmsLease(hypercms.prepareModeLease(options));
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { cmsParticipant as modeParticipant };
|
package/src/plugins/indicator.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { startsAtImport } from "../core/is-edit-mode.js";
|
|
2
2
|
import onDomReady from "../lib/dom-ready.js";
|
|
3
3
|
import { set, style } from "../lib/hostile-css.js";
|
|
4
4
|
import { bevelSurface, pageScheme } from "../ui/bevel-controls.js";
|
|
@@ -79,13 +79,65 @@ function show(state) {
|
|
|
79
79
|
if (!STICKY.has(state)) hideTimer = setTimeout(() => { set(node, "opacity", "0"); }, 2200);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
let listeners = null;
|
|
83
|
+
|
|
84
|
+
// Arming is idempotent: the plugin's own boot and a mode lease both ask for the same
|
|
85
|
+
// listeners, and one exit must be able to take all of them back.
|
|
86
|
+
function arm() {
|
|
84
87
|
saveFeedback.chip = true;
|
|
88
|
+
if (listeners) return;
|
|
89
|
+
listeners = new AbortController();
|
|
90
|
+
const { signal } = listeners;
|
|
85
91
|
for (const state of Object.keys(LABELS)) {
|
|
86
|
-
document.addEventListener("clay:save-" + state, () => show(state));
|
|
92
|
+
document.addEventListener("clay:save-" + state, () => show(state), { signal });
|
|
87
93
|
}
|
|
88
|
-
document.addEventListener("clay:page-save-state", (event) => show(event.detail?.state));
|
|
94
|
+
document.addEventListener("clay:page-save-state", (event) => show(event.detail?.state), { signal });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function disarm() {
|
|
98
|
+
listeners?.abort();
|
|
99
|
+
listeners = null;
|
|
100
|
+
clearTimeout(hideTimer);
|
|
101
|
+
hideTimer = null;
|
|
102
|
+
el?.remove();
|
|
103
|
+
el = null;
|
|
89
104
|
}
|
|
90
105
|
|
|
106
|
+
function init() {
|
|
107
|
+
if (!startsAtImport()) return;
|
|
108
|
+
arm();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The save chip as a mode lease.
|
|
113
|
+
*
|
|
114
|
+
* The chip owns no input: it reports a save somebody else is making, so an exit never
|
|
115
|
+
* waits on it. `quiesce` leaves the chip and its fade timer exactly as they were, which
|
|
116
|
+
* is what a refusal has to keep showing; `resume` has nothing to reopen. `initial: true`
|
|
117
|
+
* adopts the chip the boot already armed and arms nothing again. `dispose` (after the
|
|
118
|
+
* barrier) takes the chip, its listeners and its timer down, so a save event in view
|
|
119
|
+
* draws nothing.
|
|
120
|
+
*/
|
|
121
|
+
export function indicatorParticipant() {
|
|
122
|
+
return {
|
|
123
|
+
id: "clay:indicator",
|
|
124
|
+
order: 700,
|
|
125
|
+
prepare(context = {}) {
|
|
126
|
+
return {
|
|
127
|
+
enable() {
|
|
128
|
+
if (context.initial === true) return;
|
|
129
|
+
arm();
|
|
130
|
+
},
|
|
131
|
+
quiesce() {},
|
|
132
|
+
resume() {},
|
|
133
|
+
dispose() {
|
|
134
|
+
disarm();
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export { indicatorParticipant as modeParticipant };
|
|
142
|
+
|
|
91
143
|
onDomReady(init);
|