@smartimpact-it/modern-video-embed 2.0.1

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.
Files changed (51) hide show
  1. package/README.md +1205 -0
  2. package/dist/components/VimeoEmbed.d.ts +143 -0
  3. package/dist/components/VimeoEmbed.d.ts.map +1 -0
  4. package/dist/components/VimeoEmbed.js +1176 -0
  5. package/dist/components/VimeoEmbed.js.map +1 -0
  6. package/dist/components/VimeoEmbed.min.js +1 -0
  7. package/dist/components/YouTubeEmbed.d.ts +225 -0
  8. package/dist/components/YouTubeEmbed.d.ts.map +1 -0
  9. package/dist/components/YouTubeEmbed.js +1354 -0
  10. package/dist/components/YouTubeEmbed.js.map +1 -0
  11. package/dist/components/YouTubeEmbed.min.js +1 -0
  12. package/dist/css/components.css +349 -0
  13. package/dist/css/components.css.map +1 -0
  14. package/dist/css/components.min.css +1 -0
  15. package/dist/css/main.css +12210 -0
  16. package/dist/css/main.css.map +1 -0
  17. package/dist/css/main.min.css +7 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +4 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/index.min.js +1 -0
  23. package/dist/types/index.d.ts +7 -0
  24. package/dist/types/index.d.ts.map +1 -0
  25. package/dist/types/index.js +5 -0
  26. package/dist/types/index.js.map +1 -0
  27. package/dist/vimeo-only.d.ts +7 -0
  28. package/dist/vimeo-only.d.ts.map +1 -0
  29. package/dist/vimeo-only.js +8 -0
  30. package/dist/vimeo-only.js.map +1 -0
  31. package/dist/vimeo-only.min.js +1 -0
  32. package/dist/youtube-only.d.ts +7 -0
  33. package/dist/youtube-only.d.ts.map +1 -0
  34. package/dist/youtube-only.js +8 -0
  35. package/dist/youtube-only.js.map +1 -0
  36. package/dist/youtube-only.min.js +1 -0
  37. package/package.json +75 -0
  38. package/src/components/VimeoEmbed.ts +1340 -0
  39. package/src/components/YouTubeEmbed.ts +1568 -0
  40. package/src/index.ts +3 -0
  41. package/src/styles/README.md +56 -0
  42. package/src/styles/components.scss +7 -0
  43. package/src/styles/main.scss +10 -0
  44. package/src/styles/vimeo-embed.scss +255 -0
  45. package/src/styles/youtube-embed.scss +261 -0
  46. package/src/types/common.d.ts +198 -0
  47. package/src/types/index.ts +7 -0
  48. package/src/types/vimeo-embed.d.ts +80 -0
  49. package/src/types/youtube-embed.d.ts +83 -0
  50. package/src/vimeo-only.ts +9 -0
  51. package/src/youtube-only.ts +9 -0
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ // Main entry point for Video Embed Components
2
+ import "./components/YouTubeEmbed.js";
3
+ import "./components/VimeoEmbed.js";
@@ -0,0 +1,56 @@
1
+ # CSS Files
2
+
3
+ This directory contains the styles for the video embed components.
4
+
5
+ ## For Production/Integration
6
+
7
+ Use `components.css` when integrating into your website:
8
+
9
+ ```html
10
+ <!-- Minimal CSS - Components only -->
11
+ <link rel="stylesheet" href="path/to/dist/css/components.css" />
12
+ ```
13
+
14
+ This file contains **only** the essential styles for:
15
+
16
+ - `youtube-embed` component
17
+ - `vimeo-embed` component
18
+
19
+ **Size:** ~15KB (much smaller, no Bootstrap)
20
+
21
+ ## For Demos/Examples
22
+
23
+ Use `main.css` for demos and examples:
24
+
25
+ ```html
26
+ <!-- Full CSS - Components + Bootstrap -->
27
+ <link rel="stylesheet" href="path/to/dist/css/main.css" />
28
+ ```
29
+
30
+ This file includes:
31
+
32
+ - Bootstrap framework (~200KB)
33
+ - Video embed component styles
34
+
35
+ **Size:** ~215KB (includes full Bootstrap)
36
+
37
+ ## Source Files
38
+
39
+ - `components.scss` - Production build (components only)
40
+ - `main.scss` - Demo build (Bootstrap + components)
41
+ - `youtube-embed.scss` - YouTube component styles
42
+ - `vimeo-embed.scss` - Vimeo component styles
43
+
44
+ ## Building
45
+
46
+ Both CSS files are automatically built when you run:
47
+
48
+ ```bash
49
+ npm run build
50
+ ```
51
+
52
+ Or watch for changes:
53
+
54
+ ```bash
55
+ npm run watch
56
+ ```
@@ -0,0 +1,7 @@
1
+ // Video Embed Components - Production Styles
2
+ // This file contains only the essential styles needed for the video embed components
3
+ // Use this when integrating into your website
4
+
5
+ // Import our custom video embed styles
6
+ @import "./youtube-embed.scss";
7
+ @import "./vimeo-embed.scss";
@@ -0,0 +1,10 @@
1
+ // Video Embed Components - Demo Styles
2
+ // This file includes Bootstrap and component styles for demos and examples
3
+ // For production integration, use components.scss instead
4
+
5
+ // Import Bootstrap SCSS (only needed for demos)
6
+ @import "../../node_modules/bootstrap/scss/bootstrap";
7
+
8
+ // Import our custom video embed styles
9
+ @import "./youtube-embed.scss";
10
+ @import "./vimeo-embed.scss";
@@ -0,0 +1,255 @@
1
+ /**
2
+ * SVG encoding functions (shared with YouTube embed)
3
+ */
4
+ @function svg-str-replace($string, $search, $replace: "") {
5
+ $index: str-index($string, $search);
6
+ @if $index {
7
+ @return str-slice($string, 1, $index - 1) + $replace +
8
+ svg-str-replace(
9
+ str-slice($string, $index + str-length($search)),
10
+ $search,
11
+ $replace
12
+ );
13
+ }
14
+ @return $string;
15
+ }
16
+
17
+ @function svg-url-encode($string) {
18
+ $map: (
19
+ "%": "%25",
20
+ "<": "%3C",
21
+ ">": "%3E",
22
+ " ": "%20",
23
+ "!": "%21",
24
+ "*": "%2A",
25
+ "'": "%27",
26
+ '"': "%22",
27
+ "(": "%28",
28
+ ")": "%29",
29
+ ";": "%3B",
30
+ ":": "%3A",
31
+ "@": "%40",
32
+ "&": "%26",
33
+ "=": "%3D",
34
+ "+": "%2B",
35
+ "$": "%24",
36
+ ",": "%2C",
37
+ "/": "%2F",
38
+ "?": "%3F",
39
+ "#": "%23",
40
+ "[": "%5B",
41
+ "]": "%5D",
42
+ );
43
+ $new: $string;
44
+ @each $search, $replace in $map {
45
+ $new: #{svg-str-replace($new, $search, $replace)};
46
+ }
47
+ @return $new;
48
+ }
49
+
50
+ @function inline-svg($string) {
51
+ @return url("data:image/svg+xml;utf8,#{svg-url-encode($string)}");
52
+ }
53
+
54
+ vimeo-embed {
55
+ // CSS Variables for customization
56
+ --video-aspect-ratio: 56.25%; // Default 16:9
57
+ --poster-object-fit: cover;
58
+ --video-object-fit: contain;
59
+ --control-button-size: 70px;
60
+ --control-button-color: #ffffff;
61
+ --overlay-background-color: rgba(0, 0, 0, 0.5);
62
+
63
+ display: block;
64
+ position: relative;
65
+ width: 100%;
66
+ padding-top: var(--video-aspect-ratio);
67
+ overflow: hidden;
68
+ background-color: #000;
69
+
70
+ iframe {
71
+ position: absolute;
72
+ top: 0;
73
+ left: 0;
74
+ width: 100%;
75
+ height: 100%;
76
+ border: none;
77
+ object-fit: var(--video-object-fit);
78
+ }
79
+
80
+ // Poster image
81
+ .vimeo-poster,
82
+ .video-poster {
83
+ position: absolute;
84
+ top: 0;
85
+ left: 0;
86
+ width: 100%;
87
+ height: 100%;
88
+ object-fit: var(--poster-object-fit);
89
+ display: block;
90
+ cursor: pointer;
91
+ }
92
+
93
+ // Custom control overlay
94
+ .button-overlay {
95
+ background: var(--overlay-background-color);
96
+ cursor: pointer;
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ position: absolute;
101
+ left: 0;
102
+ top: 0;
103
+ right: 0;
104
+ bottom: 0;
105
+ height: 100%;
106
+ width: 100%;
107
+ transition: opacity 0.3s ease;
108
+ z-index: 10;
109
+ }
110
+
111
+ &.is-playing .button-overlay {
112
+ opacity: 0;
113
+ }
114
+
115
+ &.is-playing:hover .button-overlay {
116
+ opacity: 1;
117
+ }
118
+
119
+ .button-overlay .button {
120
+ cursor: pointer;
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ height: var(--control-button-size);
125
+ width: var(--control-button-size);
126
+ background-image: inline-svg(
127
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#ffffff" d="M8,5.14V19.14L19,12.14L8,5.14Z" /></svg>'
128
+ );
129
+ background-size: cover;
130
+ background-repeat: no-repeat;
131
+ background-position: center;
132
+ }
133
+
134
+ &.is-playing .button-overlay .button {
135
+ background-image: inline-svg(
136
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#ffffff" d="M14,19H18V5H14M6,19H10V5H6V19Z" /></svg>'
137
+ );
138
+ }
139
+
140
+ // Background mode styles
141
+ &.is-background {
142
+ padding-top: 0;
143
+ position: absolute;
144
+ height: 100%;
145
+ width: 100%;
146
+ top: 0;
147
+ left: 0;
148
+ z-index: 0;
149
+ overflow: hidden;
150
+ background: #000;
151
+
152
+ iframe {
153
+ position: absolute;
154
+ top: 50%;
155
+ left: 50%;
156
+ transform: translate(-50%, -50%);
157
+
158
+ min-width: 100%;
159
+ min-height: 100%;
160
+ width: auto;
161
+ height: auto;
162
+
163
+ @supports (aspect-ratio: 16 / 9) {
164
+ aspect-ratio: 16 / 9;
165
+ }
166
+
167
+ pointer-events: none;
168
+ }
169
+
170
+ .button-overlay {
171
+ display: none;
172
+ }
173
+ }
174
+
175
+ // When background controls are enabled
176
+ &.has-background-controls {
177
+ .button-overlay {
178
+ display: flex;
179
+ background: none;
180
+ justify-content: flex-end;
181
+ align-items: flex-end;
182
+ padding: 1rem;
183
+
184
+ .button {
185
+ --control-button-size: 40px;
186
+ opacity: 0.7;
187
+ transition: opacity 0.2s ease;
188
+ &:hover {
189
+ opacity: 1;
190
+ }
191
+ }
192
+ }
193
+
194
+ &.is-playing .button-overlay {
195
+ opacity: 0;
196
+ &:hover {
197
+ opacity: 1;
198
+ }
199
+ }
200
+ }
201
+
202
+ // Error message styling
203
+ .vimeo-error-message {
204
+ position: absolute;
205
+ top: 0;
206
+ left: 0;
207
+ width: 100%;
208
+ height: 100%;
209
+ display: flex;
210
+ align-items: center;
211
+ justify-content: center;
212
+ background: rgba(0, 0, 0, 0.9);
213
+ color: white;
214
+ z-index: 1000;
215
+
216
+ .error-content {
217
+ text-align: center;
218
+ padding: 2rem;
219
+ max-width: 400px;
220
+
221
+ svg {
222
+ color: #00adef;
223
+ margin-bottom: 1rem;
224
+ }
225
+
226
+ .error-message {
227
+ margin: 1rem 0;
228
+ font-size: 1rem;
229
+ line-height: 1.5;
230
+ }
231
+
232
+ .retry-button {
233
+ margin-top: 1rem;
234
+ padding: 0.75rem 1.5rem;
235
+ background: #00adef;
236
+ color: white;
237
+ border: none;
238
+ border-radius: 4px;
239
+ cursor: pointer;
240
+ font-size: 1rem;
241
+ font-weight: 600;
242
+ transition: background 0.2s ease;
243
+
244
+ &:hover {
245
+ background: #0088bf;
246
+ }
247
+
248
+ &:focus {
249
+ outline: 2px solid white;
250
+ outline-offset: 2px;
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
@@ -0,0 +1,261 @@
1
+ /**
2
+ * SVG encoding functions
3
+ */
4
+ @function svg-str-replace($string, $search, $replace: "") {
5
+ $index: str-index($string, $search);
6
+ @if $index {
7
+ @return str-slice($string, 1, $index - 1) + $replace +
8
+ svg-str-replace(
9
+ str-slice($string, $index + str-length($search)),
10
+ $search,
11
+ $replace
12
+ );
13
+ }
14
+ @return $string;
15
+ }
16
+
17
+ @function svg-url-encode($string) {
18
+ $map: (
19
+ "%": "%25",
20
+ "<": "%3C",
21
+ ">": "%3E",
22
+ " ": "%20",
23
+ "!": "%21",
24
+ "*": "%2A",
25
+ "'": "%27",
26
+ '"': "%22",
27
+ "(": "%28",
28
+ ")": "%29",
29
+ ";": "%3B",
30
+ ":": "%3A",
31
+ "@": "%40",
32
+ "&": "%26",
33
+ "=": "%3D",
34
+ "+": "%2B",
35
+ "$": "%24",
36
+ ",": "%2C",
37
+ "/": "%2F",
38
+ "?": "%3F",
39
+ "#": "%23",
40
+ "[": "%5B",
41
+ "]": "%5D",
42
+ );
43
+ $new: $string;
44
+ @each $search, $replace in $map {
45
+ $new: #{svg-str-replace($new, $search, $replace)};
46
+ }
47
+ @return $new;
48
+ }
49
+
50
+ @function inline-svg($string) {
51
+ @return url("data:image/svg+xml;utf8,#{svg-url-encode($string)}");
52
+ }
53
+
54
+ youtube-embed {
55
+ // CSS Variables for customization
56
+ --video-aspect-ratio: 56.25%; // Default 16:9
57
+ --poster-object-fit: cover;
58
+ --video-object-fit: contain;
59
+ --control-button-size: 70px;
60
+ --control-button-color: #ffffff;
61
+ --overlay-background-color: rgba(0, 0, 0, 0.5);
62
+
63
+ display: block;
64
+ position: relative;
65
+ width: 100%;
66
+ padding-top: var(--video-aspect-ratio);
67
+ overflow: hidden;
68
+ background-color: #000;
69
+
70
+ iframe {
71
+ position: absolute;
72
+ top: 0;
73
+ left: 0;
74
+ width: 100%;
75
+ height: 100%;
76
+ border: none;
77
+ object-fit: var(--video-object-fit);
78
+ }
79
+
80
+ // Poster image (now appended directly to element)
81
+ .youtube-poster,
82
+ .video-poster {
83
+ position: absolute;
84
+ top: 0;
85
+ left: 0;
86
+ width: 100%;
87
+ height: 100%;
88
+ object-fit: var(--poster-object-fit);
89
+ display: block;
90
+ cursor: pointer;
91
+ }
92
+
93
+ // Custom control overlay (when controls=false)
94
+ .button-overlay {
95
+ background: var(--overlay-background-color);
96
+ cursor: pointer;
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ position: absolute;
101
+ left: 0;
102
+ top: 0;
103
+ right: 0;
104
+ bottom: 0;
105
+ height: 100%;
106
+ width: 100%;
107
+ transition: opacity 0.3s ease;
108
+ z-index: 10;
109
+ }
110
+
111
+ &.is-playing .button-overlay {
112
+ opacity: 0;
113
+ }
114
+
115
+ &.is-playing:hover .button-overlay {
116
+ opacity: 1;
117
+ }
118
+
119
+ .button-overlay .button {
120
+ cursor: pointer;
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ height: var(--control-button-size);
125
+ width: var(--control-button-size);
126
+ background-image: inline-svg(
127
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#ffffff" d="M8,5.14V19.14L19,12.14L8,5.14Z" /></svg>'
128
+ );
129
+ background-size: cover;
130
+ background-repeat: no-repeat;
131
+ background-position: center;
132
+ }
133
+
134
+ &.is-playing .button-overlay .button {
135
+ background-image: inline-svg(
136
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#ffffff" d="M14,19H18V5H14M6,19H10V5H6V19Z" /></svg>'
137
+ );
138
+ }
139
+
140
+ // Background mode styles
141
+ &.is-background {
142
+ padding-top: 0;
143
+ position: absolute;
144
+ height: 100%;
145
+ width: 100%;
146
+ top: 0;
147
+ left: 0;
148
+ z-index: 0;
149
+ overflow: hidden;
150
+ background: #000;
151
+
152
+ iframe {
153
+ position: absolute;
154
+ top: 50%;
155
+ left: 50%;
156
+ transform: translate(-50%, -50%);
157
+
158
+ // Using min-width and min-height with larger percentage to ensure coverage
159
+ // This technique makes the video always cover the container
160
+ min-width: 100%;
161
+ min-height: 100%;
162
+ width: auto;
163
+ height: auto;
164
+
165
+ // For 16:9 video: make it large enough to cover any aspect ratio container
166
+ @supports (aspect-ratio: 16 / 9) {
167
+ aspect-ratio: 16 / 9;
168
+ // If container is wider, video height = 100% and width expands
169
+ // If container is taller, video width = 100% and height expands
170
+ }
171
+
172
+ pointer-events: none;
173
+ }
174
+
175
+ .button-overlay {
176
+ display: none;
177
+ }
178
+ } // When background controls are enabled
179
+ &.has-background-controls {
180
+ .button-overlay {
181
+ display: flex;
182
+ background: none;
183
+ // Position controls in the bottom right
184
+ justify-content: flex-end;
185
+ align-items: flex-end;
186
+ padding: 1rem;
187
+
188
+ .button {
189
+ // Smaller, more discreet button
190
+ --control-button-size: 40px;
191
+ opacity: 0.7;
192
+ transition: opacity 0.2s ease;
193
+ &:hover {
194
+ opacity: 1;
195
+ }
196
+ }
197
+ }
198
+
199
+ // Hide the button when playing, but show on hover
200
+ &.is-playing .button-overlay {
201
+ opacity: 0;
202
+ &:hover {
203
+ opacity: 1;
204
+ }
205
+ }
206
+ }
207
+
208
+ // Error message styling
209
+ .youtube-error-message {
210
+ position: absolute;
211
+ top: 0;
212
+ left: 0;
213
+ width: 100%;
214
+ height: 100%;
215
+ display: flex;
216
+ align-items: center;
217
+ justify-content: center;
218
+ background: rgba(0, 0, 0, 0.9);
219
+ color: white;
220
+ z-index: 1000;
221
+
222
+ .error-content {
223
+ text-align: center;
224
+ padding: 2rem;
225
+ max-width: 400px;
226
+
227
+ svg {
228
+ color: #ff4444;
229
+ margin-bottom: 1rem;
230
+ }
231
+
232
+ .error-message {
233
+ margin: 1rem 0;
234
+ font-size: 1rem;
235
+ line-height: 1.5;
236
+ }
237
+
238
+ .retry-button {
239
+ margin-top: 1rem;
240
+ padding: 0.75rem 1.5rem;
241
+ background: #ff0000;
242
+ color: white;
243
+ border: none;
244
+ border-radius: 4px;
245
+ cursor: pointer;
246
+ font-size: 1rem;
247
+ font-weight: 600;
248
+ transition: background 0.2s ease;
249
+
250
+ &:hover {
251
+ background: #cc0000;
252
+ }
253
+
254
+ &:focus {
255
+ outline: 2px solid white;
256
+ outline-offset: 2px;
257
+ }
258
+ }
259
+ }
260
+ }
261
+ }