@rogieking/figui3 6.18.3 → 6.18.4

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/fig-lab.css CHANGED
@@ -273,15 +273,20 @@ propskit-select {
273
273
 
274
274
  fig-select {
275
275
  position: relative;
276
- flex: 0 0 auto;
277
- width: fit-content;
276
+ display: flex;
277
+ flex: 1 1 auto;
278
+ width: 100%;
278
279
  min-width: 0;
279
- margin-left: auto;
280
+ height: 100%;
280
281
  border-radius: var(--radius-medium);
281
282
  background: transparent;
282
283
  box-shadow: none;
283
284
 
284
- --fig-select-trigger-width: auto;
285
+ --fig-select-trigger-width: 100%;
286
+
287
+ &::part(label) {
288
+ text-align: right;
289
+ }
285
290
  }
286
291
  }
287
292
  }
@@ -848,6 +853,11 @@ body.fig-lab-move-active * {
848
853
  cursor: var(--fig-lab-cursor-move) !important;
849
854
  }
850
855
 
856
+ body.fig-lab-rotate-active,
857
+ body.fig-lab-rotate-active * {
858
+ cursor: var(--fig-lab-cursor-rotate) !important;
859
+ }
860
+
851
861
  fig-canvas-control {
852
862
  display: contents;
853
863
  --fig-canvas-control-line-stroke: light-dark(
@@ -888,13 +898,14 @@ fig-canvas-control {
888
898
  --fig-handle-padding: 2px !important;
889
899
  }
890
900
  &[selected]:not([selected="false"]){
891
- --fig-handle-padding: 1px;
901
+ --fig-handle-padding: 2px;
892
902
  }
893
903
  }
894
904
  }
895
905
 
906
+ /* Point handle hover — resize/rotate hit-areas set cursor via JS !important. */
896
907
  fig-handle:hover,
897
- fig-handle:hover .fig-handle-hit-area {
908
+ fig-handle:hover .fig-handle-hit-area:not([data-cursor]) {
898
909
  cursor: var(--fig-lab-cursor) !important;
899
910
  }
900
911
 
@@ -904,7 +915,7 @@ fig-canvas-control {
904
915
  }
905
916
 
906
917
  fig-handle:is(:active, .active, .dragging),
907
- fig-handle:is(:active, .active, .dragging) .fig-handle-hit-area {
918
+ fig-handle:is(:active, .active, .dragging) .fig-handle-hit-area:not([data-cursor]) {
908
919
  cursor: var(--fig-lab-cursor-move) !important;
909
920
  }
910
921
 
package/fig-lab.js CHANGED
@@ -1758,6 +1758,11 @@ class FigCanvasControl extends HTMLElement {
1758
1758
  #moveCursorPrevBodyCursor = "";
1759
1759
  #moveCursorPrevBodyCursorPriority = "";
1760
1760
  #boundMoveCursorEnd = null;
1761
+ #rotateCursorPointerId = null;
1762
+ #rotateCursorHandle = null;
1763
+ #rotateCursorPrevBodyCursor = "";
1764
+ #rotateCursorPrevBodyCursorPriority = "";
1765
+ #boundRotateCursorEnd = null;
1761
1766
 
1762
1767
  get #type() {
1763
1768
  return this.getAttribute("type") || "point";
@@ -1858,7 +1863,9 @@ class FigCanvasControl extends HTMLElement {
1858
1863
  disconnectedCallback() {
1859
1864
  this.#teardownRadiusDrag();
1860
1865
  this.#deactivateMoveCursor();
1866
+ this.#deactivateRotateCursor();
1861
1867
  document.body.classList.remove("fig-lab-move-active");
1868
+ document.body.classList.remove("fig-lab-rotate-active");
1862
1869
  }
1863
1870
 
1864
1871
  attributeChangedCallback(name, oldVal, newVal) {
@@ -2020,19 +2027,27 @@ class FigCanvasControl extends HTMLElement {
2020
2027
  this.#createSecondHandle(disabled, tooltips, handleSurface);
2021
2028
  }
2022
2029
 
2023
- this.#setupHandleMoveCursor(this.#pointHandle);
2024
- this.#setupHandleMoveCursor(this.#angleHandle);
2025
- this.#setupHandleMoveCursor(this.#secondHandle);
2030
+ this.#setupHandleDragCursor(this.#pointHandle);
2031
+ this.#setupHandleDragCursor(this.#angleHandle);
2032
+ this.#setupHandleDragCursor(this.#secondHandle);
2026
2033
  this.#setupEventListeners();
2027
2034
  this.#wireHoverTooltips();
2028
2035
  requestAnimationFrame(() => this.#syncPositions());
2029
2036
  }
2030
2037
 
2031
- #setupHandleMoveCursor(handle) {
2038
+ #setupHandleDragCursor(handle) {
2032
2039
  if (!handle) return;
2033
2040
  handle.addEventListener(
2034
2041
  "pointerdown",
2035
- (e) => this.#activateMoveCursor(e),
2042
+ (e) => {
2043
+ // Hit-area (outside ring) = rotate; handle body = move/resize.
2044
+ const onHitArea = e.target?.classList?.contains("fig-handle-hit-area");
2045
+ if (onHitArea && handle.querySelector(".fig-handle-hit-area")) {
2046
+ this.#activateRotateCursor(e, handle);
2047
+ } else {
2048
+ this.#activateMoveCursor(e);
2049
+ }
2050
+ },
2036
2051
  { capture: true },
2037
2052
  );
2038
2053
  }
@@ -2101,6 +2116,86 @@ class FigCanvasControl extends HTMLElement {
2101
2116
  }
2102
2117
  }
2103
2118
 
2119
+ #rotateDegForHandle(handle) {
2120
+ if (!handle) return 0;
2121
+ if (handle === this.#angleHandle) return this.#angle;
2122
+ if (!this.#hasSecondPoint) return 0;
2123
+ const lineDeg = this.#pointPointLineDeg();
2124
+ return handle === this.#pointHandle ? lineDeg + 180 : lineDeg;
2125
+ }
2126
+
2127
+ #refreshBodyRotateCursor() {
2128
+ if (this.#rotateCursorPointerId === null) return;
2129
+ const cursor = this.#rotateCursorSvg(
2130
+ this.#rotateDegForHandle(this.#rotateCursorHandle),
2131
+ );
2132
+ document.body.style.setProperty("--fig-lab-cursor-rotate", cursor);
2133
+ document.body.style.setProperty("cursor", cursor, "important");
2134
+ }
2135
+
2136
+ #activateRotateCursor(e, handle) {
2137
+ if (figLabBooleanAttribute(this, "disabled")) return;
2138
+ if (e?.button !== undefined && e.button !== 0) return;
2139
+ if (e?.isPrimary === false) return;
2140
+
2141
+ if (this.#rotateCursorPointerId === null) {
2142
+ this.#rotateCursorPrevBodyCursor =
2143
+ document.body.style.getPropertyValue("cursor");
2144
+ this.#rotateCursorPrevBodyCursorPriority =
2145
+ document.body.style.getPropertyPriority("cursor");
2146
+ }
2147
+
2148
+ this.#rotateCursorPointerId = e?.pointerId ?? -1;
2149
+ this.#rotateCursorHandle = handle;
2150
+ document.body.classList.add("fig-lab-rotate-active");
2151
+ this.#refreshBodyRotateCursor();
2152
+
2153
+ if (!this.#boundRotateCursorEnd) {
2154
+ this.#boundRotateCursorEnd = (event) => {
2155
+ if (
2156
+ event?.pointerId !== undefined &&
2157
+ this.#rotateCursorPointerId !== null &&
2158
+ event.pointerId !== this.#rotateCursorPointerId
2159
+ ) {
2160
+ return;
2161
+ }
2162
+ if (event?.type === "blur") {
2163
+ this.#deactivateRotateCursor();
2164
+ } else {
2165
+ requestAnimationFrame(() => this.#deactivateRotateCursor());
2166
+ }
2167
+ };
2168
+ }
2169
+
2170
+ window.addEventListener("pointerup", this.#boundRotateCursorEnd);
2171
+ window.addEventListener("pointercancel", this.#boundRotateCursorEnd);
2172
+ window.addEventListener("blur", this.#boundRotateCursorEnd);
2173
+ }
2174
+
2175
+ #deactivateRotateCursor() {
2176
+ if (this.#rotateCursorPointerId === null) return;
2177
+ document.body.classList.remove("fig-lab-rotate-active");
2178
+ document.body.style.removeProperty("--fig-lab-cursor-rotate");
2179
+ if (this.#rotateCursorPrevBodyCursor) {
2180
+ document.body.style.setProperty(
2181
+ "cursor",
2182
+ this.#rotateCursorPrevBodyCursor,
2183
+ this.#rotateCursorPrevBodyCursorPriority,
2184
+ );
2185
+ } else {
2186
+ document.body.style.removeProperty("cursor");
2187
+ }
2188
+ this.#rotateCursorPointerId = null;
2189
+ this.#rotateCursorHandle = null;
2190
+ this.#rotateCursorPrevBodyCursor = "";
2191
+ this.#rotateCursorPrevBodyCursorPriority = "";
2192
+ if (this.#boundRotateCursorEnd) {
2193
+ window.removeEventListener("pointerup", this.#boundRotateCursorEnd);
2194
+ window.removeEventListener("pointercancel", this.#boundRotateCursorEnd);
2195
+ window.removeEventListener("blur", this.#boundRotateCursorEnd);
2196
+ }
2197
+ }
2198
+
2104
2199
  #wireHoverTooltip(target, getTooltip, getText, isDraggingRef) {
2105
2200
  if (!target) return;
2106
2201
  const shouldSuppress = () => !!isDraggingRef?.();
@@ -2401,11 +2496,27 @@ class FigCanvasControl extends HTMLElement {
2401
2496
  return `url("data:image/svg+xml,%3Csvg width='32' height='32' viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform='rotate(${r} 16 16)'%3E%3Cg filter='url(%23f)'%3E%3Cpath d='M12.5607 22.4393L12.0216 21.9002C17.1558 21.2216 21.2216 17.1558 21.9002 12.0216L22.4393 12.5607C23.0251 13.1464 23.9749 13.1464 24.5607 12.5607C25.1464 11.9749 25.1464 11.0251 24.5607 10.4393L21.5607 7.43934C20.9749 6.85355 20.0251 6.85355 19.4393 7.43934L16.4393 10.4393C15.8536 11.0251 15.8536 11.9749 16.4393 12.5607C17.0251 13.1464 17.9749 13.1464 18.5607 12.5607L18.8056 12.3157C18.1013 15.5527 15.5527 18.1013 12.3157 18.8056L12.5607 18.5607C13.1464 17.9749 13.1464 17.0251 12.5607 16.4393C11.9749 15.8536 11.0251 15.8536 10.4393 16.4393L7.43934 19.4393C6.85356 20.0251 6.85356 20.9749 7.43934 21.5607L10.4393 24.5607C11.0251 25.1464 11.9749 25.1464 12.5607 24.5607C13.1464 23.9749 13.1464 23.0251 12.5607 22.4393Z' fill='white'/%3E%3C/g%3E%3Cpath d='M23.8536 11.8536C23.6583 12.0488 23.3417 12.0488 23.1464 11.8536L21 9.70711V10.5C21 16.299 16.299 21 10.5 21H9.70711L11.8536 23.1464C12.0488 23.3417 12.0488 23.6583 11.8536 23.8536C11.6583 24.0488 11.3417 24.0488 11.1464 23.8536L8.14645 20.8536C7.95119 20.6583 7.95119 20.3417 8.14645 20.1464L11.1464 17.1464C11.3417 16.9512 11.6583 16.9512 11.8536 17.1464C12.0488 17.3417 12.0488 17.6583 11.8536 17.8536L9.70711 20H10.5C15.7467 20 20 15.7467 20 10.5V9.70711L17.8536 11.8536C17.6583 12.0488 17.3417 12.0488 17.1464 11.8536C16.9512 11.6583 16.9512 11.3417 17.1464 11.1464L20.1464 8.14645C20.3417 7.95119 20.6583 7.95119 20.8536 8.14645L23.8536 11.1464C24.0488 11.3417 24.0488 11.6583 23.8536 11.8536Z' fill='black'/%3E%3C/g%3E%3Cdefs%3E%3Cfilter id='f' x='4' y='5' width='24' height='24' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeFlood flood-opacity='0' result='a'/%3E%3CfeColorMatrix in='SourceAlpha' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='b'/%3E%3CfeOffset dy='1'/%3E%3CfeGaussianBlur stdDeviation='1.5'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.35 0'/%3E%3CfeBlend in2='a' result='c'/%3E%3CfeBlend in='SourceGraphic' in2='c'/%3E%3C/filter%3E%3C/defs%3E%3C/svg%3E") 16 16, pointer`;
2402
2497
  }
2403
2498
 
2499
+ #setHitCursor(el, cursor) {
2500
+ if (!el) return;
2501
+ // !important — fig-canvas-control hover rules override plain inline cursor.
2502
+ el.style.setProperty("cursor", cursor, "important");
2503
+ }
2504
+
2505
+ #applyRotateCursor(handle, deg) {
2506
+ if (!handle) return;
2507
+ // Rotate only on the outside hit-area ring — handle body uses normal point cursor.
2508
+ const hitArea = handle.querySelector(".fig-handle-hit-area");
2509
+ if (!hitArea) return;
2510
+ hitArea.setAttribute("data-cursor", "rotate");
2511
+ this.#setHitCursor(hitArea, this.#rotateCursorSvg(deg));
2512
+ if (this.#rotateCursorHandle === handle) {
2513
+ this.#refreshBodyRotateCursor();
2514
+ }
2515
+ }
2516
+
2404
2517
  #syncAngleCursor() {
2405
2518
  if (!this.#angleHandle || !this.#hasAngle) return;
2406
- const hitArea = this.#angleHandle.querySelector(".fig-handle-hit-area");
2407
- if (!hitArea) return;
2408
- hitArea.style.cursor = this.#rotateCursorSvg(this.#angle);
2519
+ this.#applyRotateCursor(this.#angleHandle, this.#angle);
2409
2520
  }
2410
2521
 
2411
2522
  #pointPointLineDeg() {
@@ -2415,13 +2526,11 @@ class FigCanvasControl extends HTMLElement {
2415
2526
  #syncPointPointCursors() {
2416
2527
  if (!this.#hasSecondPoint) return;
2417
2528
  const deg = this.#pointPointLineDeg();
2418
- const setHitCursor = (handle, rotateDeg) => {
2419
- if (!handle) return;
2420
- const hitArea = handle.querySelector(".fig-handle-hit-area");
2421
- if (hitArea) hitArea.style.cursor = this.#rotateCursorSvg(rotateDeg);
2422
- };
2423
- setHitCursor(this.#pointHandle, deg + 180);
2424
- setHitCursor(this.#secondHandle, deg);
2529
+ // Handle body: leave cursor to CSS (same as default point handle).
2530
+ this.#pointHandle?.style.removeProperty("cursor");
2531
+ this.#secondHandle?.style.removeProperty("cursor");
2532
+ this.#applyRotateCursor(this.#pointHandle, deg + 180);
2533
+ this.#applyRotateCursor(this.#secondHandle, deg);
2425
2534
  }
2426
2535
 
2427
2536
  #positionHandle(handle, xPct, yPct, rect) {
@@ -2795,7 +2904,7 @@ class FigCanvasControl extends HTMLElement {
2795
2904
  (Math.atan2(e.clientY - rect.top - cy, e.clientX - rect.left - cx) *
2796
2905
  180) /
2797
2906
  Math.PI;
2798
- circle.style.cursor = this.#resizeCursorSvg(deg);
2907
+ this.#setHitCursor(circle, this.#resizeCursorSvg(deg));
2799
2908
  });
2800
2909
  const onDown = (e) => {
2801
2910
  if (figLabBooleanAttribute(this, "disabled")) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "6.18.3",
3
+ "version": "6.18.4",
4
4
  "description": "A lightweight web components library for building Figma plugin and widget UIs with native look and feel",
5
5
  "author": "Rogie King",
6
6
  "license": "MIT",