vidply 1.0.0 → 1.0.2

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.
@@ -16,7 +16,7 @@
16
16
  "format": "esm"
17
17
  },
18
18
  "src/icons/Icons.js": {
19
- "bytes": 12581,
19
+ "bytes": 12356,
20
20
  "imports": [],
21
21
  "format": "esm"
22
22
  },
@@ -157,7 +157,7 @@
157
157
  "format": "esm"
158
158
  },
159
159
  "src/core/Player.js": {
160
- "bytes": 30756,
160
+ "bytes": 30813,
161
161
  "imports": [
162
162
  {
163
163
  "path": "src/utils/EventEmitter.js",
@@ -249,7 +249,7 @@
249
249
  "format": "esm"
250
250
  },
251
251
  "src/index.js": {
252
- "bytes": 833,
252
+ "bytes": 2706,
253
253
  "imports": [
254
254
  {
255
255
  "path": "src/core/Player.js",
@@ -275,7 +275,7 @@
275
275
  "bytesInOutput": 4670
276
276
  },
277
277
  "src/index.js": {
278
- "bytesInOutput": 307
278
+ "bytesInOutput": 1064
279
279
  },
280
280
  "src/utils/EventEmitter.js": {
281
281
  "bytesInOutput": 436
@@ -287,7 +287,7 @@
287
287
  "bytesInOutput": 728
288
288
  },
289
289
  "src/icons/Icons.js": {
290
- "bytesInOutput": 10596
290
+ "bytesInOutput": 10407
291
291
  },
292
292
  "src/i18n/translations.js": {
293
293
  "bytesInOutput": 12646
@@ -311,7 +311,7 @@
311
311
  "bytesInOutput": 12461
312
312
  },
313
313
  "src/core/Player.js": {
314
- "bytesInOutput": 16392
314
+ "bytesInOutput": 16389
315
315
  },
316
316
  "src/renderers/YouTubeRenderer.js": {
317
317
  "bytesInOutput": 4140
@@ -326,7 +326,7 @@
326
326
  "bytesInOutput": 5245
327
327
  }
328
328
  },
329
- "bytes": 128662
329
+ "bytes": 129227
330
330
  }
331
331
  }
332
332
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vidply",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Universal, accessible video & audio player with ES6 modules",
5
5
  "type": "module",
6
6
  "main": "dist/vidply.js",
@@ -828,7 +828,7 @@ export class Player extends EventEmitter {
828
828
  this.signLanguageVideo = document.createElement('video');
829
829
  this.signLanguageVideo.className = 'vidply-sign-language-video';
830
830
  this.signLanguageVideo.src = this.signLanguageSrc;
831
- this.signLanguageVideo.setAttribute('aria-label', this.i18n.t('signLanguageVideo'));
831
+ this.signLanguageVideo.setAttribute('aria-label', i18n.t('player.signLanguage'));
832
832
 
833
833
  // Set position based on options
834
834
  const position = this.options.signLanguagePosition || 'bottom-right';
@@ -841,8 +841,8 @@ export class Player extends EventEmitter {
841
841
  this.signLanguageVideo.play();
842
842
  }
843
843
 
844
- // Add to container
845
- this.container.appendChild(this.signLanguageVideo);
844
+ // Add to video wrapper (so it overlays the video, not the entire container)
845
+ this.videoWrapper.appendChild(this.signLanguageVideo);
846
846
 
847
847
  // Create bound handlers to store references for cleanup
848
848
  this.signLanguageHandlers = {
@@ -75,9 +75,9 @@ const iconPaths = {
75
75
 
76
76
  audioDescriptionOn: `<path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z"/><path d="M10.5 19c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/><circle cx="19" cy="16" r="3" fill="#3b82f6"/><path d="M18.5 17.5l1-1 1.5 1.5" stroke="white" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`,
77
77
 
78
- signLanguage: `<path d="M12 2C10.34 2 9 3.34 9 5v4c0 .34.07.66.18.96L7.5 8.29C7.19 8.1 6.85 8 6.5 8 5.12 8 4 9.12 4 10.5v3c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-3c0-.28.22-.5.5-.5s.5.22.5.5V14l2 2v-1c0-.55.45-1 1-1s1 .45 1 1v2c0 .55.45 1 1 1s1-.45 1-1V9c0-.55.45-1 1-1s1 .45 1 1v8c0 2.21-1.79 4-4 4s-4-1.79-4-4v-2.83l-2.93-2.93A3.93 3.93 0 0 1 4 8c0-1.66 1.34-3 3-3 .83 0 1.58.34 2.12.88L11 7.76V5c0-.55.45-1 1-1s1 .45 1 1v4c0 .55.45 1 1 1s1-.45 1-1V5c0-1.66-1.34-3-3-3z"/>`,
78
+ signLanguage: `<g transform="scale(1.5)"><path d="M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z"/></g>`,
79
79
 
80
- signLanguageOn: `<path d="M12 2C10.34 2 9 3.34 9 5v4c0 .34.07.66.18.96L7.5 8.29C7.19 8.1 6.85 8 6.5 8 5.12 8 4 9.12 4 10.5v3c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-3c0-.28.22-.5.5-.5s.5.22.5.5V14l2 2v-1c0-.55.45-1 1-1s1 .45 1 1v2c0 .55.45 1 1 1s1-.45 1-1V9c0-.55.45-1 1-1s1 .45 1 1v8c0 2.21-1.79 4-4 4s-4-1.79-4-4v-2.83l-2.93-2.93A3.93 3.93 0 0 1 4 8c0-1.66 1.34-3 3-3 .83 0 1.58.34 2.12.88L11 7.76V5c0-.55.45-1 1-1s1 .45 1 1v4c0 .55.45 1 1 1s1-.45 1-1V5c0-1.66-1.34-3-3-3z"/><circle cx="19" cy="16" r="3" fill="#3b82f6"/><path d="M18.5 17.5l1-1 1.5 1.5" stroke="white" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`,
80
+ signLanguageOn: `<g transform="scale(1.5)"><path d="M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z"/></g>`,
81
81
 
82
82
  speaker: `<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/>`,
83
83
 
@@ -121,7 +121,7 @@ export function createPlayOverlay() {
121
121
  svg.setAttribute('aria-hidden', 'true');
122
122
  svg.setAttribute('role', 'presentation');
123
123
  svg.style.cursor = 'pointer';
124
-
124
+
125
125
  // Create filter for drop shadow
126
126
  const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
127
127
  const filterId = `vidply-play-shadow-${Math.random().toString(36).substr(2, 9)}`;
@@ -131,36 +131,36 @@ export function createPlayOverlay() {
131
131
  filter.setAttribute('y', '-50%');
132
132
  filter.setAttribute('width', '200%');
133
133
  filter.setAttribute('height', '200%');
134
-
134
+
135
135
  const feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
136
136
  feGaussianBlur.setAttribute('in', 'SourceAlpha');
137
137
  feGaussianBlur.setAttribute('stdDeviation', '3');
138
-
138
+
139
139
  const feOffset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset');
140
140
  feOffset.setAttribute('dx', '0');
141
141
  feOffset.setAttribute('dy', '2');
142
142
  feOffset.setAttribute('result', 'offsetblur');
143
-
143
+
144
144
  const feComponentTransfer = document.createElementNS('http://www.w3.org/2000/svg', 'feComponentTransfer');
145
145
  const feFuncA = document.createElementNS('http://www.w3.org/2000/svg', 'feFuncA');
146
146
  feFuncA.setAttribute('type', 'linear');
147
147
  feFuncA.setAttribute('slope', '0.3');
148
148
  feComponentTransfer.appendChild(feFuncA);
149
-
149
+
150
150
  const feMerge = document.createElementNS('http://www.w3.org/2000/svg', 'feMerge');
151
151
  const feMergeNode1 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');
152
152
  const feMergeNode2 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');
153
153
  feMergeNode2.setAttribute('in', 'SourceGraphic');
154
154
  feMerge.appendChild(feMergeNode1);
155
155
  feMerge.appendChild(feMergeNode2);
156
-
156
+
157
157
  filter.appendChild(feGaussianBlur);
158
158
  filter.appendChild(feOffset);
159
159
  filter.appendChild(feComponentTransfer);
160
160
  filter.appendChild(feMerge);
161
161
  defs.appendChild(filter);
162
162
  svg.appendChild(defs);
163
-
163
+
164
164
  // White circle background
165
165
  const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
166
166
  circle.setAttribute('cx', '40');
@@ -170,14 +170,14 @@ export function createPlayOverlay() {
170
170
  circle.setAttribute('filter', `url(#${filterId})`);
171
171
  circle.setAttribute('class', 'vidply-play-overlay-bg');
172
172
  svg.appendChild(circle);
173
-
173
+
174
174
  // Play icon triangle (centered with optical adjustment)
175
175
  const playTriangle = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
176
176
  playTriangle.setAttribute('points', '32,28 32,52 54,40');
177
177
  playTriangle.setAttribute('fill', '#0a406e');
178
178
  playTriangle.setAttribute('class', 'vidply-play-overlay-icon');
179
179
  svg.appendChild(playTriangle);
180
-
180
+
181
181
  return svg;
182
182
  }
183
183
 
package/src/index.js CHANGED
@@ -11,14 +11,75 @@ function initializePlayers() {
11
11
  const elements = document.querySelectorAll('[data-vidply]');
12
12
 
13
13
  elements.forEach(element => {
14
- // Parse options from data attribute
14
+ // Parse options from data attribute (JSON format)
15
15
  const options = element.dataset.vidplyOptions
16
16
  ? JSON.parse(element.dataset.vidplyOptions)
17
17
  : {};
18
18
 
19
+ // Parse individual data attributes and merge with options
20
+ // This allows for easier HTML-based configuration
21
+ const dataOptions = parseDataAttributes(element.dataset);
22
+ const mergedOptions = { ...dataOptions, ...options };
23
+
19
24
  // Create player instance
20
- new Player(element, options);
25
+ new Player(element, mergedOptions);
26
+ });
27
+ }
28
+
29
+ // Helper function to parse data attributes into options
30
+ function parseDataAttributes(dataset) {
31
+ const options = {};
32
+
33
+ // Map of data attribute names to option keys (camelCase conversion)
34
+ const attributeMap = {
35
+ // Sign Language
36
+ 'signLanguageSrc': 'signLanguageSrc',
37
+ 'signLanguageButton': 'signLanguageButton',
38
+ 'signLanguagePosition': 'signLanguagePosition',
39
+
40
+ // Audio Description
41
+ 'audioDescriptionSrc': 'audioDescriptionSrc',
42
+ 'audioDescriptionButton': 'audioDescriptionButton',
43
+
44
+ // Other common options
45
+ 'autoplay': 'autoplay',
46
+ 'loop': 'loop',
47
+ 'muted': 'muted',
48
+ 'controls': 'controls',
49
+ 'poster': 'poster',
50
+ 'width': 'width',
51
+ 'height': 'height',
52
+ 'language': 'language',
53
+ 'captions': 'captions',
54
+ 'captionsDefault': 'captionsDefault',
55
+ 'transcript': 'transcript',
56
+ 'transcriptButton': 'transcriptButton',
57
+ 'keyboard': 'keyboard',
58
+ 'responsive': 'responsive',
59
+ 'pipButton': 'pipButton',
60
+ 'fullscreenButton': 'fullscreenButton'
61
+ };
62
+
63
+ // Parse each data attribute
64
+ Object.keys(attributeMap).forEach(dataKey => {
65
+ const optionKey = attributeMap[dataKey];
66
+ const value = dataset[dataKey];
67
+
68
+ if (value !== undefined) {
69
+ // Convert string values to appropriate types
70
+ if (value === 'true') {
71
+ options[optionKey] = true;
72
+ } else if (value === 'false') {
73
+ options[optionKey] = false;
74
+ } else if (!isNaN(value) && value !== '') {
75
+ options[optionKey] = Number(value);
76
+ } else {
77
+ options[optionKey] = value;
78
+ }
79
+ }
21
80
  });
81
+
82
+ return options;
22
83
  }
23
84
 
24
85
  // Auto-initialize on DOM ready
@@ -145,6 +145,10 @@
145
145
  height: auto;
146
146
  }
147
147
 
148
+ .vidply-player.vidply-audio .vidply-menu {
149
+ max-height: 150px;
150
+ }
151
+
148
152
  /* Video/Audio Element */
149
153
  .vidply-player video,
150
154
  .vidply-player audio {
@@ -185,7 +189,7 @@
185
189
  overflow: hidden;
186
190
  position: relative;
187
191
  width: 100%;
188
- z-index: 10; /* Above track-info and playlist siblings */
192
+ z-index: 1; /* Base video layer */
189
193
  }
190
194
 
191
195
  /* Mobile: Simplify video wrapper */
@@ -216,7 +220,7 @@
216
220
  top: 50%;
217
221
  transform: translate(-50%, -50%);
218
222
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
219
- z-index: 15;
223
+ z-index: 2;
220
224
  }
221
225
 
222
226
  .vidply-play-overlay:hover {
@@ -281,7 +285,7 @@
281
285
  position: relative;
282
286
  right: 0;
283
287
  width: 100%;
284
- z-index: 100;
288
+ z-index: 10;
285
289
  }
286
290
 
287
291
  /* Allow menus to position within controls */
@@ -518,7 +522,7 @@
518
522
  position: fixed;
519
523
  right: 0;
520
524
  top: 0;
521
- z-index: 999;
525
+ z-index: 19;
522
526
  }
523
527
 
524
528
  .vidply-menu-backdrop.visible {
@@ -562,8 +566,8 @@
562
566
  /* iOS momentum scrolling */
563
567
  transform: translateX(50%);
564
568
 
565
- /* Ensure touch events work on iOS */
566
- z-index: 1000;
569
+ /* Ensure menus appear above all player content including overlays */
570
+ z-index: 20;
567
571
  }
568
572
 
569
573
  /* Menu positioned below button */
@@ -830,7 +834,12 @@
830
834
  text-align: center;
831
835
  transform: translateX(-50%);
832
836
  transition: bottom 0.3s ease;
833
- z-index: 5;
837
+ z-index: 4;
838
+ }
839
+
840
+ .vidply-audio .vidply-captions {
841
+ bottom: auto;
842
+ top: -42px;
834
843
  }
835
844
 
836
845
  .vidply-captions:empty {
@@ -864,7 +873,7 @@
864
873
  position: absolute;
865
874
  right: 0;
866
875
  top: 0;
867
- z-index: 2000;
876
+ z-index: 20;
868
877
  }
869
878
 
870
879
  @keyframes vidply-fade-in {
@@ -1176,7 +1185,7 @@
1176
1185
  top: auto;
1177
1186
  transform: translateX(-50%);
1178
1187
  width: auto;
1179
- z-index: 200;
1188
+ z-index: 15;
1180
1189
  }
1181
1190
 
1182
1191
  .vidply-menu::after {
@@ -1374,7 +1383,7 @@
1374
1383
  position: sticky;
1375
1384
  text-transform: uppercase;
1376
1385
  top: 0;
1377
- z-index: 10;
1386
+ z-index: 2;
1378
1387
  }
1379
1388
 
1380
1389
  .vidply-playlist-list {
@@ -1540,7 +1549,7 @@
1540
1549
  position: absolute;
1541
1550
  top: 0;
1542
1551
  width: 400px;
1543
- z-index: 100;
1552
+ z-index: 5;
1544
1553
  }
1545
1554
 
1546
1555
  /* Minimum height for audio player transcript */
@@ -1662,6 +1671,69 @@
1662
1671
  background: var(--vidply-border-hover);
1663
1672
  }
1664
1673
 
1674
+ /* Sign Language Video */
1675
+ .vidply-sign-language-video {
1676
+ background: var(--vidply-black);
1677
+ border: 2px solid var(--vidply-white-30);
1678
+ border-radius: 4px;
1679
+ box-shadow: 0 4px 12px var(--vidply-black-60);
1680
+ height: auto !important;
1681
+ max-width: 400px;
1682
+ min-width: 150px;
1683
+ position: absolute;
1684
+ transition: opacity 0.3s ease;
1685
+ width: 35% !important;
1686
+ z-index: 3;
1687
+ }
1688
+
1689
+ .vidply-fullscreen .vidply-sign-language-video {
1690
+ max-width: 600px;
1691
+ }
1692
+
1693
+ /* Sign Language Video Positions */
1694
+ .vidply-sign-position-bottom-right {
1695
+ bottom: 16px; /* Above controls */
1696
+ right: 16px;
1697
+ }
1698
+
1699
+ .vidply-controls-visible + .vidply-sign-position-bottom-right,
1700
+ .vidply-controls-visible + .vidply-captions + .vidply-sign-position-bottom-right {
1701
+ bottom: 95px; /* Above controls */
1702
+ }
1703
+
1704
+ .vidply-sign-position-bottom-left {
1705
+ bottom: 16px; /* Above controls */
1706
+ left: 16px;
1707
+ }
1708
+
1709
+ .vidply-controls-visible + .vidply-sign-position-bottom-left,
1710
+ .vidply-controls-visible + .vidply-captions + .vidply-sign-position-bottom-left {
1711
+ bottom: 95px; /* Above controls */
1712
+ }
1713
+
1714
+ .vidply-sign-position-top-right {
1715
+ right: 16px;
1716
+ top: 16px;
1717
+ }
1718
+
1719
+ .vidply-sign-position-top-left {
1720
+ left: 16px;
1721
+ top: 16px;
1722
+ }
1723
+
1724
+ /* Responsive Sign Language Video */
1725
+ @media (width <= 640px) {
1726
+ .vidply-sign-language-video {
1727
+ min-width: 120px;
1728
+ width: 35%;
1729
+ }
1730
+
1731
+ .vidply-sign-position-bottom-right,
1732
+ .vidply-sign-position-bottom-left {
1733
+ bottom: 126px !important; /* Adjust for smaller controls */
1734
+ }
1735
+ }
1736
+
1665
1737
  /* Responsive Adjustments */
1666
1738
  @media (width <= 640px) {
1667
1739
  .vidply-playlist-thumbnail {
@@ -1691,7 +1763,7 @@
1691
1763
  order: 3; /* After controls (which are order: 2) */
1692
1764
  position: relative;
1693
1765
  width: 100%;
1694
- z-index: 50;
1766
+ z-index: 5;
1695
1767
  }
1696
1768
 
1697
1769
  .vidply-transcript-header {