@semio/utils 0.0.0 → 0.1.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.d.mts +482 -69
- package/dist/index.d.ts +482 -69
- package/dist/index.js +573 -131
- package/dist/index.mjs +535 -126
- package/package.json +18 -9
package/dist/index.mjs
CHANGED
|
@@ -19,103 +19,114 @@ function getId(lookup) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// src/player.ts
|
|
22
|
+
var PlayerDirection = /* @__PURE__ */ ((PlayerDirection3) => {
|
|
23
|
+
PlayerDirection3["Reverse"] = "reverse";
|
|
24
|
+
PlayerDirection3["Forward"] = "forward";
|
|
25
|
+
return PlayerDirection3;
|
|
26
|
+
})(PlayerDirection || {});
|
|
22
27
|
function reset(player, stamp) {
|
|
23
28
|
const p = { ...player };
|
|
24
29
|
const nowVal = now();
|
|
25
30
|
p._currentTime = nowVal;
|
|
26
31
|
p._previousTime = nowVal;
|
|
27
32
|
p.stamp = stamp ? stamp : 0;
|
|
33
|
+
p._currentDirection = p.direction;
|
|
34
|
+
p._bounced = false;
|
|
35
|
+
p._enteredBounds = false;
|
|
28
36
|
return p;
|
|
29
37
|
}
|
|
30
38
|
function now() {
|
|
31
39
|
return (typeof performance === "undefined" ? Date : performance).now();
|
|
32
40
|
}
|
|
33
|
-
function
|
|
41
|
+
function updated(player, coldStart) {
|
|
34
42
|
const p = { ...player };
|
|
35
43
|
const duration = p.duration;
|
|
36
44
|
const t = now();
|
|
37
45
|
p._previousTime = coldStart ? t : p._currentTime;
|
|
38
46
|
p._currentTime = t;
|
|
39
47
|
const currentInBounds = p.stamp >= p.bounds[0] && p.stamp <= p.bounds[1];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
if (currentInBounds && !p._enteredBounds) {
|
|
49
|
+
p._enteredBounds = true;
|
|
50
|
+
}
|
|
51
|
+
const effectiveTimescale = p.speed * (p._currentDirection === "forward" /* Forward */ ? 1 : -1);
|
|
52
|
+
const delta = (p._currentTime - p._previousTime) * effectiveTimescale;
|
|
43
53
|
const updatedStamp = p.stamp + delta;
|
|
44
|
-
const [start, end] = currentInBounds ?
|
|
45
|
-
|
|
54
|
+
const [start, end] = !p._enteredBounds && !currentInBounds ? [0, duration] : p.bounds;
|
|
55
|
+
const movingTowardBounds = p.stamp < start && p._currentDirection === "forward" /* Forward */ || p.stamp > end && p._currentDirection === "reverse" /* Reverse */;
|
|
46
56
|
if (updatedStamp > end) {
|
|
47
|
-
if (
|
|
48
|
-
p.stamp =
|
|
49
|
-
} else if (p.playback === "bounce") {
|
|
50
|
-
p.stamp = end;
|
|
51
|
-
p.timescale *= -1;
|
|
57
|
+
if (movingTowardBounds) {
|
|
58
|
+
p.stamp = updatedStamp;
|
|
52
59
|
} else {
|
|
53
|
-
p.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
if (p.bounce && (p.looping || !p._bounced)) {
|
|
61
|
+
p.stamp = end;
|
|
62
|
+
p._currentDirection = p._currentDirection === "forward" /* Forward */ ? "reverse" /* Reverse */ : "forward" /* Forward */;
|
|
63
|
+
p._bounced = true;
|
|
64
|
+
} else if (p.looping) {
|
|
65
|
+
p.stamp = start;
|
|
66
|
+
} else {
|
|
67
|
+
p.stamp = end;
|
|
61
68
|
p.running = false;
|
|
62
69
|
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
}
|
|
71
|
+
} else if (updatedStamp < start) {
|
|
72
|
+
if (movingTowardBounds) {
|
|
73
|
+
p.stamp = updatedStamp;
|
|
66
74
|
} else {
|
|
67
|
-
p.
|
|
68
|
-
|
|
75
|
+
if (p.bounce && (p.looping || !p._bounced)) {
|
|
76
|
+
p.stamp = start;
|
|
77
|
+
p._currentDirection = p._currentDirection === "forward" /* Forward */ ? "reverse" /* Reverse */ : "forward" /* Forward */;
|
|
78
|
+
p._bounced = true;
|
|
79
|
+
} else if (p.looping) {
|
|
80
|
+
p.stamp = end;
|
|
81
|
+
} else {
|
|
82
|
+
p.stamp = start;
|
|
83
|
+
p.running = false;
|
|
84
|
+
}
|
|
69
85
|
}
|
|
70
|
-
attachOverride = true;
|
|
71
86
|
} else {
|
|
72
87
|
p.stamp = updatedStamp;
|
|
73
88
|
}
|
|
74
|
-
const newNearViewportCenter = Math.abs(p.stamp - currentViewportCenter) < 0.01;
|
|
75
|
-
const boundsInsideViewport = p.viewport[0] <= p.bounds[0] || p.viewport[1] >= p.bounds[1];
|
|
76
|
-
if (p.running && !boundsInsideViewport && (nearViewportCenterCurrent || newNearViewportCenter || attachOverride)) {
|
|
77
|
-
p.viewport = getFittedViewport(p.stamp, p.viewport);
|
|
78
|
-
} else if (p.running && !boundsInsideViewport && !newNearViewportCenter) {
|
|
79
|
-
const oomphOffset = currentViewportCenter < p.stamp ? delta : 0;
|
|
80
|
-
const idealViewport = getFittedViewport(p.stamp + oomphOffset, p.viewport);
|
|
81
|
-
p.viewport = [
|
|
82
|
-
p.viewport[0] * 0.6 + idealViewport[0] * 0.4,
|
|
83
|
-
p.viewport[1] * 0.6 + idealViewport[1] * 0.4
|
|
84
|
-
];
|
|
85
|
-
}
|
|
86
89
|
return p;
|
|
87
90
|
}
|
|
88
|
-
function
|
|
91
|
+
function withBounds(player, bounds) {
|
|
89
92
|
const p = { ...player };
|
|
90
93
|
p.bounds = bounds;
|
|
91
94
|
return p;
|
|
92
95
|
}
|
|
93
|
-
function
|
|
94
|
-
const p = { ...player };
|
|
95
|
-
p.viewport = viewport;
|
|
96
|
-
return p;
|
|
97
|
-
}
|
|
98
|
-
function play(player, speed) {
|
|
96
|
+
function play(player, speed, direction) {
|
|
99
97
|
const p = { ...player };
|
|
100
98
|
p.running = true;
|
|
101
|
-
p.
|
|
102
|
-
if (
|
|
99
|
+
if (speed !== void 0) p.speed = Math.abs(speed);
|
|
100
|
+
if (direction !== void 0) {
|
|
101
|
+
p.direction = direction;
|
|
102
|
+
}
|
|
103
|
+
p._currentDirection = p.direction;
|
|
104
|
+
p._bounced = false;
|
|
105
|
+
p._enteredBounds = false;
|
|
106
|
+
if (!p.looping && !p.bounce) {
|
|
107
|
+
if (p.direction === "forward" /* Forward */ && p.stamp === p.bounds[1]) {
|
|
108
|
+
p.stamp = p.bounds[0];
|
|
109
|
+
} else if (p.direction === "reverse" /* Reverse */ && p.stamp === p.bounds[0]) {
|
|
110
|
+
p.stamp = p.bounds[1];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const tolerance = 1;
|
|
114
|
+
if (p._currentDirection === "forward" /* Forward */ && Math.abs(p.stamp - p.bounds[1]) <= tolerance) {
|
|
103
115
|
p.stamp = p.bounds[0];
|
|
116
|
+
} else if (p._currentDirection === "reverse" /* Reverse */ && Math.abs(p.stamp - p.bounds[0]) <= tolerance) {
|
|
117
|
+
p.stamp = p.bounds[1];
|
|
104
118
|
}
|
|
105
119
|
return p;
|
|
106
120
|
}
|
|
107
121
|
function pause(player) {
|
|
108
122
|
const p = { ...player };
|
|
109
123
|
p.running = false;
|
|
110
|
-
p.timescale = 0;
|
|
111
124
|
return p;
|
|
112
125
|
}
|
|
113
126
|
function seek(player, stamp) {
|
|
114
|
-
|
|
115
|
-
p.viewport = getFittedViewport(stamp, p.viewport);
|
|
116
|
-
return p;
|
|
127
|
+
return reset(player, stamp);
|
|
117
128
|
}
|
|
118
|
-
function
|
|
129
|
+
function withDuration(player, duration) {
|
|
119
130
|
const p = { ...player };
|
|
120
131
|
p.duration = duration;
|
|
121
132
|
return p;
|
|
@@ -126,25 +137,52 @@ function newPlayer() {
|
|
|
126
137
|
_previousTime: now(),
|
|
127
138
|
_currentTime: now(),
|
|
128
139
|
stamp: 0,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
140
|
+
speed: 1,
|
|
141
|
+
direction: "forward" /* Forward */,
|
|
142
|
+
_currentDirection: "forward" /* Forward */,
|
|
143
|
+
_bounced: false,
|
|
144
|
+
_enteredBounds: false,
|
|
145
|
+
bounds: [0, 5e3],
|
|
146
|
+
bounce: false,
|
|
147
|
+
looping: true,
|
|
148
|
+
duration: 5e3
|
|
134
149
|
};
|
|
135
150
|
}
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (proposedLeft >= 0 && proposedRight <= 1) {
|
|
141
|
-
return [playhead - viewportWidth / 2, playhead + viewportWidth / 2];
|
|
142
|
-
} else if (proposedLeft < 0) {
|
|
143
|
-
return [0, viewportWidth];
|
|
144
|
-
} else {
|
|
145
|
-
return [1 - viewportWidth, 1];
|
|
151
|
+
function withSpeed(player, speed) {
|
|
152
|
+
const p = { ...player };
|
|
153
|
+
if (speed < 0) {
|
|
154
|
+
throw new Error("Speed must be a positive number.");
|
|
146
155
|
}
|
|
147
|
-
|
|
156
|
+
p.speed = speed;
|
|
157
|
+
return p;
|
|
158
|
+
}
|
|
159
|
+
function withDirection(player, direction) {
|
|
160
|
+
const p = { ...player };
|
|
161
|
+
p.direction = direction;
|
|
162
|
+
p._currentDirection = direction;
|
|
163
|
+
p._bounced = false;
|
|
164
|
+
p._enteredBounds = false;
|
|
165
|
+
return p;
|
|
166
|
+
}
|
|
167
|
+
function reversed(player) {
|
|
168
|
+
const p = { ...player };
|
|
169
|
+
const newDirection = p.direction === "forward" /* Forward */ ? "reverse" /* Reverse */ : "forward" /* Forward */;
|
|
170
|
+
p.direction = newDirection;
|
|
171
|
+
p._currentDirection = newDirection;
|
|
172
|
+
p._bounced = false;
|
|
173
|
+
p._enteredBounds = false;
|
|
174
|
+
return p;
|
|
175
|
+
}
|
|
176
|
+
function withBounce(player, bounce) {
|
|
177
|
+
const p = { ...player };
|
|
178
|
+
p.bounce = bounce;
|
|
179
|
+
return p;
|
|
180
|
+
}
|
|
181
|
+
function withLooping(player, looping) {
|
|
182
|
+
const p = { ...player };
|
|
183
|
+
p.looping = looping;
|
|
184
|
+
return p;
|
|
185
|
+
}
|
|
148
186
|
|
|
149
187
|
// src/player-store.ts
|
|
150
188
|
import { createContext } from "react";
|
|
@@ -156,29 +194,50 @@ THREE.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
|
156
194
|
enableMapSet();
|
|
157
195
|
var PlayerSlice = (set) => ({
|
|
158
196
|
player: newPlayer(),
|
|
159
|
-
// Set the duration of the player
|
|
197
|
+
// Set the duration of the player. Also rescales bounds if they were at
|
|
198
|
+
// the old default. Uses `produce` (rather than the spread+`withX` pattern
|
|
199
|
+
// the other actions use) because the bounds rescaling is a multi-field
|
|
200
|
+
// atomic conditional write. Viewport rescaling is handled separately by
|
|
201
|
+
// the viewport-follow subscription.
|
|
160
202
|
updateDuration: (duration) => {
|
|
161
203
|
set(
|
|
162
204
|
produce((state) => {
|
|
205
|
+
const oldDuration = state.player.duration;
|
|
163
206
|
state.player.duration = duration;
|
|
207
|
+
if (oldDuration > 0 && duration > 0) {
|
|
208
|
+
const b = state.player.bounds;
|
|
209
|
+
if (Math.abs(b[1] - oldDuration) < 1) {
|
|
210
|
+
state.player.bounds = [b[0], duration];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
164
213
|
})
|
|
165
214
|
);
|
|
166
215
|
},
|
|
167
|
-
// Set the
|
|
168
|
-
|
|
169
|
-
set(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
216
|
+
// Set the speed of the animation playback
|
|
217
|
+
updateSpeed: (speed) => {
|
|
218
|
+
set((state) => ({
|
|
219
|
+
player: withSpeed(state.player, speed)
|
|
220
|
+
}));
|
|
221
|
+
},
|
|
222
|
+
// Set the direction of the animation playback
|
|
223
|
+
updateDirection: (direction) => {
|
|
224
|
+
set((state) => ({
|
|
225
|
+
player: withDirection(state.player, direction)
|
|
226
|
+
}));
|
|
227
|
+
},
|
|
228
|
+
// Reverse the current direction of the animation playback
|
|
229
|
+
reverseDirection: () => {
|
|
230
|
+
set((state) => ({
|
|
231
|
+
player: reversed(state.player)
|
|
232
|
+
}));
|
|
174
233
|
},
|
|
175
234
|
// Set the time of the animation
|
|
176
235
|
resetPlayer: (time) => {
|
|
177
236
|
set((state) => ({ player: reset(state.player, time) }));
|
|
178
237
|
},
|
|
179
238
|
// Play the animation
|
|
180
|
-
playPlayer: (speed) => {
|
|
181
|
-
set((state) => ({ player: play(state.player, speed) }));
|
|
239
|
+
playPlayer: (speed, direction) => {
|
|
240
|
+
set((state) => ({ player: play(state.player, speed, direction) }));
|
|
182
241
|
},
|
|
183
242
|
// Pause the animation
|
|
184
243
|
pausePlayer: () => {
|
|
@@ -187,13 +246,13 @@ var PlayerSlice = (set) => ({
|
|
|
187
246
|
// Update the timer
|
|
188
247
|
updatePlayer: (coldStart) => {
|
|
189
248
|
set((state) => ({
|
|
190
|
-
player:
|
|
249
|
+
player: updated(state.player, coldStart ?? false)
|
|
191
250
|
}));
|
|
192
251
|
},
|
|
193
252
|
// Set the player bounds
|
|
194
253
|
updatePlayerBounds: (start, end) => {
|
|
195
254
|
set((state) => ({
|
|
196
|
-
player:
|
|
255
|
+
player: withBounds(state.player, [start, end])
|
|
197
256
|
}));
|
|
198
257
|
},
|
|
199
258
|
updatePlayerBound: (bound, time) => {
|
|
@@ -201,54 +260,32 @@ var PlayerSlice = (set) => ({
|
|
|
201
260
|
const t = time ?? state.player.stamp;
|
|
202
261
|
if (bound === "start" && state.player.bounds[1] <= t) {
|
|
203
262
|
return {
|
|
204
|
-
player:
|
|
263
|
+
player: withBounds(state.player, [state.player.bounds[1], t])
|
|
205
264
|
};
|
|
206
265
|
} else if (bound === "end" && state.player.bounds[0] >= t) {
|
|
207
266
|
return {
|
|
208
|
-
player:
|
|
267
|
+
player: withBounds(state.player, [t, state.player.bounds[0]])
|
|
209
268
|
};
|
|
210
269
|
} else if (bound === "start") {
|
|
211
270
|
return {
|
|
212
|
-
player:
|
|
271
|
+
player: withBounds(state.player, [t, state.player.bounds[1]])
|
|
213
272
|
};
|
|
214
273
|
} else {
|
|
215
274
|
return {
|
|
216
|
-
player:
|
|
275
|
+
player: withBounds(state.player, [state.player.bounds[0], t])
|
|
217
276
|
};
|
|
218
277
|
}
|
|
219
278
|
});
|
|
220
279
|
},
|
|
221
|
-
|
|
222
|
-
updatePlayerViewport: (start, end) => {
|
|
280
|
+
updateBounce: (bounce) => {
|
|
223
281
|
set((state) => ({
|
|
224
|
-
player:
|
|
282
|
+
player: withBounce(state.player, bounce)
|
|
225
283
|
}));
|
|
226
284
|
},
|
|
227
|
-
|
|
285
|
+
updateLooping: (looping) => {
|
|
228
286
|
set((state) => ({
|
|
229
|
-
player:
|
|
287
|
+
player: withLooping(state.player, looping)
|
|
230
288
|
}));
|
|
231
|
-
},
|
|
232
|
-
updatePlayerViewportBound: (bound, time) => {
|
|
233
|
-
set((state) => {
|
|
234
|
-
if (bound === "start" && state.player.viewport[1] <= time) {
|
|
235
|
-
return {
|
|
236
|
-
player: setViewport(state.player, [state.player.viewport[1], time])
|
|
237
|
-
};
|
|
238
|
-
} else if (bound === "end" && state.player.viewport[0] >= time) {
|
|
239
|
-
return {
|
|
240
|
-
player: setViewport(state.player, [time, state.player.viewport[0]])
|
|
241
|
-
};
|
|
242
|
-
} else if (bound === "start") {
|
|
243
|
-
return {
|
|
244
|
-
player: setViewport(state.player, [time, state.player.viewport[1]])
|
|
245
|
-
};
|
|
246
|
-
} else {
|
|
247
|
-
return {
|
|
248
|
-
player: setViewport(state.player, [state.player.viewport[0], time])
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
289
|
}
|
|
253
290
|
});
|
|
254
291
|
var usePlayerStore = create()(
|
|
@@ -257,6 +294,17 @@ var usePlayerStore = create()(
|
|
|
257
294
|
var PlayerContext = createContext(null);
|
|
258
295
|
|
|
259
296
|
// src/animated-values.ts
|
|
297
|
+
var AnimatableGroupType = /* @__PURE__ */ ((AnimatableGroupType2) => {
|
|
298
|
+
AnimatableGroupType2["Vector2"] = "vector2";
|
|
299
|
+
AnimatableGroupType2["Vector3"] = "vector3";
|
|
300
|
+
AnimatableGroupType2["Euler"] = "euler";
|
|
301
|
+
AnimatableGroupType2["RGB"] = "rgb";
|
|
302
|
+
AnimatableGroupType2["HSL"] = "hsl";
|
|
303
|
+
AnimatableGroupType2["Group"] = "group";
|
|
304
|
+
AnimatableGroupType2["Entity"] = "entity";
|
|
305
|
+
AnimatableGroupType2["Instance"] = "instance";
|
|
306
|
+
return AnimatableGroupType2;
|
|
307
|
+
})(AnimatableGroupType || {});
|
|
260
308
|
function instanceOfRawBoolean(object) {
|
|
261
309
|
return typeof object === "boolean";
|
|
262
310
|
}
|
|
@@ -270,10 +318,10 @@ function instanceOfRawVector3(object) {
|
|
|
270
318
|
return object.x !== void 0 && object.y !== void 0 && object.z !== void 0;
|
|
271
319
|
}
|
|
272
320
|
function instanceOfRawVector2(object) {
|
|
273
|
-
return object.x !== void 0 && object.y !== void 0;
|
|
321
|
+
return object.x !== void 0 && object.y !== void 0 && object.z === void 0;
|
|
274
322
|
}
|
|
275
323
|
function instanceOfRawEuler(object) {
|
|
276
|
-
return object.
|
|
324
|
+
return object.r !== void 0 && object.p !== void 0 && object.y !== void 0;
|
|
277
325
|
}
|
|
278
326
|
function instanceOfRawColor(object) {
|
|
279
327
|
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;
|
|
@@ -284,6 +332,12 @@ function instanceOfRawRGB(object) {
|
|
|
284
332
|
function instanceOfRawHSL(object) {
|
|
285
333
|
return object.h !== void 0 && object.s !== void 0 && object.l !== void 0;
|
|
286
334
|
}
|
|
335
|
+
function warnUnexpectedFeatureValue(feature, expected, value) {
|
|
336
|
+
console.warn(
|
|
337
|
+
`Feature "${feature}" expected ${expected}, received ${typeof value}:`,
|
|
338
|
+
value
|
|
339
|
+
);
|
|
340
|
+
}
|
|
287
341
|
function isRawObject(value) {
|
|
288
342
|
if (instanceOfRawVector3(value) || instanceOfRawVector2(value) || instanceOfRawEuler(value) || instanceOfRawColor(value) || instanceOfRawRGB(value) || instanceOfRawHSL(value))
|
|
289
343
|
return true;
|
|
@@ -365,9 +419,11 @@ function getDegenerateHexagonPath(x, y, size, height) {
|
|
|
365
419
|
}
|
|
366
420
|
|
|
367
421
|
// src/closest-frame.ts
|
|
368
|
-
function closestFrame(
|
|
369
|
-
|
|
370
|
-
|
|
422
|
+
function closestFrame(stampMs, framerate) {
|
|
423
|
+
if (framerate <= 0) return stampMs;
|
|
424
|
+
const frameDurationMs = 1e3 / framerate;
|
|
425
|
+
const frameIdx = Math.round(stampMs / frameDurationMs);
|
|
426
|
+
return frameIdx * frameDurationMs;
|
|
371
427
|
}
|
|
372
428
|
|
|
373
429
|
// src/angles.ts
|
|
@@ -462,19 +518,62 @@ function rawRGBToHex({ r, g, b }) {
|
|
|
462
518
|
function rawHSLToHex({ h, s, l }) {
|
|
463
519
|
return Color({ h, s, l }).hex();
|
|
464
520
|
}
|
|
521
|
+
function randomHexString(constrainLuminosity, constrainSaturation) {
|
|
522
|
+
const h = Math.floor(Math.random() * 255);
|
|
523
|
+
const s = Math.floor(constrainSaturation ? constrainSaturation * 100 : Math.random() * 100);
|
|
524
|
+
const l = Math.floor(constrainLuminosity ? constrainLuminosity * 100 : Math.random() * 100);
|
|
525
|
+
return Color({ h, s, l }).hex();
|
|
526
|
+
}
|
|
527
|
+
function rgbChroma([r, g, b]) {
|
|
528
|
+
const max = Math.max(r, g, b);
|
|
529
|
+
const min = Math.min(r, g, b);
|
|
530
|
+
return (max - min) / 255;
|
|
531
|
+
}
|
|
532
|
+
function rgbLightness([r, g, b]) {
|
|
533
|
+
const max = Math.max(r, g, b);
|
|
534
|
+
const min = Math.min(r, g, b);
|
|
535
|
+
return (max + min) / (2 * 255);
|
|
536
|
+
}
|
|
537
|
+
function colorChroma(color) {
|
|
538
|
+
return rgbChroma(hexToRgbArray(color));
|
|
539
|
+
}
|
|
540
|
+
function colorLightness(color) {
|
|
541
|
+
return rgbLightness(hexToRgbArray(color));
|
|
542
|
+
}
|
|
543
|
+
function shouldUseBlendForLabelColor(color, opts) {
|
|
544
|
+
if (!color) return false;
|
|
545
|
+
let rgb;
|
|
546
|
+
try {
|
|
547
|
+
rgb = hexToRgbArray(color);
|
|
548
|
+
} catch {
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
const chroma = rgbChroma(rgb);
|
|
552
|
+
const lightness = rgbLightness(rgb);
|
|
553
|
+
const { chromaCutoff = 0.08, minLightness = 0.28, maxLightness = 0.75 } = opts ?? {};
|
|
554
|
+
const isNearGray = chroma < chromaCutoff;
|
|
555
|
+
const isMidLightness = lightness > minLightness && lightness < maxLightness;
|
|
556
|
+
return !(isNearGray && isMidLightness);
|
|
557
|
+
}
|
|
558
|
+
function isNearNeutralMid(color, opts) {
|
|
559
|
+
const { chromaCutoff = 0.08, minLightness = 0.28, maxLightness = 0.75 } = opts ?? {};
|
|
560
|
+
const c = colorChroma(color);
|
|
561
|
+
const l = colorLightness(color);
|
|
562
|
+
return c < chromaCutoff && l > minLightness && l < maxLightness;
|
|
563
|
+
}
|
|
465
564
|
|
|
466
565
|
// src/use-deep.ts
|
|
467
566
|
import { useRef } from "react";
|
|
468
567
|
import deepEqual from "deep-equal";
|
|
469
568
|
function useDeepSelector(selector) {
|
|
470
|
-
const prev = useRef();
|
|
569
|
+
const prev = useRef(void 0);
|
|
471
570
|
return (state) => {
|
|
472
571
|
const next = selector(state);
|
|
473
572
|
return deepEqual(prev.current, next) ? prev.current : prev.current = next;
|
|
474
573
|
};
|
|
475
574
|
}
|
|
476
575
|
function useDeep(initializer, dependencies) {
|
|
477
|
-
const prevValue = useRef();
|
|
576
|
+
const prevValue = useRef(void 0);
|
|
478
577
|
const prevDependencies = useRef([]);
|
|
479
578
|
return deepEqual(prevDependencies.current, dependencies) ? prevValue.current : prevValue.current = initializer();
|
|
480
579
|
}
|
|
@@ -612,6 +711,98 @@ function angularDistance(euler1, euler2) {
|
|
|
612
711
|
];
|
|
613
712
|
return rotationMatrixToAngle(R12);
|
|
614
713
|
}
|
|
714
|
+
function eulerToQuaternion(euler) {
|
|
715
|
+
const [z, y, x] = euler;
|
|
716
|
+
const cx = Math.cos(x * 0.5);
|
|
717
|
+
const sx = Math.sin(x * 0.5);
|
|
718
|
+
const cy = Math.cos(y * 0.5);
|
|
719
|
+
const sy = Math.sin(y * 0.5);
|
|
720
|
+
const cz = Math.cos(z * 0.5);
|
|
721
|
+
const sz = Math.sin(z * 0.5);
|
|
722
|
+
const w = cx * cy * cz + sx * sy * sz;
|
|
723
|
+
const qx = sx * cy * cz - cx * sy * sz;
|
|
724
|
+
const qy = cx * sy * cz + sx * cy * sz;
|
|
725
|
+
const qz = cx * cy * sz - sx * sy * cz;
|
|
726
|
+
return [w, qx, qy, qz];
|
|
727
|
+
}
|
|
728
|
+
function quaternionToEuler(q) {
|
|
729
|
+
const [w, x, y, z] = q;
|
|
730
|
+
const sinrCosp = 2 * (w * x + y * z);
|
|
731
|
+
const cosrCosp = 1 - 2 * (x * x + y * y);
|
|
732
|
+
const roll = Math.atan2(sinrCosp, cosrCosp);
|
|
733
|
+
const sinp = 2 * (w * y - z * x);
|
|
734
|
+
let pitch;
|
|
735
|
+
if (Math.abs(sinp) >= 1) {
|
|
736
|
+
pitch = Math.sign(sinp) * Math.PI / 2;
|
|
737
|
+
} else {
|
|
738
|
+
pitch = Math.asin(sinp);
|
|
739
|
+
}
|
|
740
|
+
const sinyCosp = 2 * (w * z + x * y);
|
|
741
|
+
const cosyCosp = 1 - 2 * (y * y + z * z);
|
|
742
|
+
const yaw = Math.atan2(sinyCosp, cosyCosp);
|
|
743
|
+
return [yaw, pitch, roll];
|
|
744
|
+
}
|
|
745
|
+
function quaternionMultiply(q1, q2) {
|
|
746
|
+
const [w1, x1, y1, z1] = q1;
|
|
747
|
+
const [w2, x2, y2, z2] = q2;
|
|
748
|
+
const w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2;
|
|
749
|
+
const x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2;
|
|
750
|
+
const y = w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2;
|
|
751
|
+
const z = w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2;
|
|
752
|
+
return [w, x, y, z];
|
|
753
|
+
}
|
|
754
|
+
function quaternionConjugate(q) {
|
|
755
|
+
const [w, x, y, z] = q;
|
|
756
|
+
return [w, -x, -y, -z];
|
|
757
|
+
}
|
|
758
|
+
function quaternionSlerp(q1, q2, t) {
|
|
759
|
+
const [w1, x1, y1, z1] = q1;
|
|
760
|
+
const [w2, x2, y2, z2] = q2;
|
|
761
|
+
let dot = w1 * w2 + x1 * x2 + y1 * y2 + z1 * z2;
|
|
762
|
+
let q2Adjusted = [w2, x2, y2, z2];
|
|
763
|
+
if (dot < 0) {
|
|
764
|
+
q2Adjusted = [-w2, -x2, -y2, -z2];
|
|
765
|
+
dot = -dot;
|
|
766
|
+
}
|
|
767
|
+
const DOT_THRESHOLD = 0.9995;
|
|
768
|
+
if (dot > DOT_THRESHOLD) {
|
|
769
|
+
const result = [
|
|
770
|
+
w1 + t * (q2Adjusted[0] - w1),
|
|
771
|
+
x1 + t * (q2Adjusted[1] - x1),
|
|
772
|
+
y1 + t * (q2Adjusted[2] - y1),
|
|
773
|
+
z1 + t * (q2Adjusted[3] - z1)
|
|
774
|
+
];
|
|
775
|
+
const length = Math.sqrt(
|
|
776
|
+
result[0] * result[0] + result[1] * result[1] + result[2] * result[2] + result[3] * result[3]
|
|
777
|
+
);
|
|
778
|
+
return [result[0] / length, result[1] / length, result[2] / length, result[3] / length];
|
|
779
|
+
}
|
|
780
|
+
const theta0 = Math.acos(Math.abs(dot));
|
|
781
|
+
const sinTheta0 = Math.sin(theta0);
|
|
782
|
+
const theta = theta0 * t;
|
|
783
|
+
const sinTheta = Math.sin(theta);
|
|
784
|
+
const s0 = Math.cos(theta) - dot * sinTheta / sinTheta0;
|
|
785
|
+
const s1 = sinTheta / sinTheta0;
|
|
786
|
+
return [
|
|
787
|
+
s0 * w1 + s1 * q2Adjusted[0],
|
|
788
|
+
s0 * x1 + s1 * q2Adjusted[1],
|
|
789
|
+
s0 * y1 + s1 * q2Adjusted[2],
|
|
790
|
+
s0 * z1 + s1 * q2Adjusted[3]
|
|
791
|
+
];
|
|
792
|
+
}
|
|
793
|
+
function eulerSlerp(euler1, euler2, t) {
|
|
794
|
+
const q1 = eulerToQuaternion(euler1);
|
|
795
|
+
const q2 = eulerToQuaternion(euler2);
|
|
796
|
+
const qResult = quaternionSlerp(q1, q2, t);
|
|
797
|
+
return quaternionToEuler(qResult);
|
|
798
|
+
}
|
|
799
|
+
function eulerRotationBetween(euler1, euler2) {
|
|
800
|
+
const q1 = eulerToQuaternion(euler1);
|
|
801
|
+
const q2 = eulerToQuaternion(euler2);
|
|
802
|
+
const q1Conjugate = quaternionConjugate(q1);
|
|
803
|
+
const qDiff = quaternionMultiply(q2, q1Conjugate);
|
|
804
|
+
return quaternionToEuler(qDiff);
|
|
805
|
+
}
|
|
615
806
|
|
|
616
807
|
// src/overlapping-segments.ts
|
|
617
808
|
function overlappingSegments(original) {
|
|
@@ -806,30 +997,227 @@ var EMAIL = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\]
|
|
|
806
997
|
|
|
807
998
|
// src/map-deep-equal.ts
|
|
808
999
|
import isDeepEqual from "fast-deep-equal";
|
|
809
|
-
function isMapDeepEqual(map1, map2) {
|
|
810
|
-
if (map1
|
|
1000
|
+
function isMapDeepEqual(map1, map2, options = {}) {
|
|
1001
|
+
if (map1 === map2) return true;
|
|
1002
|
+
const { filter } = options || {};
|
|
1003
|
+
if (!filter) {
|
|
1004
|
+
if (map1.size !== map2.size) return false;
|
|
1005
|
+
for (const [key, value] of map1.entries()) {
|
|
1006
|
+
if (!map2.has(key)) return false;
|
|
1007
|
+
const otherValue = map2.get(key);
|
|
1008
|
+
if (value !== otherValue && !isDeepEqual(value, otherValue)) {
|
|
1009
|
+
return false;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
return true;
|
|
1013
|
+
}
|
|
1014
|
+
const filteredEntries1 = [];
|
|
1015
|
+
const filteredEntries2 = [];
|
|
811
1016
|
for (const [key, value] of map1.entries()) {
|
|
812
|
-
if (
|
|
813
|
-
|
|
814
|
-
|
|
1017
|
+
if (filter(key, value)) {
|
|
1018
|
+
filteredEntries1.push([key, value]);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
for (const [key, value] of map2.entries()) {
|
|
1022
|
+
if (filter(key, value)) {
|
|
1023
|
+
filteredEntries2.push([key, value]);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
if (filteredEntries1.length !== filteredEntries2.length) {
|
|
1027
|
+
return false;
|
|
1028
|
+
}
|
|
1029
|
+
const filteredMap2 = new Map(filteredEntries2);
|
|
1030
|
+
for (const [key, value] of filteredEntries1) {
|
|
1031
|
+
if (!filteredMap2.has(key)) return false;
|
|
1032
|
+
const otherValue = filteredMap2.get(key);
|
|
1033
|
+
if (value !== otherValue && !isDeepEqual(value, otherValue)) {
|
|
815
1034
|
return false;
|
|
816
1035
|
}
|
|
817
1036
|
}
|
|
818
1037
|
return true;
|
|
819
1038
|
}
|
|
1039
|
+
|
|
1040
|
+
// src/migrate-euler.ts
|
|
1041
|
+
function storedEulerXYZtoRPY(robotData) {
|
|
1042
|
+
if ("rotation" in robotData.features) {
|
|
1043
|
+
if (!robotData.features.rotation.animated) {
|
|
1044
|
+
const rotationValue = robotData.features.rotation.value;
|
|
1045
|
+
if (!instanceOfRawEuler(rotationValue)) {
|
|
1046
|
+
const oldRot = rotationValue;
|
|
1047
|
+
const newRot = { r: oldRot.x, p: oldRot.y, y: oldRot.z };
|
|
1048
|
+
robotData.features.rotation.value = newRot;
|
|
1049
|
+
}
|
|
1050
|
+
} else {
|
|
1051
|
+
const rotationValue = robotData.features.rotation.value;
|
|
1052
|
+
if (!instanceOfRawEuler(rotationValue.default)) {
|
|
1053
|
+
const oldRot = rotationValue.default;
|
|
1054
|
+
const newRot = { r: oldRot.x, p: oldRot.y, y: oldRot.z };
|
|
1055
|
+
robotData.features.rotation.value.default = newRot;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
if ("origin" in robotData) {
|
|
1060
|
+
const rotationValue = robotData.origin.rotation;
|
|
1061
|
+
if (!instanceOfRawEuler(rotationValue)) {
|
|
1062
|
+
const oldRot = rotationValue;
|
|
1063
|
+
const newRot = { r: oldRot.x, p: oldRot.y, y: oldRot.z };
|
|
1064
|
+
robotData.origin.rotation = newRot;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return robotData;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
// src/react/context-providers.tsx
|
|
1071
|
+
import { useContext, createElement } from "react";
|
|
1072
|
+
function createContextHook(context, name) {
|
|
1073
|
+
return function useRequiredContext() {
|
|
1074
|
+
const value = useContext(context);
|
|
1075
|
+
if (!value) {
|
|
1076
|
+
throw new Error(
|
|
1077
|
+
`${name} context is required. Make sure you're using the component within a ${name}Provider.`
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
return value;
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
function withOptionalContext(CoreComponent, contextConfig) {
|
|
1084
|
+
const { context, defaultValue } = contextConfig;
|
|
1085
|
+
return function ComponentWithContext(props) {
|
|
1086
|
+
const { skipContext = false, ...coreProps } = props;
|
|
1087
|
+
const existingContext = useContext(context);
|
|
1088
|
+
if (skipContext || existingContext) {
|
|
1089
|
+
return createElement(CoreComponent, coreProps);
|
|
1090
|
+
}
|
|
1091
|
+
return createElement(
|
|
1092
|
+
context.Provider,
|
|
1093
|
+
{ value: defaultValue },
|
|
1094
|
+
createElement(CoreComponent, coreProps)
|
|
1095
|
+
);
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
function composeContexts(contexts) {
|
|
1099
|
+
return function ComposedContexts({ children }) {
|
|
1100
|
+
return contexts.reduceRight((acc, { Provider, condition }) => {
|
|
1101
|
+
if (condition && !condition()) {
|
|
1102
|
+
return acc;
|
|
1103
|
+
}
|
|
1104
|
+
return createElement(Provider, {}, acc);
|
|
1105
|
+
}, children);
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
function createContextProvider(context, defaultValue) {
|
|
1109
|
+
return function ContextProvider({
|
|
1110
|
+
children,
|
|
1111
|
+
value = defaultValue
|
|
1112
|
+
}) {
|
|
1113
|
+
return createElement(context.Provider, { value }, children);
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
function createContextSolution(config) {
|
|
1117
|
+
const { context, defaultValue, name } = config;
|
|
1118
|
+
const useRequiredContext = createContextHook(context, name);
|
|
1119
|
+
const Provider = createContextProvider(context, defaultValue);
|
|
1120
|
+
const withOptional = (Component) => withOptionalContext(Component, config);
|
|
1121
|
+
return {
|
|
1122
|
+
useContext: useRequiredContext,
|
|
1123
|
+
Provider,
|
|
1124
|
+
withOptional,
|
|
1125
|
+
context: config.context
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
function useOptionalContext(context) {
|
|
1129
|
+
return useContext(context);
|
|
1130
|
+
}
|
|
1131
|
+
function createContextChecker(context) {
|
|
1132
|
+
return function useHasContext() {
|
|
1133
|
+
return useContext(context) !== null;
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
// src/values-store.ts
|
|
1138
|
+
import { create as create2 } from "zustand";
|
|
1139
|
+
import { subscribeWithSelector as subscribeWithSelector2 } from "zustand/middleware";
|
|
1140
|
+
function mergeValueMaps(base, updates) {
|
|
1141
|
+
if (updates.size === 0) return base;
|
|
1142
|
+
let hasChange = false;
|
|
1143
|
+
updates.forEach((value, key) => {
|
|
1144
|
+
if (hasChange) return;
|
|
1145
|
+
if (value === void 0) {
|
|
1146
|
+
if (base.has(key)) hasChange = true;
|
|
1147
|
+
} else if (base.get(key) !== value) {
|
|
1148
|
+
hasChange = true;
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
if (!hasChange) return base;
|
|
1152
|
+
const merged = new Map(base);
|
|
1153
|
+
updates.forEach((value, key) => {
|
|
1154
|
+
if (value === void 0) {
|
|
1155
|
+
merged.delete(key);
|
|
1156
|
+
} else {
|
|
1157
|
+
merged.set(key, value);
|
|
1158
|
+
}
|
|
1159
|
+
});
|
|
1160
|
+
return merged;
|
|
1161
|
+
}
|
|
1162
|
+
var useValuesStore = create2()(
|
|
1163
|
+
subscribeWithSelector2((set) => ({
|
|
1164
|
+
values: /* @__PURE__ */ new Map(),
|
|
1165
|
+
velocities: /* @__PURE__ */ new Map(),
|
|
1166
|
+
updateValues: (updates) => {
|
|
1167
|
+
set((state) => ({
|
|
1168
|
+
values: mergeValueMaps(state.values, updates)
|
|
1169
|
+
}));
|
|
1170
|
+
},
|
|
1171
|
+
updateVelocities: (updates) => {
|
|
1172
|
+
set((state) => ({
|
|
1173
|
+
velocities: mergeValueMaps(state.velocities, updates)
|
|
1174
|
+
}));
|
|
1175
|
+
},
|
|
1176
|
+
setTrackValue: (trackKey, value) => {
|
|
1177
|
+
set((state) => {
|
|
1178
|
+
const next = new Map(state.values);
|
|
1179
|
+
next.set(trackKey, value);
|
|
1180
|
+
return { values: next };
|
|
1181
|
+
});
|
|
1182
|
+
},
|
|
1183
|
+
replaceAll: (values, velocities) => {
|
|
1184
|
+
set({ values, velocities });
|
|
1185
|
+
}
|
|
1186
|
+
}))
|
|
1187
|
+
);
|
|
1188
|
+
|
|
1189
|
+
// src/three-guards.ts
|
|
1190
|
+
function isOrthographicCamera(camera) {
|
|
1191
|
+
return "isOrthographicCamera" in camera;
|
|
1192
|
+
}
|
|
1193
|
+
function isPerspectiveCamera(camera) {
|
|
1194
|
+
return "isPerspectiveCamera" in camera;
|
|
1195
|
+
}
|
|
820
1196
|
export {
|
|
1197
|
+
AnimatableGroupType,
|
|
821
1198
|
EMAIL,
|
|
822
1199
|
PlayerContext,
|
|
1200
|
+
PlayerDirection,
|
|
823
1201
|
PlayerSlice,
|
|
824
1202
|
Result,
|
|
825
1203
|
alpha,
|
|
826
1204
|
altColor,
|
|
827
1205
|
angularDistance,
|
|
828
1206
|
closestFrame,
|
|
1207
|
+
colorChroma,
|
|
1208
|
+
colorLightness,
|
|
1209
|
+
composeContexts,
|
|
829
1210
|
composeProgress,
|
|
830
1211
|
composeProgressiveResult,
|
|
1212
|
+
createContextChecker,
|
|
1213
|
+
createContextHook,
|
|
1214
|
+
createContextProvider,
|
|
1215
|
+
createContextSolution,
|
|
831
1216
|
downloadBlob,
|
|
832
1217
|
downloadJSONFile,
|
|
1218
|
+
eulerRotationBetween,
|
|
1219
|
+
eulerSlerp,
|
|
1220
|
+
eulerToQuaternion,
|
|
833
1221
|
eulerToRotationMatrix,
|
|
834
1222
|
getDegenerateHexagonPath,
|
|
835
1223
|
getHexagonPath,
|
|
@@ -850,8 +1238,12 @@ export {
|
|
|
850
1238
|
instanceOfRawVector2,
|
|
851
1239
|
instanceOfRawVector3,
|
|
852
1240
|
isMapDeepEqual,
|
|
1241
|
+
isNearNeutralMid,
|
|
1242
|
+
isOrthographicCamera,
|
|
1243
|
+
isPerspectiveCamera,
|
|
853
1244
|
isRawObject,
|
|
854
1245
|
log,
|
|
1246
|
+
mergeValueMaps,
|
|
855
1247
|
newPlayer,
|
|
856
1248
|
now,
|
|
857
1249
|
numberToDurationString,
|
|
@@ -862,22 +1254,39 @@ export {
|
|
|
862
1254
|
pause,
|
|
863
1255
|
play,
|
|
864
1256
|
pointsToPath,
|
|
1257
|
+
quaternionConjugate,
|
|
1258
|
+
quaternionMultiply,
|
|
1259
|
+
quaternionSlerp,
|
|
1260
|
+
quaternionToEuler,
|
|
1261
|
+
randomHexString,
|
|
865
1262
|
rawHSLToHex,
|
|
866
1263
|
rawRGBToHex,
|
|
867
1264
|
reset,
|
|
1265
|
+
reversed,
|
|
1266
|
+
rgbChroma,
|
|
1267
|
+
rgbLightness,
|
|
868
1268
|
rgbToRgba,
|
|
869
1269
|
rotationMatrixToAngle,
|
|
870
1270
|
seek,
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
setViewport,
|
|
1271
|
+
shouldUseBlendForLabelColor,
|
|
1272
|
+
storedEulerXYZtoRPY,
|
|
874
1273
|
stringifyMapped,
|
|
875
1274
|
toDegrees,
|
|
876
1275
|
toRadians,
|
|
877
|
-
|
|
1276
|
+
updated,
|
|
878
1277
|
useDeep,
|
|
879
1278
|
useDeepSelector,
|
|
880
1279
|
useLazy,
|
|
881
1280
|
useMediaQuery,
|
|
882
|
-
|
|
1281
|
+
useOptionalContext,
|
|
1282
|
+
usePlayerStore,
|
|
1283
|
+
useValuesStore,
|
|
1284
|
+
warnUnexpectedFeatureValue,
|
|
1285
|
+
withBounce,
|
|
1286
|
+
withBounds,
|
|
1287
|
+
withDirection,
|
|
1288
|
+
withDuration,
|
|
1289
|
+
withLooping,
|
|
1290
|
+
withOptionalContext,
|
|
1291
|
+
withSpeed
|
|
883
1292
|
};
|