@rogieking/figui3 8.9.35 → 8.9.37
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/.cursor/skills/fig-lab/SKILL.md +2 -2
- package/.cursor/skills/fig-lab/reference.md +2 -2
- package/README.md +1 -2
- package/components.css +1 -1
- package/dist/components.css +1 -1
- package/dist/fig-lab.css +1 -1
- package/dist/fig-lab.js +2 -2
- package/dist/fig.css +1 -1
- package/fig-lab.css +11 -14
- package/fig-lab.js +209 -104
- package/package.json +1 -1
package/fig-lab.css
CHANGED
|
@@ -1474,11 +1474,6 @@ propskit-slider {
|
|
|
1474
1474
|
}
|
|
1475
1475
|
|
|
1476
1476
|
fig-input-wheel {
|
|
1477
|
-
--fig-input-wheel-elastic-distance: calc(var(--spacer-2) + 0.25rem);
|
|
1478
|
-
--fig-input-wheel-elastic-scale: 1;
|
|
1479
|
-
--fig-input-wheel-elastic-origin: left center;
|
|
1480
|
-
--fig-input-wheel-elastic-transition: 0.28s
|
|
1481
|
-
cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
1482
1477
|
--fig-input-wheel-handle-drag-max: 0.5rem;
|
|
1483
1478
|
--fig-input-wheel-handle-drag-offset: 0px;
|
|
1484
1479
|
--fig-input-wheel-handle-spring: 0.28s
|
|
@@ -1494,6 +1489,7 @@ fig-input-wheel {
|
|
|
1494
1489
|
--fig-input-wheel-tick-fade: 1rem;
|
|
1495
1490
|
--fig-input-wheel-tick-opacity: 0.5;
|
|
1496
1491
|
--fig-input-wheel-tick-opacity-min: 0.1;
|
|
1492
|
+
--fig-input-wheel-fast-tick-blur: 2px;
|
|
1497
1493
|
--fig-input-wheel-handle-width: var(--spacer-1);
|
|
1498
1494
|
--fig-input-wheel-handle-height: calc(
|
|
1499
1495
|
var(--control-height) - var(--spacer-2)
|
|
@@ -1512,8 +1508,6 @@ fig-input-wheel {
|
|
|
1512
1508
|
background-color: var(--figma-color-bg-secondary);
|
|
1513
1509
|
outline: none;
|
|
1514
1510
|
cursor: ew-resize;
|
|
1515
|
-
transform-origin: var(--fig-input-wheel-elastic-origin);
|
|
1516
|
-
transition: transform var(--fig-input-wheel-elastic-transition);
|
|
1517
1511
|
|
|
1518
1512
|
&:focus-visible {
|
|
1519
1513
|
outline: var(--figma-focus-outline);
|
|
@@ -1527,8 +1521,9 @@ fig-input-wheel {
|
|
|
1527
1521
|
|
|
1528
1522
|
.fig-input-wheel-svg {
|
|
1529
1523
|
display: block;
|
|
1530
|
-
width: 100
|
|
1524
|
+
width: calc(100% - var(--spacer-3));
|
|
1531
1525
|
height: 100%;
|
|
1526
|
+
margin-inline: var(--spacer-2);
|
|
1532
1527
|
overflow: visible;
|
|
1533
1528
|
color: var(--figma-color-icon-tertiary);
|
|
1534
1529
|
mask-image: linear-gradient(
|
|
@@ -1545,6 +1540,7 @@ fig-input-wheel {
|
|
|
1545
1540
|
.fig-input-wheel-tick {
|
|
1546
1541
|
fill: currentColor;
|
|
1547
1542
|
stroke: none;
|
|
1543
|
+
transition: filter 0.12s ease-out;
|
|
1548
1544
|
}
|
|
1549
1545
|
|
|
1550
1546
|
.fig-input-wheel-handle {
|
|
@@ -1568,13 +1564,13 @@ fig-input-wheel {
|
|
|
1568
1564
|
var(--handle-shadow);
|
|
1569
1565
|
}
|
|
1570
1566
|
|
|
1571
|
-
&[data-fig-input-wheel-
|
|
1572
|
-
transform: scaleX(var(--fig-input-wheel-elastic-scale));
|
|
1567
|
+
&[data-fig-input-wheel-active] .fig-input-wheel-handle {
|
|
1573
1568
|
transition: none;
|
|
1569
|
+
}
|
|
1574
1570
|
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1571
|
+
&[data-fig-input-wheel-fast] .fig-input-wheel-tick {
|
|
1572
|
+
filter: blur(var(--fig-input-wheel-fast-tick-blur));
|
|
1573
|
+
transition: none;
|
|
1578
1574
|
}
|
|
1579
1575
|
|
|
1580
1576
|
&[data-fig-input-wheel-keyboard-moving] .fig-input-wheel-handle {
|
|
@@ -1587,6 +1583,7 @@ fig-input-wheel {
|
|
|
1587
1583
|
}
|
|
1588
1584
|
|
|
1589
1585
|
propskit-wheel {
|
|
1586
|
+
--propskit-wheel-elastic-distance: calc(var(--spacer-2) + 0.25rem);
|
|
1590
1587
|
--propskit-wheel-elastic-scale: 1;
|
|
1591
1588
|
--propskit-wheel-elastic-origin: left center;
|
|
1592
1589
|
--propskit-wheel-elastic-transition: 0.28s
|
|
@@ -1761,7 +1758,7 @@ body.fig-input-wheel-dragging * {
|
|
|
1761
1758
|
|
|
1762
1759
|
@media (prefers-reduced-motion: reduce) {
|
|
1763
1760
|
propskit-wheel,
|
|
1764
|
-
fig-input-wheel,
|
|
1761
|
+
fig-input-wheel .fig-input-wheel-tick,
|
|
1765
1762
|
fig-input-wheel .fig-input-wheel-handle {
|
|
1766
1763
|
transition: none;
|
|
1767
1764
|
}
|
package/fig-lab.js
CHANGED
|
@@ -5553,7 +5553,6 @@ figLabDefineElement("propskit-slider", PropskitSlider);
|
|
|
5553
5553
|
* @attr {number} max - Inclusive upper bound. Omitted = unbounded above.
|
|
5554
5554
|
* @attr {number} step - Increment. Defaults to 1.
|
|
5555
5555
|
* @attr {boolean|string} spin - Keeps ticks synchronized to value. Defaults to true.
|
|
5556
|
-
* @attr {boolean|string} elastic - Enables resisted handle movement. Defaults to true.
|
|
5557
5556
|
* @attr {boolean|string} disabled - Disables interaction and focus.
|
|
5558
5557
|
* @fires input - Numeric composed event during interaction.
|
|
5559
5558
|
* @fires change - Numeric composed event on commit.
|
|
@@ -5562,6 +5561,8 @@ class FigInputWheel extends HTMLElement {
|
|
|
5562
5561
|
static #TICK_COUNT = 33;
|
|
5563
5562
|
static #HALF_FOV_DEG = 60;
|
|
5564
5563
|
static #PERSPECTIVE_K = 0.55;
|
|
5564
|
+
static #FAST_MOTION_THRESHOLD_PX_PER_MS = 1.5;
|
|
5565
|
+
static #FAST_MOTION_TIMEOUT_MS = 80;
|
|
5565
5566
|
static #DRAGGING_BODY_CLASS = "fig-input-wheel-dragging";
|
|
5566
5567
|
|
|
5567
5568
|
#surface = null;
|
|
@@ -5583,9 +5584,9 @@ class FigInputWheel extends HTMLElement {
|
|
|
5583
5584
|
#dragStartValue = 0;
|
|
5584
5585
|
#visualValue = null;
|
|
5585
5586
|
#handleDragMaxPx = 0;
|
|
5586
|
-
#
|
|
5587
|
-
#
|
|
5588
|
-
#
|
|
5587
|
+
#motionLastX = null;
|
|
5588
|
+
#motionLastTime = 0;
|
|
5589
|
+
#motionBlurTimer = 0;
|
|
5589
5590
|
#boundPointerDown = this.#handlePointerDown.bind(this);
|
|
5590
5591
|
#boundPointerMove = this.#handlePointerMove.bind(this);
|
|
5591
5592
|
#boundPointerUp = this.#handlePointerUp.bind(this);
|
|
@@ -5600,7 +5601,6 @@ class FigInputWheel extends HTMLElement {
|
|
|
5600
5601
|
"min",
|
|
5601
5602
|
"max",
|
|
5602
5603
|
"spin",
|
|
5603
|
-
"elastic",
|
|
5604
5604
|
];
|
|
5605
5605
|
}
|
|
5606
5606
|
|
|
@@ -5960,7 +5960,8 @@ class FigInputWheel extends HTMLElement {
|
|
|
5960
5960
|
this.#dragStartValue = Number.isFinite(requestedStart)
|
|
5961
5961
|
? this.#clamp(requestedStart)
|
|
5962
5962
|
: this.#numericValue();
|
|
5963
|
-
this.#
|
|
5963
|
+
this.#startTickMotionTracking(clientX);
|
|
5964
|
+
this.#startHandlePull();
|
|
5964
5965
|
this.setAttribute("data-fig-input-wheel-active", "");
|
|
5965
5966
|
document.body.classList.add(FigInputWheel.#DRAGGING_BODY_CLASS);
|
|
5966
5967
|
this.focus();
|
|
@@ -6006,13 +6007,19 @@ class FigInputWheel extends HTMLElement {
|
|
|
6006
6007
|
const visibleUnits = this.#step() * visibleSteps;
|
|
6007
6008
|
const delta =
|
|
6008
6009
|
(clientX - this.#dragStartX) * (visibleUnits / width) * speed;
|
|
6010
|
+
const previousVisualValue = this.#visualValue ?? this.#dragStartValue;
|
|
6009
6011
|
const rawValue = this.#clamp(this.#dragStartValue + delta);
|
|
6012
|
+
this.#updateTickMotionBlur(
|
|
6013
|
+
clientX,
|
|
6014
|
+
speed,
|
|
6015
|
+
rawValue !== previousVisualValue,
|
|
6016
|
+
);
|
|
6010
6017
|
this.#visualValue = rawValue;
|
|
6011
6018
|
this.#commitValue(rawValue, {
|
|
6012
6019
|
snap: true,
|
|
6013
6020
|
emit: "input",
|
|
6014
6021
|
});
|
|
6015
|
-
this.#
|
|
6022
|
+
this.#updateHandlePull(clientX);
|
|
6016
6023
|
}
|
|
6017
6024
|
|
|
6018
6025
|
#handlePointerUp(event) {
|
|
@@ -6029,30 +6036,19 @@ class FigInputWheel extends HTMLElement {
|
|
|
6029
6036
|
this.#visualValue = null;
|
|
6030
6037
|
this.removeAttribute("data-fig-input-wheel-active");
|
|
6031
6038
|
document.body.classList.remove(FigInputWheel.#DRAGGING_BODY_CLASS);
|
|
6032
|
-
this.#
|
|
6039
|
+
this.#stopTickMotionTracking();
|
|
6040
|
+
this.#resetHandlePull();
|
|
6033
6041
|
window.removeEventListener("pointermove", this.#boundPointerMove);
|
|
6034
6042
|
window.removeEventListener("pointerup", this.#boundPointerUp);
|
|
6035
6043
|
window.removeEventListener("pointercancel", this.#boundPointerUp);
|
|
6036
6044
|
this.#queueWheelLayout();
|
|
6037
6045
|
}
|
|
6038
6046
|
|
|
6039
|
-
#
|
|
6040
|
-
this.#
|
|
6041
|
-
if (this.getAttribute("elastic") === "false") return;
|
|
6047
|
+
#startHandlePull() {
|
|
6048
|
+
this.#resetHandlePull();
|
|
6042
6049
|
this.#handleDragMaxPx = this.#readCssLength(
|
|
6043
6050
|
"--fig-input-wheel-handle-drag-max",
|
|
6044
6051
|
);
|
|
6045
|
-
this.#elasticMaxPx = this.#readCssLength(
|
|
6046
|
-
"--fig-input-wheel-elastic-distance",
|
|
6047
|
-
);
|
|
6048
|
-
const rect = this.#wheel?.getBoundingClientRect();
|
|
6049
|
-
if (rect) {
|
|
6050
|
-
this.#elasticRangeRect = {
|
|
6051
|
-
left: rect.left,
|
|
6052
|
-
right: rect.right,
|
|
6053
|
-
};
|
|
6054
|
-
}
|
|
6055
|
-
this.#elasticHostWidth = this.getBoundingClientRect().width;
|
|
6056
6052
|
}
|
|
6057
6053
|
|
|
6058
6054
|
#readCssLength(propertyName) {
|
|
@@ -6075,14 +6071,14 @@ class FigInputWheel extends HTMLElement {
|
|
|
6075
6071
|
return Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
6076
6072
|
}
|
|
6077
6073
|
|
|
6078
|
-
#
|
|
6079
|
-
if (!this.#handleDragMaxPx
|
|
6080
|
-
this.#
|
|
6074
|
+
#updateHandlePull(pointerX) {
|
|
6075
|
+
if (!this.#handleDragMaxPx) {
|
|
6076
|
+
this.#clearHandlePull();
|
|
6081
6077
|
return;
|
|
6082
6078
|
}
|
|
6083
6079
|
const dragDelta = pointerX - this.#dragStartX;
|
|
6084
6080
|
if (!dragDelta) {
|
|
6085
|
-
this.#
|
|
6081
|
+
this.#clearHandlePull();
|
|
6086
6082
|
return;
|
|
6087
6083
|
}
|
|
6088
6084
|
const offset =
|
|
@@ -6090,49 +6086,60 @@ class FigInputWheel extends HTMLElement {
|
|
|
6090
6086
|
Math.tanh(
|
|
6091
6087
|
dragDelta / Math.max(1, this.#handleDragMaxPx * 3),
|
|
6092
6088
|
);
|
|
6093
|
-
this.setAttribute("data-fig-input-wheel-elastic-dragging", "");
|
|
6094
6089
|
this.style.setProperty(
|
|
6095
6090
|
"--fig-input-wheel-handle-drag-offset",
|
|
6096
6091
|
`${offset}px`,
|
|
6097
6092
|
);
|
|
6093
|
+
}
|
|
6098
6094
|
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6095
|
+
#resetHandlePull() {
|
|
6096
|
+
this.#clearHandlePull();
|
|
6097
|
+
this.#handleDragMaxPx = 0;
|
|
6098
|
+
}
|
|
6099
|
+
|
|
6100
|
+
#clearHandlePull() {
|
|
6101
|
+
this.style.removeProperty("--fig-input-wheel-handle-drag-offset");
|
|
6102
|
+
}
|
|
6103
|
+
|
|
6104
|
+
#startTickMotionTracking(clientX) {
|
|
6105
|
+
this.#stopTickMotionTracking();
|
|
6106
|
+
this.#motionLastX = clientX;
|
|
6107
|
+
this.#motionLastTime = performance.now();
|
|
6108
|
+
}
|
|
6109
|
+
|
|
6110
|
+
#updateTickMotionBlur(clientX, speed, moved) {
|
|
6111
|
+
const now = performance.now();
|
|
6112
|
+
const elapsed = now - this.#motionLastTime;
|
|
6113
|
+
const distance =
|
|
6114
|
+
this.#motionLastX === null ? 0 : Math.abs(clientX - this.#motionLastX);
|
|
6115
|
+
this.#motionLastX = clientX;
|
|
6116
|
+
this.#motionLastTime = now;
|
|
6117
|
+
const velocity =
|
|
6118
|
+
elapsed > 0 ? (distance / elapsed) * Math.max(1, Math.abs(speed)) : 0;
|
|
6119
|
+
if (
|
|
6120
|
+
!moved ||
|
|
6121
|
+
velocity < FigInputWheel.#FAST_MOTION_THRESHOLD_PX_PER_MS
|
|
6122
|
+
) {
|
|
6123
|
+
this.#clearTickMotionBlur();
|
|
6110
6124
|
return;
|
|
6111
6125
|
}
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
this.style.setProperty(
|
|
6118
|
-
"--fig-input-wheel-elastic-origin",
|
|
6119
|
-
overshoot < 0 ? "right center" : "left center",
|
|
6120
|
-
);
|
|
6126
|
+
this.toggleAttribute("data-fig-input-wheel-fast", true);
|
|
6127
|
+
clearTimeout(this.#motionBlurTimer);
|
|
6128
|
+
this.#motionBlurTimer = window.setTimeout(() => {
|
|
6129
|
+
this.#clearTickMotionBlur();
|
|
6130
|
+
}, FigInputWheel.#FAST_MOTION_TIMEOUT_MS);
|
|
6121
6131
|
}
|
|
6122
6132
|
|
|
6123
|
-
#
|
|
6124
|
-
this.#
|
|
6125
|
-
this.#
|
|
6126
|
-
this.#
|
|
6127
|
-
this.#elasticRangeRect = null;
|
|
6128
|
-
this.#elasticHostWidth = 0;
|
|
6133
|
+
#stopTickMotionTracking() {
|
|
6134
|
+
this.#motionLastX = null;
|
|
6135
|
+
this.#motionLastTime = 0;
|
|
6136
|
+
this.#clearTickMotionBlur();
|
|
6129
6137
|
}
|
|
6130
6138
|
|
|
6131
|
-
#
|
|
6132
|
-
this
|
|
6133
|
-
this
|
|
6134
|
-
this.
|
|
6135
|
-
this.style.removeProperty("--fig-input-wheel-elastic-origin");
|
|
6139
|
+
#clearTickMotionBlur() {
|
|
6140
|
+
clearTimeout(this.#motionBlurTimer);
|
|
6141
|
+
this.#motionBlurTimer = 0;
|
|
6142
|
+
this.removeAttribute("data-fig-input-wheel-fast");
|
|
6136
6143
|
}
|
|
6137
6144
|
|
|
6138
6145
|
#handleWheel(event) {
|
|
@@ -6221,8 +6228,7 @@ class FigInputWheel extends HTMLElement {
|
|
|
6221
6228
|
) || 0;
|
|
6222
6229
|
const duration = multiplier > 1 ? 120 : 90;
|
|
6223
6230
|
const startedAt = performance.now();
|
|
6224
|
-
const shouldAnimateHandle =
|
|
6225
|
-
animateHandle && this.getAttribute("elastic") !== "false";
|
|
6231
|
+
const shouldAnimateHandle = animateHandle;
|
|
6226
6232
|
this.setAttribute("data-fig-input-wheel-keyboard-moving", "");
|
|
6227
6233
|
|
|
6228
6234
|
const frame = (now) => {
|
|
@@ -6336,6 +6342,7 @@ figLabDefineElement("fig-input-wheel", FigInputWheel);
|
|
|
6336
6342
|
* @attr {string} label - Field label. Defaults to "Value".
|
|
6337
6343
|
* @attr {string} default - Reset target.
|
|
6338
6344
|
* @attr {number} precision - Number field display decimals.
|
|
6345
|
+
* @attr {boolean|string} elastic - Enables resisted row stretching. Defaults to true.
|
|
6339
6346
|
* @attr {boolean|string} spin - Keeps wheel ticks synchronized to value. Defaults to true.
|
|
6340
6347
|
* @attr {boolean|string} text - Shows the number field. Defaults to true.
|
|
6341
6348
|
* @attr {string} size - Set to "small" for compact sizing.
|
|
@@ -6382,9 +6389,12 @@ class PropskitWheel extends HTMLElement {
|
|
|
6382
6389
|
#input = null;
|
|
6383
6390
|
#hasCustomLabel = false;
|
|
6384
6391
|
#observer = null;
|
|
6385
|
-
#elasticObserver = null;
|
|
6386
6392
|
#managedInputAttrs = new Set();
|
|
6387
6393
|
#initialValue = null;
|
|
6394
|
+
#elasticPointerId = null;
|
|
6395
|
+
#elasticMaxPx = 0;
|
|
6396
|
+
#elasticRangeRect = null;
|
|
6397
|
+
#elasticHostWidth = 0;
|
|
6388
6398
|
#numberPointerId = null;
|
|
6389
6399
|
#numberPointerStartX = 0;
|
|
6390
6400
|
#numberPointerStartY = 0;
|
|
@@ -6399,6 +6409,9 @@ class PropskitWheel extends HTMLElement {
|
|
|
6399
6409
|
#boundNumberPointerDown = this.#handleNumberPointerDown.bind(this);
|
|
6400
6410
|
#boundNumberPointerMove = this.#handleNumberPointerMove.bind(this);
|
|
6401
6411
|
#boundNumberPointerEnd = this.#handleNumberPointerEnd.bind(this);
|
|
6412
|
+
#boundElasticPointerDown = this.#handleElasticPointerDown.bind(this);
|
|
6413
|
+
#boundElasticPointerMove = this.#handleElasticPointerMove.bind(this);
|
|
6414
|
+
#boundElasticPointerEnd = this.#handleElasticPointerEnd.bind(this);
|
|
6402
6415
|
#boundClick = this.#handleClick.bind(this);
|
|
6403
6416
|
|
|
6404
6417
|
connectedCallback() {
|
|
@@ -6425,24 +6438,11 @@ class PropskitWheel extends HTMLElement {
|
|
|
6425
6438
|
}
|
|
6426
6439
|
});
|
|
6427
6440
|
this.#observer.observe(this, { attributes: true });
|
|
6428
|
-
this.#elasticObserver?.disconnect();
|
|
6429
|
-
this.#elasticObserver = new MutationObserver(() => {
|
|
6430
|
-
this.#syncElasticComposition();
|
|
6431
|
-
});
|
|
6432
|
-
if (this.#wheel) {
|
|
6433
|
-
this.#elasticObserver.observe(this.#wheel, {
|
|
6434
|
-
attributes: true,
|
|
6435
|
-
attributeFilter: ["style", "data-fig-input-wheel-elastic-dragging"],
|
|
6436
|
-
});
|
|
6437
|
-
}
|
|
6438
|
-
this.#syncElasticComposition();
|
|
6439
6441
|
}
|
|
6440
6442
|
|
|
6441
6443
|
disconnectedCallback() {
|
|
6442
6444
|
this.#observer?.disconnect();
|
|
6443
|
-
this.#
|
|
6444
|
-
this.#elasticObserver = null;
|
|
6445
|
-
this.#clearElasticComposition();
|
|
6445
|
+
this.#stopElasticTracking();
|
|
6446
6446
|
this.#unbindEvents();
|
|
6447
6447
|
this.#stopNumberTracking();
|
|
6448
6448
|
clearTimeout(this.#numberClickResetTimer);
|
|
@@ -6455,6 +6455,9 @@ class PropskitWheel extends HTMLElement {
|
|
|
6455
6455
|
if (oldValue === newValue || !this.#surface) return;
|
|
6456
6456
|
if (name === "label") this.#syncLabel();
|
|
6457
6457
|
if (name === "text") this.#syncText();
|
|
6458
|
+
if (name === "elastic" && newValue === "false") {
|
|
6459
|
+
this.#stopElasticTracking();
|
|
6460
|
+
}
|
|
6458
6461
|
if (
|
|
6459
6462
|
[
|
|
6460
6463
|
"units",
|
|
@@ -6542,7 +6545,7 @@ class PropskitWheel extends HTMLElement {
|
|
|
6542
6545
|
#syncPrimitive() {
|
|
6543
6546
|
if (!this.#wheel) return;
|
|
6544
6547
|
this.#wheel.removeAttribute("units");
|
|
6545
|
-
for (const name of ["min", "max", "
|
|
6548
|
+
for (const name of ["min", "max", "spin"]) {
|
|
6546
6549
|
this.#mirrorAttribute(name);
|
|
6547
6550
|
}
|
|
6548
6551
|
if (this.hasAttribute("step")) this.#mirrorAttribute("step");
|
|
@@ -6562,34 +6565,6 @@ class PropskitWheel extends HTMLElement {
|
|
|
6562
6565
|
this.#syncPrimitiveAria();
|
|
6563
6566
|
}
|
|
6564
6567
|
|
|
6565
|
-
#syncElasticComposition() {
|
|
6566
|
-
if (!this.#wheel) return;
|
|
6567
|
-
const active = this.#wheel.hasAttribute(
|
|
6568
|
-
"data-fig-input-wheel-elastic-dragging",
|
|
6569
|
-
);
|
|
6570
|
-
if (!active) {
|
|
6571
|
-
this.#clearElasticComposition();
|
|
6572
|
-
return;
|
|
6573
|
-
}
|
|
6574
|
-
this.toggleAttribute("data-propskit-wheel-elastic-dragging", true);
|
|
6575
|
-
this.style.setProperty(
|
|
6576
|
-
"--propskit-wheel-elastic-scale",
|
|
6577
|
-
this.#wheel.style.getPropertyValue("--fig-input-wheel-elastic-scale") ||
|
|
6578
|
-
"1",
|
|
6579
|
-
);
|
|
6580
|
-
this.style.setProperty(
|
|
6581
|
-
"--propskit-wheel-elastic-origin",
|
|
6582
|
-
this.#wheel.style.getPropertyValue("--fig-input-wheel-elastic-origin") ||
|
|
6583
|
-
"left center",
|
|
6584
|
-
);
|
|
6585
|
-
}
|
|
6586
|
-
|
|
6587
|
-
#clearElasticComposition() {
|
|
6588
|
-
this.removeAttribute("data-propskit-wheel-elastic-dragging");
|
|
6589
|
-
this.style.removeProperty("--propskit-wheel-elastic-scale");
|
|
6590
|
-
this.style.removeProperty("--propskit-wheel-elastic-origin");
|
|
6591
|
-
}
|
|
6592
|
-
|
|
6593
6568
|
#getForwardedInputAttrNames() {
|
|
6594
6569
|
return this.getAttributeNames().filter(
|
|
6595
6570
|
(name) =>
|
|
@@ -6685,6 +6660,9 @@ class PropskitWheel extends HTMLElement {
|
|
|
6685
6660
|
this.#wheel?.addEventListener("change", this.#boundPrimitiveChange);
|
|
6686
6661
|
this.#input?.addEventListener("input", this.#boundNumberInput);
|
|
6687
6662
|
this.#input?.addEventListener("change", this.#boundNumberChange);
|
|
6663
|
+
this.addEventListener("pointerdown", this.#boundElasticPointerDown, {
|
|
6664
|
+
capture: true,
|
|
6665
|
+
});
|
|
6688
6666
|
this.addEventListener("pointerdown", this.#boundNumberPointerDown, {
|
|
6689
6667
|
capture: true,
|
|
6690
6668
|
});
|
|
@@ -6696,6 +6674,9 @@ class PropskitWheel extends HTMLElement {
|
|
|
6696
6674
|
this.#wheel?.removeEventListener("change", this.#boundPrimitiveChange);
|
|
6697
6675
|
this.#input?.removeEventListener("input", this.#boundNumberInput);
|
|
6698
6676
|
this.#input?.removeEventListener("change", this.#boundNumberChange);
|
|
6677
|
+
this.removeEventListener("pointerdown", this.#boundElasticPointerDown, {
|
|
6678
|
+
capture: true,
|
|
6679
|
+
});
|
|
6699
6680
|
this.removeEventListener("pointerdown", this.#boundNumberPointerDown, {
|
|
6700
6681
|
capture: true,
|
|
6701
6682
|
});
|
|
@@ -6751,6 +6732,127 @@ class PropskitWheel extends HTMLElement {
|
|
|
6751
6732
|
this.#emit(type, value);
|
|
6752
6733
|
}
|
|
6753
6734
|
|
|
6735
|
+
#handleElasticPointerDown(event) {
|
|
6736
|
+
if (
|
|
6737
|
+
event.button !== 0 ||
|
|
6738
|
+
figLabBooleanAttribute(this, "disabled") ||
|
|
6739
|
+
this.getAttribute("elastic") === "false" ||
|
|
6740
|
+
!(event.target instanceof Element) ||
|
|
6741
|
+
event.target.closest("fig-input-number") ||
|
|
6742
|
+
!event.target.closest("fig-input-wheel")
|
|
6743
|
+
) {
|
|
6744
|
+
return;
|
|
6745
|
+
}
|
|
6746
|
+
this.#startElasticTracking(event.pointerId);
|
|
6747
|
+
}
|
|
6748
|
+
|
|
6749
|
+
#startElasticTracking(pointerId) {
|
|
6750
|
+
this.#stopElasticTracking();
|
|
6751
|
+
if (this.getAttribute("elastic") === "false") return;
|
|
6752
|
+
this.#elasticPointerId = pointerId;
|
|
6753
|
+
this.#elasticMaxPx = this.#readCssLength(
|
|
6754
|
+
"--propskit-wheel-elastic-distance",
|
|
6755
|
+
);
|
|
6756
|
+
const rangeRect = this.#wheel?.getBoundingClientRect();
|
|
6757
|
+
if (rangeRect) {
|
|
6758
|
+
this.#elasticRangeRect = {
|
|
6759
|
+
left: rangeRect.left,
|
|
6760
|
+
right: rangeRect.right,
|
|
6761
|
+
};
|
|
6762
|
+
}
|
|
6763
|
+
this.#elasticHostWidth = this.getBoundingClientRect().width;
|
|
6764
|
+
window.addEventListener("pointermove", this.#boundElasticPointerMove, {
|
|
6765
|
+
passive: true,
|
|
6766
|
+
});
|
|
6767
|
+
window.addEventListener("pointerup", this.#boundElasticPointerEnd);
|
|
6768
|
+
window.addEventListener("pointercancel", this.#boundElasticPointerEnd);
|
|
6769
|
+
window.addEventListener("blur", this.#boundElasticPointerEnd);
|
|
6770
|
+
}
|
|
6771
|
+
|
|
6772
|
+
#handleElasticPointerMove(event) {
|
|
6773
|
+
if (event.pointerId !== this.#elasticPointerId) return;
|
|
6774
|
+
if (event.buttons === 0) {
|
|
6775
|
+
this.#handleElasticPointerEnd(event);
|
|
6776
|
+
return;
|
|
6777
|
+
}
|
|
6778
|
+
this.#updateElasticStretch(event.clientX);
|
|
6779
|
+
}
|
|
6780
|
+
|
|
6781
|
+
#handleElasticPointerEnd(event) {
|
|
6782
|
+
if (
|
|
6783
|
+
event?.pointerId !== undefined &&
|
|
6784
|
+
this.#elasticPointerId !== null &&
|
|
6785
|
+
event.pointerId !== this.#elasticPointerId
|
|
6786
|
+
) {
|
|
6787
|
+
return;
|
|
6788
|
+
}
|
|
6789
|
+
this.#stopElasticTracking();
|
|
6790
|
+
}
|
|
6791
|
+
|
|
6792
|
+
#updateElasticStretch(pointerX) {
|
|
6793
|
+
const rect = this.#elasticRangeRect;
|
|
6794
|
+
if (!rect || !this.#elasticMaxPx) {
|
|
6795
|
+
this.#clearElasticStretch();
|
|
6796
|
+
return;
|
|
6797
|
+
}
|
|
6798
|
+
const overshoot =
|
|
6799
|
+
pointerX < rect.left
|
|
6800
|
+
? pointerX - rect.left
|
|
6801
|
+
: pointerX > rect.right
|
|
6802
|
+
? pointerX - rect.right
|
|
6803
|
+
: 0;
|
|
6804
|
+
if (!overshoot) {
|
|
6805
|
+
this.#clearElasticStretch();
|
|
6806
|
+
return;
|
|
6807
|
+
}
|
|
6808
|
+
const stretch = Math.min(this.#elasticMaxPx, Math.abs(overshoot) * 0.5);
|
|
6809
|
+
const scale = this.#elasticHostWidth
|
|
6810
|
+
? (this.#elasticHostWidth + stretch) / this.#elasticHostWidth
|
|
6811
|
+
: 1;
|
|
6812
|
+
this.toggleAttribute("data-propskit-wheel-elastic-dragging", true);
|
|
6813
|
+
this.style.setProperty("--propskit-wheel-elastic-scale", String(scale));
|
|
6814
|
+
this.style.setProperty(
|
|
6815
|
+
"--propskit-wheel-elastic-origin",
|
|
6816
|
+
overshoot < 0 ? "right center" : "left center",
|
|
6817
|
+
);
|
|
6818
|
+
}
|
|
6819
|
+
|
|
6820
|
+
#readCssLength(propertyName) {
|
|
6821
|
+
let raw = getComputedStyle(this).getPropertyValue(propertyName).trim();
|
|
6822
|
+
if (raw.includes("var(") || !raw.endsWith("px")) {
|
|
6823
|
+
const probe = document.createElement("div");
|
|
6824
|
+
Object.assign(probe.style, {
|
|
6825
|
+
position: "absolute",
|
|
6826
|
+
visibility: "hidden",
|
|
6827
|
+
pointerEvents: "none",
|
|
6828
|
+
width: `var(${propertyName})`,
|
|
6829
|
+
});
|
|
6830
|
+
this.appendChild(probe);
|
|
6831
|
+
raw = getComputedStyle(probe).width;
|
|
6832
|
+
probe.remove();
|
|
6833
|
+
}
|
|
6834
|
+
const value = Number.parseFloat(raw);
|
|
6835
|
+
return Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
6836
|
+
}
|
|
6837
|
+
|
|
6838
|
+
#stopElasticTracking() {
|
|
6839
|
+
window.removeEventListener("pointermove", this.#boundElasticPointerMove);
|
|
6840
|
+
window.removeEventListener("pointerup", this.#boundElasticPointerEnd);
|
|
6841
|
+
window.removeEventListener("pointercancel", this.#boundElasticPointerEnd);
|
|
6842
|
+
window.removeEventListener("blur", this.#boundElasticPointerEnd);
|
|
6843
|
+
this.#elasticPointerId = null;
|
|
6844
|
+
this.#elasticMaxPx = 0;
|
|
6845
|
+
this.#elasticRangeRect = null;
|
|
6846
|
+
this.#elasticHostWidth = 0;
|
|
6847
|
+
this.#clearElasticStretch();
|
|
6848
|
+
}
|
|
6849
|
+
|
|
6850
|
+
#clearElasticStretch() {
|
|
6851
|
+
this.removeAttribute("data-propskit-wheel-elastic-dragging");
|
|
6852
|
+
this.style.removeProperty("--propskit-wheel-elastic-scale");
|
|
6853
|
+
this.style.removeProperty("--propskit-wheel-elastic-origin");
|
|
6854
|
+
}
|
|
6855
|
+
|
|
6754
6856
|
#handleNumberPointerDown(event) {
|
|
6755
6857
|
if (
|
|
6756
6858
|
event.button !== 0 ||
|
|
@@ -6795,6 +6897,7 @@ class PropskitWheel extends HTMLElement {
|
|
|
6795
6897
|
if (distance < 4) return;
|
|
6796
6898
|
this.#isNumberScrubbing = true;
|
|
6797
6899
|
this.setAttribute("data-number-scrubbing", "");
|
|
6900
|
+
this.#startElasticTracking(event.pointerId);
|
|
6798
6901
|
this.#wheel?.beginScrub({
|
|
6799
6902
|
clientX: this.#numberPointerStartX,
|
|
6800
6903
|
pointerId: event.pointerId,
|
|
@@ -6802,6 +6905,7 @@ class PropskitWheel extends HTMLElement {
|
|
|
6802
6905
|
});
|
|
6803
6906
|
}
|
|
6804
6907
|
this.#wheel?.updateScrub(event);
|
|
6908
|
+
this.#updateElasticStretch(event.clientX);
|
|
6805
6909
|
}
|
|
6806
6910
|
|
|
6807
6911
|
#handleNumberPointerEnd(event) {
|
|
@@ -6813,6 +6917,7 @@ class PropskitWheel extends HTMLElement {
|
|
|
6813
6917
|
return;
|
|
6814
6918
|
}
|
|
6815
6919
|
const wasScrubbing = this.#isNumberScrubbing;
|
|
6920
|
+
this.#stopElasticTracking();
|
|
6816
6921
|
this.#stopNumberTracking();
|
|
6817
6922
|
if (wasScrubbing) {
|
|
6818
6923
|
this.#wheel?.endScrub();
|
package/package.json
CHANGED