@rogieking/figui3 3.6.0 → 3.8.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/README.md +4 -3
- package/base.css +4 -2
- package/components.css +100 -53
- package/dist/editor.js +10718 -0
- package/fig.js +107 -25
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -4019,6 +4019,7 @@ class FigFieldSlider extends HTMLElement {
|
|
|
4019
4019
|
#slider = null;
|
|
4020
4020
|
#observer = null;
|
|
4021
4021
|
#managedSliderAttrs = new Set();
|
|
4022
|
+
#steppersSyncFrame = 0;
|
|
4022
4023
|
#boundHandleSliderInput = null;
|
|
4023
4024
|
#boundHandleSliderChange = null;
|
|
4024
4025
|
#ignoredSliderAttrs = new Set(["variant", "color", "text", "full"]);
|
|
@@ -4070,6 +4071,10 @@ class FigFieldSlider extends HTMLElement {
|
|
|
4070
4071
|
|
|
4071
4072
|
disconnectedCallback() {
|
|
4072
4073
|
this.#observer?.disconnect();
|
|
4074
|
+
if (this.#steppersSyncFrame) {
|
|
4075
|
+
cancelAnimationFrame(this.#steppersSyncFrame);
|
|
4076
|
+
this.#steppersSyncFrame = 0;
|
|
4077
|
+
}
|
|
4073
4078
|
this.#unbindSliderEvents();
|
|
4074
4079
|
}
|
|
4075
4080
|
|
|
@@ -4180,15 +4185,49 @@ class FigFieldSlider extends HTMLElement {
|
|
|
4180
4185
|
}
|
|
4181
4186
|
|
|
4182
4187
|
this.#managedSliderAttrs = nextManaged;
|
|
4188
|
+
this.#queueSteppersSync();
|
|
4183
4189
|
}
|
|
4184
4190
|
|
|
4185
4191
|
#getForwardedSliderAttrNames() {
|
|
4186
|
-
const reserved = new Set([
|
|
4192
|
+
const reserved = new Set([
|
|
4193
|
+
"label",
|
|
4194
|
+
"direction",
|
|
4195
|
+
"oninput",
|
|
4196
|
+
"onchange",
|
|
4197
|
+
"steppers",
|
|
4198
|
+
]);
|
|
4187
4199
|
return this.getAttributeNames().filter(
|
|
4188
4200
|
(name) => !reserved.has(name) && !this.#ignoredSliderAttrs.has(name),
|
|
4189
4201
|
);
|
|
4190
4202
|
}
|
|
4191
4203
|
|
|
4204
|
+
#queueSteppersSync() {
|
|
4205
|
+
if (this.#steppersSyncFrame) {
|
|
4206
|
+
cancelAnimationFrame(this.#steppersSyncFrame);
|
|
4207
|
+
}
|
|
4208
|
+
this.#steppersSyncFrame = requestAnimationFrame(() => {
|
|
4209
|
+
this.#steppersSyncFrame = 0;
|
|
4210
|
+
this.#syncSteppersToNumberInput();
|
|
4211
|
+
});
|
|
4212
|
+
}
|
|
4213
|
+
|
|
4214
|
+
#syncSteppersToNumberInput() {
|
|
4215
|
+
if (!this.#slider) return;
|
|
4216
|
+
const numberInput = this.#slider.querySelector("fig-input-number");
|
|
4217
|
+
if (!numberInput) return;
|
|
4218
|
+
|
|
4219
|
+
const hasSteppers =
|
|
4220
|
+
this.hasAttribute("steppers") &&
|
|
4221
|
+
this.getAttribute("steppers") !== "false";
|
|
4222
|
+
if (!hasSteppers) {
|
|
4223
|
+
numberInput.removeAttribute("steppers");
|
|
4224
|
+
return;
|
|
4225
|
+
}
|
|
4226
|
+
|
|
4227
|
+
const steppersValue = this.getAttribute("steppers");
|
|
4228
|
+
numberInput.setAttribute("steppers", steppersValue ?? "");
|
|
4229
|
+
}
|
|
4230
|
+
|
|
4192
4231
|
#bindSliderEvents() {
|
|
4193
4232
|
if (!this.#slider) return;
|
|
4194
4233
|
if (!this.#boundHandleSliderInput) {
|
|
@@ -6655,6 +6694,8 @@ class FigEasingCurve extends HTMLElement {
|
|
|
6655
6694
|
const size = 200;
|
|
6656
6695
|
const dropdown = this.#getDropdownHTML();
|
|
6657
6696
|
|
|
6697
|
+
const hs = this.#bezierHandleRadius * 2;
|
|
6698
|
+
|
|
6658
6699
|
if (this.#mode === "spring") {
|
|
6659
6700
|
const targetY = 40;
|
|
6660
6701
|
const startY = 180;
|
|
@@ -6663,8 +6704,8 @@ class FigEasingCurve extends HTMLElement {
|
|
|
6663
6704
|
<line class="fig-easing-curve-target" x1="0" y1="${targetY}" x2="${size}" y2="${targetY}"/>
|
|
6664
6705
|
<line class="fig-easing-curve-diagonal" x1="0" y1="${startY}" x2="0" y2="${startY}"/>
|
|
6665
6706
|
<path class="fig-easing-curve-path"/>
|
|
6666
|
-
<
|
|
6667
|
-
<
|
|
6707
|
+
<foreignObject class="fig-easing-curve-handle" data-handle="bounce" width="${hs}" height="${hs}"><fig-handle></fig-handle></foreignObject>
|
|
6708
|
+
<foreignObject class="fig-easing-curve-handle fig-easing-curve-duration-bar" data-handle="duration" width="${this.#durationBarWidth}" height="${this.#durationBarHeight}"><fig-handle></fig-handle></foreignObject>
|
|
6668
6709
|
</svg></div>`;
|
|
6669
6710
|
}
|
|
6670
6711
|
|
|
@@ -6676,8 +6717,8 @@ class FigEasingCurve extends HTMLElement {
|
|
|
6676
6717
|
<path class="fig-easing-curve-path"/>
|
|
6677
6718
|
<circle class="fig-easing-curve-endpoint" data-endpoint="start" r="${this.#bezierEndpointRadius}"/>
|
|
6678
6719
|
<circle class="fig-easing-curve-endpoint" data-endpoint="end" r="${this.#bezierEndpointRadius}"/>
|
|
6679
|
-
<
|
|
6680
|
-
<
|
|
6720
|
+
<foreignObject class="fig-easing-curve-handle" data-handle="1" width="${hs}" height="${hs}"><fig-handle></fig-handle></foreignObject>
|
|
6721
|
+
<foreignObject class="fig-easing-curve-handle" data-handle="2" width="${hs}" height="${hs}"><fig-handle></fig-handle></foreignObject>
|
|
6681
6722
|
</svg></div>`;
|
|
6682
6723
|
}
|
|
6683
6724
|
|
|
@@ -6821,10 +6862,11 @@ class FigEasingCurve extends HTMLElement {
|
|
|
6821
6862
|
this.#line2.setAttribute("y1", p3.y);
|
|
6822
6863
|
this.#line2.setAttribute("x2", p2.x);
|
|
6823
6864
|
this.#line2.setAttribute("y2", p2.y);
|
|
6824
|
-
this.#
|
|
6825
|
-
this.#handle1.setAttribute("
|
|
6826
|
-
this.#
|
|
6827
|
-
this.#handle2.setAttribute("
|
|
6865
|
+
const hr = this.#bezierHandleRadius;
|
|
6866
|
+
this.#handle1.setAttribute("x", p1.x - hr);
|
|
6867
|
+
this.#handle1.setAttribute("y", p1.y - hr);
|
|
6868
|
+
this.#handle2.setAttribute("x", p2.x - hr);
|
|
6869
|
+
this.#handle2.setAttribute("y", p2.y - hr);
|
|
6828
6870
|
if (this.#bezierEndpointStart) {
|
|
6829
6871
|
this.#bezierEndpointStart.setAttribute("cx", p0.x);
|
|
6830
6872
|
this.#bezierEndpointStart.setAttribute("cy", p0.y);
|
|
@@ -6891,8 +6933,9 @@ class FigEasingCurve extends HTMLElement {
|
|
|
6891
6933
|
const peak = this.#findPeakOvershoot(points);
|
|
6892
6934
|
const peakNorm = (peak.t / totalTime) * durationNorm;
|
|
6893
6935
|
const peakPt = this.#springToSVG(peakNorm, peak.value);
|
|
6894
|
-
this.#
|
|
6895
|
-
this.#handle1.setAttribute("
|
|
6936
|
+
const hr = this.#bezierHandleRadius;
|
|
6937
|
+
this.#handle1.setAttribute("x", peakPt.x - hr);
|
|
6938
|
+
this.#handle1.setAttribute("y", peakPt.y - hr);
|
|
6896
6939
|
|
|
6897
6940
|
// Duration handle: on the target line
|
|
6898
6941
|
const targetPt = this.#springToSVG(durationNorm, 1);
|
|
@@ -6984,8 +7027,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
6984
7027
|
);
|
|
6985
7028
|
if (bezierSurface) {
|
|
6986
7029
|
bezierSurface.addEventListener("pointerdown", (e) => {
|
|
6987
|
-
|
|
6988
|
-
if (e.target?.closest?.(".fig-easing-curve-handle")) return;
|
|
7030
|
+
if (e.target?.closest?.(".fig-easing-curve-handle, fig-handle")) return;
|
|
6989
7031
|
this.#startBezierDrag(e, this.#bezierHandleForClientHalf(e));
|
|
6990
7032
|
});
|
|
6991
7033
|
}
|
|
@@ -7004,8 +7046,7 @@ class FigEasingCurve extends HTMLElement {
|
|
|
7004
7046
|
);
|
|
7005
7047
|
if (springSurface) {
|
|
7006
7048
|
springSurface.addEventListener("pointerdown", (e) => {
|
|
7007
|
-
|
|
7008
|
-
if (e.target?.closest?.(".fig-easing-curve-handle")) return;
|
|
7049
|
+
if (e.target?.closest?.(".fig-easing-curve-handle, fig-handle")) return;
|
|
7009
7050
|
this.#startSpringDrag(e, "duration");
|
|
7010
7051
|
});
|
|
7011
7052
|
}
|
|
@@ -7680,14 +7721,14 @@ class FigOriginGrid extends HTMLElement {
|
|
|
7680
7721
|
this.innerHTML = `<div class="fig-origin-grid-surface">
|
|
7681
7722
|
<div class="origin-grid" aria-label="Transform origin grid">
|
|
7682
7723
|
<div class="origin-grid-cells">${cells}</div>
|
|
7683
|
-
<
|
|
7724
|
+
<fig-handle></fig-handle>
|
|
7684
7725
|
</div>
|
|
7685
7726
|
</div>
|
|
7686
7727
|
${fieldsMarkup}`;
|
|
7687
7728
|
|
|
7688
7729
|
this.#grid = this.querySelector(".origin-grid");
|
|
7689
7730
|
this.#cells = Array.from(this.querySelectorAll(".origin-grid-cell"));
|
|
7690
|
-
this.#handle = this.querySelector("
|
|
7731
|
+
this.#handle = this.querySelector("fig-handle");
|
|
7691
7732
|
this.#xInput = this.querySelector('fig-input-number[name="x"]');
|
|
7692
7733
|
this.#yInput = this.querySelector('fig-input-number[name="y"]');
|
|
7693
7734
|
this.#syncHandlePosition();
|
|
@@ -7991,18 +8032,19 @@ class FigInputJoystick extends HTMLElement {
|
|
|
7991
8032
|
#boundXFocusOut = null;
|
|
7992
8033
|
#boundYFocusOut = null;
|
|
7993
8034
|
#isSyncingValueAttr = false;
|
|
8035
|
+
#defaultPosition = { x: 0.5, y: 0.5 };
|
|
7994
8036
|
|
|
7995
8037
|
constructor() {
|
|
7996
8038
|
super();
|
|
7997
8039
|
|
|
7998
|
-
this.position = { x: 0.5, y: 0.5 };
|
|
8040
|
+
this.position = { x: 0.5, y: 0.5 };
|
|
7999
8041
|
this.isDragging = false;
|
|
8000
8042
|
this.isShiftHeld = false;
|
|
8001
8043
|
this.plane = null;
|
|
8002
8044
|
this.cursor = null;
|
|
8003
8045
|
this.xInput = null;
|
|
8004
8046
|
this.yInput = null;
|
|
8005
|
-
this.coordinates = "screen";
|
|
8047
|
+
this.coordinates = "screen";
|
|
8006
8048
|
this.#initialized = false;
|
|
8007
8049
|
this.#boundMouseDown = (e) => this.#handleMouseDown(e);
|
|
8008
8050
|
this.#boundTouchStart = (e) => this.#handleTouchStart(e);
|
|
@@ -8033,6 +8075,7 @@ class FigInputJoystick extends HTMLElement {
|
|
|
8033
8075
|
this.#setupListeners();
|
|
8034
8076
|
this.#syncHandlePosition();
|
|
8035
8077
|
this.#syncValueAttribute();
|
|
8078
|
+
this.#syncResetButton();
|
|
8036
8079
|
this.#initialized = true;
|
|
8037
8080
|
});
|
|
8038
8081
|
}
|
|
@@ -8112,8 +8155,13 @@ class FigInputJoystick extends HTMLElement {
|
|
|
8112
8155
|
${labelsMarkup}
|
|
8113
8156
|
<div class="fig-input-joystick-plane">
|
|
8114
8157
|
<div class="fig-input-joystick-guides"></div>
|
|
8115
|
-
<
|
|
8158
|
+
<fig-handle></fig-handle>
|
|
8116
8159
|
</div>
|
|
8160
|
+
<fig-tooltip text="Reset">
|
|
8161
|
+
<fig-button variant="ghost" icon="true" class="fig-joystick-reset" aria-label="Reset to default">
|
|
8162
|
+
<span class="fig-mask-icon" style="--icon: var(--icon-reset)"></span>
|
|
8163
|
+
</fig-button>
|
|
8164
|
+
</fig-tooltip>
|
|
8117
8165
|
</div>
|
|
8118
8166
|
${
|
|
8119
8167
|
this.#fieldsEnabled
|
|
@@ -8144,13 +8192,17 @@ class FigInputJoystick extends HTMLElement {
|
|
|
8144
8192
|
|
|
8145
8193
|
#setupListeners() {
|
|
8146
8194
|
this.plane = this.querySelector(".fig-input-joystick-plane");
|
|
8147
|
-
this.cursor = this.querySelector("
|
|
8195
|
+
this.cursor = this.querySelector("fig-handle");
|
|
8148
8196
|
this.xInput = this.querySelector("fig-input-number[name='x']");
|
|
8149
8197
|
this.yInput = this.querySelector("fig-input-number[name='y']");
|
|
8150
8198
|
this.plane.addEventListener("mousedown", this.#boundMouseDown);
|
|
8151
8199
|
this.plane.addEventListener("touchstart", this.#boundTouchStart);
|
|
8152
8200
|
window.addEventListener("keydown", this.#boundKeyDown);
|
|
8153
8201
|
window.addEventListener("keyup", this.#boundKeyUp);
|
|
8202
|
+
const resetBtn = this.querySelector(".fig-joystick-reset");
|
|
8203
|
+
if (resetBtn) {
|
|
8204
|
+
resetBtn.addEventListener("click", () => this.#resetToDefault());
|
|
8205
|
+
}
|
|
8154
8206
|
if (this.#fieldsEnabled && this.xInput && this.yInput) {
|
|
8155
8207
|
this.xInput.addEventListener("input", this.#boundXInput);
|
|
8156
8208
|
this.xInput.addEventListener("change", this.#boundXInput);
|
|
@@ -8279,13 +8331,33 @@ class FigInputJoystick extends HTMLElement {
|
|
|
8279
8331
|
|
|
8280
8332
|
#syncValueAttribute() {
|
|
8281
8333
|
const next = this.value;
|
|
8282
|
-
if (this.getAttribute("value")
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8334
|
+
if (this.getAttribute("value") !== next) {
|
|
8335
|
+
this.#isSyncingValueAttr = true;
|
|
8336
|
+
this.setAttribute("value", next);
|
|
8337
|
+
this.#isSyncingValueAttr = false;
|
|
8338
|
+
}
|
|
8339
|
+
this.#syncResetButton();
|
|
8340
|
+
}
|
|
8341
|
+
|
|
8342
|
+
#syncResetButton() {
|
|
8343
|
+
const d = this.#defaultPosition;
|
|
8344
|
+
const isDefault =
|
|
8345
|
+
Math.round(this.position.x * 100) === Math.round(d.x * 100) &&
|
|
8346
|
+
Math.round(this.position.y * 100) === Math.round(d.y * 100);
|
|
8347
|
+
this.toggleAttribute("default", isDefault);
|
|
8348
|
+
this.style.setProperty("--is-not-default", isDefault ? "0" : "1");
|
|
8349
|
+
}
|
|
8350
|
+
|
|
8351
|
+
#resetToDefault() {
|
|
8352
|
+
this.position = { ...this.#defaultPosition };
|
|
8353
|
+
this.#syncHandlePosition();
|
|
8354
|
+
this.#syncValueAttribute();
|
|
8355
|
+
this.#emitInputEvent();
|
|
8356
|
+
this.#emitChangeEvent();
|
|
8286
8357
|
}
|
|
8287
8358
|
|
|
8288
8359
|
#handleMouseDown(e) {
|
|
8360
|
+
if (e.target.closest(".fig-joystick-reset, fig-tooltip")) return;
|
|
8289
8361
|
this.isDragging = true;
|
|
8290
8362
|
|
|
8291
8363
|
this.#updatePosition(e);
|
|
@@ -8312,6 +8384,7 @@ class FigInputJoystick extends HTMLElement {
|
|
|
8312
8384
|
}
|
|
8313
8385
|
|
|
8314
8386
|
#handleTouchStart(e) {
|
|
8387
|
+
if (e.target.closest(".fig-joystick-reset, fig-tooltip")) return;
|
|
8315
8388
|
e.preventDefault();
|
|
8316
8389
|
this.isDragging = true;
|
|
8317
8390
|
this.#updatePosition(e.touches[0]);
|
|
@@ -8380,6 +8453,7 @@ class FigInputJoystick extends HTMLElement {
|
|
|
8380
8453
|
}
|
|
8381
8454
|
if (this.#initialized) {
|
|
8382
8455
|
this.#syncHandlePosition();
|
|
8456
|
+
this.#syncResetButton();
|
|
8383
8457
|
}
|
|
8384
8458
|
}
|
|
8385
8459
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -11271,3 +11345,11 @@ class FigChooser extends HTMLElement {
|
|
|
11271
11345
|
}
|
|
11272
11346
|
}
|
|
11273
11347
|
customElements.define("fig-chooser", FigChooser);
|
|
11348
|
+
|
|
11349
|
+
/* Handle */
|
|
11350
|
+
class FigHandle extends HTMLElement {
|
|
11351
|
+
constructor() {
|
|
11352
|
+
super();
|
|
11353
|
+
}
|
|
11354
|
+
}
|
|
11355
|
+
customElements.define("fig-handle", FigHandle);
|
package/package.json
CHANGED