@rogieking/figui3 3.23.0 → 4.0.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 +3 -4
- package/components.css +6 -21
- package/fig.js +200 -193
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1001,10 +1001,9 @@ An image display component with optional upload, aspect ratio, and object-fit co
|
|
|
1001
1001
|
| Attribute | Type | Default | Description |
|
|
1002
1002
|
|---|---|---|---|
|
|
1003
1003
|
| `src` | string | — | Image URL |
|
|
1004
|
-
| `upload` | boolean | `false` | Show upload
|
|
1005
|
-
| `
|
|
1006
|
-
| `
|
|
1007
|
-
| `aspect-ratio` | string | — | CSS aspect-ratio (e.g. `"16 / 9"`) |
|
|
1004
|
+
| `upload` | boolean | `false` | Show upload overlay (`fig-input-file`) |
|
|
1005
|
+
| `label` | string | `"Upload"` | Upload button label |
|
|
1006
|
+
| `aspect-ratio` | string | — | CSS aspect-ratio, or `"auto"` for lazy dimension detection |
|
|
1008
1007
|
| `fit` | string | — | CSS object-fit (`"cover"`, `"contain"`, etc.) |
|
|
1009
1008
|
| `checkerboard` | boolean | `false` | Show checkerboard behind transparent images |
|
|
1010
1009
|
|
package/components.css
CHANGED
|
@@ -1395,8 +1395,12 @@ fig-image {
|
|
|
1395
1395
|
opacity: 1;
|
|
1396
1396
|
}
|
|
1397
1397
|
}
|
|
1398
|
-
|
|
1399
|
-
|
|
1398
|
+
> fig-input-file[data-generated] {
|
|
1399
|
+
opacity: 0;
|
|
1400
|
+
pointer-events: none;
|
|
1401
|
+
}
|
|
1402
|
+
&:not([src]):not([src=""]) > fig-input-file[data-generated],
|
|
1403
|
+
&:hover > fig-input-file[data-generated] {
|
|
1400
1404
|
opacity: 1;
|
|
1401
1405
|
pointer-events: all;
|
|
1402
1406
|
}
|
|
@@ -1420,25 +1424,6 @@ fig-image {
|
|
|
1420
1424
|
aspect-ratio: var(--aspect-ratio) !important;
|
|
1421
1425
|
}
|
|
1422
1426
|
}
|
|
1423
|
-
> div {
|
|
1424
|
-
display: flex;
|
|
1425
|
-
gap: var(--spacer-2);
|
|
1426
|
-
opacity: 0;
|
|
1427
|
-
pointer-events: none;
|
|
1428
|
-
}
|
|
1429
|
-
&:not([src]):not([src=""]) > div,
|
|
1430
|
-
&:hover > div {
|
|
1431
|
-
opacity: 1;
|
|
1432
|
-
pointer-events: all;
|
|
1433
|
-
}
|
|
1434
|
-
fig-button[type="download"] {
|
|
1435
|
-
display: none;
|
|
1436
|
-
}
|
|
1437
|
-
&[src]:not([src=""]) {
|
|
1438
|
-
fig-button[type="download"] {
|
|
1439
|
-
display: inline-flex;
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
1427
|
}
|
|
1443
1428
|
|
|
1444
1429
|
/* Easing Curve */
|
package/fig.js
CHANGED
|
@@ -8007,57 +8007,58 @@ customElements.define("fig-chit", FigChit);
|
|
|
8007
8007
|
class FigSwatch extends FigChit {}
|
|
8008
8008
|
customElements.define("fig-swatch", FigSwatch);
|
|
8009
8009
|
|
|
8010
|
-
/*
|
|
8010
|
+
/* Image */
|
|
8011
8011
|
/**
|
|
8012
|
-
*
|
|
8013
|
-
* @attr {
|
|
8014
|
-
* @attr {
|
|
8015
|
-
* @attr {string}
|
|
8016
|
-
* @attr {string}
|
|
8012
|
+
* @attr {string} src - Image source URL
|
|
8013
|
+
* @attr {boolean} upload - Show upload overlay (generates fig-input-file)
|
|
8014
|
+
* @attr {string} label - Upload button label (default "Upload")
|
|
8015
|
+
* @attr {string} size - small | medium | large | auto
|
|
8016
|
+
* @attr {string} aspect-ratio - CSS aspect-ratio or "auto" (lazy dimension sniff)
|
|
8017
|
+
* @attr {string} fit - CSS object-fit value
|
|
8018
|
+
* @attr {boolean} checkerboard - Show checkerboard behind transparent images
|
|
8017
8019
|
*/
|
|
8018
8020
|
class FigImage extends HTMLElement {
|
|
8019
8021
|
#src = null;
|
|
8022
|
+
#chit = null;
|
|
8023
|
+
#fileInput = null;
|
|
8024
|
+
#blobUrl = null;
|
|
8025
|
+
#file = null;
|
|
8020
8026
|
#boundHandleFileInput = this.#handleFileInput.bind(this);
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8027
|
+
|
|
8028
|
+
static get observedAttributes() {
|
|
8029
|
+
return ["src", "upload", "aspect-ratio", "fit", "checkerboard"];
|
|
8024
8030
|
}
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
? "url()"
|
|
8033
|
-
: "var(--figma-color-bg-secondary)";
|
|
8034
|
-
return `<fig-chit size="large" data-type="image" background="${bg}" disabled${cb ? " checkerboard" : ""}></fig-chit><div>${
|
|
8035
|
-
this.upload
|
|
8036
|
-
? `<fig-button variant="overlay" type="upload">
|
|
8037
|
-
${this.label}
|
|
8038
|
-
<input type="file" accept="image/*" />
|
|
8039
|
-
</fig-button>`
|
|
8040
|
-
: ""
|
|
8041
|
-
} ${
|
|
8042
|
-
this.download
|
|
8043
|
-
? `<fig-button variant="overlay" icon="true" type="download">
|
|
8044
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
8045
|
-
<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"/>
|
|
8046
|
-
</svg></fig-button>`
|
|
8047
|
-
: ""
|
|
8048
|
-
}</div>`;
|
|
8031
|
+
|
|
8032
|
+
get src() {
|
|
8033
|
+
return this.#src;
|
|
8034
|
+
}
|
|
8035
|
+
set src(value) {
|
|
8036
|
+
this.#src = value;
|
|
8037
|
+
this.setAttribute("src", value);
|
|
8049
8038
|
}
|
|
8039
|
+
|
|
8040
|
+
get file() {
|
|
8041
|
+
return this.#file;
|
|
8042
|
+
}
|
|
8043
|
+
|
|
8044
|
+
async getBase64() {
|
|
8045
|
+
const src = this.#src;
|
|
8046
|
+
if (!src) return null;
|
|
8047
|
+
const res = await fetch(src);
|
|
8048
|
+
const blob = await res.blob();
|
|
8049
|
+
const bitmap = await createImageBitmap(blob);
|
|
8050
|
+
const canvas = document.createElement("canvas");
|
|
8051
|
+
canvas.width = bitmap.width;
|
|
8052
|
+
canvas.height = bitmap.height;
|
|
8053
|
+
canvas.getContext("2d").drawImage(bitmap, 0, 0);
|
|
8054
|
+
bitmap.close();
|
|
8055
|
+
const dataUrl = canvas.toDataURL();
|
|
8056
|
+
return dataUrl;
|
|
8057
|
+
}
|
|
8058
|
+
|
|
8050
8059
|
connectedCallback() {
|
|
8051
8060
|
this.#src = this.getAttribute("src") || "";
|
|
8052
|
-
|
|
8053
|
-
this.hasAttribute("upload") && this.getAttribute("upload") !== "false";
|
|
8054
|
-
this.download =
|
|
8055
|
-
this.hasAttribute("download") &&
|
|
8056
|
-
this.getAttribute("download") !== "false";
|
|
8057
|
-
this.label = this.getAttribute("label") || "Upload";
|
|
8058
|
-
this.size = this.getAttribute("size") || "small";
|
|
8059
|
-
this.innerHTML = this.#getInnerHTML();
|
|
8060
|
-
this.#updateRefs();
|
|
8061
|
+
|
|
8061
8062
|
const ar = this.getAttribute("aspect-ratio");
|
|
8062
8063
|
if (ar && ar !== "auto") {
|
|
8063
8064
|
this.style.setProperty("--aspect-ratio", ar);
|
|
@@ -8066,182 +8067,169 @@ class FigImage extends HTMLElement {
|
|
|
8066
8067
|
if (fit) {
|
|
8067
8068
|
this.style.setProperty("--fit", fit);
|
|
8068
8069
|
}
|
|
8070
|
+
|
|
8071
|
+
if (!this.querySelector("fig-chit")) {
|
|
8072
|
+
const chit = document.createElement("fig-chit");
|
|
8073
|
+
chit.setAttribute("data-generated", "");
|
|
8074
|
+
chit.setAttribute("size", "large");
|
|
8075
|
+
chit.setAttribute("data-type", "image");
|
|
8076
|
+
chit.setAttribute("disabled", "");
|
|
8077
|
+
this.#applyChitBackground(chit);
|
|
8078
|
+
if (this.hasAttribute("checkerboard") && this.getAttribute("checkerboard") !== "false") {
|
|
8079
|
+
chit.setAttribute("checkerboard", "");
|
|
8080
|
+
}
|
|
8081
|
+
this.prepend(chit);
|
|
8082
|
+
}
|
|
8083
|
+
this.#chit = this.querySelector("fig-chit");
|
|
8084
|
+
|
|
8085
|
+
const isUpload = this.hasAttribute("upload") && this.getAttribute("upload") !== "false";
|
|
8086
|
+
if (isUpload && !this.querySelector("fig-input-file[data-generated]")) {
|
|
8087
|
+
this.#createFileInput();
|
|
8088
|
+
}
|
|
8089
|
+
|
|
8090
|
+
if (this.#src && this.getAttribute("aspect-ratio") === "auto") {
|
|
8091
|
+
this.#sniffDimensions(this.#src);
|
|
8092
|
+
}
|
|
8069
8093
|
}
|
|
8094
|
+
|
|
8070
8095
|
disconnectedCallback() {
|
|
8071
|
-
this
|
|
8072
|
-
this
|
|
8073
|
-
|
|
8074
|
-
this.#
|
|
8075
|
-
|
|
8096
|
+
this.#fileInput?.removeEventListener("change", this.#boundHandleFileInput);
|
|
8097
|
+
if (this.#blobUrl) {
|
|
8098
|
+
URL.revokeObjectURL(this.#blobUrl);
|
|
8099
|
+
this.#blobUrl = null;
|
|
8100
|
+
}
|
|
8076
8101
|
}
|
|
8077
8102
|
|
|
8078
|
-
#
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
"change",
|
|
8086
|
-
this.#boundHandleFileInput,
|
|
8087
|
-
);
|
|
8088
|
-
this.fileInput?.addEventListener("change", this.#boundHandleFileInput);
|
|
8089
|
-
}
|
|
8090
|
-
if (this.download) {
|
|
8091
|
-
this.downloadButton = this.querySelector("fig-button[type='download']");
|
|
8092
|
-
this.downloadButton?.removeEventListener(
|
|
8093
|
-
"click",
|
|
8094
|
-
this.#boundHandleDownload,
|
|
8095
|
-
);
|
|
8096
|
-
this.downloadButton?.addEventListener(
|
|
8097
|
-
"click",
|
|
8098
|
-
this.#boundHandleDownload,
|
|
8099
|
-
);
|
|
8100
|
-
}
|
|
8101
|
-
});
|
|
8103
|
+
#applyChitBackground(chit) {
|
|
8104
|
+
const cb = this.hasAttribute("checkerboard") && this.getAttribute("checkerboard") !== "false";
|
|
8105
|
+
if (this.#src) {
|
|
8106
|
+
chit.setAttribute("background", `url(${this.#src})`);
|
|
8107
|
+
} else {
|
|
8108
|
+
chit.setAttribute("background", cb ? "url()" : "var(--figma-color-bg-secondary)");
|
|
8109
|
+
}
|
|
8102
8110
|
}
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
const
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
this.image.onload = async () => {
|
|
8116
|
-
this.aspectRatio = this.image.width / this.image.height;
|
|
8117
|
-
const ar = this.getAttribute("aspect-ratio");
|
|
8118
|
-
if (!ar || ar === "auto") {
|
|
8119
|
-
this.style.setProperty(
|
|
8120
|
-
"--aspect-ratio",
|
|
8121
|
-
`${this.image.width}/${this.image.height}`,
|
|
8122
|
-
);
|
|
8123
|
-
}
|
|
8124
|
-
this.dispatchEvent(
|
|
8125
|
-
new CustomEvent("loaded", {
|
|
8126
|
-
bubbles: true,
|
|
8127
|
-
cancelable: true,
|
|
8128
|
-
detail: {
|
|
8129
|
-
blob: this.blob,
|
|
8130
|
-
base64: this.base64,
|
|
8131
|
-
},
|
|
8132
|
-
}),
|
|
8133
|
-
);
|
|
8134
|
-
resolve();
|
|
8135
|
-
|
|
8136
|
-
// Create canvas to extract blob and base64 from image
|
|
8137
|
-
const canvas = document.createElement("canvas");
|
|
8138
|
-
const ctx = canvas.getContext("2d");
|
|
8139
|
-
canvas.width = this.image.width;
|
|
8140
|
-
canvas.height = this.image.height;
|
|
8141
|
-
ctx.drawImage(this.image, 0, 0);
|
|
8142
|
-
|
|
8143
|
-
// Get base64 from canvas
|
|
8144
|
-
this.base64 = canvas.toDataURL();
|
|
8145
|
-
|
|
8146
|
-
// Get blob from canvas
|
|
8147
|
-
canvas.toBlob((blob) => {
|
|
8148
|
-
if (this.blob) {
|
|
8149
|
-
URL.revokeObjectURL(this.blob);
|
|
8150
|
-
}
|
|
8151
|
-
if (blob) {
|
|
8152
|
-
this.blob = URL.createObjectURL(blob);
|
|
8153
|
-
}
|
|
8154
|
-
});
|
|
8155
|
-
};
|
|
8156
|
-
this.image.src = src;
|
|
8157
|
-
});
|
|
8111
|
+
|
|
8112
|
+
#createFileInput() {
|
|
8113
|
+
const fi = document.createElement("fig-input-file");
|
|
8114
|
+
fi.setAttribute("data-generated", "");
|
|
8115
|
+
fi.setAttribute("accepts", "image/*");
|
|
8116
|
+
fi.setAttribute("variant", "overlay");
|
|
8117
|
+
const defaultLabel = this.getAttribute("label") || "Upload";
|
|
8118
|
+
fi.setAttribute("label", this.#src ? "Replace" : defaultLabel);
|
|
8119
|
+
if (this.#src) fi.setAttribute("url", this.#src);
|
|
8120
|
+
fi.addEventListener("change", this.#boundHandleFileInput);
|
|
8121
|
+
this.append(fi);
|
|
8122
|
+
this.#fileInput = fi;
|
|
8158
8123
|
}
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8124
|
+
|
|
8125
|
+
#removeFileInput() {
|
|
8126
|
+
if (this.#fileInput) {
|
|
8127
|
+
this.#fileInput.removeEventListener("change", this.#boundHandleFileInput);
|
|
8128
|
+
this.#fileInput.remove();
|
|
8129
|
+
this.#fileInput = null;
|
|
8130
|
+
}
|
|
8131
|
+
}
|
|
8132
|
+
|
|
8133
|
+
#handleFileInput(e) {
|
|
8134
|
+
const file = e.detail?.files?.[0];
|
|
8135
|
+
|
|
8136
|
+
if (!file) {
|
|
8137
|
+
if (this.#blobUrl) {
|
|
8138
|
+
URL.revokeObjectURL(this.#blobUrl);
|
|
8139
|
+
this.#blobUrl = null;
|
|
8140
|
+
}
|
|
8141
|
+
this.#file = null;
|
|
8142
|
+
this.removeAttribute("src");
|
|
8143
|
+
this.dispatchEvent(
|
|
8144
|
+
new CustomEvent("change", { bubbles: true, cancelable: true }),
|
|
8145
|
+
);
|
|
8146
|
+
return;
|
|
8147
|
+
}
|
|
8148
|
+
|
|
8149
|
+
if (this.#blobUrl) {
|
|
8150
|
+
URL.revokeObjectURL(this.#blobUrl);
|
|
8151
|
+
}
|
|
8152
|
+
this.#file = file;
|
|
8153
|
+
this.#blobUrl = URL.createObjectURL(file);
|
|
8154
|
+
|
|
8155
|
+
this.setAttribute("src", this.#blobUrl);
|
|
8156
|
+
|
|
8175
8157
|
this.dispatchEvent(
|
|
8176
8158
|
new CustomEvent("loaded", {
|
|
8177
8159
|
bubbles: true,
|
|
8178
8160
|
cancelable: true,
|
|
8179
|
-
detail: {
|
|
8180
|
-
blob: this.blob,
|
|
8181
|
-
base64: this.base64,
|
|
8182
|
-
},
|
|
8161
|
+
detail: { file, src: this.#blobUrl },
|
|
8183
8162
|
}),
|
|
8184
8163
|
);
|
|
8185
|
-
//emit for change too
|
|
8186
8164
|
this.dispatchEvent(
|
|
8187
|
-
new CustomEvent("change", {
|
|
8188
|
-
bubbles: true,
|
|
8189
|
-
cancelable: true,
|
|
8190
|
-
}),
|
|
8165
|
+
new CustomEvent("change", { bubbles: true, cancelable: true }),
|
|
8191
8166
|
);
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
get src() {
|
|
8198
|
-
return this.#src;
|
|
8167
|
+
|
|
8168
|
+
if (this.#fileInput) {
|
|
8169
|
+
this.#fileInput.clear();
|
|
8170
|
+
this.#fileInput.setAttribute("label", "Replace");
|
|
8171
|
+
}
|
|
8199
8172
|
}
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8173
|
+
|
|
8174
|
+
async #sniffDimensions(src) {
|
|
8175
|
+
try {
|
|
8176
|
+
let blob;
|
|
8177
|
+
if (src.startsWith("blob:")) {
|
|
8178
|
+
const res = await fetch(src);
|
|
8179
|
+
blob = await res.blob();
|
|
8180
|
+
} else {
|
|
8181
|
+
const res = await fetch(src, { mode: "cors" });
|
|
8182
|
+
blob = await res.blob();
|
|
8183
|
+
}
|
|
8184
|
+
const bitmap = await createImageBitmap(blob);
|
|
8185
|
+
this.style.setProperty("--aspect-ratio", `${bitmap.width}/${bitmap.height}`);
|
|
8186
|
+
bitmap.close();
|
|
8187
|
+
} catch {
|
|
8188
|
+
// Non-critical — CSS aspect-ratio fallback handles it
|
|
8189
|
+
}
|
|
8203
8190
|
}
|
|
8204
8191
|
|
|
8205
8192
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
8193
|
+
if (oldValue === newValue) return;
|
|
8194
|
+
|
|
8206
8195
|
if (name === "src") {
|
|
8207
8196
|
this.#src = newValue;
|
|
8208
|
-
if (this
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8197
|
+
if (this.#chit) {
|
|
8198
|
+
this.#applyChitBackground(this.#chit);
|
|
8199
|
+
}
|
|
8200
|
+
if (this.#fileInput) {
|
|
8201
|
+
const defaultLabel = this.getAttribute("label") || "Upload";
|
|
8202
|
+
this.#fileInput.setAttribute("label", this.#src ? "Replace" : defaultLabel);
|
|
8212
8203
|
if (this.#src) {
|
|
8213
|
-
this.
|
|
8204
|
+
this.#fileInput.setAttribute("url", this.#src);
|
|
8214
8205
|
} else {
|
|
8215
|
-
this.
|
|
8216
|
-
"background",
|
|
8217
|
-
hasCb ? "url()" : "var(--figma-color-bg-secondary)",
|
|
8218
|
-
);
|
|
8206
|
+
this.#fileInput.removeAttribute("url");
|
|
8219
8207
|
}
|
|
8220
8208
|
}
|
|
8221
|
-
if (this.#src) {
|
|
8222
|
-
this.#
|
|
8209
|
+
if (this.#src && this.getAttribute("aspect-ratio") === "auto") {
|
|
8210
|
+
this.#sniffDimensions(this.#src);
|
|
8223
8211
|
}
|
|
8224
8212
|
}
|
|
8213
|
+
|
|
8225
8214
|
if (name === "upload") {
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
this.innerHTML = this.#getInnerHTML();
|
|
8233
|
-
this.#updateRefs();
|
|
8234
|
-
}
|
|
8235
|
-
if (name === "size") {
|
|
8236
|
-
this.size = newValue;
|
|
8215
|
+
const on = newValue !== null && newValue !== "false";
|
|
8216
|
+
if (on && !this.#fileInput) {
|
|
8217
|
+
this.#createFileInput();
|
|
8218
|
+
} else if (!on) {
|
|
8219
|
+
this.#removeFileInput();
|
|
8220
|
+
}
|
|
8237
8221
|
}
|
|
8222
|
+
|
|
8238
8223
|
if (name === "aspect-ratio") {
|
|
8239
8224
|
if (newValue && newValue !== "auto") {
|
|
8240
8225
|
this.style.setProperty("--aspect-ratio", newValue);
|
|
8241
8226
|
} else if (!newValue) {
|
|
8242
8227
|
this.style.removeProperty("--aspect-ratio");
|
|
8228
|
+
} else if (newValue === "auto" && this.#src) {
|
|
8229
|
+
this.#sniffDimensions(this.#src);
|
|
8243
8230
|
}
|
|
8244
8231
|
}
|
|
8232
|
+
|
|
8245
8233
|
if (name === "fit") {
|
|
8246
8234
|
if (newValue) {
|
|
8247
8235
|
this.style.setProperty("--fit", newValue);
|
|
@@ -8249,12 +8237,13 @@ class FigImage extends HTMLElement {
|
|
|
8249
8237
|
this.style.removeProperty("--fit");
|
|
8250
8238
|
}
|
|
8251
8239
|
}
|
|
8240
|
+
|
|
8252
8241
|
if (name === "checkerboard") {
|
|
8253
|
-
if (this
|
|
8242
|
+
if (this.#chit) {
|
|
8254
8243
|
if (newValue !== null && newValue !== "false") {
|
|
8255
|
-
this
|
|
8244
|
+
this.#chit.setAttribute("checkerboard", "");
|
|
8256
8245
|
} else {
|
|
8257
|
-
this
|
|
8246
|
+
this.#chit.removeAttribute("checkerboard");
|
|
8258
8247
|
}
|
|
8259
8248
|
}
|
|
8260
8249
|
}
|
|
@@ -8264,7 +8253,7 @@ customElements.define("fig-image", FigImage);
|
|
|
8264
8253
|
|
|
8265
8254
|
/* File Upload Input */
|
|
8266
8255
|
class FigInputFile extends HTMLElement {
|
|
8267
|
-
static observedAttributes = ["accepts", "label", "disabled", "multiple"];
|
|
8256
|
+
static observedAttributes = ["accepts", "label", "disabled", "multiple", "variant", "url"];
|
|
8268
8257
|
|
|
8269
8258
|
#fileInput = null;
|
|
8270
8259
|
#filenameEl = null;
|
|
@@ -8277,10 +8266,24 @@ class FigInputFile extends HTMLElement {
|
|
|
8277
8266
|
return this.#files;
|
|
8278
8267
|
}
|
|
8279
8268
|
|
|
8269
|
+
get #urlFilename() {
|
|
8270
|
+
const url = this.getAttribute("url");
|
|
8271
|
+
if (!url) return "";
|
|
8272
|
+
try {
|
|
8273
|
+
const path = new URL(url, location.href).pathname;
|
|
8274
|
+
const name = path.split("/").pop();
|
|
8275
|
+
return name ? decodeURIComponent(name) : url;
|
|
8276
|
+
} catch {
|
|
8277
|
+
return url;
|
|
8278
|
+
}
|
|
8279
|
+
}
|
|
8280
|
+
|
|
8280
8281
|
get value() {
|
|
8281
|
-
if (
|
|
8282
|
-
|
|
8283
|
-
|
|
8282
|
+
if (this.#files && this.#files.length > 0) {
|
|
8283
|
+
if (this.#files.length === 1) return this.#files[0].name;
|
|
8284
|
+
return `${this.#files.length} files`;
|
|
8285
|
+
}
|
|
8286
|
+
return this.#urlFilename;
|
|
8284
8287
|
}
|
|
8285
8288
|
|
|
8286
8289
|
connectedCallback() {
|
|
@@ -8306,6 +8309,7 @@ class FigInputFile extends HTMLElement {
|
|
|
8306
8309
|
clear() {
|
|
8307
8310
|
this.#files = null;
|
|
8308
8311
|
if (this.#fileInput) this.#fileInput.value = "";
|
|
8312
|
+
this.removeAttribute("url");
|
|
8309
8313
|
this.#render();
|
|
8310
8314
|
this.#emitEvents();
|
|
8311
8315
|
}
|
|
@@ -8319,6 +8323,7 @@ class FigInputFile extends HTMLElement {
|
|
|
8319
8323
|
#onFileChange = () => {
|
|
8320
8324
|
if (this.#fileInput.files.length > 0) {
|
|
8321
8325
|
this.#files = this.#fileInput.files;
|
|
8326
|
+
this.removeAttribute("url");
|
|
8322
8327
|
this.#render();
|
|
8323
8328
|
this.#emitEvents();
|
|
8324
8329
|
}
|
|
@@ -8373,6 +8378,7 @@ class FigInputFile extends HTMLElement {
|
|
|
8373
8378
|
if (this.#fileInput) {
|
|
8374
8379
|
this.#fileInput.files = dt.files;
|
|
8375
8380
|
}
|
|
8381
|
+
this.removeAttribute("url");
|
|
8376
8382
|
this.#render();
|
|
8377
8383
|
this.#emitEvents();
|
|
8378
8384
|
};
|
|
@@ -8384,7 +8390,8 @@ class FigInputFile extends HTMLElement {
|
|
|
8384
8390
|
this.hasAttribute("disabled") &&
|
|
8385
8391
|
this.getAttribute("disabled") !== "false";
|
|
8386
8392
|
const multiple = this.hasAttribute("multiple");
|
|
8387
|
-
const
|
|
8393
|
+
const variant = this.getAttribute("variant") || "input";
|
|
8394
|
+
const hasFile = (this.#files && this.#files.length > 0) || !!this.getAttribute("url");
|
|
8388
8395
|
|
|
8389
8396
|
this.innerHTML = "";
|
|
8390
8397
|
|
|
@@ -8397,7 +8404,7 @@ class FigInputFile extends HTMLElement {
|
|
|
8397
8404
|
: "";
|
|
8398
8405
|
|
|
8399
8406
|
this.#uploadBtn = document.createElement("fig-button");
|
|
8400
|
-
this.#uploadBtn.setAttribute("variant",
|
|
8407
|
+
this.#uploadBtn.setAttribute("variant", variant);
|
|
8401
8408
|
this.#uploadBtn.setAttribute("type", "upload");
|
|
8402
8409
|
this.#uploadBtn.className = "fig-input-file-filename";
|
|
8403
8410
|
if (disabled) this.#uploadBtn.setAttribute("disabled", "");
|
|
@@ -8452,7 +8459,7 @@ class FigInputFile extends HTMLElement {
|
|
|
8452
8459
|
}
|
|
8453
8460
|
|
|
8454
8461
|
this.#uploadBtn = document.createElement("fig-button");
|
|
8455
|
-
this.#uploadBtn.setAttribute("variant",
|
|
8462
|
+
this.#uploadBtn.setAttribute("variant", variant);
|
|
8456
8463
|
this.#uploadBtn.setAttribute("type", "upload");
|
|
8457
8464
|
this.#uploadBtn.textContent = label;
|
|
8458
8465
|
if (disabled) this.#uploadBtn.setAttribute("disabled", "");
|
package/package.json
CHANGED