@thednp/tween 0.0.4 → 0.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/AGENTS.md ADDED
@@ -0,0 +1,112 @@
1
+ # AGENTS.md — @thednp/tween
2
+
3
+ ## Project Overview
4
+
5
+ **@thednp/tween** is a TypeScript-first tweening engine with framework integrations for React, Preact, SolidJS, Svelte, Vue, and VanJS.
6
+
7
+ - **Core**: `src/Tween.ts`, `src/Timeline.ts` — animation engine with auto-managed RAF loop
8
+ - **Extensions**: `src/extend/` — array, object, path, transform interpolation
9
+ - **Framework integrations**: `src/{react,preact,solid,svelte,vue,vanjs}/`
10
+ - **Tests**: `test/*.spec.{ts,tsx}` with Vitest + happy-dom
11
+ - **Build**: tsdown (rolldown-based), outputs ESM + UMD
12
+ - **Package manager**: pnpm
13
+
14
+ ## Commands
15
+
16
+ ```bash
17
+ pnpm test # run all tests (vitest)
18
+ pnpm test -- --run test/Vanjs # run specific test file
19
+ pnpm build # build all entries via tsdown
20
+ pnpm lint # deno lint src
21
+ pnpm lint:types # tsc --noEmit (pre-existing baseUrl deprecation warning is safe to ignore)
22
+ pnpm fix:ts # deno lint src --fix
23
+ pnpm format # deno fmt src
24
+ ```
25
+
26
+ ## Architecture
27
+
28
+ ### Core Engine
29
+
30
+ - **Tween** (`src/Tween.ts`) — single-property or multi-property tween. Chainable API: `.to()`, `.from()`, `.duration()`, `.easing()`, `.start()`, `.stop()`, `.pause()`, `.reverse()`
31
+ - **Timeline** (`src/Timeline.ts`) — sequences multiple tweens with labels and offsets. API: `.to()`, `.play()`, `.pause()`, `.seek()`, `.stop()`
32
+ - **Runtime** (`src/Runtime.ts`) — auto-managed RAF loop, no manual update loop needed
33
+ - **Easing** (`src/Easing.ts`) — cubic-bezier and preset easing functions
34
+
35
+ ### Framework Integration Pattern
36
+
37
+ Each framework integration follows the same structure:
38
+
39
+ ```
40
+ src/<framework>/
41
+ index.ts # createTween/createTimeline or useTween/useTimeline primitives
42
+ miniStore.ts # reactive store wrapping each property with framework-specific state primitive
43
+ ```
44
+
45
+ **Common pattern**:
46
+ 1. `miniStore(init)` creates a proxy object where each property getter/setter wraps a framework-specific state primitive
47
+ 2. `createTween(initialValues)` / `createTimeline(initialValues)` returns `[store, tween/timeline]` tuple
48
+ 3. Tween mutates store properties → framework reactivity triggers updates
49
+ 4. Cleanup: framework-specific (useEffect, onCleanup, MutationObserver, etc.)
50
+
51
+ ### VanJS Integration (latest)
52
+
53
+ - **`src/vanjs/lifecycle.ts`** — global MutationObserver + session-based state tracking
54
+ - `vanState(initial)` — wrapper around `van.state()` that collects states during a session
55
+ - `nextId()` → returns session ID, `mount(tween, id)` → registers instance
56
+ - `checkRemovedBindings()` — iterates tracked instances, stops tweens whose DOM bindings are all disconnected
57
+ - **`src/vanjs/miniStore.ts`** — uses `vanState()` instead of raw `van.state()`, stores State refs in `_states` property
58
+ - Auto-cleanup via MutationObserver on `document.body` (childList + subtree)
59
+ - SSR-safe: returns `dummyInstance` when `isServer` is true
60
+
61
+ ### miniStore Design
62
+
63
+ Each framework's miniStore adapts to its reactivity model:
64
+
65
+ | Framework | State primitive | Update trigger |
66
+ |-----------|----------------|----------------|
67
+ | React | `@preact/signals-react` signal | Signal subscription |
68
+ | Preact | `useState` + version toggle | `setVersion(v => v + 1)` |
69
+ | Solid | `createSignal()` | Signal getter access |
70
+ | Svelte | `$state()` | Svelte 5 reactivity |
71
+ | Vue | `ref()` | Vue reactivity |
72
+ | VanJS | `van.state()` | `_bindings` tracking via MutationObserver |
73
+
74
+ Arrays use a **version-toggle trick**: a hidden version signal flips on last-element mutation, forcing reactivity without replacing the entire array.
75
+
76
+ ## Testing Conventions
77
+
78
+ - Test files: `test/<Framework>.spec.ts` / `test/<Framework>.spec.tsx`
79
+ - SSR tests: `test/<Framework>-ssr.spec.ts` with `// @vitest-environment node`
80
+ - Test fixtures: `test/fixtures/<framework>.setup.{ts,tsx}` — provides `withHook()` and optionally `withDomBinding()`
81
+ - Use `vi.useFakeTimers()` / `vi.advanceTimersByTime()` for animation timing
82
+ - Use `vi.spyOn(Tween.prototype, 'stop')` for cleanup verification
83
+ - VanJS auto-cleanup tests use real timers (`vi.useRealTimers()`) since MutationObserver needs actual DOM events
84
+
85
+ ## Build Configuration
86
+
87
+ - **`tsdown.config.ts`** — one config per entry point
88
+ - `neverBundle` list: all framework dependencies that should remain external
89
+ - Each entry outputs to `dist/<framework>/<framework>.mjs`
90
+ - Svelte output: `dist/svelte/tween.svelte.js` (renamed post-build)
91
+
92
+ ## Adding a New Framework Integration
93
+
94
+ 1. `pnpm add <framework-package>`
95
+ 2. Create `src/<framework>/miniStore.ts` — reactive store using framework's state primitive
96
+ 3. Create `src/<framework>/index.ts` — `createTween`/`createTimeline` or `useTween`/`useTimeline`
97
+ 4. Add `"./<framework>": "./dist/<framework>/<framework>.mjs"` to `package.json` exports
98
+ 5. Add build entry to `tsdown.config.ts`
99
+ 6. Add framework to `neverBundle` in tsdown config
100
+ 7. Create `test/fixtures/<framework>.setup.ts`
101
+ 8. Create `test/<Framework>.spec.ts` and `test/<Framework>-ssr.spec.ts`
102
+ 9. Create `playground/<framework>/` Vite app
103
+ 10. Add `"vanjs"` to keywords in `package.json`
104
+ 11. Create `wiki/<Framework>.md`
105
+
106
+ ## Gotchas
107
+
108
+ - **Never chain `.to()`, `.duration()` etc. in component body** without safeguards — React/Preact re-renders will create duplicate tweens
109
+ - **Tween/Timeline initialProps is mandatory** — cannot create with empty object
110
+ - **`_bindings` is a VanJS internal property** — not part of public API, could change
111
+ - **playground dirs have their own node_modules** — excluded from type checking
112
+ - **pre-existing type errors** in playground files (JSX, CSS imports) are expected and safe to ignore
package/CHANGELOG.md ADDED
@@ -0,0 +1,96 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.0.6] - 2026-04-06
6
+
7
+ ### Added
8
+ - VanJS integration with `createTween` and `createTimeline` primitives
9
+ - VanJS auto-cleanup via global MutationObserver and session-based state tracking
10
+ - VanJS playground and test suite
11
+ - `pnpm-workspace.yaml` for workspace management
12
+ - `pnpm fix:ts` command for auto-fixing lint issues
13
+
14
+ ### Changed
15
+ - Updated dependencies across all playgrounds
16
+ - Improved `Tween.ts` and `Util.ts` internals
17
+ - Extended `path.ts` extension functionality
18
+ - Updated `preact/miniStore.ts` and `react/miniStore.ts`
19
+ - Enhanced test fixtures for preact setup
20
+ - Updated `tsdown.config.ts` build configuration
21
+ - Updated `tsconfig.json`
22
+ - Updated Timeline and Tween wiki documentation
23
+
24
+ ### Removed
25
+ - `.npmignore` (replaced by `files` field in package.json)
26
+
27
+ ## [0.0.5] - 2026-02-19
28
+
29
+ ### Added
30
+ - Svelte integration with `useTween` hook
31
+ - Preact integration with `useTween` hook
32
+ - Vue integration with `useTween` composable
33
+ - SSR compatibility for all framework hooks
34
+ - Demo links for all supported frameworks
35
+ - More wiki pages for framework-specific documentation
36
+
37
+ ### Changed
38
+ - Updated dependencies
39
+ - Updated playground configurations
40
+ - Improved miniStore implementation
41
+ - Updated tests instrumentation
42
+ - Fixed TypeScript issues
43
+ - Fixed prototype pollution vulnerabilities (CodeQL alerts #1, #2, #3)
44
+ - Added `objectHasProp` utility, fixed `deepAssign`
45
+
46
+ ## [0.0.4] - 2026-01-31
47
+
48
+ ### Added
49
+ - React integration with `useTween` hook
50
+ - SolidJS integration with `createTween` primitive
51
+ - Playground for React and SolidJS
52
+ - Publish workflow
53
+ - CodeQL security scanning
54
+
55
+ ### Changed
56
+ - Fixed JSDocs
57
+ - Updated README and wiki
58
+ - Updated dependencies
59
+ - Version bump
60
+
61
+ ## [0.0.3] - 2026-01-26
62
+
63
+ ### Added
64
+ - `Easing.ts` with cubic-bezier and preset easing functions
65
+ - `extend/` directory for array, object, path, transform interpolation
66
+ - Wiki pages for Tween, Timeline, Easing, and Extend
67
+
68
+ ### Changed
69
+ - Fixed types
70
+ - Code formatting
71
+ - Typos fixed
72
+ - Updated description
73
+
74
+ ## [0.0.2] - 2026-01-25
75
+
76
+ ### Added
77
+ - `Timeline.ts` for sequencing multiple tweens
78
+ - `Runtime.ts` for auto-managed RAF loop
79
+ - `Now.ts` for time utilities
80
+ - `Version.ts` for version tracking
81
+ - `types.d.ts` for TypeScript definitions
82
+ - Initial test suite with Vitest + happy-dom
83
+ - Playground directory
84
+
85
+ ### Changed
86
+ - Initial commit structure refined
87
+
88
+ ## [0.0.1] - 2026-01-25
89
+
90
+ ### Added
91
+ - Initial release of `@thednp/tween`
92
+ - Core `Tween.ts` engine forked from [@tweenjs/tweenjs](https://github.com/tweenjs/tween.js)
93
+ - TypeScript-first architecture
94
+ - Chainable API: `.to()`, `.from()`, `.duration()`, `.easing()`, `.start()`, `.stop()`, `.pause()`, `.reverse()`
95
+ - Build configuration with tsdown
96
+ - Basic wiki documentation
package/README.md CHANGED
@@ -15,6 +15,7 @@ Popular UI frameworks supported:
15
15
  [<img width="32" height="32" src="wiki/assets/preact.svg" alt="Preact" />](https://stackblitz.com/fork/github/thednp/tween/tree/master/playground/preact)
16
16
  [<img width="32" height="32" src="wiki/assets/svelte.svg" alt="Svelte" />](https://stackblitz.com/fork/github/thednp/tween/tree/master/playground/svelte)
17
17
  [<img width="32" height="32" src="wiki/assets/vue.svg" alt="Vue" />](https://stackblitz.com/fork/github/thednp/tween/tree/master/playground/vue)
18
+ [<img width="32" height="32" src="wiki/assets/vanjs.svg" alt="VanJS" />](https://stackblitz.com/fork/github/thednp/tween/tree/master/playground/vanjs)
18
19
 
19
20
  Your favorite framework isn't listed? [Let us know](https://github.com/thednp/tween/issues/new)!
20
21
 
@@ -29,7 +30,7 @@ Your favorite framework isn't listed? [Let us know](https://github.com/thednp/tw
29
30
  * **Predictable outcomes** through upfront value validation — invalid values prevent animation start with clear feedback
30
31
  * **Production-ready validation system** catches configuration errors before they break your app
31
32
  * **Natural reverse playback** via inverted easing (no `reverseEasing` option or `valuesStart` reassignment)
32
- * **Extensible interpolation** with built-in [extensions](wiki/Extend.md) or custom per-property validators and interpolators
33
+ * **Extensible interpolation** with built-in [extensions](wiki/Extend.md) for custom per-property validators and interpolators
33
34
 
34
35
  ### Performance Optimizations
35
36
 
@@ -55,6 +56,7 @@ Your favorite framework isn't listed? [Let us know](https://github.com/thednp/tw
55
56
  [<img width="32" height="32" src="wiki/assets/preact.svg" alt="Preact" />](wiki/Preact.md)
56
57
  [<img width="32" height="32" src="wiki/assets/svelte.svg" alt="Svelte" />](wiki/Svelte.md)
57
58
  [<img width="32" height="32" src="wiki/assets/vue.svg" alt="Vue" />](wiki/Vue.md)
59
+ [<img width="32" height="32" src="wiki/assets/vanjs.svg" alt="VanJS" />](wiki/VanJS.md)
58
60
 
59
61
  #### Other Sources
60
62
  * [The original Tween.js User Guide](https://github.com/tweenjs/tween.js/blob/main/docs/user_guide.md) can also provide valuable tips.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @thednp/tween hooks for Preact v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween hooks for Preact v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @thednp/tween hooks for Preact v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween hooks for Preact v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
@@ -7,7 +7,6 @@
7
7
 
8
8
  import { useEffect, useRef, useState } from "preact/hooks";
9
9
  import { Timeline, Tween, dummyInstance, isArray, isPlainObject, isServer, objectHasProp } from "@thednp/tween";
10
-
11
10
  //#region src/preact/miniStore.ts
12
11
  const STATE_PROXY = "_proxy";
13
12
  const proxyProps = {
@@ -101,10 +100,9 @@ function useMiniStore(initialValue) {
101
100
  const storeRef = useRef(null);
102
101
  const [, setVersion] = useState(0);
103
102
  if (!storeRef.current) storeRef.current = miniStore(initialValue);
104
- useEffect(() => storeRef.current.subscribe(() => setVersion((v) => v === 2 ? 0 : v + 1)), []);
103
+ useEffect(() => storeRef.current.subscribe(() => setVersion((v) => (v + 1) % 3)), []);
105
104
  return storeRef.current.state;
106
105
  }
107
-
108
106
  //#endregion
109
107
  //#region src/preact/index.ts
110
108
  /**
@@ -175,7 +173,7 @@ function useTimeline(initialValues) {
175
173
  useEffect(() => dispose, []);
176
174
  return [store, timelineRef.current];
177
175
  }
178
-
179
176
  //#endregion
180
177
  export { Timeline, Tween, useMiniStore, useTimeline, useTween };
178
+
181
179
  //# sourceMappingURL=preact.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"preact.mjs","names":[],"sources":["../../src/preact/miniStore.ts","../../src/preact/index.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"preact/hooks\";\nimport {\n type ArrayVal,\n isArray,\n isPlainObject,\n objectHasProp,\n type TweenProps,\n} from \"@thednp/tween\";\n\nconst STATE_PROXY = \"_proxy\";\nconst proxyProps = {\n value: 1,\n enumerable: false,\n configurable: false,\n writable: false,\n};\n\ntype Listener<T> = (state: T) => void;\n\nfunction defineArrayProxy<T extends ArrayVal>(\n index: number,\n value: T[number] | ArrayVal,\n target: T | ArrayVal | ArrayVal[],\n sourceLen: number,\n notifyListeners: () => void,\n) {\n const itemIsLast = index === sourceLen - 1;\n\n if (isArray(value)) {\n const subArray: typeof value = [];\n const valueLen = value.length;\n\n value.forEach((itm, idx) => {\n const subItemIsLast = itemIsLast && idx === valueLen - 1;\n\n let currentItem = itm;\n Object.defineProperty(subArray, idx, {\n get: () => currentItem,\n set: (newValue: typeof itm) => {\n currentItem = newValue;\n\n // Only notify on last element to batch updates\n if (subItemIsLast) {\n notifyListeners();\n }\n },\n enumerable: true,\n });\n });\n target[index] = subArray;\n } else {\n let currentValue = value;\n const getter = () => currentValue;\n const setter = (newVal: typeof value) => {\n currentValue = newVal;\n if (itemIsLast) {\n notifyListeners();\n }\n };\n Object.defineProperties(target, {\n [index]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n }\n}\n\nfunction defineStateProxy<T extends Omit<TweenProps, \"_proxy\">>(\n key: number | keyof T,\n value: T[keyof T],\n target: T | ArrayVal,\n notifyListeners: () => void,\n) {\n const valueIsArray = isArray(value);\n let currentValue = value as ArrayVal | ArrayVal[];\n\n const getter = () => currentValue;\n let setter;\n\n if (valueIsArray) {\n // Build array proxy structure\n const arrayProxy: ArrayVal | ArrayVal[] = [];\n const valLength = value.length;\n\n for (let i = 0; i < valLength; i++) {\n defineArrayProxy(\n i,\n (value as ArrayVal)[i],\n arrayProxy as ArrayVal,\n valLength,\n notifyListeners,\n );\n }\n currentValue = arrayProxy;\n } else {\n setter = (newValue: typeof currentValue) => {\n if (currentValue !== newValue) {\n currentValue = newValue;\n notifyListeners();\n }\n };\n }\n\n Object.defineProperties(target, {\n [STATE_PROXY]: proxyProps,\n [key]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n}\n\nfunction createMiniState<T extends TweenProps>(\n obj: T,\n parentReceiver: TweenProps,\n notifyListeners: () => void,\n) {\n if (objectHasProp(obj, STATE_PROXY)) return obj;\n\n for (const [key, value] of Object.entries(obj)) {\n if (isPlainObject(value)) {\n parentReceiver[key] = createMiniState(value, {}, notifyListeners);\n } else {\n defineStateProxy(key, value, parentReceiver, notifyListeners);\n }\n }\n\n return parentReceiver as T;\n}\n\nexport function miniStore<T extends TweenProps>(init: T) {\n const listeners = new Set<Listener<T>>();\n const notifyListeners = () => {\n listeners.forEach((listener) => listener(store));\n };\n\n const store = createMiniState(init, {}, notifyListeners) as T;\n\n return {\n get state() {\n return store;\n },\n subscribe: (listener: Listener<T>) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\nexport function useMiniStore<T extends TweenProps>(initialValue: T) {\n const storeRef = useRef<ReturnType<typeof miniStore<T>>>(null);\n const [, setVersion] = useState(0);\n\n // istanbul ignore else @preserve\n if (!storeRef.current) {\n storeRef.current = miniStore(initialValue);\n }\n\n useEffect(\n () =>\n storeRef.current!.subscribe(() => setVersion((v) => v === 2 ? 0 : v + 1)),\n [],\n );\n\n return storeRef.current!.state;\n}\n","import { useEffect, useRef } from \"preact/hooks\";\nimport {\n dummyInstance,\n isServer,\n Timeline,\n Tween,\n type TweenProps,\n} from \"@thednp/tween\";\nimport { useMiniStore } from \"./miniStore.ts\";\n\nexport { Timeline, Tween, useMiniStore };\n\n/**\n * Hook for updating values with Tween.\n *\n * **NOTE**: - configuration must be wrapped in `useEffect` or `eventListener`.\n * This has two important aspects: never configure or start update loop in SSR\n * and only configure or start the loop when component is mounted in the client.\n *\n * @param initialValues - Initial tween values\n * @returns [store, tween] Tuple of reactive store and Tween instance\n * @example\n * const App = () => {\n * const [state, tween] = useTween({ x: 0, y: 0 })\n *\n * useEffect(() => {\n * tween.to({ x: 100, y: 100 }, 1000).start()\n * }, [])\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function useTween<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Tween<T>] as const;\n }\n const store = useMiniStore(initialValues);\n const tweenRef = useRef<Tween<T>>(null);\n\n // istanbul ignore else @preserve\n if (!tweenRef.current) {\n tweenRef.current = new Tween(store);\n }\n\n const dispose = () => {\n tweenRef.current!.stop();\n tweenRef.current!.clear();\n };\n useEffect(() => dispose, []);\n\n return [store, tweenRef.current] as [T, Tween<T>];\n}\n\n/**\n * Hook for sequencing values update with Timeline.\n *\n * **NOTE**: - configuration must be wrapped in `useEffect` or `eventListener`.\n * This has two important aspects: never configure or start update loop in SSR\n * and only configure or start the loop when component is mounted in the client.\n *\n * @param initialValues - Initial tween values\n * @returns [store, timeline] Tuple of reactive store and Timeline instance\n * @example\n * const App = () => {\n * const [state, timeline] = useTimeline({ x: 0, y: 0 })\n *\n * useEffect(() => {\n * timeline.to({ x: 100, y: 100 }).play()\n * }, [])\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function useTimeline<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Timeline<T>] as const;\n }\n const store = useMiniStore(initialValues);\n const timelineRef = useRef<Timeline<T>>(null);\n\n // istanbul ignore else @preserve\n if (!timelineRef.current) {\n timelineRef.current = new Timeline(store);\n }\n\n const dispose = () => {\n timelineRef.current!.stop();\n timelineRef.current!.clear();\n };\n useEffect(() => dispose, []);\n\n return [store, timelineRef.current] as [T, Timeline<T>];\n}\n"],"mappings":";;;;;;;;;;;AASA,MAAM,cAAc;AACpB,MAAM,aAAa;CACjB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,UAAU;CACX;AAID,SAAS,iBACP,OACA,OACA,QACA,WACA,iBACA;CACA,MAAM,aAAa,UAAU,YAAY;AAEzC,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,WAAyB,EAAE;EACjC,MAAM,WAAW,MAAM;AAEvB,QAAM,SAAS,KAAK,QAAQ;GAC1B,MAAM,gBAAgB,cAAc,QAAQ,WAAW;GAEvD,IAAI,cAAc;AAClB,UAAO,eAAe,UAAU,KAAK;IACnC,WAAW;IACX,MAAM,aAAyB;AAC7B,mBAAc;AAGd,SAAI,cACF,kBAAiB;;IAGrB,YAAY;IACb,CAAC;IACF;AACF,SAAO,SAAS;QACX;EACL,IAAI,eAAe;EACnB,MAAM,eAAe;EACrB,MAAM,UAAU,WAAyB;AACvC,kBAAe;AACf,OAAI,WACF,kBAAiB;;AAGrB,SAAO,iBAAiB,QAAQ,GAC7B,QAAQ;GACP,KAAK;GACL,KAAK;GACL,YAAY;GACb,EACF,CAAC;;;AAIN,SAAS,iBACP,KACA,OACA,QACA,iBACA;CACA,MAAM,eAAe,QAAQ,MAAM;CACnC,IAAI,eAAe;CAEnB,MAAM,eAAe;CACrB,IAAI;AAEJ,KAAI,cAAc;EAEhB,MAAM,aAAoC,EAAE;EAC5C,MAAM,YAAY,MAAM;AAExB,OAAK,IAAI,IAAI,GAAG,IAAI,WAAW,IAC7B,kBACE,GACC,MAAmB,IACpB,YACA,WACA,gBACD;AAEH,iBAAe;OAEf,WAAU,aAAkC;AAC1C,MAAI,iBAAiB,UAAU;AAC7B,kBAAe;AACf,oBAAiB;;;AAKvB,QAAO,iBAAiB,QAAQ;GAC7B,cAAc;GACd,MAAM;GACL,KAAK;GACL,KAAK;GACL,YAAY;GACb;EACF,CAAC;;AAGJ,SAAS,gBACP,KACA,gBACA,iBACA;AACA,KAAI,cAAc,KAAK,YAAY,CAAE,QAAO;AAE5C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,CAC5C,KAAI,cAAc,MAAM,CACtB,gBAAe,OAAO,gBAAgB,OAAO,EAAE,EAAE,gBAAgB;KAEjE,kBAAiB,KAAK,OAAO,gBAAgB,gBAAgB;AAIjE,QAAO;;AAGT,SAAgB,UAAgC,MAAS;CACvD,MAAM,4BAAY,IAAI,KAAkB;CACxC,MAAM,wBAAwB;AAC5B,YAAU,SAAS,aAAa,SAAS,MAAM,CAAC;;CAGlD,MAAM,QAAQ,gBAAgB,MAAM,EAAE,EAAE,gBAAgB;AAExD,QAAO;EACL,IAAI,QAAQ;AACV,UAAO;;EAET,YAAY,aAA0B;AACpC,aAAU,IAAI,SAAS;AACvB,gBAAa;AACX,cAAU,OAAO,SAAS;;;EAG/B;;AAGH,SAAgB,aAAmC,cAAiB;CAClE,MAAM,WAAW,OAAwC,KAAK;CAC9D,MAAM,GAAG,cAAc,SAAS,EAAE;AAGlC,KAAI,CAAC,SAAS,QACZ,UAAS,UAAU,UAAU,aAAa;AAG5C,iBAEI,SAAS,QAAS,gBAAgB,YAAY,MAAM,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC,EAC3E,EAAE,CACH;AAED,QAAO,SAAS,QAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvI3B,SAAgB,SAA+B,eAAkB;AAC/D,KAAI,SACF,QAAO,CAAC,eAAe,cAAqC;CAE9D,MAAM,QAAQ,aAAa,cAAc;CACzC,MAAM,WAAW,OAAiB,KAAK;AAGvC,KAAI,CAAC,SAAS,QACZ,UAAS,UAAU,IAAI,MAAM,MAAM;CAGrC,MAAM,gBAAgB;AACpB,WAAS,QAAS,MAAM;AACxB,WAAS,QAAS,OAAO;;AAE3B,iBAAgB,SAAS,EAAE,CAAC;AAE5B,QAAO,CAAC,OAAO,SAAS,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;AAyBlC,SAAgB,YAAkC,eAAkB;AAClE,KAAI,SACF,QAAO,CAAC,eAAe,cAAwC;CAEjE,MAAM,QAAQ,aAAa,cAAc;CACzC,MAAM,cAAc,OAAoB,KAAK;AAG7C,KAAI,CAAC,YAAY,QACf,aAAY,UAAU,IAAI,SAAS,MAAM;CAG3C,MAAM,gBAAgB;AACpB,cAAY,QAAS,MAAM;AAC3B,cAAY,QAAS,OAAO;;AAE9B,iBAAgB,SAAS,EAAE,CAAC;AAE5B,QAAO,CAAC,OAAO,YAAY,QAAQ"}
1
+ {"version":3,"file":"preact.mjs","names":[],"sources":["../../src/preact/miniStore.ts","../../src/preact/index.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"preact/hooks\";\nimport {\n type ArrayVal,\n isArray,\n isPlainObject,\n objectHasProp,\n type TweenProps,\n} from \"@thednp/tween\";\n\nconst STATE_PROXY = \"_proxy\";\nconst proxyProps = {\n value: 1,\n enumerable: false,\n configurable: false,\n writable: false,\n};\n\ntype Listener<T> = (state: T) => void;\n\nfunction defineArrayProxy<T extends ArrayVal>(\n index: number,\n value: T[number] | ArrayVal,\n target: T | ArrayVal | ArrayVal[],\n sourceLen: number,\n notifyListeners: () => void,\n) {\n const itemIsLast = index === sourceLen - 1;\n\n if (isArray(value)) {\n const subArray: typeof value = [];\n const valueLen = value.length;\n\n value.forEach((itm, idx) => {\n const subItemIsLast = itemIsLast && idx === valueLen - 1;\n\n let currentItem = itm;\n Object.defineProperty(subArray, idx, {\n get: () => currentItem,\n set: (newValue: typeof itm) => {\n currentItem = newValue;\n\n // Only notify on last element to batch updates\n if (subItemIsLast) {\n notifyListeners();\n }\n },\n enumerable: true,\n });\n });\n target[index] = subArray;\n } else {\n let currentValue = value;\n const getter = () => currentValue;\n const setter = (newVal: typeof value) => {\n currentValue = newVal;\n if (itemIsLast) {\n notifyListeners();\n }\n };\n Object.defineProperties(target, {\n [index]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n }\n}\n\nfunction defineStateProxy<T extends Omit<TweenProps, \"_proxy\">>(\n key: number | keyof T,\n value: T[keyof T],\n target: T | ArrayVal,\n notifyListeners: () => void,\n) {\n const valueIsArray = isArray(value);\n let currentValue = value as ArrayVal | ArrayVal[];\n\n const getter = () => currentValue;\n let setter;\n\n if (valueIsArray) {\n // Build array proxy structure\n const arrayProxy: ArrayVal | ArrayVal[] = [];\n const valLength = value.length;\n\n for (let i = 0; i < valLength; i++) {\n defineArrayProxy(\n i,\n (value as ArrayVal)[i],\n arrayProxy as ArrayVal,\n valLength,\n notifyListeners,\n );\n }\n currentValue = arrayProxy;\n } else {\n setter = (newValue: typeof currentValue) => {\n if (currentValue !== newValue) {\n currentValue = newValue;\n notifyListeners();\n }\n };\n }\n\n Object.defineProperties(target, {\n [STATE_PROXY]: proxyProps,\n [key]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n}\n\nfunction createMiniState<T extends TweenProps>(\n obj: T,\n parentReceiver: TweenProps,\n notifyListeners: () => void,\n) {\n if (objectHasProp(obj, STATE_PROXY)) return obj;\n\n for (const [key, value] of Object.entries(obj)) {\n if (isPlainObject(value)) {\n parentReceiver[key] = createMiniState(value, {}, notifyListeners);\n } else {\n defineStateProxy(key, value, parentReceiver, notifyListeners);\n }\n }\n\n return parentReceiver as T;\n}\n\nexport function miniStore<T extends TweenProps>(init: T) {\n const listeners = new Set<Listener<T>>();\n const notifyListeners = () => {\n listeners.forEach((listener) => listener(store));\n };\n\n const store = createMiniState(init, {}, notifyListeners) as T;\n\n return {\n get state() {\n return store;\n },\n subscribe: (listener: Listener<T>) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\nexport function useMiniStore<T extends TweenProps>(initialValue: T) {\n const storeRef = useRef<ReturnType<typeof miniStore<T>>>(null);\n const [, setVersion] = useState(0);\n\n // istanbul ignore else @preserve\n if (!storeRef.current) {\n storeRef.current = miniStore(initialValue);\n }\n\n useEffect(\n () => storeRef.current!.subscribe(() => setVersion((v) => (v + 1) % 3)),\n [],\n );\n\n return storeRef.current!.state;\n}\n","import { useEffect, useRef } from \"preact/hooks\";\nimport {\n dummyInstance,\n isServer,\n Timeline,\n Tween,\n type TweenProps,\n} from \"@thednp/tween\";\nimport { useMiniStore } from \"./miniStore.ts\";\n\nexport { Timeline, Tween, useMiniStore };\n\n/**\n * Hook for updating values with Tween.\n *\n * **NOTE**: - configuration must be wrapped in `useEffect` or `eventListener`.\n * This has two important aspects: never configure or start update loop in SSR\n * and only configure or start the loop when component is mounted in the client.\n *\n * @param initialValues - Initial tween values\n * @returns [store, tween] Tuple of reactive store and Tween instance\n * @example\n * const App = () => {\n * const [state, tween] = useTween({ x: 0, y: 0 })\n *\n * useEffect(() => {\n * tween.to({ x: 100, y: 100 }, 1000).start()\n * }, [])\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function useTween<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Tween<T>] as const;\n }\n const store = useMiniStore(initialValues);\n const tweenRef = useRef<Tween<T>>(null);\n\n // istanbul ignore else @preserve\n if (!tweenRef.current) {\n tweenRef.current = new Tween(store);\n }\n\n const dispose = () => {\n tweenRef.current!.stop();\n tweenRef.current!.clear();\n };\n useEffect(() => dispose, []);\n\n return [store, tweenRef.current] as [T, Tween<T>];\n}\n\n/**\n * Hook for sequencing values update with Timeline.\n *\n * **NOTE**: - configuration must be wrapped in `useEffect` or `eventListener`.\n * This has two important aspects: never configure or start update loop in SSR\n * and only configure or start the loop when component is mounted in the client.\n *\n * @param initialValues - Initial tween values\n * @returns [store, timeline] Tuple of reactive store and Timeline instance\n * @example\n * const App = () => {\n * const [state, timeline] = useTimeline({ x: 0, y: 0 })\n *\n * useEffect(() => {\n * timeline.to({ x: 100, y: 100 }).play()\n * }, [])\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function useTimeline<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Timeline<T>] as const;\n }\n const store = useMiniStore(initialValues);\n const timelineRef = useRef<Timeline<T>>(null);\n\n // istanbul ignore else @preserve\n if (!timelineRef.current) {\n timelineRef.current = new Timeline(store);\n }\n\n const dispose = () => {\n timelineRef.current!.stop();\n timelineRef.current!.clear();\n };\n useEffect(() => dispose, []);\n\n return [store, timelineRef.current] as [T, Timeline<T>];\n}\n"],"mappings":";;;;;;;;;;AASA,MAAM,cAAc;AACpB,MAAM,aAAa;CACjB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,UAAU;CACX;AAID,SAAS,iBACP,OACA,OACA,QACA,WACA,iBACA;CACA,MAAM,aAAa,UAAU,YAAY;AAEzC,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,WAAyB,EAAE;EACjC,MAAM,WAAW,MAAM;AAEvB,QAAM,SAAS,KAAK,QAAQ;GAC1B,MAAM,gBAAgB,cAAc,QAAQ,WAAW;GAEvD,IAAI,cAAc;AAClB,UAAO,eAAe,UAAU,KAAK;IACnC,WAAW;IACX,MAAM,aAAyB;AAC7B,mBAAc;AAGd,SAAI,cACF,kBAAiB;;IAGrB,YAAY;IACb,CAAC;IACF;AACF,SAAO,SAAS;QACX;EACL,IAAI,eAAe;EACnB,MAAM,eAAe;EACrB,MAAM,UAAU,WAAyB;AACvC,kBAAe;AACf,OAAI,WACF,kBAAiB;;AAGrB,SAAO,iBAAiB,QAAQ,GAC7B,QAAQ;GACP,KAAK;GACL,KAAK;GACL,YAAY;GACb,EACF,CAAC;;;AAIN,SAAS,iBACP,KACA,OACA,QACA,iBACA;CACA,MAAM,eAAe,QAAQ,MAAM;CACnC,IAAI,eAAe;CAEnB,MAAM,eAAe;CACrB,IAAI;AAEJ,KAAI,cAAc;EAEhB,MAAM,aAAoC,EAAE;EAC5C,MAAM,YAAY,MAAM;AAExB,OAAK,IAAI,IAAI,GAAG,IAAI,WAAW,IAC7B,kBACE,GACC,MAAmB,IACpB,YACA,WACA,gBACD;AAEH,iBAAe;OAEf,WAAU,aAAkC;AAC1C,MAAI,iBAAiB,UAAU;AAC7B,kBAAe;AACf,oBAAiB;;;AAKvB,QAAO,iBAAiB,QAAQ;GAC7B,cAAc;GACd,MAAM;GACL,KAAK;GACL,KAAK;GACL,YAAY;GACb;EACF,CAAC;;AAGJ,SAAS,gBACP,KACA,gBACA,iBACA;AACA,KAAI,cAAc,KAAK,YAAY,CAAE,QAAO;AAE5C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,CAC5C,KAAI,cAAc,MAAM,CACtB,gBAAe,OAAO,gBAAgB,OAAO,EAAE,EAAE,gBAAgB;KAEjE,kBAAiB,KAAK,OAAO,gBAAgB,gBAAgB;AAIjE,QAAO;;AAGT,SAAgB,UAAgC,MAAS;CACvD,MAAM,4BAAY,IAAI,KAAkB;CACxC,MAAM,wBAAwB;AAC5B,YAAU,SAAS,aAAa,SAAS,MAAM,CAAC;;CAGlD,MAAM,QAAQ,gBAAgB,MAAM,EAAE,EAAE,gBAAgB;AAExD,QAAO;EACL,IAAI,QAAQ;AACV,UAAO;;EAET,YAAY,aAA0B;AACpC,aAAU,IAAI,SAAS;AACvB,gBAAa;AACX,cAAU,OAAO,SAAS;;;EAG/B;;AAGH,SAAgB,aAAmC,cAAiB;CAClE,MAAM,WAAW,OAAwC,KAAK;CAC9D,MAAM,GAAG,cAAc,SAAS,EAAE;AAGlC,KAAI,CAAC,SAAS,QACZ,UAAS,UAAU,UAAU,aAAa;AAG5C,iBACQ,SAAS,QAAS,gBAAgB,YAAY,OAAO,IAAI,KAAK,EAAE,CAAC,EACvE,EAAE,CACH;AAED,QAAO,SAAS,QAAS;;;;;;;;;;;;;;;;;;;;;;;;;;ACtI3B,SAAgB,SAA+B,eAAkB;AAC/D,KAAI,SACF,QAAO,CAAC,eAAe,cAAqC;CAE9D,MAAM,QAAQ,aAAa,cAAc;CACzC,MAAM,WAAW,OAAiB,KAAK;AAGvC,KAAI,CAAC,SAAS,QACZ,UAAS,UAAU,IAAI,MAAM,MAAM;CAGrC,MAAM,gBAAgB;AACpB,WAAS,QAAS,MAAM;AACxB,WAAS,QAAS,OAAO;;AAE3B,iBAAgB,SAAS,EAAE,CAAC;AAE5B,QAAO,CAAC,OAAO,SAAS,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;AAyBlC,SAAgB,YAAkC,eAAkB;AAClE,KAAI,SACF,QAAO,CAAC,eAAe,cAAwC;CAEjE,MAAM,QAAQ,aAAa,cAAc;CACzC,MAAM,cAAc,OAAoB,KAAK;AAG7C,KAAI,CAAC,YAAY,QACf,aAAY,UAAU,IAAI,SAAS,MAAM;CAG3C,MAAM,gBAAgB;AACpB,cAAY,QAAS,MAAM;AAC3B,cAAY,QAAS,OAAO;;AAE9B,iBAAgB,SAAS,EAAE,CAAC;AAE5B,QAAO,CAAC,OAAO,YAAY,QAAQ"}
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @thednp/tween hooks for React v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween hooks for React v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @thednp/tween hooks for React v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween hooks for React v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
@@ -7,7 +7,6 @@
7
7
 
8
8
  import { useEffect, useRef, useState } from "react";
9
9
  import { Timeline, Tween, dummyInstance, isArray, isPlainObject, isServer, objectHasProp } from "@thednp/tween";
10
-
11
10
  //#region src/react/miniStore.ts
12
11
  const STATE_PROXY = "_proxy";
13
12
  const proxyProps = {
@@ -101,10 +100,9 @@ function useMiniStore(initialValue) {
101
100
  const storeRef = useRef(null);
102
101
  const [, setVersion] = useState(0);
103
102
  if (!storeRef.current) storeRef.current = miniStore(initialValue);
104
- useEffect(() => storeRef.current.subscribe(() => setVersion((v) => v === 2 ? 0 : v + 1)), []);
103
+ useEffect(() => storeRef.current.subscribe(() => setVersion((v) => (v + 1) % 3)), []);
105
104
  return storeRef.current.state;
106
105
  }
107
-
108
106
  //#endregion
109
107
  //#region src/react/index.ts
110
108
  /**
@@ -177,7 +175,7 @@ function useTimeline(initialValues) {
177
175
  }, []);
178
176
  return [state, timelineRef.current];
179
177
  }
180
-
181
178
  //#endregion
182
179
  export { Timeline, Tween, useMiniStore, useTimeline, useTween };
180
+
183
181
  //# sourceMappingURL=react.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.mjs","names":[],"sources":["../../src/react/miniStore.ts","../../src/react/index.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n type ArrayVal,\n isArray,\n isPlainObject,\n objectHasProp,\n type TweenProps,\n} from \"@thednp/tween\";\n\nconst STATE_PROXY = \"_proxy\";\nconst proxyProps = {\n value: 1,\n enumerable: false,\n configurable: false,\n writable: false,\n};\n\ntype Listener<T> = (state: T) => void;\n\nfunction defineArrayProxy<T extends ArrayVal>(\n index: number,\n value: T[number] | ArrayVal,\n target: T | ArrayVal | ArrayVal[],\n sourceLen: number,\n notifyListeners: () => void,\n) {\n const itemIsLast = index === sourceLen - 1;\n\n if (isArray(value)) {\n const subArray: typeof value = [];\n const valueLen = value.length;\n\n value.forEach((itm, idx) => {\n const subItemIsLast = itemIsLast && idx === valueLen - 1;\n\n let currentItem = itm;\n Object.defineProperty(subArray, idx, {\n get: () => currentItem,\n set: (newValue: typeof itm) => {\n currentItem = newValue;\n\n // Only notify on last element to batch updates\n if (subItemIsLast) {\n notifyListeners();\n }\n },\n enumerable: true,\n });\n });\n target[index] = subArray;\n } else {\n let currentValue = value;\n const getter = () => currentValue;\n const setter = (newVal: typeof value) => {\n currentValue = newVal;\n if (itemIsLast) {\n notifyListeners();\n }\n };\n Object.defineProperties(target, {\n [index]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n }\n}\n\nfunction defineStateProxy<T extends Omit<TweenProps, \"_proxy\">>(\n key: number | keyof T,\n value: T[keyof T],\n target: T | ArrayVal,\n notifyListeners: () => void,\n) {\n const valueIsArray = isArray(value);\n let currentValue = value as ArrayVal | ArrayVal[];\n\n const getter = () => currentValue;\n let setter;\n\n if (valueIsArray) {\n // Build array proxy structure\n const arrayProxy: ArrayVal | ArrayVal[] = [];\n const valLength = value.length;\n\n for (let i = 0; i < valLength; i++) {\n defineArrayProxy(\n i,\n (value as ArrayVal)[i],\n arrayProxy as ArrayVal,\n valLength,\n notifyListeners,\n );\n }\n currentValue = arrayProxy;\n } else {\n setter = (newValue: typeof currentValue) => {\n if (currentValue !== newValue) {\n currentValue = newValue;\n notifyListeners();\n }\n };\n }\n\n Object.defineProperties(target, {\n [STATE_PROXY]: proxyProps,\n [key]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n}\n\nfunction createMiniState<T extends TweenProps>(\n obj: T,\n parentReceiver: TweenProps,\n notifyListeners: () => void,\n) {\n if (objectHasProp(obj, STATE_PROXY)) return obj;\n\n for (const [key, value] of Object.entries(obj)) {\n if (isPlainObject(value)) {\n parentReceiver[key] = createMiniState(value, {}, notifyListeners);\n } else {\n defineStateProxy(key, value, parentReceiver, notifyListeners);\n }\n }\n\n return parentReceiver as T;\n}\n\nexport function miniStore<T extends TweenProps>(init: T) {\n const listeners = new Set<Listener<T>>();\n const notifyListeners = () => {\n listeners.forEach((listener) => listener(store));\n };\n\n const store = createMiniState(init, {}, notifyListeners) as T;\n\n return {\n get state() {\n return store;\n },\n subscribe: (listener: Listener<T>) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\nexport function useMiniStore<T extends TweenProps>(initialValue: T) {\n const storeRef = useRef<ReturnType<typeof miniStore<T>>>(null);\n const [, setVersion] = useState(0);\n\n // istanbul ignore else @preserve\n if (!storeRef.current) {\n storeRef.current = miniStore(initialValue);\n }\n\n useEffect(\n () =>\n storeRef.current!.subscribe(() =>\n setVersion((v) => v === 2 ? /* istanbul ignore next */ 0 : v + 1)\n ),\n [],\n );\n\n return storeRef.current!.state;\n}\n","import { useEffect, useRef } from \"react\";\nimport {\n dummyInstance,\n isServer,\n Timeline,\n Tween,\n type TweenProps,\n} from \"@thednp/tween\";\nimport { useMiniStore } from \"./miniStore.ts\";\n\nexport { Timeline, Tween, useMiniStore };\n\n/**\n * Hook for updating values with Tween.\n *\n * **NOTE**: - configuration must be wrapped in `useEffect` or `eventListener`.\n * This has two important aspects: never configure or start update loop in SSR\n * and only configure or start the loop when component is mounted in the client.\n *\n * @param initialValues - Initial tween values\n * @returns [store, tween] Tuple of reactive store and Tween instance\n * @example\n * const App = () => {\n * const [state, tween] = useTween({ x: 0, y: 0 })\n *\n * useEffect(() => {\n * tween.to({ x: 100, y: 100 }).start()\n * }, [])\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport const useTween = <T extends TweenProps>(initialValues: T) => {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Tween<T>] as const;\n }\n const tweenRef = useRef<Tween<T> | null>(null);\n const state = useMiniStore(initialValues);\n\n // istanbul ignore else @preserve\n if (!tweenRef.current) {\n tweenRef.current = new Tween(state);\n }\n\n useEffect(() => {\n return () => {\n tweenRef.current?.stop();\n tweenRef.current?.clear();\n };\n }, []);\n\n return [state, tweenRef.current] as [T, Tween<T>];\n};\n\n/**\n * Hook for sequencing values update with Timeline.\n *\n * **NOTE**: - configuration must be wrapped in `useEffect` or `eventListener`.\n * This has two important aspects: never configure or start update loop in SSR\n * and only configure or start the loop when component is mounted in the client.\n *\n * @param initialValues - Initial tween values\n * @returns [store, timeline] Tuple of reactive store and Timeline instance\n * @example\n * const App = () => {\n * const [state, timeline] = useTimeline({ x: 0, y: 0 })\n *\n * useEffect(() => {\n * timeline.to({ x: 100, y: 100 }).play()\n * }, [])\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function useTimeline<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Timeline<T>] as const;\n }\n const timelineRef = useRef<Timeline<T> | null>(null);\n const state = useMiniStore(initialValues);\n\n // istanbul ignore else @preserve\n if (!timelineRef.current) {\n timelineRef.current = new Timeline(state);\n }\n\n useEffect(() => {\n return () => {\n timelineRef.current?.clear();\n timelineRef.current?.stop();\n };\n }, []);\n\n return [state, timelineRef.current] as [T, Timeline<T>];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.mjs","names":[],"sources":["../../src/react/miniStore.ts","../../src/react/index.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n type ArrayVal,\n isArray,\n isPlainObject,\n objectHasProp,\n type TweenProps,\n} from \"@thednp/tween\";\n\nconst STATE_PROXY = \"_proxy\";\nconst proxyProps = {\n value: 1,\n enumerable: false,\n configurable: false,\n writable: false,\n};\n\ntype Listener<T> = (state: T) => void;\n\nfunction defineArrayProxy<T extends ArrayVal>(\n index: number,\n value: T[number] | ArrayVal,\n target: T | ArrayVal | ArrayVal[],\n sourceLen: number,\n notifyListeners: () => void,\n) {\n const itemIsLast = index === sourceLen - 1;\n\n if (isArray(value)) {\n const subArray: typeof value = [];\n const valueLen = value.length;\n\n value.forEach((itm, idx) => {\n const subItemIsLast = itemIsLast && idx === valueLen - 1;\n\n let currentItem = itm;\n Object.defineProperty(subArray, idx, {\n get: () => currentItem,\n set: (newValue: typeof itm) => {\n currentItem = newValue;\n\n // Only notify on last element to batch updates\n if (subItemIsLast) {\n notifyListeners();\n }\n },\n enumerable: true,\n });\n });\n target[index] = subArray;\n } else {\n let currentValue = value;\n const getter = () => currentValue;\n const setter = (newVal: typeof value) => {\n currentValue = newVal;\n if (itemIsLast) {\n notifyListeners();\n }\n };\n Object.defineProperties(target, {\n [index]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n }\n}\n\nfunction defineStateProxy<T extends Omit<TweenProps, \"_proxy\">>(\n key: number | keyof T,\n value: T[keyof T],\n target: T | ArrayVal,\n notifyListeners: () => void,\n) {\n const valueIsArray = isArray(value);\n let currentValue = value as ArrayVal | ArrayVal[];\n\n const getter = () => currentValue;\n let setter;\n\n if (valueIsArray) {\n // Build array proxy structure\n const arrayProxy: ArrayVal | ArrayVal[] = [];\n const valLength = value.length;\n\n for (let i = 0; i < valLength; i++) {\n defineArrayProxy(\n i,\n (value as ArrayVal)[i],\n arrayProxy as ArrayVal,\n valLength,\n notifyListeners,\n );\n }\n currentValue = arrayProxy;\n } else {\n setter = (newValue: typeof currentValue) => {\n if (currentValue !== newValue) {\n currentValue = newValue;\n notifyListeners();\n }\n };\n }\n\n Object.defineProperties(target, {\n [STATE_PROXY]: proxyProps,\n [key]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n}\n\nfunction createMiniState<T extends TweenProps>(\n obj: T,\n parentReceiver: TweenProps,\n notifyListeners: () => void,\n) {\n if (objectHasProp(obj, STATE_PROXY)) return obj;\n\n for (const [key, value] of Object.entries(obj)) {\n if (isPlainObject(value)) {\n parentReceiver[key] = createMiniState(value, {}, notifyListeners);\n } else {\n defineStateProxy(key, value, parentReceiver, notifyListeners);\n }\n }\n\n return parentReceiver as T;\n}\n\nexport function miniStore<T extends TweenProps>(init: T) {\n const listeners = new Set<Listener<T>>();\n const notifyListeners = () => {\n listeners.forEach((listener) => listener(store));\n };\n\n const store = createMiniState(init, {}, notifyListeners) as T;\n\n return {\n get state() {\n return store;\n },\n subscribe: (listener: Listener<T>) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\nexport function useMiniStore<T extends TweenProps>(initialValue: T) {\n const storeRef = useRef<ReturnType<typeof miniStore<T>>>(null);\n const [, setVersion] = useState(0);\n\n // istanbul ignore else @preserve\n if (!storeRef.current) {\n storeRef.current = miniStore(initialValue);\n }\n\n useEffect(\n () => storeRef.current!.subscribe(() => setVersion((v) => (v + 1) % 3)),\n [],\n );\n\n return storeRef.current!.state;\n}\n","import { useEffect, useRef } from \"react\";\nimport {\n dummyInstance,\n isServer,\n Timeline,\n Tween,\n type TweenProps,\n} from \"@thednp/tween\";\nimport { useMiniStore } from \"./miniStore.ts\";\n\nexport { Timeline, Tween, useMiniStore };\n\n/**\n * Hook for updating values with Tween.\n *\n * **NOTE**: - configuration must be wrapped in `useEffect` or `eventListener`.\n * This has two important aspects: never configure or start update loop in SSR\n * and only configure or start the loop when component is mounted in the client.\n *\n * @param initialValues - Initial tween values\n * @returns [store, tween] Tuple of reactive store and Tween instance\n * @example\n * const App = () => {\n * const [state, tween] = useTween({ x: 0, y: 0 })\n *\n * useEffect(() => {\n * tween.to({ x: 100, y: 100 }).start()\n * }, [])\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport const useTween = <T extends TweenProps>(initialValues: T) => {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Tween<T>] as const;\n }\n const tweenRef = useRef<Tween<T> | null>(null);\n const state = useMiniStore(initialValues);\n\n // istanbul ignore else @preserve\n if (!tweenRef.current) {\n tweenRef.current = new Tween(state);\n }\n\n useEffect(() => {\n return () => {\n tweenRef.current?.stop();\n tweenRef.current?.clear();\n };\n }, []);\n\n return [state, tweenRef.current] as [T, Tween<T>];\n};\n\n/**\n * Hook for sequencing values update with Timeline.\n *\n * **NOTE**: - configuration must be wrapped in `useEffect` or `eventListener`.\n * This has two important aspects: never configure or start update loop in SSR\n * and only configure or start the loop when component is mounted in the client.\n *\n * @param initialValues - Initial tween values\n * @returns [store, timeline] Tuple of reactive store and Timeline instance\n * @example\n * const App = () => {\n * const [state, timeline] = useTimeline({ x: 0, y: 0 })\n *\n * useEffect(() => {\n * timeline.to({ x: 100, y: 100 }).play()\n * }, [])\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function useTimeline<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Timeline<T>] as const;\n }\n const timelineRef = useRef<Timeline<T> | null>(null);\n const state = useMiniStore(initialValues);\n\n // istanbul ignore else @preserve\n if (!timelineRef.current) {\n timelineRef.current = new Timeline(state);\n }\n\n useEffect(() => {\n return () => {\n timelineRef.current?.clear();\n timelineRef.current?.stop();\n };\n }, []);\n\n return [state, timelineRef.current] as [T, Timeline<T>];\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @thednp/tween primitives for SolidJS v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween primitives for SolidJS v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @thednp/tween primitives for SolidJS v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween primitives for SolidJS v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
@@ -7,7 +7,6 @@
7
7
 
8
8
  import { Timeline, Tween, dummyInstance, isArray, isPlainObject, isServer, objectHasProp } from "@thednp/tween";
9
9
  import { createSignal, onCleanup } from "solid-js";
10
-
11
10
  //#region src/solid/miniStore.ts
12
11
  const STATE_PROXY = "_proxy";
13
12
  const proxyProps = {
@@ -86,7 +85,6 @@ function createMiniState(obj, parentReceiver) {
86
85
  function miniStore(init) {
87
86
  return createMiniState(init, {});
88
87
  }
89
-
90
88
  //#endregion
91
89
  //#region src/solid/index.ts
92
90
  /**
@@ -151,7 +149,7 @@ function createTimeline(initialValues) {
151
149
  });
152
150
  return [store, timeline];
153
151
  }
154
-
155
152
  //#endregion
156
153
  export { Timeline, Tween, createTimeline, createTween, miniStore };
154
+
157
155
  //# sourceMappingURL=solid.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"solid.mjs","names":[],"sources":["../../src/solid/miniStore.ts","../../src/solid/index.ts"],"sourcesContent":["import { createSignal } from \"solid-js\";\nimport {\n type ArrayVal,\n isArray,\n isPlainObject,\n objectHasProp,\n type TweenProps,\n} from \"@thednp/tween\";\n\nconst STATE_PROXY = \"_proxy\";\nconst proxyProps = {\n value: 1,\n enumerable: false,\n configurable: false,\n writable: false,\n};\n\nfunction defineArrayProxy<T extends ArrayVal>(\n index: number,\n value: T[number] | ArrayVal,\n target: T | ArrayVal | ArrayVal[],\n sourceLen: number,\n notifyListeners: () => void,\n) {\n const itemIsLast = index === sourceLen - 1;\n\n if (isArray(value)) {\n const subArray: typeof value = [];\n const valueLen = value.length;\n\n value.forEach((itm, idx) => {\n const subItemIsLast = itemIsLast && idx === valueLen - 1;\n\n let currentItem = itm;\n Object.defineProperty(subArray, idx, {\n get: () => currentItem,\n set: (newValue: typeof itm) => {\n currentItem = newValue;\n\n // Only notify on last element to batch updates\n if (subItemIsLast) {\n notifyListeners();\n }\n },\n enumerable: true,\n });\n });\n target[index] = subArray;\n } else {\n let currentValue = value;\n const getter = () => currentValue;\n const setter = (newVal: typeof value) => {\n currentValue = newVal;\n if (itemIsLast) {\n notifyListeners();\n }\n };\n Object.defineProperties(target, {\n [index]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n }\n}\n\nfunction defineStateProxy<T extends Omit<TweenProps, \"_proxy\">>(\n key: number | keyof T,\n value: T[keyof T] | ArrayVal,\n target: T | ArrayVal,\n) {\n const [get, set] = createSignal(value);\n let getter = get;\n let setter;\n\n if (isArray(value)) {\n const arrayProxy: typeof value = [];\n const valLength = value.length;\n const [version, setVersion] = createSignal(0);\n for (let i = 0; i < valLength; i++) {\n defineArrayProxy(i, (value as ArrayVal)[i], arrayProxy, valLength, () => {\n setVersion((v) => 1 - v);\n });\n }\n getter = () => {\n version();\n return get();\n };\n\n set(arrayProxy);\n } else {\n setter = set;\n set(value as never);\n }\n\n Object.defineProperties(target, {\n [STATE_PROXY]: proxyProps,\n [key]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n}\n\nfunction createMiniState<T extends TweenProps>(\n obj: T,\n parentReceiver: TweenProps | number[] | [string, ...number[]][],\n) {\n if (objectHasProp(obj, STATE_PROXY)) return obj;\n\n for (const [key, value] of Object.entries(obj)) {\n if (isPlainObject(value)) {\n (parentReceiver as TweenProps)[key] = createMiniState(value, {});\n } else {\n defineStateProxy(key, value, parentReceiver);\n }\n }\n\n return parentReceiver as T;\n}\n\nexport function miniStore<T extends TweenProps>(init: T) {\n return createMiniState(init, {}) as T;\n}\n","import {\n dummyInstance,\n isServer,\n Timeline,\n Tween,\n type TweenProps,\n} from \"@thednp/tween\";\nimport { onCleanup } from \"solid-js\";\nimport { miniStore } from \"./miniStore.ts\";\n\nexport { miniStore, Timeline, Tween };\n\n/**\n * SolidJS primitive for updating values with Tween.\n *\n * @param initialValues - Initial tween values\n * @returns [store, tween] Tuple of reactive store and Tween instance\n * @example\n * const App = () => {\n * const [state, tween] = createTween({ x: 0, y: 0 })\n *\n * // configuration is free-form, no re-render ever happens\n * tween.to({ x: 100, y: 100 })\n *\n * onMount(() => {\n * tween.start()\n * })\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function createTween<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Tween<T>] as const;\n }\n const store = miniStore(initialValues);\n const tween = new Tween(store);\n\n onCleanup(() => {\n tween.stop();\n tween.clear();\n });\n\n return [store, tween] as [T, Tween<T>];\n}\n\n/**\n * SolidJS primitive for sequencing values update with Timeline.\n *\n * @param initialValues - Initial tween values\n * @returns [store, timeline] Tuple of reactive store and Timeline instance\n * @example\n * const App = () => {\n * const [state, timeline] = createTimeline({ x: 0, y: 0 })\n *\n * // configuration is free-form\n * timeline.to({ x: 100, y: 100 })\n *\n * onMount(() => {\n * timeline.play()\n * })\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function createTimeline<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Timeline<T>] as const;\n }\n const store = miniStore(initialValues);\n const timeline = new Timeline(store);\n\n onCleanup(() => {\n timeline.stop();\n timeline.clear();\n });\n\n return [store, timeline] as [T, Timeline<T>];\n}\n"],"mappings":";;;;;;;;;;;AASA,MAAM,cAAc;AACpB,MAAM,aAAa;CACjB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,UAAU;CACX;AAED,SAAS,iBACP,OACA,OACA,QACA,WACA,iBACA;CACA,MAAM,aAAa,UAAU,YAAY;AAEzC,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,WAAyB,EAAE;EACjC,MAAM,WAAW,MAAM;AAEvB,QAAM,SAAS,KAAK,QAAQ;GAC1B,MAAM,gBAAgB,cAAc,QAAQ,WAAW;GAEvD,IAAI,cAAc;AAClB,UAAO,eAAe,UAAU,KAAK;IACnC,WAAW;IACX,MAAM,aAAyB;AAC7B,mBAAc;AAGd,SAAI,cACF,kBAAiB;;IAGrB,YAAY;IACb,CAAC;IACF;AACF,SAAO,SAAS;QACX;EACL,IAAI,eAAe;EACnB,MAAM,eAAe;EACrB,MAAM,UAAU,WAAyB;AACvC,kBAAe;AACf,OAAI,WACF,kBAAiB;;AAGrB,SAAO,iBAAiB,QAAQ,GAC7B,QAAQ;GACP,KAAK;GACL,KAAK;GACL,YAAY;GACb,EACF,CAAC;;;AAIN,SAAS,iBACP,KACA,OACA,QACA;CACA,MAAM,CAAC,KAAK,OAAO,aAAa,MAAM;CACtC,IAAI,SAAS;CACb,IAAI;AAEJ,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,aAA2B,EAAE;EACnC,MAAM,YAAY,MAAM;EACxB,MAAM,CAAC,SAAS,cAAc,aAAa,EAAE;AAC7C,OAAK,IAAI,IAAI,GAAG,IAAI,WAAW,IAC7B,kBAAiB,GAAI,MAAmB,IAAI,YAAY,iBAAiB;AACvE,eAAY,MAAM,IAAI,EAAE;IACxB;AAEJ,iBAAe;AACb,YAAS;AACT,UAAO,KAAK;;AAGd,MAAI,WAAW;QACV;AACL,WAAS;AACT,MAAI,MAAe;;AAGrB,QAAO,iBAAiB,QAAQ;GAC7B,cAAc;GACd,MAAM;GACL,KAAK;GACL,KAAK;GACL,YAAY;GACb;EACF,CAAC;;AAGJ,SAAS,gBACP,KACA,gBACA;AACA,KAAI,cAAc,KAAK,YAAY,CAAE,QAAO;AAE5C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,CAC5C,KAAI,cAAc,MAAM,CACtB,CAAC,eAA8B,OAAO,gBAAgB,OAAO,EAAE,CAAC;KAEhE,kBAAiB,KAAK,OAAO,eAAe;AAIhD,QAAO;;AAGT,SAAgB,UAAgC,MAAS;AACvD,QAAO,gBAAgB,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;AC3FlC,SAAgB,YAAkC,eAAkB;AAClE,KAAI,SACF,QAAO,CAAC,eAAe,cAAqC;CAE9D,MAAM,QAAQ,UAAU,cAAc;CACtC,MAAM,QAAQ,IAAI,MAAM,MAAM;AAE9B,iBAAgB;AACd,QAAM,MAAM;AACZ,QAAM,OAAO;GACb;AAEF,QAAO,CAAC,OAAO,MAAM;;;;;;;;;;;;;;;;;;;;;;;AAwBvB,SAAgB,eAAqC,eAAkB;AACrE,KAAI,SACF,QAAO,CAAC,eAAe,cAAwC;CAEjE,MAAM,QAAQ,UAAU,cAAc;CACtC,MAAM,WAAW,IAAI,SAAS,MAAM;AAEpC,iBAAgB;AACd,WAAS,MAAM;AACf,WAAS,OAAO;GAChB;AAEF,QAAO,CAAC,OAAO,SAAS"}
1
+ {"version":3,"file":"solid.mjs","names":[],"sources":["../../src/solid/miniStore.ts","../../src/solid/index.ts"],"sourcesContent":["import { createSignal } from \"solid-js\";\nimport {\n type ArrayVal,\n isArray,\n isPlainObject,\n objectHasProp,\n type TweenProps,\n} from \"@thednp/tween\";\n\nconst STATE_PROXY = \"_proxy\";\nconst proxyProps = {\n value: 1,\n enumerable: false,\n configurable: false,\n writable: false,\n};\n\nfunction defineArrayProxy<T extends ArrayVal>(\n index: number,\n value: T[number] | ArrayVal,\n target: T | ArrayVal | ArrayVal[],\n sourceLen: number,\n notifyListeners: () => void,\n) {\n const itemIsLast = index === sourceLen - 1;\n\n if (isArray(value)) {\n const subArray: typeof value = [];\n const valueLen = value.length;\n\n value.forEach((itm, idx) => {\n const subItemIsLast = itemIsLast && idx === valueLen - 1;\n\n let currentItem = itm;\n Object.defineProperty(subArray, idx, {\n get: () => currentItem,\n set: (newValue: typeof itm) => {\n currentItem = newValue;\n\n // Only notify on last element to batch updates\n if (subItemIsLast) {\n notifyListeners();\n }\n },\n enumerable: true,\n });\n });\n target[index] = subArray;\n } else {\n let currentValue = value;\n const getter = () => currentValue;\n const setter = (newVal: typeof value) => {\n currentValue = newVal;\n if (itemIsLast) {\n notifyListeners();\n }\n };\n Object.defineProperties(target, {\n [index]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n }\n}\n\nfunction defineStateProxy<T extends Omit<TweenProps, \"_proxy\">>(\n key: number | keyof T,\n value: T[keyof T] | ArrayVal,\n target: T | ArrayVal,\n) {\n const [get, set] = createSignal(value);\n let getter = get;\n let setter;\n\n if (isArray(value)) {\n const arrayProxy: typeof value = [];\n const valLength = value.length;\n const [version, setVersion] = createSignal(0);\n for (let i = 0; i < valLength; i++) {\n defineArrayProxy(i, (value as ArrayVal)[i], arrayProxy, valLength, () => {\n setVersion((v) => 1 - v);\n });\n }\n getter = () => {\n version();\n return get();\n };\n\n set(arrayProxy);\n } else {\n setter = set;\n set(value as never);\n }\n\n Object.defineProperties(target, {\n [STATE_PROXY]: proxyProps,\n [key]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n}\n\nfunction createMiniState<T extends TweenProps>(\n obj: T,\n parentReceiver: TweenProps | number[] | [string, ...number[]][],\n) {\n if (objectHasProp(obj, STATE_PROXY)) return obj;\n\n for (const [key, value] of Object.entries(obj)) {\n if (isPlainObject(value)) {\n (parentReceiver as TweenProps)[key] = createMiniState(value, {});\n } else {\n defineStateProxy(key, value, parentReceiver);\n }\n }\n\n return parentReceiver as T;\n}\n\nexport function miniStore<T extends TweenProps>(init: T) {\n return createMiniState(init, {}) as T;\n}\n","import {\n dummyInstance,\n isServer,\n Timeline,\n Tween,\n type TweenProps,\n} from \"@thednp/tween\";\nimport { onCleanup } from \"solid-js\";\nimport { miniStore } from \"./miniStore.ts\";\n\nexport { miniStore, Timeline, Tween };\n\n/**\n * SolidJS primitive for updating values with Tween.\n *\n * @param initialValues - Initial tween values\n * @returns [store, tween] Tuple of reactive store and Tween instance\n * @example\n * const App = () => {\n * const [state, tween] = createTween({ x: 0, y: 0 })\n *\n * // configuration is free-form, no re-render ever happens\n * tween.to({ x: 100, y: 100 })\n *\n * onMount(() => {\n * tween.start()\n * })\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function createTween<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Tween<T>] as const;\n }\n const store = miniStore(initialValues);\n const tween = new Tween(store);\n\n onCleanup(() => {\n tween.stop();\n tween.clear();\n });\n\n return [store, tween] as [T, Tween<T>];\n}\n\n/**\n * SolidJS primitive for sequencing values update with Timeline.\n *\n * @param initialValues - Initial tween values\n * @returns [store, timeline] Tuple of reactive store and Timeline instance\n * @example\n * const App = () => {\n * const [state, timeline] = createTimeline({ x: 0, y: 0 })\n *\n * // configuration is free-form\n * timeline.to({ x: 100, y: 100 })\n *\n * onMount(() => {\n * timeline.play()\n * })\n *\n * return (\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n * );\n * }\n */\nexport function createTimeline<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Timeline<T>] as const;\n }\n const store = miniStore(initialValues);\n const timeline = new Timeline(store);\n\n onCleanup(() => {\n timeline.stop();\n timeline.clear();\n });\n\n return [store, timeline] as [T, Timeline<T>];\n}\n"],"mappings":";;;;;;;;;;AASA,MAAM,cAAc;AACpB,MAAM,aAAa;CACjB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,UAAU;CACX;AAED,SAAS,iBACP,OACA,OACA,QACA,WACA,iBACA;CACA,MAAM,aAAa,UAAU,YAAY;AAEzC,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,WAAyB,EAAE;EACjC,MAAM,WAAW,MAAM;AAEvB,QAAM,SAAS,KAAK,QAAQ;GAC1B,MAAM,gBAAgB,cAAc,QAAQ,WAAW;GAEvD,IAAI,cAAc;AAClB,UAAO,eAAe,UAAU,KAAK;IACnC,WAAW;IACX,MAAM,aAAyB;AAC7B,mBAAc;AAGd,SAAI,cACF,kBAAiB;;IAGrB,YAAY;IACb,CAAC;IACF;AACF,SAAO,SAAS;QACX;EACL,IAAI,eAAe;EACnB,MAAM,eAAe;EACrB,MAAM,UAAU,WAAyB;AACvC,kBAAe;AACf,OAAI,WACF,kBAAiB;;AAGrB,SAAO,iBAAiB,QAAQ,GAC7B,QAAQ;GACP,KAAK;GACL,KAAK;GACL,YAAY;GACb,EACF,CAAC;;;AAIN,SAAS,iBACP,KACA,OACA,QACA;CACA,MAAM,CAAC,KAAK,OAAO,aAAa,MAAM;CACtC,IAAI,SAAS;CACb,IAAI;AAEJ,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,aAA2B,EAAE;EACnC,MAAM,YAAY,MAAM;EACxB,MAAM,CAAC,SAAS,cAAc,aAAa,EAAE;AAC7C,OAAK,IAAI,IAAI,GAAG,IAAI,WAAW,IAC7B,kBAAiB,GAAI,MAAmB,IAAI,YAAY,iBAAiB;AACvE,eAAY,MAAM,IAAI,EAAE;IACxB;AAEJ,iBAAe;AACb,YAAS;AACT,UAAO,KAAK;;AAGd,MAAI,WAAW;QACV;AACL,WAAS;AACT,MAAI,MAAe;;AAGrB,QAAO,iBAAiB,QAAQ;GAC7B,cAAc;GACd,MAAM;GACL,KAAK;GACL,KAAK;GACL,YAAY;GACb;EACF,CAAC;;AAGJ,SAAS,gBACP,KACA,gBACA;AACA,KAAI,cAAc,KAAK,YAAY,CAAE,QAAO;AAE5C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,CAC5C,KAAI,cAAc,MAAM,CACrB,gBAA8B,OAAO,gBAAgB,OAAO,EAAE,CAAC;KAEhE,kBAAiB,KAAK,OAAO,eAAe;AAIhD,QAAO;;AAGT,SAAgB,UAAgC,MAAS;AACvD,QAAO,gBAAgB,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AC3FlC,SAAgB,YAAkC,eAAkB;AAClE,KAAI,SACF,QAAO,CAAC,eAAe,cAAqC;CAE9D,MAAM,QAAQ,UAAU,cAAc;CACtC,MAAM,QAAQ,IAAI,MAAM,MAAM;AAE9B,iBAAgB;AACd,QAAM,MAAM;AACZ,QAAM,OAAO;GACb;AAEF,QAAO,CAAC,OAAO,MAAM;;;;;;;;;;;;;;;;;;;;;;;AAwBvB,SAAgB,eAAqC,eAAkB;AACrE,KAAI,SACF,QAAO,CAAC,eAAe,cAAwC;CAEjE,MAAM,QAAQ,UAAU,cAAc;CACtC,MAAM,WAAW,IAAI,SAAS,MAAM;AAEpC,iBAAgB;AACd,WAAS,MAAM;AACf,WAAS,OAAO;GAChB;AAEF,QAAO,CAAC,OAAO,SAAS"}
@@ -1 +1 @@
1
- {"version":3,"file":"svelte.mjs","names":[],"sources":["../../src/svelte/miniStore.svelte.ts","../../src/svelte/index.svelte.ts"],"sourcesContent":["import {\n type ArrayVal,\n isArray,\n isPlainObject,\n objectHasProp,\n type TweenProps,\n} from \"@thednp/tween\";\n\nconst STATE_PROXY = \"_proxy\";\nconst proxyProps = {\n value: 1,\n enumerable: false,\n configurable: false,\n writable: false,\n};\n\nfunction defineArrayProxy<T extends ArrayVal>(\n index: number,\n value: T[number] | ArrayVal,\n target: T | ArrayVal | ArrayVal[],\n sourceLen: number,\n notifyListeners: () => void,\n) {\n const itemIsLast = index === sourceLen - 1;\n\n if (isArray(value)) {\n const subArray: typeof value = [];\n const valueLen = value.length;\n\n value.forEach((itm, idx) => {\n const subItemIsLast = itemIsLast && idx === valueLen - 1;\n let currentItem = itm;\n\n Object.defineProperty(subArray, idx, {\n get: () => currentItem,\n set: (newValue: typeof itm) => {\n currentItem = newValue;\n\n // Only notify on last element to batch updates\n if (subItemIsLast) {\n notifyListeners();\n }\n },\n enumerable: true,\n });\n });\n target[index] = subArray;\n } else {\n let currentValue = value;\n const getter = () => currentValue;\n const setter = (newVal: typeof value) => {\n currentValue = newVal;\n if (itemIsLast) {\n notifyListeners();\n }\n };\n Object.defineProperties(target, {\n [index]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n }\n}\n\nfunction defineStateProxy<T extends Omit<TweenProps, \"_proxy\">>(\n key: number | keyof T,\n value: T[keyof T] | ArrayVal,\n target: T | ArrayVal,\n) {\n let state = $state.raw(value);\n let getter = () => state;\n let setter;\n\n if (isArray(value)) {\n const arrayProxy: typeof value = [];\n const valLength = value.length;\n let version = $state.raw(0);\n const getVersion = () => version;\n for (let i = 0; i < valLength; i++) {\n defineArrayProxy(i, (value as ArrayVal)[i], arrayProxy, valLength, () => {\n version = 1 - version;\n });\n }\n getter = () => {\n getVersion();\n return state;\n };\n\n state = arrayProxy;\n } else {\n setter = (newVal: typeof value) => state = newVal;\n state = value;\n }\n\n Object.defineProperties(target, {\n [STATE_PROXY]: proxyProps,\n [key]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n}\n\nfunction createMiniState<T extends TweenProps>(\n obj: T,\n parentReceiver: TweenProps | number[] | [string, ...number[]][],\n) {\n if (objectHasProp(obj, STATE_PROXY)) return obj;\n\n for (const [key, value] of Object.entries(obj)) {\n if (isPlainObject(value)) {\n (parentReceiver as TweenProps)[key] = createMiniState(value, {});\n } else {\n defineStateProxy(key, value, parentReceiver);\n }\n }\n\n return parentReceiver as T;\n}\n\nexport function miniStore<T extends TweenProps>(init: T) {\n return createMiniState(init, {}) as T;\n}\n","import {\n dummyInstance,\n isServer,\n Timeline,\n Tween,\n type TweenProps,\n} from \"@thednp/tween\";\nimport { onDestroy } from \"svelte\";\nimport { miniStore } from \"./miniStore.svelte.ts\";\n\nexport { miniStore, Timeline, Tween };\n\n/**\n * Svelte hook for updating values with Tween.\n *\n * @param initialValues - Initial tween values\n * @returns [store, tween] Tuple of reactive store and Tween instance\n *\n * @example\n * <script lang=\"ts\">\n * const [state, tween] = createTween({ x: 0, y: 0 })\n *\n * // configuration is free-form, no re-render ever happens\n * tween.to({ x: 100, y: 100 })\n *\n * onMount(() => {\n * tween.start()\n * })\n * </script>\n *\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n */\nexport function createTween<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Tween<T>] as const;\n }\n const store = miniStore(initialValues);\n const tween = new Tween(store);\n\n onDestroy(() => {\n tween.stop();\n tween.clear();\n });\n\n return [store, tween] as [T, Tween<T>];\n}\n\n/**\n * Svelte hook for sequencing values update with Timeline.\n *\n * @param initialValues - Initial tween values\n * @returns [store, timeline] Tuple of reactive store and Timeline instance\n *\n * @example\n * <script lang=\"ts\">\n * const [state, timeline] = createTimeline({ x: 0, y: 0 })\n *\n * // configuration is free-form\n * timeline.to({ x: 100, y: 100 })\n *\n * onMount(() => {\n * timeline.play()\n * })\n * </script>\n *\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n */\nexport function createTimeline<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Timeline<T>] as const;\n }\n const store = miniStore(initialValues);\n const timeline = new Timeline(store);\n\n onDestroy(() => {\n timeline.stop();\n timeline.clear();\n });\n\n return [store, timeline] as [T, Timeline<T>];\n}\n"],"mappings":";;;;;;;;;;;AAQA,MAAM,cAAc;AACpB,MAAM,aAAa;CACjB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,UAAU;CACX;AAED,SAAS,iBACP,OACA,OACA,QACA,WACA,iBACA;CACA,MAAM,aAAa,UAAU,YAAY;AAEzC,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,WAAyB,EAAE;EACjC,MAAM,WAAW,MAAM;AAEvB,QAAM,SAAS,KAAK,QAAQ;GAC1B,MAAM,gBAAgB,cAAc,QAAQ,WAAW;GACvD,IAAI,cAAc;AAElB,UAAO,eAAe,UAAU,KAAK;IACnC,WAAW;IACX,MAAM,aAAyB;AAC7B,mBAAc;AAGd,SAAI,cACF,kBAAiB;;IAGrB,YAAY;IACb,CAAC;IACF;AACF,SAAO,SAAS;QACX;EACL,IAAI,eAAe;EACnB,MAAM,eAAe;EACrB,MAAM,UAAU,WAAyB;AACvC,kBAAe;AACf,OAAI,WACF,kBAAiB;;AAGrB,SAAO,iBAAiB,QAAQ,GAC7B,QAAQ;GACP,KAAK;GACL,KAAK;GACL,YAAY;GACb,EACF,CAAC;;;AAIN,SAAS,iBACP,KACA,OACA,QACA;CACA,IAAI,QAAQ,OAAO,IAAI,MAAM;CAC7B,IAAI,eAAe;CACnB,IAAI;AAEJ,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,aAA2B,EAAE;EACnC,MAAM,YAAY,MAAM;EACxB,IAAI,UAAU,OAAO,IAAI,EAAE;EAC3B,MAAM,mBAAmB;AACzB,OAAK,IAAI,IAAI,GAAG,IAAI,WAAW,IAC7B,kBAAiB,GAAI,MAAmB,IAAI,YAAY,iBAAiB;AACvE,aAAU,IAAI;IACd;AAEJ,iBAAe;AACb,eAAY;AACZ,UAAO;;AAGT,UAAQ;QACH;AACL,YAAU,WAAyB,QAAQ;AAC3C,UAAQ;;AAGV,QAAO,iBAAiB,QAAQ;GAC7B,cAAc;GACd,MAAM;GACL,KAAK;GACL,KAAK;GACL,YAAY;GACb;EACF,CAAC;;AAGJ,SAAS,gBACP,KACA,gBACA;AACA,KAAI,cAAc,KAAK,YAAY,CAAE,QAAO;AAE5C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,CAC5C,KAAI,cAAc,MAAM,CACtB,CAAC,eAA8B,OAAO,gBAAgB,OAAO,EAAE,CAAC;KAEhE,kBAAiB,KAAK,OAAO,eAAe;AAIhD,QAAO;;AAGT,SAAgB,UAAgC,MAAS;AACvD,QAAO,gBAAgB,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AC5FlC,SAAgB,YAAkC,eAAkB;AAClE,KAAI,SACF,QAAO,CAAC,eAAe,cAAqC;CAE9D,MAAM,QAAQ,UAAU,cAAc;CACtC,MAAM,QAAQ,IAAI,MAAM,MAAM;AAE9B,iBAAgB;AACd,QAAM,MAAM;AACZ,QAAM,OAAO;GACb;AAEF,QAAO,CAAC,OAAO,MAAM;;;;;;;;;;;;;;;;;;;;;;AAuBvB,SAAgB,eAAqC,eAAkB;AACrE,KAAI,SACF,QAAO,CAAC,eAAe,cAAwC;CAEjE,MAAM,QAAQ,UAAU,cAAc;CACtC,MAAM,WAAW,IAAI,SAAS,MAAM;AAEpC,iBAAgB;AACd,WAAS,MAAM;AACf,WAAS,OAAO;GAChB;AAEF,QAAO,CAAC,OAAO,SAAS"}
1
+ {"version":3,"file":"svelte.mjs","names":[],"sources":["../../src/svelte/miniStore.svelte.ts","../../src/svelte/index.svelte.ts"],"sourcesContent":["import {\n type ArrayVal,\n isArray,\n isPlainObject,\n objectHasProp,\n type TweenProps,\n} from \"@thednp/tween\";\n\nconst STATE_PROXY = \"_proxy\";\nconst proxyProps = {\n value: 1,\n enumerable: false,\n configurable: false,\n writable: false,\n};\n\nfunction defineArrayProxy<T extends ArrayVal>(\n index: number,\n value: T[number] | ArrayVal,\n target: T | ArrayVal | ArrayVal[],\n sourceLen: number,\n notifyListeners: () => void,\n) {\n const itemIsLast = index === sourceLen - 1;\n\n if (isArray(value)) {\n const subArray: typeof value = [];\n const valueLen = value.length;\n\n value.forEach((itm, idx) => {\n const subItemIsLast = itemIsLast && idx === valueLen - 1;\n let currentItem = itm;\n\n Object.defineProperty(subArray, idx, {\n get: () => currentItem,\n set: (newValue: typeof itm) => {\n currentItem = newValue;\n\n // Only notify on last element to batch updates\n if (subItemIsLast) {\n notifyListeners();\n }\n },\n enumerable: true,\n });\n });\n target[index] = subArray;\n } else {\n let currentValue = value;\n const getter = () => currentValue;\n const setter = (newVal: typeof value) => {\n currentValue = newVal;\n if (itemIsLast) {\n notifyListeners();\n }\n };\n Object.defineProperties(target, {\n [index]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n }\n}\n\nfunction defineStateProxy<T extends Omit<TweenProps, \"_proxy\">>(\n key: number | keyof T,\n value: T[keyof T] | ArrayVal,\n target: T | ArrayVal,\n) {\n let state = $state.raw(value);\n let getter = () => state;\n let setter;\n\n if (isArray(value)) {\n const arrayProxy: typeof value = [];\n const valLength = value.length;\n let version = $state.raw(0);\n const getVersion = () => version;\n for (let i = 0; i < valLength; i++) {\n defineArrayProxy(i, (value as ArrayVal)[i], arrayProxy, valLength, () => {\n version = 1 - version;\n });\n }\n getter = () => {\n getVersion();\n return state;\n };\n\n state = arrayProxy;\n } else {\n setter = (newVal: typeof value) => state = newVal;\n state = value;\n }\n\n Object.defineProperties(target, {\n [STATE_PROXY]: proxyProps,\n [key]: {\n get: getter,\n set: setter,\n enumerable: true,\n },\n });\n}\n\nfunction createMiniState<T extends TweenProps>(\n obj: T,\n parentReceiver: TweenProps | number[] | [string, ...number[]][],\n) {\n if (objectHasProp(obj, STATE_PROXY)) return obj;\n\n for (const [key, value] of Object.entries(obj)) {\n if (isPlainObject(value)) {\n (parentReceiver as TweenProps)[key] = createMiniState(value, {});\n } else {\n defineStateProxy(key, value, parentReceiver);\n }\n }\n\n return parentReceiver as T;\n}\n\nexport function miniStore<T extends TweenProps>(init: T) {\n return createMiniState(init, {}) as T;\n}\n","import {\n dummyInstance,\n isServer,\n Timeline,\n Tween,\n type TweenProps,\n} from \"@thednp/tween\";\nimport { onDestroy } from \"svelte\";\nimport { miniStore } from \"./miniStore.svelte.ts\";\n\nexport { miniStore, Timeline, Tween };\n\n/**\n * Svelte hook for updating values with Tween.\n *\n * @param initialValues - Initial tween values\n * @returns [store, tween] Tuple of reactive store and Tween instance\n *\n * @example\n * <script lang=\"ts\">\n * const [state, tween] = createTween({ x: 0, y: 0 })\n *\n * // configuration is free-form, no re-render ever happens\n * tween.to({ x: 100, y: 100 })\n *\n * onMount(() => {\n * tween.start()\n * })\n * </script>\n *\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n */\nexport function createTween<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Tween<T>] as const;\n }\n const store = miniStore(initialValues);\n const tween = new Tween(store);\n\n onDestroy(() => {\n tween.stop();\n tween.clear();\n });\n\n return [store, tween] as [T, Tween<T>];\n}\n\n/**\n * Svelte hook for sequencing values update with Timeline.\n *\n * @param initialValues - Initial tween values\n * @returns [store, timeline] Tuple of reactive store and Timeline instance\n *\n * @example\n * <script lang=\"ts\">\n * const [state, timeline] = createTimeline({ x: 0, y: 0 })\n *\n * // configuration is free-form\n * timeline.to({ x: 100, y: 100 })\n *\n * onMount(() => {\n * timeline.play()\n * })\n * </script>\n *\n * <div style={{ translate: `${state.x}px ${state.y}px` }} />\n */\nexport function createTimeline<T extends TweenProps>(initialValues: T) {\n if (isServer) {\n return [initialValues, dummyInstance as unknown as Timeline<T>] as const;\n }\n const store = miniStore(initialValues);\n const timeline = new Timeline(store);\n\n onDestroy(() => {\n timeline.stop();\n timeline.clear();\n });\n\n return [store, timeline] as [T, Timeline<T>];\n}\n"],"mappings":";;;;;;;;;;AAQA,MAAM,cAAc;AACpB,MAAM,aAAa;CACjB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,UAAU;CACX;AAED,SAAS,iBACP,OACA,OACA,QACA,WACA,iBACA;CACA,MAAM,aAAa,UAAU,YAAY;AAEzC,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,WAAyB,EAAE;EACjC,MAAM,WAAW,MAAM;AAEvB,QAAM,SAAS,KAAK,QAAQ;GAC1B,MAAM,gBAAgB,cAAc,QAAQ,WAAW;GACvD,IAAI,cAAc;AAElB,UAAO,eAAe,UAAU,KAAK;IACnC,WAAW;IACX,MAAM,aAAyB;AAC7B,mBAAc;AAGd,SAAI,cACF,kBAAiB;;IAGrB,YAAY;IACb,CAAC;IACF;AACF,SAAO,SAAS;QACX;EACL,IAAI,eAAe;EACnB,MAAM,eAAe;EACrB,MAAM,UAAU,WAAyB;AACvC,kBAAe;AACf,OAAI,WACF,kBAAiB;;AAGrB,SAAO,iBAAiB,QAAQ,GAC7B,QAAQ;GACP,KAAK;GACL,KAAK;GACL,YAAY;GACb,EACF,CAAC;;;AAIN,SAAS,iBACP,KACA,OACA,QACA;CACA,IAAI,QAAQ,OAAO,IAAI,MAAM;CAC7B,IAAI,eAAe;CACnB,IAAI;AAEJ,KAAI,QAAQ,MAAM,EAAE;EAClB,MAAM,aAA2B,EAAE;EACnC,MAAM,YAAY,MAAM;EACxB,IAAI,UAAU,OAAO,IAAI,EAAE;EAC3B,MAAM,mBAAmB;AACzB,OAAK,IAAI,IAAI,GAAG,IAAI,WAAW,IAC7B,kBAAiB,GAAI,MAAmB,IAAI,YAAY,iBAAiB;AACvE,aAAU,IAAI;IACd;AAEJ,iBAAe;AACb,eAAY;AACZ,UAAO;;AAGT,UAAQ;QACH;AACL,YAAU,WAAyB,QAAQ;AAC3C,UAAQ;;AAGV,QAAO,iBAAiB,QAAQ;GAC7B,cAAc;GACd,MAAM;GACL,KAAK;GACL,KAAK;GACL,YAAY;GACb;EACF,CAAC;;AAGJ,SAAS,gBACP,KACA,gBACA;AACA,KAAI,cAAc,KAAK,YAAY,CAAE,QAAO;AAE5C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,CAC5C,KAAI,cAAc,MAAM,CACrB,gBAA8B,OAAO,gBAAgB,OAAO,EAAE,CAAC;KAEhE,kBAAiB,KAAK,OAAO,eAAe;AAIhD,QAAO;;AAGT,SAAgB,UAAgC,MAAS;AACvD,QAAO,gBAAgB,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AC5FlC,SAAgB,YAAkC,eAAkB;AAClE,KAAI,SACF,QAAO,CAAC,eAAe,cAAqC;CAE9D,MAAM,QAAQ,UAAU,cAAc;CACtC,MAAM,QAAQ,IAAI,MAAM,MAAM;AAE9B,iBAAgB;AACd,QAAM,MAAM;AACZ,QAAM,OAAO;GACb;AAEF,QAAO,CAAC,OAAO,MAAM;;;;;;;;;;;;;;;;;;;;;;AAuBvB,SAAgB,eAAqC,eAAkB;AACrE,KAAI,SACF,QAAO,CAAC,eAAe,cAAwC;CAEjE,MAAM,QAAQ,UAAU,cAAc;CACtC,MAAM,WAAW,IAAI,SAAS,MAAM;AAEpC,iBAAgB;AACd,WAAS,MAAM;AACf,WAAS,OAAO;GAChB;AAEF,QAAO,CAAC,OAAO,SAAS"}
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @thednp/tween utils for Svelte v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween utils for Svelte v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @thednp/tween utils for Svelte v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween utils for Svelte v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
@@ -7,7 +7,6 @@
7
7
 
8
8
  import { Timeline, Tween, dummyInstance, isArray, isPlainObject, isServer, objectHasProp } from "@thednp/tween";
9
9
  import { onDestroy } from "svelte";
10
-
11
10
  //#region src/svelte/miniStore.svelte.ts
12
11
  const STATE_PROXY = "_proxy";
13
12
  const proxyProps = {
@@ -87,7 +86,6 @@ function createMiniState(obj, parentReceiver) {
87
86
  function miniStore(init) {
88
87
  return createMiniState(init, {});
89
88
  }
90
-
91
89
  //#endregion
92
90
  //#region src/svelte/index.svelte.ts
93
91
  /**
@@ -150,7 +148,7 @@ function createTimeline(initialValues) {
150
148
  });
151
149
  return [store, timeline];
152
150
  }
153
-
154
151
  //#endregion
155
152
  export { Timeline, Tween, createTimeline, createTween, miniStore };
153
+
156
154
  //# sourceMappingURL=svelte.mjs.map
@@ -1,10 +1,12 @@
1
1
  /*!
2
- * @thednp/tween v0.0.4 (https://github.com/thednp/tween)
2
+ * @thednp/tween v0.1.0 (https://github.com/thednp/tween)
3
3
  * Copyright 2026 © thednp
4
4
  * Licensed under MIT (https://github.com/thednp/tween/blob/master/LICENSE)
5
5
  */
6
6
  "use strict";
7
7
 
8
+ import { equalizePaths, equalizeSegments, pathToString } from "svg-path-commander/util";
9
+
8
10
  //#region src/Tween.d.ts
9
11
  /**
10
12
  * Lightweight tween engine for interpolating values over time.
@@ -653,13 +655,6 @@ declare const isServer: boolean;
653
655
  */
654
656
  declare const dummyInstance: Record<string, typeof dummyMethod>;
655
657
  declare function dummyMethod(this: typeof dummyInstance): Record<string, typeof dummyMethod>;
656
- /**
657
- * Utility to round numbers to a specified number of decimals.
658
- * @param n Input number value
659
- * @param round Number of decimals
660
- * @returns The rounded number
661
- */
662
- declare const roundTo: (n: number, round: number) => number;
663
658
  declare const objectHasProp: <T extends object>(obj: T, prop: keyof T) => boolean;
664
659
  /**
665
660
  * A small utility to deep assign up to one level deep nested objects.
@@ -729,15 +724,6 @@ declare const arrayConfig: {
729
724
  };
730
725
  //#endregion
731
726
  //#region src/extend/path.d.ts
732
- /**
733
- * Iterates a `PathArray` value and concatenates the values into a string to return it.
734
- *
735
- * **NOTE**: Segment values are rounded to 4 decimals by default.
736
- * @param path A source PathArray
737
- * @param round An optional parameter to round segment values to a number of decimals
738
- * @returns A valid HTML `description` (d) path string value
739
- */
740
- declare function pathToString(path: MorphPathArray, round?: number): string;
741
727
  /**
742
728
  * Interpolate `PathArray` values.
743
729
  *
@@ -954,5 +940,5 @@ declare function removeFromQueue<T extends TweenProps>(removedItem: AnimationIte
954
940
  //#region package.json.d.ts
955
941
  declare let version: string;
956
942
  //#endregion
957
- export { AnimationItem, ArrayVal, BaseTweenProps, CubicValues, DeepObject, DeepPartial, Easing, EasingFunction, EasingFunctionGroup, InterpolatorFunction, LineValues, MorphPathArray, MorphPathSegment, PathLike, Position, PropConfig, QuadValues, Queue, Rotate, RotateAxisAngle, RotateZ, Runtime, Scale, Timeline, TimelineCallback, TimelineEntry, TimelineEntryConfig, TransformArray, TransformLike, TransformStep, TransformStepInternal, Translate, Tween, TweenCallback, TweenProps, TweenRuntime, TweenUpdateCallback, ValidationFunction, ValidationResultEntry, Vec3, addToQueue, arrayConfig, deepAssign, deproxy, dummyInstance, eulerToAxisAngle, interpolateArray, interpolateObject, interpolatePath, interpolateTransform, isArray, isDeepObject, isFunction, isNumber, isObject, isPathLike, isPlainObject, isServer, isString, isTransformLike, isValidArray, isValidPath, isValidTransformArray, now, objectConfig, objectHasProp, pathArrayConfig, pathToString, removeFromQueue, roundTo, setNow, transformConfig, transformToString, validateArray, validateObject, validatePath, validateTransform, validateValues, version };
943
+ export { AnimationItem, ArrayVal, BaseTweenProps, CubicValues, DeepObject, DeepPartial, Easing, EasingFunction, EasingFunctionGroup, InterpolatorFunction, LineValues, MorphPathArray, MorphPathSegment, PathLike, Position, PropConfig, QuadValues, Queue, Rotate, RotateAxisAngle, RotateZ, Runtime, Scale, Timeline, TimelineCallback, TimelineEntry, TimelineEntryConfig, TransformArray, TransformLike, TransformStep, TransformStepInternal, Translate, Tween, TweenCallback, TweenProps, TweenRuntime, TweenUpdateCallback, ValidationFunction, ValidationResultEntry, Vec3, addToQueue, arrayConfig, deepAssign, deproxy, dummyInstance, equalizePaths, equalizeSegments, eulerToAxisAngle, interpolateArray, interpolateObject, interpolatePath, interpolateTransform, isArray, isDeepObject, isFunction, isNumber, isObject, isPathLike, isPlainObject, isServer, isString, isTransformLike, isValidArray, isValidPath, isValidTransformArray, now, objectConfig, objectHasProp, pathArrayConfig, pathToString, removeFromQueue, setNow, transformConfig, transformToString, validateArray, validateObject, validatePath, validateTransform, validateValues, version };
958
944
  //# sourceMappingURL=index.d.mts.map