@panphora/clayjs 1.17.0 → 1.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/all.js +1 -1
- package/dist/clay-dom.js +1 -1
- package/dist/clay-events.js +1 -1
- package/dist/clay-internals.js +1 -1
- package/dist/clay-options.js +1 -1
- package/dist/clay-router.js +1 -1
- package/dist/clay-ui.js +1 -1
- package/dist/clay-utils.js +1 -1
- package/dist/clay.js +1 -1
- package/dist/clay.standalone.js +72474 -62090
- package/dist/m/attrs/{save-freeze-MYNVXREN.js → save-freeze-LWGF6XUN.js} +1 -1
- package/dist/m/c-2GRUM77Q.js +30 -0
- package/dist/m/c-2KIEGNC4.js +1 -0
- package/dist/m/{c-AMSNPOCX.js → c-2KL3BD52.js} +1 -1
- package/dist/m/c-2ZZBC45O.js +1 -0
- package/dist/m/c-372N6H3B.js +1 -0
- package/dist/m/{c-4WKFKEKF.js → c-3G2DGZUP.js} +1 -1
- package/dist/m/c-3LDGIBMN.js +1 -0
- package/dist/m/c-3O7OBDCM.js +1 -0
- package/dist/m/c-4ASQPRQL.js +1 -0
- package/dist/m/c-4TXNLX4K.js +6 -0
- package/dist/m/c-4YU3BR4D.js +6 -0
- package/dist/m/c-5734MF2P.js +1 -0
- package/dist/m/c-57XDY6HC.js +1 -0
- package/dist/m/{c-KAU6E43D.js → c-5B4YBZXC.js} +1 -1
- package/dist/m/c-5ONTYIUI.js +1 -0
- package/dist/m/c-5OOVFCJM.js +1 -0
- package/dist/m/{c-3XIRD4NU.js → c-5T6NZHNM.js} +1 -1
- package/dist/m/{c-74MGYWZF.js → c-5ZQV7KC4.js} +1 -1
- package/dist/m/{c-7OLLJPWP.js → c-6DB2OLRJ.js} +1 -1
- package/dist/m/c-6DNRCPNM.js +1 -0
- package/dist/m/c-6UGWFMQC.js +2 -0
- package/dist/m/c-7K4SCQB7.js +1 -0
- package/dist/m/c-7MG5RU63.js +1 -0
- package/dist/m/c-7PRJCA3E.js +1 -0
- package/dist/m/c-A6L3FMUS.js +1 -0
- package/dist/m/c-AMU3BPPR.js +4 -0
- package/dist/m/{c-Y5HBBIQ4.js → c-AMYEFA2E.js} +1 -1
- package/dist/m/c-AQYCG7QW.js +1 -0
- package/dist/m/c-ATKAOH23.js +1 -0
- package/dist/m/c-B5CS55WR.js +1 -0
- package/dist/m/c-B5UJQT7W.js +1 -0
- package/dist/m/c-B7J4K2AE.js +3 -0
- package/dist/m/c-BHZYSHW4.js +1 -0
- package/dist/m/{c-VHM5XQHK.js → c-BIJALSRD.js} +1 -1
- package/dist/m/c-BJ7YQ5QZ.js +1 -0
- package/dist/m/{c-KIPQJX4B.js → c-BRLCTNMC.js} +1 -1
- package/dist/m/{c-VE6ZMYMC.js → c-BUAYFEV5.js} +1 -1
- package/dist/m/c-C6IPRG34.js +1 -0
- package/dist/m/{c-KU3ZFADW.js → c-CAS3NND4.js} +1 -1
- package/dist/m/{c-PS5ARVWR.js → c-CCQ25GFY.js} +1 -1
- package/dist/m/c-CJFDLD43.js +1 -0
- package/dist/m/c-COPTL5WB.js +1 -0
- package/dist/m/c-D3E4WJ4M.js +166 -0
- package/dist/m/c-D5IKEKXW.js +7 -0
- package/dist/m/c-DHBRA6DL.js +1 -0
- package/dist/m/c-DKLS74XB.js +72 -0
- package/dist/m/c-DVYGFTSK.js +3 -0
- package/dist/m/c-E3ZXARWA.js +1 -0
- package/dist/m/c-EK63G3CG.js +1 -0
- package/dist/m/c-ERQSNR6K.js +13 -0
- package/dist/m/c-EVYAISP3.js +1 -0
- package/dist/m/c-EXKHPOVC.js +3 -0
- package/dist/m/{c-QJ4OM3G6.js → c-FWKHM4E7.js} +1 -1
- package/dist/m/{c-4Q2XTQ2N.js → c-GBKB5WDL.js} +1 -1
- package/dist/m/c-GNDL3TKB.js +1 -0
- package/dist/m/c-GRWMD6O5.js +1 -0
- package/dist/m/c-GRXHHFPO.js +1 -0
- package/dist/m/c-HG2C77BM.js +4 -0
- package/dist/m/c-HHGJBU4D.js +1 -0
- package/dist/m/c-HMV6P4RX.js +1 -0
- package/dist/m/c-HMYWIHFG.js +1 -0
- package/dist/m/c-HT2DKBV2.js +1 -0
- package/dist/m/c-I2SCCUEW.js +1 -0
- package/dist/m/{c-TJ6WOJL3.js → c-ICJYHABF.js} +2 -2
- package/dist/m/c-IMZCWYHR.js +7 -0
- package/dist/m/c-IVMD3FEM.js +1 -0
- package/dist/m/{c-WDC5GVKU.js → c-IVTRVENZ.js} +1 -1
- package/dist/m/c-JKZJIUIP.js +1 -0
- package/dist/m/{c-UDUUJPFZ.js → c-JNLX3RJB.js} +1 -1
- package/dist/m/c-K3ADYNLU.js +1 -0
- package/dist/m/c-KGHVFRR3.js +1 -0
- package/dist/m/{c-5QWQ7A5L.js → c-KJJPV77R.js} +1 -1
- package/dist/m/{c-CZUSOB7V.js → c-KNPDOMDY.js} +1 -1
- package/dist/m/{c-EZU56NQV.js → c-KP64LT2A.js} +2 -2
- package/dist/m/c-KQ7E3PYY.js +1 -0
- package/dist/m/c-L3F5ZLIV.js +1 -0
- package/dist/m/{c-3RUU4TPX.js → c-L42OLXWM.js} +3 -2
- package/dist/m/c-L5VFATT6.js +1 -0
- package/dist/m/c-L7JL5TL3.js +3 -0
- package/dist/m/c-LKSL4AUJ.js +1 -0
- package/dist/m/c-M6FNQCTQ.js +1 -0
- package/dist/m/c-MCOOHCSG.js +1 -0
- package/dist/m/c-MHI3GYKF.js +1 -0
- package/dist/m/c-MWXFLW4J.js +1 -0
- package/dist/m/{c-5RJFTLSF.js → c-NEL7HQW3.js} +1 -1
- package/dist/m/{c-DCXOXBF3.js → c-NQJRVJ56.js} +1 -1
- package/dist/m/c-NWX3MFT4.js +1 -0
- package/dist/m/{c-HPURYVZS.js → c-OJYM642Q.js} +1 -1
- package/dist/m/c-OKXI52N7.js +1 -0
- package/dist/m/{c-R3L7ZJGB.js → c-OPLUZR3A.js} +1 -1
- package/dist/m/{c-GSFIGKOP.js → c-OTMKN2OO.js} +1 -1
- package/dist/m/{c-6NC5I2TV.js → c-OYRZ7XG2.js} +1 -1
- package/dist/m/{c-EVCQ3BKA.js → c-P3OFYUMA.js} +1 -1
- package/dist/m/c-PLN76GF3.js +6 -0
- package/dist/m/c-PLP4JKFC.js +1 -0
- package/dist/m/c-Q26MME6N.js +1 -0
- package/dist/m/{c-S7H2DRCB.js → c-Q3XOWZEV.js} +1 -1
- package/dist/m/{c-FRLHSY7E.js → c-QIKT6SKM.js} +1 -1
- package/dist/m/c-QIXT3Q7C.js +28 -0
- package/dist/m/c-QO4HNGCQ.js +1 -0
- package/dist/m/{c-JU3NK25H.js → c-R27DWQKX.js} +1 -1
- package/dist/m/{c-RSMOODDU.js → c-R2XUODVY.js} +1 -1
- package/dist/m/{c-QNKREOL6.js → c-R7LBFMF5.js} +1 -1
- package/dist/m/c-RND3G2S2.js +1 -0
- package/dist/m/{c-Q622NS2Y.js → c-S2U6NJU4.js} +1 -1
- package/dist/m/c-SPZPGD3R.js +1 -0
- package/dist/m/c-SW4YEG2D.js +8 -0
- package/dist/m/c-T637T7SN.js +1 -0
- package/dist/m/c-TJAXGIRV.js +1 -0
- package/dist/m/{c-RYUXUUBX.js → c-TNEM3RNM.js} +1 -1
- package/dist/m/c-TTB5EK4S.js +32 -0
- package/dist/m/c-U7SHNWDH.js +1 -0
- package/dist/m/c-UDHIVLYH.js +20 -0
- package/dist/m/{c-BBVGTQG7.js → c-UGNV5MFB.js} +1 -1
- package/dist/m/{c-QICP2YR5.js → c-UORXLSD3.js} +1 -1
- package/dist/m/c-UPD33ZPE.js +1 -0
- package/dist/m/c-URSMSFCB.js +1 -0
- package/dist/m/c-UY4QX42B.js +1 -0
- package/dist/m/c-V44KWI2L.js +4 -0
- package/dist/m/c-VILENZTD.js +1 -0
- package/dist/m/{c-HDDEEL77.js → c-VJYEVRYK.js} +1 -1
- package/dist/m/{c-SMBZG5X4.js → c-VR2BJ4AN.js} +1 -1
- package/dist/m/c-W4JCVLAB.js +1 -0
- package/dist/m/c-W6DQSHXI.js +135 -0
- package/dist/m/c-WBGWGOM7.js +1 -0
- package/dist/m/{c-4L3BTFRK.js → c-WCXLG3MV.js} +1 -1
- package/dist/m/c-WGW764WX.js +1 -0
- package/dist/m/c-WMRJKQ2V.js +5 -0
- package/dist/m/c-WNTYKCDG.js +1 -0
- package/dist/m/c-WQWIRWO3.js +72 -0
- package/dist/m/c-X5LNHET5.js +1 -0
- package/dist/m/{c-I2ZATQCD.js → c-X5TSXZYJ.js} +2 -2
- package/dist/m/c-XGH4GS2T.js +1 -0
- package/dist/m/c-Y6F2FORL.js +1 -0
- package/dist/m/c-YBKHUAK7.js +10 -0
- package/dist/m/c-YBSS55KU.js +20 -0
- package/dist/m/c-YCLU4UNT.js +2 -0
- package/dist/m/c-YVZ2L7CE.js +1 -0
- package/dist/m/c-ZK4GIZH2.js +1 -0
- package/dist/m/c-ZRXJD4G6.js +1 -0
- package/dist/m/c-ZWBI4HYK.js +1 -0
- package/dist/m/core/{admin-attrs-QHOKPJ7W.js → admin-attrs-YY7T5FGU.js} +1 -1
- package/dist/m/core/autosave-S6OMNDCK.js +1 -0
- package/dist/m/core/conflict-notice-IWHMHH43.js +1 -0
- package/dist/m/core/{host-permission-FNXVEFNE.js → host-permission-6EVJGNPL.js} +1 -1
- package/dist/m/core/is-edit-mode-GCX6767E.js +1 -0
- package/dist/m/core/{persist-JFYRHMRJ.js → persist-UKXV5KLA.js} +1 -1
- package/dist/m/core/recovery-DRFZRJED.js +1 -0
- package/dist/m/core/save-LYY7K6U7.js +1 -0
- package/dist/m/core/save-core-MKRPSEEO.js +1 -0
- package/dist/m/core/snapshot-NU3YM6GR.js +1 -0
- package/dist/m/core/unsaved-warning-7QTKEN7Z.js +1 -0
- package/dist/m/internals/{index-PVXGPUDA.js → index-TGLQINN3.js} +1 -1
- package/dist/m/loader-3BBNZZGM.js +1 -0
- package/dist/m/manifest-26C55578.js +1 -0
- package/dist/m/manifest-edit-4396A009.js +1 -0
- package/dist/m/manifest.json +2111 -1573
- package/dist/m/page/{editor-NNJA4OKD.js → editor-6LRB3GE4.js} +123 -21
- package/dist/m/plugins/ai-edit-UTV7YO2I.js +6 -0
- package/dist/m/plugins/{cms-HP3LSTPN.js → cms-LRAOZHT7.js} +9 -9
- package/dist/m/plugins/{demo-RM5IR6AO.js → demo-OYO5GCAO.js} +1 -1
- package/dist/m/plugins/{derive-UAAA4V4S.js → derive-FRE5JJQE.js} +1 -1
- package/dist/m/plugins/indicator-4VDXWYTD.js +1 -0
- package/dist/m/plugins/live-AD4H6XSL.js +1 -0
- package/dist/m/plugins/menu-M5WW7DBF.js +1 -0
- package/dist/m/plugins/page-MD3T2ZX3.js +2 -0
- package/dist/m/plugins/page-view-PAWVZNFY.js +1 -0
- package/dist/m/plugins/{people-SGPJKANK.js → people-JCHVPF7P.js} +1 -1
- package/dist/m/plugins/quickcrop-BQ5YYFCH.js +26 -0
- package/dist/m/plugins/{richclay-NRQDSWX6.js → richclay-KLGETK77.js} +2 -2
- package/dist/m/plugins/sortable-4S6SQC3D.js +1 -0
- package/dist/m/plugins/source-TJXOIOYY.js +1 -0
- package/dist/m/plugins/undo-NLPGCJQY.js +1 -0
- package/dist/m/plugins/{unsent-HJFLQJ2O.js → unsent-OA4RGBUT.js} +1 -1
- package/dist/m/plugins/upgrade-HSUNDNJD.js +1 -0
- package/dist/m/plugins/{upload-WLYKK6TL.js → upload-NHGJXZK2.js} +1 -1
- package/dist/m/plugins/visitor-drafts-BW43DGY3.js +20 -0
- package/dist/m/plugins/visitor-drafts-owner-7ODQG7JX.js +1 -0
- package/dist/m/plugins/{wire-4N6GYAF6.js → wire-VBWXEXU2.js} +1 -1
- package/dist/m/reader-core-4W2KYEWQ.js +77 -0
- package/dist/m/route/route-62CHXL5B.js +1 -0
- package/dist/m/sync/live-sync-MO5DH33W.js +1 -0
- package/dist/m/ui/index-IVWN2QC4.js +1 -0
- package/dist/m/vendor/sap-core.vendor-RN4ZVY4X.js +6 -0
- package/dist/offline-manifest.json +1367 -930
- package/dist/page/themes/light-1.css +8 -7
- package/dist/server/core.cjs +1440 -288
- package/dist/server/offline-runtime.cjs +63 -63
- package/dist/server/offline-runtime.mjs +63 -63
- package/dist/server/page-compaction-worker.cjs +3710 -0
- package/dist/server/rooms.mjs +5 -0
- package/docs/guide.md +653 -101
- package/entries/sap.js +5 -5
- package/package.json +1 -1
- package/src/core/admin-contenteditable.js +5 -2
- package/src/core/admin-inputs.js +1 -0
- package/src/core/admin-onclick.js +2 -1
- package/src/core/conflict-notice-ui.js +4 -7
- package/src/core/download.js +2 -2
- package/src/core/host-meta.js +38 -0
- package/src/core/is-edit-mode.js +17 -1
- package/src/core/mode-key.js +125 -19
- package/src/core/mode-support.js +5 -0
- package/src/core/mode-transition.js +20 -6
- package/src/core/preserve-authored.js +4 -4
- package/src/core/recovery.js +121 -33
- package/src/core/save-accepted.js +33 -0
- package/src/core/save-core.js +106 -31
- package/src/core/save-job.js +108 -0
- package/src/core/save-prepare.js +53 -0
- package/src/core/save-size-notice.js +3 -1
- package/src/core/save-slices.js +15 -0
- package/src/core/save.js +557 -127
- package/src/core/serialize-steps.js +109 -0
- package/src/core/snapshot.js +170 -39
- package/src/core/source-map.js +83 -38
- package/src/core/stale-host-notice.js +1 -0
- package/src/core/upgrade-run.js +59 -8
- package/src/dom/active-element.js +5 -0
- package/src/lib/assets.js +1 -0
- package/src/lib/slice.js +65 -0
- package/src/lib/uimotion.js +774 -0
- package/src/lib/unsaved-state.js +2 -2
- package/src/live/fast-lane.js +10 -3
- package/src/live/local-lane.js +202 -11
- package/src/live/ops.js +16 -0
- package/src/live/page-compaction.js +162 -0
- package/src/live/server-lane.js +1 -0
- package/src/live/store.js +11 -3
- package/src/loader-logic.js +3 -1
- package/src/loader.js +14 -4
- package/src/page/adopt-boot.js +2 -1
- package/src/page/awareness.js +33 -2
- package/src/page/blocks.js +89 -27
- package/src/page/boot-pack.js +1 -1
- package/src/page/chart-tables.js +21 -3
- package/src/page/chart.js +406 -63
- package/src/page/checklist.js +10 -135
- package/src/page/checkpoint-proof.js +7 -1
- package/src/page/chrome.js +250 -51
- package/src/page/clipboard-shape.js +126 -0
- package/src/page/drag.js +33 -3
- package/src/page/editor.js +136 -25
- package/src/page/export-assets.js +357 -0
- package/src/page/export-html.js +209 -0
- package/src/page/export-markdown.js +361 -0
- package/src/page/features/checklist.js +428 -0
- package/src/page/features/export-html.js +189 -0
- package/src/page/features/export-markdown.js +169 -0
- package/src/page/features/import-markdown.js +349 -0
- package/src/page/features/media.js +61 -5
- package/src/page/features/registry.js +18 -0
- package/src/page/features/table.js +373 -83
- package/src/page/features/title-cover.js +331 -0
- package/src/page/features/title-icon.js +213 -0
- package/src/page/features/toc.js +87 -0
- package/src/page/format-command.js +25 -1
- package/src/page/format-gate.js +68 -18
- package/src/page/format-host.js +17 -0
- package/src/page/format-native-commands.js +21 -5
- package/src/page/image-actions.js +64 -0
- package/src/page/import-markdown.js +262 -0
- package/src/page/items.js +135 -17
- package/src/page/markdown.js +6 -2
- package/src/page/media.js +35 -119
- package/src/page/placeholder.js +14 -1
- package/src/page/projection.js +98 -10
- package/src/page/recover.js +10 -12
- package/src/page/recovery-ui.js +464 -0
- package/src/page/rich/chart.js +63 -7
- package/src/page/save-projection.js +28 -0
- package/src/page/save-states.js +13 -3
- package/src/page/schema.js +19 -3
- package/src/page/table-paste.js +3 -1
- package/src/page/table-style.js +4 -4
- package/src/page/table.js +44 -2
- package/src/page/themes/light-1.css +8 -7
- package/src/page/themes/light-1.source.css +8 -7
- package/src/page/toc-link.js +31 -0
- package/src/page/toc.js +5 -0
- package/src/page/view-hooks.js +38 -12
- package/src/page/view.js +13 -0
- package/src/page/ybind/binding.js +88 -5
- package/src/page/ybind/bridge.js +187 -20
- package/src/page/ybind/containment.js +162 -0
- package/src/page/ybind/doc.js +17 -9
- package/src/page/ybind/file-debt.js +63 -0
- package/src/page/ybind/layout.js +7 -2
- package/src/page/ybind/marks.js +1 -1
- package/src/page/ybind/moves.js +5 -4
- package/src/page/ybind/origins.js +106 -4
- package/src/page/ybind/parts.js +8 -1
- package/src/page/ybind/provider.js +113 -17
- package/src/page/ybind/recovery-proof.js +32 -9
- package/src/page/ybind/recovery-replay.js +558 -15
- package/src/page/ybind/recovery.js +174 -45
- package/src/page/ybind/table.js +67 -11
- package/src/page/ybind/walk-delta.js +258 -0
- package/src/page/ybind/walk.js +54 -29
- package/src/page/ybind/writer.js +1 -1
- package/src/plugins/ai-edit.js +13 -9
- package/src/plugins/indicator-chip.js +91 -0
- package/src/plugins/indicator.js +13 -80
- package/src/plugins/live.js +89 -14
- package/src/plugins/menu/actions.js +196 -0
- package/src/plugins/menu/people.js +279 -0
- package/src/plugins/menu/placement.js +121 -0
- package/src/plugins/menu/preferences.js +9 -0
- package/src/plugins/menu/seo.js +316 -397
- package/src/plugins/menu/style.js +171 -0
- package/src/plugins/menu/variants.js +296 -0
- package/src/plugins/menu.js +186 -183
- package/src/plugins/page-view.js +3 -2
- package/src/plugins/page.js +249 -44
- package/src/plugins/sortable.js +8 -1
- package/src/plugins/source.js +6 -0
- package/src/plugins/upgrade.js +51 -17
- package/src/plugins/upload-ui.js +12 -17
- package/src/plugins/visitor-drafts/bottom-ui.js +12 -4
- package/src/plugins/visitor-drafts/intro-style.js +7 -2
- package/src/plugins/visitor-drafts/intro.js +5 -3
- package/src/plugins/visitor-drafts/owner-chip.js +8 -12
- package/src/plugins/visitor-drafts/prompt.js +11 -9
- package/src/plugins/visitor-drafts/source.js +4 -3
- package/src/plugins/visitor-drafts/store.js +138 -9
- package/src/plugins/visitor-drafts/ui-memory.js +2 -2
- package/src/plugins/visitor-drafts-owner.js +4 -6
- package/src/plugins/visitor-drafts.js +5 -3
- package/src/recovery/store.js +1 -1
- package/src/route/route.js +4 -0
- package/src/server/rooms/index.js +5 -1
- package/src/server/rooms/live-data-rooms.js +302 -50
- package/src/server/rooms/page-compaction-worker.js +12 -0
- package/src/server/rooms/page-compactor.js +92 -0
- package/src/server/rooms/page-room-conformance.js +461 -0
- package/src/source/parse-steps.js +94 -0
- package/src/source/session.js +233 -57
- package/src/sync/editing-sender.js +12 -0
- package/src/sync/live-sync-edit.js +22 -2
- package/src/sync/live-sync.js +150 -23
- package/src/sync/page-relay.js +52 -0
- package/src/sync/presence-store.js +44 -4
- package/src/sync/presence.js +6 -3
- package/src/sync/saved-stream.js +11 -6
- package/src/ui/bevel-controls.js +1 -0
- package/src/ui/bevel-dialog.js +5 -2
- package/src/ui/editor-ui.js +77 -0
- package/src/ui/page-colour.js +281 -0
- package/src/ui/toast.js +16 -7
- package/src/vendor/hyper-html-api-upgrade.vendor.js +2 -2
- package/src/vendor/hyper-undo.vendor.js +1 -1
- package/src/vendor/hypercms.vendor.js +9 -9
- package/src/vendor/parse5.vendor.js +2 -2
- package/src/vendor/sap-core.vendor.js +5 -5
- package/dist/m/c-2SPVQSHC.js +0 -1
- package/dist/m/c-336SGU5W.js +0 -1
- package/dist/m/c-3H6BZDNJ.js +0 -6
- package/dist/m/c-4DFEJ2PO.js +0 -3
- package/dist/m/c-56QRZTZH.js +0 -1
- package/dist/m/c-5J4E7O4Y.js +0 -4
- package/dist/m/c-5LKDWQTL.js +0 -19
- package/dist/m/c-5V3MOVJT.js +0 -1
- package/dist/m/c-6AZOGAPE.js +0 -1
- package/dist/m/c-6CRUUXOX.js +0 -5
- package/dist/m/c-6HMB24EV.js +0 -1
- package/dist/m/c-6KEVEQ7L.js +0 -1
- package/dist/m/c-A3E3NIMC.js +0 -1
- package/dist/m/c-BQ6LOBEE.js +0 -1
- package/dist/m/c-BTDI4Y23.js +0 -1
- package/dist/m/c-CJ3A7ZKE.js +0 -1
- package/dist/m/c-CQHPGKX2.js +0 -1
- package/dist/m/c-DFS4XZJV.js +0 -2
- package/dist/m/c-DNENWY4O.js +0 -1
- package/dist/m/c-E4LIR5X5.js +0 -1
- package/dist/m/c-FDNHHZY5.js +0 -1
- package/dist/m/c-FROJUZMV.js +0 -1
- package/dist/m/c-G2JPKCTP.js +0 -1
- package/dist/m/c-GB6TU7WV.js +0 -1
- package/dist/m/c-GFJJEBTU.js +0 -1
- package/dist/m/c-GJAEGGXY.js +0 -1
- package/dist/m/c-GOWBDM6J.js +0 -1
- package/dist/m/c-HFKUVACH.js +0 -1
- package/dist/m/c-HHDFCNHV.js +0 -1
- package/dist/m/c-IEM4NTCS.js +0 -1
- package/dist/m/c-JDCX26UP.js +0 -25
- package/dist/m/c-KGVGROZT.js +0 -1
- package/dist/m/c-KQ6TYJAP.js +0 -135
- package/dist/m/c-LFPHCXY3.js +0 -1
- package/dist/m/c-LRPUO2MX.js +0 -1
- package/dist/m/c-LWLBHLVC.js +0 -3
- package/dist/m/c-M2L47S2X.js +0 -7
- package/dist/m/c-MFP2ZWD4.js +0 -1
- package/dist/m/c-MKSQ4Y57.js +0 -1
- package/dist/m/c-NUFFJVVJ.js +0 -1
- package/dist/m/c-NUHSPT5P.js +0 -1
- package/dist/m/c-O72HVYSA.js +0 -1
- package/dist/m/c-OIBUTDXI.js +0 -1
- package/dist/m/c-OW5QIGG3.js +0 -1
- package/dist/m/c-PGRCK73F.js +0 -1
- package/dist/m/c-Q7NQD65V.js +0 -1
- package/dist/m/c-QH63LQOS.js +0 -1
- package/dist/m/c-R7IWVINQ.js +0 -1
- package/dist/m/c-RM7J7BV2.js +0 -1
- package/dist/m/c-S4ZEH46B.js +0 -9
- package/dist/m/c-SDAXDM2D.js +0 -1
- package/dist/m/c-SMGU7RT3.js +0 -235
- package/dist/m/c-SPIORRYS.js +0 -1
- package/dist/m/c-SWLRT66R.js +0 -1
- package/dist/m/c-TCJTVAFN.js +0 -1
- package/dist/m/c-TQEMVJCS.js +0 -1
- package/dist/m/c-TYLXX4NF.js +0 -21
- package/dist/m/c-U62OB4BT.js +0 -1
- package/dist/m/c-U6YWUAR3.js +0 -8
- package/dist/m/c-UDCSU5G5.js +0 -2
- package/dist/m/c-VI5RMSVY.js +0 -1
- package/dist/m/c-VRZN56XY.js +0 -1
- package/dist/m/c-W5MCHEGA.js +0 -1
- package/dist/m/c-WNYBLIOZ.js +0 -1
- package/dist/m/c-WWXIDH4O.js +0 -28
- package/dist/m/c-XCNTK76U.js +0 -1
- package/dist/m/c-XMS6DPBR.js +0 -1
- package/dist/m/c-ZUCOKOHT.js +0 -1
- package/dist/m/c-ZVPVXTJF.js +0 -4
- package/dist/m/c-ZVRKXKM7.js +0 -1
- package/dist/m/core/autosave-HRYGUWV6.js +0 -1
- package/dist/m/core/conflict-notice-6MROJN2L.js +0 -1
- package/dist/m/core/is-edit-mode-KTWA3O5N.js +0 -1
- package/dist/m/core/recovery-FLTCC2OC.js +0 -1
- package/dist/m/core/save-HQZ4S667.js +0 -1
- package/dist/m/core/save-core-KGQWFUNH.js +0 -1
- package/dist/m/core/snapshot-EGQZNT45.js +0 -1
- package/dist/m/core/unsaved-warning-IDJLD66H.js +0 -1
- package/dist/m/loader-S4I7GKXR.js +0 -1
- package/dist/m/manifest-4C419D67.js +0 -1
- package/dist/m/manifest-edit-B077F288.js +0 -1
- package/dist/m/plugins/ai-edit-QN4PMMNL.js +0 -6
- package/dist/m/plugins/indicator-URDBBOQO.js +0 -1
- package/dist/m/plugins/live-HFWD4OIH.js +0 -1
- package/dist/m/plugins/menu-3HIEQSI6.js +0 -138
- package/dist/m/plugins/page-JOKB6XPR.js +0 -2
- package/dist/m/plugins/page-view-NXOJHNW6.js +0 -1
- package/dist/m/plugins/quickcrop-QNY3PKLD.js +0 -26
- package/dist/m/plugins/sortable-GWT4PWDV.js +0 -1
- package/dist/m/plugins/source-4ZRSAIYM.js +0 -1
- package/dist/m/plugins/undo-VDA5P7FH.js +0 -1
- package/dist/m/plugins/upgrade-W7FG5VFG.js +0 -1
- package/dist/m/plugins/visitor-drafts-LIDY7NH6.js +0 -21
- package/dist/m/plugins/visitor-drafts-owner-ZXCKBZE7.js +0 -1
- package/dist/m/reader-core-DXYCURFF.js +0 -68
- package/dist/m/route/route-KOCZSEGN.js +0 -1
- package/dist/m/sync/live-sync-J7VMYTKS.js +0 -1
- package/dist/m/ui/index-3JLVI27O.js +0 -1
- package/dist/m/vendor/sap-core.vendor-A7BMUYZT.js +0 -6
- /package/dist/m/{c-FILLTJA7.js → c-QTTJYJMA.js} +0 -0
- /package/dist/m/plugins/{quickcrop-QNY3PKLD.js.LEGAL.txt → quickcrop-BQ5YYFCH.js.LEGAL.txt} +0 -0
- /package/dist/m/plugins/{richclay-NRQDSWX6.js.LEGAL.txt → richclay-KLGETK77.js.LEGAL.txt} +0 -0
package/src/page/ybind/walk.js
CHANGED
|
@@ -41,21 +41,24 @@ function walkFlow(pd, index) {
|
|
|
41
41
|
const liveSources = new Set(liveBySource.keys());
|
|
42
42
|
const movedSources = new Set();
|
|
43
43
|
const retired = [];
|
|
44
|
+
const copyBoundary = (client, clock) => {
|
|
45
|
+
const sourceKey = `${client}.${clock}`;
|
|
46
|
+
const record = index.boundaryOf({ client, clock });
|
|
47
|
+
if (!record || record.kind !== "copy") return;
|
|
48
|
+
if (intents.copyActive.has(sourceKey)) { if (record.recoveryOf) movedSources.add(record.recoveryOf); }
|
|
49
|
+
else if (liveSources.has(sourceKey)) retired.push({ key: copyActiveKey(sourceKey), sourceKey, source: { client, clock }, operationId: null, blockId: record.blockId, end: null, sv: [], legacy: false, implicit: true });
|
|
50
|
+
};
|
|
51
|
+
const markers = index.markers?.() ?? null;
|
|
44
52
|
const candidateSets = new Map();
|
|
45
|
-
|
|
53
|
+
if (markers) {
|
|
54
|
+
for (const entry of markers.records) if (entry.live && entry.kind === "boundary") copyBoundary(entry.client, entry.clock);
|
|
55
|
+
} else for (const key of pd.origins.keys()) {
|
|
46
56
|
let parts;
|
|
47
57
|
try { parts = JSON.parse(key); } catch { continue; }
|
|
48
58
|
if (!Array.isArray(parts) || parts.length !== 3 || (parts[0] !== "boundary" && parts[0] !== "alias")) continue;
|
|
49
59
|
const [, client, clock] = parts;
|
|
50
60
|
if (!Number.isSafeInteger(client) || client < 0 || !Number.isSafeInteger(clock) || clock < 0) continue;
|
|
51
|
-
if (parts[0] === "boundary")
|
|
52
|
-
const sourceKey = `${client}.${clock}`;
|
|
53
|
-
const record = index.boundaryOf({ client, clock });
|
|
54
|
-
if (record && record.kind === "copy") {
|
|
55
|
-
if (intents.copyActive.has(sourceKey)) { if (record.recoveryOf) movedSources.add(record.recoveryOf); }
|
|
56
|
-
else if (liveSources.has(sourceKey)) retired.push({ key: copyActiveKey(sourceKey), sourceKey, source: { client, clock }, operationId: null, blockId: record.blockId, end: null, sv: [], legacy: false, implicit: true });
|
|
57
|
-
}
|
|
58
|
-
}
|
|
61
|
+
if (parts[0] === "boundary") copyBoundary(client, clock);
|
|
59
62
|
const clocks = candidateSets.get(client) ?? candidateSets.set(client, new Set()).get(client);
|
|
60
63
|
clocks.add(clock);
|
|
61
64
|
}
|
|
@@ -113,7 +116,7 @@ function walkFlow(pd, index) {
|
|
|
113
116
|
for (const key of restore.covers) set.add(key);
|
|
114
117
|
}
|
|
115
118
|
const recoveredMarkers = new Map();
|
|
116
|
-
for (let it = pd.flow._start; it; it = it.right) {
|
|
119
|
+
if (restoredSources.size) for (let it = pd.flow._start; it; it = it.right) {
|
|
117
120
|
if (it.deleted) continue;
|
|
118
121
|
const source = it.content instanceof Y.ContentEmbed ? markerSource(it, it.content.embed && it.content.embed.b) : null;
|
|
119
122
|
if (source === null) continue;
|
|
@@ -131,9 +134,13 @@ function walkFlow(pd, index) {
|
|
|
131
134
|
const segs = [];
|
|
132
135
|
const orphans = [];
|
|
133
136
|
const hidden = [];
|
|
134
|
-
const fences = [];
|
|
137
|
+
const fences = [], stops = [];
|
|
135
138
|
let cur = null, prevId = "start", hiding = null, at = 0;
|
|
136
139
|
const cattrs = {};
|
|
140
|
+
let styled = null;
|
|
141
|
+
// The format state a block starts and ends with, so one block can be walked again on its
|
|
142
|
+
// own (walk-delta.js) and the next block's marks proven unchanged.
|
|
143
|
+
const fmt = () => { for (const key in cattrs) return { ...cattrs }; return null; };
|
|
137
144
|
const typeOf = (id) => { const m = pd.attrs.get(id); return (m && m.get("t")) || "paragraph"; };
|
|
138
145
|
const hideUnit = (len) => {
|
|
139
146
|
if (!len) return;
|
|
@@ -145,12 +152,16 @@ function walkFlow(pd, index) {
|
|
|
145
152
|
const id = `recovered:${sourceKey}`;
|
|
146
153
|
const t = root ? root.type : "paragraph";
|
|
147
154
|
const opaque = !Object.hasOwn(schema.nodes, t);
|
|
148
|
-
|
|
155
|
+
const f = fmt();
|
|
156
|
+
if (cur) cur.fmtOut = f;
|
|
157
|
+
cur = { kind: "b", id, baseId: id, brk: { client: it.id.client, clock: it.id.clock }, implicit: false, runs: [], len: 1, atom: !opaque && !schema.nodes[t]?.isTextblock, opaque, recovered: true, restored: !moved, sourceKey, t, fields: root ? root.attrs : null, fmtIn: f, fmtOut: null };
|
|
149
158
|
segs.push(cur);
|
|
150
159
|
prevId = id;
|
|
151
160
|
};
|
|
152
161
|
const open = (id, brk, implicit) => {
|
|
153
|
-
|
|
162
|
+
const f = fmt();
|
|
163
|
+
if (cur) cur.fmtOut = f;
|
|
164
|
+
cur = { kind: "b", id, baseId: id, brk, implicit, runs: [], len: implicit ? 0 : 1, atom: false, items: !implicit && (markerCount.get(id) ?? 0) > 1 ? [] : null, fmtIn: f, fmtOut: null };
|
|
154
165
|
if (!implicit) {
|
|
155
166
|
cur.t = typeOf(id);
|
|
156
167
|
// A type this runtime has no schema for still owns the text and marks up to
|
|
@@ -175,15 +186,15 @@ function walkFlow(pd, index) {
|
|
|
175
186
|
if (a.legacy && a.text) orphans.push({ key: a.key, id: a.blockId, text: a.text, h: hashText(a.text) });
|
|
176
187
|
hidden.push({ key: a.key, sourceKey: a.sourceKey, blockId: a.blockId, end: a.end, sv: a.sv, at: a.at, live: a.live, items: a.items });
|
|
177
188
|
};
|
|
178
|
-
const matchesEnd = (it, end) => {
|
|
179
|
-
if (covers(it, end)) return true;
|
|
189
|
+
const matchesEnd = (it, end, after = -1) => {
|
|
190
|
+
if (covers(it, end) && end.clock > after) return true;
|
|
180
191
|
return markerIdsWithin(it).some((id) => {
|
|
181
|
-
if (!pd.origins.has(aliasKey(id.client, id.clock))) return false;
|
|
192
|
+
if (id.clock <= after || !pd.origins.has(aliasKey(id.client, id.clock))) return false;
|
|
182
193
|
const resolved = index.resolve(id);
|
|
183
194
|
return resolved.client === end.client && resolved.clock === end.clock;
|
|
184
195
|
});
|
|
185
196
|
};
|
|
186
|
-
const markerClocks = new Map([...candidateSets].map(([client, clocks]) => [client, [...clocks].sort((a, b) => a - b)]));
|
|
197
|
+
const markerClocks = markers ? markers.clocks : new Map([...candidateSets].map(([client, clocks]) => [client, [...clocks].sort((a, b) => a - b)]));
|
|
187
198
|
const markerIdsWithin = (it) => {
|
|
188
199
|
const clocks = markerClocks.get(it.id.client) ?? [];
|
|
189
200
|
let lo = 0, hi = clocks.length;
|
|
@@ -192,6 +203,16 @@ function walkFlow(pd, index) {
|
|
|
192
203
|
for (let i = lo; i < clocks.length && clocks[i] < it.id.clock + it.length; i++) ids.push({ client: it.id.client, clock: clocks[i] });
|
|
193
204
|
return ids;
|
|
194
205
|
};
|
|
206
|
+
const deletedEdgesIn = (it, after = -1) => (it.deleted ? markerIdsWithin(it).flatMap((id) => {
|
|
207
|
+
if (id.clock <= after) return [];
|
|
208
|
+
const sourceKey = idKey(index.resolve(id));
|
|
209
|
+
const record = index.boundaryOf(id);
|
|
210
|
+
if (!record || (record.kind !== "removed" && record.kind !== "copy") || liveSources.has(sourceKey)) return [];
|
|
211
|
+
return [{ blockId: record.blockId, sourceKey }];
|
|
212
|
+
}) : []);
|
|
213
|
+
// `after` limits an end to what lies past a removal's own source: Yjs merges adjacent deleted
|
|
214
|
+
// items, so a removal can start and end inside the same one, on some replicas and not others.
|
|
215
|
+
const endsIn = (it, a, { deletedEdges, boundary = false, edge, after = -1 }) => a.end ? matchesEnd(it, a.end, after) : a.implicit ? boundary || deletedEdges.some((e) => e.sourceKey !== a.sourceKey) : (boundary && edge !== a.blockId) || deletedEdges.some((e) => e.blockId !== a.blockId);
|
|
195
216
|
const proj = [];
|
|
196
217
|
const endsOf = (removal) => ({ blockId: removal.blockId, end: removal.end ? parseKey(removal.end) : null, implicit: removal.implicit === true, sourceKey: removal.sourceKey });
|
|
197
218
|
for (let it = pd.flow._start; it; it = it.right) {
|
|
@@ -200,13 +221,8 @@ function walkFlow(pd, index) {
|
|
|
200
221
|
if (hiding || proj.length) {
|
|
201
222
|
const edge = !it.deleted && it.content instanceof Y.ContentEmbed ? it.content.embed.b : undefined;
|
|
202
223
|
const boundary = edge !== undefined && boundarySource(it, edge) === null;
|
|
203
|
-
const deletedEdges =
|
|
204
|
-
|
|
205
|
-
const record = index.boundaryOf(id);
|
|
206
|
-
if (!record || record.kind !== "removed" || liveSources.has(sourceKey)) return [];
|
|
207
|
-
return [{ blockId: record.blockId, sourceKey }];
|
|
208
|
-
}) : [];
|
|
209
|
-
const ends = (a) => a.end ? matchesEnd(it, a.end) : a.implicit ? boundary || deletedEdges.some((e) => e.sourceKey !== a.sourceKey) : (boundary && edge !== a.blockId) || deletedEdges.some((e) => e.blockId !== a.blockId);
|
|
224
|
+
const deletedEdges = deletedEdgesIn(it);
|
|
225
|
+
const ends = (a) => endsIn(it, a, { deletedEdges, boundary, edge });
|
|
210
226
|
if (hiding) {
|
|
211
227
|
const keep = [];
|
|
212
228
|
for (const a of hiding.active) { if (ends(a)) settle(a); else keep.push(a); }
|
|
@@ -220,6 +236,7 @@ function walkFlow(pd, index) {
|
|
|
220
236
|
}
|
|
221
237
|
const removals = removalStarts.get(it);
|
|
222
238
|
if (removals) {
|
|
239
|
+
if (it.deleted) stops.push({ client: it.id.client, clock: it.id.clock, len: it.length });
|
|
223
240
|
if (!hiding && exposed(removals[0].sourceKey)) {
|
|
224
241
|
if (!it.deleted) hideUnit(it.length);
|
|
225
242
|
proj.push({ active: removals.map(endsOf), sourceKey: removals[0].sourceKey, root: null });
|
|
@@ -228,14 +245,17 @@ function walkFlow(pd, index) {
|
|
|
228
245
|
if (!hiding && it.deleted) fences.push({ client: it.id.client, clock: it.id.clock });
|
|
229
246
|
for (const removal of removals) {
|
|
230
247
|
const a = { legacy: false, implicit: removal.implicit === true, key: removal.key, sourceKey: removal.sourceKey, blockId: removal.blockId, end: removal.end ? parseKey(removal.end) : null, sv: removal.sv, at: here, live: !it.deleted, items: [] };
|
|
248
|
+
const after = it.deleted && covers(it, removal.source) ? removal.source.clock : null;
|
|
249
|
+
if (after !== null && endsIn(it, a, { deletedEdges: deletedEdgesIn(it, after), after })) { settle(a); continue; }
|
|
231
250
|
if (hiding) hiding.active.push(a);
|
|
232
251
|
else hiding = { active: [a], len: 0, resume: cur };
|
|
233
252
|
}
|
|
234
|
-
if (!it.deleted) hiding.len += it.length;
|
|
253
|
+
if (hiding && !it.deleted) hiding.len += it.length;
|
|
235
254
|
continue;
|
|
236
255
|
}
|
|
237
256
|
const start = starts.get(it);
|
|
238
257
|
if (start) {
|
|
258
|
+
if (it.deleted) stops.push({ client: it.id.client, clock: it.id.clock, len: it.length });
|
|
239
259
|
if (!hiding && exposed(start.key)) {
|
|
240
260
|
if (!it.deleted) hideUnit(it.length);
|
|
241
261
|
proj.push({ active: [{ blockId: start.blockId, end: start.end }], sourceKey: start.key, root: null });
|
|
@@ -249,7 +269,7 @@ function walkFlow(pd, index) {
|
|
|
249
269
|
}
|
|
250
270
|
if (it.deleted) continue;
|
|
251
271
|
const c = it.content;
|
|
252
|
-
if (c instanceof Y.ContentFormat) { if (c.value === null) delete cattrs[c.key]; else cattrs[c.key] = c.value; continue; }
|
|
272
|
+
if (c instanceof Y.ContentFormat) { if (c.value === null) delete cattrs[c.key]; else cattrs[c.key] = c.value; styled = null; continue; }
|
|
253
273
|
if (hiding) {
|
|
254
274
|
if (c instanceof Y.ContentString || c instanceof Y.ContentEmbed) {
|
|
255
275
|
const piece = c instanceof Y.ContentString ? c.str : c.embed.b !== undefined ? "\u00b6" : "\n";
|
|
@@ -286,13 +306,18 @@ function walkFlow(pd, index) {
|
|
|
286
306
|
}
|
|
287
307
|
if (c instanceof Y.ContentString) {
|
|
288
308
|
if (!cur || cur.atom) open(`~${prevId}`, null, true);
|
|
289
|
-
const
|
|
290
|
-
|
|
309
|
+
const code = cur.t === "code_block";
|
|
310
|
+
if (!styled || styled.code !== code) {
|
|
311
|
+
const marks = marksFromAttributes(cattrs, cur.t);
|
|
312
|
+
styled = { code, marks, mk: marksKey(marks) };
|
|
313
|
+
}
|
|
314
|
+
cur.runs.push({ text: c.str, marks: styled.marks, mk: styled.mk });
|
|
291
315
|
if (cur.items) cur.items.push({ at: here, id: idKey(it.id), client: it.id.client, clock: it.id.clock, length: it.length, kind: "text", text: c.str, blockId: null, raw: { ...cattrs } });
|
|
292
316
|
cur.len += c.str.length;
|
|
293
317
|
}
|
|
294
318
|
}
|
|
295
319
|
if (hiding) { for (const a of hiding.active) settle(a); flush(); }
|
|
320
|
+
if (cur) cur.fmtOut = fmt();
|
|
296
321
|
const groups = new Map();
|
|
297
322
|
for (const s of segs) {
|
|
298
323
|
if (s.kind !== "b" || s.implicit) continue;
|
|
@@ -336,5 +361,5 @@ function walkFlow(pd, index) {
|
|
|
336
361
|
}
|
|
337
362
|
tokens += s.len;
|
|
338
363
|
}
|
|
339
|
-
return { visible, holes, orphans, tokens, copies, hidden, removals: lostCopies.length ? [...removals, ...lostCopies] : removals, fences };
|
|
364
|
+
return { visible, holes, orphans, tokens, copies, hidden, removals: lostCopies.length ? [...removals, ...lostCopies] : removals, fences, stops };
|
|
340
365
|
}
|
package/src/page/ybind/writer.js
CHANGED
|
@@ -146,7 +146,7 @@ const fenceAfter = (pd, yIdx, fences) => {
|
|
|
146
146
|
|
|
147
147
|
// Yjs places an insertion after every deleted item to its right. A hidden range that starts at a
|
|
148
148
|
// deleted item would then swallow text typed just before it, so the fence counts as live for the call.
|
|
149
|
-
const beforeFence = (pd, yIdx, fences, fn) => {
|
|
149
|
+
export const beforeFence = (pd, yIdx, fences, fn) => {
|
|
150
150
|
const fence = fenceAfter(pd, yIdx, fences);
|
|
151
151
|
if (!fence) return fn();
|
|
152
152
|
fence.deleted = false;
|
package/src/plugins/ai-edit.js
CHANGED
|
@@ -44,13 +44,14 @@
|
|
|
44
44
|
import { loadedEngine, mergeEngine } from "../sync/merge-engine.js";
|
|
45
45
|
import Mutation from "../lib/mutation.js";
|
|
46
46
|
import { startsAtImport } from "../core/is-edit-mode.js";
|
|
47
|
+
import { deepActiveElement } from "../dom/active-element.js";
|
|
47
48
|
import { holdAllSaves, releaseAllSaves } from "../core/save.js";
|
|
48
49
|
import { STRIP_FROM_SAVE, SNAPSHOT_REMOVE_SELECTOR } from "../lib/region-policy.js";
|
|
49
50
|
import { enableContentEditable } from "../core/admin-contenteditable.js";
|
|
50
51
|
import onDomReady from "../lib/dom-ready.js";
|
|
51
52
|
import wire from "./wire.js";
|
|
52
53
|
import { set } from "../lib/hostile-css.js";
|
|
53
|
-
import { bevelBox, bevelButton, bevelSurface, bevelText, bevelInput, bevelIconButton, pageScheme, setShown, RUNTIME_ONLY } from "../ui/bevel-controls.js";
|
|
54
|
+
import { bevelBox, bevelButton, bevelSurface, bevelText, bevelInput, bevelIconButton, pageScheme, paintLook, setShown, RUNTIME_ONLY } from "../ui/bevel-controls.js";
|
|
54
55
|
import { TOKENS, GLYPHS, FONT_SANS, FONT_MONO, SHADOW } from "../ui/bevel.js";
|
|
55
56
|
|
|
56
57
|
const HELPER = "ai-edit";
|
|
@@ -237,7 +238,7 @@ function sessionMorph(s, content, { rewind = false } = {}) {
|
|
|
237
238
|
}
|
|
238
239
|
HyperMorph.morph(document.body, content, {
|
|
239
240
|
morphStyle: 'outerHTML',
|
|
240
|
-
restoreFocus:
|
|
241
|
+
restoreFocus: document.activeElement?.localName !== 'clay-editor-ui',
|
|
241
242
|
scripts,
|
|
242
243
|
callbacks: {
|
|
243
244
|
beforeNodeRemoved: node => !(node.nodeType === 1 && node.matches(STRIP_FROM_SAVE))
|
|
@@ -711,6 +712,7 @@ function syncBubble() {
|
|
|
711
712
|
if (!doc) return;
|
|
712
713
|
const wanted = !barMode && helperState === 'ready' && !!doc.querySelector('[data-edit-id]');
|
|
713
714
|
setShown(docBubble, wanted, 'inline-grid');
|
|
715
|
+
if (wanted) paintLook(docBubble);
|
|
714
716
|
}
|
|
715
717
|
|
|
716
718
|
// The selected words stay marked while the person types, through the CSS Custom
|
|
@@ -757,6 +759,7 @@ function placeBubble() {
|
|
|
757
759
|
right: beside ? `${Math.round((document.documentElement.clientWidth || window.innerWidth) - rect.left + 8)}px` : '16px',
|
|
758
760
|
bottom: beside ? `${Math.round((document.documentElement.clientHeight || window.innerHeight) - rect.bottom)}px` : '16px',
|
|
759
761
|
});
|
|
762
|
+
paintLook(docBubble);
|
|
760
763
|
}
|
|
761
764
|
|
|
762
765
|
// ---------------------------------------------------------------- hover chip
|
|
@@ -770,9 +773,9 @@ function showChipFor(unit) {
|
|
|
770
773
|
chip.pin({
|
|
771
774
|
left: Math.min(rect.right + 8, window.innerWidth - 34) + 'px',
|
|
772
775
|
top: Math.max(8, rect.top) + 'px',
|
|
773
|
-
'color-scheme': pageScheme(),
|
|
774
776
|
});
|
|
775
777
|
setShown(chip, true, 'inline-grid');
|
|
778
|
+
paintLook(chip);
|
|
776
779
|
}
|
|
777
780
|
|
|
778
781
|
function hideChip() {
|
|
@@ -808,9 +811,9 @@ function showChipForSelection() {
|
|
|
808
811
|
chip.pin({
|
|
809
812
|
left: Math.min(end.right + 6, window.innerWidth - 34) + 'px',
|
|
810
813
|
top: Math.max(8, end.top + end.height / 2 - 13) + 'px',
|
|
811
|
-
'color-scheme': pageScheme(),
|
|
812
814
|
});
|
|
813
815
|
setShown(chip, true, 'inline-grid');
|
|
816
|
+
paintLook(chip);
|
|
814
817
|
}
|
|
815
818
|
|
|
816
819
|
// Compose-only messages: the host's switch being off and a request too large to send
|
|
@@ -850,10 +853,10 @@ function showBar(mode) {
|
|
|
850
853
|
setShown(control, controls.includes(control), 'inline-flex');
|
|
851
854
|
}
|
|
852
855
|
hideChip();
|
|
853
|
-
set(bar, 'color-scheme', pageScheme());
|
|
854
856
|
setShown(bar, true, 'flex');
|
|
855
857
|
syncBubble();
|
|
856
858
|
positionChrome();
|
|
859
|
+
paintLook(bar);
|
|
857
860
|
// The bar opens on the control that belongs to its state, and a state change moves
|
|
858
861
|
// focus only when the button holding it has just gone away.
|
|
859
862
|
const first = controls[0];
|
|
@@ -950,8 +953,6 @@ function openPanel(el, quote) {
|
|
|
950
953
|
anchorEl = el;
|
|
951
954
|
anchorRange = range ? range.cloneRange() : null;
|
|
952
955
|
hideChip();
|
|
953
|
-
set(panel, 'color-scheme', pageScheme());
|
|
954
|
-
set(ring, 'color-scheme', pageScheme());
|
|
955
956
|
setShown(panel, true);
|
|
956
957
|
pendingSelection = quote;
|
|
957
958
|
const shown = quote ? (quote.text.trim().length > 400 ? quote.text.trim().slice(0, 400) + '\u2026' : quote.text.trim()) : '';
|
|
@@ -962,6 +963,8 @@ function openPanel(el, quote) {
|
|
|
962
963
|
applyHelperState();
|
|
963
964
|
positionChrome();
|
|
964
965
|
fitTextarea();
|
|
966
|
+
paintLook(panel);
|
|
967
|
+
paintLook(ring);
|
|
965
968
|
textarea.focus();
|
|
966
969
|
refreshHelperState();
|
|
967
970
|
}
|
|
@@ -1001,6 +1004,7 @@ function closePanelForSend() {
|
|
|
1001
1004
|
textarea.value = '';
|
|
1002
1005
|
fitTextarea();
|
|
1003
1006
|
positionChrome();
|
|
1007
|
+
paintLook(ring);
|
|
1004
1008
|
}
|
|
1005
1009
|
|
|
1006
1010
|
// The target is gone from the page: whatever was live for it ends, and no observer,
|
|
@@ -1031,7 +1035,7 @@ function isShortcut(event) {
|
|
|
1031
1035
|
|
|
1032
1036
|
// A field the page owns keeps its own Ctrl+J, and so does the panel's own box.
|
|
1033
1037
|
function pageOwnsFocus() {
|
|
1034
|
-
const el =
|
|
1038
|
+
const el = deepActiveElement();
|
|
1035
1039
|
if (!el || el === document.body) return false;
|
|
1036
1040
|
if (panel && panel.contains(el)) return !panel.hidden;
|
|
1037
1041
|
return el.matches('input,textarea,select');
|
|
@@ -1045,7 +1049,7 @@ const PAGE_FIELD = 'input,textarea,select,[contenteditable=""],[contenteditable=
|
|
|
1045
1049
|
function escapeIsMine(event) {
|
|
1046
1050
|
if (event.defaultPrevented) return false;
|
|
1047
1051
|
if (document.querySelector(MODAL_SELECTOR)) return false;
|
|
1048
|
-
const el =
|
|
1052
|
+
const el = deepActiveElement();
|
|
1049
1053
|
if (!el || el === document.body) return true;
|
|
1050
1054
|
if (panel.contains(el) || bar.contains(el)) return true;
|
|
1051
1055
|
if (el.isContentEditable === true) return false;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// The save chip's drawing: loaded at the person's first input or the first save state,
|
|
2
|
+
// so a page nobody edits never pays for the surface it is drawn with.
|
|
3
|
+
import { set, style } from "../lib/hostile-css.js";
|
|
4
|
+
import { bevelSurface, pageScheme, paintLook } from "../ui/bevel-controls.js";
|
|
5
|
+
import { TOKENS, FONT_SANS } from "../ui/bevel.js";
|
|
6
|
+
import { saveFeedback } from "../core/save-feedback.js";
|
|
7
|
+
|
|
8
|
+
// No 'conflict' here on purpose. core/conflict-notice.js owns that state now,
|
|
9
|
+
// and it ships in every document rather than only the ones that turned this chip on.
|
|
10
|
+
// Both listen to clay:save-conflict, so keeping a label here put a chip in the corner
|
|
11
|
+
// saying the same thing as the bar at the same moment. Dropping it from this side
|
|
12
|
+
// leaves core unaware that this plugin exists, which is the direction that
|
|
13
|
+
// dependency has to point.
|
|
14
|
+
const LABELS = {
|
|
15
|
+
saving: "Saving…",
|
|
16
|
+
saved: "Saved",
|
|
17
|
+
error: "Couldn't save",
|
|
18
|
+
offline: "Offline, not saved",
|
|
19
|
+
retrying: "Saving…",
|
|
20
|
+
blocked: "Can't save here",
|
|
21
|
+
pending: "Saving…",
|
|
22
|
+
acknowledged: "Saving…",
|
|
23
|
+
checkpointed: "Saved",
|
|
24
|
+
unavailable: "Can't store changes: download a copy",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// States that stay on screen instead of fading: a save still in flight, one that keeps
|
|
28
|
+
// trying, one the host will not take without help, and where the journal says the work is.
|
|
29
|
+
const STICKY = new Set(["saving", "retrying", "blocked", "pending", "acknowledged", "unavailable"]);
|
|
30
|
+
|
|
31
|
+
const ALARMING = new Set(["error", "offline", "blocked", "unavailable"]);
|
|
32
|
+
|
|
33
|
+
const REST = [`background:${TOKENS.surface}`, `color:${TOKENS.ink}`, `border-color:${TOKENS["line-2"]}`];
|
|
34
|
+
const ALARM = [
|
|
35
|
+
`background:${TOKENS["ox-soft"]}`,
|
|
36
|
+
`color:${TOKENS.ox}`,
|
|
37
|
+
`border-color:color-mix(in srgb, ${TOKENS.ox} 28%, ${TOKENS["ox-soft"]})`,
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
let el = null;
|
|
41
|
+
let hideTimer = null;
|
|
42
|
+
|
|
43
|
+
function ensure() {
|
|
44
|
+
// Looked up on every call, never trusted once detached: a live-sync morph or a
|
|
45
|
+
// caller can empty the body, and a detached chip would swallow every later state.
|
|
46
|
+
if (el && el.isConnected) return el;
|
|
47
|
+
const reduced = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
48
|
+
el = bevelSurface("div", [
|
|
49
|
+
"position:fixed", "right:16px", "bottom:16px", "z-index:2147483000",
|
|
50
|
+
"padding:4px 12px", `font:500 13px/1.6 ${FONT_SANS}`,
|
|
51
|
+
"opacity:0", `transition:${reduced ? "none" : "opacity .25s"}`, "pointer-events:none",
|
|
52
|
+
`color-scheme:${pageScheme()}`,
|
|
53
|
+
]);
|
|
54
|
+
el.setAttribute("data-clay-indicator", "");
|
|
55
|
+
el.setAttribute("role", "status");
|
|
56
|
+
document.body.appendChild(el);
|
|
57
|
+
return el;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function show(state) {
|
|
61
|
+
if (!LABELS[state]) return;
|
|
62
|
+
// A failed or offline save is the persistent toast's to report when clay-ui is loaded,
|
|
63
|
+
// and so is saved when the page turned on clay.saveToast. Blocked is the exception:
|
|
64
|
+
// the page cannot save at all, so the chip stays even beside the generic toast.
|
|
65
|
+
const ownedByToast = state !== "blocked" &&
|
|
66
|
+
(ALARMING.has(state) || (state === "saved" && saveFeedback.savedToast));
|
|
67
|
+
if (saveFeedback.toasts && ownedByToast) {
|
|
68
|
+
clearTimeout(hideTimer);
|
|
69
|
+
if (el) {
|
|
70
|
+
set(el, "opacity", "0");
|
|
71
|
+
el.textContent = "";
|
|
72
|
+
delete el.dataset.state;
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const node = ensure();
|
|
77
|
+
node.textContent = LABELS[state];
|
|
78
|
+
node.dataset.state = state;
|
|
79
|
+
style(node, ALARMING.has(state) ? ALARM : REST);
|
|
80
|
+
paintLook(node, { background: ALARMING.has(state) ? null : TOKENS.surface });
|
|
81
|
+
set(node, "opacity", "1");
|
|
82
|
+
clearTimeout(hideTimer);
|
|
83
|
+
if (!STICKY.has(state)) hideTimer = setTimeout(() => { set(node, "opacity", "0"); }, 2200);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function remove() {
|
|
87
|
+
clearTimeout(hideTimer);
|
|
88
|
+
hideTimer = null;
|
|
89
|
+
el?.remove();
|
|
90
|
+
el = null;
|
|
91
|
+
}
|
package/src/plugins/indicator.js
CHANGED
|
@@ -1,83 +1,15 @@
|
|
|
1
1
|
import { startsAtImport } from "../core/is-edit-mode.js";
|
|
2
2
|
import onDomReady from "../lib/dom-ready.js";
|
|
3
|
-
import { set, style } from "../lib/hostile-css.js";
|
|
4
|
-
import { bevelSurface, pageScheme } from "../ui/bevel-controls.js";
|
|
5
|
-
import { TOKENS, FONT_SANS } from "../ui/bevel.js";
|
|
6
3
|
import { saveFeedback } from "../core/save-feedback.js";
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
// and it ships in every document rather than only the ones that turned this chip on.
|
|
10
|
-
// Both listen to clay:save-conflict, so keeping a label here put a chip in the corner
|
|
11
|
-
// saying the same thing as the bar at the same moment. Dropping it from this side
|
|
12
|
-
// leaves core unaware that this plugin exists, which is the direction that
|
|
13
|
-
// dependency has to point.
|
|
14
|
-
const LABELS = {
|
|
15
|
-
saving: "Saving…",
|
|
16
|
-
saved: "Saved",
|
|
17
|
-
error: "Couldn't save",
|
|
18
|
-
offline: "Offline, not saved",
|
|
19
|
-
retrying: "Saving…",
|
|
20
|
-
blocked: "Can't save here",
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// States that stay on screen instead of fading: a save still in flight, one that
|
|
24
|
-
// keeps trying, and one the host will not take without a person's help.
|
|
25
|
-
const STICKY = new Set(["saving", "retrying", "blocked"]);
|
|
26
|
-
|
|
27
|
-
const ALARMING = new Set(["error", "offline", "blocked"]);
|
|
5
|
+
const SAVE_EVENTS = ["saving", "saved", "error", "offline", "retrying", "blocked"];
|
|
28
6
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
let el = null;
|
|
37
|
-
let hideTimer = null;
|
|
38
|
-
|
|
39
|
-
function ensure() {
|
|
40
|
-
// Looked up on every call, never trusted once detached: a live-sync morph or a
|
|
41
|
-
// caller can empty the body, and a detached chip would swallow every later state.
|
|
42
|
-
if (el && el.isConnected) return el;
|
|
43
|
-
const reduced = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
44
|
-
el = bevelSurface("div", [
|
|
45
|
-
"position:fixed", "right:16px", "bottom:16px", "z-index:2147483000",
|
|
46
|
-
"padding:4px 12px", `font:500 13px/1.6 ${FONT_SANS}`,
|
|
47
|
-
"opacity:0", `transition:${reduced ? "none" : "opacity .25s"}`, "pointer-events:none",
|
|
48
|
-
`color-scheme:${pageScheme()}`,
|
|
49
|
-
]);
|
|
50
|
-
el.setAttribute("data-clay-indicator", "");
|
|
51
|
-
el.setAttribute("role", "status");
|
|
52
|
-
document.body.appendChild(el);
|
|
53
|
-
return el;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function show(state) {
|
|
57
|
-
if (!LABELS[state]) return;
|
|
58
|
-
// A failed or offline save is the persistent toast's to report when clay-ui is loaded,
|
|
59
|
-
// and so is saved when the page turned on clay.saveToast. Blocked is the exception:
|
|
60
|
-
// the page cannot save at all, so the chip stays even beside the generic toast.
|
|
61
|
-
const ownedByToast = state !== "blocked" &&
|
|
62
|
-
(ALARMING.has(state) || (state === "saved" && saveFeedback.savedToast));
|
|
63
|
-
if (saveFeedback.toasts && ownedByToast) {
|
|
64
|
-
clearTimeout(hideTimer);
|
|
65
|
-
if (el) {
|
|
66
|
-
set(el, "opacity", "0");
|
|
67
|
-
el.textContent = "";
|
|
68
|
-
delete el.dataset.state;
|
|
69
|
-
}
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const node = ensure();
|
|
73
|
-
node.textContent = LABELS[state];
|
|
74
|
-
node.dataset.state = state;
|
|
75
|
-
set(node, "color-scheme", pageScheme());
|
|
76
|
-
style(node, ALARMING.has(state) ? ALARM : REST);
|
|
77
|
-
set(node, "opacity", "1");
|
|
78
|
-
clearTimeout(hideTimer);
|
|
79
|
-
if (!STICKY.has(state)) hideTimer = setTimeout(() => { set(node, "opacity", "0"); }, 2200);
|
|
80
|
-
}
|
|
7
|
+
// The drawing arrives on demand; states that come before it are shown in order once it has.
|
|
8
|
+
let chip = null;
|
|
9
|
+
const loadChip = () => (chip ??= import("./indicator-chip.js"));
|
|
10
|
+
const show = (state) => {
|
|
11
|
+
loadChip().then((m) => { if (listeners) m.show(state); }, () => {});
|
|
12
|
+
};
|
|
81
13
|
|
|
82
14
|
let listeners = null;
|
|
83
15
|
|
|
@@ -88,7 +20,11 @@ function arm() {
|
|
|
88
20
|
if (listeners) return;
|
|
89
21
|
listeners = new AbortController();
|
|
90
22
|
const { signal } = listeners;
|
|
91
|
-
|
|
23
|
+
// Typing is the first sign a save is coming: fetch the drawing then, not at boot.
|
|
24
|
+
for (const type of ["beforeinput", "keydown", "pointerdown"]) {
|
|
25
|
+
document.addEventListener(type, loadChip, { signal, once: true, capture: true });
|
|
26
|
+
}
|
|
27
|
+
for (const state of SAVE_EVENTS) {
|
|
92
28
|
document.addEventListener("clay:save-" + state, () => show(state), { signal });
|
|
93
29
|
}
|
|
94
30
|
document.addEventListener("clay:page-save-state", (event) => show(event.detail?.state), { signal });
|
|
@@ -97,10 +33,7 @@ function arm() {
|
|
|
97
33
|
function disarm() {
|
|
98
34
|
listeners?.abort();
|
|
99
35
|
listeners = null;
|
|
100
|
-
|
|
101
|
-
hideTimer = null;
|
|
102
|
-
el?.remove();
|
|
103
|
-
el = null;
|
|
36
|
+
chip?.then((m) => m.remove(), () => {});
|
|
104
37
|
}
|
|
105
38
|
|
|
106
39
|
function init() {
|