@motion-core/motion-gpu 0.3.0 → 0.4.1

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 (38) hide show
  1. package/README.md +72 -1
  2. package/dist/core/material-preprocess.d.ts +5 -5
  3. package/dist/core/material-preprocess.js +1 -4
  4. package/dist/core/material.d.ts +32 -23
  5. package/dist/core/material.js +14 -7
  6. package/dist/core/render-targets.d.ts +1 -0
  7. package/dist/core/runtime-loop.d.ts +1 -0
  8. package/dist/core/textures.d.ts +1 -0
  9. package/dist/core/types.d.ts +21 -10
  10. package/dist/passes/CopyPass.d.ts +1 -0
  11. package/dist/passes/FullscreenPass.d.ts +1 -0
  12. package/dist/react/FragCanvas.d.ts +27 -0
  13. package/dist/react/FragCanvas.js +218 -0
  14. package/dist/react/MotionGPUErrorOverlay.d.ts +6 -0
  15. package/dist/react/MotionGPUErrorOverlay.js +305 -0
  16. package/dist/react/Portal.d.ts +6 -0
  17. package/dist/react/Portal.js +24 -0
  18. package/dist/react/advanced.d.ts +11 -0
  19. package/dist/react/advanced.js +6 -0
  20. package/dist/react/frame-context.d.ts +14 -0
  21. package/dist/react/frame-context.js +98 -0
  22. package/dist/react/index.d.ts +15 -0
  23. package/dist/react/index.js +9 -0
  24. package/dist/react/motiongpu-context.d.ts +73 -0
  25. package/dist/react/motiongpu-context.js +18 -0
  26. package/dist/react/use-motiongpu-user-context.d.ts +49 -0
  27. package/dist/react/use-motiongpu-user-context.js +94 -0
  28. package/dist/react/use-texture.d.ts +40 -0
  29. package/dist/react/use-texture.js +162 -0
  30. package/dist/svelte/FragCanvas.svelte +8 -22
  31. package/dist/svelte/FragCanvas.svelte.d.ts +1 -0
  32. package/dist/svelte/MotionGPUErrorOverlay.svelte +17 -20
  33. package/dist/svelte/Portal.svelte +6 -21
  34. package/dist/svelte/use-motiongpu-user-context.d.ts +9 -1
  35. package/dist/svelte/use-motiongpu-user-context.js +4 -1
  36. package/dist/svelte/use-texture.d.ts +6 -2
  37. package/dist/svelte/use-texture.js +6 -2
  38. package/package.json +32 -4
@@ -94,14 +94,16 @@
94
94
 
95
95
  <style>
96
96
  .motiongpu-error-overlay {
97
- --motiongpu-color-background: var(--color-background, #ffffff);
98
- --motiongpu-color-background-muted: var(--color-background-inset, #f6f6f7);
99
- --motiongpu-color-foreground: var(--color-foreground, #262626);
100
- --motiongpu-color-foreground-muted: var(--color-foreground-muted, rgba(38, 38, 38, 0.64));
101
- --motiongpu-color-card: var(--color-background, #ffffff);
102
- --motiongpu-color-accent: var(--color-accent, #ff6900);
103
- --motiongpu-color-accent-secondary: var(--color-accent-secondary, #bd4d00);
104
- --motiongpu-color-border: var(--color-border, rgba(107, 107, 107, 0.2));
97
+ --motiongpu-base-hue: var(--base-hue, 265);
98
+ --motiongpu-color-background: oklch(0.2178 0.0056 var(--motiongpu-base-hue));
99
+ --motiongpu-color-background-muted: oklch(0.261 0.007 var(--motiongpu-base-hue));
100
+ --motiongpu-color-foreground: oklch(1 0 0);
101
+ --motiongpu-color-foreground-muted: oklch(0.6699 0.0081 var(--motiongpu-base-hue));
102
+ --motiongpu-color-card: var(--motiongpu-color-background);
103
+ --motiongpu-color-accent: oklch(0.6996 0.181959 44.4414);
104
+ --motiongpu-color-accent-secondary: oklch(0.5096 0.131959 44.4414);
105
+ --motiongpu-color-border: oklch(0.928 0.013 var(--motiongpu-base-hue) / 0.05);
106
+ --motiongpu-color-white-fixed: oklch(1 0 0);
105
107
  --motiongpu-shadow-card: var(
106
108
  --shadow-2xl,
107
109
  0px 1px 1px -0.5px rgba(0, 0, 0, 0.06),
@@ -128,12 +130,11 @@
128
130
  display: grid;
129
131
  place-items: center;
130
132
  padding: clamp(0.75rem, 1.4vw, 1.5rem);
131
- background:
132
- radial-gradient(125% 125% at 50% 0%, rgba(255, 105, 0, 0.12) 0%, rgba(255, 105, 0, 0) 56%),
133
- rgba(12, 12, 14, 0.38);
133
+ background: rgba(0, 0, 0, 0.8);
134
134
  backdrop-filter: blur(10px);
135
135
  z-index: 2147483647;
136
136
  font-family: var(--motiongpu-font-sans);
137
+ color-scheme: dark;
137
138
  }
138
139
 
139
140
  .motiongpu-error-dialog {
@@ -149,11 +150,7 @@
149
150
  font-size: 0.875rem;
150
151
  font-weight: 400;
151
152
  line-height: 1.45;
152
- background: linear-gradient(
153
- 180deg,
154
- var(--motiongpu-color-card) 0%,
155
- var(--motiongpu-color-background-muted) 100%
156
- );
153
+ background: var(--motiongpu-color-card);
157
154
  color: var(--motiongpu-color-foreground);
158
155
  box-shadow: var(--motiongpu-shadow-card);
159
156
  }
@@ -187,7 +184,7 @@
187
184
  line-height: 1;
188
185
  font-weight: 500;
189
186
  text-transform: uppercase;
190
- color: var(--motiongpu-color-background);
187
+ color: var(--motiongpu-color-white-fixed);
191
188
  background: linear-gradient(
192
189
  180deg,
193
190
  var(--motiongpu-color-accent) 0%,
@@ -215,9 +212,9 @@
215
212
  .motiongpu-error-message {
216
213
  margin: 0;
217
214
  padding: 0.72rem 0.78rem;
218
- border: 1px solid color-mix(in srgb, var(--motiongpu-color-accent) 28%, transparent);
215
+ border: 1px solid color-mix(in oklch, var(--motiongpu-color-accent) 28%, transparent);
219
216
  border-radius: var(--motiongpu-radius-md);
220
- background: color-mix(in srgb, var(--motiongpu-color-accent) 9%, var(--motiongpu-color-card));
217
+ background: color-mix(in oklch, var(--motiongpu-color-accent) 10%, transparent);
221
218
  font-size: 0.82rem;
222
219
  line-height: 1.4;
223
220
  font-weight: 400;
@@ -302,7 +299,7 @@
302
299
  }
303
300
 
304
301
  .motiongpu-error-source-row-active {
305
- background: color-mix(in srgb, var(--motiongpu-color-accent) 10%, transparent);
302
+ background: color-mix(in oklch, var(--motiongpu-color-accent) 10%, transparent);
306
303
  }
307
304
 
308
305
  .motiongpu-error-source-line {
@@ -14,33 +14,18 @@
14
14
  : (input ?? document.body);
15
15
  }
16
16
 
17
- const portal = (node: HTMLDivElement, initialTarget: string | HTMLElement | null) => {
18
- let targetElement = resolveTargetElement(initialTarget);
17
+ const portal = (node: HTMLDivElement) => {
18
+ const targetElement = resolveTargetElement(target);
19
19
  targetElement.appendChild(node);
20
20
 
21
- return {
22
- update(nextTarget: string | HTMLElement | null) {
23
- const nextTargetElement = resolveTargetElement(nextTarget);
24
- if (nextTargetElement === targetElement) {
25
- return;
26
- }
27
-
28
- if (node.parentNode === targetElement) {
29
- targetElement.removeChild(node);
30
- }
31
-
32
- nextTargetElement.appendChild(node);
33
- targetElement = nextTargetElement;
34
- },
35
- destroy() {
36
- if (node.parentNode === targetElement) {
37
- targetElement.removeChild(node);
38
- }
21
+ return () => {
22
+ if (node.parentNode === targetElement) {
23
+ targetElement.removeChild(node);
39
24
  }
40
25
  };
41
26
  };
42
27
  </script>
43
28
 
44
- <div use:portal={target}>
29
+ <div {@attach portal}>
45
30
  {@render children?.()}
46
31
  </div>
@@ -17,6 +17,14 @@ export interface SetMotionGPUUserContextOptions {
17
17
  * @default 'skip'
18
18
  */
19
19
  existing?: 'merge' | 'replace' | 'skip';
20
+ /**
21
+ * How function inputs should be interpreted:
22
+ * - `factory`: call function and store its return value
23
+ * - `value`: store function itself
24
+ *
25
+ * @default 'factory'
26
+ */
27
+ functionValue?: 'factory' | 'value';
20
28
  }
21
29
  /**
22
30
  * Returns a read-only view of the entire motiongpu user context store.
@@ -25,7 +33,7 @@ export declare function useMotionGPUUserContext<UC extends UserContextStore = Us
25
33
  /**
26
34
  * Reads a namespaced user context value as a reactive readable store.
27
35
  */
28
- export declare function useMotionGPUUserContext<UCT = unknown>(namespace: MotionGPUUserNamespace): CurrentReadable<UCT | undefined>;
36
+ export declare function useMotionGPUUserContext<UC extends UserContextStore = UserContextStore, K extends keyof UC & MotionGPUUserNamespace = keyof UC & MotionGPUUserNamespace>(namespace: K): CurrentReadable<UC[K] | undefined>;
29
37
  /**
30
38
  * Sets a namespaced user context value with explicit write semantics.
31
39
  *
@@ -43,6 +43,7 @@ export function useMotionGPUUserContext(namespace) {
43
43
  export function setMotionGPUUserContext(namespace, value, options) {
44
44
  const userStore = useMotionGPU().user;
45
45
  const mode = options?.existing ?? 'skip';
46
+ const functionValueMode = options?.functionValue ?? 'factory';
46
47
  let resolvedValue;
47
48
  userStore.update((context) => {
48
49
  const hasExisting = namespace in context;
@@ -50,7 +51,9 @@ export function setMotionGPUUserContext(namespace, value, options) {
50
51
  resolvedValue = context[namespace];
51
52
  return context;
52
53
  }
53
- const nextValue = typeof value === 'function' ? value() : value;
54
+ const nextValue = typeof value === 'function' && functionValueMode === 'factory'
55
+ ? value()
56
+ : value;
54
57
  if (hasExisting && mode === 'merge') {
55
58
  const currentValue = context[namespace];
56
59
  if (isObjectEntry(currentValue) && isObjectEntry(nextValue)) {
@@ -30,11 +30,15 @@ export interface UseTextureResult {
30
30
  * Supported URL input variants for `useTexture`.
31
31
  */
32
32
  export type TextureUrlInput = string[] | (() => string[]);
33
+ /**
34
+ * Supported options input variants for `useTexture`.
35
+ */
36
+ export type TextureOptionsInput = TextureLoadOptions | (() => TextureLoadOptions);
33
37
  /**
34
38
  * Loads textures from URLs and exposes reactive loading/error state.
35
39
  *
36
40
  * @param urlInput - URLs array or lazy URL provider.
37
- * @param options - Loader options passed to URL fetch/decode pipeline.
41
+ * @param optionsInput - Loader options object or lazy options provider.
38
42
  * @returns Reactive texture loading state with reload support.
39
43
  */
40
- export declare function useTexture(urlInput: TextureUrlInput, options?: TextureLoadOptions): UseTextureResult;
44
+ export declare function useTexture(urlInput: TextureUrlInput, optionsInput?: TextureOptionsInput): UseTextureResult;
@@ -54,10 +54,10 @@ function mergeAbortSignals(primary, secondary) {
54
54
  * Loads textures from URLs and exposes reactive loading/error state.
55
55
  *
56
56
  * @param urlInput - URLs array or lazy URL provider.
57
- * @param options - Loader options passed to URL fetch/decode pipeline.
57
+ * @param optionsInput - Loader options object or lazy options provider.
58
58
  * @returns Reactive texture loading state with reload support.
59
59
  */
60
- export function useTexture(urlInput, options = {}) {
60
+ export function useTexture(urlInput, optionsInput = {}) {
61
61
  const textures = currentWritable(null);
62
62
  const loading = currentWritable(true);
63
63
  const error = currentWritable(null);
@@ -68,6 +68,9 @@ export function useTexture(urlInput, options = {}) {
68
68
  let runningLoad = null;
69
69
  let reloadQueued = false;
70
70
  const getUrls = typeof urlInput === 'function' ? urlInput : () => urlInput;
71
+ const getOptions = typeof optionsInput === 'function'
72
+ ? optionsInput
73
+ : () => optionsInput;
71
74
  const executeLoad = async () => {
72
75
  if (disposed) {
73
76
  return;
@@ -79,6 +82,7 @@ export function useTexture(urlInput, options = {}) {
79
82
  error.set(null);
80
83
  errorReport.set(null);
81
84
  const previous = textures.current;
85
+ const options = getOptions() ?? {};
82
86
  const mergedSignal = mergeAbortSignals(controller.signal, options.signal);
83
87
  try {
84
88
  const loaded = await loadTexturesFromUrls(getUrls(), {
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@motion-core/motion-gpu",
3
- "version": "0.3.0",
4
- "description": "Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte adapter entrypoints.",
3
+ "version": "0.4.1",
4
+ "description": "Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte and React adapter entrypoints.",
5
5
  "keywords": [
6
6
  "svelte",
7
7
  "svelte5",
8
+ "react",
9
+ "react18",
8
10
  "webgpu",
9
11
  "wgsl",
10
12
  "shader",
@@ -46,6 +48,14 @@
46
48
  "svelte": "./dist/svelte/advanced.js",
47
49
  "default": "./dist/svelte/advanced.js"
48
50
  },
51
+ "./react": {
52
+ "types": "./dist/react/index.d.ts",
53
+ "default": "./dist/react/index.js"
54
+ },
55
+ "./react/advanced": {
56
+ "types": "./dist/react/advanced.d.ts",
57
+ "default": "./dist/react/advanced.js"
58
+ },
49
59
  "./core": {
50
60
  "types": "./dist/core/index.d.ts",
51
61
  "default": "./dist/core/index.js"
@@ -59,7 +69,8 @@
59
69
  "dist"
60
70
  ],
61
71
  "scripts": {
62
- "build": "svelte-package -i src/lib -o dist",
72
+ "build": "svelte-package -i src/lib -o dist && node ./scripts/build/transpile-react-tsx.mjs && node ./scripts/build/patch-webgpu-types-dts.mjs",
73
+ "build:watch": "svelte-package -i src/lib -o dist -w --preserve-output",
63
74
  "prepack": "bun run build",
64
75
  "check": "svelte-check --tsconfig ./tsconfig.json && publint",
65
76
  "test": "vitest run",
@@ -68,6 +79,8 @@
68
79
  "test:e2e": "playwright test",
69
80
  "test:e2e:headed": "playwright test --headed",
70
81
  "e2e:serve": "vite --config e2e/vite.config.ts",
82
+ "e2e:serve:svelte": "MOTION_GPU_E2E_FRAMEWORK=svelte vite --config e2e/vite.config.ts",
83
+ "e2e:serve:react": "MOTION_GPU_E2E_FRAMEWORK=react vite --config e2e/vite.config.ts",
71
84
  "perf:core": "bun run ./scripts/perf/core-benchmark.ts",
72
85
  "perf:core:check": "bun run ./scripts/perf/core-benchmark.ts --strict",
73
86
  "perf:core:baseline": "bun run ./scripts/perf/core-benchmark.ts --update-baseline",
@@ -78,23 +91,36 @@
78
91
  "format": "prettier --write ."
79
92
  },
80
93
  "peerDependencies": {
94
+ "react": "^18.0.0 || ^19.0.0",
95
+ "react-dom": "^18.0.0 || ^19.0.0",
81
96
  "svelte": "^5.0.0"
82
97
  },
83
98
  "peerDependenciesMeta": {
99
+ "react": {
100
+ "optional": true
101
+ },
102
+ "react-dom": {
103
+ "optional": true
104
+ },
84
105
  "svelte": {
85
106
  "optional": true
86
107
  }
87
108
  },
109
+ "dependencies": {
110
+ "@webgpu/types": "^0.1.66"
111
+ },
88
112
  "devDependencies": {
89
113
  "@eslint/compat": "^2.0.2",
90
114
  "@eslint/js": "^10.0.1",
91
115
  "@playwright/test": "^1.58.2",
92
116
  "@sveltejs/package": "^2.5.0",
93
117
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
118
+ "@testing-library/react": "^16.3.0",
94
119
  "@testing-library/svelte": "^5.2.8",
120
+ "@types/react": "^19.2.2",
121
+ "@types/react-dom": "^19.2.2",
95
122
  "@vitest/coverage-v8": "^4.0.18",
96
123
  "@types/node": "^25.3.3",
97
- "@webgpu/types": "^0.1.66",
98
124
  "eslint": "^10.0.2",
99
125
  "eslint-config-prettier": "^10.1.8",
100
126
  "eslint-plugin-svelte": "^3.14.0",
@@ -104,6 +130,8 @@
104
130
  "prettier-plugin-svelte": "^3.4.1",
105
131
  "prettier-plugin-tailwindcss": "^0.7.2",
106
132
  "publint": "^0.3.15",
133
+ "react": "^19.2.0",
134
+ "react-dom": "^19.2.0",
107
135
  "svelte": "^5.51.0",
108
136
  "svelte-check": "^4.3.6",
109
137
  "typescript": "^5.9.3",