3d-spinner 0.9.0 → 0.9.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 (29) hide show
  1. package/README.md +49 -8
  2. package/dist/animations/object-motion.d.ts +4 -1
  3. package/dist/animations/object-motion.js +2 -1
  4. package/dist/animations/spin.d.ts +4 -1
  5. package/dist/animations/spin.js +2 -1
  6. package/dist/cjs/animations/object-motion.cjs +1368 -0
  7. package/dist/cjs/animations/spin.cjs +1299 -0
  8. package/dist/cjs/engines/little-3d-engine/little-3d-engine.cjs +1324 -0
  9. package/dist/cjs/engines/little-3d-engine/loaders/obj.cjs +58 -0
  10. package/dist/cjs/engines/little-tween-engine/little-tween-engine.cjs +279 -0
  11. package/dist/cjs/index.cjs +120 -0
  12. package/dist/cjs/motion/motion.cjs +140 -0
  13. package/dist/cjs/motion/transitions.cjs +80 -0
  14. package/dist/engines/little-3d-engine/core/mesh.d.ts +18 -0
  15. package/dist/engines/little-3d-engine/little-3d-engine.d.ts +10 -3
  16. package/dist/engines/little-3d-engine/little-3d-engine.js +12 -8
  17. package/dist/engines/little-3d-engine/loaders/obj.d.ts +2 -2
  18. package/dist/engines/little-3d-engine/loaders/obj.js +2 -2
  19. package/dist/engines/little-3d-engine/renderer.d.ts +15 -1
  20. package/dist/engines/little-3d-engine/renderer.js +36 -0
  21. package/dist/engines/little-3d-engine/renderers/canvas2d.d.ts +1 -1
  22. package/dist/engines/little-3d-engine/renderers/canvas2d.js +22 -2
  23. package/dist/engines/little-3d-engine/renderers/webgl.d.ts +1 -1
  24. package/dist/engines/little-3d-engine/renderers/webgl.js +38 -1
  25. package/dist/engines/little-3d-engine/renderers/webgpu.d.ts +3 -1
  26. package/dist/engines/little-3d-engine/renderers/webgpu.js +70 -17
  27. package/dist/umd/spinner.global.js +2408 -0
  28. package/dist/umd/spinner.global.min.js +58 -0
  29. package/package.json +26 -11
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/engines/little-3d-engine/loaders/obj.ts
21
+ var obj_exports = {};
22
+ __export(obj_exports, {
23
+ parseObj: () => parseObj
24
+ });
25
+ module.exports = __toCommonJS(obj_exports);
26
+ var DEFAULT_COLORS = ["#3b82f6", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#ef4444"];
27
+ function resolveIndex(token, vertexCount) {
28
+ const n = parseInt(token, 10);
29
+ return n < 0 ? vertexCount + n : n - 1;
30
+ }
31
+ function parseObj(text, options = {}) {
32
+ const colors = options.colors ?? DEFAULT_COLORS;
33
+ const vertices = [];
34
+ const faces = [];
35
+ for (const line of text.split("\n")) {
36
+ const trimmed = line.trim();
37
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
38
+ const parts = trimmed.split(/\s+/);
39
+ const keyword = parts[0];
40
+ if (keyword === "v") {
41
+ vertices.push({
42
+ x: parseFloat(parts[1]),
43
+ y: parseFloat(parts[2]),
44
+ z: parseFloat(parts[3])
45
+ });
46
+ } else if (keyword === "f") {
47
+ const indices = [];
48
+ for (let i = 1; i < parts.length; i++) {
49
+ const vertexToken = parts[i].split("/")[0];
50
+ indices.push(resolveIndex(vertexToken, vertices.length));
51
+ }
52
+ if (indices.length >= 3) {
53
+ faces.push({ indices, color: colors[faces.length % colors.length] });
54
+ }
55
+ }
56
+ }
57
+ return { vertices, faces };
58
+ }
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/engines/little-tween-engine/little-tween-engine.ts
21
+ var little_tween_engine_exports = {};
22
+ __export(little_tween_engine_exports, {
23
+ LittleTweenEngine: () => LittleTweenEngine,
24
+ cubic: () => cubic,
25
+ ease: () => ease,
26
+ easeInBack: () => easeInBack,
27
+ easeInBounce: () => easeInBounce,
28
+ easeInCirc: () => easeInCirc,
29
+ easeInCubic: () => easeInCubic,
30
+ easeInElastic: () => easeInElastic,
31
+ easeInExpo: () => easeInExpo,
32
+ easeInOutBack: () => easeInOutBack,
33
+ easeInOutBounce: () => easeInOutBounce,
34
+ easeInOutCirc: () => easeInOutCirc,
35
+ easeInOutCubic: () => easeInOutCubic,
36
+ easeInOutElastic: () => easeInOutElastic,
37
+ easeInOutExpo: () => easeInOutExpo,
38
+ easeInOutQuad: () => easeInOutQuad,
39
+ easeInOutQuart: () => easeInOutQuart,
40
+ easeInOutQuint: () => easeInOutQuint,
41
+ easeInOutSine: () => easeInOutSine,
42
+ easeInQuad: () => easeInQuad,
43
+ easeInQuart: () => easeInQuart,
44
+ easeInQuint: () => easeInQuint,
45
+ easeInSine: () => easeInSine,
46
+ easeOutBack: () => easeOutBack,
47
+ easeOutBounce: () => easeOutBounce,
48
+ easeOutCirc: () => easeOutCirc,
49
+ easeOutCubic: () => easeOutCubic,
50
+ easeOutElastic: () => easeOutElastic,
51
+ easeOutExpo: () => easeOutExpo,
52
+ easeOutQuad: () => easeOutQuad,
53
+ easeOutQuart: () => easeOutQuart,
54
+ easeOutQuint: () => easeOutQuint,
55
+ easeOutSine: () => easeOutSine,
56
+ easeTypes: () => easeTypes,
57
+ linear: () => linear,
58
+ quadratic: () => quadratic,
59
+ quartic: () => quartic,
60
+ quintic: () => quintic
61
+ });
62
+ module.exports = __toCommonJS(little_tween_engine_exports);
63
+
64
+ // src/engines/little-tween-engine/core/tweens.ts
65
+ function input(value, overextend) {
66
+ if (Number.isNaN(value)) return 0;
67
+ if (overextend) return value;
68
+ return Math.min(1, Math.max(0, value));
69
+ }
70
+ function linear(value, overextend = false) {
71
+ return input(value, overextend);
72
+ }
73
+ function quadratic(value, overextend = false) {
74
+ return easeInQuad(value, overextend);
75
+ }
76
+ function cubic(value, overextend = false) {
77
+ return easeInCubic(value, overextend);
78
+ }
79
+ function quartic(value, overextend = false) {
80
+ return easeInQuart(value, overextend);
81
+ }
82
+ function quintic(value, overextend = false) {
83
+ return easeInQuint(value, overextend);
84
+ }
85
+ function easeInSine(value, overextend = false) {
86
+ const x = input(value, overextend);
87
+ return 1 - Math.cos(x * Math.PI / 2);
88
+ }
89
+ function easeOutSine(value, overextend = false) {
90
+ const x = input(value, overextend);
91
+ return Math.sin(x * Math.PI / 2);
92
+ }
93
+ function easeInOutSine(value, overextend = false) {
94
+ const x = input(value, overextend);
95
+ return -(Math.cos(Math.PI * x) - 1) / 2;
96
+ }
97
+ function easeInQuad(value, overextend = false) {
98
+ const x = input(value, overextend);
99
+ return x * x;
100
+ }
101
+ function easeOutQuad(value, overextend = false) {
102
+ const x = input(value, overextend);
103
+ return 1 - (1 - x) * (1 - x);
104
+ }
105
+ function easeInOutQuad(value, overextend = false) {
106
+ const x = input(value, overextend);
107
+ return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
108
+ }
109
+ function easeInCubic(value, overextend = false) {
110
+ const x = input(value, overextend);
111
+ return x * x * x;
112
+ }
113
+ function easeOutCubic(value, overextend = false) {
114
+ const x = input(value, overextend);
115
+ return 1 - Math.pow(1 - x, 3);
116
+ }
117
+ function easeInOutCubic(value, overextend = false) {
118
+ const x = input(value, overextend);
119
+ return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
120
+ }
121
+ function easeInQuart(value, overextend = false) {
122
+ const x = input(value, overextend);
123
+ return x * x * x * x;
124
+ }
125
+ function easeOutQuart(value, overextend = false) {
126
+ const x = input(value, overextend);
127
+ return 1 - Math.pow(1 - x, 4);
128
+ }
129
+ function easeInOutQuart(value, overextend = false) {
130
+ const x = input(value, overextend);
131
+ return x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2;
132
+ }
133
+ function easeInQuint(value, overextend = false) {
134
+ const x = input(value, overextend);
135
+ return x * x * x * x * x;
136
+ }
137
+ function easeOutQuint(value, overextend = false) {
138
+ const x = input(value, overextend);
139
+ return 1 - Math.pow(1 - x, 5);
140
+ }
141
+ function easeInOutQuint(value, overextend = false) {
142
+ const x = input(value, overextend);
143
+ return x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2;
144
+ }
145
+ function easeInExpo(value, overextend = false) {
146
+ const x = input(value, overextend);
147
+ return x === 0 ? 0 : Math.pow(2, 10 * x - 10);
148
+ }
149
+ function easeOutExpo(value, overextend = false) {
150
+ const x = input(value, overextend);
151
+ return x === 1 ? 1 : 1 - Math.pow(2, -10 * x);
152
+ }
153
+ function easeInOutExpo(value, overextend = false) {
154
+ const x = input(value, overextend);
155
+ return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? Math.pow(2, 20 * x - 10) / 2 : (2 - Math.pow(2, -20 * x + 10)) / 2;
156
+ }
157
+ function easeInCirc(value, overextend = false) {
158
+ const x = input(value, overextend);
159
+ return 1 - Math.sqrt(1 - Math.pow(x, 2));
160
+ }
161
+ function easeOutCirc(value, overextend = false) {
162
+ const x = input(value, overextend);
163
+ return Math.sqrt(1 - Math.pow(x - 1, 2));
164
+ }
165
+ function easeInOutCirc(value, overextend = false) {
166
+ const x = input(value, overextend);
167
+ return x < 0.5 ? (1 - Math.sqrt(1 - Math.pow(2 * x, 2))) / 2 : (Math.sqrt(1 - Math.pow(-2 * x + 2, 2)) + 1) / 2;
168
+ }
169
+ function easeInBack(value, overextend = false) {
170
+ const x = input(value, overextend);
171
+ const c1 = 1.70158;
172
+ const c3 = c1 + 1;
173
+ return c3 * x * x * x - c1 * x * x;
174
+ }
175
+ function easeOutBack(value, overextend = false) {
176
+ const x = input(value, overextend);
177
+ const c1 = 1.70158;
178
+ const c3 = c1 + 1;
179
+ return 1 + c3 * Math.pow(x - 1, 3) + c1 * Math.pow(x - 1, 2);
180
+ }
181
+ function easeInOutBack(value, overextend = false) {
182
+ const x = input(value, overextend);
183
+ const c1 = 1.70158;
184
+ const c2 = c1 * 1.525;
185
+ return x < 0.5 ? Math.pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2) / 2 : (Math.pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;
186
+ }
187
+ function easeInElastic(value, overextend = false) {
188
+ const x = input(value, overextend);
189
+ const c4 = 2 * Math.PI / 3;
190
+ return x === 0 ? 0 : x === 1 ? 1 : -Math.pow(2, 10 * x - 10) * Math.sin((x * 10 - 10.75) * c4);
191
+ }
192
+ function easeOutElastic(value, overextend = false) {
193
+ const x = input(value, overextend);
194
+ const c4 = 2 * Math.PI / 3;
195
+ return x === 0 ? 0 : x === 1 ? 1 : Math.pow(2, -10 * x) * Math.sin((x * 10 - 0.75) * c4) + 1;
196
+ }
197
+ function easeInOutElastic(value, overextend = false) {
198
+ const x = input(value, overextend);
199
+ const c5 = 2 * Math.PI / 4.5;
200
+ return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? -(Math.pow(2, 20 * x - 10) * Math.sin((20 * x - 11.125) * c5)) / 2 : Math.pow(2, -20 * x + 10) * Math.sin((20 * x - 11.125) * c5) / 2 + 1;
201
+ }
202
+ function easeInBounce(value, overextend = false) {
203
+ const x = input(value, overextend);
204
+ return 1 - easeOutBounce(1 - x, true);
205
+ }
206
+ function easeOutBounce(value, overextend = false) {
207
+ let x = input(value, overextend);
208
+ const n1 = 7.5625;
209
+ const d1 = 2.75;
210
+ if (x < 1 / d1) {
211
+ return n1 * x * x;
212
+ }
213
+ if (x < 2 / d1) {
214
+ x -= 1.5 / d1;
215
+ return n1 * x * x + 0.75;
216
+ }
217
+ if (x < 2.5 / d1) {
218
+ x -= 2.25 / d1;
219
+ return n1 * x * x + 0.9375;
220
+ }
221
+ x -= 2.625 / d1;
222
+ return n1 * x * x + 0.984375;
223
+ }
224
+ function easeInOutBounce(value, overextend = false) {
225
+ const x = input(value, overextend);
226
+ return x < 0.5 ? (1 - easeOutBounce(1 - 2 * x, true)) / 2 : (1 + easeOutBounce(2 * x - 1, true)) / 2;
227
+ }
228
+ var easeTypes = {
229
+ linear,
230
+ quadratic,
231
+ cubic,
232
+ quartic,
233
+ quintic,
234
+ easeInSine,
235
+ easeOutSine,
236
+ easeInOutSine,
237
+ easeInQuad,
238
+ easeOutQuad,
239
+ easeInOutQuad,
240
+ easeInCubic,
241
+ easeOutCubic,
242
+ easeInOutCubic,
243
+ easeInQuart,
244
+ easeOutQuart,
245
+ easeInOutQuart,
246
+ easeInQuint,
247
+ easeOutQuint,
248
+ easeInOutQuint,
249
+ easeInExpo,
250
+ easeOutExpo,
251
+ easeInOutExpo,
252
+ easeInCirc,
253
+ easeOutCirc,
254
+ easeInOutCirc,
255
+ easeInBack,
256
+ easeOutBack,
257
+ easeInOutBack,
258
+ easeInElastic,
259
+ easeOutElastic,
260
+ easeInOutElastic,
261
+ easeInBounce,
262
+ easeOutBounce,
263
+ easeInOutBounce
264
+ };
265
+ function ease(type, value, overextend = false) {
266
+ return easeTypes[type](value, overextend);
267
+ }
268
+
269
+ // src/engines/little-tween-engine/little-tween-engine.ts
270
+ var LittleTweenEngine = class {
271
+ constructor(options = {}) {
272
+ this.type = options.type ?? "linear";
273
+ this.overextend = options.overextend ?? false;
274
+ }
275
+ /** Map `value` through the selected ease type. */
276
+ value(value, type = this.type, overextend = this.overextend) {
277
+ return ease(type, value, overextend);
278
+ }
279
+ };
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ createSpinner: () => createSpinner
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+ function clamp01(value) {
27
+ if (Number.isNaN(value)) return 0;
28
+ return Math.min(1, Math.max(0, value));
29
+ }
30
+ function lerp(from, to, t) {
31
+ return from + (to - from) * t;
32
+ }
33
+ function createSpinner(target, options) {
34
+ if (!(target instanceof HTMLElement)) {
35
+ throw new Error("3d-spinner: createSpinner requires a target HTMLElement.");
36
+ }
37
+ const { animation } = options;
38
+ const indeterminate = options.type === "indeterminate";
39
+ if (indeterminate && options.periodMs !== void 0 && (!Number.isFinite(options.periodMs) || options.periodMs <= 0)) {
40
+ throw new RangeError("3d-spinner: periodMs must be a finite number greater than zero.");
41
+ }
42
+ animation.mount(target);
43
+ const start = performance.now();
44
+ let rafId = 0;
45
+ let stopped = false;
46
+ let destroyed = false;
47
+ let entered = false;
48
+ let exiting = false;
49
+ let current = 0;
50
+ let targetProgress = 0;
51
+ let deadline = Infinity;
52
+ if (!indeterminate) {
53
+ const opts = options;
54
+ if (typeof opts.progress === "number") {
55
+ current = clamp01(opts.progress);
56
+ targetProgress = current;
57
+ }
58
+ if (typeof opts.timeout === "number") deadline = Math.min(deadline, start + opts.timeout);
59
+ if (opts.until instanceof Date) deadline = Math.min(deadline, opts.until.getTime());
60
+ }
61
+ function computeProgress(now) {
62
+ if (!indeterminate) {
63
+ if (now >= deadline) targetProgress = 1;
64
+ current = lerp(current, targetProgress, 0.12);
65
+ if (Math.abs(targetProgress - current) < 5e-4) current = targetProgress;
66
+ return current;
67
+ }
68
+ const opts = options;
69
+ const period = opts.periodMs ?? 2e3;
70
+ const t = (now - start) / period;
71
+ if ((opts.loop ?? "bounce") === "restart") return t - Math.floor(t);
72
+ const phase = t - 2 * Math.floor(t / 2);
73
+ return phase <= 1 ? phase : 2 - phase;
74
+ }
75
+ function frame(now) {
76
+ if (stopped) return;
77
+ const progress = computeProgress(now);
78
+ if (!entered && (indeterminate || progress > 0)) {
79
+ animation.enter(now);
80
+ entered = true;
81
+ }
82
+ if (!exiting && entered && !indeterminate && progress >= 1 && targetProgress >= 1) {
83
+ animation.exit(now);
84
+ exiting = true;
85
+ }
86
+ const target2 = indeterminate ? progress : targetProgress;
87
+ animation.render(now, { progress, targetProgress: target2, indeterminate });
88
+ if (exiting && animation.isFinished()) {
89
+ halt();
90
+ return;
91
+ }
92
+ rafId = requestAnimationFrame(frame);
93
+ }
94
+ function halt() {
95
+ if (stopped) return;
96
+ stopped = true;
97
+ if (rafId) cancelAnimationFrame(rafId);
98
+ rafId = 0;
99
+ }
100
+ function setProgress(value) {
101
+ if (!indeterminate) targetProgress = clamp01(value);
102
+ }
103
+ function stop() {
104
+ if (stopped || exiting) return;
105
+ if (!entered) {
106
+ halt();
107
+ return;
108
+ }
109
+ animation.exit(performance.now());
110
+ exiting = true;
111
+ }
112
+ function destroy() {
113
+ if (destroyed) return;
114
+ destroyed = true;
115
+ halt();
116
+ animation.destroy();
117
+ }
118
+ rafId = requestAnimationFrame(frame);
119
+ return { setProgress, stop, destroy };
120
+ }
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/motion/motion.ts
21
+ var motion_exports = {};
22
+ __export(motion_exports, {
23
+ circleMotion: () => circleMotion,
24
+ figureEightMotion: () => figureEightMotion,
25
+ squareMotion: () => squareMotion,
26
+ wanderMotion: () => wanderMotion
27
+ });
28
+ module.exports = __toCommonJS(motion_exports);
29
+
30
+ // src/motion/circle.ts
31
+ function circleMotion(options = {}) {
32
+ const radius = options.radius ?? 1.3;
33
+ const periodMs = options.periodMs ?? 3e3;
34
+ const tilt = options.tilt ?? 0.5;
35
+ const direction = options.direction ?? 1;
36
+ const cosTilt = Math.cos(tilt);
37
+ const sinTilt = Math.sin(tilt);
38
+ return {
39
+ positionAt(t) {
40
+ const angle = direction * t / periodMs * Math.PI * 2;
41
+ const x = radius * Math.cos(angle);
42
+ const flatY = radius * Math.sin(angle);
43
+ return { x, y: flatY * cosTilt, z: flatY * sinTilt };
44
+ }
45
+ };
46
+ }
47
+
48
+ // src/motion/square.ts
49
+ function squareMotion(options = {}) {
50
+ const half = (options.size ?? 2.4) / 2;
51
+ const periodMs = options.periodMs ?? 4e3;
52
+ const tilt = options.tilt ?? 0.45;
53
+ const direction = options.direction ?? 1;
54
+ const cosTilt = Math.cos(tilt);
55
+ const sinTilt = Math.sin(tilt);
56
+ return {
57
+ positionAt(t) {
58
+ const lap = direction * t / periodMs;
59
+ const s = (lap - Math.floor(lap)) * 4;
60
+ const edge = Math.floor(s);
61
+ const f = s - edge;
62
+ let flatX;
63
+ let flatY;
64
+ if (edge === 0) {
65
+ flatX = -half + 2 * half * f;
66
+ flatY = -half;
67
+ } else if (edge === 1) {
68
+ flatX = half;
69
+ flatY = -half + 2 * half * f;
70
+ } else if (edge === 2) {
71
+ flatX = half - 2 * half * f;
72
+ flatY = half;
73
+ } else {
74
+ flatX = -half;
75
+ flatY = half - 2 * half * f;
76
+ }
77
+ return { x: flatX, y: flatY * cosTilt, z: flatY * sinTilt };
78
+ }
79
+ };
80
+ }
81
+
82
+ // src/motion/figure-eight.ts
83
+ var LOOP_X = 1.5;
84
+ var LOOP_Y = 1;
85
+ var LOOP_Z = 1.05;
86
+ function figureEightMotion(options = {}) {
87
+ const size = options.size ?? 1;
88
+ const periodMs = options.periodMs ?? 3600;
89
+ return {
90
+ positionAt(t) {
91
+ const a = t / periodMs * Math.PI * 2;
92
+ return {
93
+ x: size * LOOP_X * Math.sin(a),
94
+ y: size * LOOP_Y * Math.sin(a) * Math.cos(a),
95
+ z: size * LOOP_Z * Math.cos(a)
96
+ };
97
+ }
98
+ };
99
+ }
100
+
101
+ // src/motion/wander.ts
102
+ function mulberry32(seed) {
103
+ let a = seed >>> 0;
104
+ return () => {
105
+ a = a + 1831565813 | 0;
106
+ let t = Math.imul(a ^ a >>> 15, 1 | a);
107
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
108
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
109
+ };
110
+ }
111
+ function axisDrift(rnd, omega, bound) {
112
+ const components = [0, 1, 2].map(() => ({
113
+ freq: 0.5 + rnd() * 1.4,
114
+ phase: rnd() * Math.PI * 2,
115
+ weight: 0.5 + rnd()
116
+ }));
117
+ const total = components.reduce((sum, c) => sum + c.weight, 0);
118
+ return (t) => {
119
+ let value = 0;
120
+ for (const c of components) value += c.weight * Math.sin(omega * c.freq * t + c.phase);
121
+ return value / total * bound;
122
+ };
123
+ }
124
+ function wanderMotion(options = {}) {
125
+ const boundX = options.bounds?.x ?? 1.4;
126
+ const boundY = options.bounds?.y ?? 1;
127
+ const boundZ = options.bounds?.z ?? 0.6;
128
+ const periodMs = options.periodMs ?? 9e3;
129
+ const seed = options.seed ?? Math.random() * 1e9 | 0;
130
+ const rnd = mulberry32(seed);
131
+ const omega = 2 * Math.PI / periodMs;
132
+ const driftX = axisDrift(rnd, omega, boundX);
133
+ const driftY = axisDrift(rnd, omega, boundY);
134
+ const driftZ = axisDrift(rnd, omega, boundZ);
135
+ return {
136
+ positionAt(t) {
137
+ return { x: driftX(t), y: driftY(t), z: driftZ(t) };
138
+ }
139
+ };
140
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/motion/transitions.ts
21
+ var transitions_exports = {};
22
+ __export(transitions_exports, {
23
+ enterFromObjectDirection: () => enterFromObjectDirection,
24
+ grow: () => grow,
25
+ leaveInObjectDirection: () => leaveInObjectDirection,
26
+ shrink: () => shrink
27
+ });
28
+ module.exports = __toCommonJS(transitions_exports);
29
+ var DEFAULT_DISTANCE = 3.5;
30
+ function add(a, b) {
31
+ return { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
32
+ }
33
+ function scaleVector(v, factor) {
34
+ return { x: v.x * factor, y: v.y * factor, z: v.z * factor };
35
+ }
36
+ function vectorLength(v) {
37
+ return Math.hypot(v.x, v.y, v.z);
38
+ }
39
+ function normalizeVector(v) {
40
+ const length = vectorLength(v);
41
+ if (length < 1e-6) return { x: 1, y: 0, z: 0 };
42
+ return scaleVector(v, 1 / length);
43
+ }
44
+ function resolveDirection(input, fallback) {
45
+ return normalizeVector(fallback ?? input.direction ?? input.velocity ?? { x: 1, y: 0, z: 0 });
46
+ }
47
+ function easeOutBack(delta) {
48
+ const c = 1.70158;
49
+ const u = delta - 1;
50
+ return 1 + (c + 1) * u * u * u + c * u * u;
51
+ }
52
+ function joinVelocity(input, options, durationMs) {
53
+ const inputSpeed = input.velocity ? vectorLength(input.velocity) : 0;
54
+ if (input.velocity && inputSpeed > 1e-6 && !options.direction) {
55
+ return input.velocity;
56
+ }
57
+ const distance = options.distance ?? DEFAULT_DISTANCE;
58
+ return scaleVector(resolveDirection(input, options.direction), distance / durationMs);
59
+ }
60
+ function enterFromObjectDirection(options = {}) {
61
+ return (input) => {
62
+ const durationMs = Math.max(1, input.durationMs);
63
+ const velocity = joinVelocity(input, options, durationMs);
64
+ const remaining = durationMs - input.elapsedMs;
65
+ return { position: add(input.position, scaleVector(velocity, -remaining)) };
66
+ };
67
+ }
68
+ function leaveInObjectDirection(options = {}) {
69
+ return (input) => {
70
+ const durationMs = Math.max(1, input.durationMs);
71
+ const velocity = joinVelocity(input, options, durationMs);
72
+ return { position: add(input.position, scaleVector(velocity, input.elapsedMs)) };
73
+ };
74
+ }
75
+ function grow() {
76
+ return (input) => ({ size: (input.size ?? 1) * easeOutBack(input.delta) });
77
+ }
78
+ function shrink() {
79
+ return (input) => ({ size: (input.size ?? 1) * (1 - input.delta * input.delta) });
80
+ }
@@ -11,6 +11,24 @@ export interface Mesh {
11
11
  vertices: Vec3[];
12
12
  faces: Face[];
13
13
  }
14
+ /** Draw only outward-facing transparent surfaces. */
15
+ export interface OneSidedTransparency {
16
+ mode: "one-sided";
17
+ /** Surface opacity from `0` (invisible) to `1` (opaque). Default `0.35`. */
18
+ opacity?: number;
19
+ }
20
+ /** Draw back surfaces before front surfaces to suggest a transparent solid. */
21
+ export interface TwoSidedTransparency {
22
+ mode: "two-sided";
23
+ /** Front opacity shorthand; back opacity is derived as two-thirds of front. */
24
+ opacity?: number;
25
+ /** Back-surface opacity from `0` to `1`. Default `0.84`. */
26
+ backOpacity?: number;
27
+ /** Front-surface opacity from `0` to `1`. Default `0.56`. */
28
+ frontOpacity?: number;
29
+ }
30
+ /** Transparency mode for one mesh instance. */
31
+ export type Transparency = OneSidedTransparency | TwoSidedTransparency;
14
32
  /** Position and orientation (Euler radians) applied to a mesh when rendered. */
15
33
  export interface Transform {
16
34
  position: Vec3;