@vouchfor/embeds 0.0.0-experiment.df12bef → 0.0.0-experiment.e7e20dd

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. package/dist/es/embeds.js +979 -1453
  2. package/dist/es/embeds.js.map +1 -1
  3. package/dist/es/src/components/DialogEmbed/DialogOverlay.d.ts +20 -0
  4. package/dist/es/src/components/DialogEmbed/DialogPortal.d.ts +36 -0
  5. package/dist/es/src/components/DialogEmbed/index.d.ts +38 -0
  6. package/dist/es/src/components/PlayerEmbed/controllers/event-forwarder.d.ts +15 -0
  7. package/dist/es/src/components/{Embed → PlayerEmbed}/controllers/fetcher.d.ts +5 -4
  8. package/dist/es/src/components/{Embed/controllers/tracking.d.ts → PlayerEmbed/controllers/tracking/index.d.ts} +14 -11
  9. package/dist/es/src/components/PlayerEmbed/controllers/tracking/utils.d.ts +17 -0
  10. package/dist/es/src/components/{Embed → PlayerEmbed}/index.d.ts +28 -21
  11. package/dist/es/src/components/PlayerEmbed/tests/data.d.ts +3 -0
  12. package/dist/es/src/index.d.ts +2 -1
  13. package/dist/iife/dialog-embed/embed.iife.js +1750 -0
  14. package/dist/iife/dialog-embed/embed.iife.js.map +1 -0
  15. package/dist/iife/embeds.iife.js +662 -457
  16. package/dist/iife/embeds.iife.js.map +1 -1
  17. package/dist/iife/player-embed/embed.iife.js +1612 -0
  18. package/dist/iife/player-embed/embed.iife.js.map +1 -0
  19. package/package.json +43 -31
  20. package/src/components/DialogEmbed/Dialog.stories.ts +91 -0
  21. package/src/components/DialogEmbed/DialogOverlay.ts +131 -0
  22. package/src/components/DialogEmbed/DialogPortal.ts +126 -0
  23. package/src/components/DialogEmbed/index.ts +97 -0
  24. package/src/components/{Embed/Embed.stories.ts → PlayerEmbed/PlayerEmbed.stories.ts} +26 -14
  25. package/src/components/{Embed → PlayerEmbed}/controllers/event-forwarder.ts +6 -5
  26. package/src/components/{Embed → PlayerEmbed}/controllers/fetcher.ts +33 -14
  27. package/src/components/{Embed/controllers/tracking.ts → PlayerEmbed/controllers/tracking/index.ts} +47 -115
  28. package/src/components/PlayerEmbed/controllers/tracking/utils.ts +95 -0
  29. package/src/components/{Embed → PlayerEmbed}/index.ts +71 -27
  30. package/src/components/PlayerEmbed/tests/PlayerEmbed.spec.ts +80 -0
  31. package/src/components/PlayerEmbed/tests/data.ts +183 -0
  32. package/src/index.ts +2 -1
@@ -1,26 +1,29 @@
1
1
  import { Task } from '@lit/task';
2
2
  import { v4 as uuidv4 } from 'uuid';
3
3
 
4
- import type { Embed, EmbedProps } from '..';
4
+ import type { PlayerEmbed, PlayerEmbedProps } from '..';
5
5
  import type { ReactiveControllerHost } from 'lit';
6
6
  import type { Environment } from '~/utils/env';
7
7
 
8
8
  import { getEnvUrls } from '~/utils/env';
9
9
 
10
- type EmbedHost = ReactiveControllerHost & Embed;
10
+ type PlayerEmbedHost = ReactiveControllerHost & PlayerEmbed;
11
11
 
12
- type TaskDeps = [
13
- EmbedProps['env'],
14
- EmbedProps['apiKey'],
15
- EmbedProps['data'],
16
- EmbedProps['vouchId'],
17
- EmbedProps['templateId']
12
+ type FetchTaskDeps = [
13
+ PlayerEmbedProps['env'],
14
+ PlayerEmbedProps['apiKey'],
15
+ PlayerEmbedProps['data'],
16
+ PlayerEmbedProps['vouchId'],
17
+ PlayerEmbedProps['templateId']
18
18
  ];
19
19
 
20
+ type FilterTaskDeps = [PlayerEmbedProps['data'], PlayerEmbedProps['questions']];
21
+
20
22
  class FetcherController {
21
- host: EmbedHost;
23
+ host: PlayerEmbedHost;
22
24
 
23
25
  private _fetching = false;
26
+ private _vouch: PlayerEmbedProps['data'];
24
27
 
25
28
  set fetching(value) {
26
29
  if (this._fetching !== value) {
@@ -94,11 +97,11 @@ class FetcherController {
94
97
  return template;
95
98
  };
96
99
 
97
- constructor(host: EmbedHost) {
100
+ constructor(host: PlayerEmbedHost) {
98
101
  this.host = host;
99
- new Task<TaskDeps, void>(
102
+ new Task<FetchTaskDeps, void>(
100
103
  this.host,
101
- async ([env, apiKey, data, vouchId, templateId]: TaskDeps) => {
104
+ async ([env, apiKey, data, vouchId, templateId]: FetchTaskDeps) => {
102
105
  try {
103
106
  host.vouch = undefined;
104
107
  host.template = undefined;
@@ -109,7 +112,7 @@ class FetcherController {
109
112
  this.fetching = true;
110
113
  template = await this.getTemplate(env, apiKey, templateId);
111
114
  }
112
- host.vouch = data;
115
+ this._vouch = data;
113
116
  host.template = template ?? data?.settings?.template?.instance;
114
117
  } else if (vouchId) {
115
118
  this.fetching = true;
@@ -118,7 +121,7 @@ class FetcherController {
118
121
  this.getVouch(env, apiKey, vouchId),
119
122
  templateId ? this.getTemplate(env, apiKey, templateId) : null
120
123
  ]);
121
- host.vouch = vouch;
124
+ this._vouch = vouch;
122
125
  host.template = template ?? vouch?.settings?.template?.instance;
123
126
  }
124
127
  } finally {
@@ -127,6 +130,22 @@ class FetcherController {
127
130
  },
128
131
  () => [host.env, host.apiKey, host.data, host.vouchId, host.templateId]
129
132
  );
133
+
134
+ // This second task is to be able to filter the vouch without fetching it again if only the questions changed
135
+ new Task<FilterTaskDeps, void>(
136
+ this.host,
137
+ ([vouch, questions]: FilterTaskDeps) => {
138
+ host.vouch = vouch
139
+ ? {
140
+ ...vouch,
141
+ questions: {
142
+ items: vouch?.questions.items.filter((_, index) => !questions?.length || questions?.includes(index + 1))
143
+ }
144
+ }
145
+ : undefined;
146
+ },
147
+ () => [this._vouch, host.questions]
148
+ );
130
149
  }
131
150
  }
132
151
 
@@ -1,15 +1,13 @@
1
- import { v4 as uuidv4 } from 'uuid';
2
-
3
- import type { Embed } from '..';
1
+ import type { PlayerEmbed } from '../..';
4
2
  import type { VideoEventDetail } from '@vouchfor/media-player';
5
3
  import type { ReactiveController, ReactiveControllerHost } from 'lit';
6
4
 
7
- import packageJson from '../../../../package.json';
5
+ import { findVouchId, getReportingMetadata, getUids } from './utils';
8
6
  import { getEnvUrls } from '~/utils/env';
9
7
 
10
8
  const MINIMUM_SEND_THRESHOLD = 1;
11
9
 
12
- type EmbedHost = ReactiveControllerHost & Embed;
10
+ type PlayerEmbedHost = ReactiveControllerHost & PlayerEmbed;
13
11
 
14
12
  type TrackingEvent = 'VOUCH_LOADED' | 'VOUCH_RESPONSE_VIEWED' | 'VIDEO_PLAYED' | 'VIDEO_STREAMED';
15
13
  type TrackingPayload = {
@@ -19,6 +17,13 @@ type TrackingPayload = {
19
17
  streamEnd?: number;
20
18
  };
21
19
 
20
+ type BatchEvent = {
21
+ event: TrackingEvent;
22
+ payload: TrackingPayload & {
23
+ time: string;
24
+ };
25
+ };
26
+
22
27
  type TimeMap = {
23
28
  [key: string]: number;
24
29
  };
@@ -28,12 +33,9 @@ type BooleanMap = {
28
33
  };
29
34
 
30
35
  class TrackingController implements ReactiveController {
31
- host: EmbedHost;
32
-
33
- private _tabId: string | undefined = undefined;
34
- private _clientId: string | undefined = undefined;
35
- private _visitorId: string | undefined = undefined;
36
+ host: PlayerEmbedHost;
36
37
 
38
+ private _batchedEvents: BatchEvent[] = [];
37
39
  private _hasPlayed = false;
38
40
  private _hasLoaded: BooleanMap = {};
39
41
  private _answersViewed: BooleanMap = {};
@@ -41,124 +43,53 @@ class TrackingController implements ReactiveController {
41
43
  private _streamLatestTime: TimeMap = {};
42
44
  private _currentlyPlayingVideo: VideoEventDetail | null = null;
43
45
 
44
- constructor(host: EmbedHost) {
46
+ constructor(host: PlayerEmbedHost) {
45
47
  this.host = host;
46
48
  host.addController(this);
47
49
  }
48
50
 
49
- private _findVouchId(payload?: TrackingPayload) {
50
- if (payload && 'vouchId' in payload) {
51
- return payload.vouchId;
52
- }
53
- if (this.host.vouch) {
54
- return this.host.vouch.id;
55
- }
56
- return null;
57
- }
58
-
59
- private _createVisitor = (visitorId: string) => {
60
- const { publicApiUrl } = getEnvUrls(this.host.env);
61
- window.localStorage?.setItem?.('vouch-uid-visitor', visitorId);
62
- navigator.sendBeacon(`${publicApiUrl}/api/visitor`, JSON.stringify({ visitorId }));
63
- return visitorId;
64
- };
65
-
66
- private _getUids() {
67
- if (typeof window === 'undefined') {
68
- return {
69
- client: null,
70
- tab: null,
71
- request: uuidv4()
72
- };
73
- }
74
-
75
- // Persisted for a user for the same device + browser, so we can e.g. search for all logs related to that browser
76
- const visitorId =
77
- this._visitorId || window.localStorage?.getItem?.('vouch-uid-visitor') || this._createVisitor(uuidv4());
78
- // Persisted for a user for the same device + browser, so we can e.g. search for all logs related to that browser
79
- const clientId = this._clientId || window.localStorage?.getItem?.('vouch-uid-client') || uuidv4();
80
- // Persisted in session storage, so we can search for everything the user has done in a specific tab
81
- const tabId = this._tabId || window.sessionStorage?.getItem?.('vouch-uid-tab') || uuidv4();
82
- // Not persisted, allows us to search for any logs related to a single FE request
83
- // E.g. BE should pass this request ID through all other services to be able to group logs
84
- const requestId = uuidv4();
85
-
86
- // Cache and persist uids
87
- if (visitorId !== this._visitorId) {
88
- this._visitorId = visitorId;
89
- window.localStorage?.setItem?.('vouch-uid-visitor', visitorId);
90
- }
91
-
92
- if (clientId !== this._clientId) {
93
- this._clientId = clientId;
94
- window.localStorage?.setItem?.('vouch-uid-client', clientId);
95
- }
51
+ private _createTrackingEvent = (event: TrackingEvent, payload?: TrackingPayload) => {
52
+ const vouchId = findVouchId(payload, this.host.vouch);
96
53
 
97
- if (tabId !== this._tabId) {
98
- this._tabId = tabId;
99
- window.sessionStorage?.setItem?.('vouch-uid-tab', tabId);
54
+ if (!vouchId || this.host.disableTracking) {
55
+ return;
100
56
  }
101
57
 
102
- return {
103
- client: clientId,
104
- tab: tabId,
105
- request: requestId,
106
- visitor: visitorId
107
- };
108
- }
109
-
110
- private _getReportingMetadata = () => {
111
- const [country, region] = Intl.DateTimeFormat().resolvedOptions().timeZone?.split?.('/') ?? [];
112
-
113
- const utmParams: any = {};
114
- [...new URLSearchParams(location.search).entries()].forEach(([key, value]) => {
115
- if (/utm/.test(key)) {
116
- const param = key.toLowerCase().replace(/[-_][a-z0-9]/g, (group) => group.slice(-1).toUpperCase());
117
- utmParams[param] = value;
58
+ this._batchedEvents.push({
59
+ event,
60
+ payload: {
61
+ ...payload,
62
+ vouchId,
63
+ time: new Date().toISOString()
118
64
  }
119
65
  });
120
-
121
- return {
122
- source: this.host.trackingSource,
123
- time: new Date(),
124
- region,
125
- country,
126
- screenHeight: window.screen.height,
127
- screenWidth: window.screen.width,
128
- referrer: document.referrer,
129
- currentUrl: location.href,
130
- ...utmParams
131
- };
132
66
  };
133
67
 
134
- private _sendTrackingEvent = (event: TrackingEvent, payload?: TrackingPayload) => {
135
- const vouchId = this._findVouchId(payload);
136
-
137
- if (!vouchId || this.host.disableTracking) {
68
+ private _sendTrackingEvent = () => {
69
+ if (this._batchedEvents.length <= 0) {
138
70
  return;
139
71
  }
140
72
 
141
73
  const { publicApiUrl } = getEnvUrls(this.host.env);
142
- const { client, tab, request, visitor } = this._getUids();
74
+ const { client, tab, request, visitor } = getUids(this.host.env);
143
75
 
144
76
  navigator.sendBeacon(
145
- `${publicApiUrl}/api/v2/events`,
77
+ `${publicApiUrl}/api/batchevents`,
146
78
  JSON.stringify({
147
- event,
148
79
  payload: {
149
- ...payload,
150
- vouchId
80
+ events: this._batchedEvents
151
81
  },
152
82
  context: {
153
83
  'x-uid-client': client,
154
84
  'x-uid-tab': tab,
155
85
  'x-uid-request': request,
156
86
  'x-uid-visitor': visitor,
157
- 'x-reporting-metadata': this._getReportingMetadata(),
158
- 'x-embeds-version': packageJson.version
87
+ 'x-reporting-metadata': getReportingMetadata(this.host.trackingSource)
159
88
  }
160
89
  })
161
90
  );
91
+
92
+ this._batchedEvents = [];
162
93
  };
163
94
 
164
95
  private _streamEnded = () => {
@@ -168,7 +99,7 @@ class TrackingController implements ReactiveController {
168
99
  if (this._streamLatestTime[key] > this._streamStartTime[key] + MINIMUM_SEND_THRESHOLD) {
169
100
  // Send a video streamed event any time the stream ends to capture the time between starting
170
101
  // the video and the video stopping for any reason (pausing, deleting the embed node or closing the browser)
171
- this._sendTrackingEvent('VIDEO_STREAMED', {
102
+ this._createTrackingEvent('VIDEO_STREAMED', {
172
103
  answerId: id,
173
104
  streamStart: this._streamStartTime[key],
174
105
  streamEnd: this._streamLatestTime[key]
@@ -188,7 +119,7 @@ class TrackingController implements ReactiveController {
188
119
 
189
120
  // Only send loaded event once per session
190
121
  if (!this._hasLoaded[vouchId]) {
191
- this._sendTrackingEvent('VOUCH_LOADED', { vouchId });
122
+ this._createTrackingEvent('VOUCH_LOADED', { vouchId });
192
123
  this._hasLoaded[vouchId] = true;
193
124
  }
194
125
  };
@@ -196,26 +127,21 @@ class TrackingController implements ReactiveController {
196
127
  private _handlePlay = () => {
197
128
  // Only send the video played event once per session
198
129
  if (!this._hasPlayed) {
199
- this._sendTrackingEvent('VIDEO_PLAYED', {
130
+ this._createTrackingEvent('VIDEO_PLAYED', {
200
131
  streamStart: this.host.currentTime
201
132
  });
202
133
  this._hasPlayed = true;
203
134
  }
204
135
  };
205
136
 
206
- private _handleVideoPlay = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
137
+ private _handleVideoPlay = ({ detail: { id, key } }: CustomEvent<VideoEventDetail>) => {
207
138
  // Only increment play count once per session
208
139
  if (!this._answersViewed[key]) {
209
- this._sendTrackingEvent('VOUCH_RESPONSE_VIEWED', {
140
+ this._createTrackingEvent('VOUCH_RESPONSE_VIEWED', {
210
141
  answerId: id
211
142
  });
212
143
  this._answersViewed[key] = true;
213
144
  }
214
-
215
- if (!this._streamStartTime[key]) {
216
- this._streamStartTime[key] = node.currentTime;
217
- this._streamLatestTime[key] = node.currentTime;
218
- }
219
145
  };
220
146
 
221
147
  private _handleVideoTimeUpdate = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
@@ -227,12 +153,17 @@ class TrackingController implements ReactiveController {
227
153
  ) {
228
154
  this._currentlyPlayingVideo = { id, key, node };
229
155
  this._streamLatestTime[key] = node.currentTime;
156
+
157
+ if (!this._streamStartTime[key]) {
158
+ this._streamStartTime[key] = node.currentTime;
159
+ this._streamLatestTime[key] = node.currentTime;
160
+ }
230
161
  }
231
162
  };
232
163
 
233
164
  private _handleVideoPause = ({ detail: { id, key } }: CustomEvent<VideoEventDetail>) => {
234
165
  if (this._streamLatestTime[key] > this._streamStartTime[key] + MINIMUM_SEND_THRESHOLD) {
235
- this._sendTrackingEvent('VIDEO_STREAMED', {
166
+ this._createTrackingEvent('VIDEO_STREAMED', {
236
167
  answerId: id,
237
168
  streamStart: this._streamStartTime[key],
238
169
  streamEnd: this._streamLatestTime[key]
@@ -244,9 +175,7 @@ class TrackingController implements ReactiveController {
244
175
 
245
176
  private _pageUnloading = () => {
246
177
  this._streamEnded();
247
- // This will try to send the same stream event again so we delete the start and latest
248
- // time in stream ended so that there is no times to send and the pause event does nothing
249
- this.host.pause();
178
+ this._sendTrackingEvent();
250
179
  };
251
180
 
252
181
  private _handleVisibilityChange = () => {
@@ -275,7 +204,9 @@ class TrackingController implements ReactiveController {
275
204
  }
276
205
 
277
206
  hostDisconnected() {
278
- this._streamEnded();
207
+ // Send events if DOM node is destroyed
208
+ this._pageUnloading();
209
+
279
210
  if ('onvisibilitychange' in document) {
280
211
  document.removeEventListener('visibilitychange', this._handleVisibilityChange);
281
212
  } else {
@@ -290,3 +221,4 @@ class TrackingController implements ReactiveController {
290
221
  }
291
222
 
292
223
  export { TrackingController };
224
+ export type { TrackingEvent, TrackingPayload };
@@ -0,0 +1,95 @@
1
+ import { TEMPLATE_VERSION } from '@vouchfor/canvas-video';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+
4
+ import type { TrackingPayload } from '.';
5
+ import type { Vouch } from '@vouchfor/video-utils';
6
+ import type { Environment } from '~/utils/env';
7
+
8
+ import packageJson from '~/../package.json';
9
+ import { getEnvUrls } from '~/utils/env';
10
+
11
+ function createVisitor(env: Environment) {
12
+ const { publicApiUrl } = getEnvUrls(env);
13
+ const visitorId = uuidv4();
14
+ navigator.sendBeacon(`${publicApiUrl}/api/visitor`, JSON.stringify({ visitorId }));
15
+ return visitorId;
16
+ }
17
+
18
+ function getUids(env: Environment) {
19
+ if (typeof window === 'undefined') {
20
+ return {
21
+ client: null,
22
+ tab: null,
23
+ request: uuidv4()
24
+ };
25
+ }
26
+
27
+ // Persisted for a user for the same device + browser, so we can e.g. search for all logs related to that browser
28
+ let visitorId = window.localStorage?.getItem?.('vouch-uid-visitor');
29
+ // Persisted for a user for the same device + browser, so we can e.g. search for all logs related to that browser
30
+ let clientId = window.localStorage?.getItem?.('vouch-uid-client');
31
+ // Persisted in session storage, so we can search for everything the user has done in a specific tab
32
+ let tabId = window.sessionStorage?.getItem?.('vouch-uid-tab');
33
+ // Not persisted, allows us to search for any logs related to a single FE request
34
+ // E.g. BE should pass this request ID through all other services to be able to group logs
35
+ const requestId = uuidv4();
36
+
37
+ // Cache uids
38
+ if (!visitorId) {
39
+ visitorId = createVisitor(env);
40
+ window.localStorage?.setItem?.('vouch-uid-visitor', visitorId);
41
+ }
42
+
43
+ if (!clientId) {
44
+ clientId = uuidv4();
45
+ window.localStorage?.setItem?.('vouch-uid-client', clientId);
46
+ }
47
+
48
+ if (!tabId) {
49
+ tabId = uuidv4();
50
+ window.sessionStorage?.setItem?.('vouch-uid-tab', tabId);
51
+ }
52
+
53
+ return {
54
+ client: clientId,
55
+ tab: tabId,
56
+ request: requestId,
57
+ visitor: visitorId
58
+ };
59
+ }
60
+
61
+ function findVouchId(payload?: TrackingPayload, vouch?: Vouch) {
62
+ if (payload && 'vouchId' in payload) {
63
+ return payload.vouchId;
64
+ }
65
+ return vouch?.id ?? null;
66
+ }
67
+
68
+ function getReportingMetadata(source = 'embedded_player') {
69
+ const [country, region] = Intl.DateTimeFormat().resolvedOptions().timeZone?.split?.('/') ?? [];
70
+
71
+ const utmParams: any = {};
72
+ [...new URLSearchParams(location.search).entries()].forEach(([key, value]) => {
73
+ if (/utm/.test(key)) {
74
+ const param = key.toLowerCase().replace(/[-_][a-z0-9]/g, (group) => group.slice(-1).toUpperCase());
75
+ utmParams[param] = value;
76
+ }
77
+ });
78
+
79
+ return {
80
+ source,
81
+ time: new Date(),
82
+ region,
83
+ country,
84
+ screenHeight: window.screen.height,
85
+ screenWidth: window.screen.width,
86
+ referrer: document.referrer,
87
+ currentUrl: location.href,
88
+ embedType: 'media-player-embed',
89
+ embedVersion: packageJson.version,
90
+ templateVersion: TEMPLATE_VERSION,
91
+ ...utmParams
92
+ };
93
+ }
94
+
95
+ export { getUids, findVouchId, getReportingMetadata };
@@ -1,11 +1,10 @@
1
- import { html, LitElement } from 'lit';
1
+ import { css, html, LitElement } from 'lit';
2
2
  import { customElement, property, state } from 'lit/decorators.js';
3
3
  import { ifDefined } from 'lit/directives/if-defined.js';
4
4
  import { createRef, ref } from 'lit/directives/ref.js';
5
5
 
6
6
  import type { Scene, Scenes, TemplateInstance } from '@vouchfor/canvas-video';
7
7
  import type { MediaPlayer, MediaPlayerProps } from '@vouchfor/media-player';
8
- import type { Ref } from 'lit/directives/ref.js';
9
8
  import type { Environment } from '~/utils/env';
10
9
 
11
10
  import { EventForwardController } from './controllers/event-forwarder';
@@ -14,32 +13,41 @@ import { TrackingController } from './controllers/tracking';
14
13
 
15
14
  import '@vouchfor/media-player';
16
15
 
17
- type EmbedProps = Pick<MediaPlayerProps, 'data' | 'aspectRatio' | 'preload' | 'autoplay' | 'controls'> & {
16
+ type PlayerEmbedProps = Pick<MediaPlayerProps, 'data' | 'aspectRatio' | 'preload' | 'autoplay' | 'controls'> & {
18
17
  env: Environment;
19
18
  apiKey: string;
20
19
  disableTracking?: boolean;
21
20
  trackingSource?: string;
22
21
  vouchId?: string;
23
22
  templateId?: string;
23
+ // Index of the questions to include starting from 1
24
+ questions?: number[];
24
25
  };
25
26
 
26
- @customElement('vouch-embed')
27
- class Embed extends LitElement {
28
- private _mediaPlayerRef: Ref<MediaPlayer> = createRef();
29
-
30
- @property({ type: Object, attribute: 'data' }) data: EmbedProps['data'];
31
- @property({ type: String }) vouchId: EmbedProps['vouchId'];
32
- @property({ type: String }) templateId: EmbedProps['templateId'];
33
-
34
- @property({ type: String }) env: EmbedProps['env'] = 'prod';
35
- @property({ type: String }) apiKey: EmbedProps['apiKey'] = '';
36
- @property({ type: Boolean }) disableTracking: EmbedProps['disableTracking'] = false;
37
- @property({ type: String }) trackingSource: EmbedProps['trackingSource'] = 'embed';
38
-
39
- @property({ type: Array }) controls: EmbedProps['controls'];
40
- @property({ type: String }) preload: EmbedProps['preload'] = 'auto';
41
- @property({ type: Boolean }) autoplay: EmbedProps['autoplay'] = false;
42
- @property({ type: Number }) aspectRatio: EmbedProps['aspectRatio'] = 0;
27
+ @customElement('vouch-embed-player')
28
+ class PlayerEmbed extends LitElement {
29
+ static styles = [
30
+ css`
31
+ :host {
32
+ display: flex;
33
+ }
34
+ `
35
+ ];
36
+
37
+ @property({ type: Object }) data: PlayerEmbedProps['data'];
38
+ @property({ type: String }) vouchId: PlayerEmbedProps['vouchId'];
39
+ @property({ type: String }) templateId: PlayerEmbedProps['templateId'];
40
+ @property({ type: Array }) questions: PlayerEmbedProps['questions'];
41
+
42
+ @property({ type: String }) env: PlayerEmbedProps['env'] = 'prod';
43
+ @property({ type: String }) apiKey: PlayerEmbedProps['apiKey'] = '';
44
+ @property({ type: Boolean }) disableTracking: PlayerEmbedProps['disableTracking'] = false;
45
+ @property({ type: String }) trackingSource: PlayerEmbedProps['trackingSource'] = 'embedded_player';
46
+
47
+ @property({ type: Array }) controls: PlayerEmbedProps['controls'];
48
+ @property({ type: String }) preload: PlayerEmbedProps['preload'] = 'auto';
49
+ @property({ type: Boolean }) autoplay: PlayerEmbedProps['autoplay'] = false;
50
+ @property({ type: Number }) aspectRatio: PlayerEmbedProps['aspectRatio'] = 0;
43
51
 
44
52
  private eventController = new EventForwardController(this, [
45
53
  'durationchange',
@@ -74,17 +82,23 @@ class Embed extends LitElement {
74
82
  // @ts-ignore
75
83
  private _trackingController = new TrackingController(this);
76
84
 
77
- @state() vouch: EmbedProps['data'];
85
+ @state() vouch: PlayerEmbedProps['data'];
78
86
  @state() template: TemplateInstance | undefined;
79
87
 
80
88
  get fetching() {
81
89
  return this._fetcherController.fetching;
82
90
  }
83
91
 
92
+ private _mediaPlayerRef = createRef<MediaPlayer>();
93
+
84
94
  get waiting() {
85
95
  return this._mediaPlayerRef.value?.waiting;
86
96
  }
87
97
 
98
+ get initialised() {
99
+ return this._mediaPlayerRef.value?.initialised;
100
+ }
101
+
88
102
  get seeking() {
89
103
  return this._mediaPlayerRef.value?.seeking;
90
104
  }
@@ -169,13 +183,43 @@ class Embed extends LitElement {
169
183
  this._mediaPlayerRef.value?.pause();
170
184
  }
171
185
 
186
+ reset(time = 0, play = false) {
187
+ this._mediaPlayerRef.value?.reset(time, play);
188
+ }
189
+
172
190
  setScene(index: number) {
173
191
  this._mediaPlayerRef.value?.setScene(index);
174
192
  }
175
193
 
194
+ private _renderStyles() {
195
+ if (!this.aspectRatio) {
196
+ return html`
197
+ <style>
198
+ :host {
199
+ width: 100%;
200
+ height: 100%;
201
+ }
202
+ </style>
203
+ `;
204
+ }
205
+
206
+ if (typeof this.aspectRatio === 'number') {
207
+ return html`
208
+ <style>
209
+ :host {
210
+ aspect-ratio: ${this.aspectRatio};
211
+ }
212
+ </style>
213
+ `;
214
+ }
215
+
216
+ return null;
217
+ }
218
+
176
219
  render() {
177
220
  return html`
178
- <vmp-new-media-player
221
+ ${this._renderStyles()}
222
+ <vmp-media-player
179
223
  ${ref(this._mediaPlayerRef)}
180
224
  ${this.eventController.register()}
181
225
  ?autoplay=${this.autoplay}
@@ -185,22 +229,22 @@ class Embed extends LitElement {
185
229
  aspectRatio=${ifDefined(this.aspectRatio)}
186
230
  preload=${ifDefined(this.preload)}
187
231
  .controls=${this.controls}
188
- ></vmp-new-media-player>
232
+ ></vmp-media-player>
189
233
  `;
190
234
  }
191
235
  }
192
236
 
193
237
  declare global {
194
238
  interface HTMLElementTagNameMap {
195
- 'vouch-embed': Embed;
239
+ 'vouch-embed-player': PlayerEmbed;
196
240
  }
197
241
 
198
242
  namespace JSX {
199
243
  interface IntrinsicElements {
200
- 'vouch-embed': Embed;
244
+ 'vouch-embed-player': PlayerEmbed;
201
245
  }
202
246
  }
203
247
  }
204
248
 
205
- export { Embed };
206
- export type { EmbedProps };
249
+ export { PlayerEmbed };
250
+ export type { PlayerEmbedProps };