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//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 | 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, 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 ` ================================================ 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,"&").replace(/=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&&(jg.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"+i.content+""},!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://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\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://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(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".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*\\.{3}(?:[^{}]|)*\\})";function a(t,n){return t=t.replace(//g,(function(){return"(?:\\s|//.*(?!.)|/\\*(?:[^*]|\\*(?!/))\\*/)"})).replace(//g,(function(){return"(?:\\{(?:\\{(?:\\{[^{}]*\\}|[^{}])*\\}|[^{}])*\\})"})).replace(//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{'\"/>=]+|))?|))**/?)?>"),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(""),inside:t.languages.jsx}},t.languages.jsx.tag),t.languages.insertBefore("inside","special-attr",{script:{pattern:a("="),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;a0&&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);a0&&("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$]|(?= AutoAnimate - Add motion to your apps with a single line of code
================================================ FILE: docs/src/App.vue ================================================ ================================================ FILE: docs/src/components/AsideTip.vue ================================================ ================================================ FILE: docs/src/components/CodeExample.vue ================================================ ================================================ FILE: docs/src/components/ColorModeToggle.vue ================================================ ================================================ FILE: docs/src/components/FormKitLogo.vue ================================================ ================================================ FILE: docs/src/components/GitHubLogo.vue ================================================ ================================================ FILE: docs/src/components/HeroTitle.vue ================================================ ================================================ FILE: docs/src/components/IconAngular.vue ================================================ ================================================ FILE: docs/src/components/IconArrow.vue ================================================ ================================================ FILE: docs/src/components/IconBun.vue ================================================ ================================================ FILE: docs/src/components/IconDiscord.vue ================================================ ================================================ FILE: docs/src/components/IconDown.vue ================================================ ================================================ FILE: docs/src/components/IconHTML.vue ================================================ ================================================ FILE: docs/src/components/IconJavaScript.vue ================================================ ================================================ FILE: docs/src/components/IconLightbulb.vue ================================================ ================================================ FILE: docs/src/components/IconMoon.vue ================================================ ================================================ FILE: docs/src/components/IconNPM.vue ================================================ ================================================ FILE: docs/src/components/IconNuxt.vue ================================================ ================================================ FILE: docs/src/components/IconOutbound.vue ================================================ ================================================ FILE: docs/src/components/IconPNPM.vue ================================================ ================================================ FILE: docs/src/components/IconPreact.vue ================================================ ================================================ FILE: docs/src/components/IconQwik.vue ================================================ ================================================ FILE: docs/src/components/IconReact.vue ================================================ ================================================ FILE: docs/src/components/IconRemove.vue ================================================ ================================================ FILE: docs/src/components/IconSolid.vue ================================================ ================================================ FILE: docs/src/components/IconSun.vue ================================================ ================================================ FILE: docs/src/components/IconSvelte.vue ================================================ ================================================ FILE: docs/src/components/IconTwitter.vue ================================================ ================================================ FILE: docs/src/components/IconVue.vue ================================================ ================================================ FILE: docs/src/components/IconYarn.vue ================================================ ================================================ FILE: docs/src/components/KickstartPromo.vue ================================================ ================================================ FILE: docs/src/components/Navigation.vue ================================================ ================================================ FILE: docs/src/components/PoliteAd.vue ================================================ ================================================ FILE: docs/src/components/ReducedMotionWarning.vue ================================================ ================================================ FILE: docs/src/components/TempoPromo.vue ================================================ ================================================ FILE: docs/src/components/TheFooter.vue ================================================ ================================================ FILE: docs/src/components/TheHeader.vue ================================================ ================================================ FILE: docs/src/components/TheLogo.vue ================================================ ================================================ FILE: docs/src/examples/accordion/ActualAccordion.vue ================================================ ================================================ FILE: docs/src/examples/angular/ActualAngularApp.vue ================================================ ================================================ 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) {

{{ story.title }}

@if (story.showStory) {
{{ story.story }}
}
} \`, }) export class AppComponent { readonly stories = [ {title: 'The Ant and The Grasshopper', showStory: false, story: "The ant and the grasshopper were good friends..."}, {title: 'The Boy Who Cried Wolf', showStory: false, story: "There was once a shepherd boy who liked to play tricks..."}, ]; } `, }, } export { angularDirectiveMain } ================================================ FILE: docs/src/examples/basic/basic.ts ================================================ import autoAnimate from "@formkit/auto-animate" autoAnimate(Element) ================================================ FILE: docs/src/examples/basic/index.ts ================================================ import example from "./basic.ts?raw" export default { ts: { language: "typescript", ext: "ts", example, }, } ================================================ FILE: docs/src/examples/boxes/ActualBoxes.vue ================================================ ================================================ FILE: docs/src/examples/cards/ActualCards.vue ================================================ ================================================ FILE: docs/src/examples/config/index.ts ================================================ export default { js: { language: "typescript", title: "MyComponent.ts", example: `autoAnimate(el, { // Animation duration in milliseconds (default: 250) duration: 250, // Easing for motion (default: 'ease-in-out') easing: 'ease-in-out' // When true, this will enable animations even if the user has indicated // they don’t want them via prefers-reduced-motion. disrespectUserMotionPreference: false })`, }, } ================================================ FILE: docs/src/examples/disable/ActualDisable.vue ================================================ ================================================ FILE: docs/src/examples/disable/disable.html ================================================
  • Red
  • Green
  • Blue
================================================ FILE: docs/src/examples/disable/disable.jsx ================================================ import { useEffect, useState } from 'react' import { useAutoAnimate } from '@formkit/auto-animate/react' function Juggle() { const [balls, setBalls] = useState(['red', 'green', 'blue']) const [isEnabled, setIsEnabled] = useState(true) const [parent, enable] = useAutoAnimate({ duration: 500 }) function toggle () { enable(!isEnabled) setIsEnabled(!isEnabled) } useEffect(() => { setTimeout(() => { const juggled = [...balls] juggled.push(juggled.shift()) setBalls(juggled) }, 600) }, [balls]) return ( <>
    { balls.map(color =>
  • { color }
  • ) }
) } export default Juggle ================================================ FILE: docs/src/examples/disable/disable.vue ================================================ ================================================ FILE: docs/src/examples/disable/index.ts ================================================ import vueExample from "./disable.vue?raw" import reactExample from "./disable.jsx?raw" // import htmlExample from "./disable.html?raw" export default { react: { example: reactExample, ext: "jsx", language: "jsx", }, vue: { ext: "vue", language: "html", example: vueExample, }, // js: { // example: htmlExample, // ext: "html", // language: "html", // }, } ================================================ FILE: docs/src/examples/dropdown/ActualDropdown.vue ================================================ ================================================ FILE: docs/src/examples/dropdown/dropdown-solid.tsx ================================================ import { createAutoAnimate } from "@formkit/auto-animate/solid" import { createSignal, Show } from "solid-js" const Dropdown = () => { const [show, setShow] = createSignal(false) const reveal = () => setShow(!show()) const [parent, setEnabled] = createAutoAnimate(/* optional config */) return (
Click me to open!
) } export default Dropdown ================================================ FILE: docs/src/examples/dropdown/dropdown.html ================================================ ================================================ FILE: docs/src/examples/dropdown/dropdown.jsx ================================================ import { useState, useRef, useEffect } from 'react' import autoAnimate from '@formkit/auto-animate' const Dropdown = () => { const [show, setShow] = useState(false) const parent = useRef(null) useEffect(() => { parent.current && autoAnimate(parent.current) }, [parent]) const reveal = () => setShow(!show) return
Click me to open! { show &&

Lorum ipsum...

}
} export default Dropdown ================================================ FILE: docs/src/examples/dropdown/dropdown.vue ================================================ ================================================ FILE: docs/src/examples/dropdown/index.ts ================================================ import vueExample from "./dropdown.vue?raw" import reactExample from "./dropdown.jsx?raw" import solidExample from "./dropdown-solid.tsx?raw" import nativeExample from "./dropdown.html?raw" export default { react: { language: "jsx", ext: "jsx", example: reactExample, }, solid: { language: "tsx", ext: "tsx", example: solidExample, }, vue: { language: "html", ext: "vue", example: vueExample, }, js: { language: "html", ext: "html", example: nativeExample, }, } ================================================ FILE: docs/src/examples/first-demo/ActualDemo.vue ================================================ ================================================ FILE: docs/src/examples/first-demo/Arrow.vue ================================================ ================================================ FILE: docs/src/examples/first-demo/Close.vue ================================================ ================================================ FILE: docs/src/examples/first-demo/FrameworkList.vue ================================================ ================================================ FILE: docs/src/examples/formkit/ActualFormKit.vue ================================================ ================================================ FILE: docs/src/examples/installation/index.ts ================================================ export default { yarn: { example: "yarn add @formkit/auto-animate", language: "shell", title: "~/my-app", }, npm: { example: "npm install @formkit/auto-animate", language: "shell", title: "~/my-app", }, pnpm: { example: "pnpm add @formkit/auto-animate", language: "shell", title: "~/my-app", }, bun:{ example:"bun install @formkit/auto-animate", language:"shell", title:"~/my-app", }, } ================================================ FILE: docs/src/examples/intro/index.ts ================================================ import vueExample from "./intro.vue?raw" import reactExample from "./intro.jsx?raw" import preactExample from "./intro-preact.jsx?raw" import solidExample from "./intro-solid.jsx?raw" import htmlExample from "./intro.html?raw" import svelteExample from "./intro.svelte?raw" import angularExample from "./intro.angular?raw" export default { react: { example: reactExample, ext: "jsx", language: "jsx", }, vue: { ext: "vue", language: "html", example: vueExample, }, solid: { example: solidExample, ext: "jsx", language: "jsx", }, preact: { example: preactExample, ext: "jsx", language: "jsx", }, svelte: { example: svelteExample, ext: "svelte", language: "html", }, angular: { example: angularExample, ext: "angular", language: "html", }, js: { example: htmlExample, ext: "html", language: "html", }, } ================================================ FILE: docs/src/examples/intro/intro-preact.jsx ================================================ import { useAutoAnimate } from '@formkit/auto-animate/preact' function MyList () { const [animationParent] = useAutoAnimate() return (
    {/* 🪄 Magic animations for your list */}
) } ================================================ FILE: docs/src/examples/intro/intro-solid.jsx ================================================ import { createAutoAnimate } from '@formkit/auto-animate/solid' function MyList () { const [animationParent] = createAutoAnimate() return (
    {/* 🪄 Magic animations for your list */}
) } ================================================ FILE: docs/src/examples/intro/intro.angular ================================================
================================================ FILE: docs/src/examples/intro/intro.html ================================================
================================================ FILE: docs/src/examples/intro/intro.jsx ================================================ import { useAutoAnimate } from '@formkit/auto-animate/react' function MyList () { const [animationParent] = useAutoAnimate() return (
    {/* 🪄 Magic animations for your list */}
) } ================================================ FILE: docs/src/examples/intro/intro.svelte ================================================
================================================ FILE: docs/src/examples/intro/intro.vue ================================================ ================================================ FILE: docs/src/examples/list/ActualList.vue ================================================ ================================================ FILE: docs/src/examples/plugin/ActualPlugin.vue ================================================ ================================================ FILE: docs/src/examples/plugin/index.ts ================================================ const pluginMain = { js: { ext: "js", language: "javascript", example: `import autoAnimate, { getTransitionSizes } from '@formkit/auto-animate' autoAnimate(parentElement, (el, action, oldCoords, newCoords) => { let keyframes // supply a different set of keyframes for each action if (action === 'add') { keyframes = [ { transform: 'scale(0)', opacity: 0 }, { transform: 'scale(1.15)', opacity: 1, offset: 0.75 }, { transform: 'scale(1)', opacity: 1 } ] } // keyframes can have as many "steps" as you prefer // and you can use the 'offset' key to tune the timing if (action === 'remove') { keyframes = [ { transform: 'scale(1)', opacity: 1 }, { transform: 'scale(1.15)', opacity: 1, offset: 0.33 }, { transform: 'scale(0.75)', opacity: 0.1, offset: 0.5 }, { transform: 'scale(0.5)', opacity: 0 } ] } if (action === 'remain') { // for items that remain, calculate the delta // from their old position to their new position const deltaX = oldCoords.left - newCoords.left const deltaY = oldCoords.top - newCoords.top // use the getTransitionSizes() helper function to // get the old and new widths of the elements const [widthFrom, widthTo, heightFrom, heightTo] = getTransitionSizes(el, oldCoords, newCoords) // set up our steps with our positioning keyframes const start = { transform: \`translate(\${deltaX}px, \${deltaY}px)\` } const mid = { transform: \`translate(\${deltaX * -0.15}px, \${deltaY * -0.15}px)\`, offset: 0.75 } const end = { transform: \`translate(0, 0)\` } // if the dimensions changed, animate them too. if (widthFrom !== widthTo) { start.width = \`\${widthFrom}px\` mid.width = \`\${widthFrom >= widthTo ? widthTo / 1.05 : widthTo * 1.05}px\` end.width = \`\${widthTo}px\` } if (heightFrom !== heightTo) { start.height = \`\${heightFrom}px\` mid.height = \`\${heightFrom >= heightTo ? heightTo / 1.05 : heightTo * 1.05}px\` end.height = \`\${heightTo}px\` } keyframes = [start, mid, end] } // return our KeyframeEffect() and pass // it the chosen keyframes. return new KeyframeEffect(el, keyframes, { duration: 600, easing: 'ease-out' }) })) `, }, } export default pluginMain ================================================ FILE: docs/src/examples/preact/ActualPreactApp.vue ================================================ ================================================ FILE: docs/src/examples/preact/index.ts ================================================ export default { preact: { language: "jsx", ext: "jsx", example: `import { useState } from 'preact/hooks' import { useAutoAnimate } from '@formkit/auto-animate/preact' const App = function () { const [items, setItems] = useState(["🎁", "📦", "🚚", "💪", "🐽", "🐸", "🐻", "🪱", "🪳"]) const [parent] = useAutoAnimate(/* optional config */) function cycle() { items.unshift(items.pop()) setItems(items) } return <>
    {items.map( item =>
  • { item }
  • )}
} export default App`, }, } ================================================ FILE: docs/src/examples/qwik/index.ts ================================================ export default { qwik: { language: "jsx", ext: "jsx", example: `import { useSignal } from '@builder.io/qwik' import { useAutoAnimate } from '@formkit/auto-animate/qwik' const App = function () { const items = useSignal([0, 1, 2]) const [parentRef, enableAnimations$] = useAutoAnimate(/* optional config */) return <>
    {items.value.map( item =>
  • { item }
  • )}
} export default App`, }, } ================================================ FILE: docs/src/examples/react/ActualReactApp.vue ================================================ ================================================ FILE: docs/src/examples/react/index.ts ================================================ export default { react: { language: "jsx", ext: "jsx", example: `import { useState } from 'react' import { useAutoAnimate } from '@formkit/auto-animate/react' const App = function () { const [items, setItems] = useState([0, 1, 2]) const [parent, enableAnimations] = useAutoAnimate(/* optional config */) const add = () => setItems([...items, items.length]) return <>
    {items.map( item =>
  • { item }
  • )}
} export default App`, }, } ================================================ FILE: docs/src/examples/solid/ActualSolidApp.vue ================================================ ================================================ FILE: docs/src/examples/solid/index.ts ================================================ const solidPrimitive = { solid: { language: "tsx", ext: "tsx", example: `import { createSignal, For, Show } from 'solid-js' import { createAutoAnimate } from '@formkit/auto-animate/solid' const App = function () { const [parent, setEnabled] = createAutoAnimate(/* optional config */) const menuItems = ["Home", "Settings", "Logout"] const [isExpanded, setIsExpanded] = createSignal(true) return
    {item =>
  • {item}
  • }
} export default App `, }, } const solidDirective = { solid: { language: "tsx", ext: "tsx", example: `import { createSignal, For, Show } from 'solid-js' import { createAutoAnimateDirective } from '@formkit/auto-animate/solid' const App = function () { const autoAnimate = createAutoAnimateDirective() const menuItems = ["Home", "Settings", "Logout"] const [isExpanded, setIsExpanded] = createSignal(true) return
    {item =>
  • {item}
  • }
} export default App`, }, } export { solidPrimitive, solidDirective } ================================================ FILE: docs/src/examples/svelte/ActualSvelteApp.vue ================================================ ================================================ FILE: docs/src/examples/svelte/index.ts ================================================ export default { svelte: { ext: "svelte", language: "html", example: ` `, }, } ================================================ FILE: docs/src/examples/vue/ActualVueApp.vue ================================================ ================================================ FILE: docs/src/examples/vue/ActualVueAppHook.vue ================================================ ================================================ FILE: docs/src/examples/vue/index.ts ================================================ const vueDirectiveMain = { js: { ext: "ts", language: "typescript", example: `import { createApp } from 'vue' import { autoAnimatePlugin } from '@formkit/auto-animate/vue' import App from 'App.vue' createApp(App).use(autoAnimatePlugin).mount('#app') `, }, nuxt: { language: "typescript", ext: "ts", example: `// nuxt.config.ts export default defineNuxtConfig({ modules: ['@formkit/auto-animate/nuxt'], }) `, }, } const vueDirectiveApp = { vue: { ext: "vue", language: "html", example: ` `, }, } const vueComposable = { vue: { ext: "vue", language: "html", example: ` `, }, } export { vueDirectiveMain, vueDirectiveApp, vueComposable } ================================================ FILE: docs/src/global.d.ts ================================================ interface Window { Prism: any } ================================================ FILE: docs/src/main.ts ================================================ import { ViteSSG } from "vite-ssg" import { plugin, defaultConfig } from "@formkit/vue" import App from "./App.vue" import PageHome from "./pages/PageHome.vue" import type { RouteRecordRaw } from "vue-router" import "../assets/main.css" const routes: RouteRecordRaw[] = [ { path: "/", component: PageHome }, { path: "/lists", component: () => import("./pages/PageList.vue") }, { path: "/tests", component: () => import("./pages/PageTests.vue") }, { path: "/tests-keep-alive", component: () => import("./pages/PageTestKeepAlive.vue"), }, { path: "/bottom-jump-test", component: () => import("./pages/PageBottomJumpTest.vue"), }, { path: "/:catchAll(.*)", redirect: "/", }, ] export const createApp = ViteSSG(App, { routes }, ({ app }) => { app.use(plugin, defaultConfig) }) ================================================ FILE: docs/src/pages/PageBottomJumpTest.vue ================================================ ================================================ FILE: docs/src/pages/PageHome.vue ================================================ ================================================ FILE: docs/src/pages/PageList.vue ================================================ ================================================ FILE: docs/src/pages/PageTestKeepAlive.vue ================================================ ================================================ FILE: docs/src/pages/PageTests.vue ================================================