@humanspeak/svelte-motion 0.0.11 → 0.0.13

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/README.md CHANGED
@@ -14,70 +14,13 @@
14
14
 
15
15
  ## Why are we here?
16
16
 
17
- Just a little wrapper for motion. I love their work! The typical this is a WIP, if you have issues please give me a react example working so that I can work to ensure its running properly 😍
17
+ Motion vibes, Svelte runes. This brings Motion’s declarative animation goodness to Svelte with `motion.<tag>` components, interaction props, and composable config. If you spot a cool React example, drop it in an issue—we’ll port it. 😍
18
+
19
+ Requests welcome: Have a feature/prop/example you want? Please open an issue (ideally include a working Motion/React snippet or example link) and we’ll prioritize it.
18
20
 
19
21
  ## Supported Elements
20
22
 
21
- ### Regular Elements
22
-
23
- - `motion.a`
24
- - `motion.article`
25
- - `motion.aside`
26
- - `motion.blockquote`
27
- - `motion.button`
28
- - `motion.code`
29
- - `motion.dd`
30
- - `motion.div`
31
- - `motion.dl`
32
- - `motion.dt`
33
- - `motion.fieldset`
34
- - `motion.figcaption`
35
- - `motion.figure`
36
- - `motion.footer`
37
- - `motion.form`
38
- - `motion.h1`
39
- - `motion.h2`
40
- - `motion.h3`
41
- - `motion.h4`
42
- - `motion.h5`
43
- - `motion.h6`
44
- - `motion.header`
45
- - `motion.label`
46
- - `motion.legend`
47
- - `motion.li`
48
- - `motion.main`
49
- - `motion.nav`
50
- - `motion.ol`
51
- - `motion.option`
52
- - `motion.p`
53
- - `motion.pre`
54
- - `motion.section`
55
- - `motion.select`
56
- - `motion.span`
57
- - `motion.table`
58
- - `motion.tbody`
59
- - `motion.td`
60
- - `motion.textarea`
61
- - `motion.tfoot`
62
- - `motion.th`
63
- - `motion.thead`
64
- - `motion.tr`
65
- - `motion.ul`
66
-
67
- ### Void Elements
68
-
69
- - `motion.area`
70
- - `motion.base`
71
- - `motion.br`
72
- - `motion.col`
73
- - `motion.embed`
74
- - `motion.hr`
75
- - `motion.img`
76
- - `motion.input`
77
- - `motion.param`
78
- - `motion.source`
79
- - `motion.track`
80
- - `motion.wbr`
23
+ All standard HTML elements are supported as motion components (e.g., `motion.div`, `motion.button`). See the full set in `src/lib/html/`.
81
24
 
82
25
  ## Configuration
83
26
 
@@ -100,6 +43,7 @@ Some Motion features are not yet implemented:
100
43
  - `features` configuration
101
44
  - Performance optimizations like `transformPagePoint`
102
45
  - Advanced transition controls
46
+ - `layout`/`layoutId` (FLIP) — prototype planned
103
47
 
104
48
  We're actively working on adding these features. Check our GitHub issues for progress updates or to contribute.
105
49
 
@@ -117,10 +61,12 @@ This package carefully selects its dependencies to provide a robust and maintain
117
61
 
118
62
  ### Examples
119
63
 
120
- | Motion | REPL |
121
- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
122
- | [React - Enter Animation](https://examples.motion.dev/react/enter-animation) | [View Example](https://svelte.dev/playground/7f60c347729f4ea48b1a4590c9dedc02?version=5.20.2) |
123
- | [Random - Shiny Button](https://www.youtube.com/watch?v=jcpLprT5F0I) by [@verse\_](https://x.com/verse_) | [View Example](https://svelte.dev/playground/96f9e0bf624f4396adaf06c519147450?version=5.20.2) |
64
+ | Motion | Demo / Route | REPL |
65
+ | -------------------------------------------------------------------------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------- |
66
+ | [React - Enter Animation](https://examples.motion.dev/react/enter-animation) | `/tests/motion/enter-animation` | [View Example](https://svelte.dev/playground/7f60c347729f4ea48b1a4590c9dedc02?version=5.20.2) |
67
+ | HTML Content (0→100 counter) | `/tests/motion/html-content` | [View Example](https://svelte.dev/playground/31cd72df4a3242b4b4589501a25e774f?version=5.38.10) |
68
+ | [Random - Shiny Button](https://www.youtube.com/watch?v=jcpLprT5F0I) by [@verse\_](https://x.com/verse_) | `/tests/random/shiny-button` | [View Example](https://svelte.dev/playground/96f9e0bf624f4396adaf06c519147450?version=5.38.10) |
69
+ | [Fancy Like Button](https://github.com/DRlFTER/fancyLikeButton) | `/tests/random/fancy-like-button` | [View Example](https://svelte.dev/playground/c34b7e53d41c48b0ab1eaf21ca120c6e?version=5.38.10) |
124
70
 
125
71
  ## License
126
72
 
@@ -128,4 +74,4 @@ MIT © [Humanspeak, Inc.](LICENSE)
128
74
 
129
75
  ## Credits
130
76
 
131
- Made with by [Humanspeak](https://humanspeak.com)
77
+ Made with ❤️ by [Humanspeak](https://humanspeak.com)
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { getMotionConfig } from '../components/motionConfig.context.js'
3
- import type { MotionProps } from '../types.js'
4
- import { getCommonKeys, isNotEmpty } from '../utils/objects.js'
3
+ import type { MotionProps, MotionTransition } from '../types.js'
4
+ import { isNotEmpty } from '../utils/objects.js'
5
5
  import { sleep } from '../utils/testing.js'
6
- import { animate, press } from 'motion'
6
+ import { animate } from 'motion'
7
7
  import { type Snippet } from 'svelte'
8
8
  import type { SvelteHTMLElements } from 'svelte/elements'
9
9
 
@@ -19,6 +19,8 @@
19
19
  initial: initialProp,
20
20
  animate: animateProp,
21
21
  transition: transitionProp,
22
+ onAnimationStart: onAnimationStartProp,
23
+ onAnimationComplete: onAnimationCompleteProp,
22
24
  style: styleProp,
23
25
  class: classProp,
24
26
  whileTap: whileTapProp,
@@ -32,75 +34,141 @@
32
34
  typeof window !== 'undefined' &&
33
35
  window.location.search.includes('@humanspeak-svelte-motion-isPlaywright=true')
34
36
 
35
- $effect(() => {
36
- transitionProp = {
37
- ...(motionConfig?.transition ?? {}),
38
- ...(transitionProp ?? {})
39
- }
37
+ // Compute merged transition without mutating props to avoid effect write loops
38
+ let mergedTransition = $derived<MotionTransition>({
39
+ ...(motionConfig?.transition ?? {}),
40
+ ...(transitionProp ?? {})
40
41
  })
41
42
 
43
+ // Type guards for animate return types
44
+ function isPromiseLike(value: unknown): value is Promise<unknown> {
45
+ return (
46
+ typeof value === 'object' &&
47
+ value !== null &&
48
+ 'then' in (value as { then?: unknown }) &&
49
+ typeof (value as { then?: unknown }).then === 'function'
50
+ )
51
+ }
52
+ type WithFinished = { finished?: Promise<unknown> }
53
+ function hasFinishedPromise(value: unknown): value is WithFinished {
54
+ return (
55
+ typeof value === 'object' &&
56
+ value !== null &&
57
+ 'finished' in (value as { finished?: unknown }) &&
58
+ isPromiseLike((value as { finished?: unknown }).finished)
59
+ )
60
+ }
61
+
42
62
  const runAnimation = () => {
43
63
  if (!element || !animateProp) return
44
- const transitionAmimate = {
45
- ...(transitionProp ?? {})
64
+ const transitionAmimate: MotionTransition = mergedTransition ?? {}
65
+ // Fire lifecycle callbacks for main animate transitions
66
+ const payload = $state.snapshot(animateProp)
67
+ onAnimationStartProp?.(payload)
68
+ const controls = animate(element, payload, transitionAmimate)
69
+ // controls may be a promise-like or have a finished promise depending on engine
70
+ if (hasFinishedPromise(controls)) {
71
+ controls.finished?.then(() => onAnimationCompleteProp?.(payload)).catch(() => {})
72
+ } else if (isPromiseLike(controls as unknown)) {
73
+ ;(controls as unknown as Promise<unknown>)
74
+ .then(() => onAnimationCompleteProp?.(payload))
75
+ .catch(() => {})
46
76
  }
47
- animate(element, animateProp, transitionAmimate)
48
77
  }
49
78
 
79
+ // Merge style for before/after ready so styles carry through post-anim
80
+ // Merge styles directly in markup; keep effect solely for readiness logic
81
+
82
+ // whileTap handling without relying on motion.press (fallback compatible)
50
83
  $effect(() => {
51
- if (element && isLoaded === 'ready') {
52
- if (isNotEmpty(whileTapProp)) {
53
- press(element, (element: Element) => {
54
- animate(element, whileTapProp!)
55
- return () => {
56
- if (isNotEmpty(initialProp)) {
57
- const commonProps = getCommonKeys(initialProp!, whileTapProp!)
58
- const resetProps = Object.fromEntries(
59
- commonProps.map((key) => [key, initialProp![key]])
60
- )
61
- animate(element, resetProps)
62
- }
63
- }
64
- })
84
+ if (!(element && isLoaded === 'ready' && isNotEmpty(whileTapProp))) return
85
+
86
+ const handlePointerDown = () => {
87
+ animate(element!, whileTapProp!)
88
+ }
89
+ const handlePointerUp = () => {
90
+ // Build reset record preferring animateProp values, falling back to initialProp
91
+ if (isNotEmpty(whileTapProp) && (isNotEmpty(initialProp) || isNotEmpty(animateProp))) {
92
+ const initialRecord = (initialProp ?? {}) as Record<string, unknown>
93
+ const animateRecord = (animateProp ?? {}) as Record<string, unknown>
94
+ const whileTapRecord = (whileTapProp ?? {}) as Record<string, unknown>
95
+
96
+ const keys = new Set<string>([
97
+ ...Object.keys(initialRecord),
98
+ ...Object.keys(animateRecord)
99
+ ])
100
+ const overlappingKeys: string[] = []
101
+ for (const k of keys) if (k in whileTapRecord) overlappingKeys.push(k)
102
+
103
+ const resetRecord: Record<string, unknown> = {}
104
+ for (const k of overlappingKeys) {
105
+ resetRecord[k] = Object.prototype.hasOwnProperty.call(animateRecord, k)
106
+ ? animateRecord[k]
107
+ : initialRecord[k]
108
+ }
109
+ if (Object.keys(resetRecord).length > 0) {
110
+ animate(
111
+ element!,
112
+ resetRecord as unknown as import('motion').DOMKeyframesDefinition
113
+ )
114
+ }
65
115
  }
66
116
  }
117
+
118
+ element.addEventListener('pointerdown', handlePointerDown)
119
+ element.addEventListener('pointerup', handlePointerUp)
120
+ element.addEventListener('pointercancel', handlePointerUp)
121
+
122
+ return () => {
123
+ element?.removeEventListener('pointerdown', handlePointerDown)
124
+ element?.removeEventListener('pointerup', handlePointerUp)
125
+ element?.removeEventListener('pointercancel', handlePointerUp)
126
+ }
67
127
  })
68
128
 
129
+ // Re-run animate when animateProp changes while ready
69
130
  $effect(() => {
70
- if (element) {
71
- if (animateProp) {
72
- if (isNotEmpty(initialProp)) {
73
- // Set initial state immediately
74
- isLoaded = 'initial'
75
- dataPath = 1
76
- // Give time for initial render
77
- setTimeout(async () => {
78
- await animate(element!, initialProp!)
79
- if (isPlaywright) {
80
- await sleep(250)
81
- }
82
- isLoaded = 'ready'
83
- runAnimation()
84
- }, 5)
85
- } else {
86
- dataPath = 2
87
- isLoaded = 'ready'
88
- runAnimation()
89
- }
90
- } else if (isNotEmpty(initialProp)) {
91
- dataPath = 3
131
+ if (element && isLoaded === 'ready' && isNotEmpty(animateProp)) {
132
+ runAnimation()
133
+ }
134
+ })
135
+
136
+ $effect(() => {
137
+ if (!(element && isLoaded === 'mounting')) return
138
+ if (animateProp) {
139
+ if (isNotEmpty(initialProp)) {
140
+ // Apply initial instantly BEFORE exposing 'initial' state
141
+ animate(element!, initialProp!, { duration: 0 })
142
+ // Mark initial after styles are applied so tests read CSS=0 while state=initial
92
143
  isLoaded = 'initial'
93
- setTimeout(async () => {
94
- await animate(element!, initialProp!)
144
+ dataPath = 1
145
+ // Then promote to ready and run the enter animation
146
+ requestAnimationFrame(async () => {
95
147
  if (isPlaywright) {
96
- await sleep(250)
148
+ await sleep(10)
97
149
  }
98
150
  isLoaded = 'ready'
99
- }, 5)
151
+ runAnimation()
152
+ })
100
153
  } else {
101
- dataPath = 4
154
+ dataPath = 2
102
155
  isLoaded = 'ready'
156
+ runAnimation()
103
157
  }
158
+ } else if (isNotEmpty(initialProp)) {
159
+ // Apply initial instantly BEFORE exposing 'initial' state
160
+ animate(element!, initialProp!, { duration: 0 })
161
+ dataPath = 3
162
+ isLoaded = 'initial'
163
+ requestAnimationFrame(async () => {
164
+ if (isPlaywright) {
165
+ await sleep(10)
166
+ }
167
+ isLoaded = 'ready'
168
+ })
169
+ } else {
170
+ dataPath = 4
171
+ isLoaded = 'ready'
104
172
  }
105
173
  })
106
174
  </script>
@@ -109,11 +177,11 @@
109
177
  this={tag}
110
178
  bind:this={element}
111
179
  {...rest}
112
- data-playwright={isPlaywright}
180
+ data-playwright={isPlaywright ? isPlaywright : undefined}
113
181
  data-is-loaded={isPlaywright ? isLoaded : undefined}
114
182
  data-path={isPlaywright ? dataPath : undefined}
115
- style={isLoaded === 'ready' ? `${styleProp} ${element?.style.cssText}` : undefined}
116
- class={isLoaded === 'ready' ? classProp : undefined}
183
+ style={styleProp}
184
+ class={classProp}
117
185
  >
118
186
  {#if isLoaded === 'ready'}
119
187
  {@render children?.()}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import MotionConfig from './components/MotionConfig.svelte';
2
2
  import type { MotionComponents } from './html/index.js';
3
3
  export declare const motion: MotionComponents;
4
+ export { animate } from 'motion';
4
5
  export type { MotionAnimate, MotionInitial, MotionTransition, MotionWhileTap } from './types.js';
5
6
  export { MotionConfig };
package/dist/index.js CHANGED
@@ -2,4 +2,6 @@ import MotionConfig from './components/MotionConfig.svelte';
2
2
  import * as html from './html/index.js';
3
3
  // Create the motion object with all components
4
4
  export const motion = Object.fromEntries(Object.entries(html).map(([key, component]) => [key.toLowerCase(), component]));
5
+ // Export all types
6
+ export { animate } from 'motion';
5
7
  export { MotionConfig };
package/dist/types.d.ts CHANGED
@@ -41,6 +41,11 @@ export type MotionTransition = AnimationOptions | undefined;
41
41
  * ```
42
42
  */
43
43
  export type MotionWhileTap = DOMKeyframesDefinition | undefined;
44
+ /**
45
+ * Animation lifecycle callbacks for motion components.
46
+ */
47
+ export type MotionAnimationStart = ((definition: DOMKeyframesDefinition | undefined) => void) | undefined;
48
+ export type MotionAnimationComplete = ((definition: DOMKeyframesDefinition | undefined) => void) | undefined;
44
49
  /**
45
50
  * Base motion props shared by all motion components.
46
51
  */
@@ -53,6 +58,10 @@ export type MotionProps = {
53
58
  transition?: MotionTransition;
54
59
  /** Tap/click interaction animation */
55
60
  whileTap?: MotionWhileTap;
61
+ /** Called right before a main animate transition starts */
62
+ onAnimationStart?: MotionAnimationStart;
63
+ /** Called after a main animate transition completes */
64
+ onAnimationComplete?: MotionAnimationComplete;
56
65
  /** Inline styles */
57
66
  style?: string;
58
67
  /** CSS classes */
package/package.json CHANGED
@@ -1,136 +1,138 @@
1
1
  {
2
- "name": "@humanspeak/svelte-motion",
3
- "version": "0.0.11",
4
- "description": "A lightweight animation library for Svelte 5 that provides smooth, hardware-accelerated animations. Features include spring physics, custom easing, and fluid transitions. Built on top of the motion library, it offers a simple API for creating complex animations with minimal code. Perfect for interactive UIs, micro-interactions, and engaging user experiences.",
5
- "keywords": [
6
- "svelte",
7
- "animation",
8
- "motion",
9
- "transitions",
10
- "spring-physics",
11
- "ui-animation",
12
- "svelte5",
13
- "hardware-accelerated",
14
- "micro-interactions",
15
- "performance"
16
- ],
17
- "bugs": {
18
- "url": "https://github.com/humanspeak/svelte-motion/issues"
19
- },
20
- "repository": {
21
- "type": "git",
22
- "url": "git+https://github.com/humanspeak/svelte-motion.git"
23
- },
24
- "funding": {
25
- "type": "github",
26
- "url": "https://github.com/sponsors/humanspeak"
27
- },
28
- "license": "MIT",
29
- "author": "Humanspeak, Inc.",
30
- "sideEffects": [
31
- "**/*.css"
32
- ],
33
- "type": "module",
34
- "exports": {
35
- ".": {
36
- "types": "./dist/index.d.ts",
37
- "svelte": "./dist/index.js"
38
- }
39
- },
40
- "svelte": "./dist/index.js",
41
- "types": "./dist/index.d.ts",
42
- "files": [
43
- "dist",
44
- "!dist/**/*.test.*",
45
- "!dist/**/*.spec.*",
46
- "!dist/lib/html/*.template"
47
- ],
48
- "scripts": {
49
- "build": "vite build && npm run package",
50
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
51
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
52
- "dev": "vite dev",
53
- "format": "prettier --write .",
54
- "generate": "tsx scripts/generate-html.ts",
55
- "lint": "prettier --check . && eslint .",
56
- "lint:fix": "npm run format && eslint . --fix",
57
- "package": "svelte-kit sync && svelte-package && publint",
58
- "prepublishOnly": "npm run package",
59
- "preview": "vite preview",
60
- "test": "vitest run --coverage",
61
- "test:all": "npm run test && npm run test:e2e",
62
- "test:e2e": "playwright test",
63
- "test:e2e:debug": "playwright test --debug",
64
- "test:e2e:report": "playwright show-report",
65
- "test:e2e:ui": "playwright test --ui",
66
- "test:only": "vitest run",
67
- "test:watch": "vitest"
68
- },
69
- "dependencies": {
70
- "motion": "^12.4.10"
71
- },
72
- "devDependencies": {
73
- "@eslint/compat": "^1.2.7",
74
- "@eslint/js": "^9.21.0",
75
- "@playwright/test": "^1.50.1",
76
- "@sveltejs/adapter-auto": "^4.0.0",
77
- "@sveltejs/kit": "^2.17.3",
78
- "@sveltejs/package": "^2.3.10",
79
- "@sveltejs/vite-plugin-svelte": "^5.0.3",
80
- "@tailwindcss/aspect-ratio": "^0.4.2",
81
- "@tailwindcss/container-queries": "^0.1.1",
82
- "@tailwindcss/forms": "^0.5.10",
83
- "@tailwindcss/postcss": "^4.0.9",
84
- "@tailwindcss/typography": "^0.5.16",
85
- "@testing-library/jest-dom": "^6.6.3",
86
- "@testing-library/svelte": "^5.2.7",
87
- "@types/node": "^22.13.9",
88
- "@vitest/coverage-v8": "^3.0.7",
89
- "eslint": "^9.21.0",
90
- "eslint-config-prettier": "^10.0.2",
91
- "eslint-plugin-svelte": "^3.0.2",
92
- "globals": "^16.0.0",
93
- "jsdom": "^26.0.0",
94
- "prettier": "^3.5.3",
95
- "prettier-plugin-organize-imports": "^4.1.0",
96
- "prettier-plugin-svelte": "^3.3.3",
97
- "prettier-plugin-tailwindcss": "^0.6.11",
98
- "publint": "^0.3.8",
99
- "svelte": "^5.21.0",
100
- "svelte-check": "^4.1.4",
101
- "tailwind-merge": "^3.0.2",
102
- "tailwind-variants": "^0.3.1",
103
- "tailwindcss": "^4.0.9",
104
- "tailwindcss-animate": "^1.0.7",
105
- "tsx": "^4.19.3",
106
- "typescript": "^5.8.2",
107
- "typescript-eslint": "^8.26.0",
108
- "vite": "^6.2.0",
109
- "vitest": "^3.0.7"
110
- },
111
- "peerDependencies": {
112
- "svelte": "^5.0.0"
113
- },
114
- "volta": {
115
- "node": "22.14.0"
116
- },
117
- "publishConfig": {
118
- "access": "public"
119
- },
120
- "overrides": {
121
- "@sveltejs/kit": {
122
- "cookie": "^0.7.0"
123
- }
124
- },
125
- "tags": [
126
- "svelte",
127
- "animation",
128
- "motion",
129
- "transitions",
130
- "spring-physics",
131
- "performance",
132
- "ui-animation",
133
- "micro-interactions",
134
- "svelte5"
135
- ]
136
- }
2
+ "name": "@humanspeak/svelte-motion",
3
+ "version": "0.0.13",
4
+ "description": "A lightweight animation library for Svelte 5 that provides smooth, hardware-accelerated animations. Features include spring physics, custom easing, and fluid transitions. Built on top of the motion library, it offers a simple API for creating complex animations with minimal code. Perfect for interactive UIs, micro-interactions, and engaging user experiences.",
5
+ "keywords": [
6
+ "svelte",
7
+ "animation",
8
+ "motion",
9
+ "transitions",
10
+ "spring-physics",
11
+ "ui-animation",
12
+ "svelte5",
13
+ "hardware-accelerated",
14
+ "micro-interactions",
15
+ "performance"
16
+ ],
17
+ "bugs": {
18
+ "url": "https://github.com/humanspeak/svelte-motion/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/humanspeak/svelte-motion.git"
23
+ },
24
+ "funding": {
25
+ "type": "github",
26
+ "url": "https://github.com/sponsors/humanspeak"
27
+ },
28
+ "license": "MIT",
29
+ "author": "Humanspeak, Inc.",
30
+ "sideEffects": [
31
+ "**/*.css"
32
+ ],
33
+ "type": "module",
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/index.d.ts",
37
+ "svelte": "./dist/index.js"
38
+ }
39
+ },
40
+ "svelte": "./dist/index.js",
41
+ "types": "./dist/index.d.ts",
42
+ "files": [
43
+ "dist",
44
+ "!dist/**/*.test.*",
45
+ "!dist/**/*.spec.*",
46
+ "!dist/lib/html/*.template"
47
+ ],
48
+ "overrides": {
49
+ "@sveltejs/kit": {
50
+ "cookie": "^0.7.0"
51
+ }
52
+ },
53
+ "dependencies": {
54
+ "motion": "^12.23.13"
55
+ },
56
+ "devDependencies": {
57
+ "@eslint/compat": "^1.3.2",
58
+ "@eslint/js": "^9.35.0",
59
+ "@playwright/test": "^1.55.0",
60
+ "@sveltejs/adapter-auto": "^6.1.0",
61
+ "@sveltejs/kit": "^2.41.0",
62
+ "@sveltejs/package": "^2.5.2",
63
+ "@sveltejs/vite-plugin-svelte": "^6.2.0",
64
+ "@tailwindcss/aspect-ratio": "^0.4.2",
65
+ "@tailwindcss/container-queries": "^0.1.1",
66
+ "@tailwindcss/forms": "^0.5.10",
67
+ "@tailwindcss/postcss": "^4.1.13",
68
+ "@tailwindcss/typography": "^0.5.16",
69
+ "@testing-library/jest-dom": "^6.8.0",
70
+ "@testing-library/svelte": "^5.2.8",
71
+ "@types/node": "^22.13.14",
72
+ "@vitest/coverage-v8": "^3.2.4",
73
+ "eslint": "^9.35.0",
74
+ "eslint-config-prettier": "^10.1.8",
75
+ "eslint-plugin-svelte": "^3.12.3",
76
+ "globals": "^16.4.0",
77
+ "husky": "^9.1.7",
78
+ "jsdom": "^27.0.0",
79
+ "prettier": "^3.6.2",
80
+ "prettier-plugin-organize-imports": "^4.2.0",
81
+ "prettier-plugin-svelte": "^3.4.0",
82
+ "prettier-plugin-tailwindcss": "^0.6.14",
83
+ "publint": "^0.3.12",
84
+ "svelte": "^5.38.10",
85
+ "svelte-check": "^4.3.1",
86
+ "tailwind-merge": "^3.3.1",
87
+ "tailwind-variants": "^3.1.1",
88
+ "tailwindcss": "^4.1.13",
89
+ "tailwindcss-animate": "^1.0.7",
90
+ "tsx": "^4.20.5",
91
+ "typescript": "^5.9.2",
92
+ "typescript-eslint": "^8.44.0",
93
+ "vite": "^7.1.5",
94
+ "vite-tsconfig-paths": "^5.1.4",
95
+ "vitest": "^3.2.4"
96
+ },
97
+ "peerDependencies": {
98
+ "svelte": "^5.0.0"
99
+ },
100
+ "volta": {
101
+ "node": "22.19.0"
102
+ },
103
+ "publishConfig": {
104
+ "access": "public"
105
+ },
106
+ "tags": [
107
+ "svelte",
108
+ "animation",
109
+ "motion",
110
+ "transitions",
111
+ "spring-physics",
112
+ "performance",
113
+ "ui-animation",
114
+ "micro-interactions",
115
+ "svelte5"
116
+ ],
117
+ "scripts": {
118
+ "build": "vite build && npm run package",
119
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
120
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
121
+ "dev": "vite dev",
122
+ "format": "prettier --write .",
123
+ "generate": "tsx scripts/generate-html.ts",
124
+ "husky": "husky",
125
+ "lint": "prettier --check . && eslint .",
126
+ "lint:fix": "npm run format && eslint . --fix",
127
+ "package": "svelte-kit sync && svelte-package && publint",
128
+ "preview": "vite preview",
129
+ "test": "vitest run --coverage",
130
+ "test:all": "npm run test && npm run test:e2e",
131
+ "test:e2e": "playwright test",
132
+ "test:e2e:debug": "playwright test --debug",
133
+ "test:e2e:report": "playwright show-report",
134
+ "test:e2e:ui": "playwright test --ui",
135
+ "test:only": "vitest run",
136
+ "test:watch": "vitest"
137
+ }
138
+ }
@@ -1,10 +0,0 @@
1
- <script lang="ts">
2
- import MotionContainer from './_MotionContainer.svelte'
3
- import type { HTMLElementProps } from '../types.js'
4
-
5
- let { children, ...rest }: HTMLElementProps = $props()
6
- </script>
7
-
8
- <MotionContainer tag="{{tag}}" {...rest}>
9
- {@render children?.()}
10
- </MotionContainer>
@@ -1,8 +0,0 @@
1
- <script lang="ts">
2
- import MotionContainer from './_MotionContainer.svelte'
3
- import type { HTMLVoidElementProps } from '../types.js'
4
-
5
- let { ...rest }: HTMLVoidElementProps = $props()
6
- </script>
7
-
8
- <MotionContainer tag="{{tag}}" {...rest} />