@rogieking/figui3 1.7.7 → 1.7.9

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/components.css CHANGED
@@ -771,6 +771,17 @@ fig-button {
771
771
  color: var(--figma-color-text);
772
772
  }
773
773
 
774
+ /* Variant: Overlay (for on top of content) */
775
+ &[variant="overlay"] {
776
+ background-color: var(--figma-color-bg);
777
+ color: var(--figma-color-text);
778
+ box-shadow: 0 0 0 1px var(--figma-color-bordertranslucent);
779
+
780
+ &:active {
781
+ background-color: var(--figma-color-bg-secondary);
782
+ }
783
+ }
784
+
774
785
  /* Icon only */
775
786
  &[icon] {
776
787
  width: var(--spacer-4);
@@ -1230,10 +1241,6 @@ fig-image {
1230
1241
  fig-chit {
1231
1242
  --size: var(--image-size) !important;
1232
1243
  }
1233
- fig-button {
1234
- opacity: 0;
1235
- pointer-events: none;
1236
- }
1237
1244
  &:not([src]):not([src=""]) fig-button,
1238
1245
  &:hover fig-button {
1239
1246
  opacity: 1;
@@ -1255,6 +1262,25 @@ fig-image {
1255
1262
  aspect-ratio: var(--aspect-ratio) !important;
1256
1263
  }
1257
1264
  }
1265
+ > div {
1266
+ display: flex;
1267
+ gap: var(--spacer-2);
1268
+ opacity: 0;
1269
+ pointer-events: none;
1270
+ }
1271
+ &:not([src]):not([src=""]) > div,
1272
+ &:hover > div {
1273
+ opacity: 1;
1274
+ pointer-events: all;
1275
+ }
1276
+ fig-button[type="download"] {
1277
+ display: none;
1278
+ }
1279
+ &[src]:not([src=""]) {
1280
+ fig-button[type="download"] {
1281
+ display: inline-flex;
1282
+ }
1283
+ }
1258
1284
  }
1259
1285
 
1260
1286
  /* Combo input */
package/example.html CHANGED
@@ -280,6 +280,7 @@
280
280
  <fig-field>
281
281
  <label>Large (with upload)</label>
282
282
  <fig-image upload="true"
283
+ download="true"
283
284
  label="Upload image"
284
285
  size="large"></fig-image>
285
286
  </fig-field>
package/fig.js CHANGED
@@ -220,6 +220,8 @@ customElements.define("fig-dropdown", FigDropdown);
220
220
  class FigTooltip extends HTMLElement {
221
221
  #boundHideOnChromeOpen;
222
222
  #boundHideOnDragStart;
223
+ #touchTimeout;
224
+ #isTouching = false;
223
225
  constructor() {
224
226
  super();
225
227
  this.action = this.getAttribute("action") || "hover";
@@ -245,6 +247,15 @@ class FigTooltip extends HTMLElement {
245
247
  );
246
248
  // Remove mousedown listener
247
249
  this.removeEventListener("mousedown", this.#boundHideOnDragStart);
250
+
251
+ // Clean up touch-related timers and listeners
252
+ clearTimeout(this.#touchTimeout);
253
+ if (this.action === "hover") {
254
+ this.removeEventListener("touchstart", this.#handleTouchStart);
255
+ this.removeEventListener("touchend", this.#handleTouchEnd);
256
+ } else if (this.action === "click") {
257
+ this.removeEventListener("touchstart", this.showDelayedPopup);
258
+ }
248
259
  }
249
260
 
250
261
  setup() {
@@ -286,12 +297,25 @@ class FigTooltip extends HTMLElement {
286
297
  this.addEventListener("pointerleave", this.hidePopup.bind(this));
287
298
  // Add mousedown listener instead of dragstart
288
299
  this.addEventListener("mousedown", this.#boundHideOnDragStart);
300
+
301
+ // Touch support for mobile hover simulation
302
+ this.addEventListener("touchstart", this.#handleTouchStart.bind(this), {
303
+ passive: true,
304
+ });
305
+ this.addEventListener("touchend", this.#handleTouchEnd.bind(this), {
306
+ passive: true,
307
+ });
289
308
  } else if (this.action === "click") {
290
309
  this.addEventListener("click", this.showDelayedPopup.bind(this));
291
310
  document.body.addEventListener(
292
311
  "click",
293
312
  this.hidePopupOutsideClick.bind(this)
294
313
  );
314
+
315
+ // Touch support for better mobile responsiveness
316
+ this.addEventListener("touchstart", this.showDelayedPopup.bind(this), {
317
+ passive: true,
318
+ });
295
319
  }
296
320
 
297
321
  // Add listener for chrome interactions
@@ -352,6 +376,7 @@ class FigTooltip extends HTMLElement {
352
376
 
353
377
  hidePopup() {
354
378
  clearTimeout(this.timeout);
379
+ clearTimeout(this.#touchTimeout);
355
380
  this.popup.style.opacity = "0";
356
381
  this.popup.style.display = "block";
357
382
  this.popup.style.pointerEvents = "none";
@@ -364,6 +389,27 @@ class FigTooltip extends HTMLElement {
364
389
  this.hidePopup();
365
390
  }
366
391
  }
392
+
393
+ // Touch event handlers for mobile support
394
+ #handleTouchStart(event) {
395
+ if (this.action === "hover") {
396
+ this.#isTouching = true;
397
+ // Show popup on touch start for hover action
398
+ this.showDelayedPopup();
399
+ }
400
+ }
401
+
402
+ #handleTouchEnd(event) {
403
+ if (this.action === "hover" && this.#isTouching) {
404
+ this.#isTouching = false;
405
+ // Hide popup after a short delay to allow for taps
406
+ clearTimeout(this.#touchTimeout);
407
+ this.#touchTimeout = setTimeout(() => {
408
+ this.hidePopup();
409
+ }, 100);
410
+ }
411
+ }
412
+
367
413
  static get observedAttributes() {
368
414
  return ["action", "delay", "open"];
369
415
  }
@@ -1836,22 +1882,29 @@ class FigImage extends HTMLElement {
1836
1882
  #getInnerHTML() {
1837
1883
  return `<fig-chit type="image" size="large" ${
1838
1884
  this.src ? `src="${this.src}"` : ""
1839
- } disabled="true"></fig-chit>${
1885
+ } disabled="true"></fig-chit><div>${
1840
1886
  this.upload
1841
- ? `<fig-button variant="primary" type="upload">
1887
+ ? `<fig-button variant="overlay" type="upload">
1842
1888
  ${this.label}
1843
1889
  <input type="file" accept="image/*" />
1844
1890
  </fig-button>`
1845
1891
  : ""
1846
- }`;
1892
+ } ${
1893
+ this.download
1894
+ ? `<fig-button variant="overlay" icon="true" type="download">
1895
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1896
+ <path d="M17.5 13C17.7761 13 18 13.2239 18 13.5V16.5C18 17.3284 17.3284 18 16.5 18H7.5C6.67157 18 6 17.3284 6 16.5V13.5C6 13.2239 6.22386 13 6.5 13C6.77614 13 7 13.2239 7 13.5V16.5C7 16.7761 7.22386 17 7.5 17H16.5C16.7761 17 17 16.7761 17 16.5V13.5C17 13.2239 17.2239 13 17.5 13ZM12 6C12.2761 6 12.5 6.22386 12.5 6.5V12.293L14.6465 10.1465C14.8417 9.95122 15.1583 9.95122 15.3535 10.1465C15.5488 10.3417 15.5488 10.6583 15.3535 10.8535L12.3535 13.8535C12.2597 13.9473 12.1326 14 12 14C11.9006 14 11.8042 13.9704 11.7227 13.916L11.6465 13.8535L8.64648 10.8535C8.45122 10.6583 8.45122 10.3417 8.64648 10.1465C8.84175 9.95122 9.15825 9.95122 9.35352 10.1465L11.5 12.293V6.5C11.5 6.22386 11.7239 6 12 6Z" fill="black"/>
1897
+ </svg></fig-button>`
1898
+ : ""
1899
+ }</div>`;
1847
1900
  }
1848
1901
  connectedCallback() {
1849
1902
  this.src = this.getAttribute("src") || "";
1850
1903
  this.upload = this.getAttribute("upload") === "true";
1904
+ this.download = this.getAttribute("download") === "true";
1851
1905
  this.label = this.getAttribute("label") || "Upload";
1852
1906
  this.size = this.getAttribute("size") || "small";
1853
1907
  this.innerHTML = this.#getInnerHTML();
1854
- this.#updateRefs();
1855
1908
  }
1856
1909
  disconnectedCallback() {
1857
1910
  this.fileInput.removeEventListener(
@@ -1864,16 +1917,38 @@ class FigImage extends HTMLElement {
1864
1917
  requestAnimationFrame(() => {
1865
1918
  this.chit = this.querySelector("fig-chit");
1866
1919
  if (this.upload) {
1867
- this.uploadButton = this.querySelector("fig-button");
1920
+ this.uploadButton = this.querySelector("fig-button[type='upload']");
1868
1921
  this.fileInput = this.uploadButton?.querySelector("input");
1869
-
1922
+ this.fileInput.removeEventListener(
1923
+ "change",
1924
+ this.#handleFileInput.bind(this)
1925
+ );
1870
1926
  this.fileInput.addEventListener(
1871
1927
  "change",
1872
1928
  this.#handleFileInput.bind(this)
1873
1929
  );
1874
1930
  }
1931
+ if (this.download) {
1932
+ console.log("binding download");
1933
+ this.downloadButton = this.querySelector("fig-button[type='download']");
1934
+ this.downloadButton.removeEventListener(
1935
+ "click",
1936
+ this.#handleDownload.bind(this)
1937
+ );
1938
+ this.downloadButton.addEventListener(
1939
+ "click",
1940
+ this.#handleDownload.bind(this)
1941
+ );
1942
+ }
1875
1943
  });
1876
1944
  }
1945
+ #handleDownload() {
1946
+ //force blob download
1947
+ const link = document.createElement("a");
1948
+ link.href = this.blob;
1949
+ link.download = "image.png";
1950
+ link.click();
1951
+ }
1877
1952
  async #loadImage(src) {
1878
1953
  // Get blob from canvas
1879
1954
  await new Promise((resolve) => {
@@ -1967,8 +2042,9 @@ class FigImage extends HTMLElement {
1967
2042
  this.#loadImage(this.#src);
1968
2043
  }
1969
2044
  }
1970
- if (name === "upload") {
2045
+ if (name === "upload" || name === "download") {
1971
2046
  this.upload = newValue.toLowerCase() === "true";
2047
+ this.download = newValue.toLowerCase() === "true";
1972
2048
  this.innerHTML = this.#getInnerHTML();
1973
2049
  this.#updateRefs();
1974
2050
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "1.7.7",
3
+ "version": "1.7.9",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "devDependencies": {