@rogieking/figui3 1.3.1 → 1.3.3

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.
Files changed (4) hide show
  1. package/example.html +11 -1
  2. package/fig.css +58 -14
  3. package/fig.js +355 -39
  4. package/package.json +1 -1
package/example.html CHANGED
@@ -23,7 +23,14 @@
23
23
  <h2>UI3 Components</h2>
24
24
  </fig-header>
25
25
  <fig-content>
26
+ <fig-input-angle text="true"
27
+ value="0"
28
+ onInput="console.log(event.target.value)"></fig-input-angle>
29
+ <br /><br />
30
+ <fig-input-joystick></fig-input-joystick>
31
+ <br /><br />
26
32
  <fig-input-joystick text="true"
33
+ value="0,0"
27
34
  onInput="console.log(event.target.value)"></fig-input-joystick>
28
35
  <fig-header>
29
36
  <h2>Details</h2>
@@ -444,8 +451,11 @@
444
451
  </fig-header>
445
452
  <fig-field>
446
453
  <label>Switches</label>
447
- <fig-switch on="true"
454
+ <fig-switch checked="true"
455
+ onInput="console.log(event.target.checked)"
448
456
  label="On"></fig-switch>
457
+ <fig-switch checked="false"
458
+ label="Off"></fig-switch>
449
459
  <fig-switch indeterminate="true"
450
460
  label="Indeterminate"></fig-switch>
451
461
  <fig-switch disabled
package/fig.css CHANGED
@@ -2263,18 +2263,6 @@ fig-segmented-control {
2263
2263
  }
2264
2264
  }
2265
2265
 
2266
- /* Utilities */
2267
-
2268
- @keyframes fig-spinner-spin {
2269
- from {
2270
- transform: rotate(0deg);
2271
- }
2272
-
2273
- to {
2274
- transform: rotate(360deg);
2275
- }
2276
- }
2277
-
2278
2266
  fig-input-joystick {
2279
2267
  --size: 1.5rem;
2280
2268
  display: inline-flex;
@@ -2284,6 +2272,10 @@ fig-input-joystick {
2284
2272
  width: 1.5rem;
2285
2273
  height: 1.5rem;
2286
2274
  place-items: center;
2275
+ flex-shrink: 0;
2276
+ flex-grow: 0;
2277
+ align-items: center;
2278
+ justify-content: center;
2287
2279
  }
2288
2280
  .fig-input-joystick-plane {
2289
2281
  display: inline-grid;
@@ -2292,9 +2284,10 @@ fig-input-joystick {
2292
2284
  width: var(--size);
2293
2285
  height: var(--size);
2294
2286
  flex-shrink: 0;
2295
- &:hover {
2287
+ &.dragging {
2296
2288
  cursor: grab;
2297
2289
  --size: 3rem;
2290
+ z-index: 2;
2298
2291
  }
2299
2292
  }
2300
2293
  .fig-input-joystick-plane > * {
@@ -2330,7 +2323,7 @@ fig-input-joystick {
2330
2323
  pointer-events: none;
2331
2324
  }
2332
2325
  }
2333
- .fig-input-joystick-plane:hover .fig-input-joystick-guides {
2326
+ .fig-input-joystick-plane.dragging .fig-input-joystick-guides {
2334
2327
  background: linear-gradient(
2335
2328
  45deg,
2336
2329
  transparent calc(50% - 0.5px),
@@ -2358,3 +2351,54 @@ fig-input-joystick {
2358
2351
  transform: translate(-50%, -50%);
2359
2352
  }
2360
2353
  }
2354
+
2355
+ fig-input-angle {
2356
+ --size: 1.5rem;
2357
+ display: inline-flex;
2358
+ gap: var(--spacer-2);
2359
+
2360
+ .fig-input-angle-plane {
2361
+ display: inline-grid;
2362
+ place-items: center;
2363
+ width: var(--size);
2364
+ height: var(--size);
2365
+ aspect-ratio: 1/1;
2366
+ flex-shrink: 0;
2367
+ background-color: var(--figma-color-bg-secondary);
2368
+ border-radius: 100%;
2369
+ box-shadow: inset 0 0 0 1px var(--figma-color-border);
2370
+ &.dragging {
2371
+ cursor: grab;
2372
+ --size: 3rem;
2373
+ z-index: 2;
2374
+ }
2375
+ }
2376
+ .fig-input-angle-handle {
2377
+ display: inline-grid;
2378
+ place-items: center;
2379
+ grid-area: 1/1;
2380
+ width: calc(0.5rem + 2px);
2381
+ height: calc(0.5rem + 2px);
2382
+ &:before {
2383
+ content: "";
2384
+ display: block;
2385
+ width: 0.5rem;
2386
+ height: 0.5rem;
2387
+ background: var(--figma-color-icon-onbrand);
2388
+ box-shadow: var(--handle-shadow);
2389
+ border-radius: 50%;
2390
+ }
2391
+ }
2392
+ }
2393
+
2394
+ /* Utilities */
2395
+
2396
+ @keyframes fig-spinner-spin {
2397
+ from {
2398
+ transform: rotate(0deg);
2399
+ }
2400
+
2401
+ to {
2402
+ transform: rotate(360deg);
2403
+ }
2404
+ }
package/fig.js CHANGED
@@ -1671,6 +1671,7 @@ class FigImage extends HTMLElement {
1671
1671
  this.innerHTML = this.#getInnerHTML();
1672
1672
  this.#updateRefs();
1673
1673
  }
1674
+
1674
1675
  #updateRefs() {
1675
1676
  requestAnimationFrame(() => {
1676
1677
  this.chit = this.querySelector("fig-chit");
@@ -1712,6 +1713,13 @@ class FigImage extends HTMLElement {
1712
1713
  }
1713
1714
  window.customElements.define("fig-image", FigImage);
1714
1715
 
1716
+ /**
1717
+ * A custom joystick input element.
1718
+ * @attr {string} value - The current position of the joystick (e.g., "0.5,0.5").
1719
+ * @attr {number} precision - The number of decimal places for the output.
1720
+ * @attr {number} transform - A scaling factor for the output.
1721
+ * @attr {boolean} text - Whether to display text inputs for X and Y values.
1722
+ */
1715
1723
  class FigInputJoystick extends HTMLElement {
1716
1724
  constructor() {
1717
1725
  super();
@@ -1720,6 +1728,10 @@ class FigInputJoystick extends HTMLElement {
1720
1728
  this.value = [0.5, 0.5];
1721
1729
  this.isDragging = false;
1722
1730
  this.isShiftHeld = false;
1731
+ this.plane = null;
1732
+ this.cursor = null;
1733
+ this.xInput = null;
1734
+ this.yInput = null;
1723
1735
 
1724
1736
  // Initialize position
1725
1737
  requestAnimationFrame(() => {
@@ -1729,21 +1741,32 @@ class FigInputJoystick extends HTMLElement {
1729
1741
  this.transform = Number(this.transform);
1730
1742
  this.text = this.getAttribute("text") === "true";
1731
1743
 
1732
- this.render();
1744
+ this.#render();
1733
1745
 
1734
- this.setupListeners();
1746
+ this.#setupListeners();
1735
1747
 
1736
- this.cursor.style.left = `${this.position.x * 100}%`;
1737
- this.cursor.style.top = `${this.position.y * 100}%`;
1738
- if (this.text) {
1739
- this.xInput.value = this.position.x.toFixed(this.precision);
1740
- this.yInput.value = this.position.y.toFixed(this.precision);
1748
+ this.#syncHandlePosition();
1749
+ if (this.text && this.xInput && this.yInput) {
1750
+ this.xInput.setAttribute(
1751
+ "value",
1752
+ this.position.x.toFixed(this.precision)
1753
+ );
1754
+ this.yInput.setAttribute(
1755
+ "value",
1756
+ this.position.y.toFixed(this.precision)
1757
+ );
1741
1758
  }
1742
1759
  });
1743
1760
  }
1761
+ disconnectedCallback() {
1762
+ this.#cleanupListeners();
1763
+ }
1744
1764
 
1745
- render() {
1746
- this.innerHTML = `
1765
+ #render() {
1766
+ this.innerHTML = this.#getInnerHTML();
1767
+ }
1768
+ #getInnerHTML() {
1769
+ return `
1747
1770
  <div class="fig-input-joystick-plane-container">
1748
1771
  <div class="fig-input-joystick-plane">
1749
1772
  <div class="fig-input-joystick-guides"></div>
@@ -1775,41 +1798,49 @@ class FigInputJoystick extends HTMLElement {
1775
1798
  `;
1776
1799
  }
1777
1800
 
1778
- setupListeners() {
1801
+ #setupListeners() {
1779
1802
  this.plane = this.querySelector(".fig-input-joystick-plane");
1780
1803
  this.cursor = this.querySelector(".fig-input-joystick-handle");
1781
- if (this.text) {
1782
- this.xInput = this.querySelector("fig-input-text[name='x']");
1783
- this.yInput = this.querySelector("fig-input-text[name='y']");
1804
+ this.plane.addEventListener("mousedown", this.#handleMouseDown.bind(this));
1805
+ this.plane.addEventListener(
1806
+ "touchstart",
1807
+ this.#handleTouchStart.bind(this)
1808
+ );
1809
+ window.addEventListener("keydown", this.#handleKeyDown.bind(this));
1810
+ window.addEventListener("keyup", this.#handleKeyUp.bind(this));
1811
+ if (this.text && this.xInput && this.yInput) {
1812
+ this.xInput.addEventListener("input", this.#handleXInput.bind(this));
1813
+ this.yInput.addEventListener("input", this.#handleYInput.bind(this));
1784
1814
  }
1815
+ }
1785
1816
 
1786
- this.plane.addEventListener("mousedown", this.handleMouseDown.bind(this));
1787
- window.addEventListener("keydown", this.handleKeyDown.bind(this));
1788
- window.addEventListener("keyup", this.handleKeyUp.bind(this));
1789
-
1790
- this.xInput.addEventListener("input", this.handleXInput.bind(this));
1791
- this.yInput.addEventListener("input", this.handleYInput.bind(this));
1817
+ #cleanupListeners() {
1818
+ this.plane.removeEventListener("mousedown", this.#handleMouseDown);
1819
+ window.removeEventListener("keydown", this.#handleKeyDown);
1820
+ window.removeEventListener("keyup", this.#handleKeyUp);
1821
+ if (this.text && this.xInput && this.yInput) {
1822
+ this.xInput.removeEventListener("input", this.#handleXInput);
1823
+ this.yInput.removeEventListener("input", this.#handleYInput);
1824
+ }
1792
1825
  }
1793
1826
 
1794
- handleXInput(e) {
1827
+ #handleXInput(e) {
1795
1828
  e.stopPropagation();
1796
1829
  this.position.x = Number(e.target.value);
1797
- this.value = [this.position.x, this.position.y];
1798
1830
  this.#syncHandlePosition();
1799
1831
  this.#emitInputEvent();
1800
1832
  this.#emitChangeEvent();
1801
1833
  }
1802
1834
 
1803
- handleYInput(e) {
1835
+ #handleYInput(e) {
1804
1836
  e.stopPropagation();
1805
1837
  this.position.y = Number(e.target.value);
1806
- this.value = [this.position.x, this.position.y];
1807
1838
  this.#syncHandlePosition();
1808
1839
  this.#emitInputEvent();
1809
1840
  this.#emitChangeEvent();
1810
1841
  }
1811
1842
 
1812
- snapToGuide(value) {
1843
+ #snapToGuide(value) {
1813
1844
  if (!this.isShiftHeld) return value;
1814
1845
  if (value < 0.1) return 0;
1815
1846
  if (value > 0.9) return 1;
@@ -1817,7 +1848,7 @@ class FigInputJoystick extends HTMLElement {
1817
1848
  return value;
1818
1849
  }
1819
1850
 
1820
- snapToDiagonal(x, y) {
1851
+ #snapToDiagonal(x, y) {
1821
1852
  if (!this.isShiftHeld) return { x, y };
1822
1853
  const diff = Math.abs(x - y);
1823
1854
  if (diff < 0.1) return { x: (x + y) / 2, y: (x + y) / 2 };
@@ -1830,25 +1861,22 @@ class FigInputJoystick extends HTMLElement {
1830
1861
  let x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
1831
1862
  let y = Math.max(0, Math.min(1, (e.clientY - rect.top) / rect.height));
1832
1863
 
1833
- // Invert Y coordinate to match typical coordinate system
1834
- y = 1 - y;
1835
-
1836
- x = this.snapToGuide(x);
1837
- y = this.snapToGuide(y);
1864
+ x = this.#snapToGuide(x);
1865
+ y = this.#snapToGuide(y);
1838
1866
 
1839
- const snapped = this.snapToDiagonal(x, y);
1867
+ const snapped = this.#snapToDiagonal(x, y);
1840
1868
  this.position = snapped;
1841
- this.value = [snapped.x, snapped.y];
1842
1869
 
1843
1870
  this.cursor.style.left = `${snapped.x * 100}%`;
1844
- this.cursor.style.top = `${(1 - snapped.y) * 100}%`; // Invert Y for display
1845
- if (this.text) {
1871
+ this.cursor.style.top = `${snapped.y * 100}%`; // Invert Y for display
1872
+ if (this.text && this.xInput && this.yInput) {
1846
1873
  this.xInput.setAttribute("value", snapped.x.toFixed(3));
1847
1874
  this.yInput.setAttribute("value", snapped.y.toFixed(3));
1848
1875
  }
1849
1876
 
1850
1877
  this.#emitInputEvent();
1851
1878
  }
1879
+
1852
1880
  #emitInputEvent() {
1853
1881
  this.dispatchEvent(
1854
1882
  new CustomEvent("input", {
@@ -1868,22 +1896,27 @@ class FigInputJoystick extends HTMLElement {
1868
1896
  }
1869
1897
 
1870
1898
  #syncHandlePosition() {
1871
- this.cursor.style.left = `${this.position.x * 100}%`;
1872
- this.cursor.style.top = `${(1 - this.position.y) * 100}%`;
1899
+ if (this.cursor) {
1900
+ this.cursor.style.left = `${this.position.x * 100}%`;
1901
+ this.cursor.style.top = `${this.position.y * 100}%`;
1902
+ }
1873
1903
  }
1874
1904
 
1875
- handleMouseDown(e) {
1905
+ #handleMouseDown(e) {
1876
1906
  this.isDragging = true;
1907
+
1877
1908
  this.#updatePosition(e);
1878
1909
 
1879
1910
  this.plane.style.cursor = "grabbing";
1880
1911
 
1881
1912
  const handleMouseMove = (e) => {
1913
+ this.plane.classList.add("dragging");
1882
1914
  if (this.isDragging) this.#updatePosition(e);
1883
1915
  };
1884
1916
 
1885
1917
  const handleMouseUp = () => {
1886
1918
  this.isDragging = false;
1919
+ this.plane.classList.remove("dragging");
1887
1920
  this.plane.style.cursor = "";
1888
1921
  window.removeEventListener("mousemove", handleMouseMove);
1889
1922
  window.removeEventListener("mouseup", handleMouseUp);
@@ -1894,13 +1927,296 @@ class FigInputJoystick extends HTMLElement {
1894
1927
  window.addEventListener("mouseup", handleMouseUp);
1895
1928
  }
1896
1929
 
1897
- handleKeyDown(e) {
1930
+ #handleTouchStart(e) {
1931
+ e.preventDefault();
1932
+ this.isDragging = true;
1933
+ this.#updatePosition(e.touches[0]);
1934
+
1935
+ const handleTouchMove = (e) => {
1936
+ if (this.isDragging) this.#updatePosition(e.touches[0]);
1937
+ };
1938
+
1939
+ const handleTouchEnd = () => {
1940
+ this.isDragging = false;
1941
+ window.removeEventListener("touchmove", handleTouchMove);
1942
+ window.removeEventListener("touchend", handleTouchEnd);
1943
+ this.#emitChangeEvent();
1944
+ };
1945
+
1946
+ window.addEventListener("touchmove", handleTouchMove);
1947
+ window.addEventListener("touchend", handleTouchEnd);
1948
+ }
1949
+
1950
+ #handleKeyDown(e) {
1898
1951
  if (e.key === "Shift") this.isShiftHeld = true;
1899
1952
  }
1900
1953
 
1901
- handleKeyUp(e) {
1954
+ #handleKeyUp(e) {
1902
1955
  if (e.key === "Shift") this.isShiftHeld = false;
1903
1956
  }
1957
+ static get observedAttributes() {
1958
+ return ["value", "precision", "transform", "text"];
1959
+ }
1960
+ get value() {
1961
+ return [this.position.x, this.position.y];
1962
+ }
1963
+ set value(value) {
1964
+ let v = value.toString().split(",").map(Number);
1965
+ this.position = { x: v[0], y: v[1] };
1966
+ this.#syncHandlePosition();
1967
+ }
1968
+ attributeChangedCallback(name, oldValue, newValue) {
1969
+ if (name === "value") {
1970
+ this.value = newValue;
1971
+ }
1972
+ if (name === "precision") {
1973
+ this.precision = parseInt(newValue);
1974
+ }
1975
+ if (name === "transform") {
1976
+ this.transform = Number(newValue);
1977
+ }
1978
+ if (name === "text" && newValue !== oldValue) {
1979
+ this.text = newValue.toLowerCase() === "true";
1980
+ this.#render();
1981
+ }
1982
+ }
1904
1983
  }
1905
1984
 
1906
1985
  customElements.define("fig-input-joystick", FigInputJoystick);
1986
+
1987
+ /**
1988
+ * A custom angle chooser input element.
1989
+ * @attr {number} value - The current angle of the handle in degrees.
1990
+ * @attr {number} precision - The number of decimal places for the output.
1991
+ * @attr {boolean} text - Whether to display a text input for the angle value.
1992
+ */
1993
+ class FigInputAngle extends HTMLElement {
1994
+ constructor() {
1995
+ super();
1996
+
1997
+ this.angle = 0; // Angle in degrees
1998
+ this.isDragging = false;
1999
+ this.isShiftHeld = false;
2000
+ this.handle = null;
2001
+ this.angleInput = null;
2002
+ this.plane = null;
2003
+
2004
+ // Initialize position
2005
+ requestAnimationFrame(() => {
2006
+ this.precision = this.getAttribute("precision") || 1;
2007
+ this.precision = parseInt(this.precision);
2008
+ this.text = this.getAttribute("text") === "true";
2009
+
2010
+ this.#render();
2011
+
2012
+ this.#setupListeners();
2013
+
2014
+ this.#syncHandlePosition();
2015
+ if (this.text && this.angleInput) {
2016
+ this.angleInput.setAttribute(
2017
+ "value",
2018
+ this.angle.toFixed(this.precision)
2019
+ );
2020
+ }
2021
+ });
2022
+ }
2023
+
2024
+ disconnectedCallback() {
2025
+ this.#cleanupListeners();
2026
+ }
2027
+
2028
+ #render() {
2029
+ this.innerHTML = this.#getInnerHTML();
2030
+ }
2031
+
2032
+ #getInnerHTML() {
2033
+ return `
2034
+ <div class="fig-input-angle-plane">
2035
+ <div class="fig-input-angle-handle"></div>
2036
+ </div>
2037
+ ${
2038
+ this.text
2039
+ ? `<fig-input-text
2040
+ type="number"
2041
+ name="angle"
2042
+ step="0.1"
2043
+ value="${this.angle}"
2044
+ min="0"
2045
+ max="360">
2046
+ <span slot="append">°</span>
2047
+ </fig-input-text>`
2048
+ : ""
2049
+ }
2050
+ `;
2051
+ }
2052
+
2053
+ #setupListeners() {
2054
+ this.handle = this.querySelector(".fig-input-angle-handle");
2055
+ this.plane = this.querySelector(".fig-input-angle-plane");
2056
+ this.angleInput = this.querySelector("fig-input-text[name='angle']");
2057
+ this.plane.addEventListener("mousedown", this.#handleMouseDown.bind(this));
2058
+ this.plane.addEventListener(
2059
+ "touchstart",
2060
+ this.#handleTouchStart.bind(this)
2061
+ );
2062
+ window.addEventListener("keydown", this.#handleKeyDown.bind(this));
2063
+ window.addEventListener("keyup", this.#handleKeyUp.bind(this));
2064
+ if (this.text && this.angleInput) {
2065
+ this.angleInput = this.querySelector("fig-input-text");
2066
+ this.angleInput.addEventListener(
2067
+ "input",
2068
+ this.#handleAngleInput.bind(this)
2069
+ );
2070
+ }
2071
+ }
2072
+
2073
+ #cleanupListeners() {
2074
+ this.plane.removeEventListener("mousedown", this.#handleMouseDown);
2075
+ this.plane.removeEventListener("touchstart", this.#handleTouchStart);
2076
+ window.removeEventListener("keydown", this.#handleKeyDown);
2077
+ window.removeEventListener("keyup", this.#handleKeyUp);
2078
+ if (this.text && this.angleInput) {
2079
+ this.angleInput.removeEventListener("input", this.#handleAngleInput);
2080
+ }
2081
+ }
2082
+
2083
+ #handleAngleInput(e) {
2084
+ e.stopPropagation();
2085
+ this.angle = Number(e.target.value);
2086
+ this.#syncHandlePosition();
2087
+ this.#emitInputEvent();
2088
+ this.#emitChangeEvent();
2089
+ }
2090
+
2091
+ #snapToIncrement(angle) {
2092
+ if (!this.isShiftHeld) return angle;
2093
+ const increment = 45;
2094
+ return Math.round(angle / increment) * increment;
2095
+ }
2096
+
2097
+ #updateAngle(e) {
2098
+ const rect = this.plane.getBoundingClientRect();
2099
+ const centerX = rect.left + rect.width / 2;
2100
+ const centerY = rect.top + rect.height / 2;
2101
+ const deltaX = e.clientX - centerX;
2102
+ const deltaY = e.clientY - centerY;
2103
+ let angle = ((Math.atan2(deltaY, deltaX) * 180) / Math.PI + 360) % 360;
2104
+
2105
+ angle = this.#snapToIncrement(angle);
2106
+ this.angle = angle;
2107
+
2108
+ this.#syncHandlePosition();
2109
+ if (this.text && this.angleInput) {
2110
+ this.angleInput.setAttribute("value", this.angle.toFixed(this.precision));
2111
+ }
2112
+
2113
+ this.#emitInputEvent();
2114
+ }
2115
+
2116
+ #emitInputEvent() {
2117
+ this.dispatchEvent(
2118
+ new CustomEvent("input", {
2119
+ bubbles: true,
2120
+ cancelable: true,
2121
+ })
2122
+ );
2123
+ }
2124
+
2125
+ #emitChangeEvent() {
2126
+ this.dispatchEvent(
2127
+ new CustomEvent("change", {
2128
+ bubbles: true,
2129
+ cancelable: true,
2130
+ })
2131
+ );
2132
+ }
2133
+
2134
+ #syncHandlePosition() {
2135
+ if (this.handle) {
2136
+ const radians = (this.angle * Math.PI) / 180;
2137
+ const radius = this.plane.offsetWidth / 2 - this.handle.offsetWidth / 2;
2138
+ const x = Math.cos(radians) * radius;
2139
+ const y = Math.sin(radians) * radius;
2140
+ this.handle.style.transform = `translate(${x}px, ${y}px)`;
2141
+ }
2142
+ }
2143
+
2144
+ #handleMouseDown(e) {
2145
+ this.isDragging = true;
2146
+ this.#updateAngle(e);
2147
+
2148
+ const handleMouseMove = (e) => {
2149
+ if (this.isDragging) this.#updateAngle(e);
2150
+ };
2151
+
2152
+ const handleMouseUp = () => {
2153
+ this.isDragging = false;
2154
+ window.removeEventListener("mousemove", handleMouseMove);
2155
+ window.removeEventListener("mouseup", handleMouseUp);
2156
+ this.#emitChangeEvent();
2157
+ };
2158
+
2159
+ window.addEventListener("mousemove", handleMouseMove);
2160
+ window.addEventListener("mouseup", handleMouseUp);
2161
+ }
2162
+
2163
+ #handleTouchStart(e) {
2164
+ e.preventDefault();
2165
+ this.isDragging = true;
2166
+ this.#updateAngle(e.touches[0]);
2167
+
2168
+ const handleTouchMove = (e) => {
2169
+ if (this.isDragging) this.#updateAngle(e.touches[0]);
2170
+ };
2171
+
2172
+ const handleTouchEnd = () => {
2173
+ this.isDragging = false;
2174
+ window.removeEventListener("touchmove", handleTouchMove);
2175
+ window.removeEventListener("touchend", handleTouchEnd);
2176
+ this.#emitChangeEvent();
2177
+ };
2178
+
2179
+ window.addEventListener("touchmove", handleTouchMove);
2180
+ window.addEventListener("touchend", handleTouchEnd);
2181
+ }
2182
+
2183
+ #handleKeyDown(e) {
2184
+ if (e.key === "Shift") this.isShiftHeld = true;
2185
+ }
2186
+
2187
+ #handleKeyUp(e) {
2188
+ if (e.key === "Shift") this.isShiftHeld = false;
2189
+ }
2190
+
2191
+ static get observedAttributes() {
2192
+ return ["value", "precision", "text"];
2193
+ }
2194
+
2195
+ get value() {
2196
+ return this.angle;
2197
+ }
2198
+
2199
+ set value(value) {
2200
+ if (isNaN(value)) {
2201
+ console.error("Invalid value: must be a number.");
2202
+ return;
2203
+ }
2204
+ this.angle = value;
2205
+ this.#syncHandlePosition();
2206
+ }
2207
+
2208
+ attributeChangedCallback(name, oldValue, newValue) {
2209
+ if (name === "value") {
2210
+ this.value = Number(newValue);
2211
+ }
2212
+ if (name === "precision") {
2213
+ this.precision = parseInt(newValue);
2214
+ }
2215
+ if (name === "text" && newValue !== oldValue) {
2216
+ this.text = newValue.toLowerCase() === "true";
2217
+ this.#render();
2218
+ }
2219
+ }
2220
+ }
2221
+
2222
+ customElements.define("fig-input-angle", FigInputAngle);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "devDependencies": {