motionwind-vanilla 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,279 @@
1
+ import {
2
+ VANILLA_CAPABILITIES,
3
+ vanillaAdapter
4
+ } from "./chunk-PXUTG4VI.js";
5
+
6
+ // src/index.ts
7
+ import { animate, hover, press, inView, scroll } from "motion";
8
+ import {
9
+ parseMotionClasses,
10
+ unsupportedCapabilities
11
+ } from "motionwind-core";
12
+
13
+ // src/map.ts
14
+ var RESET_DEFAULTS = {
15
+ scale: 1,
16
+ scaleX: 1,
17
+ scaleY: 1,
18
+ opacity: 1,
19
+ x: 0,
20
+ y: 0,
21
+ z: 0,
22
+ rotate: 0,
23
+ rotateX: 0,
24
+ rotateY: 0,
25
+ skewX: 0,
26
+ skewY: 0
27
+ };
28
+ var OPTION_KEYS = [
29
+ "duration",
30
+ "delay",
31
+ "ease",
32
+ "type",
33
+ "stiffness",
34
+ "damping",
35
+ "mass",
36
+ "bounce",
37
+ "repeat",
38
+ "repeatType",
39
+ "repeatDelay",
40
+ "times"
41
+ ];
42
+ function toAnimateOptions(transition) {
43
+ const opts = {};
44
+ for (const key of OPTION_KEYS) {
45
+ if (transition[key] !== void 0) opts[key] = transition[key];
46
+ }
47
+ return opts;
48
+ }
49
+ function baseValues(parsed) {
50
+ const keys = /* @__PURE__ */ new Set();
51
+ for (const g of [
52
+ parsed.gestures.whileHover,
53
+ parsed.gestures.whileTap,
54
+ parsed.gestures.whileFocus,
55
+ parsed.gestures.whileInView
56
+ ]) {
57
+ if (g) Object.keys(g).forEach((k) => keys.add(k));
58
+ }
59
+ const base = {};
60
+ const enter = parsed.gestures.animate;
61
+ const initial = parsed.gestures.initial;
62
+ for (const k of keys) {
63
+ const v = enter?.[k] ?? initial?.[k] ?? RESET_DEFAULTS[k] ?? 0;
64
+ base[k] = v;
65
+ }
66
+ return base;
67
+ }
68
+ function subset(values, shape) {
69
+ const out = {};
70
+ for (const k of Object.keys(shape)) {
71
+ if (values[k] !== void 0) out[k] = values[k];
72
+ }
73
+ return out;
74
+ }
75
+ function interactiveValues(parsed, state) {
76
+ return {
77
+ ...baseValues(parsed),
78
+ ...state.focused ? parsed.gestures.whileFocus : void 0,
79
+ ...state.hovered ? parsed.gestures.whileHover : void 0,
80
+ ...state.pressed ? parsed.gestures.whileTap : void 0
81
+ };
82
+ }
83
+
84
+ // src/index.ts
85
+ import {
86
+ parseMotionClasses as parseMotionClasses2,
87
+ defineConfig,
88
+ definePreset,
89
+ defineMotionwindPlugin,
90
+ MOTIONWIND_RECIPES
91
+ } from "motionwind-core";
92
+ var anim = animate;
93
+ function prefersReducedMotion() {
94
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
95
+ }
96
+ function resolveGestures(parsed) {
97
+ const { variants, variantState, gestures } = parsed;
98
+ const hasVariants = Object.keys(variants).length > 0;
99
+ return {
100
+ initial: (hasVariants && variantState.initial ? variants[variantState.initial] : void 0) ?? gestures.initial,
101
+ animate: (hasVariants && variantState.animate ? variants[variantState.animate] : void 0) ?? gestures.animate,
102
+ exit: (hasVariants && variantState.exit ? variants[variantState.exit] : void 0) ?? gestures.exit
103
+ };
104
+ }
105
+ function wireElement(el, parsed, reduce) {
106
+ const opts = toAnimateOptions(parsed.transition);
107
+ const base = baseValues(parsed);
108
+ const cleanups = [];
109
+ const resolved = resolveGestures(parsed);
110
+ const whileHover = parsed.gestures.whileHover;
111
+ const whileTap = parsed.gestures.whileTap;
112
+ const whileFocus = parsed.gestures.whileFocus;
113
+ let hovered = false;
114
+ let pressed = false;
115
+ let focused = false;
116
+ const updateInteractive = () => {
117
+ const target = interactiveValues(parsed, { focused, hovered, pressed });
118
+ if (Object.keys(target).length > 0) anim(el, target, opts);
119
+ };
120
+ if (parsed.tailwindClasses) {
121
+ el.setAttribute("class", parsed.tailwindClasses);
122
+ } else {
123
+ el.removeAttribute("class");
124
+ }
125
+ if (reduce) {
126
+ const rest = {
127
+ ...resolved.animate ?? {},
128
+ ...parsed.gestures.whileInView ?? {}
129
+ };
130
+ if (Object.keys(rest).length > 0) anim(el, rest, { duration: 0 });
131
+ return () => {
132
+ };
133
+ }
134
+ if (resolved.initial) anim(el, resolved.initial, { duration: 0 });
135
+ if (resolved.animate) anim(el, resolved.animate, opts);
136
+ const exitValues = resolved.exit;
137
+ if (exitValues && Object.keys(exitValues).length > 0) {
138
+ const handleRemove = () => {
139
+ anim(el, exitValues, {
140
+ ...opts,
141
+ onComplete: () => el.remove()
142
+ });
143
+ };
144
+ el.addEventListener("motionwind:remove", handleRemove);
145
+ cleanups.push(
146
+ () => el.removeEventListener(
147
+ "motionwind:remove",
148
+ handleRemove
149
+ )
150
+ );
151
+ }
152
+ if (whileHover) {
153
+ cleanups.push(
154
+ hover(el, () => {
155
+ hovered = true;
156
+ updateInteractive();
157
+ return () => {
158
+ hovered = false;
159
+ updateInteractive();
160
+ };
161
+ })
162
+ );
163
+ }
164
+ if (whileTap) {
165
+ cleanups.push(
166
+ press(el, () => {
167
+ pressed = true;
168
+ updateInteractive();
169
+ return () => {
170
+ pressed = false;
171
+ updateInteractive();
172
+ };
173
+ })
174
+ );
175
+ }
176
+ if (whileFocus) {
177
+ const onFocus = () => {
178
+ focused = true;
179
+ updateInteractive();
180
+ };
181
+ const onBlur = () => {
182
+ focused = false;
183
+ updateInteractive();
184
+ };
185
+ el.addEventListener("focus", onFocus);
186
+ el.addEventListener("blur", onBlur);
187
+ cleanups.push(() => {
188
+ el.removeEventListener("focus", onFocus);
189
+ el.removeEventListener("blur", onBlur);
190
+ });
191
+ }
192
+ const whileInView = parsed.gestures.whileInView;
193
+ if (whileInView) {
194
+ const viewportOpts = {};
195
+ if (parsed.viewport.amount !== void 0)
196
+ viewportOpts.amount = parsed.viewport.amount;
197
+ if (parsed.viewport.margin !== void 0)
198
+ viewportOpts.margin = parsed.viewport.margin;
199
+ cleanups.push(
200
+ inView(
201
+ el,
202
+ () => {
203
+ anim(el, whileInView, opts);
204
+ if (parsed.viewport.once) return;
205
+ return () => anim(el, subset(base, whileInView), opts);
206
+ },
207
+ viewportOpts
208
+ )
209
+ );
210
+ }
211
+ if (Object.keys(parsed.scroll.values).length > 0) {
212
+ const scrollOpts = parsed.scroll.container ? { axis: parsed.scroll.axis } : { target: el, axis: parsed.scroll.axis, offset: parsed.scroll.offset };
213
+ const stop = scroll(
214
+ anim(el, parsed.scroll.values, { ease: "linear" }),
215
+ scrollOpts
216
+ );
217
+ if (typeof stop === "function") cleanups.push(stop);
218
+ }
219
+ return () => cleanups.forEach((fn) => fn());
220
+ }
221
+ function motionwind(options = {}) {
222
+ const root = options.root ?? (typeof document !== "undefined" ? document : null);
223
+ if (!root) return () => {
224
+ };
225
+ const selector = options.selector ?? '[class*="animate-"]';
226
+ const reduce = (options.respectReducedMotion ?? true) && prefersReducedMotion();
227
+ const cleanups = [];
228
+ const wire = (el) => {
229
+ try {
230
+ const parsed = parseMotionClasses(
231
+ el.getAttribute("class") ?? "",
232
+ options.config
233
+ );
234
+ const unsupported = unsupportedCapabilities(parsed, VANILLA_CAPABILITIES);
235
+ if (unsupported.length && typeof console !== "undefined") {
236
+ console.warn(
237
+ `[motionwind-vanilla] Unsupported capabilities: ${unsupported.join(", ")}.`,
238
+ el
239
+ );
240
+ }
241
+ if (parsed.hasMotion) cleanups.push(wireElement(el, parsed, reduce));
242
+ } catch (err) {
243
+ if (typeof console !== "undefined") {
244
+ console.warn(
245
+ "[motionwind-vanilla] failed to animate an element; skipping it.",
246
+ el,
247
+ err
248
+ );
249
+ }
250
+ }
251
+ };
252
+ root.querySelectorAll(selector).forEach(wire);
253
+ if (options.observe && typeof MutationObserver !== "undefined") {
254
+ const target = root instanceof Document ? root.body ?? root.documentElement : root;
255
+ const observer = new MutationObserver((mutations) => {
256
+ for (const m of mutations) {
257
+ m.addedNodes.forEach((node) => {
258
+ if (!(node instanceof Element)) return;
259
+ if (node.matches(selector)) wire(node);
260
+ node.querySelectorAll(selector).forEach(wire);
261
+ });
262
+ }
263
+ });
264
+ observer.observe(target, { childList: true, subtree: true });
265
+ cleanups.push(() => observer.disconnect());
266
+ }
267
+ return () => cleanups.forEach((fn) => fn());
268
+ }
269
+ export {
270
+ MOTIONWIND_RECIPES,
271
+ VANILLA_CAPABILITIES,
272
+ defineConfig,
273
+ defineMotionwindPlugin,
274
+ definePreset,
275
+ motionwind,
276
+ parseMotionClasses2 as parseMotionClasses,
277
+ vanillaAdapter
278
+ };
279
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/map.ts"],"sourcesContent":["import { animate, hover, press, inView, scroll } from \"motion\";\nimport {\n parseMotionClasses,\n unsupportedCapabilities,\n type MotionwindConfig,\n type ParsedResult,\n type AnimatableValues,\n} from \"motionwind-core\";\nimport {\n toAnimateOptions,\n baseValues,\n interactiveValues,\n subset,\n} from \"./map.js\";\nimport { VANILLA_CAPABILITIES } from \"./adapter.js\";\n\nexport { vanillaAdapter, VANILLA_CAPABILITIES } from \"./adapter.js\";\n\nexport interface MotionwindOptions {\n /** Where to scan for motion elements. Defaults to `document`. */\n root?: ParentNode;\n /** Selector for candidate elements. Defaults to `[class*=\"animate-\"]`. */\n selector?: string;\n /** Honor `prefers-reduced-motion` (jump to final state, no motion). Default true. */\n respectReducedMotion?: boolean;\n /** Watch the DOM and wire elements added after init (SPA/HTMX). Default false. */\n observe?: boolean;\n /** Project tokens, presets, plugins, and strictness. */\n config?: MotionwindConfig;\n}\n\nconst anim = animate as any;\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n );\n}\n\n/**\n * Resolve the initial/animate/exit gesture values for an element, preferring\n * named-variant values from `parsed.variants` when `parsed.variantState`\n * references them, and falling back to the inline gesture values otherwise.\n */\nfunction resolveGestures(parsed: ParsedResult): {\n initial?: AnimatableValues;\n animate?: AnimatableValues;\n exit?: AnimatableValues;\n} {\n const { variants, variantState, gestures } = parsed;\n const hasVariants = Object.keys(variants).length > 0;\n return {\n initial:\n (hasVariants && variantState.initial\n ? variants[variantState.initial]\n : undefined) ?? gestures.initial,\n animate:\n (hasVariants && variantState.animate\n ? variants[variantState.animate]\n : undefined) ?? gestures.animate,\n exit:\n (hasVariants && variantState.exit\n ? variants[variantState.exit]\n : undefined) ?? gestures.exit,\n };\n}\n\n/** Wire a single element's gestures/enter/scroll animations. Returns cleanup. */\nfunction wireElement(\n el: Element,\n parsed: ParsedResult,\n reduce: boolean,\n): () => void {\n const opts = toAnimateOptions(parsed.transition);\n const base = baseValues(parsed);\n const cleanups: Array<() => void> = [];\n const resolved = resolveGestures(parsed);\n const whileHover = parsed.gestures.whileHover;\n const whileTap = parsed.gestures.whileTap;\n const whileFocus = parsed.gestures.whileFocus;\n let hovered = false;\n let pressed = false;\n let focused = false;\n const updateInteractive = () => {\n const target = interactiveValues(parsed, { focused, hovered, pressed });\n if (Object.keys(target).length > 0) anim(el, target, opts);\n };\n\n // Strip animate-* classes; keep the passthrough (Tailwind/util) classes. This\n // also makes re-scans idempotent — a wired element no longer matches the\n // `animate-*` selector.\n if (parsed.tailwindClasses) {\n el.setAttribute(\"class\", parsed.tailwindClasses);\n } else {\n el.removeAttribute(\"class\");\n }\n\n // Reduced motion: jump straight to the final resting/visible state with no\n // animation, and skip all interactive + scroll wiring.\n if (reduce) {\n const rest = {\n ...(resolved.animate ?? {}),\n ...(parsed.gestures.whileInView ?? {}),\n };\n if (Object.keys(rest).length > 0) anim(el, rest, { duration: 0 });\n return () => {};\n }\n\n // Initial state (applied instantly), then enter animation.\n // Use resolved values so that named variants are applied correctly.\n if (resolved.initial) anim(el, resolved.initial, { duration: 0 });\n if (resolved.animate) anim(el, resolved.animate, opts);\n\n // Exit animation: when a consumer dispatches a custom \"motionwind:remove\"\n // event on the element, we play the exit keyframes and remove it afterwards.\n const exitValues = resolved.exit;\n if (exitValues && Object.keys(exitValues).length > 0) {\n const handleRemove = () => {\n anim(el, exitValues, {\n ...opts,\n onComplete: () => el.remove(),\n });\n };\n el.addEventListener(\"motionwind:remove\", handleRemove as EventListener);\n cleanups.push(() =>\n el.removeEventListener(\n \"motionwind:remove\",\n handleRemove as EventListener,\n ),\n );\n }\n\n // Hover\n if (whileHover) {\n cleanups.push(\n hover(el, () => {\n hovered = true;\n updateInteractive();\n return () => {\n hovered = false;\n updateInteractive();\n };\n }),\n );\n }\n\n // Tap / press\n if (whileTap) {\n cleanups.push(\n press(el, () => {\n pressed = true;\n updateInteractive();\n return () => {\n pressed = false;\n updateInteractive();\n };\n }),\n );\n }\n\n // Focus\n if (whileFocus) {\n const onFocus = () => {\n focused = true;\n updateInteractive();\n };\n const onBlur = () => {\n focused = false;\n updateInteractive();\n };\n el.addEventListener(\"focus\", onFocus);\n el.addEventListener(\"blur\", onBlur);\n cleanups.push(() => {\n el.removeEventListener(\"focus\", onFocus);\n el.removeEventListener(\"blur\", onBlur);\n });\n }\n\n // In view\n const whileInView = parsed.gestures.whileInView;\n if (whileInView) {\n const viewportOpts: Record<string, unknown> = {};\n if (parsed.viewport.amount !== undefined)\n viewportOpts.amount = parsed.viewport.amount;\n if (parsed.viewport.margin !== undefined)\n viewportOpts.margin = parsed.viewport.margin;\n cleanups.push(\n inView(\n el,\n () => {\n anim(el, whileInView, opts);\n if (parsed.viewport.once) return;\n return () => anim(el, subset(base, whileInView), opts);\n },\n viewportOpts,\n ),\n );\n }\n\n // Scroll-linked: drive style values from scroll progress.\n if (Object.keys(parsed.scroll.values).length > 0) {\n // Motion's ScrollOptions.offset is a strict string union; our offset is\n // user-provided, so cast the options bag.\n const scrollOpts: any = parsed.scroll.container\n ? { axis: parsed.scroll.axis }\n : { target: el, axis: parsed.scroll.axis, offset: parsed.scroll.offset };\n const stop = scroll(\n anim(el, parsed.scroll.values, { ease: \"linear\" }),\n scrollOpts,\n );\n if (typeof stop === \"function\") cleanups.push(stop);\n }\n\n return () => cleanups.forEach((fn) => fn());\n}\n\n/**\n * Scan the DOM for elements with `animate-*` classes and wire up their\n * animations using the vanilla Motion API. Returns a cleanup function.\n *\n * Supports: initial/enter, hover, tap, focus, in-view, scroll-linked, named\n * variants (resolved at wire-up time), and exit animations (triggered by\n * dispatching a `\"motionwind:remove\"` custom event on the element).\n * Honors `prefers-reduced-motion`, is idempotent across re-runs, and can watch\n * for dynamically-added elements via `{ observe: true }`.\n * (drag and layout are React/Vue-only.)\n *\n * @example\n * ```js\n * import { motionwind } from \"motionwind-vanilla\";\n * const stop = motionwind({ observe: true });\n * ```\n */\nexport function motionwind(options: MotionwindOptions = {}): () => void {\n const root =\n options.root ?? (typeof document !== \"undefined\" ? document : null);\n if (!root) return () => {};\n\n const selector = options.selector ?? '[class*=\"animate-\"]';\n const reduce =\n (options.respectReducedMotion ?? true) && prefersReducedMotion();\n const cleanups: Array<() => void> = [];\n\n const wire = (el: Element) => {\n try {\n // SVGElement.className is SVGAnimatedString rather than a string, so the\n // attribute is the portable source for both HTML and SVG elements.\n const parsed = parseMotionClasses(\n el.getAttribute(\"class\") ?? \"\",\n options.config,\n );\n const unsupported = unsupportedCapabilities(parsed, VANILLA_CAPABILITIES);\n if (unsupported.length && typeof console !== \"undefined\") {\n console.warn(\n `[motionwind-vanilla] Unsupported capabilities: ${unsupported.join(\", \")}.`,\n el,\n );\n }\n if (parsed.hasMotion) cleanups.push(wireElement(el, parsed, reduce));\n } catch (err) {\n // A single malformed element/class must never break the whole page.\n if (typeof console !== \"undefined\") {\n console.warn(\n \"[motionwind-vanilla] failed to animate an element; skipping it.\",\n el,\n err,\n );\n }\n }\n };\n\n root.querySelectorAll<Element>(selector).forEach(wire);\n\n if (options.observe && typeof MutationObserver !== \"undefined\") {\n const target =\n root instanceof Document ? (root.body ?? root.documentElement) : root;\n const observer = new MutationObserver((mutations) => {\n for (const m of mutations) {\n m.addedNodes.forEach((node) => {\n if (!(node instanceof Element)) return;\n if (node.matches(selector)) wire(node);\n node.querySelectorAll<Element>(selector).forEach(wire);\n });\n }\n });\n observer.observe(target as Node, { childList: true, subtree: true });\n cleanups.push(() => observer.disconnect());\n }\n\n return () => cleanups.forEach((fn) => fn());\n}\n\nexport {\n parseMotionClasses,\n defineConfig,\n definePreset,\n defineMotionwindPlugin,\n MOTIONWIND_RECIPES,\n} from \"motionwind-core\";\nexport type { ParsedResult, MotionwindConfig } from \"motionwind-core\";\n","import type {\n AnimatableValues,\n ParsedResult,\n TransitionConfig,\n} from \"motionwind-core\";\n\n/** Resting values used to animate back after a gesture ends. */\nconst RESET_DEFAULTS: Record<string, number | string> = {\n scale: 1,\n scaleX: 1,\n scaleY: 1,\n opacity: 1,\n x: 0,\n y: 0,\n z: 0,\n rotate: 0,\n rotateX: 0,\n rotateY: 0,\n skewX: 0,\n skewY: 0,\n};\n\n/** Transition keys that apply to a single vanilla `animate()` call. */\nconst OPTION_KEYS: (keyof TransitionConfig)[] = [\n \"duration\",\n \"delay\",\n \"ease\",\n \"type\",\n \"stiffness\",\n \"damping\",\n \"mass\",\n \"bounce\",\n \"repeat\",\n \"repeatType\",\n \"repeatDelay\",\n \"times\",\n];\n\n/** Project our TransitionConfig onto vanilla Motion's animate() options. */\nexport function toAnimateOptions(\n transition: TransitionConfig,\n): Record<string, unknown> {\n const opts: Record<string, unknown> = {};\n for (const key of OPTION_KEYS) {\n if (transition[key] !== undefined) opts[key] = transition[key];\n }\n return opts;\n}\n\n/**\n * Build the resting values to animate back to when a gesture (hover/tap/focus)\n * ends. Prefers the enter (`animate`) value, then `initial`, then a sensible\n * default, for each key the gestures touch.\n */\nexport function baseValues(parsed: ParsedResult): AnimatableValues {\n const keys = new Set<string>();\n for (const g of [\n parsed.gestures.whileHover,\n parsed.gestures.whileTap,\n parsed.gestures.whileFocus,\n parsed.gestures.whileInView,\n ]) {\n if (g) Object.keys(g).forEach((k) => keys.add(k));\n }\n\n const base: AnimatableValues = {};\n const enter = parsed.gestures.animate;\n const initial = parsed.gestures.initial;\n for (const k of keys) {\n const v =\n (enter as Record<string, AnimatableValues[string]> | undefined)?.[k] ??\n (initial as Record<string, AnimatableValues[string]> | undefined)?.[k] ??\n RESET_DEFAULTS[k] ??\n 0;\n base[k] = v;\n }\n return base;\n}\n\n/** Pick a subset of `values` limited to the keys present in `shape`. */\nexport function subset(\n values: AnimatableValues,\n shape: AnimatableValues,\n): AnimatableValues {\n const out: AnimatableValues = {};\n for (const k of Object.keys(shape)) {\n if (values[k] !== undefined) out[k] = values[k]!;\n }\n return out;\n}\n\n/** Merge concurrent gesture states using Motion's interaction priority. */\nexport function interactiveValues(\n parsed: ParsedResult,\n state: { focused: boolean; hovered: boolean; pressed: boolean },\n): AnimatableValues {\n return {\n ...baseValues(parsed),\n ...(state.focused ? parsed.gestures.whileFocus : undefined),\n ...(state.hovered ? parsed.gestures.whileHover : undefined),\n ...(state.pressed ? parsed.gestures.whileTap : undefined),\n };\n}\n"],"mappings":"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","names":["parseMotionClasses"]}
package/llms.txt ADDED
@@ -0,0 +1,38 @@
1
+ # motionwind-vanilla v2.0.0 — machine reference
2
+
3
+ Stable browser DOM adapter backed by Motion and motionwind-core.
4
+
5
+ Install:
6
+ npm install motionwind-vanilla@2 motion motionwind-core@2
7
+
8
+ ```js
9
+ import { motionwind } from "motionwind-vanilla";
10
+
11
+ const stop = motionwind({
12
+ root: document,
13
+ selector: '[class*="animate-"]',
14
+ observe: true,
15
+ respectReducedMotion: true,
16
+ config,
17
+ });
18
+ ```
19
+
20
+ The return value removes listeners/observers. The self-contained CDN bundle at
21
+ https://unpkg.com/motionwind-vanilla@2 initializes automatically.
22
+
23
+ Supported: initial/enter, hover, press/tap, focus, in-view, continuous scroll,
24
+ SVG path values, reduced motion, HTML/SVG class attributes, and observed DOM
25
+ insertions.
26
+
27
+ Reduced motion jumps to the resting/visible state and does not wire interactive
28
+ or scroll behavior. Interaction priority is press, then hover, then focus, then
29
+ the base state.
30
+
31
+ Not supported: drag, layout projection, exit orchestration, and variant
32
+ propagation. These require a component runtime and produce capability warnings.
33
+
34
+ The adapter strips recognized animate-* tokens after wiring while preserving
35
+ ordinary classes. Re-scanning is idempotent.
36
+
37
+ Use motionwind-core's registry and parser diagnostics; do not maintain a second
38
+ syntax list.
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "motionwind-vanilla",
3
+ "version": "2.1.0",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "description": "Write Motion animations as Tailwind-like classes in plain HTML/JS — scans the DOM and wires animations via the vanilla Motion API.",
7
+ "author": "piyush555",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/piyushzingade/motionwind.git",
12
+ "directory": "packages/motionwind-vanilla"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/piyushzingade/motionwind/issues"
16
+ },
17
+ "homepage": "https://github.com/piyushzingade/motionwind#readme",
18
+ "keywords": [
19
+ "motion",
20
+ "animation",
21
+ "tailwind",
22
+ "vanilla",
23
+ "cdn",
24
+ "motionwind"
25
+ ],
26
+ "exports": {
27
+ ".": {
28
+ "import": "./dist/index.js",
29
+ "require": "./dist/index.cjs"
30
+ },
31
+ "./adapter": {
32
+ "import": "./dist/adapter.js",
33
+ "require": "./dist/adapter.cjs"
34
+ }
35
+ },
36
+ "main": "./dist/index.cjs",
37
+ "module": "./dist/index.js",
38
+ "types": "./dist/index.d.ts",
39
+ "typesVersions": {
40
+ "*": {
41
+ "adapter": [
42
+ "./dist/adapter.d.ts"
43
+ ]
44
+ }
45
+ },
46
+ "unpkg": "./dist/cdn/motionwind.global.js",
47
+ "jsdelivr": "./dist/cdn/motionwind.global.js",
48
+ "files": [
49
+ "dist",
50
+ "llms.txt"
51
+ ],
52
+ "scripts": {
53
+ "build": "tsup",
54
+ "dev": "tsup --watch",
55
+ "test": "vitest run",
56
+ "test:watch": "vitest",
57
+ "lint": "eslint --max-warnings 0",
58
+ "check-types": "tsc --noEmit"
59
+ },
60
+ "peerDependencies": {
61
+ "motion": "^11.0.0 || ^12.0.0 || ^13.0.0"
62
+ },
63
+ "dependencies": {
64
+ "motionwind-core": "^2.1.0"
65
+ },
66
+ "devDependencies": {
67
+ "@repo/eslint-config": "*",
68
+ "@repo/typescript-config": "*",
69
+ "eslint": "^9.39.1",
70
+ "motion": "^13.4.0",
71
+ "tsup": "^8.5.0",
72
+ "typescript": "5.9.2",
73
+ "vitest": "^3.2.1"
74
+ },
75
+ "publishConfig": {
76
+ "access": "public"
77
+ }
78
+ }