unified-video-framework 1.4.369 → 1.4.371

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.
@@ -384,6 +384,7 @@ export class ChapterManager {
384
384
 
385
385
  // Check if segment changed
386
386
  if (newSegment !== this.currentSegment) {
387
+
387
388
  // Handle segment exit
388
389
  if (this.currentSegment) {
389
390
  this.emit('segmentExited', {
@@ -412,6 +413,7 @@ export class ChapterManager {
412
413
 
413
414
  // Handle segment entry
414
415
  if (this.currentSegment) {
416
+
415
417
  this.emit('segmentEntered', {
416
418
  segment: this.currentSegment,
417
419
  currentTime,
@@ -42,7 +42,6 @@ export class CreditsButtonController {
42
42
  public showCreditsButtons(segment: VideoSegment, currentTime: number): void {
43
43
  // Verify segment has nextEpisodeUrl
44
44
  if (!segment.nextEpisodeUrl) {
45
- console.warn('[CreditsButtonController] Segment does not have nextEpisodeUrl');
46
45
  return;
47
46
  }
48
47
 
@@ -129,24 +128,31 @@ export class CreditsButtonController {
129
128
  * Create the credits buttons DOM elements
130
129
  */
131
130
  private createCreditsButtons(): void {
131
+ const segment = this.currentSegment;
132
+ const style = segment?.creditsButtonStyle;
133
+ const layout = style?.layout || 'vertical';
134
+ const position = style?.position || 'bottom-right';
135
+
132
136
  // Create container
133
137
  this.buttonsContainer = document.createElement('div');
134
138
  this.buttonsContainer.className = 'uvf-credits-buttons';
135
139
  this.buttonsContainer.setAttribute('role', 'group');
136
140
  this.buttonsContainer.setAttribute('aria-label', 'Credits navigation');
137
141
 
138
- // Apply container styles
139
- Object.assign(this.buttonsContainer.style, {
142
+ // Apply container styles based on layout and position
143
+ const containerStyles: Partial<CSSStyleDeclaration> = {
140
144
  position: 'absolute',
141
- bottom: '100px',
142
- right: '30px',
143
145
  display: 'flex',
144
- flexDirection: 'column',
146
+ flexDirection: layout === 'horizontal' ? 'row' : 'column',
145
147
  gap: '10px',
146
148
  zIndex: '1000',
147
149
  opacity: '0',
148
150
  transition: 'opacity 0.3s ease-in-out'
149
- });
151
+ };
152
+
153
+ // Position the container
154
+ this.applyContainerPosition(containerStyles, position);
155
+ Object.assign(this.buttonsContainer.style, containerStyles);
150
156
 
151
157
  // Create "Watch Credits" button
152
158
  this.watchCreditsButton = document.createElement('button');
@@ -166,9 +172,9 @@ export class CreditsButtonController {
166
172
  // Add click handler for Next Episode
167
173
  this.nextEpisodeButton.addEventListener('click', () => this.handleNextEpisodeClick());
168
174
 
169
- // Apply button styles
170
- this.applyButtonStyles(this.watchCreditsButton, 'watch-credits');
171
- this.applyButtonStyles(this.nextEpisodeButton, 'next-episode');
175
+ // Apply button styles with custom colors
176
+ this.applyButtonStyles(this.watchCreditsButton, 'watch-credits', style);
177
+ this.applyButtonStyles(this.nextEpisodeButton, 'next-episode', style);
172
178
 
173
179
  // Append buttons to container
174
180
  this.buttonsContainer.appendChild(this.watchCreditsButton);
@@ -178,10 +184,36 @@ export class CreditsButtonController {
178
184
  this.playerContainer.appendChild(this.buttonsContainer);
179
185
  }
180
186
 
187
+ /**
188
+ * Apply position styles to container
189
+ */
190
+ private applyContainerPosition(styles: Partial<CSSStyleDeclaration>, position: string): void {
191
+ switch (position) {
192
+ case 'bottom-right':
193
+ Object.assign(styles, { bottom: '100px', right: '30px' });
194
+ break;
195
+ case 'bottom-left':
196
+ Object.assign(styles, { bottom: '100px', left: '30px' });
197
+ break;
198
+ case 'bottom-center':
199
+ Object.assign(styles, { bottom: '100px', left: '50%', transform: 'translateX(-50%)' });
200
+ break;
201
+ case 'top-right':
202
+ Object.assign(styles, { top: '30px', right: '30px' });
203
+ break;
204
+ case 'top-left':
205
+ Object.assign(styles, { top: '30px', left: '30px' });
206
+ break;
207
+ case 'top-center':
208
+ Object.assign(styles, { top: '30px', left: '50%', transform: 'translateX(-50%)' });
209
+ break;
210
+ }
211
+ }
212
+
181
213
  /**
182
214
  * Apply styles to buttons
183
215
  */
184
- private applyButtonStyles(button: HTMLElement, type: 'watch-credits' | 'next-episode'): void {
216
+ private applyButtonStyles(button: HTMLElement, type: 'watch-credits' | 'next-episode', customStyle?: any): void {
185
217
  const baseStyles: Partial<CSSStyleDeclaration> = {
186
218
  padding: '12px 24px',
187
219
  fontSize: '14px',
@@ -198,14 +230,14 @@ export class CreditsButtonController {
198
230
 
199
231
  if (type === 'watch-credits') {
200
232
  Object.assign(baseStyles, {
201
- backgroundColor: 'rgba(255, 255, 255, 0.15)',
202
- color: '#ffffff',
203
- border: '2px solid rgba(255, 255, 255, 0.3)'
233
+ backgroundColor: customStyle?.watchCreditsBgColor || 'rgba(255, 255, 255, 0.15)',
234
+ color: customStyle?.watchCreditsColor || '#ffffff',
235
+ border: `2px solid ${customStyle?.watchCreditsBgColor ? 'transparent' : 'rgba(255, 255, 255, 0.3)'}`
204
236
  });
205
237
  } else {
206
238
  Object.assign(baseStyles, {
207
- backgroundColor: '#e50914',
208
- color: '#ffffff',
239
+ backgroundColor: customStyle?.nextEpisodeBgColor || '#e50914',
240
+ color: customStyle?.nextEpisodeColor || '#ffffff',
209
241
  boxShadow: '0 2px 8px rgba(229, 9, 20, 0.4)'
210
242
  });
211
243
  }
@@ -215,25 +247,43 @@ export class CreditsButtonController {
215
247
  // Add hover effect
216
248
  button.addEventListener('mouseenter', () => {
217
249
  if (type === 'watch-credits') {
218
- button.style.backgroundColor = 'rgba(255, 255, 255, 0.25)';
219
- button.style.borderColor = 'rgba(255, 255, 255, 0.5)';
250
+ button.style.backgroundColor = customStyle?.watchCreditsBgColor
251
+ ? this.adjustBrightness(customStyle.watchCreditsBgColor, 20)
252
+ : 'rgba(255, 255, 255, 0.25)';
220
253
  } else {
221
- button.style.backgroundColor = '#f40612';
254
+ button.style.backgroundColor = customStyle?.nextEpisodeBgColor
255
+ ? this.adjustBrightness(customStyle.nextEpisodeBgColor, 20)
256
+ : '#f40612';
222
257
  button.style.transform = 'scale(1.03)';
223
258
  }
224
259
  });
225
260
 
226
261
  button.addEventListener('mouseleave', () => {
227
262
  if (type === 'watch-credits') {
228
- button.style.backgroundColor = 'rgba(255, 255, 255, 0.15)';
229
- button.style.borderColor = 'rgba(255, 255, 255, 0.3)';
263
+ button.style.backgroundColor = customStyle?.watchCreditsBgColor || 'rgba(255, 255, 255, 0.15)';
230
264
  } else {
231
- button.style.backgroundColor = '#e50914';
265
+ button.style.backgroundColor = customStyle?.nextEpisodeBgColor || '#e50914';
232
266
  button.style.transform = 'scale(1)';
233
267
  }
234
268
  });
235
269
  }
236
270
 
271
+ /**
272
+ * Adjust color brightness for hover effects
273
+ */
274
+ private adjustBrightness(color: string, percent: number): string {
275
+ // Simple brightness adjustment - works for hex and rgb
276
+ const num = parseInt(color.replace('#', ''), 16);
277
+ const amt = Math.round(2.55 * percent);
278
+ const R = (num >> 16) + amt;
279
+ const G = (num >> 8 & 0x00FF) + amt;
280
+ const B = (num & 0x0000FF) + amt;
281
+ return '#' + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
282
+ (G < 255 ? G < 1 ? 0 : G : 255) * 0x100 +
283
+ (B < 255 ? B < 1 ? 0 : B : 255))
284
+ .toString(16).slice(1);
285
+ }
286
+
237
287
  /**
238
288
  * Update button labels based on segment configuration
239
289
  */
@@ -48,6 +48,27 @@ export interface VideoSegment {
48
48
 
49
49
  /** Custom label for "Next Episode/Play Next" button */
50
50
  nextEpisodeLabel?: string;
51
+
52
+ /** Styling options for credits buttons */
53
+ creditsButtonStyle?: {
54
+ /** Layout direction: 'vertical' (default) or 'horizontal' */
55
+ layout?: 'vertical' | 'horizontal';
56
+
57
+ /** Watch Credits button color */
58
+ watchCreditsColor?: string;
59
+
60
+ /** Watch Credits button background color */
61
+ watchCreditsBgColor?: string;
62
+
63
+ /** Next Episode button color */
64
+ nextEpisodeColor?: string;
65
+
66
+ /** Next Episode button background color */
67
+ nextEpisodeBgColor?: string;
68
+
69
+ /** Button position */
70
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'bottom-center' | 'top-center';
71
+ };
51
72
  }
52
73
 
53
74
  /**