├── .commitlintrc.yaml ├── .editorconfig ├── .eslintrc.yaml ├── .gitattributes ├── .github └── workflows │ ├── ci.yaml │ └── deploy.yaml ├── .gitignore ├── .markdownlint.yaml ├── .npmrc ├── .prettierignore ├── .prettierrc.yaml ├── .release-it.yaml ├── .vscode ├── extensions.json └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── SECURITY.md ├── docs ├── .postcssrc.yaml ├── .vitepress │ ├── config.ts │ └── theme │ │ ├── Demo.vue │ │ ├── Layout.vue │ │ ├── index.css │ │ ├── index.ts │ │ └── shims.d.ts ├── advanced.md ├── animation-delay.md ├── animation-direction.md ├── animation-duration.md ├── animation-fill-mode.md ├── animation-iteration-count.md ├── animation-name.md ├── animation-play-state.md ├── animation-timing-function.md ├── animations.md ├── index.md ├── installation.md ├── public │ ├── animate-css.svg │ ├── commits.svg │ ├── license.svg │ ├── logo-dark.svg │ ├── logo-light.svg │ └── tailwind-css.svg ├── translation-distance.md └── tsconfig.json ├── lefthook.yaml ├── package.json ├── patches └── prettier@2.8.1.patch ├── pnpm-lock.yaml ├── src ├── defaults.ts ├── index.ts ├── keyframes.ts ├── types.ts └── utilities.ts ├── tailwind.config.cjs └── tsconfig.json /.commitlintrc.yaml: -------------------------------------------------------------------------------- 1 | extends: 2 | - '@commitlint/config-conventional' 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintrc.yaml: -------------------------------------------------------------------------------- 1 | root: true 2 | env: 3 | node: true 4 | extends: 5 | - plugin:eslint-comments/recommended 6 | - plugin:import/recommended 7 | - plugin:import/typescript 8 | - plugin:security/recommended 9 | - eslint:recommended 10 | - plugin:@typescript-eslint/recommended 11 | - plugin:@typescript-eslint/recommended-requiring-type-checking 12 | - airbnb-base 13 | - airbnb-typescript/base 14 | - plugin:prettier/recommended 15 | ignorePatterns: 16 | - dist 17 | - '!.vitepress' 18 | parser: '@typescript-eslint/parser' 19 | parserOptions: 20 | ecmaVersion: 2019 21 | project: 22 | - tsconfig.json 23 | - docs/tsconfig.json 24 | sourceType: module 25 | plugins: 26 | - '@typescript-eslint' 27 | - security 28 | settings: 29 | import/resolver: 30 | typescript: 31 | alwaysTryTypes: true 32 | project: . 33 | rules: 34 | eslint-comments/no-unused-disable: error 35 | security/detect-object-injection: off # ts handles this 36 | import/no-extraneous-dependencies: 37 | - error 38 | - devDependencies: true 39 | import/prefer-default-export: off 40 | '@typescript-eslint/array-type': 41 | - error 42 | - default: generic 43 | '@typescript-eslint/ban-tslint-comment': error 44 | '@typescript-eslint/class-literal-property-style': error 45 | '@typescript-eslint/consistent-indexed-object-style': error 46 | '@typescript-eslint/consistent-type-assertions': error 47 | '@typescript-eslint/consistent-type-definitions': 48 | - error 49 | - type 50 | '@typescript-eslint/consistent-type-exports': error 51 | '@typescript-eslint/consistent-type-imports': 52 | - error 53 | - disallowTypeAnnotations: false 54 | '@typescript-eslint/explicit-function-return-type': error 55 | '@typescript-eslint/explicit-member-accessibility': error 56 | '@typescript-eslint/explicit-module-boundary-types': error 57 | '@typescript-eslint/member-ordering': error 58 | '@typescript-eslint/method-signature-style': error 59 | '@typescript-eslint/naming-convention': error 60 | '@typescript-eslint/no-base-to-string': error 61 | '@typescript-eslint/no-confusing-non-null-assertion': error 62 | '@typescript-eslint/no-confusing-void-expression': error 63 | '@typescript-eslint/no-dynamic-delete': error 64 | '@typescript-eslint/no-extraneous-class': error 65 | '@typescript-eslint/no-invalid-void-type': error 66 | '@typescript-eslint/no-meaningless-void-operator': error 67 | '@typescript-eslint/no-non-null-asserted-nullish-coalescing': error 68 | '@typescript-eslint/no-parameter-properties': error 69 | '@typescript-eslint/no-require-imports': error 70 | '@typescript-eslint/no-unnecessary-boolean-literal-compare': error 71 | '@typescript-eslint/no-unnecessary-condition': error 72 | '@typescript-eslint/no-unnecessary-qualifier': error 73 | '@typescript-eslint/no-unnecessary-type-arguments': error 74 | '@typescript-eslint/non-nullable-type-assertion-style': error 75 | '@typescript-eslint/prefer-enum-initializers': error 76 | '@typescript-eslint/prefer-for-of': error 77 | '@typescript-eslint/prefer-function-type': error 78 | '@typescript-eslint/prefer-includes': error 79 | '@typescript-eslint/prefer-literal-enum-member': error 80 | '@typescript-eslint/prefer-nullish-coalescing': error 81 | '@typescript-eslint/prefer-optional-chain': error 82 | '@typescript-eslint/prefer-readonly': error 83 | '@typescript-eslint/prefer-reduce-type-parameter': error 84 | '@typescript-eslint/prefer-regexp-exec': error 85 | '@typescript-eslint/prefer-return-this-type': error 86 | '@typescript-eslint/prefer-string-starts-ends-with': error 87 | '@typescript-eslint/prefer-ts-expect-error': error 88 | '@typescript-eslint/promise-function-async': error 89 | '@typescript-eslint/require-array-sort-compare': 90 | - error 91 | - ignoreStringArrays: true 92 | '@typescript-eslint/sort-type-union-intersection-members': error 93 | '@typescript-eslint/strict-boolean-expressions': error 94 | '@typescript-eslint/switch-exhaustiveness-check': error 95 | '@typescript-eslint/type-annotation-spacing': error 96 | '@typescript-eslint/typedef': error 97 | '@typescript-eslint/unified-signatures': error 98 | 99 | # Override/Extension Rules 100 | brace-style: off 101 | '@typescript-eslint/brace-style': error 102 | comma-dangle: off 103 | '@typescript-eslint/comma-dangle': error 104 | comma-spacing: off 105 | '@typescript-eslint/comma-spacing': error 106 | default-param-last: off 107 | '@typescript-eslint/default-param-last': error 108 | dot-notation: off 109 | '@typescript-eslint/dot-notation': error 110 | func-call-spacing: off 111 | '@typescript-eslint/func-call-spacing': error 112 | init-declarations: off 113 | '@typescript-eslint/init-declarations': error 114 | keyword-spacing: off 115 | '@typescript-eslint/keyword-spacing': error 116 | lines-between-class-members: off 117 | '@typescript-eslint/lines-between-class-members': error 118 | no-dupe-class-members: off 119 | '@typescript-eslint/no-dupe-class-members': error 120 | no-duplicate-imports: off 121 | '@typescript-eslint/no-duplicate-imports': error 122 | no-extra-parens: off 123 | '@typescript-eslint/no-extra-parens': error 124 | no-invalid-this: off 125 | '@typescript-eslint/no-invalid-this': error 126 | no-loop-func: off 127 | '@typescript-eslint/no-loop-func': error 128 | no-redeclare: off 129 | '@typescript-eslint/no-redeclare': error 130 | no-restricted-imports: off 131 | '@typescript-eslint/no-restricted-imports': error 132 | no-shadow: off 133 | '@typescript-eslint/no-shadow': error 134 | no-throw-literal: off 135 | '@typescript-eslint/no-throw-literal': error 136 | no-unused-expressions: off 137 | '@typescript-eslint/no-unused-expressions': error 138 | no-use-before-define: off 139 | '@typescript-eslint/no-use-before-define': error 140 | no-useless-constructor: off 141 | '@typescript-eslint/no-useless-constructor': error 142 | object-curly-spacing: off 143 | '@typescript-eslint/object-curly-spacing': error 144 | padding-line-between-statements: off 145 | '@typescript-eslint/padding-line-between-statements': error 146 | quotes: off 147 | '@typescript-eslint/quotes': error 148 | no-return-await: off 149 | '@typescript-eslint/return-await': error 150 | semi: off 151 | space-before-function-paren: off 152 | '@typescript-eslint/space-before-function-paren': error 153 | space-infix-ops: off 154 | '@typescript-eslint/space-infix-ops': error 155 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | types: [opened, synchronize, reopened] 9 | schedule: 10 | - cron: '0 0 */7 * *' 11 | workflow_dispatch: 12 | 13 | jobs: 14 | test: 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | node-version: [14, 16, 18] 19 | steps: 20 | - uses: actions/checkout@v3 21 | - uses: pnpm/action-setup@v2 22 | - uses: actions/setup-node@v3 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | cache: pnpm 26 | - run: pnpm prerelease && git add . && [ -z "$(git status --porcelain)" ] 27 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: read 10 | pages: write 11 | id-token: write 12 | 13 | concurrency: 14 | group: pages 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | build: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v3 22 | with: 23 | fetch-depth: 0 24 | - uses: pnpm/action-setup@v2 25 | - uses: actions/setup-node@v3 26 | with: 27 | node-version: lts/* 28 | cache: pnpm 29 | - uses: actions/configure-pages@v1 30 | - run: pnpm i && pnpm build && pnpm vitepress build docs --base /animated-tailwindcss/ 31 | - uses: actions/upload-pages-artifact@v1 32 | with: 33 | path: docs/.vitepress/dist 34 | 35 | deploy: 36 | environment: 37 | name: github-pages 38 | url: ${{ steps.deployment.outputs.page_url }} 39 | runs-on: ubuntu-latest 40 | needs: build 41 | steps: 42 | - id: deployment 43 | uses: actions/deploy-pages@v1 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | cache 4 | *.log 5 | *.tgz 6 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | default: true 2 | MD025: false 3 | MD033: false 4 | MD013: 5 | tables: false 6 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shell-emulator=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | cache 3 | pnpm-lock.yaml 4 | CHANGELOG.md 5 | -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | proseWrap: always 2 | semi: false 3 | singleQuote: true 4 | trailingComma: all 5 | printWidth: 100 6 | htmlWhitespaceSensitivity: ignore 7 | overrides: 8 | - files: '*.md' 9 | options: 10 | printWidth: 80 11 | plugins: 12 | - prettier-plugin-packagejson 13 | - prettier-plugin-tailwindcss 14 | -------------------------------------------------------------------------------- /.release-it.yaml: -------------------------------------------------------------------------------- 1 | git: 2 | commitMessage: 'chore: release v${version}' 3 | github: 4 | release: true 5 | releaseName: v${version} 6 | plugins: 7 | '@release-it/conventional-changelog': 8 | preset: conventionalcommits 9 | infile: CHANGELOG.md 10 | ignoreRecommendedBump: true 11 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "bradlc.vscode-tailwindcss", 4 | "davidanson.vscode-markdownlint", 5 | "dbaeumer.vscode-eslint", 6 | "editorconfig.editorconfig", 7 | "esbenp.prettier-vscode", 8 | "foxundermoon.shell-format", 9 | "rohit-gohri.format-code-action", 10 | "streetsidesoftware.code-spell-checker" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "[ignore][properties][shellscript]": { "editor.defaultFormatter": "foxundermoon.shell-format" }, 4 | "editor.formatOnSave": false, 5 | "editor.codeActionsOnSave": ["source.fixAll.format", "source.fixAll.eslint"], 6 | "eslint.probe": ["typescript"], 7 | "typescript.tsdk": "node_modules/typescript/lib", 8 | "volar.vueserver.vitePress.processMdFile": true, 9 | "yaml.schemas": { 10 | "https://json.schemastore.org/github-workflow.json": "file:///c%3A/Users/brc-dd/Desktop/delete/animated-tailwindcss/.github/workflows/deploy.yaml" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 4.0.0 (2023-01-03) 4 | 5 | 6 | ### Features 7 | 8 | * v4 ([1b97909](https://github.com/brc-dd/animated-tailwindcss/commit/1b979095c47455b48315fb368734b150c56ee057)) -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | brc-dd@hotmail.com. All complaints will be reviewed and investigated promptly 64 | and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | All sorts of contributions are welcome here! 2 | 3 | When you submit code changes, your submissions are understood to be under 4 | [the same MIT license](LICENSE.md) that covers the project. Feel free to contact 5 | the maintainers if that's a concern. 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Divyansh Singh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 | A configuration to use Animate.css with 12 | Tailwind CSS. 13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |

38 | 39 | --- 40 | 41 | ## Documentation 42 | 43 | [View documentation](https://brc-dd.github.io/animated-tailwindcss/) 44 | 45 | ## Installation 46 | 47 | Please see the [full installation instructions](https://brc-dd.github.io/animated-tailwindcss/installation) for detailed steps and examples. 48 | 49 | ### Quick start with NPM 50 | 51 | In a project where you're using Tailwind CSS **v3**, run this to install this 52 | package: 53 | 54 | ```sh 55 | npm add -D animated-tailwindcss 56 | ``` 57 | 58 | Then configure your `tailwind.config.js` to use the animations: 59 | 60 | ```js 61 | const { withAnimations } = require('animated-tailwindcss') 62 | 63 | module.exports = withAnimations({ 64 | // your (existing) Tailwind CSS config here 65 | }) 66 | ``` 67 | 68 | ## Credits 69 | 70 | - [Animate.css](https://github.com/animate-css/animate.css) – for 71 | animation utilities & keyframes – used under 72 | [the MIT license](https://cdn.jsdelivr.net/npm/animate.css@4.1.1/LICENSE). 73 | - [Transform.tools](https://github.com/ritz078/transform) – for converting 74 | Animate.css to JS – used under 75 | [the MIT license](https://github.com/ritz078/transform/blob/master/LICENSE). 76 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | If you discover any security issues in this repository, please drop an email at 2 | brc-dd@hotmail.com. 3 | 4 | Thanks for helping us keep our open-source projects safe for everyone! We really 5 | appreciate it. 6 | -------------------------------------------------------------------------------- /docs/.postcssrc.yaml: -------------------------------------------------------------------------------- 1 | plugins: 2 | tailwindcss/nesting: {} 3 | tailwindcss: {} 4 | autoprefixer: {} 5 | -------------------------------------------------------------------------------- /docs/.vitepress/config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitepress' 2 | 3 | export default defineConfig({ 4 | title: 'tw-Animated', 5 | description: 'animated-tailwindcss is a package that brings Animate.css classes to Tailwind CSS', 6 | cleanUrls: 'without-subfolders', 7 | 8 | themeConfig: { 9 | socialLinks: [{ icon: 'github', link: 'https://github.com/brc-dd/animated-tailwindcss' }], 10 | 11 | outline: false, 12 | 13 | sidebar: [ 14 | { 15 | text: 'Guide', 16 | items: [ 17 | { text: 'Getting Started', link: '/installation' }, 18 | { text: 'Available Animations', link: '/animations' }, 19 | { text: 'Miscellaneous Notes', link: '/advanced' }, 20 | ], 21 | }, 22 | { 23 | text: 'Available Utilities', 24 | items: [ 25 | { text: 'Animation Delay', link: '/animation-delay' }, 26 | { text: 'Animation Direction', link: '/animation-direction' }, 27 | { text: 'Animation Duration', link: '/animation-duration' }, 28 | { text: 'Animation Fill Mode', link: '/animation-fill-mode' }, 29 | { text: 'Animation Iteration Count', link: '/animation-iteration-count' }, 30 | { text: 'Animation Name', link: '/animation-name' }, 31 | { text: 'Animation Play State', link: '/animation-play-state' }, 32 | { text: 'Animation Timing Function', link: '/animation-timing-function' }, 33 | { text: 'Translation Distance', link: '/translation-distance' }, 34 | ], 35 | }, 36 | ], 37 | 38 | editLink: { pattern: 'https://github.com/brc-dd/animated-tailwindcss/edit/main/docs/:path' }, 39 | 40 | footer: { 41 | message: 'Released under the MIT License.', 42 | copyright: 'Copyright © 2023-present Divyansh Singh', 43 | }, 44 | }, 45 | }) 46 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/Demo.vue: -------------------------------------------------------------------------------- 1 | 79 | 80 | 323 | 324 | 374 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/Layout.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 44 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --vp-c-brand-lighter: #27b7f7 !important; 7 | --vp-c-brand-light: #09aaf2 !important; 8 | --vp-c-brand: #0792cf !important; 9 | --vp-c-brand-dark: #067aad !important; 10 | --vp-c-brand-darker: #05618a !important; 11 | --vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg) !important; 12 | } 13 | 14 | table { 15 | --vp-c-bg-mute: transparent; 16 | } 17 | 18 | th, 19 | td { 20 | white-space: pre; 21 | } 22 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import DefaultTheme from 'vitepress/theme' 2 | import Layout from './Layout.vue' 3 | 4 | export default { ...DefaultTheme, Layout } 5 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/shims.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import type { Component } from 'vue' 3 | 4 | const component: Component 5 | export default component 6 | } 7 | -------------------------------------------------------------------------------- /docs/advanced.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Advanced 3 | outline: [2, 3] 4 | --- 5 | 6 | # Miscellaneous 7 | 8 | ## Editor Setup 9 | 10 | You do not need any additional configuration. IntelliSense will automatically 11 | detect the animations and utilities. Refer the 12 | [official docs](https://tailwindcss.com/docs/editor-setup) on setting up your 13 | editor. 14 | 15 | ## Customizing 16 | 17 | Refer to the 18 | [Tailwind CSS docs](https://tailwindcss.com/docs/animation#using-custom-values). 19 | If present, any animation or keyframe customization should be applied properly. 20 | Create an issue on our GitHub if something is not working. 21 | 22 | ## Accessibility 23 | 24 | Use `motion-safe` and `motion-reduce` variants provided by Tailwind CSS. 25 | `print:hidden` can also be used (for example, on elements having exit 26 | animations) to hide them while printing. 27 | 28 | Refer: 29 | 30 | - [Prefers reduced motion | Handling Hover, Focus, and Other States - Tailwind CSS](https://tailwindcss.com/docs/hover-focus-and-other-states#prefers-reduced-motion) 31 | - [Prefers reduced motion | Animation - Tailwind CSS](https://tailwindcss.com/docs/animation#prefers-reduced-motion) 32 | - [Print styles | Handling Hover, Focus, and Other States - Tailwind CSS](https://tailwindcss.com/docs/hover-focus-and-other-states#print-styles) 33 | 34 | ## Optimizing 35 | 36 | Tailwind CSS v3 has JIT mode enabled by default. So, it will only generate the 37 | CSS you are actually using in your project. Please refer 38 | [the docs](https://tailwindcss.com/docs/optimizing-for-production) to learn 39 | more. 40 | 41 | ## Upgrade Guide 42 | 43 | ### From v3 to v4 44 | 45 | Default export is removed. Use named export instead: 46 | 47 | ```ts 48 | const withAnimations = require('animated-tailwindcss') // [!code --] 49 | const { withAnimations } = require('animated-tailwindcss') // [!code ++] 50 | ``` 51 | 52 | ### From v2 to v3 53 | 54 | - We now require Tailwind CSS v3. So first upgrade it. You can refer their 55 | [upgrade guide](https://tailwindcss.com/docs/upgrade-guide). 56 | - `animate-animated` class is no longer required. You can remove it. 57 | - Accessibility measures are no longer enforced by us. Refer the 58 | [accessibility section](#accessibility). 59 | - Remove any experimental options that you might earlier be passing to 60 | `withAnimations` wrapper. Those features are now covered by semantic 61 | versioning and are stable. 62 | -------------------------------------------------------------------------------- /docs/animation-delay.md: -------------------------------------------------------------------------------- 1 | # Animation Delay 2 | 3 | | Class | Properties ([MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay)) | 4 | | ---------------------- | ------------------------------------------------------------------------------------ | 5 | | `animate-delay-[time]` | `animation-delay: time;` | 6 | 7 | Here `[time]` is one of `{75, 100, 150, 200, 300, 500, 700, 1000}` and is 8 | interpreted like 75ms, 100ms... You can also use `animate-delay-{1..5}s` classes 9 | or arbitrary values. 10 | 11 | ## Examples 12 | 13 | ```html 14 |
Foo
15 |
Bar
16 |
Baz
17 | ``` 18 | -------------------------------------------------------------------------------- /docs/animation-direction.md: -------------------------------------------------------------------------------- 1 | # Animation Direction 2 | 3 | | Class | Properties ([MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction)) | 4 | | --------------------------- | ---------------------------------------------------------------------------------------- | 5 | | `animate-normal` | `animation-direction: normal;` | 6 | | `animate-reverse` | `animation-direction: reverse;` | 7 | | `animate-alternate` | `animation-direction: alternate;` | 8 | | `animate-alternate-reverse` | `animation-direction: alternate-reverse` | 9 | -------------------------------------------------------------------------------- /docs/animation-duration.md: -------------------------------------------------------------------------------- 1 | # Animation Duration 2 | 3 | | Class | Properties ([MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-duration)) | 4 | | ------------------------- | --------------------------------------------------------------------------------------- | 5 | | `animate-faster` | `animation-duration: 0.5s;` | 6 | | `animate-fast` | `animation-duration: 0.8s;` | 7 | | `animate-slow` | `animation-duration: 2s;` | 8 | | `animate-slower` | `animation-duration: 3s;` | 9 | | `animate-duration-[time]` | `animation-duration: time;` | 10 | 11 | Here `[time]` is one of `{75, 100, 150, 200, 300, 500, 700, 1000}` and is 12 | interpreted like 75ms, 100ms... You can also use arbitrary values instead. 13 | 14 | ## Examples 15 | 16 | ```html 17 |
Foo
18 |
Bar
19 | ``` 20 | -------------------------------------------------------------------------------- /docs/animation-fill-mode.md: -------------------------------------------------------------------------------- 1 | # Animation Fill Mode 2 | 3 | | Class | Properties ([MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode)) | 4 | | ------------------------ | ---------------------------------------------------------------------------------------- | 5 | | `animate-fill-none` | `animation-fill-mode: none;` | 6 | | `animate-fill-forwards` | `animation-fill-mode: forwards;` | 7 | | `animate-fill-backwards` | `animation-fill-mode: backwards;` | 8 | | `animate-fill-both` | `animation-fill-mode: both;` | 9 | 10 | By default `animation-fill-mode` is set to `both` for all animations in 11 | Animate.css. 12 | 13 | You can use arbitrary values if you need to reference some globals or write the 14 | fill mode for multiple animations: 15 | 16 | ```html 17 |
Foo
18 |
Bar
19 | ``` 20 | -------------------------------------------------------------------------------- /docs/animation-iteration-count.md: -------------------------------------------------------------------------------- 1 | # Animation Iteration Count 2 | 3 | | Class | Properties ([MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-iteration-count)) | 4 | | -------------------- | ---------------------------------------------------------------------------------------------- | 5 | | `animate-infinite` | `animation-iteration-count: infinite;` | 6 | | `animate-repeat-[n]` | `animation-iteration-count: n;` | 7 | 8 | Here `[n]` is one of `0..12`. You can also use arbitrary values instead. 9 | 10 | ## Examples 11 | 12 | ```html 13 |
Foo
14 |
Bar
15 | ``` 16 | -------------------------------------------------------------------------------- /docs/animation-name.md: -------------------------------------------------------------------------------- 1 | # Animation Name 2 | 3 | | Class | Properties ([MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-name)) | 4 | | ---------------- | ----------------------------------------------------------------------------------- | 5 | | `animate-none` | `animation-name: none;` | 6 | | `animate-[name]` | `animation-name: name;` | 7 | 8 | ## Examples 9 | 10 | ```html 11 |
Foo
12 |
Bar
13 | ``` 14 | 15 | Refer [the demo](./animations) to see the available animations in action. You 16 | can play with them [here](https://play.tailwindcss.com/TsNC9Yw9Nc). 17 | 18 | Also refer the official Tailwind CSS documentation on 19 | [using animations with arbitrary values](https://tailwindcss.com/docs/animation#arbitrary-values). 20 | Note that these classes add some default properties and keyframe definitions 21 | too. 22 | -------------------------------------------------------------------------------- /docs/animation-play-state.md: -------------------------------------------------------------------------------- 1 | # Animation Play State 2 | 3 | | Class | Properties ([MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-play-state)) | 4 | | ----------------- | ----------------------------------------------------------------------------------------- | 5 | | `animate-paused` | `animation-play-state: paused;` | 6 | | `animate-running` | `animation-play-state: running;` | 7 | -------------------------------------------------------------------------------- /docs/animation-timing-function.md: -------------------------------------------------------------------------------- 1 | # Animation Timing Function 2 | 3 | | Class | Properties ([MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function)) | 4 | | ---------------------------- | ---------------------------------------------------------------------------------------------- | 5 | | `animate-ease` | `animation-timing-function: ease;` | 6 | | `animate-ease-linear` | `animation-timing-function: linear;` | 7 | | `animate-ease-in` | `animation-timing-function: ease-in;` | 8 | | `animate-ease-out` | `animation-timing-function: ease-out;` | 9 | | `animate-ease-in-out` | `animation-timing-function: ease-in-out;` | 10 | | `animate-[easing]` | `animation-timing-function: easing;` | 11 | | `animate-ease-[p0,p1,p2,p3]` | `animation-timing-function: cubic-bezier(p0, p1, p2, p4);` | 12 | | `animate-steps-start-[n]` | `animation-timing-function: steps(n, jump-start);` | 13 | | `animate-steps-end-[n]` | `animation-timing-function: steps(n, jump-end);` | 14 | | `animate-steps-both-[n]` | `animation-timing-function: steps(n, jump-both);` | 15 | | `animate-steps-none-[n]` | `animation-timing-function: steps(n, jump-none);` | 16 | 17 | Here `[easing]` is one of those listed at [easings.net](https://easings.net/) in 18 | kebab-case. Note that some of the easing functions listed there cannot be 19 | written in CSS. 20 | 21 | If you are planning on using custom cubic-bezier function, we would recommend 22 | using [cubic-bezier.com](https://cubic-bezier.com/) to find out what looks best. 23 | 24 | Here `[n]` is one of `0..12`. You can also use arbitrary values instead. 25 | 26 | ## Examples 27 | 28 | ```html 29 |
Foo
30 |
Bar
31 |
Baz
32 |
Qux
33 | ``` 34 | -------------------------------------------------------------------------------- /docs/animations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Animations 3 | --- 4 | 5 | # Demo 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | titleTemplate: ':title' 4 | features: 5 | - title: Derived from Animate.css 6 | details: 7 | The most popular CSS animation library with over 100 awesome cross-browser 8 | animations. 9 | - title: Enhanced for Tailwind CSS 10 | details: 11 | Fully compatible with JIT mode, allowing a vast variety of customizations 12 | and utility classes. 13 | - title: Zero extra config needed 14 | details: 15 | Wrap your Tailwind CSS config with a function and start using animations 16 | as if they are inbuilt. 17 | --- 18 | -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | --- 4 | 5 | # Getting Started 6 | 7 | In a project where you're using Tailwind CSS **v3**, run this to install this 8 | package: 9 | 10 | ```sh 11 | npm add -D animated-tailwindcss 12 | ``` 13 | 14 | Then configure your `tailwind.config.js` to use the animations: 15 | 16 | ```js 17 | const { withAnimations } = require('animated-tailwindcss') 18 | 19 | module.exports = withAnimations({ 20 | // your (existing) Tailwind CSS config here 21 | }) 22 | ``` 23 | 24 | :::details Example 25 | 26 | ```js 27 | const { withAnimations } = require('animated-tailwindcss') 28 | 29 | module.exports = withAnimations({ 30 | content: ['./src/**/*.{html,js}'], 31 | theme: { extend: {} }, 32 | plugins: [], 33 | }) 34 | ``` 35 | 36 | ::: 37 | 38 | After proper config, you can use the animations of Animate.css the same way as 39 | you use those of Tailwind CSS: 40 | 41 | ```html 42 |

Bouncing Heading

43 | ``` 44 | 45 | :::info Notes 46 | 47 | - If you're coming from classical Animate.css, please note that you need to 48 | reference the classes using hyphen instead of underscores (e.g., 49 | `animate-bounce` instead of `animate__bounce`). 50 | 51 | - The built-in animations (`spin`, `ping`, `pulse`, `bounce`) are prefixed by 52 | `tw`. So, if you want Tailwind CSS' bounce you need to write 53 | `animate-twBounce` instead of `animate-bounce`. 54 | 55 | - The animations this package provides are not exactly same as that of 56 | Animate.css. We have done some modifications to provide you with more 57 | consistent and customizable animations. 58 | 59 | ::: 60 | 61 | ## With Play CDN 62 | 63 | It is as simple as this: 64 | 65 | ```html 66 | 67 | 68 | 69 | 70 | 71 | Welcome 72 | 73 | // [!code focus:6] 74 | 75 | 79 | 80 | 81 |
82 |
Hi!
83 |
84 | 85 | 86 | ``` 87 | 88 | 103 | 104 | :::warning 105 | 106 | The Play CDN is not suitable for production builds, and the above example will 107 | not work if your browser does not support ES6 modules 108 | (_[Can I use?](https://caniuse.com/es6-module) _). 109 | 110 | ::: 111 | -------------------------------------------------------------------------------- /docs/public/animate-css.svg: -------------------------------------------------------------------------------- 1 | animate.css: v4.1.1animate.cssv4.1.1 -------------------------------------------------------------------------------- /docs/public/commits.svg: -------------------------------------------------------------------------------- 1 | commits: conventionalcommitsconventional -------------------------------------------------------------------------------- /docs/public/license.svg: -------------------------------------------------------------------------------- 1 | license: MITlicenseMIT -------------------------------------------------------------------------------- /docs/public/logo-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/public/logo-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/public/tailwind-css.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/translation-distance.md: -------------------------------------------------------------------------------- 1 | # Translation Distance 2 | 3 | Certain animations support modifying their translation distance using 4 | `--animate-distance` CSS variable. You can set it using the following utilities: 5 | 6 | | Class | Properties | 7 | | --------------------------- | ----------------------------- | 8 | | `animate-distance-[length]` | `--animate-distance: length;` | 9 | 10 | Here `[length]` is one of Tailwind CSS-style 11 | [widths](https://tailwindcss.com/docs/width). You can also use arbitrary values 12 | instead. 13 | 14 | ::: details 15 | 16 | The following classes can be customized by these utilities: 17 | 18 | ```txt 19 | animate-backXY 20 | animate-bounceXY 21 | animate-fadeXYBig 22 | animate-hinge 23 | animate-zoomXY 24 | ``` 25 | 26 | where `X` is one of `{In, Out}` and `Y` is one of `{Down, Left, Right, Up}`. 27 | 28 | `animate-distance-{min, max, fit}` are not supported. 29 | 30 | ::: 31 | 32 | ## Examples 33 | 34 | ```html 35 |
Foo
36 |
Bar
37 |
Baz
38 | ``` 39 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.web.json", 3 | "include": [".vitepress/**/*", ".vitepress/**/*.vue"] 4 | } 5 | -------------------------------------------------------------------------------- /lefthook.yaml: -------------------------------------------------------------------------------- 1 | skip_output: 2 | - meta 3 | - execution 4 | 5 | commit-msg: 6 | commands: 7 | commitlint: 8 | run: pnpm commitlint --edit {1} 9 | 10 | post-commit: 11 | commands: 12 | status: 13 | run: git status 14 | 15 | post-checkout: 16 | commands: 17 | install: 18 | run: pnpm i 19 | 20 | pre-commit: 21 | piped: true 22 | commands: 23 | 1_replace: 24 | glob: '*.{json,ts}' 25 | run: pnpm replace "'{\n'" "'{ '" {all_files} 26 | 2_prettify: 27 | run: pnpm prettier --write --ignore-unknown {all_files} 28 | 3_eslint: 29 | glob: '*.ts' 30 | run: pnpm eslint --fix --max-warnings 0 {all_files} 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/package.json", 3 | "name": "animated-tailwindcss", 4 | "version": "4.0.0", 5 | "description": "A configuration to use Animate.css with Tailwind CSS", 6 | "keywords": [ 7 | "animate.css", 8 | "animatecss", 9 | "animations", 10 | "configuration", 11 | "css", 12 | "jit", 13 | "keyframes", 14 | "plugin", 15 | "tailwind", 16 | "tailwindcss", 17 | "utilities" 18 | ], 19 | "homepage": "https://brc-dd.github.io/animated-tailwindcss", 20 | "bugs": { 21 | "url": "https://github.com/brc-dd/animated-tailwindcss", 22 | "email": "brc-dd@hotmail.com" 23 | }, 24 | "repository": "github:brc-dd/animated-tailwindcss", 25 | "funding": "https://github.com/sponsors/brc-dd", 26 | "license": "MIT", 27 | "author": "Divyansh Singh (https://github.com/brc-dd)", 28 | "sideEffects": false, 29 | "exports": { 30 | ".": { 31 | "types": "./dist/index.d.ts", 32 | "require": "./dist/index.js", 33 | "import": "./dist/index.mjs" 34 | } 35 | }, 36 | "main": "dist/index.js", 37 | "module": "dist/index.mjs", 38 | "browser": "dist/index.mjs", 39 | "types": "dist/index.d.ts", 40 | "files": [ 41 | "dist/*" 42 | ], 43 | "scripts": { 44 | "build": "rimraf dist && tsup ./src/index.ts --dts-resolve --format esm,cjs --minify --treeshake", 45 | "lint": "lefthook run pre-commit", 46 | "prerelease": "git add . && pnpm i && pnpm build && pnpm lint", 47 | "release": "pnpm prerelease && release-it" 48 | }, 49 | "devDependencies": { 50 | "@commitlint/cli": "^17.3.0", 51 | "@commitlint/config-conventional": "^17.3.0", 52 | "@release-it/conventional-changelog": "^5.1.1", 53 | "@tsconfig/node12": "^1.0.11", 54 | "@typescript-eslint/eslint-plugin": "^5.48.0", 55 | "@typescript-eslint/parser": "^5.48.0", 56 | "@vue/tsconfig": "^0.1.3", 57 | "autoprefixer": "^10.4.13", 58 | "csstype": "^3.1.1", 59 | "eslint": "^8.31.0", 60 | "eslint-config-airbnb-base": "^15.0.0", 61 | "eslint-config-airbnb-typescript": "^17.0.0", 62 | "eslint-config-prettier": "^8.6.0", 63 | "eslint-import-resolver-node": "^0.3.6", 64 | "eslint-import-resolver-typescript": "^3.5.2", 65 | "eslint-plugin-eslint-comments": "^3.2.0", 66 | "eslint-plugin-import": "^2.26.0", 67 | "eslint-plugin-prettier": "^4.2.1", 68 | "eslint-plugin-security": "^1.5.0", 69 | "lefthook": "^1.2.6", 70 | "postcss": "^8.4.20", 71 | "prettier": "^2.8.1", 72 | "prettier-plugin-packagejson": "^2.3.0", 73 | "prettier-plugin-tailwindcss": "^0.2.1", 74 | "release-it": "^15.6.0", 75 | "replace": "^1.2.2", 76 | "rimraf": "^3.0.2", 77 | "tailwindcss": "^3.2.4", 78 | "tsup": "^6.5.0", 79 | "typescript": "~4.9.4", 80 | "vitepress": "1.0.0-alpha.35", 81 | "vue": "^3.2.45" 82 | }, 83 | "peerDependencies": { 84 | "postcss": "^8", 85 | "tailwindcss": "^3" 86 | }, 87 | "peerDependenciesMeta": { 88 | "postcss": { 89 | "optional": true 90 | } 91 | }, 92 | "packageManager": "pnpm@7.21.0", 93 | "publishConfig": { 94 | "registry": "https://registry.npmjs.org" 95 | }, 96 | "pnpm": { 97 | "peerDependencyRules": { 98 | "ignoreMissing": [ 99 | "@algolia/client-search" 100 | ] 101 | }, 102 | "patchedDependencies": { 103 | "prettier@2.8.1": "patches/prettier@2.8.1.patch" 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /patches/prettier@2.8.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/index.js b/index.js 2 | index e6b12ba57310caaf0497313bb0a93e0ab7cdd8ba..c2c20c22f81b795feb394b40da4d272c29a8e5d6 100644 3 | --- a/index.js 4 | +++ b/index.js 5 | @@ -32917,6 +32917,18 @@ var require_embed3 = __commonJS2({ 6 | } 7 | } 8 | switch (node.type) { 9 | + case "html": 10 | + const isWrapped = !/\s*(script|style|template)/.test(node.value) 11 | + const doc = textToDoc(isWrapped ? `` : node.value, { 12 | + parser: "vue" 13 | + }, { 14 | + stripTrailingHardline: true 15 | + }); 16 | + if (isWrapped) { 17 | + const { contents: c } = doc[0].contents; 18 | + c.contents = c.contents.find(node => node.type === "indent").contents.slice(1); 19 | + } 20 | + return [doc]; 21 | case "front-matter": 22 | return printFrontMatter(node, textToDoc); 23 | case "importExport": -------------------------------------------------------------------------------- /src/defaults.ts: -------------------------------------------------------------------------------- 1 | const range = (a: number, b?: number, c?: number): Array => { 2 | if (b != null && c != null && ((a >= b && c >= 0) || (a < b && c < 0))) return [] 3 | return [...Array(Math.abs(b != null ? Math.ceil((b - a) / ((c ?? 1) || 1)) : a)).keys()].map( 4 | (k) => (k * (c ?? ((b != null ? a > b : a < 0) ? -1 : 1)) || 0) + (b != null ? a : 0), 5 | ) 6 | } 7 | 8 | const expandArray = ( 9 | arr: Array, 10 | append = '', 11 | inKey = false, 12 | transform = (v: T): T => v, 13 | ): Record => 14 | arr.reduce((a, v) => ({ ...a, [`${v}${inKey ? append : ''}`]: `${transform(v)}${append}` }), {}) 15 | 16 | export const duration = expandArray([75, 100, 150, 200, 300, 500, 700, 1000], 'ms') 17 | 18 | export const ease = { 19 | linear: '0,0,1,1', 20 | in: '.42,0,1,1', 21 | out: '0,0,.58,1', 22 | 'in-out': '.42,0,.58,1', 23 | 'in-sine': '.12,0,.39,0', 24 | 'out-sine': '.61,1,.88,1', 25 | 'in-out-sine': '.37,0,.63,1', 26 | 'in-quad': '.11,0,.5,0', 27 | 'out-quad': '.5,1,.89,1', 28 | 'in-out-quad': '.45,0,.55,1', 29 | 'in-cubic': '.32,0,.67,0', 30 | 'out-cubic': '.33,1,.68,1', 31 | 'in-out-cubic': '.65,0,.35,1', 32 | 'in-quart': '.5,0,.75,0', 33 | 'out-quart': '.25,1,.5,1', 34 | 'in-out-quart': '.76,0,.24,1', 35 | 'in-quint': '.64,0,.78,0', 36 | 'out-quint': '.22,1,.36,1', 37 | 'in-out-quint': '.83,0,.17,1', 38 | 'in-expo': '.7,0,.84,0', 39 | 'out-expo': '.16,1,.3,1', 40 | 'in-out-expo': '.87,0,.13,1', 41 | 'in-circ': '.55,0,1,.45', 42 | 'out-circ': '0,.55,.45,1', 43 | 'in-out-circ': '.85,0,.15,1', 44 | 'in-back': '.36,0,.66,-.56', 45 | 'out-back': '.34,1.56,.64,1', 46 | 'in-out-back': '.68,-.6,.32,1.6', 47 | } 48 | 49 | export const delay = { ...duration, ...expandArray(range(6), 's', true) } 50 | 51 | export const repeat = expandArray(range(13)) 52 | 53 | export const fill = expandArray(['none', 'forwards', 'backwards', 'both']) 54 | 55 | export const distance: Record = { 56 | px: '1px', 57 | ...expandArray( 58 | [ 59 | ...range(0, 4, 0.5), 60 | ...range(4, 12, 1), 61 | ...range(12, 16, 2), 62 | ...range(16, 64, 4), 63 | ...range(64, 80, 8), 64 | ...range(80, 100, 16), 65 | ], 66 | 'rem', 67 | false, 68 | (v) => v * 0.25, 69 | ), 70 | '1/2': '50%', 71 | '1/3': '33.333333%', 72 | '2/3': '66.666667%', 73 | '1/4': '25%', 74 | '2/4': '50%', 75 | '3/4': '75%', 76 | '1/5': '20%', 77 | '2/5': '40%', 78 | '3/5': '60%', 79 | '4/5': '80%', 80 | '1/6': '16.666667%', 81 | '2/6': '33.333333%', 82 | '3/6': '50%', 83 | '4/6': '66.666667%', 84 | '5/6': '83.333333%', 85 | '1/12': '8.333333%', 86 | '2/12': '16.666667%', 87 | '3/12': '25%', 88 | '4/12': '33.333333%', 89 | '5/12': '41.666667%', 90 | '6/12': '50%', 91 | '7/12': '58.333333%', 92 | '8/12': '66.666667%', 93 | '9/12': '75%', 94 | '10/12': '83.333333%', 95 | '11/12': '91.666667%', 96 | full: '100%', 97 | screen: '100vh', 98 | } 99 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint no-param-reassign: "off" */ 2 | 3 | import { delay, distance, duration, ease, fill, repeat } from './defaults.js' 4 | import { keyframes } from './keyframes.js' 5 | import type { CSSBlock, CSSProperties, EntryPoint, KeyValuePair, PluginsConfig } from './types.js' 6 | import { animationUtils, keyframeUtils } from './utilities.js' 7 | 8 | export * from './types.js' 9 | 10 | export const withAnimations: EntryPoint = (config = {}) => { 11 | config.theme = config.theme ?? {} 12 | 13 | // animations 14 | const animations: KeyValuePair = Object.fromEntries( 15 | Object.keys(keyframes).map((k) => [ 16 | k, 17 | `${keyframeUtils[k]?.animationDuration ?? '1s'} 18 | ${keyframeUtils[k]?.animationTimingFunction ?? ''} 19 | both ${k}`.replace(/\s+/g, ' '), 20 | ]), 21 | ) 22 | 23 | const configAnimations = config.theme.extend?.animation ?? {} 24 | config.theme.animation = { ...animations, ...configAnimations } 25 | delete config.theme.extend?.animation 26 | 27 | // patches 28 | Object.keys(animations).forEach((key) => { 29 | if (key.includes('In')) { 30 | if (!key.includes('slide')) 31 | ((keyframes[key] = keyframes[key] ?? {}).from = keyframes[key]?.from ?? {}).opacity = 0 32 | } 33 | 34 | if (key.includes('Out')) { 35 | if (!key.includes('slide')) 36 | ((keyframes[key] = keyframes[key] ?? {}).to = keyframes[key]?.to ?? {}).opacity = 0 37 | ;((keyframes[key] = keyframes[key] ?? {}).to = keyframes[key]?.to ?? {}).visibility = 'hidden' 38 | } 39 | }) 40 | 41 | // keyframes 42 | const configKeyframes = config.theme.extend?.keyframes ?? {} 43 | config.theme.keyframes = { ...keyframes, ...configKeyframes } 44 | delete config.theme.extend?.keyframes 45 | 46 | // utilities 47 | const prefixed: CSSBlock = Object.fromEntries( 48 | Object.entries({ ...keyframeUtils, ...animationUtils }).flatMap(([util, block]) => { 49 | if (util in configAnimations || !block) return [] 50 | 51 | const filtered: CSSProperties = 52 | util in animationUtils 53 | ? block // skip filtering 54 | : Object.fromEntries( 55 | Object.entries(block).filter(([key]) => !key.startsWith('animation')), 56 | ) 57 | 58 | return Object.keys(filtered).length > 0 ? [[`.animate-${util}`, filtered]] : [] 59 | }), 60 | ) 61 | 62 | // plugins 63 | const plugins: PluginsConfig = [ 64 | // static utilities 65 | ({ addUtilities }): void => { 66 | addUtilities(prefixed) 67 | }, 68 | 69 | // dynamic utilities 70 | ({ matchUtilities }): void => { 71 | matchUtilities( 72 | { 'animate-duration': (value) => ({ animationDuration: value }) }, 73 | { values: duration }, 74 | ) 75 | 76 | matchUtilities( 77 | { 'animate-ease': (value) => ({ animationTimingFunction: `cubic-bezier(${value})` }) }, 78 | { values: ease }, 79 | ) 80 | 81 | matchUtilities( 82 | { 83 | 'animate-steps-start': (value) => ({ 84 | animationTimingFunction: `steps(${value},jump-start)`, 85 | }), 86 | }, 87 | { values: repeat }, 88 | ) 89 | 90 | matchUtilities( 91 | { 92 | 'animate-steps-end': (value) => ({ animationTimingFunction: `steps(${value},jump-end)` }), 93 | }, 94 | { values: repeat }, 95 | ) 96 | 97 | matchUtilities( 98 | { 99 | 'animate-steps-both': (value) => ({ 100 | animationTimingFunction: `steps(${value},jump-both)`, 101 | }), 102 | }, 103 | { values: repeat }, 104 | ) 105 | 106 | matchUtilities( 107 | { 108 | 'animate-steps-none': (value) => ({ 109 | animationTimingFunction: `steps(${value},jump-none)`, 110 | }), 111 | }, 112 | { values: repeat }, 113 | ) 114 | 115 | matchUtilities({ 'animate-delay': (value) => ({ animationDelay: value }) }, { values: delay }) 116 | 117 | matchUtilities( 118 | { 'animate-repeat': (value) => ({ animationIterationCount: value }) }, 119 | { values: repeat }, 120 | ) 121 | 122 | matchUtilities( 123 | { 'animate-fill': (value) => ({ animationFillMode: value }) }, 124 | { values: fill }, 125 | ) 126 | 127 | matchUtilities( 128 | { 'animate-distance': (value) => ({ '--animate-distance': value }) }, 129 | { values: distance }, 130 | ) 131 | }, 132 | ] 133 | 134 | const configPlugins = config.plugins ?? [] 135 | config.plugins = [...plugins, ...configPlugins] 136 | 137 | return config 138 | } 139 | -------------------------------------------------------------------------------- /src/keyframes.ts: -------------------------------------------------------------------------------- 1 | import type { Keyframes } from './types.js' 2 | 3 | export const keyframes: Keyframes = { 4 | twSpin: { 5 | from: { transform: 'rotate3d(0, 0, 1, 0)' }, 6 | to: { transform: 'rotate3d(0, 0, 1, 360deg)' }, 7 | }, 8 | twPing: { '75%, 100%': { transform: 'scale3d(2, 2, 1)', opacity: '0' } }, 9 | twPulse: { '0%, 100%': { opacity: 1 }, '50%': { opacity: '0.5' } }, 10 | twBounce: { 11 | '0%, 100%': { 12 | transform: 'translate3d(0, -25%, 0)', 13 | animationTimingFunction: 'cubic-bezier(0.8, 0, 1, 1)', 14 | }, 15 | '50%': { 16 | transform: 'translate3d(0, 0, 0)', 17 | animationTimingFunction: 'cubic-bezier(0, 0, 0.2, 1)', 18 | }, 19 | }, 20 | bounce: { 21 | 'from, 20%, 53%, to': { 22 | animationTimingFunction: 'cubic-bezier(0.215, 0.61, 0.355, 1)', 23 | transform: 'translate3d(0, 0, 0)', 24 | }, 25 | '40%, 43%': { 26 | animationTimingFunction: 'cubic-bezier(0.755, 0.05, 0.855, 0.06)', 27 | transform: 'translate3d(0, -30px, 0) scale3d(1, 1.1, 1)', 28 | }, 29 | '70%': { 30 | animationTimingFunction: 'cubic-bezier(0.755, 0.05, 0.855, 0.06)', 31 | transform: 'translate3d(0, -15px, 0) scale3d(1, 1.05, 1)', 32 | }, 33 | '80%': { 34 | animationTimingFunction: 'cubic-bezier(0.215, 0.61, 0.355, 1)', 35 | transform: 'translate3d(0, 0, 0) scale3d(1, 0.95, 1)', 36 | }, 37 | '90%': { transform: 'translate3d(0, -4px, 0) scale3d(1, 1.02, 1)' }, 38 | }, 39 | flash: { '25%, 75%': { opacity: '0' }, '50%': { opacity: '1' } }, 40 | pulse: { '50%': { transform: 'scale3d(1.05, 1.05, 1.05)' } }, 41 | rubberBand: { 42 | '30%': { transform: 'scale3d(1.25, 0.75, 1)' }, 43 | '40%': { transform: 'scale3d(0.75, 1.25, 1)' }, 44 | '50%': { transform: 'scale3d(1.15, 0.85, 1)' }, 45 | '65%': { transform: 'scale3d(0.95, 1.05, 1)' }, 46 | '75%': { transform: 'scale3d(1.05, 0.95, 1)' }, 47 | }, 48 | shakeX: { 49 | '10%, 30%, 50%, 70%, 90%': { transform: 'translate3d(-10px, 0, 0)' }, 50 | '20%, 40%, 60%, 80%': { transform: 'translate3d(10px, 0, 0)' }, 51 | }, 52 | shakeY: { 53 | '10%, 30%, 50%, 70%, 90%': { transform: 'translate3d(0, -10px, 0)' }, 54 | '20%, 40%, 60%, 80%': { transform: 'translate3d(0, 10px, 0)' }, 55 | }, 56 | headShake: { 57 | '6.5%': { transform: 'translate3d(-6px, 0, 0) rotate3d(0, 1, 0, -9deg)' }, 58 | '18.5%': { transform: 'translate3d(5px, 0, 0) rotate3d(0, 1, 0, 7deg)' }, 59 | '31.5%': { transform: 'translate3d(-3px, 0, 0) rotate3d(0, 1, 0, -5deg)' }, 60 | '43.5%': { transform: 'translate3d(2px, 0, 0) rotate3d(0, 1, 0, 3deg)' }, 61 | '50%': { transform: 'translate3d(0, 0, 0)' }, 62 | }, 63 | swing: { 64 | '20%': { transform: 'rotate3d(0, 0, 1, 15deg)' }, 65 | '40%': { transform: 'rotate3d(0, 0, 1, -10deg)' }, 66 | '60%': { transform: 'rotate3d(0, 0, 1, 5deg)' }, 67 | '80%': { transform: 'rotate3d(0, 0, 1, -5deg)' }, 68 | }, 69 | tada: { 70 | '10%, 20%': { transform: 'scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg)' }, 71 | '30%, 50%, 70%, 90%': { transform: 'scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)' }, 72 | '40%, 60%, 80%': { transform: 'scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)' }, 73 | }, 74 | wobble: { 75 | '15%': { transform: 'translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg)' }, 76 | '30%': { transform: 'translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg)' }, 77 | '45%': { transform: 'translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg)' }, 78 | '60%': { transform: 'translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg)' }, 79 | '75%': { transform: 'translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg)' }, 80 | }, 81 | jello: { 82 | '11.1%': { transform: 'translate3d(0, 0, 0)' }, 83 | '22.2%': { transform: 'skew(-12.5deg, -12.5deg)' }, 84 | '33.3%': { transform: 'skew(6.25deg, 6.25deg)' }, 85 | '44.4%': { transform: 'skew(-3.125deg, -3.125deg)' }, 86 | '55.5%': { transform: 'skew(1.5625deg, 1.5625deg)' }, 87 | '66.6%': { transform: 'skew(-0.78125deg, -0.78125deg)' }, 88 | '77.7%': { transform: 'skew(0.390625deg, 0.390625deg)' }, 89 | '88.8%': { transform: 'skew(-0.1953125deg, -0.1953125deg)' }, 90 | }, 91 | heartBeat: { 92 | '14%': { transform: 'scale3d(1.3, 1.3, 1.3)' }, 93 | '28%': { transform: 'scale3d(1, 1, 1)' }, 94 | '42%': { transform: 'scale3d(1.3, 1.3, 1.3)' }, 95 | '70%': { transform: 'scale3d(1, 1, 1)' }, 96 | }, 97 | backInDown: { 98 | from: { 99 | transform: 'translate3d(0, calc(-1 * var(--animate-distance, 1000px)), 0) scale3d(0, 0, 1)', 100 | }, 101 | '80%': { opacity: '0.7', transform: 'translate3d(0, 0, 0) scale3d(0.7, 0.7, 1)' }, 102 | }, 103 | backInLeft: { 104 | from: { 105 | transform: 'translate3d(calc(-1 * var(--animate-distance, 2000px)), 0, 0) scale3d(0, 0, 1)', 106 | }, 107 | '80%': { opacity: '0.7', transform: 'translate3d(0, 0, 0) scale3d(0.7, 0.7, 1)' }, 108 | }, 109 | backInRight: { 110 | from: { transform: 'translate3d(var(--animate-distance, 2000px), 0, 0) scale3d(0, 0, 1)' }, 111 | '80%': { opacity: '0.7', transform: 'translate3d(0, 0, 0) scale3d(0.7, 0.7, 1)' }, 112 | }, 113 | backInUp: { 114 | from: { transform: 'translate3d(0, var(--animate-distance, 1000px), 0) scale3d(0, 0, 1)' }, 115 | '80%': { opacity: '0.7', transform: 'translate3d(0, 0, 0) scale3d(0.7, 0.7, 1)' }, 116 | }, 117 | backOutDown: { 118 | '20%': { opacity: '0.7', transform: 'translate3d(0, 0, 0) scale3d(0.7, 0.7, 1)' }, 119 | to: { transform: 'translate3d(0, var(--animate-distance, 1000px), 0) scale3d(0, 0, 1)' }, 120 | }, 121 | backOutLeft: { 122 | '20%': { opacity: '0.7', transform: 'translate3d(0, 0, 0) scale3d(0.7, 0.7, 1)' }, 123 | to: { 124 | transform: 'translate3d(calc(-1 * var(--animate-distance, 2000px)), 0, 0) scale3d(0, 0, 1)', 125 | }, 126 | }, 127 | backOutRight: { 128 | '20%': { opacity: '0.7', transform: 'translate3d(0, 0, 0) scale3d(0.7, 0.7, 1)' }, 129 | to: { transform: 'translate3d(var(--animate-distance, 2000px), 0, 0) scale3d(0, 0, 1)' }, 130 | }, 131 | backOutUp: { 132 | '20%': { opacity: '0.7', transform: 'translate3d(0, 0, 0) scale3d(0.7, 0.7, 1)' }, 133 | to: { 134 | transform: 'translate3d(0, calc(-1 * var(--animate-distance, 1000px)), 0) scale3d(0, 0, 1)', 135 | }, 136 | }, 137 | bounceIn: { 138 | from: { transform: 'scale3d(0.3, 0.3, 0.3)' }, 139 | '20%': { transform: 'scale3d(1.1, 1.1, 1.1)' }, 140 | '40%': { transform: 'scale3d(0.9, 0.9, 0.9)' }, 141 | '60%': { opacity: '1', transform: 'scale3d(1.03, 1.03, 1.03)' }, 142 | '80%': { transform: 'scale3d(0.97, 0.97, 0.97)' }, 143 | }, 144 | bounceInDown: { 145 | from: { 146 | transform: 'translate3d(0, calc(-1 * var(--animate-distance, 1000px)), 0) scale3d(1, 3, 1)', 147 | }, 148 | '60%': { opacity: '1', transform: 'translate3d(0, 20px, 0) scale3d(1, 0.9, 1)' }, 149 | '75%': { transform: 'translate3d(0, -10px, 0) scale3d(1, 0.95, 1)' }, 150 | '90%': { transform: 'translate3d(0, 5px, 0) scale3d(1, 0.985, 1)' }, 151 | }, 152 | bounceInLeft: { 153 | from: { 154 | transform: 'translate3d(calc(-1 * var(--animate-distance, 2000px)), 0, 0) scale3d(3, 1, 1)', 155 | }, 156 | '60%': { opacity: '1', transform: 'translate3d(25px, 0, 0) scale3d(1, 1, 1)' }, 157 | '75%': { transform: 'translate3d(-10px, 0, 0) scale3d(1, 0.98, 1)' }, 158 | '90%': { transform: 'translate3d(5px, 0, 0) scale3d(1, 0.995, 1)' }, 159 | }, 160 | bounceInRight: { 161 | from: { transform: 'translate3d(var(--animate-distance, 2000px), 0, 0) scale3d(3, 1, 1)' }, 162 | '60%': { opacity: '1', transform: 'translate3d(-25px, 0, 0) scale3d(1, 1, 1)' }, 163 | '75%': { transform: 'translate3d(10px, 0, 0) scale3d(1, 0.98, 1)' }, 164 | '90%': { transform: 'translate3d(-5px, 0, 0) scale3d(1, 0.995, 1)' }, 165 | }, 166 | bounceInUp: { 167 | from: { transform: 'translate3d(0, var(--animate-distance, 1000px), 0) scale3d(1, 3, 1)' }, 168 | '60%': { opacity: '1', transform: 'translate3d(0, -20px, 0) scale3d(1, 0.9, 1)' }, 169 | '75%': { transform: 'translate3d(0, 10px, 0) scale3d(1, 0.95, 1)' }, 170 | '90%': { transform: 'translate3d(0, -5px, 0) scale3d(1, 0.985, 1)' }, 171 | }, 172 | bounceOut: { 173 | '20%': { transform: 'scale3d(0.9, 0.9, 0.9)' }, 174 | '50%, 55%': { opacity: '1', transform: 'scale3d(1.1, 1.1, 1.1)' }, 175 | to: { transform: 'scale3d(0.3, 0.3, 0.3)' }, 176 | }, 177 | bounceOutDown: { 178 | '20%': { transform: 'translate3d(0, 10px, 0) scale3d(1, 0.985, 1)' }, 179 | '40%, 45%': { opacity: '1', transform: 'translate3d(0, -20px, 0) scale3d(1, 0.9, 1)' }, 180 | to: { transform: 'translate3d(0, var(--animate-distance, 1000px), 0) scale3d(1, 3, 1)' }, 181 | }, 182 | bounceOutLeft: { 183 | '20%': { opacity: '1', transform: 'translate3d(20px, 0, 0) scale3d(0.9, 1, 1)' }, 184 | to: { 185 | transform: 'translate3d(calc(-1 * var(--animate-distance, 2000px)), 0, 0) scale3d(2, 1, 1)', 186 | }, 187 | }, 188 | bounceOutRight: { 189 | '20%': { opacity: '1', transform: 'translate3d(-20px, 0, 0) scale3d(0.9, 1, 1)' }, 190 | to: { transform: 'translate3d(var(--animate-distance, 2000px), 0, 0) scale3d(2, 1, 1)' }, 191 | }, 192 | bounceOutUp: { 193 | '20%': { transform: 'translate3d(0, -10px, 0) scale3d(1, 0.985, 1)' }, 194 | '40%, 45%': { opacity: '1', transform: 'translate3d(0, 20px, 0) scale3d(1, 0.9, 1)' }, 195 | to: { 196 | transform: 'translate3d(0, calc(-1 * var(--animate-distance, 1000px)), 0) scale3d(1, 3, 1)', 197 | }, 198 | }, 199 | fadeIn: {}, 200 | fadeInDown: { from: { transform: 'translate3d(0, -100%, 0)' } }, 201 | fadeInDownBig: { 202 | from: { transform: 'translate3d(0, calc(-1 * var(--animate-distance, 1000px)), 0)' }, 203 | }, 204 | fadeInLeft: { from: { transform: 'translate3d(-100%, 0, 0)' } }, 205 | fadeInLeftBig: { 206 | from: { transform: 'translate3d(calc(-1 * var(--animate-distance, 2000px)), 0, 0)' }, 207 | }, 208 | fadeInRight: { from: { transform: 'translate3d(100%, 0, 0)' } }, 209 | fadeInRightBig: { from: { transform: 'translate3d(var(--animate-distance, 2000px), 0, 0)' } }, 210 | fadeInUp: { from: { transform: 'translate3d(0, 100%, 0)' } }, 211 | fadeInUpBig: { from: { transform: 'translate3d(0, var(--animate-distance, 1000px), 0)' } }, 212 | fadeInTopLeft: { from: { transform: 'translate3d(-100%, -100%, 0)' } }, 213 | fadeInTopRight: { from: { transform: 'translate3d(100%, -100%, 0)' } }, 214 | fadeInBottomLeft: { from: { transform: 'translate3d(-100%, 100%, 0)' } }, 215 | fadeInBottomRight: { from: { transform: 'translate3d(100%, 100%, 0)' } }, 216 | fadeOut: {}, 217 | fadeOutDown: { to: { transform: 'translate3d(0, 100%, 0)' } }, 218 | fadeOutDownBig: { to: { transform: 'translate3d(0, var(--animate-distance, 1000px), 0)' } }, 219 | fadeOutLeft: { to: { transform: 'translate3d(-100%, 0, 0)' } }, 220 | fadeOutLeftBig: { 221 | to: { transform: 'translate3d(calc(-1 * var(--animate-distance, 2000px)), 0, 0)' }, 222 | }, 223 | fadeOutRight: { to: { transform: 'translate3d(100%, 0, 0)' } }, 224 | fadeOutRightBig: { to: { transform: 'translate3d(var(--animate-distance, 2000px), 0, 0)' } }, 225 | fadeOutUp: { to: { transform: 'translate3d(0, -100%, 0)' } }, 226 | fadeOutUpBig: { 227 | to: { transform: 'translate3d(0, calc(-1 * var(--animate-distance, 1000px)), 0)' }, 228 | }, 229 | fadeOutTopLeft: { to: { transform: 'translate3d(-100%, -100%, 0)' } }, 230 | fadeOutTopRight: { to: { transform: 'translate3d(100%, -100%, 0)' } }, 231 | fadeOutBottomRight: { to: { transform: 'translate3d(100%, 100%, 0)' } }, 232 | fadeOutBottomLeft: { to: { transform: 'translate3d(-100%, 100%, 0)' } }, 233 | flip: { 234 | from: { 235 | animationTimingFunction: 'ease-out', 236 | transform: 237 | 'perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg)', 238 | }, 239 | '40%': { 240 | animationTimingFunction: 'ease-out', 241 | transform: 242 | 'perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg)', 243 | }, 244 | '50%': { 245 | animationTimingFunction: 'ease-in', 246 | transform: 247 | 'perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg)', 248 | }, 249 | '80%': { 250 | animationTimingFunction: 'ease-in', 251 | transform: 252 | 'perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg)', 253 | }, 254 | to: { 255 | animationTimingFunction: 'ease-in', 256 | transform: 'perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg)', 257 | }, 258 | }, 259 | flipInX: { 260 | from: { 261 | animationTimingFunction: 'ease-in', 262 | transform: 'perspective(400px) rotate3d(1, 0, 0, 90deg)', 263 | }, 264 | '40%': { 265 | animationTimingFunction: 'ease-in', 266 | transform: 'perspective(400px) rotate3d(1, 0, 0, -20deg)', 267 | }, 268 | '60%': { opacity: '1', transform: 'perspective(400px) rotate3d(1, 0, 0, 10deg)' }, 269 | '80%': { transform: 'perspective(400px) rotate3d(1, 0, 0, -5deg)' }, 270 | to: { transform: 'perspective(400px)' }, 271 | }, 272 | flipInY: { 273 | from: { 274 | animationTimingFunction: 'ease-in', 275 | transform: 'perspective(400px) rotate3d(0, 1, 0, 90deg)', 276 | }, 277 | '40%': { 278 | animationTimingFunction: 'ease-in', 279 | transform: 'perspective(400px) rotate3d(0, 1, 0, -20deg)', 280 | }, 281 | '60%': { opacity: '1', transform: 'perspective(400px) rotate3d(0, 1, 0, 10deg)' }, 282 | '80%': { transform: 'perspective(400px) rotate3d(0, 1, 0, -5deg)' }, 283 | to: { transform: 'perspective(400px)' }, 284 | }, 285 | flipOutX: { 286 | from: { transform: 'perspective(400px)' }, 287 | '30%': { opacity: '1', transform: 'perspective(400px) rotate3d(1, 0, 0, -20deg)' }, 288 | to: { transform: 'perspective(400px) rotate3d(1, 0, 0, 90deg)' }, 289 | }, 290 | flipOutY: { 291 | from: { transform: 'perspective(400px)' }, 292 | '30%': { opacity: '1', transform: 'perspective(400px) rotate3d(0, 1, 0, -15deg)' }, 293 | to: { transform: 'perspective(400px) rotate3d(0, 1, 0, 90deg)' }, 294 | }, 295 | lightSpeedInRight: { 296 | from: { transform: 'translate3d(100%, 0, 0) skew(-30deg)' }, 297 | '60%': { opacity: '1', transform: 'skew(20deg)' }, 298 | '80%': { transform: 'skew(-5deg)' }, 299 | }, 300 | lightSpeedInLeft: { 301 | from: { transform: 'translate3d(-100%, 0, 0) skew(30deg)' }, 302 | '60%': { opacity: '1', transform: 'skew(-20deg)' }, 303 | '80%': { transform: 'skew(5deg)' }, 304 | }, 305 | lightSpeedOutRight: { to: { transform: 'translate3d(100%, 0, 0) skew(30deg)' } }, 306 | lightSpeedOutLeft: { to: { transform: 'translate3d(-100%, 0, 0) skew(-30deg)' } }, 307 | rotateIn: { from: { transform: 'rotate3d(0, 0, 1, -200deg)' } }, 308 | rotateInDownLeft: { from: { transform: 'rotate3d(0, 0, 1, -45deg)' } }, 309 | rotateInDownRight: { from: { transform: 'rotate3d(0, 0, 1, 45deg)' } }, 310 | rotateInUpLeft: { from: { transform: 'rotate3d(0, 0, 1, 45deg)' } }, 311 | rotateInUpRight: { from: { transform: 'rotate3d(0, 0, 1, -90deg)' } }, 312 | rotateOut: { to: { transform: 'rotate3d(0, 0, 1, 200deg)' } }, 313 | rotateOutDownLeft: { to: { transform: 'rotate3d(0, 0, 1, 45deg)' } }, 314 | rotateOutDownRight: { to: { transform: 'rotate3d(0, 0, 1, -45deg)' } }, 315 | rotateOutUpLeft: { to: { transform: 'rotate3d(0, 0, 1, -45deg)' } }, 316 | rotateOutUpRight: { to: { transform: 'rotate3d(0, 0, 1, 90deg)' } }, 317 | hinge: { 318 | '20%, 60%': { transform: 'rotate3d(0, 0, 1, 80deg)' }, 319 | '40%, 80%': { opacity: '1', transform: 'rotate3d(0, 0, 1, 60deg)' }, 320 | to: { transform: 'translate3d(0, var(--animate-distance, 1000px), 0)' }, 321 | }, 322 | jackInTheBox: { 323 | from: { 324 | transform: 'scale3d(0.1, 0.1, 1) rotate3d(0, 0, 1, 30deg)', 325 | transformOrigin: 'center bottom', 326 | }, 327 | '50%': { transform: 'rotate3d(0, 0, 1, -10deg)' }, 328 | '70%': { transform: 'rotate3d(0, 0, 1, 3deg)' }, 329 | }, 330 | rollIn: { from: { transform: 'translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg)' } }, 331 | rollOut: { to: { transform: 'translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg)' } }, 332 | zoomIn: { from: { transform: 'scale3d(0.3, 0.3, 0.3)' }, '50%': { opacity: '1' } }, 333 | zoomInDown: { 334 | from: { 335 | animationTimingFunction: 'cubic-bezier(0.55, 0.055, 0.675, 0.19)', 336 | transform: 337 | 'scale3d(0.1, 0.1, 0.1) translate3d(0, calc(-1 * var(--animate-distance, 2000px)), 0)', 338 | }, 339 | '60%': { 340 | animationTimingFunction: 'cubic-bezier(0.175, 0.885, 0.32, 1)', 341 | opacity: '1', 342 | transform: 'scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0)', 343 | }, 344 | }, 345 | zoomInLeft: { 346 | from: { 347 | animationTimingFunction: 'cubic-bezier(0.55, 0.055, 0.675, 0.19)', 348 | transform: 349 | 'scale3d(0.1, 0.1, 0.1) translate3d(calc(-1 * var(--animate-distance, 1000px)), 0, 0)', 350 | }, 351 | '60%': { 352 | animationTimingFunction: 'cubic-bezier(0.175, 0.885, 0.32, 1)', 353 | opacity: '1', 354 | transform: 'scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0)', 355 | }, 356 | }, 357 | zoomInRight: { 358 | from: { 359 | animationTimingFunction: 'cubic-bezier(0.55, 0.055, 0.675, 0.19)', 360 | transform: 'scale3d(0.1, 0.1, 0.1) translate3d(var(--animate-distance, 1000px), 0, 0)', 361 | }, 362 | '60%': { 363 | animationTimingFunction: 'cubic-bezier(0.175, 0.885, 0.32, 1)', 364 | opacity: '1', 365 | transform: 'scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0)', 366 | }, 367 | }, 368 | zoomInUp: { 369 | from: { 370 | animationTimingFunction: 'cubic-bezier(0.55, 0.055, 0.675, 0.19)', 371 | transform: 'scale3d(0.1, 0.1, 0.1) translate3d(0, var(--animate-distance, 2000px), 0)', 372 | }, 373 | '60%': { 374 | animationTimingFunction: 'cubic-bezier(0.175, 0.885, 0.32, 1)', 375 | opacity: '1', 376 | transform: 'scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0)', 377 | }, 378 | }, 379 | zoomOut: { '50%': { opacity: '0', transform: 'scale3d(0.3, 0.3, 0.3)' } }, 380 | zoomOutDown: { 381 | '40%': { 382 | animationTimingFunction: 'cubic-bezier(0.55, 0.055, 0.675, 0.19)', 383 | opacity: '1', 384 | transform: 'scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0)', 385 | }, 386 | to: { 387 | animationTimingFunction: 'cubic-bezier(0.175, 0.885, 0.32, 1)', 388 | transform: 'scale3d(0.1, 0.1, 0.1) translate3d(0, var(--animate-distance, 1000px), 0)', 389 | }, 390 | }, 391 | zoomOutLeft: { 392 | '40%': { opacity: '1', transform: 'scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0)' }, 393 | to: { 394 | transform: 395 | 'scale3d(0.1, 0.1, 1) translate3d(calc(-1 * var(--animate-distance, 2000px)), 0, 0)', 396 | }, 397 | }, 398 | zoomOutRight: { 399 | '40%': { opacity: '1', transform: 'scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0)' }, 400 | to: { transform: 'scale3d(0.1, 0.1, 1) translate3d(var(--animate-distance, 2000px), 0, 0)' }, 401 | }, 402 | zoomOutUp: { 403 | '40%': { 404 | animationTimingFunction: 'cubic-bezier(0.55, 0.055, 0.675, 0.19)', 405 | opacity: '1', 406 | transform: 'scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0)', 407 | }, 408 | to: { 409 | animationTimingFunction: 'cubic-bezier(0.175, 0.885, 0.32, 1)', 410 | transform: 411 | 'scale3d(0.1, 0.1, 0.1) translate3d(0, calc(-1 * var(--animate-distance, 1000px)), 0)', 412 | }, 413 | }, 414 | slideInDown: { from: { transform: 'translate3d(0, -100%, 0)' } }, 415 | slideInLeft: { from: { transform: 'translate3d(-100%, 0, 0)' } }, 416 | slideInRight: { from: { transform: 'translate3d(100%, 0, 0)' } }, 417 | slideInUp: { from: { transform: 'translate3d(0, 100%, 0)' } }, 418 | slideOutDown: { to: { transform: 'translate3d(0, 100%, 0)' } }, 419 | slideOutLeft: { to: { transform: 'translate3d(-100%, 0, 0)' } }, 420 | slideOutRight: { to: { transform: 'translate3d(100%, 0, 0)' } }, 421 | slideOutUp: { to: { transform: 'translate3d(0, -100%, 0)' } }, 422 | } 423 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/tailwindlabs/play.tailwindcss.com/tree/master/src/monaco/ *.d.ts 2 | 3 | import type * as CSS from 'csstype' 4 | import type * as postcss from 'postcss' 5 | 6 | export type KeyValuePair = Record 7 | 8 | export type CSSProperties = CSS.Properties & Record<`--${string}`, string> 9 | 10 | export type CSSBlock = Record 11 | 12 | export type Keyframes = Record 13 | 14 | export type ConfigUtils = { 15 | negative: (input: TInput) => TOutput 16 | breakpoints: (input: TInput) => TOutput 17 | } 18 | 19 | export type ConfigDotNotationPath = string 20 | 21 | export type ResolvableTo = 22 | | TResult 23 | | ((theme: (path: ConfigDotNotationPath) => TResult, utils: ConfigUtils) => TResult) 24 | 25 | export type BaseConfig = { 26 | important: boolean | string 27 | target: 'ie11' | 'relaxed' 28 | prefix: string | ((className: string) => string) 29 | separator: string 30 | } 31 | 32 | export type PurgeConfig = 33 | | Array 34 | | false 35 | | { enabled: boolean; mode: 'all' | 'conservative'; content: Array } 36 | | { enabled: boolean; options: { content: Array; whitelist: Array } } 37 | 38 | export type ContentConfig = 39 | | Array 40 | | { 41 | files: Array 42 | safelist?: Array }> 43 | transform?: Record string> 44 | extract?: Record Array> 45 | } 46 | 47 | export type FutureConfig = Record | 'all' | [] 48 | 49 | export type ExperimentalConfig = Record | 'all' | [] 50 | 51 | export type DarkModeConfig = 'class' | 'media' | false 52 | 53 | export type BaseThemeConfig = { 54 | extend: Partial> 55 | 56 | /** Responsiveness */ 57 | screens: ResolvableTo 58 | 59 | /** Reusable base configs */ 60 | colors: ResolvableTo>> 61 | spacing: ResolvableTo 62 | 63 | /** Background */ 64 | backgroundColor: BaseThemeConfig['colors'] 65 | backgroundImage: ResolvableTo 66 | gradientColorStops: BaseThemeConfig['colors'] 67 | backgroundOpacity: BaseThemeConfig['opacity'] 68 | backgroundPosition: ResolvableTo 69 | backgroundSize: ResolvableTo 70 | backgroundOrigin: ResolvableTo 71 | 72 | /** Border */ 73 | borderColor: BaseThemeConfig['colors'] 74 | borderOpacity: BaseThemeConfig['opacity'] 75 | borderRadius: ResolvableTo 76 | borderWidth: ResolvableTo 77 | 78 | /** Shadow */ 79 | boxShadow: ResolvableTo 80 | 81 | /** Outline */ 82 | outline: ResolvableTo 83 | 84 | /** Cursor */ 85 | cursor: ResolvableTo 86 | 87 | /** Content */ 88 | content: ResolvableTo 89 | 90 | /** Divider */ 91 | divideColor: BaseThemeConfig['borderColor'] 92 | divideOpacity: BaseThemeConfig['borderOpacity'] 93 | devideWidth: BaseThemeConfig['borderWidth'] 94 | 95 | /** SVG */ 96 | fill: ResolvableTo 97 | stroke: ResolvableTo 98 | strokeWidth: ResolvableTo 99 | 100 | /** Flexbox */ 101 | flex: ResolvableTo 102 | flexGrow: ResolvableTo 103 | flexShrink: ResolvableTo 104 | 105 | /** Fonts */ 106 | fontFamily: ResolvableTo>> 107 | fontSize: ResolvableTo 108 | fontWeight: ResolvableTo 109 | 110 | /** Sizes */ 111 | height: BaseThemeConfig['spacing'] 112 | minHeight: ResolvableTo 113 | maxHeight: ResolvableTo 114 | width: BaseThemeConfig['spacing'] 115 | minWidth: ResolvableTo 116 | maxWidth: ResolvableTo 117 | aspectRatio: ResolvableTo 118 | 119 | /** Positioning */ 120 | inset: ResolvableTo 121 | zIndex: ResolvableTo 122 | 123 | /** Text */ 124 | letterSpacing: ResolvableTo 125 | lineHeight: ResolvableTo 126 | textColor: BaseThemeConfig['colors'] 127 | textOpacity: BaseThemeConfig['opacity'] 128 | textIndent: BaseThemeConfig['spacing'] 129 | 130 | /** Input */ 131 | placeholderColor: BaseThemeConfig['colors'] 132 | placeholderOpacity: BaseThemeConfig['opacity'] 133 | caretColor: BaseThemeConfig['colors'] 134 | 135 | /** Lists */ 136 | listStyleType: ResolvableTo 137 | 138 | /** Layout */ 139 | margin: BaseThemeConfig['spacing'] 140 | padding: BaseThemeConfig['spacing'] 141 | space: BaseThemeConfig['spacing'] 142 | opacity: ResolvableTo 143 | order: ResolvableTo 144 | columns: ResolvableTo 145 | 146 | /** Images */ 147 | objectPosition: ResolvableTo 148 | 149 | /** Grid */ 150 | gap: BaseThemeConfig['spacing'] 151 | gridTemplateColumns: ResolvableTo 152 | gridColumn: ResolvableTo 153 | gridColumnStart: ResolvableTo 154 | gridColumnEnd: ResolvableTo 155 | gridTemplateRows: ResolvableTo 156 | gridRow: ResolvableTo 157 | gridRowStart: ResolvableTo 158 | gridRowEnd: ResolvableTo 159 | 160 | /** Transformations */ 161 | transformOrigin: ResolvableTo 162 | scale: ResolvableTo 163 | rotate: ResolvableTo 164 | translate: BaseThemeConfig['spacing'] 165 | skew: ResolvableTo 166 | 167 | /** Transitions */ 168 | transitionProperty: ResolvableTo 169 | transitionTimingFunction: ResolvableTo 170 | transitionDuration: ResolvableTo 171 | transitionDelay: ResolvableTo 172 | willChange: ResolvableTo 173 | 174 | /** Animations */ 175 | animation: ResolvableTo 176 | keyframes: ResolvableTo 177 | 178 | /** Filters */ 179 | blur: ResolvableTo | string>> 180 | brightness: ResolvableTo | string>> 181 | contrast: ResolvableTo | string>> 182 | dropShadow: ResolvableTo | string>> 183 | grayscale: ResolvableTo | string>> 184 | hueRotate: ResolvableTo | string>> 185 | invert: ResolvableTo | string>> 186 | saturate: ResolvableTo | string>> 187 | sepia: ResolvableTo | string>> 188 | backdropFilter: ResolvableTo | string>> 189 | backdropBlur: ResolvableTo | string>> 190 | backdropBrightness: ResolvableTo | string>> 191 | backdropContrast: ResolvableTo | string>> 192 | backdropGrayscale: ResolvableTo | string>> 193 | backdropHueRotate: ResolvableTo | string>> 194 | backdropInvert: ResolvableTo | string>> 195 | backdropOpacity: ResolvableTo | string>> 196 | backdropSaturate: ResolvableTo | string>> 197 | backdropSepia: ResolvableTo | string>> 198 | 199 | /** Components */ 200 | container: Partial<{ 201 | screens: Array | Record | Record 202 | center: boolean 203 | padding: KeyValuePair | string 204 | }> 205 | } 206 | 207 | export type ThemeConfig = Partial> 208 | 209 | export type VariantsAPI = { 210 | variants: (path: string) => Array 211 | 212 | before: ( 213 | toInsert: Array, 214 | variant?: string, 215 | existingPluginVariants?: Array, 216 | ) => Array 217 | 218 | after: ( 219 | toInsert: Array, 220 | variant?: string, 221 | existingPluginVariants?: Array, 222 | ) => Array 223 | 224 | without: (toRemove: Array, existingPluginVariants?: Array) => Array 225 | } 226 | 227 | export type VariantsConfig = 228 | | Array 229 | | Record | ((api: VariantsAPI) => Array)> 230 | | { extend: Record> } 231 | 232 | export type CorePluginsConfig = Array | Record 233 | 234 | export type VariantConfig = 235 | | Array 236 | | Partial<{ variants: Array; respectPrefix: false; respectImportant: false }> 237 | 238 | export type ValueType = 239 | | 'absolute-size' 240 | | 'any' 241 | | 'color' 242 | | 'family-name' 243 | | 'generic-name' 244 | | 'image' 245 | | 'length' 246 | | 'line-width' 247 | | 'lookup' 248 | | 'number' 249 | | 'percentage' 250 | | 'position' 251 | | 'relative-size' 252 | | 'url' 253 | 254 | export type PluginAPI = { 255 | /** Get access to the whole config */ 256 | config: ( 257 | path?: ConfigDotNotationPath, 258 | defaultValue?: TDefaultValue, 259 | ) => TDefaultValue 260 | 261 | /** Escape classNames */ 262 | e: (className: string) => string 263 | 264 | /** Shortcut for the theme section of the config */ 265 | theme: (path: ConfigDotNotationPath, defaultValue?: TDefaultValue) => TDefaultValue 266 | 267 | variants: ( 268 | path: ConfigDotNotationPath, 269 | defaultValue: TDefaultValue, 270 | ) => TDefaultValue 271 | 272 | target: (path: ConfigDotNotationPath) => string 273 | 274 | prefix: (selector: string) => string 275 | 276 | /** Ability to add utilities. E.g.: .p-4 */ 277 | addUtilities: (utilities: CSSBlock, variantConfig?: VariantConfig) => void 278 | 279 | /** Ability to add components. E.g.: .btn */ 280 | addComponents: (components: CSSBlock, variantConfig?: VariantConfig) => void 281 | 282 | addBase: (base: CSSBlock) => void 283 | 284 | addVariant: ( 285 | name: string, 286 | generator: (api: { 287 | container: postcss.Container 288 | separator: string 289 | modifySelectors: ( 290 | modifierFunction: (api: { className: string; selector: string }) => void, 291 | ) => void 292 | }) => void, 293 | ) => void 294 | 295 | matchUtilities: ( 296 | utilities: Record CSSProperties>, 297 | options?: Partial<{ 298 | values: Record 299 | type: Array | ValueType 300 | respectPrefix: boolean 301 | respectImportant: boolean 302 | respectVariants: boolean 303 | }>, 304 | ) => void 305 | 306 | corePlugins: (path: string) => boolean 307 | 308 | postcss: typeof postcss 309 | } 310 | 311 | export type PluginCreator = (api: PluginAPI) => void 312 | 313 | export type PluginsConfig = Array< 314 | PluginCreator | { handler: PluginCreator; config?: TailwindConfig } 315 | > 316 | 317 | /** The holy grail Tailwind config definition */ 318 | export type TailwindConfig = Partial< 319 | BaseConfig & 320 | Record & { 321 | presets: Array 322 | future: FutureConfig 323 | experimental: ExperimentalConfig 324 | purge: PurgeConfig 325 | content: ContentConfig 326 | darkMode: DarkModeConfig 327 | theme: ThemeConfig 328 | variants: VariantsConfig 329 | corePlugins: CorePluginsConfig 330 | plugins: PluginsConfig 331 | mode: 'aot' | 'jit' 332 | } 333 | > 334 | 335 | export type EntryPoint = (config: TailwindConfig) => TailwindConfig 336 | -------------------------------------------------------------------------------- /src/utilities.ts: -------------------------------------------------------------------------------- 1 | import type { CSSBlock } from './types.js' 2 | 3 | export const keyframeUtils: CSSBlock = { 4 | twSpin: { animationTimingFunction: 'linear' }, 5 | twPing: { animationTimingFunction: 'cubic-bezier(0, 0, 0.2, 1)' }, 6 | twPulse: { animationDuration: '2s', animationTimingFunction: 'cubic-bezier(0.4, 0, 0.6, 1)' }, 7 | bounce: { transformOrigin: 'center bottom' }, 8 | pulse: { animationTimingFunction: 'ease-in-out' }, 9 | headShake: { animationTimingFunction: 'ease-in-out' }, 10 | swing: { transformOrigin: 'top center' }, 11 | jello: { transformOrigin: 'center' }, 12 | heartBeat: { animationDuration: '1.3s', animationTimingFunction: 'ease-in-out' }, 13 | bounceIn: { 14 | animationDuration: '0.75s', 15 | animationTimingFunction: 'cubic-bezier(0.215, 0.61, 0.355, 1)', 16 | }, 17 | bounceInDown: { animationTimingFunction: 'cubic-bezier(0.215, 0.61, 0.355, 1)' }, 18 | bounceInLeft: { animationTimingFunction: 'cubic-bezier(0.215, 0.61, 0.355, 1)' }, 19 | bounceInRight: { animationTimingFunction: 'cubic-bezier(0.215, 0.61, 0.355, 1)' }, 20 | bounceInUp: { animationTimingFunction: 'cubic-bezier(0.215, 0.61, 0.355, 1)' }, 21 | bounceOut: { animationDuration: '0.75s' }, 22 | flip: { backfaceVisibility: 'visible' }, 23 | flipInX: { backfaceVisibility: 'visible' }, 24 | flipInY: { backfaceVisibility: 'visible' }, 25 | flipOutX: { animationDuration: '0.75s', backfaceVisibility: 'visible' }, 26 | flipOutY: { animationDuration: '0.75s', backfaceVisibility: 'visible' }, 27 | lightSpeedInRight: { animationTimingFunction: 'ease-out' }, 28 | lightSpeedInLeft: { animationTimingFunction: 'ease-out' }, 29 | lightSpeedOutRight: { animationTimingFunction: 'ease-in' }, 30 | lightSpeedOutLeft: { animationTimingFunction: 'ease-in' }, 31 | rotateIn: { transformOrigin: 'center' }, 32 | rotateInDownLeft: { transformOrigin: 'left bottom' }, 33 | rotateInDownRight: { transformOrigin: 'right bottom' }, 34 | rotateInUpLeft: { transformOrigin: 'left bottom' }, 35 | rotateInUpRight: { transformOrigin: 'right bottom' }, 36 | rotateOut: { transformOrigin: 'center' }, 37 | rotateOutDownLeft: { transformOrigin: 'left bottom' }, 38 | rotateOutDownRight: { transformOrigin: 'right bottom' }, 39 | rotateOutUpLeft: { transformOrigin: 'left bottom' }, 40 | rotateOutUpRight: { transformOrigin: 'right bottom' }, 41 | hinge: { 42 | animationDuration: '2s', 43 | animationTimingFunction: 'ease-in-out', 44 | transformOrigin: 'top left', 45 | }, 46 | zoomOutDown: { transformOrigin: 'center bottom' }, 47 | zoomOutLeft: { transformOrigin: 'left center' }, 48 | zoomOutRight: { transformOrigin: 'right center' }, 49 | zoomOutUp: { transformOrigin: 'center bottom' }, 50 | } 51 | 52 | export const animationUtils: CSSBlock = { 53 | none: { animation: 'none' }, 54 | 55 | faster: { animationDuration: '0.5s' }, 56 | fast: { animationDuration: '0.8s' }, 57 | slow: { animationDuration: '2s' }, 58 | slower: { animationDuration: '3s' }, 59 | 60 | ease: { animationTimingFunction: 'cubic-bezier(.25,.1,.25,1)' }, 61 | 62 | infinite: { animationIterationCount: 'infinite' }, 63 | 64 | normal: { animationDirection: 'normal' }, 65 | reverse: { animationDirection: 'reverse' }, 66 | alternate: { animationDirection: 'alternate' }, 67 | 'alternate-reverse': { animationDirection: 'alternate-reverse' }, 68 | 69 | paused: { animationPlayState: 'paused' }, 70 | running: { animationPlayState: 'running' }, 71 | } 72 | -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | const { withAnimations } = require('.') 2 | 3 | module.exports = withAnimations({ 4 | // prefix: 'tw-', 5 | content: ['./docs/.vitepress/theme/*.vue'], 6 | safelist: [{ pattern: /animate-.*/ }], 7 | }) 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node12/tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "src", 5 | "declaration": true, 6 | "exactOptionalPropertyTypes": true, 7 | "outDir": "dist", 8 | "skipLibCheck": false 9 | }, 10 | "exclude": ["dist"] 11 | } 12 | --------------------------------------------------------------------------------