├── apps ├── dotlottie-playground │ ├── index.md │ ├── public │ │ ├── favicon.ico │ │ ├── toggle.lottie │ │ ├── aniki_hamster.lottie │ │ ├── theming_example.lottie │ │ └── interactivity_example.lottie │ ├── postcss.config.js │ ├── src │ │ ├── components │ │ │ ├── input-fields │ │ │ │ ├── index.tsx │ │ │ │ ├── input-number.tsx │ │ │ │ ├── input-boolean.tsx │ │ │ │ └── input-color-picker.tsx │ │ │ ├── file-tree │ │ │ │ ├── file-icon.tsx │ │ │ │ └── add-new.tsx │ │ │ ├── button.tsx │ │ │ ├── editable-title.tsx │ │ │ └── dropzone.tsx │ │ ├── vite-env.d.ts │ │ ├── assets │ │ │ ├── mock-state.json │ │ │ └── sample.json │ │ ├── store │ │ │ ├── hooks.ts │ │ │ ├── types.ts │ │ │ ├── index.ts │ │ │ ├── playground-slice.ts │ │ │ ├── state-slice.ts │ │ │ ├── theme-slice.ts │ │ │ └── animation-slice.ts │ │ ├── main.tsx │ │ ├── index.css │ │ └── utils.ts │ ├── vite.config.ts │ ├── .gitignore │ ├── tailwind.config.js │ ├── index.html │ ├── tsconfig.json │ ├── package.json │ └── README.md ├── player-component-react │ ├── src │ │ ├── vite-env.d.ts │ │ ├── main.tsx │ │ ├── App.tsx │ │ ├── App.css │ │ └── index.css │ ├── vite.config.ts │ ├── tsconfig.node.json │ ├── .gitignore │ ├── .eslintrc.cjs │ ├── index.html │ ├── tsconfig.json │ ├── package.json │ └── public │ │ └── vite.svg ├── player-component-vue │ ├── src │ │ ├── vite-env.d.ts │ │ ├── main.ts │ │ ├── assets │ │ │ └── vue.svg │ │ ├── App.vue │ │ ├── components │ │ │ └── HelloWorld.vue │ │ └── style.css │ ├── .vscode │ │ └── extensions.json │ ├── tsconfig.node.json │ ├── .gitignore │ ├── index.html │ ├── vite.config.ts │ ├── package.json │ ├── tsconfig.json │ ├── public │ │ └── vite.svg │ └── README.md ├── player-component-web │ ├── src │ │ ├── vite-env.d.ts │ │ ├── typescript.svg │ │ └── style.css │ ├── public │ │ ├── car.lottie │ │ ├── onAfter.lottie │ │ ├── pigeon.lottie │ │ ├── repeat.lottie │ │ ├── toggle.lottie │ │ ├── onComplete.lottie │ │ ├── big-dotlottie.lottie │ │ ├── loadInQueue.lottie │ │ ├── stateSegments.lottie │ │ ├── mouseEnterLeave.lottie │ │ ├── segmentsOnHover.lottie │ │ ├── animationOnHover.lottie │ │ ├── lighthouseOnScroll.lottie │ │ ├── test_02_with_states.lottie │ │ └── lf_interactivity_page.lottie │ ├── .gitignore │ ├── package.json │ ├── index.html │ └── tsconfig.json ├── player-component-nuxt │ ├── .npmrc │ ├── server │ │ └── tsconfig.json │ ├── public │ │ └── favicon.ico │ ├── tsconfig.json │ ├── plugins │ │ └── dotlottie.client.js │ ├── nuxt.config.ts │ ├── .gitignore │ ├── package.json │ ├── app.vue │ └── README.md ├── react-player-test │ ├── src │ │ ├── vite-env.d.ts │ │ ├── main.tsx │ │ └── App.tsx │ ├── public │ │ ├── audio.lottie │ │ ├── test.lottie │ │ ├── amazing.lottie │ │ └── vite.svg │ ├── tsconfig.node.json │ ├── vite.config.ts │ ├── .gitignore │ ├── index.html │ ├── tsconfig.json │ └── package.json ├── react-player-next │ ├── src │ │ └── app │ │ │ ├── favicon.ico │ │ │ ├── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── player.tsx │ │ │ └── globals.css │ ├── next.config.js │ ├── postcss.config.js │ ├── .gitignore │ ├── tailwind.config.js │ ├── public │ │ ├── vercel.svg │ │ └── next.svg │ ├── package.json │ ├── tsconfig.json │ └── README.md └── player-component-next │ ├── next.config.js │ ├── postcss.config.js │ ├── public │ ├── monster.lottie │ ├── vercel.svg │ └── next.svg │ ├── src │ └── app │ │ ├── favicon.ico │ │ ├── layout.tsx │ │ ├── globals.css │ │ ├── player.tsx │ │ └── page.tsx │ ├── .gitignore │ ├── tailwind.config.js │ ├── package.json │ ├── tsconfig.json │ └── README.md ├── tsconfig.json ├── pnpm-workspace.yaml ├── packages ├── player-component │ ├── tsconfig.json │ ├── tests │ │ ├── test.lottie │ │ ├── cat_and_texting.lottie │ │ ├── multi-animation.lottie │ │ ├── sample_dotlottie.lottie │ │ └── exploding_pigeon_and_lighthouse.lottie │ ├── cypress │ │ ├── public │ │ │ ├── audio.lottie │ │ │ ├── fake.lottie │ │ │ ├── cool-dog.lottie │ │ │ ├── bounce_wifi.lottie │ │ │ ├── big-dotlottie.lottie │ │ │ ├── puppy_sword_cartoon.lottie │ │ │ ├── lf_interactivity_page.lottie │ │ │ └── speed_3_bounce_and_reverse_playback.lottie │ │ ├── fixtures │ │ │ └── example.json │ │ ├── tsconfig.json │ │ ├── support │ │ │ ├── component.ts │ │ │ └── component-index.html │ │ └── component │ │ │ ├── no-audio.cy.ts │ │ │ ├── background.cy.ts │ │ │ ├── speed.cy.ts │ │ │ ├── intermission.cy.ts │ │ │ ├── audio.cy.ts │ │ │ ├── a11y.cy.ts │ │ │ ├── loop.cy.ts │ │ │ ├── mode.cy.ts │ │ │ ├── get-versions.cy.ts │ │ │ ├── autoplay.cy.ts │ │ │ ├── interactivity │ │ │ ├── on-scroll-zero.cy.ts │ │ │ ├── on-show-zero.cy.ts │ │ │ ├── state-toggle.cy.ts │ │ │ ├── play-on-hold-pause.cy.ts │ │ │ └── exploding-pigeon.cy.ts │ │ │ ├── light.cy.ts │ │ │ ├── props.cy.ts │ │ │ ├── hover.cy.ts │ │ │ └── direction.cy.ts │ ├── src │ │ └── fonts │ │ │ └── Karla-Regular.woff │ ├── types │ │ └── lottie-web.d.ts │ ├── vite.config.ts │ ├── tsup.config.js │ ├── tsconfig.build.json │ ├── cypress.config.ts │ └── package.json ├── react-player │ ├── src │ │ ├── providers │ │ │ ├── index.ts │ │ │ └── dotlottie.tsx │ │ ├── hooks │ │ │ ├── index.ts │ │ │ ├── use-sync-external-store.ts │ │ │ ├── use-select-dotlottie-state.ts │ │ │ ├── use-dotlottie-state.ts │ │ │ └── use-dotlottie-player.ts │ │ ├── fonts │ │ │ └── Karla-Regular.woff │ │ ├── index.ts │ │ ├── icons │ │ │ ├── play.tsx │ │ │ ├── chevron-left.tsx │ │ │ ├── chevron-right.tsx │ │ │ ├── next.tsx │ │ │ ├── check-mark.tsx │ │ │ ├── previous.tsx │ │ │ ├── pause.tsx │ │ │ ├── ellipsis-vertical.tsx │ │ │ ├── loop.tsx │ │ │ ├── loop-on.tsx │ │ │ └── loop-off.tsx │ │ └── popover │ │ │ ├── sub-item.tsx │ │ │ └── item.tsx │ ├── cypress │ │ ├── public │ │ │ ├── fake.lottie │ │ │ ├── audio.lottie │ │ │ ├── cool-dog.lottie │ │ │ ├── bounce_wifi.lottie │ │ │ ├── puppy_sword_cartoon.lottie │ │ │ ├── lf_interactivity_page.lottie │ │ │ └── speed_3_bounce_and_reverse_playback.lottie │ │ ├── tsconfig.json │ │ ├── fixtures │ │ │ └── example.json │ │ ├── support │ │ │ ├── component-index.html │ │ │ ├── component.ts │ │ │ ├── xss-injector-check.tsx │ │ │ └── player-state-wrapper.tsx │ │ └── component │ │ │ ├── no-audio.cy.tsx │ │ │ ├── a11y.cy.tsx │ │ │ ├── worker.cy.tsx │ │ │ ├── interactivity │ │ │ ├── on-scroll-zero.cy.tsx │ │ │ └── on-show-zero.cy.tsx │ │ │ ├── light.cy.tsx │ │ │ ├── props.cy.tsx │ │ │ ├── background.cy.tsx │ │ │ └── speed.cy.tsx │ ├── vite.config.ts │ ├── tsup.config.js │ ├── tsconfig.json │ ├── cypress.config.ts │ └── package.json └── common │ ├── src │ ├── index.ts │ ├── store.ts │ ├── dotlottie-audio.ts │ ├── state │ │ └── xstate-machine.ts │ └── dotlottie-state-machine-loader.ts │ ├── tsconfig.json │ ├── tsup.config.js │ └── package.json ├── .husky ├── pre-commit └── commit-msg ├── prettier.config.cjs ├── commitlint.config.cjs ├── .prettierrc.js ├── .size-limit.cjs ├── .gitattributes ├── lint-staged.config.js ├── typedoc.json ├── .changeset └── config.json ├── .remarkignore ├── tsconfig.dev.json ├── tsconfig.build.json ├── scripts └── remove-dev.mjs ├── .editorconfig ├── .prettierignore ├── turbo.json ├── .gitignore ├── .eslintignore ├── .github └── PULL_REQUEST_TEMPLATE.md ├── LICENSE └── .eslintrc.js /apps/dotlottie-playground/index.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.dev.json" 3 | } 4 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | - 'apps/*' 4 | -------------------------------------------------------------------------------- /apps/player-component-react/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /apps/player-component-vue/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /apps/player-component-web/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/player-component/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json" 3 | } 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm lint-staged -------------------------------------------------------------------------------- /apps/player-component-nuxt/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm commitlint --edit -------------------------------------------------------------------------------- /apps/player-component-nuxt/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /apps/player-component-vue/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-player/src/providers/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | export * from './dotlottie'; 6 | -------------------------------------------------------------------------------- /apps/react-player-test/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | /// 6 | -------------------------------------------------------------------------------- /packages/react-player/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | export * from './use-dotlottie-state'; 6 | -------------------------------------------------------------------------------- /prettier.config.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Design Barn Inc. 3 | */ 4 | 5 | module.exports = require('@lottiefiles/prettier-config'); 6 | -------------------------------------------------------------------------------- /apps/player-component-web/public/car.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/car.lottie -------------------------------------------------------------------------------- /apps/react-player-next/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/react-player-next/src/app/favicon.ico -------------------------------------------------------------------------------- /apps/react-player-test/public/audio.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/react-player-test/public/audio.lottie -------------------------------------------------------------------------------- /apps/react-player-test/public/test.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/react-player-test/public/test.lottie -------------------------------------------------------------------------------- /packages/player-component/tests/test.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/tests/test.lottie -------------------------------------------------------------------------------- /apps/dotlottie-playground/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/dotlottie-playground/public/favicon.ico -------------------------------------------------------------------------------- /apps/player-component-next/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | module.exports = nextConfig; 5 | -------------------------------------------------------------------------------- /apps/player-component-next/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /apps/player-component-nuxt/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-nuxt/public/favicon.ico -------------------------------------------------------------------------------- /apps/player-component-nuxt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /apps/react-player-test/public/amazing.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/react-player-test/public/amazing.lottie -------------------------------------------------------------------------------- /commitlint.config.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | module.exports = { extends: ['@commitlint/config-conventional'] }; 6 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: true, 3 | trailingComma: 'all', 4 | singleQuote: true, 5 | printWidth: 120, 6 | tabWidth: 2, 7 | }; 8 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/public/toggle.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/dotlottie-playground/public/toggle.lottie -------------------------------------------------------------------------------- /apps/player-component-next/public/monster.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-next/public/monster.lottie -------------------------------------------------------------------------------- /apps/player-component-next/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-next/src/app/favicon.ico -------------------------------------------------------------------------------- /apps/player-component-web/public/onAfter.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/onAfter.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/pigeon.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/pigeon.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/repeat.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/repeat.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/toggle.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/toggle.lottie -------------------------------------------------------------------------------- /packages/common/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | export * from './dotlottie-player'; 6 | export * from './utils'; 7 | -------------------------------------------------------------------------------- /packages/react-player/cypress/public/fake.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/react-player/cypress/public/fake.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/onComplete.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/onComplete.lottie -------------------------------------------------------------------------------- /packages/react-player/cypress/public/audio.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/react-player/cypress/public/audio.lottie -------------------------------------------------------------------------------- /packages/react-player/src/fonts/Karla-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/react-player/src/fonts/Karla-Regular.woff -------------------------------------------------------------------------------- /apps/dotlottie-playground/public/aniki_hamster.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/dotlottie-playground/public/aniki_hamster.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/big-dotlottie.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/big-dotlottie.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/loadInQueue.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/loadInQueue.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/stateSegments.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/stateSegments.lottie -------------------------------------------------------------------------------- /packages/player-component/cypress/public/audio.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/cypress/public/audio.lottie -------------------------------------------------------------------------------- /packages/player-component/cypress/public/fake.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/cypress/public/fake.lottie -------------------------------------------------------------------------------- /packages/react-player/cypress/public/cool-dog.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/react-player/cypress/public/cool-dog.lottie -------------------------------------------------------------------------------- /apps/dotlottie-playground/public/theming_example.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/dotlottie-playground/public/theming_example.lottie -------------------------------------------------------------------------------- /apps/player-component-vue/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import './style.css'; 3 | import App from './App.vue'; 4 | 5 | createApp(App).mount('#app'); 6 | -------------------------------------------------------------------------------- /apps/player-component-web/public/mouseEnterLeave.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/mouseEnterLeave.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/segmentsOnHover.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/segmentsOnHover.lottie -------------------------------------------------------------------------------- /packages/player-component/src/fonts/Karla-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/src/fonts/Karla-Regular.woff -------------------------------------------------------------------------------- /packages/player-component/tests/cat_and_texting.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/tests/cat_and_texting.lottie -------------------------------------------------------------------------------- /packages/player-component/tests/multi-animation.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/tests/multi-animation.lottie -------------------------------------------------------------------------------- /packages/player-component/tests/sample_dotlottie.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/tests/sample_dotlottie.lottie -------------------------------------------------------------------------------- /packages/react-player/cypress/public/bounce_wifi.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/react-player/cypress/public/bounce_wifi.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/animationOnHover.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/animationOnHover.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/lighthouseOnScroll.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/lighthouseOnScroll.lottie -------------------------------------------------------------------------------- /packages/player-component/cypress/public/cool-dog.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/cypress/public/cool-dog.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/test_02_with_states.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/test_02_with_states.lottie -------------------------------------------------------------------------------- /packages/player-component/cypress/public/bounce_wifi.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/cypress/public/bounce_wifi.lottie -------------------------------------------------------------------------------- /apps/dotlottie-playground/public/interactivity_example.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/dotlottie-playground/public/interactivity_example.lottie -------------------------------------------------------------------------------- /apps/player-component-web/public/lf_interactivity_page.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/apps/player-component-web/public/lf_interactivity_page.lottie -------------------------------------------------------------------------------- /packages/player-component/cypress/public/big-dotlottie.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/cypress/public/big-dotlottie.lottie -------------------------------------------------------------------------------- /packages/react-player/cypress/public/puppy_sword_cartoon.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/react-player/cypress/public/puppy_sword_cartoon.lottie -------------------------------------------------------------------------------- /packages/react-player/cypress/public/lf_interactivity_page.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/react-player/cypress/public/lf_interactivity_page.lottie -------------------------------------------------------------------------------- /packages/player-component/cypress/public/puppy_sword_cartoon.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/cypress/public/puppy_sword_cartoon.lottie -------------------------------------------------------------------------------- /packages/player-component/cypress/public/lf_interactivity_page.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/cypress/public/lf_interactivity_page.lottie -------------------------------------------------------------------------------- /packages/player-component/tests/exploding_pigeon_and_lighthouse.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/tests/exploding_pigeon_and_lighthouse.lottie -------------------------------------------------------------------------------- /apps/react-player-next/next.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | /** @type {import('next').NextConfig} */ 6 | const nextConfig = {}; 7 | 8 | module.exports = nextConfig; 9 | -------------------------------------------------------------------------------- /apps/react-player-next/postcss.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | module.exports = { 6 | plugins: { 7 | tailwindcss: {}, 8 | autoprefixer: {}, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/react-player/cypress/public/speed_3_bounce_and_reverse_playback.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/react-player/cypress/public/speed_3_bounce_and_reverse_playback.lottie -------------------------------------------------------------------------------- /packages/react-player/cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "types": ["cypress", "cypress-axe"] 6 | }, 7 | "include": ["."] 8 | } 9 | -------------------------------------------------------------------------------- /packages/player-component/cypress/public/speed_3_bounce_and_reverse_playback.lottie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotlottie/player-component/HEAD/packages/player-component/cypress/public/speed_3_bounce_and_reverse_playback.lottie -------------------------------------------------------------------------------- /packages/player-component/types/lottie-web.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | declare module 'lottie-web/build/player/lottie_svg'; 6 | declare module 'lottie-web/build/player/lottie_worker'; 7 | -------------------------------------------------------------------------------- /packages/react-player/cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /apps/player-component-nuxt/plugins/dotlottie.client.js: -------------------------------------------------------------------------------- 1 | import * as DotLottiePlayer from '@dotlottie/player-component'; 2 | 3 | export default defineNuxtPlugin((nuxtApp) => { 4 | nuxtApp.vueApp.use(DotLottiePlayer); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/player-component/cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /apps/player-component-react/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }); 8 | -------------------------------------------------------------------------------- /packages/player-component/cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "types": ["cypress", "cypress-axe", "cypress-ct-lit"] 6 | }, 7 | "include": ["."] 8 | } 9 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/postcss.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | const config = { 6 | plugins: { 7 | tailwindcss: {}, 8 | autoprefixer: {}, 9 | }, 10 | }; 11 | 12 | export default config; 13 | -------------------------------------------------------------------------------- /apps/react-player-test/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/react-player/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | export * from '@dotlottie/common'; 6 | export * from './react-player'; 7 | export * from './controls'; 8 | export * from './providers'; 9 | export * from './hooks'; 10 | -------------------------------------------------------------------------------- /.size-limit.cjs: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | path: 'packages/common/dist/index.js', 4 | }, 5 | { 6 | path: 'packages/player-component/dist/dotlottie-player.mjs', 7 | }, 8 | // { 9 | // path: 'packages/react-player/dist/index.js', 10 | // }, 11 | ]; 12 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/components/input-fields/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | export { InputBoolean } from './input-boolean'; 6 | export { InputNumber } from './input-number'; 7 | export { InputSelect, type InputSelectOption } from './input-select'; 8 | -------------------------------------------------------------------------------- /apps/react-player-test/vite.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { defineConfig } from 'vite'; 6 | import react from '@vitejs/plugin-react'; 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig({ 10 | plugins: [react()], 11 | }); 12 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | /// 6 | 7 | interface ImportMetaEnv { 8 | readonly BASE_URL: string; 9 | } 10 | 11 | interface ImportMeta { 12 | readonly env: ImportMetaEnv; 13 | } 14 | -------------------------------------------------------------------------------- /apps/player-component-vue/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/player-component-react/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/player-component-nuxt/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://nuxt.com/docs/api/configuration/nuxt-config 2 | export default defineNuxtConfig({ 3 | devtools: { enabled: true }, 4 | vue: { 5 | compilerOptions: { 6 | isCustomElement: (tag) => ['dotlottie-player'].includes(tag), 7 | }, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # AUTO-DETECT 2 | # Handle line endings automatically for files detected as 3 | # text and leave all files detected as binary untouched. 4 | # This will handle all files NOT defined below. 5 | * text eol=lf 6 | *.json linguist-language=JSON-with-Comments 7 | 8 | *.lottie binary 9 | *.zip binary 10 | -------------------------------------------------------------------------------- /lint-staged.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | module.exports = { 6 | '*.{js,jsx,ts,tsx}': 'cross-env NODE_ENV=production eslint --cache --fix', 7 | '*.md': 'remark --output --silently-ignore --', 8 | '*': 'prettier --ignore-unknown --loglevel=warn --no-editorconfig --write', 9 | }; 10 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "out": "docs", 3 | "mode": "modules", 4 | "theme": "default", 5 | "includeVersion": true, 6 | "ignoreCompilerErrors": false, 7 | "includeDeclarations": false, 8 | "excludeExternals": true, 9 | "excludePrivate": true, 10 | "excludeNotExported": true, 11 | "stripInternal": true 12 | } 13 | -------------------------------------------------------------------------------- /apps/player-component-nuxt/.gitignore: -------------------------------------------------------------------------------- 1 | # Nuxt dev/build outputs 2 | .output 3 | .nuxt 4 | .nitro 5 | .cache 6 | dist 7 | 8 | # Node dependencies 9 | node_modules 10 | 11 | # Logs 12 | logs 13 | *.log 14 | 15 | # Misc 16 | .DS_Store 17 | .fleet 18 | .idea 19 | 20 | # Local env files 21 | .env 22 | .env.* 23 | !.env.example 24 | -------------------------------------------------------------------------------- /packages/react-player/vite.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import react from '@vitejs/plugin-react'; 6 | import { defineConfig } from 'vite'; 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig({ 10 | plugins: [react()], 11 | publicDir: './cypress/public', 12 | }); 13 | -------------------------------------------------------------------------------- /apps/player-component-react/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App.tsx'; 4 | import './index.css'; 5 | 6 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 7 | 8 | 9 | , 10 | ); 11 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.1.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /apps/react-player-next/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import Player from './player'; 6 | 7 | export default function Home(): JSX.Element { 8 | return ( 9 |
10 | 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/assets/mock-state.json: -------------------------------------------------------------------------------- 1 | { 2 | "descriptor": { 3 | "id": "", 4 | "initial": "initialState" 5 | }, 6 | "states": { 7 | "initialState": { 8 | "animationId": "animationId", 9 | "playbackSettings": { 10 | "autoplay": true, 11 | "loop": true 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/vite.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import react from '@vitejs/plugin-react'; 6 | import { defineConfig } from 'vite'; 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig(({ mode }) => ({ 10 | plugins: [react()], 11 | base: mode === 'development' ? '/' : '/player-component/', 12 | })); 13 | -------------------------------------------------------------------------------- /.remarkignore: -------------------------------------------------------------------------------- 1 | # Build artifacts 2 | build/ 3 | dist/ 4 | artifacts/ 5 | 6 | # Changelog 7 | CHANGELOG.md 8 | 9 | # IDE related 10 | .idea/ 11 | .history/ 12 | 13 | # Package management 14 | node_modules/ 15 | .yarn/ 16 | 17 | # Testing 18 | __fixtures__ 19 | __snapshots__ 20 | coverage/ 21 | reports 22 | 23 | # Temporary or local data 24 | temp/ 25 | tmp/ 26 | 27 | # ADRs 28 | docs/decisions -------------------------------------------------------------------------------- /apps/dotlottie-playground/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/store/hooks.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { type TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; 6 | 7 | import type { RootState, AppDispatch } from '.'; 8 | 9 | export const useAppDispatch: () => AppDispatch = useDispatch; 10 | export const useAppSelector: TypedUseSelectorHook = useSelector; 11 | -------------------------------------------------------------------------------- /apps/player-component-react/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /apps/player-component-vue/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /apps/player-component-web/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/player-component/vite.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import legacy from '@vitejs/plugin-legacy'; 6 | import { defineConfig } from 'vite'; 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig({ 10 | publicDir: './cypress/public', 11 | plugins: [ 12 | legacy({ 13 | targets: ['defaults'], 14 | }), 15 | ], 16 | }); 17 | -------------------------------------------------------------------------------- /packages/react-player/cypress/support/component-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Components App 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | /** @type {import('tailwindcss').Config} */ 6 | 7 | const config = { 8 | content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], 9 | theme: { 10 | extend: { 11 | colors: { 12 | dark: '#1e1e1e', 13 | }, 14 | }, 15 | }, 16 | plugins: [], 17 | }; 18 | 19 | export default config; 20 | -------------------------------------------------------------------------------- /apps/react-player-test/src/main.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React from 'react'; 6 | import ReactDOM from 'react-dom/client'; 7 | 8 | import App from './App'; 9 | 10 | import '@dotlottie/react-player/dist/index.css'; 11 | 12 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 13 | 14 | 15 | , 16 | ); 17 | -------------------------------------------------------------------------------- /packages/player-component/cypress/support/component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import 'cypress-axe'; 6 | 7 | import { mount } from 'cypress-ct-lit'; 8 | 9 | import '../../dist/dotlottie-player'; 10 | 11 | declare global { 12 | namespace Cypress { 13 | interface Chainable { 14 | mount: typeof mount; 15 | } 16 | } 17 | } 18 | 19 | Cypress.Commands.add('mount', mount); 20 | -------------------------------------------------------------------------------- /apps/react-player-test/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | cypress/screenshots 27 | cypress/videos 28 | -------------------------------------------------------------------------------- /apps/player-component-react/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { browser: true, es2020: true }, 3 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended'], 4 | parser: '@typescript-eslint/parser', 5 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 6 | plugins: ['react-refresh'], 7 | rules: { 8 | 'react-refresh/only-export-components': 'warn', 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /apps/player-component-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Vue + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/react-player-test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Lottie Player test 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/player-component-react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DotLottie Playground 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/player-component-vue/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [ 7 | vue({ 8 | template: { 9 | compilerOptions: { 10 | // treat all tags with a dash as custom elements 11 | isCustomElement: (tag) => tag.includes('-'), 12 | }, 13 | }, 14 | }), 15 | ], 16 | }); 17 | -------------------------------------------------------------------------------- /apps/player-component-web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "build-project": "tsc && vite build", 8 | "run-dev": "vite", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@dotlottie/player-component": "workspace:^" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.2", 16 | "vite": "^4.3.9" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/player-component-web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/react-player/cypress/support/component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | // 6 | import 'cypress-axe'; 7 | import { mount } from 'cypress/react'; 8 | 9 | import '../../src/index.css'; 10 | 11 | declare global { 12 | // eslint-disable-next-line @typescript-eslint/no-namespace 13 | namespace Cypress { 14 | interface Chainable { 15 | mount: typeof mount; 16 | } 17 | } 18 | } 19 | 20 | Cypress.Commands.add('mount', mount); 21 | -------------------------------------------------------------------------------- /apps/player-component-next/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './globals.css'; 2 | import { Inter } from 'next/font/google'; 3 | 4 | const inter = Inter({ subsets: ['latin'] }); 5 | 6 | export const metadata = { 7 | title: 'Create Next App', 8 | description: 'Generated by create next app', 9 | }; 10 | 11 | export default function RootLayout({ children }: { children: React.ReactNode }) { 12 | return ( 13 | 14 | {children} 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /apps/player-component-nuxt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-app", 3 | "private": true, 4 | "scripts": { 5 | "build-project": "nuxt build", 6 | "run-dev": "nuxt dev", 7 | "generate": "nuxt generate", 8 | "postinstall": "nuxt prepare", 9 | "preview": "nuxt preview" 10 | }, 11 | "dependencies": { 12 | "@dotlottie/player-component": "workspace:^" 13 | }, 14 | "devDependencies": { 15 | "@nuxt/devtools": "latest", 16 | "@types/node": "^18", 17 | "nuxt": "^3.6.1" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/player-component-vue/src/assets/vue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/components/file-tree/file-icon.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React from 'react'; 6 | import { BsFiletypeJson } from 'react-icons/bs'; 7 | 8 | import type { SupportedFileTypes } from '.'; 9 | 10 | export const FileIcon = ({ type }: { type: SupportedFileTypes }): JSX.Element => { 11 | // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition 12 | if (type !== 'json') { 13 | return <>; 14 | } 15 | 16 | return ; 17 | }; 18 | -------------------------------------------------------------------------------- /apps/player-component-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "build-project": "vue-tsc && vite build", 8 | "run-dev": "vite", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@dotlottie/player-component": "workspace:^", 13 | "vue": "^3.2.47" 14 | }, 15 | "devDependencies": { 16 | "@vitejs/plugin-vue": "^4.2.3", 17 | "typescript": "^5.0.2", 18 | "vite": "^4.3.9", 19 | "vue-tsc": "^1.4.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/react-player-next/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /apps/player-component-next/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /apps/player-component-next/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | './src/pages/**/*.{js,ts,jsx,tsx,mdx}', 5 | './src/components/**/*.{js,ts,jsx,tsx,mdx}', 6 | './src/app/**/*.{js,ts,jsx,tsx,mdx}', 7 | ], 8 | theme: { 9 | extend: { 10 | backgroundImage: { 11 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 12 | 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 13 | }, 14 | }, 15 | }, 16 | plugins: [], 17 | }; 18 | -------------------------------------------------------------------------------- /apps/player-component-nuxt/app.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 24 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/no-audio.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { html } from 'lit'; 6 | 7 | describe('No audio', () => { 8 | it('Howler should not be present in the window if theres audio inside the animation', () => { 9 | cy.mount( 10 | html` 11 | 12 | 13 | `, 14 | ); 15 | 16 | cy.window().should('not.have.property', 'Howler'); 17 | }); 18 | }) 19 | -------------------------------------------------------------------------------- /apps/player-component-react/src/App.tsx: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import '@dotlottie/player-component'; 3 | 4 | declare global { 5 | namespace JSX { 6 | interface IntrinsicElements { 7 | 'dotlottie-player': any; 8 | } 9 | } 10 | } 11 | 12 | function App() { 13 | return ( 14 | <> 15 | 22 | 23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /apps/react-player-next/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | // import './globals.css' 6 | import { Inter } from 'next/font/google'; 7 | 8 | const inter = Inter({ subsets: ['latin'] }); 9 | 10 | export const metadata = { 11 | title: 'Create Next App', 12 | description: 'Generated by create next app', 13 | }; 14 | 15 | export default function RootLayout({ children }: { children: React.ReactNode }): JSX.Element { 16 | return ( 17 | 18 | {children} 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /packages/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@lottiefiles/tsconfig", 3 | "compilerOptions": { 4 | "target": "ESNext", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "jsx": "react", 10 | "module": "ESNext", 11 | "sourceMap": true, 12 | "outDir": "dist", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "allowSyntheticDefaultImports": true 16 | }, 17 | "include": ["src/**/*.ts", "types/*.ts"], 18 | "exclude": ["node_modules", "dist"] 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | // Extend from the org config 3 | "extends": "@lottiefiles/tsconfig", 4 | 5 | "compilerOptions": { 6 | // Target ES version 7 | "target": "ESNext", 8 | 9 | // Target module system 10 | "module": "ESNext" 11 | }, 12 | 13 | "exclude": [ 14 | // Exclude node_modules 15 | "**/node_modules", 16 | 17 | // Exclude non-code test resources 18 | "**/__fixtures__", 19 | "**/__snapshots__", 20 | "**/coverage", 21 | 22 | // Exclude builds 23 | "**/build", 24 | "**/dist", 25 | "**/artifacts", 26 | 27 | "**/tmp" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /apps/react-player-next/src/app/player.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | 'use client'; 6 | 7 | import { Controls, DotLottiePlayer } from '@dotlottie/react-player'; 8 | import '@dotlottie/react-player/dist/index.css'; 9 | 10 | export default function Player(): JSX.Element { 11 | return ( 12 |
13 | 19 | 20 | 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /apps/react-player-next/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb)); 22 | } 23 | -------------------------------------------------------------------------------- /apps/react-player-next/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | /** @type {import('tailwindcss').Config} */ 6 | module.exports = { 7 | content: [ 8 | './src/pages/**/*.{js,ts,jsx,tsx,mdx}', 9 | './src/components/**/*.{js,ts,jsx,tsx,mdx}', 10 | './src/app/**/*.{js,ts,jsx,tsx,mdx}', 11 | ], 12 | theme: { 13 | extend: { 14 | backgroundImage: { 15 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 16 | 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 17 | }, 18 | }, 19 | }, 20 | plugins: [], 21 | }; 22 | -------------------------------------------------------------------------------- /apps/player-component-next/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb)); 22 | } 23 | -------------------------------------------------------------------------------- /apps/player-component-next/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/react-player-next/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/react-player/tsup.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { defineConfig } from 'tsup'; 6 | 7 | export default defineConfig({ 8 | bundle: true, 9 | clean: true, 10 | dts: { 11 | entry: './src/index.ts', 12 | resolve: true, 13 | }, 14 | minify: true, 15 | sourcemap: true, 16 | treeshake: true, 17 | splitting: true, 18 | metafile: false, 19 | format: ['esm'], 20 | tsconfig: 'tsconfig.json', 21 | outDir: 'dist', 22 | platform: 'browser', 23 | target: ['esnext', 'chrome79'], 24 | entry: ['./src/*.ts', './src/*.tsx', './src/*.css'], 25 | external: ['react'], 26 | }); 27 | -------------------------------------------------------------------------------- /apps/player-component-web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "node", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "include": ["src"] 23 | } 24 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src/**/*.ts"], 20 | "exclude": ["node_modules", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/player-component/tsup.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { defineConfig } from 'tsup'; 6 | 7 | import pkg from './package.json'; 8 | 9 | export default defineConfig((options) => ({ 10 | bundle: true, 11 | clean: true, 12 | dts: true, 13 | sourcemap: true, 14 | minify: !options.watch, 15 | treeshake: true, 16 | metafile: false, 17 | format: ['esm', 'umd'], 18 | tsconfig: 'tsconfig.json', 19 | outDir: 'dist', 20 | platform: 'browser', 21 | target: ['esnext', 'chrome79'], 22 | entry: ['./src/*.ts'], 23 | globalName: 'DotLottiePlayer', 24 | noExternal: Object.keys(pkg.dependencies ?? []), 25 | })); 26 | -------------------------------------------------------------------------------- /apps/react-player-test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /apps/player-component-next/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "build-project": "next build", 7 | "run-dev": "next dev", 8 | "lint": "next lint", 9 | "start": "next start" 10 | }, 11 | "dependencies": { 12 | "@dotlottie/player-component": "workspace:^", 13 | "@types/node": "20.3.3", 14 | "@types/react": "18.2.14", 15 | "@types/react-dom": "18.2.6", 16 | "autoprefixer": "10.4.14", 17 | "next": "13.4.7", 18 | "postcss": "8.4.31", 19 | "react": "18.2.0", 20 | "react-dom": "18.2.0", 21 | "tailwindcss": "3.3.2", 22 | "typescript": "5.1.6" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/react-player-next/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-player-next", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "run-dev": "next dev", 7 | "build:x": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@dotlottie/react-player": "workspace:^", 13 | "@types/node": "20.3.3", 14 | "@types/react": "18.2.14", 15 | "@types/react-dom": "18.2.6", 16 | "autoprefixer": "10.4.14", 17 | "next": "13.4.8", 18 | "postcss": "8.4.31", 19 | "react": "18.2.0", 20 | "react-dom": "18.2.0", 21 | "tailwindcss": "3.3.2", 22 | "typescript": "5.1.6" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/play.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const Play = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /packages/react-player/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react" 18 | }, 19 | "include": ["src/**/*.ts", "src/**/*.tsx"], 20 | "exclude": ["node_modules", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/store/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | export const SUPPORTED_FILE_TYPES = ['json'] as const; 6 | export const EDITOR_ACTIONS = [ 7 | 'themes_add', 8 | 'themes_remove', 9 | 'states_add', 10 | 'states_remove', 11 | 'animations_add', 12 | 'animations_remove', 13 | ] as const; 14 | 15 | export type SupportedFileTypes = typeof SUPPORTED_FILE_TYPES[number]; 16 | export type EditorActions = typeof EDITOR_ACTIONS[number]; 17 | 18 | export interface SupportedFile { 19 | name: string; 20 | type: SupportedFileTypes; 21 | } 22 | 23 | export interface EditorAction { 24 | payload: unknown; 25 | type: EditorActions; 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "lib": ["esnext.array", "esnext", "es2017", "dom"], 7 | "declaration": true, 8 | "declarationMap": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "strict": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitThis": true, 18 | "experimentalDecorators": true 19 | }, 20 | "include": ["src/**/*.ts", "types/*.ts"], 21 | "exclude": ["node_modules", "dist"] 22 | } 23 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/main.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React from 'react'; 6 | import ReactDOM from 'react-dom/client'; 7 | import { Provider } from 'react-redux'; 8 | 9 | import App from './app'; 10 | import { DotLottieProvider } from './hooks/use-dotlottie'; 11 | import store from './store'; 12 | import './index.css'; 13 | 14 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion 15 | ReactDOM.createRoot(document.getElementById('root')!).render( 16 | 17 | 18 | 19 | 20 | 21 | 22 | , 23 | ); 24 | -------------------------------------------------------------------------------- /apps/react-player-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-player-test", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "build:prod": "tsc && vite build", 8 | "run-dev": "vite", 9 | "lint": "tsc --noEmit", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0", 15 | "@dotlottie/react-player": "workspace:^", 16 | "react-use": "^17.4.0", 17 | "wouter": "^2.10.1" 18 | }, 19 | "devDependencies": { 20 | "@types/react": "^18.0.28", 21 | "@types/react-dom": "^18.0.11", 22 | "typescript": "^4.9.3", 23 | "vite": "^4.2.0", 24 | "@vitejs/plugin-react": "^4.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apps/player-component-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /packages/common/src/store.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { Signal } from '@preact/signals-core'; 6 | import { signal } from '@preact/signals-core'; 7 | 8 | export class Store { 9 | protected _state: Signal; 10 | 11 | protected _prevState: T; 12 | 13 | public constructor(initialState: T) { 14 | this._prevState = initialState; 15 | this._state = signal(initialState); 16 | } 17 | 18 | public setState(state: T): void { 19 | this._prevState = this._state.value; 20 | this._state.value = state; 21 | } 22 | 23 | public subscribe(callback: (value: T, prevValue: T) => void): () => void { 24 | return this._state.subscribe((val) => callback(val, this._prevState)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/react-player/src/providers/dotlottie.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { DotLottieCommonPlayer } from '@dotlottie/common'; 6 | import { createError } from '@dotlottie/common'; 7 | import { createContext, useContext } from 'react'; 8 | 9 | const DotLottieContext = createContext(null); 10 | 11 | export const DotLottieProvider = DotLottieContext.Provider; 12 | 13 | export const useDotLottieContext = (): DotLottieCommonPlayer | null => { 14 | const dotLottiePlayer = useContext(DotLottieContext); 15 | 16 | if (typeof dotLottiePlayer === 'undefined') { 17 | throw createError('useDotLottieContext must be used within a DotLottieProvider'); 18 | } 19 | 20 | return dotLottiePlayer; 21 | }; 22 | -------------------------------------------------------------------------------- /scripts/remove-dev.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { $, chalk, globby, fs } from 'zx'; 6 | 7 | // Files to remove 8 | const files = [ 9 | '**/*.tsbuildinfo', 10 | '**/dist', 11 | '**/.next', 12 | '**/coverage', 13 | '**/.pnpm-debug.log', 14 | '**/.turbo', 15 | '**/.eslintcache', 16 | '**/.jestcache', 17 | ]; 18 | 19 | // Hide command outputs 20 | $.verbose = false; 21 | 22 | console.log(chalk.green('Cleaning up development artifacts...')); 23 | 24 | const entries = await globby([...files, '!**/node_modules'], { 25 | onlyFiles: false, 26 | }); 27 | 28 | await Promise.all( 29 | entries.map(async (entry) => { 30 | await fs.rm(entry, { recursive: true }); 31 | console.log(chalk.white(` ☑ ${entry}`)); 32 | }), 33 | ); 34 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/store/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { configureStore } from '@reduxjs/toolkit'; 6 | 7 | import animationSlice from './animation-slice'; 8 | import editorSlice from './editor-slice'; 9 | import playgroundSlice from './playground-slice'; 10 | import stateSlice from './state-slice'; 11 | import themeSlice from './theme-slice'; 12 | 13 | const store = configureStore({ 14 | reducer: { 15 | animations: animationSlice, 16 | themes: themeSlice, 17 | states: stateSlice, 18 | editor: editorSlice, 19 | playground: playgroundSlice, 20 | }, 21 | }); 22 | 23 | export type RootState = ReturnType; 24 | 25 | export type AppDispatch = typeof store.dispatch; 26 | 27 | export default store; 28 | -------------------------------------------------------------------------------- /apps/player-component-next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "paths": { 23 | "@/*": ["./src/*"] 24 | } 25 | }, 26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /apps/react-player-next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "paths": { 23 | "@/*": ["./src/*"] 24 | } 25 | }, 26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /apps/player-component-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "preserve", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /packages/react-player/cypress/component/no-audio.cy.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { Controls } from '../../src/controls'; 6 | import { DotLottiePlayer } from '../../src/react-player'; 7 | import { PlayerStateWrapper } from '../support/player-state-wrapper'; 8 | 9 | describe('No audio', () => { 10 | it('Howler should not be present in the window if theres no audio inside the animation', () => { 11 | cy.mount( 12 | 13 | 14 | 15 | 16 | , 17 | , 18 | ); 19 | 20 | cy.window().should('not.have.property', 'Howler'); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/background.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { html } from 'lit'; 6 | 7 | describe('Background', () => { 8 | it('should able set background color', () => { 9 | cy.mount( 10 | html` 11 | 20 | 21 | `, 22 | ); 23 | 24 | cy.get('[data-testid="testPlayer"]') 25 | .shadow() 26 | .find('.animation') 27 | .should('have.css', 'background-color') 28 | .and('eq', 'rgb(26, 189, 70)'); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | # General rules 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | 8 | # JSON 9 | [*.json] 10 | indent_size = 2 11 | indent_style = space 12 | tab_width = 2 13 | 14 | # HTML 15 | [*.html] 16 | indent_size = 4 17 | indent_style = tab 18 | tab_width = 4 19 | 20 | # Markdown 21 | [*.md] 22 | insert_final_newline = false 23 | trim_trailing_whitespace = false 24 | 25 | # Patch diffs 26 | [*.patch] 27 | insert_final_newline = false 28 | trim_trailing_whitespace = false 29 | 30 | # Typescript 31 | [*.{ts,tsx}] 32 | indent_size = 2 33 | indent_style = space 34 | insert_final_newline = true 35 | max_line_length = 120 36 | quote_type = single 37 | tab_width = 2 38 | 39 | # Yaml 40 | [*.{yaml,yml}] 41 | indent_size = 2 42 | indent_style = space 43 | insert_final_newline = true 44 | tab_width = 2 45 | -------------------------------------------------------------------------------- /apps/player-component-react/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | -------------------------------------------------------------------------------- /packages/player-component/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | // "extends": "../../tsconfig.dev.json", 3 | 4 | "compilerOptions": { 5 | "target": "ESNext", 6 | "module": "ESNext", 7 | "moduleResolution": "node", 8 | "lib": ["ESNext", "DOM"], 9 | "declaration": true, 10 | "declarationMap": true, 11 | "sourceMap": true, 12 | "inlineSources": true, 13 | "strict": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "noImplicitAny": true, 19 | "noImplicitThis": true, 20 | "experimentalDecorators": true, 21 | "allowSyntheticDefaultImports": true, 22 | "resolveJsonModule": true 23 | }, 24 | "include": ["src/**/*.ts", "types/*.ts"], 25 | "exclude": ["node_modules", "dist"] 26 | } 27 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | 2 | # Build artifacts 3 | build/ 4 | dist/ 5 | artifacts/ 6 | 7 | # Changelog 8 | CHANGELOG.md 9 | 10 | # IDE related 11 | .idea/ 12 | .history/ 13 | 14 | # Markdown (let remark handle it) 15 | *.md 16 | 17 | # Package management 18 | node_modules/ 19 | .yarn/ 20 | .pnp.* 21 | pnpm-lock.yaml 22 | 23 | # Testing 24 | __fixtures__ 25 | __snapshots__ 26 | coverage/ 27 | reports/ 28 | 29 | # Temporary or local data 30 | temp/ 31 | tmp/ 32 | 33 | # Clinic profiling 34 | .clinic 35 | 36 | # Renderer releases 37 | releases/ 38 | 39 | packages/player-component/tests/ 40 | packages/player-component/cypress/ 41 | 42 | .changeset/*.json 43 | 44 | /apps/react-player-test/ 45 | /apps/player-component-next/ 46 | /apps/player-component-nuxt/ 47 | /apps/player-component-react/ 48 | /apps/player-component-vue/ 49 | /apps/player-component-web -------------------------------------------------------------------------------- /packages/react-player/src/hooks/use-sync-external-store.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { useState, useEffect } from 'react'; 6 | 7 | type SubscribeFunction = (onStateChange: () => void) => () => void; 8 | type GetSnapshotFunction = () => T; 9 | 10 | export const useSyncExternalStore = ( 11 | subscribe: SubscribeFunction, 12 | getSnapshot: GetSnapshotFunction, 13 | getDefaultSnapshot: GetSnapshotFunction, 14 | ): T => { 15 | const [state, setState] = useState(() => { 16 | return getDefaultSnapshot(); 17 | }); 18 | 19 | useEffect(() => { 20 | const unsubscribe = subscribe(() => { 21 | const newState = getSnapshot(); 22 | 23 | setState(newState); 24 | }); 25 | 26 | return () => { 27 | unsubscribe(); 28 | }; 29 | }, [subscribe]); 30 | 31 | return state as T; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/chevron-left.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const ChevronLeft = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/chevron-right.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const ChevronRight = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/store/playground-slice.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { createSlice } from '@reduxjs/toolkit'; 6 | 7 | interface PlaygroundSlice { 8 | playerUrl: string | undefined; 9 | workingFileName: string; 10 | } 11 | 12 | const initialState: PlaygroundSlice = { 13 | playerUrl: undefined, 14 | workingFileName: '_.lottie', 15 | }; 16 | 17 | export const playgroundSlice = createSlice({ 18 | name: 'playground', 19 | initialState, 20 | reducers: { 21 | setPlayerUrl: (state, action) => { 22 | state.playerUrl = action.payload; 23 | }, 24 | setWorkingFileName: (state, action) => { 25 | state.workingFileName = action.payload; 26 | }, 27 | }, 28 | }); 29 | 30 | export const { setPlayerUrl, setWorkingFileName } = playgroundSlice.actions; 31 | 32 | export default playgroundSlice.reducer; 33 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "baseBranch": "origin/main", 4 | "globalDependencies": ["tsconfig.build.json", "tsconfig.dev.json", "tsconfig.json"], 5 | "pipeline": { 6 | "build": { 7 | "dependsOn": ["^build"], 8 | "outputs": ["dist/**"] 9 | }, 10 | "test": { 11 | "cache": false, 12 | "dependsOn": ["build"], 13 | "outputs": [] 14 | }, 15 | "test:coverage": { 16 | "cache": false, 17 | "dependsOn": ["build"], 18 | "outputs": ["coverage/**"] 19 | }, 20 | "type-check": { 21 | "cache": false 22 | }, 23 | "lint": { 24 | "cache": false, 25 | "outputs": [] 26 | }, 27 | "update-releases": { 28 | "dependsOn": ["^update-releases"] 29 | }, 30 | "clean": {}, 31 | "dev": { 32 | "cache": false 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build artifacts 2 | build/ 3 | dist/ 4 | artifacts/ 5 | .next/ 6 | *.tgz 7 | 8 | # DotEnv local files 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | 15 | # Linting 16 | .eslintcache 17 | 18 | # IDE related 19 | .idea/ 20 | .history/ 21 | 22 | # Logs 23 | *.log 24 | .*.log 25 | 26 | # NPM/Yarn 27 | node_modules/ 28 | .yarn/ 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | 33 | # Monorepo management 34 | .turbo 35 | 36 | # Operating system 37 | .DS_Store 38 | *.bak 39 | *.swp 40 | *~ 41 | 42 | # Pnpm cache 43 | .pnpm-store/ 44 | 45 | # Temporary or local data 46 | temp/ 47 | tmp/ 48 | .tmp 49 | 50 | # Testing 51 | .jestcache 52 | coverage/ 53 | reports/ 54 | __diff_output__/ 55 | 56 | # TsDoc 57 | tsdoc-metadata.json 58 | 59 | # Typescript 60 | *.tsbuildinfo 61 | 62 | 63 | .nyc_output 64 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/next.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const Next = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/check-mark.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const CheckMark = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /packages/react-player/cypress.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { defineConfig } from 'cypress'; 6 | 7 | export default defineConfig({ 8 | video: false, 9 | screenshotOnRunFailure: false, 10 | component: { 11 | setupNodeEvents(on) { 12 | on('task', { 13 | log(message) { 14 | // eslint-disable-next-line no-console 15 | console.log(message); 16 | 17 | return null; 18 | }, 19 | table(message) { 20 | // eslint-disable-next-line node/no-unsupported-features/node-builtins, no-console 21 | console.table(message); 22 | 23 | return null; 24 | }, 25 | }); 26 | }, 27 | retries: { 28 | runMode: 3, 29 | openMode: 0, 30 | }, 31 | video: false, 32 | devServer: { 33 | framework: 'react', 34 | bundler: 'vite', 35 | }, 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/store/state-slice.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { createSlice } from '@reduxjs/toolkit'; 6 | 7 | import { type SupportedFile } from './types'; 8 | 9 | interface StateSlice { 10 | list: SupportedFile[]; 11 | } 12 | 13 | const initialState: StateSlice = { 14 | list: [], 15 | }; 16 | 17 | export const stateSlice = createSlice({ 18 | name: 'states', 19 | initialState, 20 | reducers: { 21 | setStates: (state, action) => { 22 | state.list = action.payload; 23 | }, 24 | addState: (state, action) => { 25 | state.list.push(action.payload); 26 | }, 27 | removeState: (state, action) => { 28 | state.list = state.list.filter((item) => item.name !== action.payload); 29 | }, 30 | }, 31 | }); 32 | 33 | export const { addState, removeState, setStates } = stateSlice.actions; 34 | 35 | export default stateSlice.reducer; 36 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/store/theme-slice.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { createSlice } from '@reduxjs/toolkit'; 6 | 7 | import { type SupportedFile } from './types'; 8 | 9 | interface ThemeSlice { 10 | list: SupportedFile[]; 11 | } 12 | 13 | const initialState: ThemeSlice = { 14 | list: [], 15 | }; 16 | 17 | export const themeSlice = createSlice({ 18 | name: 'themes', 19 | initialState, 20 | reducers: { 21 | setThemes: (state, action) => { 22 | state.list = action.payload; 23 | }, 24 | addTheme: (state, action) => { 25 | state.list.push(action.payload); 26 | }, 27 | removeTheme: (state, action) => { 28 | state.list = state.list.filter((item) => item.name !== action.payload); 29 | }, 30 | }, 31 | }); 32 | 33 | export const { addTheme, removeTheme, setThemes } = themeSlice.actions; 34 | 35 | export default themeSlice.reducer; 36 | -------------------------------------------------------------------------------- /packages/player-component/cypress.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { defineConfig } from 'cypress'; 6 | 7 | export default defineConfig({ 8 | video: false, 9 | screenshotOnRunFailure: false, 10 | component: { 11 | setupNodeEvents(on) { 12 | on('task', { 13 | log(message) { 14 | console.log(message); 15 | 16 | return null; 17 | }, 18 | table(message) { 19 | // eslint-disable-next-line node/no-unsupported-features/node-builtins 20 | console.table(message); 21 | 22 | return null; 23 | }, 24 | }); 25 | }, 26 | retries: { 27 | runMode: 3, 28 | openMode: 0, 29 | }, 30 | devServer: { 31 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 32 | framework: 'cypress-ct-lit' as any, 33 | bundler: 'vite', 34 | }, 35 | }, 36 | }); 37 | -------------------------------------------------------------------------------- /apps/player-component-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | 25 | 39 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/previous.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const Previous = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /packages/common/tsup.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import fs from 'node:fs/promises'; 6 | 7 | import { defineConfig } from 'tsup'; 8 | 9 | import pkg from './package.json'; 10 | 11 | export default defineConfig((options) => ({ 12 | bundle: true, 13 | clean: true, 14 | dts: true, 15 | sourcemap: true, 16 | minify: !options.watch, 17 | treeshake: true, 18 | splitting: true, 19 | metafile: false, 20 | format: ['esm'], 21 | tsconfig: 'tsconfig.json', 22 | outDir: 'dist', 23 | platform: 'browser', 24 | target: ['esnext', 'chrome79'], 25 | entry: ['./src/*.ts'], 26 | noExternal: Object.keys(pkg.dependencies ?? []), 27 | onSuccess: () => { 28 | if (options.watch) { 29 | const time = new Date(); 30 | 31 | fs.utimes('../react-player/src/index.ts', time, time); 32 | fs.utimes('../player-component/src/dotlottie-player.ts', time, time); 33 | } 34 | }, 35 | })); 36 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/pause.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const Pause = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 15 | 19 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /apps/player-component-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react", 3 | "version": "0.0.0", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "build-project": "tsc && vite build", 8 | "run-dev": "vite", 9 | "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@dotlottie/player-component": "workspace:^", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0" 16 | }, 17 | "devDependencies": { 18 | "@types/react": "^18.2.9", 19 | "@types/react-dom": "^18.0.11", 20 | "@typescript-eslint/eslint-plugin": "^5.59.0", 21 | "@typescript-eslint/parser": "^5.59.0", 22 | "@vitejs/plugin-react": "^4.0.0", 23 | "eslint": "^8.38.0", 24 | "eslint-plugin-react-hooks": "^4.6.0", 25 | "eslint-plugin-react-refresh": "^0.3.4", 26 | "typescript": "^5.0.2", 27 | "vite": "^4.3.9" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/common/src/dotlottie-audio.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { Howl } from 'howler'; 6 | 7 | export interface DotLottieAudioOptions { 8 | src: string[]; 9 | } 10 | 11 | export class DotLottieAudio { 12 | private readonly _howl: Howl; 13 | 14 | public constructor({ src }: DotLottieAudioOptions) { 15 | this._howl = new Howl({ 16 | src, 17 | }); 18 | } 19 | 20 | public play(): number { 21 | return this._howl.play(); 22 | } 23 | 24 | public pause(): Howl { 25 | return this._howl.pause(); 26 | } 27 | 28 | public playing(): boolean { 29 | return this._howl.playing(); 30 | } 31 | 32 | public rate(): number { 33 | return this._howl.rate(); 34 | } 35 | 36 | public seek(): number { 37 | return this._howl.seek(); 38 | } 39 | 40 | public setVolume(): number { 41 | return this._howl.volume(); 42 | } 43 | 44 | public unload(): void { 45 | this._howl.unload(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /apps/player-component-vue/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 32 | 33 | 38 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/speed.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { html } from 'lit'; 6 | 7 | describe('Speed', () => { 8 | it('default speed should be 1', () => { 9 | cy.mount( 10 | html` 11 | 12 | 13 | `, 14 | ); 15 | 16 | cy.get('[name="speed"]').should('have.value', 1); 17 | }); 18 | 19 | it('should be able to change speed to 2', () => { 20 | cy.mount( 21 | html` 22 | 31 | 32 | `, 33 | ); 34 | 35 | cy.get('[name="speed"]').should('have.value', 2); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Build outputs 2 | build/ 3 | dist/ 4 | artifacts/ 5 | 6 | # Changelog 7 | .changeset/config.json 8 | CHANGELOG.md 9 | 10 | # IDE related 11 | .idea/ 12 | .history/ 13 | 14 | # Package management 15 | node_modules/ 16 | .yarn/ 17 | .pnp.* 18 | 19 | # Testing 20 | coverage/ 21 | __snapshots__ 22 | __fixtures__ 23 | 24 | # Temporary or local data 25 | temp/ 26 | tmp/ 27 | 28 | # Clinic profiling 29 | .clinic 30 | 31 | # Misc files to ignore 32 | .eslintrc.cjs 33 | 34 | # NextJS 35 | .next/ 36 | next-env.d.ts 37 | 38 | # Exclude from ignore 39 | !.github 40 | !.vscode, 41 | 42 | # Ignore renderer releases 43 | releases/ 44 | 45 | sample-projects/ 46 | 47 | packages/player-component/cypress/ 48 | packages/player-component/dist/ 49 | packages/common/dist/ 50 | packages/react-player/cypress/ 51 | /apps/react-player-test/ 52 | /apps/player-component-next/ 53 | /apps/player-component-nuxt/ 54 | /apps/player-component-react/ 55 | /apps/player-component-vue/ 56 | /apps/player-component-web/ 57 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/components/button.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React, { type HTMLAttributes } from 'react'; 6 | 7 | import { cn } from '../utils'; 8 | 9 | interface ButtonProps extends HTMLAttributes { 10 | color?: 'green' | 'red' | 'blue'; 11 | disabled?: boolean; 12 | onClick?: () => void | Promise; 13 | } 14 | 15 | export const Button = React.forwardRef( 16 | ({ children, color = 'blue', ...props }, ref) => { 17 | return ( 18 | 30 | ); 31 | }, 32 | ); 33 | -------------------------------------------------------------------------------- /packages/react-player/src/popover/sub-item.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React, { useCallback } from 'react'; 6 | 7 | import { CheckMark } from '../icons/check-mark'; 8 | 9 | interface SubItemProps extends React.HTMLAttributes { 10 | onSelectItem?: (value: string) => void; 11 | selected: boolean; 12 | value: string; 13 | } 14 | 15 | export const SubItem: React.FC = ({ onSelectItem, selected = false, value, ...props }) => { 16 | const onClickItem = useCallback(() => { 17 | onSelectItem?.(value); 18 | }, [onSelectItem, value]); 19 | 20 | return ( 21 | 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/assets/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "descriptor": { 3 | "id": "exploding_pigeon", 4 | "initial": "running" 5 | }, 6 | "states": { 7 | "running": { 8 | "animationId": "pigeon", 9 | "statePlaybackSettings": { 10 | "autoplay": true, 11 | "loop": true, 12 | "direction": 1, 13 | "segments": "bird" 14 | }, 15 | "onClick": { 16 | "state": "exploding" 17 | } 18 | }, 19 | "exploding": { 20 | "statePlaybackSettings": { 21 | "autoplay": true, 22 | "loop": false, 23 | "direction": 1, 24 | "segments": "explosion" 25 | }, 26 | "onComplete": { 27 | "state": "feathers" 28 | } 29 | }, 30 | "feathers": { 31 | "statePlaybackSettings": { 32 | "autoplay": true, 33 | "loop": false, 34 | "direction": 1, 35 | "segments": "feathers" 36 | }, 37 | "onComplete": { 38 | "state": "running" 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/components/input-fields/input-number.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React, { type ChangeEventHandler, useCallback } from 'react'; 6 | 7 | interface InputNumberProps { 8 | label: string; 9 | onChange?: (value: number) => void; 10 | value?: number; 11 | } 12 | 13 | export const InputNumber: React.FC = ({ label, onChange, value }) => { 14 | const handleChange = useCallback>( 15 | (event) => { 16 | onChange?.(Number(event.target.value)); 17 | }, 18 | [onChange], 19 | ); 20 | 21 | return ( 22 |
23 | {label} 24 | 31 |
32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/store/animation-slice.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { createSlice } from '@reduxjs/toolkit'; 6 | 7 | import { type SupportedFile } from './types'; 8 | 9 | interface AnimationSlice { 10 | list: SupportedFile[]; 11 | } 12 | 13 | const initialState: AnimationSlice = { 14 | list: [], 15 | }; 16 | 17 | export const animationSlice = createSlice({ 18 | name: 'animations', 19 | initialState, 20 | reducers: { 21 | setAnimations: (state, action) => { 22 | state.list = action.payload; 23 | }, 24 | addAnimation: (state, action) => { 25 | state.list.push(action.payload); 26 | }, 27 | removeAnimation: (state, action) => { 28 | state.list = state.list.filter((item) => item.name !== action.payload); 29 | }, 30 | }, 31 | }); 32 | 33 | // Action creators are generated for each case reducer function 34 | export const { addAnimation, removeAnimation, setAnimations } = animationSlice.actions; 35 | 36 | export default animationSlice.reducer; 37 | -------------------------------------------------------------------------------- /apps/player-component-next/src/app/player.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import '@dotlottie/player-component'; 4 | import { PlaybackOptions } from '@dotlottie/player-component'; 5 | 6 | export interface PlayerProps { 7 | src: string; 8 | playbackOptions?: PlaybackOptions; 9 | controls?: boolean; 10 | light?: boolean; 11 | } 12 | 13 | export default function Player(props: PlayerProps) { 14 | return ( 15 |
16 | 29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /packages/common/src/state/xstate-machine.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { DotLottieStatePlaybackSettings } from '@dotlottie/dotlottie-js'; 6 | 7 | export const EVENT_MAP = { 8 | click: 'onClick', 9 | mouseenter: 'onMouseEnter', 10 | mouseleave: 'onMouseLeave', 11 | complete: 'onComplete', 12 | after: 'onAfter', 13 | enter: 'onEnter', 14 | show: 'onShow', 15 | }; 16 | 17 | export const DotLottieStateEvents = Object.values(EVENT_MAP); 18 | 19 | export const XStateEvents = Object.keys(EVENT_MAP); 20 | 21 | export type EventMap = typeof EVENT_MAP; 22 | 23 | export interface XStateTargetEvent { 24 | target: string; 25 | } 26 | 27 | export interface XState { 28 | after: Record; 29 | entry?: () => void; 30 | exit?: () => void; 31 | meta: DotLottieStatePlaybackSettings; 32 | on: Record; 33 | } 34 | 35 | export interface XStateMachine { 36 | id: string; 37 | initial: string; 38 | states: Record; 39 | } 40 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/intermission.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { html } from 'lit'; 6 | 7 | describe('Intermission', () => { 8 | it('intermission should default to `0`', () => { 9 | cy.mount( 10 | html` 11 | 12 | 13 | `, 14 | ); 15 | 16 | cy.get('[name="intermission"]').should('have.value', 0); 17 | }); 18 | 19 | it('should be able to set intermission', () => { 20 | cy.mount( 21 | html` 22 | 31 | 32 | `, 33 | ); 34 | 35 | cy.get('[name="intermission"]').should('have.value', 1000); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/audio.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { html } from 'lit'; 6 | 7 | describe('Audio', () => { 8 | it('Howler should be present in the window if theres audio inside the animation', () => { 9 | cy.mount( 10 | html` 11 | 12 | 13 | `, 14 | ); 15 | 16 | cy.window().its('Howler').its('_howls').should('have.length', 3); 17 | cy.window().should('have.property', 'Howl'); 18 | }); 19 | 20 | it('Howler should not have any howls loaded if the active animation is changed', () => { 21 | cy.mount( 22 | html` 23 | 24 | 25 | `, 26 | ); 27 | 28 | cy.window().its('Howler').its('_howls').should('have.length', 0); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 8 | 9 | ## Type of change 10 | 11 | 16 | 17 | - [ ] Patch: Bug (non-breaking change which fixes an issue) 18 | - [ ] Minor: New feature (non-breaking change which adds functionality) 19 | - [ ] Major: Breaking change (fix or feature that would cause existing functionality to not work as expected) 20 | - [ ] Docs: Documentation updates (if none of the other choices apply) 21 | 22 | ## Checklist 23 | 24 | - [ ] Lint and unit tests pass locally with my changes. 25 | - [ ] I have added tests that prove my fix is effective or that my feature works. 26 | - [ ] I have tested my changes on the player-component and React player. -------------------------------------------------------------------------------- /apps/player-component-next/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Player from './player'; 2 | 3 | declare global { 4 | namespace JSX { 5 | interface IntrinsicElements { 6 | 'dotlottie-player': any; 7 | } 8 | } 9 | } 10 | 11 | export default function Home() { 12 | return ( 13 |
14 |
15 | 26 | 27 | 37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /packages/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dotlottie/common", 3 | "version": "0.7.11", 4 | "type": "module", 5 | "description": "", 6 | "author": "Afsal , Sam Osborne ", 7 | "license": "MIT", 8 | "engines": { 9 | "node": ">18.0.0" 10 | }, 11 | "module": "dist/index.js", 12 | "main": "dist/index.js", 13 | "types": "dist/index.d.ts", 14 | "files": [ 15 | "dist" 16 | ], 17 | "keywords": [], 18 | "scripts": { 19 | "build": "tsup", 20 | "dev": "tsup --watch", 21 | "lint": "eslint .", 22 | "type-check": "tsc --noEmit" 23 | }, 24 | "dependencies": { 25 | "@dotlottie/dotlottie-js": "^0.7.0", 26 | "@preact/signals-core": "^1.2.3", 27 | "howler": "^2.2.3", 28 | "lottie-web": "^5.12.2", 29 | "xstate": "^4.38.1" 30 | }, 31 | "devDependencies": { 32 | "@lottiefiles/lottie-types": "^1.2.0", 33 | "@types/howler": "^2.2.8", 34 | "tsup": "^7.2.0", 35 | "typescript": "^4.7.4" 36 | }, 37 | "publishConfig": { 38 | "access": "public" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /apps/player-component-nuxt/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more. 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # npm 11 | npm install 12 | 13 | # pnpm 14 | pnpm install 15 | 16 | # yarn 17 | yarn install 18 | ``` 19 | 20 | ## Development Server 21 | 22 | Start the development server on `http://localhost:3000`: 23 | 24 | ```bash 25 | # npm 26 | npm run dev 27 | 28 | # pnpm 29 | pnpm run dev 30 | 31 | # yarn 32 | yarn dev 33 | ``` 34 | 35 | ## Production 36 | 37 | Build the application for production: 38 | 39 | ```bash 40 | # npm 41 | npm run build 42 | 43 | # pnpm 44 | pnpm run build 45 | 46 | # yarn 47 | yarn build 48 | ``` 49 | 50 | Locally preview production build: 51 | 52 | ```bash 53 | # npm 54 | npm run preview 55 | 56 | # pnpm 57 | pnpm run preview 58 | 59 | # yarn 60 | yarn preview 61 | ``` 62 | 63 | Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. 64 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | .splitter-drag-bar { 6 | flex-shrink: 0; 7 | width: 5px; 8 | background-color: #d1d5db; 9 | cursor: col-resize; 10 | transition: background-color 0.15s 0.15s ease-in-out; 11 | } 12 | 13 | .splitter-drag-bar.splitter-drag-bar--dragging, 14 | .sample-drag-bar:hover { 15 | background-color: #63b3ed; 16 | } 17 | 18 | .splitter-drag-bar.splitter-drag-bar--horizontal { 19 | height: 5px; 20 | width: 100%; 21 | cursor: row-resize; 22 | } 23 | 24 | [hidden] { 25 | display: none; 26 | } 27 | 28 | .custom-scrollbar::-webkit-scrollbar { 29 | width: 10px; 30 | } 31 | 32 | /* Track */ 33 | .custom-scrollbar::-webkit-scrollbar-track { 34 | background: #1e1e1e; 35 | border-left: 1px solid rgba(156, 163, 175, 0.4); 36 | } 37 | 38 | /* Handle */ 39 | .custom-scrollbar::-webkit-scrollbar-thumb { 40 | background: rgba(120, 119, 119, 0.8); 41 | } 42 | 43 | /* Handle on hover */ 44 | .custom-scrollbar::-webkit-scrollbar-thumb:hover { 45 | background: rgba(120, 119, 119, 1); 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 LottieFiles.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/react-player/src/hooks/use-select-dotlottie-state.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { DotLottieCommonPlayer, DotLottiePlayerState } from '@dotlottie/common'; 6 | import { DEFAULT_STATE } from '@dotlottie/common'; 7 | import { useCallback } from 'react'; 8 | 9 | import { useSyncExternalStore } from './use-sync-external-store'; 10 | 11 | export type Unsubscribe = () => void; 12 | export type Subscribe = (onStateChange: () => void) => Unsubscribe; 13 | 14 | export function useSelectDotLottieState( 15 | dotLottiePlayer: DotLottieCommonPlayer, 16 | selector: (state: DotLottiePlayerState) => T, 17 | ): T { 18 | const getSelection = useCallback(() => { 19 | return selector(dotLottiePlayer.getState()); 20 | }, [selector, dotLottiePlayer]); 21 | 22 | const subscribe = useCallback( 23 | (listener: () => void) => { 24 | return dotLottiePlayer.state.subscribe(listener); 25 | }, 26 | [dotLottiePlayer], 27 | ); 28 | 29 | const getServerSnapshot = (): T => { 30 | return selector(DEFAULT_STATE); 31 | }; 32 | 33 | return useSyncExternalStore(subscribe, getSelection, getServerSnapshot); 34 | } 35 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/components/input-fields/input-boolean.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React, { useCallback } from 'react'; 6 | import { PiToggleLeftFill, PiToggleRightFill } from 'react-icons/pi'; 7 | 8 | interface InputBooleanProps { 9 | label: string; 10 | onToggle?: (value: boolean) => void; 11 | value?: boolean; 12 | } 13 | 14 | export const InputBoolean: React.FC = ({ label, onToggle, value }) => { 15 | const handleToggle = useCallback(() => { 16 | onToggle?.(!value); 17 | }, [onToggle, value]); 18 | 19 | return ( 20 |
21 | {label} 22 | 31 |
32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /packages/common/src/dotlottie-state-machine-loader.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { LottieStateMachine } from '@dotlottie/dotlottie-js'; 6 | 7 | import type { DotLottieCommonPlayer } from './dotlottie-player'; 8 | import type { DotLottieStateMachineManager } from './state/dotlottie-state-machine-manager'; 9 | import { createError } from './utils'; 10 | 11 | /** 12 | * Load all the state machines in to XState. 13 | * 14 | * @param stateMachines - The state machines to load. 15 | * @param player - The dotLottie player object. 16 | * @returns A promise that resolves DotLottie state machine manager. 17 | */ 18 | export async function loadStateMachines( 19 | stateMachines: LottieStateMachine[], 20 | player: DotLottieCommonPlayer, 21 | ): Promise { 22 | // Dynamically load state machine related dependencies 23 | const [{ DotLottieStateMachineManager }] = await Promise.all([import('./state/dotlottie-state-machine-manager')]); 24 | 25 | if (!stateMachines.length) { 26 | throw createError('No state machines available inside this .lottie!'); 27 | } 28 | 29 | return new DotLottieStateMachineManager(stateMachines, player); 30 | } 31 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dotlottie-playground", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "run-dev": "vite --mode=development", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@dotlottie/dotlottie-js": "^0.7.0", 13 | "@dotlottie/react-player": "workspace:^", 14 | "@lottiefiles/lottie-types": "^1.2.0", 15 | "@monaco-editor/react": "^4.5.1", 16 | "@reduxjs/toolkit": "^1.9.5", 17 | "monaco-editor": "^0.40.0", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0", 20 | "react-dropzone": "^14.2.3", 21 | "react-icons": "^4.10.1", 22 | "react-redux": "^8.1.2", 23 | "react-resizable-panels": "^0.0.54", 24 | "react-select": "^5.7.4", 25 | "react-toastify": "^9.1.3", 26 | "react-use": "^17.4.0", 27 | "tailwindcss": "3.3.2" 28 | }, 29 | "devDependencies": { 30 | "@types/react": "^18.2.15", 31 | "@types/react-dom": "^18.2.7", 32 | "@vitejs/plugin-react": "^4.0.3", 33 | "autoprefixer": "^10.4.14", 34 | "postcss": "^8.4.31", 35 | "typescript": "^5.0.2", 36 | "vite": "^4.4.5" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/ellipsis-vertical.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const EllipsisVertical = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 15 | 19 | 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/a11y.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { Result } from 'axe-core' 6 | 7 | import { html } from 'lit'; 8 | 9 | 10 | function logA11yViolations(violations: Result[]) { 11 | cy.task( 12 | 'log', 13 | `${violations.length} accessibility violation${violations.length === 1 ? '' : 's'} ${ 14 | violations.length === 1 ? 'was' : 'were' 15 | } detected`, 16 | ); 17 | // pluck specific keys to keep the table readable 18 | const violationData = violations.map(({ id, impact, description, nodes }) => ({ 19 | id, 20 | impact, 21 | description, 22 | nodes: nodes.length, 23 | })); 24 | 25 | cy.task('table', violationData); 26 | } 27 | 28 | describe('a11y', () => { 29 | beforeEach(() => { 30 | cy.injectAxe(); 31 | }); 32 | 33 | it('Has no detectable a11y violations on load', () => { 34 | cy.mount( 35 | html` 36 | 37 | 38 | `, 39 | ); 40 | 41 | cy.checkA11y('[data-testid="player"]', {}, logA11yViolations, true); 42 | }); 43 | }); 44 | 45 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/loop.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { html } from 'lit'; 6 | 7 | describe('Loop', () => { 8 | it('should default to `false`', () => { 9 | cy.mount( 10 | html` 11 | 12 | 13 | `, 14 | ); 15 | 16 | cy.get('[name="loop"]').should('have.value', 'false'); 17 | }); 18 | 19 | it('should be able to set `loop` = `true`', () => { 20 | cy.mount( 21 | html` 22 | 23 | 24 | `, 25 | ); 26 | 27 | cy.get('[name="loop"]').should('have.value', 'true'); 28 | }); 29 | 30 | it('should be able to set number loops', () => { 31 | cy.mount( 32 | html` 33 | 41 | 42 | `, 43 | ); 44 | 45 | cy.get('[name="loop"]').should('have.value', 3); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /packages/react-player/cypress/component/a11y.cy.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { Result } from 'axe-core'; 6 | 7 | import { Controls } from '../../src/controls'; 8 | import { DotLottiePlayer } from '../../src/react-player'; 9 | 10 | function logA11yViolations(violations: Result[]): void { 11 | cy.task( 12 | 'log', 13 | `${violations.length} accessibility violation${violations.length === 1 ? '' : 's'} ${ 14 | violations.length === 1 ? 'was' : 'were' 15 | } detected`, 16 | ); 17 | // pluck specific keys to keep the table readable 18 | const violationData = violations.map(({ description, id, impact, nodes }) => ({ 19 | description, 20 | id, 21 | impact, 22 | nodes: nodes.length, 23 | })); 24 | 25 | cy.task('table', violationData); 26 | } 27 | 28 | describe('a11y', () => { 29 | beforeEach(() => { 30 | cy.injectAxe(); 31 | }); 32 | 33 | it('Has no detectable a11y violations on load', () => { 34 | cy.mount( 35 | 41 | 42 | , 43 | ); 44 | 45 | cy.checkA11y('[data-testid="player"]', {}, logA11yViolations); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /apps/react-player-next/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/player-component-next/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/react-player/src/hooks/use-dotlottie-state.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { DotLottiePlayerState } from '@dotlottie/common'; 6 | import { DEFAULT_STATE } from '@dotlottie/common'; 7 | import { useCallback } from 'react'; 8 | 9 | import { useDotLottieContext } from '../providers'; 10 | 11 | import { useSyncExternalStore } from './use-sync-external-store'; 12 | 13 | export type Unsubscribe = () => void; 14 | export type Subscribe = (onStateChange: () => void) => Unsubscribe; 15 | const noop = (): void => { 16 | // 17 | }; 18 | 19 | export function useDotLottieState(selector: (state: DotLottiePlayerState) => T): T | undefined { 20 | const dotLottiePlayer = useDotLottieContext(); 21 | 22 | const getSelection = useCallback(() => { 23 | if (dotLottiePlayer === null) return undefined; 24 | 25 | return selector(dotLottiePlayer.getState()); 26 | }, [selector, dotLottiePlayer]); 27 | 28 | const subscribe = useCallback( 29 | (listener: () => void) => { 30 | if (dotLottiePlayer === null) return noop; 31 | 32 | return dotLottiePlayer.state.subscribe(listener); 33 | }, 34 | [dotLottiePlayer], 35 | ); 36 | 37 | const getServerSnapshot = (): T => { 38 | return selector(DEFAULT_STATE); 39 | }; 40 | 41 | return useSyncExternalStore(subscribe, getSelection, getServerSnapshot); 42 | } 43 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/README.md: -------------------------------------------------------------------------------- 1 | # React + TypeScript + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | 10 | ## Expanding the ESLint configuration 11 | 12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: 13 | 14 | - Configure the top-level `parserOptions` property like this: 15 | 16 | ```js 17 | parserOptions: { 18 | ecmaVersion: 'latest', 19 | sourceType: 'module', 20 | project: ['./tsconfig.json', './tsconfig.node.json'], 21 | tsconfigRootDir: __dirname, 22 | }, 23 | ``` 24 | 25 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` 26 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked` 27 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list 28 | -------------------------------------------------------------------------------- /apps/player-component-web/src/typescript.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/react-player/src/hooks/use-dotlottie-player.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { DotLottieConfig, DotLottieElement, RendererType } from '@dotlottie/common'; 6 | import { DotLottieCommonPlayer } from '@dotlottie/common'; 7 | import type { MutableRefObject } from 'react'; 8 | import { useLayoutEffect, useRef, useState, useEffect } from 'react'; 9 | 10 | export const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect; 11 | 12 | export const useDotLottiePlayer = ( 13 | src: Record | string, 14 | containerRef: MutableRefObject, 15 | config?: DotLottieConfig, 16 | ): DotLottieCommonPlayer => { 17 | const [dotLottiePlayer] = useState(() => new DotLottieCommonPlayer(src, containerRef.current, config)); 18 | 19 | const loadedRef = useRef(false); 20 | 21 | useIsomorphicLayoutEffect(() => { 22 | async function load(): Promise { 23 | if (!loadedRef.current && containerRef.current) { 24 | loadedRef.current = true; 25 | 26 | dotLottiePlayer.setContainer(containerRef.current); 27 | 28 | await dotLottiePlayer.load(); 29 | } 30 | } 31 | 32 | load(); 33 | 34 | return () => { 35 | if (loadedRef.current) { 36 | dotLottiePlayer.destroy(); 37 | } 38 | }; 39 | }, [dotLottiePlayer]); 40 | 41 | return dotLottiePlayer; 42 | }; 43 | -------------------------------------------------------------------------------- /apps/player-component-vue/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/react-player-test/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/player-component-react/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Design Barn Inc. 3 | */ 4 | 5 | module.exports = { 6 | root: true, 7 | 8 | plugins: ['@lottiefiles'], 9 | 10 | extends: [ 11 | 'plugin:@lottiefiles/esnext', 12 | 'plugin:@lottiefiles/typescript', 13 | 'plugin:@lottiefiles/typescript-typechecking', 14 | 'plugin:@lottiefiles/nodejs', 15 | 'plugin:@lottiefiles/prettier', 16 | ], 17 | 18 | overrides: [ 19 | { 20 | files: ['*.ts', '*.tsx', '*.cts', '*.mts'], 21 | 22 | parserOptions: { 23 | project: ['./packages/*/tsconfig.json', './tsconfig.json'], 24 | tsconfigRootDir: __dirname, 25 | }, 26 | }, 27 | 28 | // Allow code in bin and scripts folders to do CLI things 29 | { 30 | files: ['**/@(bin|scripts|examples)/**/*.@(js|ts|cjs|mjs|cts|mts)'], 31 | rules: { 32 | 'no-console': 'off', 33 | 'node/shebang': 'off', 34 | }, 35 | }, 36 | ], 37 | 38 | rules: { 39 | 'default-param-last': 'off', 40 | '@typescript-eslint/default-param-last': ['error'], 41 | '@typescript-eslint/prefer-for-of': 'off', 42 | '@typescript-eslint/dot-notation': 'off', 43 | '@typescript-eslint/member-ordering': 'off', 44 | 'prefer-object-spread': 'warn', 45 | 46 | // Disable the async generator warning 47 | 'no-restricted-syntax': 'off', 48 | 49 | // Disable deprecation testing 50 | 'deprecation/deprecation': 'off', 51 | 52 | 'no-undefined': 'off', 53 | 'import/extensions': 'off', 54 | }, 55 | }; 56 | -------------------------------------------------------------------------------- /apps/react-player-next/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 18 | 19 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/loop.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const Loop = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 15 | 19 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /apps/player-component-next/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 18 | 19 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /packages/react-player/src/icons/loop-on.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { SVGAttributes } from 'react'; 6 | import React from 'react'; 7 | 8 | export const LoopOn = (props: SVGAttributes): JSX.Element => { 9 | return ( 10 | 11 | 15 | 19 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /apps/player-component-react/src/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | 6 | color-scheme: light dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | 10 | font-synthesis: none; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | -webkit-text-size-adjust: 100%; 15 | } 16 | 17 | a { 18 | font-weight: 500; 19 | color: #646cff; 20 | text-decoration: inherit; 21 | } 22 | a:hover { 23 | color: #535bf2; 24 | } 25 | 26 | body { 27 | margin: 0; 28 | display: flex; 29 | place-items: center; 30 | min-width: 320px; 31 | min-height: 100vh; 32 | } 33 | 34 | h1 { 35 | font-size: 3.2em; 36 | line-height: 1.1; 37 | } 38 | 39 | button { 40 | border-radius: 8px; 41 | border: 1px solid transparent; 42 | padding: 0.6em 1.2em; 43 | font-size: 1em; 44 | font-weight: 500; 45 | font-family: inherit; 46 | background-color: #1a1a1a; 47 | cursor: pointer; 48 | transition: border-color 0.25s; 49 | } 50 | button:hover { 51 | border-color: #646cff; 52 | } 53 | button:focus, 54 | button:focus-visible { 55 | outline: 4px auto -webkit-focus-ring-color; 56 | } 57 | 58 | @media (prefers-color-scheme: light) { 59 | :root { 60 | color: #213547; 61 | background-color: #ffffff; 62 | } 63 | a:hover { 64 | color: #747bff; 65 | } 66 | button { 67 | background-color: #f9f9f9; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/mode.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { PlayMode } from '@dotlottie/common'; 6 | import { html } from 'lit'; 7 | 8 | describe('Mode', () => { 9 | it('mode should default to `normal`', () => { 10 | cy.mount( 11 | html` 12 | 13 | 14 | `, 15 | ); 16 | 17 | cy.get('[name="playMode"]').should('have.value', PlayMode.Normal); 18 | }); 19 | 20 | it('should be able to change mode to `bounce`', () => { 21 | cy.mount( 22 | html` 23 | 31 | 32 | `, 33 | ); 34 | 35 | cy.get('[name="playMode"]').should('have.value', PlayMode.Bounce); 36 | }); 37 | 38 | it('should be able to change mode to `normal`', () => { 39 | cy.mount( 40 | html` 41 | 49 | 50 | `, 51 | ); 52 | 53 | cy.get('[name="playMode"]').should('have.value', PlayMode.Normal); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/components/input-fields/input-color-picker.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React, { type ChangeEventHandler, useCallback, useRef } from 'react'; 6 | 7 | interface InputColorPickerProps { 8 | label: string; 9 | onChange?: (value: string) => void; 10 | value?: string; 11 | } 12 | 13 | export const InputColorPicker: React.FC = ({ label, onChange, value }) => { 14 | const inputRef = useRef(null); 15 | const handleChange = useCallback>( 16 | (event) => { 17 | onChange?.(event.target.value); 18 | }, 19 | [onChange], 20 | ); 21 | 22 | const openPicker = useCallback(() => inputRef.current?.click(), [inputRef]); 23 | 24 | return ( 25 |
26 | {label} 27 | 35 | 43 |
44 | ); 45 | }; 46 | -------------------------------------------------------------------------------- /apps/player-component-vue/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + TypeScript + Vite 2 | 3 | This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` 61 | 62 | 63 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/direction.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { PlayerState } from '@dotlottie/common'; 6 | import { html } from 'lit'; 7 | 8 | describe('Direction', () => { 9 | it('direction should default to 1', () => { 10 | cy.mount( 11 | html` 12 | 13 | 14 | `, 15 | ); 16 | 17 | cy.get('[name="direction"]').should('have.value', 1); 18 | }); 19 | 20 | it('should be able to change direction to 1', () => { 21 | cy.mount( 22 | html` 23 | 32 | 33 | `, 34 | ); 35 | 36 | cy.get('[name="direction"]').should('have.value', 1); 37 | }); 38 | 39 | it('should be able to change direction to -1', () => { 40 | cy.mount( 41 | html` 42 | 51 | 52 | `, 53 | ); 54 | 55 | cy.get('[name="direction"]').should('have.value', -1); 56 | }); 57 | 58 | it('should be able to change direction to -1 and be in completed state', () => { 59 | cy.mount( 60 | html` 61 | 70 | 71 | `, 72 | ); 73 | 74 | cy.get('[name="direction"]').should('have.value', -1); 75 | cy.get('[name="frame"]').should('have.value', 0); 76 | cy.get('[name="currentState"]').should('have.value', PlayerState.Completed); 77 | }); 78 | 79 | }); 80 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/interactivity/state-toggle.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { PlayerState } from '@dotlottie/common'; 6 | import { html } from 'lit'; 7 | 8 | describe('Interactivity: state_toggle (onClick)', () => { 9 | it('should be able set activeStateId state_toggle', () => { 10 | cy.mount( 11 | html` 12 | 13 | 14 | `, 15 | ); 16 | 17 | cy.get('[name="currentState"]').should('have.value', PlayerState.Paused); 18 | cy.get('[name="currentState"]').should('not.have.value', PlayerState.Playing); 19 | cy.get('[name="activeStateId"]').should('have.value', "state_toggle"); 20 | }); 21 | 22 | it('should transition on click', () => { 23 | cy.mount( 24 | html` 25 | 26 | 27 | `, 28 | ); 29 | 30 | // eslint-disable-next-line no-warning-comments 31 | // TODO: increase animation speed. to make the tests faster. 32 | 33 | // State: startIdle 34 | cy.get('[name="currentState"]').should('have.value', PlayerState.Paused); 35 | cy.get('[name="frame"]').should('have.value', 0); 36 | 37 | // State: playSun 38 | 39 | cy.get('[data-testid="testPlayer"]').shadow().find('.animation').click({force:true}); 40 | cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); 41 | cy.get('[name="loop"]').should('have.value', "false"); 42 | cy.get('[name="autoplay"]').should('have.value', "false"); 43 | cy.get('[name="frame"]').should('have.value', 29); 44 | 45 | // State: playReverse 46 | cy.get('[data-testid="testPlayer"]').shadow().find('.animation').click({force:true}); 47 | cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); 48 | cy.get('[name="loop"]').should('have.value', "false"); 49 | cy.get('[name="autoplay"]').should('have.value', "true"); 50 | cy.get('[name="frame"]').should('have.value', 0); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /packages/react-player/cypress/component/speed.cy.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import React, { useState } from 'react'; 6 | 7 | import { Controls } from '../../src/controls'; 8 | import { DotLottiePlayer } from '../../src/react-player'; 9 | import { PlayerStateWrapper } from '../support/player-state-wrapper'; 10 | 11 | describe('Speed', () => { 12 | it('default speed should be 1', () => { 13 | cy.mount( 14 | 15 | 16 | 17 | 18 | , 19 | , 20 | ); 21 | 22 | cy.get('[name="speed"]').should('have.value', 1); 23 | }); 24 | 25 | it('should be able to change speed to 2', () => { 26 | cy.mount( 27 | 28 | 34 | 35 | 36 | , 37 | , 38 | ); 39 | 40 | cy.get('[name="speed"]').should('have.value', 2); 41 | }); 42 | 43 | it('speed should be reactive.', () => { 44 | function Wrapper(): JSX.Element { 45 | const [speed, setSpeed] = useState(1); 46 | 47 | return ( 48 | <> 49 | 57 | 58 | 65 | 66 | 67 | 68 | 69 | ); 70 | } 71 | 72 | cy.mount(); 73 | 74 | cy.get('[name="speed"]').should('have.value', 1); 75 | 76 | cy.get('[data-testid="update"]').click({ force: true }); 77 | cy.get('[name="speed"]').should('have.value', 3); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/interactivity/play-on-hold-pause.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { PlayerState } from '@dotlottie/common'; 6 | import { html } from 'lit'; 7 | 8 | describe('Interactivity: state_toggle (onMouseEnter, onMouseLeave)', () => { 9 | it('should be able set activeStateId play_on_hold_pause', () => { 10 | cy.mount( 11 | // eslint-disable-next-line no-secrets/no-secrets 12 | html` 13 | 14 | 15 | `, 16 | ); 17 | 18 | cy.get('[name="currentState"]').should('have.value', PlayerState.Paused); 19 | cy.get('[name="currentState"]').should('not.have.value', PlayerState.Playing); 20 | cy.get('[name="activeStateId"]').should('have.value', "play_on_hold_pause"); 21 | }); 22 | 23 | it('should transition on mouseneter and on mouseleve', () => { 24 | cy.mount( 25 | // eslint-disable-next-line no-secrets/no-secrets 26 | html` 27 | 28 | 29 | `, 30 | ); 31 | 32 | // State: idleState 33 | cy.get('[name="currentState"]').should('have.value', PlayerState.Paused); 34 | cy.get('[name="autoplay"]').should('have.value', "false"); 35 | cy.get('[name="loop"]').should('have.value', "false"); 36 | 37 | // State: playState 38 | cy.get('[data-testid="testPlayer"]').shadow().find('.animation').trigger('mouseenter'); 39 | cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); 40 | cy.get('[name="autoplay"]').should('have.value', "true"); 41 | cy.get('[name="loop"]').should('have.value', "false"); 42 | cy.get('[name="direction"]').should('have.value', 1); 43 | 44 | // State: idleState 45 | cy.get('[data-testid="testPlayer"]').shadow().find('.animation').trigger('mouseleave'); 46 | cy.get('[name="currentState"]').should('have.value', PlayerState.Paused); 47 | cy.get('[name="autoplay"]').should('have.value', "false"); 48 | cy.get('[name="loop"]').should('have.value', "false"); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /apps/dotlottie-playground/src/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { type DotLottieStateMachine } from '@dotlottie/dotlottie-js'; 6 | 7 | import mockState from './assets/mock-state.json'; 8 | 9 | export const cn = (...args: unknown[]): string => args.filter(Boolean).join(' '); 10 | 11 | export function createError(error: string, prefix = 'dotLottie-common'): Error { 12 | const err = new Error(`[${prefix}]: ${error}`); 13 | 14 | return err; 15 | } 16 | 17 | export function logError(error: string, prefix: string = 'dotLottie-common', ...rest: unknown[]): void { 18 | // eslint-disable-next-line no-console 19 | console.error(`[${prefix}]:`, error, ...rest); 20 | } 21 | 22 | export function logWarning(warning: string, prefix: string = 'dotLottie-common', ...rest: unknown[]): void { 23 | // eslint-disable-next-line no-console 24 | console.warn(`[${prefix}]:`, warning, ...rest); 25 | } 26 | 27 | export function formatJSON(value: string): string { 28 | try { 29 | const res = JSON.parse(value); 30 | 31 | return JSON.stringify(res, null, '\t'); 32 | } catch (error) { 33 | const errorJson = { 34 | error, 35 | }; 36 | 37 | return JSON.stringify(errorJson, null, '\t'); 38 | } 39 | } 40 | 41 | export function processFilename(fileName: string = ''): string { 42 | return fileName.replace(/\s+/u, '_').toLowerCase(); 43 | } 44 | 45 | export function getMockDotLottieState(): DotLottieStateMachine { 46 | // Removing reference 47 | return structuredClone(mockState); 48 | } 49 | 50 | // export function getFilename(url: string = ''): string { 51 | // const trimmedUrl = url.trim(); 52 | // const pathnameIndex = trimmedUrl.lastIndexOf('/'); 53 | // const lastSegmentWithExtension = trimmedUrl.substring(pathnameIndex + 1); 54 | 55 | // const dotIndex = lastSegmentWithExtension.indexOf('.'); 56 | 57 | // if (dotIndex !== -1) { 58 | // return lastSegmentWithExtension.substring(0, dotIndex); 59 | // } 60 | 61 | // return lastSegmentWithExtension; 62 | // } 63 | 64 | // export function getKeyByValue, V>(object: T, value: V): keyof T { 65 | // const key = Object.keys(object).find((ke) => object[ke] === value); 66 | 67 | // if (key === undefined) { 68 | // throw new Error('Value not found in the object.'); 69 | // } 70 | 71 | // return key; 72 | // } 73 | -------------------------------------------------------------------------------- /packages/react-player/cypress/support/player-state-wrapper.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import type { DotLottiePlayerState } from '@dotlottie/common'; 6 | import React, { useRef, useState } from 'react'; 7 | import type { ReactNode } from 'react'; 8 | import { PlayerEvents } from '../../'; 9 | import type { DotLottieCommonPlayer } from '../../'; 10 | 11 | export const PlayerStateWrapper: React.FC<{ 12 | children: ReactNode; 13 | onRef?: (ref: DotLottieCommonPlayer | null) => void; 14 | }> = ({ children, onRef }) => { 15 | const dotLottiePlayerRef = useRef(null); 16 | const [state, setState] = useState(); 17 | 18 | function onEvent(event: PlayerEvents): void { 19 | const currentState = dotLottiePlayerRef.current?.getState(); 20 | 21 | if (event === PlayerEvents.Ready) { 22 | onRef?.(dotLottiePlayerRef.current); 23 | } 24 | 25 | if (!currentState) return; 26 | setState(currentState); 27 | } 28 | 29 | return ( 30 |
31 |
39 | {state && 40 | Object.keys(state || {}).map((key) => { 41 | return ( 42 | 64 | ); 65 | })} 66 |
67 | {React.Children.map(children, (child) => { 68 | if (!React.isValidElement(child)) return child; 69 | 70 | return React.cloneElement(child, { 71 | onEvent, 72 | ref: dotLottiePlayerRef, 73 | }); 74 | })} 75 |
76 | ); 77 | }; 78 | -------------------------------------------------------------------------------- /packages/react-player/cypress/component/interactivity/on-show-zero.cy.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { PlayerState } from '@dotlottie/common'; 6 | 7 | import { Controls } from '../../../src/controls'; 8 | import { DotLottiePlayer } from '../../../src/react-player'; 9 | import { PlayerStateWrapper } from '../../support/player-state-wrapper'; 10 | 11 | describe('Interactivity: onShowZero (onShow)', () => { 12 | it('should be able set activeStateId onShowZero', () => { 13 | cy.mount( 14 | 15 | 22 | 23 | 24 | , 25 | , 26 | ); 27 | 28 | cy.get('[name="currentState"]').should('have.value', PlayerState.Paused); 29 | cy.get('[name="activeStateId"]').should('have.value', 'onShowZero'); 30 | }); 31 | 32 | it('should change state onShow', () => { 33 | cy.mount( 34 |
35 | 36 | 43 | 44 | 45 | , 46 | 47 | , 48 |
, 49 | ); 50 | 51 | // State: intialState 52 | cy.get('[name="currentState"]').should('have.value', PlayerState.Paused); 53 | cy.get('[name="currentState"]').should('not.have.value', PlayerState.Playing); 54 | cy.get('[name="autoplay"]').should('have.value', 'false'); 55 | cy.get('[name="loop"]').should('have.value', 'false'); 56 | 57 | // State: playState 58 | cy.scrollTo('bottom', { duration: 200 }); 59 | cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); 60 | cy.get('[name="autoplay"]').should('have.value', 'true'); 61 | cy.get('[name="loop"]').should('have.value', 'true'); 62 | cy.get('[name="speed"]').should('have.value', 4); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /packages/player-component/cypress/component/interactivity/exploding-pigeon.cy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Design Barn Inc. 3 | */ 4 | 5 | import { PlayerState } from '@dotlottie/common'; 6 | import { html } from 'lit'; 7 | 8 | describe('Interactivity: exploding_pigeon (onClick, onComplete)', () => { 9 | it('should be able set activeStateId exploding_pigeon', () => { 10 | cy.mount( 11 | // eslint-disable-next-line no-secrets/no-secrets 12 | html` 13 | 14 | 15 | `, 16 | ); 17 | 18 | cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); 19 | cy.get('[name="activeStateId"]').should('have.value', "exploding_pigeon"); 20 | }); 21 | 22 | it('should transition on click', () => { 23 | cy.mount( 24 | // eslint-disable-next-line no-secrets/no-secrets 25 | html` 26 | 27 | 28 | `, 29 | ); 30 | 31 | // eslint-disable-next-line no-warning-comments 32 | // TODO: increase speed. to make the tests faster. 33 | 34 | // State: running 35 | cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); 36 | cy.get('[name="autoplay"]').should('have.value', "true"); 37 | cy.get('[name="loop"]').should('have.value', "true"); 38 | cy.get('[name="direction"]').should('have.value', 1); 39 | 40 | // State: exploding 41 | cy.get('[data-testid="testPlayer"]').shadow().find('.animation').click({force:true}); 42 | cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); 43 | cy.get('[name="autoplay"]').should('have.value', "true"); 44 | cy.get('[name="loop"]').should('have.value', 3); 45 | cy.get('[name="direction"]').should('have.value', 1); 46 | 47 | // State: feathers 48 | cy.get('[data-testid="testPlayer"]').shadow().find('.animation').click({force:true}); 49 | cy.get('[name="currentState"]').should('have.value', PlayerState.Playing); 50 | cy.get('[name="autoplay"]').should('have.value', "true"); 51 | cy.get('[name="loop"]').should('have.value', "false"); 52 | cy.get('[name="direction"]').should('have.value', 1); 53 | }); 54 | }); 55 | --------------------------------------------------------------------------------