@kieransimkin/dancemoves 3.1.19 → 3.1.20
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/AGENTS.md +6 -0
- package/README.md +14 -0
- package/docs/playback-sources.md +78 -0
- package/lib/build-manifest.json +13 -13
- package/lib/dancemoves.min.js +3 -3
- package/lib/index.cjs +504 -22
- package/lib/index.d.ts +23 -10
- package/lib/index.mjs +504 -22
- package/lib/rudiments.d.ts +4 -2
- package/lib/wordpress.js +3 -3
- package/package.json +1 -1
- package/readme.txt +2 -2
package/lib/index.mjs
CHANGED
|
@@ -17,6 +17,7 @@ function install(__dmScope) {
|
|
|
17
17
|
var lyricList = [];
|
|
18
18
|
var lyricRenderer = null;
|
|
19
19
|
var boundAudio = /* @__PURE__ */ new WeakSet();
|
|
20
|
+
var playbackBindings = /* @__PURE__ */ new Map();
|
|
20
21
|
var activeAudio = null;
|
|
21
22
|
var pageClockStarted = window2.performance && typeof window2.performance.now === "function" ? window2.performance.now() : Date.now();
|
|
22
23
|
var referenceDurationSeconds = positiveNumber(rawConfig.masterDurationMilliseconds) / 1e3;
|
|
@@ -106,13 +107,16 @@ function install(__dmScope) {
|
|
|
106
107
|
}
|
|
107
108
|
function currentTick(options) {
|
|
108
109
|
var settings = options || {};
|
|
109
|
-
var audio = settings.audio || (settings.clock === "audio" ? activeAudio : null);
|
|
110
|
+
var audio = playbackAudio(settings.audio) || (settings.clock === "audio" ? activeAudio : null);
|
|
110
111
|
if (audio && !audio.paused && !audio.ended && Number.isFinite(Number(audio.currentTime))) {
|
|
111
112
|
return Number(audio.currentTime) * effectiveBpm(settings.bpm || bpm) * TICKS_PER_BEAT / 60;
|
|
112
113
|
}
|
|
113
114
|
var now = window2.performance && typeof window2.performance.now === "function" ? window2.performance.now() : Date.now();
|
|
114
115
|
return Math.max(0, now - pageClockStarted) * effectiveBpm(settings.bpm || bpm) * TICKS_PER_BEAT / 6e4;
|
|
115
116
|
}
|
|
117
|
+
function playbackAudio(audio) {
|
|
118
|
+
return audio && api && api.playbackSource ? api.playbackSource(audio) : audio;
|
|
119
|
+
}
|
|
116
120
|
function nextIntervalTick(intervalTicks, fromTick, strictlyFuture) {
|
|
117
121
|
var interval = Math.max(1, roundHalfUp(intervalTicks));
|
|
118
122
|
var tick = Math.max(0, Number(fromTick) || 0);
|
|
@@ -169,7 +173,7 @@ function install(__dmScope) {
|
|
|
169
173
|
var pollAudio = function() {
|
|
170
174
|
if (cancelled)
|
|
171
175
|
return;
|
|
172
|
-
var candidate = settings.audio || activeAudio;
|
|
176
|
+
var candidate = playbackAudio(settings.audio) || activeAudio;
|
|
173
177
|
if (!candidate || candidate.paused || candidate.ended) {
|
|
174
178
|
if (sourceAudio && sourceAudio.ended) {
|
|
175
179
|
cancel();
|
|
@@ -731,9 +735,18 @@ function install(__dmScope) {
|
|
|
731
735
|
return Math.abs(duration - referenceDurationSeconds) <= Math.max(0.25, duration / 1e5);
|
|
732
736
|
}
|
|
733
737
|
function bindAudio(audio) {
|
|
738
|
+
if (api.playbackSource)
|
|
739
|
+
audio = api.playbackSource(audio);
|
|
734
740
|
if (boundAudio.has(audio) || !matchesMasterDuration(audio))
|
|
735
741
|
return;
|
|
736
742
|
boundAudio.add(audio);
|
|
743
|
+
var removers = [];
|
|
744
|
+
function listen(target, name, handler) {
|
|
745
|
+
__dmScope.listen(target, name, handler);
|
|
746
|
+
removers.push(function() {
|
|
747
|
+
__dmScope.unlisten(target, name, handler);
|
|
748
|
+
});
|
|
749
|
+
}
|
|
737
750
|
__dmScope.dataset(audio, "danceMovesTiming", "master-length");
|
|
738
751
|
var state = {
|
|
739
752
|
next: firstCueAfter(audio.currentTime || 0),
|
|
@@ -741,7 +754,8 @@ function install(__dmScope) {
|
|
|
741
754
|
last: audio.currentTime || 0,
|
|
742
755
|
seeking: false,
|
|
743
756
|
frame: 0,
|
|
744
|
-
pendingCue: cueAtLanding(audio.currentTime || 0)
|
|
757
|
+
pendingCue: cueAtLanding(audio.currentTime || 0),
|
|
758
|
+
endedPending: false
|
|
745
759
|
};
|
|
746
760
|
function stopFrame() {
|
|
747
761
|
if (state.frame)
|
|
@@ -750,7 +764,7 @@ function install(__dmScope) {
|
|
|
750
764
|
}
|
|
751
765
|
function tick() {
|
|
752
766
|
state.frame = 0;
|
|
753
|
-
if (audio.paused || audio.ended || state.seeking)
|
|
767
|
+
if (audio.paused || audio.ended || state.seeking || document2.hidden)
|
|
754
768
|
return;
|
|
755
769
|
var diagnosticStartedAt = diagnosticsSink ? diagnosticNow() : 0;
|
|
756
770
|
var firedCount = 0;
|
|
@@ -788,8 +802,14 @@ function install(__dmScope) {
|
|
|
788
802
|
}
|
|
789
803
|
function start() {
|
|
790
804
|
stopFrame();
|
|
805
|
+
if (document2.hidden || audio.paused || audio.ended)
|
|
806
|
+
return;
|
|
791
807
|
activeAudio = audio;
|
|
792
808
|
state.last = positiveNumber(audio.currentTime);
|
|
809
|
+
if (state.endedPending) {
|
|
810
|
+
state.pendingCue = cueAtLanding(state.last);
|
|
811
|
+
state.endedPending = false;
|
|
812
|
+
}
|
|
793
813
|
state.next = firstCueAfter(state.last);
|
|
794
814
|
state.lyric = -2;
|
|
795
815
|
if (state.pendingCue) {
|
|
@@ -799,47 +819,70 @@ function install(__dmScope) {
|
|
|
799
819
|
setOwnedPlaybackRate(audio.playbackRate);
|
|
800
820
|
state.frame = window2.requestAnimationFrame(tick);
|
|
801
821
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
822
|
+
listen(audio, "play", start);
|
|
823
|
+
listen(audio, "playing", start);
|
|
824
|
+
listen(audio, "pause", function() {
|
|
805
825
|
stopFrame();
|
|
806
826
|
if (activeAudio === audio)
|
|
807
827
|
activeAudio = null;
|
|
808
828
|
if (lyricRenderer)
|
|
809
829
|
lyricRenderer.hide();
|
|
810
830
|
});
|
|
811
|
-
|
|
831
|
+
listen(audio, "ended", function() {
|
|
812
832
|
stopFrame();
|
|
813
833
|
if (activeAudio === audio)
|
|
814
834
|
activeAudio = null;
|
|
815
835
|
state.last = 0;
|
|
816
836
|
state.next = 0;
|
|
817
837
|
state.lyric = -2;
|
|
818
|
-
state.pendingCue =
|
|
838
|
+
state.pendingCue = null;
|
|
839
|
+
state.endedPending = true;
|
|
819
840
|
if (lyricRenderer)
|
|
820
841
|
lyricRenderer.hide();
|
|
821
842
|
});
|
|
822
|
-
|
|
843
|
+
listen(audio, "seeking", function() {
|
|
823
844
|
state.seeking = true;
|
|
824
845
|
state.pendingCue = null;
|
|
825
846
|
stopFrame();
|
|
826
847
|
});
|
|
827
|
-
|
|
848
|
+
listen(audio, "seeked", function() {
|
|
828
849
|
state.seeking = false;
|
|
829
850
|
state.last = positiveNumber(audio.currentTime);
|
|
830
851
|
state.next = firstCueAfter(state.last);
|
|
831
852
|
state.lyric = -2;
|
|
832
853
|
state.pendingCue = cueAtLanding(state.last);
|
|
854
|
+
playbackBindings.set(audio, function() {
|
|
855
|
+
stopFrame();
|
|
856
|
+
removers.splice(0).forEach(function(remove) {
|
|
857
|
+
remove();
|
|
858
|
+
});
|
|
859
|
+
boundAudio.delete(audio);
|
|
860
|
+
if (activeAudio === audio)
|
|
861
|
+
activeAudio = null;
|
|
862
|
+
playbackBindings.delete(audio);
|
|
863
|
+
});
|
|
833
864
|
if (!audio.paused && !audio.ended)
|
|
834
865
|
start();
|
|
835
866
|
});
|
|
836
|
-
|
|
867
|
+
listen(audio, "ratechange", function() {
|
|
837
868
|
setOwnedPlaybackRate(audio.playbackRate);
|
|
838
869
|
});
|
|
839
|
-
|
|
870
|
+
listen(audio, "timeupdate", function() {
|
|
840
871
|
if (!audio.paused && !state.frame && !state.seeking)
|
|
841
872
|
tick();
|
|
842
873
|
});
|
|
874
|
+
listen(document2, "visibilitychange", function() {
|
|
875
|
+
if (document2.hidden) {
|
|
876
|
+
stopFrame();
|
|
877
|
+
if (lyricRenderer)
|
|
878
|
+
lyricRenderer.hide();
|
|
879
|
+
} else if (!audio.paused && !audio.ended && !state.seeking) {
|
|
880
|
+
state.pendingCue = null;
|
|
881
|
+
start();
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
if (!audio.paused && !audio.ended)
|
|
885
|
+
start();
|
|
843
886
|
}
|
|
844
887
|
function discoverAudio() {
|
|
845
888
|
var audioElements = Array.from(document2.querySelectorAll("audio"));
|
|
@@ -953,6 +996,16 @@ function install(__dmScope) {
|
|
|
953
996
|
registerAnimationScope,
|
|
954
997
|
resetRunningAnimations,
|
|
955
998
|
discoverAudio,
|
|
999
|
+
unregisterPlaybackSource: function(source) {
|
|
1000
|
+
var remove = playbackBindings.get(source);
|
|
1001
|
+
if (remove)
|
|
1002
|
+
remove();
|
|
1003
|
+
},
|
|
1004
|
+
registerPlaybackSource: function(source) {
|
|
1005
|
+
if (!referenceDurationSeconds)
|
|
1006
|
+
referenceDurationSeconds = positiveNumber(source.duration);
|
|
1007
|
+
bindAudio(source);
|
|
1008
|
+
},
|
|
956
1009
|
setDiagnosticsSink,
|
|
957
1010
|
diagnosticsEnabled: function() {
|
|
958
1011
|
return diagnosticsAllowed && Boolean(diagnosticsSink);
|
|
@@ -993,6 +1046,10 @@ function install2(__dmScope) {
|
|
|
993
1046
|
return document2.querySelector(value);
|
|
994
1047
|
return fallback || null;
|
|
995
1048
|
}
|
|
1049
|
+
function playbackElement(value, fallback) {
|
|
1050
|
+
var target = element(value, fallback);
|
|
1051
|
+
return target && motion.playbackSource ? motion.playbackSource(target) : target;
|
|
1052
|
+
}
|
|
996
1053
|
function media(query) {
|
|
997
1054
|
return window2.matchMedia(query);
|
|
998
1055
|
}
|
|
@@ -1118,7 +1175,7 @@ function install2(__dmScope) {
|
|
|
1118
1175
|
function playbackPulse(options) {
|
|
1119
1176
|
options = options || {};
|
|
1120
1177
|
var state = commonState(options, "pulse");
|
|
1121
|
-
var audio =
|
|
1178
|
+
var audio = playbackElement(options.audio, state.root.querySelector("audio"));
|
|
1122
1179
|
if (!audio)
|
|
1123
1180
|
throw new Error("DanceMovesEffects pulse requires an audio element");
|
|
1124
1181
|
var ticks = Math.max(1, Math.round(finite2(options.ticks, 16)));
|
|
@@ -1218,7 +1275,7 @@ function install2(__dmScope) {
|
|
|
1218
1275
|
function cueTimeline(options) {
|
|
1219
1276
|
options = options || {};
|
|
1220
1277
|
var state = commonState(options, "cue-timeline");
|
|
1221
|
-
var audio =
|
|
1278
|
+
var audio = playbackElement(options.audio, state.root.querySelector("audio"));
|
|
1222
1279
|
if (!audio)
|
|
1223
1280
|
throw new Error("DanceMovesEffects cueTimeline requires an audio element");
|
|
1224
1281
|
var cues = (Array.isArray(options.cues) ? options.cues : []).map(function(cue, index) {
|
|
@@ -1379,7 +1436,7 @@ function install2(__dmScope) {
|
|
|
1379
1436
|
function spritePlayback(options) {
|
|
1380
1437
|
options = options || {};
|
|
1381
1438
|
var state = commonState(options, "sprite-playback");
|
|
1382
|
-
var audio =
|
|
1439
|
+
var audio = playbackElement(options.audio, state.root.querySelector("audio"));
|
|
1383
1440
|
var target = element(options.target, state.root);
|
|
1384
1441
|
if (!audio)
|
|
1385
1442
|
throw new Error("DanceMovesEffects spritePlayback requires an audio element");
|
|
@@ -1573,7 +1630,7 @@ function install2(__dmScope) {
|
|
|
1573
1630
|
function lyricStage(options) {
|
|
1574
1631
|
options = options || {};
|
|
1575
1632
|
var state = commonState(options, "lyric-stage");
|
|
1576
|
-
var audio =
|
|
1633
|
+
var audio = playbackElement(options.audio, state.root.querySelector("audio"));
|
|
1577
1634
|
var popover = element(options.popover, document2.querySelector(".dance-moves-lyric-popover"));
|
|
1578
1635
|
if (!audio)
|
|
1579
1636
|
throw new Error("DanceMovesEffects lyricStage requires an audio element");
|
|
@@ -4792,9 +4849,11 @@ function install9(__dmScope) {
|
|
|
4792
4849
|
const clock = options.clock === void 0 ? "page" : options.clock;
|
|
4793
4850
|
if (!["page", "audio", "auto"].includes(clock))
|
|
4794
4851
|
throw new TypeError("clock must be page, audio or auto");
|
|
4795
|
-
|
|
4796
|
-
if (audio &&
|
|
4797
|
-
|
|
4852
|
+
let audio = clock === "page" ? null : element(options.audio, "audio");
|
|
4853
|
+
if (audio && motion.playbackSource)
|
|
4854
|
+
audio = motion.playbackSource(audio);
|
|
4855
|
+
if (audio && !["audio", "video"].includes(String(audio.tagName).toLowerCase()))
|
|
4856
|
+
throw new TypeError("audio must resolve to native media or a shared playback source");
|
|
4798
4857
|
const rate = options.rate === void 0 ? 1 : number(options.rate, "rate");
|
|
4799
4858
|
if (rate <= 0 || rate > 64)
|
|
4800
4859
|
throw new RangeError("rate must be in (0, 64]");
|
|
@@ -5042,7 +5101,7 @@ function install9(__dmScope) {
|
|
|
5042
5101
|
}
|
|
5043
5102
|
if (options.resetOnCue)
|
|
5044
5103
|
disposers.push(motion.onCue(typeof options.resetOnCue === "string" ? options.resetOnCue : "*", (detail) => {
|
|
5045
|
-
if (!detail.audio || !audio || detail.audio === audio)
|
|
5104
|
+
if (!detail.audio || !audio || detail.audio === audio || motion.playbackSource && motion.playbackSource(detail.audio) === motion.playbackSource(audio))
|
|
5046
5105
|
reset();
|
|
5047
5106
|
}, { id: id + ":cue-reset" }));
|
|
5048
5107
|
if (options.offscreen !== false && window2.IntersectionObserver) {
|
|
@@ -5316,6 +5375,8 @@ function createScope(root, config, { legacyGlobals = false, nonce, orientation =
|
|
|
5316
5375
|
}
|
|
5317
5376
|
const api = {
|
|
5318
5377
|
id,
|
|
5378
|
+
root,
|
|
5379
|
+
legacyGlobals,
|
|
5319
5380
|
window,
|
|
5320
5381
|
document,
|
|
5321
5382
|
get disposed() {
|
|
@@ -5918,8 +5979,428 @@ function createMotionRecorder(scope, { durationMilliseconds = 3e4, maxSamples =
|
|
|
5918
5979
|
});
|
|
5919
5980
|
}
|
|
5920
5981
|
|
|
5982
|
+
// .build/modules/playback.mjs
|
|
5983
|
+
var youtubeLoaders = /* @__PURE__ */ new WeakMap();
|
|
5984
|
+
function validatePlaybackMapping(input, masterDuration) {
|
|
5985
|
+
const offset = input.offset ?? 0, duration = input.duration ?? masterDuration, playerStart = input.playerStart ?? 0;
|
|
5986
|
+
for (const [key, value] of Object.entries({ offset, duration, playerStart, masterDuration })) {
|
|
5987
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || (key === "duration" || key === "masterDuration") && value === 0) throw new RangeError(`${key} must be a finite positive duration or nonnegative offset`);
|
|
5988
|
+
}
|
|
5989
|
+
if (offset + duration > masterDuration + 1e-3) throw new RangeError("The clip extends beyond its associated master");
|
|
5990
|
+
return Object.freeze({ offset, duration, playerStart, masterDuration });
|
|
5991
|
+
}
|
|
5992
|
+
function loadYouTubeAPI(host) {
|
|
5993
|
+
if (host.YT?.Player) return Promise.resolve(host.YT);
|
|
5994
|
+
if (youtubeLoaders.has(host)) return youtubeLoaders.get(host);
|
|
5995
|
+
const pending = new Promise((resolve, reject) => {
|
|
5996
|
+
const previous = host.onYouTubeIframeAPIReady;
|
|
5997
|
+
let timeout;
|
|
5998
|
+
const script = host.document.createElement("script");
|
|
5999
|
+
function finish(error) {
|
|
6000
|
+
host.clearTimeout(timeout);
|
|
6001
|
+
if (host.onYouTubeIframeAPIReady === ready) host.onYouTubeIframeAPIReady = previous;
|
|
6002
|
+
script.removeEventListener("error", failed);
|
|
6003
|
+
if (error) {
|
|
6004
|
+
script.remove();
|
|
6005
|
+
youtubeLoaders.delete(host);
|
|
6006
|
+
reject(error);
|
|
6007
|
+
} else resolve(host.YT);
|
|
6008
|
+
}
|
|
6009
|
+
function ready() {
|
|
6010
|
+
try {
|
|
6011
|
+
previous?.();
|
|
6012
|
+
} finally {
|
|
6013
|
+
finish(host.YT?.Player ? null : new Error("YouTube API unavailable"));
|
|
6014
|
+
}
|
|
6015
|
+
}
|
|
6016
|
+
function failed() {
|
|
6017
|
+
finish(new Error("YouTube API failed to load"));
|
|
6018
|
+
}
|
|
6019
|
+
host.onYouTubeIframeAPIReady = ready;
|
|
6020
|
+
script.src = "https://www.youtube.com/iframe_api";
|
|
6021
|
+
script.addEventListener("error", failed, { once: true });
|
|
6022
|
+
timeout = host.setTimeout(() => finish(new Error("YouTube API timed out")), 2e4);
|
|
6023
|
+
host.document.head.appendChild(script);
|
|
6024
|
+
});
|
|
6025
|
+
youtubeLoaders.set(host, pending);
|
|
6026
|
+
return pending;
|
|
6027
|
+
}
|
|
6028
|
+
function installPlayback(scope, api, host = scope.document.defaultView) {
|
|
6029
|
+
const groups = /* @__PURE__ */ new Map(), transports = /* @__PURE__ */ new WeakSet(), aliases = /* @__PURE__ */ new WeakMap(), controllers = /* @__PURE__ */ new Set(), registered = /* @__PURE__ */ new WeakMap();
|
|
6030
|
+
let disposed = false;
|
|
6031
|
+
function emit(target, type) {
|
|
6032
|
+
target.dispatchEvent(new host.Event(type));
|
|
6033
|
+
}
|
|
6034
|
+
function groupFor(reference) {
|
|
6035
|
+
if (disposed) throw new Error("DanceMoves playback owner is destroyed");
|
|
6036
|
+
const master = reference?.element || reference, declared = reference?.element ? reference.duration : void 0;
|
|
6037
|
+
const isNative = !!master?.addEventListener && ["AUDIO", "VIDEO"].includes(master.tagName);
|
|
6038
|
+
if (!isNative && (!master || typeof master.id !== "string" || !master.id.trim() || master.id.length > 160 || typeof master.duration !== "number" || !Number.isFinite(master.duration) || master.duration <= 0)) throw new TypeError("A native master or identified master duration is required");
|
|
6039
|
+
if (isNative && (master.ownerDocument !== host.document || !scope.legacyGlobals && !scope.root.contains(master))) throw new TypeError("The master must belong to this runtime root");
|
|
6040
|
+
if (groups.has(master)) {
|
|
6041
|
+
const group2 = groups.get(master);
|
|
6042
|
+
group2.setDuration(declared);
|
|
6043
|
+
return group2;
|
|
6044
|
+
}
|
|
6045
|
+
const transport = new host.EventTarget();
|
|
6046
|
+
transports.add(transport);
|
|
6047
|
+
let active = null, lastPaused = true, delegate = null;
|
|
6048
|
+
let declaredDuration = declared || 0;
|
|
6049
|
+
function setDuration(value) {
|
|
6050
|
+
if (value === void 0) return;
|
|
6051
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw new RangeError("Declared master duration must be positive and finite");
|
|
6052
|
+
if (declaredDuration && Math.abs(declaredDuration - value) > 1e-3) throw new RangeError("Conflicting master durations");
|
|
6053
|
+
if (isNative && Number(master.duration) > 0 && Math.abs(Number(master.duration) - value) > 0.25) throw new RangeError("Declared master duration does not match its native reference");
|
|
6054
|
+
declaredDuration = value;
|
|
6055
|
+
}
|
|
6056
|
+
setDuration(declared);
|
|
6057
|
+
const duration = () => delegate?.duration || declaredDuration || (Number(master.duration) > 0 && Number.isFinite(Number(master.duration)) ? Number(master.duration) : Number(api.config?.masterDurationMilliseconds || 0) / 1e3);
|
|
6058
|
+
const target = isNative ? master : scope.root;
|
|
6059
|
+
const native = { element: isNative ? master : null, read: () => ({ time: Number(master.currentTime) || 0, paused: isNative ? master.paused : true, ended: master.ended || false, rate: master.playbackRate || 1, seeking: master.seeking || false, error: master.error }), pause: () => master.pause?.(), play: () => master.play?.(), seek: (time) => {
|
|
6060
|
+
if (isNative) master.currentTime = time;
|
|
6061
|
+
}, mapping: null };
|
|
6062
|
+
active = native;
|
|
6063
|
+
function read() {
|
|
6064
|
+
if (delegate) return { time: delegate.currentTime, paused: delegate.paused, ended: delegate.ended, rate: delegate.playbackRate, seeking: delegate.seeking, error: delegate.error };
|
|
6065
|
+
const raw = active.read(), map = active.mapping || { offset: 0, playerStart: 0, duration: duration() };
|
|
6066
|
+
const local = raw.time - map.playerStart, outside = local < -1e-3 || local > map.duration + 1e-3;
|
|
6067
|
+
return { ...raw, time: map.offset + Math.max(0, Math.min(map.duration, local)), paused: raw.paused || outside, ended: raw.ended || local > map.duration + 1e-3 };
|
|
6068
|
+
}
|
|
6069
|
+
Object.defineProperties(transport, {
|
|
6070
|
+
nodeType: { value: 1 },
|
|
6071
|
+
tagName: { get: () => isNative ? master.tagName : "VIDEO" },
|
|
6072
|
+
ownerDocument: { get: () => target.ownerDocument },
|
|
6073
|
+
dataset: { get: () => target.dataset },
|
|
6074
|
+
id: { get: () => master.id },
|
|
6075
|
+
isConnected: { get: () => target.isConnected },
|
|
6076
|
+
currentTime: { get: () => read().time, set: (value) => {
|
|
6077
|
+
if (delegate) {
|
|
6078
|
+
delegate.currentTime = value;
|
|
6079
|
+
return;
|
|
6080
|
+
}
|
|
6081
|
+
const map = active.mapping || { offset: 0, playerStart: 0, duration: duration() };
|
|
6082
|
+
active.seek(map.playerStart + Math.max(0, Math.min(map.duration, Number(value) - map.offset)));
|
|
6083
|
+
} },
|
|
6084
|
+
duration: { get: duration },
|
|
6085
|
+
paused: { get: () => read().paused },
|
|
6086
|
+
ended: { get: () => read().ended },
|
|
6087
|
+
seeking: { get: () => read().seeking || false },
|
|
6088
|
+
playbackRate: { get: () => read().rate },
|
|
6089
|
+
error: { get: () => read().error || null },
|
|
6090
|
+
element: { value: isNative ? master : null },
|
|
6091
|
+
activePlayer: { get: () => delegate ? delegate.activePlayer : active.element },
|
|
6092
|
+
masterId: { get: () => delegate ? delegate.masterId : master.currentSrc || master.src || master.id }
|
|
6093
|
+
});
|
|
6094
|
+
transport.matches = (selector) => target.matches(selector);
|
|
6095
|
+
transport.getAttribute = (name) => target.getAttribute(name);
|
|
6096
|
+
transport.setAttribute = (name, value) => target.setAttribute(name, value);
|
|
6097
|
+
transport.removeAttribute = (name) => target.removeAttribute(name);
|
|
6098
|
+
transport.play = () => delegate ? delegate.play() : active.play();
|
|
6099
|
+
transport.pause = () => delegate ? delegate.pause() : active.pause();
|
|
6100
|
+
function activate(source) {
|
|
6101
|
+
if (active !== source) {
|
|
6102
|
+
const previous = active;
|
|
6103
|
+
active = source;
|
|
6104
|
+
previous.pause();
|
|
6105
|
+
emit(transport, "seeking");
|
|
6106
|
+
emit(transport, "seeked");
|
|
6107
|
+
}
|
|
6108
|
+
}
|
|
6109
|
+
function forward(source, type) {
|
|
6110
|
+
if (type === "play" || type === "playing") activate(source);
|
|
6111
|
+
if (active !== source) return;
|
|
6112
|
+
const paused = read().paused;
|
|
6113
|
+
if (type === "timeupdate" && paused !== lastPaused) emit(transport, paused ? "pause" : "playing");
|
|
6114
|
+
lastPaused = paused;
|
|
6115
|
+
emit(transport, type);
|
|
6116
|
+
}
|
|
6117
|
+
const events = ["loadedmetadata", "durationchange", "play", "playing", "pause", "ended", "seeking", "seeked", "ratechange", "timeupdate", "waiting", "error"];
|
|
6118
|
+
const removers = [];
|
|
6119
|
+
function bindNative(element, mapping) {
|
|
6120
|
+
const source = element === master ? native : { element, mapping, read: () => ({ time: Number(element.currentTime) || 0, paused: element.paused, ended: element.ended, rate: element.playbackRate || 1, seeking: element.seeking, error: element.error }), pause: () => element.pause(), play: () => element.play(), seek: (time) => {
|
|
6121
|
+
element.currentTime = time;
|
|
6122
|
+
} };
|
|
6123
|
+
source.removers = [];
|
|
6124
|
+
for (const type of events) {
|
|
6125
|
+
const listener = () => forward(source, type);
|
|
6126
|
+
scope.listen(element, type, listener);
|
|
6127
|
+
const remove = () => scope.unlisten(element, type, listener);
|
|
6128
|
+
removers.push(remove);
|
|
6129
|
+
source.removers.push(remove);
|
|
6130
|
+
}
|
|
6131
|
+
return source;
|
|
6132
|
+
}
|
|
6133
|
+
if (isNative) bindNative(master, null);
|
|
6134
|
+
const group = {
|
|
6135
|
+
transport,
|
|
6136
|
+
duration,
|
|
6137
|
+
setDuration,
|
|
6138
|
+
activate,
|
|
6139
|
+
forward,
|
|
6140
|
+
bindNative,
|
|
6141
|
+
isActive: (source) => active === source,
|
|
6142
|
+
aliasTo(target2) {
|
|
6143
|
+
removers.splice(0).forEach((remove) => remove());
|
|
6144
|
+
delegate = target2;
|
|
6145
|
+
aliases.set(transport, target2);
|
|
6146
|
+
for (const type of events) {
|
|
6147
|
+
const relay = () => emit(transport, type);
|
|
6148
|
+
scope.listen(target2, type, relay);
|
|
6149
|
+
removers.push(() => scope.unlisten(target2, type, relay));
|
|
6150
|
+
}
|
|
6151
|
+
},
|
|
6152
|
+
reconcile(source) {
|
|
6153
|
+
if (active !== source) return;
|
|
6154
|
+
const paused = read().paused;
|
|
6155
|
+
if (paused !== lastPaused) {
|
|
6156
|
+
lastPaused = paused;
|
|
6157
|
+
emit(transport, paused ? "pause" : "playing");
|
|
6158
|
+
}
|
|
6159
|
+
emit(transport, "timeupdate");
|
|
6160
|
+
},
|
|
6161
|
+
remove(source) {
|
|
6162
|
+
if (active === source) {
|
|
6163
|
+
source.pause();
|
|
6164
|
+
active = native;
|
|
6165
|
+
lastPaused = true;
|
|
6166
|
+
emit(transport, "pause");
|
|
6167
|
+
emit(transport, "seeking");
|
|
6168
|
+
emit(transport, "seeked");
|
|
6169
|
+
}
|
|
6170
|
+
},
|
|
6171
|
+
destroy() {
|
|
6172
|
+
removers.splice(0).forEach((remove) => remove());
|
|
6173
|
+
emit(transport, "pause");
|
|
6174
|
+
}
|
|
6175
|
+
};
|
|
6176
|
+
groups.set(master, group);
|
|
6177
|
+
return group;
|
|
6178
|
+
}
|
|
6179
|
+
function registerPlayer(options) {
|
|
6180
|
+
if (!options || options.masterVerified !== true) throw new TypeError("An explicitly verified master association is required");
|
|
6181
|
+
const group = groupFor(options.master), mapping = validatePlaybackMapping(options, group.duration());
|
|
6182
|
+
const element = options.player;
|
|
6183
|
+
if (!element?.addEventListener || !["AUDIO", "VIDEO"].includes(element.tagName)) throw new TypeError("player must be native audio or video");
|
|
6184
|
+
if (element.ownerDocument !== host.document || !scope.legacyGlobals && !scope.root.contains(element)) throw new TypeError("The player must belong to this runtime root");
|
|
6185
|
+
if (registered.has(element)) throw new Error("Player already has a playback owner");
|
|
6186
|
+
if (element === options.master || element === group.transport.element) throw new TypeError("The master is already registered");
|
|
6187
|
+
const previousGroup = groups.get(element);
|
|
6188
|
+
if (previousGroup && previousGroup !== group) {
|
|
6189
|
+
if ([...controllers].some((owner) => owner.source === previousGroup.transport)) throw new Error("This player already owns a different master group");
|
|
6190
|
+
api.unregisterPlaybackSource?.(previousGroup.transport);
|
|
6191
|
+
previousGroup.aliasTo(group.transport);
|
|
6192
|
+
for (const [key, value] of groups) if (value === previousGroup) groups.set(key, group);
|
|
6193
|
+
}
|
|
6194
|
+
const source = group.bindNative(element, mapping);
|
|
6195
|
+
let destroyed = false;
|
|
6196
|
+
const controller = { source: group.transport, mapping, teardown() {
|
|
6197
|
+
if (destroyed) return;
|
|
6198
|
+
destroyed = true;
|
|
6199
|
+
source.removers.splice(0).forEach((remove) => remove());
|
|
6200
|
+
group.remove(source);
|
|
6201
|
+
registered.delete(element);
|
|
6202
|
+
controllers.delete(controller);
|
|
6203
|
+
}, snapshot() {
|
|
6204
|
+
return { kind: "native", mapping, active: group.isActive(source), destroyed };
|
|
6205
|
+
} };
|
|
6206
|
+
registered.set(element, controller);
|
|
6207
|
+
if (!element.paused && !element.ended) group.forward(source, "playing");
|
|
6208
|
+
Promise.resolve(api.ready).then(() => {
|
|
6209
|
+
if (!destroyed && !disposed) api.registerPlaybackSource?.(group.transport);
|
|
6210
|
+
});
|
|
6211
|
+
controllers.add(controller);
|
|
6212
|
+
return controller;
|
|
6213
|
+
}
|
|
6214
|
+
function registerYouTube(options) {
|
|
6215
|
+
if (!options || options.masterVerified !== true) throw new TypeError("An explicitly verified master association is required");
|
|
6216
|
+
const group = groupFor(options.master), mapping = validatePlaybackMapping(options, group.duration());
|
|
6217
|
+
const iframe = options.iframe;
|
|
6218
|
+
if (iframe?.tagName !== "IFRAME") throw new TypeError("A YouTube iframe is required");
|
|
6219
|
+
if (iframe.ownerDocument !== host.document || !scope.legacyGlobals && !scope.root.contains(iframe)) throw new TypeError("The iframe must belong to this runtime root");
|
|
6220
|
+
if (registered.has(iframe)) throw new Error("Player already has a playback owner");
|
|
6221
|
+
const url2 = new URL(iframe.src, host.location.href);
|
|
6222
|
+
if (!/^https:\/\/(www\.)?youtube(-nocookie)?\.com\/embed\/[A-Za-z0-9_-]{11}(\?|$)/.test(url2.href)) throw new TypeError("Unsupported YouTube embed");
|
|
6223
|
+
url2.searchParams.set("enablejsapi", "1");
|
|
6224
|
+
url2.searchParams.set("origin", host.location.origin);
|
|
6225
|
+
const expectedVideoId = url2.pathname.split("/").at(-1);
|
|
6226
|
+
if (iframe.src !== url2.href) iframe.src = url2.href;
|
|
6227
|
+
let player = null, state = -1, error = null, frame = 0, destroyed = false, lastTime = null, lastWall = null, lastRate = 1, readyTimer = 0, rejectReady = null;
|
|
6228
|
+
const source = {
|
|
6229
|
+
element: iframe,
|
|
6230
|
+
mapping,
|
|
6231
|
+
read: () => ({ time: player?.getCurrentTime?.() || 0, paused: state !== 1, ended: state === 0, rate: player?.getPlaybackRate?.() || 1, error }),
|
|
6232
|
+
pause: () => player?.pauseVideo?.(),
|
|
6233
|
+
play: () => player?.playVideo?.(),
|
|
6234
|
+
seek: (time) => player?.seekTo?.(time, true)
|
|
6235
|
+
};
|
|
6236
|
+
function stop() {
|
|
6237
|
+
if (frame) scope.window.cancelAnimationFrame(frame);
|
|
6238
|
+
frame = 0;
|
|
6239
|
+
lastTime = null;
|
|
6240
|
+
lastWall = null;
|
|
6241
|
+
}
|
|
6242
|
+
function sample(wall) {
|
|
6243
|
+
frame = 0;
|
|
6244
|
+
if (destroyed || state !== 1 || scope.document.hidden || !group.isActive(source)) return;
|
|
6245
|
+
const raw = source.read();
|
|
6246
|
+
if (lastTime !== null && Math.abs(raw.time - lastTime - (wall - lastWall) / 1e3 * raw.rate) > 0.4) {
|
|
6247
|
+
group.forward(source, "seeking");
|
|
6248
|
+
group.forward(source, "seeked");
|
|
6249
|
+
}
|
|
6250
|
+
if (raw.rate !== lastRate) {
|
|
6251
|
+
lastRate = raw.rate;
|
|
6252
|
+
group.forward(source, "ratechange");
|
|
6253
|
+
}
|
|
6254
|
+
lastTime = raw.time;
|
|
6255
|
+
lastWall = wall;
|
|
6256
|
+
group.reconcile(source);
|
|
6257
|
+
frame = scope.window.requestAnimationFrame(sample);
|
|
6258
|
+
}
|
|
6259
|
+
function resume() {
|
|
6260
|
+
stop();
|
|
6261
|
+
if (!destroyed && state === 1 && !scope.document.hidden && group.isActive(source)) frame = scope.window.requestAnimationFrame(sample);
|
|
6262
|
+
}
|
|
6263
|
+
const visibility = () => {
|
|
6264
|
+
if (scope.document.hidden) stop();
|
|
6265
|
+
else {
|
|
6266
|
+
group.forward(source, "seeking");
|
|
6267
|
+
group.forward(source, "seeked");
|
|
6268
|
+
resume();
|
|
6269
|
+
}
|
|
6270
|
+
};
|
|
6271
|
+
const pageHide = () => stop(), pageShow = () => {
|
|
6272
|
+
if (player?.getPlayerState) state = player.getPlayerState();
|
|
6273
|
+
visibility();
|
|
6274
|
+
};
|
|
6275
|
+
scope.listen(scope.document, "visibilitychange", visibility);
|
|
6276
|
+
scope.listen(host, "pagehide", pageHide);
|
|
6277
|
+
scope.listen(host, "pageshow", pageShow);
|
|
6278
|
+
const controller = {
|
|
6279
|
+
source: group.transport,
|
|
6280
|
+
mapping,
|
|
6281
|
+
ready: null,
|
|
6282
|
+
teardown() {
|
|
6283
|
+
if (destroyed) return;
|
|
6284
|
+
destroyed = true;
|
|
6285
|
+
stop();
|
|
6286
|
+
if (readyTimer) scope.window.clearTimeout(readyTimer);
|
|
6287
|
+
readyTimer = 0;
|
|
6288
|
+
rejectReady?.(new Error("YouTube playback owner removed"));
|
|
6289
|
+
rejectReady = null;
|
|
6290
|
+
group.remove(source);
|
|
6291
|
+
scope.unlisten(scope.document, "visibilitychange", visibility);
|
|
6292
|
+
scope.unlisten(host, "pagehide", pageHide);
|
|
6293
|
+
scope.unlisten(host, "pageshow", pageShow);
|
|
6294
|
+
player?.destroy?.();
|
|
6295
|
+
registered.delete(iframe);
|
|
6296
|
+
controllers.delete(controller);
|
|
6297
|
+
},
|
|
6298
|
+
snapshot() {
|
|
6299
|
+
return { kind: "youtube", mapping, state, error, active: group.isActive(source), destroyed, polling: !!frame, time: group.transport.currentTime };
|
|
6300
|
+
}
|
|
6301
|
+
};
|
|
6302
|
+
controllers.add(controller);
|
|
6303
|
+
registered.set(iframe, controller);
|
|
6304
|
+
Promise.resolve(api.ready).then(() => {
|
|
6305
|
+
if (!destroyed && !disposed) api.registerPlaybackSource?.(group.transport);
|
|
6306
|
+
});
|
|
6307
|
+
controller.ready = loadYouTubeAPI(host).then((YT) => {
|
|
6308
|
+
if (destroyed || disposed) return controller;
|
|
6309
|
+
return new Promise((resolve, reject) => {
|
|
6310
|
+
rejectReady = reject;
|
|
6311
|
+
readyTimer = scope.window.setTimeout(() => {
|
|
6312
|
+
readyTimer = 0;
|
|
6313
|
+
error = new Error("YouTube player readiness timed out");
|
|
6314
|
+
rejectReady = null;
|
|
6315
|
+
reject(error);
|
|
6316
|
+
}, 15e3);
|
|
6317
|
+
player = new YT.Player(iframe, { events: {
|
|
6318
|
+
onReady() {
|
|
6319
|
+
if (destroyed) return;
|
|
6320
|
+
if (readyTimer) scope.window.clearTimeout(readyTimer);
|
|
6321
|
+
readyTimer = 0;
|
|
6322
|
+
rejectReady = null;
|
|
6323
|
+
const actual = Number(player.getDuration?.());
|
|
6324
|
+
if (actual > 0 && actual + 0.25 < mapping.playerStart + mapping.duration) {
|
|
6325
|
+
error = new Error("The mapped soundtrack window exceeds the video duration");
|
|
6326
|
+
reject(error);
|
|
6327
|
+
return;
|
|
6328
|
+
}
|
|
6329
|
+
group.forward(source, "loadedmetadata");
|
|
6330
|
+
const initialState = player.getPlayerState?.();
|
|
6331
|
+
if (initialState === 1) controllerState({ data: initialState });
|
|
6332
|
+
resolve(controller);
|
|
6333
|
+
},
|
|
6334
|
+
onStateChange: controllerState,
|
|
6335
|
+
onPlaybackRateChange() {
|
|
6336
|
+
if (!destroyed) group.forward(source, "ratechange");
|
|
6337
|
+
},
|
|
6338
|
+
onError(event) {
|
|
6339
|
+
if (destroyed) return;
|
|
6340
|
+
error = new Error("YouTube playback error " + event.data);
|
|
6341
|
+
state = -1;
|
|
6342
|
+
stop();
|
|
6343
|
+
if (readyTimer) scope.window.clearTimeout(readyTimer);
|
|
6344
|
+
readyTimer = 0;
|
|
6345
|
+
rejectReady = null;
|
|
6346
|
+
group.forward(source, "pause");
|
|
6347
|
+
group.forward(source, "error");
|
|
6348
|
+
reject(error);
|
|
6349
|
+
}
|
|
6350
|
+
} });
|
|
6351
|
+
function controllerState(event) {
|
|
6352
|
+
if (destroyed) return;
|
|
6353
|
+
state = event.data;
|
|
6354
|
+
stop();
|
|
6355
|
+
if (state === 1) {
|
|
6356
|
+
let actualId;
|
|
6357
|
+
try {
|
|
6358
|
+
const actualUrl = new URL(player.getVideoUrl());
|
|
6359
|
+
actualId = actualUrl.searchParams.get("v") || actualUrl.pathname.match(/^\/(?:shorts|embed)\/([A-Za-z0-9_-]{11})\/?$/)?.[1];
|
|
6360
|
+
} catch {
|
|
6361
|
+
}
|
|
6362
|
+
if (actualId !== expectedVideoId) {
|
|
6363
|
+
error = new Error("YouTube switched away from the verified soundtrack asset");
|
|
6364
|
+
state = -1;
|
|
6365
|
+
group.forward(source, "pause");
|
|
6366
|
+
group.forward(source, "error");
|
|
6367
|
+
return;
|
|
6368
|
+
}
|
|
6369
|
+
const actualDuration = Number(player.getDuration?.());
|
|
6370
|
+
if (actualDuration > 0 && actualDuration + 0.25 < mapping.playerStart + mapping.duration) {
|
|
6371
|
+
error = new Error("The mapped soundtrack window exceeds the video duration");
|
|
6372
|
+
state = -1;
|
|
6373
|
+
group.forward(source, "pause");
|
|
6374
|
+
group.forward(source, "error");
|
|
6375
|
+
return;
|
|
6376
|
+
}
|
|
6377
|
+
group.forward(source, "play");
|
|
6378
|
+
group.forward(source, "playing");
|
|
6379
|
+
resume();
|
|
6380
|
+
} else group.forward(source, state === 0 ? "ended" : state === 3 ? "waiting" : "pause");
|
|
6381
|
+
if (state === 3) group.forward(source, "pause");
|
|
6382
|
+
}
|
|
6383
|
+
});
|
|
6384
|
+
});
|
|
6385
|
+
controller.ready.catch(() => {
|
|
6386
|
+
});
|
|
6387
|
+
return controller;
|
|
6388
|
+
}
|
|
6389
|
+
Object.assign(api, { playbackSource: (master) => {
|
|
6390
|
+
let source = transports.has(master) ? master : groupFor(master).transport;
|
|
6391
|
+
while (aliases.has(source)) source = aliases.get(source);
|
|
6392
|
+
return source;
|
|
6393
|
+
}, registerPlayer, registerYouTube });
|
|
6394
|
+
scope.onDispose(() => {
|
|
6395
|
+
disposed = true;
|
|
6396
|
+
for (const controller of [...controllers]) controller.teardown();
|
|
6397
|
+
for (const group of new Set(groups.values())) group.destroy();
|
|
6398
|
+
groups.clear();
|
|
6399
|
+
});
|
|
6400
|
+
}
|
|
6401
|
+
|
|
5921
6402
|
// .build/modules/version.mjs
|
|
5922
|
-
var VERSION = "3.1.
|
|
6403
|
+
var VERSION = "3.1.20";
|
|
5923
6404
|
|
|
5924
6405
|
// .build/modules/index.mjs
|
|
5925
6406
|
var mounted = /* @__PURE__ */ new WeakMap();
|
|
@@ -5954,6 +6435,7 @@ function createDanceMoves(options = {}) {
|
|
|
5954
6435
|
}
|
|
5955
6436
|
try {
|
|
5956
6437
|
runtime_default.core(scope);
|
|
6438
|
+
installPlayback(scope, w.DanceMoves, root.ownerDocument.defaultView);
|
|
5957
6439
|
runtime_default.effects(scope);
|
|
5958
6440
|
runtime_default.orientationCore(scope);
|
|
5959
6441
|
runtime_default.native(scope);
|