saltfish 0.2.70 → 0.2.72
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/core/store.d.ts.map +1 -1
- package/dist/managers/CursorManager.d.ts +8 -1
- package/dist/managers/CursorManager.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 +40 -8
- package/dist/saltfish-playlist-player.umd.js +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1419,6 +1419,12 @@ const saltfishStore = createStore()(
|
|
|
1419
1419
|
state.backendPlaylists = playlists;
|
|
1420
1420
|
});
|
|
1421
1421
|
},
|
|
1422
|
+
// Set admin flag from backend
|
|
1423
|
+
setIsAdmin: (isAdmin) => {
|
|
1424
|
+
set2((state) => {
|
|
1425
|
+
state.isAdmin = isAdmin;
|
|
1426
|
+
});
|
|
1427
|
+
},
|
|
1422
1428
|
completePlaylist: () => {
|
|
1423
1429
|
set2((state) => {
|
|
1424
1430
|
state.currentState = transitionState({ type: "COMPLETE_PLAYLIST" });
|
|
@@ -1767,7 +1773,7 @@ __publicField(ErrorHandler, "DEFAULT_OPTIONS", {
|
|
|
1767
1773
|
shouldTriggerEvent: false,
|
|
1768
1774
|
shouldDestroy: false
|
|
1769
1775
|
});
|
|
1770
|
-
const VERSION = "0.2.
|
|
1776
|
+
const VERSION = "0.2.71";
|
|
1771
1777
|
class PlayerInitializationService {
|
|
1772
1778
|
constructor(managers) {
|
|
1773
1779
|
__publicField(this, "managers");
|
|
@@ -1834,8 +1840,8 @@ class PlayerInitializationService {
|
|
|
1834
1840
|
const store = useSaltfishStore.getState();
|
|
1835
1841
|
store.initialize(updatedConfig);
|
|
1836
1842
|
this.managers.analyticsManager.initialize(config, this.managers.sessionManager.getSessionId());
|
|
1837
|
-
if (data.isAdmin) {
|
|
1838
|
-
store.
|
|
1843
|
+
if (data.isAdmin && store.setIsAdmin) {
|
|
1844
|
+
store.setIsAdmin(true);
|
|
1839
1845
|
log("[PlayerInitializationService.initialize] Admin token detected");
|
|
1840
1846
|
}
|
|
1841
1847
|
if (data.playlists && Array.isArray(data.playlists) && store.setBackendPlaylists) {
|
|
@@ -3757,7 +3763,7 @@ const componentsControlsCss = "/* \n * Controls component styles for the Saltfis
|
|
|
3757
3763
|
const componentsTranscriptCss = "/* \n * Transcript component styles for the Saltfish Playlist Player\n * Following BEM naming convention\n */\n\n/* Transcript container */\n.sf-transcript {\n position: absolute;\n bottom: 40px; /* Above the progress bar */\n left: 0;\n right: 0;\n max-height: 200px;\n background: transparent;\n margin: 0 var(--sf-spacing-md);\n overflow: hidden;\n z-index: var(--sf-z-index-overlay);\n opacity: 0;\n transform: translateY(20px);\n transition: all 0.3s ease-out;\n pointer-events: none;\n}\n\n/* Visible state */\n.sf-transcript--visible {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n/* Transcript content */\n.sf-transcript__content {\n max-height: 180px;\n overflow: visible;\n padding: 0;\n}\n\n/* Webkit scrollbar styling */\n.sf-transcript__content::-webkit-scrollbar {\n width: 4px;\n}\n\n.sf-transcript__content::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.sf-transcript__content::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 2px;\n}\n\n.sf-transcript__content::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.5);\n}\n\n/* Word-by-word display container */\n.sf-transcript__word-container {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 0; /* Remove flex gap - spacing handled by margin on preview word */\n min-height: 60px;\n padding: 0;\n}\n\n/* Individual word styling */\n.sf-transcript__word {\n color: rgba(255, 255, 255, 0.9);\n font-size: var(--sf-font-size-lg);\n font-weight: 600;\n line-height: 1.2;\n transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateY(0);\n filter: blur(0px);\n opacity: 1;\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);\n}\n\n/* Active word (currently speaking) */\n.sf-transcript__word--active {\n opacity: 1;\n filter: blur(0px);\n transform: translateY(0) scale(1);\n color: rgba(255, 255, 255, 1);\n font-weight: 600;\n}\n\n/* Preview word (clean, unblurred when shown) */\n.sf-transcript__word--preview {\n opacity: 0.8;\n filter: blur(0px);\n transform: translateY(0) scale(0.98);\n color: rgba(255, 255, 255, 0.8);\n font-weight: 400;\n margin-left: 0.2em; /* Minimal spacing - just enough for a natural gap */\n}\n\n/* Legacy segment styling (kept for compatibility) */\n.sf-transcript__segment {\n color: rgba(255, 255, 255);\n font-size: var(--sf-font-size-sm);\n line-height: 1.4;\n padding: var(--sf-spacing-xs) 0;\n cursor: pointer;\n transition: all 0.2s ease;\n padding-left: var(--sf-spacing-xs);\n padding-right: var(--sf-spacing-xs);\n}\n\n/* CC button styling removed - now handled via icon toggling */\n\n/* Mobile responsive styles */\n@media (max-width: 768px) {\n .sf-transcript {\n bottom: 50px; /* More space on mobile */\n margin: 0 var(--sf-spacing-sm);\n max-height: 150px; /* Smaller on mobile */\n }\n \n .sf-transcript__content {\n max-height: 130px;\n padding: var(--sf-spacing-sm);\n }\n \n .sf-transcript__word-container {\n min-height: 50px;\n padding: var(--sf-spacing-sm);\n gap: var(--sf-spacing-xs);\n }\n \n .sf-transcript__word {\n font-size: var(--sf-font-size-md);\n font-weight: 500;\n }\n \n .sf-transcript__segment {\n font-size: var(--sf-font-size-xs);\n padding: var(--sf-spacing-xs) var(--sf-spacing-sm);\n }\n}\n\n/* Touch device optimizations */\n@media (pointer: coarse) {\n .sf-transcript__segment {\n padding: var(--sf-spacing-sm) var(--sf-spacing-xs);\n min-height: 44px; /* Larger touch target */\n display: flex;\n align-items: center;\n }\n}\n\n/* Hide transcript in minimized state */\n.sf-player--minimized .sf-transcript {\n display: none !important;\n}\n\n/* Hide transcript in autoplayBlocked and idleMode states */\n.sf-player--autoplayBlocked .sf-transcript,\n.sf-player--idleMode .sf-transcript {\n display: none !important;\n}\n\n/* Animation for transcript appearance */\n@keyframes transcriptFadeIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes transcriptFadeOut {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(20px);\n }\n}";
|
|
3758
3764
|
const componentsErrorCss = "/* \n * Error Display component styles for the Saltfish playlist Player\n * Clean and subtle full-widget error overlay\n */\n\n/* Error display overlay - covers full widget */\n.sf-error-display {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.75);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: calc(var(--sf-z-index-controls) + 30);\n border-radius: var(--sf-border-radius-lg);\n opacity: 0;\n transition: opacity var(--sf-transition-slow);\n pointer-events: auto;\n}\n\n/* Error display visible state */\n.sf-error-display--visible {\n opacity: 1;\n}\n\n/* Error content container */\n.sf-error-display__content {\n background-color: rgba(20, 20, 20, 0.9);\n border-radius: var(--sf-border-radius-md);\n padding: var(--sf-spacing-lg) var(--sf-spacing-xl);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border: 1px solid rgba(255, 255, 255, 0.08);\n transform: translateY(8px);\n transition: transform var(--sf-transition-slow);\n max-width: 85%;\n text-align: center;\n}\n\n/* Error content visible animation */\n.sf-error-display--visible .sf-error-display__content {\n transform: translateY(0);\n}\n\n/* Error message */\n.sf-error-display__message {\n color: rgba(255, 255, 255, 0.95);\n font-size: var(--sf-font-size-md);\n line-height: 1.5;\n margin: 0;\n text-align: center;\n font-weight: 500;\n}\n\n/* Mobile responsive adjustments */\n@media (max-width: 768px) {\n .sf-error-display__content {\n padding: var(--sf-spacing-md) var(--sf-spacing-lg);\n max-width: 90%;\n }\n\n .sf-error-display__message {\n font-size: var(--sf-font-size-sm);\n }\n}\n\n/* Minimized player state adjustments */\n.sf-player--minimized .sf-error-display__content {\n padding: var(--sf-spacing-sm) var(--sf-spacing-md);\n max-width: 80%;\n}\n\n.sf-player--minimized .sf-error-display__message {\n font-size: var(--sf-font-size-sm);\n font-weight: 400;\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n .sf-error-display__content {\n background-color: rgba(0, 0, 0, 0.95);\n border: 2px solid rgba(255, 255, 255, 0.3);\n }\n\n .sf-error-display__message {\n color: rgba(255, 255, 255, 0.95);\n }\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n .sf-error-display,\n .sf-error-display__content {\n transition: none;\n }\n}";
|
|
3759
3765
|
const componentsLoadingCss = "/**\n * Loading spinner styles\n */\n\n.sf-loading-spinner {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(2px);\n z-index: 100;\n border-radius: 12px;\n opacity: 1 !important; /* Always visible when shown, overrides parent opacity */\n}\n\n.sf-loading-spinner__content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n}\n\n.sf-loading-spinner__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n color: #000000;\n opacity: 0.9;\n}\n\n.sf-loading-spinner__icon svg {\n width: 60px;\n height: 60px;\n /* Remove the rotation animation since we now have internal SVG animation */\n}\n\n.sf-loading-spinner__text {\n color: #333333;\n font-size: 14px;\n font-weight: 500;\n text-align: center;\n opacity: 0.8;\n letter-spacing: 0.5px;\n}\n\n/* CSS keyframe animation removed - using SVG animateTransform instead */\n\n/* Responsive adjustments */\n@media (max-width: 480px) {\n .sf-loading-spinner__content {\n padding: 20px;\n gap: 10px;\n }\n \n .sf-loading-spinner__icon svg {\n width: 50px;\n height: 50px;\n }\n \n .sf-loading-spinner__text {\n font-size: 13px;\n }\n}";
|
|
3760
|
-
const componentsCursorCss = "/*\n * Cursor animation component styles for the Saltfish playlist Player\n * CSP-compliant: All styles use CSS classes and CSS custom properties instead of inline styles\n */\n\n/* Base cursor element */\n.sf-cursor {\n position: fixed;\n top: 0;\n left: 0;\n width: 36px;\n height: 36px;\n z-index: 9999999;\n pointer-events: none;\n display: none;\n will-change: transform;\n transform: var(--sf-cursor-transform, translate(0, 0));\n opacity: var(--sf-cursor-opacity, 1);\n}\n\n.sf-cursor--visible {\n display: block;\n}\n\n/* Selection element */\n.sf-selection {\n position: fixed;\n pointer-events: none;\n display: none;\n z-index: 9999998;\n border: 2px solid #ff7614;\n background: rgba(255, 118, 20, 0.1);\n left: var(--sf-selection-left, 0);\n top: var(--sf-selection-top, 0);\n width: var(--sf-selection-width, 0);\n height: var(--sf-selection-height, 0);\n}\n\n.sf-selection--visible {\n display: block;\n}\n\n/* Flashlight overlay */\n.sf-flashlight-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n pointer-events: none;\n z-index: 999997;\n display: none;\n background: var(--sf-flashlight-bg, radial-gradient(circle 150px at 50% 50%, transparent 0%, rgba(0, 0, 0, 0.4) 100%));\n clip-path: var(--sf-flashlight-clip, none);\n}\n\n.sf-flashlight-overlay--visible {\n display: block;\n}\n";
|
|
3766
|
+
const componentsCursorCss = "/*\n * Cursor animation component styles for the Saltfish playlist Player\n * CSP-compliant: All styles use CSS classes and CSS custom properties instead of inline styles\n */\n\n/* Base cursor element */\n.sf-cursor {\n position: fixed;\n top: 0;\n left: 0;\n width: 36px;\n height: 36px;\n z-index: 9999999;\n pointer-events: none;\n display: none;\n will-change: transform;\n transform: var(--sf-cursor-transform, translate(0, 0));\n opacity: var(--sf-cursor-opacity, 1);\n}\n\n.sf-cursor--visible {\n display: block;\n}\n\n/* Selection element */\n.sf-selection {\n position: fixed;\n pointer-events: none;\n display: none;\n z-index: 9999998;\n border: 2px solid var(--sf-selection-color, #ff7614);\n background: var(--sf-selection-bg-color, rgba(255, 118, 20, 0.1));\n left: var(--sf-selection-left, 0);\n top: var(--sf-selection-top, 0);\n width: var(--sf-selection-width, 0);\n height: var(--sf-selection-height, 0);\n}\n\n.sf-selection--visible {\n display: block;\n}\n\n/* Flashlight overlay */\n.sf-flashlight-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n pointer-events: none;\n z-index: 999997;\n display: none;\n background: var(--sf-flashlight-bg, radial-gradient(circle 150px at 50% 50%, transparent 0%, rgba(0, 0, 0, 0.4) 100%));\n clip-path: var(--sf-flashlight-clip, none);\n}\n\n.sf-flashlight-overlay--visible {\n display: block;\n}\n";
|
|
3761
3767
|
const animationsTransitionsCss = "/* \n * Transitions and animations for Saltfish playlist Player\n */\n\n/* Fade in animation */\n@keyframes sf-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.sf-fade-in {\n animation: sf-fade-in 0.3s ease-in-out forwards;\n}\n\n/* Slide in from bottom animation */\n@keyframes sf-slide-in-bottom {\n from { transform: translateY(100%); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n\n.sf-slide-in-bottom {\n animation: sf-slide-in-bottom 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Slide in from right animation */\n@keyframes sf-slide-in-right {\n from { transform: translateX(100%); opacity: 0; }\n to { transform: translateX(0); opacity: 1; }\n}\n\n.sf-slide-in-right {\n animation: sf-slide-in-right 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Scale in animation */\n@keyframes sf-scale-in {\n from { transform: scale(0.8); opacity: 0; }\n to { transform: scale(1); opacity: 1; }\n}\n\n.sf-scale-in {\n animation: sf-scale-in 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n}\n\n/* Scale out animation */\n@keyframes sf-scale-out {\n from { transform: scale(1); opacity: 1; }\n to { transform: scale(0.8); opacity: 0; }\n}\n\n.sf-scale-out {\n animation: sf-scale-out 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;\n} ";
|
|
3762
3768
|
const getPlayerStyles = () => `
|
|
3763
3769
|
${baseResetCss}
|
|
@@ -6146,8 +6152,8 @@ class CursorManager {
|
|
|
6146
6152
|
pointer-events: none;
|
|
6147
6153
|
display: none;
|
|
6148
6154
|
z-index: 9999998;
|
|
6149
|
-
border: 2px solid #ff7614;
|
|
6150
|
-
background: rgba(255, 118, 20, 0.1);
|
|
6155
|
+
border: 2px solid var(--sf-selection-color, #ff7614);
|
|
6156
|
+
background: var(--sf-selection-bg-color, rgba(255, 118, 20, 0.1));
|
|
6151
6157
|
left: var(--sf-selection-left, 0);
|
|
6152
6158
|
top: var(--sf-selection-top, 0);
|
|
6153
6159
|
width: var(--sf-selection-width, 0);
|
|
@@ -6906,7 +6912,7 @@ class CursorManager {
|
|
|
6906
6912
|
document.documentElement.style.removeProperty("--sf-cursor-y");
|
|
6907
6913
|
}
|
|
6908
6914
|
/**
|
|
6909
|
-
* Sets the color of the cursor SVG
|
|
6915
|
+
* Sets the color of the cursor SVG and selection highlight
|
|
6910
6916
|
* @param color - The color to set (hex, rgb, etc)
|
|
6911
6917
|
*/
|
|
6912
6918
|
setColor(color) {
|
|
@@ -6926,6 +6932,32 @@ class CursorManager {
|
|
|
6926
6932
|
} else {
|
|
6927
6933
|
console.warn("[CursorManager.setColor] No cursor element");
|
|
6928
6934
|
}
|
|
6935
|
+
if (this.selectionElement) {
|
|
6936
|
+
this.selectionElement.style.setProperty("--sf-selection-color", color);
|
|
6937
|
+
const rgbaBackground = this.colorToRgba(color, 0.1);
|
|
6938
|
+
this.selectionElement.style.setProperty("--sf-selection-bg-color", rgbaBackground);
|
|
6939
|
+
}
|
|
6940
|
+
}
|
|
6941
|
+
/**
|
|
6942
|
+
* Converts a color string (hex, rgb, rgba) to rgba format with specified opacity
|
|
6943
|
+
* @param color - The color to convert
|
|
6944
|
+
* @param opacity - The opacity value (0-1)
|
|
6945
|
+
* @returns rgba color string
|
|
6946
|
+
*/
|
|
6947
|
+
colorToRgba(color, opacity) {
|
|
6948
|
+
const tempElement = document.createElement("div");
|
|
6949
|
+
tempElement.style.color = color;
|
|
6950
|
+
document.body.appendChild(tempElement);
|
|
6951
|
+
const computedColor = window.getComputedStyle(tempElement).color;
|
|
6952
|
+
document.body.removeChild(tempElement);
|
|
6953
|
+
const rgbMatch = computedColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
6954
|
+
if (rgbMatch) {
|
|
6955
|
+
const r = rgbMatch[1];
|
|
6956
|
+
const g = rgbMatch[2];
|
|
6957
|
+
const b = rgbMatch[3];
|
|
6958
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
6959
|
+
}
|
|
6960
|
+
return color;
|
|
6929
6961
|
}
|
|
6930
6962
|
}
|
|
6931
6963
|
class InteractionManager {
|
|
@@ -10716,7 +10748,7 @@ const SaltfishPlayer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
|
|
|
10716
10748
|
__proto__: null,
|
|
10717
10749
|
SaltfishPlayer
|
|
10718
10750
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
10719
|
-
const version = "0.2.
|
|
10751
|
+
const version = "0.2.72";
|
|
10720
10752
|
const packageJson = {
|
|
10721
10753
|
version
|
|
10722
10754
|
};
|