Full Code of formkit/auto-animate for AI

master 9df29722052a cached
160 files
338.9 KB
116.7k tokens
97 symbols
1 requests
Download .txt
Showing preview only (375K chars total). Download the full file or copy to clipboard to get everything.
Repository: formkit/auto-animate
Branch: master
Commit: 9df29722052a
Files: 160
Total size: 338.9 KB

Directory structure:
gitextract_185zpymh/

├── .cursorrules
├── .dmux-hooks/
│   ├── AGENTS.md
│   ├── CLAUDE.md
│   ├── README.md
│   └── examples/
│       ├── post_merge.example
│       ├── run_dev.example
│       ├── run_test.example
│       └── worktree_created.example
├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .npmignore
├── .npmrc
├── .prettierrc
├── LICENSE
├── README.md
├── build/
│   ├── build-nuxt.ts
│   ├── build.mjs
│   ├── bundle.ts
│   └── nuxt-playground/
│       ├── app.vue
│       ├── nuxt.config.ts
│       ├── package.json
│       └── tsconfig.json
├── docs/
│   ├── assets/
│   │   ├── fonts.css
│   │   ├── main.css
│   │   ├── prism.css
│   │   ├── prism.js
│   │   └── variables.css
│   ├── index.html
│   ├── src/
│   │   ├── App.vue
│   │   ├── components/
│   │   │   ├── AsideTip.vue
│   │   │   ├── CodeExample.vue
│   │   │   ├── ColorModeToggle.vue
│   │   │   ├── FormKitLogo.vue
│   │   │   ├── GitHubLogo.vue
│   │   │   ├── HeroTitle.vue
│   │   │   ├── IconAngular.vue
│   │   │   ├── IconArrow.vue
│   │   │   ├── IconBun.vue
│   │   │   ├── IconDiscord.vue
│   │   │   ├── IconDown.vue
│   │   │   ├── IconHTML.vue
│   │   │   ├── IconJavaScript.vue
│   │   │   ├── IconLightbulb.vue
│   │   │   ├── IconMoon.vue
│   │   │   ├── IconNPM.vue
│   │   │   ├── IconNuxt.vue
│   │   │   ├── IconOutbound.vue
│   │   │   ├── IconPNPM.vue
│   │   │   ├── IconPreact.vue
│   │   │   ├── IconQwik.vue
│   │   │   ├── IconReact.vue
│   │   │   ├── IconRemove.vue
│   │   │   ├── IconSolid.vue
│   │   │   ├── IconSun.vue
│   │   │   ├── IconSvelte.vue
│   │   │   ├── IconTwitter.vue
│   │   │   ├── IconVue.vue
│   │   │   ├── IconYarn.vue
│   │   │   ├── KickstartPromo.vue
│   │   │   ├── Navigation.vue
│   │   │   ├── PoliteAd.vue
│   │   │   ├── ReducedMotionWarning.vue
│   │   │   ├── TempoPromo.vue
│   │   │   ├── TheFooter.vue
│   │   │   ├── TheHeader.vue
│   │   │   └── TheLogo.vue
│   │   ├── examples/
│   │   │   ├── accordion/
│   │   │   │   └── ActualAccordion.vue
│   │   │   ├── angular/
│   │   │   │   ├── ActualAngularApp.vue
│   │   │   │   └── index.ts
│   │   │   ├── basic/
│   │   │   │   ├── basic.ts
│   │   │   │   └── index.ts
│   │   │   ├── boxes/
│   │   │   │   └── ActualBoxes.vue
│   │   │   ├── cards/
│   │   │   │   └── ActualCards.vue
│   │   │   ├── config/
│   │   │   │   └── index.ts
│   │   │   ├── disable/
│   │   │   │   ├── ActualDisable.vue
│   │   │   │   ├── disable.html
│   │   │   │   ├── disable.jsx
│   │   │   │   ├── disable.vue
│   │   │   │   └── index.ts
│   │   │   ├── dropdown/
│   │   │   │   ├── ActualDropdown.vue
│   │   │   │   ├── dropdown-solid.tsx
│   │   │   │   ├── dropdown.html
│   │   │   │   ├── dropdown.jsx
│   │   │   │   ├── dropdown.vue
│   │   │   │   └── index.ts
│   │   │   ├── first-demo/
│   │   │   │   ├── ActualDemo.vue
│   │   │   │   ├── Arrow.vue
│   │   │   │   ├── Close.vue
│   │   │   │   └── FrameworkList.vue
│   │   │   ├── formkit/
│   │   │   │   └── ActualFormKit.vue
│   │   │   ├── installation/
│   │   │   │   └── index.ts
│   │   │   ├── intro/
│   │   │   │   ├── index.ts
│   │   │   │   ├── intro-preact.jsx
│   │   │   │   ├── intro-solid.jsx
│   │   │   │   ├── intro.angular
│   │   │   │   ├── intro.html
│   │   │   │   ├── intro.jsx
│   │   │   │   ├── intro.svelte
│   │   │   │   └── intro.vue
│   │   │   ├── list/
│   │   │   │   └── ActualList.vue
│   │   │   ├── plugin/
│   │   │   │   ├── ActualPlugin.vue
│   │   │   │   └── index.ts
│   │   │   ├── preact/
│   │   │   │   ├── ActualPreactApp.vue
│   │   │   │   └── index.ts
│   │   │   ├── qwik/
│   │   │   │   └── index.ts
│   │   │   ├── react/
│   │   │   │   ├── ActualReactApp.vue
│   │   │   │   └── index.ts
│   │   │   ├── solid/
│   │   │   │   ├── ActualSolidApp.vue
│   │   │   │   └── index.ts
│   │   │   ├── svelte/
│   │   │   │   ├── ActualSvelteApp.vue
│   │   │   │   └── index.ts
│   │   │   └── vue/
│   │   │       ├── ActualVueApp.vue
│   │   │       ├── ActualVueAppHook.vue
│   │   │       └── index.ts
│   │   ├── global.d.ts
│   │   ├── main.ts
│   │   ├── pages/
│   │   │   ├── PageBottomJumpTest.vue
│   │   │   ├── PageHome.vue
│   │   │   ├── PageList.vue
│   │   │   ├── PageTestKeepAlive.vue
│   │   │   ├── PageTests.vue
│   │   │   └── test-components/
│   │   │       ├── CompOne.vue
│   │   │       └── CompTwo.vue
│   │   └── sections/
│   │       ├── SectionExamples.vue
│   │       ├── SectionInstallation.vue
│   │       ├── SectionPlugins.vue
│   │       ├── SectionUsage.vue
│   │       └── SectionWhy.vue
│   ├── vite.config.ts
│   └── vite.config.ts.js
├── package.json
├── playwright.config.ts
├── rollup.config.js
├── src/
│   ├── angular/
│   │   └── index.ts
│   ├── debug-utils.ts
│   ├── index.ts
│   ├── nuxt/
│   │   ├── module.ts
│   │   └── runtime/
│   │       └── plugin.ts
│   ├── preact/
│   │   └── index.ts
│   ├── qwik/
│   │   └── index.ts
│   ├── react/
│   │   └── index.ts
│   ├── solid/
│   │   └── index.ts
│   └── vue/
│       └── index.ts
├── tests/
│   └── e2e/
│       ├── animations.spec.ts
│       ├── bottom-jump-fix.spec.ts
│       ├── disable.spec.ts
│       ├── exports.spec.ts
│       ├── framework-animations.spec.ts
│       ├── frameworks.spec.ts
│       ├── memory.spec.ts
│       ├── offscreen.spec.ts
│       ├── utils.ts
│       ├── visual-animation-video.spec.ts
│       ├── visual-animation.spec.ts
│       ├── visual-video.util.ts
│       ├── vue-plugin.spec.ts
│       └── vue-vif.spec.ts
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .cursorrules
================================================
### Project overview
- **Purpose**: Zero-config motion for DOM list changes. Given a parent element, automatically animates its immediate children when they are added, removed, or moved.
- **Core entry**: `src/index.ts` exports `autoAnimate(el, configOrPlugin)` and types, plus a Vue directive `vAutoAnimate`.
- **Framework adapters**: Thin wrappers providing hooks/directives for Vue, React, Solid, Preact, Angular, Qwik under `src/<framework>/index.ts`.
- **Build**: TS → ESM via Rollup; built artifacts land in `dist/`. Package `exports` map serves `index.mjs` and framework subpaths.

### Mental model (how it works)
- **Observers**
  - MutationObserver on the parent watches childList changes. For each mutation, `getElements` collects the parent and child elements that changed (including removed ones), tagging each with a non-enumerable target marker `__aa_tgt`.
  - ResizeObserver on `document.documentElement` (root) and on each observed element updates cached positions when sizes change.
  - IntersectionObserver is created per element to detect position changes while scrolling; a dynamic `rootMargin` derived from the last known coordinates triggers recalculation. Occasional low-priority polling backs this up.
- **State tracking** (all with WeakMap/WeakSet to avoid leaks)
  - `coords`: last known absolute coordinates adjusted for nearest scrolling ancestor.
  - `siblings`: prev/next references for elements removed from the DOM so they can be temporarily reinserted for exit animations.
  - `animations`: current Web Animations API `Animation` per element.
  - `intersections`, `intervals`, `debounces`: observers/intervals/timers per element.
  - `options`: the per-parent config or plugin; `enabled`: parents with animations enabled.
- **Deciding what to animate**
  - `animate(el)` selects one of: `add`, `remain`, or `remove` based on whether the element has cached coordinates and whether it’s still connected.
  - Flags: `__aa_new` marks newly reinserted nodes to ensure their next cycle is treated as an entry; `__aa_del` marks nodes currently animating out.
- **Effects**
  - Default behavior uses Web Animations API: `add` scales/ fades in; `remain` uses FLIP-style transforms (translate from old to new), also animates width/height deltas respecting `box-sizing`; `remove` temporarily re-inserts the node near its original position, absolutely positions it, and scales/fades out.
  - Plugins: if `config` is a function, it’s treated as an `AutoAnimationPlugin`. Plugin functions return a `KeyframeEffect` or `[KeyframeEffect, { styleReset | false }]`. The library will construct and play an `Animation` from the effect and handle optional style resets.
- **Scroll handling**
  - Coordinates are absolute plus the nearest scrollable ancestor’s offset.
  - During removal at page bottom, the library compensates for scroll jumps by snapshotting pre/post window scroll and performing a manual scroll animation to match the configured duration/easing.
- **Options & accessibility**
  - Defaults: `{ duration: 250, easing: 'ease-in-out' }`.
  - Respects `prefers-reduced-motion: reduce` unless `disrespectUserMotionPreference: true` or a plugin is used.
  - `AnimationController` controls enable/disable per parent.

### Public API surface
- **Default export**: `autoAnimate(el: HTMLElement, config?: Partial<AutoAnimateOptions> | AutoAnimationPlugin): AnimationController`
- **Types**: `AutoAnimateOptions`, `AutoAnimationPlugin`, `AutoAnimationPluginOptions`, `AnimationController`.
- **Vue**: `vAutoAnimate` directive, `autoAnimatePlugin`, `useAutoAnimate` hook.
- **React/Preact**: `useAutoAnimate` hook returns `[refCallback | refObject, setEnabled]`.
- **Solid**: `createAutoAnimate` and `createAutoAnimateDirective`.
- **Angular**: `AutoAnimateDirective` (`[auto-animate]`).
- **Qwik**: `useAutoAnimate` returns `[Signal<HTMLElement>, setEnabledQRL]`.
- **Nuxt**: module that registers the Vue directive and auto-imports `autoAnimate` and `useAutoAnimate`.

### Key invariants and conventions
- Do not mutate children beyond adding style resets for exit animations; remove those styles in `cleanUp`.
- All per-node state is in WeakMaps/Sets to prevent memory leaks; never store strong references to DOM nodes outside these registries.
- Only immediate children of the target parent are animated; traversal utilities (`forEach`) visit the parent first, then its children.
- Always schedule position updates after animations finish (`animation.addEventListener('finish', updatePos)`), and debounce updates using the current duration (or 500ms for plugins).
- When computing size deltas, use `getTransitionSizes` to respect `box-sizing: content-box` padding/borders.
- Tagging properties `__aa_tgt`, `__aa_del`, `__aa_new` are non-enumerable and must be defined via `Object.defineProperty`.
- Core must remain framework-agnostic; adapters import from `../index` only.

### Files and what lives where
- `src/index.ts`: All core logic and types; also exports a Vue directive for convenience.
- `src/debug-utils.ts`: Optional dev-time helpers (e.g., `drawMargins`) to visualize IntersectionObserver margins.
- `src/{vue,react,preact,solid,angular,qwik}/index.ts`: Framework bindings.
- `src/nuxt/{module.ts,runtime/plugin.ts}`: Nuxt module and runtime plugin.
- `docs/`: Vite/Vue demo and docs site.
- `cypress/`: E2E tests for docs/examples.
- `rollup.config.js`: Build configuration; `FRAMEWORK`, `DECLARATIONS`, and `MIN` env flags control outputs.
- `package.json`: Exports map and scripts.

### How to run
- **Install**: `pnpm install`.
- **Docs (playground)**: `pnpm dev` (runs Vite in `docs/`).
- **Build library**: `pnpm build` (runs `node ./build/build.mjs`).
- **Build docs**: `pnpm build-docs`.
- **Cypress**: in one terminal `pnpm cypress:server` (docs dev server), in another `pnpm cypress:open`.
- **Nuxt playground**: `pnpm nuxt:dev` (if playground present).

### Adding or changing behavior
- **Modify default animations**: adjust `add`, `remain`, `remove` in `src/index.ts`. Maintain invariants around style resets and cleanup. Ensure `updatePos` is called after each animation to keep `coords` fresh and observers connected.
- **Plugins**: The plugin signature is the extension point. If adding plugin options, keep the tuple return backwards-compatible. Only treat `config` as plugin when it’s a function.
- **Performance**: Be careful changing IntersectionObserver `threshold`/`rootMargin`; it’s tuned to avoid excessive updates and to catch movement. Use `lowPriority` for non-critical updates.
- **Accessibility**: Keep the `prefers-reduced-motion` guard; only bypass if explicitly configured.

### Common pitfalls
- Forgetting to re-observe or update positions after animation causes stale `coords` and erratic flips. Always call `updatePos` on `finish`.
- Mutating layout-affecting styles outside of animations can desync computed sizes. Prefer transform/opacity for motion; animate width/height only through `getTransitionSizes` path.
- Not accounting for scroll in coords leads to incorrect deltas. Always use `getCoords` and `getScrollOffset` utilities.
- Exit animations must temporarily reinsert the element and absolutely position it; skipping style reset or cleanup leaks styles into future reuses of that node.

### Coding style
- TypeScript strict; avoid `any` in public APIs.
- Clear, descriptive names; early returns for edge cases.
- Keep core free of framework-specific imports.
- Comments explain “why” when logic is subtle (e.g., scroll compensation), not trivial “how”.

### Testing guidance
- Prefer adding example scenarios in `docs/` for manual verification.
- E2E flows live in `cypress/integration`; add/extend specs that exercise add/remove/reorder, variable heights, nested scroll containers, and reduced-motion.

### Triage checklist for bugs
- Repro in `docs/` with a minimal list/grid.
- Check if prefers-reduced-motion disabled animations.
- Verify parent element has `position` not left `static` when required (core sets to `relative` if static).
- Inspect `coords` freshness (use `updatePos` logs or `debug-utils`).
- Confirm scroll compensation path when removing near viewport bottom.

### External APIs used
- Web Animations API (`Element.prototype.animate`, `Animation`, `KeyframeEffect`).
- `MutationObserver`, `ResizeObserver`, `IntersectionObserver`.
- `requestIdleCallback` (fallback to `requestAnimationFrame`).

### Release & packaging
- Build uses Rollup; env flags:
  - `FRAMEWORK=index|vue|react|preact|solid|angular|qwik` controls entry file.
  - `DECLARATIONS=true` emits types only.
  - `MIN=true` emits minified `.min.js`.
- `package.json#exports` serves subpath entries (`./vue`, `./react`, etc.).

### Security & SSR
- Core guards on `window` and `ResizeObserver` presence; no-ops in unsupported/non-browser contexts.
- Vue directive exposes `getSSRProps` to be SSR-safe.

### Docs site (Vite + Vue SSG)
- **Architecture**: A separate Vue 3 SPA in `docs/` built and statically generated with Vite + `vite-ssg`. It produces a fully static site (no server required at runtime).
- **Entry points**:
  - `docs/index.html` is the HTML shell that loads `/src/main.ts`.
  - `docs/src/main.ts` uses `ViteSSG(App, { routes }, setup)` to register routes and install the FormKit Vue plugin.
  - `docs/src/App.vue` renders a `RouterView` and site chrome (header/footer/announcement).
- **Routing**:
  - Routes are declared in `docs/src/main.ts` via an array of `RouteRecordRaw`.
  - Current routes: `/` → `PageHome.vue`, `/lists` → `PageList.vue`, `/tests` → `PageTests.vue`, `/tests-keep-alive` → `PageTestKeepAlive.vue` (some loaded via dynamic import for code-splitting).
  - `vite.config.ts` sets `ssgOptions.includeAllRoutes = true`, so all known routes are pre-rendered during `vite-ssg build`.
- **Content structure**:
  - `docs/src/pages/`: top-level pages composing sections and examples.
  - `docs/src/sections/`: content sections used on the home page (installation, usage, examples, plugins, why).
  - `docs/src/components/`: UI components (navigation, header/footer, icons, code example wrapper, etc.).
  - `docs/src/examples/`: live examples/demos per framework, showing how to use `@formkit/auto-animate` in practice.
  - Global styles under `docs/assets/` (`main.css`, `variables.css`, `prism.css`), images under `docs/assets/img/`, and fonts under `docs/assets/fonts/`.
- **Third-party integrations**:
  - `@vitejs/plugin-vue` for Vue SFCs.
  - `vite-ssg` for static generation.
  - `@formkit/vue` plugin registered in the SSG setup.
  - PrismJS loaded via `<script>` in `index.html` for code highlighting; GitHub buttons via their script; a site script tag is included for analytics.
- **Dev/build commands** (from `package.json`):
  - Dev playground: `pnpm dev` → `cd docs && vite --config=./vite.config.ts`.
  - Static build: `pnpm build-docs` → `cd docs && vite-ssg build --config=./vite.config.ts` (outputs static assets to the default Vite output directory).
  - Cypress E2E: start docs dev server `pnpm cypress:server` (port 5555), then run `pnpm cypress:open`.
- **How examples reference the library**:
  - Examples import from `@formkit/auto-animate` (and subpaths) to demonstrate public API usage. During local development, ensure the library is built (`pnpm build`) if the examples need the latest compiled artifacts; otherwise Vite may resolve from the package cache.
- **Deployment**:
  - The generated static output can be deployed to any static host (Netlify, Cloudflare Pages, GitHub Pages). No server logic is required.


================================================
FILE: .dmux-hooks/AGENTS.md
================================================
# dmux Hooks System - Agent Reference

**Auto-generated documentation for AI agents**

This document contains everything an AI agent needs to create, modify, and understand dmux hooks. It is automatically generated from the dmux source code and embedded in the binary.

## What You're Working On

You are editing hooks for **dmux**, a tmux pane manager that creates AI-powered development workflows. Each pane runs in its own git worktree with an AI agent (Claude Code or opencode).

## Your Goal

Create executable bash scripts in `.dmux-hooks/` that run automatically at key lifecycle events.

## Quick Start

1. **Create a hook file**: `touch .dmux-hooks/worktree_created`
2. **Make it executable**: `chmod +x .dmux-hooks/worktree_created`
3. **Add shebang**: Start with `#!/bin/bash`
4. **Use environment variables**: Access `$DMUX_ROOT`, `$DMUX_WORKTREE_PATH`, etc.
5. **Test it**: Set env vars manually and run the script

## Hook Execution Model

- **Non-blocking**: Hooks run in background (detached processes)
- **Silent failures**: Hook errors are logged but don't stop dmux
- **Environment-based**: All context passed via environment variables
- **Version controlled**: Hooks in `.dmux-hooks/` are shared with team
- **Priority resolution**: `.dmux-hooks/` → `.dmux/hooks/` → `~/.dmux/hooks/`

## Available Hooks

### Pane Lifecycle Hooks

| Hook | When | Common Use Cases |
|------|------|------------------|
| `before_pane_create` | Before pane creation | Validation, notifications, pre-flight checks |
| `pane_created` | After pane, before worktree | Configure tmux settings, prepare environment |
| `worktree_created` | After full setup | Install deps, copy configs, setup git |
| `before_pane_close` | Before closing | Save state, backup uncommitted work |
| `pane_closed` | After closed | Cleanup resources, analytics, notifications |

### Worktree Lifecycle Hooks

| Hook | When | Common Use Cases |
|------|------|------------------|
| `before_worktree_remove` | Before worktree removal | Archive worktree, save artifacts |
| `worktree_removed` | After worktree removed | Cleanup external references |

### Merge Lifecycle Hooks

| Hook | When | Common Use Cases |
|------|------|------------------|
| `pre_merge` | Before merge operation | Run final tests, create backups |
| `post_merge` | After successful merge | Deploy, close issues, notify team |

### Interactive Hooks (with HTTP callbacks)

| Hook | When | Common Use Cases |
|------|------|------------------|
| `run_test` | When tests triggered | Run test suite, report status via HTTP |
| `run_dev` | When dev server triggered | Start dev server, create tunnel, report URL |


## Environment Variables

### Always Available
```bash
DMUX_ROOT="/path/to/project"           # Project root directory
DMUX_SERVER_PORT="3142"                # HTTP server port
```

### Pane Context (most hooks)
```bash
DMUX_PANE_ID="dmux-1234567890"         # dmux pane identifier
DMUX_SLUG="fix-auth-bug"               # Branch/worktree name
DMUX_PROMPT="Fix authentication bug"   # User's prompt
DMUX_AGENT="claude"                    # Agent type (claude|opencode)
DMUX_TMUX_PANE_ID="%38"                # tmux pane ID
```

### Worktree Context
```bash
DMUX_WORKTREE_PATH="/path/.dmux/worktrees/fix-auth-bug"
DMUX_BRANCH="fix-auth-bug"             # Same as slug
```

### Merge Context
```bash
DMUX_TARGET_BRANCH="main"              # Branch being merged into
```

## HTTP Callback API

Interactive hooks (`run_test` and `run_dev`) can update dmux UI via HTTP.

### Update Test Status
```bash
curl -X PUT "http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test"   -H "Content-Type: application/json"   -d '{"status": "running", "output": "optional test output"}'

# Status values: "running" | "passed" | "failed"
```

### Update Dev Server
```bash
curl -X PUT "http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev"   -H "Content-Type: application/json"   -d '{"status": "running", "url": "http://localhost:3000"}'

# Status values: "running" | "stopped"
# url: Can be localhost or tunnel URL (ngrok, cloudflared, etc.)
```

## Common Patterns

### Pattern 1: Install Dependencies
```bash
#!/bin/bash
# .dmux-hooks/worktree_created

cd "$DMUX_WORKTREE_PATH"

if [ -f "pnpm-lock.yaml" ]; then
  pnpm install --prefer-offline &
elif [ -f "package-lock.json" ]; then
  npm install &
elif [ -f "yarn.lock" ]; then
  yarn install &
elif [ -f "Gemfile" ]; then
  bundle install &
elif [ -f "requirements.txt" ]; then
  pip install -r requirements.txt &
elif [ -f "Cargo.toml" ]; then
  cargo build &
fi
```

### Pattern 2: Copy Configuration
```bash
#!/bin/bash
# .dmux-hooks/worktree_created

# Copy environment file
if [ -f "$DMUX_ROOT/.env.local" ]; then
  cp "$DMUX_ROOT/.env.local" "$DMUX_WORKTREE_PATH/.env.local"
fi

# Copy other config files
for file in .env.development .npmrc .yarnrc; do
  if [ -f "$DMUX_ROOT/$file" ]; then
    cp "$DMUX_ROOT/$file" "$DMUX_WORKTREE_PATH/$file"
  fi
done
```

### Pattern 3: Run Tests with Status Updates
```bash
#!/bin/bash
# .dmux-hooks/run_test

set -e
cd "$DMUX_WORKTREE_PATH"
API="http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test"

# Update: starting
curl -s -X PUT "$API" -H "Content-Type: application/json"   -d '{"status": "running"}' > /dev/null

# Run tests and capture output
OUTPUT_FILE="/tmp/dmux-test-$DMUX_PANE_ID.txt"
if pnpm test > "$OUTPUT_FILE" 2>&1; then
  STATUS="passed"
else
  STATUS="failed"
fi

# Get output (truncate if too long)
OUTPUT=$(head -c 5000 "$OUTPUT_FILE")

# Update: complete
curl -s -X PUT "$API" -H "Content-Type: application/json"   -d "$(jq -n --arg status "$STATUS" --arg output "$OUTPUT"     '{status: $status, output: $output}')" > /dev/null

rm -f "$OUTPUT_FILE"
```

### Pattern 4: Dev Server with Tunnel
```bash
#!/bin/bash
# .dmux-hooks/run_dev

set -e
cd "$DMUX_WORKTREE_PATH"
API="http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev"

# Start dev server in background
LOG_FILE="/tmp/dmux-dev-$DMUX_PANE_ID.log"
pnpm dev > "$LOG_FILE" 2>&1 &
DEV_PID=$!

# Wait for server to start
sleep 5

# Detect port from logs
PORT=$(grep -oP 'localhost:Kd+' "$LOG_FILE" | head -1)
[ -z "$PORT" ] && PORT=3000

# Optional: Create tunnel with cloudflared
if command -v cloudflared &> /dev/null; then
  TUNNEL=$(cloudflared tunnel --url "http://localhost:$PORT" 2>&1 |     grep -oP 'https://[a-z0-9-]+.trycloudflare.com' | head -1)
  URL="${TUNNEL:-http://localhost:$PORT}"
else
  URL="http://localhost:$PORT"
fi

# Report status
curl -s -X PUT "$API" -H "Content-Type: application/json"   -d "{"status": "running", "url": "$URL"}" > /dev/null

echo "[Hook] Dev server running at $URL (PID: $DEV_PID)"
```

### Pattern 5: Post-Merge Deployment
```bash
#!/bin/bash
# .dmux-hooks/post_merge

set -e
cd "$DMUX_ROOT"

# Only deploy from main/master
if [ "$DMUX_TARGET_BRANCH" != "main" ] && [ "$DMUX_TARGET_BRANCH" != "master" ]; then
  exit 0
fi

# Push to remote
git push origin "$DMUX_TARGET_BRANCH"

# Trigger deployment (example: Vercel)
if [ -n "$VERCEL_TOKEN" ]; then
  curl -s -X POST "https://api.vercel.com/v1/deployments"     -H "Authorization: Bearer $VERCEL_TOKEN"     -H "Content-Type: application/json"     -d '{"name": "my-project"}' > /dev/null
fi

# Close GitHub issue if prompt contains #123
ISSUE=$(echo "$DMUX_PROMPT" | grep -oP '#Kd+' | head -1)
if [ -n "$ISSUE" ] && command -v gh &> /dev/null; then
  gh issue close "$ISSUE"     -c "Resolved in $DMUX_SLUG, merged to $DMUX_TARGET_BRANCH"     2>/dev/null || true
fi
```

## Best Practices

1. **Always start with shebang**: `#!/bin/bash`
2. **Set error handling**: `set -e` (exit on error)
3. **Make executable**: `chmod +x .dmux-hooks/hook_name`
4. **Background long operations**: Append `&` to avoid blocking
5. **Check for required tools**: `command -v tool &> /dev/null`
6. **Log for debugging**: `echo "[Hook] message" >> "$DMUX_ROOT/.dmux/hooks.log"`
7. **Handle missing vars gracefully**: `[ -z "$VAR" ] && exit 0`
8. **Use silent curl**: `curl -s` to avoid noise in logs
9. **Clean up temp files**: Remove files in `/tmp/`
10. **Test before committing**: Run hooks manually with mock env vars

## Testing Hooks

### Manual Testing
```bash
# 1. Set environment variables
export DMUX_ROOT="$(pwd)"
export DMUX_PANE_ID="test-pane"
export DMUX_SLUG="test-branch"
export DMUX_WORKTREE_PATH="$(pwd)"
export DMUX_SERVER_PORT="3142"
export DMUX_AGENT="claude"
export DMUX_PROMPT="Test prompt"

# 2. Run hook directly
./.dmux-hooks/worktree_created

# 3. Check exit code
echo $?  # Should be 0 for success
```

### Syntax Check
```bash
# Check for syntax errors without running
bash -n ./.dmux-hooks/worktree_created
```

### Shellcheck (if available)
```bash
shellcheck ./.dmux-hooks/worktree_created
```

## Project Context Analysis

Before creating hooks, analyze these files in the project:

### Package Manager Detection
```bash
# Check which package manager is used
if [ -f "pnpm-lock.yaml" ]; then
  # Use: pnpm install, pnpm test, pnpm dev
elif [ -f "package-lock.json" ]; then
  # Use: npm install, npm test, npm run dev
elif [ -f "yarn.lock" ]; then
  # Use: yarn install, yarn test, yarn dev
fi
```

### Test Command Discovery
```bash
# Read package.json to find test command
cat package.json | grep '"test"'
# Or with jq:
jq -r '.scripts.test' package.json
```

### Dev Command Discovery
```bash
# Read package.json to find dev command
cat package.json | grep '"dev"'
# Or with jq:
jq -r '.scripts.dev' package.json
```

### Environment Variables
```bash
# Check for .env files to copy
ls -la | grep '.env'
```

### Build System
```bash
# Detect build system
if [ -f "vite.config.ts" ]; then
  # Vite project
elif [ -f "next.config.js" ]; then
  # Next.js project
elif [ -f "nuxt.config.ts" ]; then
  # Nuxt project
fi
```

## Common Mistakes to Avoid

❌ **Blocking operations**: `sleep 60` (blocks dmux)
✅ **Background long tasks**: `slow_operation &`

❌ **Hardcoded paths**: `/Users/me/project`
✅ **Use variables**: `"$DMUX_ROOT"`

❌ **Assuming tools exist**: `pnpm install`
✅ **Check first**: `command -v pnpm && pnpm install`

❌ **No error handling**: Script fails silently
✅ **Set error mode**: `set -e` or check exit codes

❌ **Forgetting executable bit**: Hook won't run
✅ **Make executable**: `chmod +x`

❌ **Noisy output**: Clutters dmux logs
✅ **Silent operations**: `curl -s`, `> /dev/null 2>&1`

❌ **Not testing**: Deploy and hope
✅ **Test manually**: Run with mock env vars first

## Debugging

If a hook isn't working:

1. **Check if file exists**: `ls -la .dmux-hooks/`
2. **Check permissions**: Should show `x` in `rwxr-xr-x`
3. **Check syntax**: `bash -n .dmux-hooks/hook_name`
4. **Test manually**: Set env vars and run
5. **Check logs**: dmux logs to stderr with `[Hooks]` prefix
6. **Simplify**: Remove complex parts, test basic version
7. **Check tool availability**: `command -v required_tool`

### Debug Mode
```bash
#!/bin/bash
# Add to top of hook for debugging
set -x  # Print each command before executing
set -e  # Exit on error

# Your hook logic here
```

## Summary Checklist

When creating a new hook:

- [ ] Create file in `.dmux-hooks/`
- [ ] Add shebang: `#!/bin/bash`
- [ ] Make executable: `chmod +x`
- [ ] Add `set -e` for error handling
- [ ] Use environment variables (never hardcode paths)
- [ ] Background long operations with `&`
- [ ] Check for required tools before using
- [ ] Test manually with mock env vars
- [ ] Add comments explaining what it does
- [ ] Commit to version control

## Getting Help

- **Full documentation**: See `HOOKS.md` in project root
- **Claude-specific tips**: See `CLAUDE.md` in `.dmux-hooks/`
- **Examples**: Check `.dmux-hooks/examples/` directory
- **dmux API**: See `API.md` for REST endpoints

---

*This documentation was auto-generated from dmux source code.*
*Version: 2025-12-14*


================================================
FILE: .dmux-hooks/CLAUDE.md
================================================
# dmux Hooks System - Agent Reference

**Auto-generated documentation for AI agents**

This document contains everything an AI agent needs to create, modify, and understand dmux hooks. It is automatically generated from the dmux source code and embedded in the binary.

## What You're Working On

You are editing hooks for **dmux**, a tmux pane manager that creates AI-powered development workflows. Each pane runs in its own git worktree with an AI agent (Claude Code or opencode).

## Your Goal

Create executable bash scripts in `.dmux-hooks/` that run automatically at key lifecycle events.

## Quick Start

1. **Create a hook file**: `touch .dmux-hooks/worktree_created`
2. **Make it executable**: `chmod +x .dmux-hooks/worktree_created`
3. **Add shebang**: Start with `#!/bin/bash`
4. **Use environment variables**: Access `$DMUX_ROOT`, `$DMUX_WORKTREE_PATH`, etc.
5. **Test it**: Set env vars manually and run the script

## Hook Execution Model

- **Non-blocking**: Hooks run in background (detached processes)
- **Silent failures**: Hook errors are logged but don't stop dmux
- **Environment-based**: All context passed via environment variables
- **Version controlled**: Hooks in `.dmux-hooks/` are shared with team
- **Priority resolution**: `.dmux-hooks/` → `.dmux/hooks/` → `~/.dmux/hooks/`

## Available Hooks

### Pane Lifecycle Hooks

| Hook | When | Common Use Cases |
|------|------|------------------|
| `before_pane_create` | Before pane creation | Validation, notifications, pre-flight checks |
| `pane_created` | After pane, before worktree | Configure tmux settings, prepare environment |
| `worktree_created` | After full setup | Install deps, copy configs, setup git |
| `before_pane_close` | Before closing | Save state, backup uncommitted work |
| `pane_closed` | After closed | Cleanup resources, analytics, notifications |

### Worktree Lifecycle Hooks

| Hook | When | Common Use Cases |
|------|------|------------------|
| `before_worktree_remove` | Before worktree removal | Archive worktree, save artifacts |
| `worktree_removed` | After worktree removed | Cleanup external references |

### Merge Lifecycle Hooks

| Hook | When | Common Use Cases |
|------|------|------------------|
| `pre_merge` | Before merge operation | Run final tests, create backups |
| `post_merge` | After successful merge | Deploy, close issues, notify team |

### Interactive Hooks (with HTTP callbacks)

| Hook | When | Common Use Cases |
|------|------|------------------|
| `run_test` | When tests triggered | Run test suite, report status via HTTP |
| `run_dev` | When dev server triggered | Start dev server, create tunnel, report URL |


## Environment Variables

### Always Available
```bash
DMUX_ROOT="/path/to/project"           # Project root directory
DMUX_SERVER_PORT="3142"                # HTTP server port
```

### Pane Context (most hooks)
```bash
DMUX_PANE_ID="dmux-1234567890"         # dmux pane identifier
DMUX_SLUG="fix-auth-bug"               # Branch/worktree name
DMUX_PROMPT="Fix authentication bug"   # User's prompt
DMUX_AGENT="claude"                    # Agent type (claude|opencode)
DMUX_TMUX_PANE_ID="%38"                # tmux pane ID
```

### Worktree Context
```bash
DMUX_WORKTREE_PATH="/path/.dmux/worktrees/fix-auth-bug"
DMUX_BRANCH="fix-auth-bug"             # Same as slug
```

### Merge Context
```bash
DMUX_TARGET_BRANCH="main"              # Branch being merged into
```

## HTTP Callback API

Interactive hooks (`run_test` and `run_dev`) can update dmux UI via HTTP.

### Update Test Status
```bash
curl -X PUT "http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test"   -H "Content-Type: application/json"   -d '{"status": "running", "output": "optional test output"}'

# Status values: "running" | "passed" | "failed"
```

### Update Dev Server
```bash
curl -X PUT "http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev"   -H "Content-Type: application/json"   -d '{"status": "running", "url": "http://localhost:3000"}'

# Status values: "running" | "stopped"
# url: Can be localhost or tunnel URL (ngrok, cloudflared, etc.)
```

## Common Patterns

### Pattern 1: Install Dependencies
```bash
#!/bin/bash
# .dmux-hooks/worktree_created

cd "$DMUX_WORKTREE_PATH"

if [ -f "pnpm-lock.yaml" ]; then
  pnpm install --prefer-offline &
elif [ -f "package-lock.json" ]; then
  npm install &
elif [ -f "yarn.lock" ]; then
  yarn install &
elif [ -f "Gemfile" ]; then
  bundle install &
elif [ -f "requirements.txt" ]; then
  pip install -r requirements.txt &
elif [ -f "Cargo.toml" ]; then
  cargo build &
fi
```

### Pattern 2: Copy Configuration
```bash
#!/bin/bash
# .dmux-hooks/worktree_created

# Copy environment file
if [ -f "$DMUX_ROOT/.env.local" ]; then
  cp "$DMUX_ROOT/.env.local" "$DMUX_WORKTREE_PATH/.env.local"
fi

# Copy other config files
for file in .env.development .npmrc .yarnrc; do
  if [ -f "$DMUX_ROOT/$file" ]; then
    cp "$DMUX_ROOT/$file" "$DMUX_WORKTREE_PATH/$file"
  fi
done
```

### Pattern 3: Run Tests with Status Updates
```bash
#!/bin/bash
# .dmux-hooks/run_test

set -e
cd "$DMUX_WORKTREE_PATH"
API="http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test"

# Update: starting
curl -s -X PUT "$API" -H "Content-Type: application/json"   -d '{"status": "running"}' > /dev/null

# Run tests and capture output
OUTPUT_FILE="/tmp/dmux-test-$DMUX_PANE_ID.txt"
if pnpm test > "$OUTPUT_FILE" 2>&1; then
  STATUS="passed"
else
  STATUS="failed"
fi

# Get output (truncate if too long)
OUTPUT=$(head -c 5000 "$OUTPUT_FILE")

# Update: complete
curl -s -X PUT "$API" -H "Content-Type: application/json"   -d "$(jq -n --arg status "$STATUS" --arg output "$OUTPUT"     '{status: $status, output: $output}')" > /dev/null

rm -f "$OUTPUT_FILE"
```

### Pattern 4: Dev Server with Tunnel
```bash
#!/bin/bash
# .dmux-hooks/run_dev

set -e
cd "$DMUX_WORKTREE_PATH"
API="http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev"

# Start dev server in background
LOG_FILE="/tmp/dmux-dev-$DMUX_PANE_ID.log"
pnpm dev > "$LOG_FILE" 2>&1 &
DEV_PID=$!

# Wait for server to start
sleep 5

# Detect port from logs
PORT=$(grep -oP 'localhost:Kd+' "$LOG_FILE" | head -1)
[ -z "$PORT" ] && PORT=3000

# Optional: Create tunnel with cloudflared
if command -v cloudflared &> /dev/null; then
  TUNNEL=$(cloudflared tunnel --url "http://localhost:$PORT" 2>&1 |     grep -oP 'https://[a-z0-9-]+.trycloudflare.com' | head -1)
  URL="${TUNNEL:-http://localhost:$PORT}"
else
  URL="http://localhost:$PORT"
fi

# Report status
curl -s -X PUT "$API" -H "Content-Type: application/json"   -d "{"status": "running", "url": "$URL"}" > /dev/null

echo "[Hook] Dev server running at $URL (PID: $DEV_PID)"
```

### Pattern 5: Post-Merge Deployment
```bash
#!/bin/bash
# .dmux-hooks/post_merge

set -e
cd "$DMUX_ROOT"

# Only deploy from main/master
if [ "$DMUX_TARGET_BRANCH" != "main" ] && [ "$DMUX_TARGET_BRANCH" != "master" ]; then
  exit 0
fi

# Push to remote
git push origin "$DMUX_TARGET_BRANCH"

# Trigger deployment (example: Vercel)
if [ -n "$VERCEL_TOKEN" ]; then
  curl -s -X POST "https://api.vercel.com/v1/deployments"     -H "Authorization: Bearer $VERCEL_TOKEN"     -H "Content-Type: application/json"     -d '{"name": "my-project"}' > /dev/null
fi

# Close GitHub issue if prompt contains #123
ISSUE=$(echo "$DMUX_PROMPT" | grep -oP '#Kd+' | head -1)
if [ -n "$ISSUE" ] && command -v gh &> /dev/null; then
  gh issue close "$ISSUE"     -c "Resolved in $DMUX_SLUG, merged to $DMUX_TARGET_BRANCH"     2>/dev/null || true
fi
```

## Best Practices

1. **Always start with shebang**: `#!/bin/bash`
2. **Set error handling**: `set -e` (exit on error)
3. **Make executable**: `chmod +x .dmux-hooks/hook_name`
4. **Background long operations**: Append `&` to avoid blocking
5. **Check for required tools**: `command -v tool &> /dev/null`
6. **Log for debugging**: `echo "[Hook] message" >> "$DMUX_ROOT/.dmux/hooks.log"`
7. **Handle missing vars gracefully**: `[ -z "$VAR" ] && exit 0`
8. **Use silent curl**: `curl -s` to avoid noise in logs
9. **Clean up temp files**: Remove files in `/tmp/`
10. **Test before committing**: Run hooks manually with mock env vars

## Testing Hooks

### Manual Testing
```bash
# 1. Set environment variables
export DMUX_ROOT="$(pwd)"
export DMUX_PANE_ID="test-pane"
export DMUX_SLUG="test-branch"
export DMUX_WORKTREE_PATH="$(pwd)"
export DMUX_SERVER_PORT="3142"
export DMUX_AGENT="claude"
export DMUX_PROMPT="Test prompt"

# 2. Run hook directly
./.dmux-hooks/worktree_created

# 3. Check exit code
echo $?  # Should be 0 for success
```

### Syntax Check
```bash
# Check for syntax errors without running
bash -n ./.dmux-hooks/worktree_created
```

### Shellcheck (if available)
```bash
shellcheck ./.dmux-hooks/worktree_created
```

## Project Context Analysis

Before creating hooks, analyze these files in the project:

### Package Manager Detection
```bash
# Check which package manager is used
if [ -f "pnpm-lock.yaml" ]; then
  # Use: pnpm install, pnpm test, pnpm dev
elif [ -f "package-lock.json" ]; then
  # Use: npm install, npm test, npm run dev
elif [ -f "yarn.lock" ]; then
  # Use: yarn install, yarn test, yarn dev
fi
```

### Test Command Discovery
```bash
# Read package.json to find test command
cat package.json | grep '"test"'
# Or with jq:
jq -r '.scripts.test' package.json
```

### Dev Command Discovery
```bash
# Read package.json to find dev command
cat package.json | grep '"dev"'
# Or with jq:
jq -r '.scripts.dev' package.json
```

### Environment Variables
```bash
# Check for .env files to copy
ls -la | grep '.env'
```

### Build System
```bash
# Detect build system
if [ -f "vite.config.ts" ]; then
  # Vite project
elif [ -f "next.config.js" ]; then
  # Next.js project
elif [ -f "nuxt.config.ts" ]; then
  # Nuxt project
fi
```

## Common Mistakes to Avoid

❌ **Blocking operations**: `sleep 60` (blocks dmux)
✅ **Background long tasks**: `slow_operation &`

❌ **Hardcoded paths**: `/Users/me/project`
✅ **Use variables**: `"$DMUX_ROOT"`

❌ **Assuming tools exist**: `pnpm install`
✅ **Check first**: `command -v pnpm && pnpm install`

❌ **No error handling**: Script fails silently
✅ **Set error mode**: `set -e` or check exit codes

❌ **Forgetting executable bit**: Hook won't run
✅ **Make executable**: `chmod +x`

❌ **Noisy output**: Clutters dmux logs
✅ **Silent operations**: `curl -s`, `> /dev/null 2>&1`

❌ **Not testing**: Deploy and hope
✅ **Test manually**: Run with mock env vars first

## Debugging

If a hook isn't working:

1. **Check if file exists**: `ls -la .dmux-hooks/`
2. **Check permissions**: Should show `x` in `rwxr-xr-x`
3. **Check syntax**: `bash -n .dmux-hooks/hook_name`
4. **Test manually**: Set env vars and run
5. **Check logs**: dmux logs to stderr with `[Hooks]` prefix
6. **Simplify**: Remove complex parts, test basic version
7. **Check tool availability**: `command -v required_tool`

### Debug Mode
```bash
#!/bin/bash
# Add to top of hook for debugging
set -x  # Print each command before executing
set -e  # Exit on error

# Your hook logic here
```

## Summary Checklist

When creating a new hook:

- [ ] Create file in `.dmux-hooks/`
- [ ] Add shebang: `#!/bin/bash`
- [ ] Make executable: `chmod +x`
- [ ] Add `set -e` for error handling
- [ ] Use environment variables (never hardcode paths)
- [ ] Background long operations with `&`
- [ ] Check for required tools before using
- [ ] Test manually with mock env vars
- [ ] Add comments explaining what it does
- [ ] Commit to version control

## Getting Help

- **Full documentation**: See `HOOKS.md` in project root
- **Claude-specific tips**: See `CLAUDE.md` in `.dmux-hooks/`
- **Examples**: Check `.dmux-hooks/examples/` directory
- **dmux API**: See `API.md` for REST endpoints

---

*This documentation was auto-generated from dmux source code.*
*Version: 2025-12-14*


================================================
FILE: .dmux-hooks/README.md
================================================
# dmux Hooks

This directory contains hooks that run automatically at key lifecycle events in dmux.

## Quick Start

1. **Read the documentation**:
   - `AGENTS.md` - Complete reference (for any AI agent)
   - `CLAUDE.md` - Same content (Claude Code looks for this filename)

2. **Check examples**:
   - `examples/` directory contains starter templates

3. **Create a hook**:
   ```bash
   touch worktree_created
   chmod +x worktree_created
   nano worktree_created
   ```

4. **Test it**:
   ```bash
   export DMUX_ROOT="$(pwd)"
   export DMUX_WORKTREE_PATH="$(pwd)"
   ./worktree_created
   ```

## Available Hooks

- `before_pane_create` - Before pane creation
- `pane_created` - After pane created
- `worktree_created` - After worktree setup
- `before_pane_close` - Before closing
- `pane_closed` - After closed
- `before_worktree_remove` - Before worktree removal
- `worktree_removed` - After worktree removed
- `pre_merge` - Before merge
- `post_merge` - After merge
- `run_test` - When running tests
- `run_dev` - When starting dev server

## Documentation

See `AGENTS.md` or `CLAUDE.md` for complete documentation including:
- Environment variables
- HTTP callback API
- Common patterns
- Best practices
- Testing strategies

## Note

This directory is **version controlled**. Hooks you create here will be shared with your team.


================================================
FILE: .dmux-hooks/examples/post_merge.example
================================================
#!/bin/bash
# Example: post_merge hook
#
# This hook runs after a successful merge into the target branch.
# Use it to trigger deployments, close issues, notify teams, etc.

set -e

echo "[Hook] Post-merge processing for $DMUX_SLUG → $DMUX_TARGET_BRANCH"

cd "$DMUX_ROOT"

# Push to remote if merging to main/master
if [ "$DMUX_TARGET_BRANCH" = "main" ] || [ "$DMUX_TARGET_BRANCH" = "master" ]; then
  echo "[Hook] Pushing to origin/$DMUX_TARGET_BRANCH"
  git push origin "$DMUX_TARGET_BRANCH"

  # Optional: Trigger deployment
  # if [ -n "$VERCEL_TOKEN" ]; then
  #   echo "[Hook] Triggering Vercel deployment..."
  #   curl -X POST "https://api.vercel.com/v1/deployments" \
  #     -H "Authorization: Bearer $VERCEL_TOKEN" \
  #     -H "Content-Type: application/json" \
  #     -d '{
  #       "name": "my-project",
  #       "gitSource": {
  #         "type": "github",
  #         "ref": "main"
  #       }
  #     }'
  # fi
fi

# Close related GitHub issue (if prompt contains #123 format)
ISSUE_NUM=$(echo "$DMUX_PROMPT" | grep -oP '#\K\d+' | head -1)
if [ -n "$ISSUE_NUM" ]; then
  echo "[Hook] Closing GitHub issue #$ISSUE_NUM"
  if command -v gh &> /dev/null; then
    gh issue close "$ISSUE_NUM" \
      -c "Resolved in branch $DMUX_SLUG, merged to $DMUX_TARGET_BRANCH" \
      2>/dev/null || echo "[Hook] Warning: Failed to close issue (maybe already closed?)"
  else
    echo "[Hook] GitHub CLI (gh) not found, skipping issue close"
  fi
fi

# Send notification to Slack
# if [ -n "$SLACK_WEBHOOK" ]; then
#   echo "[Hook] Sending Slack notification"
#   curl -s -X POST "$SLACK_WEBHOOK" \
#     -H "Content-Type: application/json" \
#     -d "{
#       \"text\": \"Merged: $DMUX_SLUG → $DMUX_TARGET_BRANCH\",
#       \"blocks\": [
#         {
#           \"type\": \"section\",
#           \"text\": {
#             \"type\": \"mrkdwn\",
#             \"text\": \"*Branch Merged* :rocket:\n\n*From:* \`$DMUX_SLUG\`\n*To:* \`$DMUX_TARGET_BRANCH\`\n*Task:* $DMUX_PROMPT\"
#           }
#         }
#       ]
#     }" > /dev/null
# fi

echo "[Hook] Post-merge processing complete"


================================================
FILE: .dmux-hooks/examples/run_dev.example
================================================
#!/bin/bash
# Example: run_dev hook
#
# This hook starts a dev server and optionally creates a tunnel for sharing.
# It reports the server URL back to dmux via the HTTP API.

set -e

echo "[Hook] Starting dev server for $DMUX_SLUG"

cd "$DMUX_WORKTREE_PATH"
API_URL="http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev"

# Update status: starting
curl -s -X PUT "$API_URL" \
  -H "Content-Type: application/json" \
  -d '{"status": "running"}' > /dev/null

# Start dev server in background
# Adjust the command for your project (pnpm dev, npm run dev, vite, etc.)
LOG_FILE="/tmp/dmux-dev-$DMUX_PANE_ID.log"
pnpm dev > "$LOG_FILE" 2>&1 &
DEV_PID=$!

# Wait for server to be ready
echo "[Hook] Waiting for dev server to start..."
sleep 5

# Detect port from log output
# Adjust the grep pattern for your dev server's output format
PORT=$(grep -oP '(?<=localhost:)\d+' "$LOG_FILE" | head -1)

if [ -z "$PORT" ]; then
  echo "[Hook] Warning: Could not detect port from logs, using default 3000"
  PORT=3000
fi

LOCAL_URL="http://localhost:$PORT"
echo "[Hook] Dev server running at $LOCAL_URL"

# Optional: Create a public tunnel (uncomment to enable)
# Requires ngrok, cloudflared, or another tunneling tool

# Example with cloudflared:
# TUNNEL_URL=$(cloudflared tunnel --url "$LOCAL_URL" 2>&1 | \
#   grep -oP 'https://[a-z0-9-]+\.trycloudflare\.com' | head -1)

# Example with ngrok:
# TUNNEL_URL=$(ngrok http $PORT --log=stdout 2>&1 | \
#   grep -oP 'url=https://[^"]+' | head -1 | cut -d= -f2)

# For now, just use local URL (uncomment tunnel code above to enable)
FINAL_URL="$LOCAL_URL"

# Report status back to dmux
curl -s -X PUT "$API_URL" \
  -H "Content-Type: application/json" \
  -d "{\"status\": \"running\", \"url\": \"$FINAL_URL\"}" > /dev/null

echo "[Hook] Dev server ready at: $FINAL_URL"
echo "[Hook] Dev server PID: $DEV_PID"
echo "[Hook] Log file: $LOG_FILE"


================================================
FILE: .dmux-hooks/examples/run_test.example
================================================
#!/bin/bash
# Example: run_test hook
#
# This hook runs tests and reports the status back to dmux via the HTTP API.
# Status updates appear in real-time in the dmux UI.

set -e

echo "[Hook] Running tests for $DMUX_SLUG"

cd "$DMUX_WORKTREE_PATH"
API_URL="http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test"

# Update status: running
curl -s -X PUT "$API_URL" \
  -H "Content-Type: application/json" \
  -d '{"status": "running"}' > /dev/null

echo "[Hook] Running test suite..."

# Capture test output
OUTPUT_FILE="/tmp/dmux-test-$DMUX_PANE_ID.txt"

# Run tests (adjust command for your project)
# Examples:
#   - pnpm test
#   - npm test
#   - vitest run
#   - jest
#   - pytest
#   - cargo test
if pnpm test > "$OUTPUT_FILE" 2>&1; then
  STATUS="passed"
  echo "[Hook] Tests passed ✓"
else
  STATUS="failed"
  echo "[Hook] Tests failed ✗"
fi

# Get output (truncate if too long)
OUTPUT=$(head -c 5000 "$OUTPUT_FILE")

# Report results back to dmux
curl -s -X PUT "$API_URL" \
  -H "Content-Type: application/json" \
  -d "$(jq -n \
    --arg status "$STATUS" \
    --arg output "$OUTPUT" \
    '{status: $status, output: $output}')" > /dev/null

# Cleanup
rm -f "$OUTPUT_FILE"

echo "[Hook] Test results reported to dmux"

# Exit with test status
if [ "$STATUS" = "passed" ]; then
  exit 0
else
  exit 1
fi


================================================
FILE: .dmux-hooks/examples/worktree_created.example
================================================
#!/bin/bash
# Example: worktree_created hook
#
# This hook runs after a new worktree is created and the agent is launched.
# Use it to set up the worktree environment (install deps, copy configs, etc.)

set -e  # Exit on error

echo "[Hook] Setting up worktree: $DMUX_SLUG"

cd "$DMUX_WORKTREE_PATH"

# Install dependencies in background (don't block dmux)
if [ -f "pnpm-lock.yaml" ]; then
  echo "[Hook] Installing dependencies with pnpm..."
  pnpm install --prefer-offline &
elif [ -f "package-lock.json" ]; then
  echo "[Hook] Installing dependencies with npm..."
  npm install &
elif [ -f "yarn.lock" ]; then
  echo "[Hook] Installing dependencies with yarn..."
  yarn install &
fi

# Copy environment file if it exists
if [ -f "$DMUX_ROOT/.env.local" ]; then
  echo "[Hook] Copying .env.local"
  cp "$DMUX_ROOT/.env.local" "$DMUX_WORKTREE_PATH/.env.local"
fi

# Set custom git config for this worktree
echo "[Hook] Configuring git"
git config user.name "dmux-agent/$DMUX_SLUG"
git config user.email "agent@dmux.local"

# Create a log entry
echo "[$(date)] Created worktree: $DMUX_SLUG | Agent: $DMUX_AGENT | Prompt: $DMUX_PROMPT" \
  >> "$DMUX_ROOT/.dmux/worktree_history.log"

echo "[Hook] Worktree setup complete!"


================================================
FILE: .editorconfig
================================================
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: formkit


================================================
FILE: .github/workflows/main.yml
================================================
name: CI
on:
  push:
    branches:
      - master
      - 'release/*'
  pull_request:
    branches:
      - master
      - 'release/*'
  workflow_dispatch:

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        # version is read from package.json#packageManager
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      
      - name: Get pnpm store directory
        id: pnpm-cache
        shell: bash
        run: |
          echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
      
      - name: Setup pnpm cache
        uses: actions/cache@v4
        with:
          path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-store-
      
      - name: Get Playwright version
        id: playwright-version
        run: echo "PLAYWRIGHT_VERSION=$(pnpm ls @playwright/test --json | jq -r '.[0].devDependencies."@playwright/test".version')" >> $GITHUB_OUTPUT
      
      - name: Cache Playwright browsers
        id: playwright-cache
        uses: actions/cache@v4
        with:
          path: ~/.cache/ms-playwright
          key: ${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.PLAYWRIGHT_VERSION }}
          restore-keys: |
            ${{ runner.os }}-playwright-
      
      - name: Install dependencies
        run: pnpm install --frozen-lockfile=false
      
      - name: Install Playwright Browsers
        if: steps.playwright-cache.outputs.cache-hit != 'true'
        run: pnpm exec playwright install --with-deps
      
      - name: Install Playwright dependencies only
        if: steps.playwright-cache.outputs.cache-hit == 'true'
        run: pnpm exec playwright install-deps
      
      - name: Build project
        run: NO_NUXT=1 pnpm build
      
      - name: Run Playwright tests
        run: pnpm test:e2e
      - name: Upload Playwright report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report
      - name: Upload Playwright videos (visual)
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-videos
          path: test-results/**/video.webm


================================================
FILE: .gitignore
================================================
node_modules
dist
*.log
.DS_Store

# Playwright artifacts
playwright-report/
playwright-report/index.html
test-results/

dist
.DS_Store
node_modules
coverage
temp
*.log
.vscode
/.aws/credentials
.yalc
.idea
.nuxt
*.local.json
.node_modules_tmp


================================================
FILE: .npmignore
================================================
src
api-extractor.json
__tests__
.editorconfig
.gitignore
rollup.config.js
tsconfig.json
yarn.lock
docs
.prettierrc
.build.sh
.github


================================================
FILE: .npmrc
================================================
shamefully-hoist=true

================================================
FILE: .prettierrc
================================================
{
  "tabWidth": 2,
  "useTabs": false,
  "semi": false
}


================================================
FILE: LICENSE
================================================
Copyright 2022 FormKit Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
<img width="300" height="37" alt="AutoAnimate Logo" src="https://cdn.formk.it/web-assets/logo-auto-animate.svg" >

![Latest Build](https://github.com/formkit/auto-animate/actions/workflows/main.yml/badge.svg) ![GitHub Sponsors](https://img.shields.io/github/sponsors/formkit)

# Add motion to your apps with a single line of code.

AutoAnimate is a zero-config, drop-in animation utility that adds smooth transitions to your web app. You can use it with Vue, React, Solid or any other JavaScript application.

<a href="https://auto-animate.formkit.com"><img width="180" height="42" src="https://cdn.formk.it/web-assets/read-docs-auto-animate-v2.svg" alt="Examples & Docs"></a>

With one line of code, you can improve your interfaces, for example:

<a href="https://auto-animate.formkit.com">
  <img src="https://cdn.formk.it/web-assets/motion.gif" alt="Simple example of AutoAnimation motion">
</a>

## Installation

Install using your package manager of choice.

```bash
# yarn
yarn add @formkit/auto-animate
# npm
npm install @formkit/auto-animate
# pnpm
pnpm add @formkit/auto-animate
```

Boom! Done. That was fast! 🐇

## Usage

📖 [View the documentation site for usage instructions](https://auto-animate.formkit.com#usage).

## Examples

📖 [View the documentation site for examples](https://auto-animate.formkit.com#examples).

## Plugins

📖 [View the documentation site for plugin instructions](https://auto-animate.formkit.com#plugins).

## Support us

Is AutoAnimate saving you time?

Please consider [supporting us with a recurring or one-time donation](https://github.com/sponsors/formkit)! 🙏

## Contributing

Thank you for your willingness to contribute to this free and open source project! When contributing, consider first discussing your desired change with the core team via <a href="https://github.com/formkit/auto-animate/issues">GitHub issues</a>, <a href="https://discord.gg/SHYT8pyeNm">Discord</a>, or other method.


================================================
FILE: build/build-nuxt.ts
================================================
import { existsSync, promises as fsp } from "fs"
import { pathToFileURL } from "url"
import { resolve } from "pathe"
import { consola } from "consola"
import type { ModuleMeta, NuxtModule, NuxtConfig } from "@nuxt/schema"
import { findExports } from "mlly"

interface BuildModuleOptions {
  rootDir: string
  srcDir?: string
  sourcemap?: boolean
  stub?: boolean
  outDir?: string
}

interface PrepareModuleOptions {
  rootDir: string
  srcDir: string
}

/**
 * Original source: https://github.com/nuxt/module-builder/blob/main/src/prepare.ts
 * @param options
 */
async function prepareModule (options: PrepareModuleOptions) {
  const { runCommand } = await import('nuxi')

  return runCommand('prepare', [resolve(options.rootDir, 'build/nuxt-playground')], {
    overrides: {
      typescript: {
        builder: 'shared'
      },
      imports: {
        autoImport: false
      },
      modules: [
        resolve(options.rootDir, `${options.srcDir}/module`),
        function (_options, nuxt) {
          nuxt.hooks.hook('app:templates', (app) => {
            for (const template of app.templates) {
              template.write = true
            }
          })
        }
      ]
    } satisfies NuxtConfig
  })
}


/**
 * Original source: https://github.com/nuxt/module-builder/blob/main/src/build.ts
 * @param opts - options
 */
export async function buildModule(opts: BuildModuleOptions) {
  const { build } = await import("unbuild")

  const outDir = opts.outDir || "dist"
  const srcDir = opts.srcDir || "src"

  await prepareModule({ rootDir: opts.rootDir, srcDir })

  await build(opts.rootDir, false, {
    clean: false, // auto-animate’s build does its own cleaning
    failOnWarn: false, // unbuild will validate the package.json, but we don’t want to fail on warnings
    declaration: true,
    sourcemap: opts.sourcemap,
    stub: opts.stub,
    outDir,
    entries: [
      { input: `${srcDir}/module`, outDir: `${outDir}/nuxt` },
      { input: `${srcDir}/runtime/`, outDir: `${outDir}/nuxt/runtime`, ext: "mjs" },
    ],
    rollup: {
      emitCJS: false,
      cjsBridge: false,
      dts: {
        tsconfig: "./build/nuxt-playground/tsconfig.json",
      },
    },
    externals: [
      "@nuxt/schema",
      "@nuxt/schema-edge",
      "@nuxt/kit",
      "@nuxt/kit-edge",
      "nuxt",
      "nuxt-edge",
      "nuxt3",
      "vue",
      "vue-demi",
    ],
    hooks: {
      async "rollup:done"(ctx) {
        const outDir = resolve(ctx.options.outDir, 'nuxt')
        // Generate CommonJS stub
        await writeCJSStub(outDir)

        // Load module meta
        const moduleEntryPath = resolve(outDir, "module.mjs")
        const moduleFn: NuxtModule<any> = await import(
          pathToFileURL(moduleEntryPath).toString()
        )
          .then((r) => r.default || r)
          .catch((err) => {
            consola.error(err)
            consola.error(
              "Cannot load module. Please check dist:",
              moduleEntryPath
            )
            return null
          })

        if (!moduleFn || !moduleFn.getMeta) {
          return
        }
        const moduleMeta = await moduleFn.getMeta()

        // Enhance meta using package.json
        if (ctx.pkg) {
          if (!moduleMeta.name) {
            moduleMeta.name = ctx.pkg.name
          }
          if (!moduleMeta.version) {
            moduleMeta.version = ctx.pkg.version
          }
        }

        // Write meta
        const metaFile = resolve(outDir, "module.json")
        await fsp.writeFile(
          metaFile,
          JSON.stringify(moduleMeta, null, 2),
          "utf8"
        )

        // Generate types
        await writeTypes(outDir, moduleMeta)
      },
    },
  })
}

async function writeTypes(distDir: string, meta: ModuleMeta) {
  const dtsFile = resolve(distDir, "types.d.ts")
  const dtsFileMts = resolve(distDir, "types.d.mts")
  if (existsSync(dtsFile)) {
    return
  }

  // Read generated module types
  const moduleTypesFile = resolve(distDir, "module.d.ts")
  const moduleTypes = await fsp
    .readFile(moduleTypesFile, "utf8")
    .catch(() => "")
  const typeExports = findExports(
    // Replace `export { type Foo }` with `export { Foo }`
    moduleTypes.replace(/export\s*{.*?}/gs, (match) =>
      match.replace(/\btype\b/g, "")
    )
  )
  const isStub = moduleTypes.includes("export *")

  const schemaShims = []
  const moduleImports = []

  const hasTypeExport = (name: string) =>
    isStub || typeExports.find((exp) => exp.names.includes(name))

  if (meta.configKey && hasTypeExport("ModuleOptions")) {
    moduleImports.push("ModuleOptions")
    schemaShims.push(
      `  interface NuxtConfig { ['${meta.configKey}']?: Partial<ModuleOptions> }`
    )
    schemaShims.push(
      `  interface NuxtOptions { ['${meta.configKey}']?: ModuleOptions }`
    )
  }
  if (hasTypeExport("ModuleHooks")) {
    moduleImports.push("ModuleHooks")
    schemaShims.push("  interface NuxtHooks extends ModuleHooks {}")
  }
  if (hasTypeExport("ModuleRuntimeConfig")) {
    moduleImports.push("ModuleRuntimeConfig")
    schemaShims.push("  interface RuntimeConfig extends ModuleRuntimeConfig {}")
  }
  if (hasTypeExport("ModulePublicRuntimeConfig")) {
    moduleImports.push("ModulePublicRuntimeConfig")
    schemaShims.push(
      "  interface PublicRuntimeConfig extends ModulePublicRuntimeConfig {}"
    )
  }

  const dtsContents = `
import { ${moduleImports.join(", ")} } from './module'

${
  schemaShims.length
    ? `declare module '@nuxt/schema' {\n${schemaShims.join("\n")}\n}\n`
    : ""
}
${
  schemaShims.length
    ? `declare module 'nuxt/schema' {\n${schemaShims.join("\n")}\n}\n`
    : ""
}

export { ${typeExports[0].names.join(", ")} } from './module'
`

  await fsp.writeFile(dtsFile, dtsContents, "utf8")
  if (!existsSync(dtsFileMts)) {
    await fsp.writeFile(dtsFileMts, dtsContents, "utf8")
  }
}

async function writeCJSStub(distDir: string) {
  const cjsStubFile = resolve(distDir, "module.cjs")
  if (existsSync(cjsStubFile)) {
    return
  }
  const cjsStub = `module.exports = function(...args) {
  return import('./module.mjs').then(m => m.default.call(this, ...args))
}
const _meta = module.exports.meta = require('./module.json')
module.exports.getMeta = () => Promise.resolve(_meta)
`
  await fsp.writeFile(cjsStubFile, cjsStub, "utf8")
}


================================================
FILE: build/build.mjs
================================================
import createJITI from "jiti"
import { fileURLToPath } from "url"
import { dirname, resolve } from "path"

const __filename = fileURLToPath(import.meta.url)

const jiti = createJITI(__filename, {
  esmResolve: true,
})

jiti("./bundle.ts")


================================================
FILE: build/bundle.ts
================================================
import { dirname, resolve } from "path"
import { fileURLToPath } from "url"
import { readFile, writeFile } from "fs/promises"
import { execa } from "execa"
import { execSync } from "child_process"
import chalk from "chalk"
import prompts from "prompts"
import { sync } from "brotli-size"
import prettyBytes from "pretty-bytes"
import { buildModule } from "./build-nuxt"

const info = (m: string) => console.log(chalk.blue(m))
const error = (m: string) => console.log(chalk.red(m))
const success = (m: string) => console.log(chalk.green(m))

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const rootDir = resolve(`${__dirname}/../`)
const isPublishing = process.argv[2] === "--publish"

async function clean() {
  await execa("shx", ["rm", "-rf", `${rootDir}/dist`])
}

async function baseBuild() {
  info("Rolling up primary package")
  await execa("npx", ["rollup", "-c", "rollup.config.js"])
}

async function baseBuildMin() {
  info("Minifying primary package")
  await execa("npx", [
    "rollup",
    "-c",
    "rollup.config.js",
    "--environment",
    "MIN:true",
  ])
}

async function reactBuild() {
  info("Rolling up React package")
  await execa("npx", [
    "rollup",
    "-c",
    "rollup.config.js",
    "--environment",
    "FRAMEWORK:react",
  ])
  /**
   * This is a super hack — for some reason these imports need to be explicitly
   * to .mjs files so...we make it so.
   */
  let raw = await readFile(resolve(rootDir, "dist/react/index.mjs"), "utf8")
  raw = raw.replace("from '../index'", "from '../index.mjs'")
  await writeFile(resolve(rootDir, "dist/react/index.mjs"), raw)
}
async function solidBuild() {
  info("Rolling up Solid package")
  await execa("npx", [
    "rollup",
    "-c",
    "rollup.config.js",
    "--environment",
    "FRAMEWORK:solid",
  ])
  /**
   * This is a super hack — for some reason these imports need to be explicitly
   * to .mjs files so...we make it so.
   */
  let raw = await readFile(resolve(rootDir, "dist/solid/index.mjs"), "utf8")
  raw = raw.replace("from '../index'", "from '../index.mjs'")
  await writeFile(resolve(rootDir, "dist/solid/index.mjs"), raw)
}

async function preactBuild() {
  info("Rolling up Preact package")
  await execa("npx", [
    "rollup",
    "-c",
    "rollup.config.js",
    "--environment",
    "FRAMEWORK:preact",
  ])
  /**
   * This is a super hack — for some reason these imports need to be explicitly
   * to .mjs files so...we make it so.
   */
  let raw = await readFile(resolve(rootDir, "dist/preact/index.mjs"), "utf8")
  raw = raw.replace("from '../index'", "from '../index.mjs'")
  await writeFile(resolve(rootDir, "dist/preact/index.mjs"), raw)
}

async function vueBuild() {
  info("Rolling up Vue package")
  await execa("npx", [
    "rollup",
    "-c",
    "rollup.config.js",
    "--environment",
    "FRAMEWORK:vue",
  ])
  /**
   * This is a super hack — for some reason these imports need to be explicitly
   * to .mjs files so...we make it so.
   */
  let raw = await readFile(resolve(rootDir, "dist/vue/index.mjs"), "utf8")
  raw = raw.replace("from '../index'", "from '../index.mjs'")
  await writeFile(resolve(rootDir, "dist/vue/index.mjs"), raw)
}

async function angularBuild() {
  info("Rolling up Angular package")
  await execa("npx", [
    "rollup",
    "-c",
    "rollup.config.js",
    "--environment",
    "FRAMEWORK:angular",
  ])
  /**
   * This is a super hack — for some reason these imports need to be explicitly
   * to .mjs files so...we make it so.
   */
  let raw = await readFile(resolve(rootDir, "dist/angular/index.mjs"), "utf8")
  raw = raw.replace(
    "import autoAnimate from '../index';",
    "import autoAnimate from '../index.mjs';"
  )
  await writeFile(resolve(rootDir, "dist/angular/index.mjs"), raw)
}

// async function qwikBuild() {
//   info("Rolling up Qwik package")
//   await execa("npx", [
//     "rollup",
//     "-c",
//     "rollup.config.js",
//     "--environment",
//     "FRAMEWORK:qwik",
//   ])
//   /**
//    * This is a super hack — for some reason these imports need to be explicitly
//    * to .mjs files so...we make it so.
//    */
//   let raw = await readFile(resolve(rootDir, "dist/qwik/index.mjs"), "utf8")
//   raw = raw.replace("from '../index'", "from '../index.mjs'")
//   await writeFile(resolve(rootDir, "dist/qwik/index.mjs"), raw)
// }

async function nuxtBuild() {
  info("Building nuxt module")
  await buildModule({
    rootDir,
    srcDir: "src/nuxt",
  })
}

async function declarationsBuild() {
  info("Outputting declarations")
  await execa("npx", [
    "rollup",
    "-c",
    "rollup.config.js",
    "--environment",
    "DECLARATIONS:true",
  ])
}

async function bundleDeclarations() {
  info("Bundling declarations")
  await execa("shx", [
    "mv",
    `${rootDir}/dist/src/index.d.ts`,
    `${rootDir}/dist/index.d.ts`,
  ])
  await execa("shx", [
    "mv",
    `${rootDir}/dist/src/react/index.d.ts`,
    `${rootDir}/dist/react/index.d.ts`,
  ])
  await execa("shx", [
    "mv",
    `${rootDir}/dist/src/preact/index.d.ts`,
    `${rootDir}/dist/preact/index.d.ts`,
  ])
  await execa("shx", [
    "mv",
    `${rootDir}/dist/src/solid/index.d.ts`,
    `${rootDir}/dist/solid/index.d.ts`,
  ])
  await execa("shx", [
    "mv",
    `${rootDir}/dist/src/vue/index.d.ts`,
    `${rootDir}/dist/vue/index.d.ts`,
  ])
  await execa("shx", [
    "mv",
    `${rootDir}/dist/src/angular/index.d.ts`,
    `${rootDir}/dist/angular/index.d.ts`,
  ])
  await execa("shx", [
    "mv",
    `${rootDir}/dist/src/qwik/index.d.ts`,
    `${rootDir}/dist/qwik/index.d.ts`,
  ])
  await execa("shx", ["rm", "-rf", `${rootDir}/dist/src`])
  await execa("shx", ["rm", `${rootDir}/dist/index.js`])
}

async function addPackageJSON() {
  info("Writing package.json")
  const raw = await readFile(resolve(rootDir, "package.json"), "utf8")
  const packageJSON = JSON.parse(raw)
  delete packageJSON.private
  delete packageJSON.devDependencies
  delete packageJSON.scripts
  await writeFile(
    resolve(rootDir, "dist/package.json"),
    JSON.stringify(packageJSON, null, 2)
  )
}

async function addAssets() {
  info("Writing readme and license.")
  await execa("shx", [
    "cp",
    `${rootDir}/README.md`,
    `${rootDir}/dist/README.md`,
  ])
  await execa("shx", ["cp", `${rootDir}/LICENSE`, `${rootDir}/dist/LICENSE`])
}

async function prepareForPublishing() {
  info("Preparing for publication")
  if (
    process.env.npm_execpath &&
    !/pnpm\.cjs$/.test(process.env.npm_execpath)
  ) {
    error(`⚠️ You must run this command with pnpm.`)
    info("Please try again with:\n\n» pnpm run publish\n\n")
    process.exit()
  }
  const isClean = !execSync(`git status --untracked-files=no --porcelain`, {
    encoding: "utf-8",
  })
  if (!isClean) {
    error("Commit your changes before publishing.")
    process.exit()
  }
  // Version confirmation is now handled by bumpp in the release script
}

async function publish() {
  const raw = await readFile(resolve(rootDir, "package.json"), "utf8")
  const packageJSON = JSON.parse(raw)
  const response = await prompts([
    {
      type: "confirm",
      name: "value",
      message: `Project is build. Ready to publish?`,
      initial: false,
    },
  ])
  if (response.value) {
    execSync("pnpm publish ./dist")
    execSync(`git tag ${packageJSON.version}`)
    execSync(`git push origin --tags`)
  }
}

async function outputSize() {
  const raw = await readFile(resolve(rootDir, "dist/index.min.js"), "utf8")
  console.log("Brotli size: " + prettyBytes(sync(raw)))
}

async function main() {
  if (isPublishing) await prepareForPublishing()
  await clean()
  await baseBuild()
  await baseBuildMin()
  await reactBuild()
  await preactBuild()
  await solidBuild()
  await vueBuild()
  await angularBuild()
  // await qwikBuild()
  await declarationsBuild()
  await bundleDeclarations()
  // Skip nuxt module build in CI or when NO_NUXT is set
  if (!process.env.NO_NUXT) {
    await nuxtBuild()
  }
  await addPackageJSON()
  await addAssets()
  await outputSize()
  isPublishing ? await publish() : success("Build complete")
}

main()


================================================
FILE: build/nuxt-playground/app.vue
================================================
<script lang="ts" setup>
const items = ref(['A', 'B', 'C'])

function add () {
  items.value.push(`${items.value.length + 1}`)
}
</script>

<template>
  <ul v-auto-animate>
    This is the way...
  </ul>
  <button @click.prevent="add">Add item</button>
</template>


================================================
FILE: build/nuxt-playground/nuxt.config.ts
================================================
export default defineNuxtConfig({
  modules: ["../../src/nuxt/module.ts"],
  autoAnimate: {},
  devtools: { enabled: false },
})


================================================
FILE: build/nuxt-playground/package.json
================================================
{
  "private": true,
  "name": "auto-animate-nuxt-module",
  "type": "module",
  "scripts": {
    "dev": "nuxi dev",
    "build": "nuxi build",
    "generate": "nuxi generate"
  },
  "devDependencies": {
    "nuxt": "latest"
  }
}


================================================
FILE: build/nuxt-playground/tsconfig.json
================================================
{
  "extends": "./.nuxt/tsconfig.json"
}


================================================
FILE: docs/assets/fonts.css
================================================

@font-face {
  font-family: 'silka';
  src: url('./fonts/silka/silka-medium-webfont.eot');
  src: url('./fonts/silka/silka-medium-webfont.eot?#iefix') format('embedded-opentype'),
       url('./fonts/silka/silka-medium-webfont.woff2') format('woff2'),
       url('./fonts/silka/silka-medium-webfont.woff') format('woff'),
       url('./fonts/silka/silka-medium-webfont.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'silka';
  src: url('./fonts/silka/silka-regular-webfont.eot');
  src: url('./fonts/silka/silka-regular-webfont.eot?#iefix') format('embedded-opentype'),
       url('./fonts/silka/silka-regular-webfont.woff2') format('woff2'),
       url('./fonts/silka/silka-regular-webfont.woff') format('woff'),
       url('./fonts/silka/silka-regular-webfont.ttf') format('truetype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'silka';
  src: url('./fonts/silka/silka-semibold-webfont.eot');
  src: url('./fonts/silka/silka-semibold-webfont.eot?#iefix') format('embedded-opentype'),
       url('./fonts/silka/silka-semibold-webfont.woff2') format('woff2'),
       url('./fonts/silka/silka-semibold-webfont.woff') format('woff'),
       url('./fonts/silka/silka-semibold-webfont.ttf') format('truetype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}


================================================
FILE: docs/assets/main.css
================================================
@import './fonts.css';
@import './variables.css';

body {
  font-family: 'silka', sans-serif;
  padding: 0;
  margin: 0;
  color: var(--text);
}

::selection {
  background: var(--purple-m); /* WebKit/Blink Browsers */
  color: #fff;
}
::-moz-selection {
  background: var(--purple-m); /* Gecko Browsers */
  color: #fff;
}

html {
  min-height: 100%;
  background-image:
    url('./img/pattern.svg'),
    linear-gradient(to bottom, rgb(103 0 255 / 4%), transparent),
    linear-gradient(to bottom left, rgb(255 0 201 / 2%), transparent);
  background-size: 4px 4px, 100vw 200vh, 100vw 200vh;
  background-repeat: repeat, no-repeat, no-repeat;
  scroll-behavior: smooth;
}

html[data-dark-mode="true"] {
  background: #160430;
  background-image:
    url('./img/pattern-dark.svg'),
    linear-gradient(to bottom, rgb(103 0 255 / 15%), transparent),
    linear-gradient(to bottom left, rgb(255 0 201 / 10%), transparent 50%);
  background-size: 4px 4px, 100vw 200vh, 100vw 200vh;
  background-repeat: repeat, no-repeat, no-repeat;
}

.container {
  width: calc(100% - 2em);
  max-width: 70em;
  margin: 0 auto;
}

@media (min-width: 28em) {
  .container {
    width: calc(100% - 4em);
  }
}

h1, h2, h3, h4{
  margin: 0 0 .75em;
  letter-spacing: -0.045em;
  line-height: 1.2;
}

h2 {
  padding-top: 1em;
}

#demo > h2:first-child {
  padding-top: 2.5em;
}

@media (min-width: 42em) {
  #demo > h2:first-child {
    padding-top: 0;
  }
}

h2.no-margin {
  padding-top: 0 !important;
}

h3 {
  margin-top: 2.5em;
}

h3 a:not(.button) {
  color: var(--text);
  display: inline-flex;
  align-items: center;
}

h3 a:not(.button) svg {
  width: .875em;
  display: block;
  margin-left: .5em;
}

h3 a:not(.button):hover svg {
  fill: var(--primary);
}

@media (min-width: 20em) {
  h2 {
    font-size: 1.75em;
  }
}

@media (min-width: 42em) {
  h2 {
    font-size: 2em;
  }
}
p {
  font-weight: 300;
  line-height: 1.5;
}

code {
  font-size: 0.9375em;
  padding: .1em .2em;
  background-color: rgba(0, 0, 0, .1);
  border-radius: .25em;
  line-height: 1;
  font-family: courier, monospace;
}
[data-dark-mode="true"] p code {
  background-color: rgba(255, 255, 255, .15);
  border: 1px solid var(--purple-md);
}
[data-dark-mode="true"] code > a:not(.button),
[data-dark-mode="true"] a:not(.button) > code {
  color: var(--purple-lm);
  text-decoration: underline;
}
section {
  margin-bottom: 3em;
}

section > ul {
  line-height: 1.5;
  list-style-type: none;
  margin: 1.5em 0;
}
section > ul li {
  margin-bottom: .5em;
  font-size: 1rem;
  font-weight: 300;
  color: currentColor;
}
section > ul li::before {
  content: '';
  display: block;
  width: 5px;
  height: 5px;
  border-radius: 5px;
  background-color: var(--primary);
  position: absolute;
  margin-left: -1em;
  margin-top: .55em;
}
[data-dark-mode="true"] section > ul li::before {
  background-color: var(--purple-m);
}
section h3 {
  margin: 1.5em 0 1em 0;
}
aside {
  display: block;
  padding: 1em;
  background-color: var(--purple-l);
  border-radius: .5em;
  margin: 2em 0;
}
[data-dark-mode="true"] aside {
  background-color: transparent;
  border: 2px solid var(--ui-green);
}

aside p {
  margin: 0;
  vertical-align: middle;
  font-size: .9em;
}

aside svg {
  width: 1.5em;
  display: inline-block;
  vertical-align: middle;
  fill: var(--purple-d);
}
[data-dark-mode="true"] aside svg {
  fill: var(--ui-green);
}
aside code {
  display: inline-block;
}

.button {
  appearance: none;
  background-color: var(--primary);
  border: 2px solid var(--primary);
  color: white;
  padding: 0.75em 2em;
  border-radius: 0.5em;
  box-shadow: 0 0 1em rgba(90, 41, 228, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  margin-bottom: 1em;
  text-decoration: none;
}

.button:hover {
  opacity: .9;
}

.button svg {
  width: 1em;
  fill: currentColor;
  display: block;
  margin-left: .5em;
}

@media (min-width: 23em) {
  .button {
    display: inline-flex;
    margin-right: 1em;
  }
}

.button--alt {
  background-color: rgba(255, 255, 255, .5);
  border-color: currentColor;
  color: grey;
  box-shadow: none;
}
[data-dark-mode="true"] .button--alt {
  background-color: var(--gray-l);
  border-color: #ddd;
  color: var(--gray-d);
}

.button--alt:hover {
  color: var(--grey-md);
}
[data-dark-mode="true"] .button--alt:hover {
  color: var(--gray-d);
  background: #fff;
}

a:not(.button) {
  color: var(--primary);
  text-decoration: none;
}
[data-dark-mode="true"] a:not(.button) {
  color: var(--purple-m);
}
a:not(.button):hover {
  text-decoration: underline;
}


.important {
  display: block;
  margin: 1.5em 2em;
  line-height: 1.4;
  font-size: 1.25em;
  opacity: 0.75;
}

.example {
  margin-bottom: 2em;
}

.example li {
  margin-bottom: .5em;
}

.formkit-outer {
  margin-bottom: 1em;
}

.formkit-label {
  display: block;
  margin-bottom: .25em;
}

.formkit-outer textarea,
.formkit-outer input {
  appearance: none;
  border: 1px solid var(--gray-l);
  padding: 0.75em;
  font-size: 0.875rem;
  width: 250px;
  max-width: 100%;
  border-radius: 0.5em;
  font-family: "silka";
  font-weight: 300;
}

.formkit-help {
  font-size: .75em;
  color: var(--gray-m);
  font-weight: 300;
  margin-top: .5em;
}

.formkit-outer label {
  font-weight: bold;
  font-size: 0.875em;
}

.formkit-outer .formkit-outer {
  margin-bottom: 0.5em;
}

.formkit-messages {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

li.formkit-message {
  font-size: .75em;
  padding-top: .25em;
  color: red;
  font-weight: 300;
  margin: 0;
}

.formkit-actions {
  margin-top: 0;
  transition: margin-top .25s;
}

.framework-jumplinks {
  padding: 0;
  margin: 2em 0;
  list-style-type: none;
  display: flex;
}
.framework-jumplinks li::before {
  display: none;
}
.framework-jumplinks a {
  width: 1.5em;
  height: 1.5em;
  padding: 1em;
  display: flex;
  border: 1px solid var(--purple-l);
  border-radius: .5em;
  margin-right: 1em;
  align-items: center;
  overflow: hidden;
  justify-content: center;
}
@media (min-width: 42em) {
  .framework-jumplinks a {
    width: 2em;
    height: 2em;
    padding: 1.25em;
    margin-right: 1.5em;
  }
}

.framework-jumplinks a:hover {
  background-color: var(--purple-ll);
}
.framework-jumplinks li:last-child a {
  margin-right: 0;
}
.framework-jumplinks a svg {
  width: 2.25em;
  aspect-ratio: 1;
  height: auto;
}
.framework-jumplinks a span {
  position: absolute;
  left: -999px;
}
.balls {
  background: url('./img/triangle.svg');
}


================================================
FILE: docs/assets/prism.css
================================================
/* PrismJS 1.28.0
https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript */
code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}


================================================
FILE: docs/assets/prism.js
================================================
/* PrismJS 1.28.0
https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+bash+jsx+tsx+typescript */
var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(n,t){var r,i;switch(t=t||{},a.util.type(n)){case"Object":if(i=a.util.objId(n),t[i])return t[i];for(var l in r={},t[i]=r,n)n.hasOwnProperty(l)&&(r[l]=e(n[l],t));return r;case"Array":return i=a.util.objId(n),t[i]?t[i]:(r=[],t[i]=r,n.forEach((function(n,a){r[a]=e(n,t)})),r);default:return n}},getLanguage:function(e){for(;e;){var t=n.exec(e.className);if(t)return t[1].toLowerCase();e=e.parentElement}return"none"},setLanguage:function(e,t){e.className=e.className.replace(RegExp(n,"gi"),""),e.classList.add("language-"+t)},currentScript:function(){if("undefined"==typeof document)return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(r){var e=(/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(r.stack)||[])[1];if(e){var n=document.getElementsByTagName("script");for(var t in n)if(n[t].src==e)return n[t]}return null}},isActive:function(e,n,t){for(var r="no-"+n;e;){var a=e.classList;if(a.contains(n))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!t}},languages:{plain:r,plaintext:r,text:r,txt:r,extend:function(e,n){var t=a.util.clone(a.languages[e]);for(var r in n)t[r]=n[r];return t},insertBefore:function(e,n,t,r){var i=(r=r||a.languages)[e],l={};for(var o in i)if(i.hasOwnProperty(o)){if(o==n)for(var s in t)t.hasOwnProperty(s)&&(l[s]=t[s]);t.hasOwnProperty(o)||(l[o]=i[o])}var u=r[e];return r[e]=l,a.languages.DFS(a.languages,(function(n,t){t===u&&n!=e&&(this[n]=l)})),l},DFS:function e(n,t,r,i){i=i||{};var l=a.util.objId;for(var o in n)if(n.hasOwnProperty(o)){t.call(n,o,n[o],r||o);var s=n[o],u=a.util.type(s);"Object"!==u||i[l(s)]?"Array"!==u||i[l(s)]||(i[l(s)]=!0,e(s,t,o,i)):(i[l(s)]=!0,e(s,t,null,i))}}},plugins:{},highlightAll:function(e,n){a.highlightAllUnder(document,e,n)},highlightAllUnder:function(e,n,t){var r={callback:t,container:e,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};a.hooks.run("before-highlightall",r),r.elements=Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)),a.hooks.run("before-all-elements-highlight",r);for(var i,l=0;i=r.elements[l++];)a.highlightElement(i,!0===n,r.callback)},highlightElement:function(n,t,r){var i=a.util.getLanguage(n),l=a.languages[i];a.util.setLanguage(n,i);var o=n.parentElement;o&&"pre"===o.nodeName.toLowerCase()&&a.util.setLanguage(o,i);var s={element:n,language:i,grammar:l,code:n.textContent};function u(e){s.highlightedCode=e,a.hooks.run("before-insert",s),s.element.innerHTML=s.highlightedCode,a.hooks.run("after-highlight",s),a.hooks.run("complete",s),r&&r.call(s.element)}if(a.hooks.run("before-sanity-check",s),(o=s.element.parentElement)&&"pre"===o.nodeName.toLowerCase()&&!o.hasAttribute("tabindex")&&o.setAttribute("tabindex","0"),!s.code)return a.hooks.run("complete",s),void(r&&r.call(s.element));if(a.hooks.run("before-highlight",s),s.grammar)if(t&&e.Worker){var c=new Worker(a.filename);c.onmessage=function(e){u(e.data)},c.postMessage(JSON.stringify({language:s.language,code:s.code,immediateClose:!0}))}else u(a.highlight(s.code,s.grammar,s.language));else u(a.util.encode(s.code))},highlight:function(e,n,t){var r={code:e,grammar:n,language:t};if(a.hooks.run("before-tokenize",r),!r.grammar)throw new Error('The language "'+r.language+'" has no grammar.');return r.tokens=a.tokenize(r.code,r.grammar),a.hooks.run("after-tokenize",r),i.stringify(a.util.encode(r.tokens),r.language)},tokenize:function(e,n){var t=n.rest;if(t){for(var r in t)n[r]=t[r];delete n.rest}var a=new s;return u(a,a.head,e),o(e,a,n,a.head,0),function(e){for(var n=[],t=e.head.next;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=a.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=a.hooks.all[e];if(t&&t.length)for(var r,i=0;r=t[i++];)r(n)}},Token:i};function i(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function l(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function o(e,n,t,r,s,g){for(var f in t)if(t.hasOwnProperty(f)&&t[f]){var h=t[f];h=Array.isArray(h)?h:[h];for(var d=0;d<h.length;++d){if(g&&g.cause==f+","+d)return;var v=h[d],p=v.inside,m=!!v.lookbehind,y=!!v.greedy,k=v.alias;if(y&&!v.pattern.global){var x=v.pattern.toString().match(/[imsuy]*$/)[0];v.pattern=RegExp(v.pattern.source,x+"g")}for(var b=v.pattern||v,w=r.next,A=s;w!==n.tail&&!(g&&A>=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(j<O||"string"==typeof C.value);C=C.next)L++,j+=C.value.length;L--,E=e.slice(A,j),P.index-=A}else if(!(P=l(b,0,E,m)))continue;S=P.index;var N=P[0],_=E.slice(0,S),M=E.slice(S+N.length),W=A+E.length;g&&W>g.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;n.next=r,r.prev=n,e.length-=a}if(e.Prism=a,i.stringify=function e(n,t){if("string"==typeof n)return n;if(Array.isArray(n)){var r="";return n.forEach((function(n){r+=e(n,t)})),r}var i={type:n.type,content:e(n.content,t),tag:"span",classes:["token",n.type],attributes:{},language:t},l=n.alias;l&&(Array.isArray(l)?Array.prototype.push.apply(i.classes,l):i.classes.push(l)),a.hooks.run("wrap",i);var o="";for(var s in i.attributes)o+=" "+s+'="'+(i.attributes[s]||"").replace(/"/g,"&quot;")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+o+">"+i.content+"</"+i.tag+">"},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
Prism.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&amp;/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^<!\[CDATA\[|\]\]>$/i;var t={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:<!\\[CDATA\\[(?:[^\\]]|\\](?!\\]>))*\\]\\]>|(?!<!\\[CDATA\\[)[^])*?(?=</__>)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;
!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism);
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript;
!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:a.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var o=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],s=a.variable[1].inside,i=0;i<o.length;i++)s[o[i]]=e.languages.bash[o[i]];e.languages.shell=e.languages.bash}(Prism);
!function(t){var n=t.util.clone(t.languages.javascript),e="(?:\\{<S>*\\.{3}(?:[^{}]|<BRACES>)*\\})";function a(t,n){return t=t.replace(/<S>/g,(function(){return"(?:\\s|//.*(?!.)|/\\*(?:[^*]|\\*(?!/))\\*/)"})).replace(/<BRACES>/g,(function(){return"(?:\\{(?:\\{(?:\\{[^{}]*\\}|[^{}])*\\}|[^{}])*\\})"})).replace(/<SPREAD>/g,(function(){return e})),RegExp(t,n)}e=a(e).source,t.languages.jsx=t.languages.extend("markup",n),t.languages.jsx.tag.pattern=a("</?(?:[\\w.:-]+(?:<S>+(?:[\\w.:$-]+(?:=(?:\"(?:\\\\[^]|[^\\\\\"])*\"|'(?:\\\\[^]|[^\\\\'])*'|[^\\s{'\"/>=]+|<BRACES>))?|<SPREAD>))*<S>*/?)?>"),t.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,t.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,t.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,t.languages.jsx.tag.inside.comment=n.comment,t.languages.insertBefore("inside","attr-name",{spread:{pattern:a("<SPREAD>"),inside:t.languages.jsx}},t.languages.jsx.tag),t.languages.insertBefore("inside","special-attr",{script:{pattern:a("=<BRACES>"),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:t.languages.jsx}}},t.languages.jsx.tag);var s=function(t){return t?"string"==typeof t?t:"string"==typeof t.content?t.content:t.content.map(s).join(""):""},g=function(n){for(var e=[],a=0;a<n.length;a++){var o=n[a],i=!1;if("string"!=typeof o&&("tag"===o.type&&o.content[0]&&"tag"===o.content[0].type?"</"===o.content[0].content[0].content?e.length>0&&e[e.length-1].tagName===s(o.content[0].content[1])&&e.pop():"/>"===o.content[o.content.length-1].content||e.push({tagName:s(o.content[0].content[1]),openedBraces:0}):e.length>0&&"punctuation"===o.type&&"{"===o.content?e[e.length-1].openedBraces++:e.length>0&&e[e.length-1].openedBraces>0&&"punctuation"===o.type&&"}"===o.content?e[e.length-1].openedBraces--:i=!0),(i||"string"==typeof o)&&e.length>0&&0===e[e.length-1].openedBraces){var r=s(o);a<n.length-1&&("string"==typeof n[a+1]||"plain-text"===n[a+1].type)&&(r+=s(n[a+1]),n.splice(a+1,1)),a>0&&("string"==typeof n[a-1]||"plain-text"===n[a-1].type)&&(r=s(n[a-1])+r,n.splice(a-1,1),a--),n[a]=new t.Token("plain-text",r,null,r)}o.content&&"string"!=typeof o.content&&g(o.content)}};t.hooks.add("after-tokenize",(function(t){"jsx"!==t.language&&"tsx"!==t.language||g(t.tokens)}))}(Prism);
!function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var s=e.languages.extend("typescript",{});delete s["class-name"],e.languages.typescript["class-name"].inside=s,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:s}}}}),e.languages.ts=e.languages.typescript}(Prism);
!function(e){var a=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",a),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var t=e.languages.tsx.tag;t.pattern=RegExp("(^|[^\\w$]|(?=</))(?:"+t.pattern.source+")",t.pattern.flags),t.lookbehind=!0}(Prism);


================================================
FILE: docs/assets/variables.css
================================================
:root {
  --system-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  --primary: #4711de;
  --ui-green: #28c840;
  --ui-red: #ff5f57;
  --ui-yellow: #febc2e;
  --ui-light: #f8f2fb;
  --gray-l: #cbcbcb;
  --gray-m: #878787;
  --gray-md: #585a51;
  --gray-d: #414339;
  --text: #333;
  --text-d: #333;
  --purple-ll: #f6f2ff;
  --purple-l: #ece3ff;
  --purple-lm: #deceff;
  --purple-m: #7335d7;
  --purple-d: #6500bf;
  --orange: #fcaa5e;
}

html[data-dark-mode="true"] {
  --ui-green: #5bc553;
  --text: #f5f5f5;
  --primary: #6232e6;
  --purple-m: #8c57e3;
  --purple-md: #432d68;
  --purple-d: #350b5a;
  --gray-l: #c6c4d0;
  --gray-m: #7d7483;
  --gray-md: #55515a;
  --gray-d: #3d3943;
}


================================================
FILE: docs/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/assets/favicon.ico" />
    <link rel="icon" type="image/svg+xml" href="/assets/img/favicon.svg">
    <link rel="icon" type="image/png" href="/assets/img/favicon.png">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script async defer src="https://buttons.github.io/buttons.js"></script>
    <title>AutoAnimate - Add motion to your apps with a single line of code</title>
    <meta name="description" content="A zero-config, drop-in animation utility that automatically adds smooth transitions to your web app. Use it with React, Solid, Vue, Svelte, or any other JavaScript application." />
    <meta property="og:title" content="AutoAnimate - Add motion to your apps with a single line of code" />
    <meta property="og:description" content="A zero-config, drop-in animation utility that automatically adds smooth transitions to your web app. Use it with React, Solid, Vue, Svelte, or any other JavaScript application." />
    <meta property="og:image" content="https://cdn.formk.it/web-assets/auto-animate-og.png" />
    <meta property="og:url" content="https://auto-animate.formkit.com/" />
    <meta property="og:type" content="article" />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:creator" content="@useFormKit" />
    <meta property="twitter:image" content="https://cdn.formk.it/web-assets/auto-animate-og.png" />
    <script src="https://smile-innovative.formkit.com/script.js" data-site="KMEKCZYO" defer></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
    <script src="https://cdn.formk.it/web-assets/prism.js" data-manual></script>
    <script async defer src="https://buttons.github.io/buttons.js"></script>
  </body>
</html>


================================================
FILE: docs/src/App.vue
================================================
<script setup lang="ts">
import { RouterView } from "vue-router"
import TheHeader from "./components/TheHeader.vue"
</script>

<template>
  <div class="site-wide-announcement" ref="announcement">
    <div class="container">
      <div class="announcement-content">
        <p>
          <strong>Introducing KickStart</strong> —  AI generated FormKit forms
          in seconds. Generate from a screenshot, edit with drag-and-drop or
          conversational AI, copy & paste as components or schema!<br />
          <a
            class="button button--pro-outline"
            href="https://kickstart.formkit.com"
          >
            Try for free
            <span class="formkit-icon"
              ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
                <path
                  fill="currentColor"
                  d="M440.6 273.4c4.7-4.5 7.4-10.8 7.4-17.4s-2.7-12.8-7.4-17.4l-176-168c-9.6-9.2-24.8-8.8-33.9.8s-8.8 24.8.8 33.9L364.1 232H24c-13.3 0-24 10.7-24 24s10.7 24 24 24h340.1L231.4 406.6c-9.6 9.2-9.9 24.3-.8 33.9s24.3 9.9 33.9.8l176-168z"
                ></path></svg
            ></span>
          </a>
        </p>
      </div>
    </div>
  </div>
  <div class="container">
    <RouterView />
  </div>
</template>

<style scoped>
.site-wide-announcement {
  position: relative;
  padding: 1em;
  text-align: center;
  font-size: 0.9em;
  line-height: 1.5;
  border-bottom: 1px solid var(--ui-border-light);
  overflow: clip;

  .container {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 800px;
    margin: 0 auto;
  }

  p {
    margin: 0;
    text-wrap: balance;
    font-size: 0.85rem;

    @media screen and (min-width: 768px) {
      font-size: 0.95rem;
    }
  }

  a {
    font-size: 0.85rem;
    padding: 0.33rem 1.15rem;
    margin-top: 1em;
    display: inline-flex;

    .formkit-icon {
      display: inline-block;
      margin-left: 0em;
      margin-right: 0.25em;
      width: 0.9em;
    }
  }

  &::before,
  &::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100dvw;
    z-index: -1;
  }

  &::before {
    top: 0;
    left: 0;
    width: 33%;
    height: 100%;
    background: linear-gradient(90deg, rgb(218, 231, 245), transparent);
  }
  &::after {
    top: 0;
    right: 0;
    height: 100%;
    background: linear-gradient(-90deg, rgb(247, 211, 249), transparent);
  }
}

[data-dark-mode="true"] .site-wide-announcement {
  &::before,
  &::after {
    opacity: 0.75;
    mix-blend-mode: overlay;
  }

  &::before {
    background: linear-gradient(90deg, rgb(101, 196, 233), transparent);
  }
  &::after {
    background: linear-gradient(-90deg, rgb(255, 108, 255), transparent);
  }
}
</style>


================================================
FILE: docs/src/components/AsideTip.vue
================================================
<script setup>
import IconLightbulb from "./IconLightbulb.vue"
</script>

<template>
  <aside class="tip">
    <IconLightbulb />
    <p><slot /></p>
  </aside>
</template>

<style scoped>
.tip {
  display: flex;
  align-items: flex-start;
}
.tip svg {
  margin-right: 1em;
  margin-top: 0.25em;
  width: 1.5em;
  height: 1.5em;
  flex-shrink: 0;
}
</style>


================================================
FILE: docs/src/components/CodeExample.vue
================================================
<script setup lang="ts">
import IconVue from "./IconVue.vue"
import IconReact from "./IconReact.vue"
import IconPreact from "./IconPreact.vue"
import IconSolid from "./IconSolid.vue"
import IconQwik from "./IconQwik.vue"
import IconHTML from "./IconHTML.vue"
import IconYarn from "./IconYarn.vue"
import IconNPM from "./IconNPM.vue"
import IconPNPM from "./IconPNPM.vue"
import IconJavaScript from "./IconJavaScript.vue"
import IconSvelte from "./IconSvelte.vue"
import IconAngular from "./IconAngular.vue"
import IconNuxt from "./IconNuxt.vue"
import IconBun from "./IconBun.vue"
import { computed, ref } from "vue"
import { vAutoAnimate } from "../../../src"
import "../../assets/prism.css"

type LanguageOption =
  | "react"
  | "preact"
  | "vue"
  | "html"
  | "solid"
  | "svelte"
  | "angular"
  | "qwik"
  | "js"
  | "yarn"
  | "npm"
  | "pnpm"
  | "nuxt"
  | "bun"

type Language = {
  ext: "jsx" | "vue" | "html"
  example: string
  title?: string
  language: string
}

type ParsedExamplesType = {
  [T in LanguageOption]?: Language & { highlighted: string }
}

const props = defineProps<{
  title: string
  examples: { [T in LanguageOption]: Language }
}>()

const current = ref<LanguageOption>(
  Object.keys(props.examples)[0] as LanguageOption
)

const type = computed(() => {
  return props.examples[current.value]
})
const allExamples = computed(() => {
  if (typeof window === "undefined") return ""
  const parsedExamples: ParsedExamplesType = {}
  const keys = Object.keys(props.examples) as (keyof typeof props.examples)[]
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const example = props.examples[key]
    parsedExamples[key] = {
      ...example,
      highlighted: window.Prism.highlight(
        example.example,
        window.Prism.languages[example.language],
        example.language
      ),
    }
  }
  return parsedExamples
})

const copyStatus = ref(false)
function copyCode(value: string) {
  window.navigator.clipboard.writeText(value)
  copyStatus.value = true
  setTimeout(() => {
    copyStatus.value = false
  }, 2000)
}
</script>

<template>
  <div class="window">
    <div class="window-header">
      <div class="control control--close"></div>
      <div class="control control--minimize"></div>
      <div class="control control--expand"></div>
      <span class="control-title">{{
        type.title || `${title}.${type.ext}`
      }}</span>
    </div>
    <div v-if="allExamples" class="code-block" v-auto-animate>
      <template v-for="(currentExample, key) in allExamples" :key="key">
        <code
          v-if="key === current"
          class="code-example"
          :key="key"
          v-html="currentExample!.highlighted"
          @click="copyCode(currentExample!.example)"
        ></code>
      </template>
      <template v-if="copyStatus">
        <span class="copy-status">Copied!</span>
      </template>
    </div>

    <div class="window-footer">
      <ul class="frameworks">
        <li
          v-if="'react' in props.examples"
          @click="current = 'react'"
          :data-selected="current === 'react' || null"
        >
          <IconReact />React
        </li>
        <li
          v-if="'vue' in props.examples"
          @click="current = 'vue'"
          :data-selected="current === 'vue' || null"
        >
          <IconVue />Vue
        </li>
        <li
          v-if="'preact' in props.examples"
          @click="current = 'preact'"
          :data-selected="current === 'preact' || null"
        >
          <IconPreact />Preact
        </li>
        <li
          v-if="'solid' in props.examples"
          @click="current = 'solid'"
          :data-selected="current === 'solid' || null"
        >
          <IconSolid />Solid
        </li>
        <li
          v-if="'svelte' in props.examples"
          @click="current = 'svelte'"
          :data-selected="current === 'svelte' || null"
        >
          <IconSvelte />Svelte
        </li>
        <li
          v-if="'angular' in props.examples"
          @click="current = 'angular'"
          :data-selected="current === 'angular' || null"
        >
          <IconAngular />Angular
        </li>
        <li
          v-if="'qwik' in props.examples"
          @click="current = 'qwik'"
          :data-selected="current === 'qwik' || null"
        >
          <IconQwik />Qwik
        </li>
        <li
          v-if="'js' in props.examples"
          @click="current = 'js'"
          :data-selected="current === 'js' || null"
        >
          <IconJavaScript />Native JS
        </li>
        <li
          v-if="'html' in props.examples"
          @click="current = 'html'"
          :data-selected="current === 'html' || null"
        >
          <IconHTML />HTML
        </li>
        <li
          v-if="'yarn' in props.examples"
          @click="current = 'yarn'"
          :data-selected="current === 'yarn' || null"
        >
          <IconYarn />yarn
        </li>
        <li
          v-if="'npm' in props.examples"
          @click="current = 'npm'"
          :data-selected="current === 'npm' || null"
        >
          <IconNPM />npm
        </li>
        <li
          v-if="'pnpm' in props.examples"
          @click="current = 'pnpm'"
          :data-selected="current === 'pnpm' || null"
        >
          <IconPNPM />pnpm
        </li>
        <li
          v-if="'bun' in props.examples"
          @click="current = 'bun'"
          :data-selected="current === 'bun' || null"
        >
          <IconBun />bun
        </li>
        <li
          v-if="'nuxt' in props.examples"
          @click="current = 'nuxt'"
          :data-selected="current === 'nuxt' || null"
        >
          <IconNuxt />Nuxt
        </li>
      </ul>
    </div>
  </div>
</template>

<style scoped>
.window {
  flex-grow: 1;
  background-color: rgba(0, 0, 0, 0.85);
  border-radius: 0.75em;
  color: white;
  padding: 1em;
  font-family: courier, monospace;
  box-shadow: 0 0 2em rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  margin: 2em 0;
}

.window-header {
  font-family: var(--system-stack);
  display: flex;
  margin: -1em -1em 0 -1em;
  padding: 0.75em 1em;
  margin-bottom: 0.5em;
  font-weight: 300;
  align-items: center;
  justify-content: flex-start;
  color: var(--gray-l);
}
.control-title {
  font-size: 14px;
  justify-self: center;
  margin: 0 auto;
  padding-right: 2.4rem;
}

.code-block {
  flex-grow: 1;
  overflow: hidden;
  display: flex;
}

.code-example {
  display: block;
  white-space: pre;
  font-size: 0.9rem;
  overflow: auto;
  background-color: transparent;
  line-height: 1.25;
}

.code-example::-webkit-scrollbar {
  display: none;
}

.copy-status {
  padding-left: 1em;
  color: var(--gray-l);
  font-family: var(--system-stack);
}

.control {
  width: 0.8em;
  height: 0.8em;
  border-radius: 1em;
  background-color: transparent;
  margin-right: 0.5em;
}
.control--close {
  background-color: var(--ui-red);
}
.control--minimize {
  background-color: var(--ui-yellow);
}
.control--expand {
  background-color: var(--ui-green);
}

.window-footer {
  padding: 0;
  border-radius: 0 0 0.5em 0.5em;
  background-color: var(--gray-d);
  margin: 1em -1em -1em -1em;
  font-family: var(--system-stack);
  -webkit-font-smoothing: anti-aliased;
  overflow: hidden;
}

.frameworks {
  -webkit-overflow-scrolling: touch;
  -ms-overflow-style: none;
  scrollbar-width: none;
  display: flex;
  align-items: center;
  list-style-type: none;
  padding: 0;
  margin: 0;
  overflow: auto;
}

.frameworks::-webkit-scrollbar {
  display: none;
}

.frameworks li {
  display: flex;
  align-items: center;
  font-size: 0.75em;
  padding: 0.75em 1em;
  cursor: pointer;
  margin-bottom: 0;
  white-space: nowrap;
}
.frameworks li:hover {
  background-color: var(--gray-m);
}
.frameworks li[data-selected] {
  background-color: rgba(255, 255, 255, 0.1);
}
.frameworks svg {
  display: block;
  width: 0.9em;
  margin-right: 0.5em;
  font-size: 1rem;
  max-height: 1em;
}
</style>


================================================
FILE: docs/src/components/ColorModeToggle.vue
================================================
<script setup>
import { ref, onMounted, watch } from 'vue'
import IconMoon from './IconMoon.vue'
import IconSun from './IconSun.vue'

const isDark = ref(false)
const toggleDarkMode = () =>{
  isDark.value = !isDark.value
  localStorage.setItem('darkMode', isDark.value);
}
const setColorAttribute = () => {
  if (typeof document !== undefined) {
    document.documentElement.setAttribute('data-dark-mode', isDark.value)
  }
}

onMounted(() => {
  if (localStorage.getItem('darkMode')) {
    isDark.value = localStorage.getItem('darkMode') === 'true'
  } else {
    isDark.value = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
  }
  setColorAttribute()
})

watch(isDark, setColorAttribute)
</script>

<template>
  <span @click="toggleDarkMode">
    <IconSun v-show="!isDark" />
    <IconMoon v-show="isDark" />
  </span>
</template>

<style scoped>
span {
  cursor: pointer;
}
span svg {
  width: 1.5em;
  height: 1.5em;
}
[data-dark-mode="true"] span svg {
  height: 1.25em;
}
</style>


================================================
FILE: docs/src/components/FormKitLogo.vue
================================================
<template>
  <svg
    viewBox="0 0 26 26"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
  >
    <g stroke="none" stroke-width="1" fill-rule="evenodd">
      <g transform="translate(-49.000000, -47.000000)">
        <g transform="translate(49.000000, 47.000000)">
          <path
            d="M24,21.01824 L24,25.01824 L12,25.01824 L12,21.01824 L24,21.01824 Z M4,17.01824 L4,21.01824 L0,21.01824 L0,17.01824 L4,17.01824 Z M8,13.01824 L8,17.01824 L4,17.01824 L4,13.01824 L8,13.01824 Z M12,9.01824 L12,13.01824 L8,13.01824 L8,9.01824 L12,9.01824 Z M8,5.01824 L8,9.01824 L4,9.01824 L4,5.01824 L8,5.01824 Z M4,1.01824 L4,5.01824 L0,5.01824 L0,1.01824 L4,1.01824 Z"
          />
        </g>
      </g>
    </g>
  </svg>
</template>

<script></script>


================================================
FILE: docs/src/components/GitHubLogo.vue
================================================
<template>
  <svg
    data-name="Layer 1"
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 120.78 117.79"
  >
    <path
      class="cls-1"
      d="M60.39,0A60.39,60.39,0,0,0,41.3,117.69c3,.56,4.12-1.31,4.12-2.91,0-1.44-.05-6.19-.08-11.24C28.54,107.19,25,96.42,25,96.42c-2.75-7-6.71-8.84-6.71-8.84-5.48-3.75.41-3.67.41-3.67,6.07.43,9.26,6.22,9.26,6.22,5.39,9.23,14.13,6.57,17.57,5,.55-3.9,2.11-6.56,3.84-8.07C36,85.55,21.85,80.37,21.85,57.23A23.35,23.35,0,0,1,28.08,41c-.63-1.52-2.7-7.66.58-16,0,0,5.07-1.62,16.61,6.19a57.36,57.36,0,0,1,30.25,0C87,23.42,92.11,25,92.11,25c3.28,8.32,1.22,14.46.59,16a23.34,23.34,0,0,1,6.21,16.21c0,23.2-14.12,28.3-27.57,29.8,2.16,1.87,4.09,5.55,4.09,11.18,0,8.08-.06,14.58-.06,16.57,0,1.61,1.08,3.49,4.14,2.9A60.39,60.39,0,0,0,60.39,0Z"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/HeroTitle.vue
================================================
<script setup>
import { onMounted, ref } from "vue"
import { vAutoAnimate } from "../../../src/index"
import TheLogo from "./TheLogo.vue"
import GitHubLogo from "./GitHubLogo.vue"
import IconArrow from "./IconArrow.vue"
import FormKitLogo from "./FormKitLogo.vue"
import CodeExample from "./CodeExample.vue"
import introExample from "../examples/intro"
</script>

<template>
  <section id="hero">
    <div class="intro">
      <h1 class="title">
        Add <span class="highlight">motion</span> to your apps with a single
        line of code.
      </h1>
      <p>
        AutoAnimate is a zero-config, drop-in animation utility that adds smooth
        transitions to your web app. You can use it with React, Solid, Vue,
        Svelte, or any other JavaScript application.
      </p>
      <div>
        <a class="button" href="#installation">Get started<IconArrow /></a>
        <a
          class="button button--alt"
          href="https://github.com/formkit/auto-animate"
          >GitHub<GitHubLogo
        /></a>
      </div>
      <a class="byline" href="https://www.formkit.com">
        <FormKitLogo class="formkit" width="16" height="16" /> made with ♥ by
        the FormKit team.
      </a>
    </div>
    <CodeExample title="App" :examples="introExample" class="example" />
  </section>
</template>

<style scoped>
section {
  display: block;
  margin-top: 1em;
  margin-bottom: 3em;
}

.intro {
  width: 100%;
}

.title {
  font-size: 2em;
}

@media (min-width: 24em) {
  .title {
    font-size: 2.25em;
  }
}

.title .highlight {
  font-size: inherit;
  color: var(--primary);
  background-image: linear-gradient(-45deg, var(--primary), var(--purple-m));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.title .highlight::selection {
  color: white;
  -webkit-text-fill-color: white;
}

@media (min-width: 28em) {
  section {
    margin-top: 4em;
    margin-bottom: 3em;
  }
  .intro {
    max-width: 34em;
  }
  .title {
    font-size: 2.5em;
  }
}

.intro p {
  display: block;
  padding-bottom: 2em;
  line-height: 1.4;
  font-weight: 300;
  margin: 0;
  max-width: 32em;
}

@media (min-width: 60em) {
  section {
    display: flex;
  }
  .example {
    margin-left: 2.5em;
    margin-top: 0;
    margin-bottom: 0;
    max-width: 26.7em;
    flex-shrink: 0;
    width: 50%;
  }
}

@media (min-width: 65em) {
  .example {
    max-width: none;
  }
}

.subtitle span {
  display: inline-block;
}
.title span {
  font-size: 1.3em;
  display: inline-block;
}

@media (min-width: 22em) {
  .title span {
    font-size: 1.4em;
  }
}
.logo {
  display: inline-block;
  width: 15vw;
  margin-top: 1em;
}

.byline {
  display: flex;
  vertical-align: flex-start;
  font-size: 0.875em;
  color: var(--gray-m);
  filter: grayscale(1);
  transition: filter 0.15s ease-out;
  font-weight: 300;
  margin-top: 1em;
}
[data-dark-mode="true"] .byline {
  color: var(--gray-l);
}
.byline span,
.byline svg {
  position: relative;
}
.byline span {
  font-size: 1em;
  max-height: 16px;
  margin-right: 0.4em;
  margin-left: 0.25em;
}

.byline svg {
  top: 0.15em;
}

.byline:hover {
  text-decoration: none;
  color: var(--primary);
  filter: grayscale(0);
}
[data-dark-mode="true"] .byline:hover {
  color: var(--text);
}
.formkit {
  display: block;
  width: 1rem;
  fill: var(--gray-m);
  margin-right: 0.5em;
}

.byline:hover .formkit {
  fill: var(--orange);
}
</style>


================================================
FILE: docs/src/components/IconAngular.vue
================================================
<template>
  <svg
    width="2370"
    height="2500"
    viewBox="0 0 256 270"
    xmlns="http://www.w3.org/2000/svg"
    preserveAspectRatio="xMinYMin meet"
  >
    <path
      d="M127.606.341L.849 44.95 20.88 211.022l106.86 58.732 107.412-59.528L255.175 44.16 127.606.341z"
      fill="#B3B3B3"
    />
    <path
      d="M242.532 53.758L127.31 14.466v241.256l96.561-53.441 18.66-148.523z"
      fill="#A6120D"
    />
    <path
      d="M15.073 54.466l17.165 148.525 95.07 52.731V14.462L15.074 54.465z"
      fill="#DD1B16"
    />
    <path
      d="M159.027 142.898L127.31 157.73H93.881l-15.714 39.305-29.228.54L127.31 23.227l31.717 119.672zm-3.066-7.467l-28.44-56.303-23.329 55.334h23.117l28.652.97z"
      fill="#F2F2F2"
    />
    <path
      d="M127.309 23.226l.21 55.902 26.47 55.377h-26.62l-.06 23.189 36.81.035 17.204 39.852 27.967.518-81.981-174.873z"
      fill="#B3B3B3"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconArrow.vue
================================================
<template>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    data-name="Layer 1"
    viewBox="0 0 100 100"
    x="0px"
    y="0px"
  >
    <path
      d="M97.64,44.1,64.72,11.18a8.06,8.06,0,1,0-11.4,11.39L72.78,42H8.06a8.06,8.06,0,0,0,0,16.12H72.6L53.32,77.43a8.06,8.06,0,0,0,11.4,11.39L97.64,55.9A8,8,0,0,0,100,50.2a1.27,1.27,0,0,0,0-.2,1.41,1.41,0,0,0,0-.2A8.07,8.07,0,0,0,97.64,44.1Z"
    ></path>
  </svg>
</template>


================================================
FILE: docs/src/components/IconBun.vue
================================================
<template>
  <svg id="Bun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 70">
    <title>Bun Logo</title>
    <path
      id="Shadow"
      d="M71.09,20.74c-.16-.17-.33-.34-.5-.5s-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5A26.46,26.46,0,0,1,75.5,35.7c0,16.57-16.82,30.05-37.5,30.05-11.58,0-21.94-4.23-28.83-10.86l.5.5.5.5.5.5.5.5.5.5.5.5.5.5C19.55,65.3,30.14,69.75,42,69.75c20.68,0,37.5-13.48,37.5-30C79.5,32.69,76.46,26,71.09,20.74Z"
    />
    <g id="Body">
      <path
        id="Background"
        d="M73,35.7c0,15.21-15.67,27.54-35,27.54S3,50.91,3,35.7C3,26.27,9,17.94,18.22,13S33.18,3,38,3s8.94,4.13,19.78,10C67,17.94,73,26.27,73,35.7Z"
        style="fill: #fbf0df"
      />
      <path
        id="Bottom_Shadow"
        data-name="Bottom Shadow"
        d="M73,35.7a21.67,21.67,0,0,0-.8-5.78c-2.73,33.3-43.35,34.9-59.32,24.94A40,40,0,0,0,38,63.24C57.3,63.24,73,50.89,73,35.7Z"
        style="fill: #f6dece"
      />
      <path
        id="Light_Shine"
        data-name="Light Shine"
        d="M24.53,11.17C29,8.49,34.94,3.46,40.78,3.45A9.29,9.29,0,0,0,38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7c0,.4,0,.8,0,1.19C9.06,15.48,20.07,13.85,24.53,11.17Z"
        style="fill: #fffefc"
      />
      <path
        id="Top"
        d="M35.12,5.53A16.41,16.41,0,0,1,29.49,18c-.28.25-.06.73.3.59,3.37-1.31,7.92-5.23,6-13.14C35.71,5,35.12,5.12,35.12,5.53Zm2.27,0A16.24,16.24,0,0,1,39,19c-.12.35.31.65.55.36C41.74,16.56,43.65,11,37.93,5,37.64,4.74,37.19,5.14,37.39,5.49Zm2.76-.17A16.42,16.42,0,0,1,47,17.12a.33.33,0,0,0,.65.11c.92-3.49.4-9.44-7.17-12.53C40.08,4.54,39.82,5.08,40.15,5.32ZM21.69,15.76a16.94,16.94,0,0,0,10.47-9c.18-.36.75-.22.66.18-1.73,8-7.52,9.67-11.12,9.45C21.32,16.4,21.33,15.87,21.69,15.76Z"
        style="fill: #ccbea7; fill-rule: evenodd"
      />
      <path
        id="Outline"
        d="M38,65.75C17.32,65.75.5,52.27.5,35.7c0-10,6.18-19.33,16.53-24.92,3-1.6,5.57-3.21,7.86-4.62,1.26-.78,2.45-1.51,3.6-2.19C32,1.89,35,.5,38,.5s5.62,1.2,8.9,3.14c1,.57,2,1.19,3.07,1.87,2.49,1.54,5.3,3.28,9,5.27C69.32,16.37,75.5,25.69,75.5,35.7,75.5,52.27,58.68,65.75,38,65.75ZM38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7,3,50.89,18.7,63.25,38,63.25S73,50.89,73,35.7C73,26.62,67.31,18.13,57.78,13,54,11,51.05,9.12,48.66,7.64c-1.09-.67-2.09-1.29-3-1.84C42.63,4,40.42,3,38,3Z"
      />
    </g>
    <g id="Mouth">
      <g id="Background-2" data-name="Background">
        <path
          d="M45.05,43a8.93,8.93,0,0,1-2.92,4.71,6.81,6.81,0,0,1-4,1.88A6.84,6.84,0,0,1,34,47.71,8.93,8.93,0,0,1,31.12,43a.72.72,0,0,1,.8-.81H44.26A.72.72,0,0,1,45.05,43Z"
          style="fill: #b71422"
        />
      </g>
      <g id="Tongue">
        <path
          id="Background-3"
          data-name="Background"
          d="M34,47.79a6.91,6.91,0,0,0,4.12,1.9,6.91,6.91,0,0,0,4.11-1.9,10.63,10.63,0,0,0,1-1.07,6.83,6.83,0,0,0-4.9-2.31,6.15,6.15,0,0,0-5,2.78C33.56,47.4,33.76,47.6,34,47.79Z"
          style="fill: #ff6164"
        />
        <path
          id="Outline-2"
          data-name="Outline"
          d="M34.16,47a5.36,5.36,0,0,1,4.19-2.08,6,6,0,0,1,4,1.69c.23-.25.45-.51.66-.77a7,7,0,0,0-4.71-1.93,6.36,6.36,0,0,0-4.89,2.36A9.53,9.53,0,0,0,34.16,47Z"
        />
      </g>
      <path
        id="Outline-3"
        data-name="Outline"
        d="M38.09,50.19a7.42,7.42,0,0,1-4.45-2,9.52,9.52,0,0,1-3.11-5.05,1.2,1.2,0,0,1,.26-1,1.41,1.41,0,0,1,1.13-.51H44.26a1.44,1.44,0,0,1,1.13.51,1.19,1.19,0,0,1,.25,1h0a9.52,9.52,0,0,1-3.11,5.05A7.42,7.42,0,0,1,38.09,50.19Zm-6.17-7.4c-.16,0-.2.07-.21.09a8.29,8.29,0,0,0,2.73,4.37A6.23,6.23,0,0,0,38.09,49a6.28,6.28,0,0,0,3.65-1.73,8.3,8.3,0,0,0,2.72-4.37.21.21,0,0,0-.2-.09Z"
      />
    </g>
    <g id="Face">
      <ellipse
        id="Right_Blush"
        data-name="Right Blush"
        cx="53.22"
        cy="40.18"
        rx="5.85"
        ry="3.44"
        style="fill: #febbd0"
      />
      <ellipse
        id="Left_Bluch"
        data-name="Left Bluch"
        cx="22.95"
        cy="40.18"
        rx="5.85"
        ry="3.44"
        style="fill: #febbd0"
      />
      <path
        id="Eyes"
        d="M25.7,38.8a5.51,5.51,0,1,0-5.5-5.51A5.51,5.51,0,0,0,25.7,38.8Zm24.77,0A5.51,5.51,0,1,0,45,33.29,5.5,5.5,0,0,0,50.47,38.8Z"
        style="fill-rule: evenodd"
      />
      <path
        id="Iris"
        d="M24,33.64a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,24,33.64Zm24.77,0a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,48.75,33.64Z"
        style="fill: #fff; fill-rule: evenodd"
      />
    </g>
  </svg>
</template>


================================================
FILE: docs/src/components/IconDiscord.vue
================================================
<template>
  <svg
    width="71"
    height="55"
    viewBox="0 0 71 55"
    xmlns="http://www.w3.org/2000/svg"
  >
    <g clip-path="url(#clip0)">
      <path
        d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z"
      />
    </g>
    <defs>
      <clipPath id="clip0">
        <rect width="71" height="55" fill="white" />
      </clipPath>
    </defs>
  </svg>
</template>


================================================
FILE: docs/src/components/IconDown.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
    <path
      d="M113.95,36.55c-2.73-2.73-7.17-2.73-9.9,0l-40.05,40.05L23.95,36.55c-2.73-2.73-7.17-2.73-9.9,0-2.73,2.73-2.73,7.17,0,9.9l45,45c1.37,1.37,3.16,2.05,4.95,2.05s3.58-.68,4.95-2.05l45-45c2.73-2.73,2.73-7.17,0-9.9Z"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconHTML.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
    <title>HTML5 Logo Badge</title>
    <path fill="#E34F26" d="M71,460 L30,0 481,0 440,460 255,512" />
    <path fill="#EF652A" d="M256,472 L405,431 440,37 256,37" />
    <path
      fill="#EBEBEB"
      d="M256,208 L181,208 176,150 256,150 256,94 255,94 114,94 115,109 129,265 256,265zM256,355 L255,355 192,338 188,293 158,293 132,293 139,382 255,414 256,414z"
    />
    <path
      fill="#FFF"
      d="M255,208 L255,265 325,265 318,338 255,355 255,414 371,382 372,372 385,223 387,208 371,208zM255,94 L255,129 255,150 255,150 392,150 392,150 392,150 393,138 396,109 397,94z"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconJavaScript.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 630 630">
    <rect width="630" height="630" fill="#f7df1e" />
    <path
      d="m423.2 492.19c12.69 20.72 29.2 35.95 58.4 35.95 24.53 0 40.2-12.26 40.2-29.2 0-20.3-16.1-27.49-43.1-39.3l-14.8-6.35c-42.72-18.2-71.1-41-71.1-89.2 0-44.4 33.83-78.2 86.7-78.2 37.64 0 64.7 13.1 84.2 47.4l-46.1 29.6c-10.15-18.2-21.1-25.37-38.1-25.37-17.34 0-28.33 11-28.33 25.37 0 17.76 11 24.95 36.4 35.95l14.8 6.34c50.3 21.57 78.7 43.56 78.7 93 0 53.3-41.87 82.5-98.1 82.5-54.98 0-90.5-26.2-107.88-60.54zm-209.13 5.13c9.3 16.5 17.76 30.45 38.1 30.45 19.45 0 31.72-7.61 31.72-37.2v-201.3h59.2v202.1c0 61.3-35.94 89.2-88.4 89.2-47.4 0-74.85-24.53-88.81-54.075z"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconLightbulb.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
    <path
      d="M24.99,2c-8.26,0-14.99,6.66-14.99,14.82,0,4.41,1.98,9.7,5.1,13.65v3.71c0,1.13,.74,2.04,1.65,2.04h16.5c.91,0,1.65-.91,1.65-2.04v-3.72c3.12-3.94,5.1-9.24,5.1-13.65,0-8.16-6.74-14.82-15.01-14.82Zm0,3.26c6.48,0,11.7,5.16,11.7,11.56,0,3.47-1.48,7.91-3.89,11.25h-15.61c-2.41-3.35-3.89-7.78-3.89-11.25,0-6.4,5.21-11.56,11.69-11.56Z"
    />
    <path
      d="M17.99,37.84c-.91,0-1.65,.73-1.65,1.63s.74,1.63,1.65,1.63h14.02c.91,0,1.65-.73,1.65-1.63s-.74-1.63-1.65-1.63h-14.02Z"
    />
    <path
      d="M19.93,42.74c-.91,.04-1.61,.81-1.57,1.71,.04,.9,.82,1.59,1.73,1.55h9.9c.91,0,1.65-.73,1.65-1.63s-.74-1.63-1.65-1.63h-9.9c-.05,0-.11,0-.16,0Z"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconMoon.vue
================================================
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M32 256c0-123.8 100.3-224 223.8-224c11.36 0 29.7 1.668 40.9 3.746c9.616 1.777 11.75 14.63 3.279 19.44C245 86.5 211.2 144.6 211.2 207.8c0 109.7 99.71 193 208.3 172.3c9.561-1.805 16.28 9.324 10.11 16.95C387.9 448.6 324.8 480 255.8 480C132.1 480 32 379.6 32 256z"/></svg>
</template>


================================================
FILE: docs/src/components/IconNPM.vue
================================================
<template>
  <svg
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    x="0px"
    y="0px"
    width="540px"
    height="210px"
    viewBox="0 0 18 7"
  >
    <path
      fill="#CB3837"
      d="M0,0h18v6H9v1H5V6H0V0z M1,5h2V2h1v3h1V1H1V5z M6,1v5h2V5h2V1H6z M8,2h1v2H8V2z M11,1v4h2V2h1v3h1V2h1v3h1V1H11z"
    />
    <polygon fill="#FFFFFF" points="1,5 3,5 3,2 4,2 4,5 5,5 5,1 1,1 " />
    <path fill="#FFFFFF" d="M6,1v5h2V5h2V1H6z M9,4H8V2h1V4z" />
    <polygon
      fill="#FFFFFF"
      points="11,1 11,5 13,5 13,2 14,2 14,5 15,5 15,2 16,2 16,5 17,5 17,1 "
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconNuxt.vue
================================================
<template>
  <svg
    width="900"
    height="900"
    viewBox="0 0 900 900"
    fill="none"
  >
    <path
      d="M504.908 750H839.476C850.103 750.001 860.542 747.229 869.745 741.963C878.948 736.696 886.589 729.121 891.9 719.999C897.211 710.876 900.005 700.529 900 689.997C899.995 679.465 897.193 669.12 891.873 660.002L667.187 274.289C661.876 265.169 654.237 257.595 645.036 252.329C635.835 247.064 625.398 244.291 614.773 244.291C604.149 244.291 593.711 247.064 584.511 252.329C575.31 257.595 567.67 265.169 562.36 274.289L504.908 372.979L392.581 179.993C387.266 170.874 379.623 163.301 370.42 158.036C361.216 152.772 350.777 150 340.151 150C329.525 150 319.086 152.772 309.883 158.036C300.679 163.301 293.036 170.874 287.721 179.993L8.12649 660.002C2.80743 669.12 0.00462935 679.465 5.72978e-06 689.997C-0.00461789 700.529 2.78909 710.876 8.10015 719.999C13.4112 729.121 21.0523 736.696 30.255 741.963C39.4576 747.229 49.8973 750.001 60.524 750H270.538C353.748 750 415.112 713.775 457.336 643.101L559.849 467.145L614.757 372.979L779.547 655.834H559.849L504.908 750ZM267.114 655.737L120.551 655.704L340.249 278.586L449.87 467.145L376.474 593.175C348.433 639.03 316.577 655.737 267.114 655.737Z"
      fill="#00DC82"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconOutbound.vue
================================================
<template>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    version="1.1"
    x="0px"
    y="0px"
    viewBox="0 0 1024 1024"
    style="enable-background: new 0 0 1024 1024"
    xml:space="preserve"
    fill="currentColor"
  >
    <g>
      <g>
        <g>
          <path
            d="M631.3,160.8c30.6,0,61.2,0,91.7,0c48.9,0,97.8,0,146.7,0c11.2,0,22.3,0,33.5,0     c-13.3-13.3-26.7-26.7-40-40c0,30.6,0,61.2,0,91.7c0,48.9,0,97.8,0,146.7c0,11.2,0,22.3,0,33.5c0,20.9,18.4,41,40,40     c21.7-1,40-17.6,40-40c0-30.6,0-61.2,0-91.7c0-48.9,0-97.8,0-146.7c0-11.2,0-22.3,0-33.5c0-21.6-18.3-40-40-40     c-30.6,0-61.2,0-91.7,0c-48.9,0-97.8,0-146.7,0c-11.2,0-22.3,0-33.5,0c-20.9,0-41,18.4-40,40     C592.2,142.4,608.8,160.8,631.3,160.8L631.3,160.8z"
          ></path>
        </g>
      </g>
      <g>
        <g>
          <path
            d="M480.3,600.3c15-15,29.9-29.9,44.9-44.9c35.9-35.9,71.8-71.8,107.8-107.8     c43.5-43.5,86.9-86.9,130.4-130.4c37.6-37.6,75.1-75.1,112.7-112.7c18.3-18.3,36.8-36.3,54.8-54.8c0.3-0.3,0.5-0.5,0.8-0.8     c14.8-14.8,15.9-42,0-56.6c-16-14.7-40.8-15.8-56.6,0c-15,15-29.9,29.9-44.9,44.9c-35.9,35.9-71.8,71.8-107.8,107.8     C678.9,288.5,635.4,332,592,375.5c-37.6,37.6-75.1,75.1-112.7,112.7c-18.3,18.3-36.8,36.3-54.8,54.8c-0.3,0.3-0.5,0.5-0.8,0.8     c-14.8,14.8-15.9,42,0,56.6C439.7,614.9,464.5,616.1,480.3,600.3L480.3,600.3z"
          ></path>
        </g>
      </g>
      <g>
        <g>
          <path
            d="M863.3,572.8c0,30.4,0,60.7,0,91.1c0,47.1,0,94.2,0,141.4c0,12.5,1,25.6-0.7,38.1c0.5-3.5,1-7.1,1.4-10.6     c-0.9,5.8-2.4,11.3-4.6,16.8c1.3-3.2,2.7-6.4,4-9.6c-2.4,5.7-5.5,10.9-9.2,15.9c2.1-2.7,4.2-5.4,6.3-8.1     c-3.8,4.8-8.1,9.1-12.9,12.9c2.7-2.1,5.4-4.2,8.1-6.3c-4.9,3.7-10.2,6.8-15.9,9.2c3.2-1.3,6.4-2.7,9.6-4     c-5.4,2.2-11,3.7-16.8,4.6c3.5-0.5,7.1-1,10.6-1.4c-8.2,1.1-16.7,0.7-25,0.7c-15.5,0-30.9,0-46.4,0c-51.6,0-103.2,0-154.8,0     c-62.7,0-125.5,0-188.2,0c-54,0-108,0-162,0c-25.4,0-50.8,0.2-76.1,0c-3.4,0-6.8-0.2-10.2-0.7c3.5,0.5,7.1,1,10.6,1.4     c-5.8-0.9-11.3-2.4-16.8-4.6c3.2,1.3,6.4,2.7,9.6,4c-5.7-2.4-10.9-5.5-15.9-9.2c2.7,2.1,5.4,4.2,8.1,6.3     c-4.8-3.8-9.1-8.1-12.9-12.9c2.1,2.7,4.2,5.4,6.3,8.1c-3.7-4.9-6.8-10.2-9.2-15.9c1.3,3.2,2.7,6.4,4,9.6     c-2.2-5.4-3.7-11-4.6-16.8c0.5,3.5,1,7.1,1.4,10.6c-1.1-8.2-0.7-16.7-0.7-25c0-15.5,0-30.9,0-46.4c0-51.6,0-103.2,0-154.8     c0-62.7,0-125.5,0-188.2c0-54,0-108,0-162c0-25.4-0.2-50.8,0-76.1c0-3.4,0.2-6.8,0.7-10.2c-0.5,3.5-1,7.1-1.4,10.6     c0.9-5.8,2.4-11.3,4.6-16.8c-1.3,3.2-2.7,6.4-4,9.6c2.4-5.7,5.5-10.9,9.2-15.9c-2.1,2.7-4.2,5.4-6.3,8.1     c3.8-4.8,8.1-9.1,12.9-12.9c-2.7,2.1-5.4,4.2-8.1,6.3c4.9-3.7,10.2-6.8,15.9-9.2c-3.2,1.3-6.4,2.7-9.6,4c5.4-2.2,11-3.7,16.8-4.6     c-3.5,0.5-7.1,1-10.6,1.4c10.6-1.4,21.6-0.7,32.2-0.7c20.6,0,41.2,0,61.9,0c47.8,0,95.5,0,143.3,0c11.1,0,22.1,0,33.2,0     c20.9,0,41-18.4,40-40c-1-21.7-17.6-40-40-40c-27.2,0-54.4,0-81.6,0c-45.4,0-90.9,0-136.3,0c-13.1,0-26.2,0-39.2,0     c-30.7,0-60.5,10.7-82.1,33.1c-20.3,21.1-31.2,49-31.2,78.2c0,6.1,0,12.2,0,18.2c0,28.4,0,56.7,0,85.1c0,42.6,0,85.2,0,127.8     c0,48,0,96.1,0,144.1c0,44.7,0,89.3,0,134c0,32.5,0,65,0,97.6c0,18.9-0.8,37.8,2.3,56.5c3.5,21.1,15.5,42,30.8,56.7     c7.8,7.5,17,14.5,26.9,19.2c13.9,6.5,26.1,9.9,41.3,11.5c5.7,0.6,11.3,0.5,17,0.5c23.5,0,47.1,0,70.6,0c39.9,0,79.9,0,119.8,0     c47.5,0,95,0,142.5,0c46.2,0,92.3,0,138.5,0c36.4,0,72.9,0,109.3,0c17.5,0,35,0,52.5,0c30-0.1,60.1-11.8,80.7-34     c7.2-7.8,14.1-16.8,18.6-26.5c6.4-13.9,9.6-25.6,11.3-40.7c0.5-4.3,0.5-8.6,0.5-12.9c0-35.3,0-70.6,0-105.9     c0-42.8,0-85.6,0-128.4c0-7.3,0-14.7,0-22c0-20.9-18.4-41-40-40C881.6,533.7,863.3,550.3,863.3,572.8L863.3,572.8z"
          ></path>
        </g>
      </g>
    </g>
  </svg>
</template>


================================================
FILE: docs/src/components/IconPNPM.vue
================================================
<template>
  <svg
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    preserveAspectRatio="xMidYMid meet"
    viewBox="76.58987244897958 44 164.00775510204068 164"
    width="160.01"
    height="160"
  >
    <defs>
      <path
        d="M237.6 95L187.6 95L187.6 45L237.6 45L237.6 95Z"
        id="arNRoK435"
      ></path>
      <path
        d="M182.59 95L132.59 95L132.59 45L182.59 45L182.59 95Z"
        id="a3H2WU7Px"
      ></path>
      <path
        d="M127.59 95L77.59 95L77.59 45L127.59 45L127.59 95Z"
        id="b1DInM56vl"
      ></path>
      <path
        d="M237.6 150L187.6 150L187.6 100L237.6 100L237.6 150Z"
        id="a7LFlgQIwu"
      ></path>
      <path
        d="M182.59 150L132.59 150L132.59 100L182.59 100L182.59 150Z"
        id="amwLiZcuo"
      ></path>
      <path
        d="M182.59 205L132.59 205L132.59 155L182.59 155L182.59 205Z"
        id="f3Peu5RWan"
      ></path>
      <path
        d="M237.6 205L187.6 205L187.6 155L237.6 155L237.6 205Z"
        id="a6DXBfqPa"
      ></path>
      <path
        d="M127.59 205L77.59 205L77.59 155L127.59 155L127.59 205Z"
        id="c1GWSTH1z7"
      ></path>
    </defs>
    <g>
      <g>
        <use
          xlink:href="#arNRoK435"
          opacity="1"
          fill="#f9ad00"
          fill-opacity="1"
        ></use>
      </g>
      <g>
        <use
          xlink:href="#a3H2WU7Px"
          opacity="1"
          fill="#f9ad00"
          fill-opacity="1"
        ></use>
      </g>
      <g>
        <use
          xlink:href="#b1DInM56vl"
          opacity="1"
          fill="#f9ad00"
          fill-opacity="1"
        ></use>
      </g>
      <g>
        <use
          xlink:href="#a7LFlgQIwu"
          opacity="1"
          fill="#f9ad00"
          fill-opacity="1"
        ></use>
      </g>
      <g>
        <use
          xlink:href="#amwLiZcuo"
          opacity="1"
          fill="#4e4e4e"
          fill-opacity="1"
        ></use>
      </g>
      <g>
        <use
          xlink:href="#f3Peu5RWan"
          opacity="1"
          fill="#4e4e4e"
          fill-opacity="1"
        ></use>
      </g>
      <g>
        <use
          xlink:href="#a6DXBfqPa"
          opacity="1"
          fill="#4e4e4e"
          fill-opacity="1"
        ></use>
      </g>
      <g>
        <use
          xlink:href="#c1GWSTH1z7"
          opacity="1"
          fill="#4e4e4e"
          fill-opacity="1"
        ></use>
      </g>
    </g>
  </svg>
</template>


================================================
FILE: docs/src/components/IconPreact.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="296px" height="296px" viewBox="-20 0 296 296" version="1.1" preserveAspectRatio="xMidYMid">
	<g>
		<polygon fill="#673AB8" points="128 0 256 73.8999491 256 221.699847 128 295.599796 0 221.699847 0 73.8999491"/>
		<path d="M34.8647584,220.478469 C51.8814262,242.25881 105.959701,225.662965 157.014868,185.774297 C208.070035,145.885628 237.255632,97.428608 220.238964,75.6482664 C203.222296,53.8679249 149.144022,70.4637701 98.0888543,110.352439 C47.0336869,150.241107 17.8480906,198.698127 34.8647584,220.478469 Z M42.1343351,214.798853 C36.4908625,207.575537 38.9565723,193.395881 49.7081913,175.544904 C61.0297348,156.747677 80.2490923,135.997367 103.76847,117.622015 C127.287848,99.2466634 152.071368,85.6181573 173.049166,79.1803727 C192.970945,73.066665 207.325915,74.1045667 212.969387,81.3278822 C218.61286,88.5511977 216.14715,102.730854 205.395531,120.581832 C194.073987,139.379058 174.85463,160.129368 151.335252,178.50472 C127.815874,196.880072 103.032354,210.508578 82.054556,216.946362 C62.1327769,223.06007 47.7778077,222.022168 42.1343351,214.798853 Z" fill="#FFFFFF"/>
		<path d="M220.238964,220.478469 C237.255632,198.698127 208.070035,150.241107 157.014868,110.352439 C105.959701,70.4637701 51.8814262,53.8679249 34.8647584,75.6482664 C17.8480906,97.428608 47.0336869,145.885628 98.0888543,185.774297 C149.144022,225.662965 203.222296,242.25881 220.238964,220.478469 Z M212.969387,214.798853 C207.325915,222.022168 192.970945,223.06007 173.049166,216.946362 C152.071368,210.508578 127.287848,196.880072 103.76847,178.50472 C80.2490923,160.129368 61.0297348,139.379058 49.7081913,120.581832 C38.9565723,102.730854 36.4908625,88.5511977 42.1343351,81.3278822 C47.7778077,74.1045667 62.1327769,73.066665 82.054556,79.1803727 C103.032354,85.6181573 127.815874,99.2466634 151.335252,117.622015 C174.85463,135.997367 194.073987,156.747677 205.395531,175.544904 C216.14715,193.395881 218.61286,207.575537 212.969387,214.798853 Z" fill="#FFFFFF"/>
		<path d="M127.551861,167.666971 C138.378632,167.666971 147.155465,158.890139 147.155465,148.063368 C147.155465,137.236596 138.378632,128.459764 127.551861,128.459764 C116.72509,128.459764 107.948257,137.236596 107.948257,148.063368 C107.948257,158.890139 116.72509,167.666971 127.551861,167.666971 L127.551861,167.666971 Z" fill="#FFFFFF"/>
	</g>
  </svg>
</template>


================================================
FILE: docs/src/components/IconQwik.vue
================================================
<template>
  <svg width="256px" height="272px" viewBox="0 0 256 272" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
    <title>Qwik</title>
    <g>
        <path d="M224.802633,271.548066 L176.04373,223.065139 L175.29865,223.17158 L175.29865,222.639928 L71.6062201,120.251664 L97.1567871,95.5849889 L82.1459867,9.46423235 L10.923994,97.7115967 C-1.21249511,109.938494 -3.44814914,129.82085 5.28159772,144.493127 L49.7819901,218.280821 C56.5954198,229.657294 68.9446684,236.461781 82.2524269,236.355341 L104.289921,236.14246 L224.802633,271.548066 Z" fill="#18B6F6"></path>
        <path d="M251.41376,96.0096521 L241.619075,77.935132 L236.508852,68.685266 L234.486489,65.0701426 L234.273609,65.2830228 L207.445212,18.8201544 C200.738387,7.12474433 188.176258,-0.105173442 174.549179,4.00642427e-13 L151.021523,0.639029547 L80.8637673,0.851690324 C67.5565576,0.958020713 55.4201892,7.97527771 48.7129802,19.3517514 L6.02242644,103.983883 L82.3544777,9.25113264 L182.427394,119.187811 L164.648054,137.15644 L175.29426,223.171031 L175.4007,222.958151 L175.4007,223.171031 L175.18782,223.171031 L175.4007,223.383362 L183.704676,231.464033 L224.053163,270.909425 C225.756753,272.504381 228.524745,270.590653 227.353355,268.570486 L202.441978,219.555907 L245.877777,139.283048 L247.261498,137.688092 C247.793699,137.05 248.3259,136.412457 248.752209,135.774364 C257.269064,124.18501 258.439906,108.66231 251.41376,96.0096521 Z" fill="#AC7EF4"></path>
        <polygon fill="#FFFFFF" points="182.745617 118.763148 82.3533804 9.35773736 96.6190999 95.053337 71.0685329 119.826452 175.080283 223.065139 165.711906 137.36932"></polygon>
    </g>
  </svg>
</template>


================================================
FILE: docs/src/components/IconReact.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="-11.5 -10.23174 23 20.46348">
    <title>React Logo</title>
    <circle cx="0" cy="0" r="2.05" fill="#61dafb" />
    <g stroke="#61dafb" stroke-width="1" fill="none">
      <ellipse rx="11" ry="4.2" />
      <ellipse rx="11" ry="4.2" transform="rotate(60)" />
      <ellipse rx="11" ry="4.2" transform="rotate(120)" />
    </g>
  </svg>
</template>


================================================
FILE: docs/src/components/IconRemove.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" x="0px" y="0px">
    <path
      d="M27.19,7.64a2,2,0,1,0-2.83-2.83l-6.95,6.95a2,2,0,0,1-2.83,0L7.64,4.81A2,2,0,0,0,4.81,7.64l6.95,6.95a2,2,0,0,1,0,2.83L4.81,24.36a2,2,0,1,0,2.83,2.83l6.95-6.95a2,2,0,0,1,2.83,0l6.95,6.95a2,2,0,1,0,2.83-2.83l-6.95-6.95a2,2,0,0,1,0-2.83Z"
    ></path>
  </svg>
</template>


================================================
FILE: docs/src/components/IconSolid.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 166 155.3">
    <title>Solid Logo</title>
    <defs>
      <linearGradient
        id="a"
        gradientUnits="userSpaceOnUse"
        x1="27.5"
        y1="3"
        x2="152"
        y2="63.5"
      >
        <stop offset=".1" stop-color="#76b3e1" />
        <stop offset=".3" stop-color="#dcf2fd" />
        <stop offset="1" stop-color="#76b3e1" />
      </linearGradient>
      <linearGradient
        id="b"
        gradientUnits="userSpaceOnUse"
        x1="95.8"
        y1="32.6"
        x2="74"
        y2="105.2"
      >
        <stop offset="0" stop-color="#76b3e1" />
        <stop offset=".5" stop-color="#4377bb" />
        <stop offset="1" stop-color="#1f3b77" />
      </linearGradient>
      <linearGradient
        id="c"
        gradientUnits="userSpaceOnUse"
        x1="18.4"
        y1="64.2"
        x2="144.3"
        y2="149.8"
      >
        <stop offset="0" stop-color="#315aa9" />
        <stop offset=".5" stop-color="#518ac8" />
        <stop offset="1" stop-color="#315aa9" />
      </linearGradient>
      <linearGradient
        id="d"
        gradientUnits="userSpaceOnUse"
        x1="75.2"
        y1="74.5"
        x2="24.4"
        y2="260.8"
      >
        <stop offset="0" stop-color="#4377bb" />
        <stop offset=".5" stop-color="#1a336b" />
        <stop offset="1" stop-color="#1a336b" />
      </linearGradient>
    </defs>
    <path
      d="M163 35S110-4 69 5l-3 1c-6 2-11 5-14 9l-2 3-15 26 26 5c11 7 25 10 38 7l46 9 18-30z"
      fill="#76b3e1"
    />
    <path
      d="M163 35S110-4 69 5l-3 1c-6 2-11 5-14 9l-2 3-15 26 26 5c11 7 25 10 38 7l46 9 18-30z"
      opacity=".3"
      fill="url(#a)"
    />
    <path
      d="M52 35l-4 1c-17 5-22 21-13 35 10 13 31 20 48 15l62-21S92 26 52 35z"
      fill="#518ac8"
    />
    <path
      d="M52 35l-4 1c-17 5-22 21-13 35 10 13 31 20 48 15l62-21S92 26 52 35z"
      opacity=".3"
      fill="url(#b)"
    />
    <path
      d="M134 80a45 45 0 00-48-15L24 85 4 120l112 19 20-36c4-7 3-15-2-23z"
      fill="url(#c)"
    />
    <path
      d="M114 115a45 45 0 00-48-15L4 120s53 40 94 30l3-1c17-5 23-21 13-34z"
      fill="url(#d)"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconSun.vue
================================================
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="currentColor" d="M256 144C194.1 144 144 194.1 144 256c0 61.86 50.14 112 112 112s112-50.14 112-112C368 194.1 317.9 144 256 144zM256 320c-35.29 0-64-28.71-64-64c0-35.29 28.71-64 64-64s64 28.71 64 64C320 291.3 291.3 320 256 320zM256 112c13.25 0 24-10.75 24-24v-64C280 10.75 269.3 0 256 0S232 10.75 232 24v64C232 101.3 242.8 112 256 112zM256 400c-13.25 0-24 10.75-24 24v64C232 501.3 242.8 512 256 512s24-10.75 24-24v-64C280 410.8 269.3 400 256 400zM488 232h-64c-13.25 0-24 10.75-24 24s10.75 24 24 24h64C501.3 280 512 269.3 512 256S501.3 232 488 232zM112 256c0-13.25-10.75-24-24-24h-64C10.75 232 0 242.8 0 256s10.75 24 24 24h64C101.3 280 112 269.3 112 256zM391.8 357.8c-9.344-9.375-24.56-9.372-33.94 .0031s-9.375 24.56 0 33.93l45.25 45.28c4.672 4.688 10.83 7.031 16.97 7.031s12.28-2.344 16.97-7.031c9.375-9.375 9.375-24.56 0-33.94L391.8 357.8zM120.2 154.2c4.672 4.688 10.83 7.031 16.97 7.031S149.5 158.9 154.2 154.2c9.375-9.375 9.375-24.56 0-33.93L108.9 74.97c-9.344-9.375-24.56-9.375-33.94 0s-9.375 24.56 0 33.94L120.2 154.2zM374.8 161.2c6.141 0 12.3-2.344 16.97-7.031l45.25-45.28c9.375-9.375 9.375-24.56 0-33.94s-24.59-9.375-33.94 0l-45.25 45.28c-9.375 9.375-9.375 24.56 0 33.93C362.5 158.9 368.7 161.2 374.8 161.2zM120.2 357.8l-45.25 45.28c-9.375 9.375-9.375 24.56 0 33.94c4.688 4.688 10.83 7.031 16.97 7.031s12.3-2.344 16.97-7.031l45.25-45.28c9.375-9.375 9.375-24.56 0-33.93S129.6 348.4 120.2 357.8z"/></svg>
</template>


================================================
FILE: docs/src/components/IconSvelte.vue
================================================
<template>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 308">
    <title>Svelte Logo</title>
    <path
      fill="#FF3E00"
      d="M239.682 40.707C211.113-.182 154.69-12.301 113.895 13.69L42.247 59.356a82.198 82.198 0 0 0-37.135 55.056a86.566 86.566 0 0 0 8.536 55.576a82.425 82.425 0 0 0-12.296 30.719a87.596 87.596 0 0 0 14.964 66.244c28.574 40.893 84.997 53.007 125.787 27.016l71.648-45.664a82.182 82.182 0 0 0 37.135-55.057a86.601 86.601 0 0 0-8.53-55.577a82.409 82.409 0 0 0 12.29-30.718a87.573 87.573 0 0 0-14.963-66.244"
    />
    <path
      fill="#FFF"
      d="M106.889 270.841c-23.102 6.007-47.497-3.036-61.103-22.648a52.685 52.685 0 0 1-9.003-39.85a49.978 49.978 0 0 1 1.713-6.693l1.35-4.115l3.671 2.697a92.447 92.447 0 0 0 28.036 14.007l2.663.808l-.245 2.659a16.067 16.067 0 0 0 2.89 10.656a17.143 17.143 0 0 0 18.397 6.828a15.786 15.786 0 0 0 4.403-1.935l71.67-45.672a14.922 14.922 0 0 0 6.734-9.977a15.923 15.923 0 0 0-2.713-12.011a17.156 17.156 0 0 0-18.404-6.832a15.78 15.78 0 0 0-4.396 1.933l-27.35 17.434a52.298 52.298 0 0 1-14.553 6.391c-23.101 6.007-47.497-3.036-61.101-22.649a52.681 52.681 0 0 1-9.004-39.849a49.428 49.428 0 0 1 22.34-33.114l71.664-45.677a52.218 52.218 0 0 1 14.563-6.398c23.101-6.007 47.497 3.036 61.101 22.648a52.685 52.685 0 0 1 9.004 39.85a50.559 50.559 0 0 1-1.713 6.692l-1.35 4.116l-3.67-2.693a92.373 92.373 0 0 0-28.037-14.013l-2.664-.809l.246-2.658a16.099 16.099 0 0 0-2.89-10.656a17.143 17.143 0 0 0-18.398-6.828a15.786 15.786 0 0 0-4.402 1.935l-71.67 45.674a14.898 14.898 0 0 0-6.73 9.975a15.9 15.9 0 0 0 2.709 12.012a17.156 17.156 0 0 0 18.404 6.832a15.841 15.841 0 0 0 4.402-1.935l27.345-17.427a52.147 52.147 0 0 1 14.552-6.397c23.101-6.006 47.497 3.037 61.102 22.65a52.681 52.681 0 0 1 9.003 39.848a49.453 49.453 0 0 1-22.34 33.12l-71.664 45.673a52.218 52.218 0 0 1-14.563 6.398"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconTwitter.vue
================================================
<template>
  <svg id="Logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 248 204">
    <path
      id="Logo-2"
      data-name="Logo"
      d="M221.95,51.29c.15,2.17,.15,4.34,.15,6.53,0,66.73-50.8,143.69-143.69,143.69v-.04c-27.44,.04-54.31-7.82-77.41-22.64,3.99,.48,8,.72,12.02,.73,22.74,.02,44.83-7.61,62.72-21.66-21.61-.41-40.56-14.5-47.18-35.07,7.57,1.46,15.37,1.16,22.8-.87-23.56-4.76-40.51-25.46-40.51-49.5v-.64c7.02,3.91,14.88,6.08,22.92,6.32C11.58,63.31,4.74,33.79,18.14,10.71c25.64,31.55,63.47,50.73,104.08,52.76-4.07-17.54,1.49-35.92,14.61-48.25,20.34-19.12,52.33-18.14,71.45,2.19,11.31-2.23,22.15-6.38,32.07-12.26-3.77,11.69-11.66,21.62-22.2,27.93,10.01-1.18,19.79-3.86,29-7.95-6.78,10.14-15.31,18.99-25.19,26.14Z"
    />
  </svg>
</template>


================================================
FILE: docs/src/components/IconVue.vue
================================================
<template>
  <svg
    version="1.1"
    viewBox="0 0 261.76 226.69"
    xmlns="http://www.w3.org/2000/svg"
  >
    <g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)">
      <g transform="translate(178.06 235.01)">
        <path
          d="m0 0-22.669-39.264-22.669 39.264h-75.491l98.16-170.02 98.16 170.02z"
          fill="#41b883"
        />
      </g>
      <g transform="translate(178.06 235.01)">
        <path
          d="m0 0-22.669-39.264-22.669 39.264h-36.227l58.896-102.01 58.896 102.01z"
          fill="#34495e"
        />
      </g>
    </g>
  </svg>
</template>


================================================
FILE: docs/src/components/IconYarn.vue
================================================
<template>
  <svg
    width="256px"
    height="256px"
    viewBox="0 0 256 256"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    preserveAspectRatio="xMidYMid"
  >
    <g>
      <path
        d="M128,0 C57.3281853,0 0,57.3281853 0,128 C0,198.671815 57.3281853,256 128,256 C198.671815,256 256,198.671815 256,128 C256,57.3281853 198.671815,0 128,0"
        fill="#368FB9"
      ></path>
      <path
        d="M203.317375,174.060232 C195.410039,175.938224 191.40695,177.667954 181.621622,184.043243 C166.350579,193.927413 149.646332,198.523552 149.646332,198.523552 C149.646332,198.523552 148.262548,200.599228 144.259459,201.538224 C137.340541,203.218533 111.295753,204.651737 108.923552,204.701158 C102.548263,204.750579 98.6440154,203.07027 97.5567568,200.450965 C94.2455598,192.543629 102.301158,189.08417 102.301158,189.08417 C102.301158,189.08417 100.522008,187.996911 99.4841699,187.008494 C98.5451737,186.069498 97.5567568,184.191506 97.2602317,184.883398 C96.0247104,187.898069 95.3822394,195.261776 92.0710425,198.572973 C87.5243243,203.169112 78.9250965,201.637066 73.834749,198.96834 C68.2501931,196.003089 74.2301158,189.034749 74.2301158,189.034749 C74.2301158,189.034749 71.215444,190.8139 68.7938224,187.156757 C66.619305,183.796139 64.5930502,178.06332 65.1366795,170.996139 C65.7297297,162.940541 74.7243243,155.132046 74.7243243,155.132046 C74.7243243,155.132046 73.1428571,143.221622 78.3320463,131.014672 C83.027027,119.894981 95.6787645,110.949807 95.6787645,110.949807 C95.6787645,110.949807 85.0532819,99.1876448 89.0069498,88.611583 C91.576834,81.6926641 92.6146718,81.7420849 93.4548263,81.4455598 C96.4200772,80.3088803 99.2864865,79.0733591 101.411583,76.7505792 C112.037066,65.2849421 125.578378,67.4594595 125.578378,67.4594595 C125.578378,67.4594595 132.003089,47.9382239 137.933591,51.7436293 C139.762162,52.9297297 146.335135,67.5583012 146.335135,67.5583012 C146.335135,67.5583012 153.352896,63.4563707 154.143629,64.988417 C158.393822,73.2416988 158.888031,89.0069498 157.010039,98.5945946 C153.847104,114.409266 145.939768,122.909653 142.776834,128.247104 C142.035521,129.482625 151.27722,133.386873 157.10888,149.54749 C162.495753,164.324324 157.701931,176.728958 158.542085,178.112741 C158.690347,178.359846 158.739768,178.458687 158.739768,178.458687 C158.739768,178.458687 164.917375,178.952896 177.322008,171.292664 C183.944402,167.190734 191.802317,162.594595 200.74749,162.495753 C209.396139,162.34749 209.840927,172.478764 203.317375,174.060232 L203.317375,174.060232 Z M215.079537,166.795367 C214.189961,159.777606 208.259459,154.934363 200.648649,155.033205 C189.281853,155.181467 179.743629,161.062548 173.417761,164.966795 C170.946718,166.498842 168.821622,167.635521 166.99305,168.475676 C167.388417,162.742857 167.042471,155.230888 164.07722,146.977606 C160.469498,137.093436 155.626255,131.014672 152.166795,127.505792 C156.169884,121.674131 161.655598,113.173745 164.225483,100.027799 C166.449421,88.8092664 165.757529,71.3637066 160.667181,61.5783784 C159.629344,59.6015444 157.899614,58.1683398 155.725097,57.5752896 C154.835521,57.3281853 153.155212,56.8339768 149.844015,57.772973 C144.85251,47.4440154 143.12278,46.3567568 141.788417,45.4671815 C139.020849,43.6880309 135.759073,43.2926641 132.694981,44.4293436 C128.59305,45.9119691 125.08417,49.8656371 121.772973,56.8833977 C121.278764,57.9212355 120.833977,58.9096525 120.43861,59.8980695 C114.162162,60.3428571 104.277992,62.6162162 95.9258687,71.6602317 C94.8880309,72.7969112 92.8617761,73.6370656 90.7366795,74.4277992 L90.7861004,74.4277992 C86.4370656,75.9598456 84.4602317,79.5181467 82.03861,85.9428571 C78.6779923,94.9374517 82.1374517,103.783784 85.5474903,109.516602 C80.9019305,113.667954 74.7243243,120.290347 71.4625483,128.049421 C67.4100386,137.637066 66.965251,147.027027 67.1135135,152.117375 C63.6540541,155.774517 58.3166023,162.644015 57.7235521,170.353668 C56.9328185,181.127413 60.8370656,188.441699 62.5667954,191.110425 C63.0610039,191.901158 63.6046332,192.543629 64.1976834,193.1861 C64,194.520463 63.9505792,195.953668 64.2471042,197.436293 C64.8895753,200.895753 67.0640927,203.712741 70.3752896,205.491892 C76.8988417,208.951351 85.992278,210.433977 93.0100386,206.925097 C95.5305019,209.593822 100.126641,212.163707 108.478764,212.163707 L108.972973,212.163707 C111.098069,212.163707 138.081853,210.730502 145.939768,208.803089 C149.448649,207.962934 151.87027,206.480309 153.451737,205.145946 C158.492664,203.564479 172.429344,198.820077 185.57529,190.319691 C194.866409,184.290347 198.078764,183.005405 204.997683,181.325097 C211.718919,179.694208 215.919691,173.566023 215.079537,166.795367 L215.079537,166.795367 Z"
        fill="#FFFFFF"
      ></path>
    </g>
  </svg>
</template>


================================================
FILE: docs/src/components/KickstartPromo.vue
================================================
<template>
  <div class="kickstart-promo">
    <a
      href="https://kickstart.formkit.com/?utm_source=auto_animate_kickstart_promo&utm_medium=web"
      target="_blank"
      class="kickstart-promo__cta"
    />

    <span class="announcement-icon">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
        <path
          fill="currentColor"
          d="M544 32c17.7 0 32 14.3 32 32V448c0 17.7-14.3 32-32 32s-32-14.3-32-32V64c0-17.7 14.3-32 32-32zM64 190.3L480 64V448L348.9 408.2C338.2 449.5 300.7 480 256 480c-53 0-96-43-96-96c0-11 1.9-21.7 5.3-31.5L64 321.7C63.1 338.6 49.1 352 32 352c-17.7 0-32-14.3-32-32V192c0-17.7 14.3-32 32-32c17.1 0 31.1 13.4 32 30.3zm239 203.9l-91.6-27.8c-2.1 5.4-3.3 11.4-3.3 17.6c0 26.5 21.5 48 48 48c23 0 42.2-16.2 46.9-37.8z"
        />
      </svg>
    </span>

    <div class="kickstart-promo__image" aria-label="Kickstart">
      <svg
        id="b"
        data-name="Layer 2"
        xmlns="http://www.w3.org/2000/svg"
        width="562.4"
        height="100.3"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        viewBox="0 0 562.4 100.3"
      >
        <defs>
          <linearGradient
            id="d"
            x1="3.1"
            y1="-330.7"
            x2="67.8"
            y2="-430.7"
            gradientTransform="translate(0 -319.9) scale(1 -1)"
            gradientUnits="userSpaceOnUse"
          >
            <stop offset="0" stop-color="#f79259" />
            <stop offset="1" stop-color="#f8ce68" />
          </linearGradient>
        </defs>
        <g id="c" data-name="Layer 2">
          <path
            class="e"
            d="m16.7,0H0v16.7h16.7V0Zm0,66.7H0v16.7h16.7v-16.7Zm33.4,16.7h50v16.7h-50v-16.7ZM33.4,16.7h-16.7v16.7h16.7v16.7h16.7v-16.7h-16.7v-16.7Zm-16.7,33.3h16.7v16.7h-16.7v-16.7Z"
          />
          <g>
            <path
              class="f"
              d="m131.3,100h-11.2v-17.6h11.2v2.4h-8.4v5.2h8v2.3h-8v5.5h8.4v2.4Z"
            />
            <path
              class="f"
              d="m149.8,95.3h-6.7l-1.6,4.8h-2.8l6.4-17.6h3l6.4,17.6h-2.9l-1.6-4.8Zm-6-2.2h5.3l-2.6-7.7h0l-2.6,7.7Z"
            />
            <path
              class="f"
              d="m164.9,100h-2.7v-17.6h6.9c3.6,0,5.9,2.1,5.9,5.4s-1.3,4.3-3.4,5l4,7.2h-3.2l-3.6-6.8h-3.9v6.8Zm0-9h3.9c2.1,0,3.3-1.2,3.3-3.2s-1.3-3.2-3.4-3.2h-3.9v6.3Z"
            />
            <path class="f" d="m194.4,100h-10.9v-17.6h2.7v15.2h8.2v2.4Z" />
            <path
              class="f"
              d="m205,100v-7.2l-6.2-10.4h3.1l4.5,7.8h0l4.5-7.8h3l-6.2,10.4v7.2h-2.7Z"
            />
            <path
              class="f"
              d="m243.2,95.3h-6.7l-1.6,4.8h-2.8l6.4-17.6h3l6.4,17.6h-2.9l-1.6-4.8Zm-6-2.2h5.3l-2.6-7.7h0l-2.6,7.7Z"
            />
            <path
              class="f"
              d="m254.3,91.2c0-5.6,3.2-9.1,8.1-9.1s7,2.5,7.5,6.1h-2.7c-.5-2.3-2.4-3.7-4.8-3.7s-5.3,2.6-5.3,6.7,2.1,6.7,5.3,6.7,4.2-1.3,4.7-3.4h2.7c-.7,3.6-3.4,5.8-7.5,5.8s-8.1-3.5-8.1-9.1Z"
            />
            <path
              class="f"
              d="m277.5,91.2c0-5.6,3.2-9.1,8.1-9.1s7,2.5,7.5,6.1h-2.7c-.5-2.3-2.4-3.7-4.8-3.7s-5.3,2.6-5.3,6.7,2.1,6.7,5.3,6.7,4.2-1.3,4.7-3.4h2.7c-.7,3.6-3.4,5.8-7.5,5.8s-8.1-3.5-8.1-9.1Z"
            />
            <path
              class="f"
              d="m312.6,100h-11.2v-17.6h11.2v2.4h-8.4v5.2h8v2.3h-8v5.5h8.4v2.4Z"
            />
            <path
              class="f"
              d="m323.2,95.1c.2,1.7,1.9,2.9,4.2,2.9s3.8-1.1,3.8-2.7-1-2.2-3.2-2.7l-2.3-.5c-3.2-.8-4.7-2.3-4.7-4.7s2.6-5.1,6.4-5.1,6.3,2.1,6.4,5.1h-2.7c-.2-1.8-1.6-2.8-3.7-2.8s-3.6,1.1-3.6,2.6.9,2,3.2,2.5l1.9.5c3.6.9,5.1,2.3,5.1,4.9s-2.6,5.4-6.8,5.4-6.5-2-6.7-5.2h2.7Z"
            />
            <path
              class="f"
              d="m344.3,95.1c.2,1.7,1.9,2.9,4.2,2.9s3.8-1.1,3.8-2.7-1-2.2-3.2-2.7l-2.3-.5c-3.2-.8-4.7-2.3-4.7-4.7s2.6-5.1,6.4-5.1,6.3,2.1,6.4,5.1h-2.7c-.2-1.8-1.6-2.8-3.7-2.8s-3.6,1.1-3.6,2.6.9,2,3.2,2.5l1.9.5c3.6.9,5.1,2.3,5.1,4.9s-2.6,5.4-6.8,5.4-6.5-2-6.7-5.2h2.7Z"
            />
          </g>
          <g>
            <path
              class="g"
              d="m120.1,75.9V5.5h17.9v31h.4l24-31h19.2l-24.6,31.3,26,39.2h-21l-18-27.5-6,7.6v19.9h-17.9Z"
            />
            <path
              class="g"
              d="m187.4,8.5c0-4.9,4-8.5,8.9-8.5s8.9,3.7,8.9,8.5-4,8.5-8.9,8.5-8.9-3.6-8.9-8.5Zm.2,13h17.3v54.3h-17.3V21.6Z"
            />
            <path
              class="g"
              d="m249.1,42.9c-.6-5.6-4.1-9.3-9.4-9.3s-10.2,5.6-10.2,15.1,3.8,15.1,10.2,15.1,8.7-3.2,9.4-8.9h15.9c-.5,13.7-10.3,22.1-25.5,22.1s-27.5-10.7-27.5-28.4,10.5-28.3,27.4-28.3,25,9,25.5,22.5h-15.9Z"
            />
            <path
              class="g"
              d="m305.5,21.6h19.3l-19.5,23.3,20.7,31.1h-19.9l-13.5-20.7-3.3,3.9v16.8h-17.3V2h17.3v40.4h.3l16-20.8Z"
            />
            <path
              class="g"
              d="m344.7,55.5c.6,4.8,6.1,8.1,12.7,8.1s11.5-3.1,11.5-7.4-3-5.8-11-7.5l-9.2-1.8c-13-2.5-19.7-9.5-19.7-20.2s11.7-22.5,28-22.5,28,8.5,28.2,21.8h-16.5c-.3-5.1-5.1-8.2-11.5-8.2s-10.4,2.8-10.4,7.1,3.1,5.9,10.5,7.4l9.1,1.7c13.9,2.7,20.2,9,20.2,20.1s-11.6,22.9-29.7,22.9-29.1-8-29.2-21.6h17Z"
            />
            <path
              class="g"
              d="m415.7,9.6v12h9.8v12.8h-9.8v23.2c0,3.8,2.1,5.7,6.3,5.7s2.5,0,3.5-.2v12.3c-1.7.4-4.2.7-7.6.7-14,0-19.5-4.3-19.5-15v-26.7h-7.3v-12.8h7.3v-12h17.3Z"
            />
            <path
              class="g"
              d="m430.9,60.2c0-10.2,7.8-15.8,22-16.7l12.7-.8v-3.1c0-4.4-3.2-6.8-8.1-6.8s-7.9,2.5-8.3,5.9h-15.6c.4-11,10.1-18.3,24.8-18.3s24.1,7.4,24.1,18.3v37.2h-16.8v-7.8h-.3c-2.9,5.5-9.6,8.5-16.2,8.5-10.2,0-18.4-6.7-18.4-16.5Zm34.8-3.9v-3.8l-10,.7c-4.9.3-7.6,2.4-7.6,5.8s2.9,5.6,7.3,5.6,10.3-3.3,10.3-8.3Z"
            />
            <path
              class="g"
              d="m491.2,21.6h16.8v10.2h.3c2-7.2,6.4-10.9,12.8-10.9s3.3.3,4.4.7v14.8c-1.5-.6-3.5-1-5.6-1-7.4,0-11.5,4.2-11.5,11.8v28.7h-17.3V21.6Z"
            />
            <path
              class="g"
              d="m552.6,9.6v12h9.8v12.8h-9.8v23.2c0,3.8,2.1,5.7,6.3,5.7s2.5,0,3.5-.2v12.3c-1.7.4-4.2.7-7.6.7-14,0-19.5-4.3-19.5-15v-26.7h-7.3v-12.8h7.3v-12h17.3Z"
            />
          </g>
        </g>
      </svg>
    </div>
    <div class="kickstart-promo__content">
      <h2 class="kickstart-promo__title">
        AI-generated forms in seconds
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
          <path
            fill="currentColor"
            d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32h82.7L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3V192c0 17.7 14.3 32 32 32s32-14.3 32-32V32c0-17.7-14.3-32-32-32H320zM80 32C35.8 32 0 67.8 0 112V432c0 44.2 35.8 80 80 80H400c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32V432c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16H192c17.7 0 32-14.3 32-32s-14.3-32-32-32H80z"
          />
        </svg>
      </h2>
      <p class="kickstart-promo__description">
        KickStart your next FormKit form in seconds. Generate from a prompt,
        image, or text attachment. Copy & paste as Vue components or FormKit
        schema.
      </p>
    </div>
  </div>
</template>

<style scoped>
.kickstart-promo {
  background: #1f478d;
  border: 1px solid #b1e2fd;
  padding: 1rem;
  border-radius: 0.5rem;
  display: flex;
  flex-direction: column;
  position: relative;
  max-width: 900px;
  margin: 0 auto;
  margin-bottom: 2em;
  box-shadow: none;
  transition: all 0.2s ease;
  overflow: hidden;
  cursor: pointer;
}
.kickstart-promo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  filter: brightness(80%) contrast(100%);
  mix-blend-mode: overlay;
  background-size: cover;
  background-image: radial-gradient(
      circle at 50% 40%,
      rgba(0, 0, 0, 0),
      rgba(0, 0, 0, 0.25)
    ),
    url("data:image/svg+xml,%3Csvg viewBox='0 0 10000 10000' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
}
.kickstart-promo:hover {
  transform: translateY(-0.25rem);
  box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px,
    rgba(0, 0, 0, 0.3) 0px 30px 60px -30px;
  filter: brightness(120%);
}
[data-dark-mode="true"] .kickstart-promo {
  background: #5d0667;
  border: 1px solid #650a75;
}
@media (min-width: 768px) {
  .kickstart-promo {
    flex-direction: row;
  }
}
@media (min-width: 960px) {
  .kickstart-promo {
    margin-bottom: -2em;
  }
}

.announcement-icon {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  padding: 0.5rem;
  background: #fff;
  color: #1f2a8d;
  border-radius: 50%;
  font-size: 2rem;
  width: 1rem;
  height: 1rem;
}
.announcement-icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

.kickstart-promo__cta {
  display: block;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 5;
}

.kickstart-promo__image {
  width: 100%;
  max-width: 10rem;
  aspect-ratio: 523/191;
  mix-blend-mode: screen;
  position: relative;
  z-index: 1;
}
.kickstart-promo__image svg {
  width: 100%;
  height: 100%;
  filter: invert(1);
}

.kickstart-promo__content {
  color: white;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  position: relative;
  z-index: 2;
}
@media (min-width: 768px) {
  .kickstart-promo__content {
    justify-content: flex-start;
    align-items: flex-start;
    padding-left: 2rem;
  }
}

.kickstart-promo__title {
  margin-top: 0.25rem;
  margin-bottom: 0.1rem;
  padding-top: 0;
  font-size: 1.25rem;
  color: #fff;
  letter-spacing: -0.05rem;
}
@media (min-width: 768px) {
  .kickstart-promo {
    font-size: 1.33rem;
  }
}

.kickstart-promo__title svg {
  width: 0.75em;
  height: 0.75em;
  margin-left: 0.25em;
}

.kickstart-promo__description {
  opacity: 0.66;
  font-size: 0.85rem;
}
.kickstart-promo__content p:last-child {
  margin-bottom: 0;
}
</style>


================================================
FILE: docs/src/components/Navigation.vue
================================================
<script setup lang="ts">
import { ref } from "vue"
import IconDown from "./IconDown.vue"
import PoliteAd from "./PoliteAd.vue"
import { vAutoAnimate } from "../../../src/index"

const show = ref(false)
const activeTitle = ref("Docs Navigation")

function applySizing() {
  if (window.innerWidth >= 672) {
    show.value = true
  } else {
    show.value = false
  }
}

const handleClick = () => {
  show.value = window.innerWidth >= 672
}

let resizeTimer
if (typeof window !== "undefined") {
  show.value = window.innerWidth >= 672
  clearTimeout(resizeTimer)
  window.addEventListener("resize", () => {
    resizeTimer = setTimeout(applySizing, 200)
  })
}
</script>

<template>
  <nav v-auto-animate>
    <div class="active" @click="show = !show">
      <span class="active-title">{{ activeTitle }}</span>
      <IconDown class="down" />
    </div>
    <ul v-if="show" @click="handleClick">
      <li><a href="#installation">Installation</a></li>
      <li><a href="#usage">Usage</a></li>
      <li><a href="#usage-react">React</a></li>
      <li><a href="#usage-vue">Vue</a></li>
      <li><a href="#usage-preact">Preact</a></li>
      <li><a href="#usage-solid">Solid</a></li>
      <li><a href="#usage-svelte">Svelte</a></li>
      <li><a href="#usage-angular">Angular</a></li>
      <!-- <li><a href="#usage-qwik">Qwik</a></li> -->
      <li><a href="#usage-disable">Disable</a></li>
      <li><a href="#examples">Examples</a></li>
      <li><a href="#plugins">Plugins</a></li>
      <li><a href="#why-not">Why not...?</a></li>
    </ul>
  </nav>
</template>

<style scoped>
nav {
  background-color: white;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.025), 0 2px 4px rgba(0, 0, 0, 0.025),
    0 4px 8px rgba(0, 0, 0, 0.025), 0 8px 16px rgba(0, 0, 0, 0.025),
    0 16px 32px rgba(0, 0, 0, 0.025), 0 32px 64px rgba(0, 0, 0, 0.025);
  border-radius: 0 0 0.25em 0.25em;
  padding: 0 2em;
  position: sticky;
  top: 0;
  left: 100%;
  opacity: 0.98;
  float: left;
  width: calc(100% + 2em);
  margin-left: calc(-200vw);
  margin-right: -3em;
  z-index: 100;
  user-select: none;
}
[data-dark-mode="true"] nav {
  background-color: var(--purple-d);
}

@media (min-width: 42em) {
  nav {
    top: 2em;
    width: 10em;
    margin-left: -12em;
    margin-right: 0;
    box-sizing: border-box;
    margin-top: 0;
    left: 0;
    padding: 0 1em;
    border-radius: 0.75em;
  }
  .active {
    display: none;
  }
  nav ul {
    border-top: none;
  }
  nav a {
    padding-left: 0;
    padding-right: 0;
  }
}

@media (min-width: 50em) {
  nav {
    width: 14em;
    margin-left: -18em;
    padding: 0.5em 2em;
  }
}

ul {
  list-style-type: none;
  padding: 0.5em 0;
  margin: 0;
  position: relative;
  z-index: 2;
  border-top: 1px solid var(--ui-light);
}
[data-dark-mode="true"] ul {
  border-top: none;
}

a,
.active-title {
  display: block;
  padding: 0.5em 1em;
  color: var(--primary);
}
[data-dark-mode="true"] li a,
[data-dark-mode="true"] .active-title {
  color: var(--text);
}

li:last-child {
  padding-bottom: 0.5em;
}

.active-title {
  padding: 0 1em;
}
.active {
  padding-top: 0.75em;
  padding-bottom: 0.75em;
  cursor: pointer;
  position: relative;
  padding-right: 2em;
}

.down {
  fill: var(--primary);
  width: 1em;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  right: 1em;
}
[data-dark-mode="true"] .down {
  fill: var(--text);
}
</style>


================================================
FILE: docs/src/components/PoliteAd.vue
================================================
<script setup>

</script>

<template>
  <section class="polite-area">
    <div class="polite-header">
      <h5>Sponsored Ad</h5>
      <a class="polite-sponsored" href="https://formkit.com/ads">Want this Spot? Current bid: $4/day →</a>
    </div>
    <a href="https://formvalidation.io/">
      <picture>
        <source
          srcset="https://cdn.formk.it/polite/FormValidation-1500x250.png"
          media="(min-width: 750px)"
        >
        <source
          srcset="https://cdn.formk.it/polite/FormValidation-750x250.png"
          media="(max-width: 749px)"
        >
        <img class="polite-spot" src="https://cdn.formk.it/polite/FormValidation-1500x250.png" alt="FormValidation.io poster" />
      </picture>
    </a>
    <a v-if="false" href="mailto:ads@formkit.com">
      <div class="your-logo-here">
        Your image here!<br>
        <small>
          Promote your product to a JavaScript audience — over 30,000 visitors in the last 30 days.<br>
          Click through to contact for details.<br>
          Current bid: $3/day
        </small>
      </div>
    </a>
  </section>
</template>

<style scoped>
h5 {
  margin-bottom: 0.25em;
  margin-top: 0;
}

.polite-area {
  margin-bottom: 2em;
}

.polite-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.polite-sponsored {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .025em;
  filter: grayscale(1);
  transition: filter 0.15s ease-out;
}

.polite-sponsored:hover {
  text-decoration: none;
  color: var(--primary);
  filter: grayscale(0);
}
.polite-spot {
  max-width: 100%;
  border-radius: 1em;
}
.your-logo-here {
  border: dashed 2px var(--gray-l);
  border-radius: 1em;
  padding: 3em;
  text-align: center;
  margin-bottom: 2em;
  aspect-ratio: 5/1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
small {
  color: var(--text);
  opacity: 0.66;
}

[data-dark-mode="true"] .your-logo-here {
  border-color: var(--gray-m);
}

@media (min-width: 42em) {
  .polite-area {
    margin-left: -12em;
    margin-bottom: 6em;
  }
  .your-logo-here {
    aspect-ratio: 12/1;
    margin-bottom: 6em;
  }
}
@media (min-width: 50em) {
  .polite-area {
    margin-left: -18em;
  }
}
</style>


================================================
FILE: docs/src/components/ReducedMotionWarning.vue
================================================
<template>
  <div class="motion-notice">
    <p>
      <strong>Notice</strong>: Your current device has its "reduce motion" accessibility option enabled.
      Out of respect for this setting AutoAnimate animations will not play.
      Please disable your device's "reduce motion" setting if you wish to see AutoAnimate in action.
    </p>
  </div>
</template>

<style lang="css">
.motion-notice {
  padding-top: 3em;
}
.motion-notice p {
  display: block;
  padding: 2em;
  color: var(--ui-red);
  border: 1px solid var(--ui-red);
  border-radius: 0.5em;
}
@media (min-width: 42em) {
  .motion-notice {
    padding-top: 0;
  }
}
</style>


================================================
FILE: docs/src/components/TempoPromo.vue
================================================
<template>
  <div class="tempo-promo">
    <a
      href="https://tempo.formkit.com/?utm_source=auto_animate_tempo_promo&utm_medium=web"
      target="_blank"
      class="tempo-promo__cta"
    />

    <span class="announcement-icon">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
        <path
          fill="currentColor"
          d="M544 32c17.7 0 32 14.3 32 32V448c0 17.7-14.3 32-32 32s-32-14.3-32-32V64c0-17.7 14.3-32 32-32zM64 190.3L480 64V448L348.9 408.2C338.2 449.5 300.7 480 256 480c-53 0-96-43-96-96c0-11 1.9-21.7 5.3-31.5L64 321.7C63.1 338.6 49.1 352 32 352c-17.7 0-32-14.3-32-32V192c0-17.7 14.3-32 32-32c17.1 0 31.1 13.4 32 30.3zm239 203.9l-91.6-27.8c-2.1 5.4-3.3 11.4-3.3 17.6c0 26.5 21.5 48 48 48c23 0 42.2-16.2 46.9-37.8z"
        />
      </svg>
    </span>

    <div class="tempo-promo__image" aria-label="Tempo"></div>
    <div class="tempo-promo__content">
      <h2 class="tempo-promo__title">
        The easiest way to work with dates in JavaScript
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
          <path
            fill="currentColor"
            d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32h82.7L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3V192c0 17.7 14.3 32 32 32s32-14.3 32-32V32c0-17.7-14.3-32-32-32H320zM80 32C35.8 32 0 67.8 0 112V432c0 44.2 35.8 80 80 80H400c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32V432c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16H192c17.7 0 32-14.3 32-32s-14.3-32-32-32H80z"
          />
        </svg>
      </h2>
      <p class="tempo-promo__description">
        Tempo is a new open-source library by FormKit that makes working with
        dates — including complex operations across timezones — a breeze. It’s
        lightweight, fast, and easy to use.
      </p>
    </div>
  </div>
</template>

<style scoped>
.tempo-promo {
  background: #5c1f8d;
  border: 1px solid #b376e6;
  padding: 1rem;
  border-radius: 0.5rem;
  display: flex;
  flex-direction: column;
  position: relative;
  max-width: 900px;
  margin: 0 auto;
  margin-bottom: 2em;
  box-shadow: none;
  transition: all 0.2s ease;
  overflow: hidden;
  cursor: pointer;
}
.tempo-promo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  filter: brightness(80%) contrast(100%);
  mix-blend-mode: overlay;
  background-size: cover;
  background-image: radial-gradient(
      circle at 50% 40%,
      rgba(0, 0, 0, 0),
      rgba(0, 0, 0, 0.25)
    ),
    url("data:image/svg+xml,%3Csvg viewBox='0 0 10000 10000' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
}
.tempo-promo:hover {
  transform: translateY(-0.25rem);
  box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px,
    rgba(0, 0, 0, 0.3) 0px 30px 60px -30px;
  filter: brightness(120%);
}
[data-dark-mode="true"] .tempo-promo {
  background: #38085f;
  border: 1px solid #450a75;
}
@media (min-width: 768px) {
  .tempo-promo {
    flex-direction: row;
  }
}
@media (min-width: 960px) {
  .tempo-promo {
    margin-bottom: -2em;
  }
}

.announcement-icon {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  padding: 0.5rem;
  background: #fff;
  color: #5c1f8d;
  border-radius: 50%;
  font-size: 2rem;
  width: 1rem;
  height: 1rem;
}
.announcement-icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

.tempo-promo__cta {
  display: block;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 5;
}

.tempo-promo__image {
  width: 100%;
  max-width: 10rem;
  aspect-ratio: 523/191;
  mix-blend-mode: lighten;
  position: relative;
  z-index: 1;
  background: url("/img/tempo.png") no-repeat center center;
  background-size: contain;
}

.tempo-promo__content {
  color: white;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  position: relative;
  z-index: 2;
}
@media (min-width: 768px) {
  .tempo-promo__content {
    justify-content: flex-start;
    align-items: flex-start;
    padding-left: 2rem;
  }
}

.tempo-promo__title {
  margin-top: 0.25rem;
  margin-bottom: 0.1rem;
  padding-top: 0;
  font-size: 1.25rem;
  color: #fff;
  letter-spacing: -0.05rem;
}
@media (min-width: 768px) {
  .tempo-promo {
    font-size: 1.33rem;
  }
}

.tempo-promo__title svg {
  width: 0.75em;
  height: 0.75em;
  margin-left: 0.25em;
}

.tempo-promo__description {
  opacity: 0.66;
  font-size: 0.85rem;
}
.tempo-promo__content p:last-child {
  margin-bottom: 0;
}
</style>


================================================
FILE: docs/src/components/TheFooter.vue
================================================
<script setup>
const year = new Date().getFullYear()
</script>

<template>
  <footer>
    <p class="copyright">
      Released under the <a href="https://opensource.org/licenses/MIT">MIT License</a>.<br>
      Copyright &copy; {{ year }} FormKit, Inc.
    </p>
  </footer>
</template>

<style scoped>
footer {
  display: flex;
  justify-content: center;
  width: 100%;
  margin-top: 6em;
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}
[data-dark-mode="true"] footer {
  border-top-color: rgba(255, 255, 255, 0.15);
}
.copyright {
  display: inline-block;
  font-size: 0.8rem;
  margin: 0 auto;
  padding: 3em 2em;
  text-align: center;
}
</style>


================================================
FILE: docs/src/components/TheHeader.vue
================================================
<script setup lang="ts">
import TheLogo from "./TheLogo.vue"
import IconDiscord from "./IconDiscord.vue"
import IconTwitter from "./IconTwitter.vue"
import ColorModeToggle from "./ColorModeToggle.vue"
import GithubButton from "vue-github-button"
</script>

<template>
  <header>
    <TheLogo class="logo" />
    <div class="buttons">
      <a href="https://discord.gg/SHYT8pyeNm" aria-label="Discord"
        ><IconDiscord class="icon"
      /></a>
      <a href="https://twitter.com/FormKit" aria-label="Twitter"
        ><IconTwitter class="icon"
      /></a>
      <GithubButton
        href="https://github.com/formkit/auto-animate"
        data-size="large"
        data-show-count="true"
        data-icon="star"
        aria-label="Star formkit/auto-animate on GitHub"
        >Star</GithubButton
      >
      <GithubButton
        href="https://github.com/sponsors/formkit"
        data-size="large"
        data-icon="heart"
        aria-label="Sponsor FormKit on GitHub"
        >Sponsor</GithubButton
      >
      <ColorModeToggle />
    </div>
  </header>
</template>

<style scoped>
header {
  height: 4em;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  padding-top: 2em;
  margin-bottom: 6em;
  justify-content: space-between;
  user-select: none;
}
.logo {
  width: 90%;
  max-width: 15em;
  margin-right: 1em;
  margin-bottom: 1em;
}

.buttons {
  display: flex;
  align-items: center;
}

.buttons a:hover {
  text-decoration: none;
}

.icon {
  width: 1.25em;
  fill: var(--gray-m);
  margin-right: 1em;
}
[data-dark-mode="true"] .icon {
  fill: var(--gray-l);
}

.buttons span {
  margin-right: 1em;
}
.buttons span:last-child {
  margin-right: 0;
}

.buttons a:hover .icon {
  fill: var(--primary);
}

@media (min-width: 700px) {
  header {
    padding-top: 1em;
    margin-bottom: 3em;
  }
  .logo {
    max-width: 12em;
    margin-bottom: 0;
  }
}
</style>


================================================
FILE: docs/src/components/TheLogo.vue
================================================
<script setup lang="ts">
import { onMounted, ref } from "vue"
import { vAutoAnimate } from "../../../src"

const sequence = ref(0)

const duration = 50

onMounted(() => {
  const interval = setInterval(() => {
    sequence.value++
    if (sequence.value > 11) {
      clearInterval(interval)
    }
  }, duration)
})
</script>

<template>
  <svg
    id="logo"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    viewBox="0 0 2493.5 306.9"
  >
    <defs>
      <linearGradient
        id="linear-gradient"
        x1="0"
        y1="145.3"
        x2="300"
        y2="145.3"
        gradientTransform="translate(0 302.2) scale(1 -1)"
        gradientUnits="userSpaceOnUse"
      >
        <stop offset="0" stop-color="#4711de" />
        <stop offset=".29" stop-color="#4811da" />
        <stop offset=".6" stop-color="#4a11cd" />
        <stop offset=".92" stop-color="#4e11b8" />
        <stop offset="1" stop-color="#4f11b1" />
      </linearGradient>
    </defs>
    <g id="letters" class="cls-3">
      <path
        v-if="sequence > 0"
        class="cls-2"
        d="M426.6,13.1h45.3l89.9,242.9h-39.4l-19-52.7h-108.9l-19,52.7h-38.4L426.6,13.1Zm65,156.5l-41.5-114.5h-2.4l-41.5,114.5h85.4Z"
      />
      <path
        v-if="sequence > 1"
        class="cls-2"
        d="M583.6,191.2V74.6h36.3v110c0,25.7,17.6,42.3,40.4,42.3,25.2,0,43.9-19.4,43.9-45.8V74.6h36.3v181.5h-35.3v-24.3h-2.4c-7.3,14.9-25.9,28.8-52.9,28.8-41.1,0-66.3-30.2-66.3-69.4Z"
      />
      <path
        v-if="sequence > 2"
        class="cls-2"
        d="M803.4,198.4V104.4h-32.5v-29.5h23.9c6.2,0,10.7-4.5,10.7-11.8V23.2h34.2v51.4h52.5v29.8h-52.5v93c0,17.3,7.3,27.8,26.3,27.8h24.5v30.9h-30.1c-35.5-.1-57-19.8-57-57.7Z"
      />
      <path
        v-if="sequence > 3"
        class="cls-2"
        d="M914.8,165.5c0-54.5,40.1-95.4,95.8-95.4s95.1,41.3,95.1,95.4-40.1,95.1-95.4,95.1-95.5-40.6-95.5-95.1Zm153.8,0c0-36.1-24.2-62.1-58.4-62.1s-58.4,26.4-58.4,62.1,24.5,62.1,58.4,62.1,58.4-26.4,58.4-62.1Z"
      />
      <path
        v-if="sequence > 4"
        class="cls-2"
        d="M1215,13.1h45.3l89.9,242.9h-39.4l-19-52.7h-108.9l-19,52.7h-38.4L1215,13.1Zm65,156.5l-41.4-114.5h-2.4l-41.5,114.5h85.3Z"
      />
      <path
        v-if="sequence > 5"
        class="cls-2"
        d="M1376.5,74.6h35.3v24.3h2.4c7.3-14.9,25.9-28.8,52.9-28.8,41.1,0,66.4,30.2,66.4,69.4v116.6h-36.3v-109.7c0-25.3-17.6-42.3-40.4-42.3-25.2,0-43.9,19.8-43.9,46.2v105.8h-36.3l-.1-181.5h0Z"
      />
      <path
        v-if="sequence > 6"
        class="cls-2"
        d="M1572.2,22.9c0-13.2,10-22.9,23.9-22.9s24.2,9.7,24.2,22.9c0,13.9-10,23.2-24.2,23.2s-23.9-9.4-23.9-23.2Zm5.5,51.7h36.3v181.5h-36.3V74.6Z"
      />
      <path
        v-if="sequence > 7"
        class="cls-2"
        d="M1658.2,74.6h35.3v23.9h2.4c8-15.3,24.9-28.5,50.8-28.5s44.9,12.1,55.3,30.5h2.4c12.1-21.5,31.1-30.5,55.7-30.5,39.8,0,66,27.8,66,67v119h-36.3v-106.5c0-29.5-14.2-45.5-38-45.5s-41.1,17-41.1,46.2v105.8h-36.3v-110.6c0-25.3-16.2-41.3-39.1-41.3s-40.8,18.4-40.8,45.1v106.9h-36.3V74.6Z"
      />
      <path
        v-if="sequence > 8"
        class="cls-2"
        d="M1957.6,165.8c0-56.2,35.6-95.8,86.1-95.8,34.6,0,53.2,21.5,59.1,30.9h2.4v-26.4h36.3V256h-35.5v-25.7h-2.1c-4.8,6.9-22.5,30.2-58.4,30.2-51.9,.1-87.9-38.5-87.9-94.7Zm148.7-.3c0-39.2-24.2-62.1-56-62.1s-55.7,25.7-55.7,62.1,22.8,62.1,56,62.1,55.7-27.8,55.7-62.1Z"
      />
      <path
        v-if="sequence > 9"
        class="cls-2"
        d="M2203.4,198.4V104.4h-32.5v-29.5h23.9c6.2,0,10.7-4.5,10.7-11.8V23.2h34.2v51.4h52.5v29.8h-52.5v93c0,17.3,7.3,27.8,26.3,27.8h24.5v30.9h-30.1c-35.5-.1-57-19.8-57-57.7Z"
      />
      <path
        v-if="sequence > 10"
        class="cls-2"
        d="M2314.8,165.8c0-57.6,38.7-95.8,90.2-95.8,56.4,0,88.5,41.6,88.5,93.3v13.5h-142.4c1.4,31.6,22.5,53.1,55.7,53.1,22.8,0,42.5-11.1,49.8-28.8h35.3c-9.3,35-41.5,59.3-86.1,59.3-54.4,.2-91-40.1-91-94.6Zm142.7-17c-2.4-30.5-24.5-48.2-52.5-48.2s-50.5,19.8-53.2,48.2h105.7Z"
      />
    </g>
    <path
      id="mark"
      class="cls-1"
      d="M300,256.9v50H150v-50h150ZM50,206.9v50H0v-50H50Zm50-50v50H50v-50h50Zm50-50v50h-50v-50h50Zm-50-50v50H50V56.9h50ZM50,6.9V56.9H0V6.9H50Z"
    />
  </svg>
</template>

<style scoped>
.cls-1 {
  fill: url(#linear-gradient);
  fill-rule: evenodd;
}

.cls-2 {
  fill: #111;
}
[data-dark-mode="true"] .cls-2 {
  fill: #eee;
}

.cls-3 {
  isolation: isolate;
}
</style>


================================================
FILE: docs/src/examples/accordion/ActualAccordion.vue
================================================
<script setup lang="ts">
import { ref } from "vue"
import { vAutoAnimate } from "../../../../src"

const faq = ref([
  {
    id: "why",
    question: "Why did you create it?",
    answer: `We needed a way to animate DOM elements without adding to the
    virtual DOM in Vue and React. And it turned out our solution was gonna work
    great for lots of other use cases as well.`,
  },
  {
    id: "license",
    question: "Is it open source?",
    answer: `It sure is! AutoAnimate is MIT licensed, which basically means you
    are free to take it and do whatever you want with it. If you find it useful
    consider <a href="https://github.com/sponsors/formkit">supporting our open source efforts</a>.`,
  },
  {
    id: "who",
    question: "Who made this?",
    answer: `AutoAnimate is a team effort 💪 . Most of the code was written by
      <a href='https://twitter.com/jpschroeder'>Justin Schroeder</a>,
      <a href='https://twitter.com/0xBOYD'>Andrew Boyd</a> played a key
      role on the docs, and the rest of the <a href='https://formkit.com'>FormKit</a>
      team held down the fort.`,
  },
])

const current = ref(faq.value[0].id)
</script>

<template>
  <div class="example accordion-example">
    <ul class="accordion">
      <li class="accordion-item" v-for="q in faq" :key="q.id" v-auto-animate>
        <div
          class="question"
          @click="current = current === q.id ? false : q.id"
        >
          {{ q.question }}
        </div>
        <p class="answer" v-if="q.id === current" v-html="q.answer" />
      </li>
    </ul>
  </div>
</template>

<style scoped>
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

li {
  display: block;
  background-color: var(--ui-light);
  border-radius: 0.5em;
  overflow: hidden;
}
[data-dark-mode="true"] li {
  background-color: var(--purple-d);
}

.question {
  padding: 1em;
  display: flex;
  align-items: center;
  cursor: pointer;
}
.question::before {
  content: "Q";
  font-size: 1.5em;
  margin-right: 0.5em;
  color: var(--primary);
}
[data-dark-mode="true"] .question::before {
  color: var(--purple-m);
}
.answer {
  margin: 0 1rem;
  padding: 0 0 1rem 0;
  font-size: 0.875em;
}
</style>


================================================
FILE: docs/src/examples/angular/ActualAngularApp.vue
================================================
<script setup>
import { vAutoAnimate } from "../../../../src/index"
import { ref } from "vue"

const storyA = {title: 'The Ant and The Grasshopper', showStory: false, story: "The ant and the grasshopper were good friends. In the summer, the ant works hard to fill his storage with food. While the grasshopper was enjoying the fine weather and playing all day. When winter came, the ant was lying cozily in his home surrounded by the food he stored during the summer. While the grasshopper was in his home, hungry and freezing. He asked the ant for food and the ant gave him some. But it wasn’t enough to last the entire winter. When he tried to ask the ant again, the latter replied: \"I'm sorry my friend but my food is just enough for my family to last until the end of winter. If I give you more, we too will starve. We had the entire summer to prepare for the winter but you chose to play instead.\""}
const storyB = {title: 'The Boy Who Cried Wolf', showStory: false, story: "There was once a shepherd boy who liked to play tricks. One day, while he was watching over the herd, the boy decided to play a trick and cried “wolf! wolf!”. The people who heard rushed over to help him. But they were disappointed when they saw that there was no wolf and the boy was laughing at them. The next day, he did it again and people rushed to his aid only to be disappointed once again. On the third day, the boy saw a wolf devouring one of his sheep and cried for help. But the people who heard him thought this is just another of the boy’s pranks so no one came to help him. That day, the boy lost some of his sheep to the wolf."}
const stories = ref([storyA, storyB]);

</script>

<template>
  <div class="example angular-example grid">
    <div v-for="(story, key) in stories" :key="key">
      <div class="story-card" v-auto-animate>
        <h2>{{ story.title }}</h2>
        <div v-if="story.showStory">{{ story.story }}</div>
        <button class="button toggle-story-btn" @click="story.showStory = !story.showStory">Toggle story</button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.grid { display: grid; grid-template-columns: repeat(2, 1fr); grid-gap: 10px; font-size: 0.875em; }
.story-card { background-color: var(--purple-md); padding: 0.75em; border-radius: 0.5em; box-shadow: 0 0 0.5em rgb(0 0 0 / 10%); }
.story-card h2 { margin: 0; padding: 0; font-size: 1.5em}
.toggle-story-btn { margin: 1em 0 0; }
</style>


================================================
FILE: docs/src/examples/angular/index.ts
================================================
const angularDirectiveMain = {
  angular: {
    ext: "angular",
    language: "jsx",
    example: `import { Component } from '@angular/core';
import { AutoAnimateDirective } from '@formkit/auto-animate/angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [AutoAnimateDirective],
  template: \`
    @for (story of stories; track story.title) {
      <div>
        <div class="story-card" auto-animate>
          <h2>{{ story.title }}</h2>
          @if (story.showStory) {
            <div>{{ story.story }}</div>
          }
          <button (click)="story.showStory = !story.showStory">Toggle story</button>
        </div>
      </div>
    }
  \`,
})
export class AppComponent {
  readonly stories = [
    {title: 'The Ant and The Grasshopper', showStory: false, story: "T
Download .txt
gitextract_185zpymh/

├── .cursorrules
├── .dmux-hooks/
│   ├── AGENTS.md
│   ├── CLAUDE.md
│   ├── README.md
│   └── examples/
│       ├── post_merge.example
│       ├── run_dev.example
│       ├── run_test.example
│       └── worktree_created.example
├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .npmignore
├── .npmrc
├── .prettierrc
├── LICENSE
├── README.md
├── build/
│   ├── build-nuxt.ts
│   ├── build.mjs
│   ├── bundle.ts
│   └── nuxt-playground/
│       ├── app.vue
│       ├── nuxt.config.ts
│       ├── package.json
│       └── tsconfig.json
├── docs/
│   ├── assets/
│   │   ├── fonts.css
│   │   ├── main.css
│   │   ├── prism.css
│   │   ├── prism.js
│   │   └── variables.css
│   ├── index.html
│   ├── src/
│   │   ├── App.vue
│   │   ├── components/
│   │   │   ├── AsideTip.vue
│   │   │   ├── CodeExample.vue
│   │   │   ├── ColorModeToggle.vue
│   │   │   ├── FormKitLogo.vue
│   │   │   ├── GitHubLogo.vue
│   │   │   ├── HeroTitle.vue
│   │   │   ├── IconAngular.vue
│   │   │   ├── IconArrow.vue
│   │   │   ├── IconBun.vue
│   │   │   ├── IconDiscord.vue
│   │   │   ├── IconDown.vue
│   │   │   ├── IconHTML.vue
│   │   │   ├── IconJavaScript.vue
│   │   │   ├── IconLightbulb.vue
│   │   │   ├── IconMoon.vue
│   │   │   ├── IconNPM.vue
│   │   │   ├── IconNuxt.vue
│   │   │   ├── IconOutbound.vue
│   │   │   ├── IconPNPM.vue
│   │   │   ├── IconPreact.vue
│   │   │   ├── IconQwik.vue
│   │   │   ├── IconReact.vue
│   │   │   ├── IconRemove.vue
│   │   │   ├── IconSolid.vue
│   │   │   ├── IconSun.vue
│   │   │   ├── IconSvelte.vue
│   │   │   ├── IconTwitter.vue
│   │   │   ├── IconVue.vue
│   │   │   ├── IconYarn.vue
│   │   │   ├── KickstartPromo.vue
│   │   │   ├── Navigation.vue
│   │   │   ├── PoliteAd.vue
│   │   │   ├── ReducedMotionWarning.vue
│   │   │   ├── TempoPromo.vue
│   │   │   ├── TheFooter.vue
│   │   │   ├── TheHeader.vue
│   │   │   └── TheLogo.vue
│   │   ├── examples/
│   │   │   ├── accordion/
│   │   │   │   └── ActualAccordion.vue
│   │   │   ├── angular/
│   │   │   │   ├── ActualAngularApp.vue
│   │   │   │   └── index.ts
│   │   │   ├── basic/
│   │   │   │   ├── basic.ts
│   │   │   │   └── index.ts
│   │   │   ├── boxes/
│   │   │   │   └── ActualBoxes.vue
│   │   │   ├── cards/
│   │   │   │   └── ActualCards.vue
│   │   │   ├── config/
│   │   │   │   └── index.ts
│   │   │   ├── disable/
│   │   │   │   ├── ActualDisable.vue
│   │   │   │   ├── disable.html
│   │   │   │   ├── disable.jsx
│   │   │   │   ├── disable.vue
│   │   │   │   └── index.ts
│   │   │   ├── dropdown/
│   │   │   │   ├── ActualDropdown.vue
│   │   │   │   ├── dropdown-solid.tsx
│   │   │   │   ├── dropdown.html
│   │   │   │   ├── dropdown.jsx
│   │   │   │   ├── dropdown.vue
│   │   │   │   └── index.ts
│   │   │   ├── first-demo/
│   │   │   │   ├── ActualDemo.vue
│   │   │   │   ├── Arrow.vue
│   │   │   │   ├── Close.vue
│   │   │   │   └── FrameworkList.vue
│   │   │   ├── formkit/
│   │   │   │   └── ActualFormKit.vue
│   │   │   ├── installation/
│   │   │   │   └── index.ts
│   │   │   ├── intro/
│   │   │   │   ├── index.ts
│   │   │   │   ├── intro-preact.jsx
│   │   │   │   ├── intro-solid.jsx
│   │   │   │   ├── intro.angular
│   │   │   │   ├── intro.html
│   │   │   │   ├── intro.jsx
│   │   │   │   ├── intro.svelte
│   │   │   │   └── intro.vue
│   │   │   ├── list/
│   │   │   │   └── ActualList.vue
│   │   │   ├── plugin/
│   │   │   │   ├── ActualPlugin.vue
│   │   │   │   └── index.ts
│   │   │   ├── preact/
│   │   │   │   ├── ActualPreactApp.vue
│   │   │   │   └── index.ts
│   │   │   ├── qwik/
│   │   │   │   └── index.ts
│   │   │   ├── react/
│   │   │   │   ├── ActualReactApp.vue
│   │   │   │   └── index.ts
│   │   │   ├── solid/
│   │   │   │   ├── ActualSolidApp.vue
│   │   │   │   └── index.ts
│   │   │   ├── svelte/
│   │   │   │   ├── ActualSvelteApp.vue
│   │   │   │   └── index.ts
│   │   │   └── vue/
│   │   │       ├── ActualVueApp.vue
│   │   │       ├── ActualVueAppHook.vue
│   │   │       └── index.ts
│   │   ├── global.d.ts
│   │   ├── main.ts
│   │   ├── pages/
│   │   │   ├── PageBottomJumpTest.vue
│   │   │   ├── PageHome.vue
│   │   │   ├── PageList.vue
│   │   │   ├── PageTestKeepAlive.vue
│   │   │   ├── PageTests.vue
│   │   │   └── test-components/
│   │   │       ├── CompOne.vue
│   │   │       └── CompTwo.vue
│   │   └── sections/
│   │       ├── SectionExamples.vue
│   │       ├── SectionInstallation.vue
│   │       ├── SectionPlugins.vue
│   │       ├── SectionUsage.vue
│   │       └── SectionWhy.vue
│   ├── vite.config.ts
│   └── vite.config.ts.js
├── package.json
├── playwright.config.ts
├── rollup.config.js
├── src/
│   ├── angular/
│   │   └── index.ts
│   ├── debug-utils.ts
│   ├── index.ts
│   ├── nuxt/
│   │   ├── module.ts
│   │   └── runtime/
│   │       └── plugin.ts
│   ├── preact/
│   │   └── index.ts
│   ├── qwik/
│   │   └── index.ts
│   ├── react/
│   │   └── index.ts
│   ├── solid/
│   │   └── index.ts
│   └── vue/
│       └── index.ts
├── tests/
│   └── e2e/
│       ├── animations.spec.ts
│       ├── bottom-jump-fix.spec.ts
│       ├── disable.spec.ts
│       ├── exports.spec.ts
│       ├── framework-animations.spec.ts
│       ├── frameworks.spec.ts
│       ├── memory.spec.ts
│       ├── offscreen.spec.ts
│       ├── utils.ts
│       ├── visual-animation-video.spec.ts
│       ├── visual-animation.spec.ts
│       ├── visual-video.util.ts
│       ├── vue-plugin.spec.ts
│       └── vue-vif.spec.ts
└── tsconfig.json
Download .txt
SYMBOL INDEX (97 symbols across 22 files)

FILE: build/build-nuxt.ts
  type BuildModuleOptions (line 8) | interface BuildModuleOptions {
  type PrepareModuleOptions (line 16) | interface PrepareModuleOptions {
  function prepareModule (line 25) | async function prepareModule (options: PrepareModuleOptions) {
  function buildModule (line 55) | async function buildModule(opts: BuildModuleOptions) {
  function writeTypes (line 143) | async function writeTypes(distDir: string, meta: ModuleMeta) {
  function writeCJSStub (line 216) | async function writeCJSStub(distDir: string) {

FILE: build/bundle.ts
  function clean (line 21) | async function clean() {
  function baseBuild (line 25) | async function baseBuild() {
  function baseBuildMin (line 30) | async function baseBuildMin() {
  function reactBuild (line 41) | async function reactBuild() {
  function solidBuild (line 58) | async function solidBuild() {
  function preactBuild (line 76) | async function preactBuild() {
  function vueBuild (line 94) | async function vueBuild() {
  function angularBuild (line 112) | async function angularBuild() {
  function nuxtBuild (line 151) | async function nuxtBuild() {
  function declarationsBuild (line 159) | async function declarationsBuild() {
  function bundleDeclarations (line 170) | async function bundleDeclarations() {
  function addPackageJSON (line 211) | async function addPackageJSON() {
  function addAssets (line 224) | async function addAssets() {
  function prepareForPublishing (line 234) | async function prepareForPublishing() {
  function publish (line 254) | async function publish() {
  function outputSize (line 272) | async function outputSize() {
  function main (line 277) | async function main() {

FILE: docs/assets/prism.js
  function u (line 3) | function u(e){s.highlightedCode=e,a.hooks.run("before-insert",s),s.eleme...
  function i (line 3) | function i(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=...
  function l (line 3) | function l(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a...
  function o (line 3) | function o(e,n,t,r,s,g){for(var f in t)if(t.hasOwnProperty(f)&&t[f]){var...
  function s (line 3) | function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e...
  function u (line 3) | function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a...
  function c (line 3) | function c(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;n.ne...
  function f (line 3) | function f(){a.manual||a.highlightAll()}
  function a (line 9) | function a(t,n){return t=t.replace(/<S>/g,(function(){return"(?:\\s|//.*...

FILE: docs/src/examples/disable/disable.jsx
  function Juggle (line 4) | function Juggle() {

FILE: docs/src/examples/intro/intro-preact.jsx
  function MyList (line 3) | function MyList () {

FILE: docs/src/examples/intro/intro-solid.jsx
  function MyList (line 3) | function MyList () {

FILE: docs/src/examples/intro/intro.jsx
  function MyList (line 3) | function MyList () {

FILE: docs/src/global.d.ts
  type Window (line 1) | interface Window {

FILE: rollup.config.js
  constant FRAMEWORK (line 4) | const FRAMEWORK = process.env.FRAMEWORK || "index"
  constant DECLARATIONS (line 5) | const DECLARATIONS = process.env.DECLARATIONS || false
  constant MIN (line 6) | const MIN = process.env.MIN || false
  function createOutput (line 18) | function createOutput() {

FILE: src/angular/index.ts
  class AutoAnimateDirective (line 15) | class AutoAnimateDirective {
    method constructor (line 18) | constructor(el: ElementRef) {

FILE: src/debug-utils.ts
  function raw (line 1) | function raw(str: string): number {
  function drawMargins (line 14) | function drawMargins(

FILE: src/index.ts
  type Coordinates (line 4) | interface Coordinates {
  type AnimationController (line 14) | interface AnimationController<P = unknown> {
  constant TGT (line 95) | const TGT = "__aa_tgt"
  constant DEL (line 99) | const DEL = "__aa_del"
  constant NEW (line 105) | const NEW = "__aa_new"
  function isOffscreen (line 134) | function isOffscreen(el: Element): boolean {
  function observePosition (line 145) | function observePosition(el: Element) {
  function updatePos (line 184) | function updatePos(el: Element, debounce = true) {
  function updateAllPos (line 212) | function updateAllPos() {
  function poll (line 232) | function poll(el: Element) {
  function lowPriority (line 248) | function lowPriority(callback: CallableFunction) {
  function getElements (line 291) | function getElements(mutations: MutationRecord[]): Set<Element> | false {
  function target (line 350) | function target(el: Element, child?: Element) {
  function animate (line 361) | function animate(el: Element) {
  function raw (line 385) | function raw(str: string): number {
  function getScrollOffset (line 394) | function getScrollOffset(el: Element) {
  function getCoords (line 410) | function getCoords(el: Element): Coordinates {
  function getTransitionSizes (line 429) | function getTransitionSizes(
  function getOptions (line 466) | function getOptions(el: Element): AutoAnimateOptions | AutoAnimationPlug...
  function getTarget (line 477) | function getTarget(el: Element): Element | undefined {
  function isEnabled (line 487) | function isEnabled(el: Element): boolean {
  function forEach (line 497) | function forEach(
  function getPluginTuple (line 513) | function getPluginTuple(
  function isPlugin (line 524) | function isPlugin(
  function remain (line 535) | function remain(el: Element) {
  function add (line 601) | function add(el: Element) {
  function cleanUp (line 641) | function cleanUp(el: Element, styles?: Partial<CSSStyleDeclaration>) {
  function remove (line 662) | function remove(el: Element) {
  function adjustScroll (line 756) | function adjustScroll(
  function deletePosition (line 807) | function deletePosition(
  type AutoAnimateOptions (line 837) | interface AutoAnimateOptions {
  type AutoAnimationPluginOptions (line 857) | interface AutoAnimationPluginOptions {
  type AutoAnimationPlugin (line 865) | interface AutoAnimationPlugin {
  function autoAnimate (line 883) | function autoAnimate(

FILE: src/nuxt/module.ts
  method setup (line 18) | setup() {

FILE: src/preact/index.ts
  function useAutoAnimate (line 13) | function useAutoAnimate<T extends Element>(

FILE: src/qwik/index.ts
  function useAutoAnimate (line 23) | function useAutoAnimate<T extends HTMLElement>(

FILE: src/react/index.ts
  function useAutoAnimate (line 13) | function useAutoAnimate<T extends Element>(

FILE: src/solid/index.ts
  type Directives (line 10) | interface Directives {

FILE: src/vue/index.ts
  function createVAutoAnimate (line 21) | function createVAutoAnimate(
  method install (line 53) | install(app, defaults?: Partial<AutoAnimateOptions> | AutoAnimationPlugi...
  function useAutoAnimate (line 64) | function useAutoAnimate<T extends Element | Component>(

FILE: tests/e2e/utils.ts
  function assertNoConsoleErrors (line 3) | async function assertNoConsoleErrors(page: Page) {
  function withAnimationObserver (line 14) | async function withAnimationObserver(page: Page, selector: string) {
  function waitForActiveAnimations (line 32) | async function waitForActiveAnimations(page: Page, selector: string, tim...
  function approximateMemoryUsage (line 45) | async function approximateMemoryUsage(page: Page) {
  function forceGC (line 61) | async function forceGC(page: Page) {

FILE: tests/e2e/visual-animation-video.spec.ts
  function scrub (line 60) | async function scrub(fraction: number) {

FILE: tests/e2e/visual-animation.spec.ts
  function scrub (line 51) | async function scrub(fraction: number) {

FILE: tests/e2e/visual-video.util.ts
  function getVideoDurationSec (line 7) | async function getVideoDurationSec(videoPath: string): Promise<number> {
  function extractFrameAt (line 17) | async function extractFrameAt(videoPath: string, timeSec: number, outPat...
  function diffImages (line 30) | async function diffImages(aPath: string, bPath: string): Promise<{ ratio...
Condensed preview — 160 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (374K chars).
[
  {
    "path": ".cursorrules",
    "chars": 11539,
    "preview": "### Project overview\n- **Purpose**: Zero-config motion for DOM list changes. Given a parent element, automatically anima"
  },
  {
    "path": ".dmux-hooks/AGENTS.md",
    "chars": 11821,
    "preview": "# dmux Hooks System - Agent Reference\n\n**Auto-generated documentation for AI agents**\n\nThis document contains everything"
  },
  {
    "path": ".dmux-hooks/CLAUDE.md",
    "chars": 11821,
    "preview": "# dmux Hooks System - Agent Reference\n\n**Auto-generated documentation for AI agents**\n\nThis document contains everything"
  },
  {
    "path": ".dmux-hooks/README.md",
    "chars": 1340,
    "preview": "# dmux Hooks\n\nThis directory contains hooks that run automatically at key lifecycle events in dmux.\n\n## Quick Start\n\n1. "
  },
  {
    "path": ".dmux-hooks/examples/post_merge.example",
    "chars": 2093,
    "preview": "#!/bin/bash\n# Example: post_merge hook\n#\n# This hook runs after a successful merge into the target branch.\n# Use it to t"
  },
  {
    "path": ".dmux-hooks/examples/run_dev.example",
    "chars": 1888,
    "preview": "#!/bin/bash\n# Example: run_dev hook\n#\n# This hook starts a dev server and optionally creates a tunnel for sharing.\n# It "
  },
  {
    "path": ".dmux-hooks/examples/run_test.example",
    "chars": 1323,
    "preview": "#!/bin/bash\n# Example: run_test hook\n#\n# This hook runs tests and reports the status back to dmux via the HTTP API.\n# St"
  },
  {
    "path": ".dmux-hooks/examples/worktree_created.example",
    "chars": 1222,
    "preview": "#!/bin/bash\n# Example: worktree_created hook\n#\n# This hook runs after a new worktree is created and the agent is launche"
  },
  {
    "path": ".editorconfig",
    "chars": 207,
    "preview": "# editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 63,
    "preview": "# These are supported funding model platforms\n\ngithub: formkit\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "chars": 2488,
    "preview": "name: CI\non:\n  push:\n    branches:\n      - master\n      - 'release/*'\n  pull_request:\n    branches:\n      - master\n     "
  },
  {
    "path": ".gitignore",
    "chars": 244,
    "preview": "node_modules\ndist\n*.log\n.DS_Store\n\n# Playwright artifacts\nplaywright-report/\nplaywright-report/index.html\ntest-results/\n"
  },
  {
    "path": ".npmignore",
    "chars": 134,
    "preview": "src\napi-extractor.json\n__tests__\n.editorconfig\n.gitignore\nrollup.config.js\ntsconfig.json\nyarn.lock\ndocs\n.prettierrc\n.bui"
  },
  {
    "path": ".npmrc",
    "chars": 21,
    "preview": "shamefully-hoist=true"
  },
  {
    "path": ".prettierrc",
    "chars": 57,
    "preview": "{\n  \"tabWidth\": 2,\n  \"useTabs\": false,\n  \"semi\": false\n}\n"
  },
  {
    "path": "LICENSE",
    "chars": 1052,
    "preview": "Copyright 2022 FormKit Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this softwa"
  },
  {
    "path": "README.md",
    "chars": 1938,
    "preview": "<img width=\"300\" height=\"37\" alt=\"AutoAnimate Logo\" src=\"https://cdn.formk.it/web-assets/logo-auto-animate.svg\" >\n\n![Lat"
  },
  {
    "path": "build/build-nuxt.ts",
    "chars": 6334,
    "preview": "import { existsSync, promises as fsp } from \"fs\"\nimport { pathToFileURL } from \"url\"\nimport { resolve } from \"pathe\"\nimp"
  },
  {
    "path": "build/build.mjs",
    "chars": 240,
    "preview": "import createJITI from \"jiti\"\nimport { fileURLToPath } from \"url\"\nimport { dirname, resolve } from \"path\"\n\nconst __filen"
  },
  {
    "path": "build/bundle.ts",
    "chars": 8117,
    "preview": "import { dirname, resolve } from \"path\"\nimport { fileURLToPath } from \"url\"\nimport { readFile, writeFile } from \"fs/prom"
  },
  {
    "path": "build/nuxt-playground/app.vue",
    "chars": 265,
    "preview": "<script lang=\"ts\" setup>\nconst items = ref(['A', 'B', 'C'])\n\nfunction add () {\n  items.value.push(`${items.value.length "
  },
  {
    "path": "build/nuxt-playground/nuxt.config.ts",
    "chars": 129,
    "preview": "export default defineNuxtConfig({\n  modules: [\"../../src/nuxt/module.ts\"],\n  autoAnimate: {},\n  devtools: { enabled: fal"
  },
  {
    "path": "build/nuxt-playground/package.json",
    "chars": 231,
    "preview": "{\n  \"private\": true,\n  \"name\": \"auto-animate-nuxt-module\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"nuxi dev\",\n   "
  },
  {
    "path": "build/nuxt-playground/tsconfig.json",
    "chars": 41,
    "preview": "{\n  \"extends\": \"./.nuxt/tsconfig.json\"\n}\n"
  },
  {
    "path": "docs/assets/fonts.css",
    "chars": 1401,
    "preview": "\n@font-face {\n  font-family: 'silka';\n  src: url('./fonts/silka/silka-medium-webfont.eot');\n  src: url('./fonts/silka/si"
  },
  {
    "path": "docs/assets/main.css",
    "chars": 6486,
    "preview": "@import './fonts.css';\n@import './variables.css';\n\nbody {\n  font-family: 'silka', sans-serif;\n  padding: 0;\n  margin: 0;"
  },
  {
    "path": "docs/assets/prism.css",
    "chars": 1429,
    "preview": "/* PrismJS 1.28.0\nhttps://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript */\ncode["
  },
  {
    "path": "docs/assets/prism.js",
    "chars": 26925,
    "preview": "/* PrismJS 1.28.0\nhttps://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+bash+jsx"
  },
  {
    "path": "docs/assets/variables.css",
    "chars": 793,
    "preview": ":root {\n  --system-stack: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Co"
  },
  {
    "path": "docs/index.html",
    "chars": 1875,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"/assets/favicon.ico\" /"
  },
  {
    "path": "docs/src/App.vue",
    "chars": 2765,
    "preview": "<script setup lang=\"ts\">\nimport { RouterView } from \"vue-router\"\nimport TheHeader from \"./components/TheHeader.vue\"\n</sc"
  },
  {
    "path": "docs/src/components/AsideTip.vue",
    "chars": 357,
    "preview": "<script setup>\nimport IconLightbulb from \"./IconLightbulb.vue\"\n</script>\n\n<template>\n  <aside class=\"tip\">\n    <IconLigh"
  },
  {
    "path": "docs/src/components/CodeExample.vue",
    "chars": 8009,
    "preview": "<script setup lang=\"ts\">\nimport IconVue from \"./IconVue.vue\"\nimport IconReact from \"./IconReact.vue\"\nimport IconPreact f"
  },
  {
    "path": "docs/src/components/ColorModeToggle.vue",
    "chars": 1019,
    "preview": "<script setup>\nimport { ref, onMounted, watch } from 'vue'\nimport IconMoon from './IconMoon.vue'\nimport IconSun from './"
  },
  {
    "path": "docs/src/components/FormKitLogo.vue",
    "chars": 806,
    "preview": "<template>\n  <svg\n    viewBox=\"0 0 26 26\"\n    version=\"1.1\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    xmlns:xlink=\"http"
  },
  {
    "path": "docs/src/components/GitHubLogo.vue",
    "chars": 805,
    "preview": "<template>\n  <svg\n    data-name=\"Layer 1\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    viewBox=\"0 0 120.78 117.79\"\n  >\n   "
  },
  {
    "path": "docs/src/components/HeroTitle.vue",
    "chars": 3407,
    "preview": "<script setup>\nimport { onMounted, ref } from \"vue\"\nimport { vAutoAnimate } from \"../../../src/index\"\nimport TheLogo fro"
  },
  {
    "path": "docs/src/components/IconAngular.vue",
    "chars": 911,
    "preview": "<template>\n  <svg\n    width=\"2370\"\n    height=\"2500\"\n    viewBox=\"0 0 256 270\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  "
  },
  {
    "path": "docs/src/components/IconArrow.vue",
    "chars": 422,
    "preview": "<template>\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    data-name=\"Layer 1\"\n    viewBox=\"0 0 100 100\"\n    x=\"0px\"\n "
  },
  {
    "path": "docs/src/components/IconBun.vue",
    "chars": 4664,
    "preview": "<template>\n  <svg id=\"Bun\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 80 70\">\n    <title>Bun Logo</title>\n    <path"
  },
  {
    "path": "docs/src/components/IconDiscord.vue",
    "chars": 2171,
    "preview": "<template>\n  <svg\n    width=\"71\"\n    height=\"55\"\n    viewBox=\"0 0 71 55\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    "
  },
  {
    "path": "docs/src/components/IconDown.vue",
    "chars": 331,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 128 128\">\n    <path\n      d=\"M113.95,36.55c-2.73-2.73-"
  },
  {
    "path": "docs/src/components/IconHTML.vue",
    "chars": 683,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n    <title>HTML5 Logo Badge</title>\n    <pat"
  },
  {
    "path": "docs/src/components/IconJavaScript.vue",
    "chars": 735,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 630 630\">\n    <rect width=\"630\" height=\"630\" fill=\"#f7"
  },
  {
    "path": "docs/src/components/IconLightbulb.vue",
    "chars": 759,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 50 50\">\n    <path\n      d=\"M24.99,2c-8.26,0-14.99,6.66"
  },
  {
    "path": "docs/src/components/IconMoon.vue",
    "chars": 551,
    "preview": "<template>\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><!--! Font Awesome Pro 6.1.1 by @fontawesome - "
  },
  {
    "path": "docs/src/components/IconNPM.vue",
    "chars": 595,
    "preview": "<template>\n  <svg\n    version=\"1.1\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    x=\"0px\"\n    y=\"0px\"\n    width=\"540px\"\n   "
  },
  {
    "path": "docs/src/components/IconNuxt.vue",
    "chars": 1248,
    "preview": "<template>\n  <svg\n    width=\"900\"\n    height=\"900\"\n    viewBox=\"0 0 900 900\"\n    fill=\"none\"\n  >\n    <path\n      d=\"M504"
  },
  {
    "path": "docs/src/components/IconOutbound.vue",
    "chars": 3747,
    "preview": "<template>\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n    version=\"1.1"
  },
  {
    "path": "docs/src/components/IconPNPM.vue",
    "chars": 2511,
    "preview": "<template>\n  <svg\n    version=\"1.1\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    xmlns:xlink=\"http://www.w3.org/1999/xlink"
  },
  {
    "path": "docs/src/components/IconPreact.vue",
    "chars": 2430,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"296px\" height=\"29"
  },
  {
    "path": "docs/src/components/IconQwik.vue",
    "chars": 1734,
    "preview": "<template>\n  <svg width=\"256px\" height=\"272px\" viewBox=\"0 0 256 272\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xm"
  },
  {
    "path": "docs/src/components/IconReact.vue",
    "chars": 411,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-11.5 -10.23174 23 20.46348\">\n    <title>React Logo</title"
  },
  {
    "path": "docs/src/components/IconRemove.vue",
    "chars": 378,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\" x=\"0px\" y=\"0px\">\n    <path\n      d=\"M27.19,7.64"
  },
  {
    "path": "docs/src/components/IconSolid.vue",
    "chars": 2220,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 166 155.3\">\n    <title>Solid Logo</title>\n    <defs>\n "
  },
  {
    "path": "docs/src/components/IconSun.vue",
    "chars": 1673,
    "preview": "<template>\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><!--! Font Awesome Pro 6.1.1 by @fontawesome - "
  },
  {
    "path": "docs/src/components/IconSvelte.vue",
    "chars": 1877,
    "preview": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 308\">\n    <title>Svelte Logo</title>\n    <path\n   "
  },
  {
    "path": "docs/src/components/IconTwitter.vue",
    "chars": 756,
    "preview": "<template>\n  <svg id=\"Logo\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 248 204\">\n    <path\n      id=\"Logo-2\"\n      "
  },
  {
    "path": "docs/src/components/IconVue.vue",
    "chars": 585,
    "preview": "<template>\n  <svg\n    version=\"1.1\"\n    viewBox=\"0 0 261.76 226.69\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <g tr"
  },
  {
    "path": "docs/src/components/IconYarn.vue",
    "chars": 4788,
    "preview": "<template>\n  <svg\n    width=\"256px\"\n    height=\"256px\"\n    viewBox=\"0 0 256 256\"\n    version=\"1.1\"\n    xmlns=\"http://www"
  },
  {
    "path": "docs/src/components/KickstartPromo.vue",
    "chars": 10120,
    "preview": "<template>\n  <div class=\"kickstart-promo\">\n    <a\n      href=\"https://kickstart.formkit.com/?utm_source=auto_animate_kic"
  },
  {
    "path": "docs/src/components/Navigation.vue",
    "chars": 3382,
    "preview": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport IconDown from \"./IconDown.vue\"\nimport PoliteAd from \"./PoliteA"
  },
  {
    "path": "docs/src/components/PoliteAd.vue",
    "chars": 2266,
    "preview": "<script setup>\n\n</script>\n\n<template>\n  <section class=\"polite-area\">\n    <div class=\"polite-header\">\n      <h5>Sponsore"
  },
  {
    "path": "docs/src/components/ReducedMotionWarning.vue",
    "chars": 639,
    "preview": "<template>\n  <div class=\"motion-notice\">\n    <p>\n      <strong>Notice</strong>: Your current device has its \"reduce moti"
  },
  {
    "path": "docs/src/components/TempoPromo.vue",
    "chars": 4705,
    "preview": "<template>\n  <div class=\"tempo-promo\">\n    <a\n      href=\"https://tempo.formkit.com/?utm_source=auto_animate_tempo_promo"
  },
  {
    "path": "docs/src/components/TheFooter.vue",
    "chars": 646,
    "preview": "<script setup>\nconst year = new Date().getFullYear()\n</script>\n\n<template>\n  <footer>\n    <p class=\"copyright\">\n      Re"
  },
  {
    "path": "docs/src/components/TheHeader.vue",
    "chars": 1894,
    "preview": "<script setup lang=\"ts\">\nimport TheLogo from \"./TheLogo.vue\"\nimport IconDiscord from \"./IconDiscord.vue\"\nimport IconTwit"
  },
  {
    "path": "docs/src/components/TheLogo.vue",
    "chars": 4423,
    "preview": "<script setup lang=\"ts\">\nimport { onMounted, ref } from \"vue\"\nimport { vAutoAnimate } from \"../../../src\"\n\nconst sequenc"
  },
  {
    "path": "docs/src/examples/accordion/ActualAccordion.vue",
    "chars": 2184,
    "preview": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { vAutoAnimate } from \"../../../../src\"\n\nconst faq = ref([\n  {"
  },
  {
    "path": "docs/src/examples/angular/ActualAngularApp.vue",
    "chars": 2438,
    "preview": "<script setup>\nimport { vAutoAnimate } from \"../../../../src/index\"\nimport { ref } from \"vue\"\n\nconst storyA = {title: 'T"
  },
  {
    "path": "docs/src/examples/angular/index.ts",
    "chars": 1025,
    "preview": "const angularDirectiveMain = {\n  angular: {\n    ext: \"angular\",\n    language: \"jsx\",\n    example: `import { Component } "
  },
  {
    "path": "docs/src/examples/basic/basic.ts",
    "chars": 70,
    "preview": "import autoAnimate from \"@formkit/auto-animate\"\n\nautoAnimate(Element)\n"
  },
  {
    "path": "docs/src/examples/basic/index.ts",
    "chars": 126,
    "preview": "import example from \"./basic.ts?raw\"\n\nexport default {\n  ts: {\n    language: \"typescript\",\n    ext: \"ts\",\n    example,\n "
  },
  {
    "path": "docs/src/examples/boxes/ActualBoxes.vue",
    "chars": 957,
    "preview": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { vAutoAnimate } from \"../../../../src\"\n\nconst numbers = ref<n"
  },
  {
    "path": "docs/src/examples/cards/ActualCards.vue",
    "chars": 2665,
    "preview": "<script setup>\nimport { ref } from \"vue\"\nimport { vAutoAnimate } from \"../../../../src/index\"\n\nconst showForm = ref(fals"
  },
  {
    "path": "docs/src/examples/config/index.ts",
    "chars": 439,
    "preview": "export default {\n  js: {\n    language: \"typescript\",\n    title: \"MyComponent.ts\",\n    example: `autoAnimate(el, {\n  // A"
  },
  {
    "path": "docs/src/examples/disable/ActualDisable.vue",
    "chars": 1657,
    "preview": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { useAutoAnimate } from \"../../../../src/vue\"\n\nconst balls = r"
  },
  {
    "path": "docs/src/examples/disable/disable.html",
    "chars": 736,
    "preview": "<ul class=\"balls\" id=\"juggle\">\n  <li class=\"red\">Red</li>\n  <li class=\"green\">Green</li>\n  <li class=\"blue\">Blue</li>\n</"
  },
  {
    "path": "docs/src/examples/disable/disable.jsx",
    "chars": 840,
    "preview": "import { useEffect, useState } from 'react'\nimport { useAutoAnimate } from '@formkit/auto-animate/react'\n\nfunction Juggl"
  },
  {
    "path": "docs/src/examples/disable/disable.vue",
    "chars": 690,
    "preview": "<script setup>\nimport { ref } from \"vue\"\nimport { useAutoAnimate } from \"../../../../src/vue\"\n\nconst balls = ref([\"red\","
  },
  {
    "path": "docs/src/examples/disable/index.ts",
    "chars": 406,
    "preview": "import vueExample from \"./disable.vue?raw\"\nimport reactExample from \"./disable.jsx?raw\"\n// import htmlExample from \"./di"
  },
  {
    "path": "docs/src/examples/dropdown/ActualDropdown.vue",
    "chars": 1449,
    "preview": "<script setup>\nimport { ref, onMounted } from \"vue\"\nimport autoAnimate from \"../../../../src/index\"\n\nconst dropdown = re"
  },
  {
    "path": "docs/src/examples/dropdown/dropdown-solid.tsx",
    "chars": 571,
    "preview": "import { createAutoAnimate } from \"@formkit/auto-animate/solid\"\nimport { createSignal, Show } from \"solid-js\"\n\nconst Dro"
  },
  {
    "path": "docs/src/examples/dropdown/dropdown.html",
    "chars": 456,
    "preview": "<div id=\"dropdown\" class=\"dropdown\">\n  <strong class=\"dropdown-label\" onclick=\"toggle\">\n    Click me to open!\n  </strong"
  },
  {
    "path": "docs/src/examples/dropdown/dropdown.jsx",
    "chars": 539,
    "preview": "import { useState, useRef, useEffect } from 'react'\nimport autoAnimate from '@formkit/auto-animate'\n\nconst Dropdown = ()"
  },
  {
    "path": "docs/src/examples/dropdown/dropdown.vue",
    "chars": 477,
    "preview": "<script setup>\nimport { ref, onMounted } from \"vue\"\nimport autoAnimate from \"@formkit/auto-animate\"\n\nconst dropdown = re"
  },
  {
    "path": "docs/src/examples/dropdown/index.ts",
    "chars": 526,
    "preview": "import vueExample from \"./dropdown.vue?raw\"\nimport reactExample from \"./dropdown.jsx?raw\"\nimport solidExample from \"./dr"
  },
  {
    "path": "docs/src/examples/first-demo/ActualDemo.vue",
    "chars": 3313,
    "preview": "<script setup>\nimport FrameworkList from \"./FrameworkList.vue\"\n</script>\n\n<template>\n  <div class=\"comparison-app\">\n    "
  },
  {
    "path": "docs/src/examples/first-demo/Arrow.vue",
    "chars": 420,
    "preview": "<script setup>\ndefineProps({\n  direction: {\n    type: String,\n    default: \"\",\n  },\n})\n</script>\n\n<template>\n  <svg\n    "
  },
  {
    "path": "docs/src/examples/first-demo/Close.vue",
    "chars": 475,
    "preview": "<template>\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    viewBox=\"0 0 60 60\"\n  >\n    <path d=\"M34.2,30l13.5-13.4c.6-"
  },
  {
    "path": "docs/src/examples/first-demo/FrameworkList.vue",
    "chars": 2896,
    "preview": "<script setup>\nimport { ref, onMounted, computed } from \"vue\"\nimport autoAnimate from \"../../../../src/index\"\nimport Arr"
  },
  {
    "path": "docs/src/examples/formkit/ActualFormKit.vue",
    "chars": 2305,
    "preview": "<script setup>\nimport { ref, onMounted } from \"vue\"\nimport autoAnimate from \"../../../../src\"\n\nconst example = ref()\n\non"
  },
  {
    "path": "docs/src/examples/installation/index.ts",
    "chars": 451,
    "preview": "export default {\n  yarn: {\n    example: \"yarn add @formkit/auto-animate\",\n    language: \"shell\",\n    title: \"~/my-app\",\n"
  },
  {
    "path": "docs/src/examples/intro/index.ts",
    "chars": 915,
    "preview": "import vueExample from \"./intro.vue?raw\"\nimport reactExample from \"./intro.jsx?raw\"\nimport preactExample from \"./intro-p"
  },
  {
    "path": "docs/src/examples/intro/intro-preact.jsx",
    "chars": 234,
    "preview": "import { useAutoAnimate } from '@formkit/auto-animate/preact'\n\nfunction MyList () {\n  const [animationParent] = useAutoA"
  },
  {
    "path": "docs/src/examples/intro/intro-solid.jsx",
    "chars": 239,
    "preview": "import { createAutoAnimate } from '@formkit/auto-animate/solid'\n\nfunction MyList () {\n  const [animationParent] = create"
  },
  {
    "path": "docs/src/examples/intro/intro.angular",
    "chars": 68,
    "preview": "<ul auto-animate>\n  <!-- 🪄 Magic animations for your list -->\n</ul>\n"
  },
  {
    "path": "docs/src/examples/intro/intro.html",
    "chars": 229,
    "preview": "<ul id=\"myList\">\n  <!-- 🪄 Magic animations for your list -->\n</ul>\n\n<script type=\"module\">\n  import autoAnimate from 'ht"
  },
  {
    "path": "docs/src/examples/intro/intro.jsx",
    "chars": 233,
    "preview": "import { useAutoAnimate } from '@formkit/auto-animate/react'\n\nfunction MyList () {\n  const [animationParent] = useAutoAn"
  },
  {
    "path": "docs/src/examples/intro/intro.svelte",
    "chars": 141,
    "preview": "<script>\n  import autoAnimate from \"@formkit/auto-animate\"\n</script>\n\n<ul use:autoAnimate>\n  <!-- 🪄 Magic animations for"
  },
  {
    "path": "docs/src/examples/intro/intro.vue",
    "chars": 99,
    "preview": "<template>\n  <ul v-auto-animate>\n    <!-- 🪄 Magic animations for your list -->\n  </ul>\n</template>\n"
  },
  {
    "path": "docs/src/examples/list/ActualList.vue",
    "chars": 2152,
    "preview": "<script setup lang=\"ts\">\nimport { onMounted, ref } from \"vue\"\nimport autoAnimate from \"../../../../src\"\nimport IconRemov"
  },
  {
    "path": "docs/src/examples/plugin/ActualPlugin.vue",
    "chars": 3660,
    "preview": "<script setup lang=\"ts\">\nimport { onMounted, ref } from \"vue\"\nimport autoAnimate, { getTransitionSizes } from \"../../../"
  },
  {
    "path": "docs/src/examples/plugin/index.ts",
    "chars": 2301,
    "preview": "const pluginMain = {\n  js: {\n    ext: \"js\",\n    language: \"javascript\",\n    example: `import autoAnimate, { getTransitio"
  },
  {
    "path": "docs/src/examples/preact/ActualPreactApp.vue",
    "chars": 663,
    "preview": "<script setup>\nimport { useAutoAnimate } from \"../../../../src/vue/index.ts\"\nimport { ref } from \"vue\"\nconst [parent] = "
  },
  {
    "path": "docs/src/examples/preact/index.ts",
    "chars": 616,
    "preview": "export default {\n  preact: {\n    language: \"jsx\",\n    ext: \"jsx\",\n    example: `import { useState } from 'preact/hooks'\n"
  },
  {
    "path": "docs/src/examples/qwik/index.ts",
    "chars": 645,
    "preview": "export default {\n  qwik: {\n    language: \"jsx\",\n    ext: \"jsx\",\n    example: `import { useSignal } from '@builder.io/qwi"
  },
  {
    "path": "docs/src/examples/react/ActualReactApp.vue",
    "chars": 644,
    "preview": "<script setup>\nimport { useAutoAnimate } from \"../../../../src/vue/index.ts\"\nimport { ref } from \"vue\"\nconst [parent, se"
  },
  {
    "path": "docs/src/examples/react/index.ts",
    "chars": 630,
    "preview": "export default {\n  react: {\n    language: \"jsx\",\n    ext: \"jsx\",\n    example: `import { useState } from 'react'\nimport {"
  },
  {
    "path": "docs/src/examples/solid/ActualSolidApp.vue",
    "chars": 1116,
    "preview": "<script setup>\nimport { useAutoAnimate } from \"../../../../src/vue/index.ts\"\nimport { ref } from \"vue\"\nconst [parent] = "
  },
  {
    "path": "docs/src/examples/solid/index.ts",
    "chars": 1849,
    "preview": "const solidPrimitive = {\n  solid: {\n    language: \"tsx\",\n    ext: \"tsx\",\n    example: `import { createSignal, For, Show "
  },
  {
    "path": "docs/src/examples/svelte/ActualSvelteApp.vue",
    "chars": 2079,
    "preview": "<script setup>\nimport IconRemove from \"../../components/IconRemove.vue\"\nimport { vAutoAnimate } from \"../../../../src/in"
  },
  {
    "path": "docs/src/examples/svelte/index.ts",
    "chars": 837,
    "preview": "export default {\n  svelte: {\n    ext: \"svelte\",\n    language: \"html\",\n    example: `<script>\n  import autoAnimate from '"
  },
  {
    "path": "docs/src/examples/vue/ActualVueApp.vue",
    "chars": 1213,
    "preview": "<script setup>\nimport { vAutoAnimate } from \"../../../../src/index\"\nimport { ref } from \"vue\"\nconst items = ref([\n  \"😏\","
  },
  {
    "path": "docs/src/examples/vue/ActualVueAppHook.vue",
    "chars": 574,
    "preview": "<script setup>\nimport { ref } from \"vue\"\nimport { useAutoAnimate } from \"../../../../src/vue\"\n\nconst items = ref([\"React"
  },
  {
    "path": "docs/src/examples/vue/index.ts",
    "chars": 1668,
    "preview": "const vueDirectiveMain = {\n  js: {\n    ext: \"ts\",\n    language: \"typescript\",\n    example: `import { createApp } from 'v"
  },
  {
    "path": "docs/src/global.d.ts",
    "chars": 34,
    "preview": "interface Window {\n  Prism: any\n}\n"
  },
  {
    "path": "docs/src/main.ts",
    "chars": 819,
    "preview": "import { ViteSSG } from \"vite-ssg\"\nimport { plugin, defaultConfig } from \"@formkit/vue\"\nimport App from \"./App.vue\"\nimpo"
  },
  {
    "path": "docs/src/pages/PageBottomJumpTest.vue",
    "chars": 1582,
    "preview": "<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue'\nimport { vAutoAnimate } from \"../../../src/index\"\n\nconst i"
  },
  {
    "path": "docs/src/pages/PageHome.vue",
    "chars": 1498,
    "preview": "<script setup lang=\"ts\">\nimport { ref, onMounted } from \"vue\"\nimport TheHeader from \"../components/TheHeader.vue\"\nimport"
  },
  {
    "path": "docs/src/pages/PageList.vue",
    "chars": 1850,
    "preview": "<script setup lang=\"ts\">\nimport { onMounted, ref } from \"vue\"\nimport autoAnimate from \"../../../src\"\n\nconst items = ref("
  },
  {
    "path": "docs/src/pages/PageTestKeepAlive.vue",
    "chars": 1020,
    "preview": "\n<script setup lang=\"ts\">\nimport CompOne from \"./test-components/CompOne.vue\";\nimport CompTwo from \"./test-components/Co"
  },
  {
    "path": "docs/src/pages/PageTests.vue",
    "chars": 2905,
    "preview": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { vAutoAnimate } from \"../../../src/index\"\nconst show = ref(fa"
  },
  {
    "path": "docs/src/pages/test-components/CompOne.vue",
    "chars": 184,
    "preview": "<template>\n  <div class=\"comp\">Comp One</div>\n</template>\n\n<script lang=\"ts\">\nexport default {\n  name: \"CompOne\",\n  prop"
  },
  {
    "path": "docs/src/pages/test-components/CompTwo.vue",
    "chars": 252,
    "preview": "<template>\n  <div class=\"comp\">Comp Two</div>\n</template>\n\n<script lang=\"ts\">\nexport default {\n  name: \"CompTwo\",\n  prop"
  },
  {
    "path": "docs/src/sections/SectionExamples.vue",
    "chars": 3058,
    "preview": "<script setup>\nimport ActualCards from \"../examples/cards/ActualCards.vue\"\nimport ActualList from \"../examples/list/Actu"
  },
  {
    "path": "docs/src/sections/SectionInstallation.vue",
    "chars": 1503,
    "preview": "<script setup>\nimport HomepageDemo from \"../examples/first-demo/ActualDemo.vue\"\nimport installation from \"../examples/in"
  },
  {
    "path": "docs/src/sections/SectionPlugins.vue",
    "chars": 1274,
    "preview": "<script setup>\nimport CodeExample from \"../components/CodeExample.vue\"\nimport Bouncy from '../examples/plugin'\nimport Ac"
  },
  {
    "path": "docs/src/sections/SectionUsage.vue",
    "chars": 12644,
    "preview": "<script setup>\nimport CodeExample from \"../components/CodeExample.vue\"\nimport AsideTip from \"../components/AsideTip.vue\""
  },
  {
    "path": "docs/src/sections/SectionWhy.vue",
    "chars": 1430,
    "preview": "<script setup lang=\"ts\">\nimport CodeExample from \"../components/CodeExample.vue\"\nimport examples from \"../examples/basic"
  },
  {
    "path": "docs/vite.config.ts",
    "chars": 233,
    "preview": "import { defineConfig } from \"vite\"\nimport vue from \"@vitejs/plugin-vue\"\n\nexport default defineConfig({\n  root: \"./\",\n  "
  },
  {
    "path": "docs/vite.config.ts.js",
    "chars": 1094,
    "preview": "// vite.config.ts\nimport { defineConfig } from \"vite\";\nimport vue from \"@vitejs/plugin-vue\";\nvar vite_config_default = d"
  },
  {
    "path": "package.json",
    "chars": 3488,
    "preview": "{\n  \"name\": \"@formkit/auto-animate\",\n  \"version\": \"0.9.0\",\n  \"description\": \"Add motion to your apps with a single line "
  },
  {
    "path": "playwright.config.ts",
    "chars": 1170,
    "preview": "import { defineConfig, devices } from '@playwright/test'\n\nexport default defineConfig({\n  testDir: './tests/e2e',\n  full"
  },
  {
    "path": "rollup.config.js",
    "chars": 1089,
    "preview": "import typescript from \"@rollup/plugin-typescript\"\nimport terser from \"@rollup/plugin-terser\"\n\nconst FRAMEWORK = process"
  },
  {
    "path": "src/angular/index.ts",
    "chars": 423,
    "preview": "import {\n  Directive,\n  ElementRef,\n  effect,\n  input,\n} from \"@angular/core\";\nimport autoAnimate, { AutoAnimateOptions "
  },
  {
    "path": "src/debug-utils.ts",
    "chars": 1437,
    "preview": "function raw(str: string): number {\n  return Number(str.replace(/[^0-9.\\-]/g, \"\"))\n}\n\nconst lines = new WeakMap<\n  Inter"
  },
  {
    "path": "src/index.ts",
    "chars": 28348,
    "preview": "/**\n * Absolute coordinate positions adjusted for scroll.\n */\ninterface Coordinates {\n  top: number\n  left: number\n  wid"
  },
  {
    "path": "src/nuxt/module.ts",
    "chars": 754,
    "preview": "import {\n  defineNuxtModule,\n  addImports,\n  addPlugin,\n  createResolver,\n} from \"@nuxt/kit\"\n\n// Module options TypeScri"
  },
  {
    "path": "src/nuxt/runtime/plugin.ts",
    "chars": 229,
    "preview": "import { defineNuxtPlugin } from \"#imports\"\nimport { vAutoAnimate } from \"@formkit/auto-animate/vue\"\n\nexport default def"
  },
  {
    "path": "src/preact/index.ts",
    "chars": 1009,
    "preview": "import { useEffect, useState, useRef } from \"preact/hooks\"\nimport autoAnimate, {\n  AutoAnimateOptions,\n  AutoAnimationPl"
  },
  {
    "path": "src/qwik/index.ts",
    "chars": 1416,
    "preview": "import {\n  $,\n  NoSerialize,\n  noSerialize,\n  QRL,\n  Signal,\n  useSignal,\n  useVisibleTask$,\n} from \"@builder.io/qwik\"\n\n"
  },
  {
    "path": "src/react/index.ts",
    "chars": 1197,
    "preview": "import { useState, useCallback, RefCallback, useMemo, useEffect } from \"react\"\nimport autoAnimate, {\n  AutoAnimateOption"
  },
  {
    "path": "src/solid/index.ts",
    "chars": 1538,
    "preview": "import autoAnimate, {\n  AutoAnimateOptions,\n  AutoAnimationPlugin,\n  AnimationController,\n} from \"../index\"\nimport { cre"
  },
  {
    "path": "src/vue/index.ts",
    "chars": 3090,
    "preview": "import { ref, onMounted, watchEffect, Plugin, Ref, onBeforeUnmount } from \"vue\"\nimport type { Component, Directive } fro"
  },
  {
    "path": "tests/e2e/animations.spec.ts",
    "chars": 1385,
    "preview": "import { test, expect } from '@playwright/test'\nimport { assertNoConsoleErrors, withAnimationObserver } from './utils'\n\n"
  },
  {
    "path": "tests/e2e/bottom-jump-fix.spec.ts",
    "chars": 6744,
    "preview": "import { test, expect } from '@playwright/test'\nimport { assertNoConsoleErrors, withAnimationObserver } from './utils'\n\n"
  },
  {
    "path": "tests/e2e/disable.spec.ts",
    "chars": 958,
    "preview": "import { test, expect } from '@playwright/test'\nimport { assertNoConsoleErrors, withAnimationObserver } from './utils'\n\n"
  },
  {
    "path": "tests/e2e/exports.spec.ts",
    "chars": 416,
    "preview": "import { test, expect } from '@playwright/test'\n\ntest.describe('ESM exports', () => {\n  test('named export autoAnimate i"
  },
  {
    "path": "tests/e2e/framework-animations.spec.ts",
    "chars": 4382,
    "preview": "import { test, expect } from '@playwright/test'\nimport { assertNoConsoleErrors, withAnimationObserver } from './utils'\n\n"
  },
  {
    "path": "tests/e2e/frameworks.spec.ts",
    "chars": 757,
    "preview": "import { test, expect } from '@playwright/test'\nimport { assertNoConsoleErrors } from './utils'\n\n// The home page mounts"
  },
  {
    "path": "tests/e2e/memory.spec.ts",
    "chars": 1548,
    "preview": "import { test, expect } from '@playwright/test'\nimport { approximateMemoryUsage, forceGC } from './utils'\n\n// This is a "
  },
  {
    "path": "tests/e2e/offscreen.spec.ts",
    "chars": 1483,
    "preview": "import { test, expect } from '@playwright/test'\nimport { assertNoConsoleErrors } from './utils'\n\ntest.describe('Offscree"
  },
  {
    "path": "tests/e2e/utils.ts",
    "chars": 2307,
    "preview": "import { expect, Page } from '@playwright/test'\n\nexport async function assertNoConsoleErrors(page: Page) {\n  const error"
  },
  {
    "path": "tests/e2e/visual-animation-video.spec.ts",
    "chars": 5472,
    "preview": "import { test, expect } from '@playwright/test'\nimport path from 'node:path'\nimport fs from 'node:fs/promises'\nimport { "
  },
  {
    "path": "tests/e2e/visual-animation.spec.ts",
    "chars": 5773,
    "preview": "import { test, expect } from '@playwright/test'\nimport pixelmatch from 'pixelmatch'\nimport { PNG } from 'pngjs'\n\n// Visu"
  },
  {
    "path": "tests/e2e/visual-video.util.ts",
    "chars": 1456,
    "preview": "import { execa } from 'execa'\nimport { PNG } from 'pngjs'\nimport pixelmatch from 'pixelmatch'\nimport fs from 'node:fs/pr"
  },
  {
    "path": "tests/e2e/vue-plugin.spec.ts",
    "chars": 598,
    "preview": "import { test, expect } from '@playwright/test'\nimport { assertNoConsoleErrors, withAnimationObserver } from './utils'\n\n"
  },
  {
    "path": "tests/e2e/vue-vif.spec.ts",
    "chars": 982,
    "preview": "import { test, expect } from '@playwright/test'\nimport { assertNoConsoleErrors, withAnimationObserver } from './utils'\n\n"
  },
  {
    "path": "tsconfig.json",
    "chars": 382,
    "preview": "{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"module\": \"esnext\",\n    \"target\": \"es2019\",\n    \"lib\": "
  }
]

About this extraction

This page contains the full source code of the formkit/auto-animate GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 160 files (338.9 KB), approximately 116.7k tokens, and a symbol index with 97 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!