saltfish 0.3.73 → 0.3.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/LoadingSpinner.d.ts.map +1 -1
- package/dist/components/buttons/ExitButton.d.ts.map +1 -1
- package/dist/components/buttons/MinimizeButton.d.ts.map +1 -1
- package/dist/components/buttons/PlayPauseButton.d.ts.map +1 -1
- package/dist/managers/CursorManager.d.ts +0 -20
- package/dist/managers/CursorManager.d.ts.map +1 -1
- package/dist/managers/VideoControlsUI.d.ts.map +1 -1
- package/dist/player.js +2 -2
- package/dist/player.min.js +2 -2
- package/dist/saltfish-playlist-player.es.js +96 -173
- package/dist/saltfish-playlist-player.umd.js +1 -1
- package/dist/utils/colorUtils.d.ts +22 -0
- package/dist/utils/colorUtils.d.ts.map +1 -0
- package/dist/utils/domSnapshotCapture.d.ts +23 -0
- package/dist/utils/domSnapshotCapture.d.ts.map +1 -0
- package/dist/utils/elementErrorReporter.d.ts +7 -0
- package/dist/utils/elementErrorReporter.d.ts.map +1 -1
- package/dist/utils/icons.d.ts +19 -0
- package/dist/utils/icons.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -5272,6 +5272,19 @@ function createDevicePlaybackHandler(deviceInfo) {
|
|
|
5272
5272
|
return new DesktopPlaybackHandler(deviceInfo);
|
|
5273
5273
|
}
|
|
5274
5274
|
}
|
|
5275
|
+
const ICON_CLOSE = `<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>`;
|
|
5276
|
+
const ICON_PLUS = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
5277
|
+
const ICON_PLAY = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 5v14l11-7z" fill="currentColor"/></svg>`;
|
|
5278
|
+
const ICON_SPEAKER = `<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z"/></svg>`;
|
|
5279
|
+
const ICON_SPEAKER_MUTED = `<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm101.66-61.3a8,8,0,0,1-11.32,11.32L216,139.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L204.69,128l-18.35-18.34a8,8,0,0,1,11.32-11.32L216,116.69l18.34-18.35a8,8,0,0,1,11.32,11.32L227.31,128Z"/></svg>`;
|
|
5280
|
+
const ICON_CC = `<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM118.92,151.71A8,8,0,0,1,116,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,118.92,151.71Zm80,0A8,8,0,0,1,196,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,198.92,151.71Z"/></svg>`;
|
|
5281
|
+
const ICON_CC_DISABLED = `<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM118.92,151.71A8,8,0,0,1,116,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,118.92,151.71Zm80,0A8,8,0,0,1,196,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,198.92,151.71Z"/><line x1="48" y1="48" x2="208" y2="208" stroke="currentColor" stroke-width="16" stroke-linecap="round"/></svg>`;
|
|
5282
|
+
const ICON_CURSOR = `<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none"><defs><filter id="cursor-shadow" x="-50%" y="-50%" width="200%" height="200%"><feDropShadow dx="0" dy="1" stdDeviation="1.2" flood-color="rgba(0, 0, 0, 0.22)"/></filter></defs><path d="M3.5 3.5L10.5 20.5L13.3 13.3L20.5 10.5L3.5 3.5Z" fill="#ff7614" stroke="white" stroke-width="0.7" stroke-linejoin="round" stroke-linecap="round" filter="url(#cursor-shadow)"/></svg>`;
|
|
5283
|
+
const ICON_LOADING_SPINNER = `<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"><g transform="translate(10, 10) scale(0.656)"><g clip-path="url(#saltfish-clip)"><path d="M61.0002 30.1906C61.0002 46.8644 47.4834 60.3812 30.8097 60.3812C14.136 60.3812 27.1659 46.8644 27.1659 30.1906C27.1659 13.5168 14.136 0 30.8097 0C47.4834 0 61.0002 13.5168 61.0002 30.1906Z" fill="black" fill-opacity="0.9"/><path d="M24.13 29.8618C24.13 40.3565 15.6978 48.8642 5.29602 48.8642C-5.10576 48.8642 3.02294 40.3565 3.02294 29.8618C3.02294 19.3671 -5.10576 10.8594 5.29602 10.8594C15.6978 10.8594 24.13 19.3671 24.13 29.8618Z" fill="black" fill-opacity="0.9"/></g><defs><clipPath id="saltfish-clip"><rect width="61" height="61" fill="white"/></clipPath></defs></g><circle cx="30" cy="30" r="28" stroke="black" stroke-width="2" fill="none" stroke-linecap="round" stroke-dasharray="8 6" stroke-opacity="0.3"><animateTransform attributeName="transform" type="rotate" values="0 30 30;360 30 30" dur="2s" repeatCount="indefinite"/></circle></svg>`;
|
|
5284
|
+
const ICON_SPEAKER_OUTLINE = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="none"/><path d="M15 9c0.8 0.8 1.5 1.9 1.5 3s-0.7 2.2-1.5 3" stroke="currentColor"/><path d="M19 7c1.6 1.6 2.5 3.8 2.5 6s-0.9 4.4-2.5 6" stroke="currentColor"/></svg>`;
|
|
5285
|
+
function createCloseIcon(size = 18) {
|
|
5286
|
+
return `<svg width="${size}" height="${size}" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>`;
|
|
5287
|
+
}
|
|
5275
5288
|
class VideoControlsUI {
|
|
5276
5289
|
constructor(container, deviceHandler, callbacks) {
|
|
5277
5290
|
// Container and control elements
|
|
@@ -5368,13 +5381,7 @@ class VideoControlsUI {
|
|
|
5368
5381
|
this.muteButton = document.createElement("button");
|
|
5369
5382
|
this.muteButton.className = "sf-video-container__mute-button";
|
|
5370
5383
|
this.deviceHandler.configureControlElement(this.muteButton);
|
|
5371
|
-
this.muteButton.innerHTML =
|
|
5372
|
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
5373
|
-
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="none"></polygon>
|
|
5374
|
-
<path d="M15 9c0.8 0.8 1.5 1.9 1.5 3s-0.7 2.2-1.5 3" stroke="currentColor"></path>
|
|
5375
|
-
<path d="M19 7c1.6 1.6 2.5 3.8 2.5 6s-0.9 4.4-2.5 6" stroke="currentColor"></path>
|
|
5376
|
-
</svg>
|
|
5377
|
-
`;
|
|
5384
|
+
this.muteButton.innerHTML = ICON_SPEAKER_OUTLINE;
|
|
5378
5385
|
if (controlsConfig.useTouch) {
|
|
5379
5386
|
this.muteButton.addEventListener("touchend", (event) => {
|
|
5380
5387
|
event.preventDefault();
|
|
@@ -5565,17 +5572,9 @@ class VideoControlsUI {
|
|
|
5565
5572
|
const store = getSaltfishStore();
|
|
5566
5573
|
const isMuted = store.isMuted;
|
|
5567
5574
|
if (isMuted) {
|
|
5568
|
-
this.muteButton.innerHTML =
|
|
5569
|
-
<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
5570
|
-
<path d="M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm101.66-61.3a8,8,0,0,1-11.32,11.32L216,139.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L204.69,128l-18.35-18.34a8,8,0,0,1,11.32-11.32L216,116.69l18.34-18.35a8,8,0,0,1,11.32,11.32L227.31,128Z"></path>
|
|
5571
|
-
</svg>
|
|
5572
|
-
`;
|
|
5575
|
+
this.muteButton.innerHTML = ICON_SPEAKER_MUTED;
|
|
5573
5576
|
} else {
|
|
5574
|
-
this.muteButton.innerHTML =
|
|
5575
|
-
<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
5576
|
-
<path d="M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z"></path>
|
|
5577
|
-
</svg>
|
|
5578
|
-
`;
|
|
5577
|
+
this.muteButton.innerHTML = ICON_SPEAKER;
|
|
5579
5578
|
}
|
|
5580
5579
|
}
|
|
5581
5580
|
/**
|
|
@@ -5584,18 +5583,9 @@ class VideoControlsUI {
|
|
|
5584
5583
|
updateCCButtonIcon(isEnabled) {
|
|
5585
5584
|
if (!this.ccButton) return;
|
|
5586
5585
|
if (isEnabled) {
|
|
5587
|
-
this.ccButton.innerHTML =
|
|
5588
|
-
<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
5589
|
-
<path d="M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM118.92,151.71A8,8,0,0,1,116,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,118.92,151.71Zm80,0A8,8,0,0,1,196,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,198.92,151.71Z"></path>
|
|
5590
|
-
</svg>
|
|
5591
|
-
`;
|
|
5586
|
+
this.ccButton.innerHTML = ICON_CC;
|
|
5592
5587
|
} else {
|
|
5593
|
-
this.ccButton.innerHTML =
|
|
5594
|
-
<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
5595
|
-
<path d="M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM118.92,151.71A8,8,0,0,1,116,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,118.92,151.71Zm80,0A8,8,0,0,1,196,162.64a40,40,0,1,1,0-69.28,8,8,0,1,1-8,13.85,24,24,0,1,0,0,41.58A8,8,0,0,1,198.92,151.71Z"></path>
|
|
5596
|
-
<line x1="48" y1="48" x2="208" y2="208" stroke="currentColor" stroke-width="16" stroke-linecap="round"/>
|
|
5597
|
-
</svg>
|
|
5598
|
-
`;
|
|
5588
|
+
this.ccButton.innerHTML = ICON_CC_DISABLED;
|
|
5599
5589
|
}
|
|
5600
5590
|
}
|
|
5601
5591
|
/**
|
|
@@ -7025,6 +7015,32 @@ function isElementValid(element, expectedElement, expectedSize, config = DEFAULT
|
|
|
7025
7015
|
}
|
|
7026
7016
|
return true;
|
|
7027
7017
|
}
|
|
7018
|
+
const RRWEB_SNAPSHOT_URL = "https://storage.saltfish.ai/libs/rrweb-snapshot-2.0.0-alpha.18.js";
|
|
7019
|
+
async function captureDOMSnapshot() {
|
|
7020
|
+
try {
|
|
7021
|
+
const rrwebSnapshot = await import(
|
|
7022
|
+
/* webpackIgnore: true */
|
|
7023
|
+
RRWEB_SNAPSHOT_URL
|
|
7024
|
+
);
|
|
7025
|
+
const domSnapshot = rrwebSnapshot.snapshot(document);
|
|
7026
|
+
return domSnapshot;
|
|
7027
|
+
} catch (error2) {
|
|
7028
|
+
console.warn("Failed to capture DOM snapshot:", error2);
|
|
7029
|
+
return null;
|
|
7030
|
+
}
|
|
7031
|
+
}
|
|
7032
|
+
async function captureDOMSnapshotAsString() {
|
|
7033
|
+
const snapshot = await captureDOMSnapshot();
|
|
7034
|
+
if (!snapshot) {
|
|
7035
|
+
return null;
|
|
7036
|
+
}
|
|
7037
|
+
try {
|
|
7038
|
+
return JSON.stringify(snapshot);
|
|
7039
|
+
} catch (error2) {
|
|
7040
|
+
console.warn("Failed to serialize DOM snapshot:", error2);
|
|
7041
|
+
return null;
|
|
7042
|
+
}
|
|
7043
|
+
}
|
|
7028
7044
|
const API_URL = "https://player.saltfish.ai/element-errors";
|
|
7029
7045
|
function determineFailureReason(selector, expectedElement, expectedSize) {
|
|
7030
7046
|
const elements = document.querySelectorAll(selector);
|
|
@@ -7047,21 +7063,48 @@ function determineFailureReason(selector, expectedElement, expectedSize) {
|
|
|
7047
7063
|
}
|
|
7048
7064
|
function reportElementError(playlistId, stepId, selector, expectedElement, expectedSize) {
|
|
7049
7065
|
const failureReason = determineFailureReason(selector, expectedElement, expectedSize);
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7066
|
+
(async () => {
|
|
7067
|
+
try {
|
|
7068
|
+
const payload = {
|
|
7069
|
+
playlistId,
|
|
7070
|
+
stepId,
|
|
7071
|
+
failureReason,
|
|
7072
|
+
selector
|
|
7073
|
+
};
|
|
7074
|
+
const domSnapshot = await captureDOMSnapshotAsString();
|
|
7075
|
+
if (domSnapshot) {
|
|
7076
|
+
payload.domSnapshot = domSnapshot;
|
|
7077
|
+
}
|
|
7078
|
+
await fetch(API_URL, {
|
|
7079
|
+
method: "POST",
|
|
7080
|
+
headers: {
|
|
7081
|
+
"Content-Type": "application/json"
|
|
7082
|
+
},
|
|
7083
|
+
body: JSON.stringify(payload)
|
|
7084
|
+
});
|
|
7085
|
+
} catch (error2) {
|
|
7086
|
+
console.warn("Failed to report element error:", error2);
|
|
7087
|
+
}
|
|
7088
|
+
})();
|
|
7089
|
+
}
|
|
7090
|
+
function parseColorToRgb(color) {
|
|
7091
|
+
const el = document.createElement("div");
|
|
7092
|
+
el.style.color = color;
|
|
7093
|
+
document.body.appendChild(el);
|
|
7094
|
+
const computed = window.getComputedStyle(el).color;
|
|
7095
|
+
document.body.removeChild(el);
|
|
7096
|
+
const match = computed.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
7097
|
+
return match ? { r: +match[1], g: +match[2], b: +match[3] } : null;
|
|
7098
|
+
}
|
|
7099
|
+
function colorToRgba(color, opacity) {
|
|
7100
|
+
const rgb = parseColorToRgb(color);
|
|
7101
|
+
return rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${opacity})` : color;
|
|
7102
|
+
}
|
|
7103
|
+
function getContrastingTextColor(bgColor) {
|
|
7104
|
+
const rgb = parseColorToRgb(bgColor);
|
|
7105
|
+
if (!rgb) return "#fff";
|
|
7106
|
+
const luminance = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1e3;
|
|
7107
|
+
return luminance > 150 ? "#333" : "#fff";
|
|
7065
7108
|
}
|
|
7066
7109
|
class CursorManager {
|
|
7067
7110
|
constructor() {
|
|
@@ -7551,16 +7594,7 @@ class CursorManager {
|
|
|
7551
7594
|
this.injectCursorStyles();
|
|
7552
7595
|
this.cursor = document.createElement("div");
|
|
7553
7596
|
this.cursor.className = "sf-cursor";
|
|
7554
|
-
this.cursor.innerHTML =
|
|
7555
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none">
|
|
7556
|
-
<defs>
|
|
7557
|
-
<filter id="cursor-shadow" x="-50%" y="-50%" width="200%" height="200%">
|
|
7558
|
-
<feDropShadow dx="0" dy="1" stdDeviation="1.2" flood-color="rgba(0, 0, 0, 0.22)"/>
|
|
7559
|
-
</filter>
|
|
7560
|
-
</defs>
|
|
7561
|
-
<path d="M3.5 3.5L10.5 20.5L13.3 13.3L20.5 10.5L3.5 3.5Z" fill="#ff7614" stroke="white" stroke-width="0.7" stroke-linejoin="round" stroke-linecap="round" filter="url(#cursor-shadow)" />
|
|
7562
|
-
</svg>
|
|
7563
|
-
`;
|
|
7597
|
+
this.cursor.innerHTML = ICON_CURSOR;
|
|
7564
7598
|
this.labelElement = document.createElement("div");
|
|
7565
7599
|
this.labelElement.className = "sf-cursor-label";
|
|
7566
7600
|
this.selectionElement = document.createElement("div");
|
|
@@ -8432,81 +8466,17 @@ class CursorManager {
|
|
|
8432
8466
|
const path = svg.querySelector("path");
|
|
8433
8467
|
if (path) {
|
|
8434
8468
|
path.setAttribute("fill", color);
|
|
8435
|
-
} else {
|
|
8436
|
-
console.warn("[CursorManager.setColor] No path found in SVG");
|
|
8437
8469
|
}
|
|
8438
|
-
} else {
|
|
8439
|
-
console.warn("[CursorManager.setColor] No SVG found in cursor");
|
|
8440
8470
|
}
|
|
8441
|
-
} else {
|
|
8442
|
-
console.warn("[CursorManager.setColor] No cursor element");
|
|
8443
8471
|
}
|
|
8444
8472
|
if (this.selectionElement) {
|
|
8445
8473
|
this.selectionElement.style.setProperty("--sf-selection-color", color);
|
|
8446
|
-
|
|
8447
|
-
this.selectionElement.style.setProperty("--sf-selection-bg-color", rgbaBackground);
|
|
8474
|
+
this.selectionElement.style.setProperty("--sf-selection-bg-color", colorToRgba(color, 0));
|
|
8448
8475
|
}
|
|
8449
8476
|
if (this.labelElement) {
|
|
8450
8477
|
this.labelElement.style.setProperty("--sf-cursor-label-bg", color);
|
|
8451
|
-
|
|
8452
|
-
this.labelElement.style.setProperty("--sf-cursor-label-text", textColor);
|
|
8453
|
-
}
|
|
8454
|
-
}
|
|
8455
|
-
/**
|
|
8456
|
-
* Calculates whether white or black text provides better contrast against a background color
|
|
8457
|
-
* Uses relative luminance calculation for accessibility
|
|
8458
|
-
* @param bgColor - The background color (hex, rgb, etc)
|
|
8459
|
-
* @returns '#fff' for dark backgrounds, '#333' for light backgrounds
|
|
8460
|
-
*/
|
|
8461
|
-
getContrastingTextColor(bgColor) {
|
|
8462
|
-
const rgb = this.parseColorToRgb(bgColor);
|
|
8463
|
-
if (!rgb) {
|
|
8464
|
-
return "#fff";
|
|
8465
|
-
}
|
|
8466
|
-
const luminance = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1e3;
|
|
8467
|
-
return luminance > 150 ? "#333" : "#fff";
|
|
8468
|
-
}
|
|
8469
|
-
/**
|
|
8470
|
-
* Parses a color string to RGB values
|
|
8471
|
-
* @param color - The color to parse (hex, rgb, rgba)
|
|
8472
|
-
* @returns RGB object or null if parsing fails
|
|
8473
|
-
*/
|
|
8474
|
-
parseColorToRgb(color) {
|
|
8475
|
-
const tempElement = document.createElement("div");
|
|
8476
|
-
tempElement.style.color = color;
|
|
8477
|
-
document.body.appendChild(tempElement);
|
|
8478
|
-
const computedColor = window.getComputedStyle(tempElement).color;
|
|
8479
|
-
document.body.removeChild(tempElement);
|
|
8480
|
-
const rgbMatch = computedColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
8481
|
-
if (rgbMatch) {
|
|
8482
|
-
return {
|
|
8483
|
-
r: parseInt(rgbMatch[1], 10),
|
|
8484
|
-
g: parseInt(rgbMatch[2], 10),
|
|
8485
|
-
b: parseInt(rgbMatch[3], 10)
|
|
8486
|
-
};
|
|
8487
|
-
}
|
|
8488
|
-
return null;
|
|
8489
|
-
}
|
|
8490
|
-
/**
|
|
8491
|
-
* Converts a color string (hex, rgb, rgba) to rgba format with specified opacity
|
|
8492
|
-
* @param color - The color to convert
|
|
8493
|
-
* @param opacity - The opacity value (0-1)
|
|
8494
|
-
* @returns rgba color string
|
|
8495
|
-
*/
|
|
8496
|
-
colorToRgba(color, opacity) {
|
|
8497
|
-
const tempElement = document.createElement("div");
|
|
8498
|
-
tempElement.style.color = color;
|
|
8499
|
-
document.body.appendChild(tempElement);
|
|
8500
|
-
const computedColor = window.getComputedStyle(tempElement).color;
|
|
8501
|
-
document.body.removeChild(tempElement);
|
|
8502
|
-
const rgbMatch = computedColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
8503
|
-
if (rgbMatch) {
|
|
8504
|
-
const r = rgbMatch[1];
|
|
8505
|
-
const g = rgbMatch[2];
|
|
8506
|
-
const b = rgbMatch[3];
|
|
8507
|
-
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
8478
|
+
this.labelElement.style.setProperty("--sf-cursor-label-text", getContrastingTextColor(color));
|
|
8508
8479
|
}
|
|
8509
|
-
return color;
|
|
8510
8480
|
}
|
|
8511
8481
|
/**
|
|
8512
8482
|
* Sets the label text to display beside the cursor
|
|
@@ -11493,11 +11463,7 @@ class MinimizeButton {
|
|
|
11493
11463
|
this.playerElement = playerElement;
|
|
11494
11464
|
this.button = document.createElement("button");
|
|
11495
11465
|
this.button.className = "sf-player__minimize-button";
|
|
11496
|
-
this.button.innerHTML =
|
|
11497
|
-
<svg width="20" height="20" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
11498
|
-
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
11499
|
-
</svg>
|
|
11500
|
-
`;
|
|
11466
|
+
this.button.innerHTML = createCloseIcon(20);
|
|
11501
11467
|
this.button.addEventListener("click", this.handleClick.bind(this));
|
|
11502
11468
|
this.playerElement.appendChild(this.button);
|
|
11503
11469
|
this.updateVisibility(getSaltfishStore().isMinimized);
|
|
@@ -11517,18 +11483,10 @@ class MinimizeButton {
|
|
|
11517
11483
|
}
|
|
11518
11484
|
}
|
|
11519
11485
|
minimize() {
|
|
11520
|
-
this.button.innerHTML =
|
|
11521
|
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
11522
|
-
<path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
11523
|
-
</svg>
|
|
11524
|
-
`;
|
|
11486
|
+
this.button.innerHTML = ICON_PLUS;
|
|
11525
11487
|
}
|
|
11526
11488
|
maximize() {
|
|
11527
|
-
this.button.innerHTML =
|
|
11528
|
-
<svg width="20" height="20" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
11529
|
-
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
11530
|
-
</svg>
|
|
11531
|
-
`;
|
|
11489
|
+
this.button.innerHTML = createCloseIcon(20);
|
|
11532
11490
|
}
|
|
11533
11491
|
updateVisibility(isMinimized) {
|
|
11534
11492
|
if (isMinimized) {
|
|
@@ -11554,11 +11512,7 @@ class PlayPauseButton {
|
|
|
11554
11512
|
createButton() {
|
|
11555
11513
|
this.playButton = document.createElement("button");
|
|
11556
11514
|
this.playButton.className = "sf-controls-container__play-button";
|
|
11557
|
-
this.playButton.innerHTML =
|
|
11558
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
11559
|
-
<path d="M8 5v14l11-7z" fill="currentColor"/>
|
|
11560
|
-
</svg>
|
|
11561
|
-
`;
|
|
11515
|
+
this.playButton.innerHTML = ICON_PLAY;
|
|
11562
11516
|
this.playButton.addEventListener("click", this.handlePlayClick.bind(this));
|
|
11563
11517
|
this.container.appendChild(this.playButton);
|
|
11564
11518
|
}
|
|
@@ -11610,11 +11564,7 @@ class ExitButton {
|
|
|
11610
11564
|
this.playerElement = playerElement;
|
|
11611
11565
|
this.button = document.createElement("button");
|
|
11612
11566
|
this.button.className = "sf-player__exit-button";
|
|
11613
|
-
this.button.innerHTML =
|
|
11614
|
-
<svg width="18" height="18" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
11615
|
-
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
11616
|
-
</svg>
|
|
11617
|
-
`;
|
|
11567
|
+
this.button.innerHTML = ICON_CLOSE;
|
|
11618
11568
|
this.button.addEventListener("click", this.handleClick.bind(this));
|
|
11619
11569
|
this.playerElement.appendChild(this.button);
|
|
11620
11570
|
this.updateVisibility(getSaltfishStore().isMinimized);
|
|
@@ -11756,34 +11706,7 @@ class LoadingSpinner {
|
|
|
11756
11706
|
this.spinnerElement.className = `${CSS_CLASSES.LOADING_SPINNER}`;
|
|
11757
11707
|
this.spinnerElement.innerHTML = `
|
|
11758
11708
|
<div class="sf-loading-spinner__content">
|
|
11759
|
-
<div class="sf-loading-spinner__icon">
|
|
11760
|
-
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
11761
|
-
<!-- Static Saltfish logo in center -->
|
|
11762
|
-
<g transform="translate(10, 10) scale(0.656)">
|
|
11763
|
-
<g clip-path="url(#saltfish-clip)">
|
|
11764
|
-
<path d="M61.0002 30.1906C61.0002 46.8644 47.4834 60.3812 30.8097 60.3812C14.136 60.3812 27.1659 46.8644 27.1659 30.1906C27.1659 13.5168 14.136 0 30.8097 0C47.4834 0 61.0002 13.5168 61.0002 30.1906Z" fill="black" fill-opacity="0.9"/>
|
|
11765
|
-
<path d="M24.13 29.8618C24.13 40.3565 15.6978 48.8642 5.29602 48.8642C-5.10576 48.8642 3.02294 40.3565 3.02294 29.8618C3.02294 19.3671 -5.10576 10.8594 5.29602 10.8594C15.6978 10.8594 24.13 19.3671 24.13 29.8618Z" fill="black" fill-opacity="0.9"/>
|
|
11766
|
-
</g>
|
|
11767
|
-
<defs>
|
|
11768
|
-
<clipPath id="saltfish-clip">
|
|
11769
|
-
<rect width="61" height="61" fill="white"/>
|
|
11770
|
-
</clipPath>
|
|
11771
|
-
</defs>
|
|
11772
|
-
</g>
|
|
11773
|
-
|
|
11774
|
-
<!-- Animated circular ring around logo -->
|
|
11775
|
-
<circle cx="30" cy="30" r="28"
|
|
11776
|
-
stroke="black" stroke-width="2"
|
|
11777
|
-
fill="none" stroke-linecap="round"
|
|
11778
|
-
stroke-dasharray="8 6" stroke-opacity="0.3">
|
|
11779
|
-
<animateTransform attributeName="transform"
|
|
11780
|
-
type="rotate"
|
|
11781
|
-
values="0 30 30;360 30 30"
|
|
11782
|
-
dur="2s"
|
|
11783
|
-
repeatCount="indefinite"/>
|
|
11784
|
-
</circle>
|
|
11785
|
-
</svg>
|
|
11786
|
-
</div>
|
|
11709
|
+
<div class="sf-loading-spinner__icon">${ICON_LOADING_SPINNER}</div>
|
|
11787
11710
|
<div class="sf-loading-spinner__text">Loading playlist...</div>
|
|
11788
11711
|
</div>
|
|
11789
11712
|
`;
|
|
@@ -12709,7 +12632,7 @@ const SaltfishPlayer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
|
|
|
12709
12632
|
__proto__: null,
|
|
12710
12633
|
SaltfishPlayer
|
|
12711
12634
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
12712
|
-
const version = "0.3.
|
|
12635
|
+
const version = "0.3.75";
|
|
12713
12636
|
const packageJson = {
|
|
12714
12637
|
version
|
|
12715
12638
|
};
|