@vouchfor/embeds 1.0.2 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. package/dist/es/{browser-2070b7b8.js → browser-25a8d581.js} +2 -2
  2. package/dist/es/{browser-2070b7b8.js.map → browser-25a8d581.js.map} +1 -1
  3. package/dist/es/embeds.js +5 -2
  4. package/dist/es/embeds.js.map +1 -1
  5. package/dist/es/{index-6d91e49b.js → index-45b0c060.js} +4010 -3643
  6. package/dist/es/index-45b0c060.js.map +1 -0
  7. package/dist/es/src/components/DialogEmbed/DialogOverlay.d.ts +19 -0
  8. package/dist/es/src/components/DialogEmbed/DialogPortal.d.ts +35 -0
  9. package/dist/es/src/components/DialogEmbed/index.d.ts +35 -0
  10. package/dist/es/src/components/PlayerEmbed/controllers/event-forwarder.d.ts +15 -0
  11. package/dist/es/src/index.d.ts +1 -0
  12. package/dist/iife/dialog-embed/browser-e1c0fc69.js +433 -0
  13. package/dist/iife/dialog-embed/browser-e1c0fc69.js.map +1 -0
  14. package/dist/iife/dialog-embed/embed.iife.js +1721 -0
  15. package/dist/iife/dialog-embed/embed.iife.js.map +1 -0
  16. package/dist/iife/dialog-embed/embed.js +5 -0
  17. package/dist/iife/dialog-embed/embed.js.map +1 -0
  18. package/dist/iife/dialog-embed/index-aa6cdaeb.js +32924 -0
  19. package/dist/iife/dialog-embed/index-aa6cdaeb.js.map +1 -0
  20. package/dist/iife/dialog-embed/src/components/DialogEmbed/DialogOverlay.d.ts +19 -0
  21. package/dist/iife/dialog-embed/src/components/DialogEmbed/DialogPortal.d.ts +35 -0
  22. package/dist/iife/dialog-embed/src/components/DialogEmbed/index.d.ts +35 -0
  23. package/dist/iife/dialog-embed/src/components/PlayerEmbed/controllers/event-forwarder.d.ts +15 -0
  24. package/dist/iife/dialog-embed/src/components/PlayerEmbed/controllers/fetcher.d.ts +14 -0
  25. package/dist/iife/dialog-embed/src/components/PlayerEmbed/controllers/tracking/index.d.ts +36 -0
  26. package/dist/iife/dialog-embed/src/components/PlayerEmbed/controllers/tracking/utils.d.ts +17 -0
  27. package/dist/iife/dialog-embed/src/components/PlayerEmbed/tests/data.d.ts +3 -0
  28. package/dist/iife/dialog-embed/src/index.d.ts +2 -0
  29. package/dist/iife/dialog-embed/src/utils/env.d.ts +12 -0
  30. package/dist/iife/dialog-embed/src/utils/events.d.ts +2 -0
  31. package/dist/iife/embeds.iife.js +326 -177
  32. package/dist/iife/embeds.iife.js.map +1 -1
  33. package/dist/iife/player-embed/browser-eb42680e.js +433 -0
  34. package/dist/iife/player-embed/browser-eb42680e.js.map +1 -0
  35. package/dist/iife/player-embed/embed.iife.js +1585 -0
  36. package/dist/iife/player-embed/embed.iife.js.map +1 -0
  37. package/dist/iife/player-embed/embed.js +5 -0
  38. package/dist/iife/player-embed/embed.js.map +1 -0
  39. package/dist/iife/player-embed/index-52048e3b.js +32481 -0
  40. package/dist/iife/player-embed/index-52048e3b.js.map +1 -0
  41. package/dist/iife/player-embed/src/components/DialogEmbed/DialogOverlay.d.ts +19 -0
  42. package/dist/iife/player-embed/src/components/DialogEmbed/DialogPortal.d.ts +35 -0
  43. package/dist/iife/player-embed/src/components/DialogEmbed/index.d.ts +35 -0
  44. package/dist/iife/player-embed/src/components/PlayerEmbed/controllers/event-forwarder.d.ts +15 -0
  45. package/dist/iife/player-embed/src/components/PlayerEmbed/controllers/fetcher.d.ts +14 -0
  46. package/dist/iife/player-embed/src/components/PlayerEmbed/controllers/tracking/index.d.ts +36 -0
  47. package/dist/iife/player-embed/src/components/PlayerEmbed/controllers/tracking/utils.d.ts +17 -0
  48. package/dist/iife/player-embed/src/components/PlayerEmbed/tests/data.d.ts +3 -0
  49. package/dist/iife/player-embed/src/index.d.ts +2 -0
  50. package/dist/iife/player-embed/src/utils/env.d.ts +12 -0
  51. package/dist/iife/player-embed/src/utils/events.d.ts +2 -0
  52. package/package.json +8 -3
  53. package/src/components/DialogEmbed/Dialog.stories.ts +79 -0
  54. package/src/components/DialogEmbed/DialogOverlay.ts +130 -0
  55. package/src/components/DialogEmbed/DialogPortal.ts +114 -0
  56. package/src/components/DialogEmbed/index.ts +93 -0
  57. package/src/components/PlayerEmbed/controllers/event-forwarder.ts +2 -1
  58. package/src/components/PlayerEmbed/index.ts +5 -103
  59. package/src/index.ts +1 -0
  60. package/src/mixins/media-player-proxy.ts +116 -0
  61. package/dist/es/index-6d91e49b.js.map +0 -1
  62. package/dist/es/src/components/PlayerEmbed/index.d.ts +0 -72
@@ -0,0 +1,19 @@
1
+ import { LitElement } from 'lit';
2
+ import type { DialogEmbedProps } from '.';
3
+ declare class DialogOverlay extends LitElement {
4
+ static styles: import("lit").CSSResult[];
5
+ open: boolean;
6
+ aspectRatio: DialogEmbedProps['aspectRatio'];
7
+ render(): import("lit").TemplateResult<1>;
8
+ }
9
+ declare global {
10
+ interface HTMLElementTagNameMap {
11
+ 'vouch-embed-dialog-overlay': DialogOverlay;
12
+ }
13
+ namespace JSX {
14
+ interface IntrinsicElements {
15
+ 'vouch-embed-dialog-overlay': DialogOverlay;
16
+ }
17
+ }
18
+ }
19
+ export { DialogOverlay };
@@ -0,0 +1,35 @@
1
+ import { LitElement } from 'lit';
2
+ import type { DialogEmbedProps } from '.';
3
+ declare class DialogPortal extends LitElement {
4
+ vouchId: DialogEmbedProps['vouchId'];
5
+ templateId: DialogEmbedProps['templateId'];
6
+ questions: DialogEmbedProps['questions'];
7
+ env: DialogEmbedProps['env'];
8
+ apiKey: DialogEmbedProps['apiKey'];
9
+ disableTracking: DialogEmbedProps['disableTracking'];
10
+ trackingSource: DialogEmbedProps['trackingSource'];
11
+ controls: DialogEmbedProps['controls'];
12
+ preload: DialogEmbedProps['preload'];
13
+ disableAutoplay: DialogEmbedProps['disableAutoplay'];
14
+ aspectRatio: DialogEmbedProps['aspectRatio'];
15
+ private _mediaPlayerRef;
16
+ open: boolean;
17
+ private _handleToggle;
18
+ private _handleClose;
19
+ private _handleDocumentKeyUp;
20
+ connectedCallback(): void;
21
+ disconnectedCallback(): void;
22
+ protected createRenderRoot(): HTMLElement | DocumentFragment;
23
+ render(): import("lit").TemplateResult<1>;
24
+ }
25
+ declare global {
26
+ interface HTMLElementTagNameMap {
27
+ 'vouch-embed-dialog-portal': DialogPortal;
28
+ }
29
+ namespace JSX {
30
+ interface IntrinsicElements {
31
+ 'vouch-embed-dialog-portal': DialogPortal;
32
+ }
33
+ }
34
+ }
35
+ export { DialogPortal };
@@ -0,0 +1,35 @@
1
+ import { LitElement } from 'lit';
2
+ import type { PlayerEmbedProps } from '../PlayerEmbed';
3
+ type DialogEmbedProps = Omit<PlayerEmbedProps, 'data'> & {
4
+ disableAutoplay?: boolean;
5
+ };
6
+ declare class DialogEmbed extends LitElement {
7
+ static styles: import("lit").CSSResult[];
8
+ vouchId: DialogEmbedProps['vouchId'];
9
+ templateId: DialogEmbedProps['templateId'];
10
+ questions: DialogEmbedProps['questions'];
11
+ env: DialogEmbedProps['env'];
12
+ apiKey: DialogEmbedProps['apiKey'];
13
+ disableTracking: DialogEmbedProps['disableTracking'];
14
+ trackingSource: DialogEmbedProps['trackingSource'];
15
+ controls: DialogEmbedProps['controls'];
16
+ preload: DialogEmbedProps['preload'];
17
+ disableAutoplay: DialogEmbedProps['disableAutoplay'];
18
+ aspectRatio: DialogEmbedProps['aspectRatio'];
19
+ private _handleRootClick;
20
+ connectedCallback(): void;
21
+ disconnectedCallback(): void;
22
+ render(): import("lit").TemplateResult<1>;
23
+ }
24
+ declare global {
25
+ interface HTMLElementTagNameMap {
26
+ 'vouch-embed-dialog': DialogEmbed;
27
+ }
28
+ namespace JSX {
29
+ interface IntrinsicElements {
30
+ 'vouch-embed-dialog': DialogEmbed;
31
+ }
32
+ }
33
+ }
34
+ export { DialogEmbed };
35
+ export type { DialogEmbedProps };
@@ -0,0 +1,15 @@
1
+ import type { PlayerEmbed } from '..';
2
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
3
+ import type { DirectiveResult } from 'lit/directive.js';
4
+ type PlayerEmbedHost = ReactiveControllerHost & PlayerEmbed;
5
+ declare class EventForwardController implements ReactiveController {
6
+ host: PlayerEmbedHost;
7
+ private _events;
8
+ private _cleanup;
9
+ private _forwardElementRef;
10
+ constructor(host: PlayerEmbedHost, events: string[]);
11
+ register(): DirectiveResult;
12
+ hostConnected(): void;
13
+ hostDisconnected(): void;
14
+ }
15
+ export { EventForwardController };
@@ -0,0 +1,14 @@
1
+ import type { PlayerEmbed } from '..';
2
+ import type { ReactiveControllerHost } from 'lit';
3
+ type PlayerEmbedHost = ReactiveControllerHost & PlayerEmbed;
4
+ declare class FetcherController {
5
+ host: PlayerEmbedHost;
6
+ private _fetching;
7
+ private _vouch;
8
+ set fetching(value: boolean);
9
+ get fetching(): boolean;
10
+ private getVouch;
11
+ private getTemplate;
12
+ constructor(host: PlayerEmbedHost);
13
+ }
14
+ export { FetcherController };
@@ -0,0 +1,36 @@
1
+ import type { PlayerEmbed } from '../..';
2
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
3
+ type PlayerEmbedHost = ReactiveControllerHost & PlayerEmbed;
4
+ type TrackingEvent = 'VOUCH_LOADED' | 'VOUCH_RESPONSE_VIEWED' | 'VIDEO_PLAYED' | 'VIDEO_STREAMED';
5
+ type TrackingPayload = {
6
+ vouchId?: string;
7
+ answerId?: string;
8
+ streamStart?: number;
9
+ streamEnd?: number;
10
+ };
11
+ declare class TrackingController implements ReactiveController {
12
+ host: PlayerEmbedHost;
13
+ private _batchedEvents;
14
+ private _hasPlayed;
15
+ private _hasLoaded;
16
+ private _answersViewed;
17
+ private _streamStartTime;
18
+ private _streamLatestTime;
19
+ private _currentlyPlayingVideo;
20
+ constructor(host: PlayerEmbedHost);
21
+ private _createTrackingEvent;
22
+ private _sendTrackingEvent;
23
+ private _streamEnded;
24
+ private _handleVouchLoaded;
25
+ private _handlePlay;
26
+ private _handleVideoPlay;
27
+ private _handleVideoTimeUpdate;
28
+ private _handleVideoPause;
29
+ private _pageUnloading;
30
+ private _handleVisibilityChange;
31
+ private _handlePageHide;
32
+ hostConnected(): void;
33
+ hostDisconnected(): void;
34
+ }
35
+ export { TrackingController };
36
+ export type { TrackingEvent, TrackingPayload };
@@ -0,0 +1,17 @@
1
+ import type { TrackingPayload } from '.';
2
+ import type { Vouch } from '@vouchfor/media-player';
3
+ import type { Environment } from '../../../../utils/env';
4
+ declare function getUids(env: Environment): {
5
+ client: null;
6
+ tab: null;
7
+ request: string;
8
+ visitor?: undefined;
9
+ } | {
10
+ client: string;
11
+ tab: string;
12
+ request: string;
13
+ visitor: string;
14
+ };
15
+ declare function findVouchId(payload?: TrackingPayload, vouch?: Vouch): string | null | undefined;
16
+ declare function getReportingMetadata(source?: string): any;
17
+ export { getUids, findVouchId, getReportingMetadata };
@@ -0,0 +1,3 @@
1
+ import type { Vouch } from '@vouchfor/media-player';
2
+ declare const data: Vouch;
3
+ export { data };
@@ -0,0 +1,2 @@
1
+ export { PlayerEmbed } from './components/PlayerEmbed';
2
+ export { DialogEmbed } from './components/DialogEmbed';
@@ -0,0 +1,12 @@
1
+ type Environment = 'local' | 'dev' | 'staging' | 'prod';
2
+ type GetEnvUrlsReturn = {
3
+ videoUrl: string;
4
+ publicApiUrl: string;
5
+ embedApiUrl: string;
6
+ };
7
+ declare const devEmbedApiUrl = "https://embed-dev.vouchfor.com/v2";
8
+ declare const stagingEmbedApiUrl = "https://embed-staging.vouchfor.com/v2";
9
+ declare const prodEmbedApiUrl = "https://embed.vouchfor.com/v2";
10
+ declare function getEnvUrls(env: Environment): GetEnvUrlsReturn;
11
+ export { devEmbedApiUrl, stagingEmbedApiUrl, prodEmbedApiUrl, getEnvUrls };
12
+ export type { Environment };
@@ -0,0 +1,2 @@
1
+ declare function forwardEvent(type: string, fromElement: HTMLElement, toElement: HTMLElement): () => void;
2
+ export { forwardEvent };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vouchfor/embeds",
3
- "version": "1.0.2",
3
+ "version": "1.1.1",
4
4
  "license": "MIT",
5
5
  "author": "Aaron Williams",
6
6
  "main": "dist/es/embeds.js",
@@ -19,8 +19,9 @@
19
19
  "access": "public"
20
20
  },
21
21
  "scripts": {
22
- "build": "rm -rf dist && tsc && vite build --mode iife && vite build --mode es",
22
+ "build": "rm -rf dist && tsc && yarn build:self",
23
23
  "build:deps": "yarn --cwd ../media-player build",
24
+ "build:self": "vite build --mode iife && vite build --mode es && node scripts/build.cjs",
24
25
  "build:package": "yarn build",
25
26
  "build:storybook": "yarn prebuild && storybook build",
26
27
  "generate:manifest": "wca src --outFile custom-elements.json",
@@ -39,8 +40,9 @@
39
40
  "**/*.{md,json,yml}": "prettier --write"
40
41
  },
41
42
  "dependencies": {
43
+ "@a11y/focus-trap": "^1.0.5",
42
44
  "@lit/task": "^1.0.0",
43
- "@vouchfor/media-player": "^2.0.2",
45
+ "@vouchfor/media-player": "^2.0.4",
44
46
  "uuid": "^9.0.1"
45
47
  },
46
48
  "peerDependencies": {
@@ -65,11 +67,14 @@
65
67
  "dotenv": "^16.3.1",
66
68
  "eslint": "^8.50.0",
67
69
  "eslint-plugin-import": "^2.28.1",
70
+ "glob": "^10.3.10",
68
71
  "lint-staged": "^14.0.1",
69
72
  "lit": "^3.1.0",
73
+ "lodash": "^4.17.21",
70
74
  "prettier": "^3.0.3",
71
75
  "react": "^18.2.0",
72
76
  "react-dom": "^18.2.0",
77
+ "rollup-plugin-internal": "^1.0.4",
73
78
  "sinon": "^17.0.1",
74
79
  "storybook": "^7.4.5",
75
80
  "typescript": "^5.1.3",
@@ -0,0 +1,79 @@
1
+ import { html } from 'lit';
2
+ import { ifDefined } from 'lit/directives/if-defined.js';
3
+
4
+ import type { DialogEmbedProps } from '.';
5
+ import type { Meta, StoryObj } from '@storybook/web-components';
6
+
7
+ import '.';
8
+
9
+ type DialogEmbedArgs = DialogEmbedProps & {
10
+ showVouch?: boolean;
11
+ };
12
+
13
+ const _DialogEmbed = ({
14
+ vouchId,
15
+ templateId,
16
+ questions,
17
+ preload,
18
+ autoplay,
19
+ env,
20
+ apiKey,
21
+ controls,
22
+ aspectRatio
23
+ }: DialogEmbedArgs) => {
24
+ return html`
25
+ <div style="padding: 20px;">
26
+ <vouch-embed-dialog
27
+ env=${ifDefined(env)}
28
+ apiKey=${ifDefined(apiKey)}
29
+ vouchId=${ifDefined(vouchId)}
30
+ templateId=${ifDefined(templateId)}
31
+ .questions=${questions}
32
+ .controls=${controls}
33
+ ?autoplay=${autoplay}
34
+ preload=${ifDefined(preload)}
35
+ aspectRatio=${ifDefined(aspectRatio)}
36
+ @error=${console.log}
37
+ ></vouch-embed-dialog>
38
+ </div>
39
+ `;
40
+ };
41
+
42
+ // More on how to set up stories at: https://storybook.js.org/docs/web-components/writing-stories/introduction
43
+ const meta = {
44
+ title: 'Dialog',
45
+ tags: ['autodocs'],
46
+ render: (args) => _DialogEmbed(args),
47
+ component: 'vouch-embed-dialog'
48
+ } satisfies Meta<DialogEmbedProps>;
49
+
50
+ type Story = StoryObj<DialogEmbedArgs>;
51
+
52
+ const Dialog: Story = {
53
+ args: {
54
+ env: 'dev',
55
+ apiKey: 'TVik9uTMgE-PD25UTHIS6gyl0hMBWC7AT4dkpdlLBT4VIfDWZJrQiCk6Ak7m1',
56
+ vouchId: '6JQEIPeStt',
57
+ templateId: '357fc118-e179-4171-9446-ff2b8e9d1b29',
58
+ questions: [],
59
+ aspectRatio: 0,
60
+ preload: 'none',
61
+ autoplay: false
62
+ },
63
+ argTypes: {
64
+ env: {
65
+ control: 'radio',
66
+ options: ['local', 'dev', 'staging', 'prod']
67
+ },
68
+ preload: {
69
+ control: 'radio',
70
+ options: ['auto', 'none']
71
+ }
72
+ },
73
+ parameters: {
74
+ layout: 'fullscreen'
75
+ }
76
+ };
77
+
78
+ export default meta;
79
+ export { Dialog };
@@ -0,0 +1,130 @@
1
+ import { css, html, LitElement } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+ import { classMap } from 'lit/directives/class-map.js';
4
+ import { styleMap } from 'lit/directives/style-map.js';
5
+
6
+ import type { DialogEmbedProps } from '.';
7
+
8
+ import '@a11y/focus-trap';
9
+
10
+ @customElement('vouch-embed-dialog-overlay')
11
+ class DialogOverlay extends LitElement {
12
+ static styles = [
13
+ css`
14
+ :host {
15
+ --vouch-media-player-border-radius: var(--vu-media-player-border-radius, 12px);
16
+ --overlay-background-color: var(--vu-overlay-background-color, black);
17
+ --overlay-background-opacity: var(--vu-overlay-background-opacity, 0.4);
18
+
19
+ --dialog-width: var(--vu-dialog-width, 890px);
20
+ --dialog-height: var(--vu-dialog-height, 500px);
21
+ }
22
+
23
+ .container {
24
+ position: absolute;
25
+ display: flex;
26
+ inset: 0;
27
+ opacity: 1;
28
+ align-items: center;
29
+ justify-content: center;
30
+ transition: opacity 100ms ease-in;
31
+ }
32
+
33
+ .hidden {
34
+ opacity: 0;
35
+ pointer-events: none;
36
+ }
37
+
38
+ .background {
39
+ position: absolute;
40
+ inset: 0;
41
+ opacity: var(--overlay-background-opacity);
42
+ background-color: var(--overlay-background-color);
43
+ }
44
+
45
+ focus-trap {
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ margin: 40px;
50
+ width: var(--dialog-width);
51
+ height: var(--dialog-height);
52
+ max-width: calc(100% - 80px);
53
+ max-height: calc(100% - 80px);
54
+ }
55
+
56
+ .video-frame {
57
+ position: relative;
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ max-width: 100%;
62
+ max-height: 100%;
63
+ }
64
+
65
+ .video-frame.grow {
66
+ width: 100%;
67
+ height: 100%;
68
+ }
69
+
70
+ vmp-icon-button {
71
+ position: absolute;
72
+ top: 0;
73
+ right: 0;
74
+ margin: 10px;
75
+ }
76
+ `
77
+ ];
78
+
79
+ @property({ type: Boolean }) open = false;
80
+ @property({ type: Number }) aspectRatio: DialogEmbedProps['aspectRatio'] = 0;
81
+
82
+ render() {
83
+ return html`
84
+ <div
85
+ class=${classMap({
86
+ container: true,
87
+ hidden: !this.open
88
+ })}
89
+ >
90
+ <div
91
+ class="background"
92
+ @click=${() => this.dispatchEvent(new CustomEvent('overlay:click', { bubbles: true, composed: true }))}
93
+ ></div>
94
+ <focus-trap>
95
+ <div
96
+ class=${classMap({
97
+ 'video-frame': true,
98
+ grow: this.aspectRatio === 0
99
+ })}
100
+ style=${styleMap({
101
+ aspectRatio: this.aspectRatio
102
+ })}
103
+ >
104
+ <slot></slot>
105
+ <vmp-icon-button
106
+ icon="close"
107
+ rounded="full"
108
+ weight="heavy"
109
+ @click=${() => this.dispatchEvent(new CustomEvent('close:click', { bubbles: true, composed: true }))}
110
+ ></vmp-icon-button>
111
+ </div>
112
+ </focus-trap>
113
+ </div>
114
+ `;
115
+ }
116
+ }
117
+
118
+ declare global {
119
+ interface HTMLElementTagNameMap {
120
+ 'vouch-embed-dialog-overlay': DialogOverlay;
121
+ }
122
+
123
+ namespace JSX {
124
+ interface IntrinsicElements {
125
+ 'vouch-embed-dialog-overlay': DialogOverlay;
126
+ }
127
+ }
128
+ }
129
+
130
+ export { DialogOverlay };
@@ -0,0 +1,114 @@
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
+ import { styleMap } from 'lit/directives/style-map.js';
6
+
7
+ import type { DialogEmbedProps } from '.';
8
+ import type { MediaPlayer } from '@vouchfor/media-player';
9
+
10
+ import './DialogOverlay';
11
+
12
+ @customElement('vouch-embed-dialog-portal')
13
+ class DialogPortal extends LitElement {
14
+ @property({ type: String }) vouchId: DialogEmbedProps['vouchId'];
15
+ @property({ type: String }) templateId: DialogEmbedProps['templateId'];
16
+ @property({ type: Array }) questions: DialogEmbedProps['questions'];
17
+
18
+ @property({ type: String }) env: DialogEmbedProps['env'] = 'prod';
19
+ @property({ type: String }) apiKey: DialogEmbedProps['apiKey'] = '';
20
+ @property({ type: Boolean }) disableTracking: DialogEmbedProps['disableTracking'] = false;
21
+ @property({ type: String }) trackingSource: DialogEmbedProps['trackingSource'] = 'embedded_player';
22
+
23
+ @property({ type: Array }) controls: DialogEmbedProps['controls'];
24
+ @property({ type: String }) preload: DialogEmbedProps['preload'] = 'none';
25
+ @property({ type: Boolean }) disableAutoplay: DialogEmbedProps['disableAutoplay'] = false;
26
+ @property({ type: Number }) aspectRatio: DialogEmbedProps['aspectRatio'] = 0;
27
+
28
+ private _mediaPlayerRef = createRef<MediaPlayer>();
29
+
30
+ @state() open = false;
31
+
32
+ private _handleToggle = () => {
33
+ this.open = !this.open;
34
+
35
+ if (this.open) {
36
+ if (!this.disableAutoplay && this._mediaPlayerRef?.value) {
37
+ this._mediaPlayerRef.value.muted = false;
38
+ this._mediaPlayerRef.value.play();
39
+ }
40
+ } else {
41
+ this._mediaPlayerRef?.value?.pause();
42
+ }
43
+ };
44
+
45
+ private _handleClose = () => {
46
+ this.open = false;
47
+ this._mediaPlayerRef?.value?.pause();
48
+ };
49
+
50
+ private _handleDocumentKeyUp = (e: KeyboardEvent) => {
51
+ if (e.key === 'Escape') {
52
+ this._handleClose();
53
+ }
54
+ };
55
+
56
+ connectedCallback(): void {
57
+ super.connectedCallback();
58
+ document.addEventListener('dialogembed:click', this._handleToggle);
59
+ document.addEventListener('keyup', this._handleDocumentKeyUp);
60
+ document.addEventListener('close:click', this._handleClose);
61
+ document.addEventListener('overlay:click', this._handleClose);
62
+ }
63
+
64
+ disconnectedCallback(): void {
65
+ super.disconnectedCallback();
66
+ document.removeEventListener('dialogembed:click', this._handleToggle);
67
+ document.removeEventListener('keyup', this._handleDocumentKeyUp);
68
+ document.removeEventListener('close:click', this._handleClose);
69
+ document.removeEventListener('overlay:click', this._handleClose);
70
+ }
71
+
72
+ protected createRenderRoot(): HTMLElement | DocumentFragment {
73
+ return document.body;
74
+ }
75
+
76
+ render() {
77
+ return html`
78
+ <vouch-embed-dialog-overlay ?open=${this.open} aspectRatio=${this.aspectRatio}>
79
+ <vouch-embed-player
80
+ ${ref(this._mediaPlayerRef)}
81
+ style=${styleMap({
82
+ maxWidth: '100%',
83
+ maxHeight: '100%'
84
+ })}
85
+ ?autoplay=${false}
86
+ vouchId=${ifDefined(this.vouchId)}
87
+ templateId=${ifDefined(this.templateId)}
88
+ .questions=${this.questions}
89
+ .controls=${this.controls}
90
+ env=${ifDefined(this.env)}
91
+ apiKey=${ifDefined(this.apiKey)}
92
+ ?disableTracking=${this.disableTracking}
93
+ trackingSource=${ifDefined(this.trackingSource)}
94
+ preload=${ifDefined(this.preload)}
95
+ aspectRatio=${this.aspectRatio}
96
+ ></vouch-embed-player>
97
+ </vouch-embed-dialog-overlay>
98
+ `;
99
+ }
100
+ }
101
+
102
+ declare global {
103
+ interface HTMLElementTagNameMap {
104
+ 'vouch-embed-dialog-portal': DialogPortal;
105
+ }
106
+
107
+ namespace JSX {
108
+ interface IntrinsicElements {
109
+ 'vouch-embed-dialog-portal': DialogPortal;
110
+ }
111
+ }
112
+ }
113
+
114
+ export { DialogPortal };
@@ -0,0 +1,93 @@
1
+ import { css, html, LitElement } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+ import { ifDefined } from 'lit/directives/if-defined.js';
4
+
5
+ import type { PlayerEmbedProps } from '../PlayerEmbed';
6
+
7
+ import '../PlayerEmbed';
8
+ import './DialogPortal';
9
+
10
+ type DialogEmbedProps = Omit<PlayerEmbedProps, 'data'> & {
11
+ disableAutoplay?: boolean;
12
+ };
13
+
14
+ @customElement('vouch-embed-dialog')
15
+ class DialogEmbed extends LitElement {
16
+ static styles = [
17
+ css`
18
+ :host {
19
+ --vu-button-padding: 10px 20px;
20
+ --vu-button-background: #287179;
21
+ --vu-button-background-hover: #4faab2;
22
+
23
+ display: flex;
24
+ width: fit-content;
25
+ height: fit-content;
26
+ }
27
+ `
28
+ ];
29
+
30
+ @property({ type: String }) vouchId: DialogEmbedProps['vouchId'];
31
+ @property({ type: String }) templateId: DialogEmbedProps['templateId'];
32
+ @property({ type: Array }) questions: DialogEmbedProps['questions'];
33
+
34
+ @property({ type: String }) env: DialogEmbedProps['env'] = 'prod';
35
+ @property({ type: String }) apiKey: DialogEmbedProps['apiKey'] = '';
36
+ @property({ type: Boolean }) disableTracking: DialogEmbedProps['disableTracking'] = false;
37
+ @property({ type: String }) trackingSource: DialogEmbedProps['trackingSource'] = 'embedded_player';
38
+
39
+ @property({ type: Array }) controls: DialogEmbedProps['controls'];
40
+ @property({ type: String }) preload: DialogEmbedProps['preload'] = 'none';
41
+ @property({ type: Boolean }) disableAutoplay: DialogEmbedProps['disableAutoplay'] = false;
42
+ @property({ type: Number }) aspectRatio: DialogEmbedProps['aspectRatio'] = 0;
43
+
44
+ private _handleRootClick = () => {
45
+ this.dispatchEvent(new CustomEvent('dialogembed:click', { bubbles: true, composed: true }));
46
+ };
47
+
48
+ connectedCallback(): void {
49
+ super.connectedCallback();
50
+ this.addEventListener('click', this._handleRootClick);
51
+ }
52
+
53
+ disconnectedCallback(): void {
54
+ super.disconnectedCallback();
55
+ this.removeEventListener('click', this._handleRootClick);
56
+ }
57
+
58
+ render() {
59
+ return html`
60
+ <slot>
61
+ <vmp-button size="large">Play</vmp-button>
62
+ </slot>
63
+ <vouch-embed-dialog-portal
64
+ ?autoplay=${false}
65
+ vouchId=${ifDefined(this.vouchId)}
66
+ templateId=${ifDefined(this.templateId)}
67
+ .questions=${this.questions}
68
+ .controls=${this.controls}
69
+ env=${ifDefined(this.env)}
70
+ apiKey=${ifDefined(this.apiKey)}
71
+ ?disableTracking=${this.disableTracking}
72
+ trackingSource=${ifDefined(this.trackingSource)}
73
+ preload=${ifDefined(this.preload)}
74
+ aspectRatio=${this.aspectRatio}
75
+ ></vouch-embed-dialog-portal>
76
+ `;
77
+ }
78
+ }
79
+
80
+ declare global {
81
+ interface HTMLElementTagNameMap {
82
+ 'vouch-embed-dialog': DialogEmbed;
83
+ }
84
+
85
+ namespace JSX {
86
+ interface IntrinsicElements {
87
+ 'vouch-embed-dialog': DialogEmbed;
88
+ }
89
+ }
90
+ }
91
+
92
+ export { DialogEmbed };
93
+ export type { DialogEmbedProps };
@@ -2,6 +2,7 @@ import { createRef, ref } from 'lit/directives/ref.js';
2
2
 
3
3
  import type { PlayerEmbed } from '..';
4
4
  import type { ReactiveController, ReactiveControllerHost } from 'lit';
5
+ import type { DirectiveResult } from 'lit/directive.js';
5
6
  import type { Ref } from 'lit/directives/ref.js';
6
7
 
7
8
  import { forwardEvent } from '~/utils/events';
@@ -21,7 +22,7 @@ class EventForwardController implements ReactiveController {
21
22
  host.addController(this);
22
23
  }
23
24
 
24
- register() {
25
+ register(): DirectiveResult {
25
26
  return ref(this._forwardElementRef);
26
27
  }
27
28