@cardstack/boxel-cli 0.13.0-unstable.4 → 0.13.0-unstable.5
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/bundled-realms/pretui/components/doc-report.gts +2 -2
- package/bundled-realms/pretui/components/doc-report.usage.gts +3 -3
- package/bundled-realms/pretui/components/form-field.md +1 -1
- package/bundled-realms/pretui/components/icon-button.md +1 -1
- package/bundled-realms/pretui/components/popup.md +1 -1
- package/bundled-realms/pretui/components/switch.gts +13 -0
- package/bundled-realms/pretui/components/switch.md +5 -3
- package/bundled-realms/pretui/components/theme-frame.gts +49 -22
- package/bundled-realms/pretui/components/tooltip.gts +141 -42
- package/bundled-realms/pretui/components/tooltip.md +10 -12
- package/bundled-realms/pretui/components/tooltip.usage.gts +3 -5
- package/bundled-realms/pretui/docs/structure.md +1 -1
- package/bundled-realms/pretui/internal/overlay.gts +4 -2
- package/bundled-realms/pretui/pretui-css.gts +6 -2
- package/bundled-realms/pretui/theme-scoped-css.gts +262 -0
- package/bundled-test-harness/assets/account-switch-failed-test-DwAZq6Sc.js +45 -0
- package/bundled-test-harness/assets/adapter-C_6pnsx1.js +2 -0
- package/bundled-test-harness/assets/add-field-to-card-definition-tool-test-zMYtJWBv.js +112 -0
- package/bundled-test-harness/assets/ai-assistant-create-workspace-test-CwhAV-Ow.js +130 -0
- package/bundled-test-harness/assets/ai-assistant-panel-relogin-test-DNgclkGJ.js +46 -0
- package/bundled-test-harness/assets/ai-assistant-test-DGYFiRTb.js +2223 -0
- package/bundled-test-harness/assets/ai-function-generation-test-Dj6WzKkh.js +1176 -0
- package/bundled-test-harness/assets/ai-module-creation-test-EsOoJpQ1.js +151 -0
- package/bundled-test-harness/assets/aibot-message-uGaCPn5o.js +1312 -0
- package/bundled-test-harness/assets/app-pIzBYfiZ.js +14146 -0
- package/bundled-test-harness/assets/apply-markdown-edit-test-CPhfeg1i.js +230 -0
- package/bundled-test-harness/assets/ask-user-picker-NVRkhKwt.js +370 -0
- package/bundled-test-harness/assets/ask-user-picker-test-SsZqFm9W.js +39 -0
- package/bundled-test-harness/assets/assistant-transcript-test-DesuBCIB.js +57 -0
- package/bundled-test-harness/assets/audio-metadata-extractor-test-8JM6oZXG.js +1176 -0
- package/bundled-test-harness/assets/authed-fetch-test-yPTMe-9V.js +73 -0
- package/bundled-test-harness/assets/avif-image-def-test-Kyknj908.js +187 -0
- package/bundled-test-harness/assets/basic-test-D9OrrMaq.js +139 -0
- package/bundled-test-harness/assets/binary-upload-dedupe-test-Dnxlbbu6.js +308 -0
- package/bundled-test-harness/assets/bot-registration-test-Bk2lTaCW.js +97 -0
- package/bundled-test-harness/assets/box-test-BbV9sMyU.js +50 -0
- package/bundled-test-harness/assets/brand-guide-attachments-test-z4wTsKbI.js +84 -0
- package/bundled-test-harness/assets/brand-guide-custom-css-test-BlSJE8xo.js +196 -0
- package/bundled-test-harness/assets/brand-guide-edit-test-DJ1OQ6IB.js +140 -0
- package/bundled-test-harness/assets/brand-logo-mark-field-test-ux7eetkO.js +86 -0
- package/bundled-test-harness/assets/broken-link-template-test-CqB3MWyw.js +192 -0
- package/bundled-test-harness/assets/bundled-base-modules-test-B2oNLZSJ.js +54 -0
- package/bundled-test-harness/assets/bundled-base-oracle-test-DelPfFjn.js +37 -0
- package/bundled-test-harness/assets/buried-stack-item-scroll-test-Ixsl1tS0.js +236 -0
- package/bundled-test-harness/assets/button-BvYQm_A1.js +141 -0
- package/bundled-test-harness/assets/bxl-cyclic-graph-test-p23WCLRW.js +47 -0
- package/bundled-test-harness/assets/bxl-expression-test-CVTQYT_C.js +250 -0
- package/bundled-test-harness/assets/bxl-indexing-test-D_A7X2sr.js +212 -0
- package/bundled-test-harness/assets/bxl-platform-module-test-Cltfyybp.js +71 -0
- package/bundled-test-harness/assets/can-invoke-test-DJi7jMaU.js +455 -0
- package/bundled-test-harness/assets/can-read-realm-test-CIz6WX_K.js +56 -0
- package/bundled-test-harness/assets/cancel-indexing-job-test-0LlrOgYK.js +69 -0
- package/bundled-test-harness/assets/capture-test-diHIWmh0.js +360 -0
- package/bundled-test-harness/assets/card-api-test-Ci9b0ghP.js +198 -0
- package/bundled-test-harness/assets/card-basics-test-RKQoQWZD.js +5364 -0
- package/bundled-test-harness/assets/card-chooser-paging-test-BoUyFMEw.js +235 -0
- package/bundled-test-harness/assets/card-chooser-test-7ZwhxxkH.js +393 -0
- package/bundled-test-harness/assets/card-context-search-results-KmkXJbmC.js +30 -0
- package/bundled-test-harness/assets/card-context-search-results-test-CpMr8OlX.js +184 -0
- package/bundled-test-harness/assets/card-def-field-def-relationships-test-ByPl5n55.js +562 -0
- package/bundled-test-harness/assets/card-def-menu-items-test-ohuHc0b4.js +228 -0
- package/bundled-test-harness/assets/card-delete-test-Be971b-V.js +466 -0
- package/bundled-test-harness/assets/card-error-3q1o3i0e.js +72 -0
- package/bundled-test-harness/assets/card-error-awaiting-index-test-DPgYKfbF.js +53 -0
- package/bundled-test-harness/assets/card-info-thumbnail-picker-test-CVfeJyjt.js +219 -0
- package/bundled-test-harness/assets/card-playground-test-D-7bi4PQ.js +1491 -0
- package/bundled-test-harness/assets/card-prerender-DemTfK_a.js +12939 -0
- package/bundled-test-harness/assets/card-thunk-error-test-DCBh1vRT.js +48 -0
- package/bundled-test-harness/assets/card-type-service-test-DXPrfVYk.js +161 -0
- package/bundled-test-harness/assets/check-correctness-test-DjE7r1X2.js +1093 -0
- package/bundled-test-harness/assets/check-domain-availability-test-U10xSKbY.js +98 -0
- package/bundled-test-harness/assets/chip-0r_r9SC8.js +44 -0
- package/bundled-test-harness/assets/choreo-Ci5dG5fv.js +2 -0
- package/bundled-test-harness/assets/choreo-D1K9RyjM.js +1031 -0
- package/bundled-test-harness/assets/choreo-feature-reel-test-vzmW-SFd.js +155 -0
- package/bundled-test-harness/assets/choreo-gallery-build-order-test-J6n0_PKm.js +436 -0
- package/bundled-test-harness/assets/choreo-gallery-compositor-test-DSi1N9bi.js +399 -0
- package/bundled-test-harness/assets/choreo-gallery-cover-test-BT05gNKC.js +214 -0
- package/bundled-test-harness/assets/choreo-gallery-crossing-stage-test-BIuLOZH6.js +133 -0
- package/bundled-test-harness/assets/choreo-gallery-demos-alive-test-ClGjpnj6.js +42 -0
- package/bundled-test-harness/assets/choreo-gallery-drift-test-OjxMXV0Y.js +620 -0
- package/bundled-test-harness/assets/choreo-gallery-escort-test-D6VL4FfT.js +187 -0
- package/bundled-test-harness/assets/choreo-gallery-films-test-DBcDHGx8.js +140 -0
- package/bundled-test-harness/assets/choreo-gallery-filter-test-BUghtJZe.js +46 -0
- package/bundled-test-harness/assets/choreo-gallery-fold-test-0D9-_h_I.js +180 -0
- package/bundled-test-harness/assets/choreo-gallery-guide-pages-test-DS41eNNV.js +114 -0
- package/bundled-test-harness/assets/choreo-gallery-guides-test-CZnaxUNJ.js +321 -0
- package/bundled-test-harness/assets/choreo-gallery-hang-test-WFvsJ-MJ.js +426 -0
- package/bundled-test-harness/assets/choreo-gallery-highlight-test-Dn0hYPLC.js +60 -0
- package/bundled-test-harness/assets/choreo-gallery-inline-edit-test-C5WvS67s.js +370 -0
- package/bundled-test-harness/assets/choreo-gallery-interruption-test-CgT9RKTe.js +176 -0
- package/bundled-test-harness/assets/choreo-gallery-lone-stack-test-BZgqbTJd.js +104 -0
- package/bundled-test-harness/assets/choreo-gallery-navigation-test-CWzXkvbW.js +193 -0
- package/bundled-test-harness/assets/choreo-gallery-playhead-transport-test-Dt71t4CU.js +111 -0
- package/bundled-test-harness/assets/choreo-gallery-poplayout-subtree-test-B_rDq4em.js +127 -0
- package/bundled-test-harness/assets/choreo-gallery-presence-modes-test-j_cZ9cAM.js +100 -0
- package/bundled-test-harness/assets/choreo-gallery-presentation-test-CIFKR65J.js +157 -0
- package/bundled-test-harness/assets/choreo-gallery-reduced-motion-test-BvRCiCvB.js +145 -0
- package/bundled-test-harness/assets/choreo-gallery-sheet-standalone-test-DgO2MBzU.js +89 -0
- package/bundled-test-harness/assets/choreo-gallery-sheet-test-BntUKT_P.js +48 -0
- package/bundled-test-harness/assets/choreo-gallery-site-test-CvSE6Jyq.js +237 -0
- package/bundled-test-harness/assets/choreo-gallery-stage-Dj6tFzon.js +256 -0
- package/bundled-test-harness/assets/choreo-gallery-stage-keyboard-test-CkDrAPA8.js +102 -0
- package/bundled-test-harness/assets/choreo-gallery-stages-test-DHUmzoRW.js +35 -0
- package/bundled-test-harness/assets/choreo-gallery-subdivision-test-BZ9-cDFh.js +138 -0
- package/bundled-test-harness/assets/choreo-gallery-table-plan-test-7uP6mZpo.js +144 -0
- package/bundled-test-harness/assets/choreo-gallery-theater-test-DgEue9FD.js +252 -0
- package/bundled-test-harness/assets/choreo-gallery-tuning-test-CfPx5iCp.js +95 -0
- package/bundled-test-harness/assets/choreo-gallery-widget-room-test-o9T2EFKq.js +88 -0
- package/bundled-test-harness/assets/choreo-gallery-wires-test-73JLkxn6.js +148 -0
- package/bundled-test-harness/assets/client-telemetry-test-DFM4mML2.js +340 -0
- package/bundled-test-harness/assets/clip-CsRtHZiN.js +92 -0
- package/bundled-test-harness/assets/clip-CycGr0Lf.js +2 -0
- package/bundled-test-harness/assets/code-block-DRE8KQZQ.js +502 -0
- package/bundled-test-harness/assets/code-ref-test-CDcqE8_C.js +163 -0
- package/bundled-test-harness/assets/code-submode-availability-test-DPTqZYYm.js +198 -0
- package/bundled-test-harness/assets/code-submode-test-AHV4mzJ4.js +1839 -0
- package/bundled-test-harness/assets/codeblocks-test-D9pbJMK8.js +418 -0
- package/bundled-test-harness/assets/codemirror-editor-test-BeAMVivu.js +1512 -0
- package/bundled-test-harness/assets/codemirror-embed-toolbar-test-Bnb7_KUT.js +366 -0
- package/bundled-test-harness/assets/color-field-test-CR6gGEqE.js +212 -0
- package/bundled-test-harness/assets/compaction-test-BSqAGv4g.js +150 -0
- package/bundled-test-harness/assets/computed-test-DtyZGgdc.js +1320 -0
- package/bundled-test-harness/assets/container-CEslVSTe.js +10884 -0
- package/bundled-test-harness/assets/content-preview-components-test-BztI4fz-.js +462 -0
- package/bundled-test-harness/assets/copy-and-edit-test-Cqw7kcur.js +292 -0
- package/bundled-test-harness/assets/copy-card-test-D5m3eVEH.js +218 -0
- package/bundled-test-harness/assets/copy-file-to-realm-test-FPY-6Ddm.js +148 -0
- package/bundled-test-harness/assets/copy-source-test-9pJD-qey.js +56 -0
- package/bundled-test-harness/assets/create-file-test-DjMf88u_.js +1086 -0
- package/bundled-test-harness/assets/create-file-test-XbgOqg38.js +464 -0
- package/bundled-test-harness/assets/create-listing-modal-test-DyGlGMWu.js +273 -0
- package/bundled-test-harness/assets/create-listing-pr-request-test-CBtIV0Z8.js +117 -0
- package/bundled-test-harness/assets/create-spec-test-4xR0gM7E.js +256 -0
- package/bundled-test-harness/assets/create-submission-workflow-test-DQpWrpGT.js +132 -0
- package/bundled-test-harness/assets/create-workspace-test-BQAudgpS.js +104 -0
- package/bundled-test-harness/assets/credential-fields-test-DXKBdbZD.js +200 -0
- package/bundled-test-harness/assets/csv-file-def-test-Cnp4y834.js +102 -0
- package/bundled-test-harness/assets/dashboard-CmuOhIYC.js +3628 -0
- package/bundled-test-harness/assets/dashboard-CzN49x74.css +2400 -0
- package/bundled-test-harness/assets/dashboard-add-workspace-test-T32hWB-g.js +50 -0
- package/bundled-test-harness/assets/dashboard-agents-test-BN5maCgQ.js +334 -0
- package/bundled-test-harness/assets/dashboard-archive-test-BzwUte_Z.js +128 -0
- package/bundled-test-harness/assets/dashboard-delete-test-D2Gcp81V.js +163 -0
- package/bundled-test-harness/assets/dashboard-duplicate-offer-test-BgKNIr35.js +71 -0
- package/bundled-test-harness/assets/dashboard-duplicate-test-D7JEWylc.js +222 -0
- package/bundled-test-harness/assets/dashboard-get-started-test-DOGPzGoA.js +374 -0
- package/bundled-test-harness/assets/dashboard-ir2bakJS.js +142 -0
- package/bundled-test-harness/assets/dashboard-pinned-cards-test-Bn_P9xJU.js +220 -0
- package/bundled-test-harness/assets/dashboard-publish-test-64sGQ0nG.js +70 -0
- package/bundled-test-harness/assets/dashboard-reindex-test-DJjYq1ct.js +115 -0
- package/bundled-test-harness/assets/dashboard-section-rail-test-ZkAhWu5V.js +169 -0
- package/bundled-test-harness/assets/dashboard-state-test-BbkpPB5L.js +162 -0
- package/bundled-test-harness/assets/dashboard-test-CBLdPrSt.js +545 -0
- package/bundled-test-harness/assets/dashboard-unreachable-notice-test-DFT3R1Zx.js +62 -0
- package/bundled-test-harness/assets/dashboard-workspace-test-DqBdCFo2.js +537 -0
- package/bundled-test-harness/assets/dashboard-workspaces-section-test-CH1HDfxR.js +410 -0
- package/bundled-test-harness/assets/data-file-def-preview-test-CNsZwQEJ.js +155 -0
- package/bundled-test-harness/assets/date-time-fields-test-CEFaZTnF.js +359 -0
- package/bundled-test-harness/assets/debug-message-test-0hv0RwE_.js +117 -0
- package/bundled-test-harness/assets/declared-captures-test-C-0yPRU7.js +879 -0
- package/bundled-test-harness/assets/delete-workspace-test-CZOwGy78.js +102 -0
- package/bundled-test-harness/assets/diffing-test-BEKI905O.js +210 -0
- package/bundled-test-harness/assets/download-file-to-realm-test-C1kAGDll.js +119 -0
- package/bundled-test-harness/assets/editor-test-C9x5ZY6g.js +688 -0
- package/bundled-test-harness/assets/edits-D76-aanh.js +651 -0
- package/bundled-test-harness/assets/email-field-test-LGkrB_2B.js +75 -0
- package/bundled-test-harness/assets/enum-field-test-CPyV1J-m.js +935 -0
- package/bundled-test-harness/assets/error-display-test-bWuUtfIG.js +343 -0
- package/bundled-test-harness/assets/evaluate-module-test-CbS5h8t3.js +91 -0
- package/bundled-test-harness/assets/execute-atomic-operations-test-B4Kfco0k.js +113 -0
- package/bundled-test-harness/assets/externals-CDQm-Lm7.js +4393 -0
- package/bundled-test-harness/assets/fallback-banner-live-delete-test-DQSiTzvj.js +207 -0
- package/bundled-test-harness/assets/fallback-banner-test-CJFKLpOy.js +225 -0
- package/bundled-test-harness/assets/fallback-banner-test-DQkrFE4-.js +53 -0
- package/bundled-test-harness/assets/fallback-models-test-CiWfmxaB.js +161 -0
- package/bundled-test-harness/assets/fetch-card-json-test-DULUqUEu.js +61 -0
- package/bundled-test-harness/assets/field-configuration-test-BXZq28xa.js +551 -0
- package/bundled-test-harness/assets/field-markdown-domain-test-DdXCifs6.js +616 -0
- package/bundled-test-harness/assets/field-markdown-oversize-test-DouPPTHX.js +88 -0
- package/bundled-test-harness/assets/field-markdown-primitives-test-DSRGJeyl.js +365 -0
- package/bundled-test-harness/assets/field-markdown-specialized-test-DlTYLl_s.js +534 -0
- package/bundled-test-harness/assets/field-playground-test-NhS4VvoN.js +894 -0
- package/bundled-test-harness/assets/field-support-predicates-test-DWpyT1Qf.js +167 -0
- package/bundled-test-harness/assets/file-attachment-test-m72-VerW.js +796 -0
- package/bundled-test-harness/assets/file-chooser-panel-test-DuAqD9bn.js +153 -0
- package/bundled-test-harness/assets/file-chooser-test-CjaXXwpT.js +504 -0
- package/bundled-test-harness/assets/file-def-format-templates-test-BDs4OmHq.js +380 -0
- package/bundled-test-harness/assets/file-def-live-reload-test-BqTdnq-W.js +124 -0
- package/bundled-test-harness/assets/file-def-menu-items-test-DqdINXsD.js +138 -0
- package/bundled-test-harness/assets/file-def-navigation-test-BPGr0SQy.js +109 -0
- package/bundled-test-harness/assets/file-def-serialization-test-CvjW-FlC.js +89 -0
- package/bundled-test-harness/assets/file-def-test-C-Yv_NjS.js +216 -0
- package/bundled-test-harness/assets/file-preview-live-reload-test-MzwGwasU.js +310 -0
- package/bundled-test-harness/assets/file-resource-primitives-test-D3GmfqNs.js +255 -0
- package/bundled-test-harness/assets/file-tree-from-index-test-CfldnUgm.js +96 -0
- package/bundled-test-harness/assets/file-tree-test--0ZCPRe9.js +851 -0
- package/bundled-test-harness/assets/file-view-model-test-BDIAeBV8.js +346 -0
- package/bundled-test-harness/assets/filedef-export-shape-test-B2tgU404.js +61 -0
- package/bundled-test-harness/assets/film-D1E-odYG.js +13 -0
- package/bundled-test-harness/assets/film-D25Y0ED6.js +2 -0
- package/bundled-test-harness/assets/film-D97U-ydx.js +4074 -0
- package/bundled-test-harness/assets/flac-audio-def-test-ByoXMoQ1.js +143 -0
- package/bundled-test-harness/assets/font-metadata-extractor-test-hawLTDTG.js +415 -0
- package/bundled-test-harness/assets/formatted-aibot-message-test-Bdx_-Ktn.js +109 -0
- package/bundled-test-harness/assets/formatted-user-message-test-CodbrU3t.js +43 -0
- package/bundled-test-harness/assets/freestyle-test-faQhSciz.js +17 -0
- package/bundled-test-harness/assets/full-reindex-realm-test-CE5RJTIC.js +101 -0
- package/bundled-test-harness/assets/garbage-collection-test-v-3sev77.js +403 -0
- package/bundled-test-harness/assets/general-test-DQuxDvXK.js +923 -0
- package/bundled-test-harness/assets/generate-example-cards-one-shot-test-CucWyrkH.js +65 -0
- package/bundled-test-harness/assets/generic-file-def-preview-test-_EDRsebi.js +71 -0
- package/bundled-test-harness/assets/get-available-realm-identifiers-test-CV023yek.js +47 -0
- package/bundled-test-harness/assets/get-catalog-realm-identifiers-test--DOu3DyV.js +47 -0
- package/bundled-test-harness/assets/get-default-writable-realm-test-Bic8jl6R.js +54 -0
- package/bundled-test-harness/assets/get-published-realms-test-DrA5YcFN.js +71 -0
- package/bundled-test-harness/assets/get-realm-of-resource-identifier-test-jfU6SIWn.js +54 -0
- package/bundled-test-harness/assets/get-relationship-membership-state-test-Ccy2Z7MN.js +1308 -0
- package/bundled-test-harness/assets/get-user-system-card-test-Bmq2lmWv.js +67 -0
- package/bundled-test-harness/assets/gif-image-def-test-N1mMQC-X.js +188 -0
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-DzPKH76g.js +160 -0
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-D9mlcQuN.js +74 -0
- package/bundled-test-harness/assets/gts-file-def-test-BL1jpQ9J.js +100 -0
- package/bundled-test-harness/assets/head-format-preview-test-BVCaPQqc.js +158 -0
- package/bundled-test-harness/assets/helpers-Ds68JxHe.js +5 -0
- package/bundled-test-harness/assets/host-mode-service-B4bisRdR.js +262 -0
- package/bundled-test-harness/assets/host-mode-test-BmkN2PCJ.js +831 -0
- package/bundled-test-harness/assets/host-submode-test-C6SxQ796.js +1392 -0
- package/bundled-test-harness/assets/html-component-test-CNQ9wF0Q.js +65 -0
- package/bundled-test-harness/assets/html-def-test-BcaCVVQq.js +160 -0
- package/bundled-test-harness/assets/html-meta-extractor-test-BU1hjkTp.js +60 -0
- package/bundled-test-harness/assets/hydratable-card-test-CX6MWiti.js +426 -0
- package/bundled-test-harness/assets/icon-button-C1zH38Nc.js +67 -0
- package/bundled-test-harness/assets/image-metadata-extractor-test-CakSBPZ_.js +1109 -0
- package/bundled-test-harness/assets/index-changes-test-D8RtgfyG.js +367 -0
- package/bundled-test-harness/assets/index-query-engine-test-BOvxkx07.js +2593 -0
- package/bundled-test-harness/assets/index-writer-test-B_bR2fjw.js +3040 -0
- package/bundled-test-harness/assets/inspector-test-BwPXJj1S.js +2058 -0
- package/bundled-test-harness/assets/instance-filter-matcher-test-COAlkUed.js +788 -0
- package/bundled-test-harness/assets/instantiate-card-test-BVQhZjpq.js +164 -0
- package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DzQLG41H.js +475 -0
- package/bundled-test-harness/assets/interact-submode-setup-C5bKXq73.js +566 -0
- package/bundled-test-harness/assets/invalidate-realm-identifiers-test-Cd3dpjhB.js +99 -0
- package/bundled-test-harness/assets/invite-user-to-room-test-Brabz1tt.js +142 -0
- package/bundled-test-harness/assets/invoke-card-operation-test-C1Q1FUf4.js +333 -0
- package/bundled-test-harness/assets/isolated-render-test-BLJfS7BU.js +51 -0
- package/bundled-test-harness/assets/job-scoped-doc-cache-test-Bgv5woaB.js +181 -0
- package/bundled-test-harness/assets/job-scoped-instance-residency-test-C_bB6KpR.js +103 -0
- package/bundled-test-harness/assets/jpg-image-def-test-gdLIKocD.js +697 -0
- package/bundled-test-harness/assets/json-file-def-test-CPYMRBY-.js +95 -0
- package/bundled-test-harness/assets/key-notices-badge-test-DemslfLw.js +155 -0
- package/bundled-test-harness/assets/key-readiness-test-5tq5JycL.js +190 -0
- package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-BbhDZ2PH.js +398 -0
- package/bundled-test-harness/assets/linksto-error-sentinel-test-C2t7fFPi.js +238 -0
- package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test--U_UvUty.js +354 -0
- package/bundled-test-harness/assets/linksto-many-per-slot-access-test-Dj3Xy0ZF.js +303 -0
- package/bundled-test-harness/assets/linksto-sentinel-reload-test-D0dK4Jjs.js +197 -0
- package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test---IYiXok.js +260 -0
- package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-CT04MhES.js +196 -0
- package/bundled-test-harness/assets/lint-and-fix-test-aadgx7rX.js +51 -0
- package/bundled-test-harness/assets/live-test-BGij_vuc.js +100 -0
- package/bundled-test-harness/assets/live-test-CppvValf.js +2 -0
- package/bundled-test-harness/assets/load-default-skills-test-Cp2m_ebp.js +74 -0
- package/bundled-test-harness/assets/loader-parallel-prefetch-test-vU_26Jqu.js +257 -0
- package/bundled-test-harness/assets/loader-test-CTaw8K_B.js +482 -0
- package/bundled-test-harness/assets/loading-test-DGGt4qZZ.js +63 -0
- package/bundled-test-harness/assets/m4a-audio-def-test-DAiReOXH.js +190 -0
- package/bundled-test-harness/assets/main-DUKPWRts.js +5 -0
- package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-CIXq9FqR.js +470 -0
- package/bundled-test-harness/assets/markdown-embed-chooser-test-zFGh9WfP.js +334 -0
- package/bundled-test-harness/assets/markdown-embed-preview-pane-test-Byn_WFwY.js +447 -0
- package/bundled-test-harness/assets/markdown-embed-preview-test-Y3iFMttg.js +368 -0
- package/bundled-test-harness/assets/markdown-fallback-test-Br1TPkLZ.js +316 -0
- package/bundled-test-harness/assets/markdown-file-def-test-Crm2MAnq.js +380 -0
- package/bundled-test-harness/assets/markdown-helpers-test-CZ9Vvywc.js +188 -0
- package/bundled-test-harness/assets/markdown-highlighting-test-CFMkoVDl.js +244 -0
- package/bundled-test-harness/assets/markdown-preview-Df5fp1SY.js +72 -0
- package/bundled-test-harness/assets/markdown-preview-test-DDaPzsVs.js +238 -0
- package/bundled-test-harness/assets/markdown-skill-frontmatter-test-aH6HQly1.js +146 -0
- package/bundled-test-harness/assets/markdown-skill-search-test-CiNLQs-5.js +80 -0
- package/bundled-test-harness/assets/matrix-service-account-switch-sessions-test-DaA8w1Jj.js +63 -0
- package/bundled-test-harness/assets/matrix-service-boot-assembly-test-21GIlf55.js +300 -0
- package/bundled-test-harness/assets/matrix-service-personal-realm-test-jn9DUENm.js +125 -0
- package/bundled-test-harness/assets/matrix-service-realm-servers-test-eNZVJakl.js +55 -0
- package/bundled-test-harness/assets/matrix-service-realms-list-updated-test-Cabm8_dY.js +132 -0
- package/bundled-test-harness/assets/matrix-service-relogin-test-C77EFgjc.js +59 -0
- package/bundled-test-harness/assets/matrix-service-sliding-sync-test-BgM0fPiO.js +35 -0
- package/bundled-test-harness/assets/menu-Cl50TSFe.js +3561 -0
- package/bundled-test-harness/assets/message-service-subscription-test-CfEqH2jP.js +110 -0
- package/bundled-test-harness/assets/message-service-test-DsTzH1In.js +144 -0
- package/bundled-test-harness/assets/message-tool-test-C5xVfTtj.js +33 -0
- package/bundled-test-harness/assets/midi-audio-def-test-goLRCNCZ.js +182 -0
- package/bundled-test-harness/assets/migrate-skill-test-yPCbVfxG.js +161 -0
- package/bundled-test-harness/assets/mini-YXjrY_tH.js +1404 -0
- package/bundled-test-harness/assets/mini-card-chooser-test-DrllikHB.js +272 -0
- package/bundled-test-harness/assets/mini-file-chooser-test-BfqayhmI.js +201 -0
- package/bundled-test-harness/assets/mock-matrix-C7BrPS6S.js +2 -0
- package/bundled-test-harness/assets/mock-matrix-FjsXmU7-.js +15107 -0
- package/bundled-test-harness/assets/modal-BgaZavcs.js +322 -0
- package/bundled-test-harness/assets/model-cost-tier-test-CZlu1zww.js +174 -0
- package/bundled-test-harness/assets/model-file-extract-test-CjEBupY5.js +206 -0
- package/bundled-test-harness/assets/module-transpile-cache-test-XW6DDsmz.js +67 -0
- package/bundled-test-harness/assets/monaco-test-DkoRuFiQ.js +100 -0
- package/bundled-test-harness/assets/mp3-audio-def-test-v369NNsQ.js +133 -0
- package/bundled-test-harness/assets/multiple-stacks-test-CJpYPWdM.js +208 -0
- package/bundled-test-harness/assets/nested-query-field-render-test-CfDrBcUN.js +249 -0
- package/bundled-test-harness/assets/no-stacks-test-MmsJeLpz.js +48 -0
- package/bundled-test-harness/assets/number-field-test-A7B2r0M5.js +184 -0
- package/bundled-test-harness/assets/office-file-def-test-BNRvFmCB.js +263 -0
- package/bundled-test-harness/assets/office-metadata-extractor-test-zlDoEIEp.js +218 -0
- package/bundled-test-harness/assets/office-poster-capture-test-DdFEaOxR.js +203 -0
- package/bundled-test-harness/assets/ogg-audio-def-test-kk91BzQY.js +196 -0
- package/bundled-test-harness/assets/open-create-listing-modal-test-D1Dl1pov.js +131 -0
- package/bundled-test-harness/assets/open-image-in-new-tab-test-DyCmdMyO.js +52 -0
- package/bundled-test-harness/assets/open-secure-window-test-dz1vPudF.js +253 -0
- package/bundled-test-harness/assets/open-workspace-test-BvTcskzP.js +46 -0
- package/bundled-test-harness/assets/operation-lowering-test-CKkamOQt.js +2957 -0
- package/bundled-test-harness/assets/operations-invocation-test-BMj42rQe.js +523 -0
- package/bundled-test-harness/assets/operations-optimistic-test-KJLyzT8v.js +203 -0
- package/bundled-test-harness/assets/operations-query-test-J3HcnaoK.js +459 -0
- package/bundled-test-harness/assets/operations-store-reconciliation-test-CkbGBMBQ.js +406 -0
- package/bundled-test-harness/assets/operations-test-C7zXXpRW.js +2518 -0
- package/bundled-test-harness/assets/operator-mode-acceptance-test-BPolI_RD.js +1195 -0
- package/bundled-test-harness/assets/operator-mode-card-chooser-test-CQ1v8med.js +1036 -0
- package/bundled-test-harness/assets/operator-mode-links-test-BMHEauS3.js +797 -0
- package/bundled-test-harness/assets/operator-mode-test-blL_JVF8.js +696 -0
- package/bundled-test-harness/assets/operator-mode-ui-test-BG6I7-Hc.js +1045 -0
- package/bundled-test-harness/assets/overlay-D2rQi8lJ.js +427 -0
- package/bundled-test-harness/assets/overlay-menu-items-test-D-zmRQQ0.js +331 -0
- package/bundled-test-harness/assets/overlays-COinwHCP.js +2 -0
- package/bundled-test-harness/assets/overlays-detached-element-test-C73nMXes.js +56 -0
- package/bundled-test-harness/assets/overlays-nTqcu69K.js +75 -0
- package/bundled-test-harness/assets/panel-D9SEMehG.js +15124 -0
- package/bundled-test-harness/assets/past-sessions-test-De9N4wVX.js +321 -0
- package/bundled-test-harness/assets/patch-fields-test-Bp2IE0Jw.js +1014 -0
- package/bundled-test-harness/assets/patch-instance-test-DssuRGKP.js +348 -0
- package/bundled-test-harness/assets/pdf-file-def-test-Barj9ffD.js +111 -0
- package/bundled-test-harness/assets/pdf-metadata-extractor-test-B7KnXcIm.js +130 -0
- package/bundled-test-harness/assets/permission-checking-realm-test-OBzvhDB_.js +306 -0
- package/bundled-test-harness/assets/persist-module-inspector-view-test-BIdbkdPr.js +60 -0
- package/bundled-test-harness/assets/persist-scroll-position-test-Bhb7wJiy.js +254 -0
- package/bundled-test-harness/assets/phone-number-field-test-C2yuCrXY.js +73 -0
- package/bundled-test-harness/assets/pill-menu-test-BIp91YXi.js +60 -0
- package/bundled-test-harness/assets/plate-DAr_pvwC.js +41 -0
- package/bundled-test-harness/assets/plate-DeoQd99m.js +2 -0
- package/bundled-test-harness/assets/player-BvXGBItd.js +2 -0
- package/bundled-test-harness/assets/player-CAVQUyKk.js +82 -0
- package/bundled-test-harness/assets/playground-B02e8uqB.js +58 -0
- package/bundled-test-harness/assets/plural-field-components-test-C1acuN-A.js +198 -0
- package/bundled-test-harness/assets/png-image-def-test-B9QeVo1f.js +266 -0
- package/bundled-test-harness/assets/policy-audit-confirmation-test-CeVquvc_.js +155 -0
- package/bundled-test-harness/assets/policy-scoped-search-test-SFPiIqR3.js +339 -0
- package/bundled-test-harness/assets/prerender-file-extract-test-HSJKAHyO.js +346 -0
- package/bundled-test-harness/assets/prerender-html-test-BTAcFCme.js +670 -0
- package/bundled-test-harness/assets/prerender-meta-test-Csyz2b21.js +614 -0
- package/bundled-test-harness/assets/prerender-module-test-DpTYAbmI.js +409 -0
- package/bundled-test-harness/assets/prerender-persistence-block-test-BhIt-7kK.js +124 -0
- package/bundled-test-harness/assets/prerender-pre-model-error-test-DxKPQKqx.js +61 -0
- package/bundled-test-harness/assets/prerender-serialize-cycle-test-C8V5YWQO.js +134 -0
- package/bundled-test-harness/assets/prerendered-html-read-test-Cq7JVGwg.js +191 -0
- package/bundled-test-harness/assets/pretui-components-test-Ducr9fLT.css +743 -0
- package/bundled-test-harness/assets/pretui-components-test-Hs0uyIUQ.js +992 -0
- package/bundled-test-harness/assets/pretui-primitives-CRs8NRm0.js +69 -0
- package/bundled-test-harness/assets/preview-format-test-cCqLrfdY.js +103 -0
- package/bundled-test-harness/assets/preview-test-BMqJSoR1.js +474 -0
- package/bundled-test-harness/assets/process-card-test-578tfDvr.js +94 -0
- package/bundled-test-harness/assets/profile-settings-modal-CVnNl7Yu.js +990 -0
- package/bundled-test-harness/assets/publish-realm-COoeWexp.js +82 -0
- package/bundled-test-harness/assets/publish-realm-test-a5nkx0Ov.js +210 -0
- package/bundled-test-harness/assets/query-field-barrier-test-qX3xVPfk.js +113 -0
- package/bundled-test-harness/assets/query-field-error-sentinel-test-V6JDPFLX.js +201 -0
- package/bundled-test-harness/assets/query-field-membership-status-test-CK7eDf-K.js +323 -0
- package/bundled-test-harness/assets/query-field-page-optin-test-B5YBHUvU.js +126 -0
- package/bundled-test-harness/assets/query-field-schema-test-D4SjOGlK.js +231 -0
- package/bundled-test-harness/assets/query-field-search-throttle-test-BVkm1-D8.js +154 -0
- package/bundled-test-harness/assets/query-field-stale-prerender-test-9g7hcD91.js +152 -0
- package/bundled-test-harness/assets/query-fields-test-CQYqhzpN.js +535 -0
- package/bundled-test-harness/assets/quick-look-test-icQwb1NJ.js +139 -0
- package/bundled-test-harness/assets/read-card-for-ai-assistant-test-D0mJorwH.js +91 -0
- package/bundled-test-harness/assets/read-file-for-ai-assistant-test-B_F_2GEB.js +45 -0
- package/bundled-test-harness/assets/read-source-test-BgJV4B4F.js +67 -0
- package/bundled-test-harness/assets/read-text-file-test-DaeLzg4u.js +124 -0
- package/bundled-test-harness/assets/realm-C_a9su1j.js +2858 -0
- package/bundled-test-harness/assets/realm-api-keys-D5USFOoS.js +2 -0
- package/bundled-test-harness/assets/realm-api-keys-m_VOcixC.js +578 -0
- package/bundled-test-harness/assets/realm-api-keys-test-C_uZnTmq.js +588 -0
- package/bundled-test-harness/assets/realm-api-keys-test-gtJ8XZCE.js +109 -0
- package/bundled-test-harness/assets/realm-config-m5eccPW8.js +833 -0
- package/bundled-test-harness/assets/realm-config-policy-standing-test-CXJ4ZMde.js +290 -0
- package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-DoEunShH.js +274 -0
- package/bundled-test-harness/assets/realm-config-settings-test-BYi9i4O6.js +187 -0
- package/bundled-test-harness/assets/realm-field-test-B_PUoqnk.js +100 -0
- package/bundled-test-harness/assets/realm-indexing-test-8iLjeV_e.js +4380 -0
- package/bundled-test-harness/assets/realm-policy-fitted-test-Bptvra0U.js +206 -0
- package/bundled-test-harness/assets/realm-policy-test-DwG0qqXE.js +1141 -0
- package/bundled-test-harness/assets/realm-querying-test-Dvw26A6Q.js +1067 -0
- package/bundled-test-harness/assets/realm-server-form-agnostic-test-DrXQH0UP.js +96 -0
- package/bundled-test-harness/assets/realm-server-subscriber-test-Dkj23vQK.js +46 -0
- package/bundled-test-harness/assets/realm-service-info-test-CdRlDhj-.js +67 -0
- package/bundled-test-harness/assets/realm-test-DGYN48Qx.js +2364 -0
- package/bundled-test-harness/assets/realm-token-refresh-test-CEWATL9h.js +153 -0
- package/bundled-test-harness/assets/realm-url-tooltip-test-8ZjTNPuy.js +78 -0
- package/bundled-test-harness/assets/reasoning-test-WUx-4agu.js +221 -0
- package/bundled-test-harness/assets/recent-files-test-Dc6L6Dm4.js +450 -0
- package/bundled-test-harness/assets/reindex-realm-test-CFRSt39u.js +117 -0
- package/bundled-test-harness/assets/relationship-loading-state-test-FKbtOFUr.js +290 -0
- package/bundled-test-harness/assets/remix-card-test-CKGC_Sgq.js +58 -0
- package/bundled-test-harness/assets/rendered-markdown-B_jWmDrK.js +292 -0
- package/bundled-test-harness/assets/rendered-markdown-test-sdWhU0NA.js +587 -0
- package/bundled-test-harness/assets/resident-instance-reuse-test-BjdhE6CM.js +82 -0
- package/bundled-test-harness/assets/result-tile-o6dtjgX4.js +144 -0
- package/bundled-test-harness/assets/rich-markdown-field-test-VXr6l20h.js +1647 -0
- package/bundled-test-harness/assets/room-message-test-BYNhZ39n.js +484 -0
- package/bundled-test-harness/assets/run-FzaqmBEl.js +3959 -0
- package/bundled-test-harness/assets/run-realm-code-DsBUf1si.js +2964 -0
- package/bundled-test-harness/assets/run-realm-code-test-cS0DzaKo.js +3844 -0
- package/bundled-test-harness/assets/sanitize-module-list-test-CvuOOiUY.js +85 -0
- package/bundled-test-harness/assets/save-card-skip-index-wait-test-fpJ1eq32.js +89 -0
- package/bundled-test-harness/assets/schema-editor-test-NkKjCgyf.js +785 -0
- package/bundled-test-harness/assets/schema-generation-test-Dmg3lWl7.js +28 -0
- package/bundled-test-harness/assets/scrolling-test-Dd4gv_fj.js +412 -0
- package/bundled-test-harness/assets/search-adorn-test-CZebk7_y.js +136 -0
- package/bundled-test-harness/assets/search-and-choose-test-Bd4NZUup.js +154 -0
- package/bundled-test-harness/assets/search-correlation-id-test-DXKlEO55.js +139 -0
- package/bundled-test-harness/assets/search-entries-result-test-QQawA8Fm.js +234 -0
- package/bundled-test-harness/assets/search-entries-test-3DlqGPQq.js +1486 -0
- package/bundled-test-harness/assets/search-entries-tool-test-D1TvDE9D.js +504 -0
- package/bundled-test-harness/assets/search-google-images-test-DqsoQGr1.js +166 -0
- package/bundled-test-harness/assets/search-results-DGrNaPxh.js +266 -0
- package/bundled-test-harness/assets/search-results-test-CqVHYNRt.js +578 -0
- package/bundled-test-harness/assets/search-selection-menu-test-D6bIjKiH.js +108 -0
- package/bundled-test-harness/assets/search-sheet-files-test-Bf37TQXo.js +126 -0
- package/bundled-test-harness/assets/search-sheet-persistence-test-CV4_XdxR.js +131 -0
- package/bundled-test-harness/assets/search-test-Dlb-wg3a.js +2249 -0
- package/bundled-test-harness/assets/search-tool-test-BJLgVMoL.js +156 -0
- package/bundled-test-harness/assets/searchable-option-test-eJaIPH_L.js +322 -0
- package/bundled-test-harness/assets/searchable-search-doc-test-yH9fLGNS.js +1271 -0
- package/bundled-test-harness/assets/section-rail-CNFCebtT.js +113 -0
- package/bundled-test-harness/assets/section-rail-test-KNJAWWl6.js +256 -0
- package/bundled-test-harness/assets/secure-sign-in-Dyljp0Th.js +174 -0
- package/bundled-test-harness/assets/secure-sign-in-test-QnqNuTP3.js +373 -0
- package/bundled-test-harness/assets/segmented-control-DxJdoJ4Z.js +173 -0
- package/bundled-test-harness/assets/select-BiQTg2ts.js +175 -0
- package/bundled-test-harness/assets/send-ai-assistant-message-test-CAn7M2dZ.js +52 -0
- package/bundled-test-harness/assets/send-bot-trigger-event-test-qBu5E_jy.js +56 -0
- package/bundled-test-harness/assets/send-request-via-proxy-test-CLuwLBq_.js +380 -0
- package/bundled-test-harness/assets/sending-test-Dt9Dh2wW.js +659 -0
- package/bundled-test-harness/assets/serialization-rri-form-audit-test-hMJukiKt.js +136 -0
- package/bundled-test-harness/assets/serialization-test-W5e3wKbz.js +8758 -0
- package/bundled-test-harness/assets/set-user-system-card-test-CjgWLkNV.js +59 -0
- package/bundled-test-harness/assets/setup-CssMNvui.js +772 -0
- package/bundled-test-harness/assets/setup-D8YXvK-p.js +2 -0
- package/bundled-test-harness/assets/shared-link-target-reuse-test-D42UO8DC.js +207 -0
- package/bundled-test-harness/assets/show-card-test-CHEaS514.js +365 -0
- package/bundled-test-harness/assets/signed-capture-link-test-BgEu0F-S.js +132 -0
- package/bundled-test-harness/assets/single-stack-test-DYcu_v7Z.js +652 -0
- package/bundled-test-harness/assets/skills-test-BP8QNesE.js +648 -0
- package/bundled-test-harness/assets/skip-boot-index-guard-test-BzRIncDN.js +46 -0
- package/bundled-test-harness/assets/spec-test-BYvFR6Xb.js +1077 -0
- package/bundled-test-harness/assets/spinner-Bx9x55NA.js +49 -0
- package/bundled-test-harness/assets/src-LqENIikj.js +5 -0
- package/bundled-test-harness/assets/src-a4d10Hra.js +216 -0
- package/bundled-test-harness/assets/stick-to-bottom-resize-test-BBLiCR3X.js +56 -0
- package/bundled-test-harness/assets/store-add-test-D_9IHQjZ.js +50 -0
- package/bundled-test-harness/assets/store-module-rebuild-test-BRGZoLRV.js +454 -0
- package/bundled-test-harness/assets/store-search-test-3G8JHuj2.js +175 -0
- package/bundled-test-harness/assets/store-test-Dd4WQp7L.js +3672 -0
- package/bundled-test-harness/assets/structured-theme-test-11TNsgUW.js +377 -0
- package/bundled-test-harness/assets/summarize-session-test-CwzD_ZbD.js +172 -0
- package/bundled-test-harness/assets/svg-image-def-test-zV6aMK9q.js +167 -0
- package/bundled-test-harness/assets/switch-submode-test-DQU2cP5_.js +168 -0
- package/bundled-test-harness/assets/sync-openrouter-models-test-xrXVaC2H.js +97 -0
- package/bundled-test-harness/assets/test-support-QTh6wGxu.js +3 -0
- package/bundled-test-harness/assets/test-support-Tr-PYFgc.js +99 -0
- package/bundled-test-harness/assets/tests-zLlwPutr.js +3598 -0
- package/bundled-test-harness/assets/text-file-def-test-Cyq78UFY.js +94 -0
- package/bundled-test-harness/assets/text-input-validator-test-C1uDVZU7.js +156 -0
- package/bundled-test-harness/assets/text-suggestion-test-C4XAqWqY.js +340 -0
- package/bundled-test-harness/assets/theme-card-test-dVNz4tgU.js +621 -0
- package/bundled-test-harness/assets/theme-dashboard-nav-test-DYSn5pqo.js +196 -0
- package/bundled-test-harness/assets/theme-scheme-island-test-C1WpkfEP.js +264 -0
- package/bundled-test-harness/assets/theme-scoped-css-parity-test-BVluppsE.js +176 -0
- package/bundled-test-harness/assets/titles-0a1luoTq.js +52 -0
- package/bundled-test-harness/assets/titles-DKHNLVwC.js +2 -0
- package/bundled-test-harness/assets/to-device-streaming-test-3A6jI0_r.js +163 -0
- package/bundled-test-harness/assets/token-usage-test-33ovcqPk.js +160 -0
- package/bundled-test-harness/assets/tools-J_Knr_W6.js +774 -0
- package/bundled-test-harness/assets/tools-calling-test-CfqZX0Ed.js +200 -0
- package/bundled-test-harness/assets/tools-test-B4x58ZmI.js +1624 -0
- package/bundled-test-harness/assets/tools-test-DtUQp5ez.js +3204 -0
- package/bundled-test-harness/assets/tooltip-B0rEgyMW.css +66 -0
- package/bundled-test-harness/assets/tooltip-DvUMUgVX.js +195 -0
- package/bundled-test-harness/assets/transform-cards-test-CYQbZeD9.js +341 -0
- package/bundled-test-harness/assets/ts-file-def-preview-test-m39f8Zio.js +95 -0
- package/bundled-test-harness/assets/ts-file-def-test-xIcL5xWe.js +92 -0
- package/bundled-test-harness/assets/ttf-font-def-test-ClQ2SzFF.js +206 -0
- package/bundled-test-harness/assets/turn-settling-test-DqYk312r.js +160 -0
- package/bundled-test-harness/assets/turn-summary-Bmt7ZxTS.js +1039 -0
- package/bundled-test-harness/assets/unpublish-realm-test-0ToTJczx.js +102 -0
- package/bundled-test-harness/assets/update-room-skills-test-o_j8NOUV.js +240 -0
- package/bundled-test-harness/assets/use-ai-assistant-test-D7HFpxKJ.js +384 -0
- package/bundled-test-harness/assets/user-message-BAOt1hS3.js +262 -0
- package/bundled-test-harness/assets/validate-realm-test-e3xIbNLB.js +67 -0
- package/bundled-test-harness/assets/video-metadata-extractor-test-D8naLSlg.js +520 -0
- package/bundled-test-harness/assets/view-visually-test-BuhGau5E.js +335 -0
- package/bundled-test-harness/assets/virtual-network-reset-test-CgaFNGPi.js +96 -0
- package/bundled-test-harness/assets/wav-audio-def-test-CWG_UdCh.js +160 -0
- package/bundled-test-harness/assets/webp-image-def-test-sN4yw8Zu.js +226 -0
- package/bundled-test-harness/assets/workspace-0LfPqbYB.js +445 -0
- package/bundled-test-harness/assets/workspace-a11y-test-DQxYDRAP.js +197 -0
- package/bundled-test-harness/assets/workspace-actions-jGJSfl8M.js +588 -0
- package/bundled-test-harness/assets/workspace-behavior-test-BnF-bmBN.js +338 -0
- package/bundled-test-harness/assets/workspace-delete-multiple-test-D-rxPDuT.js +212 -0
- package/bundled-test-harness/assets/workspace-delete-summary-test-C2-Mve5R.js +63 -0
- package/bundled-test-harness/assets/workspace-hosting-test-BvDKdlOb.js +138 -0
- package/bundled-test-harness/assets/workspace-indexing-test-B34T3kqD.js +71 -0
- package/bundled-test-harness/assets/workspace-test-CJivgv-m.js +51 -0
- package/bundled-test-harness/assets/workspace-test-CuSRpPnQ.js +385 -0
- package/bundled-test-harness/assets/workspace-timestamp-labels-test-aWgjdbCp.js +68 -0
- package/bundled-test-harness/assets/workspace-unit-test-DHMUf2KT.js +122 -0
- package/bundled-test-harness/assets/write-binary-file-test-P-hVQuin.js +124 -0
- package/bundled-test-harness/assets/write-text-file-test-fXvJueDd.js +191 -0
- package/bundled-test-harness/assets/zip-archive-test-C2P5CUSR.js +285 -0
- package/bundled-test-harness/assets/zip-file-def-test-BfJZAmGt.js +164 -0
- package/bundled-test-harness/boxel-ui-checksum.txt +1 -1
- package/bundled-test-harness/index.html +47 -47
- package/bundled-test-harness/tests/index.html +49 -49
- package/bundled-types/boxel-ui/helpers/theme-scoped-css.ts +4 -0
- package/bundled-types/choreo/choreo.gts +13 -1
- package/bundled-types/choreo/run.ts +19 -0
- package/bundled-types/host-app/components/operator-mode/dashboard/get-started.gts +152 -7
- package/bundled-types/host-app/components/operator-mode/dashboard/index.gts +2 -0
- package/bundled-types/host-app/components/operator-mode/dashboard/workspace.gts +5 -3
- package/bundled-types/host-app/components/operator-mode/dashboard-modals/workspace-modals.gts +5 -22
- package/bundled-types/host-app/components/operator-mode/host-submode/publishing-realm-popover.gts +1 -1
- package/bundled-types/host-app/components/operator-mode/host-submode.gts +111 -37
- package/bundled-types/host-app/components/operator-mode/publish-realm-modal.gts +1 -0
- package/bundled-types/host-app/lib/modal-focus-trap.ts +33 -0
- package/bundled-types/host-app/lib/workspace-actions.ts +21 -0
- package/bundled-types/host-app/services/host-mode-service.ts +39 -0
- package/bundled-types/host-app/services/realm.ts +14 -0
- package/bundled-types/host-tests/helpers/dashboard.ts +67 -0
- package/package.json +1 -1
- package/bundled-test-harness/assets/account-switch-failed-test-FytUFiPO.js +0 -45
- package/bundled-test-harness/assets/adapter-DvmPwSZv.js +0 -2
- package/bundled-test-harness/assets/add-field-to-card-definition-tool-test-DN525jiY.js +0 -112
- package/bundled-test-harness/assets/ai-assistant-create-workspace-test-q3tKqVJQ.js +0 -130
- package/bundled-test-harness/assets/ai-assistant-panel-relogin-test-DgeXcCyi.js +0 -46
- package/bundled-test-harness/assets/ai-assistant-test-lDIGPKFP.js +0 -2223
- package/bundled-test-harness/assets/ai-function-generation-test-D5GbLyvL.js +0 -1176
- package/bundled-test-harness/assets/ai-module-creation-test-I3-j2beD.js +0 -151
- package/bundled-test-harness/assets/aibot-message-Dmsjifs6.js +0 -1312
- package/bundled-test-harness/assets/app-BS9_-DhN.js +0 -14146
- package/bundled-test-harness/assets/apply-markdown-edit-test-4zlwt0Db.js +0 -230
- package/bundled-test-harness/assets/ask-user-picker-Dr-0qpNr.js +0 -370
- package/bundled-test-harness/assets/ask-user-picker-test-633AFdmS.js +0 -39
- package/bundled-test-harness/assets/assistant-transcript-test-BgRnLvMg.js +0 -57
- package/bundled-test-harness/assets/audio-metadata-extractor-test-4xsQqL-0.js +0 -1176
- package/bundled-test-harness/assets/authed-fetch-test-663mT5_N.js +0 -73
- package/bundled-test-harness/assets/avif-image-def-test-h01BPIJy.js +0 -187
- package/bundled-test-harness/assets/basic-test-DiD6T-8Q.js +0 -139
- package/bundled-test-harness/assets/binary-upload-dedupe-test-CkjMPO_e.js +0 -308
- package/bundled-test-harness/assets/bot-registration-test-CFZHpwdj.js +0 -97
- package/bundled-test-harness/assets/box-test-C3pSy5ED.js +0 -50
- package/bundled-test-harness/assets/brand-guide-attachments-test-EoC_u7Vc.js +0 -84
- package/bundled-test-harness/assets/brand-guide-custom-css-test-Dn3fvblr.js +0 -196
- package/bundled-test-harness/assets/brand-guide-edit-test-NeiT3MyK.js +0 -140
- package/bundled-test-harness/assets/brand-logo-mark-field-test-C2A1EnBB.js +0 -86
- package/bundled-test-harness/assets/broken-link-template-test-CWn6V5zZ.js +0 -192
- package/bundled-test-harness/assets/bundled-base-modules-test-D7mLzpsw.js +0 -54
- package/bundled-test-harness/assets/bundled-base-oracle-test-I7xCId_k.js +0 -37
- package/bundled-test-harness/assets/buried-stack-item-scroll-test-DFBev0h-.js +0 -236
- package/bundled-test-harness/assets/button-BeSuhveJ.js +0 -207
- package/bundled-test-harness/assets/bxl-cyclic-graph-test-DPykwvvx.js +0 -47
- package/bundled-test-harness/assets/bxl-expression-test-LBWJiFb9.js +0 -250
- package/bundled-test-harness/assets/bxl-indexing-test-BuZmLk7y.js +0 -212
- package/bundled-test-harness/assets/bxl-platform-module-test-BNIvlkCM.js +0 -71
- package/bundled-test-harness/assets/can-invoke-test-t-bFIIeX.js +0 -455
- package/bundled-test-harness/assets/can-read-realm-test-2Q_MzRT9.js +0 -56
- package/bundled-test-harness/assets/cancel-indexing-job-test-QeYxEukn.js +0 -69
- package/bundled-test-harness/assets/capture-test-CJmJG8YR.js +0 -360
- package/bundled-test-harness/assets/card-api-test-B43I510H.js +0 -198
- package/bundled-test-harness/assets/card-basics-test-CBClzP2y.js +0 -5364
- package/bundled-test-harness/assets/card-chooser-paging-test-HEVzf6pR.js +0 -235
- package/bundled-test-harness/assets/card-chooser-test-GfjBRPFI.js +0 -393
- package/bundled-test-harness/assets/card-context-search-results-CoSr4EdS.js +0 -30
- package/bundled-test-harness/assets/card-context-search-results-test-BLMlZu9t.js +0 -184
- package/bundled-test-harness/assets/card-def-field-def-relationships-test-DEBOzKan.js +0 -562
- package/bundled-test-harness/assets/card-def-menu-items-test-88_h8o0D.js +0 -228
- package/bundled-test-harness/assets/card-delete-test-DKom1phy.js +0 -466
- package/bundled-test-harness/assets/card-error-awaiting-index-test-DEwgFZMP.js +0 -53
- package/bundled-test-harness/assets/card-error-r6_cXst9.js +0 -72
- package/bundled-test-harness/assets/card-info-thumbnail-picker-test-B7LiY15e.js +0 -219
- package/bundled-test-harness/assets/card-playground-test-CgyIJHui.js +0 -1491
- package/bundled-test-harness/assets/card-prerender-rPfzpIOU.js +0 -12939
- package/bundled-test-harness/assets/card-thunk-error-test-L0pvg4Ce.js +0 -48
- package/bundled-test-harness/assets/card-type-service-test-B2dhqxSD.js +0 -161
- package/bundled-test-harness/assets/check-correctness-test-DgqaLlCW.js +0 -1093
- package/bundled-test-harness/assets/check-domain-availability-test-B0hJHY5l.js +0 -98
- package/bundled-test-harness/assets/chip-D01NW3WH.js +0 -44
- package/bundled-test-harness/assets/choreo-D2Jl79RU.js +0 -1019
- package/bundled-test-harness/assets/choreo-_E8SOEe-.js +0 -2
- package/bundled-test-harness/assets/choreo-feature-reel-test-WLjsZDmS.js +0 -155
- package/bundled-test-harness/assets/choreo-gallery-build-order-test-6jnS8PsS.js +0 -436
- package/bundled-test-harness/assets/choreo-gallery-compositor-test-CbUZsVB6.js +0 -399
- package/bundled-test-harness/assets/choreo-gallery-cover-test-CbvAStgk.js +0 -214
- package/bundled-test-harness/assets/choreo-gallery-crossing-stage-test-tdjvUSa6.js +0 -133
- package/bundled-test-harness/assets/choreo-gallery-demos-alive-test-CsnM3hQK.js +0 -42
- package/bundled-test-harness/assets/choreo-gallery-drift-test-DG2LQTa7.js +0 -620
- package/bundled-test-harness/assets/choreo-gallery-escort-test-mn3-qXP1.js +0 -187
- package/bundled-test-harness/assets/choreo-gallery-films-test-BuktaC0D.js +0 -140
- package/bundled-test-harness/assets/choreo-gallery-filter-test-Dd-zpps0.js +0 -46
- package/bundled-test-harness/assets/choreo-gallery-fold-test-CWc1ijGc.js +0 -180
- package/bundled-test-harness/assets/choreo-gallery-guide-pages-test-tk2QmYPU.js +0 -114
- package/bundled-test-harness/assets/choreo-gallery-guides-test-DVbf1zM4.js +0 -321
- package/bundled-test-harness/assets/choreo-gallery-hang-test-B7EFp2dx.js +0 -426
- package/bundled-test-harness/assets/choreo-gallery-highlight-test-BFgbdesP.js +0 -60
- package/bundled-test-harness/assets/choreo-gallery-inline-edit-test-DJb8FC5R.js +0 -370
- package/bundled-test-harness/assets/choreo-gallery-interruption-test-DWyMXo5D.js +0 -176
- package/bundled-test-harness/assets/choreo-gallery-lone-stack-test-D3b8LsJ6.js +0 -104
- package/bundled-test-harness/assets/choreo-gallery-navigation-test-CjjU6Rvn.js +0 -193
- package/bundled-test-harness/assets/choreo-gallery-playhead-transport-test-Le_h3QWU.js +0 -111
- package/bundled-test-harness/assets/choreo-gallery-poplayout-subtree-test-Cp-DlWj4.js +0 -127
- package/bundled-test-harness/assets/choreo-gallery-presence-modes-test-DayS4GCJ.js +0 -100
- package/bundled-test-harness/assets/choreo-gallery-presentation-test-DeAfuFS7.js +0 -157
- package/bundled-test-harness/assets/choreo-gallery-reduced-motion-test-BgPWpggq.js +0 -145
- package/bundled-test-harness/assets/choreo-gallery-sheet-standalone-test-PzyoMNYv.js +0 -89
- package/bundled-test-harness/assets/choreo-gallery-sheet-test-CxaiNBkL.js +0 -48
- package/bundled-test-harness/assets/choreo-gallery-site-test-6xtSntS5.js +0 -237
- package/bundled-test-harness/assets/choreo-gallery-stage-E6Q5r-zU.js +0 -256
- package/bundled-test-harness/assets/choreo-gallery-stage-keyboard-test-C7aWMr9a.js +0 -102
- package/bundled-test-harness/assets/choreo-gallery-stages-test-CDWWgC61.js +0 -35
- package/bundled-test-harness/assets/choreo-gallery-subdivision-test-Bkp15XJv.js +0 -138
- package/bundled-test-harness/assets/choreo-gallery-table-plan-test-CcGRi_3O.js +0 -144
- package/bundled-test-harness/assets/choreo-gallery-theater-test-Qph5pLT_.js +0 -252
- package/bundled-test-harness/assets/choreo-gallery-tuning-test-C4DhFLVA.js +0 -95
- package/bundled-test-harness/assets/choreo-gallery-widget-room-test-LK493r1M.js +0 -88
- package/bundled-test-harness/assets/choreo-gallery-wires-test-B7SeUCc8.js +0 -148
- package/bundled-test-harness/assets/client-telemetry-test-DGmHzAFx.js +0 -340
- package/bundled-test-harness/assets/clip-BpYQPVz_.js +0 -2
- package/bundled-test-harness/assets/clip-CNaYbIwL.js +0 -92
- package/bundled-test-harness/assets/code-block-Cp2CJo5-.js +0 -502
- package/bundled-test-harness/assets/code-ref-test-C8JBHDb-.js +0 -163
- package/bundled-test-harness/assets/code-submode-availability-test-CzG1Tv6L.js +0 -198
- package/bundled-test-harness/assets/code-submode-test-BclVWjm5.js +0 -1839
- package/bundled-test-harness/assets/codeblocks-test-CmQlyxN7.js +0 -418
- package/bundled-test-harness/assets/codemirror-editor-test-B74H_yn8.js +0 -1512
- package/bundled-test-harness/assets/codemirror-embed-toolbar-test-Bz6VEysU.js +0 -366
- package/bundled-test-harness/assets/color-field-test-DMCPQKIP.js +0 -212
- package/bundled-test-harness/assets/compaction-test-saQCLBrQ.js +0 -150
- package/bundled-test-harness/assets/computed-test-C05HliJC.js +0 -1320
- package/bundled-test-harness/assets/container-Cqcwrd-m.js +0 -10857
- package/bundled-test-harness/assets/content-preview-components-test-DZPj4_CU.js +0 -462
- package/bundled-test-harness/assets/copy-and-edit-test-DiXTQNTF.js +0 -292
- package/bundled-test-harness/assets/copy-card-test-ys7GquUY.js +0 -218
- package/bundled-test-harness/assets/copy-file-to-realm-test-Gn0Wn4vT.js +0 -148
- package/bundled-test-harness/assets/copy-source-test-BTLrOmPm.js +0 -56
- package/bundled-test-harness/assets/create-file-test-BCeIW-Rt.js +0 -464
- package/bundled-test-harness/assets/create-file-test-DbHQ5JsS.js +0 -1086
- package/bundled-test-harness/assets/create-listing-modal-test-CeHc4ter.js +0 -273
- package/bundled-test-harness/assets/create-listing-pr-request-test-DXbJNfMh.js +0 -117
- package/bundled-test-harness/assets/create-spec-test-BDIZoyHT.js +0 -256
- package/bundled-test-harness/assets/create-submission-workflow-test-Bix5J-3A.js +0 -132
- package/bundled-test-harness/assets/create-workspace-test-BmNnLHwC.js +0 -104
- package/bundled-test-harness/assets/credential-fields-test-NK1F4QWn.js +0 -200
- package/bundled-test-harness/assets/csv-file-def-test-BSfs4TTP.js +0 -102
- package/bundled-test-harness/assets/dashboard-C4T7ffKY.js +0 -3576
- package/bundled-test-harness/assets/dashboard-CFeHuP5-.js +0 -81
- package/bundled-test-harness/assets/dashboard-DQlpW-ux.css +0 -2392
- package/bundled-test-harness/assets/dashboard-add-workspace-test--rr6objf.js +0 -50
- package/bundled-test-harness/assets/dashboard-agents-test-D1y8H4xH.js +0 -334
- package/bundled-test-harness/assets/dashboard-archive-test-bN4EQaXv.js +0 -128
- package/bundled-test-harness/assets/dashboard-delete-test-BvsASb8B.js +0 -163
- package/bundled-test-harness/assets/dashboard-duplicate-offer-test-DEsd5ZzZ.js +0 -71
- package/bundled-test-harness/assets/dashboard-duplicate-test-BnR0sTgB.js +0 -222
- package/bundled-test-harness/assets/dashboard-get-started-test-DG4uUXLv.js +0 -246
- package/bundled-test-harness/assets/dashboard-pinned-cards-test-AoGGVRAS.js +0 -220
- package/bundled-test-harness/assets/dashboard-reindex-test-BN9a96Xp.js +0 -115
- package/bundled-test-harness/assets/dashboard-section-rail-test-B3OT9V2T.js +0 -169
- package/bundled-test-harness/assets/dashboard-state-test-BY0Zqrmj.js +0 -162
- package/bundled-test-harness/assets/dashboard-test-C13oNpWt.js +0 -545
- package/bundled-test-harness/assets/dashboard-unreachable-notice-test-DZIV4x5j.js +0 -62
- package/bundled-test-harness/assets/dashboard-workspace-test-CBnOQViI.js +0 -537
- package/bundled-test-harness/assets/dashboard-workspaces-section-test-KU8ZVOYp.js +0 -396
- package/bundled-test-harness/assets/data-file-def-preview-test-CI5gcdtK.js +0 -155
- package/bundled-test-harness/assets/date-time-fields-test-D2CpR_Pb.js +0 -359
- package/bundled-test-harness/assets/debug-message-test-Df1kHesw.js +0 -117
- package/bundled-test-harness/assets/declared-captures-test-hQ43zuox.js +0 -879
- package/bundled-test-harness/assets/delete-workspace-test-BhfMKsix.js +0 -102
- package/bundled-test-harness/assets/diffing-test-CHRh55mC.js +0 -210
- package/bundled-test-harness/assets/download-file-to-realm-test-CC1HURCi.js +0 -119
- package/bundled-test-harness/assets/editor-test-DkeCv28f.js +0 -688
- package/bundled-test-harness/assets/edits-BSJqtUXM.js +0 -651
- package/bundled-test-harness/assets/email-field-test-DihK0suO.js +0 -75
- package/bundled-test-harness/assets/enum-field-test-Gja3bzt5.js +0 -935
- package/bundled-test-harness/assets/error-display-test-GhYZu7cp.js +0 -343
- package/bundled-test-harness/assets/evaluate-module-test-D_t4CiUq.js +0 -91
- package/bundled-test-harness/assets/execute-atomic-operations-test-xtou8Zeg.js +0 -113
- package/bundled-test-harness/assets/externals-B02-sD_L.js +0 -4393
- package/bundled-test-harness/assets/fallback-banner-live-delete-test-DtxzNXdE.js +0 -207
- package/bundled-test-harness/assets/fallback-banner-test-BfmiQ_68.js +0 -53
- package/bundled-test-harness/assets/fallback-banner-test-DLtTdmvn.js +0 -225
- package/bundled-test-harness/assets/fallback-models-test-BxNJxhfd.js +0 -161
- package/bundled-test-harness/assets/fetch-card-json-test-DofKbzvC.js +0 -61
- package/bundled-test-harness/assets/field-configuration-test-SUoPaXWy.js +0 -551
- package/bundled-test-harness/assets/field-markdown-domain-test-BwtR0dPP.js +0 -616
- package/bundled-test-harness/assets/field-markdown-oversize-test-D8UJcBc3.js +0 -88
- package/bundled-test-harness/assets/field-markdown-primitives-test-D5_ZdoDO.js +0 -365
- package/bundled-test-harness/assets/field-markdown-specialized-test-Dpd5hs04.js +0 -534
- package/bundled-test-harness/assets/field-playground-test-CzhYzKGv.js +0 -894
- package/bundled-test-harness/assets/field-support-predicates-test-BSvVOFth.js +0 -167
- package/bundled-test-harness/assets/file-attachment-test-fM-yFedm.js +0 -796
- package/bundled-test-harness/assets/file-chooser-panel-test-CKj8YTdY.js +0 -153
- package/bundled-test-harness/assets/file-chooser-test-Bs8jFXqa.js +0 -504
- package/bundled-test-harness/assets/file-def-format-templates-test-CxrRoWoD.js +0 -380
- package/bundled-test-harness/assets/file-def-live-reload-test-X_8YEkve.js +0 -124
- package/bundled-test-harness/assets/file-def-menu-items-test-Dx879o_o.js +0 -138
- package/bundled-test-harness/assets/file-def-navigation-test-MMI_EEO1.js +0 -109
- package/bundled-test-harness/assets/file-def-serialization-test-B5lguBQD.js +0 -89
- package/bundled-test-harness/assets/file-def-test-Di9QWcrj.js +0 -216
- package/bundled-test-harness/assets/file-preview-live-reload-test-aqx93A7c.js +0 -310
- package/bundled-test-harness/assets/file-resource-primitives-test-a5abpcSB.js +0 -255
- package/bundled-test-harness/assets/file-tree-from-index-test-CnruGxJ8.js +0 -96
- package/bundled-test-harness/assets/file-tree-test-BCyWDdSE.js +0 -851
- package/bundled-test-harness/assets/file-view-model-test-BfpLa01Y.js +0 -346
- package/bundled-test-harness/assets/filedef-export-shape-test-CQ9XbrzS.js +0 -61
- package/bundled-test-harness/assets/film-CL1zj_bJ.js +0 -2
- package/bundled-test-harness/assets/film-Dq_quZ31.js +0 -13
- package/bundled-test-harness/assets/film-xbkQa060.js +0 -4074
- package/bundled-test-harness/assets/flac-audio-def-test-BmVp9dMx.js +0 -143
- package/bundled-test-harness/assets/focus-Dm4wkM72.js +0 -306
- package/bundled-test-harness/assets/font-metadata-extractor-test-OWEh9_MS.js +0 -415
- package/bundled-test-harness/assets/formatted-aibot-message-test-BpHsWpuV.js +0 -109
- package/bundled-test-harness/assets/formatted-user-message-test-DZW5TAr0.js +0 -43
- package/bundled-test-harness/assets/freestyle-test-D_uaPU_3.js +0 -17
- package/bundled-test-harness/assets/full-reindex-realm-test-C6vHL5kC.js +0 -101
- package/bundled-test-harness/assets/garbage-collection-test-D-Ao4t2n.js +0 -403
- package/bundled-test-harness/assets/general-test-PSGI8W0z.js +0 -923
- package/bundled-test-harness/assets/generate-example-cards-one-shot-test-J-m-0E6W.js +0 -65
- package/bundled-test-harness/assets/generic-file-def-preview-test-BAsOhTYU.js +0 -71
- package/bundled-test-harness/assets/get-available-realm-identifiers-test-D5PBOr97.js +0 -47
- package/bundled-test-harness/assets/get-catalog-realm-identifiers-test-NM9UURHE.js +0 -47
- package/bundled-test-harness/assets/get-default-writable-realm-test-BxXc9a3J.js +0 -54
- package/bundled-test-harness/assets/get-published-realms-test-C8TJEc4-.js +0 -71
- package/bundled-test-harness/assets/get-realm-of-resource-identifier-test-Dt8CB6lS.js +0 -54
- package/bundled-test-harness/assets/get-relationship-membership-state-test-9_8x3myJ.js +0 -1308
- package/bundled-test-harness/assets/get-user-system-card-test-k0UO-uba.js +0 -67
- package/bundled-test-harness/assets/gif-image-def-test-BWrqPGDX.js +0 -188
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-BgG8QI9E.js +0 -160
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-BKOvNyCN.js +0 -74
- package/bundled-test-harness/assets/gts-file-def-test-BCRHwDeZ.js +0 -100
- package/bundled-test-harness/assets/head-format-preview-test-DnfUhniI.js +0 -158
- package/bundled-test-harness/assets/helpers-DklkegO_.js +0 -5
- package/bundled-test-harness/assets/host-mode-service-vOfN0smp.js +0 -232
- package/bundled-test-harness/assets/host-mode-test-CCCJFz6_.js +0 -831
- package/bundled-test-harness/assets/host-submode-test-CtCfbuPA.js +0 -1342
- package/bundled-test-harness/assets/html-component-test-CWyhb5ZX.js +0 -65
- package/bundled-test-harness/assets/html-def-test-Cb8C2lUx.js +0 -160
- package/bundled-test-harness/assets/html-meta-extractor-test-BHT9Rtir.js +0 -60
- package/bundled-test-harness/assets/hydratable-card-test-DpgpdesD.js +0 -426
- package/bundled-test-harness/assets/icon-button-ABCGVF3C.js +0 -67
- package/bundled-test-harness/assets/image-metadata-extractor-test-ClhPTouq.js +0 -1109
- package/bundled-test-harness/assets/index-changes-test-CgnVr3LH.js +0 -367
- package/bundled-test-harness/assets/index-query-engine-test-CQTwju5_.js +0 -2593
- package/bundled-test-harness/assets/index-writer-test-IoVOoZT2.js +0 -3040
- package/bundled-test-harness/assets/inspector-test-BN2Ieb77.js +0 -2058
- package/bundled-test-harness/assets/instance-filter-matcher-test-Bq-_Sy89.js +0 -788
- package/bundled-test-harness/assets/instantiate-card-test-DEeDTzFV.js +0 -164
- package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DP6kOyJS.js +0 -475
- package/bundled-test-harness/assets/interact-submode-setup-B0_cHqH-.js +0 -566
- package/bundled-test-harness/assets/invalidate-realm-identifiers-test-9uUD91Pw.js +0 -99
- package/bundled-test-harness/assets/invite-user-to-room-test-CcDA45Ac.js +0 -142
- package/bundled-test-harness/assets/invoke-card-operation-test-DmUtgueM.js +0 -333
- package/bundled-test-harness/assets/isolated-render-test-B2eXNHu6.js +0 -51
- package/bundled-test-harness/assets/job-scoped-doc-cache-test-DF9D7cOc.js +0 -181
- package/bundled-test-harness/assets/job-scoped-instance-residency-test-CSS8xUU5.js +0 -103
- package/bundled-test-harness/assets/jpg-image-def-test-voECMTht.js +0 -697
- package/bundled-test-harness/assets/json-file-def-test-8Y4KLjUC.js +0 -95
- package/bundled-test-harness/assets/key-notices-badge-test-d1mYqx0e.js +0 -155
- package/bundled-test-harness/assets/key-readiness-test-BtCg7PCk.js +0 -190
- package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-CyCMbJnN.js +0 -398
- package/bundled-test-harness/assets/linksto-error-sentinel-test-BDW572-v.js +0 -238
- package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test-B4wM97hD.js +0 -354
- package/bundled-test-harness/assets/linksto-many-per-slot-access-test-BhJmtJ0_.js +0 -303
- package/bundled-test-harness/assets/linksto-sentinel-reload-test-BpBQ5V_i.js +0 -197
- package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test-pkBBl4e9.js +0 -260
- package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-Bb6wjUdD.js +0 -196
- package/bundled-test-harness/assets/lint-and-fix-test-CcMLn-co.js +0 -51
- package/bundled-test-harness/assets/live-test-AyBnq7BX.js +0 -2
- package/bundled-test-harness/assets/live-test-CgnAcIDw.js +0 -100
- package/bundled-test-harness/assets/load-default-skills-test-BIOwtx0Y.js +0 -74
- package/bundled-test-harness/assets/loader-parallel-prefetch-test-D5_oRSER.js +0 -257
- package/bundled-test-harness/assets/loader-test-DSc_jR1c.js +0 -482
- package/bundled-test-harness/assets/loading-test-8pldx7S-.js +0 -63
- package/bundled-test-harness/assets/m4a-audio-def-test-BDI5apzM.js +0 -190
- package/bundled-test-harness/assets/main-5kHyCkdm.js +0 -5
- package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-Wud0s7WZ.js +0 -470
- package/bundled-test-harness/assets/markdown-embed-chooser-test-DVzzS-0C.js +0 -334
- package/bundled-test-harness/assets/markdown-embed-preview-pane-test-B5W_iqsi.js +0 -447
- package/bundled-test-harness/assets/markdown-embed-preview-test-CZF_s0fB.js +0 -368
- package/bundled-test-harness/assets/markdown-fallback-test-fT6BS4W7.js +0 -316
- package/bundled-test-harness/assets/markdown-file-def-test-B1aTzazR.js +0 -380
- package/bundled-test-harness/assets/markdown-helpers-test-gNKZf7Mw.js +0 -188
- package/bundled-test-harness/assets/markdown-highlighting-test-Du5_CQmD.js +0 -244
- package/bundled-test-harness/assets/markdown-preview-h-_aJhRc.js +0 -72
- package/bundled-test-harness/assets/markdown-preview-test-DJvoVsXw.js +0 -238
- package/bundled-test-harness/assets/markdown-skill-frontmatter-test-VwJi3Paj.js +0 -146
- package/bundled-test-harness/assets/markdown-skill-search-test-ysCdf0xM.js +0 -80
- package/bundled-test-harness/assets/matrix-service-account-switch-sessions-test-K2JuMy36.js +0 -63
- package/bundled-test-harness/assets/matrix-service-boot-assembly-test-CkdL_-os.js +0 -300
- package/bundled-test-harness/assets/matrix-service-personal-realm-test-Dy1DultK.js +0 -125
- package/bundled-test-harness/assets/matrix-service-realm-servers-test-DHDDKuEg.js +0 -55
- package/bundled-test-harness/assets/matrix-service-realms-list-updated-test-DcTbZpMl.js +0 -132
- package/bundled-test-harness/assets/matrix-service-relogin-test-D3NQktoa.js +0 -59
- package/bundled-test-harness/assets/matrix-service-sliding-sync-test-6CAflWOA.js +0 -35
- package/bundled-test-harness/assets/menu-kUSaJIPq.js +0 -3562
- package/bundled-test-harness/assets/message-service-subscription-test-DaQdgDWi.js +0 -110
- package/bundled-test-harness/assets/message-service-test-BsGEgM_m.js +0 -144
- package/bundled-test-harness/assets/message-tool-test-BB_4kw1V.js +0 -33
- package/bundled-test-harness/assets/midi-audio-def-test-BbbkFjqf.js +0 -182
- package/bundled-test-harness/assets/migrate-skill-test-X9xImDuq.js +0 -161
- package/bundled-test-harness/assets/mini-AwF31elJ.js +0 -1404
- package/bundled-test-harness/assets/mini-card-chooser-test-BZtrEiWu.js +0 -272
- package/bundled-test-harness/assets/mini-file-chooser-test-MIHW3kCI.js +0 -201
- package/bundled-test-harness/assets/mock-matrix-Dd8k0DNa.js +0 -15107
- package/bundled-test-harness/assets/mock-matrix-DhPN_34j.js +0 -2
- package/bundled-test-harness/assets/modal-LTh3_oHK.js +0 -322
- package/bundled-test-harness/assets/model-cost-tier-test-h1IkU9mp.js +0 -174
- package/bundled-test-harness/assets/model-file-extract-test-ntSo0wZF.js +0 -206
- package/bundled-test-harness/assets/module-transpile-cache-test-CDeRaaeP.js +0 -67
- package/bundled-test-harness/assets/monaco-test-C0Fa744D.js +0 -100
- package/bundled-test-harness/assets/mp3-audio-def-test-B4j4qR9H.js +0 -133
- package/bundled-test-harness/assets/multiple-stacks-test-BhA25ywL.js +0 -208
- package/bundled-test-harness/assets/nested-query-field-render-test-S9Y8YNKB.js +0 -249
- package/bundled-test-harness/assets/no-stacks-test-B7VciWyg.js +0 -48
- package/bundled-test-harness/assets/number-field-test-CS74lDPN.js +0 -184
- package/bundled-test-harness/assets/office-file-def-test-2cKc1pmd.js +0 -263
- package/bundled-test-harness/assets/office-metadata-extractor-test-DC8Fo-OW.js +0 -218
- package/bundled-test-harness/assets/office-poster-capture-test-Ba0_5UrT.js +0 -203
- package/bundled-test-harness/assets/ogg-audio-def-test-CIPQ1d4w.js +0 -196
- package/bundled-test-harness/assets/open-create-listing-modal-test-bmQkY5Zl.js +0 -131
- package/bundled-test-harness/assets/open-image-in-new-tab-test-DBD7_vMH.js +0 -52
- package/bundled-test-harness/assets/open-secure-window-test-BgeuYAqz.js +0 -253
- package/bundled-test-harness/assets/open-workspace-test-DRHGljV0.js +0 -46
- package/bundled-test-harness/assets/operation-lowering-test-CH1c0pSH.js +0 -2957
- package/bundled-test-harness/assets/operations-invocation-test-B1YkCLrv.js +0 -523
- package/bundled-test-harness/assets/operations-optimistic-test-DAbtOwsC.js +0 -203
- package/bundled-test-harness/assets/operations-query-test-9p1ZIDe-.js +0 -459
- package/bundled-test-harness/assets/operations-store-reconciliation-test-D0EQh3w2.js +0 -406
- package/bundled-test-harness/assets/operations-test-BQhlrfe3.js +0 -2518
- package/bundled-test-harness/assets/operator-mode-acceptance-test-DtHnonEb.js +0 -1195
- package/bundled-test-harness/assets/operator-mode-card-chooser-test-DQUxZxaq.js +0 -1036
- package/bundled-test-harness/assets/operator-mode-links-test-BJ26HllS.js +0 -797
- package/bundled-test-harness/assets/operator-mode-test-DIPDI0qt.js +0 -696
- package/bundled-test-harness/assets/operator-mode-ui-test-CfA-fAh4.js +0 -1045
- package/bundled-test-harness/assets/overlay-DecPh3nt.js +0 -123
- package/bundled-test-harness/assets/overlay-menu-items-test-C6XqjLtu.js +0 -331
- package/bundled-test-harness/assets/overlays-Ctp8ePzZ.js +0 -75
- package/bundled-test-harness/assets/overlays-CzWpSg5T.js +0 -2
- package/bundled-test-harness/assets/overlays-detached-element-test-DvL_8Bb5.js +0 -56
- package/bundled-test-harness/assets/panel-CImumikB.js +0 -15124
- package/bundled-test-harness/assets/past-sessions-test-N6riGN_I.js +0 -321
- package/bundled-test-harness/assets/patch-fields-test-D30_-KwQ.js +0 -1014
- package/bundled-test-harness/assets/patch-instance-test-C5rGscZq.js +0 -348
- package/bundled-test-harness/assets/pdf-file-def-test-DtiqGRvZ.js +0 -111
- package/bundled-test-harness/assets/pdf-metadata-extractor-test-FU02KmdV.js +0 -130
- package/bundled-test-harness/assets/permission-checking-realm-test-DqdNJDwU.js +0 -306
- package/bundled-test-harness/assets/persist-module-inspector-view-test-BHOAgPVy.js +0 -60
- package/bundled-test-harness/assets/persist-scroll-position-test-qtmS518r.js +0 -254
- package/bundled-test-harness/assets/phone-number-field-test-DhdaM7uL.js +0 -73
- package/bundled-test-harness/assets/pill-menu-test-C9Mrrepl.js +0 -60
- package/bundled-test-harness/assets/plate-9n-sXyCw.js +0 -41
- package/bundled-test-harness/assets/plate-BnZcAk-_.js +0 -2
- package/bundled-test-harness/assets/player-Cu5b4LEJ.js +0 -82
- package/bundled-test-harness/assets/player-unk2mkxV.js +0 -2
- package/bundled-test-harness/assets/playground-BwA8wFGK.js +0 -58
- package/bundled-test-harness/assets/plural-field-components-test-CFNQKETg.js +0 -198
- package/bundled-test-harness/assets/png-image-def-test-DG5Vhlqb.js +0 -266
- package/bundled-test-harness/assets/policy-audit-confirmation-test-yfKU47LR.js +0 -155
- package/bundled-test-harness/assets/policy-scoped-search-test-BjQRDYqR.js +0 -339
- package/bundled-test-harness/assets/prerender-file-extract-test-CEU4SaAZ.js +0 -346
- package/bundled-test-harness/assets/prerender-html-test-CGB3ClCS.js +0 -670
- package/bundled-test-harness/assets/prerender-meta-test-xqc4fW_0.js +0 -614
- package/bundled-test-harness/assets/prerender-module-test-CI1TmZw-.js +0 -409
- package/bundled-test-harness/assets/prerender-persistence-block-test-Da0dJO_N.js +0 -124
- package/bundled-test-harness/assets/prerender-pre-model-error-test-BVLyhk8R.js +0 -61
- package/bundled-test-harness/assets/prerender-serialize-cycle-test-glJFfxHU.js +0 -134
- package/bundled-test-harness/assets/prerendered-html-read-test-Mp4L0VHQ.js +0 -191
- package/bundled-test-harness/assets/pretui-components-test-BBpA9UnA.js +0 -991
- package/bundled-test-harness/assets/pretui-components-test-BqFq7rw_.css +0 -730
- package/bundled-test-harness/assets/preview-format-test-C55Bwcur.js +0 -103
- package/bundled-test-harness/assets/preview-test-CTAhRGU8.js +0 -474
- package/bundled-test-harness/assets/process-card-test-UjqpuxB7.js +0 -94
- package/bundled-test-harness/assets/profile-settings-modal-C8bCgTMK.js +0 -989
- package/bundled-test-harness/assets/publish-realm-ixUB4FPK.js +0 -82
- package/bundled-test-harness/assets/publish-realm-test-CrrsdL4W.js +0 -210
- package/bundled-test-harness/assets/query-field-barrier-test-DjivFE93.js +0 -113
- package/bundled-test-harness/assets/query-field-error-sentinel-test-0HwnV4Mw.js +0 -201
- package/bundled-test-harness/assets/query-field-membership-status-test-C8yTTBkc.js +0 -323
- package/bundled-test-harness/assets/query-field-page-optin-test-D4l_GcII.js +0 -126
- package/bundled-test-harness/assets/query-field-schema-test-DDbcNNm5.js +0 -231
- package/bundled-test-harness/assets/query-field-search-throttle-test-CXp50Ax0.js +0 -154
- package/bundled-test-harness/assets/query-field-stale-prerender-test-DErzt-Cv.js +0 -152
- package/bundled-test-harness/assets/query-fields-test-Dz67fdSl.js +0 -535
- package/bundled-test-harness/assets/quick-look-test-B1ijDsh_.js +0 -139
- package/bundled-test-harness/assets/read-card-for-ai-assistant-test-DJxZ16H_.js +0 -91
- package/bundled-test-harness/assets/read-file-for-ai-assistant-test-BoRQkZ8c.js +0 -45
- package/bundled-test-harness/assets/read-source-test-Bl-NjchO.js +0 -67
- package/bundled-test-harness/assets/read-text-file-test-CP37CZoo.js +0 -124
- package/bundled-test-harness/assets/realm-CaK5mkT-.js +0 -2852
- package/bundled-test-harness/assets/realm-api-keys-BNUFWbGR.js +0 -579
- package/bundled-test-harness/assets/realm-api-keys-CkshxhXC.js +0 -2
- package/bundled-test-harness/assets/realm-api-keys-test-BP8xifjn.js +0 -109
- package/bundled-test-harness/assets/realm-api-keys-test-CwdK9YXp.js +0 -588
- package/bundled-test-harness/assets/realm-config-iKwE3Htp.js +0 -833
- package/bundled-test-harness/assets/realm-config-policy-standing-test-BgVEIDnB.js +0 -290
- package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-BoJoKzmX.js +0 -274
- package/bundled-test-harness/assets/realm-config-settings-test-Kxw-GHye.js +0 -187
- package/bundled-test-harness/assets/realm-field-test-CdGOxrFb.js +0 -100
- package/bundled-test-harness/assets/realm-indexing-test-CHtsBV2b.js +0 -4380
- package/bundled-test-harness/assets/realm-policy-fitted-test--DhNZSdC.js +0 -206
- package/bundled-test-harness/assets/realm-policy-test-D7714iVa.js +0 -1141
- package/bundled-test-harness/assets/realm-querying-test-Cj1ekZ0H.js +0 -1067
- package/bundled-test-harness/assets/realm-server-form-agnostic-test-CZFPNJfD.js +0 -96
- package/bundled-test-harness/assets/realm-server-subscriber-test-C86WmBp0.js +0 -46
- package/bundled-test-harness/assets/realm-service-info-test-CdgcwKDR.js +0 -67
- package/bundled-test-harness/assets/realm-test-DPoLsvKz.js +0 -2364
- package/bundled-test-harness/assets/realm-token-refresh-test-Ch35Siwi.js +0 -153
- package/bundled-test-harness/assets/realm-url-tooltip-test-x8xWOENK.js +0 -78
- package/bundled-test-harness/assets/reasoning-test-BxpE8Jvf.js +0 -221
- package/bundled-test-harness/assets/recent-files-test-DTmEzPLq.js +0 -450
- package/bundled-test-harness/assets/reindex-realm-test-BQ8KULn4.js +0 -117
- package/bundled-test-harness/assets/relationship-loading-state-test-BJoArPWf.js +0 -290
- package/bundled-test-harness/assets/remix-card-test-DsTA1KoG.js +0 -58
- package/bundled-test-harness/assets/rendered-markdown-DvukulDO.js +0 -292
- package/bundled-test-harness/assets/rendered-markdown-test-DxGptXSV.js +0 -587
- package/bundled-test-harness/assets/resident-instance-reuse-test-ZWnVu8uj.js +0 -82
- package/bundled-test-harness/assets/result-tile-CPyI6Vmv.js +0 -144
- package/bundled-test-harness/assets/rich-markdown-field-test-CdygoXIO.js +0 -1647
- package/bundled-test-harness/assets/room-message-test-D3NfMqH0.js +0 -484
- package/bundled-test-harness/assets/run-D_Px28eF.js +0 -3956
- package/bundled-test-harness/assets/run-realm-code-qWCZxmJ7.js +0 -2964
- package/bundled-test-harness/assets/run-realm-code-test-UzyeEJq6.js +0 -3844
- package/bundled-test-harness/assets/sanitize-module-list-test-Babq44bP.js +0 -85
- package/bundled-test-harness/assets/save-card-skip-index-wait-test-BcELXlQ_.js +0 -89
- package/bundled-test-harness/assets/schema-editor-test-CEvruZbt.js +0 -785
- package/bundled-test-harness/assets/schema-generation-test-hYAMdCrn.js +0 -28
- package/bundled-test-harness/assets/scrolling-test-DVIsh-_1.js +0 -412
- package/bundled-test-harness/assets/search-adorn-test-CkVhqFd0.js +0 -136
- package/bundled-test-harness/assets/search-and-choose-test-DUhOB3FV.js +0 -154
- package/bundled-test-harness/assets/search-correlation-id-test-Drn4r26N.js +0 -139
- package/bundled-test-harness/assets/search-entries-result-test-DTCRJ_wc.js +0 -234
- package/bundled-test-harness/assets/search-entries-test-CE0B47pw.js +0 -1486
- package/bundled-test-harness/assets/search-entries-tool-test-C4aG0ckM.js +0 -504
- package/bundled-test-harness/assets/search-google-images-test-LyhcB2f3.js +0 -166
- package/bundled-test-harness/assets/search-results-D4pSne0x.js +0 -266
- package/bundled-test-harness/assets/search-results-test-CRZHhqhn.js +0 -578
- package/bundled-test-harness/assets/search-selection-menu-test-B7Y3E_nj.js +0 -108
- package/bundled-test-harness/assets/search-sheet-files-test-C2y534g8.js +0 -126
- package/bundled-test-harness/assets/search-sheet-persistence-test-DePC59Bk.js +0 -131
- package/bundled-test-harness/assets/search-test-Dy8NxFkU.js +0 -2249
- package/bundled-test-harness/assets/search-tool-test-lctDaMH3.js +0 -156
- package/bundled-test-harness/assets/searchable-option-test-CE64M8oM.js +0 -322
- package/bundled-test-harness/assets/searchable-search-doc-test-C6u3mVvT.js +0 -1271
- package/bundled-test-harness/assets/section-rail-B_UQX00B.js +0 -113
- package/bundled-test-harness/assets/section-rail-test-DIda7MIw.js +0 -256
- package/bundled-test-harness/assets/secure-sign-in-CqqqfQG8.js +0 -174
- package/bundled-test-harness/assets/secure-sign-in-test-DimbVr_W.js +0 -373
- package/bundled-test-harness/assets/segmented-control-iePxSdTS.js +0 -173
- package/bundled-test-harness/assets/select-tNs6_xwW.js +0 -175
- package/bundled-test-harness/assets/send-ai-assistant-message-test-2GVrMF9Z.js +0 -52
- package/bundled-test-harness/assets/send-bot-trigger-event-test-B_3dKfGN.js +0 -56
- package/bundled-test-harness/assets/send-request-via-proxy-test-_clNWyYc.js +0 -380
- package/bundled-test-harness/assets/sending-test-DCPFXUVg.js +0 -659
- package/bundled-test-harness/assets/serialization-rri-form-audit-test-BI0zCs8Y.js +0 -136
- package/bundled-test-harness/assets/serialization-test-bjdtVlZL.js +0 -8758
- package/bundled-test-harness/assets/set-user-system-card-test-BUv1vL08.js +0 -59
- package/bundled-test-harness/assets/setup-BW1mmC7C.js +0 -772
- package/bundled-test-harness/assets/setup-DsIcFT-T.js +0 -2
- package/bundled-test-harness/assets/shared-link-target-reuse-test-9NeJEjkb.js +0 -207
- package/bundled-test-harness/assets/show-card-test-mfyLwusD.js +0 -365
- package/bundled-test-harness/assets/signed-capture-link-test-BOtKNCAM.js +0 -132
- package/bundled-test-harness/assets/single-stack-test-B4MGjaLk.js +0 -652
- package/bundled-test-harness/assets/skills-test-BuP-Yzk1.js +0 -648
- package/bundled-test-harness/assets/skip-boot-index-guard-test-Cmrx2-K7.js +0 -46
- package/bundled-test-harness/assets/spec-test-BhZDdhVQ.js +0 -1077
- package/bundled-test-harness/assets/spinner-CpIBUG9m.js +0 -49
- package/bundled-test-harness/assets/src-DGHttmW-.js +0 -216
- package/bundled-test-harness/assets/src-DaNDSbp7.js +0 -5
- package/bundled-test-harness/assets/stick-to-bottom-resize-test-Dpy3OVum.js +0 -56
- package/bundled-test-harness/assets/store-add-test-_IYS8o74.js +0 -50
- package/bundled-test-harness/assets/store-module-rebuild-test-B5VMaICy.js +0 -454
- package/bundled-test-harness/assets/store-search-test-C2VZabrH.js +0 -175
- package/bundled-test-harness/assets/store-test-D6PObxoD.js +0 -3672
- package/bundled-test-harness/assets/structured-theme-test-BHjVeMf-.js +0 -377
- package/bundled-test-harness/assets/summarize-session-test-BFtTuhe0.js +0 -172
- package/bundled-test-harness/assets/svg-image-def-test-BL6lkWUX.js +0 -167
- package/bundled-test-harness/assets/switch-submode-test-6Uv3bZMl.js +0 -168
- package/bundled-test-harness/assets/sync-openrouter-models-test-Dp9E05tL.js +0 -97
- package/bundled-test-harness/assets/test-support-DYm8XZ0E.js +0 -3
- package/bundled-test-harness/assets/test-support-DfnhiIMV.js +0 -99
- package/bundled-test-harness/assets/tests-CZk0Iag2.js +0 -3596
- package/bundled-test-harness/assets/text-file-def-test-CHdC0yIU.js +0 -94
- package/bundled-test-harness/assets/text-input-validator-test-B9ZR8XPU.js +0 -156
- package/bundled-test-harness/assets/text-suggestion-test-CGLspKFQ.js +0 -340
- package/bundled-test-harness/assets/theme-card-test-CXZvSEvG.js +0 -621
- package/bundled-test-harness/assets/theme-dashboard-nav-test-CkEE0ILk.js +0 -196
- package/bundled-test-harness/assets/theme-scheme-island-test-URXTjipF.js +0 -264
- package/bundled-test-harness/assets/titles-C6enAdIv.js +0 -2
- package/bundled-test-harness/assets/titles-Dft1HoUT.js +0 -52
- package/bundled-test-harness/assets/to-device-streaming-test-D33ZOc9o.js +0 -163
- package/bundled-test-harness/assets/token-usage-test-BHQlU4J4.js +0 -160
- package/bundled-test-harness/assets/tools-CrudqfS3.js +0 -774
- package/bundled-test-harness/assets/tools-calling-test-jo7IREau.js +0 -200
- package/bundled-test-harness/assets/tools-test-D1wMfUa0.js +0 -1624
- package/bundled-test-harness/assets/tools-test-Dn1LYsXp.js +0 -3204
- package/bundled-test-harness/assets/tooltip-8Wyz4IIn.css +0 -68
- package/bundled-test-harness/assets/tooltip-CqwLzRz5.js +0 -134
- package/bundled-test-harness/assets/transform-cards-test-BPhwPFtp.js +0 -341
- package/bundled-test-harness/assets/ts-file-def-preview-test-Bq3zTgw8.js +0 -95
- package/bundled-test-harness/assets/ts-file-def-test-GLswMl7O.js +0 -92
- package/bundled-test-harness/assets/ttf-font-def-test-DQulvUWs.js +0 -206
- package/bundled-test-harness/assets/turn-settling-test-BspmOUQP.js +0 -160
- package/bundled-test-harness/assets/turn-summary-9A8nvC0-.js +0 -1039
- package/bundled-test-harness/assets/unpublish-realm-test-SkYPEhDz.js +0 -102
- package/bundled-test-harness/assets/update-room-skills-test-cTxb-WU6.js +0 -240
- package/bundled-test-harness/assets/use-ai-assistant-test-uaqW1T_A.js +0 -384
- package/bundled-test-harness/assets/user-message-BudkIP-3.js +0 -262
- package/bundled-test-harness/assets/validate-realm-test-DxrGgH9n.js +0 -67
- package/bundled-test-harness/assets/video-metadata-extractor-test-B2pe-Iqa.js +0 -520
- package/bundled-test-harness/assets/view-visually-test-PNon6fUo.js +0 -335
- package/bundled-test-harness/assets/virtual-network-reset-test-uYJLaQHf.js +0 -96
- package/bundled-test-harness/assets/wav-audio-def-test-F4OrFFR4.js +0 -160
- package/bundled-test-harness/assets/webp-image-def-test-B0a_-Vya.js +0 -226
- package/bundled-test-harness/assets/workspace-Cyftysy9.js +0 -440
- package/bundled-test-harness/assets/workspace-a11y-test-sKiPDcbl.js +0 -197
- package/bundled-test-harness/assets/workspace-actions-BuawjFmZ.js +0 -561
- package/bundled-test-harness/assets/workspace-behavior-test-CKa-pb3T.js +0 -338
- package/bundled-test-harness/assets/workspace-delete-multiple-test-Dt2weG5R.js +0 -212
- package/bundled-test-harness/assets/workspace-delete-summary-test-CkqgFqZ8.js +0 -63
- package/bundled-test-harness/assets/workspace-hosting-test-Ci7EEtHP.js +0 -138
- package/bundled-test-harness/assets/workspace-indexing-test-BPVxxY6W.js +0 -71
- package/bundled-test-harness/assets/workspace-test-CWr7vFbg.js +0 -385
- package/bundled-test-harness/assets/workspace-test-INNpQovc.js +0 -51
- package/bundled-test-harness/assets/workspace-timestamp-labels-test-CigQb5wr.js +0 -68
- package/bundled-test-harness/assets/workspace-unit-test-BwVKpuXT.js +0 -122
- package/bundled-test-harness/assets/write-binary-file-test-BKP3gv1k.js +0 -124
- package/bundled-test-harness/assets/write-text-file-test-B6ijTKTa.js +0 -191
- package/bundled-test-harness/assets/zip-archive-test-C-PBzkTn.js +0 -285
- package/bundled-test-harness/assets/zip-file-def-test-FyCzJT-9.js +0 -164
|
@@ -1,3956 +0,0 @@
|
|
|
1
|
-
import "./chunk-Rp0pCe6z.js";
|
|
2
|
-
import { $ as flushKeyframeResolvers, Ft as easingDefinitionToFunction, Nt as time, _t as generateLinearEasing, bt as mix, gt as maxGeneratorDuration, ht as calcGeneratorDuration, nn as registerBusyProbe, pt as spring, vt as cancelFrame, yt as frame } from "./layout-group-BS0gklZp.js";
|
|
3
|
-
import { C as animateTarget, c as defineParticipantArg, l as setParticipantHost, w as positionalKeys } from "./node-BWOLCOMI.js";
|
|
4
|
-
import "./src-CbBcj3xm.js";
|
|
5
|
-
import { r as scaleTransition, t as motionSpeed } from "./speed-bIo0tyrM.js";
|
|
6
|
-
//#region ../choreo/src/measure.ts
|
|
7
|
-
/**
|
|
8
|
-
* One measurement layer, for everything that measures.
|
|
9
|
-
*
|
|
10
|
-
* The region and the beacon registry both turn a DOMRect into the three spaces
|
|
11
|
-
* a step can ask for — page, region-relative, offset-parent-relative — and they
|
|
12
|
-
* have to agree exactly, because a Move routinely reads one sprite's `page` and
|
|
13
|
-
* another's. Ember Animated learned the same thing the hard way and ended up
|
|
14
|
-
* with a single bounds module; two copies of `minus` that drift by a scroll
|
|
15
|
-
* offset produce a flight that lands next to its target, which is the kind of
|
|
16
|
-
* bug that looks like a spring problem for a day.
|
|
17
|
-
*/
|
|
18
|
-
defineParticipantArg("pack", (el, pack) => {
|
|
19
|
-
if (pack === "content") el.setAttribute("data-choreo-pack", "content");
|
|
20
|
-
else el.removeAttribute("data-choreo-pack");
|
|
21
|
-
});
|
|
22
|
-
/** a box in page space */
|
|
23
|
-
var rect = (r) => ({
|
|
24
|
-
height: r.height,
|
|
25
|
-
width: r.width,
|
|
26
|
-
x: r.left,
|
|
27
|
-
y: r.top
|
|
28
|
-
});
|
|
29
|
-
/** `a` expressed relative to `b`'s top-left, keeping a's size */
|
|
30
|
-
var minus = (a, b) => ({
|
|
31
|
-
height: a.height,
|
|
32
|
-
width: a.width,
|
|
33
|
-
x: a.left - b.left,
|
|
34
|
-
y: a.top - b.top
|
|
35
|
-
});
|
|
36
|
-
/** an element's box together with the box it is positioned inside */
|
|
37
|
-
/**
|
|
38
|
-
* The shrink-wrap of `el`'s contents — the ink — not the stretched layout
|
|
39
|
-
* box. A full-bleed title (`left:0; right:0; width:auto`) still has a
|
|
40
|
-
* word-sized range; Crossing crop must match THAT, or the type explodes
|
|
41
|
-
* into a viewport strip. Empty / collapsed → undefined, so the frame wins.
|
|
42
|
-
*/
|
|
43
|
-
var inkBox = (el) => {
|
|
44
|
-
const doc = el.ownerDocument;
|
|
45
|
-
if (!doc) return;
|
|
46
|
-
const range = doc.createRange();
|
|
47
|
-
range.selectNodeContents(el);
|
|
48
|
-
const r = range.getBoundingClientRect();
|
|
49
|
-
if (r.width < .5 && r.height < .5) return;
|
|
50
|
-
return r;
|
|
51
|
-
};
|
|
52
|
-
var substanceOf = (el) => {
|
|
53
|
-
const marked = el.querySelector("[data-choreo-substance]")?.getBoundingClientRect();
|
|
54
|
-
if (marked) return marked;
|
|
55
|
-
if (el.getAttribute("data-choreo-pack") === "content") return inkBox(el);
|
|
56
|
-
};
|
|
57
|
-
/** the containing block a `position: absolute` child would be placed against */
|
|
58
|
-
var offsetBox = (el) => (el.offsetParent ?? el.parentElement ?? el).getBoundingClientRect();
|
|
59
|
-
/**
|
|
60
|
-
* Does the element have a layout box? One under `display: none` (its own or
|
|
61
|
-
* an ancestor's, as with the `hidden` attribute) measures as an empty rect at
|
|
62
|
-
* the page origin, which is no place to move from or to.
|
|
63
|
-
*/
|
|
64
|
-
var isRendered = (el) => el.getClientRects().length > 0;
|
|
65
|
-
/** `undefined` for an element with no layout box (see `isRendered`) */
|
|
66
|
-
var measure = (el) => isRendered(el) ? snapshotOf(el) : void 0;
|
|
67
|
-
var snapshotOf = (el) => ({
|
|
68
|
-
el: el.getBoundingClientRect(),
|
|
69
|
-
paint: getComputedStyle(el).backgroundColor,
|
|
70
|
-
parent: offsetBox(el),
|
|
71
|
-
substance: substanceOf(el)
|
|
72
|
-
});
|
|
73
|
-
/** the three spaces, from a snapshot and the region's own box */
|
|
74
|
-
var boundsOf = (snap, root) => ({
|
|
75
|
-
context: minus(snap.el, root),
|
|
76
|
-
page: rect(snap.el),
|
|
77
|
-
paint: snap.paint,
|
|
78
|
-
parent: minus(snap.el, snap.parent),
|
|
79
|
-
substance: snap.substance && rect(snap.substance)
|
|
80
|
-
});
|
|
81
|
-
/** measure an element straight into bounds — what a beacon needs */
|
|
82
|
-
var measureBounds = (el, root) => {
|
|
83
|
-
const snap = measure(el);
|
|
84
|
-
return snap && boundsOf(snap, root);
|
|
85
|
-
};
|
|
86
|
-
//#endregion
|
|
87
|
-
//#region ../choreo/src/beacons.ts
|
|
88
|
-
/**
|
|
89
|
-
* Beacons — a named box that does not animate.
|
|
90
|
-
*
|
|
91
|
-
* Ember Animated's primitive: `<AnimatedBeacon>` measures its child when a
|
|
92
|
-
* transition starts, stores a sprite on the motion service, and a generator
|
|
93
|
-
* reads `context.beacons` to say "start here" or "end there". The beacon
|
|
94
|
-
* itself never moves.
|
|
95
|
-
*
|
|
96
|
-
* <button {{beacon 'trash'}}>Trash</button>
|
|
97
|
-
*
|
|
98
|
-
* <Choreo as |c|>
|
|
99
|
-
* …
|
|
100
|
-
* <c.Move @of={{c.removed 'row'}} @to={{c.beacon 'trash'}} />
|
|
101
|
-
* </Choreo>
|
|
102
|
-
*
|
|
103
|
-
* This is deliberately NOT `layoutId`. `layoutId` pairs two real elements that
|
|
104
|
-
* share an identity and morphs one into the other — putting it on a leaving row
|
|
105
|
-
* and on the bin would make the bin a shared element, and it would stretch. A
|
|
106
|
-
* beacon has no identity in the changeset: it is not inserted, kept or removed,
|
|
107
|
-
* it is a point other sprites may borrow. A beacon moving on its own never
|
|
108
|
-
* starts a run.
|
|
109
|
-
*
|
|
110
|
-
* The registry is document-global on purpose. The case that wants beacons is an
|
|
111
|
-
* inbox — the trash lives in the chrome, the list lives in the outlet, and they
|
|
112
|
-
* are different regions precisely so their changesets stay apart. A region-local
|
|
113
|
-
* registry could not see across that boundary, which is the whole point.
|
|
114
|
-
* packages/choreo-gallery/realm/docs/nested-choreo.md has the reasoning.
|
|
115
|
-
*/
|
|
116
|
-
/** name → the element claiming it. First registration this pass wins, as Ember Animated's `hasBeacon` does. */
|
|
117
|
-
var registry = /* @__PURE__ */ new Map();
|
|
118
|
-
function registerBeacon(name, element) {
|
|
119
|
-
if (!registry.has(name)) registry.set(name, element);
|
|
120
|
-
return () => {
|
|
121
|
-
if (registry.get(name) === element) registry.delete(name);
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Measure the live beacons, in the same window the region measures `final`.
|
|
126
|
-
*
|
|
127
|
-
* Re-measured every pass, never cached: the trash can move without the list
|
|
128
|
-
* rendering at all — a header that hides, a column that resizes, a scroll.
|
|
129
|
-
*
|
|
130
|
-
* A region passes the names its score asked for, so a pass measures only
|
|
131
|
-
* those: a page can claim hundreds of beacons (every chip a sheet may open
|
|
132
|
-
* from), and each region measuring every one on every pass would cost a
|
|
133
|
-
* layout read per beacon per region. Without `names`, every claimed beacon
|
|
134
|
-
* is measured.
|
|
135
|
-
*/
|
|
136
|
-
function measureBeacons(root, names) {
|
|
137
|
-
const out = /* @__PURE__ */ new Map();
|
|
138
|
-
const wanted = names ? [...names].map((name) => [name, registry.get(name)]) : [...registry];
|
|
139
|
-
for (const [name, el] of wanted) {
|
|
140
|
-
if (!el?.isConnected) continue;
|
|
141
|
-
const bounds = measureBounds(el, root);
|
|
142
|
-
if (bounds) out.set(name, bounds);
|
|
143
|
-
}
|
|
144
|
-
return out;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Forget every claimed name. The registry outlives any one owner, so a test
|
|
148
|
-
* that tore down mid-flight would otherwise leave a dead element holding a
|
|
149
|
-
* name the next test wants — first-wins turns into first-test-wins.
|
|
150
|
-
* `setupChoreo(hooks)` runs this before and after every test; nothing in an
|
|
151
|
-
* app should.
|
|
152
|
-
*/
|
|
153
|
-
function resetBeacons() {
|
|
154
|
-
registry.clear();
|
|
155
|
-
}
|
|
156
|
-
//#endregion
|
|
157
|
-
//#region ../choreo/src/gesture.ts
|
|
158
|
-
/**
|
|
159
|
-
* `c.gesture` — the live drag as a first-class geometry source (§6.1, §6.4).
|
|
160
|
-
*
|
|
161
|
-
* A document-level pointer tracker (listeners, not timers) keeps the last
|
|
162
|
-
* pointer position and a short velocity window. A Move that borrows
|
|
163
|
-
* `{{c.gesture}}` as its `@from` starts from wherever the finger let go —
|
|
164
|
-
* sized as the sprite, centred on the pointer — and any spring that flies
|
|
165
|
-
* it inherits the pointer's velocity, so a toss leaves at the speed it was
|
|
166
|
-
* thrown.
|
|
167
|
-
*/
|
|
168
|
-
var GESTURE = { gesture: true };
|
|
169
|
-
function isGestureRef(v) {
|
|
170
|
-
return typeof v === "object" && v !== null && v.gesture === true;
|
|
171
|
-
}
|
|
172
|
-
var samples = [];
|
|
173
|
-
var tracking = false;
|
|
174
|
-
function record(event) {
|
|
175
|
-
const now = performance.now();
|
|
176
|
-
samples.push({
|
|
177
|
-
t: now,
|
|
178
|
-
x: event.clientX,
|
|
179
|
-
y: event.clientY
|
|
180
|
-
});
|
|
181
|
-
if (samples.length > 8) samples.shift();
|
|
182
|
-
}
|
|
183
|
-
/** idempotent; the first <Choreo> turns it on */
|
|
184
|
-
function trackGestures() {
|
|
185
|
-
if (tracking || typeof window === "undefined") return;
|
|
186
|
-
tracking = true;
|
|
187
|
-
window.addEventListener("pointerdown", record, {
|
|
188
|
-
capture: true,
|
|
189
|
-
passive: true
|
|
190
|
-
});
|
|
191
|
-
window.addEventListener("pointermove", record, {
|
|
192
|
-
capture: true,
|
|
193
|
-
passive: true
|
|
194
|
-
});
|
|
195
|
-
window.addEventListener("pointerup", record, {
|
|
196
|
-
capture: true,
|
|
197
|
-
passive: true
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
/** the pointer's page position now, or null before any pointer event */
|
|
201
|
-
function gesturePoint() {
|
|
202
|
-
const last = samples[samples.length - 1];
|
|
203
|
-
return last ? {
|
|
204
|
-
x: last.x,
|
|
205
|
-
y: last.y
|
|
206
|
-
} : null;
|
|
207
|
-
}
|
|
208
|
-
/** units per second over the recent window — what a spring inherits */
|
|
209
|
-
function gestureVelocity() {
|
|
210
|
-
if (samples.length < 2) return {
|
|
211
|
-
x: 0,
|
|
212
|
-
y: 0
|
|
213
|
-
};
|
|
214
|
-
const now = performance.now();
|
|
215
|
-
const a = samples.filter((s) => now - s.t < 120)[0] ?? samples[samples.length - 2];
|
|
216
|
-
const b = samples[samples.length - 1];
|
|
217
|
-
const dt = (b.t - a.t) / 1e3;
|
|
218
|
-
if (dt <= 0) return {
|
|
219
|
-
x: 0,
|
|
220
|
-
y: 0
|
|
221
|
-
};
|
|
222
|
-
return {
|
|
223
|
-
x: (b.x - a.x) / dt,
|
|
224
|
-
y: (b.y - a.y) / dt
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
/** the gesture as a box: the sprite\'s own size, centred on the pointer */
|
|
228
|
-
function gestureBounds(size) {
|
|
229
|
-
const point = gesturePoint();
|
|
230
|
-
if (!point) return null;
|
|
231
|
-
const page = {
|
|
232
|
-
height: size.height,
|
|
233
|
-
width: size.width,
|
|
234
|
-
x: point.x - size.width / 2,
|
|
235
|
-
y: point.y - size.height / 2
|
|
236
|
-
};
|
|
237
|
-
return {
|
|
238
|
-
context: page,
|
|
239
|
-
page,
|
|
240
|
-
parent: page
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
/** test-support: forget everything between tests */
|
|
244
|
-
function resetGestures() {
|
|
245
|
-
samples = [];
|
|
246
|
-
}
|
|
247
|
-
//#endregion
|
|
248
|
-
//#region ../choreo/src/compile.ts
|
|
249
|
-
/**
|
|
250
|
-
* boxel-motion's OrchestrationMatrix, as a cue list: the timeline tree becomes
|
|
251
|
-
* one (sprite, start, duration) per step per sprite. Sequences add, parallels
|
|
252
|
-
* overlay; a spring's length is computed with the engine's own generator so a
|
|
253
|
-
* sequence can follow one — the thing the legacy could not do.
|
|
254
|
-
*/
|
|
255
|
-
var isBlock = (node) => node.kind === "sequence" || node.kind === "parallel";
|
|
256
|
-
var isGate = (node) => node.kind === "gate";
|
|
257
|
-
var DEFAULT_SPRING = {
|
|
258
|
-
damping: 30,
|
|
259
|
-
stiffness: 300
|
|
260
|
-
};
|
|
261
|
-
/**
|
|
262
|
-
* What `c.Follow` is allowed to drive: paint, never layout. See the throw
|
|
263
|
-
* in the 'follow' case for why the line is drawn exactly here.
|
|
264
|
-
*/
|
|
265
|
-
var DERIVABLE = new Set([
|
|
266
|
-
"filter",
|
|
267
|
-
"opacity",
|
|
268
|
-
"rotate",
|
|
269
|
-
"rotateX",
|
|
270
|
-
"rotateY",
|
|
271
|
-
"rotateZ",
|
|
272
|
-
"scale",
|
|
273
|
-
"scaleX",
|
|
274
|
-
"scaleY",
|
|
275
|
-
"skewX",
|
|
276
|
-
"skewY",
|
|
277
|
-
"x",
|
|
278
|
-
"y",
|
|
279
|
-
"z"
|
|
280
|
-
]);
|
|
281
|
-
/** the shared offstage <svg> that path geometry is sampled inside */
|
|
282
|
-
var pathHost;
|
|
283
|
-
function samplePath(d, samples = 64) {
|
|
284
|
-
if (!pathHost) {
|
|
285
|
-
pathHost = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
286
|
-
pathHost.setAttribute("aria-hidden", "true");
|
|
287
|
-
pathHost.style.cssText = "position:absolute;width:0;height:0;overflow:hidden";
|
|
288
|
-
document.body.appendChild(pathHost);
|
|
289
|
-
}
|
|
290
|
-
const el = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
291
|
-
el.setAttribute("d", d);
|
|
292
|
-
pathHost.appendChild(el);
|
|
293
|
-
try {
|
|
294
|
-
const length = el.getTotalLength();
|
|
295
|
-
return Array.from({ length: samples + 1 }, (_, i) => {
|
|
296
|
-
const pt = el.getPointAtLength(length * i / samples);
|
|
297
|
-
return {
|
|
298
|
-
x: pt.x,
|
|
299
|
-
y: pt.y
|
|
300
|
-
};
|
|
301
|
-
});
|
|
302
|
-
} finally {
|
|
303
|
-
el.remove();
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Similarity-map a drawn path so its start is the sprite's start and its end
|
|
308
|
-
* is the measured landing (§4.4): the path bends the journey, never the
|
|
309
|
-
* destination. Complex multiplication: m = D / v rotates and scales the
|
|
310
|
-
* author's stroke onto the real displacement.
|
|
311
|
-
*/
|
|
312
|
-
function mapFlight(raw, dx, dy) {
|
|
313
|
-
const s0 = raw[0];
|
|
314
|
-
const e = raw[raw.length - 1];
|
|
315
|
-
const vx = e.x - s0.x;
|
|
316
|
-
const vy = e.y - s0.y;
|
|
317
|
-
const mag = vx * vx + vy * vy;
|
|
318
|
-
if (mag < 1e-6) return raw.map((_, i) => ({
|
|
319
|
-
x: dx * i / (raw.length - 1),
|
|
320
|
-
y: dy * i / (raw.length - 1)
|
|
321
|
-
}));
|
|
322
|
-
const mr = (dx * vx + dy * vy) / mag;
|
|
323
|
-
const mi = (dy * vx - dx * vy) / mag;
|
|
324
|
-
return raw.map((pt) => {
|
|
325
|
-
const px = pt.x - s0.x;
|
|
326
|
-
const py = pt.y - s0.y;
|
|
327
|
-
return {
|
|
328
|
-
x: px * mr - py * mi,
|
|
329
|
-
y: px * mi + py * mr
|
|
330
|
-
};
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
var resolve = (v, sprite, cs) => typeof v === "function" ? v(sprite, cs) : v;
|
|
334
|
-
var single = (v) => Array.isArray(v) ? v[0] : v;
|
|
335
|
-
var num = (v) => {
|
|
336
|
-
if (typeof v === "number") return v;
|
|
337
|
-
const n = parseFloat(String(v));
|
|
338
|
-
return Number.isNaN(n) ? 0 : n;
|
|
339
|
-
};
|
|
340
|
-
/** the value a spring starts from when the step does not say: the engine's, else the computed style's */
|
|
341
|
-
function currentValue(sprite, key) {
|
|
342
|
-
const ve = sprite.node.visualElement;
|
|
343
|
-
if (ve?.hasValue(key)) return num(ve.getValue(key).get());
|
|
344
|
-
const latest = ve?.latestValues?.[key];
|
|
345
|
-
if (latest !== void 0) return num(latest);
|
|
346
|
-
return num(getComputedStyle(sprite.element).getPropertyValue(key.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase())));
|
|
347
|
-
}
|
|
348
|
-
function springDuration(from, to, spec) {
|
|
349
|
-
if (from === to) return 0;
|
|
350
|
-
const generator = spring({
|
|
351
|
-
keyframes: [from, to],
|
|
352
|
-
...spec
|
|
353
|
-
});
|
|
354
|
-
return Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
|
|
355
|
-
}
|
|
356
|
-
/** a cue before it is placed on the run's clock; `offset` is its rung of the stagger ladder */
|
|
357
|
-
/**
|
|
358
|
-
* The rung each index takes on the stagger ladder, under a delivery order.
|
|
359
|
-
* 'center' delivers from the middle outward; 'random' shuffles per run —
|
|
360
|
-
* seeded input is the native driver's requirement, not this one's.
|
|
361
|
-
*/
|
|
362
|
-
function ladder(n, order) {
|
|
363
|
-
const ranks = Array.from({ length: n }, (_, i) => i);
|
|
364
|
-
switch (order) {
|
|
365
|
-
case "reverse": return ranks.map((i) => n - 1 - i);
|
|
366
|
-
case "center": {
|
|
367
|
-
const mid = (n - 1) / 2;
|
|
368
|
-
const byDistance = [...ranks].sort((a, b) => Math.abs(a - mid) - Math.abs(b - mid));
|
|
369
|
-
const out = new Array(n);
|
|
370
|
-
byDistance.forEach((index, rank) => out[index] = rank);
|
|
371
|
-
return out;
|
|
372
|
-
}
|
|
373
|
-
case "random": {
|
|
374
|
-
const shuffled = [...ranks];
|
|
375
|
-
for (let i = n - 1; i > 0; i--) {
|
|
376
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
377
|
-
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
378
|
-
}
|
|
379
|
-
const out = new Array(n);
|
|
380
|
-
shuffled.forEach((index, rank) => out[index] = rank);
|
|
381
|
-
return out;
|
|
382
|
-
}
|
|
383
|
-
default: return ranks;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
function resolveTarget(step, sprite, cs) {
|
|
387
|
-
const target = {};
|
|
388
|
-
let longest = 0;
|
|
389
|
-
for (const key in step.props) {
|
|
390
|
-
const to = resolve(step.props[key], sprite, cs);
|
|
391
|
-
if (Array.isArray(to)) {
|
|
392
|
-
if (step.kind === "spring" && to.length > 2) throw new Error(`choreo: a spring animates between two keyframes; \`${key}\` was given ${to.length}`);
|
|
393
|
-
target[key] = to;
|
|
394
|
-
if (step.kind === "spring") longest = Math.max(longest, springDuration(num(to[0]), num(to[to.length - 1]), step.spring ?? DEFAULT_SPRING));
|
|
395
|
-
} else {
|
|
396
|
-
target[key] = to;
|
|
397
|
-
if (step.kind === "spring") longest = Math.max(longest, springDuration(currentValue(sprite, key), num(to), step.spring ?? DEFAULT_SPRING));
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
return {
|
|
401
|
-
longest,
|
|
402
|
-
target
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* The two boxes a shape-matched flight aligns: the declared subjects
|
|
407
|
-
* ([data-choreo-substance], or pack="content" ink) when either end has
|
|
408
|
-
* one — Keynote matches OBJECTS, not slide frames — with the undeclared
|
|
409
|
-
* end derived by fraction (content laid out proportionally keeps one
|
|
410
|
-
* fraction at both scales; the return trip's card, whose demo has not
|
|
411
|
-
* boarded yet, has nothing to measure). Neither end declared: the frames
|
|
412
|
-
* themselves.
|
|
413
|
-
*/
|
|
414
|
-
function matchBoxes(initial, final, from, to, z) {
|
|
415
|
-
const subI = initial.substance && descale(initial.substance, z);
|
|
416
|
-
const subF = final.substance && descale(final.substance, z);
|
|
417
|
-
if (!subI && !subF) return {
|
|
418
|
-
from,
|
|
419
|
-
to
|
|
420
|
-
};
|
|
421
|
-
const map = (s, a, b) => ({
|
|
422
|
-
height: s.height / (a.height || 1) * b.height,
|
|
423
|
-
width: s.width / (a.width || 1) * b.width,
|
|
424
|
-
x: b.x + (s.x - a.x) / (a.width || 1) * b.width,
|
|
425
|
-
y: b.y + (s.y - a.y) / (a.height || 1) * b.height
|
|
426
|
-
});
|
|
427
|
-
return {
|
|
428
|
-
from: subI ?? map(subF, to, from),
|
|
429
|
-
to: subF ?? map(subI, from, to)
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
var centreOf = (r) => ({
|
|
433
|
-
x: r.x + r.width / 2,
|
|
434
|
-
y: r.y + r.height / 2
|
|
435
|
-
});
|
|
436
|
-
/** a page-space box, divided back into local space by the measure-time zoom */
|
|
437
|
-
function descale(r, z) {
|
|
438
|
-
return z === 1 ? r : {
|
|
439
|
-
height: r.height / z,
|
|
440
|
-
width: r.width / z,
|
|
441
|
-
x: r.x / z,
|
|
442
|
-
y: r.y / z
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
function resolveMove(step, sprite, cs) {
|
|
446
|
-
const size = (sprite.final ?? sprite.initial)?.page ?? {
|
|
447
|
-
height: 0,
|
|
448
|
-
width: 0,
|
|
449
|
-
x: 0,
|
|
450
|
-
y: 0
|
|
451
|
-
};
|
|
452
|
-
const hot = step.from && isGestureRef(step.from);
|
|
453
|
-
const borrowedFrom = step.from ? hot ? gestureBounds(size) : cs.beacon(step.from.beacon) : null;
|
|
454
|
-
const borrowedTo = step.to ? cs.beacon(step.to.beacon) : null;
|
|
455
|
-
const initial = borrowedFrom ?? sprite.initial;
|
|
456
|
-
const final = borrowedTo ?? sprite.final;
|
|
457
|
-
if (!initial || !final) return null;
|
|
458
|
-
const z = cs.measureZoom ?? 1;
|
|
459
|
-
const parentSpace = step.space === "parent" && !borrowedFrom && !borrowedTo;
|
|
460
|
-
const from = descale(parentSpace ? initial.parent : initial.page, z);
|
|
461
|
-
const to = descale(parentSpace ? final.parent : final.page, z);
|
|
462
|
-
const target = {};
|
|
463
|
-
const pairs = [];
|
|
464
|
-
const scaleMode = step.size === "scale" || step.size === "crop";
|
|
465
|
-
const cropMode = step.size === "crop";
|
|
466
|
-
const m = scaleMode ? matchBoxes(initial, final, from, to, z) : null;
|
|
467
|
-
const dx = m ? centreOf(m.to).x - centreOf(m.from).x : to.x - from.x;
|
|
468
|
-
const dy = m ? cropMode ? m.to.y - m.from.y : centreOf(m.to).y - centreOf(m.from).y : to.y - from.y;
|
|
469
|
-
/**
|
|
470
|
-
* Which end the element is actually sitting on decides the sign.
|
|
471
|
-
*
|
|
472
|
-
* The usual FLIP case is a kept sprite: the pass has already put it at its
|
|
473
|
-
* destination, so it is pulled back by the delta and animated to zero. A
|
|
474
|
-
* REMOVED sprite is the other way round — the region has locked it in the
|
|
475
|
-
* orphan layer at the place it was, so it starts at zero and travels the
|
|
476
|
-
* delta. That is the only case that can have a `final` at all, and it only
|
|
477
|
-
* has one because a beacon lent it one.
|
|
478
|
-
*/
|
|
479
|
-
const holdsStart = sprite.type === "removed";
|
|
480
|
-
const leg = (d) => holdsStart ? [0, d] : [-d, 0];
|
|
481
|
-
let flight;
|
|
482
|
-
if (step.path && (dx !== 0 || dy !== 0)) {
|
|
483
|
-
flight = {
|
|
484
|
-
points: mapFlight(samplePath(step.path), dx, dy),
|
|
485
|
-
rest: holdsStart ? {
|
|
486
|
-
x: 0,
|
|
487
|
-
y: 0
|
|
488
|
-
} : {
|
|
489
|
-
x: dx,
|
|
490
|
-
y: dy
|
|
491
|
-
},
|
|
492
|
-
rotate: step.rotate
|
|
493
|
-
};
|
|
494
|
-
pairs.push(leg(Math.hypot(dx, dy)));
|
|
495
|
-
} else if (m) {
|
|
496
|
-
const crop = cropMode;
|
|
497
|
-
const rx = m.from.width / (m.to.width || 1) || 1;
|
|
498
|
-
const ry = m.from.height / (m.to.height || 1) || 1;
|
|
499
|
-
const su = rx;
|
|
500
|
-
const sx = crop ? su : rx;
|
|
501
|
-
const sy = crop ? su : ry;
|
|
502
|
-
const fx = holdsStart ? 1 / sx : sx;
|
|
503
|
-
const fy = holdsStart ? 1 / sy : sy;
|
|
504
|
-
const anchor = centreOf(holdsStart ? from : to);
|
|
505
|
-
const matched = holdsStart ? m.from : m.to;
|
|
506
|
-
const pinned = crop ? {
|
|
507
|
-
x: centreOf(matched).x,
|
|
508
|
-
y: matched.y
|
|
509
|
-
} : centreOf(matched);
|
|
510
|
-
const cx = (1 - fx) * (pinned.x - anchor.x);
|
|
511
|
-
const cy = (1 - fy) * (pinned.y - anchor.y);
|
|
512
|
-
const x = holdsStart ? dx + cx : -dx + cx;
|
|
513
|
-
const y = holdsStart ? dy + cy : -dy + cy;
|
|
514
|
-
if (x !== 0) {
|
|
515
|
-
target["x"] = holdsStart ? [0, x] : [x, 0];
|
|
516
|
-
pairs.push(holdsStart ? [0, x] : [x, 0]);
|
|
517
|
-
}
|
|
518
|
-
if (y !== 0) {
|
|
519
|
-
target["y"] = holdsStart ? [0, y] : [y, 0];
|
|
520
|
-
pairs.push(holdsStart ? [0, y] : [y, 0]);
|
|
521
|
-
}
|
|
522
|
-
if (crop) {
|
|
523
|
-
if (fx !== 1) target["scale"] = holdsStart ? [1, fx] : [fx, 1];
|
|
524
|
-
const frame = holdsStart ? from : to;
|
|
525
|
-
const window = holdsStart ? m.to : m.from;
|
|
526
|
-
const f = holdsStart ? fx : sx;
|
|
527
|
-
const d = {
|
|
528
|
-
x,
|
|
529
|
-
y
|
|
530
|
-
};
|
|
531
|
-
const pre = (edge) => anchor.y + (edge - anchor.y - d.y) / f;
|
|
532
|
-
const clamp = (v) => Math.max(0, v);
|
|
533
|
-
const b = clamp(frame.y + frame.height - pre(window.y + window.height));
|
|
534
|
-
if (b > .5) {
|
|
535
|
-
const far = `inset(0px 0px ${b.toFixed(2)}px 0px)`;
|
|
536
|
-
const rest = "inset(0px 0px 0px 0px)";
|
|
537
|
-
target["clipPath"] = holdsStart ? [rest, far] : [far, rest];
|
|
538
|
-
}
|
|
539
|
-
} else {
|
|
540
|
-
if (fx !== 1) target["scaleX"] = holdsStart ? [1, fx] : [fx, 1];
|
|
541
|
-
if (fy !== 1) target["scaleY"] = holdsStart ? [1, fy] : [fy, 1];
|
|
542
|
-
}
|
|
543
|
-
} else {
|
|
544
|
-
if (dx !== 0) {
|
|
545
|
-
target["x"] = leg(dx);
|
|
546
|
-
pairs.push(leg(dx));
|
|
547
|
-
}
|
|
548
|
-
if (dy !== 0) {
|
|
549
|
-
target["y"] = leg(dy);
|
|
550
|
-
pairs.push(leg(dy));
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
if (scaleMode) {} else if (step.size !== false) {
|
|
554
|
-
if (from.width !== to.width) {
|
|
555
|
-
target["width"] = [from.width, to.width];
|
|
556
|
-
pairs.push([from.width, to.width]);
|
|
557
|
-
}
|
|
558
|
-
if (from.height !== to.height) {
|
|
559
|
-
target["height"] = [from.height, to.height];
|
|
560
|
-
pairs.push([from.height, to.height]);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
if (!pairs.length) return null;
|
|
564
|
-
let longest = step.ms ?? 0;
|
|
565
|
-
if (step.ms === void 0) {
|
|
566
|
-
const spec = step.spring ?? DEFAULT_SPRING;
|
|
567
|
-
for (const [a, b] of pairs) longest = Math.max(longest, springDuration(a, b, spec));
|
|
568
|
-
}
|
|
569
|
-
return {
|
|
570
|
-
flight,
|
|
571
|
-
longest,
|
|
572
|
-
target,
|
|
573
|
-
velocity: hot ? gestureVelocity() : void 0
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
/** parse a computed rgb()/rgba() color into channels, or null */
|
|
577
|
-
function rgbOf(css) {
|
|
578
|
-
if (!css) return null;
|
|
579
|
-
const m = /^rgba?\(([\d.]+),\s*([\d.]+),\s*([\d.]+)(?:,\s*([\d.]+))?\)$/.exec(css);
|
|
580
|
-
if (!m) return null;
|
|
581
|
-
return {
|
|
582
|
-
a: m[4] === void 0 ? 1 : parseFloat(m[4]),
|
|
583
|
-
b: parseFloat(m[3]),
|
|
584
|
-
g: parseFloat(m[2]),
|
|
585
|
-
r: parseFloat(m[1])
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* A skin's EFFECTIVE color: its background alpha-blended against the ground
|
|
590
|
-
* it stood on — opacity turned into an actual color (§4.7). Null when the
|
|
591
|
-
* skin has no visible background (type over transparency crossfades as
|
|
592
|
-
* opacity, there is nothing to solidify) or wears a color this parser does
|
|
593
|
-
* not speak, in which case the crossfade stays a plain dissolve.
|
|
594
|
-
*/
|
|
595
|
-
function effective(paint, ground) {
|
|
596
|
-
const src = rgbOf(paint);
|
|
597
|
-
if (!src || src.a === 0) return null;
|
|
598
|
-
if (src.a === 1) return `rgb(${src.r}, ${src.g}, ${src.b})`;
|
|
599
|
-
const dst = rgbOf(ground);
|
|
600
|
-
if (!dst) return null;
|
|
601
|
-
const mix = (s, d) => Math.round(s * src.a + d * (1 - src.a));
|
|
602
|
-
return `rgb(${mix(src.r, dst.r)}, ${mix(src.g, dst.g)}, ${mix(src.b, dst.b)})`;
|
|
603
|
-
}
|
|
604
|
-
var tweenTransition = (step, ms) => ({
|
|
605
|
-
duration: ms / 1e3,
|
|
606
|
-
ease: step.ease ?? "easeInOut",
|
|
607
|
-
type: "tween",
|
|
608
|
-
..."times" in step && step.times ? { times: step.times } : {}
|
|
609
|
-
});
|
|
610
|
-
var springTransition = (spec) => ({
|
|
611
|
-
...spec ?? DEFAULT_SPRING,
|
|
612
|
-
type: "spring"
|
|
613
|
-
});
|
|
614
|
-
function resolveStep(step, cs, exclude) {
|
|
615
|
-
const sprites = cs.sprites(step.of ?? {}).filter((s) => !exclude || !exclude.has(s));
|
|
616
|
-
const delay = step.delay ?? 0;
|
|
617
|
-
const cues = [];
|
|
618
|
-
const stagger = step.stagger ?? 0;
|
|
619
|
-
/** text delivery: the sprite is split and the ladder happens INSIDE the
|
|
620
|
-
* step's span, so the sprites themselves are not laddered */
|
|
621
|
-
const splitting = (step.kind === "tween" || step.kind === "spring") && step.by !== void 0 && step.by !== "item";
|
|
622
|
-
const order = step.kind === "tween" || step.kind === "spring" ? step.order ?? "forward" : "forward";
|
|
623
|
-
const ranks = splitting ? [] : ladder(sprites.length, order);
|
|
624
|
-
let longest = 0;
|
|
625
|
-
let open = false;
|
|
626
|
-
for (const [index, sprite] of sprites.entries()) {
|
|
627
|
-
if ((step.kind === "camera" || step.kind === "camera3d" || step.kind === "tether" || step.of === void 0) && index > 0) break;
|
|
628
|
-
const offset = splitting ? 0 : stagger * (ranks[index] ?? index);
|
|
629
|
-
switch (step.kind) {
|
|
630
|
-
case "tween": {
|
|
631
|
-
const { target } = resolveTarget(step, sprite, cs);
|
|
632
|
-
if (step.times !== void 0) {
|
|
633
|
-
const times = step.times;
|
|
634
|
-
if (times.length < 2 || times[0] !== 0 || times[times.length - 1] !== 1 || times.some((time, i) => !Number.isFinite(time) || time < 0 || time > 1 || i > 0 && time <= times[i - 1]) || Object.values(target).some((value) => Array.isArray(value) && value.length !== times.length)) throw new Error("choreo: Tween times must increase from 0 to 1 and match every keyframe array");
|
|
635
|
-
}
|
|
636
|
-
if (Object.keys(target).length) {
|
|
637
|
-
const loop = step.repeat === Infinity;
|
|
638
|
-
const plays = loop ? 1 : 1 + (step.repeat ?? 0);
|
|
639
|
-
const length = step.ms * plays;
|
|
640
|
-
const transition = tweenTransition(step, step.ms);
|
|
641
|
-
if (step.repeat) {
|
|
642
|
-
transition["repeat"] = step.repeat;
|
|
643
|
-
transition["repeatType"] = step.repeatType ?? "loop";
|
|
644
|
-
}
|
|
645
|
-
cues.push({
|
|
646
|
-
delivery: splitting ? {
|
|
647
|
-
by: step.by,
|
|
648
|
-
order,
|
|
649
|
-
stagger
|
|
650
|
-
} : void 0,
|
|
651
|
-
duration: length,
|
|
652
|
-
kind: "tween",
|
|
653
|
-
loop: loop || void 0,
|
|
654
|
-
offset,
|
|
655
|
-
sprite,
|
|
656
|
-
target,
|
|
657
|
-
transition
|
|
658
|
-
});
|
|
659
|
-
longest = Math.max(longest, offset + (loop ? step.ms : length));
|
|
660
|
-
}
|
|
661
|
-
break;
|
|
662
|
-
}
|
|
663
|
-
case "spring": {
|
|
664
|
-
const { target, longest: d } = resolveTarget(step, sprite, cs);
|
|
665
|
-
if (Object.keys(target).length) {
|
|
666
|
-
cues.push({
|
|
667
|
-
delivery: splitting ? {
|
|
668
|
-
by: step.by,
|
|
669
|
-
order,
|
|
670
|
-
stagger
|
|
671
|
-
} : void 0,
|
|
672
|
-
duration: d,
|
|
673
|
-
kind: "spring",
|
|
674
|
-
offset,
|
|
675
|
-
sprite,
|
|
676
|
-
target,
|
|
677
|
-
transition: springTransition(step.spring)
|
|
678
|
-
});
|
|
679
|
-
longest = Math.max(longest, offset + d);
|
|
680
|
-
}
|
|
681
|
-
break;
|
|
682
|
-
}
|
|
683
|
-
case "move": {
|
|
684
|
-
const r = resolveMove(step, sprite, cs);
|
|
685
|
-
if (r) {
|
|
686
|
-
const transition = step.ms === void 0 ? springTransition(step.spring) : tweenTransition(step, step.ms);
|
|
687
|
-
if (r.velocity && step.ms === void 0) {
|
|
688
|
-
if (r.target["x"]) transition["x"] = {
|
|
689
|
-
...transition,
|
|
690
|
-
velocity: r.velocity.x
|
|
691
|
-
};
|
|
692
|
-
if (r.target["y"]) transition["y"] = {
|
|
693
|
-
...transition,
|
|
694
|
-
velocity: r.velocity.y
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
cues.push({
|
|
698
|
-
duration: r.longest,
|
|
699
|
-
flight: r.flight,
|
|
700
|
-
kind: "move",
|
|
701
|
-
offset,
|
|
702
|
-
sprite,
|
|
703
|
-
target: r.target,
|
|
704
|
-
transition
|
|
705
|
-
});
|
|
706
|
-
longest = Math.max(longest, offset + r.longest);
|
|
707
|
-
const cp = sprite.counterpart;
|
|
708
|
-
const swap = step.swap ?? "during";
|
|
709
|
-
if (cp && !cp.sent && swap !== "none" && sprite.final && cp.initial) {
|
|
710
|
-
const cpz = cs.measureZoom ?? 1;
|
|
711
|
-
const from = descale(cp.initial.page, cpz);
|
|
712
|
-
const to = descale(sprite.final.page, cpz);
|
|
713
|
-
const cpTarget = {};
|
|
714
|
-
if (step.size === "scale" || step.size === "crop") {
|
|
715
|
-
const crop = step.size === "crop";
|
|
716
|
-
const cpm = matchBoxes(cp.initial, sprite.final, from, to, cpz);
|
|
717
|
-
const mf = centreOf(cpm.from);
|
|
718
|
-
const mt = centreOf(cpm.to);
|
|
719
|
-
const anchor = centreOf(from);
|
|
720
|
-
const rx = cpm.to.width / (cpm.from.width || 1) || 1;
|
|
721
|
-
const ry = cpm.to.height / (cpm.from.height || 1) || 1;
|
|
722
|
-
const eu = rx;
|
|
723
|
-
const ex = crop ? eu : rx;
|
|
724
|
-
const ey = crop ? eu : ry;
|
|
725
|
-
const dxe = mt.x - anchor.x - ex * (mf.x - anchor.x);
|
|
726
|
-
const dye = crop ? cpm.to.y - anchor.y - ey * (cpm.from.y - anchor.y) : mt.y - anchor.y - ey * (mf.y - anchor.y);
|
|
727
|
-
if (dxe !== 0) cpTarget["x"] = [0, dxe];
|
|
728
|
-
if (dye !== 0) cpTarget["y"] = [0, dye];
|
|
729
|
-
if (crop) {
|
|
730
|
-
if (ex !== 1) cpTarget["scale"] = [1, ex];
|
|
731
|
-
const pre = (edge) => anchor.y + (edge - anchor.y - dye) / ex;
|
|
732
|
-
const clamp = (v) => Math.max(0, v);
|
|
733
|
-
const cb = clamp(from.y + from.height - pre(cpm.to.y + cpm.to.height));
|
|
734
|
-
if (cb > .5) cpTarget["clipPath"] = ["inset(0px 0px 0px 0px)", `inset(0px 0px ${cb.toFixed(2)}px 0px)`];
|
|
735
|
-
} else {
|
|
736
|
-
if (ex !== 1) cpTarget["scaleX"] = [1, ex];
|
|
737
|
-
if (ey !== 1) cpTarget["scaleY"] = [1, ey];
|
|
738
|
-
}
|
|
739
|
-
} else {
|
|
740
|
-
if (to.x !== from.x) cpTarget["x"] = [0, to.x - from.x];
|
|
741
|
-
if (to.y !== from.y) cpTarget["y"] = [0, to.y - from.y];
|
|
742
|
-
if (step.size !== false) {
|
|
743
|
-
if (from.width !== to.width) cpTarget["width"] = [from.width, to.width];
|
|
744
|
-
if (from.height !== to.height) cpTarget["height"] = [from.height, to.height];
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
if (Object.keys(cpTarget).length) cues.push({
|
|
748
|
-
duration: r.longest,
|
|
749
|
-
kind: "move",
|
|
750
|
-
offset,
|
|
751
|
-
sprite: cp,
|
|
752
|
-
target: cpTarget,
|
|
753
|
-
transition
|
|
754
|
-
});
|
|
755
|
-
if (swap === "during") {
|
|
756
|
-
const oldSkin = effective(cp.initial?.paint, cs.ground);
|
|
757
|
-
const newSkin = effective(sprite.final?.paint, cs.ground);
|
|
758
|
-
const fade = {
|
|
759
|
-
duration: r.longest / 1e3,
|
|
760
|
-
ease: "easeInOut"
|
|
761
|
-
};
|
|
762
|
-
if (oldSkin && newSkin) {
|
|
763
|
-
cues.push({
|
|
764
|
-
borrow: true,
|
|
765
|
-
duration: r.longest,
|
|
766
|
-
kind: "tween",
|
|
767
|
-
offset,
|
|
768
|
-
sprite,
|
|
769
|
-
target: { backgroundColor: [oldSkin, newSkin] },
|
|
770
|
-
transition: fade
|
|
771
|
-
});
|
|
772
|
-
cues.push({
|
|
773
|
-
duration: r.longest,
|
|
774
|
-
hold: {
|
|
775
|
-
fill: false,
|
|
776
|
-
values: { zIndex: 3 }
|
|
777
|
-
},
|
|
778
|
-
kind: "hold",
|
|
779
|
-
offset,
|
|
780
|
-
sprite: cp
|
|
781
|
-
});
|
|
782
|
-
} else cues.push({
|
|
783
|
-
duration: r.longest,
|
|
784
|
-
kind: "tween",
|
|
785
|
-
offset,
|
|
786
|
-
sprite,
|
|
787
|
-
target: { opacity: [0, 1] },
|
|
788
|
-
transition: fade
|
|
789
|
-
});
|
|
790
|
-
cues.push({
|
|
791
|
-
duration: r.longest,
|
|
792
|
-
kind: "tween",
|
|
793
|
-
offset,
|
|
794
|
-
sprite: cp,
|
|
795
|
-
target: { opacity: [1, 0] },
|
|
796
|
-
transition: fade
|
|
797
|
-
});
|
|
798
|
-
} else cues.push({
|
|
799
|
-
duration: r.longest,
|
|
800
|
-
hold: {
|
|
801
|
-
fill: false,
|
|
802
|
-
values: { opacity: 0 }
|
|
803
|
-
},
|
|
804
|
-
kind: "hold",
|
|
805
|
-
offset,
|
|
806
|
-
sprite
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
break;
|
|
811
|
-
}
|
|
812
|
-
case "hold": {
|
|
813
|
-
const values = {};
|
|
814
|
-
for (const key in step.props) values[key] = single(resolve(step.props[key], sprite, cs));
|
|
815
|
-
cues.push({
|
|
816
|
-
duration: step.ms ?? 0,
|
|
817
|
-
hold: {
|
|
818
|
-
fill: step.fill ?? false,
|
|
819
|
-
values
|
|
820
|
-
},
|
|
821
|
-
kind: "hold",
|
|
822
|
-
offset,
|
|
823
|
-
sprite
|
|
824
|
-
});
|
|
825
|
-
if (step.ms === void 0) open = true;
|
|
826
|
-
else longest = Math.max(longest, offset + step.ms);
|
|
827
|
-
break;
|
|
828
|
-
}
|
|
829
|
-
case "camera": {
|
|
830
|
-
const ms = step.ms ?? 600;
|
|
831
|
-
const fitting = step.fit !== void 0;
|
|
832
|
-
const aiming = step.aim !== void 0;
|
|
833
|
-
const aimQuery = fitting ? step.fit : step.aim ?? step.origin;
|
|
834
|
-
const originSprite = aimQuery ? cs.sprite(aimQuery) : null;
|
|
835
|
-
const box = originSprite?.final?.context ?? originSprite?.initial?.context;
|
|
836
|
-
const oz = cs.measureZoom ?? 1;
|
|
837
|
-
const origin = box ? {
|
|
838
|
-
x: (box.x + box.width / 2) / oz,
|
|
839
|
-
y: (box.y + box.height / 2) / oz
|
|
840
|
-
} : void 0;
|
|
841
|
-
let to = {
|
|
842
|
-
x: step.x,
|
|
843
|
-
y: step.y,
|
|
844
|
-
zoom: step.zoom
|
|
845
|
-
};
|
|
846
|
-
const by = step.panBy || step.zoomBy !== void 0 ? {
|
|
847
|
-
x: step.panBy?.x,
|
|
848
|
-
y: step.panBy?.y,
|
|
849
|
-
zoom: step.zoomBy
|
|
850
|
-
} : void 0;
|
|
851
|
-
if (aiming && !fitting) to = box && origin && cs.frame ? {
|
|
852
|
-
x: cs.frame.width / 2 - origin.x,
|
|
853
|
-
y: cs.frame.height / 2 - origin.y,
|
|
854
|
-
zoom: void 0
|
|
855
|
-
} : {
|
|
856
|
-
x: 0,
|
|
857
|
-
y: 0,
|
|
858
|
-
zoom: 1
|
|
859
|
-
};
|
|
860
|
-
if (fitting) if (box && origin && cs.frame) {
|
|
861
|
-
const zoom = step.zoom ?? (step.margin ?? .72) * Math.min(cs.frame.width * oz / box.width, cs.frame.height * oz / box.height);
|
|
862
|
-
to = {
|
|
863
|
-
x: cs.frame.width / 2 - origin.x,
|
|
864
|
-
y: cs.frame.height / 2 - origin.y,
|
|
865
|
-
zoom
|
|
866
|
-
};
|
|
867
|
-
} else to = {
|
|
868
|
-
x: 0,
|
|
869
|
-
y: 0,
|
|
870
|
-
zoom: 1
|
|
871
|
-
};
|
|
872
|
-
cues.push({
|
|
873
|
-
camera: {
|
|
874
|
-
by,
|
|
875
|
-
centre: cs.frame ? {
|
|
876
|
-
x: cs.frame.width / 2,
|
|
877
|
-
y: cs.frame.height / 2
|
|
878
|
-
} : void 0,
|
|
879
|
-
origin,
|
|
880
|
-
steady: step.steady ? cs.sprites(step.steady) : [],
|
|
881
|
-
to
|
|
882
|
-
},
|
|
883
|
-
duration: ms,
|
|
884
|
-
kind: "camera",
|
|
885
|
-
offset,
|
|
886
|
-
sprite,
|
|
887
|
-
transition: step.spring ? springTransition(step.spring) : {
|
|
888
|
-
duration: ms / 1e3,
|
|
889
|
-
ease: step.ease ?? "easeInOut"
|
|
890
|
-
}
|
|
891
|
-
});
|
|
892
|
-
longest = Math.max(longest, offset + ms);
|
|
893
|
-
break;
|
|
894
|
-
}
|
|
895
|
-
case "camera3d": {
|
|
896
|
-
const ms = step.ms ?? 600;
|
|
897
|
-
cues.push({
|
|
898
|
-
camera3d: {
|
|
899
|
-
by: step.by,
|
|
900
|
-
settle: step.settle,
|
|
901
|
-
tension: step.tension,
|
|
902
|
-
through: step.through,
|
|
903
|
-
to: {
|
|
904
|
-
dolly: step.dolly,
|
|
905
|
-
look: step.look,
|
|
906
|
-
pitch: step.pitch,
|
|
907
|
-
x: step.x,
|
|
908
|
-
y: step.y,
|
|
909
|
-
yaw: step.yaw
|
|
910
|
-
}
|
|
911
|
-
},
|
|
912
|
-
duration: ms,
|
|
913
|
-
kind: "camera3d",
|
|
914
|
-
offset,
|
|
915
|
-
sprite,
|
|
916
|
-
transition: step.spring ? springTransition(step.spring) : {
|
|
917
|
-
duration: ms / 1e3,
|
|
918
|
-
ease: step.ease ?? "easeInOut"
|
|
919
|
-
}
|
|
920
|
-
});
|
|
921
|
-
longest = Math.max(longest, offset + ms);
|
|
922
|
-
break;
|
|
923
|
-
}
|
|
924
|
-
case "tether":
|
|
925
|
-
cues.push({
|
|
926
|
-
duration: step.ms ?? 0,
|
|
927
|
-
kind: "tether",
|
|
928
|
-
offset,
|
|
929
|
-
sprite,
|
|
930
|
-
tether: {
|
|
931
|
-
from: cs.sprites(step.from)[0] ?? null,
|
|
932
|
-
name: step.name,
|
|
933
|
-
path: step.path,
|
|
934
|
-
to: cs.sprites(step.to)[0] ?? null
|
|
935
|
-
}
|
|
936
|
-
});
|
|
937
|
-
if (step.ms === void 0) open = true;
|
|
938
|
-
else longest = Math.max(longest, offset + step.ms);
|
|
939
|
-
break;
|
|
940
|
-
case "follow": {
|
|
941
|
-
for (const key of Object.keys(step.rest)) if (!DERIVABLE.has(key)) throw new Error(`choreo: c.Follow cannot drive '${key}' — a derived value is computed every frame, so it may only write transform, opacity and filter properties, never layout`);
|
|
942
|
-
const fz = cs.measureZoom ?? 1;
|
|
943
|
-
const inZ = (r) => ({
|
|
944
|
-
height: r.height / fz,
|
|
945
|
-
width: r.width / fz,
|
|
946
|
-
x: r.x / fz,
|
|
947
|
-
y: r.y / fz
|
|
948
|
-
});
|
|
949
|
-
const restBounds = sprite.final ?? sprite.initial;
|
|
950
|
-
if (!restBounds) break;
|
|
951
|
-
const followed = [];
|
|
952
|
-
for (const source of cs.sprites(step.to)) {
|
|
953
|
-
const toB = source.final ?? source.initial;
|
|
954
|
-
const fromB = source.initial ?? source.final;
|
|
955
|
-
if (toB && fromB) followed.push({
|
|
956
|
-
from: inZ(fromB.context),
|
|
957
|
-
sprite: source,
|
|
958
|
-
to: inZ(toB.context)
|
|
959
|
-
});
|
|
960
|
-
}
|
|
961
|
-
const ms = step.ms;
|
|
962
|
-
cues.push({
|
|
963
|
-
derive: {
|
|
964
|
-
read: step.read,
|
|
965
|
-
rest: step.rest,
|
|
966
|
-
restBox: inZ(restBounds.context),
|
|
967
|
-
sources: followed
|
|
968
|
-
},
|
|
969
|
-
duration: ms ?? 0,
|
|
970
|
-
kind: "follow",
|
|
971
|
-
offset,
|
|
972
|
-
sprite
|
|
973
|
-
});
|
|
974
|
-
if (ms === void 0) open = true;
|
|
975
|
-
else longest = Math.max(longest, offset + ms);
|
|
976
|
-
break;
|
|
977
|
-
}
|
|
978
|
-
case "scroll": {
|
|
979
|
-
const ms = step.ms ?? 420;
|
|
980
|
-
cues.push({
|
|
981
|
-
duration: ms,
|
|
982
|
-
kind: "scroll",
|
|
983
|
-
offset,
|
|
984
|
-
scroll: { align: step.align ?? "center" },
|
|
985
|
-
sprite
|
|
986
|
-
});
|
|
987
|
-
longest = Math.max(longest, offset + ms);
|
|
988
|
-
break;
|
|
989
|
-
}
|
|
990
|
-
case "raise":
|
|
991
|
-
cues.push({
|
|
992
|
-
duration: step.ms ?? 0,
|
|
993
|
-
kind: "raise",
|
|
994
|
-
offset,
|
|
995
|
-
raise: { shadow: step.shadow ?? false },
|
|
996
|
-
sprite
|
|
997
|
-
});
|
|
998
|
-
if (step.ms === void 0) open = true;
|
|
999
|
-
else longest = Math.max(longest, offset + step.ms);
|
|
1000
|
-
break;
|
|
1001
|
-
case "attach":
|
|
1002
|
-
cues.push({
|
|
1003
|
-
attach: {
|
|
1004
|
-
end: step.end ?? "hold",
|
|
1005
|
-
exact: step.exact ?? false,
|
|
1006
|
-
in: step.in ?? 0,
|
|
1007
|
-
rate: step.rate ?? 1,
|
|
1008
|
-
region: step.region
|
|
1009
|
-
},
|
|
1010
|
-
duration: step.ms,
|
|
1011
|
-
kind: "attach",
|
|
1012
|
-
offset,
|
|
1013
|
-
sprite
|
|
1014
|
-
});
|
|
1015
|
-
longest = Math.max(longest, offset + step.ms);
|
|
1016
|
-
break;
|
|
1017
|
-
case "wait":
|
|
1018
|
-
cues.push({
|
|
1019
|
-
duration: step.ms,
|
|
1020
|
-
kind: "wait",
|
|
1021
|
-
offset,
|
|
1022
|
-
sprite
|
|
1023
|
-
});
|
|
1024
|
-
longest = Math.max(longest, offset + step.ms);
|
|
1025
|
-
break;
|
|
1026
|
-
case "perform":
|
|
1027
|
-
cues.push({
|
|
1028
|
-
duration: 0,
|
|
1029
|
-
kind: "perform",
|
|
1030
|
-
offset,
|
|
1031
|
-
perform: {
|
|
1032
|
-
action: step.action,
|
|
1033
|
-
payload: step.payload,
|
|
1034
|
-
target: step.target
|
|
1035
|
-
},
|
|
1036
|
-
sprite
|
|
1037
|
-
});
|
|
1038
|
-
longest = Math.max(longest, offset);
|
|
1039
|
-
break;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
return {
|
|
1043
|
-
cues,
|
|
1044
|
-
duration: cues.length ? delay + longest : 0,
|
|
1045
|
-
open
|
|
1046
|
-
};
|
|
1047
|
-
}
|
|
1048
|
-
function compile(tree, cs) {
|
|
1049
|
-
const explicit = /* @__PURE__ */ new Set();
|
|
1050
|
-
const claim = (node) => {
|
|
1051
|
-
if (isGate(node)) return;
|
|
1052
|
-
if (isBlock(node)) {
|
|
1053
|
-
node.children.forEach(claim);
|
|
1054
|
-
return;
|
|
1055
|
-
}
|
|
1056
|
-
if (node.generic || node.kind !== "tween" && node.kind !== "spring" && node.kind !== "move" && node.kind !== "hold") return;
|
|
1057
|
-
const q = node.of;
|
|
1058
|
-
if (!(Array.isArray(q) ? q.length > 0 : q.id !== void 0 || q.role !== void 0 || q.type !== void 0)) return;
|
|
1059
|
-
for (const s of cs.sprites(q)) explicit.add(s);
|
|
1060
|
-
};
|
|
1061
|
-
tree.forEach(claim);
|
|
1062
|
-
const resolved = /* @__PURE__ */ new Map();
|
|
1063
|
-
const of = (step) => {
|
|
1064
|
-
let r = resolved.get(step);
|
|
1065
|
-
if (!r) {
|
|
1066
|
-
r = resolveStep(step, cs, step.generic ? explicit : void 0);
|
|
1067
|
-
resolved.set(step, r);
|
|
1068
|
-
}
|
|
1069
|
-
return r;
|
|
1070
|
-
};
|
|
1071
|
-
/**
|
|
1072
|
-
* A node's own length, anchoring aside — for a block, the span its
|
|
1073
|
-
* children occupy, which is what a `@name` on it promises to anyone who
|
|
1074
|
-
* anchors against it.
|
|
1075
|
-
*/
|
|
1076
|
-
const extent = (node) => {
|
|
1077
|
-
if (isGate(node)) return 0;
|
|
1078
|
-
if (!isBlock(node)) return of(node).duration;
|
|
1079
|
-
return node.kind === "sequence" ? node.children.reduce((sum, c) => sum + measure(c), 0) : node.children.reduce((max, c) => Math.max(max, measure(c)), 0);
|
|
1080
|
-
};
|
|
1081
|
-
/** what a node contributes to its parent's flow */
|
|
1082
|
-
const measure = (node) => {
|
|
1083
|
-
if (isGate(node)) return 0;
|
|
1084
|
-
if (node.at) return 0;
|
|
1085
|
-
return isBlock(node) ? (node.delay ?? 0) + extent(node) : of(node).duration;
|
|
1086
|
-
};
|
|
1087
|
-
const out = [];
|
|
1088
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1089
|
-
const checkNames = (node) => {
|
|
1090
|
-
if (isGate(node)) return;
|
|
1091
|
-
if (node.name) {
|
|
1092
|
-
if (seen.has(node.name)) throw new Error(`choreo: two steps named '${node.name}'`);
|
|
1093
|
-
seen.add(node.name);
|
|
1094
|
-
}
|
|
1095
|
-
if (isBlock(node)) node.children.forEach(checkNames);
|
|
1096
|
-
};
|
|
1097
|
-
tree.forEach(checkNames);
|
|
1098
|
-
/** where each named step landed: when it starts (delay spent) and how long it plays */
|
|
1099
|
-
const names = /* @__PURE__ */ new Map();
|
|
1100
|
-
const gates = [];
|
|
1101
|
-
/**
|
|
1102
|
-
* A pause is a total order (§4.1): a gate may only stand in a sequence
|
|
1103
|
-
* that no parallel contains — including the implicit parallel that is the
|
|
1104
|
-
* region's root when it has more than one top-level node.
|
|
1105
|
-
*/
|
|
1106
|
-
const forbidGates = (node) => {
|
|
1107
|
-
if (isGate(node)) throw new Error("choreo: a gate inside a parallel has no meaning — a pause is a total order; only an uncontained sequence can hold one");
|
|
1108
|
-
if (isBlock(node)) node.children.forEach(forbidGates);
|
|
1109
|
-
};
|
|
1110
|
-
/**
|
|
1111
|
-
* The whole score's span — computed BEFORE anything is placed, because an
|
|
1112
|
-
* open step's window depends on it.
|
|
1113
|
-
*
|
|
1114
|
-
* A score of nothing but open steps measures zero, and an open step's
|
|
1115
|
-
* window is "the enclosing block's span" — so the annotation the author
|
|
1116
|
-
* asked to be simply ON compiled to a zero-length run that ended on the
|
|
1117
|
-
* frame it was born. That is not a short wire, it is no wire; the app
|
|
1118
|
-
* that hit it wrote `ms: 3_600_000` to get an hour of clock out of a
|
|
1119
|
-
* step whose real lifetime is the scene's. So a score with no length of
|
|
1120
|
-
* its own does not borrow zero: its open cues STAND (§4.6), and the run
|
|
1121
|
-
* holds them until it is cancelled or replaced.
|
|
1122
|
-
*/
|
|
1123
|
-
const root = measure({
|
|
1124
|
-
children: tree,
|
|
1125
|
-
kind: "parallel"
|
|
1126
|
-
});
|
|
1127
|
-
const standingScore = root === 0;
|
|
1128
|
-
/** did any cue actually take the standing window? */
|
|
1129
|
-
let stood = false;
|
|
1130
|
-
/** span: the time a hold without @duration is allowed to last from `start` */
|
|
1131
|
-
const place = (node, start, span) => {
|
|
1132
|
-
if (isGate(node)) {
|
|
1133
|
-
gates.push({
|
|
1134
|
-
at: start,
|
|
1135
|
-
auto: node.ms
|
|
1136
|
-
});
|
|
1137
|
-
return;
|
|
1138
|
-
}
|
|
1139
|
-
/** where an anchored node begins — the same arithmetic for a step and a block */
|
|
1140
|
-
const anchored = (ref) => {
|
|
1141
|
-
const target = names.get(ref.anchor);
|
|
1142
|
-
if (!target) throw new Error(`choreo: @at names '${ref.anchor}', which is not a step above this one — anchors point up the score`);
|
|
1143
|
-
return ref.edge === "end" ? target.start + target.duration + (ref.delay ?? 0) * 1e3 : target.start + (ref.progress ?? 0) * target.duration;
|
|
1144
|
-
};
|
|
1145
|
-
if (!isBlock(node)) {
|
|
1146
|
-
const r = of(node);
|
|
1147
|
-
const delay = node.delay ?? 0;
|
|
1148
|
-
let base = start;
|
|
1149
|
-
if (node.at) {
|
|
1150
|
-
if (r.open) throw new Error("choreo: an anchored hold needs its own @duration — lifted out of its block, it has no span to borrow");
|
|
1151
|
-
base = anchored(node.at);
|
|
1152
|
-
}
|
|
1153
|
-
if (node.name) names.set(node.name, {
|
|
1154
|
-
duration: Math.max(0, r.duration - delay),
|
|
1155
|
-
start: base + delay
|
|
1156
|
-
});
|
|
1157
|
-
for (const cue of r.cues) {
|
|
1158
|
-
const { offset, ...rest } = cue;
|
|
1159
|
-
const borrows = r.open && (cue.kind === "hold" || cue.kind === "raise" || cue.kind === "tether" || cue.kind === "follow");
|
|
1160
|
-
if (borrows && standingScore) stood = true;
|
|
1161
|
-
out.push({
|
|
1162
|
-
...rest,
|
|
1163
|
-
duration: borrows ? standingScore ? Infinity : Math.max(0, span - delay - offset) : cue.duration,
|
|
1164
|
-
standing: borrows && standingScore ? true : void 0,
|
|
1165
|
-
start: base + delay + offset
|
|
1166
|
-
});
|
|
1167
|
-
}
|
|
1168
|
-
return;
|
|
1169
|
-
}
|
|
1170
|
-
const total = extent(node);
|
|
1171
|
-
const from = (node.at ? anchored(node.at) : start) + (node.delay ?? 0);
|
|
1172
|
-
if (node.name) names.set(node.name, {
|
|
1173
|
-
duration: total,
|
|
1174
|
-
start: from
|
|
1175
|
-
});
|
|
1176
|
-
if (node.kind === "sequence") {
|
|
1177
|
-
let offset = 0;
|
|
1178
|
-
for (const child of node.children) {
|
|
1179
|
-
place(child, from + offset, total - offset);
|
|
1180
|
-
offset += measure(child);
|
|
1181
|
-
}
|
|
1182
|
-
return;
|
|
1183
|
-
}
|
|
1184
|
-
node.children.forEach(forbidGates);
|
|
1185
|
-
for (const child of node.children) place(child, from, total);
|
|
1186
|
-
};
|
|
1187
|
-
if (tree.length > 1) tree.forEach(forbidGates);
|
|
1188
|
-
for (const node of tree) place(node, 0, root);
|
|
1189
|
-
gates.sort((a, b) => a.at - b.at);
|
|
1190
|
-
const derived = out.filter((cue) => cue.derive);
|
|
1191
|
-
if (!derived.length) return {
|
|
1192
|
-
cues: out,
|
|
1193
|
-
gates,
|
|
1194
|
-
open: stood
|
|
1195
|
-
};
|
|
1196
|
-
const nameOf = (sprite) => sprite.id ?? sprite.role ?? "a sprite";
|
|
1197
|
-
const drivenBy = /* @__PURE__ */ new Map();
|
|
1198
|
-
for (const cue of derived) drivenBy.set(cue.sprite, cue);
|
|
1199
|
-
for (const cue of derived) for (const source of cue.derive.sources) if (drivenBy.has(source.sprite)) throw new Error(`choreo: c.Follow on '${nameOf(cue.sprite)}' reads '${nameOf(source.sprite)}', which is itself derived — a follower may not follow a follower`);
|
|
1200
|
-
return {
|
|
1201
|
-
cues: [...out.filter((cue) => !cue.derive), ...derived],
|
|
1202
|
-
gates,
|
|
1203
|
-
open: stood
|
|
1204
|
-
};
|
|
1205
|
-
}
|
|
1206
|
-
/**
|
|
1207
|
-
* A replacement pass's continuity cue (§3.1): the prior run was driving
|
|
1208
|
-
* this sprite through space and the new score does not name it. Unnamed
|
|
1209
|
-
* it would be released to its rest in one frame — the whole-bay snap —
|
|
1210
|
-
* so the region completes the score: one shape-matched move from the
|
|
1211
|
-
* painted box (which is what a mid-flight sprite's `initial` IS, by
|
|
1212
|
-
* design) to its rest. Transform-only, so a continuation can never
|
|
1213
|
-
* reflow the scene it is tidying; on the interrupted cue's own spring
|
|
1214
|
-
* when it had one, so the carry-on keeps the flight's character.
|
|
1215
|
-
*/
|
|
1216
|
-
function continuation(sprite, cs, inherited) {
|
|
1217
|
-
const r = resolveMove({
|
|
1218
|
-
kind: "move",
|
|
1219
|
-
of: {},
|
|
1220
|
-
size: "scale"
|
|
1221
|
-
}, sprite, cs);
|
|
1222
|
-
if (!r) return null;
|
|
1223
|
-
const springy = inherited && (inherited["type"] === "spring" || "stiffness" in inherited || "visualDuration" in inherited || "bounce" in inherited);
|
|
1224
|
-
return {
|
|
1225
|
-
duration: r.longest,
|
|
1226
|
-
flight: r.flight,
|
|
1227
|
-
kind: "move",
|
|
1228
|
-
sprite,
|
|
1229
|
-
start: 0,
|
|
1230
|
-
target: r.target,
|
|
1231
|
-
transition: springy ? inherited : springTransition(void 0)
|
|
1232
|
-
};
|
|
1233
|
-
}
|
|
1234
|
-
/**
|
|
1235
|
-
* A replacement pass's continuity cue for a cut-short tween (§3.1): the
|
|
1236
|
-
* prior run was taking these values (an opacity, mostly) somewhere and the
|
|
1237
|
-
* new score does not. Stopped where they stood they would stay there for
|
|
1238
|
-
* good — a fade-in frozen at a few percent — so the region carries each on
|
|
1239
|
-
* from its painted value to where it was going, over the time it had left,
|
|
1240
|
-
* after the delay it had left (a staggered arrival that had not begun).
|
|
1241
|
-
*/
|
|
1242
|
-
function fadeOn(sprite, to, remaining, delay = 0) {
|
|
1243
|
-
return {
|
|
1244
|
-
duration: remaining,
|
|
1245
|
-
kind: "tween",
|
|
1246
|
-
sprite,
|
|
1247
|
-
start: delay,
|
|
1248
|
-
target: { ...to },
|
|
1249
|
-
transition: {
|
|
1250
|
-
duration: remaining / 1e3,
|
|
1251
|
-
ease: "easeOut"
|
|
1252
|
-
}
|
|
1253
|
-
};
|
|
1254
|
-
}
|
|
1255
|
-
/**
|
|
1256
|
-
* Whether two compiled scores are the SAME statement — used by the region
|
|
1257
|
-
* to keep an in-flight run when an unrelated render replays the pass (the
|
|
1258
|
-
* render detector is volatile by design, so on a busy page every region
|
|
1259
|
-
* re-passes on every app render; a neighbouring demo writing tracked state
|
|
1260
|
-
* per frame must not restart this region's clock).
|
|
1261
|
-
*
|
|
1262
|
-
* The comparison is deliberately conservative. A FLIGHT is measured off the
|
|
1263
|
-
* page and is not comparable by value: any cue carrying one makes the scores
|
|
1264
|
-
* different, and the pass replays exactly as it always did. Values that ARE
|
|
1265
|
-
* comparable (targets, transitions, delivery plans, holds, camera aims)
|
|
1266
|
-
* compare structurally, so an edit that retimes or re-aims anything replays.
|
|
1267
|
-
*
|
|
1268
|
-
* Tethers, raises and scrolls used to be lumped in with flights, and that was
|
|
1269
|
-
* wrong in a way that only showed up on standing annotations: a wire that is
|
|
1270
|
-
* simply ON was recompiled to the identical statement on every pass and, being
|
|
1271
|
-
* declared different every time, had its run torn down and rebuilt — the path
|
|
1272
|
-
* element removed from the layer and a new one appended, sixty times a second
|
|
1273
|
-
* on a busy page. None of the three carries measured geometry in its cue: a
|
|
1274
|
-
* tether is two sprites and a function, a raise is a sprite and a flag, a
|
|
1275
|
-
* scroll is a sprite and an alignment. They compare by IDENTITY, which is
|
|
1276
|
-
* exactly what "the same statement" means for them — and it matters most for
|
|
1277
|
-
* the scroll, where replacing the cue is a visible restart of the scroll.
|
|
1278
|
-
*/
|
|
1279
|
-
function sameScore(a, b) {
|
|
1280
|
-
return a.length === b.length && a.every((cue, i) => sameCue(cue, b[i]));
|
|
1281
|
-
}
|
|
1282
|
-
function sameCue(a, b) {
|
|
1283
|
-
if (a.kind !== b.kind || a.sprite.node !== b.sprite.node || a.start !== b.start || a.duration !== b.duration || (a.loop ?? false) !== (b.loop ?? false)) return false;
|
|
1284
|
-
if (a.flight || b.flight) return false;
|
|
1285
|
-
if (a.tether || b.tether) {
|
|
1286
|
-
if (!a.tether || !b.tether || a.tether.from?.node !== b.tether.from?.node || a.tether.to?.node !== b.tether.to?.node || a.tether.path !== b.tether.path || a.tether.name !== b.tether.name) return false;
|
|
1287
|
-
}
|
|
1288
|
-
if (a.raise || b.raise) {
|
|
1289
|
-
if (!a.raise || !b.raise || a.raise.shadow !== b.raise.shadow) return false;
|
|
1290
|
-
}
|
|
1291
|
-
if (a.attach || b.attach) {
|
|
1292
|
-
if (!a.attach || !b.attach || a.attach.region !== b.attach.region || a.attach.in !== b.attach.in || a.attach.rate !== b.attach.rate || a.attach.end !== b.attach.end) return false;
|
|
1293
|
-
}
|
|
1294
|
-
if (a.scroll || b.scroll) {
|
|
1295
|
-
if (!a.scroll || !b.scroll || a.scroll.align !== b.scroll.align) return false;
|
|
1296
|
-
}
|
|
1297
|
-
const plain = (v) => JSON.stringify(v ?? null);
|
|
1298
|
-
const cam = (c) => c ? {
|
|
1299
|
-
centre: c.centre ?? null,
|
|
1300
|
-
origin: c.origin ?? null,
|
|
1301
|
-
steady: c.steady.length,
|
|
1302
|
-
to: c.to
|
|
1303
|
-
} : null;
|
|
1304
|
-
return plain(a.target) === plain(b.target) && plain(a.transition) === plain(b.transition) && plain(a.delivery) === plain(b.delivery) && plain(a.hold) === plain(b.hold) && plain(cam(a.camera)) === plain(cam(b.camera)) && plain(a.camera3d) === plain(b.camera3d);
|
|
1305
|
-
}
|
|
1306
|
-
//#endregion
|
|
1307
|
-
//#region ../choreo/src/far.ts
|
|
1308
|
-
/**
|
|
1309
|
-
* Far matching — one identity, two regions.
|
|
1310
|
-
*
|
|
1311
|
-
* A `<Choreo>` is a scene: it reconciles its own participants and nothing else.
|
|
1312
|
-
* That is the point of nesting, and it is why an element that leaves one region
|
|
1313
|
-
* and appears in another looks like a death and an unrelated birth rather than
|
|
1314
|
-
* one continuous flight.
|
|
1315
|
-
*
|
|
1316
|
-
* Ember Animated calls the two halves `sentSprites` and `receivedSprites` and
|
|
1317
|
-
* pairs them at a `farMatch` rendezvous — every animator that is starting this
|
|
1318
|
-
* pass parks, they all wake together, and each reads the others' lists. The
|
|
1319
|
-
* legacy boxel-motion described this but never built it.
|
|
1320
|
-
*
|
|
1321
|
-
* The rendezvous here is a barrier in the render pass itself, not a timed one.
|
|
1322
|
-
* Every region that will animate this pass announces itself while Glimmer is
|
|
1323
|
-
* still rendering (`join`), the first announcement books one post-render
|
|
1324
|
-
* callback for all of them, and that callback runs three phases in order:
|
|
1325
|
-
*
|
|
1326
|
-
* 1. MEASURE — every region builds its changeset. Nobody has run anything,
|
|
1327
|
-
* so nobody's in-flight values are polluting anybody else's measurement.
|
|
1328
|
-
* 2. MATCH — inserted ids are paired against removed ids in OTHER regions.
|
|
1329
|
-
* 3. RUN — every region compiles and plays its own timeline.
|
|
1330
|
-
*
|
|
1331
|
-
* All three are synchronous, so no frame is painted between a region measuring
|
|
1332
|
-
* and a region pinning its start values. That matters: the whole reason cues
|
|
1333
|
-
* pin synchronously is that one frame of the destination layout is visible
|
|
1334
|
-
* otherwise, and a barrier that yielded would hand that frame back.
|
|
1335
|
-
*
|
|
1336
|
-
* The pairing itself is the same shape as the counterpart matching a region
|
|
1337
|
-
* already does within itself. The receiving element is the one that flies: it
|
|
1338
|
-
* takes the sender's bounds as an `initial` it never had, and the sender is
|
|
1339
|
-
* dropped rather than orphaned, because the thing it would animate is already
|
|
1340
|
-
* being animated somewhere else.
|
|
1341
|
-
*
|
|
1342
|
-
* Bounds cross the boundary in PAGE space, which is the only space the two
|
|
1343
|
-
* regions agree on — a region-relative measurement means nothing to a region
|
|
1344
|
-
* somewhere else on the page.
|
|
1345
|
-
*/
|
|
1346
|
-
/** one region's measured pass, waiting for the others before it runs */
|
|
1347
|
-
var intents = /* @__PURE__ */ new Set();
|
|
1348
|
-
var booked = false;
|
|
1349
|
-
/** a seam for the region to book the callback without far.ts importing the scheduler */
|
|
1350
|
-
var schedule = (fn) => fn();
|
|
1351
|
-
function setPassScheduler(fn) {
|
|
1352
|
-
schedule = fn;
|
|
1353
|
-
}
|
|
1354
|
-
/**
|
|
1355
|
-
* Announce that this region has a pass coming. Called while Glimmer is still
|
|
1356
|
-
* rendering, so by the time the barrier runs, every region taking part in this
|
|
1357
|
-
* pass is known — which is what lets the match be synchronous.
|
|
1358
|
-
*/
|
|
1359
|
-
function join(host) {
|
|
1360
|
-
intents.add(host);
|
|
1361
|
-
if (!booked) {
|
|
1362
|
-
booked = true;
|
|
1363
|
-
schedule(runBarrier);
|
|
1364
|
-
}
|
|
1365
|
-
}
|
|
1366
|
-
function leave(host) {
|
|
1367
|
-
intents.delete(host);
|
|
1368
|
-
}
|
|
1369
|
-
/** a booked barrier is work outstanding: nothing has measured yet */
|
|
1370
|
-
registerBusyProbe(() => booked && "far-match barrier booked");
|
|
1371
|
-
/**
|
|
1372
|
-
* Drop a barrier that will never run. A test torn down between `join` and the
|
|
1373
|
-
* post-render callback leaves a destroyed region parked in `intents`, and the
|
|
1374
|
-
* next test's first pass would try to measure it. `setupChoreo(hooks)` runs
|
|
1375
|
-
* this before and after every test.
|
|
1376
|
-
*/
|
|
1377
|
-
function resetBarrier() {
|
|
1378
|
-
intents.clear();
|
|
1379
|
-
booked = false;
|
|
1380
|
-
}
|
|
1381
|
-
/** mount everything rendered this pass before ANY region measures */
|
|
1382
|
-
var beforeMeasure = () => {};
|
|
1383
|
-
function setBeforeMeasure(fn) {
|
|
1384
|
-
beforeMeasure = fn;
|
|
1385
|
-
}
|
|
1386
|
-
/**
|
|
1387
|
-
* SETTLE: state that the pass implies but that is not markup, settled after
|
|
1388
|
-
* this pass's mounts and before any region measures. A scroll owner (a list
|
|
1389
|
-
* that keeps its scroll at the newest content, or holds a row in place while
|
|
1390
|
-
* rows above it change) holds its anchor here: a scroll position is state,
|
|
1391
|
-
* so it lands in the same pass as the change that moved it, and every region
|
|
1392
|
-
* measures the page as the reader will see it. An element the scroll kept
|
|
1393
|
-
* still then reads as not moved and gets no motion; only what really moved
|
|
1394
|
-
* on screen does.
|
|
1395
|
-
*
|
|
1396
|
-
* A settler only runs inside a barrier, and a barrier runs only when a
|
|
1397
|
-
* region joins a pass: with no region mounted, every region idle, or motion
|
|
1398
|
-
* off, no settler runs. So the owner sets its scroll through its own path as
|
|
1399
|
-
* well (on render or on resize, as it would with no Choreo on the page), and
|
|
1400
|
-
* the settler only makes that happen before regions measure. State never
|
|
1401
|
-
* depends on a settler (ADR 007 §1.1).
|
|
1402
|
-
*
|
|
1403
|
-
* Settlers run in registration order; one that throws is reported and the
|
|
1404
|
-
* pass goes on. Returns the unregister function.
|
|
1405
|
-
*/
|
|
1406
|
-
var settlers = /* @__PURE__ */ new Set();
|
|
1407
|
-
function registerSettle(fn) {
|
|
1408
|
-
settlers.add(fn);
|
|
1409
|
-
return () => {
|
|
1410
|
-
settlers.delete(fn);
|
|
1411
|
-
};
|
|
1412
|
-
}
|
|
1413
|
-
function runBarrier() {
|
|
1414
|
-
booked = false;
|
|
1415
|
-
const hosts = [...intents];
|
|
1416
|
-
intents.clear();
|
|
1417
|
-
beforeMeasure();
|
|
1418
|
-
for (const settle of [...settlers]) try {
|
|
1419
|
-
settle();
|
|
1420
|
-
} catch (e) {
|
|
1421
|
-
queueMicrotask(() => {
|
|
1422
|
-
throw e;
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
1425
|
-
const passes = [];
|
|
1426
|
-
for (const host of hosts) {
|
|
1427
|
-
const pass = host.measurePass();
|
|
1428
|
-
if (pass) passes.push(pass);
|
|
1429
|
-
}
|
|
1430
|
-
if (passes.length > 1) match(passes);
|
|
1431
|
-
for (const pass of passes) pass.host.finishPass(pass);
|
|
1432
|
-
}
|
|
1433
|
-
var deltaOf = (s) => s.initial && s.final ? {
|
|
1434
|
-
height: s.final.page.height - s.initial.page.height,
|
|
1435
|
-
width: s.final.page.width - s.initial.page.width,
|
|
1436
|
-
x: s.final.page.x - s.initial.page.x,
|
|
1437
|
-
y: s.final.page.y - s.initial.page.y
|
|
1438
|
-
} : void 0;
|
|
1439
|
-
/**
|
|
1440
|
-
* Pair an id inserted in one region against the same id removed in another.
|
|
1441
|
-
*
|
|
1442
|
-
* The receiver becomes a kept sprite carrying the sender as its counterpart —
|
|
1443
|
-
* exactly what same-region counterpart matching produces, so every step that
|
|
1444
|
-
* already understands `kept` and `counterpart` works across the boundary with
|
|
1445
|
-
* no further teaching. The sender is flagged `sent` so its own region knows to
|
|
1446
|
-
* let it go quietly instead of playing a removal for it.
|
|
1447
|
-
*/
|
|
1448
|
-
function match(passes) {
|
|
1449
|
-
for (const pass of passes) for (const s of pass.inserted) {
|
|
1450
|
-
if (s.id === null || s.counterpart) continue;
|
|
1451
|
-
for (const other of passes) {
|
|
1452
|
-
if (other === pass) continue;
|
|
1453
|
-
const sender = other.removed.find((r) => r.id === s.id && !r.counterpart && !r.sent);
|
|
1454
|
-
if (sender) {
|
|
1455
|
-
sender.sent = true;
|
|
1456
|
-
s.counterpart = sender;
|
|
1457
|
-
s.initial = sender.initial;
|
|
1458
|
-
s.type = "kept";
|
|
1459
|
-
s.delta = deltaOf(s);
|
|
1460
|
-
break;
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
//#endregion
|
|
1466
|
-
//#region ../choreo/src/registry.ts
|
|
1467
|
-
/**
|
|
1468
|
-
* A region is a participant host (glimmer-motion/participant): its root
|
|
1469
|
-
* renders `data-motion-host` beside `data-choreo`, and registering a region
|
|
1470
|
-
* here registers it as that element's participant host too, so the {{motion}}
|
|
1471
|
-
* elements inside join it. The lookups below are Choreo's own, for code that
|
|
1472
|
-
* already speaks in regions.
|
|
1473
|
-
*/
|
|
1474
|
-
/** anything that can put a node on a region's timeline — a step component, or a lane from outside */
|
|
1475
|
-
var hosts = /* @__PURE__ */ new WeakMap();
|
|
1476
|
-
/** regions rendered with `@id`, so an attachment can name one without a DOM query per frame */
|
|
1477
|
-
var hostsById = /* @__PURE__ */ new Map();
|
|
1478
|
-
function setChoreoHost(el, host) {
|
|
1479
|
-
const id = el.getAttribute("data-choreo");
|
|
1480
|
-
if (host) {
|
|
1481
|
-
hosts.set(el, host);
|
|
1482
|
-
setParticipantHost(el, host);
|
|
1483
|
-
if (id) hostsById.set(id, host);
|
|
1484
|
-
} else {
|
|
1485
|
-
const mine = hosts.get(el);
|
|
1486
|
-
hosts.delete(el);
|
|
1487
|
-
setParticipantHost(el, void 0);
|
|
1488
|
-
if (id && mine && hostsById.get(id) === mine) hostsById.delete(id);
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
function closestChoreo(el) {
|
|
1492
|
-
const root = el.parentElement?.closest("[data-choreo]");
|
|
1493
|
-
return root ? hosts.get(root) : void 0;
|
|
1494
|
-
}
|
|
1495
|
-
/** the host of a region element itself (not an ancestor's) */
|
|
1496
|
-
function choreoHostAt(el) {
|
|
1497
|
-
return hosts.get(el);
|
|
1498
|
-
}
|
|
1499
|
-
/** the host of the region rendered with `@id` — a lane's way of naming the region it plays in */
|
|
1500
|
-
function choreoHostById(id) {
|
|
1501
|
-
return hostsById.get(id);
|
|
1502
|
-
}
|
|
1503
|
-
//#endregion
|
|
1504
|
-
//#region ../choreo/src/deliver.ts
|
|
1505
|
-
/**
|
|
1506
|
-
* Text delivery — `@by='word' | 'character' | 'paragraph'` (§4.3).
|
|
1507
|
-
*
|
|
1508
|
-
* The split is a run-time costume, not a render: the sprite's own text
|
|
1509
|
-
* nodes are lifted out whole and kept (Glimmer still owns them — a tracked
|
|
1510
|
-
* update mid-flight writes into the detached node and comes back at
|
|
1511
|
-
* restore), stand-in spans deliver the animation, and the restore puts the
|
|
1512
|
-
* original nodes back exactly where they were. Assistive tech reads the
|
|
1513
|
-
* full text throughout: the container carries it as a label while the
|
|
1514
|
-
* chopped-up copy is hidden.
|
|
1515
|
-
*
|
|
1516
|
-
* Slots play on the platform's own animations (WAAPI), not the engine:
|
|
1517
|
-
* they are ephemeral, their schedule is computed once, and a spring's
|
|
1518
|
-
* clock arrives pre-sampled through the generator — the same shape the
|
|
1519
|
-
* native driver uses for everything.
|
|
1520
|
-
*/
|
|
1521
|
-
var spanFor = (text) => {
|
|
1522
|
-
const span = document.createElement("span");
|
|
1523
|
-
span.textContent = text;
|
|
1524
|
-
span.setAttribute("aria-hidden", "true");
|
|
1525
|
-
span.style.display = "inline-block";
|
|
1526
|
-
span.style.whiteSpace = "pre";
|
|
1527
|
-
return span;
|
|
1528
|
-
};
|
|
1529
|
-
function textNodesOf(root) {
|
|
1530
|
-
const out = [];
|
|
1531
|
-
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
1532
|
-
for (let n = walker.nextNode(); n; n = walker.nextNode()) if ((n.textContent ?? "").length) out.push(n);
|
|
1533
|
-
return out;
|
|
1534
|
-
}
|
|
1535
|
-
function unitsOf(text, by) {
|
|
1536
|
-
if (by === "character") return Array.from(text);
|
|
1537
|
-
return text.match(/\S+\s*|\s+/g) ?? [];
|
|
1538
|
-
}
|
|
1539
|
-
function split(el, by) {
|
|
1540
|
-
if (by === "paragraph") {
|
|
1541
|
-
const slots = Array.from(el.children).filter((c) => c instanceof HTMLElement);
|
|
1542
|
-
if (!slots.length) throw new Error("choreo: @by='paragraph' needs child elements to deliver");
|
|
1543
|
-
return {
|
|
1544
|
-
restore() {},
|
|
1545
|
-
slots: slots.map((s) => ({ el: s }))
|
|
1546
|
-
};
|
|
1547
|
-
}
|
|
1548
|
-
const originals = textNodesOf(el);
|
|
1549
|
-
if (!originals.length) throw new Error(`choreo: @by='${by}' needs text to deliver`);
|
|
1550
|
-
const ws = getComputedStyle(el).whiteSpace;
|
|
1551
|
-
const collapsing = ws === "normal" || ws === "nowrap" || ws === "pre-line";
|
|
1552
|
-
const textOf = (node, index) => {
|
|
1553
|
-
let text = node.textContent ?? "";
|
|
1554
|
-
if (collapsing) {
|
|
1555
|
-
text = text.replace(/\s+/g, " ");
|
|
1556
|
-
if (index === 0) text = text.replace(/^ /, "");
|
|
1557
|
-
if (index === originals.length - 1) text = text.replace(/ $/, "");
|
|
1558
|
-
}
|
|
1559
|
-
return text;
|
|
1560
|
-
};
|
|
1561
|
-
const label = el.getAttribute("aria-label");
|
|
1562
|
-
el.setAttribute("aria-label", el.textContent ?? "");
|
|
1563
|
-
const slots = [];
|
|
1564
|
-
const undo = [];
|
|
1565
|
-
for (const [index, node] of originals.entries()) {
|
|
1566
|
-
const parent = node.parentNode;
|
|
1567
|
-
const marker = document.createComment("choreo-delivery");
|
|
1568
|
-
parent.replaceChild(marker, node);
|
|
1569
|
-
const spans = [];
|
|
1570
|
-
for (const unit of unitsOf(textOf(node, index), by)) {
|
|
1571
|
-
const span = spanFor(unit);
|
|
1572
|
-
parent.insertBefore(span, marker);
|
|
1573
|
-
spans.push(span);
|
|
1574
|
-
if (by === "character" && /^\s+$/.test(unit)) continue;
|
|
1575
|
-
slots.push({ el: span });
|
|
1576
|
-
}
|
|
1577
|
-
undo.push(() => {
|
|
1578
|
-
for (const span of spans) span.remove();
|
|
1579
|
-
marker.parentNode?.replaceChild(node, marker);
|
|
1580
|
-
});
|
|
1581
|
-
}
|
|
1582
|
-
let restored = false;
|
|
1583
|
-
return {
|
|
1584
|
-
restore() {
|
|
1585
|
-
if (restored) return;
|
|
1586
|
-
restored = true;
|
|
1587
|
-
undo.reverse().forEach((fn) => fn());
|
|
1588
|
-
if (label === null) el.removeAttribute("aria-label");
|
|
1589
|
-
else el.setAttribute("aria-label", label);
|
|
1590
|
-
},
|
|
1591
|
-
slots
|
|
1592
|
-
};
|
|
1593
|
-
}
|
|
1594
|
-
/**
|
|
1595
|
-
* `@stagger` seconds between starts, window = what remains of the span; with
|
|
1596
|
-
* no stagger, the Build Order demo's policy: a 0.55-of-span window with the
|
|
1597
|
-
* starts distributed across the remainder.
|
|
1598
|
-
*/
|
|
1599
|
-
function windows(n, span, stagger) {
|
|
1600
|
-
if (n <= 1 || span <= 0) return Array.from({ length: n }, () => ({
|
|
1601
|
-
at: 0,
|
|
1602
|
-
ms: span
|
|
1603
|
-
}));
|
|
1604
|
-
if (stagger > 0) {
|
|
1605
|
-
const ms = Math.max(1, span - (n - 1) * stagger);
|
|
1606
|
-
return Array.from({ length: n }, (_, i) => ({
|
|
1607
|
-
at: i * stagger,
|
|
1608
|
-
ms
|
|
1609
|
-
}));
|
|
1610
|
-
}
|
|
1611
|
-
const ms = span * .55;
|
|
1612
|
-
return Array.from({ length: n }, (_, i) => ({
|
|
1613
|
-
at: i * (span - ms) / (n - 1),
|
|
1614
|
-
ms
|
|
1615
|
-
}));
|
|
1616
|
-
}
|
|
1617
|
-
var UNITLESS = new Set([
|
|
1618
|
-
"opacity",
|
|
1619
|
-
"scale",
|
|
1620
|
-
"scaleX",
|
|
1621
|
-
"scaleY"
|
|
1622
|
-
]);
|
|
1623
|
-
var TRANSFORMS = {
|
|
1624
|
-
rotate: (v) => `rotate(${v}deg)`,
|
|
1625
|
-
scale: (v) => `scale(${v})`,
|
|
1626
|
-
x: (v) => `translateX(${v}px)`,
|
|
1627
|
-
y: (v) => `translateY(${v}px)`
|
|
1628
|
-
};
|
|
1629
|
-
/**
|
|
1630
|
-
* cue.target without the keys that move a box: the positional keys motion-dom
|
|
1631
|
-
* jumps rather than animates when motion is reduced. Opacity, colour and
|
|
1632
|
-
* filters are left to animate.
|
|
1633
|
-
*/
|
|
1634
|
-
function withoutMovement(target) {
|
|
1635
|
-
const out = {};
|
|
1636
|
-
for (const key in target) if (!positionalKeys.has(key)) out[key] = target[key];
|
|
1637
|
-
return out;
|
|
1638
|
-
}
|
|
1639
|
-
/** cue.target, as WAAPI property-indexed keyframes */
|
|
1640
|
-
function keyframesOf(target, times, ease) {
|
|
1641
|
-
const out = {};
|
|
1642
|
-
const transforms = /* @__PURE__ */ new Map();
|
|
1643
|
-
for (const key in target) {
|
|
1644
|
-
const raw = target[key];
|
|
1645
|
-
const values = (Array.isArray(raw) ? raw : [raw]).map(String);
|
|
1646
|
-
if (TRANSFORMS[key]) transforms.set(key, values);
|
|
1647
|
-
else out[UNITLESS.has(key) || isNaN(Number(values[0])) ? key : key] = values;
|
|
1648
|
-
}
|
|
1649
|
-
if (transforms.size) {
|
|
1650
|
-
const length = Math.max(...[...transforms.values()].map((v) => v.length));
|
|
1651
|
-
const frames = [];
|
|
1652
|
-
for (let i = 0; i < length; i++) {
|
|
1653
|
-
const parts = [];
|
|
1654
|
-
for (const [key, values] of transforms) parts.push(TRANSFORMS[key](values[Math.min(i, values.length - 1)]));
|
|
1655
|
-
frames.push(parts.join(" "));
|
|
1656
|
-
}
|
|
1657
|
-
out["transform"] = frames;
|
|
1658
|
-
}
|
|
1659
|
-
return times ? {
|
|
1660
|
-
...out,
|
|
1661
|
-
offset: times,
|
|
1662
|
-
easing: times.map(() => ease ?? "linear")
|
|
1663
|
-
} : out;
|
|
1664
|
-
}
|
|
1665
|
-
var NAMED = {
|
|
1666
|
-
anticipate: "cubic-bezier(0.68,-0.6,0.32,1.6)",
|
|
1667
|
-
backIn: "cubic-bezier(0.36,0,0.66,-0.56)",
|
|
1668
|
-
backInOut: "cubic-bezier(0.68,-0.6,0.32,1.6)",
|
|
1669
|
-
backOut: "cubic-bezier(0.34,1.56,0.64,1)",
|
|
1670
|
-
circIn: "cubic-bezier(0.55,0,1,0.45)",
|
|
1671
|
-
circInOut: "cubic-bezier(0.85,0,0.15,1)",
|
|
1672
|
-
circOut: "cubic-bezier(0,0.55,0.45,1)",
|
|
1673
|
-
easeIn: "ease-in",
|
|
1674
|
-
easeInOut: "ease-in-out",
|
|
1675
|
-
easeOut: "ease-out",
|
|
1676
|
-
linear: "linear"
|
|
1677
|
-
};
|
|
1678
|
-
function cssEasing(ease, ms) {
|
|
1679
|
-
if (ease === void 0) return "ease-in-out";
|
|
1680
|
-
if (typeof ease === "string") return NAMED[ease] ?? "ease-in-out";
|
|
1681
|
-
if (Array.isArray(ease)) return `cubic-bezier(${ease.join(",")})`;
|
|
1682
|
-
return generateLinearEasing(ease, ms);
|
|
1683
|
-
}
|
|
1684
|
-
/** a spring's clock, pre-sampled: its real duration and a linear() easing */
|
|
1685
|
-
function springEasing(spec) {
|
|
1686
|
-
const generator = spring({
|
|
1687
|
-
keyframes: [0, 100],
|
|
1688
|
-
...spec ?? {}
|
|
1689
|
-
});
|
|
1690
|
-
const ms = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
|
|
1691
|
-
const progress = (t) => generator.next(t * ms).value / 100;
|
|
1692
|
-
return {
|
|
1693
|
-
easing: generateLinearEasing(progress, ms),
|
|
1694
|
-
ms
|
|
1695
|
-
};
|
|
1696
|
-
}
|
|
1697
|
-
/**
|
|
1698
|
-
* play one delivery cue: split, animate the slots, restore, land the end
|
|
1699
|
-
* values. With `reduced`, the slots keep their windows but not their
|
|
1700
|
-
* movement: a word fades in where it stands rather than rising into place.
|
|
1701
|
-
*/
|
|
1702
|
-
function deliver(cue, speed, reduced = false) {
|
|
1703
|
-
const { by, order, stagger } = cue.delivery;
|
|
1704
|
-
if (by === "item") throw new Error("choreo: item delivery is the ladder, not a split");
|
|
1705
|
-
const parts = split(cue.sprite.element, by);
|
|
1706
|
-
const ranks = ladder(parts.slots.length, order);
|
|
1707
|
-
const spans = windows(parts.slots.length, cue.duration, stagger);
|
|
1708
|
-
const times = cue.transition?.times;
|
|
1709
|
-
const target = reduced ? withoutMovement(cue.target) : cue.target ?? {};
|
|
1710
|
-
const keyframes = keyframesOf(target, Object.keys(target).length ? times : void 0, cssEasing(cue.transition?.ease, cue.duration));
|
|
1711
|
-
const sprung = cue.kind === "spring" ? springEasing(cue.transition) : void 0;
|
|
1712
|
-
const animations = [];
|
|
1713
|
-
for (const [index, slot] of parts.slots.entries()) {
|
|
1714
|
-
const w = spans[ranks[index] ?? index];
|
|
1715
|
-
const ms = sprung ? Math.min(sprung.ms, w.ms) : w.ms;
|
|
1716
|
-
animations.push(slot.el.animate(keyframes, {
|
|
1717
|
-
delay: w.at * speed,
|
|
1718
|
-
duration: Math.max(1, ms * speed),
|
|
1719
|
-
easing: times ? "linear" : sprung ? sprung.easing : cssEasing(cue.transition?.ease, ms),
|
|
1720
|
-
fill: "both"
|
|
1721
|
-
}));
|
|
1722
|
-
}
|
|
1723
|
-
let done = false;
|
|
1724
|
-
let held = false;
|
|
1725
|
-
const land = () => {
|
|
1726
|
-
if (done) return;
|
|
1727
|
-
done = true;
|
|
1728
|
-
const ve = cue.sprite.node.visualElement;
|
|
1729
|
-
if (ve && cue.target) {
|
|
1730
|
-
for (const key in cue.target) {
|
|
1731
|
-
const raw = cue.target[key];
|
|
1732
|
-
const end = Array.isArray(raw) ? raw[raw.length - 1] : raw;
|
|
1733
|
-
ve.getValue(key, end).jump(end);
|
|
1734
|
-
}
|
|
1735
|
-
ve.render();
|
|
1736
|
-
}
|
|
1737
|
-
parts.restore();
|
|
1738
|
-
};
|
|
1739
|
-
return {
|
|
1740
|
-
cancel() {
|
|
1741
|
-
done = true;
|
|
1742
|
-
animations.forEach((a) => a.cancel());
|
|
1743
|
-
parts.restore();
|
|
1744
|
-
},
|
|
1745
|
-
complete() {
|
|
1746
|
-
animations.forEach((a) => {
|
|
1747
|
-
try {
|
|
1748
|
-
a.finish();
|
|
1749
|
-
} catch {
|
|
1750
|
-
a.cancel();
|
|
1751
|
-
}
|
|
1752
|
-
});
|
|
1753
|
-
land();
|
|
1754
|
-
},
|
|
1755
|
-
finished: Promise.all(animations.map((a) => a.finished.catch(() => {}))).then(land),
|
|
1756
|
-
get inFlight() {
|
|
1757
|
-
return !done && !held;
|
|
1758
|
-
},
|
|
1759
|
-
pause() {
|
|
1760
|
-
held = true;
|
|
1761
|
-
animations.forEach((a) => a.pause());
|
|
1762
|
-
},
|
|
1763
|
-
play() {
|
|
1764
|
-
held = false;
|
|
1765
|
-
animations.forEach((a) => a.play());
|
|
1766
|
-
},
|
|
1767
|
-
seek(ms) {
|
|
1768
|
-
const t = Math.max(0, ms * speed);
|
|
1769
|
-
animations.forEach((a) => a.currentTime = t);
|
|
1770
|
-
},
|
|
1771
|
-
speed(rate) {
|
|
1772
|
-
animations.forEach((a) => a.playbackRate = rate);
|
|
1773
|
-
}
|
|
1774
|
-
};
|
|
1775
|
-
}
|
|
1776
|
-
//#endregion
|
|
1777
|
-
//#region ../choreo/src/path.ts
|
|
1778
|
-
/**
|
|
1779
|
-
* THE CAMERA'S PATH — the arithmetic behind `c.Camera3D @through`, and
|
|
1780
|
-
* the only place in Choreo that owns a curve rather than a tween.
|
|
1781
|
-
*
|
|
1782
|
-
* Everything here is a pure function of PROGRESS. That is the whole
|
|
1783
|
-
* point: a seek must land the shot exactly where playing there would, so
|
|
1784
|
-
* nothing in this file may remember a previous frame. A spline that is
|
|
1785
|
-
* sampled rather than integrated can be scrubbed, rendered a frame at a
|
|
1786
|
-
* time, and played, and all three agree by construction.
|
|
1787
|
-
*/
|
|
1788
|
-
/**
|
|
1789
|
-
* One cardinal-spline component: Hermite through p1 and p2, tangents off
|
|
1790
|
-
* p0 and p3 scaled by `k = (1 - tension) / 2`. Tension 0 is the classic
|
|
1791
|
-
* Catmull-Rom — lively, and loose enough to overshoot between waypoints
|
|
1792
|
-
* that change direction; 1 collapses the tangents and the path goes
|
|
1793
|
-
* piecewise-linear. The default (0.5) is the steady hand: it still crosses
|
|
1794
|
-
* every waypoint with continuous velocity, but it does not sway on the way.
|
|
1795
|
-
*/
|
|
1796
|
-
function crVal(p0, p1, p2, p3, u, k) {
|
|
1797
|
-
const m1 = k * (p2 - p0);
|
|
1798
|
-
const m2 = k * (p3 - p1);
|
|
1799
|
-
const u2 = u * u;
|
|
1800
|
-
const u3 = u2 * u;
|
|
1801
|
-
return (2 * u3 - 3 * u2 + 1) * p1 + (u3 - 2 * u2 + u) * m1 + (-2 * u3 + 3 * u2) * p2 + (u3 - u2) * m2;
|
|
1802
|
-
}
|
|
1803
|
-
/**
|
|
1804
|
-
* Resolve a `@through` path's control points: the pose in force first, then
|
|
1805
|
-
* each waypoint with its omissions carried forward. If ANY point carries a
|
|
1806
|
-
* look, every point gets one (the origin, when unstated), so the aim is
|
|
1807
|
-
* splined by the same arithmetic as the pose.
|
|
1808
|
-
*/
|
|
1809
|
-
function resolveThrough(from, through) {
|
|
1810
|
-
const aimed = !!from.look || through.some((w) => w.look);
|
|
1811
|
-
const seed = {
|
|
1812
|
-
...from,
|
|
1813
|
-
look: aimed ? from.look ?? {
|
|
1814
|
-
x: 0,
|
|
1815
|
-
y: 0,
|
|
1816
|
-
z: 0
|
|
1817
|
-
} : void 0
|
|
1818
|
-
};
|
|
1819
|
-
const pts = [seed];
|
|
1820
|
-
let prev = seed;
|
|
1821
|
-
for (const w of through) {
|
|
1822
|
-
const p = {
|
|
1823
|
-
dolly: w.dolly ?? prev.dolly,
|
|
1824
|
-
look: aimed ? w.look ?? prev.look : void 0,
|
|
1825
|
-
pitch: w.pitch ?? prev.pitch,
|
|
1826
|
-
x: w.x ?? prev.x,
|
|
1827
|
-
y: w.y ?? prev.y,
|
|
1828
|
-
yaw: w.yaw ?? prev.yaw
|
|
1829
|
-
};
|
|
1830
|
-
pts.push(p);
|
|
1831
|
-
prev = p;
|
|
1832
|
-
}
|
|
1833
|
-
return pts;
|
|
1834
|
-
}
|
|
1835
|
-
/** the shot a slot position falls in — points [a, e), window [w0, w1) */
|
|
1836
|
-
/**
|
|
1837
|
-
* WHICH SHOT A SLOT POSITION IS IN. A waypoint marked `cut` opens a new
|
|
1838
|
-
* one, and the two facts a caller needs about it are the points it may
|
|
1839
|
-
* reach for and the slice of the clock it owns — the second so that
|
|
1840
|
-
* nothing (a sample, a settle) ever reads across a seam.
|
|
1841
|
-
*/
|
|
1842
|
-
function shotAt(through, points, segs, s) {
|
|
1843
|
-
let seams;
|
|
1844
|
-
for (const [n, w] of through.entries()) if (w.cut) (seams ??= []).push(n + 1);
|
|
1845
|
-
let a = 0;
|
|
1846
|
-
let e = points;
|
|
1847
|
-
let w0 = 0;
|
|
1848
|
-
let w1 = segs;
|
|
1849
|
-
if (seams) {
|
|
1850
|
-
if (seams[0] === 1) {
|
|
1851
|
-
a = 1;
|
|
1852
|
-
seams = seams.slice(1);
|
|
1853
|
-
}
|
|
1854
|
-
for (const seam of seams) {
|
|
1855
|
-
if (s < seam) {
|
|
1856
|
-
e = seam;
|
|
1857
|
-
w1 = seam;
|
|
1858
|
-
break;
|
|
1859
|
-
}
|
|
1860
|
-
a = seam;
|
|
1861
|
-
w0 = seam;
|
|
1862
|
-
}
|
|
1863
|
-
}
|
|
1864
|
-
return {
|
|
1865
|
-
a,
|
|
1866
|
-
e,
|
|
1867
|
-
w0,
|
|
1868
|
-
w1
|
|
1869
|
-
};
|
|
1870
|
-
}
|
|
1871
|
-
/**
|
|
1872
|
-
* Sample the spline at overall progress p ∈ [0, 1] (uniform segments).
|
|
1873
|
-
*
|
|
1874
|
-
* SPLICES (packages/choreo-gallery/realm/docs/choreo-splices.md): a waypoint marked `cut` starts a new
|
|
1875
|
-
* SHOT. Each shot is a clamped spline of its own points — endpoint
|
|
1876
|
-
* tangents one-sided, so no shot's velocity crosses a seam — and each
|
|
1877
|
-
* shot's window runs from its first slot to the next seam, its points
|
|
1878
|
-
* spread uniformly across it. The outgoing shot therefore plays through
|
|
1879
|
-
* the seam instant (its motion stretches by one slot rather than
|
|
1880
|
-
* parking), the incoming one begins exactly on it, and the sampled pose
|
|
1881
|
-
* is a step function at the seam. Waypoints keep their uniform slots, so
|
|
1882
|
-
* cues anchored to waypoint moments keep their clock. A cut on the first
|
|
1883
|
-
* waypoint drops the pose-in-force seed: the score opens inside its
|
|
1884
|
-
* first shot.
|
|
1885
|
-
*/
|
|
1886
|
-
function sampleThrough(from, through, progress, tension) {
|
|
1887
|
-
const k = (1 - (tension ?? .5)) / 2;
|
|
1888
|
-
const pts = resolveThrough(from, through);
|
|
1889
|
-
const segs = pts.length - 1;
|
|
1890
|
-
const s = Math.min(segs - 1e-9, Math.max(0, progress * segs));
|
|
1891
|
-
const { a, e, w0, w1 } = shotAt(through, pts.length, segs, s);
|
|
1892
|
-
const m = e - a;
|
|
1893
|
-
const ss = (m === 1 ? 0 : Math.max(0, Math.min(.999999999, (s - w0) / (w1 - w0)))) * (m - 1);
|
|
1894
|
-
const i = a + Math.floor(ss);
|
|
1895
|
-
const u = m === 1 ? 0 : ss - Math.floor(ss);
|
|
1896
|
-
const P = (j) => pts[Math.max(a, Math.min(e - 1, j))];
|
|
1897
|
-
const p0 = P(i - 1);
|
|
1898
|
-
const p1 = P(i);
|
|
1899
|
-
const p2 = P(i + 1);
|
|
1900
|
-
const p3 = P(i + 2);
|
|
1901
|
-
const v = (key) => crVal(p0[key], p1[key], p2[key], p3[key], u, k);
|
|
1902
|
-
const out = {
|
|
1903
|
-
dolly: v("dolly"),
|
|
1904
|
-
pitch: v("pitch"),
|
|
1905
|
-
x: v("x"),
|
|
1906
|
-
y: v("y"),
|
|
1907
|
-
yaw: v("yaw")
|
|
1908
|
-
};
|
|
1909
|
-
if (p1.look && p2.look) {
|
|
1910
|
-
const l = (a) => crVal((p0.look ?? p1.look)[a], p1.look[a], p2.look[a], (p3.look ?? p2.look)[a], u, k);
|
|
1911
|
-
out.look = {
|
|
1912
|
-
x: l("x"),
|
|
1913
|
-
y: l("y"),
|
|
1914
|
-
z: l("z")
|
|
1915
|
-
};
|
|
1916
|
-
}
|
|
1917
|
-
return out;
|
|
1918
|
-
}
|
|
1919
|
-
/**
|
|
1920
|
-
* A SETTLE — the operator's second hand, written as a function of time.
|
|
1921
|
-
*
|
|
1922
|
-
* A cardinal spline crosses its waypoints with continuous velocity but
|
|
1923
|
-
* not continuous acceleration: at every control point the curvature
|
|
1924
|
-
* steps, and the eye reads that step as a tick. The usual cure is a
|
|
1925
|
-
* spring chasing the pose, which works and costs the two things a
|
|
1926
|
-
* seekable engine cannot pay — it remembers the last frame, so a scrub
|
|
1927
|
-
* lands somewhere a play would not, and it lags, so the camera is always
|
|
1928
|
-
* behind the score by however much smoothing it was given.
|
|
1929
|
-
*
|
|
1930
|
-
* This is the same cure without either cost: the reported pose is a
|
|
1931
|
-
* Hann-weighted average of the SAME spline sampled around the current
|
|
1932
|
-
* progress. Averaging a curve is a low-pass filter, and a Hann window
|
|
1933
|
-
* kills the acceleration steps outright, so the result is a hand rather
|
|
1934
|
-
* than a mechanism. Being centred, it has no lag — it reads slightly
|
|
1935
|
-
* ahead of the score exactly as much as it reads behind. Being an
|
|
1936
|
-
* average of one pure function, it is still a pure function: play,
|
|
1937
|
-
* scrub and frame-by-frame render all report the same pose.
|
|
1938
|
-
*
|
|
1939
|
-
* TWO EDGES IT MUST NOT CROSS. A cut is a step in the pose on purpose,
|
|
1940
|
-
* and an average that straddled it would smear the cut into a very fast
|
|
1941
|
-
* pan. The window is therefore TAPERED to the shot the progress is in:
|
|
1942
|
-
* near either edge the kernel shrinks to the room it has, reaching zero
|
|
1943
|
-
* at the edge itself. So a cut stays a cut, a path still lands exactly
|
|
1944
|
-
* on its last waypoint, and the pose handed forward to the next cue is
|
|
1945
|
-
* the waypoint rather than an average of one — the filter is an identity
|
|
1946
|
-
* at every boundary and a smoother everywhere else.
|
|
1947
|
-
*
|
|
1948
|
-
* The taper is `tanh`, not a `min`, and the difference is the whole
|
|
1949
|
-
* reason it works. A hard `min(width, 2 × room)` has a corner in it
|
|
1950
|
-
* where the two branches meet, and a filter whose width has a corner
|
|
1951
|
-
* puts one back into what it filters: measured against a path with two
|
|
1952
|
-
* right-angle corners in it, the hard taper LOST ground as the window
|
|
1953
|
-
* widened (worst jerk 8.7e-4 at a window of 0.175, 2.5e-3 at 0.3) while
|
|
1954
|
-
* the smooth one held 8.0e-4 at every width against 4.2e-3 unfiltered.
|
|
1955
|
-
* `tanh(x) ≤ x` everywhere, which is what keeps the taps inside the
|
|
1956
|
-
* shot; it is smooth, which is what keeps the tick out.
|
|
1957
|
-
*
|
|
1958
|
-
* `width` is in progress, not seconds: the kinks being filtered are at
|
|
1959
|
-
* the waypoints, which are spread uniformly across the clock, so a
|
|
1960
|
-
* window measured against the clock is a window measured against the
|
|
1961
|
-
* spacing of the things it exists to smooth. The caller converts.
|
|
1962
|
-
*/
|
|
1963
|
-
function settleThrough(from, through, progress, tension, width, taps = 15) {
|
|
1964
|
-
const pts = resolveThrough(from, through);
|
|
1965
|
-
const segs = pts.length - 1;
|
|
1966
|
-
const s = Math.min(segs - 1e-9, Math.max(0, progress * segs));
|
|
1967
|
-
const { w0, w1 } = shotAt(through, pts.length, segs, s);
|
|
1968
|
-
const lo = w0 / segs;
|
|
1969
|
-
const hi = w1 / segs;
|
|
1970
|
-
const p = Math.min(hi, Math.max(lo, progress));
|
|
1971
|
-
const room = Math.min(p - lo, hi - p);
|
|
1972
|
-
const w = width > 0 ? width * Math.tanh(2 * room / width) : 0;
|
|
1973
|
-
if (!(w > 1e-6) || taps < 3) return sampleThrough(from, through, progress, tension);
|
|
1974
|
-
const aimed = !!from.look || through.some((t) => t.look);
|
|
1975
|
-
let sum = 0;
|
|
1976
|
-
let dolly = 0;
|
|
1977
|
-
let pitch = 0;
|
|
1978
|
-
let x = 0;
|
|
1979
|
-
let y = 0;
|
|
1980
|
-
let yaw = 0;
|
|
1981
|
-
let lx = 0;
|
|
1982
|
-
let ly = 0;
|
|
1983
|
-
let lz = 0;
|
|
1984
|
-
for (let i = 0; i < taps; i += 1) {
|
|
1985
|
-
const f = (i + 1) / (taps + 1);
|
|
1986
|
-
const weight = .5 - .5 * Math.cos(2 * Math.PI * f);
|
|
1987
|
-
const q = sampleThrough(from, through, p + (f - .5) * w, tension);
|
|
1988
|
-
sum += weight;
|
|
1989
|
-
dolly += weight * q.dolly;
|
|
1990
|
-
pitch += weight * q.pitch;
|
|
1991
|
-
x += weight * q.x;
|
|
1992
|
-
y += weight * q.y;
|
|
1993
|
-
yaw += weight * q.yaw;
|
|
1994
|
-
if (aimed && q.look) {
|
|
1995
|
-
lx += weight * q.look.x;
|
|
1996
|
-
ly += weight * q.look.y;
|
|
1997
|
-
lz += weight * q.look.z;
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
const out = {
|
|
2001
|
-
dolly: dolly / sum,
|
|
2002
|
-
pitch: pitch / sum,
|
|
2003
|
-
x: x / sum,
|
|
2004
|
-
y: y / sum,
|
|
2005
|
-
yaw: yaw / sum
|
|
2006
|
-
};
|
|
2007
|
-
if (aimed) out.look = {
|
|
2008
|
-
x: lx / sum,
|
|
2009
|
-
y: ly / sum,
|
|
2010
|
-
z: lz / sum
|
|
2011
|
-
};
|
|
2012
|
-
return out;
|
|
2013
|
-
}
|
|
2014
|
-
//#endregion
|
|
2015
|
-
//#region ../choreo/src/run.ts
|
|
2016
|
-
/**
|
|
2017
|
-
* Play a cue list on the motion-dom engine — as a run you can hold (§4.6).
|
|
2018
|
-
*
|
|
2019
|
-
* The old executor fired timers and forgot; this one owns a master clock.
|
|
2020
|
-
* Cues start when the clock crosses them, a gate parks the clock until
|
|
2021
|
-
* `advance()` (§4.1), `time` is settable in either direction (a scrubbed
|
|
2022
|
-
* frame is a still), and `speed` scales the whole score. Ambient loops and
|
|
2023
|
-
* text deliveries ride the platform's own animations, so a busy probe never
|
|
2024
|
-
* mistakes an idle loop for motion.
|
|
2025
|
-
*
|
|
2026
|
-
* The clock runs in tempo-scaled milliseconds; the public face (`time`,
|
|
2027
|
-
* `duration`) speaks seconds at 1×, as Motion's playback controls do.
|
|
2028
|
-
*/
|
|
2029
|
-
/** the properties whose mid-flight drive means a sprite is IN SPACE — a
|
|
2030
|
-
* replacement pass must carry these on, never snap them (§3.1) */
|
|
2031
|
-
var MIDFLIGHT_KEYS = [
|
|
2032
|
-
"height",
|
|
2033
|
-
"rotate",
|
|
2034
|
-
"scale",
|
|
2035
|
-
"scaleX",
|
|
2036
|
-
"scaleY",
|
|
2037
|
-
"width",
|
|
2038
|
-
"x",
|
|
2039
|
-
"y"
|
|
2040
|
-
];
|
|
2041
|
-
/** how fast each value was moving, in units per second, keyed by element then property */
|
|
2042
|
-
/**
|
|
2043
|
-
* Where each ambient loop stood in its cycle, from 0 to 1, keyed by sprite
|
|
2044
|
-
* then by the loop's properties (see loopKey).
|
|
2045
|
-
*/
|
|
2046
|
-
/** a loop's properties, which tell it apart from another loop on its sprite */
|
|
2047
|
-
var loopKey = (cue) => Object.keys(cue.target ?? {}).sort().join(",");
|
|
2048
|
-
/** a tween a replacement pass carries on: see Run.midfade */
|
|
2049
|
-
function isSpring(transition) {
|
|
2050
|
-
if (!transition) return false;
|
|
2051
|
-
if (transition["type"]) return transition["type"] === "spring";
|
|
2052
|
-
return "bounce" in transition || "damping" in transition || "stiffness" in transition || "visualDuration" in transition;
|
|
2053
|
-
}
|
|
2054
|
-
/**
|
|
2055
|
-
* Controls that wrap a platform Animation rather than a motion-dom one: the
|
|
2056
|
-
* frame clock's hold-back has no tween to move in them, and no private
|
|
2057
|
-
* fields to find.
|
|
2058
|
-
*/
|
|
2059
|
-
var platformControlled = /* @__PURE__ */ new WeakSet();
|
|
2060
|
-
/**
|
|
2061
|
-
* A platform Animation in the controls shape the transport speaks, so
|
|
2062
|
-
* setPaused / speed / stopTrack drive it exactly like an engine animation.
|
|
2063
|
-
*/
|
|
2064
|
-
function platformControls(animation) {
|
|
2065
|
-
const controls = {
|
|
2066
|
-
cancel: () => animation.cancel(),
|
|
2067
|
-
pause: () => animation.pause(),
|
|
2068
|
-
play: () => animation.play(),
|
|
2069
|
-
get speed() {
|
|
2070
|
-
return animation.playbackRate;
|
|
2071
|
-
},
|
|
2072
|
-
set speed(rate) {
|
|
2073
|
-
animation.playbackRate = rate;
|
|
2074
|
-
},
|
|
2075
|
-
get state() {
|
|
2076
|
-
return animation.playState;
|
|
2077
|
-
},
|
|
2078
|
-
stop: () => animation.cancel(),
|
|
2079
|
-
get time() {
|
|
2080
|
-
return (animation.currentTime ?? 0) / 1e3;
|
|
2081
|
-
},
|
|
2082
|
-
set time(seconds) {
|
|
2083
|
-
animation.currentTime = seconds * 1e3;
|
|
2084
|
-
}
|
|
2085
|
-
};
|
|
2086
|
-
platformControlled.add(controls);
|
|
2087
|
-
return controls;
|
|
2088
|
-
}
|
|
2089
|
-
function carryVelocity(transition, cue, inherit) {
|
|
2090
|
-
if (!inherit || !cue.target || !isSpring(transition)) return transition;
|
|
2091
|
-
const was = inherit.get(cue.sprite.element) ?? (cue.sprite.counterpart && inherit.get(cue.sprite.counterpart.element));
|
|
2092
|
-
if (!was) return transition;
|
|
2093
|
-
let out = transition;
|
|
2094
|
-
for (const key in cue.target) {
|
|
2095
|
-
const velocity = was.get(key);
|
|
2096
|
-
if (velocity) {
|
|
2097
|
-
if (out === transition) out = { ...transition };
|
|
2098
|
-
out[key] = {
|
|
2099
|
-
...transition,
|
|
2100
|
-
velocity
|
|
2101
|
-
};
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
return out;
|
|
2105
|
-
}
|
|
2106
|
-
var dash = (key) => key.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
|
|
2107
|
-
var noop = () => {};
|
|
2108
|
-
var SIZES = {
|
|
2109
|
-
height: true,
|
|
2110
|
-
width: true
|
|
2111
|
-
};
|
|
2112
|
-
function applyHold(ve, el, values) {
|
|
2113
|
-
const held = [];
|
|
2114
|
-
for (const key in values) {
|
|
2115
|
-
const had = ve.hasValue(key);
|
|
2116
|
-
const prior = had ? ve.getValue(key).get() : void 0;
|
|
2117
|
-
const priorStyle = key.startsWith("--") ? el.style.getPropertyValue(key) : el.style[key] ?? "";
|
|
2118
|
-
ve.getValue(key, values[key]).jump(values[key]);
|
|
2119
|
-
held.push({
|
|
2120
|
-
had,
|
|
2121
|
-
key,
|
|
2122
|
-
prior,
|
|
2123
|
-
priorStyle
|
|
2124
|
-
});
|
|
2125
|
-
}
|
|
2126
|
-
ve.scheduleRender();
|
|
2127
|
-
return held;
|
|
2128
|
-
}
|
|
2129
|
-
function releaseHold(ve, el, held) {
|
|
2130
|
-
for (const { had, key, prior, priorStyle } of held) if (had) ve.getValue(key)?.jump(prior);
|
|
2131
|
-
else {
|
|
2132
|
-
ve.removeValue(key);
|
|
2133
|
-
if (priorStyle) el.style.setProperty(dash(key), priorStyle);
|
|
2134
|
-
else el.style.removeProperty(dash(key));
|
|
2135
|
-
}
|
|
2136
|
-
ve.scheduleRender();
|
|
2137
|
-
}
|
|
2138
|
-
/** what one cue is doing right now */
|
|
2139
|
-
var warnedPrivateFields = false;
|
|
2140
|
-
/** let the next run that misses motion-dom's private fields say so again (a test's reset) */
|
|
2141
|
-
function resetRunWarnings() {
|
|
2142
|
-
warnedPrivateFields = false;
|
|
2143
|
-
}
|
|
2144
|
-
/** the run's frame clock reads motion-dom's private animation fields; say once when they are gone */
|
|
2145
|
-
function warnPrivateFieldsMoved() {
|
|
2146
|
-
if (warnedPrivateFields) return;
|
|
2147
|
-
warnedPrivateFields = true;
|
|
2148
|
-
console.warn("@cardstack/choreo: motion-dom no longer exposes the animation fields a run's frame clock reads (_animation, startTime, holdTime); a run compiled in a long task will open its tweens that far in, and with @maxFrameStep a long frame will skip them ahead instead of slowing them");
|
|
2149
|
-
}
|
|
2150
|
-
var ChoreoRun = class ChoreoRun {
|
|
2151
|
-
cues;
|
|
2152
|
-
velocities = /* @__PURE__ */ new Map();
|
|
2153
|
-
finished;
|
|
2154
|
-
master = 0;
|
|
2155
|
-
playing = true;
|
|
2156
|
-
parkedAt = null;
|
|
2157
|
-
rate = 1;
|
|
2158
|
-
scale = motionSpeed();
|
|
2159
|
-
reduced;
|
|
2160
|
-
standing;
|
|
2161
|
-
total;
|
|
2162
|
-
gates;
|
|
2163
|
-
tracks = [];
|
|
2164
|
-
rowEnd = /* @__PURE__ */ new Map();
|
|
2165
|
-
released = /* @__PURE__ */ new Set();
|
|
2166
|
-
pending;
|
|
2167
|
-
options;
|
|
2168
|
-
borrowedValues = [];
|
|
2169
|
-
/** rest is what releaseForMeasure jumps to: 0 for translates, 1 for scales, 'none' for clips */
|
|
2170
|
-
movedValues = [];
|
|
2171
|
-
/** what the last releaseForMeasure retired, so a kept pass can put it back */
|
|
2172
|
-
retired = {
|
|
2173
|
-
borrowed: [],
|
|
2174
|
-
moved: []
|
|
2175
|
-
};
|
|
2176
|
-
owned = [];
|
|
2177
|
-
cancelled = false;
|
|
2178
|
-
ended = false;
|
|
2179
|
-
resolveFinished;
|
|
2180
|
-
ticking = false;
|
|
2181
|
-
/**
|
|
2182
|
-
* The next tick is the first since the clock started (or resumed): it
|
|
2183
|
-
* paints the run where it stands and advances nothing. The frame loop's
|
|
2184
|
-
* delta on that tick is the time since ITS last frame, up to 40 ms, so a
|
|
2185
|
-
* run started by a render pass would otherwise open with that whole step
|
|
2186
|
-
* on its own clock: every cue the clock starts, gates, or drives frame by
|
|
2187
|
-
* frame (a camera, a wire, a later cue's start) would begin that far in.
|
|
2188
|
-
* The tweens the run started get the same fresh start from holdBack. A
|
|
2189
|
-
* run that opens `continuing` skips it.
|
|
2190
|
-
*/
|
|
2191
|
-
freshClock = false;
|
|
2192
|
-
/**
|
|
2193
|
-
* The run replaces one in flight and has not painted yet. Its first frame
|
|
2194
|
-
* continues a motion already on screen, so it advances like any other
|
|
2195
|
-
* frame, the clock and its tweens alike: standing still there would draw
|
|
2196
|
-
* the last frame twice. A later start (a resume, a gate) is from rest.
|
|
2197
|
-
*/
|
|
2198
|
-
continuing = false;
|
|
2199
|
-
/** the frame timestamp holdBack saw last; undefined before its first frame */
|
|
2200
|
-
lastStamp;
|
|
2201
|
-
/**
|
|
2202
|
-
* motion-dom's clock as the run (re)started ticking. That clock holds one
|
|
2203
|
-
* reading until the microtask queue next drains, and startTicking reads it
|
|
2204
|
-
* in the same synchronous call that started or resumed the run's tweens,
|
|
2205
|
-
* so this is the time they were dated from, however long the task ran
|
|
2206
|
-
* before it.
|
|
2207
|
-
*/
|
|
2208
|
-
startedAt = 0;
|
|
2209
|
-
autoTimer;
|
|
2210
|
-
constructor(compiled, options) {
|
|
2211
|
-
this.options = options;
|
|
2212
|
-
this.continuing = options.continuing ?? false;
|
|
2213
|
-
this.reduced = options.reduced ?? false;
|
|
2214
|
-
this.camera = options.camera ?? {
|
|
2215
|
-
x: 0,
|
|
2216
|
-
y: 0,
|
|
2217
|
-
zoom: 1
|
|
2218
|
-
};
|
|
2219
|
-
this.camera3d = options.camera3d ?? {
|
|
2220
|
-
dolly: 1,
|
|
2221
|
-
pitch: 0,
|
|
2222
|
-
x: 0,
|
|
2223
|
-
y: 0,
|
|
2224
|
-
yaw: 0
|
|
2225
|
-
};
|
|
2226
|
-
this.initial3d = { ...this.camera3d };
|
|
2227
|
-
this.cameraAim = options.cameraAim ?? null;
|
|
2228
|
-
this.initialCamera = { ...this.camera };
|
|
2229
|
-
this.initialAim = this.cameraAim ? { ...this.cameraAim } : null;
|
|
2230
|
-
this.cues = compiled.cues;
|
|
2231
|
-
this.pending = new Set(options.removed);
|
|
2232
|
-
const s = this.scale;
|
|
2233
|
-
this.gates = compiled.gates.map((g) => ({
|
|
2234
|
-
at: g.at * s,
|
|
2235
|
-
auto: g.auto === void 0 ? void 0 : g.auto * s,
|
|
2236
|
-
opened: false
|
|
2237
|
-
}));
|
|
2238
|
-
this.standing = compiled.open ?? false;
|
|
2239
|
-
let total = 0;
|
|
2240
|
-
for (const cue of this.cues) {
|
|
2241
|
-
const start = cue.start * s;
|
|
2242
|
-
const duration = cue.duration * s;
|
|
2243
|
-
this.tracks.push({
|
|
2244
|
-
cue,
|
|
2245
|
-
end: start + duration,
|
|
2246
|
-
passed: false,
|
|
2247
|
-
start,
|
|
2248
|
-
started: false
|
|
2249
|
-
});
|
|
2250
|
-
if (!cue.loop && !cue.standing) total = Math.max(total, start + duration);
|
|
2251
|
-
this.rowEnd.set(cue.sprite, Math.max(this.rowEnd.get(cue.sprite) ?? 0, cue.standing ? start : start + duration));
|
|
2252
|
-
}
|
|
2253
|
-
for (const g of this.gates) total = Math.max(total, g.at);
|
|
2254
|
-
for (const [sprite, end] of this.rowEnd) if (sprite.counterpart) this.rowEnd.set(sprite.counterpart, Math.max(this.rowEnd.get(sprite.counterpart) ?? 0, end));
|
|
2255
|
-
this.total = total;
|
|
2256
|
-
this.finished = new Promise((resolve) => {
|
|
2257
|
-
this.resolveFinished = resolve;
|
|
2258
|
-
});
|
|
2259
|
-
this.pinStarts();
|
|
2260
|
-
this.evaluate();
|
|
2261
|
-
this.startTicking();
|
|
2262
|
-
activeRuns.add(this);
|
|
2263
|
-
this.finished.then(() => activeRuns.delete(this));
|
|
2264
|
-
}
|
|
2265
|
-
get duration() {
|
|
2266
|
-
return this.total / this.scale / 1e3;
|
|
2267
|
-
}
|
|
2268
|
-
get paused() {
|
|
2269
|
-
return !this.playing;
|
|
2270
|
-
}
|
|
2271
|
-
get time() {
|
|
2272
|
-
return this.master / this.scale / 1e3;
|
|
2273
|
-
}
|
|
2274
|
-
/**
|
|
2275
|
-
* The run's motion is under way on screen: it is playing, its clock has
|
|
2276
|
-
* not reached its end, and it has painted a frame since it started or
|
|
2277
|
-
* resumed, or carries on a run that had. A run compiled and replaced
|
|
2278
|
-
* before any frame was never seen moving, so its replacement starts from
|
|
2279
|
-
* rest.
|
|
2280
|
-
*/
|
|
2281
|
-
get inFlight() {
|
|
2282
|
-
return this.ticking && this.master < this.total && (this.lastStamp !== void 0 || this.continuing);
|
|
2283
|
-
}
|
|
2284
|
-
set time(seconds) {
|
|
2285
|
-
this.seekTo(seconds * 1e3 * this.scale);
|
|
2286
|
-
}
|
|
2287
|
-
get speed() {
|
|
2288
|
-
return this.rate;
|
|
2289
|
-
}
|
|
2290
|
-
set speed(rate) {
|
|
2291
|
-
this.rate = rate;
|
|
2292
|
-
for (const t of this.tracks) {
|
|
2293
|
-
t.controls?.forEach((c) => c.speed = rate);
|
|
2294
|
-
if (t.delivery) t.delivery.speed(rate);
|
|
2295
|
-
if (t.loopAnimation) t.loopAnimation.playbackRate = rate;
|
|
2296
|
-
if (t.cameraAnimation) t.cameraAnimation.playbackRate = rate;
|
|
2297
|
-
}
|
|
2298
|
-
}
|
|
2299
|
-
get segment() {
|
|
2300
|
-
let n = 0;
|
|
2301
|
-
for (const g of this.gates) if (this.master > g.at || this.master === g.at && g.opened) n++;
|
|
2302
|
-
return n;
|
|
2303
|
-
}
|
|
2304
|
-
get parked() {
|
|
2305
|
-
return this.parkedAt !== null;
|
|
2306
|
-
}
|
|
2307
|
-
/**
|
|
2308
|
-
* ATTACH: write each attached region's clock from this one's.
|
|
2309
|
-
*
|
|
2310
|
-
* Several windows may name one region — a film's every beat has a plate
|
|
2311
|
-
* window, and the plate is one region re-keyed per beat — so the run
|
|
2312
|
-
* resolves ONE governing window per region on every evaluate: the window
|
|
2313
|
-
* that holds `now`; else the latest past one, if it holds; else the
|
|
2314
|
-
* earliest future one, which stands the child at its head (Remotion's
|
|
2315
|
-
* premount: mounted early, clock frozen at `in`). The child's run is
|
|
2316
|
-
* paused and told `in + (now − start) × rate`. No history is kept on
|
|
2317
|
-
* either side, which is what makes a seek into a window land where
|
|
2318
|
-
* playing there would.
|
|
2319
|
-
*/
|
|
2320
|
-
driveAttachments(now) {
|
|
2321
|
-
let governing;
|
|
2322
|
-
for (const t of this.tracks) {
|
|
2323
|
-
const a = t.cue.attach;
|
|
2324
|
-
if (!a || t.refused) continue;
|
|
2325
|
-
governing ??= /* @__PURE__ */ new Map();
|
|
2326
|
-
const g = governing.get(a.region);
|
|
2327
|
-
if (!g) {
|
|
2328
|
-
governing.set(a.region, t);
|
|
2329
|
-
continue;
|
|
2330
|
-
}
|
|
2331
|
-
const rank = (x) => now >= x.start && now < x.end ? 2 : now >= x.end ? 1 : 0;
|
|
2332
|
-
const rt = rank(t);
|
|
2333
|
-
const rg = rank(g);
|
|
2334
|
-
if (rt > rg || rt === rg && rt === 1 && t.end > g.end || rt === rg && rt === 0 && t.start < g.start) governing.set(a.region, t);
|
|
2335
|
-
}
|
|
2336
|
-
if (!governing) return;
|
|
2337
|
-
for (const [region, t] of governing) {
|
|
2338
|
-
const a = t.cue.attach;
|
|
2339
|
-
const child = choreoHostById(region)?.currentRun() ?? null;
|
|
2340
|
-
if (!child || child === this) continue;
|
|
2341
|
-
if (a.exact && child.hasIntegrator()) {
|
|
2342
|
-
t.refused = true;
|
|
2343
|
-
console.error(`choreo: <Choreo "${region}"> is attached under an exact clock, but its score integrates (a spring or a follow): its state is its history, and a driven clock has none`);
|
|
2344
|
-
continue;
|
|
2345
|
-
}
|
|
2346
|
-
let local;
|
|
2347
|
-
if (now < t.start) local = a.in;
|
|
2348
|
-
else if (now < t.end) local = a.in + (now - t.start) / 1e3 / this.scale * a.rate;
|
|
2349
|
-
else if (a.end === "hold") local = a.in + t.cue.duration / 1e3 * a.rate;
|
|
2350
|
-
else continue;
|
|
2351
|
-
const inside = now >= t.start && now < t.end;
|
|
2352
|
-
if (this.playing && inside && !this.ended) {
|
|
2353
|
-
if (child.paused) {
|
|
2354
|
-
child.time = local;
|
|
2355
|
-
child.play();
|
|
2356
|
-
} else if (Math.abs(child.time - local) > 1 / 30) child.time = local;
|
|
2357
|
-
const speed = this.rate * a.rate;
|
|
2358
|
-
if (Math.abs(child.speed - speed) > 1e-6) child.speed = speed;
|
|
2359
|
-
continue;
|
|
2360
|
-
}
|
|
2361
|
-
if (!child.paused) child.pause();
|
|
2362
|
-
if (Math.abs(child.time - local) > 1e-4) child.time = local;
|
|
2363
|
-
}
|
|
2364
|
-
}
|
|
2365
|
-
/** does this run's score integrate — a spring, a follow — so that its state is its history? */
|
|
2366
|
-
hasIntegrator() {
|
|
2367
|
-
return this.tracks.some((t) => t.cue.kind === "spring" || !!t.cue.derive);
|
|
2368
|
-
}
|
|
2369
|
-
isDone() {
|
|
2370
|
-
return this.ended || this.cancelled;
|
|
2371
|
-
}
|
|
2372
|
-
/**
|
|
2373
|
-
* A text delivery is still standing in for its sprite's text. The clock
|
|
2374
|
-
* can end first: a delivery lands on its own platform animations, and the
|
|
2375
|
-
* run leaves it to finish its tail rather than cutting it short.
|
|
2376
|
-
*/
|
|
2377
|
-
get delivering() {
|
|
2378
|
-
return !this.cancelled && this.tracks.some((t) => t.delivery?.inFlight === true);
|
|
2379
|
-
}
|
|
2380
|
-
loopPhases() {
|
|
2381
|
-
const out = /* @__PURE__ */ new Map();
|
|
2382
|
-
for (const t of this.tracks) {
|
|
2383
|
-
const animation = t.loopAnimation;
|
|
2384
|
-
if (!animation || animation.playState === "idle") continue;
|
|
2385
|
-
const cycle = Number(animation.effect?.getComputedTiming().duration);
|
|
2386
|
-
if (!(cycle > 0)) continue;
|
|
2387
|
-
const node = t.cue.sprite.node;
|
|
2388
|
-
let phases = out.get(node);
|
|
2389
|
-
if (!phases) out.set(node, phases = /* @__PURE__ */ new Map());
|
|
2390
|
-
phases.set(loopKey(t.cue), Number(animation.currentTime ?? 0) % cycle / cycle);
|
|
2391
|
-
}
|
|
2392
|
-
return out;
|
|
2393
|
-
}
|
|
2394
|
-
midflight() {
|
|
2395
|
-
const out = /* @__PURE__ */ new Map();
|
|
2396
|
-
if (this.isDone()) return out;
|
|
2397
|
-
for (const t of this.tracks) {
|
|
2398
|
-
const { cue } = t;
|
|
2399
|
-
if (!t.started || t.passed) continue;
|
|
2400
|
-
if (cue.flight !== void 0 || cue.target !== void 0 && MIDFLIGHT_KEYS.some((key) => key in cue.target)) out.set(cue.sprite.node, cue.transition);
|
|
2401
|
-
}
|
|
2402
|
-
return out;
|
|
2403
|
-
}
|
|
2404
|
-
midfade() {
|
|
2405
|
-
const out = /* @__PURE__ */ new Map();
|
|
2406
|
-
if (this.isDone()) return out;
|
|
2407
|
-
const now = this.master;
|
|
2408
|
-
const gate = this.gates.find((g) => !g.opened && g.at >= now)?.at;
|
|
2409
|
-
const scale = this.scale || 1;
|
|
2410
|
-
for (const t of this.tracks) {
|
|
2411
|
-
const { cue } = t;
|
|
2412
|
-
if (t.passed || t.end <= now || gate !== void 0 && t.start >= gate && !t.started || cue.kind !== "tween" || cue.loop || cue.borrow || !cue.target) continue;
|
|
2413
|
-
const { repeat, repeatType } = cue.transition ?? {};
|
|
2414
|
-
const first = typeof repeat === "number" && repeat % 2 === 1 && repeatType !== "loop";
|
|
2415
|
-
const to = {};
|
|
2416
|
-
for (const [key, value] of Object.entries(cue.target)) {
|
|
2417
|
-
if (MIDFLIGHT_KEYS.includes(key)) continue;
|
|
2418
|
-
const end = Array.isArray(value) ? value[first ? 0 : value.length - 1] : value;
|
|
2419
|
-
if (end !== void 0 && end !== null) to[key] = end;
|
|
2420
|
-
}
|
|
2421
|
-
if (!Object.keys(to).length) continue;
|
|
2422
|
-
const begins = Math.max(now, t.start);
|
|
2423
|
-
const fades = out.get(cue.sprite.node) ?? [];
|
|
2424
|
-
fades.push({
|
|
2425
|
-
delay: (begins - now) / scale,
|
|
2426
|
-
remaining: (t.end - begins) / scale,
|
|
2427
|
-
to
|
|
2428
|
-
});
|
|
2429
|
-
out.set(cue.sprite.node, fades);
|
|
2430
|
-
}
|
|
2431
|
-
return out;
|
|
2432
|
-
}
|
|
2433
|
-
pause() {
|
|
2434
|
-
if (!this.playing) return;
|
|
2435
|
-
this.playing = false;
|
|
2436
|
-
this.setPaused(true);
|
|
2437
|
-
this.driveAttachments(this.master);
|
|
2438
|
-
this.scheduleRestill();
|
|
2439
|
-
}
|
|
2440
|
-
play() {
|
|
2441
|
-
if (this.playing || this.ended || this.cancelled) return;
|
|
2442
|
-
if (this.parkedAt) return;
|
|
2443
|
-
this.playing = true;
|
|
2444
|
-
this.setPaused(false);
|
|
2445
|
-
this.startTicking();
|
|
2446
|
-
}
|
|
2447
|
-
advance() {
|
|
2448
|
-
if (this.ended || this.cancelled) return;
|
|
2449
|
-
const gate = this.parkedAt;
|
|
2450
|
-
if (gate) {
|
|
2451
|
-
gate.opened = true;
|
|
2452
|
-
this.parkedAt = null;
|
|
2453
|
-
clearTimeout(this.autoTimer);
|
|
2454
|
-
this.playing = true;
|
|
2455
|
-
this.setPaused(false);
|
|
2456
|
-
this.startTicking();
|
|
2457
|
-
return;
|
|
2458
|
-
}
|
|
2459
|
-
const next = this.gates.find((g) => !g.opened && g.at >= this.master);
|
|
2460
|
-
this.seekTo(next ? next.at : this.total);
|
|
2461
|
-
if (!next && this.master >= this.total && !this.standing) this.finish();
|
|
2462
|
-
}
|
|
2463
|
-
retreat() {
|
|
2464
|
-
if (this.cancelled) return false;
|
|
2465
|
-
const eps = 1e-6;
|
|
2466
|
-
const behind = this.gates.filter((g) => g.at < this.master - eps);
|
|
2467
|
-
const target = behind[behind.length - 1];
|
|
2468
|
-
if (!target) return false;
|
|
2469
|
-
clearTimeout(this.autoTimer);
|
|
2470
|
-
for (const g of this.gates) if (g.at >= target.at) g.opened = false;
|
|
2471
|
-
this.ended = false;
|
|
2472
|
-
this.master = Math.max(0, target.at - .5);
|
|
2473
|
-
this.playing = false;
|
|
2474
|
-
this.setPaused(true);
|
|
2475
|
-
this.evaluate();
|
|
2476
|
-
this.park(target, false);
|
|
2477
|
-
return true;
|
|
2478
|
-
}
|
|
2479
|
-
startTicking() {
|
|
2480
|
-
if (this.ticking || !this.playing || this.cancelled || this.ended) return;
|
|
2481
|
-
this.ticking = true;
|
|
2482
|
-
this.freshClock = !this.continuing;
|
|
2483
|
-
this.lastStamp = void 0;
|
|
2484
|
-
this.startedAt = time.now();
|
|
2485
|
-
frame.read(this.holdBack, !!this.options.maxFrameStep);
|
|
2486
|
-
frame.update(this.tick, true);
|
|
2487
|
-
}
|
|
2488
|
-
stopTicking() {
|
|
2489
|
-
if (this.ticking) {
|
|
2490
|
-
this.ticking = false;
|
|
2491
|
-
this.continuing = false;
|
|
2492
|
-
cancelFrame(this.tick);
|
|
2493
|
-
cancelFrame(this.holdBack);
|
|
2494
|
-
}
|
|
2495
|
-
}
|
|
2496
|
-
/** what one painted frame advances a running clock: the frame loop's delta, capped */
|
|
2497
|
-
frameStep(data) {
|
|
2498
|
-
const step = this.options.maxFrameStep;
|
|
2499
|
-
return step ? Math.min(data.delta, step) : data.delta;
|
|
2500
|
-
}
|
|
2501
|
-
/**
|
|
2502
|
-
* The fresh start and maxFrameStep for the animations themselves. The
|
|
2503
|
-
* run's own clock gets both in tick; the tweens and springs it started
|
|
2504
|
-
* run on motion-dom's frame clock, which takes the real time since their
|
|
2505
|
-
* start, so they would open and skip on their own. Before they update,
|
|
2506
|
-
* each one driven on the main thread has its start moved:
|
|
2507
|
-
*
|
|
2508
|
-
* - on the first frame the run paints, to this frame, less the progress
|
|
2509
|
-
* it had as the run started. A tween the pass began was dated from
|
|
2510
|
-
* motion-dom's clock, which holds one reading through a synchronous
|
|
2511
|
-
* stretch of work, so a pass late in a long one would date it back to
|
|
2512
|
-
* that reading and its first frame would show that much of it gone; it
|
|
2513
|
-
* opens at zero instead. A tween resuming with the run is dated from
|
|
2514
|
-
* the same reading less its held time, and keeps it. Every way the
|
|
2515
|
-
* clock stops (a pause, a gate, a seek) holds the run's tweens first,
|
|
2516
|
-
* and no gate stands inside a parallel, so no tween is still running
|
|
2517
|
-
* when the clock starts again. A `continuing` run moves them one
|
|
2518
|
-
* ordinary frame further, as its clock moves;
|
|
2519
|
-
* - after that, with a cap, on by the time past the cap since the last
|
|
2520
|
-
* frame: it resumes from where the last frame left it, plus one step.
|
|
2521
|
-
* Without a cap this runs on the first frame only.
|
|
2522
|
-
*
|
|
2523
|
-
* Animations on the compositor (WAAPI) start on the frame that commits
|
|
2524
|
-
* them and kept playing through a long frame; they are left alone.
|
|
2525
|
-
*/
|
|
2526
|
-
holdBack = (data) => {
|
|
2527
|
-
const step = this.options.maxFrameStep;
|
|
2528
|
-
const last = this.lastStamp;
|
|
2529
|
-
this.lastStamp = data.timestamp;
|
|
2530
|
-
const opening = last === void 0 && this.continuing ? this.frameStep(data) : 0;
|
|
2531
|
-
if (last === void 0) this.continuing = false;
|
|
2532
|
-
for (const t of this.tracks) for (const c of t.controls ?? []) {
|
|
2533
|
-
if (platformControlled.has(c)) continue;
|
|
2534
|
-
const inner = c._animation;
|
|
2535
|
-
if (!inner || !("animation" in inner) && !("startTime" in inner && "holdTime" in inner)) warnPrivateFieldsMoved();
|
|
2536
|
-
if (!inner || "animation" in inner || typeof inner.startTime !== "number" || inner.holdTime !== null) continue;
|
|
2537
|
-
if (last === void 0) {
|
|
2538
|
-
const progress = Math.max(0, this.startedAt - inner.startTime);
|
|
2539
|
-
inner.startTime = data.timestamp - progress - opening;
|
|
2540
|
-
} else if (step && data.timestamp - last > step) inner.startTime += data.timestamp - last - step;
|
|
2541
|
-
}
|
|
2542
|
-
};
|
|
2543
|
-
tick = (data) => {
|
|
2544
|
-
if (!this.playing || this.cancelled || this.ended) {
|
|
2545
|
-
this.stopTicking();
|
|
2546
|
-
return;
|
|
2547
|
-
}
|
|
2548
|
-
const delta = this.freshClock ? 0 : this.frameStep(data);
|
|
2549
|
-
this.freshClock = false;
|
|
2550
|
-
const next = this.master + delta * this.rate;
|
|
2551
|
-
const gate = this.gates.find((g) => !g.opened && g.at >= this.master && g.at <= next);
|
|
2552
|
-
if (gate) {
|
|
2553
|
-
this.master = gate.at;
|
|
2554
|
-
this.evaluate(gate.at);
|
|
2555
|
-
this.park(gate);
|
|
2556
|
-
return;
|
|
2557
|
-
}
|
|
2558
|
-
this.master = next;
|
|
2559
|
-
this.evaluate();
|
|
2560
|
-
for (const [sprite, end] of this.rowEnd) if (this.master >= end && !this.released.has(sprite)) {
|
|
2561
|
-
this.released.add(sprite);
|
|
2562
|
-
if (this.pending.delete(sprite)) this.options.onSpriteDone(sprite);
|
|
2563
|
-
}
|
|
2564
|
-
if (this.master >= this.total && !this.standing) this.finish();
|
|
2565
|
-
};
|
|
2566
|
-
park(gate, auto = true) {
|
|
2567
|
-
gate.opened = false;
|
|
2568
|
-
this.parkedAt = gate;
|
|
2569
|
-
this.playing = false;
|
|
2570
|
-
this.stopTicking();
|
|
2571
|
-
/**
|
|
2572
|
-
* HAND BACK THE LEAVERS, but only when nobody is left to open the gate.
|
|
2573
|
-
*
|
|
2574
|
-
* `pending` is removed sprites and nothing else — elements a <Presence>
|
|
2575
|
-
* is holding in the document only because this run undertook to see them
|
|
2576
|
-
* out. Parking stops the clock (above), so from here nothing advances:
|
|
2577
|
-
* every row end still ahead of `master` is unreachable, `onSpriteDone`
|
|
2578
|
-
* can never fire for it, and `finished` never resolves. The Presence
|
|
2579
|
-
* waits on a beat that is not coming.
|
|
2580
|
-
*
|
|
2581
|
-
* `doomed` is what separates that from an ordinary build, and the
|
|
2582
|
-
* distinction is real rather than a hedge. A gated build parks with the
|
|
2583
|
-
* same sprites pending and means it: the slide is still on screen, the
|
|
2584
|
-
* click is still coming, and the leaver is meant to fly out when it
|
|
2585
|
-
* arrives — releasing it there would make the item vanish instead, which
|
|
2586
|
-
* is the animation the registration exists to protect. A region where
|
|
2587
|
-
* every participant is leaving has no slide left to click on. Nothing
|
|
2588
|
-
* stays, so nothing can ask, and the gate is waiting on an event that
|
|
2589
|
-
* cannot happen.
|
|
2590
|
-
*
|
|
2591
|
-
* That is not hypothetical. Rack's score is a gate followed by one
|
|
2592
|
-
* parallel over sixty-one tiles, held still until its slider asks — so
|
|
2593
|
-
* filtering its card out of the gallery compiled a score that parked at
|
|
2594
|
-
* t=0 with all sixty-one of its participants pending and a clock that
|
|
2595
|
-
* never moved. Because <Presence> releases its leavers as a BATCH, those
|
|
2596
|
-
* sixty-one held all forty cards leaving beside them: under the default
|
|
2597
|
-
* mode the survivors never closed up, and under popLayout forty
|
|
2598
|
-
* invisible cards stayed lifted over the grid taking clicks meant for
|
|
2599
|
-
* the two you could see.
|
|
2600
|
-
*
|
|
2601
|
-
* A parked run is a STILL, in this file's own words — settled, not in
|
|
2602
|
-
* flight. A still is not an exit animation, so there is nothing here to
|
|
2603
|
-
* cut short. If the gate is ever opened the elements are simply gone,
|
|
2604
|
-
* which is what leaving means.
|
|
2605
|
-
*/
|
|
2606
|
-
if (this.options.doomed) for (const sprite of [...this.pending]) {
|
|
2607
|
-
this.pending.delete(sprite);
|
|
2608
|
-
this.options.onSpriteDone(sprite);
|
|
2609
|
-
}
|
|
2610
|
-
for (const t of this.tracks) if (t.started && !t.cue.loop && !t.cue.hold && t.end <= this.master) this.completeTrack(t);
|
|
2611
|
-
this.setPaused(true);
|
|
2612
|
-
this.scheduleRestill();
|
|
2613
|
-
if (auto && gate.auto !== void 0) this.autoTimer = setTimeout(() => {
|
|
2614
|
-
if (this.parkedAt === gate && !this.cancelled) this.advance();
|
|
2615
|
-
}, gate.auto / this.rate);
|
|
2616
|
-
}
|
|
2617
|
-
finish() {
|
|
2618
|
-
if (this.ended) return;
|
|
2619
|
-
this.ended = true;
|
|
2620
|
-
this.stopTicking();
|
|
2621
|
-
this.driveAttachments(this.master);
|
|
2622
|
-
this.options.onCamera?.({ ...this.camera });
|
|
2623
|
-
for (const t of this.tracks) if (t.started && !t.cue.loop && !t.cue.hold && !t.cue.delivery) this.completeTrack(t);
|
|
2624
|
-
this.releaseForMeasure();
|
|
2625
|
-
for (const sprite of [...this.pending]) {
|
|
2626
|
-
this.pending.delete(sprite);
|
|
2627
|
-
this.options.onSpriteDone(sprite);
|
|
2628
|
-
}
|
|
2629
|
-
this.resolveFinished();
|
|
2630
|
-
}
|
|
2631
|
-
setPaused(paused) {
|
|
2632
|
-
const now = this.master;
|
|
2633
|
-
for (const t of this.tracks) {
|
|
2634
|
-
if (!t.started) continue;
|
|
2635
|
-
const due = now >= t.start && (now < t.end || t.cue.loop);
|
|
2636
|
-
const run = !paused && due;
|
|
2637
|
-
t.controls?.forEach((c) => {
|
|
2638
|
-
if (run) {
|
|
2639
|
-
if (c.state === "running" || c.state === "paused") c.play();
|
|
2640
|
-
} else if (c.state === "running") c.pause();
|
|
2641
|
-
});
|
|
2642
|
-
if (t.delivery) if (paused && now >= t.end) t.delivery.complete();
|
|
2643
|
-
else (run ? t.delivery.play : t.delivery.pause)();
|
|
2644
|
-
if (t.loopAnimation) if (run) t.loopAnimation.play();
|
|
2645
|
-
else t.loopAnimation.pause();
|
|
2646
|
-
if (t.cameraAnimation) if (run) t.cameraAnimation.play();
|
|
2647
|
-
else t.cameraAnimation.pause();
|
|
2648
|
-
}
|
|
2649
|
-
}
|
|
2650
|
-
seekTo(target) {
|
|
2651
|
-
const gate = this.gates.find((g) => !g.opened && g.at >= this.master && g.at <= target);
|
|
2652
|
-
const clamped = Math.max(0, Math.min(gate ? gate.at : target, this.total));
|
|
2653
|
-
this.master = clamped;
|
|
2654
|
-
if (this.ended && clamped < this.total) this.ended = false;
|
|
2655
|
-
const wasPlaying = this.playing;
|
|
2656
|
-
this.playing = false;
|
|
2657
|
-
this.setPaused(true);
|
|
2658
|
-
this.reconstructCameraAt(gate ? gate.at : Infinity);
|
|
2659
|
-
this.evaluate(gate ? gate.at : Infinity);
|
|
2660
|
-
if (gate) {
|
|
2661
|
-
this.park(gate);
|
|
2662
|
-
return;
|
|
2663
|
-
}
|
|
2664
|
-
if (wasPlaying && !this.ended) {
|
|
2665
|
-
this.playing = true;
|
|
2666
|
-
this.setPaused(false);
|
|
2667
|
-
this.startTicking();
|
|
2668
|
-
return;
|
|
2669
|
-
}
|
|
2670
|
-
this.scheduleRestill();
|
|
2671
|
-
}
|
|
2672
|
-
/**
|
|
2673
|
-
* The one cost WAAPI acceleration charges a scrubbable run: a finished
|
|
2674
|
-
* accelerated animation commits its finals asynchronously, and that
|
|
2675
|
-
* commit can land AFTER a still's jump and overwrite it. So a still is
|
|
2676
|
-
* re-asserted on the two frames after it is entered — by then any
|
|
2677
|
-
* pending commit has landed, and the computed frame wins again.
|
|
2678
|
-
*/
|
|
2679
|
-
restillPending = 0;
|
|
2680
|
-
scheduleRestill() {
|
|
2681
|
-
if (this.restillPending > 0) return;
|
|
2682
|
-
this.restillPending = 2;
|
|
2683
|
-
const pass = () => {
|
|
2684
|
-
if (this.playing || this.cancelled) {
|
|
2685
|
-
this.restillPending = 0;
|
|
2686
|
-
return;
|
|
2687
|
-
}
|
|
2688
|
-
this.restill();
|
|
2689
|
-
this.restillPending -= 1;
|
|
2690
|
-
if (this.restillPending > 0) frame.postRender(pass);
|
|
2691
|
-
};
|
|
2692
|
-
frame.postRender(pass);
|
|
2693
|
-
}
|
|
2694
|
-
restill() {
|
|
2695
|
-
const now = this.master;
|
|
2696
|
-
const rewinds = [];
|
|
2697
|
-
for (const t of this.tracks) {
|
|
2698
|
-
const { cue } = t;
|
|
2699
|
-
if (!cue.sprite.node.visualElement || cue.camera || cue.tether) continue;
|
|
2700
|
-
if (!t.started && t.origin && now < t.start) rewinds.push(t);
|
|
2701
|
-
else if (t.started && !t.controls && !t.delivery && !t.loopAnimation && (cue.target || cue.flight) && now >= t.start && now < t.end) this.sampleStill(t, now);
|
|
2702
|
-
}
|
|
2703
|
-
this.rewind(rewinds, now);
|
|
2704
|
-
}
|
|
2705
|
-
evaluate(limit = Infinity) {
|
|
2706
|
-
const now = this.master;
|
|
2707
|
-
const rewinds = [];
|
|
2708
|
-
/**
|
|
2709
|
-
* The shot is FOLDED, not remembered.
|
|
2710
|
-
*
|
|
2711
|
-
* Every other cue kind owns an element and can be started and rewound
|
|
2712
|
-
* in place. A camera3d cue owns one shared triple, and per-cue state
|
|
2713
|
-
* does not survive that: seeking back from cue two to inside cue one
|
|
2714
|
-
* runs cue one's lerp (correct) and then cue two's rewind (which
|
|
2715
|
-
* restores the pose cue two INHERITED — cue one's end), and the
|
|
2716
|
-
* second write wins because it comes later in the list. The shot
|
|
2717
|
-
* ended up at the boundary value for every seek backwards.
|
|
2718
|
-
*
|
|
2719
|
-
* So it is recomputed from the score on every evaluate: start at the
|
|
2720
|
-
* pose the run inherited, walk the cues in order, and let each one
|
|
2721
|
-
* pass through, lerp, or land. A relative cue resolves against
|
|
2722
|
-
* whatever the walk has accumulated by the time it is reached, which
|
|
2723
|
-
* is precisely "the pose in force at cue start" — and it means a
|
|
2724
|
-
* direct seek is identical to having played there, by construction
|
|
2725
|
-
* rather than by bookkeeping.
|
|
2726
|
-
*/
|
|
2727
|
-
let shot = null;
|
|
2728
|
-
for (const t of this.tracks) {
|
|
2729
|
-
const { cue } = t;
|
|
2730
|
-
if (t.passed && now < t.end) {
|
|
2731
|
-
t.passed = false;
|
|
2732
|
-
if (now < t.start && t.origin) rewinds.push(t);
|
|
2733
|
-
}
|
|
2734
|
-
const fill = cue.hold?.fill ?? false;
|
|
2735
|
-
const inside = now >= t.start && t.start < limit && (now < t.end || cue.loop || fill);
|
|
2736
|
-
if (cue.camera) {
|
|
2737
|
-
if (inside && !t.started) {
|
|
2738
|
-
t.started = true;
|
|
2739
|
-
t.cameraFrom = { ...this.camera };
|
|
2740
|
-
const aimTo = cue.camera.origin ?? this.cameraAim ?? cue.camera.centre ?? {
|
|
2741
|
-
x: 0,
|
|
2742
|
-
y: 0
|
|
2743
|
-
};
|
|
2744
|
-
t.aimFrom = this.cameraAim ?? aimTo;
|
|
2745
|
-
t.aimTo = aimTo;
|
|
2746
|
-
this.cameraAim = aimTo;
|
|
2747
|
-
t.cameraTo = ChoreoRun.resolveCameraTo(cue.camera, t.cameraFrom);
|
|
2748
|
-
} else if (!inside && t.started && now < t.start) {
|
|
2749
|
-
t.started = false;
|
|
2750
|
-
t.cameraTo = void 0;
|
|
2751
|
-
t.cameraAnimation?.cancel();
|
|
2752
|
-
t.cameraAnimation = void 0;
|
|
2753
|
-
if (t.cameraFrom) {
|
|
2754
|
-
this.camera = { ...t.cameraFrom };
|
|
2755
|
-
this.cameraAim = t.aimFrom ?? null;
|
|
2756
|
-
t.cameraP = 0;
|
|
2757
|
-
this.applyCamera(t);
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
if (t.started && (now < t.end || !t.passed)) {
|
|
2761
|
-
const p = now >= t.end ? 1 : this.cameraProgress(t, now - t.start);
|
|
2762
|
-
const from = t.cameraFrom;
|
|
2763
|
-
const to = t.cameraTo ?? ChoreoRun.resolveCameraTo(cue.camera, from);
|
|
2764
|
-
t.cameraP = p;
|
|
2765
|
-
this.camera = {
|
|
2766
|
-
x: from.x + (to.x - from.x) * p,
|
|
2767
|
-
y: from.y + (to.y - from.y) * p,
|
|
2768
|
-
zoom: from.zoom + (to.zoom - from.zoom) * p
|
|
2769
|
-
};
|
|
2770
|
-
if (this.playing && now < t.end) {
|
|
2771
|
-
if (!t.cameraAnimation) this.startCameraAnimation(t, now);
|
|
2772
|
-
else if (t.cameraAnimation.playState === "paused") t.cameraAnimation.play();
|
|
2773
|
-
} else if (t.cameraAnimation) if (now >= t.end) this.dropCameraAnimation(t);
|
|
2774
|
-
else {
|
|
2775
|
-
t.cameraAnimation.pause();
|
|
2776
|
-
t.cameraAnimation.currentTime = Math.max(0, now - t.start);
|
|
2777
|
-
}
|
|
2778
|
-
this.applyCamera(t);
|
|
2779
|
-
if (now >= t.end && this.playing && !t.passed) {
|
|
2780
|
-
t.passed = true;
|
|
2781
|
-
this.options.onCamera?.({ ...this.camera });
|
|
2782
|
-
}
|
|
2783
|
-
}
|
|
2784
|
-
continue;
|
|
2785
|
-
}
|
|
2786
|
-
if (cue.camera3d) {
|
|
2787
|
-
const from = shot ?? { ...this.initial3d };
|
|
2788
|
-
const through = cue.camera3d.through;
|
|
2789
|
-
if (through?.length) {
|
|
2790
|
-
/**
|
|
2791
|
-
* A PATH: the pose in force and the waypoints are the control
|
|
2792
|
-
* points of a Catmull-Rom spline, sampled at the cue's eased
|
|
2793
|
-
* progress. One clock over the whole chain, so the camera
|
|
2794
|
-
* CROSSES each waypoint with continuous velocity instead of
|
|
2795
|
-
* parking at it — and it stays a pure function of the clock,
|
|
2796
|
-
* which no per-frame integrator can claim.
|
|
2797
|
-
*/
|
|
2798
|
-
if (now <= t.start) shot = from;
|
|
2799
|
-
else {
|
|
2800
|
-
const p = now >= t.end ? 1 : this.cameraProgress(t, now - t.start);
|
|
2801
|
-
const settle = cue.camera3d.settle;
|
|
2802
|
-
const span = t.end - t.start;
|
|
2803
|
-
shot = settle && span > 0 ? settleThrough(from, through, p, cue.camera3d.tension, settle * 1e3 / span) : sampleThrough(from, through, p, cue.camera3d.tension);
|
|
2804
|
-
}
|
|
2805
|
-
continue;
|
|
2806
|
-
}
|
|
2807
|
-
const want = cue.camera3d.to;
|
|
2808
|
-
const fromLook = from.look;
|
|
2809
|
-
const to = cue.camera3d.by ? {
|
|
2810
|
-
dolly: from.dolly * (want.dolly ?? 1),
|
|
2811
|
-
look: want.look ? {
|
|
2812
|
-
x: (fromLook?.x ?? 0) + want.look.x,
|
|
2813
|
-
y: (fromLook?.y ?? 0) + want.look.y,
|
|
2814
|
-
z: (fromLook?.z ?? 0) + want.look.z
|
|
2815
|
-
} : fromLook,
|
|
2816
|
-
pitch: from.pitch + (want.pitch ?? 0),
|
|
2817
|
-
x: from.x + (want.x ?? 0),
|
|
2818
|
-
y: from.y + (want.y ?? 0),
|
|
2819
|
-
yaw: from.yaw + (want.yaw ?? 0)
|
|
2820
|
-
} : {
|
|
2821
|
-
dolly: want.dolly ?? from.dolly,
|
|
2822
|
-
look: want.look ?? fromLook,
|
|
2823
|
-
pitch: want.pitch ?? from.pitch,
|
|
2824
|
-
x: want.x ?? from.x,
|
|
2825
|
-
y: want.y ?? from.y,
|
|
2826
|
-
yaw: want.yaw ?? from.yaw
|
|
2827
|
-
};
|
|
2828
|
-
if (now <= t.start) shot = from;
|
|
2829
|
-
else {
|
|
2830
|
-
const p = now >= t.end ? 1 : this.cameraProgress(t, now - t.start);
|
|
2831
|
-
shot = {
|
|
2832
|
-
dolly: from.dolly + (to.dolly - from.dolly) * p,
|
|
2833
|
-
pitch: from.pitch + (to.pitch - from.pitch) * p,
|
|
2834
|
-
x: from.x + (to.x - from.x) * p,
|
|
2835
|
-
y: from.y + (to.y - from.y) * p,
|
|
2836
|
-
yaw: from.yaw + (to.yaw - from.yaw) * p
|
|
2837
|
-
};
|
|
2838
|
-
if (to.look || fromLook) {
|
|
2839
|
-
const a = fromLook ?? {
|
|
2840
|
-
x: 0,
|
|
2841
|
-
y: 0,
|
|
2842
|
-
z: 0
|
|
2843
|
-
};
|
|
2844
|
-
const b = to.look ?? a;
|
|
2845
|
-
shot.look = {
|
|
2846
|
-
x: a.x + (b.x - a.x) * p,
|
|
2847
|
-
y: a.y + (b.y - a.y) * p,
|
|
2848
|
-
z: a.z + (b.z - a.z) * p
|
|
2849
|
-
};
|
|
2850
|
-
}
|
|
2851
|
-
}
|
|
2852
|
-
continue;
|
|
2853
|
-
}
|
|
2854
|
-
if (cue.tether) {
|
|
2855
|
-
if (inside && !t.started) {
|
|
2856
|
-
t.started = true;
|
|
2857
|
-
const layer = this.options.tetherLayer;
|
|
2858
|
-
if (layer) {
|
|
2859
|
-
t.wire = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
2860
|
-
t.wire.setAttribute("data-choreo-tether", "");
|
|
2861
|
-
if (t.cue.tether?.name) t.wire.setAttribute("data-thread", t.cue.tether.name);
|
|
2862
|
-
layer.appendChild(t.wire);
|
|
2863
|
-
}
|
|
2864
|
-
} else if (!inside && t.started) {
|
|
2865
|
-
t.started = false;
|
|
2866
|
-
t.wire?.remove();
|
|
2867
|
-
t.wire = void 0;
|
|
2868
|
-
}
|
|
2869
|
-
if (t.started && t.wire) this.scheduleTetherDraw();
|
|
2870
|
-
continue;
|
|
2871
|
-
}
|
|
2872
|
-
if (cue.derive) {
|
|
2873
|
-
if (inside && !t.started) {
|
|
2874
|
-
t.started = true;
|
|
2875
|
-
const ve = cue.sprite.node.visualElement;
|
|
2876
|
-
if (ve) for (const [key, rest] of Object.entries(cue.derive.rest)) this.movedValues.push({
|
|
2877
|
-
key,
|
|
2878
|
-
rest,
|
|
2879
|
-
ve
|
|
2880
|
-
});
|
|
2881
|
-
} else if (!inside && t.started) {
|
|
2882
|
-
t.started = false;
|
|
2883
|
-
this.restDerived(t);
|
|
2884
|
-
}
|
|
2885
|
-
if (t.started) this.drive(t, now);
|
|
2886
|
-
continue;
|
|
2887
|
-
}
|
|
2888
|
-
if (cue.raise) {
|
|
2889
|
-
if (inside && !t.started) {
|
|
2890
|
-
t.started = true;
|
|
2891
|
-
this.promote(t);
|
|
2892
|
-
} else if (!inside && t.started) {
|
|
2893
|
-
t.started = false;
|
|
2894
|
-
this.restore(t);
|
|
2895
|
-
}
|
|
2896
|
-
continue;
|
|
2897
|
-
}
|
|
2898
|
-
if (cue.scroll) {
|
|
2899
|
-
if (inside && !t.started) {
|
|
2900
|
-
t.started = true;
|
|
2901
|
-
this.startScroll(t);
|
|
2902
|
-
} else if (!inside && t.started && now < t.start) {
|
|
2903
|
-
t.started = false;
|
|
2904
|
-
this.stopScroll(t, true);
|
|
2905
|
-
}
|
|
2906
|
-
if (t.started && t.scrolling) {
|
|
2907
|
-
const p = this.flightlessProgress(t, now - t.start);
|
|
2908
|
-
const { container, from, to } = t.scrolling;
|
|
2909
|
-
container.scrollTop = from.top + (to.top - from.top) * p;
|
|
2910
|
-
container.scrollLeft = from.left + (to.left - from.left) * p;
|
|
2911
|
-
if (p >= 1 && this.playing) this.stopScroll(t, false);
|
|
2912
|
-
}
|
|
2913
|
-
continue;
|
|
2914
|
-
}
|
|
2915
|
-
if (cue.hold) {
|
|
2916
|
-
if (inside && !t.started) {
|
|
2917
|
-
t.started = true;
|
|
2918
|
-
const ve = cue.sprite.node.visualElement;
|
|
2919
|
-
if (ve) t.held = applyHold(ve, cue.sprite.element, cue.hold.values);
|
|
2920
|
-
} else if (!inside && t.started) {
|
|
2921
|
-
t.started = false;
|
|
2922
|
-
const ve = cue.sprite.node.visualElement;
|
|
2923
|
-
if (ve && t.held) {
|
|
2924
|
-
releaseHold(ve, cue.sprite.element, t.held);
|
|
2925
|
-
t.held = void 0;
|
|
2926
|
-
}
|
|
2927
|
-
}
|
|
2928
|
-
continue;
|
|
2929
|
-
}
|
|
2930
|
-
if (cue.kind === "wait") continue;
|
|
2931
|
-
if (inside && !t.started) this.startTrack(t);
|
|
2932
|
-
else if (inside && t.started && this.playing && !t.controls && !t.delivery && !t.loopAnimation && (cue.target || cue.flight)) this.startTrack(t);
|
|
2933
|
-
else if (!inside && t.started && now < t.start) {
|
|
2934
|
-
t.passed = false;
|
|
2935
|
-
t.started = false;
|
|
2936
|
-
flushKeyframeResolvers();
|
|
2937
|
-
this.stopTrack(t);
|
|
2938
|
-
t.delivery?.cancel();
|
|
2939
|
-
t.delivery = void 0;
|
|
2940
|
-
t.loopAnimation?.cancel();
|
|
2941
|
-
t.loopAnimation = void 0;
|
|
2942
|
-
if (t.origin) rewinds.push(t);
|
|
2943
|
-
} else if (t.started && now >= t.end && !cue.loop && !this.playing) this.completeTrack(t);
|
|
2944
|
-
else if (!t.started && !t.passed && now >= t.end && !cue.loop) this.jumpFinals(t);
|
|
2945
|
-
if (t.started && !this.playing && now >= t.start) {
|
|
2946
|
-
if (t.delivery) {
|
|
2947
|
-
t.delivery.pause();
|
|
2948
|
-
t.delivery.seek(now - t.start);
|
|
2949
|
-
} else if (t.loopAnimation) {
|
|
2950
|
-
t.loopAnimation.pause();
|
|
2951
|
-
const cycle = t.end - t.start;
|
|
2952
|
-
t.loopAnimation.currentTime = cycle ? (now - t.start + (t.loopOffset ?? 0)) % cycle : 0;
|
|
2953
|
-
} else if (cue.target || cue.flight) {
|
|
2954
|
-
if (t.controls) {
|
|
2955
|
-
flushKeyframeResolvers();
|
|
2956
|
-
this.stopTrack(t);
|
|
2957
|
-
}
|
|
2958
|
-
this.sampleStill(t, now);
|
|
2959
|
-
}
|
|
2960
|
-
}
|
|
2961
|
-
}
|
|
2962
|
-
if (shot) {
|
|
2963
|
-
const was = this.camera3d;
|
|
2964
|
-
if (was.yaw !== shot.yaw || was.pitch !== shot.pitch || was.dolly !== shot.dolly || was.x !== shot.x || was.y !== shot.y || was.look?.x !== shot.look?.x || was.look?.y !== shot.look?.y || was.look?.z !== shot.look?.z) {
|
|
2965
|
-
this.camera3d = shot;
|
|
2966
|
-
this.options.onCamera3D?.({ ...shot });
|
|
2967
|
-
}
|
|
2968
|
-
}
|
|
2969
|
-
this.rewind(rewinds, now);
|
|
2970
|
-
this.driveAttachments(now);
|
|
2971
|
-
this.foldPerforms(limit);
|
|
2972
|
-
}
|
|
2973
|
-
/** perform tracks whose commands the host currently holds (see foldPerforms) */
|
|
2974
|
-
performed = /* @__PURE__ */ new Set();
|
|
2975
|
-
/** dispatches queued for after the render pass, in fold order */
|
|
2976
|
-
pendingPerforms = [];
|
|
2977
|
-
performFlushBooked = false;
|
|
2978
|
-
/**
|
|
2979
|
-
* The command fold (§C4): the set of Perform cues at or before the
|
|
2980
|
-
* clock IS the commanded state. Every evaluate — a play tick and a seek
|
|
2981
|
-
* alike — re-derives the eligible set; growth dispatches the new
|
|
2982
|
-
* commands in time order, and any shrink (a backward seek) resets the
|
|
2983
|
-
* host first and replays the whole remaining prefix. Commands are
|
|
2984
|
-
* idempotent statements of state by contract (`lamp.on`, never a
|
|
2985
|
-
* toggle), which is exactly what makes the replay a re-derivation.
|
|
2986
|
-
*
|
|
2987
|
-
* Dispatches are DEFERRED past the render pass: the constructor's first
|
|
2988
|
-
* evaluate runs while Glimmer may still be rendering, and a command
|
|
2989
|
-
* exists to mutate application state. A reset collapses the queue — the
|
|
2990
|
-
* dropped dispatches were never seen, and the replay that follows
|
|
2991
|
-
* restates everything still standing.
|
|
2992
|
-
*/
|
|
2993
|
-
foldPerforms(limit) {
|
|
2994
|
-
if (!this.options.onPerform && !this.options.onPerformReset) return;
|
|
2995
|
-
const now = this.master;
|
|
2996
|
-
const eligible = this.tracks.filter((t) => t.cue.perform && now >= t.start && t.start < limit).sort((a, b) => a.start - b.start);
|
|
2997
|
-
const held = new Set(eligible);
|
|
2998
|
-
if ([...this.performed].some((t) => !held.has(t))) {
|
|
2999
|
-
this.performed.clear();
|
|
3000
|
-
this.pendingPerforms.length = 0;
|
|
3001
|
-
this.pendingPerforms.push("reset");
|
|
3002
|
-
}
|
|
3003
|
-
for (const t of eligible) {
|
|
3004
|
-
if (this.performed.has(t)) continue;
|
|
3005
|
-
this.performed.add(t);
|
|
3006
|
-
const p = t.cue.perform;
|
|
3007
|
-
this.pendingPerforms.push({
|
|
3008
|
-
action: p.action,
|
|
3009
|
-
payload: p.payload,
|
|
3010
|
-
target: p.target,
|
|
3011
|
-
time: t.start / this.scale / 1e3
|
|
3012
|
-
});
|
|
3013
|
-
}
|
|
3014
|
-
if (this.pendingPerforms.length && !this.performFlushBooked) {
|
|
3015
|
-
this.performFlushBooked = true;
|
|
3016
|
-
frame.postRender(() => {
|
|
3017
|
-
this.performFlushBooked = false;
|
|
3018
|
-
const queue = this.pendingPerforms;
|
|
3019
|
-
this.pendingPerforms = [];
|
|
3020
|
-
for (const item of queue) if (item === "reset") this.options.onPerformReset?.();
|
|
3021
|
-
else this.options.onPerform?.(item);
|
|
3022
|
-
});
|
|
3023
|
-
}
|
|
3024
|
-
}
|
|
3025
|
-
/**
|
|
3026
|
-
* Stand rewound tracks back on their origins — the part of a backward
|
|
3027
|
-
* seek that must be ORDERED. A sprite with sequential cues has one
|
|
3028
|
-
* origin per cue, each equal to the previous cue's landing; restored
|
|
3029
|
-
* in track order they clobber forward and the sprite ends up standing
|
|
3030
|
-
* on its LAST future cue's origin (the Playhead demo's hand parked on
|
|
3031
|
-
* 'place' after a scrub to zero; its receipt refusing to dismiss). So:
|
|
3032
|
-
* latest-first, which leaves the EARLIEST future cue's origin — the
|
|
3033
|
-
* value the timeline actually holds at `now` — standing; and a key
|
|
3034
|
-
* that any track AT or BEFORE `now` writes is not touched at all,
|
|
3035
|
-
* because that track's own sample or landing is the answer.
|
|
3036
|
-
*/
|
|
3037
|
-
rewind(rewinds, now) {
|
|
3038
|
-
rewinds.sort((a, b) => b.start - a.start);
|
|
3039
|
-
for (const t of rewinds) {
|
|
3040
|
-
const ve = t.cue.sprite.node.visualElement;
|
|
3041
|
-
if (!ve || !t.origin) continue;
|
|
3042
|
-
let wrote = false;
|
|
3043
|
-
for (const key in t.origin) if (!this.tracks.some((s) => s !== t && s.start <= now && s.cue.target !== void 0 && key in s.cue.target && s.cue.sprite.node.visualElement === ve)) {
|
|
3044
|
-
ve.getValue(key, t.origin[key]).jump(t.origin[key]);
|
|
3045
|
-
wrote = true;
|
|
3046
|
-
}
|
|
3047
|
-
if (wrote) ve.render();
|
|
3048
|
-
}
|
|
3049
|
-
}
|
|
3050
|
-
/** the eased progress of a plain clock-driven track */
|
|
3051
|
-
flightlessProgress(t, ms) {
|
|
3052
|
-
if (this.reduced) return ms > 0 ? 1 : 0;
|
|
3053
|
-
const span = t.end - t.start;
|
|
3054
|
-
const raw = span > 0 ? Math.min(1, Math.max(0, ms / span)) : 1;
|
|
3055
|
-
return easingDefinitionToFunction("easeInOut")(raw);
|
|
3056
|
-
}
|
|
3057
|
-
/**
|
|
3058
|
-
* The orbit pose in force. Public for the same reason `camera` is: it is
|
|
3059
|
-
* hand-off state, and a replacement run must continue from where this
|
|
3060
|
-
* one left the shot rather than snapping back to the framing.
|
|
3061
|
-
*/
|
|
3062
|
-
camera3d;
|
|
3063
|
-
initial3d;
|
|
3064
|
-
camera;
|
|
3065
|
-
/**
|
|
3066
|
-
* The aim point P in force, local px. With transform-origin pinned at
|
|
3067
|
-
* 0 0, the applied transform is translate(x + (1−z)·P) scale(z) — the
|
|
3068
|
-
* frame's centre cancels out of the algebra entirely, so neither a
|
|
3069
|
-
* board that reflows mid-cue nor a stage that changes height between
|
|
3070
|
-
* cues can move the picture: the formula reads no live DOM at all.
|
|
3071
|
-
* z = 1 is the identity for any P. Public because it is hand-off state:
|
|
3072
|
-
* the next run lerps from the point THIS run left aimed, exactly as it
|
|
3073
|
-
* inherits the camera.
|
|
3074
|
-
*/
|
|
3075
|
-
cameraAim = null;
|
|
3076
|
-
/**
|
|
3077
|
-
* The absolute pose a camera cue lands on, resolved against the pose it
|
|
3078
|
-
* starts from. Absolute fields pass through; missing fields hold; a
|
|
3079
|
-
* relative cue (Pan / SlowZoom) offsets and multiplies the pose in
|
|
3080
|
-
* force — which is why resolution happens AT START (live) or during the
|
|
3081
|
-
* prefix fold (reconstruction), never at compile.
|
|
3082
|
-
*/
|
|
3083
|
-
static resolveCameraTo(cue, from) {
|
|
3084
|
-
const { by, to } = cue;
|
|
3085
|
-
return {
|
|
3086
|
-
x: by?.x !== void 0 ? from.x + by.x : to.x ?? from.x,
|
|
3087
|
-
y: by?.y !== void 0 ? from.y + by.y : to.y ?? from.y,
|
|
3088
|
-
zoom: by?.zoom !== void 0 ? from.zoom * by.zoom : to.zoom ?? from.zoom
|
|
3089
|
-
};
|
|
3090
|
-
}
|
|
3091
|
-
cameraProgress(t, ms) {
|
|
3092
|
-
if (this.reduced) return ms > 0 ? 1 : 0;
|
|
3093
|
-
const span = t.end - t.start;
|
|
3094
|
-
const raw = span > 0 ? Math.min(1, Math.max(0, ms / span)) : 1;
|
|
3095
|
-
const transition = t.cue.transition;
|
|
3096
|
-
if (isSpring(transition)) return spring({
|
|
3097
|
-
keyframes: [0, 100],
|
|
3098
|
-
...transition ?? {}
|
|
3099
|
-
}).next(ms / this.scale).value / 100;
|
|
3100
|
-
return easingDefinitionToFunction(transition?.ease ?? "easeInOut")(raw);
|
|
3101
|
-
}
|
|
3102
|
-
/**
|
|
3103
|
-
* The camera and aim this run inherited, frozen at construction — the
|
|
3104
|
-
* fold origin every reconstruction starts from. Public because a
|
|
3105
|
-
* replacement run that re-executes the SAME score must inherit this
|
|
3106
|
-
* origin, not the pose in force: the pose in force is what the score's
|
|
3107
|
-
* prefix already produced, and folding the prefix from it applies every
|
|
3108
|
-
* relative cue twice (the world-dock law).
|
|
3109
|
-
*/
|
|
3110
|
-
initialCamera;
|
|
3111
|
-
initialAim;
|
|
3112
|
-
/**
|
|
3113
|
-
* Rebuild the camera fold from the score prefix before a seek's still
|
|
3114
|
-
* (packages/choreo-gallery/realm/design/external-clock-camera-seek-handoff.md). Forward playback folds
|
|
3115
|
-
* each camera cue's landing into the run's cumulative camera as the
|
|
3116
|
-
* clock crosses it — but a random-access seek can jump clean over a
|
|
3117
|
-
* window, and a cue that never starts never folds: the clock reads `t`
|
|
3118
|
-
* while the picture holds an earlier shot. So every camera track's
|
|
3119
|
-
* bookkeeping (started, cameraFrom, aimFrom/aimTo, cameraP) is
|
|
3120
|
-
* re-derived here in timeline order from the run's initial camera;
|
|
3121
|
-
* evaluate() then recomputes exactly the numbers forward playback would
|
|
3122
|
-
* have produced, and play-after-scrub resumes from them. Pure
|
|
3123
|
-
* arithmetic over frozen numbers, like the rest of the camera: no DOM
|
|
3124
|
-
* is read, so backward and repeated seeks agree to the pixel.
|
|
3125
|
-
*/
|
|
3126
|
-
reconstructCameraAt(limit) {
|
|
3127
|
-
const cams = this.tracks.filter((t) => t.cue.camera);
|
|
3128
|
-
if (!cams.length) return;
|
|
3129
|
-
const now = this.master;
|
|
3130
|
-
cams.sort((a, b) => a.start - b.start);
|
|
3131
|
-
const state = { ...this.initialCamera };
|
|
3132
|
-
let aim = this.initialAim ? { ...this.initialAim } : null;
|
|
3133
|
-
for (const t of cams) {
|
|
3134
|
-
if (!(now >= t.start && t.start < limit)) {
|
|
3135
|
-
t.started = false;
|
|
3136
|
-
t.passed = false;
|
|
3137
|
-
t.cameraP = 0;
|
|
3138
|
-
t.cameraTo = void 0;
|
|
3139
|
-
t.aimFrom = aim ?? void 0;
|
|
3140
|
-
t.aimTo = aim ?? void 0;
|
|
3141
|
-
t.cameraAnimation?.cancel();
|
|
3142
|
-
t.cameraAnimation = void 0;
|
|
3143
|
-
continue;
|
|
3144
|
-
}
|
|
3145
|
-
const cue = t.cue.camera;
|
|
3146
|
-
const aimTo = cue.origin ?? aim ?? cue.centre ?? {
|
|
3147
|
-
x: 0,
|
|
3148
|
-
y: 0
|
|
3149
|
-
};
|
|
3150
|
-
t.started = true;
|
|
3151
|
-
t.passed = false;
|
|
3152
|
-
t.cameraFrom = { ...state };
|
|
3153
|
-
t.cameraTo = ChoreoRun.resolveCameraTo(cue, t.cameraFrom);
|
|
3154
|
-
t.aimFrom = aim ?? aimTo;
|
|
3155
|
-
t.aimTo = aimTo;
|
|
3156
|
-
aim = aimTo;
|
|
3157
|
-
if (now >= t.end) {
|
|
3158
|
-
state.x = t.cameraTo.x;
|
|
3159
|
-
state.y = t.cameraTo.y;
|
|
3160
|
-
state.zoom = t.cameraTo.zoom;
|
|
3161
|
-
t.cameraP = 1;
|
|
3162
|
-
t.cameraAnimation?.cancel();
|
|
3163
|
-
t.cameraAnimation = void 0;
|
|
3164
|
-
}
|
|
3165
|
-
}
|
|
3166
|
-
this.camera = state;
|
|
3167
|
-
this.cameraAim = aim;
|
|
3168
|
-
if (!cams.some((t) => t.started)) this.applyCamera(cams[0]);
|
|
3169
|
-
}
|
|
3170
|
-
/**
|
|
3171
|
-
* The damped counter-scale (§6.4): steady sprites scale with the host but
|
|
3172
|
-
* not 1:1 — pow(z, .30) zoomed out so they stay readable, pow(z, .70)
|
|
3173
|
-
* zoomed in so they don't feel stuck, clamped to what the eye tolerates.
|
|
3174
|
-
*/
|
|
3175
|
-
static damped(zoom) {
|
|
3176
|
-
return Math.min(1.8, Math.max(.85, Math.pow(zoom, zoom < 1 ? .3 : .7))) / zoom;
|
|
3177
|
-
}
|
|
3178
|
-
/**
|
|
3179
|
-
* The frame's APPLIED transform for a camera state at aim progress `p`.
|
|
3180
|
-
*
|
|
3181
|
-
* Transform-origin is pinned at 0 0, so the applied transform is
|
|
3182
|
-
* translate(x + (1−z)·P) scale(z) with P the lerped aim point — pure
|
|
3183
|
-
* arithmetic over frozen numbers. Nothing here reads the DOM, so a board
|
|
3184
|
-
* that reflows mid-cue cannot move the camera, and every boundary
|
|
3185
|
-
* (landing, re-aim, next run) agrees to the pixel. At z = 1 the aim term
|
|
3186
|
-
* vanishes: an unpanned camera is EXACTLY the identity.
|
|
3187
|
-
*/
|
|
3188
|
-
appliedCamera(t, state, p) {
|
|
3189
|
-
const from = t.aimFrom ?? t.aimTo ?? {
|
|
3190
|
-
x: 0,
|
|
3191
|
-
y: 0
|
|
3192
|
-
};
|
|
3193
|
-
const to = t.aimTo ?? from;
|
|
3194
|
-
const aim = {
|
|
3195
|
-
x: from.x + (to.x - from.x) * p,
|
|
3196
|
-
y: from.y + (to.y - from.y) * p
|
|
3197
|
-
};
|
|
3198
|
-
return {
|
|
3199
|
-
x: state.x + (1 - state.zoom) * aim.x,
|
|
3200
|
-
y: state.y + (1 - state.zoom) * aim.y,
|
|
3201
|
-
zoom: state.zoom
|
|
3202
|
-
};
|
|
3203
|
-
}
|
|
3204
|
-
static cameraCss(a) {
|
|
3205
|
-
return a.zoom === 1 && a.x === 0 && a.y === 0 ? "" : `translate(${a.x}px, ${a.y}px) scale(${a.zoom})`;
|
|
3206
|
-
}
|
|
3207
|
-
/**
|
|
3208
|
-
* Fly the region's frame on the platform: two transform keyframes and the
|
|
3209
|
-
* eased clock pre-sampled into a linear() easing. The biggest layer in the
|
|
3210
|
-
* region composites off the main thread for the whole move.
|
|
3211
|
-
*/
|
|
3212
|
-
startCameraAnimation(t, now) {
|
|
3213
|
-
const host = this.options.cameraFrame;
|
|
3214
|
-
const from = t.cameraFrom;
|
|
3215
|
-
const cue = t.cue.camera;
|
|
3216
|
-
if (!host || !from || !cue) return;
|
|
3217
|
-
const final = t.cameraTo ?? ChoreoRun.resolveCameraTo(cue, from);
|
|
3218
|
-
const span = Math.max(1, t.end - t.start);
|
|
3219
|
-
const anim = host.animate([{ transform: ChoreoRun.cameraCss(this.appliedCamera(t, from, 0)) || "none" }, { transform: ChoreoRun.cameraCss(this.appliedCamera(t, final, 1)) || "none" }], {
|
|
3220
|
-
duration: span,
|
|
3221
|
-
easing: generateLinearEasing((p) => this.cameraProgress(t, p * span), span),
|
|
3222
|
-
fill: "both"
|
|
3223
|
-
});
|
|
3224
|
-
anim.playbackRate = this.rate;
|
|
3225
|
-
anim.currentTime = Math.max(0, now - t.start);
|
|
3226
|
-
t.cameraAnimation = anim;
|
|
3227
|
-
}
|
|
3228
|
-
/**
|
|
3229
|
-
* Retire the frame's platform animation and hand the picture back to
|
|
3230
|
-
* inline style, written from the shadow state — so a cancel mid-zoom
|
|
3231
|
-
* freezes exactly where the eye was, and a landing holds its final.
|
|
3232
|
-
*/
|
|
3233
|
-
dropCameraAnimation(t) {
|
|
3234
|
-
if (!t.cameraAnimation) return;
|
|
3235
|
-
t.cameraAnimation.cancel();
|
|
3236
|
-
t.cameraAnimation = void 0;
|
|
3237
|
-
this.applyCamera(t);
|
|
3238
|
-
}
|
|
3239
|
-
applyCamera(t) {
|
|
3240
|
-
const frame = this.options.cameraFrame;
|
|
3241
|
-
if (!frame) return;
|
|
3242
|
-
const { zoom } = this.camera;
|
|
3243
|
-
frame.style.transformOrigin = "0px 0px";
|
|
3244
|
-
if (!t.cameraAnimation) frame.style.transform = ChoreoRun.cameraCss(this.appliedCamera(t, this.camera, t.cameraP ?? 1));
|
|
3245
|
-
for (const sprite of t.cue.camera?.steady ?? []) {
|
|
3246
|
-
const ve = sprite.node.visualElement;
|
|
3247
|
-
if (ve) {
|
|
3248
|
-
const counter = ChoreoRun.damped(zoom);
|
|
3249
|
-
ve.getValue("scale", counter).set(counter);
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
}
|
|
3253
|
-
tetherDrawScheduled = false;
|
|
3254
|
-
scheduleTetherDraw() {
|
|
3255
|
-
if (this.tetherDrawScheduled) return;
|
|
3256
|
-
this.tetherDrawScheduled = true;
|
|
3257
|
-
frame.postRender(() => {
|
|
3258
|
-
this.tetherDrawScheduled = false;
|
|
3259
|
-
for (const t of this.tracks) if (t.started && t.wire) this.drawTether(t);
|
|
3260
|
-
});
|
|
3261
|
-
}
|
|
3262
|
-
/**
|
|
3263
|
-
* One frame of a derived value (§4.10): compose the context from the
|
|
3264
|
-
* pass's measurements, hand it to the author's function, write what
|
|
3265
|
-
* comes back.
|
|
3266
|
-
*
|
|
3267
|
-
* Nothing here touches the DOM — that is the design, not an
|
|
3268
|
-
* optimisation (packages/choreo-gallery/realm/docs/postmortem-follow.md). The resting boxes were
|
|
3269
|
-
* measured by the pass with every moved value released, and a source's
|
|
3270
|
-
* `now` is its resting box composed with the motion values driving it
|
|
3271
|
-
* this frame: JS-side numbers, not a measurement. So a follower is pure
|
|
3272
|
-
* BY CONSTRUCTION — there is no live box in reach, it cannot read back
|
|
3273
|
-
* its own output, and it cannot force a style recalculation in the
|
|
3274
|
-
* middle of a move. It is also correct under INTERRUPTION for free: a
|
|
3275
|
-
* replacement run's pass re-measures, so a run born mid-flight computes
|
|
3276
|
-
* from rests that are right immediately, with no "last frame" to
|
|
3277
|
-
* disagree with.
|
|
3278
|
-
*
|
|
3279
|
-
* `set`, not an animation: a derived value IS the frame, so there is
|
|
3280
|
-
* nothing to interpolate toward and nothing the compositor could be
|
|
3281
|
-
* given — this is the main-thread cost the step charges, and the reason
|
|
3282
|
-
* it is the same cost `c.Tether` already pays.
|
|
3283
|
-
*/
|
|
3284
|
-
drive(t, now) {
|
|
3285
|
-
const derive = t.cue.derive;
|
|
3286
|
-
const ve = t.cue.sprite.node.visualElement;
|
|
3287
|
-
if (!derive || !ve) return;
|
|
3288
|
-
const sources = derive.sources.map(({ from, sprite, to }) => {
|
|
3289
|
-
const sv = sprite.node.visualElement;
|
|
3290
|
-
const num = (key) => {
|
|
3291
|
-
const value = sv?.getValue(key)?.get();
|
|
3292
|
-
return typeof value === "number" ? value : void 0;
|
|
3293
|
-
};
|
|
3294
|
-
const sx = num("scaleX") ?? num("scale") ?? 1;
|
|
3295
|
-
const sy = num("scaleY") ?? num("scale") ?? 1;
|
|
3296
|
-
const width = to.width * sx;
|
|
3297
|
-
const height = to.height * sy;
|
|
3298
|
-
return {
|
|
3299
|
-
from,
|
|
3300
|
-
now: {
|
|
3301
|
-
height,
|
|
3302
|
-
width,
|
|
3303
|
-
x: to.x + (num("x") ?? 0) + (to.width - width) / 2,
|
|
3304
|
-
y: to.y + (num("y") ?? 0) + (to.height - height) / 2
|
|
3305
|
-
},
|
|
3306
|
-
to
|
|
3307
|
-
};
|
|
3308
|
-
});
|
|
3309
|
-
const span = t.end - t.start;
|
|
3310
|
-
const values = derive.read({
|
|
3311
|
-
camera: { ...this.camera },
|
|
3312
|
-
p: span > 0 ? Math.max(0, Math.min(1, (now - t.start) / span)) : 1,
|
|
3313
|
-
rest: { ...derive.restBox },
|
|
3314
|
-
sources,
|
|
3315
|
-
t: now / 1e3
|
|
3316
|
-
});
|
|
3317
|
-
for (const [key, value] of Object.entries(values)) ve.getValue(key, value).set(value);
|
|
3318
|
-
ve.render();
|
|
3319
|
-
}
|
|
3320
|
-
/** the window closed (or was scrubbed out of): put the declared rest back */
|
|
3321
|
-
restDerived(t) {
|
|
3322
|
-
const rest = t.cue.derive?.rest;
|
|
3323
|
-
const ve = t.cue.sprite.node.visualElement;
|
|
3324
|
-
if (!rest || !ve) return;
|
|
3325
|
-
for (const [key, value] of Object.entries(rest)) ve.getValue(key, value).jump(value);
|
|
3326
|
-
ve.render();
|
|
3327
|
-
}
|
|
3328
|
-
drawTether(t) {
|
|
3329
|
-
const layer = this.options.tetherLayer;
|
|
3330
|
-
const tether = t.cue.tether;
|
|
3331
|
-
if (!layer || !tether || !t.wire) return;
|
|
3332
|
-
const inverse = layer.getScreenCTM()?.inverse();
|
|
3333
|
-
const box = layer.getBoundingClientRect();
|
|
3334
|
-
const toLocal = (clientX, clientY) => {
|
|
3335
|
-
if (!inverse) return {
|
|
3336
|
-
x: clientX - box.left,
|
|
3337
|
-
y: clientY - box.top
|
|
3338
|
-
};
|
|
3339
|
-
const p = new DOMPoint(clientX, clientY).matrixTransform(inverse);
|
|
3340
|
-
return {
|
|
3341
|
-
x: p.x,
|
|
3342
|
-
y: p.y
|
|
3343
|
-
};
|
|
3344
|
-
};
|
|
3345
|
-
const rectOf = (sprite) => {
|
|
3346
|
-
const el = sprite?.element;
|
|
3347
|
-
if (!el?.isConnected) return null;
|
|
3348
|
-
const r = el.getBoundingClientRect();
|
|
3349
|
-
const tl = toLocal(r.left, r.top);
|
|
3350
|
-
const br = toLocal(r.right, r.bottom);
|
|
3351
|
-
return {
|
|
3352
|
-
height: br.y - tl.y,
|
|
3353
|
-
width: br.x - tl.x,
|
|
3354
|
-
x: tl.x,
|
|
3355
|
-
y: tl.y
|
|
3356
|
-
};
|
|
3357
|
-
};
|
|
3358
|
-
const a = rectOf(tether.from);
|
|
3359
|
-
const b = rectOf(tether.to);
|
|
3360
|
-
if (a && b) t.wire.setAttribute("d", tether.path(a, b));
|
|
3361
|
-
}
|
|
3362
|
-
/**
|
|
3363
|
-
* The scale between the layer's own pixels and the screen's, per axis.
|
|
3364
|
-
*
|
|
3365
|
-
* A promotion reads client rects and writes LOCAL pixels, and every
|
|
3366
|
-
* transform above the region — a camera zoom, a page crossing carrying the
|
|
3367
|
-
* whole scene, any ancestor with a scale on it — sits between the two. Read
|
|
3368
|
-
* off the layer itself: its rect is what the screen shows, its offset size
|
|
3369
|
-
* is what its own coordinate system calls that. Dividing by the camera zoom
|
|
3370
|
-
* alone would catch the region's own transform and miss everything outside
|
|
3371
|
-
* it, which is the double-scale the tether draw already dodges by mapping
|
|
3372
|
-
* through the screen CTM.
|
|
3373
|
-
*/
|
|
3374
|
-
static layerScale(el, box) {
|
|
3375
|
-
return {
|
|
3376
|
-
x: el.offsetWidth ? box.width / el.offsetWidth : 1,
|
|
3377
|
-
y: el.offsetHeight ? box.height / el.offsetHeight : 1
|
|
3378
|
-
};
|
|
3379
|
-
}
|
|
3380
|
-
promote(t) {
|
|
3381
|
-
const layer = this.options.raisedLayer;
|
|
3382
|
-
const el = t.cue.sprite.element;
|
|
3383
|
-
if (!layer || !el.isConnected || t.perch) return;
|
|
3384
|
-
const box = el.getBoundingClientRect();
|
|
3385
|
-
const layerBox = layer.getBoundingClientRect();
|
|
3386
|
-
const s = ChoreoRun.layerScale(layer, layerBox);
|
|
3387
|
-
const width = box.width / s.x;
|
|
3388
|
-
const height = box.height / s.y;
|
|
3389
|
-
const placeholder = document.createElement(el.tagName);
|
|
3390
|
-
placeholder.setAttribute("aria-hidden", "true");
|
|
3391
|
-
placeholder.style.cssText = `visibility:hidden;width:${width}px;height:${height}px;margin:0;flex:none`;
|
|
3392
|
-
const prior = el.style.cssText;
|
|
3393
|
-
el.parentNode?.insertBefore(placeholder, el);
|
|
3394
|
-
layer.appendChild(el);
|
|
3395
|
-
el.style.position = "absolute";
|
|
3396
|
-
el.style.left = `${(box.left - layerBox.left) / s.x}px`;
|
|
3397
|
-
el.style.top = `${(box.top - layerBox.top) / s.y}px`;
|
|
3398
|
-
el.style.width = `${width}px`;
|
|
3399
|
-
el.style.height = `${height}px`;
|
|
3400
|
-
el.style.margin = "0";
|
|
3401
|
-
if (t.cue.raise?.shadow) el.style.filter = "drop-shadow(0 18px 24px rgba(0,0,0,0.35))";
|
|
3402
|
-
t.perch = {
|
|
3403
|
-
placeholder,
|
|
3404
|
-
prior
|
|
3405
|
-
};
|
|
3406
|
-
}
|
|
3407
|
-
restore(t) {
|
|
3408
|
-
const el = t.cue.sprite.element;
|
|
3409
|
-
const perch = t.perch;
|
|
3410
|
-
if (!perch) return;
|
|
3411
|
-
t.perch = void 0;
|
|
3412
|
-
perch.placeholder.parentNode?.replaceChild(el, perch.placeholder);
|
|
3413
|
-
el.style.cssText = perch.prior;
|
|
3414
|
-
t.cue.sprite.node.visualElement?.scheduleRender();
|
|
3415
|
-
}
|
|
3416
|
-
startScroll(t) {
|
|
3417
|
-
const el = t.cue.sprite.element;
|
|
3418
|
-
let container = el.parentElement;
|
|
3419
|
-
while (container) {
|
|
3420
|
-
const cs = getComputedStyle(container);
|
|
3421
|
-
if (/(auto|scroll)/.test(cs.overflowY + cs.overflowX)) break;
|
|
3422
|
-
container = container.parentElement;
|
|
3423
|
-
}
|
|
3424
|
-
if (!container) return;
|
|
3425
|
-
const box = el.getBoundingClientRect();
|
|
3426
|
-
const cBox = container.getBoundingClientRect();
|
|
3427
|
-
const s = ChoreoRun.layerScale(container, cBox);
|
|
3428
|
-
const align = t.cue.scroll.align;
|
|
3429
|
-
const offsetY = (box.top - cBox.top) / s.y + container.scrollTop;
|
|
3430
|
-
const offsetX = (box.left - cBox.left) / s.x + container.scrollLeft;
|
|
3431
|
-
const factor = align === "center" ? .5 : align === "end" ? 1 : 0;
|
|
3432
|
-
const to = {
|
|
3433
|
-
left: Math.max(0, offsetX - (container.clientWidth - box.width / s.x) * factor),
|
|
3434
|
-
top: Math.max(0, offsetY - (container.clientHeight - box.height / s.y) * factor)
|
|
3435
|
-
};
|
|
3436
|
-
const onWheel = () => this.stopScroll(t, false);
|
|
3437
|
-
container.addEventListener("wheel", onWheel, { passive: true });
|
|
3438
|
-
container.addEventListener("touchmove", onWheel, { passive: true });
|
|
3439
|
-
t.scrolling = {
|
|
3440
|
-
cancelListener: () => {
|
|
3441
|
-
container.removeEventListener("wheel", onWheel);
|
|
3442
|
-
container.removeEventListener("touchmove", onWheel);
|
|
3443
|
-
},
|
|
3444
|
-
container,
|
|
3445
|
-
from: {
|
|
3446
|
-
left: container.scrollLeft,
|
|
3447
|
-
top: container.scrollTop
|
|
3448
|
-
},
|
|
3449
|
-
to
|
|
3450
|
-
};
|
|
3451
|
-
}
|
|
3452
|
-
stopScroll(t, rewind) {
|
|
3453
|
-
const s = t.scrolling;
|
|
3454
|
-
if (!s) return;
|
|
3455
|
-
t.scrolling = void 0;
|
|
3456
|
-
s.cancelListener();
|
|
3457
|
-
if (rewind) {
|
|
3458
|
-
s.container.scrollTop = s.from.top;
|
|
3459
|
-
s.container.scrollLeft = s.from.left;
|
|
3460
|
-
}
|
|
3461
|
-
}
|
|
3462
|
-
/** stop a track's animations at the value level — an async animation
|
|
3463
|
-
* cancelled before it resolves stays 'idle' forever if only the controls
|
|
3464
|
-
* are stopped, and its value then reads as animating for good */
|
|
3465
|
-
stopTrack(t) {
|
|
3466
|
-
t.controls?.forEach((c) => c.stop());
|
|
3467
|
-
t.controls = void 0;
|
|
3468
|
-
t.platform?.forEach((a) => a.cancel());
|
|
3469
|
-
t.platform = void 0;
|
|
3470
|
-
const ve = t.cue.sprite.node.visualElement;
|
|
3471
|
-
if (ve && t.cue.target) for (const key in t.cue.target) ve.getValue(key)?.stop();
|
|
3472
|
-
}
|
|
3473
|
-
/** land a cue's end values without ever having played it */
|
|
3474
|
-
jumpFinals(t) {
|
|
3475
|
-
const { cue } = t;
|
|
3476
|
-
const ve = cue.sprite.node.visualElement;
|
|
3477
|
-
if (!ve || !cue.target && !cue.flight) return;
|
|
3478
|
-
if (cue.flight) {
|
|
3479
|
-
this.applyFlight(t, 1);
|
|
3480
|
-
ve.render();
|
|
3481
|
-
if (!cue.target) {
|
|
3482
|
-
t.passed = true;
|
|
3483
|
-
return;
|
|
3484
|
-
}
|
|
3485
|
-
}
|
|
3486
|
-
if (!t.origin) {
|
|
3487
|
-
const origin = {};
|
|
3488
|
-
for (const key in cue.target) {
|
|
3489
|
-
const value = cue.target[key];
|
|
3490
|
-
if (Array.isArray(value)) origin[key] = value[0];
|
|
3491
|
-
else {
|
|
3492
|
-
const held = ve.getValue(key)?.get();
|
|
3493
|
-
origin[key] = held !== void 0 ? held : getComputedStyle(cue.sprite.element).getPropertyValue(dash(key)) || 0;
|
|
3494
|
-
}
|
|
3495
|
-
}
|
|
3496
|
-
t.origin = origin;
|
|
3497
|
-
}
|
|
3498
|
-
t.passed = true;
|
|
3499
|
-
for (const key in cue.target) {
|
|
3500
|
-
const raw = cue.target[key];
|
|
3501
|
-
const end = Array.isArray(raw) ? raw[raw.length - 1] : raw;
|
|
3502
|
-
ve.getValue(key, end).jump(end);
|
|
3503
|
-
}
|
|
3504
|
-
ve.render();
|
|
3505
|
-
}
|
|
3506
|
-
startTrack(t) {
|
|
3507
|
-
const { cue } = t;
|
|
3508
|
-
const ve = cue.sprite.node.visualElement;
|
|
3509
|
-
if (!ve) return;
|
|
3510
|
-
t.started = true;
|
|
3511
|
-
t.passed = false;
|
|
3512
|
-
if (cue.target && !t.origin) {
|
|
3513
|
-
const origin = {};
|
|
3514
|
-
for (const key in cue.target) {
|
|
3515
|
-
const value = cue.target[key];
|
|
3516
|
-
if (Array.isArray(value)) origin[key] = value[0];
|
|
3517
|
-
else {
|
|
3518
|
-
const held = ve.getValue(key)?.get();
|
|
3519
|
-
const latest = ve.latestValues[key];
|
|
3520
|
-
origin[key] = held !== void 0 ? held : latest !== void 0 ? latest : getComputedStyle(cue.sprite.element).getPropertyValue(dash(key)) || 0;
|
|
3521
|
-
}
|
|
3522
|
-
}
|
|
3523
|
-
t.origin = origin;
|
|
3524
|
-
}
|
|
3525
|
-
if (cue.delivery) {
|
|
3526
|
-
for (const key in cue.target) {
|
|
3527
|
-
const raw = cue.target[key];
|
|
3528
|
-
if (Array.isArray(raw)) {
|
|
3529
|
-
const end = raw[raw.length - 1];
|
|
3530
|
-
ve.getValue(key, end).jump(end);
|
|
3531
|
-
}
|
|
3532
|
-
}
|
|
3533
|
-
ve.render();
|
|
3534
|
-
t.delivery = deliver(cue, this.scale, this.reduced);
|
|
3535
|
-
if (!this.playing) t.delivery.pause();
|
|
3536
|
-
return;
|
|
3537
|
-
}
|
|
3538
|
-
if (cue.loop) {
|
|
3539
|
-
const target = this.reduced ? withoutMovement(cue.target) : cue.target;
|
|
3540
|
-
const el = cue.sprite.element;
|
|
3541
|
-
const cycle = t.end - t.start;
|
|
3542
|
-
const phase = this.options.loops?.get(cue.sprite.node)?.get(loopKey(cue));
|
|
3543
|
-
t.loopOffset = phase === void 0 ? void 0 : phase * cycle;
|
|
3544
|
-
const times = cue.transition?.times;
|
|
3545
|
-
const segmentEase = cssEasing(cue.transition?.ease, cycle);
|
|
3546
|
-
t.loopAnimation = el.animate(keyframesOf(target ?? {}, Object.keys(target ?? {}).length ? times : void 0, segmentEase), {
|
|
3547
|
-
duration: Math.max(1, cycle),
|
|
3548
|
-
easing: times ? "linear" : segmentEase,
|
|
3549
|
-
iterations: Infinity
|
|
3550
|
-
});
|
|
3551
|
-
t.loopAnimation.currentTime = (Math.max(0, this.master - t.start) + (t.loopOffset ?? 0)) % Math.max(1, cycle);
|
|
3552
|
-
t.loopAnimation.playbackRate = this.rate;
|
|
3553
|
-
if (!this.playing) t.loopAnimation.pause();
|
|
3554
|
-
return;
|
|
3555
|
-
}
|
|
3556
|
-
if (cue.flight) {
|
|
3557
|
-
this.startFlight(t);
|
|
3558
|
-
return;
|
|
3559
|
-
}
|
|
3560
|
-
if (!cue.target) return;
|
|
3561
|
-
if (!this.playing) {
|
|
3562
|
-
this.sampleStill(t, this.master);
|
|
3563
|
-
return;
|
|
3564
|
-
}
|
|
3565
|
-
const transition = carryVelocity(scaleTransition({
|
|
3566
|
-
...cue.transition,
|
|
3567
|
-
reduceMotion: this.reduced
|
|
3568
|
-
}, this.scale), cue, this.options.inherit);
|
|
3569
|
-
t.controls = animateTarget(ve, {
|
|
3570
|
-
...cue.target,
|
|
3571
|
-
transition
|
|
3572
|
-
});
|
|
3573
|
-
for (const c of t.controls) c.speed = this.rate;
|
|
3574
|
-
}
|
|
3575
|
-
/** put the sprite at progress `p` of its sampled flight path (§4.4) */
|
|
3576
|
-
applyFlight(t, p) {
|
|
3577
|
-
const { cue } = t;
|
|
3578
|
-
const ve = cue.sprite.node.visualElement;
|
|
3579
|
-
const flight = cue.flight;
|
|
3580
|
-
if (!ve || !flight) return;
|
|
3581
|
-
const pts = flight.points;
|
|
3582
|
-
const at = Math.min(pts.length - 1 - 1e-9, Math.max(0, p) * (pts.length - 1));
|
|
3583
|
-
const index = Math.floor(at);
|
|
3584
|
-
const local = at - index;
|
|
3585
|
-
const a = pts[index];
|
|
3586
|
-
const b = pts[Math.min(index + 1, pts.length - 1)];
|
|
3587
|
-
const x = a.x + (b.x - a.x) * local - flight.rest.x;
|
|
3588
|
-
const y = a.y + (b.y - a.y) * local - flight.rest.y;
|
|
3589
|
-
ve.getValue("x", x).set(x);
|
|
3590
|
-
ve.getValue("y", y).set(y);
|
|
3591
|
-
if (flight.rotate !== void 0) {
|
|
3592
|
-
const angle = Math.atan2(b.y - a.y, b.x - a.x) * 180 / Math.PI + (typeof flight.rotate === "number" ? flight.rotate : 0);
|
|
3593
|
-
ve.getValue("rotate", angle).set(angle);
|
|
3594
|
-
}
|
|
3595
|
-
}
|
|
3596
|
-
/** the eased progress a flight sits at, `ms` into its window */
|
|
3597
|
-
flightProgress(t, ms) {
|
|
3598
|
-
if (this.reduced) return ms > 0 ? 1 : 0;
|
|
3599
|
-
const span = t.end - t.start;
|
|
3600
|
-
const raw = span > 0 ? Math.min(1, Math.max(0, ms / span)) : 1;
|
|
3601
|
-
const transition = t.cue.transition;
|
|
3602
|
-
if (isSpring(transition)) {
|
|
3603
|
-
const pts = t.cue.flight.points;
|
|
3604
|
-
const end = pts[pts.length - 1];
|
|
3605
|
-
const distance = Math.hypot(end.x, end.y) || 1;
|
|
3606
|
-
return spring({
|
|
3607
|
-
keyframes: [0, distance],
|
|
3608
|
-
...transition ?? {}
|
|
3609
|
-
}).next(ms / this.scale).value / distance;
|
|
3610
|
-
}
|
|
3611
|
-
return easingDefinitionToFunction(transition?.ease ?? "easeInOut")(raw);
|
|
3612
|
-
}
|
|
3613
|
-
/**
|
|
3614
|
-
* The sampled path as platform keyframes: each point becomes a transform,
|
|
3615
|
-
* uniformly spaced (the points were sampled uniformly in progress), and
|
|
3616
|
-
* the eased clock rides the animation's easing instead of per-frame JS.
|
|
3617
|
-
*/
|
|
3618
|
-
flightKeyframes(t) {
|
|
3619
|
-
const flight = t.cue.flight;
|
|
3620
|
-
const pts = flight.points;
|
|
3621
|
-
const frames = [];
|
|
3622
|
-
for (let i = 0; i < pts.length; i++) {
|
|
3623
|
-
const p = pts[i];
|
|
3624
|
-
let transform = `translate(${p.x - flight.rest.x}px, ${p.y - flight.rest.y}px)`;
|
|
3625
|
-
if (flight.rotate !== void 0) {
|
|
3626
|
-
const a = pts[Math.max(0, i - 1)];
|
|
3627
|
-
const b = pts[Math.min(pts.length - 1, i + 1)];
|
|
3628
|
-
const angle = Math.atan2(b.y - a.y, b.x - a.x) * 180 / Math.PI + (typeof flight.rotate === "number" ? flight.rotate : 0);
|
|
3629
|
-
transform += ` rotate(${angle}deg)`;
|
|
3630
|
-
}
|
|
3631
|
-
frames.push({ transform });
|
|
3632
|
-
}
|
|
3633
|
-
return frames;
|
|
3634
|
-
}
|
|
3635
|
-
startFlight(t) {
|
|
3636
|
-
const { cue } = t;
|
|
3637
|
-
const ve = cue.sprite.node.visualElement;
|
|
3638
|
-
if (!ve) return;
|
|
3639
|
-
if (!this.playing) {
|
|
3640
|
-
this.sampleStill(t, this.master);
|
|
3641
|
-
return;
|
|
3642
|
-
}
|
|
3643
|
-
const span = Math.max(1, t.end - t.start);
|
|
3644
|
-
const controls = [];
|
|
3645
|
-
const anim = cue.sprite.element.animate(this.flightKeyframes(t), {
|
|
3646
|
-
duration: span,
|
|
3647
|
-
easing: generateLinearEasing((p) => this.flightProgress(t, p * span), span),
|
|
3648
|
-
fill: "both"
|
|
3649
|
-
});
|
|
3650
|
-
anim.playbackRate = this.rate;
|
|
3651
|
-
anim.currentTime = Math.min(span, Math.max(0, this.master - t.start));
|
|
3652
|
-
(t.platform ??= []).push(anim);
|
|
3653
|
-
controls.push(platformControls(anim));
|
|
3654
|
-
if (cue.target && Object.keys(cue.target).length) {
|
|
3655
|
-
const transition = scaleTransition({
|
|
3656
|
-
...cue.transition,
|
|
3657
|
-
onUpdate: noop
|
|
3658
|
-
}, this.scale);
|
|
3659
|
-
controls.push(...animateTarget(ve, {
|
|
3660
|
-
...cue.target,
|
|
3661
|
-
transition
|
|
3662
|
-
}));
|
|
3663
|
-
}
|
|
3664
|
-
for (const c of controls) c.speed = this.rate;
|
|
3665
|
-
t.controls = controls;
|
|
3666
|
-
}
|
|
3667
|
-
/** compute one still frame of a cue and jump the values onto the element */
|
|
3668
|
-
sampleStill(t, now) {
|
|
3669
|
-
const { cue } = t;
|
|
3670
|
-
const ve = cue.sprite.node.visualElement;
|
|
3671
|
-
if (!ve || !cue.target && !cue.flight) return;
|
|
3672
|
-
if (cue.flight) {
|
|
3673
|
-
this.applyFlight(t, this.flightProgress(t, now - t.start));
|
|
3674
|
-
ve.render();
|
|
3675
|
-
if (!cue.target) return;
|
|
3676
|
-
}
|
|
3677
|
-
const span = t.end - t.start;
|
|
3678
|
-
const p = span > 0 ? Math.min(1, Math.max(0, (now - t.start) / span)) : 1;
|
|
3679
|
-
const transition = cue.transition;
|
|
3680
|
-
const sprung = isSpring(transition);
|
|
3681
|
-
const ease = sprung ? null : easingDefinitionToFunction(transition?.ease ?? "easeInOut");
|
|
3682
|
-
for (const key in cue.target) {
|
|
3683
|
-
const raw = cue.target[key];
|
|
3684
|
-
const frames = Array.isArray(raw) ? raw : [t.origin?.[key] ?? 0, raw];
|
|
3685
|
-
const numeric = frames.map((f) => parseFloat(String(f)));
|
|
3686
|
-
if (numeric.some((n) => Number.isNaN(n))) {
|
|
3687
|
-
const segments = frames.length - 1;
|
|
3688
|
-
if (segments < 1) {
|
|
3689
|
-
ve.getValue(key, frames[0]).jump(frames[0]);
|
|
3690
|
-
continue;
|
|
3691
|
-
}
|
|
3692
|
-
let at;
|
|
3693
|
-
if (sprung) at = spring({
|
|
3694
|
-
keyframes: [0, segments],
|
|
3695
|
-
...transition ?? {}
|
|
3696
|
-
}).next(now - t.start).value;
|
|
3697
|
-
else at = (ease ? ease(p) : p) * segments;
|
|
3698
|
-
at = Math.min(segments - 1e-9, Math.max(0, at));
|
|
3699
|
-
const index = Math.floor(at);
|
|
3700
|
-
const value = mix(frames[index], frames[index + 1])(at - index);
|
|
3701
|
-
ve.getValue(key, value).jump(value);
|
|
3702
|
-
continue;
|
|
3703
|
-
}
|
|
3704
|
-
let value;
|
|
3705
|
-
if (sprung) value = spring({
|
|
3706
|
-
keyframes: [numeric[0], numeric[numeric.length - 1]],
|
|
3707
|
-
...transition ?? {}
|
|
3708
|
-
}).next(now - t.start).value;
|
|
3709
|
-
else {
|
|
3710
|
-
const times = Array.isArray(raw) ? transition?.times : void 0;
|
|
3711
|
-
const eased = ease ? ease(p) : p;
|
|
3712
|
-
const segments = numeric.length - 1;
|
|
3713
|
-
const at = Math.min(segments - 1e-9, eased * segments);
|
|
3714
|
-
const index = times ? p >= 1 ? segments - 1 : Math.max(0, times.findIndex((time) => time > p) - 1) : Math.max(0, Math.floor(at));
|
|
3715
|
-
const progress = times ? p >= 1 ? 1 : (p - times[index]) / (times[index + 1] - times[index]) : at - index;
|
|
3716
|
-
const local = times && ease ? ease(progress) : progress;
|
|
3717
|
-
value = numeric[index] + (numeric[index + 1] - numeric[index]) * local;
|
|
3718
|
-
}
|
|
3719
|
-
ve.getValue(key, value).jump(value);
|
|
3720
|
-
}
|
|
3721
|
-
ve.render();
|
|
3722
|
-
}
|
|
3723
|
-
completeTrack(t) {
|
|
3724
|
-
const { cue } = t;
|
|
3725
|
-
if (t.passed) return;
|
|
3726
|
-
t.passed = true;
|
|
3727
|
-
t.started = false;
|
|
3728
|
-
flushKeyframeResolvers();
|
|
3729
|
-
this.stopTrack(t);
|
|
3730
|
-
if (t.delivery) {
|
|
3731
|
-
t.delivery.complete();
|
|
3732
|
-
t.delivery = void 0;
|
|
3733
|
-
}
|
|
3734
|
-
const ve = cue.sprite.node.visualElement;
|
|
3735
|
-
if (ve && cue.flight) {
|
|
3736
|
-
this.applyFlight(t, 1);
|
|
3737
|
-
ve.render();
|
|
3738
|
-
}
|
|
3739
|
-
if (ve && cue.target) {
|
|
3740
|
-
for (const key in cue.target) {
|
|
3741
|
-
const raw = cue.target[key];
|
|
3742
|
-
const end = Array.isArray(raw) ? raw[raw.length - 1] : raw;
|
|
3743
|
-
ve.getValue(key, end).jump(end);
|
|
3744
|
-
}
|
|
3745
|
-
ve.render();
|
|
3746
|
-
}
|
|
3747
|
-
}
|
|
3748
|
-
pinStarts() {
|
|
3749
|
-
const pinned = /* @__PURE__ */ new Set();
|
|
3750
|
-
const rendered = /* @__PURE__ */ new Set();
|
|
3751
|
-
for (const t of [...this.tracks].sort((a, b) => a.start - b.start)) {
|
|
3752
|
-
const cue = t.cue;
|
|
3753
|
-
const ve = cue.sprite.node.visualElement;
|
|
3754
|
-
if (!ve || cue.loop) continue;
|
|
3755
|
-
if (cue.flight) {
|
|
3756
|
-
this.movedValues.push({
|
|
3757
|
-
key: "x",
|
|
3758
|
-
ve
|
|
3759
|
-
}, {
|
|
3760
|
-
key: "y",
|
|
3761
|
-
ve
|
|
3762
|
-
});
|
|
3763
|
-
this.owned.push({
|
|
3764
|
-
el: cue.sprite.element,
|
|
3765
|
-
key: "x",
|
|
3766
|
-
ve
|
|
3767
|
-
}, {
|
|
3768
|
-
el: cue.sprite.element,
|
|
3769
|
-
key: "y",
|
|
3770
|
-
ve
|
|
3771
|
-
});
|
|
3772
|
-
if (cue.flight.rotate !== void 0) this.movedValues.push({
|
|
3773
|
-
key: "rotate",
|
|
3774
|
-
ve
|
|
3775
|
-
});
|
|
3776
|
-
this.applyFlight({ ...t }, 0);
|
|
3777
|
-
rendered.add(ve);
|
|
3778
|
-
}
|
|
3779
|
-
if (!cue.target) continue;
|
|
3780
|
-
for (const key in cue.target) {
|
|
3781
|
-
const value = cue.target[key];
|
|
3782
|
-
if (!Array.isArray(value) || value[0] === void 0) continue;
|
|
3783
|
-
const seen = `${cue.sprite.node.layoutKey}:${key}`;
|
|
3784
|
-
if (pinned.has(seen)) continue;
|
|
3785
|
-
pinned.add(seen);
|
|
3786
|
-
this.owned.push({
|
|
3787
|
-
el: cue.sprite.element,
|
|
3788
|
-
key,
|
|
3789
|
-
ve
|
|
3790
|
-
});
|
|
3791
|
-
if (cue.kind === "move") if (key in SIZES) {
|
|
3792
|
-
if (!ve.hasValue(key)) this.borrowedValues.push({
|
|
3793
|
-
el: cue.sprite.element,
|
|
3794
|
-
key,
|
|
3795
|
-
prior: cue.sprite.element.style.getPropertyValue(dash(key)),
|
|
3796
|
-
ve
|
|
3797
|
-
});
|
|
3798
|
-
} else this.movedValues.push({
|
|
3799
|
-
key,
|
|
3800
|
-
rest: key.startsWith("scale") ? 1 : key === "clipPath" ? "none" : 0,
|
|
3801
|
-
ve
|
|
3802
|
-
});
|
|
3803
|
-
else if (cue.borrow && !ve.hasValue(key)) this.borrowedValues.push({
|
|
3804
|
-
el: cue.sprite.element,
|
|
3805
|
-
key,
|
|
3806
|
-
prior: cue.sprite.element.style.getPropertyValue(dash(key)),
|
|
3807
|
-
ve
|
|
3808
|
-
});
|
|
3809
|
-
ve.getValue(key, value[0]).jump(value[0]);
|
|
3810
|
-
rendered.add(ve);
|
|
3811
|
-
}
|
|
3812
|
-
}
|
|
3813
|
-
rendered.forEach((ve) => ve.render());
|
|
3814
|
-
}
|
|
3815
|
-
sampleVelocities() {
|
|
3816
|
-
for (const { ve, el, key } of this.owned) {
|
|
3817
|
-
let byKey = this.velocities.get(el);
|
|
3818
|
-
if (byKey?.has(key)) continue;
|
|
3819
|
-
const velocity = ve.getValue(key)?.getVelocity();
|
|
3820
|
-
if (!velocity) continue;
|
|
3821
|
-
if (!byKey) this.velocities.set(el, byKey = /* @__PURE__ */ new Map());
|
|
3822
|
-
byKey.set(key, velocity);
|
|
3823
|
-
}
|
|
3824
|
-
}
|
|
3825
|
-
releaseForMeasure() {
|
|
3826
|
-
this.sampleVelocities();
|
|
3827
|
-
for (const t of this.tracks) {
|
|
3828
|
-
t.platform?.forEach((a) => a.cancel());
|
|
3829
|
-
t.platform = void 0;
|
|
3830
|
-
this.dropCameraAnimation(t);
|
|
3831
|
-
}
|
|
3832
|
-
const touched = /* @__PURE__ */ new Set();
|
|
3833
|
-
this.retired = {
|
|
3834
|
-
borrowed: [],
|
|
3835
|
-
moved: []
|
|
3836
|
-
};
|
|
3837
|
-
for (const { ve, el, key, prior } of this.borrowedValues.splice(0)) {
|
|
3838
|
-
this.retired.borrowed.push({
|
|
3839
|
-
el,
|
|
3840
|
-
key,
|
|
3841
|
-
prior,
|
|
3842
|
-
value: ve.getValue(key)?.get(),
|
|
3843
|
-
ve
|
|
3844
|
-
});
|
|
3845
|
-
ve.removeValue(key);
|
|
3846
|
-
if (prior) el.style.setProperty(dash(key), prior);
|
|
3847
|
-
else el.style.removeProperty(dash(key));
|
|
3848
|
-
touched.add(ve);
|
|
3849
|
-
}
|
|
3850
|
-
for (const { ve, key, rest } of this.movedValues.splice(0)) {
|
|
3851
|
-
this.retired.moved.push({
|
|
3852
|
-
key,
|
|
3853
|
-
rest,
|
|
3854
|
-
value: ve.getValue(key)?.get(),
|
|
3855
|
-
ve
|
|
3856
|
-
});
|
|
3857
|
-
ve.getValue(key)?.jump(rest ?? 0);
|
|
3858
|
-
touched.add(ve);
|
|
3859
|
-
}
|
|
3860
|
-
touched.forEach((ve) => ve.render());
|
|
3861
|
-
}
|
|
3862
|
-
/**
|
|
3863
|
-
* A pass measured this run's world at rest and then decided to KEEP the
|
|
3864
|
-
* run — but the measurement itself was destructive: releaseForMeasure
|
|
3865
|
-
* cancels platform animations, returns borrowed values, and jumps every
|
|
3866
|
-
* moved value to rest, and a MotionValue.jump() STOPS the animation
|
|
3867
|
-
* driving it. Left like that, a kept run keeps its clock and its landing
|
|
3868
|
-
* but loses its picture: the flight freezes at rest until the finals
|
|
3869
|
-
* land — which on a busy page (the gallery: neighbours re-pass the
|
|
3870
|
-
* region every render) is every crossing, every time. So the keep path
|
|
3871
|
-
* calls this: moved and borrowed values are stood back where they were,
|
|
3872
|
-
* their bookkeeping is re-registered, every in-flight track's animation
|
|
3873
|
-
* is retired so evaluate re-enters it — the machinery a scrub-then-play
|
|
3874
|
-
* already uses — and the re-entered animations are seeked back onto the
|
|
3875
|
-
* run's own clock, so a keep is invisible rather than a restart.
|
|
3876
|
-
*/
|
|
3877
|
-
reassert() {
|
|
3878
|
-
const { borrowed, moved } = this.retired;
|
|
3879
|
-
this.retired = {
|
|
3880
|
-
borrowed: [],
|
|
3881
|
-
moved: []
|
|
3882
|
-
};
|
|
3883
|
-
for (const { el, key, prior, value, ve } of borrowed) {
|
|
3884
|
-
if (value !== void 0) ve.getValue(key, value).jump(value);
|
|
3885
|
-
this.borrowedValues.push({
|
|
3886
|
-
el,
|
|
3887
|
-
key,
|
|
3888
|
-
prior,
|
|
3889
|
-
ve
|
|
3890
|
-
});
|
|
3891
|
-
}
|
|
3892
|
-
for (const { key, rest, value, ve } of moved) {
|
|
3893
|
-
if (value !== void 0) ve.getValue(key)?.jump(value);
|
|
3894
|
-
this.movedValues.push({
|
|
3895
|
-
key,
|
|
3896
|
-
rest,
|
|
3897
|
-
ve
|
|
3898
|
-
});
|
|
3899
|
-
}
|
|
3900
|
-
if (!this.playing) return;
|
|
3901
|
-
const now = this.master;
|
|
3902
|
-
const restarted = [];
|
|
3903
|
-
for (const t of this.tracks) if (t.started && !t.passed && now >= t.start && (now < t.end || t.cue.loop) && (t.cue.target || t.cue.flight)) {
|
|
3904
|
-
flushKeyframeResolvers();
|
|
3905
|
-
this.stopTrack(t);
|
|
3906
|
-
restarted.push(t);
|
|
3907
|
-
}
|
|
3908
|
-
this.evaluate();
|
|
3909
|
-
for (const t of restarted) if (!t.cue.flight) {
|
|
3910
|
-
const at = Math.max(0, now - t.start) / 1e3;
|
|
3911
|
-
t.controls?.forEach((c) => {
|
|
3912
|
-
c.time = at;
|
|
3913
|
-
});
|
|
3914
|
-
}
|
|
3915
|
-
}
|
|
3916
|
-
cancel(keep) {
|
|
3917
|
-
if (this.cancelled) return;
|
|
3918
|
-
this.cancelled = true;
|
|
3919
|
-
activeRuns.delete(this);
|
|
3920
|
-
this.stopTicking();
|
|
3921
|
-
clearTimeout(this.autoTimer);
|
|
3922
|
-
this.pendingPerforms.length = 0;
|
|
3923
|
-
this.options.onCamera?.({ ...this.camera });
|
|
3924
|
-
flushKeyframeResolvers();
|
|
3925
|
-
this.sampleVelocities();
|
|
3926
|
-
for (const t of this.tracks) {
|
|
3927
|
-
this.stopTrack(t);
|
|
3928
|
-
t.delivery?.cancel();
|
|
3929
|
-
t.loopAnimation?.cancel();
|
|
3930
|
-
this.dropCameraAnimation(t);
|
|
3931
|
-
this.restore(t);
|
|
3932
|
-
this.stopScroll(t, false);
|
|
3933
|
-
t.wire?.remove();
|
|
3934
|
-
t.wire = void 0;
|
|
3935
|
-
const ve = t.cue.sprite.node.visualElement;
|
|
3936
|
-
if (t.held && ve) {
|
|
3937
|
-
releaseHold(ve, t.cue.sprite.element, t.held);
|
|
3938
|
-
t.held = void 0;
|
|
3939
|
-
}
|
|
3940
|
-
}
|
|
3941
|
-
this.releaseForMeasure();
|
|
3942
|
-
for (const sprite of [...this.pending]) if (keep?.has(sprite.node)) this.pending.delete(sprite);
|
|
3943
|
-
else {
|
|
3944
|
-
this.pending.delete(sprite);
|
|
3945
|
-
this.options.onSpriteDone(sprite);
|
|
3946
|
-
}
|
|
3947
|
-
this.resolveFinished();
|
|
3948
|
-
}
|
|
3949
|
-
};
|
|
3950
|
-
/** every live run, for the test helpers that drive gates and clocks */
|
|
3951
|
-
var activeRuns = /* @__PURE__ */ new Set();
|
|
3952
|
-
function execute(compiled, options) {
|
|
3953
|
-
return new ChoreoRun(compiled, options);
|
|
3954
|
-
}
|
|
3955
|
-
//#endregion
|
|
3956
|
-
export { resetBeacons as C, measure as E, registerBeacon as S, isRendered as T, sameScore as _, choreoHostById as a, trackGestures as b, join as c, resetBarrier as d, setBeforeMeasure as f, fadeOn as g, continuation as h, choreoHostAt as i, leave as l, compile as m, execute as n, closestChoreo as o, setPassScheduler as p, resetRunWarnings as r, setChoreoHost as s, activeRuns as t, registerSettle as u, GESTURE as v, boundsOf as w, measureBeacons as x, resetGestures as y };
|