@vouchfor/embeds 0.0.0-experiment.e14607a → 0.0.0-experiment.e7e20dd
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.
- package/dist/es/embeds.js +979 -1453
- package/dist/es/embeds.js.map +1 -1
- package/dist/es/src/components/DialogEmbed/DialogOverlay.d.ts +20 -0
- package/dist/es/src/components/DialogEmbed/DialogPortal.d.ts +36 -0
- package/dist/es/src/components/DialogEmbed/index.d.ts +38 -0
- package/dist/es/src/components/PlayerEmbed/controllers/event-forwarder.d.ts +15 -0
- package/dist/es/src/components/{Embed → PlayerEmbed}/controllers/fetcher.d.ts +5 -4
- package/dist/es/src/components/{Embed/controllers/tracking.d.ts → PlayerEmbed/controllers/tracking/index.d.ts} +14 -11
- package/dist/es/src/components/PlayerEmbed/controllers/tracking/utils.d.ts +17 -0
- package/dist/es/src/components/{Embed → PlayerEmbed}/index.d.ts +28 -21
- package/dist/es/src/components/PlayerEmbed/tests/data.d.ts +3 -0
- package/dist/es/src/index.d.ts +2 -1
- package/dist/iife/dialog-embed/embed.iife.js +1750 -0
- package/dist/iife/dialog-embed/embed.iife.js.map +1 -0
- package/dist/iife/embeds.iife.js +721 -470
- package/dist/iife/embeds.iife.js.map +1 -1
- package/dist/iife/player-embed/embed.iife.js +1612 -0
- package/dist/iife/player-embed/embed.iife.js.map +1 -0
- package/package.json +43 -31
- package/src/components/DialogEmbed/Dialog.stories.ts +91 -0
- package/src/components/DialogEmbed/DialogOverlay.ts +131 -0
- package/src/components/DialogEmbed/DialogPortal.ts +126 -0
- package/src/components/DialogEmbed/index.ts +97 -0
- package/src/components/{Embed/Embed.stories.ts → PlayerEmbed/PlayerEmbed.stories.ts} +27 -14
- package/src/components/{Embed → PlayerEmbed}/controllers/event-forwarder.ts +6 -5
- package/src/components/{Embed → PlayerEmbed}/controllers/fetcher.ts +33 -14
- package/src/components/{Embed/controllers/tracking.ts → PlayerEmbed/controllers/tracking/index.ts} +47 -115
- package/src/components/PlayerEmbed/controllers/tracking/utils.ts +95 -0
- package/src/components/{Embed → PlayerEmbed}/index.ts +71 -27
- package/src/components/PlayerEmbed/tests/PlayerEmbed.spec.ts +80 -0
- package/src/components/PlayerEmbed/tests/data.ts +183 -0
- package/src/index.ts +2 -1
    
        package/package.json
    CHANGED
    
    | @@ -1,12 +1,12 @@ | |
| 1 1 | 
             
            {
         | 
| 2 2 | 
             
              "name": "@vouchfor/embeds",
         | 
| 3 | 
            -
              "version": "0.0.0-experiment. | 
| 3 | 
            +
              "version": "0.0.0-experiment.e7e20dd",
         | 
| 4 4 | 
             
              "license": "MIT",
         | 
| 5 5 | 
             
              "author": "Aaron Williams",
         | 
| 6 6 | 
             
              "main": "dist/es/embeds.js",
         | 
| 7 7 | 
             
              "module": "dist/es/embeds.js",
         | 
| 8 8 | 
             
              "type": "module",
         | 
| 9 | 
            -
              "types": "dist/es/index.d.ts",
         | 
| 9 | 
            +
              "types": "dist/es/src/index.d.ts",
         | 
| 10 10 | 
             
              "exports": {
         | 
| 11 11 | 
             
                ".": "./dist/es/embeds.js"
         | 
| 12 12 | 
             
              },
         | 
| @@ -15,9 +15,13 @@ | |
| 15 15 | 
             
                "tag": "experiment",
         | 
| 16 16 | 
             
                "access": "public"
         | 
| 17 17 | 
             
              },
         | 
| 18 | 
            +
              "engines": {
         | 
| 19 | 
            +
                "node": ">=18.18.0"
         | 
| 20 | 
            +
              },
         | 
| 18 21 | 
             
              "scripts": {
         | 
| 19 | 
            -
                "build": "rm -rf dist && tsc &&  | 
| 22 | 
            +
                "build": "rm -rf dist && tsc && yarn build:self",
         | 
| 20 23 | 
             
                "build:deps": "yarn --cwd ../media-player build",
         | 
| 24 | 
            +
                "build:self": "vite build --mode iife && vite build --mode es && node scripts/build.cjs",
         | 
| 21 25 | 
             
                "build:package": "yarn build",
         | 
| 22 26 | 
             
                "build:storybook": "yarn prebuild && storybook build",
         | 
| 23 27 | 
             
                "generate:manifest": "wca src --outFile custom-elements.json",
         | 
| @@ -28,48 +32,56 @@ | |
| 28 32 | 
             
                "size": "size-limit",
         | 
| 29 33 | 
             
                "storybook": "yarn prebuild && storybook dev -p 6007",
         | 
| 30 34 | 
             
                "prebuild": "yarn build:deps && yarn generate:manifest",
         | 
| 31 | 
            -
                "test": " | 
| 35 | 
            +
                "test": "rm -rf test/lib && yarn prebuild && vite build --mode test && web-test-runner",
         | 
| 36 | 
            +
                "test:ci": "yarn test --config web-test-runner.ci.config.js"
         | 
| 32 37 | 
             
              },
         | 
| 33 38 | 
             
              "lint-staged": {
         | 
| 34 39 | 
             
                "**/*.{ts,tsx,js}": "eslint --fix --quiet",
         | 
| 35 40 | 
             
                "**/*.{md,json,yml}": "prettier --write"
         | 
| 36 41 | 
             
              },
         | 
| 37 42 | 
             
              "dependencies": {
         | 
| 43 | 
            +
                "@a11y/focus-trap": "^1.0.5",
         | 
| 38 44 | 
             
                "@lit/task": "^1.0.0",
         | 
| 39 | 
            -
                "@vouchfor/ | 
| 45 | 
            +
                "@vouchfor/canvas-video": "0.0.0-experiment.e7e20dd",
         | 
| 46 | 
            +
                "@vouchfor/media-player": "0.0.0-experiment.e7e20dd",
         | 
| 40 47 | 
             
                "uuid": "^9.0.1"
         | 
| 41 48 | 
             
              },
         | 
| 42 49 | 
             
              "peerDependencies": {
         | 
| 43 | 
            -
                "lit": "^3.1. | 
| 50 | 
            +
                "lit": "^3.1.2"
         | 
| 44 51 | 
             
              },
         | 
| 45 52 | 
             
              "devDependencies": {
         | 
| 46 53 | 
             
                "@esm-bundle/chai": "^4.3.4-fix.0",
         | 
| 47 | 
            -
                "@open-wc/testing": "^ | 
| 48 | 
            -
                "@storybook/addon-essentials": "^ | 
| 49 | 
            -
                "@storybook/addon-links": "^ | 
| 50 | 
            -
                "@storybook/blocks": "^ | 
| 51 | 
            -
                "@storybook/web-components": "^ | 
| 52 | 
            -
                "@storybook/web-components-vite": "^ | 
| 53 | 
            -
                "@ | 
| 54 | 
            -
                "@ | 
| 55 | 
            -
                "@ | 
| 56 | 
            -
                "@ | 
| 57 | 
            -
                "@ | 
| 58 | 
            -
                "@ | 
| 59 | 
            -
                "@web/ | 
| 60 | 
            -
                "@web/test-runner | 
| 61 | 
            -
                " | 
| 62 | 
            -
                " | 
| 63 | 
            -
                " | 
| 64 | 
            -
                " | 
| 65 | 
            -
                " | 
| 66 | 
            -
                " | 
| 54 | 
            +
                "@open-wc/testing": "^4.0.0",
         | 
| 55 | 
            +
                "@storybook/addon-essentials": "^8.0.2",
         | 
| 56 | 
            +
                "@storybook/addon-links": "^8.0.2",
         | 
| 57 | 
            +
                "@storybook/blocks": "^8.0.2",
         | 
| 58 | 
            +
                "@storybook/web-components": "^8.0.2",
         | 
| 59 | 
            +
                "@storybook/web-components-vite": "^8.0.2",
         | 
| 60 | 
            +
                "@svgr/core": "^8.1.0",
         | 
| 61 | 
            +
                "@types/flat": "^5.0.5",
         | 
| 62 | 
            +
                "@types/mocha": "^10.0.6",
         | 
| 63 | 
            +
                "@vouchfor/eslint-config": "^1.0.1",
         | 
| 64 | 
            +
                "@vouchfor/prettier-config": "^1.0.1",
         | 
| 65 | 
            +
                "@vouchfor/video-utils": "0.0.0-experiment.e7e20dd",
         | 
| 66 | 
            +
                "@web/dev-server-esbuild": "^1.0.2",
         | 
| 67 | 
            +
                "@web/test-runner": "^0.18.1",
         | 
| 68 | 
            +
                "@web/test-runner-browserstack": "^0.7.1",
         | 
| 69 | 
            +
                "@web/test-runner-mocha": "^0.9.0",
         | 
| 70 | 
            +
                "@web/test-runner-playwright": "^0.11.0",
         | 
| 71 | 
            +
                "glob": "^10.3.10",
         | 
| 72 | 
            +
                "lint-staged": "^15.2.2",
         | 
| 73 | 
            +
                "lit": "^3.1.2",
         | 
| 74 | 
            +
                "lodash": "^4.17.21",
         | 
| 67 75 | 
             
                "react": "^18.2.0",
         | 
| 68 76 | 
             
                "react-dom": "^18.2.0",
         | 
| 69 | 
            -
                " | 
| 70 | 
            -
                " | 
| 71 | 
            -
                " | 
| 72 | 
            -
                " | 
| 73 | 
            -
                " | 
| 77 | 
            +
                "rollup-plugin-tla": "^0.0.2",
         | 
| 78 | 
            +
                "sinon": "^17.0.1",
         | 
| 79 | 
            +
                "storybook": "^8.0.2",
         | 
| 80 | 
            +
                "svgson": "^5.3.1",
         | 
| 81 | 
            +
                "typescript": "^5.4.3",
         | 
| 82 | 
            +
                "vite": "^5.2.2",
         | 
| 83 | 
            +
                "vite-plugin-commonjs": "^0.10.1",
         | 
| 84 | 
            +
                "vite-plugin-dts": "^3.7.3",
         | 
| 85 | 
            +
                "web-component-analyzer": "^2.0.0"
         | 
| 74 86 | 
             
              }
         | 
| 75 87 | 
             
            }
         | 
| @@ -0,0 +1,91 @@ | |
| 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 | 
            +
                  <vouch-embed-dialog
         | 
| 39 | 
            +
                    env=${ifDefined(env)}
         | 
| 40 | 
            +
                    apiKey=${ifDefined(apiKey)}
         | 
| 41 | 
            +
                    vouchId=${ifDefined(vouchId)}
         | 
| 42 | 
            +
                    templateId=${ifDefined(templateId)}
         | 
| 43 | 
            +
                    .questions=${questions}
         | 
| 44 | 
            +
                    .controls=${controls}
         | 
| 45 | 
            +
                    ?autoplay=${autoplay}
         | 
| 46 | 
            +
                    preload=${ifDefined(preload)}
         | 
| 47 | 
            +
                    aspectRatio=${ifDefined(aspectRatio)}
         | 
| 48 | 
            +
                    @error=${console.log}
         | 
| 49 | 
            +
                  ></vouch-embed-dialog>
         | 
| 50 | 
            +
                </div>
         | 
| 51 | 
            +
              `;
         | 
| 52 | 
            +
            };
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            // More on how to set up stories at: https://storybook.js.org/docs/web-components/writing-stories/introduction
         | 
| 55 | 
            +
            const meta = {
         | 
| 56 | 
            +
              title: 'Dialog',
         | 
| 57 | 
            +
              tags: ['autodocs'],
         | 
| 58 | 
            +
              render: (args) => _DialogEmbed(args),
         | 
| 59 | 
            +
              component: 'vouch-embed-dialog'
         | 
| 60 | 
            +
            } satisfies Meta<DialogEmbedProps>;
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            type Story = StoryObj<DialogEmbedArgs>;
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            const Dialog: Story = {
         | 
| 65 | 
            +
              args: {
         | 
| 66 | 
            +
                env: 'dev',
         | 
| 67 | 
            +
                apiKey: 'TVik9uTMgE-PD25UTHIS6gyl0hMBWC7AT4dkpdlLBT4VIfDWZJrQiCk6Ak7m1',
         | 
| 68 | 
            +
                vouchId: '6JQEIPeStt',
         | 
| 69 | 
            +
                templateId: '357fc118-e179-4171-9446-ff2b8e9d1b29',
         | 
| 70 | 
            +
                questions: [],
         | 
| 71 | 
            +
                aspectRatio: 0,
         | 
| 72 | 
            +
                preload: 'none',
         | 
| 73 | 
            +
                autoplay: false
         | 
| 74 | 
            +
              },
         | 
| 75 | 
            +
              argTypes: {
         | 
| 76 | 
            +
                env: {
         | 
| 77 | 
            +
                  control: 'radio',
         | 
| 78 | 
            +
                  options: ['local', 'dev', 'staging', 'prod']
         | 
| 79 | 
            +
                },
         | 
| 80 | 
            +
                preload: {
         | 
| 81 | 
            +
                  control: 'radio',
         | 
| 82 | 
            +
                  options: ['auto', 'none']
         | 
| 83 | 
            +
                }
         | 
| 84 | 
            +
              },
         | 
| 85 | 
            +
              parameters: {
         | 
| 86 | 
            +
                layout: 'fullscreen'
         | 
| 87 | 
            +
              }
         | 
| 88 | 
            +
            };
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            export default meta;
         | 
| 91 | 
            +
            export { Dialog };
         | 
| @@ -0,0 +1,131 @@ | |
| 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: fixed;
         | 
| 25 | 
            +
                    display: flex;
         | 
| 26 | 
            +
                    inset: 0;
         | 
| 27 | 
            +
                    opacity: 1;
         | 
| 28 | 
            +
                    z-index: 2147483647;
         | 
| 29 | 
            +
                    align-items: center;
         | 
| 30 | 
            +
                    justify-content: center;
         | 
| 31 | 
            +
                    transition: opacity 100ms ease-in;
         | 
| 32 | 
            +
                  }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  .hidden {
         | 
| 35 | 
            +
                    opacity: 0;
         | 
| 36 | 
            +
                    pointer-events: none;
         | 
| 37 | 
            +
                  }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  .background {
         | 
| 40 | 
            +
                    position: absolute;
         | 
| 41 | 
            +
                    inset: 0;
         | 
| 42 | 
            +
                    opacity: var(--overlay-background-opacity);
         | 
| 43 | 
            +
                    background-color: var(--overlay-background-color);
         | 
| 44 | 
            +
                  }
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  focus-trap {
         | 
| 47 | 
            +
                    display: flex;
         | 
| 48 | 
            +
                    align-items: center;
         | 
| 49 | 
            +
                    justify-content: center;
         | 
| 50 | 
            +
                    margin: 40px;
         | 
| 51 | 
            +
                    width: var(--dialog-width);
         | 
| 52 | 
            +
                    height: var(--dialog-height);
         | 
| 53 | 
            +
                    max-width: calc(100% - 80px);
         | 
| 54 | 
            +
                    max-height: calc(100% - 80px);
         | 
| 55 | 
            +
                  }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  .video-frame {
         | 
| 58 | 
            +
                    position: relative;
         | 
| 59 | 
            +
                    display: flex;
         | 
| 60 | 
            +
                    align-items: center;
         | 
| 61 | 
            +
                    justify-content: center;
         | 
| 62 | 
            +
                    max-width: 100%;
         | 
| 63 | 
            +
                    max-height: 100%;
         | 
| 64 | 
            +
                  }
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  .video-frame.grow {
         | 
| 67 | 
            +
                    width: 100%;
         | 
| 68 | 
            +
                    height: 100%;
         | 
| 69 | 
            +
                  }
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  vmp-icon-button {
         | 
| 72 | 
            +
                    position: absolute;
         | 
| 73 | 
            +
                    top: 0;
         | 
| 74 | 
            +
                    right: 0;
         | 
| 75 | 
            +
                    margin: 10px;
         | 
| 76 | 
            +
                  }
         | 
| 77 | 
            +
                `
         | 
| 78 | 
            +
              ];
         | 
| 79 | 
            +
             | 
| 80 | 
            +
              @property({ type: Boolean }) open = false;
         | 
| 81 | 
            +
              @property({ type: Number }) aspectRatio: DialogEmbedProps['aspectRatio'] = 0;
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              render() {
         | 
| 84 | 
            +
                return html`
         | 
| 85 | 
            +
                  <div
         | 
| 86 | 
            +
                    class=${classMap({
         | 
| 87 | 
            +
                      container: true,
         | 
| 88 | 
            +
                      hidden: !this.open
         | 
| 89 | 
            +
                    })}
         | 
| 90 | 
            +
                  >
         | 
| 91 | 
            +
                    <div
         | 
| 92 | 
            +
                      class="background"
         | 
| 93 | 
            +
                      @click=${() => this.dispatchEvent(new CustomEvent('overlay:click', { bubbles: true, composed: true }))}
         | 
| 94 | 
            +
                    ></div>
         | 
| 95 | 
            +
                    <focus-trap>
         | 
| 96 | 
            +
                      <div
         | 
| 97 | 
            +
                        class=${classMap({
         | 
| 98 | 
            +
                          'video-frame': true,
         | 
| 99 | 
            +
                          grow: this.aspectRatio === 0
         | 
| 100 | 
            +
                        })}
         | 
| 101 | 
            +
                        style=${styleMap({
         | 
| 102 | 
            +
                          aspectRatio: this.aspectRatio
         | 
| 103 | 
            +
                        })}
         | 
| 104 | 
            +
                      >
         | 
| 105 | 
            +
                        <slot></slot>
         | 
| 106 | 
            +
                        <vmp-icon-button
         | 
| 107 | 
            +
                          icon="close"
         | 
| 108 | 
            +
                          rounded="full"
         | 
| 109 | 
            +
                          weight="heavy"
         | 
| 110 | 
            +
                          @click=${() => this.dispatchEvent(new CustomEvent('close:click', { bubbles: true, composed: true }))}
         | 
| 111 | 
            +
                        ></vmp-icon-button>
         | 
| 112 | 
            +
                      </div>
         | 
| 113 | 
            +
                    </focus-trap>
         | 
| 114 | 
            +
                  </div>
         | 
| 115 | 
            +
                `;
         | 
| 116 | 
            +
              }
         | 
| 117 | 
            +
            }
         | 
| 118 | 
            +
             | 
| 119 | 
            +
            declare global {
         | 
| 120 | 
            +
              interface HTMLElementTagNameMap {
         | 
| 121 | 
            +
                'vouch-embed-dialog-overlay': DialogOverlay;
         | 
| 122 | 
            +
              }
         | 
| 123 | 
            +
             | 
| 124 | 
            +
              namespace JSX {
         | 
| 125 | 
            +
                interface IntrinsicElements {
         | 
| 126 | 
            +
                  'vouch-embed-dialog-overlay': DialogOverlay;
         | 
| 127 | 
            +
                }
         | 
| 128 | 
            +
              }
         | 
| 129 | 
            +
            }
         | 
| 130 | 
            +
             | 
| 131 | 
            +
            export { DialogOverlay };
         | 
| @@ -0,0 +1,126 @@ | |
| 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 = ({ detail }: CustomEvent<string>) => {
         | 
| 33 | 
            +
                // Because we have to attach this listener to the document since this element is portalled outside of the button,
         | 
| 34 | 
            +
                // we also have to make sure that this player is actually the one we want to open and play by passing in an ID
         | 
| 35 | 
            +
                // from the button wrapper parent and checking against that same ID we pass as the event detail
         | 
| 36 | 
            +
                if (this.id === detail) {
         | 
| 37 | 
            +
                  this.open = !this.open;
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  if (this.open) {
         | 
| 40 | 
            +
                    if (!this.disableAutoplay && this._mediaPlayerRef?.value) {
         | 
| 41 | 
            +
                      this._mediaPlayerRef.value.muted = false;
         | 
| 42 | 
            +
                      this._mediaPlayerRef.value.play();
         | 
| 43 | 
            +
                    }
         | 
| 44 | 
            +
                  } else {
         | 
| 45 | 
            +
                    this._mediaPlayerRef?.value?.pause();
         | 
| 46 | 
            +
                  }
         | 
| 47 | 
            +
                }
         | 
| 48 | 
            +
              };
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              // We could do the same thing on close and check for the correct ID but it doesn't really matter
         | 
| 51 | 
            +
              private _handleClose = () => {
         | 
| 52 | 
            +
                this.open = false;
         | 
| 53 | 
            +
                this._mediaPlayerRef?.value?.pause();
         | 
| 54 | 
            +
              };
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              private _handleDocumentKeyUp = (e: KeyboardEvent) => {
         | 
| 57 | 
            +
                if (e.key === 'Escape') {
         | 
| 58 | 
            +
                  this._handleClose();
         | 
| 59 | 
            +
                }
         | 
| 60 | 
            +
              };
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              connectedCallback(): void {
         | 
| 63 | 
            +
                super.connectedCallback();
         | 
| 64 | 
            +
                document.addEventListener('dialogembed:click', this._handleToggle);
         | 
| 65 | 
            +
                document.addEventListener('keyup', this._handleDocumentKeyUp);
         | 
| 66 | 
            +
                document.addEventListener('close:click', this._handleClose);
         | 
| 67 | 
            +
                document.addEventListener('overlay:click', this._handleClose);
         | 
| 68 | 
            +
              }
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              disconnectedCallback(): void {
         | 
| 71 | 
            +
                super.disconnectedCallback();
         | 
| 72 | 
            +
                document.removeEventListener('dialogembed:click', this._handleToggle);
         | 
| 73 | 
            +
                document.removeEventListener('keyup', this._handleDocumentKeyUp);
         | 
| 74 | 
            +
                document.removeEventListener('close:click', this._handleClose);
         | 
| 75 | 
            +
                document.removeEventListener('overlay:click', this._handleClose);
         | 
| 76 | 
            +
              }
         | 
| 77 | 
            +
             | 
| 78 | 
            +
              protected createRenderRoot(): HTMLElement | DocumentFragment {
         | 
| 79 | 
            +
                // We must create a new node here because portalling into the same node (document.body) causes the second
         | 
| 80 | 
            +
                // element to overwrite the first for some reason (not behaviour really stated in the docs)
         | 
| 81 | 
            +
                // I am fairly certain this function is only run once as the default behaviour creates the open shadow root
         | 
| 82 | 
            +
                // and returns that shadow root in this function: https://lit.dev/docs/components/shadow-dom/#implementing-createrenderroot
         | 
| 83 | 
            +
                const newNode = document.createElement('div');
         | 
| 84 | 
            +
                document.body.appendChild(newNode);
         | 
| 85 | 
            +
                return newNode;
         | 
| 86 | 
            +
              }
         | 
| 87 | 
            +
             | 
| 88 | 
            +
              render() {
         | 
| 89 | 
            +
                return html`
         | 
| 90 | 
            +
                  <vouch-embed-dialog-overlay ?open=${this.open} aspectRatio=${this.aspectRatio}>
         | 
| 91 | 
            +
                    <vouch-embed-player
         | 
| 92 | 
            +
                      ${ref(this._mediaPlayerRef)}
         | 
| 93 | 
            +
                      style=${styleMap({
         | 
| 94 | 
            +
                        maxWidth: '100%',
         | 
| 95 | 
            +
                        maxHeight: '100%'
         | 
| 96 | 
            +
                      })}
         | 
| 97 | 
            +
                      ?autoplay=${false}
         | 
| 98 | 
            +
                      vouchId=${ifDefined(this.vouchId)}
         | 
| 99 | 
            +
                      templateId=${ifDefined(this.templateId)}
         | 
| 100 | 
            +
                      .questions=${this.questions}
         | 
| 101 | 
            +
                      .controls=${this.controls}
         | 
| 102 | 
            +
                      env=${ifDefined(this.env)}
         | 
| 103 | 
            +
                      apiKey=${ifDefined(this.apiKey)}
         | 
| 104 | 
            +
                      ?disableTracking=${this.disableTracking}
         | 
| 105 | 
            +
                      trackingSource=${ifDefined(this.trackingSource)}
         | 
| 106 | 
            +
                      preload=${ifDefined(this.preload)}
         | 
| 107 | 
            +
                      aspectRatio=${this.aspectRatio}
         | 
| 108 | 
            +
                    ></vouch-embed-player>
         | 
| 109 | 
            +
                  </vouch-embed-dialog-overlay>
         | 
| 110 | 
            +
                `;
         | 
| 111 | 
            +
              }
         | 
| 112 | 
            +
            }
         | 
| 113 | 
            +
             | 
| 114 | 
            +
            declare global {
         | 
| 115 | 
            +
              interface HTMLElementTagNameMap {
         | 
| 116 | 
            +
                'vouch-embed-dialog-portal': DialogPortal;
         | 
| 117 | 
            +
              }
         | 
| 118 | 
            +
             | 
| 119 | 
            +
              namespace JSX {
         | 
| 120 | 
            +
                interface IntrinsicElements {
         | 
| 121 | 
            +
                  'vouch-embed-dialog-portal': DialogPortal;
         | 
| 122 | 
            +
                }
         | 
| 123 | 
            +
              }
         | 
| 124 | 
            +
            }
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            export { DialogPortal };
         | 
| @@ -0,0 +1,97 @@ | |
| 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 | 
            +
            import { v4 as uuidv4 } from 'uuid';
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import type { PlayerEmbedProps } from '../PlayerEmbed';
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            import '../PlayerEmbed';
         | 
| 9 | 
            +
            import './DialogPortal';
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            type DialogEmbedProps = Omit<PlayerEmbedProps, 'data'> & {
         | 
| 12 | 
            +
              disableAutoplay?: boolean;
         | 
| 13 | 
            +
            };
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            @customElement('vouch-embed-dialog')
         | 
| 16 | 
            +
            class DialogEmbed extends LitElement {
         | 
| 17 | 
            +
              static styles = [
         | 
| 18 | 
            +
                css`
         | 
| 19 | 
            +
                  :host {
         | 
| 20 | 
            +
                    --vu-button-padding: 10px 20px;
         | 
| 21 | 
            +
                    --vu-button-background: #287179;
         | 
| 22 | 
            +
                    --vu-button-background-hover: #4faab2;
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    display: flex;
         | 
| 25 | 
            +
                    width: fit-content;
         | 
| 26 | 
            +
                    height: fit-content;
         | 
| 27 | 
            +
                  }
         | 
| 28 | 
            +
                `
         | 
| 29 | 
            +
              ];
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              @property({ type: String }) vouchId: DialogEmbedProps['vouchId'];
         | 
| 32 | 
            +
              @property({ type: String }) templateId: DialogEmbedProps['templateId'];
         | 
| 33 | 
            +
              @property({ type: Array }) questions: DialogEmbedProps['questions'];
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              @property({ type: String }) env: DialogEmbedProps['env'] = 'prod';
         | 
| 36 | 
            +
              @property({ type: String }) apiKey: DialogEmbedProps['apiKey'] = '';
         | 
| 37 | 
            +
              @property({ type: Boolean }) disableTracking: DialogEmbedProps['disableTracking'] = false;
         | 
| 38 | 
            +
              @property({ type: String }) trackingSource: DialogEmbedProps['trackingSource'] = 'embedded_player';
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              @property({ type: Array }) controls: DialogEmbedProps['controls'];
         | 
| 41 | 
            +
              @property({ type: String }) preload: DialogEmbedProps['preload'] = 'none';
         | 
| 42 | 
            +
              @property({ type: Boolean }) disableAutoplay: DialogEmbedProps['disableAutoplay'] = false;
         | 
| 43 | 
            +
              @property({ type: Number }) aspectRatio: DialogEmbedProps['aspectRatio'] = 0;
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              private _id = uuidv4();
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              private _handleRootClick = () => {
         | 
| 48 | 
            +
                this.dispatchEvent(new CustomEvent('dialogembed:click', { detail: this._id, bubbles: true, composed: true }));
         | 
| 49 | 
            +
              };
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              connectedCallback(): void {
         | 
| 52 | 
            +
                super.connectedCallback();
         | 
| 53 | 
            +
                this.addEventListener('click', this._handleRootClick);
         | 
| 54 | 
            +
              }
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              disconnectedCallback(): void {
         | 
| 57 | 
            +
                super.disconnectedCallback();
         | 
| 58 | 
            +
                this.removeEventListener('click', this._handleRootClick);
         | 
| 59 | 
            +
              }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              render() {
         | 
| 62 | 
            +
                return html`
         | 
| 63 | 
            +
                  <slot>
         | 
| 64 | 
            +
                    <vmp-button size="large">Play</vmp-button>
         | 
| 65 | 
            +
                  </slot>
         | 
| 66 | 
            +
                  <vouch-embed-dialog-portal
         | 
| 67 | 
            +
                    id=${this._id}
         | 
| 68 | 
            +
                    ?autoplay=${false}
         | 
| 69 | 
            +
                    vouchId=${ifDefined(this.vouchId)}
         | 
| 70 | 
            +
                    templateId=${ifDefined(this.templateId)}
         | 
| 71 | 
            +
                    .questions=${this.questions}
         | 
| 72 | 
            +
                    .controls=${this.controls}
         | 
| 73 | 
            +
                    env=${ifDefined(this.env)}
         | 
| 74 | 
            +
                    apiKey=${ifDefined(this.apiKey)}
         | 
| 75 | 
            +
                    ?disableTracking=${this.disableTracking}
         | 
| 76 | 
            +
                    trackingSource=${ifDefined(this.trackingSource)}
         | 
| 77 | 
            +
                    preload=${ifDefined(this.preload)}
         | 
| 78 | 
            +
                    aspectRatio=${this.aspectRatio}
         | 
| 79 | 
            +
                  ></vouch-embed-dialog-portal>
         | 
| 80 | 
            +
                `;
         | 
| 81 | 
            +
              }
         | 
| 82 | 
            +
            }
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            declare global {
         | 
| 85 | 
            +
              interface HTMLElementTagNameMap {
         | 
| 86 | 
            +
                'vouch-embed-dialog': DialogEmbed;
         | 
| 87 | 
            +
              }
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              namespace JSX {
         | 
| 90 | 
            +
                interface IntrinsicElements {
         | 
| 91 | 
            +
                  'vouch-embed-dialog': DialogEmbed;
         | 
| 92 | 
            +
                }
         | 
| 93 | 
            +
              }
         | 
| 94 | 
            +
            }
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            export { DialogEmbed };
         | 
| 97 | 
            +
            export type { DialogEmbedProps };
         | 
| @@ -1,48 +1,61 @@ | |
| 1 1 | 
             
            import { html } from 'lit';
         | 
| 2 2 | 
             
            import { ifDefined } from 'lit/directives/if-defined.js';
         | 
| 3 3 |  | 
| 4 | 
            -
            import type {  | 
| 4 | 
            +
            import type { PlayerEmbedProps } from '.';
         | 
| 5 5 | 
             
            import type { Meta, StoryObj } from '@storybook/web-components';
         | 
| 6 6 |  | 
| 7 | 
            -
            import ' | 
| 7 | 
            +
            import '.';
         | 
| 8 8 |  | 
| 9 | 
            -
            type  | 
| 9 | 
            +
            type PlayerEmbedArgs = PlayerEmbedProps & {
         | 
| 10 10 | 
             
              showVouch?: boolean;
         | 
| 11 11 | 
             
            };
         | 
| 12 12 |  | 
| 13 | 
            -
            const  | 
| 13 | 
            +
            const _PlayerEmbed = ({
         | 
| 14 | 
            +
              vouchId,
         | 
| 15 | 
            +
              templateId,
         | 
| 16 | 
            +
              questions,
         | 
| 17 | 
            +
              preload,
         | 
| 18 | 
            +
              autoplay,
         | 
| 19 | 
            +
              env,
         | 
| 20 | 
            +
              apiKey,
         | 
| 21 | 
            +
              controls,
         | 
| 22 | 
            +
              aspectRatio
         | 
| 23 | 
            +
            }: PlayerEmbedArgs) => {
         | 
| 14 24 | 
             
              return html`
         | 
| 15 25 | 
             
                <div style="height: 100vh">
         | 
| 16 | 
            -
                  <vouch-embed
         | 
| 26 | 
            +
                  <vouch-embed-player
         | 
| 17 27 | 
             
                    env=${ifDefined(env)}
         | 
| 18 28 | 
             
                    apiKey=${ifDefined(apiKey)}
         | 
| 19 29 | 
             
                    vouchId=${ifDefined(vouchId)}
         | 
| 20 30 | 
             
                    templateId=${ifDefined(templateId)}
         | 
| 31 | 
            +
                    .questions=${questions}
         | 
| 21 32 | 
             
                    .controls=${controls}
         | 
| 22 33 | 
             
                    ?autoplay=${autoplay}
         | 
| 23 34 | 
             
                    preload=${ifDefined(preload)}
         | 
| 24 35 | 
             
                    aspectRatio=${ifDefined(aspectRatio)}
         | 
| 25 | 
            -
             | 
| 36 | 
            +
                    @error=${console.log}
         | 
| 37 | 
            +
                  ></vouch-embed-player>
         | 
| 26 38 | 
             
                </div>
         | 
| 27 39 | 
             
              `;
         | 
| 28 40 | 
             
            };
         | 
| 29 41 |  | 
| 30 42 | 
             
            // More on how to set up stories at: https://storybook.js.org/docs/web-components/writing-stories/introduction
         | 
| 31 43 | 
             
            const meta = {
         | 
| 32 | 
            -
              title: ' | 
| 44 | 
            +
              title: 'Embeds',
         | 
| 33 45 | 
             
              tags: ['autodocs'],
         | 
| 34 | 
            -
              render: (args) =>  | 
| 35 | 
            -
              component: 'vouch-embed'
         | 
| 36 | 
            -
            } satisfies Meta< | 
| 46 | 
            +
              render: (args) => _PlayerEmbed(args),
         | 
| 47 | 
            +
              component: 'vouch-embed-player'
         | 
| 48 | 
            +
            } satisfies Meta<PlayerEmbedProps>;
         | 
| 37 49 |  | 
| 38 | 
            -
            type Story = StoryObj< | 
| 50 | 
            +
            type Story = StoryObj<PlayerEmbedArgs>;
         | 
| 39 51 |  | 
| 40 | 
            -
            const  | 
| 52 | 
            +
            const Player: Story = {
         | 
| 41 53 | 
             
              args: {
         | 
| 42 | 
            -
                env: ' | 
| 54 | 
            +
                env: 'dev',
         | 
| 43 55 | 
             
                apiKey: 'TVik9uTMgE-PD25UTHIS6gyl0hMBWC7AT4dkpdlLBT4VIfDWZJrQiCk6Ak7m1',
         | 
| 44 56 | 
             
                vouchId: '6JQEIPeStt',
         | 
| 45 57 | 
             
                templateId: '357fc118-e179-4171-9446-ff2b8e9d1b29',
         | 
| 58 | 
            +
                questions: [],
         | 
| 46 59 | 
             
                aspectRatio: 0,
         | 
| 47 60 | 
             
                preload: 'none',
         | 
| 48 61 | 
             
                autoplay: false
         | 
| @@ -63,4 +76,4 @@ const Embed: Story = { | |
| 63 76 | 
             
            };
         | 
| 64 77 |  | 
| 65 78 | 
             
            export default meta;
         | 
| 66 | 
            -
            export {  | 
| 79 | 
            +
            export { Player };
         | 
| @@ -1,27 +1,28 @@ | |
| 1 1 | 
             
            import { createRef, ref } from 'lit/directives/ref.js';
         | 
| 2 2 |  | 
| 3 | 
            -
            import type {  | 
| 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';
         | 
| 8 9 |  | 
| 9 | 
            -
            type  | 
| 10 | 
            +
            type PlayerEmbedHost = ReactiveControllerHost & PlayerEmbed;
         | 
| 10 11 |  | 
| 11 12 | 
             
            class EventForwardController implements ReactiveController {
         | 
| 12 | 
            -
              host:  | 
| 13 | 
            +
              host: PlayerEmbedHost;
         | 
| 13 14 |  | 
| 14 15 | 
             
              private _events: string[] = [];
         | 
| 15 16 | 
             
              private _cleanup: (() => void)[] = [];
         | 
| 16 17 | 
             
              private _forwardElementRef: Ref<HTMLElement> = createRef();
         | 
| 17 18 |  | 
| 18 | 
            -
              constructor(host:  | 
| 19 | 
            +
              constructor(host: PlayerEmbedHost, events: string[]) {
         | 
| 19 20 | 
             
                this.host = host;
         | 
| 20 21 | 
             
                this._events = events;
         | 
| 21 22 | 
             
                host.addController(this);
         | 
| 22 23 | 
             
              }
         | 
| 23 24 |  | 
| 24 | 
            -
              register() {
         | 
| 25 | 
            +
              register(): DirectiveResult {
         | 
| 25 26 | 
             
                return ref(this._forwardElementRef);
         | 
| 26 27 | 
             
              }
         | 
| 27 28 |  |