motion 13.1.1-alpha.0 → 13.2.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.
@@ -0,0 +1,192 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var dom = require('framer-motion/dom');
6
+
7
+ /**
8
+ * Binds motion values to Three.js objects, materials and uniforms.
9
+ *
10
+ * Register with `animate.addEffect(threeEffect)` so `animate()` can target
11
+ * meshes, lights, cameras, materials and uniforms directly, or call it
12
+ * yourself to wire up existing motion values:
13
+ *
14
+ * ```ts
15
+ * threeEffect(mesh, { x, rotateY, color })
16
+ * threeEffect(uniforms, { progress })
17
+ * ```
18
+ *
19
+ * Writes happen once per frame in `frame.preRender`, ahead of render loops
20
+ * scheduled with `frame.render`.
21
+ */
22
+ const threeEffect = dom.createEffect((subject, state, key, value) => state.set(key, value, () => setObjectValue(subject, key, state.latest[key]), undefined, false), {
23
+ test: isThreeSubject,
24
+ read: getObjectValue,
25
+ step: dom.frame.preRender,
26
+ });
27
+ /**
28
+ * Claims Three.js objects, materials and uniforms objects. Vectors, colors
29
+ * and Eulers aren't claimed so `animate(mesh.position, { x })` keeps working
30
+ * as a plain object animation.
31
+ */
32
+ function isThreeSubject(subject) {
33
+ if (!subject || typeof subject !== "object")
34
+ return false;
35
+ const object = subject;
36
+ return Boolean(object.isObject3D || object.isMaterial || isUniforms(object));
37
+ }
38
+ function isUniforms(object) {
39
+ const keys = Object.keys(object);
40
+ return keys.length > 0 && keys.every((key) => isUniform(object[key]));
41
+ }
42
+ const transformMap = {
43
+ x: ["position", "x"],
44
+ y: ["position", "y"],
45
+ z: ["position", "z"],
46
+ rotateX: ["rotation", "x"],
47
+ rotateY: ["rotation", "y"],
48
+ rotateZ: ["rotation", "z"],
49
+ scaleX: ["scale", "x"],
50
+ scaleY: ["scale", "y"],
51
+ scaleZ: ["scale", "z"],
52
+ };
53
+ function getObjectValue(object, key) {
54
+ if (isUniform(object[key]))
55
+ return getAnimatableValue(object[key].value);
56
+ const transform = transformMap[key];
57
+ if (transform) {
58
+ const [name, axis] = transform;
59
+ const value = object[name]?.[axis];
60
+ return key.startsWith("rotate") && typeof value === "number"
61
+ ? value * (180 / Math.PI)
62
+ : getAnimatableValue(value);
63
+ }
64
+ if (key === "scale") {
65
+ return getAnimatableValue(object.scale?.x);
66
+ }
67
+ const node = getNodeUniform(object, key);
68
+ if (node)
69
+ return getAnimatableValue(node.value);
70
+ const uniforms = getUniforms(object);
71
+ return (getProperty(object, key) ??
72
+ getProperty(object.material, key) ??
73
+ getUniformValue(uniforms, key) ??
74
+ getVectorComponent(object, key) ??
75
+ getVectorComponent(object.material, key) ??
76
+ getUniformComponent(uniforms, key) ??
77
+ getUniformComponent(object, key));
78
+ }
79
+ /**
80
+ * Uniforms live on ShaderMaterials, on the mesh itself or the subject can
81
+ * be a bare uniforms object.
82
+ */
83
+ function getUniforms(object) {
84
+ return object.material?.uniforms ?? object.uniforms;
85
+ }
86
+ /**
87
+ * Resolves TSL uniform nodes assigned to node material slots, e.g.
88
+ * material.colorNode = uniform(color). Non-uniform nodes are compiled
89
+ * into the shader so can't be animated via their value.
90
+ */
91
+ function getNodeUniform(object, key) {
92
+ const node = object[key + "Node"] ?? object.material?.[key + "Node"];
93
+ return node?.isUniformNode ? node : undefined;
94
+ }
95
+ function getProperty(target, key) {
96
+ return target && key in target ? getAnimatableValue(target[key]) : undefined;
97
+ }
98
+ function getUniformValue(uniforms, key) {
99
+ return getAnimatableValue(uniforms?.[key]?.value);
100
+ }
101
+ function getVectorComponent(target, key) {
102
+ const axis = key.slice(-1).toLowerCase();
103
+ const vector = target?.[key.slice(0, -1)];
104
+ return vector && ["x", "y", "z", "w"].includes(axis)
105
+ ? getAnimatableValue(vector[axis])
106
+ : undefined;
107
+ }
108
+ function getUniformComponent(uniforms, key) {
109
+ const uniform = uniforms?.[key.slice(0, -1)];
110
+ return isUniform(uniform)
111
+ ? getVectorComponent(uniform, `value${key.slice(-1)}`)
112
+ : undefined;
113
+ }
114
+ function getAnimatableValue(value) {
115
+ if (typeof value === "string" || typeof value === "number")
116
+ return value;
117
+ return value && typeof value.getStyle === "function"
118
+ ? value.getStyle()
119
+ : undefined;
120
+ }
121
+ function isUniform(value) {
122
+ return Boolean(value && typeof value === "object" && "value" in value);
123
+ }
124
+ function setObjectValue(object, key, value) {
125
+ if (isUniform(object[key])) {
126
+ setProperty(object[key], "value", value);
127
+ return;
128
+ }
129
+ const transform = transformMap[key];
130
+ if (transform) {
131
+ const [name, axis] = transform;
132
+ object[name][axis] = key.startsWith("rotate")
133
+ ? value * (Math.PI / 180)
134
+ : value;
135
+ return;
136
+ }
137
+ if (key === "scale") {
138
+ object.scale.x = object.scale.y = object.scale.z = value;
139
+ return;
140
+ }
141
+ const node = getNodeUniform(object, key);
142
+ if (node) {
143
+ setProperty(node, "value", value);
144
+ return;
145
+ }
146
+ if (setProperty(object, key, value))
147
+ return;
148
+ const material = object.material;
149
+ if (setProperty(material, key, value))
150
+ return;
151
+ const uniforms = getUniforms(object);
152
+ const uniform = uniforms?.[key];
153
+ if (uniform) {
154
+ setProperty(uniform, "value", value);
155
+ return;
156
+ }
157
+ if (setVectorComponent(object, key, value) ||
158
+ setVectorComponent(material, key, value) ||
159
+ setUniformComponent(uniforms, key, value) ||
160
+ setUniformComponent(object, key, value)) {
161
+ return;
162
+ }
163
+ object[key] = value;
164
+ }
165
+ function setProperty(target, key, value) {
166
+ if (!target || !(key in target))
167
+ return false;
168
+ const current = target[key];
169
+ if (current && typeof current.set === "function") {
170
+ Array.isArray(value) ? current.set(...value) : current.set(value);
171
+ }
172
+ else {
173
+ target[key] = value;
174
+ }
175
+ return true;
176
+ }
177
+ function setVectorComponent(target, key, value) {
178
+ const axis = key.slice(-1).toLowerCase();
179
+ const vector = target?.[key.slice(0, -1)];
180
+ if (!vector || !["x", "y", "z", "w"].includes(axis))
181
+ return false;
182
+ vector[axis] = value;
183
+ return true;
184
+ }
185
+ function setUniformComponent(uniforms, key, value) {
186
+ const uniform = uniforms?.[key.slice(0, -1)];
187
+ return isUniform(uniform)
188
+ ? setVectorComponent(uniform, `value${key.slice(-1)}`, value)
189
+ : false;
190
+ }
191
+
192
+ exports.threeEffect = threeEffect;
@@ -0,0 +1,248 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var dom = require('framer-motion/dom');
6
+
7
+ const axes = "xyzw";
8
+ const radiansPerDegree = Math.PI / 180;
9
+ const transforms = {
10
+ x: ["position", 0],
11
+ y: ["position", 1],
12
+ z: ["position", 2],
13
+ rotateX: ["rotation", 0, true],
14
+ rotateY: ["rotation", 1, true],
15
+ rotateZ: ["rotation", 2, true],
16
+ scaleX: ["scale", 0],
17
+ scaleY: ["scale", 1],
18
+ scaleZ: ["scale", 2],
19
+ };
20
+ /**
21
+ * Last vector written to each path. vgpu subjects like Effect and
22
+ * SharedUniforms have no getters, and SceneNode stores rotation as a
23
+ * quaternion, so this is how single components find their siblings.
24
+ */
25
+ const shadows = new WeakMap();
26
+ /**
27
+ * Values changed this frame, flushed into one set() per subject.
28
+ */
29
+ const pending = new Map();
30
+ function flush() {
31
+ pending.forEach(applyValues);
32
+ pending.clear();
33
+ }
34
+ /**
35
+ * Binds motion values to vgpu shared uniforms, Effect/Draw/Compute bindings
36
+ * ("params.time"), scene nodes (x, rotateY, scale), cameras, lights,
37
+ * materials, orbit controls and target clear colors.
38
+ *
39
+ * Register with `animate.addEffect(vgpuEffect)` so `animate()` can target
40
+ * these subjects directly, or call it yourself to wire up existing motion
41
+ * values:
42
+ *
43
+ * ```ts
44
+ * vgpuEffect(wave, { "params.time": time })
45
+ * vgpuEffect(cube, { x, rotateY })
46
+ * ```
47
+ *
48
+ * Changed values are batched into a single set() per subject per frame in
49
+ * `frame.preRender`, ahead of render loops scheduled with `frame.render`.
50
+ */
51
+ const vgpuEffect = dom.createEffect((subject, state, key, value) => state.set(key, value, () => {
52
+ const bag = pending.get(subject) ?? {};
53
+ bag[key] = state.latest[key];
54
+ pending.set(subject, bag);
55
+ dom.frame.preRender(flush, false, true);
56
+ }, undefined, false), {
57
+ test: isVGPUSubject,
58
+ read: readInitial,
59
+ step: dom.frame.preRender,
60
+ });
61
+ /**
62
+ * Claims vgpu shader units (Effect, Draw, Compute), shared uniforms, scene
63
+ * nodes, materials, orbit controls and targets. Everything else, including
64
+ * Three.js vectors and plain objects, is left alone.
65
+ */
66
+ function isVGPUSubject(subject) {
67
+ if (!subject || typeof subject !== "object")
68
+ return false;
69
+ const s = subject;
70
+ return typeof s.set === "function"
71
+ ? typeof s.kind === "string" ||
72
+ "gpu" in s ||
73
+ "reflection" in s ||
74
+ typeof s.yaw === "number"
75
+ : "clearColor" in s && "gpu" in s;
76
+ }
77
+ function isNode(subject) {
78
+ return "quaternion" in subject;
79
+ }
80
+ function isVector(value) {
81
+ return Array.isArray(value) || ArrayBuffer.isView(value);
82
+ }
83
+ function resolveKey(subject, key) {
84
+ const transform = isNode(subject) && transforms[key];
85
+ if (transform) {
86
+ return {
87
+ path: [transform[0]],
88
+ index: transform[1],
89
+ degrees: transform[2],
90
+ };
91
+ }
92
+ const path = key.split(".");
93
+ const last = path[path.length - 1];
94
+ const index = axes.indexOf(last.slice(-1).toLowerCase());
95
+ if (last.length > 1 && index !== -1) {
96
+ const base = [...path.slice(0, -1), last.slice(0, -1)];
97
+ if (getVector(subject, base))
98
+ return { path: base, index };
99
+ }
100
+ return { path };
101
+ }
102
+ function readPath(subject, path) {
103
+ return path.reduce((value, key) => value?.[key], subject);
104
+ }
105
+ /**
106
+ * Reads a subject property, falling back to ShaderMaterial's `values` record.
107
+ */
108
+ function readValue(subject, path) {
109
+ return (readPath(subject, path) ??
110
+ (subject.values && readPath(subject.values, path)));
111
+ }
112
+ function getVector(subject, path) {
113
+ const value = readValue(subject, path);
114
+ if (isVector(value))
115
+ return Array.from(value);
116
+ const shadow = shadows.get(subject)?.[path.join(".")];
117
+ if (shadow)
118
+ return shadow;
119
+ return path[0] === "rotation" && isNode(subject)
120
+ ? eulerFromQuaternion(subject.quaternion)
121
+ : undefined;
122
+ }
123
+ function setShadow(subject, path, vector) {
124
+ const shadow = shadows.get(subject) ?? {};
125
+ shadow[path.join(".")] = vector;
126
+ shadows.set(subject, shadow);
127
+ }
128
+ function setPath(target, path, value) {
129
+ var _a;
130
+ const last = path.length - 1;
131
+ let current = target;
132
+ for (let i = 0; i < last; i++) {
133
+ current = current[_a = path[i]] ?? (current[_a] = {});
134
+ }
135
+ current[path[last]] = value;
136
+ }
137
+ function isColorTarget(target) {
138
+ const sample = Array.isArray(target)
139
+ ? target.find((value) => typeof value === "string")
140
+ : target;
141
+ return typeof sample === "string" && dom.color.test(sample);
142
+ }
143
+ function readInitial(subject, key, target) {
144
+ const { path, index, degrees } = resolveKey(subject, key);
145
+ if (index !== undefined) {
146
+ const value = getVector(subject, path)?.[index];
147
+ return degrees && value !== undefined ? value / radiansPerDegree : value;
148
+ }
149
+ const value = readValue(subject, path);
150
+ if (typeof value === "number")
151
+ return value;
152
+ if (!isVector(value))
153
+ return undefined;
154
+ if (isColorTarget(target))
155
+ return toColorString(value);
156
+ const sample = Array.isArray(target)
157
+ ? target.find((keyframe) => keyframe !== null)
158
+ : target;
159
+ // A numeric target on a vector reads the first component (uniform scale)
160
+ return typeof sample === "string" ? Array.from(value).join(" ") : value[0];
161
+ }
162
+ function applyValues(values, subject) {
163
+ const bag = {};
164
+ const vectors = new Map();
165
+ for (const key in values) {
166
+ const target = resolveKey(subject, key);
167
+ const { path, index, degrees } = target;
168
+ const value = values[key];
169
+ if (index === undefined) {
170
+ const parsed = parseValue(value, getVector(subject, path));
171
+ Array.isArray(parsed) && setShadow(subject, path, parsed);
172
+ setPath(bag, path, parsed);
173
+ continue;
174
+ }
175
+ const id = path.join(".");
176
+ const entry = vectors.get(id) ?? {
177
+ ...target,
178
+ vector: getVector(subject, path) ?? [],
179
+ };
180
+ vectors.set(id, entry);
181
+ entry.vector[index] = degrees
182
+ ? value * radiansPerDegree
183
+ : value;
184
+ }
185
+ vectors.forEach(({ path, vector }) => {
186
+ setShadow(subject, path, vector);
187
+ setPath(bag, path, vector);
188
+ });
189
+ typeof subject.set === "function"
190
+ ? subject.set(bag)
191
+ : Object.assign(subject, bag);
192
+ }
193
+ /**
194
+ * Converts animated strings into vgpu values: CSS colors become linear RGB
195
+ * (matching vgpu/scene's srgb()), "1 0 0" becomes [1, 0, 0].
196
+ */
197
+ function parseValue(value, current) {
198
+ if (typeof value !== "string")
199
+ return value;
200
+ if (dom.color.test(value)) {
201
+ const parsed = dom.color.parse(value);
202
+ const { red, green, blue, alpha = 1, } = "hue" in parsed ? dom.hslaToRgba(parsed) : parsed;
203
+ const linear = [red, green, blue].map((channel) => toLinear(channel / 255));
204
+ return current?.length === 4 ? [...linear, alpha] : linear;
205
+ }
206
+ const parts = value
207
+ .split(",")
208
+ .join(" ")
209
+ .split(" ")
210
+ .filter(Boolean)
211
+ .map(Number);
212
+ return parts.length > 1 && parts.every((part) => !isNaN(part))
213
+ ? parts
214
+ : value;
215
+ }
216
+ function toLinear(channel) {
217
+ return channel <= 0.04045
218
+ ? channel / 12.92
219
+ : ((channel + 0.055) / 1.055) ** 2.4;
220
+ }
221
+ function toSRGB(channel) {
222
+ return channel <= 0.0031308
223
+ ? channel * 12.92
224
+ : 1.055 * channel ** (1 / 2.4) - 0.055;
225
+ }
226
+ function toColorString(linear) {
227
+ const [red, green, blue, alpha = 1] = Array.from(linear).map((channel, i) => i < 3 ? toSRGB(channel) * 255 : channel);
228
+ return dom.rgba.transform({ red, green, blue, alpha });
229
+ }
230
+ /**
231
+ * Inverse of vgpu's quatFromEuler (intrinsic XYZ).
232
+ */
233
+ function eulerFromQuaternion(quaternion) {
234
+ const [x, y, z, w] = Array.from(quaternion);
235
+ const m13 = 2 * (x * z + w * y);
236
+ const singular = Math.abs(m13) > 0.9999999;
237
+ return [
238
+ singular
239
+ ? Math.atan2(2 * (y * z + w * x), 1 - 2 * (x * x + z * z))
240
+ : Math.atan2(-2 * (y * z - w * x), 1 - 2 * (x * x + y * y)),
241
+ Math.asin(dom.clamp(-1, 1, m13)),
242
+ singular
243
+ ? 0
244
+ : Math.atan2(-2 * (x * y - w * z), 1 - 2 * (y * y + z * z)),
245
+ ];
246
+ }
247
+
248
+ exports.vgpuEffect = vgpuEffect;
@@ -0,0 +1,188 @@
1
+ import { createEffect, frame } from 'framer-motion/dom';
2
+
3
+ /**
4
+ * Binds motion values to Three.js objects, materials and uniforms.
5
+ *
6
+ * Register with `animate.addEffect(threeEffect)` so `animate()` can target
7
+ * meshes, lights, cameras, materials and uniforms directly, or call it
8
+ * yourself to wire up existing motion values:
9
+ *
10
+ * ```ts
11
+ * threeEffect(mesh, { x, rotateY, color })
12
+ * threeEffect(uniforms, { progress })
13
+ * ```
14
+ *
15
+ * Writes happen once per frame in `frame.preRender`, ahead of render loops
16
+ * scheduled with `frame.render`.
17
+ */
18
+ const threeEffect = createEffect((subject, state, key, value) => state.set(key, value, () => setObjectValue(subject, key, state.latest[key]), undefined, false), {
19
+ test: isThreeSubject,
20
+ read: getObjectValue,
21
+ step: frame.preRender,
22
+ });
23
+ /**
24
+ * Claims Three.js objects, materials and uniforms objects. Vectors, colors
25
+ * and Eulers aren't claimed so `animate(mesh.position, { x })` keeps working
26
+ * as a plain object animation.
27
+ */
28
+ function isThreeSubject(subject) {
29
+ if (!subject || typeof subject !== "object")
30
+ return false;
31
+ const object = subject;
32
+ return Boolean(object.isObject3D || object.isMaterial || isUniforms(object));
33
+ }
34
+ function isUniforms(object) {
35
+ const keys = Object.keys(object);
36
+ return keys.length > 0 && keys.every((key) => isUniform(object[key]));
37
+ }
38
+ const transformMap = {
39
+ x: ["position", "x"],
40
+ y: ["position", "y"],
41
+ z: ["position", "z"],
42
+ rotateX: ["rotation", "x"],
43
+ rotateY: ["rotation", "y"],
44
+ rotateZ: ["rotation", "z"],
45
+ scaleX: ["scale", "x"],
46
+ scaleY: ["scale", "y"],
47
+ scaleZ: ["scale", "z"],
48
+ };
49
+ function getObjectValue(object, key) {
50
+ if (isUniform(object[key]))
51
+ return getAnimatableValue(object[key].value);
52
+ const transform = transformMap[key];
53
+ if (transform) {
54
+ const [name, axis] = transform;
55
+ const value = object[name]?.[axis];
56
+ return key.startsWith("rotate") && typeof value === "number"
57
+ ? value * (180 / Math.PI)
58
+ : getAnimatableValue(value);
59
+ }
60
+ if (key === "scale") {
61
+ return getAnimatableValue(object.scale?.x);
62
+ }
63
+ const node = getNodeUniform(object, key);
64
+ if (node)
65
+ return getAnimatableValue(node.value);
66
+ const uniforms = getUniforms(object);
67
+ return (getProperty(object, key) ??
68
+ getProperty(object.material, key) ??
69
+ getUniformValue(uniforms, key) ??
70
+ getVectorComponent(object, key) ??
71
+ getVectorComponent(object.material, key) ??
72
+ getUniformComponent(uniforms, key) ??
73
+ getUniformComponent(object, key));
74
+ }
75
+ /**
76
+ * Uniforms live on ShaderMaterials, on the mesh itself or the subject can
77
+ * be a bare uniforms object.
78
+ */
79
+ function getUniforms(object) {
80
+ return object.material?.uniforms ?? object.uniforms;
81
+ }
82
+ /**
83
+ * Resolves TSL uniform nodes assigned to node material slots, e.g.
84
+ * material.colorNode = uniform(color). Non-uniform nodes are compiled
85
+ * into the shader so can't be animated via their value.
86
+ */
87
+ function getNodeUniform(object, key) {
88
+ const node = object[key + "Node"] ?? object.material?.[key + "Node"];
89
+ return node?.isUniformNode ? node : undefined;
90
+ }
91
+ function getProperty(target, key) {
92
+ return target && key in target ? getAnimatableValue(target[key]) : undefined;
93
+ }
94
+ function getUniformValue(uniforms, key) {
95
+ return getAnimatableValue(uniforms?.[key]?.value);
96
+ }
97
+ function getVectorComponent(target, key) {
98
+ const axis = key.slice(-1).toLowerCase();
99
+ const vector = target?.[key.slice(0, -1)];
100
+ return vector && ["x", "y", "z", "w"].includes(axis)
101
+ ? getAnimatableValue(vector[axis])
102
+ : undefined;
103
+ }
104
+ function getUniformComponent(uniforms, key) {
105
+ const uniform = uniforms?.[key.slice(0, -1)];
106
+ return isUniform(uniform)
107
+ ? getVectorComponent(uniform, `value${key.slice(-1)}`)
108
+ : undefined;
109
+ }
110
+ function getAnimatableValue(value) {
111
+ if (typeof value === "string" || typeof value === "number")
112
+ return value;
113
+ return value && typeof value.getStyle === "function"
114
+ ? value.getStyle()
115
+ : undefined;
116
+ }
117
+ function isUniform(value) {
118
+ return Boolean(value && typeof value === "object" && "value" in value);
119
+ }
120
+ function setObjectValue(object, key, value) {
121
+ if (isUniform(object[key])) {
122
+ setProperty(object[key], "value", value);
123
+ return;
124
+ }
125
+ const transform = transformMap[key];
126
+ if (transform) {
127
+ const [name, axis] = transform;
128
+ object[name][axis] = key.startsWith("rotate")
129
+ ? value * (Math.PI / 180)
130
+ : value;
131
+ return;
132
+ }
133
+ if (key === "scale") {
134
+ object.scale.x = object.scale.y = object.scale.z = value;
135
+ return;
136
+ }
137
+ const node = getNodeUniform(object, key);
138
+ if (node) {
139
+ setProperty(node, "value", value);
140
+ return;
141
+ }
142
+ if (setProperty(object, key, value))
143
+ return;
144
+ const material = object.material;
145
+ if (setProperty(material, key, value))
146
+ return;
147
+ const uniforms = getUniforms(object);
148
+ const uniform = uniforms?.[key];
149
+ if (uniform) {
150
+ setProperty(uniform, "value", value);
151
+ return;
152
+ }
153
+ if (setVectorComponent(object, key, value) ||
154
+ setVectorComponent(material, key, value) ||
155
+ setUniformComponent(uniforms, key, value) ||
156
+ setUniformComponent(object, key, value)) {
157
+ return;
158
+ }
159
+ object[key] = value;
160
+ }
161
+ function setProperty(target, key, value) {
162
+ if (!target || !(key in target))
163
+ return false;
164
+ const current = target[key];
165
+ if (current && typeof current.set === "function") {
166
+ Array.isArray(value) ? current.set(...value) : current.set(value);
167
+ }
168
+ else {
169
+ target[key] = value;
170
+ }
171
+ return true;
172
+ }
173
+ function setVectorComponent(target, key, value) {
174
+ const axis = key.slice(-1).toLowerCase();
175
+ const vector = target?.[key.slice(0, -1)];
176
+ if (!vector || !["x", "y", "z", "w"].includes(axis))
177
+ return false;
178
+ vector[axis] = value;
179
+ return true;
180
+ }
181
+ function setUniformComponent(uniforms, key, value) {
182
+ const uniform = uniforms?.[key.slice(0, -1)];
183
+ return isUniform(uniform)
184
+ ? setVectorComponent(uniform, `value${key.slice(-1)}`, value)
185
+ : false;
186
+ }
187
+
188
+ export { threeEffect };