@vouchfor/embeds 0.0.0-experiment.79ff9cf → 0.0.0-experiment.88ebbc0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,197 @@
1
+ import { html, LitElement } from 'lit';
2
+ import { customElement, property, state } from 'lit/decorators.js';
3
+ import { ifDefined } from 'lit/directives/if-defined.js';
4
+ import { createRef, ref } from 'lit/directives/ref.js';
5
+
6
+ import type { Scene, TemplateInstance } from '@vouchfor/canvas-video';
7
+ import type { MediaPlayer, MediaPlayerProps } from '@vouchfor/media-player';
8
+ import type { Ref } from 'lit/directives/ref.js';
9
+ import type { Environment } from '~/utils/env';
10
+
11
+ import { EventForwardController } from './controllers/event-forwarder';
12
+ import { FetcherController } from './controllers/fetcher';
13
+ import { TrackingController } from './controllers/tracking';
14
+
15
+ import '@vouchfor/media-player';
16
+
17
+ type EmbedProps = Pick<MediaPlayerProps, 'data' | 'aspectRatio' | 'preload' | 'autoplay' | 'controls'> & {
18
+ env: Environment;
19
+ apiKey: string;
20
+ vouchId?: string;
21
+ templateId?: string;
22
+ };
23
+
24
+ @customElement('vouch-embed')
25
+ class Embed extends LitElement {
26
+ private _mediaPlayerRef: Ref<MediaPlayer> = createRef();
27
+
28
+ @property({ type: Object, attribute: 'data' }) data: EmbedProps['data'];
29
+ @property({ type: String }) vouchId: EmbedProps['vouchId'];
30
+ @property({ type: String }) templateId: EmbedProps['templateId'];
31
+
32
+ @property({ type: String }) env: EmbedProps['env'] = 'prod';
33
+ @property({ type: String }) apiKey: EmbedProps['apiKey'] = '';
34
+
35
+ @property({ type: Array }) controls: EmbedProps['controls'];
36
+ @property({ type: String }) preload: EmbedProps['preload'] = 'auto';
37
+ @property({ type: Boolean }) autoplay: EmbedProps['autoplay'] = false;
38
+ @property({ type: Number }) aspectRatio: EmbedProps['aspectRatio'] = 0;
39
+
40
+ private eventController = new EventForwardController(this, [
41
+ 'durationchange',
42
+ 'ended',
43
+ 'error',
44
+ 'loadeddata',
45
+ 'pause',
46
+ 'stalled',
47
+ 'play',
48
+ 'playing',
49
+ 'ratechange',
50
+ 'scenechange',
51
+ 'seeking',
52
+ 'seeked',
53
+ 'timeupdate',
54
+ 'volumechange',
55
+ 'waiting',
56
+
57
+ 'video:loadeddata',
58
+ 'video:seeked',
59
+ 'video:play',
60
+ 'video:playing',
61
+ 'video:pause',
62
+ 'video:stalled',
63
+ 'video:timeupdate',
64
+ 'video:ended',
65
+ 'video:error'
66
+ ]);
67
+ private _fetcherController = new FetcherController(this);
68
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
69
+ // @ts-ignore
70
+ private _trackingController = new TrackingController(this);
71
+
72
+ @state() vouch: EmbedProps['data'];
73
+ @state() template: TemplateInstance | undefined;
74
+
75
+ get fetching() {
76
+ return this._fetcherController.fetching;
77
+ }
78
+
79
+ get waiting() {
80
+ return this._mediaPlayerRef.value?.waiting;
81
+ }
82
+
83
+ get seeking() {
84
+ return this._mediaPlayerRef.value?.seeking;
85
+ }
86
+
87
+ get paused() {
88
+ return this._mediaPlayerRef.value?.paused;
89
+ }
90
+
91
+ get captions() {
92
+ return this._mediaPlayerRef.value?.captions;
93
+ }
94
+
95
+ get fullscreen() {
96
+ return this._mediaPlayerRef.value?.fullscreen;
97
+ }
98
+
99
+ get duration() {
100
+ return this._mediaPlayerRef.value?.duration;
101
+ }
102
+
103
+ set currentTime(value: number) {
104
+ if (this._mediaPlayerRef.value) {
105
+ this._mediaPlayerRef.value.currentTime = value;
106
+ }
107
+ }
108
+ get currentTime() {
109
+ return this._mediaPlayerRef.value?.currentTime ?? 0;
110
+ }
111
+
112
+ set playbackRate(value: number) {
113
+ if (this._mediaPlayerRef.value) {
114
+ this._mediaPlayerRef.value.playbackRate = value;
115
+ }
116
+ }
117
+ get playbackRate() {
118
+ return this._mediaPlayerRef.value?.playbackRate ?? 1;
119
+ }
120
+
121
+ set volume(value: number) {
122
+ if (this._mediaPlayerRef.value) {
123
+ this._mediaPlayerRef.value.volume = value;
124
+ }
125
+ }
126
+ get volume() {
127
+ return this._mediaPlayerRef.value?.volume ?? 1;
128
+ }
129
+
130
+ set muted(value: boolean) {
131
+ if (this._mediaPlayerRef.value) {
132
+ this._mediaPlayerRef.value.muted = value;
133
+ }
134
+ }
135
+ get muted() {
136
+ return this._mediaPlayerRef.value?.muted ?? false;
137
+ }
138
+
139
+ get scene(): Scene | null {
140
+ return this._mediaPlayerRef.value?.scene ?? null;
141
+ }
142
+
143
+ get scenes(): Scene[] {
144
+ return this._mediaPlayerRef.value?.scenes ?? [];
145
+ }
146
+
147
+ get videoState() {
148
+ return this._mediaPlayerRef.value?.videoState;
149
+ }
150
+
151
+ get mediaPlayer() {
152
+ return this._mediaPlayerRef.value;
153
+ }
154
+
155
+ play() {
156
+ this._mediaPlayerRef.value?.play();
157
+ }
158
+
159
+ pause() {
160
+ this._mediaPlayerRef.value?.pause();
161
+ }
162
+
163
+ setScene(index: number) {
164
+ this._mediaPlayerRef.value?.setScene(index);
165
+ }
166
+
167
+ render() {
168
+ return html`
169
+ <vmp-new-media-player
170
+ ${ref(this._mediaPlayerRef)}
171
+ ${this.eventController.register()}
172
+ ?autoplay=${this.autoplay}
173
+ ?loading=${this.fetching}
174
+ .data=${this.vouch}
175
+ .template=${this.template}
176
+ aspectRatio=${ifDefined(this.aspectRatio)}
177
+ preload=${ifDefined(this.preload)}
178
+ .controls=${this.controls}
179
+ ></vmp-new-media-player>
180
+ `;
181
+ }
182
+ }
183
+
184
+ declare global {
185
+ interface HTMLElementTagNameMap {
186
+ 'vouch-embed': Embed;
187
+ }
188
+
189
+ namespace JSX {
190
+ interface IntrinsicElements {
191
+ 'vouch-embed': Embed;
192
+ }
193
+ }
194
+ }
195
+
196
+ export { Embed };
197
+ export type { EmbedProps };
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export { InlineEmbed } from '~/components/InlineEmbed';
1
+ export { Embed } from '~/components/Embed';
@@ -0,0 +1,78 @@
1
+ type Environment = 'dev' | 'staging' | 'prod';
2
+
3
+ type GetEnvUrlsReturn = {
4
+ marketingUrl: string;
5
+ videoUrl: string;
6
+ publicApiUrl: string;
7
+ embedApiUrl: string;
8
+ publicRecorderUrl: string;
9
+ };
10
+
11
+ const marketingUrl = 'https://vouchfor.com';
12
+
13
+ const devVideoUrl = 'https://d2rxhdlm2q91uk.cloudfront.net';
14
+ const stagingVideoUrl = 'https://d1ix11aj5kfygl.cloudfront.net';
15
+ const prodVideoUrl = 'https://d157jlwnudd93d.cloudfront.net';
16
+
17
+ const devPublicApiUrl = 'https://bshyfw4h5a.execute-api.ap-southeast-2.amazonaws.com/dev';
18
+ const stagingPublicApiUrl = 'https://gyzw7rpbq3.execute-api.ap-southeast-2.amazonaws.com/staging';
19
+ const prodPublicApiUrl = 'https://vfcjuim1l3.execute-api.ap-southeast-2.amazonaws.com/prod';
20
+
21
+ const devEmbedApiUrl = 'https://embed-dev.vouchfor.com/v2';
22
+ const stagingEmbedApiUrl = 'https://embed-staging.vouchfor.com/v2';
23
+ const prodEmbedApiUrl = 'https://embed.vouchfor.com/v2';
24
+
25
+ const devPublicRecorderUrl = 'https://dev.vouchfor.com';
26
+ const stagingPublicRecorderUrl = 'https://staging.vouchfor.com';
27
+ const prodPublicRecorderUrl = 'https://app.vouchfor.com';
28
+
29
+ // We are handling the case where env is an unknown string so the ts error is a lie
30
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
31
+ // @ts-ignore
32
+ function getEnvUrls(env: Environment): GetEnvUrlsReturn {
33
+ if (!['dev', 'staging', 'prod'].includes(env)) {
34
+ throw new Error(`Unknown environment: ${env}`);
35
+ }
36
+
37
+ if (env === 'dev') {
38
+ return {
39
+ marketingUrl,
40
+ videoUrl: devVideoUrl,
41
+ publicApiUrl: devPublicApiUrl,
42
+ embedApiUrl: devEmbedApiUrl,
43
+ publicRecorderUrl: devPublicRecorderUrl
44
+ };
45
+ }
46
+
47
+ if (env === 'staging') {
48
+ return {
49
+ marketingUrl,
50
+ videoUrl: stagingVideoUrl,
51
+ publicApiUrl: stagingPublicApiUrl,
52
+ embedApiUrl: stagingEmbedApiUrl,
53
+ publicRecorderUrl: stagingPublicRecorderUrl
54
+ };
55
+ }
56
+
57
+ if (env === 'prod') {
58
+ return {
59
+ marketingUrl,
60
+ videoUrl: prodVideoUrl,
61
+ publicApiUrl: prodPublicApiUrl,
62
+ embedApiUrl: prodEmbedApiUrl,
63
+ publicRecorderUrl: prodPublicRecorderUrl
64
+ };
65
+ }
66
+ }
67
+
68
+ export {
69
+ marketingUrl,
70
+ devEmbedApiUrl,
71
+ stagingEmbedApiUrl,
72
+ prodEmbedApiUrl,
73
+ devPublicRecorderUrl,
74
+ stagingPublicRecorderUrl,
75
+ prodPublicRecorderUrl,
76
+ getEnvUrls
77
+ };
78
+ export type { Environment };
@@ -0,0 +1,13 @@
1
+ function forwardEvent(type: string, fromElement: HTMLElement, toElement: HTMLElement) {
2
+ function forwarder(event: Event) {
3
+ toElement.dispatchEvent(new CustomEvent(event.type, event));
4
+ }
5
+
6
+ fromElement.addEventListener(type, forwarder);
7
+
8
+ return () => {
9
+ fromElement.removeEventListener(type, forwarder);
10
+ };
11
+ }
12
+
13
+ export { forwardEvent };
@@ -1,12 +0,0 @@
1
- import { MediaPlayer } from '@vouchfor/media-player';
2
- import type { MediaPlayerProps } from '@vouchfor/media-player';
3
- type InlineEmbedProps = MediaPlayerProps;
4
- declare class InlineEmbed extends MediaPlayer {
5
- }
6
- declare global {
7
- interface HTMLElementTagNameMap {
8
- 'vembed-inline': InlineEmbed;
9
- }
10
- }
11
- export { InlineEmbed };
12
- export type { InlineEmbedProps };
@@ -1,2 +0,0 @@
1
- export { InlineEmbed } from './InlineEmbed';
2
- export type { InlineEmbedProps } from './InlineEmbed';