@motion-core/motion-gpu 0.4.0 → 0.4.2

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.
Files changed (207) hide show
  1. package/dist/advanced.d.ts +1 -0
  2. package/dist/advanced.d.ts.map +1 -0
  3. package/dist/advanced.js +12 -6
  4. package/dist/core/advanced.d.ts +1 -0
  5. package/dist/core/advanced.d.ts.map +1 -0
  6. package/dist/core/advanced.js +12 -5
  7. package/dist/core/current-value.d.ts +1 -0
  8. package/dist/core/current-value.d.ts.map +1 -0
  9. package/dist/core/current-value.js +35 -34
  10. package/dist/core/current-value.js.map +1 -0
  11. package/dist/core/error-diagnostics.d.ts +1 -0
  12. package/dist/core/error-diagnostics.d.ts.map +1 -0
  13. package/dist/core/error-diagnostics.js +70 -137
  14. package/dist/core/error-diagnostics.js.map +1 -0
  15. package/dist/core/error-report.d.ts +1 -0
  16. package/dist/core/error-report.d.ts.map +1 -0
  17. package/dist/core/error-report.js +184 -233
  18. package/dist/core/error-report.js.map +1 -0
  19. package/dist/core/frame-registry.d.ts +1 -0
  20. package/dist/core/frame-registry.d.ts.map +1 -0
  21. package/dist/core/frame-registry.js +546 -662
  22. package/dist/core/frame-registry.js.map +1 -0
  23. package/dist/core/index.d.ts +1 -0
  24. package/dist/core/index.d.ts.map +1 -0
  25. package/dist/core/index.js +11 -12
  26. package/dist/core/material-preprocess.d.ts +1 -0
  27. package/dist/core/material-preprocess.d.ts.map +1 -0
  28. package/dist/core/material-preprocess.js +128 -151
  29. package/dist/core/material-preprocess.js.map +1 -0
  30. package/dist/core/material.d.ts +1 -0
  31. package/dist/core/material.d.ts.map +1 -0
  32. package/dist/core/material.js +263 -317
  33. package/dist/core/material.js.map +1 -0
  34. package/dist/core/recompile-policy.d.ts +1 -0
  35. package/dist/core/recompile-policy.d.ts.map +1 -0
  36. package/dist/core/recompile-policy.js +18 -13
  37. package/dist/core/recompile-policy.js.map +1 -0
  38. package/dist/core/render-graph.d.ts +1 -0
  39. package/dist/core/render-graph.d.ts.map +1 -0
  40. package/dist/core/render-graph.js +61 -68
  41. package/dist/core/render-graph.js.map +1 -0
  42. package/dist/core/render-targets.d.ts +2 -0
  43. package/dist/core/render-targets.d.ts.map +1 -0
  44. package/dist/core/render-targets.js +52 -53
  45. package/dist/core/render-targets.js.map +1 -0
  46. package/dist/core/renderer.d.ts +1 -0
  47. package/dist/core/renderer.d.ts.map +1 -0
  48. package/dist/core/renderer.js +942 -1081
  49. package/dist/core/renderer.js.map +1 -0
  50. package/dist/core/runtime-loop.d.ts +2 -0
  51. package/dist/core/runtime-loop.d.ts.map +1 -0
  52. package/dist/core/runtime-loop.js +305 -362
  53. package/dist/core/runtime-loop.js.map +1 -0
  54. package/dist/core/scheduler-helpers.d.ts +1 -0
  55. package/dist/core/scheduler-helpers.d.ts.map +1 -0
  56. package/dist/core/scheduler-helpers.js +52 -51
  57. package/dist/core/scheduler-helpers.js.map +1 -0
  58. package/dist/core/shader.d.ts +1 -0
  59. package/dist/core/shader.d.ts.map +1 -0
  60. package/dist/core/shader.js +92 -117
  61. package/dist/core/shader.js.map +1 -0
  62. package/dist/core/texture-loader.d.ts +1 -0
  63. package/dist/core/texture-loader.d.ts.map +1 -0
  64. package/dist/core/texture-loader.js +205 -273
  65. package/dist/core/texture-loader.js.map +1 -0
  66. package/dist/core/textures.d.ts +2 -0
  67. package/dist/core/textures.d.ts.map +1 -0
  68. package/dist/core/textures.js +106 -116
  69. package/dist/core/textures.js.map +1 -0
  70. package/dist/core/types.d.ts +2 -0
  71. package/dist/core/types.d.ts.map +1 -0
  72. package/dist/core/types.js +0 -4
  73. package/dist/core/uniforms.d.ts +1 -0
  74. package/dist/core/uniforms.d.ts.map +1 -0
  75. package/dist/core/uniforms.js +170 -191
  76. package/dist/core/uniforms.js.map +1 -0
  77. package/dist/index.d.ts +1 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +11 -6
  80. package/dist/passes/BlitPass.d.ts +1 -0
  81. package/dist/passes/BlitPass.d.ts.map +1 -0
  82. package/dist/passes/BlitPass.js +23 -18
  83. package/dist/passes/BlitPass.js.map +1 -0
  84. package/dist/passes/CopyPass.d.ts +2 -0
  85. package/dist/passes/CopyPass.d.ts.map +1 -0
  86. package/dist/passes/CopyPass.js +58 -52
  87. package/dist/passes/CopyPass.js.map +1 -0
  88. package/dist/passes/FullscreenPass.d.ts +2 -0
  89. package/dist/passes/FullscreenPass.d.ts.map +1 -0
  90. package/dist/passes/FullscreenPass.js +127 -130
  91. package/dist/passes/FullscreenPass.js.map +1 -0
  92. package/dist/passes/ShaderPass.d.ts +1 -0
  93. package/dist/passes/ShaderPass.d.ts.map +1 -0
  94. package/dist/passes/ShaderPass.js +40 -37
  95. package/dist/passes/ShaderPass.js.map +1 -0
  96. package/dist/passes/index.d.ts +1 -0
  97. package/dist/passes/index.d.ts.map +1 -0
  98. package/dist/passes/index.js +4 -3
  99. package/dist/react/FragCanvas.d.ts +2 -0
  100. package/dist/react/FragCanvas.d.ts.map +1 -0
  101. package/dist/react/FragCanvas.js +234 -211
  102. package/dist/react/FragCanvas.js.map +1 -0
  103. package/dist/react/MotionGPUErrorOverlay.d.ts +1 -0
  104. package/dist/react/MotionGPUErrorOverlay.d.ts.map +1 -0
  105. package/dist/react/MotionGPUErrorOverlay.js +384 -48
  106. package/dist/react/MotionGPUErrorOverlay.js.map +1 -0
  107. package/dist/react/Portal.d.ts +1 -0
  108. package/dist/react/Portal.d.ts.map +1 -0
  109. package/dist/react/Portal.js +18 -21
  110. package/dist/react/Portal.js.map +1 -0
  111. package/dist/react/advanced.d.ts +1 -0
  112. package/dist/react/advanced.d.ts.map +1 -0
  113. package/dist/react/advanced.js +12 -6
  114. package/dist/react/frame-context.d.ts +1 -0
  115. package/dist/react/frame-context.d.ts.map +1 -0
  116. package/dist/react/frame-context.js +88 -94
  117. package/dist/react/frame-context.js.map +1 -0
  118. package/dist/react/index.d.ts +1 -0
  119. package/dist/react/index.d.ts.map +1 -0
  120. package/dist/react/index.js +10 -9
  121. package/dist/react/motiongpu-context.d.ts +1 -0
  122. package/dist/react/motiongpu-context.d.ts.map +1 -0
  123. package/dist/react/motiongpu-context.js +18 -15
  124. package/dist/react/motiongpu-context.js.map +1 -0
  125. package/dist/react/use-motiongpu-user-context.d.ts +1 -0
  126. package/dist/react/use-motiongpu-user-context.d.ts.map +1 -0
  127. package/dist/react/use-motiongpu-user-context.js +83 -82
  128. package/dist/react/use-motiongpu-user-context.js.map +1 -0
  129. package/dist/react/use-texture.d.ts +1 -0
  130. package/dist/react/use-texture.d.ts.map +1 -0
  131. package/dist/react/use-texture.js +132 -152
  132. package/dist/react/use-texture.js.map +1 -0
  133. package/dist/svelte/FragCanvas.svelte.d.ts +2 -0
  134. package/dist/svelte/FragCanvas.svelte.d.ts.map +1 -0
  135. package/dist/svelte/MotionGPUErrorOverlay.svelte +17 -20
  136. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts +1 -0
  137. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts.map +1 -0
  138. package/dist/svelte/Portal.svelte.d.ts +1 -0
  139. package/dist/svelte/Portal.svelte.d.ts.map +1 -0
  140. package/dist/svelte/advanced.d.ts +1 -0
  141. package/dist/svelte/advanced.d.ts.map +1 -0
  142. package/dist/svelte/advanced.js +11 -6
  143. package/dist/svelte/frame-context.d.ts +1 -0
  144. package/dist/svelte/frame-context.d.ts.map +1 -0
  145. package/dist/svelte/frame-context.js +27 -27
  146. package/dist/svelte/frame-context.js.map +1 -0
  147. package/dist/svelte/index.d.ts +1 -0
  148. package/dist/svelte/index.d.ts.map +1 -0
  149. package/dist/svelte/index.js +10 -9
  150. package/dist/svelte/motiongpu-context.d.ts +1 -0
  151. package/dist/svelte/motiongpu-context.d.ts.map +1 -0
  152. package/dist/svelte/motiongpu-context.js +24 -21
  153. package/dist/svelte/motiongpu-context.js.map +1 -0
  154. package/dist/svelte/use-motiongpu-user-context.d.ts +1 -0
  155. package/dist/svelte/use-motiongpu-user-context.d.ts.map +1 -0
  156. package/dist/svelte/use-motiongpu-user-context.js +69 -70
  157. package/dist/svelte/use-motiongpu-user-context.js.map +1 -0
  158. package/dist/svelte/use-texture.d.ts +1 -0
  159. package/dist/svelte/use-texture.d.ts.map +1 -0
  160. package/dist/svelte/use-texture.js +125 -147
  161. package/dist/svelte/use-texture.js.map +1 -0
  162. package/package.json +15 -7
  163. package/src/lib/advanced.ts +6 -0
  164. package/src/lib/core/advanced.ts +12 -0
  165. package/src/lib/core/current-value.ts +64 -0
  166. package/src/lib/core/error-diagnostics.ts +236 -0
  167. package/src/lib/core/error-report.ts +406 -0
  168. package/src/lib/core/frame-registry.ts +1189 -0
  169. package/src/lib/core/index.ts +77 -0
  170. package/src/lib/core/material-preprocess.ts +284 -0
  171. package/src/lib/core/material.ts +667 -0
  172. package/src/lib/core/recompile-policy.ts +31 -0
  173. package/src/lib/core/render-graph.ts +143 -0
  174. package/src/lib/core/render-targets.ts +107 -0
  175. package/src/lib/core/renderer.ts +1547 -0
  176. package/src/lib/core/runtime-loop.ts +458 -0
  177. package/src/lib/core/scheduler-helpers.ts +136 -0
  178. package/src/lib/core/shader.ts +258 -0
  179. package/src/lib/core/texture-loader.ts +476 -0
  180. package/src/lib/core/textures.ts +235 -0
  181. package/src/lib/core/types.ts +582 -0
  182. package/src/lib/core/uniforms.ts +282 -0
  183. package/src/lib/index.ts +6 -0
  184. package/src/lib/passes/BlitPass.ts +54 -0
  185. package/src/lib/passes/CopyPass.ts +80 -0
  186. package/src/lib/passes/FullscreenPass.ts +173 -0
  187. package/src/lib/passes/ShaderPass.ts +88 -0
  188. package/src/lib/passes/index.ts +3 -0
  189. package/src/lib/react/MotionGPUErrorOverlay.tsx +392 -0
  190. package/src/lib/react/advanced.ts +36 -0
  191. package/src/lib/react/frame-context.ts +169 -0
  192. package/src/lib/react/index.ts +51 -0
  193. package/src/lib/react/motiongpu-context.ts +88 -0
  194. package/src/lib/react/use-motiongpu-user-context.ts +186 -0
  195. package/src/lib/react/use-texture.ts +233 -0
  196. package/src/lib/svelte/FragCanvas.svelte +249 -0
  197. package/src/lib/svelte/MotionGPUErrorOverlay.svelte +382 -0
  198. package/src/lib/svelte/Portal.svelte +31 -0
  199. package/src/lib/svelte/advanced.ts +32 -0
  200. package/src/lib/svelte/frame-context.ts +87 -0
  201. package/src/lib/svelte/index.ts +51 -0
  202. package/src/lib/svelte/motiongpu-context.ts +97 -0
  203. package/src/lib/svelte/use-motiongpu-user-context.ts +145 -0
  204. package/src/lib/svelte/use-texture.ts +232 -0
  205. package/dist/react/MotionGPUErrorOverlay.tsx +0 -129
  206. /package/{dist → src/lib}/react/FragCanvas.tsx +0 -0
  207. /package/{dist → src/lib}/react/Portal.tsx +0 -0
@@ -1,26 +1,29 @@
1
- import { getContext, setContext } from 'svelte';
1
+ import { getContext, setContext } from "svelte";
2
+ //#region src/lib/svelte/motiongpu-context.ts
2
3
  /**
3
- * Svelte context key used to expose `FragCanvas` runtime state.
4
- */
5
- const MOTIONGPU_CONTEXT_KEY = Symbol('motiongpu.context');
4
+ * Svelte context key used to expose `FragCanvas` runtime state.
5
+ */
6
+ var MOTIONGPU_CONTEXT_KEY = Symbol("motiongpu.context");
6
7
  /**
7
- * Registers the motiongpu context in the current Svelte component tree.
8
- *
9
- * @param context - Context payload to provide.
10
- */
11
- export function provideMotionGPUContext(context) {
12
- setContext(MOTIONGPU_CONTEXT_KEY, context);
8
+ * Registers the motiongpu context in the current Svelte component tree.
9
+ *
10
+ * @param context - Context payload to provide.
11
+ */
12
+ function provideMotionGPUContext(context) {
13
+ setContext(MOTIONGPU_CONTEXT_KEY, context);
13
14
  }
14
15
  /**
15
- * Returns the active motiongpu context.
16
- *
17
- * @returns Active context.
18
- * @throws {Error} When called outside `<FragCanvas>`.
19
- */
20
- export function useMotionGPU() {
21
- const context = getContext(MOTIONGPU_CONTEXT_KEY);
22
- if (!context) {
23
- throw new Error('useMotionGPU must be used inside <FragCanvas>');
24
- }
25
- return context;
16
+ * Returns the active motiongpu context.
17
+ *
18
+ * @returns Active context.
19
+ * @throws {Error} When called outside `<FragCanvas>`.
20
+ */
21
+ function useMotionGPU() {
22
+ const context = getContext(MOTIONGPU_CONTEXT_KEY);
23
+ if (!context) throw new Error("useMotionGPU must be used inside <FragCanvas>");
24
+ return context;
26
25
  }
26
+ //#endregion
27
+ export { provideMotionGPUContext, useMotionGPU };
28
+
29
+ //# sourceMappingURL=motiongpu-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motiongpu-context.js","names":[],"sources":["../../src/lib/svelte/motiongpu-context.ts"],"sourcesContent":["import { getContext, setContext } from 'svelte';\nimport type { RenderMode } from '../core/types.js';\nimport type { CurrentReadable, CurrentWritable } from '../core/current-value.js';\nimport type {\n\tFrameProfilingSnapshot,\n\tFrameRunTimings,\n\tFrameScheduleSnapshot\n} from '../core/frame-registry.js';\nimport type { MotionGPUScheduler as CoreMotionGPUScheduler } from '../core/scheduler-helpers.js';\n\n/**\n * Svelte context key used to expose `FragCanvas` runtime state.\n */\nconst MOTIONGPU_CONTEXT_KEY = Symbol('motiongpu.context');\n\nexport type MotionGPUScheduler = CoreMotionGPUScheduler;\nexport type { FrameProfilingSnapshot, FrameRunTimings, FrameScheduleSnapshot };\n\n/**\n * Namespace identifier for user-owned context entries.\n */\nexport type MotionGPUUserNamespace = string | symbol;\n\n/**\n * Shared user context store exposed by `FragCanvas`.\n */\nexport type MotionGPUUserContext = CurrentWritable<Record<MotionGPUUserNamespace, unknown>>;\n\n/**\n * Public `FragCanvas` runtime context available to hooks and user components.\n */\nexport interface MotionGPUContext {\n\t/**\n\t * Underlying canvas element used by the renderer.\n\t */\n\tcanvas: HTMLCanvasElement | undefined;\n\t/**\n\t * Reactive canvas pixel size.\n\t */\n\tsize: CurrentReadable<{ width: number; height: number }>;\n\t/**\n\t * Device pixel ratio multiplier.\n\t */\n\tdpr: CurrentWritable<number>;\n\t/**\n\t * Max frame delta clamp passed to scheduled callbacks.\n\t */\n\tmaxDelta: CurrentWritable<number>;\n\t/**\n\t * Scheduler render mode (`always`, `on-demand`, `manual`).\n\t */\n\trenderMode: CurrentWritable<RenderMode>;\n\t/**\n\t * Global toggle for automatic rendering.\n\t */\n\tautoRender: CurrentWritable<boolean>;\n\t/**\n\t * Namespaced user context store shared within the canvas subtree.\n\t */\n\tuser: MotionGPUUserContext;\n\t/**\n\t * Marks current frame as invalidated.\n\t */\n\tinvalidate: () => void;\n\t/**\n\t * Requests one manual frame advance.\n\t */\n\tadvance: () => void;\n\t/**\n\t * Public scheduler API.\n\t */\n\tscheduler: MotionGPUScheduler;\n}\n\n/**\n * Registers the motiongpu context in the current Svelte component tree.\n *\n * @param context - Context payload to provide.\n */\nexport function provideMotionGPUContext(context: MotionGPUContext): void {\n\tsetContext(MOTIONGPU_CONTEXT_KEY, context);\n}\n\n/**\n * Returns the active motiongpu context.\n *\n * @returns Active context.\n * @throws {Error} When called outside `<FragCanvas>`.\n */\nexport function useMotionGPU(): MotionGPUContext {\n\tconst context = getContext<MotionGPUContext>(MOTIONGPU_CONTEXT_KEY);\n\tif (!context) {\n\t\tthrow new Error('useMotionGPU must be used inside <FragCanvas>');\n\t}\n\n\treturn context;\n}\n"],"mappings":";;;;;AAaA,IAAM,wBAAwB,OAAO,oBAAoB;;;;;;AAkEzD,SAAgB,wBAAwB,SAAiC;AACxE,YAAW,uBAAuB,QAAQ;;;;;;;;AAS3C,SAAgB,eAAiC;CAChD,MAAM,UAAU,WAA6B,sBAAsB;AACnE,KAAI,CAAC,QACJ,OAAM,IAAI,MAAM,gDAAgD;AAGjE,QAAO"}
@@ -41,3 +41,4 @@ export declare function useMotionGPUUserContext<UC extends UserContextStore = Us
41
41
  */
42
42
  export declare function setMotionGPUUserContext<UCT = unknown>(namespace: MotionGPUUserNamespace, value: UCT | (() => UCT), options?: SetMotionGPUUserContextOptions): UCT | undefined;
43
43
  export {};
44
+ //# sourceMappingURL=use-motiongpu-user-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-motiongpu-user-context.d.ts","sourceRoot":"","sources":["../../src/lib/svelte/use-motiongpu-user-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAgB,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEnF;;GAEG;AACH,KAAK,gBAAgB,GAAG,MAAM,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;AAOhE;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACxC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CACpC;AASD;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,EAAE,SAAS,gBAAgB,GAAG,gBAAgB,KAC1C,eAAe,CAAC,EAAE,CAAC,CAAC;AAEzB;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,EAAE,SAAS,gBAAgB,GAAG,gBAAgB,EAC9C,CAAC,SAAS,MAAM,EAAE,GAAG,sBAAsB,GAAG,MAAM,EAAE,GAAG,sBAAsB,EAC9E,SAAS,EAAE,CAAC,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAwCpD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,GAAG,OAAO,EACpD,SAAS,EAAE,sBAAsB,EACjC,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EACxB,OAAO,CAAC,EAAE,8BAA8B,GACtC,GAAG,GAAG,SAAS,CAuCjB"}
@@ -1,77 +1,76 @@
1
- import { useMotionGPU } from './motiongpu-context.js';
1
+ import { useMotionGPU } from "./motiongpu-context.js";
2
+ //#region src/lib/svelte/use-motiongpu-user-context.ts
2
3
  /**
3
- * Checks whether a value is a non-array object suitable for shallow merge.
4
- */
4
+ * Checks whether a value is a non-array object suitable for shallow merge.
5
+ */
5
6
  function isObjectEntry(value) {
6
- return typeof value === 'object' && value !== null && !Array.isArray(value);
7
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7
8
  }
8
9
  /**
9
- * Read-only user context hook:
10
- * - no args: returns full user context store
11
- * - namespace: returns namespaced store view
12
- *
13
- * @param namespace - Optional namespace key.
14
- */
15
- export function useMotionGPUUserContext(namespace) {
16
- const userStore = useMotionGPU().user;
17
- if (namespace === undefined) {
18
- const allStore = {
19
- get current() {
20
- return userStore.current;
21
- },
22
- subscribe(run) {
23
- return userStore.subscribe((context) => run(context));
24
- }
25
- };
26
- return allStore;
27
- }
28
- const scopedStore = {
29
- get current() {
30
- return userStore.current[namespace];
31
- },
32
- subscribe(run) {
33
- return userStore.subscribe((context) => run(context[namespace]));
34
- }
35
- };
36
- return scopedStore;
10
+ * Read-only user context hook:
11
+ * - no args: returns full user context store
12
+ * - namespace: returns namespaced store view
13
+ *
14
+ * @param namespace - Optional namespace key.
15
+ */
16
+ function useMotionGPUUserContext(namespace) {
17
+ const userStore = useMotionGPU().user;
18
+ if (namespace === void 0) return {
19
+ get current() {
20
+ return userStore.current;
21
+ },
22
+ subscribe(run) {
23
+ return userStore.subscribe((context) => run(context));
24
+ }
25
+ };
26
+ return {
27
+ get current() {
28
+ return userStore.current[namespace];
29
+ },
30
+ subscribe(run) {
31
+ return userStore.subscribe((context) => run(context[namespace]));
32
+ }
33
+ };
37
34
  }
38
35
  /**
39
- * Sets a namespaced user context value with explicit write semantics.
40
- *
41
- * Returns the effective value stored under the namespace.
42
- */
43
- export function setMotionGPUUserContext(namespace, value, options) {
44
- const userStore = useMotionGPU().user;
45
- const mode = options?.existing ?? 'skip';
46
- const functionValueMode = options?.functionValue ?? 'factory';
47
- let resolvedValue;
48
- userStore.update((context) => {
49
- const hasExisting = namespace in context;
50
- if (hasExisting && mode === 'skip') {
51
- resolvedValue = context[namespace];
52
- return context;
53
- }
54
- const nextValue = typeof value === 'function' && functionValueMode === 'factory'
55
- ? value()
56
- : value;
57
- if (hasExisting && mode === 'merge') {
58
- const currentValue = context[namespace];
59
- if (isObjectEntry(currentValue) && isObjectEntry(nextValue)) {
60
- resolvedValue = {
61
- ...currentValue,
62
- ...nextValue
63
- };
64
- return {
65
- ...context,
66
- [namespace]: resolvedValue
67
- };
68
- }
69
- }
70
- resolvedValue = nextValue;
71
- return {
72
- ...context,
73
- [namespace]: nextValue
74
- };
75
- });
76
- return resolvedValue;
36
+ * Sets a namespaced user context value with explicit write semantics.
37
+ *
38
+ * Returns the effective value stored under the namespace.
39
+ */
40
+ function setMotionGPUUserContext(namespace, value, options) {
41
+ const userStore = useMotionGPU().user;
42
+ const mode = options?.existing ?? "skip";
43
+ const functionValueMode = options?.functionValue ?? "factory";
44
+ let resolvedValue;
45
+ userStore.update((context) => {
46
+ const hasExisting = namespace in context;
47
+ if (hasExisting && mode === "skip") {
48
+ resolvedValue = context[namespace];
49
+ return context;
50
+ }
51
+ const nextValue = typeof value === "function" && functionValueMode === "factory" ? value() : value;
52
+ if (hasExisting && mode === "merge") {
53
+ const currentValue = context[namespace];
54
+ if (isObjectEntry(currentValue) && isObjectEntry(nextValue)) {
55
+ resolvedValue = {
56
+ ...currentValue,
57
+ ...nextValue
58
+ };
59
+ return {
60
+ ...context,
61
+ [namespace]: resolvedValue
62
+ };
63
+ }
64
+ }
65
+ resolvedValue = nextValue;
66
+ return {
67
+ ...context,
68
+ [namespace]: nextValue
69
+ };
70
+ });
71
+ return resolvedValue;
77
72
  }
73
+ //#endregion
74
+ export { setMotionGPUUserContext, useMotionGPUUserContext };
75
+
76
+ //# sourceMappingURL=use-motiongpu-user-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-motiongpu-user-context.js","names":[],"sources":["../../src/lib/svelte/use-motiongpu-user-context.ts"],"sourcesContent":["import type { CurrentReadable } from '../core/current-value.js';\nimport { useMotionGPU, type MotionGPUUserNamespace } from './motiongpu-context.js';\n\n/**\n * Internal shape of the user context store.\n */\ntype UserContextStore = Record<MotionGPUUserNamespace, unknown>;\n\n/**\n * Object-like context payload used by merge semantics.\n */\ntype UserContextEntry = Record<string, unknown>;\n\n/**\n * Controls how a namespaced user context value behaves when already present.\n */\nexport interface SetMotionGPUUserContextOptions {\n\t/**\n\t * Conflict strategy when namespace already exists:\n\t * - `skip`: keep current value\n\t * - `replace`: replace current value\n\t * - `merge`: shallow merge object values, fallback to replace otherwise\n\t *\n\t * @default 'skip'\n\t */\n\texisting?: 'merge' | 'replace' | 'skip';\n\t/**\n\t * How function inputs should be interpreted:\n\t * - `factory`: call function and store its return value\n\t * - `value`: store function itself\n\t *\n\t * @default 'factory'\n\t */\n\tfunctionValue?: 'factory' | 'value';\n}\n\n/**\n * Checks whether a value is a non-array object suitable for shallow merge.\n */\nfunction isObjectEntry(value: unknown): value is UserContextEntry {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Returns a read-only view of the entire motiongpu user context store.\n */\nexport function useMotionGPUUserContext<\n\tUC extends UserContextStore = UserContextStore\n>(): CurrentReadable<UC>;\n\n/**\n * Reads a namespaced user context value as a reactive readable store.\n */\nexport function useMotionGPUUserContext<\n\tUC extends UserContextStore = UserContextStore,\n\tK extends keyof UC & MotionGPUUserNamespace = keyof UC & MotionGPUUserNamespace\n>(namespace: K): CurrentReadable<UC[K] | undefined>;\n\n/**\n * Read-only user context hook:\n * - no args: returns full user context store\n * - namespace: returns namespaced store view\n *\n * @param namespace - Optional namespace key.\n */\nexport function useMotionGPUUserContext<\n\tUC extends UserContextStore = UserContextStore,\n\tK extends keyof UC & MotionGPUUserNamespace = keyof UC & MotionGPUUserNamespace\n>(namespace?: K): CurrentReadable<UC> | CurrentReadable<UC[K] | undefined> {\n\tconst userStore = useMotionGPU().user;\n\n\tif (namespace === undefined) {\n\t\tconst allStore: CurrentReadable<UC> = {\n\t\t\tget current() {\n\t\t\t\treturn userStore.current as UC;\n\t\t\t},\n\t\t\tsubscribe(run) {\n\t\t\t\treturn userStore.subscribe((context) => run(context as UC));\n\t\t\t}\n\t\t};\n\n\t\treturn allStore;\n\t}\n\n\tconst scopedStore: CurrentReadable<UC[K] | undefined> = {\n\t\tget current() {\n\t\t\treturn userStore.current[namespace] as UC[K] | undefined;\n\t\t},\n\t\tsubscribe(run) {\n\t\t\treturn userStore.subscribe((context) => run(context[namespace] as UC[K] | undefined));\n\t\t}\n\t};\n\n\treturn scopedStore;\n}\n\n/**\n * Sets a namespaced user context value with explicit write semantics.\n *\n * Returns the effective value stored under the namespace.\n */\nexport function setMotionGPUUserContext<UCT = unknown>(\n\tnamespace: MotionGPUUserNamespace,\n\tvalue: UCT | (() => UCT),\n\toptions?: SetMotionGPUUserContextOptions\n): UCT | undefined {\n\tconst userStore = useMotionGPU().user;\n\tconst mode = options?.existing ?? 'skip';\n\tconst functionValueMode = options?.functionValue ?? 'factory';\n\tlet resolvedValue: UCT | undefined;\n\n\tuserStore.update((context) => {\n\t\tconst hasExisting = namespace in context;\n\t\tif (hasExisting && mode === 'skip') {\n\t\t\tresolvedValue = context[namespace] as UCT | undefined;\n\t\t\treturn context;\n\t\t}\n\n\t\tconst nextValue =\n\t\t\ttypeof value === 'function' && functionValueMode === 'factory'\n\t\t\t\t? (value as () => UCT)()\n\t\t\t\t: (value as UCT);\n\t\tif (hasExisting && mode === 'merge') {\n\t\t\tconst currentValue = context[namespace];\n\t\t\tif (isObjectEntry(currentValue) && isObjectEntry(nextValue)) {\n\t\t\t\tresolvedValue = {\n\t\t\t\t\t...currentValue,\n\t\t\t\t\t...nextValue\n\t\t\t\t} as UCT;\n\t\t\t\treturn {\n\t\t\t\t\t...context,\n\t\t\t\t\t[namespace]: resolvedValue\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tresolvedValue = nextValue;\n\t\treturn {\n\t\t\t...context,\n\t\t\t[namespace]: nextValue\n\t\t};\n\t});\n\n\treturn resolvedValue;\n}\n"],"mappings":";;;;;AAuCA,SAAS,cAAc,OAA2C;AACjE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;;;;;;;;AAyB5E,SAAgB,wBAGd,WAAyE;CAC1E,MAAM,YAAY,cAAc,CAAC;AAEjC,KAAI,cAAc,OAUjB,QATsC;EACrC,IAAI,UAAU;AACb,UAAO,UAAU;;EAElB,UAAU,KAAK;AACd,UAAO,UAAU,WAAW,YAAY,IAAI,QAAc,CAAC;;EAE5D;AAcF,QATwD;EACvD,IAAI,UAAU;AACb,UAAO,UAAU,QAAQ;;EAE1B,UAAU,KAAK;AACd,UAAO,UAAU,WAAW,YAAY,IAAI,QAAQ,WAAgC,CAAC;;EAEtF;;;;;;;AAUF,SAAgB,wBACf,WACA,OACA,SACkB;CAClB,MAAM,YAAY,cAAc,CAAC;CACjC,MAAM,OAAO,SAAS,YAAY;CAClC,MAAM,oBAAoB,SAAS,iBAAiB;CACpD,IAAI;AAEJ,WAAU,QAAQ,YAAY;EAC7B,MAAM,cAAc,aAAa;AACjC,MAAI,eAAe,SAAS,QAAQ;AACnC,mBAAgB,QAAQ;AACxB,UAAO;;EAGR,MAAM,YACL,OAAO,UAAU,cAAc,sBAAsB,YACjD,OAAqB,GACrB;AACL,MAAI,eAAe,SAAS,SAAS;GACpC,MAAM,eAAe,QAAQ;AAC7B,OAAI,cAAc,aAAa,IAAI,cAAc,UAAU,EAAE;AAC5D,oBAAgB;KACf,GAAG;KACH,GAAG;KACH;AACD,WAAO;KACN,GAAG;MACF,YAAY;KACb;;;AAIH,kBAAgB;AAChB,SAAO;GACN,GAAG;IACF,YAAY;GACb;GACA;AAEF,QAAO"}
@@ -42,3 +42,4 @@ export type TextureOptionsInput = TextureLoadOptions | (() => TextureLoadOptions
42
42
  * @returns Reactive texture loading state with reload support.
43
43
  */
44
44
  export declare function useTexture(urlInput: TextureUrlInput, optionsInput?: TextureOptionsInput): UseTextureResult;
45
+ //# sourceMappingURL=use-texture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-texture.d.ts","sourceRoot":"","sources":["../../src/lib/svelte/use-texture.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,eAAe,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGN,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAA0B,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE5F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,QAAQ,EAAE,eAAe,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,CAAC;IAClD;;OAEG;IACH,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAClC;;OAEG;IACH,KAAK,EAAE,eAAe,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACrC;;OAEG;IACH,WAAW,EAAE,eAAe,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC1D;;OAEG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,GAAG,CAAC,MAAM,kBAAkB,CAAC,CAAC;AAkElF;;;;;;GAMG;AACH,wBAAgB,UAAU,CACzB,QAAQ,EAAE,eAAe,EACzB,YAAY,GAAE,mBAAwB,GACpC,gBAAgB,CA4GlB"}
@@ -1,157 +1,135 @@
1
- import { onDestroy } from 'svelte';
2
- import { createCurrentWritable as currentWritable } from '../core/current-value.js';
3
- import { isAbortError, loadTexturesFromUrls } from '../core/texture-loader.js';
4
- import { toMotionGPUErrorReport } from '../core/error-report.js';
1
+ import { toMotionGPUErrorReport } from "../core/error-report.js";
2
+ import { createCurrentWritable } from "../core/current-value.js";
3
+ import { isAbortError, loadTexturesFromUrls } from "../core/texture-loader.js";
4
+ import { onDestroy } from "svelte";
5
+ //#region src/lib/svelte/use-texture.ts
5
6
  /**
6
- * Normalizes unknown thrown values to an `Error` instance.
7
- */
7
+ * Normalizes unknown thrown values to an `Error` instance.
8
+ */
8
9
  function toError(error) {
9
- if (error instanceof Error) {
10
- return error;
11
- }
12
- return new Error('Unknown texture loading error');
10
+ if (error instanceof Error) return error;
11
+ return /* @__PURE__ */ new Error("Unknown texture loading error");
13
12
  }
14
13
  /**
15
- * Releases GPU-side resources for a list of loaded textures.
16
- */
14
+ * Releases GPU-side resources for a list of loaded textures.
15
+ */
17
16
  function disposeTextures(list) {
18
- for (const texture of list ?? []) {
19
- texture.dispose();
20
- }
17
+ for (const texture of list ?? []) texture.dispose();
21
18
  }
22
19
  function mergeAbortSignals(primary, secondary) {
23
- if (!secondary) {
24
- return {
25
- signal: primary,
26
- dispose: () => { }
27
- };
28
- }
29
- if (typeof AbortSignal.any === 'function') {
30
- return {
31
- signal: AbortSignal.any([primary, secondary]),
32
- dispose: () => { }
33
- };
34
- }
35
- const fallback = new AbortController();
36
- let disposed = false;
37
- const cleanup = () => {
38
- if (disposed) {
39
- return;
40
- }
41
- disposed = true;
42
- primary.removeEventListener('abort', abort);
43
- secondary.removeEventListener('abort', abort);
44
- };
45
- const abort = () => fallback.abort();
46
- primary.addEventListener('abort', abort, { once: true });
47
- secondary.addEventListener('abort', abort, { once: true });
48
- return {
49
- signal: fallback.signal,
50
- dispose: cleanup
51
- };
20
+ if (!secondary) return {
21
+ signal: primary,
22
+ dispose: () => {}
23
+ };
24
+ if (typeof AbortSignal.any === "function") return {
25
+ signal: AbortSignal.any([primary, secondary]),
26
+ dispose: () => {}
27
+ };
28
+ const fallback = new AbortController();
29
+ let disposed = false;
30
+ const cleanup = () => {
31
+ if (disposed) return;
32
+ disposed = true;
33
+ primary.removeEventListener("abort", abort);
34
+ secondary.removeEventListener("abort", abort);
35
+ };
36
+ const abort = () => fallback.abort();
37
+ primary.addEventListener("abort", abort, { once: true });
38
+ secondary.addEventListener("abort", abort, { once: true });
39
+ return {
40
+ signal: fallback.signal,
41
+ dispose: cleanup
42
+ };
52
43
  }
53
44
  /**
54
- * Loads textures from URLs and exposes reactive loading/error state.
55
- *
56
- * @param urlInput - URLs array or lazy URL provider.
57
- * @param optionsInput - Loader options object or lazy options provider.
58
- * @returns Reactive texture loading state with reload support.
59
- */
60
- export function useTexture(urlInput, optionsInput = {}) {
61
- const textures = currentWritable(null);
62
- const loading = currentWritable(true);
63
- const error = currentWritable(null);
64
- const errorReport = currentWritable(null);
65
- let disposed = false;
66
- let requestVersion = 0;
67
- let activeController = null;
68
- let runningLoad = null;
69
- let reloadQueued = false;
70
- const getUrls = typeof urlInput === 'function' ? urlInput : () => urlInput;
71
- const getOptions = typeof optionsInput === 'function'
72
- ? optionsInput
73
- : () => optionsInput;
74
- const executeLoad = async () => {
75
- if (disposed) {
76
- return;
77
- }
78
- const version = ++requestVersion;
79
- const controller = new AbortController();
80
- activeController = controller;
81
- loading.set(true);
82
- error.set(null);
83
- errorReport.set(null);
84
- const previous = textures.current;
85
- const options = getOptions() ?? {};
86
- const mergedSignal = mergeAbortSignals(controller.signal, options.signal);
87
- try {
88
- const loaded = await loadTexturesFromUrls(getUrls(), {
89
- ...options,
90
- signal: mergedSignal.signal
91
- });
92
- if (disposed || version !== requestVersion) {
93
- disposeTextures(loaded);
94
- return;
95
- }
96
- textures.set(loaded);
97
- disposeTextures(previous);
98
- }
99
- catch (nextError) {
100
- if (disposed || version !== requestVersion) {
101
- return;
102
- }
103
- if (isAbortError(nextError)) {
104
- return;
105
- }
106
- disposeTextures(previous);
107
- textures.set(null);
108
- const normalizedError = toError(nextError);
109
- error.set(normalizedError);
110
- errorReport.set(toMotionGPUErrorReport(normalizedError, 'initialization'));
111
- }
112
- finally {
113
- if (!disposed && version === requestVersion) {
114
- loading.set(false);
115
- }
116
- if (activeController === controller) {
117
- activeController = null;
118
- }
119
- mergedSignal.dispose();
120
- }
121
- };
122
- const runLoadLoop = async () => {
123
- do {
124
- reloadQueued = false;
125
- await executeLoad();
126
- } while (reloadQueued && !disposed);
127
- };
128
- const load = () => {
129
- activeController?.abort();
130
- if (runningLoad) {
131
- reloadQueued = true;
132
- return runningLoad;
133
- }
134
- const pending = runLoadLoop();
135
- const trackedPending = pending.finally(() => {
136
- if (runningLoad === trackedPending) {
137
- runningLoad = null;
138
- }
139
- });
140
- runningLoad = trackedPending;
141
- return trackedPending;
142
- };
143
- void load();
144
- onDestroy(() => {
145
- disposed = true;
146
- requestVersion += 1;
147
- activeController?.abort();
148
- disposeTextures(textures.current);
149
- });
150
- return {
151
- textures,
152
- loading,
153
- error,
154
- errorReport,
155
- reload: load
156
- };
45
+ * Loads textures from URLs and exposes reactive loading/error state.
46
+ *
47
+ * @param urlInput - URLs array or lazy URL provider.
48
+ * @param optionsInput - Loader options object or lazy options provider.
49
+ * @returns Reactive texture loading state with reload support.
50
+ */
51
+ function useTexture(urlInput, optionsInput = {}) {
52
+ const textures = createCurrentWritable(null);
53
+ const loading = createCurrentWritable(true);
54
+ const error = createCurrentWritable(null);
55
+ const errorReport = createCurrentWritable(null);
56
+ let disposed = false;
57
+ let requestVersion = 0;
58
+ let activeController = null;
59
+ let runningLoad = null;
60
+ let reloadQueued = false;
61
+ const getUrls = typeof urlInput === "function" ? urlInput : () => urlInput;
62
+ const getOptions = typeof optionsInput === "function" ? optionsInput : () => optionsInput;
63
+ const executeLoad = async () => {
64
+ if (disposed) return;
65
+ const version = ++requestVersion;
66
+ const controller = new AbortController();
67
+ activeController = controller;
68
+ loading.set(true);
69
+ error.set(null);
70
+ errorReport.set(null);
71
+ const previous = textures.current;
72
+ const options = getOptions() ?? {};
73
+ const mergedSignal = mergeAbortSignals(controller.signal, options.signal);
74
+ try {
75
+ const loaded = await loadTexturesFromUrls(getUrls(), {
76
+ ...options,
77
+ signal: mergedSignal.signal
78
+ });
79
+ if (disposed || version !== requestVersion) {
80
+ disposeTextures(loaded);
81
+ return;
82
+ }
83
+ textures.set(loaded);
84
+ disposeTextures(previous);
85
+ } catch (nextError) {
86
+ if (disposed || version !== requestVersion) return;
87
+ if (isAbortError(nextError)) return;
88
+ disposeTextures(previous);
89
+ textures.set(null);
90
+ const normalizedError = toError(nextError);
91
+ error.set(normalizedError);
92
+ errorReport.set(toMotionGPUErrorReport(normalizedError, "initialization"));
93
+ } finally {
94
+ if (!disposed && version === requestVersion) loading.set(false);
95
+ if (activeController === controller) activeController = null;
96
+ mergedSignal.dispose();
97
+ }
98
+ };
99
+ const runLoadLoop = async () => {
100
+ do {
101
+ reloadQueued = false;
102
+ await executeLoad();
103
+ } while (reloadQueued && !disposed);
104
+ };
105
+ const load = () => {
106
+ activeController?.abort();
107
+ if (runningLoad) {
108
+ reloadQueued = true;
109
+ return runningLoad;
110
+ }
111
+ const trackedPending = runLoadLoop().finally(() => {
112
+ if (runningLoad === trackedPending) runningLoad = null;
113
+ });
114
+ runningLoad = trackedPending;
115
+ return trackedPending;
116
+ };
117
+ load();
118
+ onDestroy(() => {
119
+ disposed = true;
120
+ requestVersion += 1;
121
+ activeController?.abort();
122
+ disposeTextures(textures.current);
123
+ });
124
+ return {
125
+ textures,
126
+ loading,
127
+ error,
128
+ errorReport,
129
+ reload: load
130
+ };
157
131
  }
132
+ //#endregion
133
+ export { useTexture };
134
+
135
+ //# sourceMappingURL=use-texture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-texture.js","names":[],"sources":["../../src/lib/svelte/use-texture.ts"],"sourcesContent":["import { onDestroy } from 'svelte';\nimport {\n\tcreateCurrentWritable as currentWritable,\n\ttype CurrentReadable\n} from '../core/current-value.js';\nimport {\n\tisAbortError,\n\tloadTexturesFromUrls,\n\ttype LoadedTexture,\n\ttype TextureLoadOptions\n} from '../core/texture-loader.js';\nimport { toMotionGPUErrorReport, type MotionGPUErrorReport } from '../core/error-report.js';\n\n/**\n * Reactive state returned by {@link useTexture}.\n */\nexport interface UseTextureResult {\n\t/**\n\t * Loaded textures or `null` when unavailable/failed.\n\t */\n\ttextures: CurrentReadable<LoadedTexture[] | null>;\n\t/**\n\t * `true` while an active load request is running.\n\t */\n\tloading: CurrentReadable<boolean>;\n\t/**\n\t * Last loading error.\n\t */\n\terror: CurrentReadable<Error | null>;\n\t/**\n\t * Last loading error normalized to MotionGPU diagnostics report shape.\n\t */\n\terrorReport: CurrentReadable<MotionGPUErrorReport | null>;\n\t/**\n\t * Reloads all textures using current URL input.\n\t */\n\treload: () => Promise<void>;\n}\n\n/**\n * Supported URL input variants for `useTexture`.\n */\nexport type TextureUrlInput = string[] | (() => string[]);\n\n/**\n * Supported options input variants for `useTexture`.\n */\nexport type TextureOptionsInput = TextureLoadOptions | (() => TextureLoadOptions);\n\n/**\n * Normalizes unknown thrown values to an `Error` instance.\n */\nfunction toError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\n\treturn new Error('Unknown texture loading error');\n}\n\n/**\n * Releases GPU-side resources for a list of loaded textures.\n */\nfunction disposeTextures(list: LoadedTexture[] | null): void {\n\tfor (const texture of list ?? []) {\n\t\ttexture.dispose();\n\t}\n}\n\ninterface MergedAbortSignal {\n\tsignal: AbortSignal;\n\tdispose: () => void;\n}\n\nfunction mergeAbortSignals(\n\tprimary: AbortSignal,\n\tsecondary: AbortSignal | undefined\n): MergedAbortSignal {\n\tif (!secondary) {\n\t\treturn {\n\t\t\tsignal: primary,\n\t\t\tdispose: () => {}\n\t\t};\n\t}\n\n\tif (typeof AbortSignal.any === 'function') {\n\t\treturn {\n\t\t\tsignal: AbortSignal.any([primary, secondary]),\n\t\t\tdispose: () => {}\n\t\t};\n\t}\n\n\tconst fallback = new AbortController();\n\tlet disposed = false;\n\tconst cleanup = (): void => {\n\t\tif (disposed) {\n\t\t\treturn;\n\t\t}\n\t\tdisposed = true;\n\t\tprimary.removeEventListener('abort', abort);\n\t\tsecondary.removeEventListener('abort', abort);\n\t};\n\tconst abort = (): void => fallback.abort();\n\n\tprimary.addEventListener('abort', abort, { once: true });\n\tsecondary.addEventListener('abort', abort, { once: true });\n\n\treturn {\n\t\tsignal: fallback.signal,\n\t\tdispose: cleanup\n\t};\n}\n\n/**\n * Loads textures from URLs and exposes reactive loading/error state.\n *\n * @param urlInput - URLs array or lazy URL provider.\n * @param optionsInput - Loader options object or lazy options provider.\n * @returns Reactive texture loading state with reload support.\n */\nexport function useTexture(\n\turlInput: TextureUrlInput,\n\toptionsInput: TextureOptionsInput = {}\n): UseTextureResult {\n\tconst textures = currentWritable<LoadedTexture[] | null>(null);\n\tconst loading = currentWritable(true);\n\tconst error = currentWritable<Error | null>(null);\n\tconst errorReport = currentWritable<MotionGPUErrorReport | null>(null);\n\tlet disposed = false;\n\tlet requestVersion = 0;\n\tlet activeController: AbortController | null = null;\n\tlet runningLoad: Promise<void> | null = null;\n\tlet reloadQueued = false;\n\tconst getUrls = typeof urlInput === 'function' ? urlInput : () => urlInput;\n\tconst getOptions =\n\t\ttypeof optionsInput === 'function'\n\t\t\t? (optionsInput as () => TextureLoadOptions)\n\t\t\t: () => optionsInput;\n\n\tconst executeLoad = async (): Promise<void> => {\n\t\tif (disposed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst version = ++requestVersion;\n\t\tconst controller = new AbortController();\n\t\tactiveController = controller;\n\t\tloading.set(true);\n\t\terror.set(null);\n\t\terrorReport.set(null);\n\n\t\tconst previous = textures.current;\n\t\tconst options = getOptions() ?? {};\n\t\tconst mergedSignal = mergeAbortSignals(controller.signal, options.signal);\n\t\ttry {\n\t\t\tconst loaded = await loadTexturesFromUrls(getUrls(), {\n\t\t\t\t...options,\n\t\t\t\tsignal: mergedSignal.signal\n\t\t\t});\n\t\t\tif (disposed || version !== requestVersion) {\n\t\t\t\tdisposeTextures(loaded);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttextures.set(loaded);\n\t\t\tdisposeTextures(previous);\n\t\t} catch (nextError) {\n\t\t\tif (disposed || version !== requestVersion) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (isAbortError(nextError)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdisposeTextures(previous);\n\t\t\ttextures.set(null);\n\t\t\tconst normalizedError = toError(nextError);\n\t\t\terror.set(normalizedError);\n\t\t\terrorReport.set(toMotionGPUErrorReport(normalizedError, 'initialization'));\n\t\t} finally {\n\t\t\tif (!disposed && version === requestVersion) {\n\t\t\t\tloading.set(false);\n\t\t\t}\n\t\t\tif (activeController === controller) {\n\t\t\t\tactiveController = null;\n\t\t\t}\n\t\t\tmergedSignal.dispose();\n\t\t}\n\t};\n\n\tconst runLoadLoop = async (): Promise<void> => {\n\t\tdo {\n\t\t\treloadQueued = false;\n\t\t\tawait executeLoad();\n\t\t} while (reloadQueued && !disposed);\n\t};\n\n\tconst load = (): Promise<void> => {\n\t\tactiveController?.abort();\n\t\tif (runningLoad) {\n\t\t\treloadQueued = true;\n\t\t\treturn runningLoad;\n\t\t}\n\n\t\tconst pending = runLoadLoop();\n\t\tconst trackedPending = pending.finally(() => {\n\t\t\tif (runningLoad === trackedPending) {\n\t\t\t\trunningLoad = null;\n\t\t\t}\n\t\t});\n\t\trunningLoad = trackedPending;\n\t\treturn trackedPending;\n\t};\n\n\tvoid load();\n\n\tonDestroy(() => {\n\t\tdisposed = true;\n\t\trequestVersion += 1;\n\t\tactiveController?.abort();\n\t\tdisposeTextures(textures.current);\n\t});\n\n\treturn {\n\t\ttextures,\n\t\tloading,\n\t\terror,\n\t\terrorReport,\n\t\treload: load\n\t};\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motion-core/motion-gpu",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte and React adapter entrypoints.",
5
5
  "keywords": [
6
6
  "svelte",
@@ -66,10 +66,16 @@
66
66
  }
67
67
  },
68
68
  "files": [
69
- "dist"
69
+ "dist",
70
+ "!dist/**/*.test.*",
71
+ "!dist/**/*.spec.*",
72
+ "src/lib",
73
+ "!src/lib/**/*.test.*",
74
+ "!src/lib/**/*.spec.*"
70
75
  ],
71
76
  "scripts": {
72
- "build": "svelte-package -i src/lib -o dist && node ./scripts/build/transpile-react-tsx.mjs",
77
+ "build": "vite build --config ./vite.package.config.ts",
78
+ "build:watch": "vite build --watch --config ./vite.package.config.ts",
73
79
  "prepack": "bun run build",
74
80
  "check": "svelte-check --tsconfig ./tsconfig.json && publint",
75
81
  "test": "vitest run",
@@ -105,19 +111,20 @@
105
111
  "optional": true
106
112
  }
107
113
  },
114
+ "dependencies": {
115
+ "@webgpu/types": "^0.1.66"
116
+ },
108
117
  "devDependencies": {
109
118
  "@eslint/compat": "^2.0.2",
110
119
  "@eslint/js": "^10.0.1",
111
120
  "@playwright/test": "^1.58.2",
112
- "@sveltejs/package": "^2.5.0",
113
- "@sveltejs/vite-plugin-svelte": "^6.2.4",
121
+ "@sveltejs/vite-plugin-svelte": "^7.0.0",
114
122
  "@testing-library/react": "^16.3.0",
115
123
  "@testing-library/svelte": "^5.2.8",
116
124
  "@types/react": "^19.2.2",
117
125
  "@types/react-dom": "^19.2.2",
118
126
  "@vitest/coverage-v8": "^4.0.18",
119
127
  "@types/node": "^25.3.3",
120
- "@webgpu/types": "^0.1.66",
121
128
  "eslint": "^10.0.2",
122
129
  "eslint-config-prettier": "^10.1.8",
123
130
  "eslint-plugin-svelte": "^3.14.0",
@@ -130,10 +137,11 @@
130
137
  "react": "^19.2.0",
131
138
  "react-dom": "^19.2.0",
132
139
  "svelte": "^5.51.0",
140
+ "svelte2tsx": "^0.7.51",
133
141
  "svelte-check": "^4.3.6",
134
142
  "typescript": "^5.9.3",
135
143
  "typescript-eslint": "^8.54.0",
136
- "vite": "^7.3.1",
144
+ "vite": "^8.0.1",
137
145
  "vitest": "^4.0.18"
138
146
  }
139
147
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Root advanced package entrypoint.
3
+ *
4
+ * Framework-agnostic advanced core entrypoint.
5
+ */
6
+ export * from './core/advanced.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Framework-agnostic advanced MotionGPU core entrypoint.
3
+ */
4
+ export * from './index.js';
5
+ export { applySchedulerPreset, captureSchedulerDebugSnapshot } from './scheduler-helpers.js';
6
+ export type {
7
+ ApplySchedulerPresetOptions,
8
+ MotionGPUScheduler,
9
+ SchedulerDebugSnapshot,
10
+ SchedulerPreset,
11
+ SchedulerPresetConfig
12
+ } from './scheduler-helpers.js';