@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,774 @@
|
|
|
1
|
+
export const ease = {
|
|
2
|
+
standard: [0.33, 0, 0.67, 1],
|
|
3
|
+
out: [0.17, 0.17, 0.4, 1],
|
|
4
|
+
snap: [0.87, 0, 0.38, 1],
|
|
5
|
+
in: [0.69, 0, 0.83, 0.83],
|
|
6
|
+
pop: [0.27, 0, 0.73, 1],
|
|
7
|
+
settle: [0.17, 0, 0.83, 1],
|
|
8
|
+
linear: [0, 0, 1, 1],
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const defaults = {
|
|
12
|
+
rise: { distance: 14, duration: 270, stagger: 125, fade: 0.2, fadeDuration: 210, ease: 'standard' },
|
|
13
|
+
cascade: { dx: 27, dy: 43, duration: 460, stagger: 167, fade: 0.7, fadeDuration: 290, ease: 'out' },
|
|
14
|
+
pop: { from: 0.9, duration: 210, ease: 'pop', overshoot: false, peak: 1.07, up: 275, down: 210, fade: 0, fadeDuration: 100 },
|
|
15
|
+
exit: { distance: 57, duration: 330, opacity: 0, ease: 'standard' },
|
|
16
|
+
slideOff: { dx: 150, dy: 0, duration: 460, stagger: 0, ease: 'in' },
|
|
17
|
+
hover: { scale: 1.03, lift: 4, rotate: 1, duration: 250, hold: 0, back: 290, ease: 'standard' },
|
|
18
|
+
press: { scale: 1.08, up: 125, down: 125 },
|
|
19
|
+
click: { settle: 160, cursorScale: 1.18, up: 125, down: 167, targetScale: 1.08, press: true },
|
|
20
|
+
move: { ease: 'standard', arc: 0.12, offset: [0.5, 0.5] },
|
|
21
|
+
ripple: { from: [0.94, 0.68], duration: 500, fade: 0.3, fadeAt: 290, fadeDuration: 210, ease: 'out' },
|
|
22
|
+
flip: { deg: 180, duration: 125, ease: 'standard' },
|
|
23
|
+
grow: { from: 0, duration: 600, ease: 'out', axis: 'x', stagger: 0 },
|
|
24
|
+
zoom: { scale: 1.28, focus: [0.5, 0.5], duration: 700, ease: 'snap' },
|
|
25
|
+
zoomOut: { duration: 420, ease: 'settle' },
|
|
26
|
+
reset: { duration: 420, ease: 'standard' },
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const IDENTITY = { translate: [0, 0], scale: [1, 1], rotate: [0], opacity: [1] }
|
|
30
|
+
const round = n => Math.round(n * 1000) / 1000
|
|
31
|
+
const FORMAT = {
|
|
32
|
+
translate: v => `${round(v[0])}px ${round(v[1])}px`,
|
|
33
|
+
scale: v => `${round(v[0])} ${round(v[1])}`,
|
|
34
|
+
rotate: v => `${round(v[0])}deg`,
|
|
35
|
+
opacity: v => `${round(v[0])}`,
|
|
36
|
+
}
|
|
37
|
+
const CURSOR_SVG = '<svg viewBox="136 60 330 400" width="20" height="24" aria-hidden="true"><path d="M142 118C142 84 180 58 214 84L440 268C472 294 455 338 418 338L335 338C310 338 290 348 274 368L226 432C202 462 158 448 156 412Z" fill="currentColor"/></svg>'
|
|
38
|
+
|
|
39
|
+
function toBezier(e) {
|
|
40
|
+
const a = typeof e === 'string' ? ease[e] : e
|
|
41
|
+
if (!Array.isArray(a) || a.length !== 4) throw new Error(`uimotion: unknown ease "${e}"`)
|
|
42
|
+
return a
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function cssEase(a) {
|
|
46
|
+
return a[0] === 0 && a[1] === 0 && a[2] === 1 && a[3] === 1 ? 'linear' : `cubic-bezier(${a.join(', ')})`
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function bezierAt([x1, y1, x2, y2], x) {
|
|
50
|
+
if (x <= 0) return 0
|
|
51
|
+
if (x >= 1) return 1
|
|
52
|
+
const curve = (a, b, t) => 3 * a * t * (1 - t) ** 2 + 3 * b * t * t * (1 - t) + t ** 3
|
|
53
|
+
let lo = 0
|
|
54
|
+
let hi = 1
|
|
55
|
+
let t = x
|
|
56
|
+
for (let i = 0; i < 40; i++) {
|
|
57
|
+
const v = curve(x1, x2, t)
|
|
58
|
+
if (Math.abs(v - x) < 1e-6) break
|
|
59
|
+
if (v < x) lo = t
|
|
60
|
+
else hi = t
|
|
61
|
+
t = (lo + hi) / 2
|
|
62
|
+
}
|
|
63
|
+
return curve(y1, y2, t)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function vec(prop, v) {
|
|
67
|
+
if (Array.isArray(v)) return v
|
|
68
|
+
if (prop === 'scale') return [v, v]
|
|
69
|
+
if (prop === 'translate') throw new Error('uimotion: translate takes [x, y]')
|
|
70
|
+
return [v]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const same = (a, b) => a.every((n, i) => Math.abs(n - b[i]) < 1e-9)
|
|
74
|
+
const lerp = (a, b, u) => a.map((n, i) => n + (b[i] - n) * u)
|
|
75
|
+
const quad = (a, c, b, u) => a.map((n, i) => (1 - u) ** 2 * n + 2 * u * (1 - u) * c[i] + u * u * b[i])
|
|
76
|
+
const SAMPLES = 24
|
|
77
|
+
const EPSILON = 1e-6
|
|
78
|
+
|
|
79
|
+
function initialValue(keys) {
|
|
80
|
+
if (keys[0].t > 0) return keys[0].v
|
|
81
|
+
let i = 0
|
|
82
|
+
while (i < keys.length - 1 && keys[i + 1].t === keys[0].t) i++
|
|
83
|
+
return keys[i].v
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function resolve(tweens, resets = []) {
|
|
87
|
+
if (!tweens.length) return []
|
|
88
|
+
const firstStart = Math.min(...tweens.map(t => t.start))
|
|
89
|
+
const list = [
|
|
90
|
+
...tweens,
|
|
91
|
+
...resets.filter(r => r.start >= firstStart).map(r => ({ ...r, toInitial: true })),
|
|
92
|
+
].sort((a, b) => a.start - b.start)
|
|
93
|
+
const keys = []
|
|
94
|
+
let cur = IDENTITY[tweens[0].prop]
|
|
95
|
+
let lastEnd = -Infinity
|
|
96
|
+
let lastTween = null
|
|
97
|
+
for (const tw of list) {
|
|
98
|
+
if (tw.start < lastEnd - EPSILON) {
|
|
99
|
+
throw new Error(`uimotion: two ${tweens[0].prop} tweens overlap on the same element at ${Math.round(tw.start)} ms (the earlier one ends at ${Math.round(lastEnd)} ms, from ${lastTween.source ?? 'a step'})`)
|
|
100
|
+
}
|
|
101
|
+
const start = Math.max(tw.start, lastEnd)
|
|
102
|
+
const from = tw.from ?? cur
|
|
103
|
+
const to = tw.toInitial ? initialValue(keys) : tw.to ?? from
|
|
104
|
+
const last = keys[keys.length - 1]
|
|
105
|
+
if (keys.length && !same(from, cur)) keys.push({ t: start, v: cur, ease: ease.linear })
|
|
106
|
+
if (!(last && last.t === start && same(last.v, from))) keys.push({ t: start, v: from, ease: ease.linear })
|
|
107
|
+
const head = keys[keys.length - 1]
|
|
108
|
+
if (tw.path) {
|
|
109
|
+
for (let i = 1; i <= SAMPLES; i++) {
|
|
110
|
+
const u = i / SAMPLES
|
|
111
|
+
keys.push({ t: start + tw.dur * u, v: tw.path(bezierAt(tw.ease, u)), ease: ease.linear })
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
head.ease = tw.ease
|
|
115
|
+
keys.push({ t: start + tw.dur, v: to, ease: ease.linear })
|
|
116
|
+
}
|
|
117
|
+
cur = keys[keys.length - 1].v
|
|
118
|
+
lastEnd = start + tw.dur
|
|
119
|
+
lastTween = tw
|
|
120
|
+
}
|
|
121
|
+
return keys
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function valueAt(keys, t, prop) {
|
|
125
|
+
if (!keys.length) return IDENTITY[prop]
|
|
126
|
+
if (t < keys[0].t) return keys[0].v
|
|
127
|
+
let i = 0
|
|
128
|
+
while (i < keys.length - 1 && keys[i + 1].t <= t) i++
|
|
129
|
+
const a = keys[i]
|
|
130
|
+
const b = keys[i + 1]
|
|
131
|
+
if (!b) return a.v
|
|
132
|
+
return lerp(a.v, b.v, bezierAt(a.ease, (t - a.t) / (b.t - a.t)))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function keyframes(keys, prop, total) {
|
|
136
|
+
const frames = keys.map(k => ({
|
|
137
|
+
offset: Math.min(1, Math.max(0, k.t / total)),
|
|
138
|
+
[prop]: FORMAT[prop](k.v),
|
|
139
|
+
easing: cssEase(k.ease),
|
|
140
|
+
}))
|
|
141
|
+
if (frames[0].offset > 0) frames.unshift({ ...frames[0], offset: 0, easing: 'linear' })
|
|
142
|
+
if (frames[frames.length - 1].offset < 1) frames.push({ ...frames[frames.length - 1], offset: 1, easing: 'linear' })
|
|
143
|
+
return frames
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function scene(stage, options) {
|
|
147
|
+
return new Scene(stage, options)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
class Scene {
|
|
151
|
+
constructor(stage, { loop = true, cursor, still } = {}) {
|
|
152
|
+
this.stage = typeof stage === 'string' ? document.querySelector(stage) : stage
|
|
153
|
+
if (!this.stage) throw new Error(`uimotion: no stage "${stage}"`)
|
|
154
|
+
this.loop = loop
|
|
155
|
+
this.cursorStart = cursor
|
|
156
|
+
this.stillAt = still
|
|
157
|
+
this.tweens = []
|
|
158
|
+
this.resets = []
|
|
159
|
+
this.t = 0
|
|
160
|
+
this.last = { start: 0, end: 0 }
|
|
161
|
+
this.mode = null
|
|
162
|
+
this.rects = new Map()
|
|
163
|
+
this.animations = null
|
|
164
|
+
this.playing = false
|
|
165
|
+
this.rate = 1
|
|
166
|
+
const view = this.stage.ownerDocument?.defaultView
|
|
167
|
+
if (view && view.getComputedStyle(this.stage).position === 'static') this.stage.style.position = 'relative'
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
get duration() {
|
|
171
|
+
return Math.max(this.t, 1)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
els(target) {
|
|
175
|
+
if (typeof target === 'string') {
|
|
176
|
+
const list = [...this.stage.querySelectorAll(target)]
|
|
177
|
+
if (!list.length) throw new Error(`uimotion: nothing matches "${target}"`)
|
|
178
|
+
return list
|
|
179
|
+
}
|
|
180
|
+
if (Array.isArray(target)) return target
|
|
181
|
+
if (target && typeof target.length === 'number' && !target.nodeType) return [...target]
|
|
182
|
+
return [target]
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
el(target) {
|
|
186
|
+
return this.els(target)[0]
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
nextStart() {
|
|
190
|
+
if (this.mode?.with != null) return this.last.start + this.mode.with
|
|
191
|
+
return this.mode?.at ?? this.t
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
step(name, build) {
|
|
195
|
+
const resume = this.animations ? { time: this.time, playing: this.playing } : null
|
|
196
|
+
this.animations?.forEach(a => a.cancel())
|
|
197
|
+
this.animations = null
|
|
198
|
+
const start = this.nextStart()
|
|
199
|
+
this.mode = null
|
|
200
|
+
this.source = `${name} at ${Math.round(start)} ms`
|
|
201
|
+
const before = this.tweens.length
|
|
202
|
+
let end = start + build(start)
|
|
203
|
+
for (const tw of this.tweens.slice(before)) end = Math.max(end, tw.start + tw.dur)
|
|
204
|
+
this.last = { start, end }
|
|
205
|
+
this.t = Math.max(this.t, end)
|
|
206
|
+
if (resume) {
|
|
207
|
+
this.seek(resume.time)
|
|
208
|
+
if (resume.playing) this.play()
|
|
209
|
+
}
|
|
210
|
+
return this
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
add(el, prop, start, dur, to, { from, ease: e = 'standard', path } = {}) {
|
|
214
|
+
this.tweens.push({
|
|
215
|
+
el,
|
|
216
|
+
prop,
|
|
217
|
+
start,
|
|
218
|
+
dur,
|
|
219
|
+
from: from == null ? undefined : vec(prop, from),
|
|
220
|
+
to: to == null ? undefined : vec(prop, to),
|
|
221
|
+
ease: toBezier(e),
|
|
222
|
+
path,
|
|
223
|
+
source: this.source,
|
|
224
|
+
})
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
current(el, prop, t) {
|
|
228
|
+
const keys = resolve(this.tweens.filter(tw => tw.el === el && tw.prop === prop), this.resets)
|
|
229
|
+
return valueAt(keys, t, prop)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
rect(el) {
|
|
233
|
+
if (!this.rects.has(el)) {
|
|
234
|
+
const s = this.stage.getBoundingClientRect()
|
|
235
|
+
const r = el.getBoundingClientRect()
|
|
236
|
+
const k = this.stageScale()
|
|
237
|
+
const x = (r.left - s.left) / k - (this.stage.clientLeft || 0)
|
|
238
|
+
const y = (r.top - s.top) / k - (this.stage.clientTop || 0)
|
|
239
|
+
const w = r.width / k
|
|
240
|
+
const h = r.height / k
|
|
241
|
+
const origin = this.stage.ownerDocument?.defaultView?.getComputedStyle(el).transformOrigin
|
|
242
|
+
const [ox, oy] = (origin ?? '').split(' ').map(parseFloat)
|
|
243
|
+
this.rects.set(el, {
|
|
244
|
+
x, y, w, h,
|
|
245
|
+
origin: [x + (Number.isFinite(ox) ? ox : w / 2), y + (Number.isFinite(oy) ? oy : h / 2)],
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
return this.rects.get(el)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
stageScale() {
|
|
252
|
+
const w = this.stage.getBoundingClientRect().width
|
|
253
|
+
return this.stage.offsetWidth ? w / this.stage.offsetWidth : 1
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
stageSize() {
|
|
257
|
+
const r = this.stage.getBoundingClientRect()
|
|
258
|
+
const k = this.stageScale()
|
|
259
|
+
return [r.width / k, r.height / k]
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
chain(el, until = this.stage) {
|
|
263
|
+
const nodes = []
|
|
264
|
+
for (let n = el; n && n !== until && n !== this.stage; n = n.parentElement) {
|
|
265
|
+
if (this.tweens.some(tw => tw.el === n)) nodes.push(n)
|
|
266
|
+
}
|
|
267
|
+
return nodes
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
transformAt(n, t) {
|
|
271
|
+
return {
|
|
272
|
+
o: this.rect(n).origin,
|
|
273
|
+
s: this.current(n, 'scale', t),
|
|
274
|
+
r: this.current(n, 'rotate', t)[0] * Math.PI / 180,
|
|
275
|
+
d: this.current(n, 'translate', t),
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
transformPoint(n, p, t) {
|
|
280
|
+
const { o, s, r, d } = this.transformAt(n, t)
|
|
281
|
+
const x = (p[0] - o[0]) * s[0]
|
|
282
|
+
const y = (p[1] - o[1]) * s[1]
|
|
283
|
+
return [o[0] + x * Math.cos(r) - y * Math.sin(r) + d[0], o[1] + x * Math.sin(r) + y * Math.cos(r) + d[1]]
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
untransformPoint(n, p, t) {
|
|
287
|
+
const { o, s, r, d } = this.transformAt(n, t)
|
|
288
|
+
const x = p[0] - o[0] - d[0]
|
|
289
|
+
const y = p[1] - o[1] - d[1]
|
|
290
|
+
return [o[0] + (x * Math.cos(r) + y * Math.sin(r)) / s[0], o[1] + (-x * Math.sin(r) + y * Math.cos(r)) / s[1]]
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
pointAt(el, t, [fx, fy] = [0.5, 0.5], until = this.stage) {
|
|
294
|
+
const r = this.rect(el)
|
|
295
|
+
let p = [r.x + r.w * fx, r.y + r.h * fy]
|
|
296
|
+
for (const n of this.chain(el, until)) p = this.transformPoint(n, p, t)
|
|
297
|
+
return p
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
cursorEl() {
|
|
301
|
+
if (this.cursor) return this.cursor
|
|
302
|
+
const doc = this.stage.ownerDocument
|
|
303
|
+
const el = doc.createElement('div')
|
|
304
|
+
el.className = 'uimotion-cursor'
|
|
305
|
+
el.setAttribute('aria-hidden', 'true')
|
|
306
|
+
el.setAttribute('clay', 'editor-ui')
|
|
307
|
+
el.innerHTML = CURSOR_SVG
|
|
308
|
+
Object.assign(el.style, {
|
|
309
|
+
position: 'absolute', left: '-1px', top: '-2px', width: '20px', height: '24px',
|
|
310
|
+
pointerEvents: 'none', zIndex: '10', transformOrigin: '1px 2px',
|
|
311
|
+
})
|
|
312
|
+
this.stage.append(el)
|
|
313
|
+
this.cursor = el
|
|
314
|
+
const [w, h] = this.stageSize()
|
|
315
|
+
const start = this.cursorStart ?? [w * 0.7, h * 0.85]
|
|
316
|
+
this.tweens.push({ el, prop: 'translate', start: 0, dur: 0, to: start, from: start, ease: ease.linear, source: 'cursor start' })
|
|
317
|
+
return el
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
with(offset = 0) {
|
|
321
|
+
this.mode = { with: offset }
|
|
322
|
+
return this
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
at(ms) {
|
|
326
|
+
this.mode = { at: ms }
|
|
327
|
+
return this
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
wait(ms) {
|
|
331
|
+
return this.step('wait', () => ms)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
set(target, values) {
|
|
335
|
+
return this.step('set', start => {
|
|
336
|
+
for (const el of this.els(target)) {
|
|
337
|
+
for (const [prop, v] of Object.entries(values)) this.add(el, prop, start, 0, v, { ease: 'linear' })
|
|
338
|
+
}
|
|
339
|
+
return 0
|
|
340
|
+
})
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
tween(target, prop, to, { duration = 300, delay = 0, stagger = 0, ...opts } = {}) {
|
|
344
|
+
return this.step('tween', start => {
|
|
345
|
+
const list = this.els(target)
|
|
346
|
+
list.forEach((el, i) => this.add(el, prop, start + delay + i * stagger, duration, to, opts))
|
|
347
|
+
return delay + (list.length - 1) * stagger + duration
|
|
348
|
+
})
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
rise(target, opts) {
|
|
352
|
+
const o = { ...defaults.rise, ...opts }
|
|
353
|
+
return this.step('rise', start => {
|
|
354
|
+
const list = this.els(target)
|
|
355
|
+
list.forEach((el, i) => {
|
|
356
|
+
const t = start + i * o.stagger
|
|
357
|
+
this.add(el, 'translate', t, o.duration, [0, 0], { from: [0, o.distance], ease: o.ease })
|
|
358
|
+
this.add(el, 'opacity', t, o.fadeDuration, 1, { from: o.fade, ease: 'linear' })
|
|
359
|
+
})
|
|
360
|
+
return (list.length - 1) * o.stagger + o.duration
|
|
361
|
+
})
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
cascade(target, opts) {
|
|
365
|
+
const o = { ...defaults.cascade, ...opts }
|
|
366
|
+
return this.step('cascade', start => {
|
|
367
|
+
const list = this.els(target)
|
|
368
|
+
list.forEach((el, i) => {
|
|
369
|
+
const t = start + i * o.stagger
|
|
370
|
+
this.add(el, 'translate', t, o.duration, [0, 0], { from: [-o.dx, -o.dy], ease: o.ease })
|
|
371
|
+
this.add(el, 'opacity', t, o.fadeDuration, 1, { from: o.fade, ease: 'out' })
|
|
372
|
+
})
|
|
373
|
+
return (list.length - 1) * o.stagger + o.duration
|
|
374
|
+
})
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
pop(target, opts) {
|
|
378
|
+
const o = { ...defaults.pop, ...opts }
|
|
379
|
+
return this.step('pop', start => {
|
|
380
|
+
for (const el of this.els(target)) {
|
|
381
|
+
if (o.fade !== false) this.add(el, 'opacity', start, o.fadeDuration, 1, { from: o.fade, ease: 'linear' })
|
|
382
|
+
if (o.overshoot) {
|
|
383
|
+
this.add(el, 'scale', start, o.up, o.peak, { from: o.from, ease: 'linear' })
|
|
384
|
+
this.add(el, 'scale', start + o.up, o.down, 1, { ease: 'linear' })
|
|
385
|
+
} else {
|
|
386
|
+
this.add(el, 'scale', start, o.duration, 1, { from: o.from, ease: o.ease })
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return o.overshoot ? o.up + o.down : o.duration
|
|
390
|
+
})
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
exit(target, opts) {
|
|
394
|
+
const o = { ...defaults.exit, ...opts }
|
|
395
|
+
return this.step('exit', start => {
|
|
396
|
+
for (const el of this.els(target)) {
|
|
397
|
+
const d = this.current(el, 'translate', start)
|
|
398
|
+
this.add(el, 'translate', start, o.duration, [d[0], d[1] - o.distance], { ease: o.ease })
|
|
399
|
+
this.add(el, 'opacity', start, o.duration, o.opacity, { ease: 'linear' })
|
|
400
|
+
}
|
|
401
|
+
return o.duration
|
|
402
|
+
})
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
slideOff(target, opts) {
|
|
406
|
+
const o = { ...defaults.slideOff, ...opts }
|
|
407
|
+
return this.step('slideOff', start => {
|
|
408
|
+
const list = this.els(target)
|
|
409
|
+
list.forEach((el, i) => {
|
|
410
|
+
const t = start + i * o.stagger
|
|
411
|
+
const d = this.current(el, 'translate', t)
|
|
412
|
+
this.add(el, 'translate', t, o.duration, [d[0] + o.dx, d[1] + o.dy], { ease: o.ease })
|
|
413
|
+
this.add(el, 'opacity', t, o.duration, 0, { ease: 'linear' })
|
|
414
|
+
})
|
|
415
|
+
return (list.length - 1) * o.stagger + o.duration
|
|
416
|
+
})
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
hover(target, opts) {
|
|
420
|
+
const o = { ...defaults.hover, ...opts }
|
|
421
|
+
return this.step('hover', start => {
|
|
422
|
+
for (const el of this.els(target)) {
|
|
423
|
+
const d = this.current(el, 'translate', start)
|
|
424
|
+
const s = this.current(el, 'scale', start)
|
|
425
|
+
const r = this.current(el, 'rotate', start)
|
|
426
|
+
const back = start + o.duration + o.hold
|
|
427
|
+
this.add(el, 'translate', start, o.duration, [d[0], d[1] - o.lift], { ease: o.ease })
|
|
428
|
+
this.add(el, 'scale', start, o.duration, [s[0] * o.scale, s[1] * o.scale], { ease: o.ease })
|
|
429
|
+
this.add(el, 'rotate', start, o.duration, [r[0] + o.rotate], { ease: o.ease })
|
|
430
|
+
this.add(el, 'translate', back, o.back, d, { ease: o.ease })
|
|
431
|
+
this.add(el, 'scale', back, o.back, s, { ease: o.ease })
|
|
432
|
+
this.add(el, 'rotate', back, o.back, r, { ease: o.ease })
|
|
433
|
+
}
|
|
434
|
+
return o.duration + o.hold + o.back
|
|
435
|
+
})
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
pulse(el, t, factor, up, down) {
|
|
439
|
+
const s = this.current(el, 'scale', t)
|
|
440
|
+
this.add(el, 'scale', t, up, [s[0] * factor, s[1] * factor], { ease: 'linear' })
|
|
441
|
+
this.add(el, 'scale', t + up, down, s, { ease: 'linear' })
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
press(target, opts) {
|
|
445
|
+
const o = { ...defaults.press, ...opts }
|
|
446
|
+
return this.step('press', start => {
|
|
447
|
+
for (const el of this.els(target)) this.pulse(el, start, o.scale, o.up, o.down)
|
|
448
|
+
return o.up + o.down
|
|
449
|
+
})
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
move(target, opts) {
|
|
453
|
+
const o = { ...defaults.move, ...opts }
|
|
454
|
+
return this.step('move', start => {
|
|
455
|
+
const c = this.cursorEl()
|
|
456
|
+
const a = this.current(c, 'translate', start)
|
|
457
|
+
const el = Array.isArray(target) ? null : this.el(target)
|
|
458
|
+
const aim = t => el ? this.pointAt(el, t, o.offset) : target
|
|
459
|
+
const timeFor = d => o.duration ?? (d < 120 ? 290 : Math.min(1000, 400 + d * 1.2))
|
|
460
|
+
let b = aim(start)
|
|
461
|
+
let dur = 0
|
|
462
|
+
for (let i = 0; i < 3; i++) {
|
|
463
|
+
dur = timeFor(Math.hypot(b[0] - a[0], b[1] - a[1]))
|
|
464
|
+
b = aim(start + dur)
|
|
465
|
+
}
|
|
466
|
+
const dist = Math.hypot(b[0] - a[0], b[1] - a[1])
|
|
467
|
+
if (dist < 1) return 0
|
|
468
|
+
const bow = dist < 120 ? 0 : o.arc * dist
|
|
469
|
+
let n = [-(b[1] - a[1]) / dist, (b[0] - a[0]) / dist]
|
|
470
|
+
if (n[1] < 0) n = [-n[0], -n[1]]
|
|
471
|
+
const ctrl = [(a[0] + b[0]) / 2 + n[0] * bow, (a[1] + b[1]) / 2 + n[1] * bow]
|
|
472
|
+
this.add(c, 'translate', start, dur, b, { ease: o.ease, path: u => quad(a, ctrl, b, u) })
|
|
473
|
+
return dur
|
|
474
|
+
})
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
click(target, opts = {}) {
|
|
478
|
+
const o = { ...defaults.click, ...opts }
|
|
479
|
+
if (target != null) {
|
|
480
|
+
const at = this.nextStart()
|
|
481
|
+
const p = Array.isArray(target) ? target : this.pointAt(this.el(target), at, o.offset)
|
|
482
|
+
const c = this.current(this.cursorEl(), 'translate', at)
|
|
483
|
+
if (Math.hypot(p[0] - c[0], p[1] - c[1]) > 2) {
|
|
484
|
+
this.move(target, { offset: o.offset, ...o.move })
|
|
485
|
+
this.mode = { at: this.last.end }
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return this.step('click', start => {
|
|
489
|
+
const t = start + o.settle
|
|
490
|
+
this.pulse(this.cursorEl(), t, o.cursorScale, o.up, o.down)
|
|
491
|
+
if (target != null && !Array.isArray(target) && o.press) this.pulse(this.el(target), t, o.targetScale, o.up, o.up)
|
|
492
|
+
return o.settle + o.up + o.down
|
|
493
|
+
})
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
ripple(target, opts) {
|
|
497
|
+
const o = { ...defaults.ripple, ...opts }
|
|
498
|
+
return this.step('ripple', start => {
|
|
499
|
+
for (const el of this.els(target)) {
|
|
500
|
+
this.add(el, 'scale', start, o.duration, 1, { from: o.from, ease: o.ease })
|
|
501
|
+
this.add(el, 'opacity', start, 0, o.fade, { from: 0, ease: 'linear' })
|
|
502
|
+
this.add(el, 'opacity', start + o.fadeAt, o.fadeDuration, 0, { ease: 'linear' })
|
|
503
|
+
}
|
|
504
|
+
return Math.max(o.duration, o.fadeAt + o.fadeDuration)
|
|
505
|
+
})
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
flip(target, opts) {
|
|
509
|
+
const o = { ...defaults.flip, ...opts }
|
|
510
|
+
return this.step('flip', start => {
|
|
511
|
+
for (const el of this.els(target)) {
|
|
512
|
+
const r = this.current(el, 'rotate', start)
|
|
513
|
+
this.add(el, 'rotate', start, o.duration, [r[0] + o.deg], { ease: o.ease })
|
|
514
|
+
}
|
|
515
|
+
return o.duration
|
|
516
|
+
})
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
grow(target, opts) {
|
|
520
|
+
const o = { ...defaults.grow, ...opts }
|
|
521
|
+
return this.step('grow', start => {
|
|
522
|
+
const list = this.els(target)
|
|
523
|
+
const from = o.axis === 'x' ? [o.from, 1] : [1, o.from]
|
|
524
|
+
list.forEach((el, i) => this.add(el, 'scale', start + i * o.stagger, o.duration, [1, 1], { from, ease: o.ease }))
|
|
525
|
+
return (list.length - 1) * o.stagger + o.duration
|
|
526
|
+
})
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
zoom(target, opts) {
|
|
530
|
+
const o = { ...defaults.zoom, ...opts }
|
|
531
|
+
return this.step('zoom', start => {
|
|
532
|
+
const el = this.el(target)
|
|
533
|
+
const end = start + o.duration
|
|
534
|
+
const s = vec('scale', o.scale)
|
|
535
|
+
let d = [0, 0]
|
|
536
|
+
if (o.to) {
|
|
537
|
+
const p = Array.isArray(o.to) ? o.to : this.pointAt(this.el(o.to), end, [0.5, 0.5], el)
|
|
538
|
+
const st = this.stageSize()
|
|
539
|
+
let f = [st[0] * o.focus[0], st[1] * o.focus[1]]
|
|
540
|
+
for (const n of this.chain(el.parentElement).reverse()) f = this.untransformPoint(n, f, end)
|
|
541
|
+
const c = this.rect(el).origin
|
|
542
|
+
const r = this.current(el, 'rotate', end)[0] * Math.PI / 180
|
|
543
|
+
const x = (p[0] - c[0]) * s[0]
|
|
544
|
+
const y = (p[1] - c[1]) * s[1]
|
|
545
|
+
d = [f[0] - c[0] - (x * Math.cos(r) - y * Math.sin(r)), f[1] - c[1] - (x * Math.sin(r) + y * Math.cos(r))]
|
|
546
|
+
}
|
|
547
|
+
this.add(el, 'scale', start, o.duration, s, { ease: o.ease })
|
|
548
|
+
this.add(el, 'translate', start, o.duration, d, { ease: o.ease })
|
|
549
|
+
return o.duration
|
|
550
|
+
})
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
zoomOut(target, opts) {
|
|
554
|
+
const o = { ...defaults.zoomOut, ...opts }
|
|
555
|
+
return this.step('zoomOut', start => {
|
|
556
|
+
const el = this.el(target)
|
|
557
|
+
this.add(el, 'scale', start, o.duration, 1, { ease: o.ease })
|
|
558
|
+
this.add(el, 'translate', start, o.duration, [0, 0], { ease: o.ease })
|
|
559
|
+
return o.duration
|
|
560
|
+
})
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
reset(opts) {
|
|
564
|
+
const o = { ...defaults.reset, ...opts }
|
|
565
|
+
return this.step('reset', start => {
|
|
566
|
+
if (this.stillAt == null) this.stillAt = start
|
|
567
|
+
this.resets.push({ start, dur: o.duration, ease: toBezier(o.ease), source: `reset at ${Math.round(start)} ms` })
|
|
568
|
+
return o.duration
|
|
569
|
+
})
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
build() {
|
|
573
|
+
if (this.animations) return this.animations
|
|
574
|
+
const total = this.duration
|
|
575
|
+
const groups = new Map()
|
|
576
|
+
for (const tw of this.tweens) {
|
|
577
|
+
const key = groups.get(tw.el) ?? new Map()
|
|
578
|
+
groups.set(tw.el, key)
|
|
579
|
+
if (!key.has(tw.prop)) key.set(tw.prop, [])
|
|
580
|
+
key.get(tw.prop).push(tw)
|
|
581
|
+
}
|
|
582
|
+
const animations = []
|
|
583
|
+
try {
|
|
584
|
+
for (const [el, props] of groups) {
|
|
585
|
+
for (const [prop, list] of props) {
|
|
586
|
+
const keys = resolve(list, this.resets)
|
|
587
|
+
if (this.loop && this.resets.length && !same(keys[keys.length - 1].v, initialValue(keys))) {
|
|
588
|
+
const late = list.reduce((a, b) => (b.start > a.start ? b : a))
|
|
589
|
+
throw new Error(`uimotion: ${prop} on an element still changes after the last reset() (${late.source}), so the loop jumps. Move reset() to the end, or return it to its start value.`)
|
|
590
|
+
}
|
|
591
|
+
const anim = el.animate(keyframes(keys, prop, total), { duration: total, iterations: this.loop ? Infinity : 1, fill: 'both' })
|
|
592
|
+
anim.pause()
|
|
593
|
+
anim.playbackRate = this.rate
|
|
594
|
+
animations.push(anim)
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
} catch (error) {
|
|
598
|
+
animations.forEach(a => a.cancel())
|
|
599
|
+
throw error
|
|
600
|
+
}
|
|
601
|
+
this.animations = animations
|
|
602
|
+
if (this.stage.dataset) this.stage.dataset.uimotion = 'ready'
|
|
603
|
+
return animations
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
play() {
|
|
607
|
+
this.build()
|
|
608
|
+
const reduce = this.stage.ownerDocument.defaultView?.matchMedia?.('(prefers-reduced-motion: reduce)').matches
|
|
609
|
+
if (reduce) return this.seek(this.stillAt ?? (this.loop ? this.duration - 0.01 : this.duration))
|
|
610
|
+
this.animations.forEach(a => a.play())
|
|
611
|
+
this.playing = true
|
|
612
|
+
return this
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
pause() {
|
|
616
|
+
this.build().forEach(a => a.pause())
|
|
617
|
+
this.playing = false
|
|
618
|
+
return this
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
seek(ms) {
|
|
622
|
+
this.build().forEach(a => {
|
|
623
|
+
a.pause()
|
|
624
|
+
a.currentTime = ms
|
|
625
|
+
})
|
|
626
|
+
this.playing = false
|
|
627
|
+
return this
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
speed(rate) {
|
|
631
|
+
this.rate = rate
|
|
632
|
+
this.build().forEach(a => { a.playbackRate = rate })
|
|
633
|
+
return this
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
get time() {
|
|
637
|
+
const t = this.build()[0]?.currentTime ?? 0
|
|
638
|
+
return this.loop ? t % this.duration : Math.min(t, this.duration)
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
debug() {
|
|
642
|
+
const doc = this.stage.ownerDocument
|
|
643
|
+
const bar = doc.createElement('div')
|
|
644
|
+
bar.className = 'uimotion-debug'
|
|
645
|
+
bar.setAttribute('clay', 'editor-ui')
|
|
646
|
+
bar.style.cssText = 'display:flex;gap:8px;align-items:center;margin-top:8px;font:12px/1.4 ui-monospace,monospace'
|
|
647
|
+
bar.innerHTML = '<button type="button">Pause</button><input type="range" min="0" step="1" style="flex:1"><select><option>0.25</option><option>0.5</option><option selected>1</option></select><span></span>'
|
|
648
|
+
const [button, range, select, label] = bar.children
|
|
649
|
+
range.max = Math.round(this.duration)
|
|
650
|
+
this.stage.after(bar)
|
|
651
|
+
let playing = true
|
|
652
|
+
const show = t => { label.textContent = `${Math.round(t)} / ${Math.round(this.duration)} ms` }
|
|
653
|
+
button.onclick = () => {
|
|
654
|
+
playing = !playing
|
|
655
|
+
if (playing) this.play()
|
|
656
|
+
else this.pause()
|
|
657
|
+
button.textContent = playing ? 'Pause' : 'Play'
|
|
658
|
+
}
|
|
659
|
+
range.oninput = () => {
|
|
660
|
+
playing = false
|
|
661
|
+
button.textContent = 'Play'
|
|
662
|
+
this.seek(+range.value)
|
|
663
|
+
show(+range.value)
|
|
664
|
+
}
|
|
665
|
+
select.onchange = () => this.speed(+select.value)
|
|
666
|
+
const tick = () => {
|
|
667
|
+
if (playing) {
|
|
668
|
+
range.value = this.time
|
|
669
|
+
show(this.time)
|
|
670
|
+
}
|
|
671
|
+
doc.defaultView.requestAnimationFrame(tick)
|
|
672
|
+
}
|
|
673
|
+
tick()
|
|
674
|
+
return this
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// A step that returns every animated property to its start value at this point, except
|
|
679
|
+
// opacity on `keep`, which the scene fades itself.
|
|
680
|
+
export function rewind(s, keep = []) {
|
|
681
|
+
return s.step('rewind', start => {
|
|
682
|
+
const groups = new Map()
|
|
683
|
+
for (const tw of s.tweens) {
|
|
684
|
+
if (tw.prop === 'opacity' && keep.includes(tw.el)) continue
|
|
685
|
+
const props = groups.get(tw.el) ?? new Map()
|
|
686
|
+
groups.set(tw.el, props)
|
|
687
|
+
if (!props.has(tw.prop)) props.set(tw.prop, [])
|
|
688
|
+
props.get(tw.prop).push(tw)
|
|
689
|
+
}
|
|
690
|
+
for (const [el, props] of groups) {
|
|
691
|
+
for (const [prop, list] of props) {
|
|
692
|
+
const keys = resolve(list, s.resets)
|
|
693
|
+
const v = initialValue(keys)
|
|
694
|
+
if (!same(valueAt(keys, start, prop), v)) s.add(el, prop, start, 0, v, { ease: 'linear' })
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return 0
|
|
698
|
+
})
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// Plays a scene in a stage while the stage is in the page: rebuilt when its width changes
|
|
702
|
+
// or the fonts arrive (keeping its place in the loop), paused while the tab is hidden or
|
|
703
|
+
// the stage is off screen, and stopped for good once the stage leaves the page.
|
|
704
|
+
export function mount(stage, build, { watch = stage, teardown, debug = false } = {}) {
|
|
705
|
+
const doc = stage.ownerDocument
|
|
706
|
+
let s = null
|
|
707
|
+
let width = 0
|
|
708
|
+
let onScreen = true
|
|
709
|
+
let queued = false
|
|
710
|
+
let queuedForce = false
|
|
711
|
+
let done = false
|
|
712
|
+
const shown = () => onScreen && doc.visibilityState !== 'hidden'
|
|
713
|
+
const sync = () => { if (s) shown() ? s.play() : s.pause() }
|
|
714
|
+
const clear = () => {
|
|
715
|
+
if (!s) return
|
|
716
|
+
s.animations?.forEach(a => a.cancel())
|
|
717
|
+
s.cursor?.remove()
|
|
718
|
+
if (stage.nextElementSibling?.classList.contains('uimotion-debug')) stage.nextElementSibling.remove()
|
|
719
|
+
teardown?.(stage)
|
|
720
|
+
delete stage.dataset.uimotion
|
|
721
|
+
delete stage.uimotionScene
|
|
722
|
+
s = null
|
|
723
|
+
width = 0
|
|
724
|
+
}
|
|
725
|
+
const stop = () => {
|
|
726
|
+
if (done) return
|
|
727
|
+
done = true
|
|
728
|
+
clear()
|
|
729
|
+
ro.disconnect()
|
|
730
|
+
io?.disconnect()
|
|
731
|
+
doc.removeEventListener('visibilitychange', sync)
|
|
732
|
+
}
|
|
733
|
+
const start = force => {
|
|
734
|
+
if (done) return
|
|
735
|
+
if (!stage.isConnected) return stop()
|
|
736
|
+
const w = stage.offsetWidth
|
|
737
|
+
if (!force && w === width) return
|
|
738
|
+
const time = s ? s.time : 0
|
|
739
|
+
clear()
|
|
740
|
+
if (!w) return
|
|
741
|
+
try {
|
|
742
|
+
s = build(stage)
|
|
743
|
+
width = w
|
|
744
|
+
stage.uimotionScene = s
|
|
745
|
+
s.seek(time)
|
|
746
|
+
sync()
|
|
747
|
+
if (debug) s.debug()
|
|
748
|
+
} catch (error) {
|
|
749
|
+
console.error(error)
|
|
750
|
+
clear()
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
const queue = force => {
|
|
754
|
+
queuedForce = queuedForce || force
|
|
755
|
+
if (queued) return
|
|
756
|
+
queued = true
|
|
757
|
+
requestAnimationFrame(() => {
|
|
758
|
+
queued = false
|
|
759
|
+
const f = queuedForce
|
|
760
|
+
queuedForce = false
|
|
761
|
+
start(f)
|
|
762
|
+
})
|
|
763
|
+
}
|
|
764
|
+
const ro = new ResizeObserver(() => (stage.isConnected ? queue(false) : stop()))
|
|
765
|
+
ro.observe(watch)
|
|
766
|
+
const io = typeof IntersectionObserver === 'function'
|
|
767
|
+
? new IntersectionObserver(entries => { onScreen = entries[entries.length - 1].isIntersecting; sync() })
|
|
768
|
+
: null
|
|
769
|
+
io?.observe(stage)
|
|
770
|
+
doc.addEventListener('visibilitychange', sync)
|
|
771
|
+
if (doc.fonts && doc.fonts.status !== 'loaded') doc.fonts.ready.then(() => queue(true))
|
|
772
|
+
start(false)
|
|
773
|
+
return { stop, get scene() { return s } }
|
|
774
|
+
}
|