@semio/utils 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,981 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ EMAIL: () => EMAIL,
34
+ PlayerContext: () => PlayerContext,
35
+ PlayerSlice: () => PlayerSlice,
36
+ Result: () => Result,
37
+ alpha: () => alpha,
38
+ altColor: () => altColor,
39
+ angularDistance: () => angularDistance,
40
+ closestFrame: () => closestFrame,
41
+ composeProgress: () => composeProgress,
42
+ composeProgressiveResult: () => composeProgressiveResult,
43
+ downloadBlob: () => downloadBlob,
44
+ downloadJSONFile: () => downloadJSONFile,
45
+ eulerToRotationMatrix: () => eulerToRotationMatrix,
46
+ getDegenerateHexagonPath: () => getDegenerateHexagonPath,
47
+ getHexagonPath: () => getHexagonPath,
48
+ getId: () => getId,
49
+ getLookup: () => getLookup,
50
+ getNamespace: () => getNamespace,
51
+ hexToRgbArray: () => hexToRgbArray,
52
+ hexToRgba: () => hexToRgba,
53
+ hslToRgba: () => hslToRgba,
54
+ incrementProgress: () => incrementProgress,
55
+ instanceOfRawBoolean: () => instanceOfRawBoolean,
56
+ instanceOfRawColor: () => instanceOfRawColor,
57
+ instanceOfRawEuler: () => instanceOfRawEuler,
58
+ instanceOfRawHSL: () => instanceOfRawHSL,
59
+ instanceOfRawNumber: () => instanceOfRawNumber,
60
+ instanceOfRawRGB: () => instanceOfRawRGB,
61
+ instanceOfRawString: () => instanceOfRawString,
62
+ instanceOfRawVector2: () => instanceOfRawVector2,
63
+ instanceOfRawVector3: () => instanceOfRawVector3,
64
+ isMapDeepEqual: () => isMapDeepEqual,
65
+ isRawObject: () => isRawObject,
66
+ log: () => log,
67
+ newPlayer: () => newPlayer,
68
+ now: () => now,
69
+ numberToDurationString: () => numberToDurationString,
70
+ overlappingSegments: () => overlappingSegments,
71
+ pairwise: () => pairwise,
72
+ parseJSONFileEvent: () => parseJSONFileEvent,
73
+ parseToMapped: () => parseToMapped,
74
+ pause: () => pause,
75
+ play: () => play,
76
+ pointsToPath: () => pointsToPath,
77
+ rawHSLToHex: () => rawHSLToHex,
78
+ rawRGBToHex: () => rawRGBToHex,
79
+ reset: () => reset,
80
+ rgbToRgba: () => rgbToRgba,
81
+ rotationMatrixToAngle: () => rotationMatrixToAngle,
82
+ seek: () => seek,
83
+ setBounds: () => setBounds,
84
+ setDuration: () => setDuration,
85
+ setViewport: () => setViewport,
86
+ stringifyMapped: () => stringifyMapped,
87
+ toDegrees: () => toDegrees,
88
+ toRadians: () => toRadians,
89
+ update: () => update,
90
+ useDeep: () => useDeep,
91
+ useDeepSelector: () => useDeepSelector,
92
+ useLazy: () => useLazy,
93
+ useMediaQuery: () => useMediaQuery,
94
+ usePlayerStore: () => usePlayerStore
95
+ });
96
+ module.exports = __toCommonJS(index_exports);
97
+
98
+ // src/log.ts
99
+ function log(value) {
100
+ console.log(value);
101
+ }
102
+
103
+ // src/namespace.ts
104
+ function getLookup(namespace, id) {
105
+ return `${namespace === "default" ? "default." : `${namespace}.`}${id}`;
106
+ }
107
+ function getNamespace(lookup) {
108
+ if (lookup.includes(".")) {
109
+ return lookup.split(".")[0];
110
+ } else return "default";
111
+ }
112
+ function getId(lookup) {
113
+ if (lookup.includes(".")) {
114
+ return lookup.split(".")[1];
115
+ } else return lookup;
116
+ }
117
+
118
+ // src/player.ts
119
+ function reset(player, stamp) {
120
+ const p = { ...player };
121
+ const nowVal = now();
122
+ p._currentTime = nowVal;
123
+ p._previousTime = nowVal;
124
+ p.stamp = stamp ? stamp : 0;
125
+ return p;
126
+ }
127
+ function now() {
128
+ return (typeof performance === "undefined" ? Date : performance).now();
129
+ }
130
+ function update(player, coldStart) {
131
+ const p = { ...player };
132
+ const duration = p.duration;
133
+ const t = now();
134
+ p._previousTime = coldStart ? t : p._currentTime;
135
+ p._currentTime = t;
136
+ const currentInBounds = p.stamp >= p.bounds[0] && p.stamp <= p.bounds[1];
137
+ const currentViewportCenter = (p.viewport[1] + p.viewport[0]) / 2;
138
+ const nearViewportCenterCurrent = Math.abs(p.stamp - currentViewportCenter) < 0.01;
139
+ const delta = (p._currentTime - p._previousTime) * p.timescale / duration;
140
+ const updatedStamp = p.stamp + delta;
141
+ const [start, end] = currentInBounds ? p.bounds : [0, 1];
142
+ let attachOverride = false;
143
+ if (updatedStamp > end) {
144
+ if (p.playback === "loop") {
145
+ p.stamp = start;
146
+ } else if (p.playback === "bounce") {
147
+ p.stamp = end;
148
+ p.timescale *= -1;
149
+ } else {
150
+ p.stamp = start;
151
+ p.running = false;
152
+ }
153
+ attachOverride = true;
154
+ } else if (currentInBounds && updatedStamp < start) {
155
+ if (p.playback === "loop") {
156
+ p.stamp = start;
157
+ if (p.timescale < 0) {
158
+ p.running = false;
159
+ }
160
+ } else if (p.playback === "bounce") {
161
+ p.stamp = start;
162
+ p.timescale *= -1;
163
+ } else {
164
+ p.stamp = start;
165
+ p.running = false;
166
+ }
167
+ attachOverride = true;
168
+ } else {
169
+ p.stamp = updatedStamp;
170
+ }
171
+ const newNearViewportCenter = Math.abs(p.stamp - currentViewportCenter) < 0.01;
172
+ const boundsInsideViewport = p.viewport[0] <= p.bounds[0] || p.viewport[1] >= p.bounds[1];
173
+ if (p.running && !boundsInsideViewport && (nearViewportCenterCurrent || newNearViewportCenter || attachOverride)) {
174
+ p.viewport = getFittedViewport(p.stamp, p.viewport);
175
+ } else if (p.running && !boundsInsideViewport && !newNearViewportCenter) {
176
+ const oomphOffset = currentViewportCenter < p.stamp ? delta : 0;
177
+ const idealViewport = getFittedViewport(p.stamp + oomphOffset, p.viewport);
178
+ p.viewport = [
179
+ p.viewport[0] * 0.6 + idealViewport[0] * 0.4,
180
+ p.viewport[1] * 0.6 + idealViewport[1] * 0.4
181
+ ];
182
+ }
183
+ return p;
184
+ }
185
+ function setBounds(player, bounds) {
186
+ const p = { ...player };
187
+ p.bounds = bounds;
188
+ return p;
189
+ }
190
+ function setViewport(player, viewport) {
191
+ const p = { ...player };
192
+ p.viewport = viewport;
193
+ return p;
194
+ }
195
+ function play(player, speed) {
196
+ const p = { ...player };
197
+ p.running = true;
198
+ p.timescale = speed ?? 1;
199
+ if (p.playback === "once" && p.stamp === p.bounds[1]) {
200
+ p.stamp = p.bounds[0];
201
+ }
202
+ return p;
203
+ }
204
+ function pause(player) {
205
+ const p = { ...player };
206
+ p.running = false;
207
+ p.timescale = 0;
208
+ return p;
209
+ }
210
+ function seek(player, stamp) {
211
+ const p = reset(player, stamp);
212
+ p.viewport = getFittedViewport(stamp, p.viewport);
213
+ return p;
214
+ }
215
+ function setDuration(player, duration) {
216
+ const p = { ...player };
217
+ p.duration = duration;
218
+ return p;
219
+ }
220
+ function newPlayer() {
221
+ return {
222
+ running: false,
223
+ _previousTime: now(),
224
+ _currentTime: now(),
225
+ stamp: 0,
226
+ timescale: 0,
227
+ bounds: [0, 1],
228
+ playback: "loop",
229
+ viewport: [0, 1],
230
+ duration: 1e3
231
+ };
232
+ }
233
+ var getFittedViewport = (playhead, proposedViewport) => {
234
+ const viewportWidth = proposedViewport[1] - proposedViewport[0];
235
+ const proposedLeft = playhead - viewportWidth / 2;
236
+ const proposedRight = playhead + viewportWidth / 2;
237
+ if (proposedLeft >= 0 && proposedRight <= 1) {
238
+ return [playhead - viewportWidth / 2, playhead + viewportWidth / 2];
239
+ } else if (proposedLeft < 0) {
240
+ return [0, viewportWidth];
241
+ } else {
242
+ return [1 - viewportWidth, 1];
243
+ }
244
+ };
245
+
246
+ // src/player-store.ts
247
+ var import_react = require("react");
248
+ var import_zustand = require("zustand");
249
+ var import_middleware = require("zustand/middleware");
250
+ var import_immer = require("immer");
251
+ var THREE = __toESM(require("three"));
252
+ THREE.Object3D.DEFAULT_UP.set(0, 0, 1);
253
+ (0, import_immer.enableMapSet)();
254
+ var PlayerSlice = (set) => ({
255
+ player: newPlayer(),
256
+ // Set the duration of the player
257
+ updateDuration: (duration) => {
258
+ set(
259
+ (0, import_immer.produce)((state) => {
260
+ state.player.duration = duration;
261
+ })
262
+ );
263
+ },
264
+ // Set the timescale of the animation playback
265
+ updateTimescale: (speed) => {
266
+ set(
267
+ (0, import_immer.produce)((state) => {
268
+ state.player.timescale = speed;
269
+ })
270
+ );
271
+ },
272
+ // Set the time of the animation
273
+ resetPlayer: (time) => {
274
+ set((state) => ({ player: reset(state.player, time) }));
275
+ },
276
+ // Play the animation
277
+ playPlayer: (speed) => {
278
+ set((state) => ({ player: play(state.player, speed) }));
279
+ },
280
+ // Pause the animation
281
+ pausePlayer: () => {
282
+ set((state) => ({ player: pause(state.player) }));
283
+ },
284
+ // Update the timer
285
+ updatePlayer: (coldStart) => {
286
+ set((state) => ({
287
+ player: update(state.player, coldStart ?? false)
288
+ }));
289
+ },
290
+ // Set the player bounds
291
+ updatePlayerBounds: (start, end) => {
292
+ set((state) => ({
293
+ player: setBounds(state.player, [start, end])
294
+ }));
295
+ },
296
+ updatePlayerBound: (bound, time) => {
297
+ set((state) => {
298
+ const t = time ?? state.player.stamp;
299
+ if (bound === "start" && state.player.bounds[1] <= t) {
300
+ return {
301
+ player: setBounds(state.player, [state.player.bounds[1], t])
302
+ };
303
+ } else if (bound === "end" && state.player.bounds[0] >= t) {
304
+ return {
305
+ player: setBounds(state.player, [t, state.player.bounds[0]])
306
+ };
307
+ } else if (bound === "start") {
308
+ return {
309
+ player: setBounds(state.player, [t, state.player.bounds[1]])
310
+ };
311
+ } else {
312
+ return {
313
+ player: setBounds(state.player, [state.player.bounds[0], t])
314
+ };
315
+ }
316
+ });
317
+ },
318
+ // Set the player viewport
319
+ updatePlayerViewport: (start, end) => {
320
+ set((state) => ({
321
+ player: setViewport(state.player, [start, end])
322
+ }));
323
+ },
324
+ updatePlayerViewportCenter: (time) => {
325
+ set((state) => ({
326
+ player: seek(state.player, time ?? state.player.stamp)
327
+ }));
328
+ },
329
+ updatePlayerViewportBound: (bound, time) => {
330
+ set((state) => {
331
+ if (bound === "start" && state.player.viewport[1] <= time) {
332
+ return {
333
+ player: setViewport(state.player, [state.player.viewport[1], time])
334
+ };
335
+ } else if (bound === "end" && state.player.viewport[0] >= time) {
336
+ return {
337
+ player: setViewport(state.player, [time, state.player.viewport[0]])
338
+ };
339
+ } else if (bound === "start") {
340
+ return {
341
+ player: setViewport(state.player, [time, state.player.viewport[1]])
342
+ };
343
+ } else {
344
+ return {
345
+ player: setViewport(state.player, [state.player.viewport[0], time])
346
+ };
347
+ }
348
+ });
349
+ }
350
+ });
351
+ var usePlayerStore = (0, import_zustand.create)()(
352
+ (0, import_middleware.subscribeWithSelector)(PlayerSlice)
353
+ );
354
+ var PlayerContext = (0, import_react.createContext)(null);
355
+
356
+ // src/animated-values.ts
357
+ function instanceOfRawBoolean(object) {
358
+ return typeof object === "boolean";
359
+ }
360
+ function instanceOfRawNumber(object) {
361
+ return typeof object === "number";
362
+ }
363
+ function instanceOfRawString(object) {
364
+ return typeof object === "string";
365
+ }
366
+ function instanceOfRawVector3(object) {
367
+ return object.x !== void 0 && object.y !== void 0 && object.z !== void 0;
368
+ }
369
+ function instanceOfRawVector2(object) {
370
+ return object.x !== void 0 && object.y !== void 0;
371
+ }
372
+ function instanceOfRawEuler(object) {
373
+ return object.x !== void 0 && object.y !== void 0 && object.z !== void 0;
374
+ }
375
+ function instanceOfRawColor(object) {
376
+ return object.r !== void 0 && object.g !== void 0 && object.b !== void 0 || object.h !== void 0 && object.s !== void 0 && object.l !== void 0;
377
+ }
378
+ function instanceOfRawRGB(object) {
379
+ return object.r !== void 0 && object.g !== void 0 && object.b !== void 0;
380
+ }
381
+ function instanceOfRawHSL(object) {
382
+ return object.h !== void 0 && object.s !== void 0 && object.l !== void 0;
383
+ }
384
+ function isRawObject(value) {
385
+ if (instanceOfRawVector3(value) || instanceOfRawVector2(value) || instanceOfRawEuler(value) || instanceOfRawColor(value) || instanceOfRawRGB(value) || instanceOfRawHSL(value))
386
+ return true;
387
+ return false;
388
+ }
389
+
390
+ // src/time.ts
391
+ var numberToDurationString = (duration) => {
392
+ let milliseconds = Math.floor(duration % 1e3 / 10).toString();
393
+ let seconds = Math.floor(duration / 1e3 % 60);
394
+ let minutes = Math.floor(duration / (1e3 * 60) % 60);
395
+ minutes = minutes < 10 ? `0${minutes.toString()}` : minutes;
396
+ seconds = seconds < 10 ? `0${seconds.toString()}` : seconds;
397
+ milliseconds = milliseconds.length === 1 ? `0${milliseconds}` : milliseconds;
398
+ return `${minutes.toString()}:${seconds.toString()}:${milliseconds}`;
399
+ };
400
+
401
+ // src/pairwise.ts
402
+ function pairwise(arr) {
403
+ return arr.slice(1).map((_, i) => [arr[i], arr[i + 1]]);
404
+ }
405
+
406
+ // src/lazy.ts
407
+ var import_react2 = require("react");
408
+ function useLazy(value, timeout) {
409
+ const [lazy, setLazy] = (0, import_react2.useState)(value);
410
+ const [timeoutValue, setTimeoutValue] = (0, import_react2.useState)(null);
411
+ (0, import_react2.useEffect)(() => {
412
+ if (value) {
413
+ setLazy(value);
414
+ if (timeoutValue) {
415
+ clearTimeout(timeoutValue);
416
+ }
417
+ } else {
418
+ const timer = setTimeout(() => {
419
+ setLazy(value);
420
+ setTimeoutValue(timer);
421
+ }, timeout);
422
+ return () => {
423
+ if (timeoutValue) {
424
+ clearTimeout(timeoutValue);
425
+ }
426
+ };
427
+ }
428
+ }, [value, timeout, timeoutValue]);
429
+ return lazy;
430
+ }
431
+
432
+ // src/hexagon.ts
433
+ function getHexagonPath(x, y, size, height) {
434
+ const path = [
435
+ `${x.toString()},${(y - height / 2).toString()}`,
436
+ `${x.toString()},${(y - size / 2).toString()}`,
437
+ `${(x + size * 0.433).toString()},${(y - size / 4).toString()}`,
438
+ `${(x + size * 0.433).toString()},${(y + size / 4).toString()}`,
439
+ `${x.toString()},${(y + size / 2).toString()}`,
440
+ `${x.toString()},${(y + height / 2).toString()}`,
441
+ `${x.toString()},${(y + size / 2).toString()}`,
442
+ `${(x - size * 0.433).toString()},${(y + size / 4).toString()}`,
443
+ `${(x - size * 0.433).toString()},${(y - size / 4).toString()}`,
444
+ `${x.toString()},${(y - size / 2).toString()}`
445
+ ].join("L");
446
+ return `M${path}Z`;
447
+ }
448
+ function getDegenerateHexagonPath(x, y, size, height) {
449
+ const path = [
450
+ `${x.toString()},${(y - height / 2).toString()}`,
451
+ `${x.toString()},${(y - size / 2).toString()}`,
452
+ `${x.toString()},${(y - size / 4).toString()}`,
453
+ `${x.toString()},${(y + size / 4).toString()}`,
454
+ `${x.toString()},${(y + size / 2).toString()}`,
455
+ `${x.toString()},${(y + height / 2).toString()}`,
456
+ `${x.toString()},${(y + size / 2).toString()}`,
457
+ `${x.toString()},${(y + size / 4).toString()}`,
458
+ `${x.toString()},${(y - size / 4).toString()}`,
459
+ `${x.toString()},${(y - size / 2).toString()}`
460
+ ].join("L");
461
+ return `M${path}Z`;
462
+ }
463
+
464
+ // src/closest-frame.ts
465
+ function closestFrame(completion, count) {
466
+ const frameIdx = Math.round(completion * count);
467
+ return frameIdx / count;
468
+ }
469
+
470
+ // src/angles.ts
471
+ var toDegrees = (radians) => radians * (180 / Math.PI);
472
+ var toRadians = (degrees) => degrees * (Math.PI / 180);
473
+
474
+ // src/colors.ts
475
+ var import_color = __toESM(require("color"));
476
+ var regex = /(\d+),\s*(\d+),\s*(\d+)/;
477
+ var hexToRgba = (hex, alpha2) => {
478
+ const h = hex.replace(/^#/, "");
479
+ let r, g, b;
480
+ if (h.length === 3) {
481
+ r = parseInt(h[0] + h[0], 16);
482
+ g = parseInt(h[1] + h[1], 16);
483
+ b = parseInt(h[2] + h[2], 16);
484
+ } else if (h.length === 6) {
485
+ r = parseInt(h.substring(0, 2), 16);
486
+ g = parseInt(h.substring(2, 4), 16);
487
+ b = parseInt(h.substring(4, 6), 16);
488
+ } else {
489
+ throw new Error("Invalid HEX color.");
490
+ }
491
+ return `rgba(${r.toFixed(0)}, ${g.toFixed(0)}, ${b.toFixed(0)}, ${alpha2.toString()})`;
492
+ };
493
+ var rgbToRgba = (rgb, alpha2) => {
494
+ const result = regex.exec(rgb);
495
+ if (!result) {
496
+ throw new Error("Invalid RGB color.");
497
+ }
498
+ const r = parseInt(result[1]);
499
+ const g = parseInt(result[2]);
500
+ const b = parseInt(result[3]);
501
+ return `rgba(${r.toFixed()}, ${g.toFixed()}, ${b.toFixed()}, ${alpha2.toFixed(2)})`;
502
+ };
503
+ var hslToRgba = (hsl, alpha2) => {
504
+ const result = regex.exec(hsl);
505
+ if (!result) {
506
+ throw new Error("Invalid HSL color.");
507
+ }
508
+ const h = parseInt(result[1]) / 360;
509
+ const s = parseInt(result[2]) / 100;
510
+ const l = parseInt(result[3]) / 100;
511
+ let r, g, b;
512
+ if (s === 0) {
513
+ r = l;
514
+ g = l;
515
+ b = l;
516
+ } else {
517
+ const hue2rgb = (p2, q2, t) => {
518
+ let t1 = t;
519
+ if (t1 < 0) t1 += 1;
520
+ if (t1 > 1) t1 -= 1;
521
+ if (t1 < 1 / 6) return p2 + (q2 - p2) * 6 * t1;
522
+ if (t1 < 1 / 2) return q2;
523
+ if (t1 < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - t1) * 6;
524
+ return p2;
525
+ };
526
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
527
+ const p = 2 * l - q;
528
+ r = hue2rgb(p, q, h + 1 / 3);
529
+ g = hue2rgb(p, q, h);
530
+ b = hue2rgb(p, q, h - 1 / 3);
531
+ }
532
+ return `rgba(${Math.round(r * 255).toFixed(0)}, ${Math.round(g * 255).toFixed(0)}, ${Math.round(b * 255).toFixed(0)}, ${alpha2.toString()})`;
533
+ };
534
+ var alpha = (color, opacity) => {
535
+ if (color.startsWith("#")) {
536
+ return hexToRgba(color, opacity);
537
+ } else if (color.startsWith("rgb")) {
538
+ return rgbToRgba(color, opacity);
539
+ } else if (color.startsWith("hsl")) {
540
+ return hslToRgba(color, opacity);
541
+ } else {
542
+ throw new Error("Unsupported color format.");
543
+ }
544
+ };
545
+ function altColor(color, factor) {
546
+ if (factor > 0) {
547
+ return (0, import_color.default)(color).lighten(factor).hex();
548
+ } else {
549
+ return (0, import_color.default)(color).darken(-1 * factor).hex();
550
+ }
551
+ }
552
+ function hexToRgbArray(color) {
553
+ const c = (0, import_color.default)(color);
554
+ return [c.red(), c.green(), c.blue()];
555
+ }
556
+ function rawRGBToHex({ r, g, b }) {
557
+ return (0, import_color.default)({ r, g, b }).hex();
558
+ }
559
+ function rawHSLToHex({ h, s, l }) {
560
+ return (0, import_color.default)({ h, s, l }).hex();
561
+ }
562
+
563
+ // src/use-deep.ts
564
+ var import_react3 = require("react");
565
+ var import_deep_equal = __toESM(require("deep-equal"));
566
+ function useDeepSelector(selector) {
567
+ const prev = (0, import_react3.useRef)();
568
+ return (state) => {
569
+ const next = selector(state);
570
+ return (0, import_deep_equal.default)(prev.current, next) ? prev.current : prev.current = next;
571
+ };
572
+ }
573
+ function useDeep(initializer, dependencies) {
574
+ const prevValue = (0, import_react3.useRef)();
575
+ const prevDependencies = (0, import_react3.useRef)([]);
576
+ return (0, import_deep_equal.default)(prevDependencies.current, dependencies) ? prevValue.current : prevValue.current = initializer();
577
+ }
578
+
579
+ // src/use-media-query.ts
580
+ var import_react4 = require("react");
581
+ var useMediaQuery = (query) => {
582
+ const [matches, setMatches] = (0, import_react4.useState)(false);
583
+ (0, import_react4.useEffect)(() => {
584
+ const mediaQueryList = window.matchMedia(query);
585
+ const documentChangeHandler = () => setMatches(mediaQueryList.matches);
586
+ setMatches(mediaQueryList.matches);
587
+ mediaQueryList.addEventListener("change", documentChangeHandler);
588
+ return () => {
589
+ mediaQueryList.removeEventListener("change", documentChangeHandler);
590
+ };
591
+ }, [query]);
592
+ return matches;
593
+ };
594
+
595
+ // src/json.ts
596
+ function replacer(key, value) {
597
+ if (value instanceof Map) {
598
+ return {
599
+ dataType: "Map",
600
+ value: Array.from(value.entries())
601
+ // or with spread: value: [...value]
602
+ };
603
+ }
604
+ return value;
605
+ }
606
+ function isSerializedMap(value) {
607
+ return typeof value === "object" && value !== null && "dataType" in value && value.dataType === "Map" && Array.isArray(value.value);
608
+ }
609
+ function reviver(key, value) {
610
+ if (isSerializedMap(value)) {
611
+ return new Map(value.value);
612
+ }
613
+ return value;
614
+ }
615
+ function stringifyMapped(value) {
616
+ return JSON.stringify(value, replacer, 2);
617
+ }
618
+ function parseToMapped(json) {
619
+ return JSON.parse(json, reviver);
620
+ }
621
+ function parseJSONFileEvent(event, fn) {
622
+ const files = event.target.files;
623
+ if (files && files.length > 0) {
624
+ const reader = new FileReader();
625
+ reader.onload = (e) => {
626
+ if (e.target?.result) {
627
+ const json = e.target.result;
628
+ const data = parseToMapped(json);
629
+ if (Array.isArray(data)) {
630
+ data.forEach((d) => {
631
+ fn(d);
632
+ });
633
+ } else {
634
+ fn(data);
635
+ }
636
+ }
637
+ };
638
+ reader.readAsText(files[0]);
639
+ }
640
+ }
641
+
642
+ // src/download.ts
643
+ function downloadJSONFile(data, filename) {
644
+ const json = stringifyMapped(data);
645
+ const blob = new Blob([json], { type: "application/json" });
646
+ downloadBlob(blob, filename);
647
+ }
648
+ function downloadBlob(blob, filename) {
649
+ const url = URL.createObjectURL(blob);
650
+ const a = document.createElement("a");
651
+ a.href = url;
652
+ a.download = filename;
653
+ document.body.appendChild(a);
654
+ a.click();
655
+ document.body.removeChild(a);
656
+ URL.revokeObjectURL(url);
657
+ }
658
+
659
+ // src/points-to-path.ts
660
+ function pointsToPath(points, close) {
661
+ if (close) {
662
+ return [
663
+ points.map((p, i) => `${i === 0 ? "M" : "L"} ${p[0].toString()} ${p[1].toString()}`).join(" "),
664
+ " Z"
665
+ ].join(" ");
666
+ } else {
667
+ return points.map((p, i) => `${i === 0 ? "M" : "L"} ${p[0].toString()} ${p[1].toString()}`).join(" ");
668
+ }
669
+ }
670
+
671
+ // src/euler.ts
672
+ function eulerToRotationMatrix(euler) {
673
+ const [z, y, x] = euler;
674
+ const cz = Math.cos(z);
675
+ const sz = Math.sin(z);
676
+ const cy = Math.cos(y);
677
+ const sy = Math.sin(y);
678
+ const cx = Math.cos(x);
679
+ const sx = Math.sin(x);
680
+ return [
681
+ [cz * cy, cz * sy * sx - sz * cx, cz * sy * cx + sz * sx],
682
+ [sz * cy, sz * sy * sx + cz * cx, sz * sy * cx - cz * sx],
683
+ [-sy, cy * sx, cy * cx]
684
+ ];
685
+ }
686
+ function rotationMatrixToAngle(R) {
687
+ const trace = R[0][0] + R[1][1] + R[2][2];
688
+ return Math.acos((trace - 1) / 2);
689
+ }
690
+ function angularDistance(euler1, euler2) {
691
+ const R1 = eulerToRotationMatrix(euler1);
692
+ const R2 = eulerToRotationMatrix(euler2);
693
+ const R12 = [
694
+ [
695
+ R1[0][0] * R2[0][0] + R1[0][1] * R2[1][0] + R1[0][2] * R2[2][0],
696
+ R1[0][0] * R2[0][1] + R1[0][1] * R2[1][1] + R1[0][2] * R2[2][1],
697
+ R1[0][0] * R2[0][2] + R1[0][1] * R2[1][2] + R1[0][2] * R2[2][2]
698
+ ],
699
+ [
700
+ R1[1][0] * R2[0][0] + R1[1][1] * R2[1][0] + R1[1][2] * R2[2][0],
701
+ R1[1][0] * R2[0][1] + R1[1][1] * R2[1][1] + R1[1][2] * R2[2][1],
702
+ R1[1][0] * R2[0][2] + R1[1][1] * R2[1][2] + R1[1][2] * R2[2][2]
703
+ ],
704
+ [
705
+ R1[2][0] * R2[0][0] + R1[2][1] * R2[1][0] + R1[2][2] * R2[2][0],
706
+ R1[2][0] * R2[0][1] + R1[2][1] * R2[1][1] + R1[2][2] * R2[2][1],
707
+ R1[2][0] * R2[0][2] + R1[2][1] * R2[1][2] + R1[2][2] * R2[2][2]
708
+ ]
709
+ ];
710
+ return rotationMatrixToAngle(R12);
711
+ }
712
+
713
+ // src/overlapping-segments.ts
714
+ function overlappingSegments(original) {
715
+ const output = [];
716
+ original.toSorted((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]).forEach(([start, end]) => {
717
+ const lastIndex = output.length - 1;
718
+ if (output.length > 0 && output[lastIndex][1] >= start) {
719
+ output[lastIndex][1] = Math.max(output[lastIndex][1], end);
720
+ } else {
721
+ output.push([start, end]);
722
+ }
723
+ });
724
+ return output;
725
+ }
726
+
727
+ // src/result.ts
728
+ var Result = class _Result {
729
+ constructor(value, error) {
730
+ this.value = value;
731
+ this.error = error;
732
+ }
733
+ /**
734
+ * Creates a new Result instance with a success value
735
+ * @template T The type of the success value
736
+ * @template E The type of the error value
737
+ * @param value The success value
738
+ * @returns A new Result instance containing the success value
739
+ */
740
+ static Ok(value) {
741
+ return new _Result(value);
742
+ }
743
+ /**
744
+ * Creates a new Result instance with an error value
745
+ * @template T The type of the success value
746
+ * @template E The type of the error value
747
+ * @param error The error value
748
+ * @returns A new Result instance containing the error value
749
+ */
750
+ static Err(error) {
751
+ return new _Result(void 0, error);
752
+ }
753
+ /**
754
+ * Creates a new Result instance with an Error created from a string message
755
+ * @template T The type of the success value
756
+ * @param errorMessage The error message string
757
+ * @returns A new Result instance containing an Error with the given message
758
+ */
759
+ static ErrFromStr(errorMessage) {
760
+ const error = new Error(errorMessage);
761
+ return new _Result(void 0, error);
762
+ }
763
+ /**
764
+ * Maps the success value to a new value using the provided function
765
+ * @template U The type of the new success value
766
+ * @param fn The mapping function
767
+ * @returns A new Result with the mapped success value or the original error
768
+ */
769
+ map(fn) {
770
+ return this.isOk() ? _Result.Ok(fn(this.value)) : _Result.Err(this.error);
771
+ }
772
+ /**
773
+ * Maps the error value to a new error using the provided function
774
+ * @template F The type of the new error value
775
+ * @param fn The mapping function
776
+ * @returns A new Result with the mapped error value or the original success value
777
+ */
778
+ mapErr(fn) {
779
+ return this.isOk() ? _Result.Ok(this.value) : _Result.Err(fn(this.error));
780
+ }
781
+ /**
782
+ * Chains a computation that returns a Result
783
+ * @template U The type of the new success value
784
+ * @param fn The function to chain
785
+ * @returns The result of the chained function or the original error
786
+ */
787
+ andThen(fn) {
788
+ return this.isOk() ? fn(this.value) : _Result.Err(this.error);
789
+ }
790
+ /**
791
+ * Applies one of two functions depending on whether the Result is Ok or Err
792
+ * @template U The type of the return value
793
+ * @param ok The function to apply to the success value
794
+ * @param err The function to apply to the error value
795
+ * @returns The result of applying the appropriate function
796
+ */
797
+ match(ok, err) {
798
+ return this.isOk() ? ok(this.value) : err(this.error);
799
+ }
800
+ /**
801
+ * Checks if the Result contains a success value
802
+ * @returns true if the Result contains a success value, false otherwise
803
+ */
804
+ isOk() {
805
+ return this.error === void 0;
806
+ }
807
+ /**
808
+ * Checks if the Result contains an error value
809
+ * @returns true if the Result contains an error value, false otherwise
810
+ */
811
+ isErr() {
812
+ return this.error !== void 0;
813
+ }
814
+ /**
815
+ * Extracts the success value from the Result
816
+ * @throws Error if the Result contains an error value
817
+ * @returns The success value
818
+ */
819
+ unwrap() {
820
+ if (this.isErr()) {
821
+ throw new Error(`Tried to unwrap an Err value${this.error ? `: ${String(this.error)}` : ""}`);
822
+ }
823
+ return this.value;
824
+ }
825
+ /**
826
+ * Returns the success value or a default value if the Result contains an error
827
+ * @param defaultValue The value to return if the Result contains an error
828
+ * @returns The success value or the default value
829
+ */
830
+ unwrapOr(defaultValue) {
831
+ return this.isOk() ? this.value : defaultValue;
832
+ }
833
+ /**
834
+ * Extracts the error value from the Result
835
+ * @throws Error if the Result contains a success value
836
+ * @returns The error value
837
+ */
838
+ unwrapErr() {
839
+ if (this.isOk()) {
840
+ throw new Error("Tried to unwrap an Ok value");
841
+ }
842
+ return this.error;
843
+ }
844
+ /**
845
+ * Converts the Result to a string representation
846
+ * @returns A string representation of the Result
847
+ */
848
+ toString() {
849
+ return this.isOk() ? `Ok(${typeof this.value === "object" ? JSON.stringify(this.value) : String(this.value)})` : `Err(${typeof this.error === "object" ? JSON.stringify(this.error) : String(this.error)})`;
850
+ }
851
+ };
852
+
853
+ // src/progress.ts
854
+ function incrementProgress(progress, message, increment = 1) {
855
+ return {
856
+ ...progress,
857
+ current: progress.current + increment,
858
+ message: message ?? progress.message
859
+ };
860
+ }
861
+ function composeProgress(progresses) {
862
+ let current = 0;
863
+ let total = 0;
864
+ let message = "";
865
+ progresses.forEach((progress) => {
866
+ current += progress.current;
867
+ total += progress.total;
868
+ if (progress.message) {
869
+ message += `${progress.message}
870
+ `;
871
+ }
872
+ });
873
+ message = message.trim();
874
+ return { current, total, message };
875
+ }
876
+ function composeProgressiveResult(progressiveResults, expectedIds) {
877
+ const fullProgress = composeProgress(progressiveResults.map((pr) => pr.progress));
878
+ let fullResult;
879
+ if (progressiveResults.some((res) => res.result?.isErr() ?? true)) {
880
+ fullResult = Result.ErrFromStr("There was an error");
881
+ } else {
882
+ const metas = progressiveResults.flatMap((res) => {
883
+ const innerRes = res.result?.unwrap();
884
+ if (Array.isArray(innerRes)) return innerRes;
885
+ return [innerRes];
886
+ });
887
+ if (expectedIds) {
888
+ const data = expectedIds.map((id) => metas.find((m) => "id" in (m || {}) && m?.id === id));
889
+ if (fullProgress.current >= fullProgress.total && data.some((m) => m === void 0 || m === null)) {
890
+ fullResult = Result.ErrFromStr("Some documents not found");
891
+ } else {
892
+ fullResult = Result.Ok(data);
893
+ }
894
+ } else {
895
+ fullResult = Result.Ok(metas);
896
+ }
897
+ }
898
+ return { result: fullResult, progress: fullProgress };
899
+ }
900
+
901
+ // src/regex.ts
902
+ var EMAIL = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
903
+
904
+ // src/map-deep-equal.ts
905
+ var import_fast_deep_equal = __toESM(require("fast-deep-equal"));
906
+ function isMapDeepEqual(map1, map2) {
907
+ if (map1.size !== map2.size) return false;
908
+ for (const [key, value] of map1.entries()) {
909
+ if (!map2.has(key)) return false;
910
+ const otherValue = map2.get(key);
911
+ if (!(0, import_fast_deep_equal.default)(value, otherValue)) {
912
+ return false;
913
+ }
914
+ }
915
+ return true;
916
+ }
917
+ // Annotate the CommonJS export names for ESM import in node:
918
+ 0 && (module.exports = {
919
+ EMAIL,
920
+ PlayerContext,
921
+ PlayerSlice,
922
+ Result,
923
+ alpha,
924
+ altColor,
925
+ angularDistance,
926
+ closestFrame,
927
+ composeProgress,
928
+ composeProgressiveResult,
929
+ downloadBlob,
930
+ downloadJSONFile,
931
+ eulerToRotationMatrix,
932
+ getDegenerateHexagonPath,
933
+ getHexagonPath,
934
+ getId,
935
+ getLookup,
936
+ getNamespace,
937
+ hexToRgbArray,
938
+ hexToRgba,
939
+ hslToRgba,
940
+ incrementProgress,
941
+ instanceOfRawBoolean,
942
+ instanceOfRawColor,
943
+ instanceOfRawEuler,
944
+ instanceOfRawHSL,
945
+ instanceOfRawNumber,
946
+ instanceOfRawRGB,
947
+ instanceOfRawString,
948
+ instanceOfRawVector2,
949
+ instanceOfRawVector3,
950
+ isMapDeepEqual,
951
+ isRawObject,
952
+ log,
953
+ newPlayer,
954
+ now,
955
+ numberToDurationString,
956
+ overlappingSegments,
957
+ pairwise,
958
+ parseJSONFileEvent,
959
+ parseToMapped,
960
+ pause,
961
+ play,
962
+ pointsToPath,
963
+ rawHSLToHex,
964
+ rawRGBToHex,
965
+ reset,
966
+ rgbToRgba,
967
+ rotationMatrixToAngle,
968
+ seek,
969
+ setBounds,
970
+ setDuration,
971
+ setViewport,
972
+ stringifyMapped,
973
+ toDegrees,
974
+ toRadians,
975
+ update,
976
+ useDeep,
977
+ useDeepSelector,
978
+ useLazy,
979
+ useMediaQuery,
980
+ usePlayerStore
981
+ });