@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
package/src/page/media.js
CHANGED
|
@@ -3,25 +3,31 @@
|
|
|
3
3
|
// Nothing reaches the record until the host has answered with a URL; then one
|
|
4
4
|
// transaction inserts the block at the bookmark. A cancelled or failed upload
|
|
5
5
|
// leaves no trace in the record.
|
|
6
|
-
|
|
6
|
+
//
|
|
7
|
+
// The paste, the drop, the picker and the upload itself are here, so a file lands
|
|
8
|
+
// where it was dropped without waiting for anything. What an upload can then offer
|
|
9
|
+
// (retry, embedding, the alt text and width the chrome sets) is in the media view
|
|
10
|
+
// part, which loads with the first paste, drop, insert or upload.
|
|
11
|
+
import { state } from "../vendor/prosemirror.vendor.js";
|
|
7
12
|
import { schema } from "./schema.js";
|
|
8
13
|
import { outline } from "./blocks.js";
|
|
9
14
|
import { newId } from "./model.js";
|
|
10
15
|
import { asStep } from "./blocksel.js";
|
|
11
16
|
import { announce } from "./announce.js";
|
|
12
17
|
import { safeFileHref } from "./address.js";
|
|
13
|
-
import { mediaViews } from "./media-views.js";
|
|
14
18
|
|
|
15
19
|
const { Plugin, PluginKey } = state;
|
|
16
|
-
const { Decoration, DecorationSet } = pmView;
|
|
17
20
|
const N = schema.nodes;
|
|
18
21
|
|
|
19
22
|
export const mediaKey = new PluginKey("page-media");
|
|
20
23
|
export const EMBED_MAX = 1.5 * 1024 * 1024;
|
|
21
|
-
export const
|
|
22
|
-
const runtime = new WeakMap();
|
|
24
|
+
export const mediaRuntime = new WeakMap();
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
// The view part hands its upload actions back here when it installs, so the
|
|
27
|
+
// bookmark's own buttons reach them without this module importing it.
|
|
28
|
+
export const mediaParts = new WeakMap();
|
|
29
|
+
|
|
30
|
+
export const boundary = (doc, pos) => {
|
|
25
31
|
const $p = doc.resolve(Math.max(0, Math.min(pos, doc.content.size)));
|
|
26
32
|
return $p.depth === 0 ? $p.pos : $p.after(1);
|
|
27
33
|
};
|
|
@@ -109,31 +115,30 @@ export function insertFiles(view, files, place = hostPlace(view.state, view.stat
|
|
|
109
115
|
return true;
|
|
110
116
|
}
|
|
111
117
|
|
|
112
|
-
const live = (view, id) => mediaKey.getState(view.state).items.find((x) => x.id === id);
|
|
113
|
-
const update = (view, id, patch) => view.dispatch(view.state.tr.setMeta(mediaKey, { update: { id, ...patch } }));
|
|
114
|
-
const
|
|
115
|
-
const attrsFor = (it, src) => (it.kind === "image" ? { src, alt: "", caption: "" } : { src, name: it.name, size: it.file.size ?? null, mime: it.file.type || null });
|
|
118
|
+
export const live = (view, id) => mediaKey.getState(view.state).items.find((x) => x.id === id);
|
|
119
|
+
export const update = (view, id, patch) => view.dispatch(view.state.tr.setMeta(mediaKey, { update: { id, ...patch } }));
|
|
120
|
+
export const attrsFor = (it, src) => (it.kind === "image" ? { src, alt: "", caption: "" } : { src, name: it.name, size: it.file.size ?? null, mime: it.file.type || null });
|
|
116
121
|
|
|
117
|
-
function settle(it, view, tr) {
|
|
122
|
+
export function settle(it, view, tr) {
|
|
118
123
|
if (it.preview) URL.revokeObjectURL?.(it.preview);
|
|
119
124
|
if (tr) view.dispatch(tr);
|
|
120
125
|
}
|
|
121
126
|
|
|
122
|
-
async function run(view, it) {
|
|
123
|
-
const rt =
|
|
127
|
+
export async function run(view, it) {
|
|
128
|
+
const rt = mediaRuntime.get(view);
|
|
124
129
|
const abort = new AbortController();
|
|
125
130
|
rt.aborts.set(it.id, abort);
|
|
126
131
|
let last = -5;
|
|
127
132
|
const onProgress = ({ percent }) => {
|
|
128
133
|
if (percent - last < 5 && percent !== 100) return;
|
|
129
134
|
last = percent;
|
|
130
|
-
if (
|
|
135
|
+
if (mediaRuntime.has(view) && live(view, it.id)) update(view, it.id, { percent });
|
|
131
136
|
};
|
|
132
137
|
let res;
|
|
133
138
|
try { res = await rt.upload(it.file, { onProgress, signal: abort.signal }); }
|
|
134
139
|
catch { res = { code: "network", msg: "Upload failed" }; }
|
|
135
140
|
rt.aborts.delete(it.id);
|
|
136
|
-
if (!
|
|
141
|
+
if (!mediaRuntime.has(view) || !live(view, it.id)) return;
|
|
137
142
|
if (res?.ok) {
|
|
138
143
|
const src = safeFileHref(res.uploads?.[0]?.url);
|
|
139
144
|
if (src) {
|
|
@@ -159,46 +164,19 @@ async function run(view, it) {
|
|
|
159
164
|
announce(view, `${it.name}: ${message}`);
|
|
160
165
|
}
|
|
161
166
|
|
|
162
|
-
export async function embedUpload(view, id) {
|
|
163
|
-
const it = live(view, id);
|
|
164
|
-
if (!it || it.state !== "embed-choice") return;
|
|
165
|
-
const src = await readDataUrl(it.file);
|
|
166
|
-
if (!runtime.has(view) || !live(view, id)) return;
|
|
167
|
-
settle(it, view, placeTr(view.state, id, attrsFor(it, src)));
|
|
168
|
-
announce(view, "Saved inside the document");
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export function retryUpload(view, id) {
|
|
172
|
-
const it = live(view, id);
|
|
173
|
-
if (!it) return;
|
|
174
|
-
update(view, id, { state: "uploading", percent: 0, code: null, message: null });
|
|
175
|
-
run(view, live(view, id));
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export function cancelUpload(view, id) {
|
|
179
|
-
const rt = runtime.get(view);
|
|
180
|
-
const abort = rt?.aborts.get(id);
|
|
181
|
-
const it = live(view, id);
|
|
182
|
-
if (it) settle(it, view, removeTr(view.state, id));
|
|
183
|
-
rt?.aborts.delete(id);
|
|
184
|
-
abort?.abort();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
167
|
const htmlHasText = (html) => html.replace(/<(meta|style|img)\b[^>]*>/gi, "").replace(/<[^>]+>/g, "").trim() !== "";
|
|
188
168
|
|
|
189
169
|
export function mediaPlugin({ upload, features = null }) {
|
|
190
|
-
let editorView = null;
|
|
191
170
|
// Only the bookmark widget waits for the view part: the upload and its block
|
|
192
171
|
// are core, and the block draws through the schema until the part arrives.
|
|
193
172
|
const showBookmark = (view) => {
|
|
194
|
-
if (!features || features.has("media") || !
|
|
173
|
+
if (!features || features.has("media") || !mediaRuntime.has(view)) return;
|
|
195
174
|
features.ensure("media").catch(() => {});
|
|
196
175
|
};
|
|
197
176
|
return new Plugin({
|
|
198
177
|
key: mediaKey,
|
|
199
178
|
state: mediaState,
|
|
200
179
|
view(view) {
|
|
201
|
-
editorView = view;
|
|
202
180
|
const doc = view.dom.ownerDocument;
|
|
203
181
|
const input = doc.createElement("input");
|
|
204
182
|
input.type = "file";
|
|
@@ -206,7 +184,7 @@ export function mediaPlugin({ upload, features = null }) {
|
|
|
206
184
|
input.hidden = true;
|
|
207
185
|
input.className = "page-file-input";
|
|
208
186
|
view.dom.parentElement.append(input);
|
|
209
|
-
|
|
187
|
+
mediaRuntime.set(view, { upload, aborts: new Map(), input });
|
|
210
188
|
input.addEventListener("change", () => {
|
|
211
189
|
const files = [...(input.files ?? [])];
|
|
212
190
|
const picker = mediaKey.getState(view.state).picker;
|
|
@@ -230,18 +208,18 @@ export function mediaPlugin({ upload, features = null }) {
|
|
|
230
208
|
const b = e.target.closest?.(".page-upload-btn");
|
|
231
209
|
if (!b) return;
|
|
232
210
|
e.preventDefault();
|
|
211
|
+
const part = mediaParts.get(view);
|
|
233
212
|
const id = b.dataset.upload;
|
|
234
|
-
if (b.dataset.act === "retry") retryUpload(view, id);
|
|
235
|
-
else if (b.dataset.act === "embed") embedUpload(view, id);
|
|
236
|
-
else cancelUpload(view, id);
|
|
213
|
+
if (b.dataset.act === "retry") part?.retryUpload(view, id);
|
|
214
|
+
else if (b.dataset.act === "embed") part?.embedUpload(view, id);
|
|
215
|
+
else part?.cancelUpload(view, id);
|
|
237
216
|
};
|
|
238
217
|
view.dom.addEventListener("click", onClick);
|
|
239
218
|
return {
|
|
240
219
|
destroy() {
|
|
241
220
|
view.dom.removeEventListener("click", onClick);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
runtime.delete(view);
|
|
221
|
+
const rt = mediaRuntime.get(view);
|
|
222
|
+
mediaRuntime.delete(view);
|
|
245
223
|
for (const it of mediaKey.getState(view.state).items) if (it.preview) URL.revokeObjectURL?.(it.preview);
|
|
246
224
|
for (const a of rt.aborts.values()) a.abort();
|
|
247
225
|
input.remove();
|
|
@@ -249,14 +227,6 @@ export function mediaPlugin({ upload, features = null }) {
|
|
|
249
227
|
};
|
|
250
228
|
},
|
|
251
229
|
props: {
|
|
252
|
-
decorations(st) {
|
|
253
|
-
const { items } = mediaKey.getState(st);
|
|
254
|
-
const render = editorView ? mediaViews.get(editorView) : null;
|
|
255
|
-
if (!items.length || !render) return null;
|
|
256
|
-
return DecorationSet.create(st.doc, items.map((it) => Decoration.widget(boundary(st.doc, it.pos), (view) => render(view.dom.ownerDocument, it), {
|
|
257
|
-
side: -1000 + it.order, key: `${it.id}:${it.state}:${it.percent}`, stopEvent: () => true, ignoreSelection: true,
|
|
258
|
-
})));
|
|
259
|
-
},
|
|
260
230
|
handlePaste(view, event) {
|
|
261
231
|
const data = event.clipboardData;
|
|
262
232
|
const files = [...(data?.files ?? [])];
|
|
@@ -287,72 +257,18 @@ export function mediaPlugin({ upload, features = null }) {
|
|
|
287
257
|
});
|
|
288
258
|
}
|
|
289
259
|
|
|
290
|
-
export function pickFiles(view, accept, place = hostPlace(view.state, view.state.selection.$head.index(0)), remove = null) {
|
|
291
|
-
const rt = runtime.get(view);
|
|
292
|
-
if (!rt) return false;
|
|
293
|
-
const picker = { place, remove: remove && { ...remove, text: view.state.doc.textBetween(remove.from, remove.to) } };
|
|
294
|
-
view.dispatch(view.state.tr.setMeta(mediaKey, { picker }));
|
|
295
|
-
rt.input.accept = accept;
|
|
296
|
-
rt.input.click();
|
|
297
|
-
return true;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
260
|
const indexOfId = (doc, id) => {
|
|
301
261
|
let found = -1;
|
|
302
262
|
doc.forEach((n, _, i) => { if (n.attrs.id === id) found = i; });
|
|
303
263
|
return found;
|
|
304
264
|
};
|
|
305
265
|
|
|
306
|
-
export function
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
view.dispatch(asStep(st.tr.setNodeMarkup(at, null, { ...node.attrs, ...patch })));
|
|
314
|
-
return true;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
export function openAltEditor(view, id) {
|
|
318
|
-
const index = indexOfId(view.state.doc, id);
|
|
319
|
-
if (index < 0) return false;
|
|
320
|
-
const shell = view.dom.parentElement;
|
|
321
|
-
const doc = shell.ownerDocument;
|
|
322
|
-
let at = 0;
|
|
323
|
-
for (let i = 0; i < index; i++) at += view.state.doc.child(i).nodeSize;
|
|
324
|
-
const box = doc.createElement("div");
|
|
325
|
-
box.className = "page-link";
|
|
326
|
-
box.dataset.mode = "alt";
|
|
327
|
-
const input = doc.createElement("input");
|
|
328
|
-
input.className = "page-link-input";
|
|
329
|
-
input.type = "text";
|
|
330
|
-
input.value = view.state.doc.child(index).attrs.alt || "";
|
|
331
|
-
input.placeholder = "Describe the image";
|
|
332
|
-
input.setAttribute("aria-label", "Alt text");
|
|
333
|
-
box.append(input);
|
|
334
|
-
const rect = view.nodeDOM(at)?.getBoundingClientRect?.();
|
|
335
|
-
const shellBox = shell.getBoundingClientRect();
|
|
336
|
-
if (rect) {
|
|
337
|
-
box.style.setProperty("--page-pop-x", `${rect.left - shellBox.left}px`);
|
|
338
|
-
box.style.setProperty("--page-pop-y", `${rect.bottom - shellBox.top + 6}px`);
|
|
339
|
-
}
|
|
340
|
-
shell.append(box);
|
|
341
|
-
let done = false;
|
|
342
|
-
const close = (commit, refocus = true) => {
|
|
343
|
-
if (done) return;
|
|
344
|
-
done = true;
|
|
345
|
-
const value = input.value.trim();
|
|
346
|
-
box.remove();
|
|
347
|
-
const i = indexOfId(view.state.doc, id);
|
|
348
|
-
if (commit && i >= 0 && value !== view.state.doc.child(i).attrs.alt) setImageAttrs(view, id, { alt: value });
|
|
349
|
-
if (refocus) view.focus();
|
|
350
|
-
};
|
|
351
|
-
input.addEventListener("keydown", (e) => {
|
|
352
|
-
if (e.key === "Enter") { e.preventDefault(); close(true); }
|
|
353
|
-
else if (e.key === "Escape") { e.preventDefault(); e.stopPropagation(); close(false); }
|
|
354
|
-
});
|
|
355
|
-
input.addEventListener("blur", () => close(true, false));
|
|
356
|
-
input.focus();
|
|
266
|
+
export function pickFiles(view, accept, place = hostPlace(view.state, view.state.selection.$head.index(0)), remove = null) {
|
|
267
|
+
const rt = mediaRuntime.get(view);
|
|
268
|
+
if (!rt) return false;
|
|
269
|
+
const picker = { place, remove: remove && { ...remove, text: view.state.doc.textBetween(remove.from, remove.to) } };
|
|
270
|
+
view.dispatch(view.state.tr.setMeta(mediaKey, { picker }));
|
|
271
|
+
rt.input.accept = accept;
|
|
272
|
+
rt.input.click();
|
|
357
273
|
return true;
|
|
358
274
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// The people picker the @ command draws: one listbox at the caret, outside the saved
|
|
2
|
+
// article and never in it. It is built from the editor's own menu markup, so it needs no
|
|
3
|
+
// stylesheet of its own, and it takes no focus: the caret and the typed query stay in the
|
|
4
|
+
// document, and the active row is announced through the editor's aria-activedescendant as
|
|
5
|
+
// the slash menu does. A name is only ever text.
|
|
6
|
+
export const PICKER = "page-mention-picker";
|
|
7
|
+
export const OPTION = "page-menu-item";
|
|
8
|
+
const EMPTY = "No people to mention";
|
|
9
|
+
|
|
10
|
+
let count = 0;
|
|
11
|
+
|
|
12
|
+
// The people a picker may offer: the ones the document already names, with the host's live
|
|
13
|
+
// list laid over them by id, so a renamed person is shown under the name the host answers
|
|
14
|
+
// with. Nothing is invented when the host has no list.
|
|
15
|
+
export function peopleFrom(saved = [], allowed = null) {
|
|
16
|
+
const byId = new Map();
|
|
17
|
+
for (const person of saved ?? []) if (person && typeof person.id === "string") byId.set(person.id, person);
|
|
18
|
+
for (const person of Array.isArray(allowed) ? allowed : []) if (person && typeof person.id === "string") byId.set(person.id, person);
|
|
19
|
+
return [...byId.values()];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const filterPeople = (people, query) => {
|
|
23
|
+
const q = String(query ?? "").trim().toLowerCase();
|
|
24
|
+
if (!q) return people;
|
|
25
|
+
return people.filter((person) => String(person.name ?? "").toLowerCase().includes(q));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// The shell takes the words a command shows, so a date command reuses the same listbox:
|
|
29
|
+
// same placement, same rows, same keyboard, and its own name for what it lists.
|
|
30
|
+
export function createMentionPicker({ document: doc = globalThis.document, onPick = () => {}, label = "Mention a person", empty = EMPTY } = {}) {
|
|
31
|
+
const id = `page-mentions-${++count}`;
|
|
32
|
+
const el = doc.createElement("div");
|
|
33
|
+
el.className = `page-menu ${PICKER}`;
|
|
34
|
+
el.id = id;
|
|
35
|
+
el.setAttribute("role", "listbox");
|
|
36
|
+
el.setAttribute("aria-label", label);
|
|
37
|
+
el.hidden = true;
|
|
38
|
+
let people = [];
|
|
39
|
+
let active = 0;
|
|
40
|
+
|
|
41
|
+
const draw = () => {
|
|
42
|
+
if (!people.length) {
|
|
43
|
+
const none = doc.createElement("div");
|
|
44
|
+
none.className = "page-menu-title";
|
|
45
|
+
none.textContent = empty;
|
|
46
|
+
el.replaceChildren(none);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
el.replaceChildren(...people.map((person, i) => {
|
|
50
|
+
const row = doc.createElement("button");
|
|
51
|
+
row.type = "button";
|
|
52
|
+
row.className = `${OPTION}${i === active ? " is-active" : ""}`;
|
|
53
|
+
row.id = `${id}-${i}`;
|
|
54
|
+
row.dataset.index = String(i);
|
|
55
|
+
row.setAttribute("role", "option");
|
|
56
|
+
row.setAttribute("aria-selected", String(i === active));
|
|
57
|
+
row.textContent = String(person.name ?? "");
|
|
58
|
+
row.addEventListener("mousedown", (event) => event.preventDefault());
|
|
59
|
+
row.addEventListener("click", () => onPick(i));
|
|
60
|
+
return row;
|
|
61
|
+
}));
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// The caret the list hangs from, in the page's own placement variables: the same ones
|
|
65
|
+
// the block menu writes, so the existing menu stylesheet paints and lifts it.
|
|
66
|
+
const place = (at) => {
|
|
67
|
+
el.style.setProperty("--page-pop-x", `${at.x}px`);
|
|
68
|
+
el.style.setProperty("--page-pop-y", `${at.y}px`);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
el,
|
|
73
|
+
show: (next, at = null) => {
|
|
74
|
+
people = next;
|
|
75
|
+
active = 0;
|
|
76
|
+
draw();
|
|
77
|
+
if (at) place(at);
|
|
78
|
+
el.hidden = false;
|
|
79
|
+
},
|
|
80
|
+
move: (step) => {
|
|
81
|
+
if (!people.length) return;
|
|
82
|
+
active = (active + step + people.length) % people.length;
|
|
83
|
+
draw();
|
|
84
|
+
},
|
|
85
|
+
activeId: () => (people.length ? `${id}-${active}` : null),
|
|
86
|
+
index: () => active,
|
|
87
|
+
personAt: (i) => people[i] ?? null,
|
|
88
|
+
hide: () => {
|
|
89
|
+
el.hidden = true;
|
|
90
|
+
people = [];
|
|
91
|
+
active = 0;
|
|
92
|
+
el.replaceChildren();
|
|
93
|
+
},
|
|
94
|
+
destroy() {
|
|
95
|
+
this.hide();
|
|
96
|
+
el.remove();
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
package/src/page/merge.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { canon, renderModel, parseModel, fragmentCleaner } from "./projection.js";
|
|
2
2
|
|
|
3
|
-
const TEXT = new Set(["paragraph", "heading", "list_item", "callout", "code_block", "toggle"]);
|
|
3
|
+
const TEXT = new Set(["paragraph", "heading", "list_item", "callout", "quote", "code_block", "toggle"]);
|
|
4
4
|
const same = (a, b) => canon(a) === canon(b);
|
|
5
5
|
|
|
6
6
|
function inlineOf(item, doc) {
|
package/src/page/placeholder.js
CHANGED
|
@@ -5,6 +5,7 @@ const { Decoration, DecorationSet } = pmView;
|
|
|
5
5
|
|
|
6
6
|
export const PLACEHOLDER_TEXT = "Type / for blocks";
|
|
7
7
|
export const TITLE_PLACEHOLDER = "Untitled";
|
|
8
|
+
export const CHECK_PLACEHOLDER = "To do";
|
|
8
9
|
|
|
9
10
|
function titlePlaceholder(doc) {
|
|
10
11
|
let done = false;
|
|
@@ -18,11 +19,23 @@ function titlePlaceholder(doc) {
|
|
|
18
19
|
return decoration;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
// An empty check item keeps its tags, so the line it leaves is the whole click area;
|
|
23
|
+
// the words say where to click.
|
|
24
|
+
function checkPlaceholders(doc) {
|
|
25
|
+
const decorations = [];
|
|
26
|
+
doc.forEach((node, offset) => {
|
|
27
|
+
if (node.type !== schema.nodes.list_item || node.attrs.kind !== "check") return;
|
|
28
|
+
if (node.content.size || node.attrs.checked) return;
|
|
29
|
+
decorations.push(Decoration.node(offset, offset + node.nodeSize, { class: "page-check-placeholder", "data-placeholder": CHECK_PLACEHOLDER }));
|
|
30
|
+
});
|
|
31
|
+
return decorations;
|
|
32
|
+
}
|
|
33
|
+
|
|
21
34
|
export function placeholderPlugin(text = PLACEHOLDER_TEXT) {
|
|
22
35
|
return new state.Plugin({
|
|
23
36
|
props: {
|
|
24
37
|
decorations(st) {
|
|
25
|
-
const decorations =
|
|
38
|
+
const decorations = checkPlaceholders(st.doc);
|
|
26
39
|
const title = titlePlaceholder(st.doc);
|
|
27
40
|
if (title) decorations.push(title);
|
|
28
41
|
const { selection } = st;
|