@rogieking/figui3 9.0.1 → 9.0.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.
- package/README.md +34 -3
- package/components.css +2 -1
- package/dist/components.css +1 -1
- package/dist/fig.css +1 -1
- package/dist/fig.js +5 -5
- package/fig.js +259 -53
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -14054,15 +14054,18 @@ figDefineElement("fig-input-file", FigInputFile);
|
|
|
14054
14054
|
|
|
14055
14055
|
/**
|
|
14056
14056
|
* A bezier / spring easing curve editor with draggable control points.
|
|
14057
|
-
* @attr {string} value - Bezier
|
|
14057
|
+
* @attr {string} value - Bezier/spring shorthand or a serialized easing object
|
|
14058
14058
|
* @attr {string} mode - Optional editor constraint: "bezier" or "spring".
|
|
14059
14059
|
* @attr {number} precision - Decimal places for output values (default 2)
|
|
14060
14060
|
* @attr {boolean} edit - Show the editor and custom preset options (default true; set "false" for presets only)
|
|
14061
|
+
* @attr {boolean} presets - Show the preset selector (default true)
|
|
14062
|
+
* @attr {boolean} text - Show the manual value input (default true)
|
|
14063
|
+
* @property {object|null} spring - Structured spring configuration when in spring mode
|
|
14061
14064
|
*/
|
|
14062
14065
|
class FigEasingCurve extends HTMLElement {
|
|
14063
14066
|
#cp1 = { x: 0.42, y: 0 };
|
|
14064
14067
|
#cp2 = { x: 0.58, y: 1 };
|
|
14065
|
-
#spring = { stiffness: 200, damping: 15, mass: 1 };
|
|
14068
|
+
#spring = { stiffness: 200, damping: 15, mass: 1, initialVelocity: 0 };
|
|
14066
14069
|
#mode = "bezier";
|
|
14067
14070
|
#precision = 2;
|
|
14068
14071
|
#isDragging = null;
|
|
@@ -14155,7 +14158,15 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14155
14158
|
];
|
|
14156
14159
|
|
|
14157
14160
|
static get observedAttributes() {
|
|
14158
|
-
return [
|
|
14161
|
+
return [
|
|
14162
|
+
"value",
|
|
14163
|
+
"mode",
|
|
14164
|
+
"precision",
|
|
14165
|
+
"aspect-ratio",
|
|
14166
|
+
"edit",
|
|
14167
|
+
"presets",
|
|
14168
|
+
"text",
|
|
14169
|
+
];
|
|
14159
14170
|
}
|
|
14160
14171
|
|
|
14161
14172
|
connectedCallback() {
|
|
@@ -14191,12 +14202,15 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14191
14202
|
return;
|
|
14192
14203
|
}
|
|
14193
14204
|
|
|
14194
|
-
if (name === "edit") {
|
|
14205
|
+
if (name === "edit" || name === "presets" || name === "text") {
|
|
14195
14206
|
if (this.isConnected) this.#render();
|
|
14196
14207
|
return;
|
|
14197
14208
|
}
|
|
14198
14209
|
|
|
14199
14210
|
if (name === "mode") {
|
|
14211
|
+
this.#applyModeConstraint();
|
|
14212
|
+
const value = this.getAttribute("value");
|
|
14213
|
+
if (value) this.#parseValue(value);
|
|
14200
14214
|
this.#applyModeConstraint();
|
|
14201
14215
|
this.#presetName = this.#matchPreset();
|
|
14202
14216
|
if (this.isConnected) this.#render();
|
|
@@ -14222,8 +14236,9 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14222
14236
|
|
|
14223
14237
|
get value() {
|
|
14224
14238
|
if (this.#mode === "spring") {
|
|
14225
|
-
const { stiffness, damping, mass } = this.#spring;
|
|
14226
|
-
|
|
14239
|
+
const { stiffness, damping, mass, initialVelocity = 0 } = this.#spring;
|
|
14240
|
+
const velocity = initialVelocity ? `, ${initialVelocity}` : "";
|
|
14241
|
+
return `spring(${stiffness}, ${damping}, ${mass}${velocity})`;
|
|
14227
14242
|
}
|
|
14228
14243
|
const p = this.#precision;
|
|
14229
14244
|
return `${this.#cp1.x.toFixed(p)}, ${this.#cp1.y.toFixed(p)}, ${this.#cp2.x.toFixed(p)}, ${this.#cp2.y.toFixed(p)}`;
|
|
@@ -14251,9 +14266,39 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14251
14266
|
}
|
|
14252
14267
|
|
|
14253
14268
|
set value(v) {
|
|
14269
|
+
if (v && typeof v === "object") {
|
|
14270
|
+
const normalized = this.#normalizeStructuredValue(v);
|
|
14271
|
+
if (!normalized) {
|
|
14272
|
+
throw new TypeError("Invalid easing value or mode/type mismatch");
|
|
14273
|
+
}
|
|
14274
|
+
const serialized =
|
|
14275
|
+
normalized.type === "spring"
|
|
14276
|
+
? { type: "spring", ...normalized.spring }
|
|
14277
|
+
: {
|
|
14278
|
+
type: "bezier",
|
|
14279
|
+
x1: normalized.bezier[0],
|
|
14280
|
+
y1: normalized.bezier[1],
|
|
14281
|
+
x2: normalized.bezier[2],
|
|
14282
|
+
y2: normalized.bezier[3],
|
|
14283
|
+
};
|
|
14284
|
+
this.setAttribute("value", JSON.stringify(serialized));
|
|
14285
|
+
return;
|
|
14286
|
+
}
|
|
14254
14287
|
this.setAttribute("value", v);
|
|
14255
14288
|
}
|
|
14256
14289
|
|
|
14290
|
+
get spring() {
|
|
14291
|
+
if (this.#mode !== "spring") return null;
|
|
14292
|
+
return { ...this.#spring, initialVelocity: this.#spring.initialVelocity ?? 0 };
|
|
14293
|
+
}
|
|
14294
|
+
|
|
14295
|
+
set spring(value) {
|
|
14296
|
+
if (!value || typeof value !== "object") {
|
|
14297
|
+
throw new TypeError("spring must be an object");
|
|
14298
|
+
}
|
|
14299
|
+
this.value = { ...value, type: "spring" };
|
|
14300
|
+
}
|
|
14301
|
+
|
|
14257
14302
|
#constrainedMode() {
|
|
14258
14303
|
const mode = this.getAttribute("mode")?.trim().toLowerCase();
|
|
14259
14304
|
return mode === "bezier" || mode === "spring" ? mode : null;
|
|
@@ -14269,15 +14314,114 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14269
14314
|
return !mode || preset.type === mode;
|
|
14270
14315
|
}
|
|
14271
14316
|
|
|
14272
|
-
#
|
|
14273
|
-
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14317
|
+
#normalizeStructuredValue(value) {
|
|
14318
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
14319
|
+
const constrainedMode = this.#constrainedMode();
|
|
14320
|
+
const declaredType =
|
|
14321
|
+
typeof value.type === "string" ? value.type.trim().toLowerCase() : null;
|
|
14322
|
+
if (declaredType && declaredType !== "bezier" && declaredType !== "spring") {
|
|
14323
|
+
return null;
|
|
14324
|
+
}
|
|
14325
|
+
if (declaredType && constrainedMode && declaredType !== constrainedMode) {
|
|
14326
|
+
return null;
|
|
14327
|
+
}
|
|
14328
|
+
const type = declaredType || constrainedMode;
|
|
14329
|
+
if (!type) return null;
|
|
14330
|
+
|
|
14331
|
+
if (type === "spring") {
|
|
14332
|
+
const spring = {
|
|
14333
|
+
mass: Number(value.mass),
|
|
14334
|
+
stiffness: Number(value.stiffness),
|
|
14335
|
+
damping: Number(value.damping),
|
|
14336
|
+
initialVelocity:
|
|
14337
|
+
value.initialVelocity === undefined
|
|
14338
|
+
? 0
|
|
14339
|
+
: Number(value.initialVelocity),
|
|
14340
|
+
};
|
|
14341
|
+
if (
|
|
14342
|
+
!Number.isFinite(spring.mass) ||
|
|
14343
|
+
spring.mass <= 0 ||
|
|
14344
|
+
!Number.isFinite(spring.stiffness) ||
|
|
14345
|
+
spring.stiffness <= 0 ||
|
|
14346
|
+
!Number.isFinite(spring.damping) ||
|
|
14347
|
+
spring.damping < 0 ||
|
|
14348
|
+
!Number.isFinite(spring.initialVelocity)
|
|
14349
|
+
) {
|
|
14350
|
+
return null;
|
|
14351
|
+
}
|
|
14352
|
+
return { type, spring };
|
|
14353
|
+
}
|
|
14354
|
+
|
|
14355
|
+
const bezier = [value.x1, value.y1, value.x2, value.y2].map(Number);
|
|
14356
|
+
if (
|
|
14357
|
+
bezier.some((part) => !Number.isFinite(part)) ||
|
|
14358
|
+
bezier[0] < 0 ||
|
|
14359
|
+
bezier[0] > 1 ||
|
|
14360
|
+
bezier[2] < 0 ||
|
|
14361
|
+
bezier[2] > 1
|
|
14362
|
+
) {
|
|
14363
|
+
return null;
|
|
14364
|
+
}
|
|
14365
|
+
return { type, bezier };
|
|
14366
|
+
}
|
|
14367
|
+
|
|
14368
|
+
#applyStructuredValue(value) {
|
|
14369
|
+
if (value.type === "spring") {
|
|
14370
|
+
this.#mode = "spring";
|
|
14371
|
+
this.#spring = { ...value.spring };
|
|
14372
|
+
} else {
|
|
14373
|
+
this.#mode = "bezier";
|
|
14374
|
+
[this.#cp1.x, this.#cp1.y, this.#cp2.x, this.#cp2.y] = value.bezier;
|
|
14375
|
+
}
|
|
14376
|
+
}
|
|
14377
|
+
|
|
14378
|
+
#parseSpringString(str) {
|
|
14379
|
+
const match = str.match(/^spring\(\s*(.*?)\s*\)$/i);
|
|
14380
|
+
if (!match) return null;
|
|
14381
|
+
const parts = match[1].split(",").map((part) => Number(part.trim()));
|
|
14382
|
+
if (
|
|
14383
|
+
(parts.length !== 3 && parts.length !== 4) ||
|
|
14384
|
+
parts.some((part) => !Number.isFinite(part))
|
|
14385
|
+
) {
|
|
14386
|
+
return null;
|
|
14387
|
+
}
|
|
14388
|
+
const spring = {
|
|
14389
|
+
stiffness: parts[0],
|
|
14390
|
+
damping: parts[1],
|
|
14391
|
+
mass: parts[2],
|
|
14392
|
+
initialVelocity: parts[3] ?? 0,
|
|
14393
|
+
};
|
|
14394
|
+
if (
|
|
14395
|
+
spring.stiffness <= 0 ||
|
|
14396
|
+
spring.damping < 0 ||
|
|
14397
|
+
spring.mass <= 0
|
|
14398
|
+
) {
|
|
14399
|
+
return null;
|
|
14400
|
+
}
|
|
14401
|
+
return spring;
|
|
14402
|
+
}
|
|
14403
|
+
|
|
14404
|
+
#parseValue(input) {
|
|
14405
|
+
if (input && typeof input === "object") {
|
|
14406
|
+
const normalized = this.#normalizeStructuredValue(input);
|
|
14407
|
+
if (!normalized) return false;
|
|
14408
|
+
this.#applyStructuredValue(normalized);
|
|
14409
|
+
return true;
|
|
14410
|
+
}
|
|
14411
|
+
if (typeof input !== "string") return false;
|
|
14412
|
+
const str = input.trim();
|
|
14413
|
+
if (str.startsWith("{")) {
|
|
14414
|
+
try {
|
|
14415
|
+
return this.#parseValue(JSON.parse(str));
|
|
14416
|
+
} catch {
|
|
14417
|
+
return false;
|
|
14418
|
+
}
|
|
14419
|
+
}
|
|
14420
|
+
|
|
14421
|
+
const spring = this.#parseSpringString(str);
|
|
14422
|
+
if (spring && this.#constrainedMode() !== "bezier") {
|
|
14277
14423
|
this.#mode = "spring";
|
|
14278
|
-
this.#spring
|
|
14279
|
-
this.#spring.damping = parseFloat(springMatch[2]);
|
|
14280
|
-
this.#spring.mass = parseFloat(springMatch[3]);
|
|
14424
|
+
this.#spring = spring;
|
|
14281
14425
|
return true;
|
|
14282
14426
|
}
|
|
14283
14427
|
const parts = str.split(",").map((s) => parseFloat(s.trim()));
|
|
@@ -14316,7 +14460,8 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14316
14460
|
if (
|
|
14317
14461
|
Math.abs(this.#spring.stiffness - p.spring.stiffness) < ep &&
|
|
14318
14462
|
Math.abs(this.#spring.damping - p.spring.damping) < ep &&
|
|
14319
|
-
Math.abs(this.#spring.mass - p.spring.mass) < ep
|
|
14463
|
+
Math.abs(this.#spring.mass - p.spring.mass) < ep &&
|
|
14464
|
+
Math.abs(this.#spring.initialVelocity ?? 0) < ep
|
|
14320
14465
|
)
|
|
14321
14466
|
return p.name;
|
|
14322
14467
|
}
|
|
@@ -14326,12 +14471,12 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14326
14471
|
// --- Spring simulation ---
|
|
14327
14472
|
|
|
14328
14473
|
#simulateSpring() {
|
|
14329
|
-
const { stiffness, damping, mass } = this.#spring;
|
|
14474
|
+
const { stiffness, damping, mass, initialVelocity = 0 } = this.#spring;
|
|
14330
14475
|
const dt = 0.004;
|
|
14331
14476
|
const maxTime = 5;
|
|
14332
14477
|
const points = [];
|
|
14333
14478
|
let pos = 0,
|
|
14334
|
-
vel =
|
|
14479
|
+
vel = initialVelocity;
|
|
14335
14480
|
for (let t = 0; t <= maxTime; t += dt) {
|
|
14336
14481
|
const force = -stiffness * (pos - 1) - damping * vel;
|
|
14337
14482
|
vel += (force / mass) * dt;
|
|
@@ -14344,12 +14489,12 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14344
14489
|
}
|
|
14345
14490
|
|
|
14346
14491
|
static #springIcon(spring, size = 24) {
|
|
14347
|
-
const { stiffness, damping, mass } = spring;
|
|
14492
|
+
const { stiffness, damping, mass, initialVelocity = 0 } = spring;
|
|
14348
14493
|
const dt = 0.004;
|
|
14349
14494
|
const maxTime = 5;
|
|
14350
14495
|
const pts = [];
|
|
14351
14496
|
let pos = 0,
|
|
14352
|
-
vel =
|
|
14497
|
+
vel = initialVelocity;
|
|
14353
14498
|
for (let t = 0; t <= maxTime; t += dt) {
|
|
14354
14499
|
const force = -stiffness * (pos - 1) - damping * vel;
|
|
14355
14500
|
vel += (force / mass) * dt;
|
|
@@ -14467,6 +14612,14 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14467
14612
|
return this.getAttribute("edit") !== "false";
|
|
14468
14613
|
}
|
|
14469
14614
|
|
|
14615
|
+
#isPresetsEnabled() {
|
|
14616
|
+
return this.getAttribute("presets") !== "false";
|
|
14617
|
+
}
|
|
14618
|
+
|
|
14619
|
+
#isTextEnabled() {
|
|
14620
|
+
return this.getAttribute("text") !== "false";
|
|
14621
|
+
}
|
|
14622
|
+
|
|
14470
14623
|
#render() {
|
|
14471
14624
|
this.classList.toggle("spring-mode", this.#mode === "spring");
|
|
14472
14625
|
this.classList.toggle("bezier-mode", this.#mode !== "spring");
|
|
@@ -14594,13 +14747,26 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14594
14747
|
|
|
14595
14748
|
#createContent() {
|
|
14596
14749
|
const size = 200;
|
|
14597
|
-
const select = this.#createSelect();
|
|
14598
|
-
if (!this.#isEditEnabled()) return [select];
|
|
14599
|
-
const valueInput =
|
|
14600
|
-
|
|
14601
|
-
|
|
14602
|
-
|
|
14603
|
-
|
|
14750
|
+
const select = this.#isPresetsEnabled() ? this.#createSelect() : null;
|
|
14751
|
+
if (!this.#isEditEnabled()) return select ? [select] : [];
|
|
14752
|
+
const valueInput = this.#isTextEnabled()
|
|
14753
|
+
? this.#mode === "spring"
|
|
14754
|
+
? figCreateElement("fig-input-number", {
|
|
14755
|
+
className: "fig-easing-curve-value-input",
|
|
14756
|
+
value: this.#springBounce().toFixed(2),
|
|
14757
|
+
min: "0",
|
|
14758
|
+
max: "1",
|
|
14759
|
+
step: "0.01",
|
|
14760
|
+
precision: "2",
|
|
14761
|
+
"aria-label": "Spring bounce",
|
|
14762
|
+
full: true,
|
|
14763
|
+
})
|
|
14764
|
+
: figCreateElement("fig-input-text", {
|
|
14765
|
+
className: "fig-easing-curve-value-input",
|
|
14766
|
+
value: this.value,
|
|
14767
|
+
full: true,
|
|
14768
|
+
})
|
|
14769
|
+
: null;
|
|
14604
14770
|
const svgChildren = [
|
|
14605
14771
|
figCreateSvgElement("rect", {
|
|
14606
14772
|
className: "fig-easing-curve-bounds",
|
|
@@ -14686,13 +14852,13 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14686
14852
|
svgChildren,
|
|
14687
14853
|
);
|
|
14688
14854
|
return [
|
|
14689
|
-
select,
|
|
14855
|
+
...(select ? [select] : []),
|
|
14690
14856
|
figCreateElement(
|
|
14691
14857
|
"div",
|
|
14692
14858
|
{ className: "fig-easing-curve-svg-container" },
|
|
14693
14859
|
svg,
|
|
14694
14860
|
),
|
|
14695
|
-
valueInput,
|
|
14861
|
+
...(valueInput ? [valueInput] : []),
|
|
14696
14862
|
];
|
|
14697
14863
|
}
|
|
14698
14864
|
|
|
@@ -14981,7 +15147,43 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14981
15147
|
|
|
14982
15148
|
#syncValueInput() {
|
|
14983
15149
|
if (!this.#valueInput) return;
|
|
14984
|
-
|
|
15150
|
+
const value =
|
|
15151
|
+
this.#mode === "spring"
|
|
15152
|
+
? this.#springBounce().toFixed(2)
|
|
15153
|
+
: this.value;
|
|
15154
|
+
this.#valueInput.setAttribute("value", value);
|
|
15155
|
+
}
|
|
15156
|
+
|
|
15157
|
+
#springBounce() {
|
|
15158
|
+
const { stiffness, damping, mass } = this.#spring;
|
|
15159
|
+
const criticalDamping = 2 * Math.sqrt(stiffness * mass);
|
|
15160
|
+
if (!Number.isFinite(criticalDamping) || criticalDamping <= 0) return 0;
|
|
15161
|
+
return Math.max(0, Math.min(1, 1 - damping / criticalDamping));
|
|
15162
|
+
}
|
|
15163
|
+
|
|
15164
|
+
#setSpringBounce(value) {
|
|
15165
|
+
const bounce = Math.max(0, Math.min(1, Number(value)));
|
|
15166
|
+
const criticalDamping = 2 * Math.sqrt(
|
|
15167
|
+
this.#spring.stiffness * this.#spring.mass,
|
|
15168
|
+
);
|
|
15169
|
+
this.#spring.damping = Number(
|
|
15170
|
+
(criticalDamping * (1 - bounce)).toFixed(4),
|
|
15171
|
+
);
|
|
15172
|
+
}
|
|
15173
|
+
|
|
15174
|
+
#applySpringBounce(value, eventType) {
|
|
15175
|
+
const bounce = Number(value);
|
|
15176
|
+
if (!Number.isFinite(bounce)) {
|
|
15177
|
+
if (eventType === "change") this.#syncValueInput();
|
|
15178
|
+
return;
|
|
15179
|
+
}
|
|
15180
|
+
|
|
15181
|
+
this.#setSpringBounce(bounce);
|
|
15182
|
+
this.#presetName = this.#matchPreset();
|
|
15183
|
+
this.#updatePaths();
|
|
15184
|
+
this.#syncSelect();
|
|
15185
|
+
if (eventType === "change") this.#syncValueInput();
|
|
15186
|
+
this.#emit(eventType);
|
|
14985
15187
|
}
|
|
14986
15188
|
|
|
14987
15189
|
#parseManualBezierValue(value) {
|
|
@@ -14996,16 +15198,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
14996
15198
|
}
|
|
14997
15199
|
|
|
14998
15200
|
#parseManualSpringValue(value) {
|
|
14999
|
-
|
|
15000
|
-
/^spring\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)$/,
|
|
15001
|
-
);
|
|
15002
|
-
if (!match) return null;
|
|
15003
|
-
const spring = {
|
|
15004
|
-
stiffness: Number(match[1]),
|
|
15005
|
-
damping: Number(match[2]),
|
|
15006
|
-
mass: Number(match[3]),
|
|
15007
|
-
};
|
|
15008
|
-
return Object.values(spring).every((part) => part > 0) ? spring : null;
|
|
15201
|
+
return this.#parseSpringString(value);
|
|
15009
15202
|
}
|
|
15010
15203
|
|
|
15011
15204
|
#applyManualValue(value, eventType) {
|
|
@@ -15115,18 +15308,19 @@ class FigEasingCurve extends HTMLElement {
|
|
|
15115
15308
|
const unit = event.shiftKey ? 10 : 1;
|
|
15116
15309
|
|
|
15117
15310
|
if (handleType === "bounce") {
|
|
15311
|
+
const step = unit / 100;
|
|
15118
15312
|
switch (event.key) {
|
|
15119
15313
|
case "ArrowUp":
|
|
15120
|
-
this.#
|
|
15314
|
+
this.#setSpringBounce(this.#springBounce() + step);
|
|
15121
15315
|
break;
|
|
15122
15316
|
case "ArrowDown":
|
|
15123
|
-
this.#
|
|
15317
|
+
this.#setSpringBounce(this.#springBounce() - step);
|
|
15124
15318
|
break;
|
|
15125
15319
|
case "Home":
|
|
15126
|
-
this.#
|
|
15320
|
+
this.#setSpringBounce(0);
|
|
15127
15321
|
break;
|
|
15128
15322
|
case "End":
|
|
15129
|
-
this.#
|
|
15323
|
+
this.#setSpringBounce(1);
|
|
15130
15324
|
break;
|
|
15131
15325
|
default:
|
|
15132
15326
|
return false;
|
|
@@ -15201,6 +15395,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
15201
15395
|
// --- Events ---
|
|
15202
15396
|
|
|
15203
15397
|
#emit(type) {
|
|
15398
|
+
const spring = this.spring;
|
|
15204
15399
|
this.dispatchEvent(
|
|
15205
15400
|
new CustomEvent(type, {
|
|
15206
15401
|
bubbles: true,
|
|
@@ -15209,6 +15404,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
15209
15404
|
value: this.value,
|
|
15210
15405
|
cssValue: this.cssValue,
|
|
15211
15406
|
preset: this.#presetName,
|
|
15407
|
+
...(spring ? { spring } : {}),
|
|
15212
15408
|
},
|
|
15213
15409
|
}),
|
|
15214
15410
|
);
|
|
@@ -15260,7 +15456,14 @@ class FigEasingCurve extends HTMLElement {
|
|
|
15260
15456
|
}
|
|
15261
15457
|
|
|
15262
15458
|
if (this.#select) {
|
|
15459
|
+
this.#select.addEventListener("input", (e) => {
|
|
15460
|
+
e.stopPropagation();
|
|
15461
|
+
});
|
|
15462
|
+
this.#select.addEventListener("optionhover", (e) => {
|
|
15463
|
+
e.stopPropagation();
|
|
15464
|
+
});
|
|
15263
15465
|
this.#select.addEventListener("change", (e) => {
|
|
15466
|
+
e.stopPropagation();
|
|
15264
15467
|
const name = e.detail;
|
|
15265
15468
|
const preset = FigEasingCurve.PRESETS.find((p) => p.name === name);
|
|
15266
15469
|
if (!preset) return;
|
|
@@ -15282,7 +15485,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
15282
15485
|
}
|
|
15283
15486
|
} else if (preset.type === "spring") {
|
|
15284
15487
|
if (preset.spring) {
|
|
15285
|
-
this.#spring = { ...preset.spring };
|
|
15488
|
+
this.#spring = { ...preset.spring, initialVelocity: 0 };
|
|
15286
15489
|
}
|
|
15287
15490
|
this.#presetName = name;
|
|
15288
15491
|
if (this.#mode !== "spring") {
|
|
@@ -15302,14 +15505,20 @@ class FigEasingCurve extends HTMLElement {
|
|
|
15302
15505
|
this.#valueInput.addEventListener("input", (e) => {
|
|
15303
15506
|
e.stopPropagation();
|
|
15304
15507
|
const value = e.detail ?? e.target?.value;
|
|
15305
|
-
if (
|
|
15306
|
-
|
|
15508
|
+
if (this.#mode === "spring") {
|
|
15509
|
+
this.#applySpringBounce(value, "input");
|
|
15510
|
+
} else if (typeof value === "string") {
|
|
15511
|
+
this.#applyManualValue(value, "input");
|
|
15512
|
+
}
|
|
15307
15513
|
});
|
|
15308
15514
|
this.#valueInput.addEventListener("change", (e) => {
|
|
15309
15515
|
e.stopPropagation();
|
|
15310
15516
|
const value = e.detail ?? e.target?.value;
|
|
15311
|
-
if (
|
|
15312
|
-
|
|
15517
|
+
if (this.#mode === "spring") {
|
|
15518
|
+
this.#applySpringBounce(value, "change");
|
|
15519
|
+
} else if (typeof value === "string") {
|
|
15520
|
+
this.#applyManualValue(value, "change");
|
|
15521
|
+
}
|
|
15313
15522
|
});
|
|
15314
15523
|
}
|
|
15315
15524
|
}
|
|
@@ -15397,7 +15606,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
15397
15606
|
this.#isDragging = handleType;
|
|
15398
15607
|
this.classList.toggle("spring-bounce-dragging", handleType === "bounce");
|
|
15399
15608
|
|
|
15400
|
-
const
|
|
15609
|
+
const startBounce = this.#springBounce();
|
|
15401
15610
|
const startStiffness = this.#spring.stiffness;
|
|
15402
15611
|
const startDuration = this.#springDuration;
|
|
15403
15612
|
const startY = e.clientY;
|
|
@@ -15408,10 +15617,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
15408
15617
|
|
|
15409
15618
|
if (handleType === "bounce") {
|
|
15410
15619
|
const dy = e.clientY - startY;
|
|
15411
|
-
this.#
|
|
15412
|
-
1,
|
|
15413
|
-
Math.round(startDamping + dy * 0.15),
|
|
15414
|
-
);
|
|
15620
|
+
this.#setSpringBounce(startBounce - dy / 200);
|
|
15415
15621
|
} else {
|
|
15416
15622
|
const dx = e.clientX - startX;
|
|
15417
15623
|
this.#springDuration = Math.max(
|
package/package.json
CHANGED