@kieransimkin/dancemoves 3.1.18 → 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/phone-motion-connections.md +2 -0
- package/docs/playback-sources.md +78 -0
- package/lib/build-manifest.json +17 -17
- package/lib/dancemoves.css +1 -1
- 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/styles/dance-moves-core.css +1 -1
- package/lib/wordpress.js +3 -3
- package/package.json +1 -1
- package/readme.txt +2 -2
package/lib/index.cjs
CHANGED
|
@@ -48,6 +48,7 @@ function install(__dmScope) {
|
|
|
48
48
|
var lyricList = [];
|
|
49
49
|
var lyricRenderer = null;
|
|
50
50
|
var boundAudio = /* @__PURE__ */ new WeakSet();
|
|
51
|
+
var playbackBindings = /* @__PURE__ */ new Map();
|
|
51
52
|
var activeAudio = null;
|
|
52
53
|
var pageClockStarted = window2.performance && typeof window2.performance.now === "function" ? window2.performance.now() : Date.now();
|
|
53
54
|
var referenceDurationSeconds = positiveNumber(rawConfig.masterDurationMilliseconds) / 1e3;
|
|
@@ -137,13 +138,16 @@ function install(__dmScope) {
|
|
|
137
138
|
}
|
|
138
139
|
function currentTick(options) {
|
|
139
140
|
var settings = options || {};
|
|
140
|
-
var audio = settings.audio || (settings.clock === "audio" ? activeAudio : null);
|
|
141
|
+
var audio = playbackAudio(settings.audio) || (settings.clock === "audio" ? activeAudio : null);
|
|
141
142
|
if (audio && !audio.paused && !audio.ended && Number.isFinite(Number(audio.currentTime))) {
|
|
142
143
|
return Number(audio.currentTime) * effectiveBpm(settings.bpm || bpm) * TICKS_PER_BEAT / 60;
|
|
143
144
|
}
|
|
144
145
|
var now = window2.performance && typeof window2.performance.now === "function" ? window2.performance.now() : Date.now();
|
|
145
146
|
return Math.max(0, now - pageClockStarted) * effectiveBpm(settings.bpm || bpm) * TICKS_PER_BEAT / 6e4;
|
|
146
147
|
}
|
|
148
|
+
function playbackAudio(audio) {
|
|
149
|
+
return audio && api && api.playbackSource ? api.playbackSource(audio) : audio;
|
|
150
|
+
}
|
|
147
151
|
function nextIntervalTick(intervalTicks, fromTick, strictlyFuture) {
|
|
148
152
|
var interval = Math.max(1, roundHalfUp(intervalTicks));
|
|
149
153
|
var tick = Math.max(0, Number(fromTick) || 0);
|
|
@@ -200,7 +204,7 @@ function install(__dmScope) {
|
|
|
200
204
|
var pollAudio = function() {
|
|
201
205
|
if (cancelled)
|
|
202
206
|
return;
|
|
203
|
-
var candidate = settings.audio || activeAudio;
|
|
207
|
+
var candidate = playbackAudio(settings.audio) || activeAudio;
|
|
204
208
|
if (!candidate || candidate.paused || candidate.ended) {
|
|
205
209
|
if (sourceAudio && sourceAudio.ended) {
|
|
206
210
|
cancel();
|
|
@@ -762,9 +766,18 @@ function install(__dmScope) {
|
|
|
762
766
|
return Math.abs(duration - referenceDurationSeconds) <= Math.max(0.25, duration / 1e5);
|
|
763
767
|
}
|
|
764
768
|
function bindAudio(audio) {
|
|
769
|
+
if (api.playbackSource)
|
|
770
|
+
audio = api.playbackSource(audio);
|
|
765
771
|
if (boundAudio.has(audio) || !matchesMasterDuration(audio))
|
|
766
772
|
return;
|
|
767
773
|
boundAudio.add(audio);
|
|
774
|
+
var removers = [];
|
|
775
|
+
function listen(target, name, handler) {
|
|
776
|
+
__dmScope.listen(target, name, handler);
|
|
777
|
+
removers.push(function() {
|
|
778
|
+
__dmScope.unlisten(target, name, handler);
|
|
779
|
+
});
|
|
780
|
+
}
|
|
768
781
|
__dmScope.dataset(audio, "danceMovesTiming", "master-length");
|
|
769
782
|
var state = {
|
|
770
783
|
next: firstCueAfter(audio.currentTime || 0),
|
|
@@ -772,7 +785,8 @@ function install(__dmScope) {
|
|
|
772
785
|
last: audio.currentTime || 0,
|
|
773
786
|
seeking: false,
|
|
774
787
|
frame: 0,
|
|
775
|
-
pendingCue: cueAtLanding(audio.currentTime || 0)
|
|
788
|
+
pendingCue: cueAtLanding(audio.currentTime || 0),
|
|
789
|
+
endedPending: false
|
|
776
790
|
};
|
|
777
791
|
function stopFrame() {
|
|
778
792
|
if (state.frame)
|
|
@@ -781,7 +795,7 @@ function install(__dmScope) {
|
|
|
781
795
|
}
|
|
782
796
|
function tick() {
|
|
783
797
|
state.frame = 0;
|
|
784
|
-
if (audio.paused || audio.ended || state.seeking)
|
|
798
|
+
if (audio.paused || audio.ended || state.seeking || document2.hidden)
|
|
785
799
|
return;
|
|
786
800
|
var diagnosticStartedAt = diagnosticsSink ? diagnosticNow() : 0;
|
|
787
801
|
var firedCount = 0;
|
|
@@ -819,8 +833,14 @@ function install(__dmScope) {
|
|
|
819
833
|
}
|
|
820
834
|
function start() {
|
|
821
835
|
stopFrame();
|
|
836
|
+
if (document2.hidden || audio.paused || audio.ended)
|
|
837
|
+
return;
|
|
822
838
|
activeAudio = audio;
|
|
823
839
|
state.last = positiveNumber(audio.currentTime);
|
|
840
|
+
if (state.endedPending) {
|
|
841
|
+
state.pendingCue = cueAtLanding(state.last);
|
|
842
|
+
state.endedPending = false;
|
|
843
|
+
}
|
|
824
844
|
state.next = firstCueAfter(state.last);
|
|
825
845
|
state.lyric = -2;
|
|
826
846
|
if (state.pendingCue) {
|
|
@@ -830,47 +850,70 @@ function install(__dmScope) {
|
|
|
830
850
|
setOwnedPlaybackRate(audio.playbackRate);
|
|
831
851
|
state.frame = window2.requestAnimationFrame(tick);
|
|
832
852
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
853
|
+
listen(audio, "play", start);
|
|
854
|
+
listen(audio, "playing", start);
|
|
855
|
+
listen(audio, "pause", function() {
|
|
836
856
|
stopFrame();
|
|
837
857
|
if (activeAudio === audio)
|
|
838
858
|
activeAudio = null;
|
|
839
859
|
if (lyricRenderer)
|
|
840
860
|
lyricRenderer.hide();
|
|
841
861
|
});
|
|
842
|
-
|
|
862
|
+
listen(audio, "ended", function() {
|
|
843
863
|
stopFrame();
|
|
844
864
|
if (activeAudio === audio)
|
|
845
865
|
activeAudio = null;
|
|
846
866
|
state.last = 0;
|
|
847
867
|
state.next = 0;
|
|
848
868
|
state.lyric = -2;
|
|
849
|
-
state.pendingCue =
|
|
869
|
+
state.pendingCue = null;
|
|
870
|
+
state.endedPending = true;
|
|
850
871
|
if (lyricRenderer)
|
|
851
872
|
lyricRenderer.hide();
|
|
852
873
|
});
|
|
853
|
-
|
|
874
|
+
listen(audio, "seeking", function() {
|
|
854
875
|
state.seeking = true;
|
|
855
876
|
state.pendingCue = null;
|
|
856
877
|
stopFrame();
|
|
857
878
|
});
|
|
858
|
-
|
|
879
|
+
listen(audio, "seeked", function() {
|
|
859
880
|
state.seeking = false;
|
|
860
881
|
state.last = positiveNumber(audio.currentTime);
|
|
861
882
|
state.next = firstCueAfter(state.last);
|
|
862
883
|
state.lyric = -2;
|
|
863
884
|
state.pendingCue = cueAtLanding(state.last);
|
|
885
|
+
playbackBindings.set(audio, function() {
|
|
886
|
+
stopFrame();
|
|
887
|
+
removers.splice(0).forEach(function(remove) {
|
|
888
|
+
remove();
|
|
889
|
+
});
|
|
890
|
+
boundAudio.delete(audio);
|
|
891
|
+
if (activeAudio === audio)
|
|
892
|
+
activeAudio = null;
|
|
893
|
+
playbackBindings.delete(audio);
|
|
894
|
+
});
|
|
864
895
|
if (!audio.paused && !audio.ended)
|
|
865
896
|
start();
|
|
866
897
|
});
|
|
867
|
-
|
|
898
|
+
listen(audio, "ratechange", function() {
|
|
868
899
|
setOwnedPlaybackRate(audio.playbackRate);
|
|
869
900
|
});
|
|
870
|
-
|
|
901
|
+
listen(audio, "timeupdate", function() {
|
|
871
902
|
if (!audio.paused && !state.frame && !state.seeking)
|
|
872
903
|
tick();
|
|
873
904
|
});
|
|
905
|
+
listen(document2, "visibilitychange", function() {
|
|
906
|
+
if (document2.hidden) {
|
|
907
|
+
stopFrame();
|
|
908
|
+
if (lyricRenderer)
|
|
909
|
+
lyricRenderer.hide();
|
|
910
|
+
} else if (!audio.paused && !audio.ended && !state.seeking) {
|
|
911
|
+
state.pendingCue = null;
|
|
912
|
+
start();
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
if (!audio.paused && !audio.ended)
|
|
916
|
+
start();
|
|
874
917
|
}
|
|
875
918
|
function discoverAudio() {
|
|
876
919
|
var audioElements = Array.from(document2.querySelectorAll("audio"));
|
|
@@ -984,6 +1027,16 @@ function install(__dmScope) {
|
|
|
984
1027
|
registerAnimationScope,
|
|
985
1028
|
resetRunningAnimations,
|
|
986
1029
|
discoverAudio,
|
|
1030
|
+
unregisterPlaybackSource: function(source) {
|
|
1031
|
+
var remove = playbackBindings.get(source);
|
|
1032
|
+
if (remove)
|
|
1033
|
+
remove();
|
|
1034
|
+
},
|
|
1035
|
+
registerPlaybackSource: function(source) {
|
|
1036
|
+
if (!referenceDurationSeconds)
|
|
1037
|
+
referenceDurationSeconds = positiveNumber(source.duration);
|
|
1038
|
+
bindAudio(source);
|
|
1039
|
+
},
|
|
987
1040
|
setDiagnosticsSink,
|
|
988
1041
|
diagnosticsEnabled: function() {
|
|
989
1042
|
return diagnosticsAllowed && Boolean(diagnosticsSink);
|
|
@@ -1024,6 +1077,10 @@ function install2(__dmScope) {
|
|
|
1024
1077
|
return document2.querySelector(value);
|
|
1025
1078
|
return fallback || null;
|
|
1026
1079
|
}
|
|
1080
|
+
function playbackElement(value, fallback) {
|
|
1081
|
+
var target = element(value, fallback);
|
|
1082
|
+
return target && motion.playbackSource ? motion.playbackSource(target) : target;
|
|
1083
|
+
}
|
|
1027
1084
|
function media(query) {
|
|
1028
1085
|
return window2.matchMedia(query);
|
|
1029
1086
|
}
|
|
@@ -1149,7 +1206,7 @@ function install2(__dmScope) {
|
|
|
1149
1206
|
function playbackPulse(options) {
|
|
1150
1207
|
options = options || {};
|
|
1151
1208
|
var state = commonState(options, "pulse");
|
|
1152
|
-
var audio =
|
|
1209
|
+
var audio = playbackElement(options.audio, state.root.querySelector("audio"));
|
|
1153
1210
|
if (!audio)
|
|
1154
1211
|
throw new Error("DanceMovesEffects pulse requires an audio element");
|
|
1155
1212
|
var ticks = Math.max(1, Math.round(finite2(options.ticks, 16)));
|
|
@@ -1249,7 +1306,7 @@ function install2(__dmScope) {
|
|
|
1249
1306
|
function cueTimeline(options) {
|
|
1250
1307
|
options = options || {};
|
|
1251
1308
|
var state = commonState(options, "cue-timeline");
|
|
1252
|
-
var audio =
|
|
1309
|
+
var audio = playbackElement(options.audio, state.root.querySelector("audio"));
|
|
1253
1310
|
if (!audio)
|
|
1254
1311
|
throw new Error("DanceMovesEffects cueTimeline requires an audio element");
|
|
1255
1312
|
var cues = (Array.isArray(options.cues) ? options.cues : []).map(function(cue, index) {
|
|
@@ -1410,7 +1467,7 @@ function install2(__dmScope) {
|
|
|
1410
1467
|
function spritePlayback(options) {
|
|
1411
1468
|
options = options || {};
|
|
1412
1469
|
var state = commonState(options, "sprite-playback");
|
|
1413
|
-
var audio =
|
|
1470
|
+
var audio = playbackElement(options.audio, state.root.querySelector("audio"));
|
|
1414
1471
|
var target = element(options.target, state.root);
|
|
1415
1472
|
if (!audio)
|
|
1416
1473
|
throw new Error("DanceMovesEffects spritePlayback requires an audio element");
|
|
@@ -1604,7 +1661,7 @@ function install2(__dmScope) {
|
|
|
1604
1661
|
function lyricStage(options) {
|
|
1605
1662
|
options = options || {};
|
|
1606
1663
|
var state = commonState(options, "lyric-stage");
|
|
1607
|
-
var audio =
|
|
1664
|
+
var audio = playbackElement(options.audio, state.root.querySelector("audio"));
|
|
1608
1665
|
var popover = element(options.popover, document2.querySelector(".dance-moves-lyric-popover"));
|
|
1609
1666
|
if (!audio)
|
|
1610
1667
|
throw new Error("DanceMovesEffects lyricStage requires an audio element");
|
|
@@ -4823,9 +4880,11 @@ function install9(__dmScope) {
|
|
|
4823
4880
|
const clock = options.clock === void 0 ? "page" : options.clock;
|
|
4824
4881
|
if (!["page", "audio", "auto"].includes(clock))
|
|
4825
4882
|
throw new TypeError("clock must be page, audio or auto");
|
|
4826
|
-
|
|
4827
|
-
if (audio &&
|
|
4828
|
-
|
|
4883
|
+
let audio = clock === "page" ? null : element(options.audio, "audio");
|
|
4884
|
+
if (audio && motion.playbackSource)
|
|
4885
|
+
audio = motion.playbackSource(audio);
|
|
4886
|
+
if (audio && !["audio", "video"].includes(String(audio.tagName).toLowerCase()))
|
|
4887
|
+
throw new TypeError("audio must resolve to native media or a shared playback source");
|
|
4829
4888
|
const rate = options.rate === void 0 ? 1 : number(options.rate, "rate");
|
|
4830
4889
|
if (rate <= 0 || rate > 64)
|
|
4831
4890
|
throw new RangeError("rate must be in (0, 64]");
|
|
@@ -5073,7 +5132,7 @@ function install9(__dmScope) {
|
|
|
5073
5132
|
}
|
|
5074
5133
|
if (options.resetOnCue)
|
|
5075
5134
|
disposers.push(motion.onCue(typeof options.resetOnCue === "string" ? options.resetOnCue : "*", (detail) => {
|
|
5076
|
-
if (!detail.audio || !audio || detail.audio === audio)
|
|
5135
|
+
if (!detail.audio || !audio || detail.audio === audio || motion.playbackSource && motion.playbackSource(detail.audio) === motion.playbackSource(audio))
|
|
5077
5136
|
reset();
|
|
5078
5137
|
}, { id: id + ":cue-reset" }));
|
|
5079
5138
|
if (options.offscreen !== false && window2.IntersectionObserver) {
|
|
@@ -5347,6 +5406,8 @@ function createScope(root, config, { legacyGlobals = false, nonce, orientation =
|
|
|
5347
5406
|
}
|
|
5348
5407
|
const api = {
|
|
5349
5408
|
id,
|
|
5409
|
+
root,
|
|
5410
|
+
legacyGlobals,
|
|
5350
5411
|
window,
|
|
5351
5412
|
document,
|
|
5352
5413
|
get disposed() {
|
|
@@ -5949,8 +6010,428 @@ function createMotionRecorder(scope, { durationMilliseconds = 3e4, maxSamples =
|
|
|
5949
6010
|
});
|
|
5950
6011
|
}
|
|
5951
6012
|
|
|
6013
|
+
// .build/modules/playback.mjs
|
|
6014
|
+
var youtubeLoaders = /* @__PURE__ */ new WeakMap();
|
|
6015
|
+
function validatePlaybackMapping(input, masterDuration) {
|
|
6016
|
+
const offset = input.offset ?? 0, duration = input.duration ?? masterDuration, playerStart = input.playerStart ?? 0;
|
|
6017
|
+
for (const [key, value] of Object.entries({ offset, duration, playerStart, masterDuration })) {
|
|
6018
|
+
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`);
|
|
6019
|
+
}
|
|
6020
|
+
if (offset + duration > masterDuration + 1e-3) throw new RangeError("The clip extends beyond its associated master");
|
|
6021
|
+
return Object.freeze({ offset, duration, playerStart, masterDuration });
|
|
6022
|
+
}
|
|
6023
|
+
function loadYouTubeAPI(host) {
|
|
6024
|
+
if (host.YT?.Player) return Promise.resolve(host.YT);
|
|
6025
|
+
if (youtubeLoaders.has(host)) return youtubeLoaders.get(host);
|
|
6026
|
+
const pending = new Promise((resolve, reject) => {
|
|
6027
|
+
const previous = host.onYouTubeIframeAPIReady;
|
|
6028
|
+
let timeout;
|
|
6029
|
+
const script = host.document.createElement("script");
|
|
6030
|
+
function finish(error) {
|
|
6031
|
+
host.clearTimeout(timeout);
|
|
6032
|
+
if (host.onYouTubeIframeAPIReady === ready) host.onYouTubeIframeAPIReady = previous;
|
|
6033
|
+
script.removeEventListener("error", failed);
|
|
6034
|
+
if (error) {
|
|
6035
|
+
script.remove();
|
|
6036
|
+
youtubeLoaders.delete(host);
|
|
6037
|
+
reject(error);
|
|
6038
|
+
} else resolve(host.YT);
|
|
6039
|
+
}
|
|
6040
|
+
function ready() {
|
|
6041
|
+
try {
|
|
6042
|
+
previous?.();
|
|
6043
|
+
} finally {
|
|
6044
|
+
finish(host.YT?.Player ? null : new Error("YouTube API unavailable"));
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
function failed() {
|
|
6048
|
+
finish(new Error("YouTube API failed to load"));
|
|
6049
|
+
}
|
|
6050
|
+
host.onYouTubeIframeAPIReady = ready;
|
|
6051
|
+
script.src = "https://www.youtube.com/iframe_api";
|
|
6052
|
+
script.addEventListener("error", failed, { once: true });
|
|
6053
|
+
timeout = host.setTimeout(() => finish(new Error("YouTube API timed out")), 2e4);
|
|
6054
|
+
host.document.head.appendChild(script);
|
|
6055
|
+
});
|
|
6056
|
+
youtubeLoaders.set(host, pending);
|
|
6057
|
+
return pending;
|
|
6058
|
+
}
|
|
6059
|
+
function installPlayback(scope, api, host = scope.document.defaultView) {
|
|
6060
|
+
const groups = /* @__PURE__ */ new Map(), transports = /* @__PURE__ */ new WeakSet(), aliases = /* @__PURE__ */ new WeakMap(), controllers = /* @__PURE__ */ new Set(), registered = /* @__PURE__ */ new WeakMap();
|
|
6061
|
+
let disposed = false;
|
|
6062
|
+
function emit(target, type) {
|
|
6063
|
+
target.dispatchEvent(new host.Event(type));
|
|
6064
|
+
}
|
|
6065
|
+
function groupFor(reference) {
|
|
6066
|
+
if (disposed) throw new Error("DanceMoves playback owner is destroyed");
|
|
6067
|
+
const master = reference?.element || reference, declared = reference?.element ? reference.duration : void 0;
|
|
6068
|
+
const isNative = !!master?.addEventListener && ["AUDIO", "VIDEO"].includes(master.tagName);
|
|
6069
|
+
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");
|
|
6070
|
+
if (isNative && (master.ownerDocument !== host.document || !scope.legacyGlobals && !scope.root.contains(master))) throw new TypeError("The master must belong to this runtime root");
|
|
6071
|
+
if (groups.has(master)) {
|
|
6072
|
+
const group2 = groups.get(master);
|
|
6073
|
+
group2.setDuration(declared);
|
|
6074
|
+
return group2;
|
|
6075
|
+
}
|
|
6076
|
+
const transport = new host.EventTarget();
|
|
6077
|
+
transports.add(transport);
|
|
6078
|
+
let active = null, lastPaused = true, delegate = null;
|
|
6079
|
+
let declaredDuration = declared || 0;
|
|
6080
|
+
function setDuration(value) {
|
|
6081
|
+
if (value === void 0) return;
|
|
6082
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw new RangeError("Declared master duration must be positive and finite");
|
|
6083
|
+
if (declaredDuration && Math.abs(declaredDuration - value) > 1e-3) throw new RangeError("Conflicting master durations");
|
|
6084
|
+
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");
|
|
6085
|
+
declaredDuration = value;
|
|
6086
|
+
}
|
|
6087
|
+
setDuration(declared);
|
|
6088
|
+
const duration = () => delegate?.duration || declaredDuration || (Number(master.duration) > 0 && Number.isFinite(Number(master.duration)) ? Number(master.duration) : Number(api.config?.masterDurationMilliseconds || 0) / 1e3);
|
|
6089
|
+
const target = isNative ? master : scope.root;
|
|
6090
|
+
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) => {
|
|
6091
|
+
if (isNative) master.currentTime = time;
|
|
6092
|
+
}, mapping: null };
|
|
6093
|
+
active = native;
|
|
6094
|
+
function read() {
|
|
6095
|
+
if (delegate) return { time: delegate.currentTime, paused: delegate.paused, ended: delegate.ended, rate: delegate.playbackRate, seeking: delegate.seeking, error: delegate.error };
|
|
6096
|
+
const raw = active.read(), map = active.mapping || { offset: 0, playerStart: 0, duration: duration() };
|
|
6097
|
+
const local = raw.time - map.playerStart, outside = local < -1e-3 || local > map.duration + 1e-3;
|
|
6098
|
+
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 };
|
|
6099
|
+
}
|
|
6100
|
+
Object.defineProperties(transport, {
|
|
6101
|
+
nodeType: { value: 1 },
|
|
6102
|
+
tagName: { get: () => isNative ? master.tagName : "VIDEO" },
|
|
6103
|
+
ownerDocument: { get: () => target.ownerDocument },
|
|
6104
|
+
dataset: { get: () => target.dataset },
|
|
6105
|
+
id: { get: () => master.id },
|
|
6106
|
+
isConnected: { get: () => target.isConnected },
|
|
6107
|
+
currentTime: { get: () => read().time, set: (value) => {
|
|
6108
|
+
if (delegate) {
|
|
6109
|
+
delegate.currentTime = value;
|
|
6110
|
+
return;
|
|
6111
|
+
}
|
|
6112
|
+
const map = active.mapping || { offset: 0, playerStart: 0, duration: duration() };
|
|
6113
|
+
active.seek(map.playerStart + Math.max(0, Math.min(map.duration, Number(value) - map.offset)));
|
|
6114
|
+
} },
|
|
6115
|
+
duration: { get: duration },
|
|
6116
|
+
paused: { get: () => read().paused },
|
|
6117
|
+
ended: { get: () => read().ended },
|
|
6118
|
+
seeking: { get: () => read().seeking || false },
|
|
6119
|
+
playbackRate: { get: () => read().rate },
|
|
6120
|
+
error: { get: () => read().error || null },
|
|
6121
|
+
element: { value: isNative ? master : null },
|
|
6122
|
+
activePlayer: { get: () => delegate ? delegate.activePlayer : active.element },
|
|
6123
|
+
masterId: { get: () => delegate ? delegate.masterId : master.currentSrc || master.src || master.id }
|
|
6124
|
+
});
|
|
6125
|
+
transport.matches = (selector) => target.matches(selector);
|
|
6126
|
+
transport.getAttribute = (name) => target.getAttribute(name);
|
|
6127
|
+
transport.setAttribute = (name, value) => target.setAttribute(name, value);
|
|
6128
|
+
transport.removeAttribute = (name) => target.removeAttribute(name);
|
|
6129
|
+
transport.play = () => delegate ? delegate.play() : active.play();
|
|
6130
|
+
transport.pause = () => delegate ? delegate.pause() : active.pause();
|
|
6131
|
+
function activate(source) {
|
|
6132
|
+
if (active !== source) {
|
|
6133
|
+
const previous = active;
|
|
6134
|
+
active = source;
|
|
6135
|
+
previous.pause();
|
|
6136
|
+
emit(transport, "seeking");
|
|
6137
|
+
emit(transport, "seeked");
|
|
6138
|
+
}
|
|
6139
|
+
}
|
|
6140
|
+
function forward(source, type) {
|
|
6141
|
+
if (type === "play" || type === "playing") activate(source);
|
|
6142
|
+
if (active !== source) return;
|
|
6143
|
+
const paused = read().paused;
|
|
6144
|
+
if (type === "timeupdate" && paused !== lastPaused) emit(transport, paused ? "pause" : "playing");
|
|
6145
|
+
lastPaused = paused;
|
|
6146
|
+
emit(transport, type);
|
|
6147
|
+
}
|
|
6148
|
+
const events = ["loadedmetadata", "durationchange", "play", "playing", "pause", "ended", "seeking", "seeked", "ratechange", "timeupdate", "waiting", "error"];
|
|
6149
|
+
const removers = [];
|
|
6150
|
+
function bindNative(element, mapping) {
|
|
6151
|
+
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) => {
|
|
6152
|
+
element.currentTime = time;
|
|
6153
|
+
} };
|
|
6154
|
+
source.removers = [];
|
|
6155
|
+
for (const type of events) {
|
|
6156
|
+
const listener = () => forward(source, type);
|
|
6157
|
+
scope.listen(element, type, listener);
|
|
6158
|
+
const remove = () => scope.unlisten(element, type, listener);
|
|
6159
|
+
removers.push(remove);
|
|
6160
|
+
source.removers.push(remove);
|
|
6161
|
+
}
|
|
6162
|
+
return source;
|
|
6163
|
+
}
|
|
6164
|
+
if (isNative) bindNative(master, null);
|
|
6165
|
+
const group = {
|
|
6166
|
+
transport,
|
|
6167
|
+
duration,
|
|
6168
|
+
setDuration,
|
|
6169
|
+
activate,
|
|
6170
|
+
forward,
|
|
6171
|
+
bindNative,
|
|
6172
|
+
isActive: (source) => active === source,
|
|
6173
|
+
aliasTo(target2) {
|
|
6174
|
+
removers.splice(0).forEach((remove) => remove());
|
|
6175
|
+
delegate = target2;
|
|
6176
|
+
aliases.set(transport, target2);
|
|
6177
|
+
for (const type of events) {
|
|
6178
|
+
const relay = () => emit(transport, type);
|
|
6179
|
+
scope.listen(target2, type, relay);
|
|
6180
|
+
removers.push(() => scope.unlisten(target2, type, relay));
|
|
6181
|
+
}
|
|
6182
|
+
},
|
|
6183
|
+
reconcile(source) {
|
|
6184
|
+
if (active !== source) return;
|
|
6185
|
+
const paused = read().paused;
|
|
6186
|
+
if (paused !== lastPaused) {
|
|
6187
|
+
lastPaused = paused;
|
|
6188
|
+
emit(transport, paused ? "pause" : "playing");
|
|
6189
|
+
}
|
|
6190
|
+
emit(transport, "timeupdate");
|
|
6191
|
+
},
|
|
6192
|
+
remove(source) {
|
|
6193
|
+
if (active === source) {
|
|
6194
|
+
source.pause();
|
|
6195
|
+
active = native;
|
|
6196
|
+
lastPaused = true;
|
|
6197
|
+
emit(transport, "pause");
|
|
6198
|
+
emit(transport, "seeking");
|
|
6199
|
+
emit(transport, "seeked");
|
|
6200
|
+
}
|
|
6201
|
+
},
|
|
6202
|
+
destroy() {
|
|
6203
|
+
removers.splice(0).forEach((remove) => remove());
|
|
6204
|
+
emit(transport, "pause");
|
|
6205
|
+
}
|
|
6206
|
+
};
|
|
6207
|
+
groups.set(master, group);
|
|
6208
|
+
return group;
|
|
6209
|
+
}
|
|
6210
|
+
function registerPlayer(options) {
|
|
6211
|
+
if (!options || options.masterVerified !== true) throw new TypeError("An explicitly verified master association is required");
|
|
6212
|
+
const group = groupFor(options.master), mapping = validatePlaybackMapping(options, group.duration());
|
|
6213
|
+
const element = options.player;
|
|
6214
|
+
if (!element?.addEventListener || !["AUDIO", "VIDEO"].includes(element.tagName)) throw new TypeError("player must be native audio or video");
|
|
6215
|
+
if (element.ownerDocument !== host.document || !scope.legacyGlobals && !scope.root.contains(element)) throw new TypeError("The player must belong to this runtime root");
|
|
6216
|
+
if (registered.has(element)) throw new Error("Player already has a playback owner");
|
|
6217
|
+
if (element === options.master || element === group.transport.element) throw new TypeError("The master is already registered");
|
|
6218
|
+
const previousGroup = groups.get(element);
|
|
6219
|
+
if (previousGroup && previousGroup !== group) {
|
|
6220
|
+
if ([...controllers].some((owner) => owner.source === previousGroup.transport)) throw new Error("This player already owns a different master group");
|
|
6221
|
+
api.unregisterPlaybackSource?.(previousGroup.transport);
|
|
6222
|
+
previousGroup.aliasTo(group.transport);
|
|
6223
|
+
for (const [key, value] of groups) if (value === previousGroup) groups.set(key, group);
|
|
6224
|
+
}
|
|
6225
|
+
const source = group.bindNative(element, mapping);
|
|
6226
|
+
let destroyed = false;
|
|
6227
|
+
const controller = { source: group.transport, mapping, teardown() {
|
|
6228
|
+
if (destroyed) return;
|
|
6229
|
+
destroyed = true;
|
|
6230
|
+
source.removers.splice(0).forEach((remove) => remove());
|
|
6231
|
+
group.remove(source);
|
|
6232
|
+
registered.delete(element);
|
|
6233
|
+
controllers.delete(controller);
|
|
6234
|
+
}, snapshot() {
|
|
6235
|
+
return { kind: "native", mapping, active: group.isActive(source), destroyed };
|
|
6236
|
+
} };
|
|
6237
|
+
registered.set(element, controller);
|
|
6238
|
+
if (!element.paused && !element.ended) group.forward(source, "playing");
|
|
6239
|
+
Promise.resolve(api.ready).then(() => {
|
|
6240
|
+
if (!destroyed && !disposed) api.registerPlaybackSource?.(group.transport);
|
|
6241
|
+
});
|
|
6242
|
+
controllers.add(controller);
|
|
6243
|
+
return controller;
|
|
6244
|
+
}
|
|
6245
|
+
function registerYouTube(options) {
|
|
6246
|
+
if (!options || options.masterVerified !== true) throw new TypeError("An explicitly verified master association is required");
|
|
6247
|
+
const group = groupFor(options.master), mapping = validatePlaybackMapping(options, group.duration());
|
|
6248
|
+
const iframe = options.iframe;
|
|
6249
|
+
if (iframe?.tagName !== "IFRAME") throw new TypeError("A YouTube iframe is required");
|
|
6250
|
+
if (iframe.ownerDocument !== host.document || !scope.legacyGlobals && !scope.root.contains(iframe)) throw new TypeError("The iframe must belong to this runtime root");
|
|
6251
|
+
if (registered.has(iframe)) throw new Error("Player already has a playback owner");
|
|
6252
|
+
const url2 = new URL(iframe.src, host.location.href);
|
|
6253
|
+
if (!/^https:\/\/(www\.)?youtube(-nocookie)?\.com\/embed\/[A-Za-z0-9_-]{11}(\?|$)/.test(url2.href)) throw new TypeError("Unsupported YouTube embed");
|
|
6254
|
+
url2.searchParams.set("enablejsapi", "1");
|
|
6255
|
+
url2.searchParams.set("origin", host.location.origin);
|
|
6256
|
+
const expectedVideoId = url2.pathname.split("/").at(-1);
|
|
6257
|
+
if (iframe.src !== url2.href) iframe.src = url2.href;
|
|
6258
|
+
let player = null, state = -1, error = null, frame = 0, destroyed = false, lastTime = null, lastWall = null, lastRate = 1, readyTimer = 0, rejectReady = null;
|
|
6259
|
+
const source = {
|
|
6260
|
+
element: iframe,
|
|
6261
|
+
mapping,
|
|
6262
|
+
read: () => ({ time: player?.getCurrentTime?.() || 0, paused: state !== 1, ended: state === 0, rate: player?.getPlaybackRate?.() || 1, error }),
|
|
6263
|
+
pause: () => player?.pauseVideo?.(),
|
|
6264
|
+
play: () => player?.playVideo?.(),
|
|
6265
|
+
seek: (time) => player?.seekTo?.(time, true)
|
|
6266
|
+
};
|
|
6267
|
+
function stop() {
|
|
6268
|
+
if (frame) scope.window.cancelAnimationFrame(frame);
|
|
6269
|
+
frame = 0;
|
|
6270
|
+
lastTime = null;
|
|
6271
|
+
lastWall = null;
|
|
6272
|
+
}
|
|
6273
|
+
function sample(wall) {
|
|
6274
|
+
frame = 0;
|
|
6275
|
+
if (destroyed || state !== 1 || scope.document.hidden || !group.isActive(source)) return;
|
|
6276
|
+
const raw = source.read();
|
|
6277
|
+
if (lastTime !== null && Math.abs(raw.time - lastTime - (wall - lastWall) / 1e3 * raw.rate) > 0.4) {
|
|
6278
|
+
group.forward(source, "seeking");
|
|
6279
|
+
group.forward(source, "seeked");
|
|
6280
|
+
}
|
|
6281
|
+
if (raw.rate !== lastRate) {
|
|
6282
|
+
lastRate = raw.rate;
|
|
6283
|
+
group.forward(source, "ratechange");
|
|
6284
|
+
}
|
|
6285
|
+
lastTime = raw.time;
|
|
6286
|
+
lastWall = wall;
|
|
6287
|
+
group.reconcile(source);
|
|
6288
|
+
frame = scope.window.requestAnimationFrame(sample);
|
|
6289
|
+
}
|
|
6290
|
+
function resume() {
|
|
6291
|
+
stop();
|
|
6292
|
+
if (!destroyed && state === 1 && !scope.document.hidden && group.isActive(source)) frame = scope.window.requestAnimationFrame(sample);
|
|
6293
|
+
}
|
|
6294
|
+
const visibility = () => {
|
|
6295
|
+
if (scope.document.hidden) stop();
|
|
6296
|
+
else {
|
|
6297
|
+
group.forward(source, "seeking");
|
|
6298
|
+
group.forward(source, "seeked");
|
|
6299
|
+
resume();
|
|
6300
|
+
}
|
|
6301
|
+
};
|
|
6302
|
+
const pageHide = () => stop(), pageShow = () => {
|
|
6303
|
+
if (player?.getPlayerState) state = player.getPlayerState();
|
|
6304
|
+
visibility();
|
|
6305
|
+
};
|
|
6306
|
+
scope.listen(scope.document, "visibilitychange", visibility);
|
|
6307
|
+
scope.listen(host, "pagehide", pageHide);
|
|
6308
|
+
scope.listen(host, "pageshow", pageShow);
|
|
6309
|
+
const controller = {
|
|
6310
|
+
source: group.transport,
|
|
6311
|
+
mapping,
|
|
6312
|
+
ready: null,
|
|
6313
|
+
teardown() {
|
|
6314
|
+
if (destroyed) return;
|
|
6315
|
+
destroyed = true;
|
|
6316
|
+
stop();
|
|
6317
|
+
if (readyTimer) scope.window.clearTimeout(readyTimer);
|
|
6318
|
+
readyTimer = 0;
|
|
6319
|
+
rejectReady?.(new Error("YouTube playback owner removed"));
|
|
6320
|
+
rejectReady = null;
|
|
6321
|
+
group.remove(source);
|
|
6322
|
+
scope.unlisten(scope.document, "visibilitychange", visibility);
|
|
6323
|
+
scope.unlisten(host, "pagehide", pageHide);
|
|
6324
|
+
scope.unlisten(host, "pageshow", pageShow);
|
|
6325
|
+
player?.destroy?.();
|
|
6326
|
+
registered.delete(iframe);
|
|
6327
|
+
controllers.delete(controller);
|
|
6328
|
+
},
|
|
6329
|
+
snapshot() {
|
|
6330
|
+
return { kind: "youtube", mapping, state, error, active: group.isActive(source), destroyed, polling: !!frame, time: group.transport.currentTime };
|
|
6331
|
+
}
|
|
6332
|
+
};
|
|
6333
|
+
controllers.add(controller);
|
|
6334
|
+
registered.set(iframe, controller);
|
|
6335
|
+
Promise.resolve(api.ready).then(() => {
|
|
6336
|
+
if (!destroyed && !disposed) api.registerPlaybackSource?.(group.transport);
|
|
6337
|
+
});
|
|
6338
|
+
controller.ready = loadYouTubeAPI(host).then((YT) => {
|
|
6339
|
+
if (destroyed || disposed) return controller;
|
|
6340
|
+
return new Promise((resolve, reject) => {
|
|
6341
|
+
rejectReady = reject;
|
|
6342
|
+
readyTimer = scope.window.setTimeout(() => {
|
|
6343
|
+
readyTimer = 0;
|
|
6344
|
+
error = new Error("YouTube player readiness timed out");
|
|
6345
|
+
rejectReady = null;
|
|
6346
|
+
reject(error);
|
|
6347
|
+
}, 15e3);
|
|
6348
|
+
player = new YT.Player(iframe, { events: {
|
|
6349
|
+
onReady() {
|
|
6350
|
+
if (destroyed) return;
|
|
6351
|
+
if (readyTimer) scope.window.clearTimeout(readyTimer);
|
|
6352
|
+
readyTimer = 0;
|
|
6353
|
+
rejectReady = null;
|
|
6354
|
+
const actual = Number(player.getDuration?.());
|
|
6355
|
+
if (actual > 0 && actual + 0.25 < mapping.playerStart + mapping.duration) {
|
|
6356
|
+
error = new Error("The mapped soundtrack window exceeds the video duration");
|
|
6357
|
+
reject(error);
|
|
6358
|
+
return;
|
|
6359
|
+
}
|
|
6360
|
+
group.forward(source, "loadedmetadata");
|
|
6361
|
+
const initialState = player.getPlayerState?.();
|
|
6362
|
+
if (initialState === 1) controllerState({ data: initialState });
|
|
6363
|
+
resolve(controller);
|
|
6364
|
+
},
|
|
6365
|
+
onStateChange: controllerState,
|
|
6366
|
+
onPlaybackRateChange() {
|
|
6367
|
+
if (!destroyed) group.forward(source, "ratechange");
|
|
6368
|
+
},
|
|
6369
|
+
onError(event) {
|
|
6370
|
+
if (destroyed) return;
|
|
6371
|
+
error = new Error("YouTube playback error " + event.data);
|
|
6372
|
+
state = -1;
|
|
6373
|
+
stop();
|
|
6374
|
+
if (readyTimer) scope.window.clearTimeout(readyTimer);
|
|
6375
|
+
readyTimer = 0;
|
|
6376
|
+
rejectReady = null;
|
|
6377
|
+
group.forward(source, "pause");
|
|
6378
|
+
group.forward(source, "error");
|
|
6379
|
+
reject(error);
|
|
6380
|
+
}
|
|
6381
|
+
} });
|
|
6382
|
+
function controllerState(event) {
|
|
6383
|
+
if (destroyed) return;
|
|
6384
|
+
state = event.data;
|
|
6385
|
+
stop();
|
|
6386
|
+
if (state === 1) {
|
|
6387
|
+
let actualId;
|
|
6388
|
+
try {
|
|
6389
|
+
const actualUrl = new URL(player.getVideoUrl());
|
|
6390
|
+
actualId = actualUrl.searchParams.get("v") || actualUrl.pathname.match(/^\/(?:shorts|embed)\/([A-Za-z0-9_-]{11})\/?$/)?.[1];
|
|
6391
|
+
} catch {
|
|
6392
|
+
}
|
|
6393
|
+
if (actualId !== expectedVideoId) {
|
|
6394
|
+
error = new Error("YouTube switched away from the verified soundtrack asset");
|
|
6395
|
+
state = -1;
|
|
6396
|
+
group.forward(source, "pause");
|
|
6397
|
+
group.forward(source, "error");
|
|
6398
|
+
return;
|
|
6399
|
+
}
|
|
6400
|
+
const actualDuration = Number(player.getDuration?.());
|
|
6401
|
+
if (actualDuration > 0 && actualDuration + 0.25 < mapping.playerStart + mapping.duration) {
|
|
6402
|
+
error = new Error("The mapped soundtrack window exceeds the video duration");
|
|
6403
|
+
state = -1;
|
|
6404
|
+
group.forward(source, "pause");
|
|
6405
|
+
group.forward(source, "error");
|
|
6406
|
+
return;
|
|
6407
|
+
}
|
|
6408
|
+
group.forward(source, "play");
|
|
6409
|
+
group.forward(source, "playing");
|
|
6410
|
+
resume();
|
|
6411
|
+
} else group.forward(source, state === 0 ? "ended" : state === 3 ? "waiting" : "pause");
|
|
6412
|
+
if (state === 3) group.forward(source, "pause");
|
|
6413
|
+
}
|
|
6414
|
+
});
|
|
6415
|
+
});
|
|
6416
|
+
controller.ready.catch(() => {
|
|
6417
|
+
});
|
|
6418
|
+
return controller;
|
|
6419
|
+
}
|
|
6420
|
+
Object.assign(api, { playbackSource: (master) => {
|
|
6421
|
+
let source = transports.has(master) ? master : groupFor(master).transport;
|
|
6422
|
+
while (aliases.has(source)) source = aliases.get(source);
|
|
6423
|
+
return source;
|
|
6424
|
+
}, registerPlayer, registerYouTube });
|
|
6425
|
+
scope.onDispose(() => {
|
|
6426
|
+
disposed = true;
|
|
6427
|
+
for (const controller of [...controllers]) controller.teardown();
|
|
6428
|
+
for (const group of new Set(groups.values())) group.destroy();
|
|
6429
|
+
groups.clear();
|
|
6430
|
+
});
|
|
6431
|
+
}
|
|
6432
|
+
|
|
5952
6433
|
// .build/modules/version.mjs
|
|
5953
|
-
var VERSION = "3.1.
|
|
6434
|
+
var VERSION = "3.1.20";
|
|
5954
6435
|
|
|
5955
6436
|
// .build/modules/index.mjs
|
|
5956
6437
|
var mounted = /* @__PURE__ */ new WeakMap();
|
|
@@ -5985,6 +6466,7 @@ function createDanceMoves(options = {}) {
|
|
|
5985
6466
|
}
|
|
5986
6467
|
try {
|
|
5987
6468
|
runtime_default.core(scope);
|
|
6469
|
+
installPlayback(scope, w.DanceMoves, root.ownerDocument.defaultView);
|
|
5988
6470
|
runtime_default.effects(scope);
|
|
5989
6471
|
runtime_default.orientationCore(scope);
|
|
5990
6472
|
runtime_default.native(scope);
|