unified-video-framework 1.4.102 → 1.4.104

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.
@@ -1989,16 +1989,20 @@ export class WebPlayer extends BasePlayer {
1989
1989
  width: 100%;
1990
1990
  height: 4px;
1991
1991
  position: relative;
1992
- background: rgba(255,255,255,0.15);
1993
- border-radius: 2px;
1992
+ background: rgba(255, 255, 255, 0.15);
1993
+ border-radius: 6px;
1994
1994
  cursor: pointer;
1995
- padding: 12px 0;
1995
+ padding: 14px 0;
1996
1996
  overflow: visible;
1997
- transition: height 0.2s ease;
1997
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
1998
+ backdrop-filter: blur(4px);
1998
1999
  }
1999
2000
 
2000
2001
  .uvf-progress-bar-wrapper:hover {
2001
2002
  height: 6px;
2003
+ background: rgba(255, 255, 255, 0.2);
2004
+ border-radius: 8px;
2005
+ transform: scaleY(1.1);
2002
2006
  }
2003
2007
 
2004
2008
  .uvf-progress-buffered {
@@ -2006,132 +2010,289 @@ export class WebPlayer extends BasePlayer {
2006
2010
  top: 0;
2007
2011
  left: 0;
2008
2012
  height: 100%;
2009
- background: rgba(255,255,255,0.35);
2010
- border-radius: 2px;
2013
+ background: linear-gradient(90deg,
2014
+ rgba(255, 255, 255, 0.25) 0%,
2015
+ rgba(255, 255, 255, 0.35) 30%,
2016
+ rgba(255, 255, 255, 0.4) 50%,
2017
+ rgba(255, 255, 255, 0.35) 70%,
2018
+ rgba(255, 255, 255, 0.3) 100%
2019
+ );
2020
+ border-radius: 6px;
2011
2021
  pointer-events: none;
2012
- transition: width 0.2s ease;
2022
+ transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
2013
2023
  z-index: 1;
2024
+ position: relative;
2025
+ overflow: hidden;
2026
+ }
2027
+
2028
+ /* Buffered progress loading shimmer effect */
2029
+ .uvf-progress-buffered::before {
2030
+ content: '';
2031
+ position: absolute;
2032
+ top: 0;
2033
+ left: -100%;
2034
+ width: 100%;
2035
+ height: 100%;
2036
+ background: linear-gradient(90deg,
2037
+ transparent 0%,
2038
+ rgba(255, 255, 255, 0.15) 50%,
2039
+ transparent 100%
2040
+ );
2041
+ animation: bufferShimmer 2s infinite;
2042
+ border-radius: 6px;
2043
+ }
2044
+
2045
+ @keyframes bufferShimmer {
2046
+ 0% { left: -100%; }
2047
+ 100% { left: 100%; }
2048
+ }
2049
+
2050
+ .uvf-progress-bar-wrapper:hover .uvf-progress-buffered {
2051
+ border-radius: 8px;
2052
+ background: linear-gradient(90deg,
2053
+ rgba(255, 255, 255, 0.3) 0%,
2054
+ rgba(255, 255, 255, 0.4) 30%,
2055
+ rgba(255, 255, 255, 0.5) 50%,
2056
+ rgba(255, 255, 255, 0.4) 70%,
2057
+ rgba(255, 255, 255, 0.35) 100%
2058
+ );
2059
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
2060
+ }
2061
+
2062
+ .uvf-progress-bar-wrapper:hover .uvf-progress-buffered::before {
2063
+ border-radius: 8px;
2014
2064
  }
2015
2065
 
2016
2066
  .uvf-progress-filled {
2017
- position: relative;
2067
+ position: absolute;
2068
+ top: 0;
2069
+ left: 0;
2018
2070
  height: 100%;
2019
- background: linear-gradient(90deg, #ff5722, #ff7043);
2020
- border-radius: 2px;
2071
+ background: linear-gradient(90deg,
2072
+ #ff4500 0%,
2073
+ #ff5722 25%,
2074
+ #ff6b35 50%,
2075
+ #ff7043 75%,
2076
+ #ff8c69 100%
2077
+ );
2078
+ border-radius: 6px;
2021
2079
  pointer-events: none;
2022
- transition: width 0.2s ease;
2080
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
2023
2081
  z-index: 2;
2082
+ box-shadow: 0 0 12px rgba(255, 87, 34, 0.3);
2083
+ }
2084
+
2085
+ .uvf-progress-bar-wrapper:hover .uvf-progress-filled {
2086
+ border-radius: 8px;
2087
+ background: linear-gradient(90deg,
2088
+ #ff4500 0%,
2089
+ #ff5722 20%,
2090
+ #ff6b35 40%,
2091
+ #ff7043 60%,
2092
+ #ff8c69 80%,
2093
+ #ffa500 100%
2094
+ );
2095
+ box-shadow: 0 0 20px rgba(255, 87, 34, 0.5);
2024
2096
  }
2025
2097
 
2026
2098
  .uvf-progress-handle {
2027
2099
  position: absolute;
2028
- width: 12px;
2029
- height: 12px;
2030
- background: #ffffff;
2031
- border: 2px solid #ff5722;
2100
+ width: 14px;
2101
+ height: 14px;
2102
+ background: radial-gradient(circle,
2103
+ rgba(255, 255, 255, 0.95) 0%,
2104
+ rgba(255, 255, 255, 0.9) 70%,
2105
+ rgba(255, 255, 255, 0.85) 100%
2106
+ );
2107
+ border: 2px solid rgba(255, 87, 34, 0.8);
2032
2108
  border-radius: 50%;
2033
2109
  top: 50%;
2034
- left: 100%;
2035
- margin-left: -6px;
2036
- transform: translateY(-50%);
2110
+ transform: translate(-50%, -50%) scale(0);
2037
2111
  opacity: 0;
2038
- transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
2039
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
2112
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
2113
+ box-shadow:
2114
+ 0 0 0 0 rgba(255, 87, 34, 0.4),
2115
+ 0 4px 12px rgba(0, 0, 0, 0.25),
2116
+ inset 0 1px 0 rgba(255, 255, 255, 0.4);
2040
2117
  cursor: grab;
2041
2118
  z-index: 3;
2119
+ pointer-events: all;
2120
+ backdrop-filter: blur(8px);
2042
2121
  }
2043
2122
 
2044
2123
  .uvf-progress-bar-wrapper:hover .uvf-progress-handle {
2045
2124
  opacity: 1;
2046
- transform: translateY(-50%) scale(1);
2125
+ transform: translate(-50%, -50%) scale(1);
2126
+ box-shadow:
2127
+ 0 0 0 4px rgba(255, 87, 34, 0.2),
2128
+ 0 6px 20px rgba(0, 0, 0, 0.3),
2129
+ inset 0 1px 0 rgba(255, 255, 255, 0.6);
2047
2130
  }
2048
2131
 
2049
2132
  .uvf-progress-handle:hover {
2050
- transform: translateY(-50%) scale(1.15);
2051
- box-shadow: 0 3px 12px rgba(255, 87, 34, 0.4);
2133
+ transform: translate(-50%, -50%) scale(1.25);
2134
+ background: radial-gradient(circle,
2135
+ rgba(255, 255, 255, 1) 0%,
2136
+ rgba(255, 255, 255, 0.95) 70%,
2137
+ rgba(255, 255, 255, 0.9) 100%
2138
+ );
2139
+ border-color: rgba(255, 87, 34, 1);
2140
+ box-shadow:
2141
+ 0 0 0 6px rgba(255, 87, 34, 0.3),
2142
+ 0 8px 25px rgba(255, 87, 34, 0.4),
2143
+ inset 0 1px 0 rgba(255, 255, 255, 0.8);
2052
2144
  }
2053
2145
 
2054
2146
  .uvf-progress-handle:active,
2055
2147
  .uvf-progress-handle.dragging {
2056
2148
  cursor: grabbing;
2057
- transform: translateY(-50%) scale(1.3);
2058
- box-shadow: 0 4px 16px rgba(255, 87, 34, 0.6);
2149
+ transform: translate(-50%, -50%) scale(1.4);
2150
+ background: radial-gradient(circle,
2151
+ rgba(255, 255, 255, 1) 0%,
2152
+ rgba(255, 255, 255, 0.98) 50%,
2153
+ rgba(255, 255, 255, 0.95) 100%
2154
+ );
2155
+ border-color: #ff4500;
2156
+ box-shadow:
2157
+ 0 0 0 8px rgba(255, 87, 34, 0.4),
2158
+ 0 12px 35px rgba(255, 69, 0, 0.5),
2159
+ inset 0 2px 0 rgba(255, 255, 255, 0.9);
2160
+ transition: all 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
2059
2161
  }
2060
2162
 
2061
2163
  .uvf-time-tooltip {
2062
2164
  position: absolute;
2063
- bottom: 24px;
2165
+ bottom: 32px;
2064
2166
  left: 50%;
2065
- transform: translateX(-50%);
2066
- background: rgba(0, 0, 0, 0.95);
2167
+ transform: translateX(-50%) translateY(8px) scale(0.9);
2168
+ background: linear-gradient(135deg,
2169
+ rgba(0, 0, 0, 0.95) 0%,
2170
+ rgba(20, 20, 20, 0.92) 50%,
2171
+ rgba(0, 0, 0, 0.98) 100%
2172
+ );
2067
2173
  color: #ffffff;
2068
- padding: 8px 14px;
2069
- border-radius: 8px;
2174
+ padding: 10px 16px;
2175
+ border-radius: 12px;
2070
2176
  font-size: 13px;
2071
2177
  font-weight: 600;
2178
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
2179
+ letter-spacing: 0.5px;
2072
2180
  white-space: nowrap;
2073
2181
  opacity: 0;
2074
- transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
2182
+ transition: all 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
2075
2183
  pointer-events: none;
2076
2184
  z-index: 4;
2077
- box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
2078
- backdrop-filter: blur(12px);
2079
- border: 1px solid rgba(255, 255, 255, 0.1);
2185
+ box-shadow:
2186
+ 0 0 0 1px rgba(255, 255, 255, 0.05),
2187
+ 0 8px 32px rgba(0, 0, 0, 0.6),
2188
+ 0 2px 8px rgba(0, 0, 0, 0.3),
2189
+ inset 0 1px 0 rgba(255, 255, 255, 0.1);
2190
+ backdrop-filter: blur(20px) saturate(1.5);
2191
+ border: 1px solid rgba(255, 255, 255, 0.08);
2192
+ min-width: 52px;
2193
+ text-align: center;
2080
2194
  }
2081
2195
 
2196
+ /* Glass morphism tooltip arrow with multiple layers */
2082
2197
  .uvf-time-tooltip::after {
2083
2198
  content: '';
2084
2199
  position: absolute;
2085
- bottom: -8px;
2200
+ bottom: -10px;
2086
2201
  left: 50%;
2087
2202
  transform: translateX(-50%);
2088
2203
  width: 0;
2089
2204
  height: 0;
2090
- border-left: 8px solid transparent;
2091
- border-right: 8px solid transparent;
2092
- border-top: 8px solid rgba(0, 0, 0, 0.95);
2205
+ border-left: 10px solid transparent;
2206
+ border-right: 10px solid transparent;
2207
+ border-top: 10px solid rgba(0, 0, 0, 0.95);
2208
+ filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
2093
2209
  }
2094
2210
 
2095
2211
  .uvf-time-tooltip::before {
2096
2212
  content: '';
2097
2213
  position: absolute;
2098
- bottom: -9px;
2214
+ bottom: -11px;
2099
2215
  left: 50%;
2100
2216
  transform: translateX(-50%);
2101
2217
  width: 0;
2102
2218
  height: 0;
2103
- border-left: 9px solid transparent;
2104
- border-right: 9px solid transparent;
2105
- border-top: 9px solid rgba(255, 255, 255, 0.1);
2219
+ border-left: 11px solid transparent;
2220
+ border-right: 11px solid transparent;
2221
+ border-top: 11px solid rgba(255, 255, 255, 0.08);
2106
2222
  z-index: -1;
2107
2223
  }
2108
2224
 
2225
+ /* Enhanced tooltip animations */
2109
2226
  .uvf-progress-bar-wrapper:hover .uvf-time-tooltip {
2110
2227
  opacity: 1;
2111
- transform: translateX(-50%) translateY(-2px);
2228
+ transform: translateX(-50%) translateY(-2px) scale(1);
2229
+ }
2230
+
2231
+ /* Tooltip pulse animation on first hover */
2232
+ @keyframes tooltipPulse {
2233
+ 0% { transform: translateX(-50%) translateY(-2px) scale(1); }
2234
+ 50% { transform: translateX(-50%) translateY(-4px) scale(1.05); }
2235
+ 100% { transform: translateX(-50%) translateY(-2px) scale(1); }
2236
+ }
2237
+
2238
+ .uvf-time-tooltip.pulse {
2239
+ animation: tooltipPulse 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) once;
2112
2240
  }
2113
2241
 
2114
- /* Mobile responsive handle sizing */
2242
+ /* Mobile responsive design with enhanced touch targets */
2115
2243
  @media (max-width: 768px) {
2244
+ .uvf-progress-bar-wrapper {
2245
+ padding: 20px 0; /* Larger touch area */
2246
+ height: 6px; /* Slightly thicker on mobile */
2247
+ }
2248
+
2249
+ .uvf-progress-bar-wrapper:hover {
2250
+ height: 8px;
2251
+ }
2252
+
2116
2253
  .uvf-progress-handle {
2117
- width: 16px;
2118
- height: 16px;
2119
- margin-left: -8px;
2120
- opacity: 0.7; /* Slightly visible always on mobile */
2254
+ width: 18px;
2255
+ height: 18px;
2256
+ opacity: 0.8; /* More visible on mobile for discoverability */
2257
+ border-width: 3px;
2258
+ box-shadow:
2259
+ 0 0 0 2px rgba(255, 87, 34, 0.3),
2260
+ 0 6px 16px rgba(0, 0, 0, 0.3),
2261
+ inset 0 1px 0 rgba(255, 255, 255, 0.5);
2121
2262
  }
2122
2263
 
2123
2264
  .uvf-progress-bar-wrapper:hover .uvf-progress-handle,
2124
2265
  .uvf-progress-handle:active {
2125
2266
  opacity: 1;
2267
+ transform: translate(-50%, -50%) scale(1);
2126
2268
  }
2127
2269
 
2128
2270
  .uvf-progress-handle:hover {
2129
- transform: translateY(-50%) scale(1.1);
2271
+ transform: translate(-50%, -50%) scale(1.15);
2272
+ box-shadow:
2273
+ 0 0 0 4px rgba(255, 87, 34, 0.4),
2274
+ 0 8px 20px rgba(255, 87, 34, 0.35),
2275
+ inset 0 2px 0 rgba(255, 255, 255, 0.7);
2130
2276
  }
2131
2277
 
2132
2278
  .uvf-progress-handle:active,
2133
2279
  .uvf-progress-handle.dragging {
2134
- transform: translateY(-50%) scale(1.25);
2280
+ transform: translate(-50%, -50%) scale(1.3);
2281
+ box-shadow:
2282
+ 0 0 0 6px rgba(255, 87, 34, 0.5),
2283
+ 0 10px 25px rgba(255, 69, 0, 0.4),
2284
+ inset 0 2px 0 rgba(255, 255, 255, 0.8);
2285
+ }
2286
+ }
2287
+
2288
+ /* High DPI displays optimization */
2289
+ @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
2290
+ .uvf-progress-handle {
2291
+ background: radial-gradient(circle,
2292
+ rgba(255, 255, 255, 0.98) 0%,
2293
+ rgba(255, 255, 255, 0.92) 70%,
2294
+ rgba(255, 255, 255, 0.88) 100%
2295
+ );
2135
2296
  }
2136
2297
  }
2137
2298
  /* Controls Row */
@@ -4035,15 +4196,14 @@ export class WebPlayer extends BasePlayer {
4035
4196
  progressBar.id = 'uvf-progress-bar';
4036
4197
  progressBar.innerHTML = `
4037
4198
  <div class="uvf-progress-buffered" id="uvf-progress-buffered"></div>
4038
- <div class="uvf-progress-filled" id="uvf-progress-filled">
4039
- <div class="uvf-progress-handle" id="uvf-progress-handle"
4040
- role="slider"
4041
- tabindex="0"
4042
- aria-label="Seek"
4043
- aria-valuemin="0"
4044
- aria-valuemax="100"
4045
- aria-valuenow="0"></div>
4046
- </div>
4199
+ <div class="uvf-progress-filled" id="uvf-progress-filled"></div>
4200
+ <div class="uvf-progress-handle" id="uvf-progress-handle"
4201
+ role="slider"
4202
+ tabindex="0"
4203
+ aria-label="Seek"
4204
+ aria-valuemin="0"
4205
+ aria-valuemax="100"
4206
+ aria-valuenow="0"></div>
4047
4207
  <div class="uvf-time-tooltip" id="uvf-time-tooltip">00:00</div>
4048
4208
  `;
4049
4209
  progressSection.appendChild(progressBar);
@@ -4404,14 +4564,15 @@ export class WebPlayer extends BasePlayer {
4404
4564
  const progressFilled = document.getElementById('uvf-progress-filled') as HTMLElement;
4405
4565
  const progressHandle = document.getElementById('uvf-progress-handle') as HTMLElement;
4406
4566
 
4407
- if (this.video && progressFilled) {
4567
+ if (this.video && progressFilled && progressHandle) {
4408
4568
  const percent = (this.video.currentTime / this.video.duration) * 100;
4409
4569
  progressFilled.style.width = percent + '%';
4410
4570
 
4571
+ // Position handle at the progress position
4572
+ progressHandle.style.left = percent + '%';
4573
+
4411
4574
  // Update handle aria-valuenow for accessibility
4412
- if (progressHandle) {
4413
- progressHandle.setAttribute('aria-valuenow', percent.toString());
4414
- }
4575
+ progressHandle.setAttribute('aria-valuenow', percent.toString());
4415
4576
  }
4416
4577
 
4417
4578
  // Update time display using the dedicated method
@@ -4999,11 +5160,22 @@ export class WebPlayer extends BasePlayer {
4999
5160
 
5000
5161
  private handleProgressChange(e: MouseEvent): void {
5001
5162
  const progressBar = document.getElementById('uvf-progress-bar');
5163
+ const progressFilled = document.getElementById('uvf-progress-filled') as HTMLElement;
5164
+ const progressHandle = document.getElementById('uvf-progress-handle') as HTMLElement;
5002
5165
  if (!progressBar || !this.video) return;
5003
5166
 
5004
5167
  const rect = progressBar.getBoundingClientRect();
5005
- const percent = (e.clientX - rect.left) / rect.width;
5006
- const time = percent * this.video.duration;
5168
+ const x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
5169
+ const percent = (x / rect.width) * 100;
5170
+ const time = (percent / 100) * this.video.duration;
5171
+
5172
+ // Update UI immediately for responsive feedback
5173
+ if (progressFilled) {
5174
+ progressFilled.style.width = percent + '%';
5175
+ }
5176
+ if (progressHandle) {
5177
+ progressHandle.style.left = percent + '%';
5178
+ }
5007
5179
 
5008
5180
  this.seek(time);
5009
5181
  }
@@ -5148,12 +5320,21 @@ export class WebPlayer extends BasePlayer {
5148
5320
  if (!progressBar || !timeTooltip || !this.video) return;
5149
5321
 
5150
5322
  const rect = progressBar.getBoundingClientRect();
5151
- const percent = (e.clientX - rect.left) / rect.width;
5152
- const time = percent * this.video.duration;
5323
+ const x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
5324
+ const percent = (x / rect.width) * 100;
5325
+ const time = (percent / 100) * this.video.duration;
5153
5326
 
5154
5327
  timeTooltip.textContent = this.formatTime(time);
5155
- timeTooltip.style.left = `${e.clientX - rect.left}px`;
5328
+ timeTooltip.style.left = percent + '%';
5156
5329
  timeTooltip.style.opacity = '1';
5330
+
5331
+ // Add pulse animation on first hover
5332
+ if (!timeTooltip.classList.contains('pulse') && timeTooltip.style.opacity === '1') {
5333
+ timeTooltip.classList.add('pulse');
5334
+ setTimeout(() => {
5335
+ timeTooltip.classList.remove('pulse');
5336
+ }, 600);
5337
+ }
5157
5338
  }
5158
5339
 
5159
5340
  private hideTimeTooltip(): void {
@@ -5166,6 +5347,7 @@ export class WebPlayer extends BasePlayer {
5166
5347
  private updateProgressTooltip(e: MouseEvent): void {
5167
5348
  const progressBar = document.getElementById('uvf-progress-bar');
5168
5349
  const timeTooltip = document.getElementById('uvf-time-tooltip');
5350
+ const progressHandle = document.getElementById('uvf-progress-handle');
5169
5351
  if (!progressBar || !timeTooltip || !this.video) return;
5170
5352
 
5171
5353
  const rect = progressBar.getBoundingClientRect();
@@ -5176,6 +5358,12 @@ export class WebPlayer extends BasePlayer {
5176
5358
  timeTooltip.textContent = this.formatTime(time);
5177
5359
  timeTooltip.style.left = percent + '%';
5178
5360
  timeTooltip.style.opacity = '1';
5361
+
5362
+ // Add visual feedback during dragging
5363
+ if (progressHandle && this.isDragging) {
5364
+ progressHandle.style.transform = 'translate(-50%, -50%) scale(1.4)';
5365
+ progressHandle.classList.add('dragging');
5366
+ }
5179
5367
  }
5180
5368
 
5181
5369