@panphora/clayjs 1.16.0 → 1.18.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/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 +72519 -59839
- package/dist/m/attrs/refetch-on-save-ZUE7PSCI.js +1 -0
- package/dist/m/attrs/save-freeze-LWGF6XUN.js +1 -0
- package/dist/m/c-2GRUM77Q.js +30 -0
- package/dist/m/c-2KIEGNC4.js +1 -0
- package/dist/m/{c-5R4PTRG2.js → c-2KL3BD52.js} +1 -1
- package/dist/m/c-2YYDMLNZ.js +1 -0
- 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-VFX45IZQ.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-5T6NZHNM.js +1 -0
- package/dist/m/{c-YDH7Q3NY.js → c-5ZQV7KC4.js} +1 -1
- package/dist/m/{c-Z36J63PP.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-AMYEFA2E.js +1 -0
- package/dist/m/c-AQYCG7QW.js +1 -0
- package/dist/m/c-ATKAOH23.js +1 -0
- package/dist/m/c-B3JM5ZXC.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-BIJALSRD.js +1 -0
- package/dist/m/c-BJ7YQ5QZ.js +1 -0
- package/dist/m/c-BPF2NSPV.js +1 -0
- package/dist/m/{c-KIPQJX4B.js → c-BRLCTNMC.js} +1 -1
- package/dist/m/c-BUAYFEV5.js +1 -0
- package/dist/m/c-C6IPRG34.js +1 -0
- package/dist/m/{c-2JL6E75N.js → c-CAS3NND4.js} +1 -1
- package/dist/m/{c-4DRMS4QG.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-7VGZ7RU5.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-OYTFP5QN.js → c-GY422N3Q.js} +1 -1
- package/dist/m/c-HAWFNBYG.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-HRDCD3WN.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-IVTRVENZ.js +1 -0
- package/dist/m/c-IW6GGOU2.js +1 -0
- package/dist/m/c-JKZJIUIP.js +1 -0
- package/dist/m/{c-NZMNXVF6.js → c-JNLX3RJB.js} +1 -1
- package/dist/m/c-JRKY44DK.js +1 -0
- package/dist/m/c-K3ADYNLU.js +1 -0
- package/dist/m/c-KBS3UV6B.js +1 -0
- package/dist/m/c-KGHVFRR3.js +1 -0
- package/dist/m/c-KJJPV77R.js +1 -0
- package/dist/m/{c-CZUSOB7V.js → c-KNPDOMDY.js} +1 -1
- package/dist/m/{c-5Y6TNX5W.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-LR4CGEPT.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-NEL7HQW3.js +1 -0
- package/dist/m/c-NQJRVJ56.js +1 -0
- 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-MMUIUUZG.js → c-OPLUZR3A.js} +1 -1
- package/dist/m/{c-J7CA54IP.js → c-OTMKN2OO.js} +1 -1
- package/dist/m/{c-LTGMXXKO.js → c-OYRZ7XG2.js} +1 -1
- package/dist/m/c-P3OFYUMA.js +1 -0
- 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-SWRJFCNN.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-R27DWQKX.js +1 -0
- package/dist/m/{c-HVYXIS72.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-S2U6NJU4.js +1 -0
- package/dist/m/c-SPZPGD3R.js +1 -0
- package/dist/m/c-SW4YEG2D.js +8 -0
- package/dist/m/c-SZGYW5HT.js +1 -0
- package/dist/m/c-T637T7SN.js +1 -0
- package/dist/m/c-TJAXGIRV.js +1 -0
- package/dist/m/{c-KKWLDOPM.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-TQZ2JYHD.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-VG5XIN4T.js +1 -0
- package/dist/m/c-VILENZTD.js +1 -0
- package/dist/m/{c-33HUYEDI.js → c-VJYEVRYK.js} +1 -1
- package/dist/m/c-VR2BJ4AN.js +1 -0
- 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-X5TSXZYJ.js +2 -0
- 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/{c-HT33EQRN.js → c-ZWIOJGMT.js} +1 -1
- package/dist/m/core/admin-attrs-YY7T5FGU.js +1 -0
- 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-6EVJGNPL.js +1 -0
- package/dist/m/core/is-edit-mode-GCX6767E.js +1 -0
- package/dist/m/core/{persist-HKHA66IY.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/events/index-RN2JNGBV.js +1 -0
- package/dist/m/internals/index-TGLQINN3.js +1 -0
- package/dist/m/lib/cache-bust-MUMFXZK6.js +1 -0
- package/dist/m/loader-3BBNZZGM.js +1 -0
- package/dist/m/manifest-F449FF98.js +1 -0
- package/dist/m/manifest-edit-4396A009.js +1 -0
- package/dist/m/manifest.json +2509 -1474
- package/dist/m/options/options-EJMS3K24.js +1 -0
- package/dist/m/page/editor-6LRB3GE4.js +304 -0
- 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-OYO5GCAO.js +1 -0
- 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-JCHVPF7P.js +1 -0
- package/dist/m/plugins/quickcrop-BQ5YYFCH.js +26 -0
- package/dist/m/plugins/{richclay-RC3L2F6X.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-NHGJXZK2.js +1 -0
- 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-VBWXEXU2.js +1 -0
- 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 +1560 -889
- package/dist/page/themes/light-1.css +33 -8
- package/dist/server/core.cjs +1554 -311
- 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/boot-phase.js +2 -1
- package/src/core/conflict-download.js +3 -29
- package/src/core/conflict-notice-ui.js +4 -7
- package/src/core/download.js +32 -0
- package/src/core/host-meta.js +56 -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 +111 -32
- 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 +209 -40
- 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/autosave-scheduler.js +3 -4
- 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 +122 -27
- package/src/page/board-views.js +2 -16
- package/src/page/boot-pack.js +1 -1
- package/src/page/chart-tables.js +29 -0
- package/src/page/chart.js +411 -72
- package/src/page/checklist.js +10 -135
- package/src/page/checkpoint-proof.js +295 -0
- package/src/page/chrome.js +257 -40
- package/src/page/clipboard-shape.js +126 -0
- package/src/page/document-title-dom.js +12 -0
- package/src/page/document-title-runtime.js +15 -1
- package/src/page/document-title.js +4 -1
- package/src/page/drag.js +33 -3
- package/src/page/editor.js +207 -31
- package/src/page/emoji-data.js +162 -0
- 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/board.js +12 -3
- package/src/page/features/chart.js +11 -0
- package/src/page/features/checklist.js +428 -0
- package/src/page/features/dates.js +180 -0
- package/src/page/features/emoji.js +187 -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/mentions.js +188 -0
- package/src/page/features/registry.js +24 -1
- package/src/page/features/table.js +375 -85
- 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 +33 -0
- package/src/page/format-gate.js +68 -18
- package/src/page/format-host.js +71 -0
- package/src/page/format-native-commands.js +158 -0
- package/src/page/format-native.js +42 -0
- package/src/page/image-actions.js +64 -0
- package/src/page/import-markdown.js +262 -0
- package/src/page/inline.js +32 -8
- package/src/page/items.js +141 -11
- package/src/page/markdown.js +30 -2
- package/src/page/media.js +35 -119
- package/src/page/mention-picker.js +99 -0
- package/src/page/merge.js +1 -1
- package/src/page/placeholder.js +14 -1
- package/src/page/projection.js +156 -25
- 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 +67 -0
- package/src/page/save-states.js +14 -4
- package/src/page/schema.js +52 -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/content.css +25 -1
- package/src/page/themes/light-1.css +33 -8
- 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 +58 -0
- package/src/page/view.js +13 -0
- package/src/page/ybind/binding.js +116 -6
- 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 +2 -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 +125 -18
- package/src/page/ybind/recovery-proof.js +32 -9
- package/src/page/ybind/recovery-replay.js +905 -4
- 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 +126 -15
- 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 +362 -43
- 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 +7 -4
- 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/checkpoint/index.js +2 -2
- 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 +28 -14
- 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/attrs/refetch-on-save-NWPPXOCZ.js +0 -1
- package/dist/m/attrs/save-freeze-FUP4Q4X3.js +0 -1
- package/dist/m/c-2M73252O.js +0 -1
- package/dist/m/c-2SPVQSHC.js +0 -1
- package/dist/m/c-35NBGMZB.js +0 -1
- package/dist/m/c-3IQRECYS.js +0 -1
- package/dist/m/c-4B6H4G5V.js +0 -1
- package/dist/m/c-4FFHZM32.js +0 -1
- package/dist/m/c-4YSCRICO.js +0 -1
- package/dist/m/c-54RCDCBU.js +0 -1
- package/dist/m/c-5M4YEKCX.js +0 -4
- package/dist/m/c-5V3MOVJT.js +0 -1
- package/dist/m/c-66O32MV3.js +0 -28
- package/dist/m/c-6HMB24EV.js +0 -1
- package/dist/m/c-7O6AFR65.js +0 -1
- package/dist/m/c-ANQTJ3B5.js +0 -2
- package/dist/m/c-AYVOREBE.js +0 -1
- package/dist/m/c-B2ZXPOS3.js +0 -3
- package/dist/m/c-BMIZKMPV.js +0 -1
- package/dist/m/c-BTDI4Y23.js +0 -1
- package/dist/m/c-CJZSLMVQ.js +0 -1
- package/dist/m/c-DBE6ORSI.js +0 -1
- package/dist/m/c-EDHUR4MX.js +0 -1
- package/dist/m/c-EY6UOM54.js +0 -1
- package/dist/m/c-F3CKJTJS.js +0 -1
- package/dist/m/c-F7Y6FLPY.js +0 -1
- package/dist/m/c-FA4DZVTC.js +0 -1
- package/dist/m/c-G2BUZITR.js +0 -1
- package/dist/m/c-GB3JTV6E.js +0 -1
- package/dist/m/c-GBGWXTX4.js +0 -1
- package/dist/m/c-GHBCCVG4.js +0 -1
- package/dist/m/c-GJAEGGXY.js +0 -1
- package/dist/m/c-GOWBDM6J.js +0 -1
- package/dist/m/c-IB52R237.js +0 -1
- package/dist/m/c-IKWNE4R4.js +0 -1
- package/dist/m/c-IU3IYEU6.js +0 -1
- package/dist/m/c-IZ2EBRAJ.js +0 -1
- package/dist/m/c-KR4UW4KW.js +0 -1
- package/dist/m/c-KY3VJGUA.js +0 -8
- package/dist/m/c-LFPHCXY3.js +0 -1
- package/dist/m/c-LRPUO2MX.js +0 -1
- package/dist/m/c-LXENEBV7.js +0 -1
- package/dist/m/c-NMJRXKPC.js +0 -8
- package/dist/m/c-OIBUTDXI.js +0 -1
- package/dist/m/c-PPOSCAQD.js +0 -1
- package/dist/m/c-QIX5BJYN.js +0 -1
- package/dist/m/c-QQHEX6HA.js +0 -1
- package/dist/m/c-R7RMANJI.js +0 -9
- package/dist/m/c-RI4NT75Y.js +0 -1
- package/dist/m/c-RM7J7BV2.js +0 -1
- package/dist/m/c-RUJKSUQW.js +0 -1
- package/dist/m/c-SGCCC4FW.js +0 -25
- package/dist/m/c-T4VO4OCB.js +0 -1
- package/dist/m/c-TQEMVJCS.js +0 -1
- package/dist/m/c-TR6RMDQ7.js +0 -3
- package/dist/m/c-UKHTLWUW.js +0 -1
- package/dist/m/c-UNN7LWCT.js +0 -1
- package/dist/m/c-UXBMRDZB.js +0 -235
- package/dist/m/c-V7PZZRG7.js +0 -1
- package/dist/m/c-VL52ADDR.js +0 -1
- package/dist/m/c-WNYBLIOZ.js +0 -1
- package/dist/m/c-WWDBYXLK.js +0 -1
- package/dist/m/c-XNNW2CWK.js +0 -1
- package/dist/m/c-Y6USGTS5.js +0 -5
- package/dist/m/c-YG2NJYS6.js +0 -135
- package/dist/m/c-Z4VRC7GU.js +0 -7
- package/dist/m/c-Z6K52OLP.js +0 -19
- package/dist/m/c-ZDY2MDAA.js +0 -21
- package/dist/m/c-ZUCOKOHT.js +0 -1
- package/dist/m/core/admin-attrs-VGNLAUDK.js +0 -1
- package/dist/m/core/autosave-E4PEFPZ6.js +0 -1
- package/dist/m/core/conflict-notice-VQ6Y64PH.js +0 -1
- package/dist/m/core/host-permission-XN3K2IW3.js +0 -1
- package/dist/m/core/is-edit-mode-JXHDVGUL.js +0 -1
- package/dist/m/core/recovery-TBBSICE2.js +0 -1
- package/dist/m/core/save-WUCHTQBE.js +0 -1
- package/dist/m/core/save-core-FJVHT5M3.js +0 -1
- package/dist/m/core/snapshot-F3SWDZMM.js +0 -1
- package/dist/m/core/unsaved-warning-STKBHE6G.js +0 -1
- package/dist/m/events/index-23DPTUT4.js +0 -1
- package/dist/m/internals/index-WOVAP3RU.js +0 -1
- package/dist/m/lib/cache-bust-CGWT6ZJI.js +0 -1
- package/dist/m/loader-HXX6YNH5.js +0 -1
- package/dist/m/manifest-F22DEDAC.js +0 -1
- package/dist/m/manifest-edit-C3C7376B.js +0 -1
- package/dist/m/options/options-2LH76JQ3.js +0 -1
- package/dist/m/page/editor-XUTB2HB2.js +0 -189
- package/dist/m/plugins/ai-edit-ZQ4CGWIP.js +0 -6
- package/dist/m/plugins/demo-ZIBFAA3R.js +0 -1
- package/dist/m/plugins/indicator-PV4YW2ID.js +0 -1
- package/dist/m/plugins/live-NUTTXSBS.js +0 -1
- package/dist/m/plugins/menu-HCKO3DSP.js +0 -138
- package/dist/m/plugins/page-KSUH7G6J.js +0 -2
- package/dist/m/plugins/page-view-W73OW7WI.js +0 -1
- package/dist/m/plugins/people-AJJ32YCG.js +0 -1
- package/dist/m/plugins/quickcrop-QNY3PKLD.js +0 -26
- package/dist/m/plugins/sortable-YRMQX3ZU.js +0 -1
- package/dist/m/plugins/source-KHK5UUSK.js +0 -1
- package/dist/m/plugins/undo-OF2L3CXU.js +0 -1
- package/dist/m/plugins/upgrade-ZNYODP5Y.js +0 -1
- package/dist/m/plugins/upload-XSGNILUY.js +0 -1
- package/dist/m/plugins/visitor-drafts-XK5GW55Q.js +0 -21
- package/dist/m/plugins/visitor-drafts-owner-KSSH75EV.js +0 -1
- package/dist/m/plugins/wire-ZWVWKF76.js +0 -1
- package/dist/m/reader-core-ILWLXVMP.js +0 -68
- package/dist/m/route/route-KOCZSEGN.js +0 -1
- package/dist/m/sync/live-sync-4AUVXVJU.js +0 -1
- package/dist/m/ui/index-EVHKMKBL.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-RC3L2F6X.js.LEGAL.txt → richclay-KLGETK77.js.LEGAL.txt} +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { addRegionToken } from "../lib/region-policy.js";
|
|
2
|
+
|
|
3
|
+
// Every interface ClayJS draws over a document mounts through here, inside an open
|
|
4
|
+
// shadow root, so the document's own CSS cannot restyle it. The host takes no box
|
|
5
|
+
// (display: contents) and stops inheritance at the boundary (all: initial); custom
|
|
6
|
+
// properties still cross, which is how theme tokens arrive.
|
|
7
|
+
export const HOST_CSS = `:host { all: initial !important; display: contents !important; }
|
|
8
|
+
:host([hidden]) { display: none !important; }
|
|
9
|
+
@media print { :host { display: none !important; } }`;
|
|
10
|
+
|
|
11
|
+
const sheetsByDocument = new WeakMap();
|
|
12
|
+
const guardedWindows = new WeakSet();
|
|
13
|
+
|
|
14
|
+
// A key event from a field inside a root reaches the page's listeners retargeted to the
|
|
15
|
+
// host, so a page's "is someone typing?" check sees no field and runs its shortcut (a
|
|
16
|
+
// "/" that focuses search, an arrow that turns a slide). Typing and caret keys stop at
|
|
17
|
+
// the window, before any page listener; the browser still types and moves the caret.
|
|
18
|
+
// Enter, Escape and Tab pass, since the fields' own handlers use them.
|
|
19
|
+
const CARET_KEYS = new Set(["Backspace", "Delete", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End", "PageUp", "PageDown"]);
|
|
20
|
+
|
|
21
|
+
function keepTypingInside(event) {
|
|
22
|
+
if (event.ctrlKey || event.metaKey || event.altKey) return;
|
|
23
|
+
if (event.key?.length !== 1 && !CARET_KEYS.has(event.key)) return;
|
|
24
|
+
const target = event.composedPath()[0];
|
|
25
|
+
if (!target?.matches?.("input, textarea, select") && !target?.isContentEditable) return;
|
|
26
|
+
if (target.getRootNode().host?.localName === "clay-editor-ui") event.stopPropagation();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function guardTyping(win) {
|
|
30
|
+
if (!win || guardedWindows.has(win)) return;
|
|
31
|
+
guardedWindows.add(win);
|
|
32
|
+
for (const type of ["keydown", "keypress", "keyup"]) win.addEventListener(type, keepTypingInside, true);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function adopts(doc, shadow) {
|
|
36
|
+
return "adoptedStyleSheets" in shadow && typeof doc.defaultView?.CSSStyleSheet?.prototype?.replaceSync === "function";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function sheetFor(doc, text) {
|
|
40
|
+
let sheets = sheetsByDocument.get(doc);
|
|
41
|
+
if (!sheets) sheetsByDocument.set(doc, (sheets = new Map()));
|
|
42
|
+
let sheet = sheets.get(text);
|
|
43
|
+
if (!sheet) {
|
|
44
|
+
sheet = new doc.defaultView.CSSStyleSheet();
|
|
45
|
+
sheet.replaceSync(text);
|
|
46
|
+
sheets.set(text, sheet);
|
|
47
|
+
}
|
|
48
|
+
return sheet;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// The region policy walks parentElement, which stops at a shadow root, so the inner
|
|
52
|
+
// content needs its own editor-ui marker; the host's keeps it out of every capture.
|
|
53
|
+
export function mountEditorUI({ name, content, css = [], parent = document.body, before = null, attributes = {} }) {
|
|
54
|
+
const doc = parent.ownerDocument;
|
|
55
|
+
const host = doc.createElement("clay-editor-ui");
|
|
56
|
+
host.setAttribute("data-clay-ui", name);
|
|
57
|
+
addRegionToken(host, "editor-ui");
|
|
58
|
+
for (const [key, value] of Object.entries(attributes)) host.setAttribute(key, value);
|
|
59
|
+
addRegionToken(content, "editor-ui");
|
|
60
|
+
|
|
61
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
62
|
+
const texts = [HOST_CSS, ...css];
|
|
63
|
+
if (adopts(doc, shadow)) {
|
|
64
|
+
shadow.adoptedStyleSheets = texts.map((text) => sheetFor(doc, text));
|
|
65
|
+
} else {
|
|
66
|
+
for (const text of texts) {
|
|
67
|
+
const style = doc.createElement("style");
|
|
68
|
+
style.textContent = text;
|
|
69
|
+
shadow.append(style);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
shadow.append(content);
|
|
73
|
+
guardTyping(doc.defaultView);
|
|
74
|
+
parent.insertBefore(host, before);
|
|
75
|
+
|
|
76
|
+
return { host, shadow, content, remove: () => host.remove() };
|
|
77
|
+
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
// The colour painted behind a viewport rectangle, read from the DOM, so ClayJS UI can
|
|
2
|
+
// take the page's scheme and lean its surface toward the page instead of guessing from
|
|
3
|
+
// the reader's preference. It answers null when it cannot tell (photos, video, canvas,
|
|
4
|
+
// gradients, busy patterns, split regions), and the UI then keeps Bevel's own look.
|
|
5
|
+
// Measured on about 1,000 real pages: right on 86% of flat regions, about 1 answer in
|
|
6
|
+
// 10,000 regions with the wrong scheme (plans/starter-templates/page-colour/report.md).
|
|
7
|
+
//
|
|
8
|
+
// Per point: the elementsFromPoint stack (open shadow roots spliced in, ClayJS UI
|
|
9
|
+
// skipped), plus pointer-events:none painters that hit-testing cannot see (a census
|
|
10
|
+
// refreshed every 15 s), each layer's background composited front to back over the
|
|
11
|
+
// canvas colour, with ancestor opacity. Unknown layers are folded as black and as
|
|
12
|
+
// white; if the two disagree, the point is unknown. Fifteen points vote in OKLab.
|
|
13
|
+
//
|
|
14
|
+
// It imports nothing: under jest's ESM linker, a module with imports of its own that
|
|
15
|
+
// joins bevel-controls.js's graph fails dynamic imports of bevel-dialog.js with "not in
|
|
16
|
+
// cache". So page-scheme.js's rule is repeated here and the inline !important is direct.
|
|
17
|
+
|
|
18
|
+
const pageScheme = () => {
|
|
19
|
+
const s = getComputedStyle(document.documentElement).colorScheme;
|
|
20
|
+
return s === 'light' || s === 'dark' ? s : 'light dark';
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// ClayJS's own UI and anything else drawn over the page that is never saved.
|
|
24
|
+
const UI = '[clay~="editor-ui"], [clay~="no-snapshot"], [editor-ui], [no-snapshot], [snapshot-remove]';
|
|
25
|
+
const REPLACED = /^(img|video|canvas|iframe|embed|object|image|use|path|rect|circle|ellipse|line|poly(line|gon))$/;
|
|
26
|
+
const BAD = /(invert|brightness|contrast|grayscale|sepia|hue-rotate|opacity|url)\(/;
|
|
27
|
+
const TO_LMS = [0.4122, 0.5363, 0.0514, 0.2119, 0.6807, 0.1074, 0.0883, 0.2817, 0.63];
|
|
28
|
+
const TO_LAB = [0.2105, 0.7936, -0.0041, 1.978, -2.4286, 0.4506, 0.0259, 0.7828, -0.8087];
|
|
29
|
+
const FROM_LAB = [1, 0.3963, 0.2158, 1, -0.1056, -0.0639, 1, -0.0895, -1.2915];
|
|
30
|
+
const FROM_LMS = [4.0767, -3.3077, 0.231, -1.2684, 2.6098, -0.3413, -0.0042, -0.7034, 1.7076];
|
|
31
|
+
|
|
32
|
+
const clamp = (v) => (v < 0 ? 0 : v > 1 ? 1 : v || 0);
|
|
33
|
+
const multiply = (m, v) => [0, 3, 6].map((k) => m[k] * v[0] + m[k + 1] * v[1] + m[k + 2] * v[2]);
|
|
34
|
+
const lin = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
|
|
35
|
+
const gamma = (c) => clamp(c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055);
|
|
36
|
+
const oklab = (rgb) => multiply(TO_LAB, multiply(TO_LMS, rgb.map(lin)).map(Math.cbrt));
|
|
37
|
+
const fromOklab = (lab) => multiply(FROM_LMS, multiply(FROM_LAB, lab).map((v) => v ** 3)).map(gamma);
|
|
38
|
+
const luminance = (rgb) => rgb.map(lin).reduce((sum, c, k) => sum + c * [0.2126, 0.7152, 0.0722][k], 0.05);
|
|
39
|
+
const contrast = (p, q) => Math.max(luminance(p) / luminance(q), luminance(q) / luminance(p));
|
|
40
|
+
const darkInk = (rgb) => luminance(rgb) >= 0.2343;
|
|
41
|
+
const distance = (p, q) => Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);
|
|
42
|
+
const average = (list) => [0, 1, 2].map((k) => list.reduce((sum, v) => sum + v[k], 0) / list.length);
|
|
43
|
+
const fade = (c, k) => c && [c[0], c[1], c[2], c[3] * k];
|
|
44
|
+
const inside = (r, x, y) => x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;
|
|
45
|
+
|
|
46
|
+
const colours = new Map();
|
|
47
|
+
function colour(text) {
|
|
48
|
+
if (!colours.has(text)) {
|
|
49
|
+
const [, fn, body = ''] = /^(rgba?|oklch|oklab|color)\(([^()]*)\)$/.exec(text) || [];
|
|
50
|
+
const v = body.replace(/^srgb /, '').split(/[\s,/]+/).map((t) => parseFloat(t) || 0);
|
|
51
|
+
const h = (v[2] * Math.PI) / 180;
|
|
52
|
+
const rgb = !fn || (fn === 'color' && !body.startsWith('srgb ')) ? null
|
|
53
|
+
: fn === 'color' ? v.slice(0, 3).map(clamp)
|
|
54
|
+
: fn[0] === 'r' ? v.slice(0, 3).map((c) => clamp(c / 255))
|
|
55
|
+
: fromOklab(fn === 'oklab' ? v : [v[0], v[1] * Math.cos(h), v[1] * Math.sin(h)]);
|
|
56
|
+
colours.set(text, rgb && [...rgb, v.length > 3 ? clamp(v[3]) : 1]);
|
|
57
|
+
}
|
|
58
|
+
return colours.get(text);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A gradient whose stops are all one colour is that colour; any other image is unknown.
|
|
62
|
+
function paint(cs) {
|
|
63
|
+
const image = cs.backgroundImage, c = colour(cs.backgroundColor);
|
|
64
|
+
const stops = (/url\(/.test(image) ? [null] : image.match(/[a-z]+\([^()]*\)/g) || [null]).map(colour);
|
|
65
|
+
const flat = stops.every((s) => s && Math.abs(s[3] - stops[0][3]) < 0.05 && distance(oklab(s), oklab(stops[0])) < 0.02) && stops[0];
|
|
66
|
+
const covers = cs.backgroundRepeat === 'repeat' || /^(auto|cover|100%)( (auto|100%))?$/.test(cs.backgroundSize);
|
|
67
|
+
if (cs.backgroundClip.includes('text')) return [];
|
|
68
|
+
return [
|
|
69
|
+
...(image !== 'none' && (!flat || flat[3] > 0) ? [{ c: flat, maybe: flat && !covers }] : []),
|
|
70
|
+
...(!c || c[3] > 0 ? [{ c }] : []),
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Read again every 15 s, or after a second when elements were added or removed.
|
|
75
|
+
let painters = [], censusAt = -Infinity, censusSize = 0;
|
|
76
|
+
function findPainters() {
|
|
77
|
+
const all = document.getElementsByTagName('*'), age = performance.now() - censusAt;
|
|
78
|
+
if (age > 15000 || (age > 1000 && all.length !== censusSize)) {
|
|
79
|
+
censusAt = performance.now();
|
|
80
|
+
censusSize = all.length;
|
|
81
|
+
painters = [...(all.length > 8000 ? [] : all)].filter((el) => {
|
|
82
|
+
const cs = getComputedStyle(el), r = cs.pointerEvents === 'none' && el.getBoundingClientRect();
|
|
83
|
+
return r?.width >= 40 && r.height >= 20 && cs.visibility === 'visible' && !el.closest(UI) && (REPLACED.test(el.localName) || paint(cs).some((l) => !l.c || l.c[3] > 0.03));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return painters;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function deepStack(x, y) {
|
|
90
|
+
const stack = document.elementsFromPoint(x, y), seen = new Set();
|
|
91
|
+
for (let k = 0; k < stack.length; k++) {
|
|
92
|
+
const host = stack[k], root = host.shadowRoot;
|
|
93
|
+
if (root && !seen.has(root) && seen.add(root)) stack.splice(k--, inside(host.getBoundingClientRect(), x, y) ? 0 : 1, ...root.elementsFromPoint(x, y).filter((e) => e.getRootNode() === root));
|
|
94
|
+
}
|
|
95
|
+
return stack;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const grid = ({ x, y, width, height }) => [0, 1, 2].flatMap((j) => [0, 1, 2, 3, 4].map((i) => [x + ((i + 0.5 + (j - 1) / 4) * width) / 5, y + ((j + 0.5) * height) / 3]));
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The colour behind a viewport rectangle: { colour: [r, g, b], confidence: 0..1,
|
|
102
|
+
* scheme: 'light' | 'dark' }, or null when it cannot tell.
|
|
103
|
+
*/
|
|
104
|
+
export function pageColour(rect) {
|
|
105
|
+
const html = document.documentElement, body = document.body;
|
|
106
|
+
if (typeof document.elementsFromPoint !== 'function' || !body || !(rect.width > 0 && rect.height > 0)) return null;
|
|
107
|
+
const memo = new Map();
|
|
108
|
+
const info = (el) => memo.get(el) || memo.set(el, { el, cs: getComputedStyle(el) }).get(el);
|
|
109
|
+
const rectOf = (i) => (i.rect ??= i.el.getBoundingClientRect());
|
|
110
|
+
|
|
111
|
+
const hcs = getComputedStyle(html);
|
|
112
|
+
const propagated = !paint(hcs).length && body.localName === 'body';
|
|
113
|
+
const owners = propagated ? [html, body] : [html];
|
|
114
|
+
const scheme = hcs.colorScheme === 'normal' ? document.querySelector('meta[name="color-scheme"]')?.content : hcs.colorScheme;
|
|
115
|
+
const dark = /dark/.test(scheme) && (!/light/.test(scheme) || matchMedia('(prefers-color-scheme: dark)').matches);
|
|
116
|
+
|
|
117
|
+
function group(el) {
|
|
118
|
+
const i = info(el), cs = i.cs;
|
|
119
|
+
if (i.k === undefined) {
|
|
120
|
+
const host = el.assignedSlot || el.parentElement || el.parentNode?.host;
|
|
121
|
+
const parent = host ? group(host) : { k: 1 };
|
|
122
|
+
i.k = parent.k * +cs.opacity;
|
|
123
|
+
i.ui = parent.ui || el.matches(UI);
|
|
124
|
+
i.bad = parent.bad || BAD.test(cs.filter + cs.backdropFilter) || cs.mixBlendMode !== 'normal' || /\(/.test(cs.maskImage);
|
|
125
|
+
}
|
|
126
|
+
return i;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const ownOf = (i) => (i.own ??= [...(REPLACED.test(i.el.localName) ? [{ c: null }] : []), ...(owners.includes(i.el) ? [] : paint(i.cs))]);
|
|
130
|
+
|
|
131
|
+
// Visible text at a point whose answer it cannot be read on means a painter was missed.
|
|
132
|
+
function inkOf(i) {
|
|
133
|
+
const ink = colour(i.cs.webkitTextFillColor || i.cs.color);
|
|
134
|
+
return (i.ink ??= ink?.[3] >= 0.5 && [...i.el.childNodes].some((n) => n.nodeType === 3 && /\S/.test(n.data)) && ink);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function fold(layers, unknown, withMaybe) {
|
|
138
|
+
let rgb = [0, 0, 0], through = 1;
|
|
139
|
+
for (const { c, k = 1, maybe } of layers) {
|
|
140
|
+
const [r, g, b, a] = c || [unknown, unknown, unknown, k];
|
|
141
|
+
const opacity = maybe && !withMaybe ? 0 : a;
|
|
142
|
+
rgb = rgb.map((v, k) => v + through * opacity * [r, g, b][k]);
|
|
143
|
+
through *= 1 - opacity;
|
|
144
|
+
}
|
|
145
|
+
return oklab(rgb);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function samplePoint(x, y, found) {
|
|
149
|
+
const raw = deepStack(x, y);
|
|
150
|
+
if (!raw.length) return;
|
|
151
|
+
const unplaced = new Set();
|
|
152
|
+
for (const el of found) {
|
|
153
|
+
const r = rectOf(info(el));
|
|
154
|
+
if (raw.includes(el) || !inside(r, x, y) || !el.isConnected || info(el).cs.visibility !== 'visible') continue;
|
|
155
|
+
let at = raw.findLastIndex((e) => el.contains(e)) + 1;
|
|
156
|
+
if (!at && info(el).cs.zIndex < 0) at = Math.max(0, raw.findIndex((e) => owners.includes(e)));
|
|
157
|
+
if (!at) unplaced.add(el);
|
|
158
|
+
raw.splice(at, 0, el);
|
|
159
|
+
}
|
|
160
|
+
const layers = [];
|
|
161
|
+
let ink = null, covered = false;
|
|
162
|
+
for (const [k, el] of raw.entries()) {
|
|
163
|
+
const i = group(el);
|
|
164
|
+
if (i.ui || !i.k) continue;
|
|
165
|
+
const own = raw.lastIndexOf(el) === k, stray = !owners.includes(el) && !inside(rectOf(i), x, y);
|
|
166
|
+
for (const l of stray ? [{}] : own ? ownOf(i) : []) layers.push({ c: i.bad ? null : fade(l.c, i.k), k: i.k, maybe: l.maybe || unplaced.has(el) });
|
|
167
|
+
if (own && !ink && !covered && !stray) ink = inkOf(i);
|
|
168
|
+
covered ||= stray || (own && ownOf(i).some((l) => !l.maybe && (!l.c || l.c[3] >= 0.5)));
|
|
169
|
+
}
|
|
170
|
+
const root = group(html);
|
|
171
|
+
for (const l of paint(propagated ? getComputedStyle(body) : hcs)) layers.push({ c: root.bad ? null : fade(l.c, root.k) });
|
|
172
|
+
layers.push({ c: dark ? [0.0706, 0.0706, 0.0706, 1] : [1, 1, 1, 1] });
|
|
173
|
+
const variants = [0, 1].flatMap((unknown) => [fold(layers, unknown, false), fold(layers, unknown, true)]);
|
|
174
|
+
if (variants.some((v) => distance(v, variants[0]) > 0.06)) return null;
|
|
175
|
+
const lab = average(variants), rgb = fromOklab(lab);
|
|
176
|
+
const contra = !!ink && contrast([0, 1, 2].map((k) => ink[k] * ink[3] + rgb[k] * (1 - ink[3])), rgb) < 1.25;
|
|
177
|
+
return { lab, contra, approx: layers.some((l) => !l.c || l.maybe) };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const found = findPainters();
|
|
181
|
+
const results = grid(rect).map(([x, y]) => samplePoint(x, y, found)).filter((r) => r !== undefined);
|
|
182
|
+
const total = results.length, known = results.filter(Boolean);
|
|
183
|
+
const near = (centre) => known.filter((b) => distance(centre, b.lab) <= 0.035);
|
|
184
|
+
const seed = known.map((a) => near(a.lab)).sort((p, q) => q.length - p.length)[0];
|
|
185
|
+
const members = seed ? near(average(seed.map((m) => m.lab))) : [];
|
|
186
|
+
if (!members.length || members.length < 0.6 * total) return null;
|
|
187
|
+
const contra = members.filter((m) => m.contra).length, rgb = fromOklab(average(members.map((m) => m.lab)));
|
|
188
|
+
const against = known.filter((b) => !members.includes(b) && darkInk(fromOklab(b.lab)) !== darkInk(rgb)).length;
|
|
189
|
+
if ((contra >= 2 && contra >= members.length / 3) || (against >= 2 && against >= 0.2 * total)) return null;
|
|
190
|
+
const approx = members.filter((m) => m.approx).length / members.length;
|
|
191
|
+
return {
|
|
192
|
+
colour: rgb.map((v) => Math.round(v * 255)),
|
|
193
|
+
confidence: +((members.length / total) * (1 - 0.3 * approx) * (1 - contra / members.length)).toFixed(3),
|
|
194
|
+
scheme: darkInk(rgb) ? 'light' : 'dark',
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Bevel's surface and its weakest text ink, per scheme. A surface with its own
|
|
199
|
+
// palette (the page menu's stylesheet) passes its own pair.
|
|
200
|
+
export const BEVEL_SURFACE = { light: [0xFF, 0xFC, 0xF6], dark: [0x11, 0x13, 0x1E], mutedLight: [0x6B, 0x59, 0x42], mutedDark: [0x8A, 0x90, 0xAB] };
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* The look for UI drawn over `rect`: { scheme, surface }. `scheme` is the detected
|
|
204
|
+
* one, or pageScheme() when the colour is unknown. `surface` is Bevel's surface mixed
|
|
205
|
+
* up to 35% toward a confidently detected colour, never so far that the muted ink
|
|
206
|
+
* drops below 4.5:1, or null to keep Bevel's own fill. A page the detector cannot
|
|
207
|
+
* read is unknown, never a reason for the UI drawing over it to fail.
|
|
208
|
+
*/
|
|
209
|
+
export function uiLook(rect, base = BEVEL_SURFACE) {
|
|
210
|
+
let found = null;
|
|
211
|
+
try {
|
|
212
|
+
found = pageColour(rect);
|
|
213
|
+
} catch {}
|
|
214
|
+
if (!found || found.confidence < 0.5) return { scheme: pageScheme(), surface: null };
|
|
215
|
+
const { scheme } = found;
|
|
216
|
+
const own = base[scheme], muted = (scheme === 'dark' ? base.mutedDark : base.mutedLight).map((v) => v / 255);
|
|
217
|
+
let surface = null;
|
|
218
|
+
for (let w = 0.35; found.confidence >= 0.75 && !surface && w > 0.01; w -= 0.05) {
|
|
219
|
+
const mix = own.map((v, k) => Math.round(v + (found.colour[k] - v) * w));
|
|
220
|
+
if (contrast(mix.map((v) => v / 255), muted) >= 4.5) surface = `rgb(${mix.join(' ')})`;
|
|
221
|
+
}
|
|
222
|
+
return { scheme, surface };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Gives an inline-styled Bevel surface the look for where it sits: `color-scheme`
|
|
227
|
+
* always, and `background` set to the tint or back to `background` when there is
|
|
228
|
+
* none. Pass `background: null` to leave the fill alone (a surface whose fill means
|
|
229
|
+
* something, like an alarm).
|
|
230
|
+
*/
|
|
231
|
+
// A Bevel button rebuilds its inline style on every hover and focus, keeping only what
|
|
232
|
+
// was pinned, so on a button the look is pinned. An element with no size yet (hidden,
|
|
233
|
+
// empty) takes the page's declared scheme, or keeps the look it has.
|
|
234
|
+
export function paintLook(el, { rect = el.getBoundingClientRect(), background = null } = {}) {
|
|
235
|
+
const sized = rect.width > 0 && rect.height > 0;
|
|
236
|
+
if (!sized && pageScheme() === 'light dark') return null;
|
|
237
|
+
const look = sized ? uiLook(rect) : { scheme: pageScheme(), surface: null };
|
|
238
|
+
const props = { 'color-scheme': look.scheme };
|
|
239
|
+
if (background !== null) props.background = look.surface || background;
|
|
240
|
+
if (typeof el.pin === 'function') el.pin(props);
|
|
241
|
+
else for (const [prop, value] of Object.entries(props)) el.style.setProperty(prop, value, 'important');
|
|
242
|
+
return look;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* The same look for a surface styled by a stylesheet of Bevel variables (the page
|
|
247
|
+
* menu): `color-scheme`, and `--bevel-surface` when tinted, set inline on `el`.
|
|
248
|
+
*/
|
|
249
|
+
export function lookAt(el, rect, base) {
|
|
250
|
+
const look = uiLook(rect, base);
|
|
251
|
+
el.style.setProperty('color-scheme', look.scheme, 'important');
|
|
252
|
+
if (look.surface) el.style.setProperty('--bevel-surface', look.surface, 'important');
|
|
253
|
+
else el.style.removeProperty('--bevel-surface');
|
|
254
|
+
return look;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// A fixed surface the page moves under: read again once scrolling or resizing settles,
|
|
258
|
+
// when html or body change attributes (a theme toggle), when the reader's scheme
|
|
259
|
+
// changes, when it moves to another corner and when it is shown again. While it has
|
|
260
|
+
// no size (hidden) it keeps its last look.
|
|
261
|
+
export function followLook(root, target, base) {
|
|
262
|
+
let timer = 0;
|
|
263
|
+
const refresh = () => {
|
|
264
|
+
timer = 0;
|
|
265
|
+
const rect = target.getBoundingClientRect();
|
|
266
|
+
if (!document.hidden && root.isConnected && rect.width && rect.height) lookAt(root, rect, base);
|
|
267
|
+
};
|
|
268
|
+
const soon = () => {
|
|
269
|
+
clearTimeout(timer);
|
|
270
|
+
timer = setTimeout(refresh, 150);
|
|
271
|
+
};
|
|
272
|
+
window.addEventListener('scroll', soon, { capture: true, passive: true });
|
|
273
|
+
window.addEventListener('resize', soon);
|
|
274
|
+
document.addEventListener('visibilitychange', soon);
|
|
275
|
+
window.matchMedia?.('(prefers-color-scheme: dark)').addEventListener?.('change', soon);
|
|
276
|
+
const watch = new MutationObserver(soon);
|
|
277
|
+
watch.observe(document.documentElement, { attributes: true });
|
|
278
|
+
watch.observe(document.body, { attributes: true });
|
|
279
|
+
watch.observe(root, { attributes: true, attributeFilter: ['data-corner', 'hidden'] });
|
|
280
|
+
refresh();
|
|
281
|
+
}
|
package/src/ui/toast.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
// The Hyperclay dashboard's toast (Bevel's React toast with the dashboard's overrides),
|
|
5
5
|
// drawn inline: a 3px tone edge, a 16px Bevel glyph, 13.5px semibold text, a quiet close.
|
|
6
6
|
import { set } from "../lib/hostile-css.js";
|
|
7
|
-
import { bevelBox, bevelSurface, bevelText, bevelButton,
|
|
7
|
+
import { bevelBox, bevelSurface, bevelText, bevelButton, protectIcon, paintLook } from "./bevel-controls.js";
|
|
8
8
|
import { TOKENS, RULES, GLYPHS } from "./bevel.js";
|
|
9
|
+
import { mountEditorUI } from "./editor-ui.js";
|
|
9
10
|
|
|
10
11
|
const TONES = {
|
|
11
12
|
success: { edge: TOKENS.teal, icon: GLYPHS.toastSuccess },
|
|
@@ -24,9 +25,11 @@ function motion() {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
// Looked up on every call, never cached: a live-sync morph or a caller can empty the
|
|
27
|
-
// body, and a detached stack would swallow every toast after it.
|
|
28
|
+
// body, and a detached stack would swallow every toast after it. The stack sits in its own
|
|
29
|
+
// shadow root: the inline !important rules already beat the page's stylesheets, and the
|
|
30
|
+
// root also keeps out what they cannot, such as a page's ::before content.
|
|
28
31
|
function stack() {
|
|
29
|
-
const existing = document.querySelector("[data-clay-toasts]");
|
|
32
|
+
const existing = document.querySelector('clay-editor-ui[data-clay-ui="toasts"]')?.shadowRoot.querySelector("[data-clay-toasts]");
|
|
30
33
|
if (existing) return existing;
|
|
31
34
|
const box = bevelBox("div", [
|
|
32
35
|
"position:fixed", "top:18px", "right:18px", "z-index:9999",
|
|
@@ -35,7 +38,7 @@ function stack() {
|
|
|
35
38
|
]);
|
|
36
39
|
box.setAttribute("data-clay-toasts", "");
|
|
37
40
|
box.setAttribute("aria-live", "polite");
|
|
38
|
-
|
|
41
|
+
mountEditorUI({ name: "toasts", content: box });
|
|
39
42
|
return box;
|
|
40
43
|
}
|
|
41
44
|
|
|
@@ -44,7 +47,7 @@ function build(message, type, { detail = "", actions = [] } = {}) {
|
|
|
44
47
|
const el = bevelSurface("div", [
|
|
45
48
|
"display:flex", "align-items:flex-start", ...RULES.toast, "width:100%",
|
|
46
49
|
`border-inline-start:3px solid ${tone.edge}`,
|
|
47
|
-
"cursor:pointer", "pointer-events:auto",
|
|
50
|
+
"cursor:pointer", "pointer-events:auto",
|
|
48
51
|
...HIDDEN, `transition:${motion()}`,
|
|
49
52
|
]);
|
|
50
53
|
el.setAttribute("data-clay-toast", type);
|
|
@@ -99,6 +102,7 @@ function closeButton(onClick) {
|
|
|
99
102
|
|
|
100
103
|
function reveal(el) {
|
|
101
104
|
stack().append(el);
|
|
105
|
+
paintLook(el, { background: TOKENS.surface });
|
|
102
106
|
setTimeout(() => {
|
|
103
107
|
set(el, "opacity", "1");
|
|
104
108
|
set(el, "transform", "none");
|
|
@@ -145,11 +149,16 @@ function toastPersistent(message, messageType = "warning", { detail = "", action
|
|
|
145
149
|
reveal(el);
|
|
146
150
|
}
|
|
147
151
|
|
|
148
|
-
// Takes down the persistent toast showing this message, if one is up.
|
|
149
|
-
|
|
152
|
+
// Takes down the persistent toast showing this message, if one is up. `now` takes the
|
|
153
|
+
// node out at once: a session that is over has no one left to read the fade.
|
|
154
|
+
function dismissPersistent(message, { now = false } = {}) {
|
|
150
155
|
const el = activePersistentToasts.get(message);
|
|
151
156
|
if (!el) return;
|
|
152
157
|
activePersistentToasts.delete(message);
|
|
158
|
+
if (now) {
|
|
159
|
+
el.remove();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
153
162
|
dismiss(el);
|
|
154
163
|
}
|
|
155
164
|
|