@rogieking/figui3 6.29.1 → 6.31.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 +2 -0
- package/components.css +15 -2
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-lab.css +1 -1
- package/dist/fig-lab.js +3 -3
- package/dist/fig.css +1 -1
- package/dist/fig.js +2 -2
- package/fig-lab.css +81 -0
- package/fig-lab.js +199 -0
- package/fig.js +3 -0
- package/package.json +1 -1
package/fig-lab.js
CHANGED
|
@@ -193,6 +193,205 @@ figLabDefineElement("fig-ai-prompt", FigAiPrompt);
|
|
|
193
193
|
class FigChatMessage extends HTMLElement {}
|
|
194
194
|
figLabDefineElement("fig-chat-message", FigChatMessage);
|
|
195
195
|
|
|
196
|
+
/**
|
|
197
|
+
* A removable image attachment for compact prompt surfaces.
|
|
198
|
+
*
|
|
199
|
+
* @attr {string} src - Image preview URL.
|
|
200
|
+
* @attr {string} name - Attachment name used for the tooltip and image alt text.
|
|
201
|
+
* @attr {string} value - Optional application-owned attachment identifier.
|
|
202
|
+
* @attr {boolean|string} removable - "false" hides the remove button.
|
|
203
|
+
* @attr {boolean|string} disabled - Disables removal.
|
|
204
|
+
* @fires remove - Cancelable request for the owning application to remove the attachment.
|
|
205
|
+
*/
|
|
206
|
+
class FigAttachment extends HTMLElement {
|
|
207
|
+
#tooltip = null;
|
|
208
|
+
#image = null;
|
|
209
|
+
#fallback = null;
|
|
210
|
+
#removeTooltip = null;
|
|
211
|
+
#removeButton = null;
|
|
212
|
+
#mediaImage = null;
|
|
213
|
+
#boundHandleRemove = this.#handleRemove.bind(this);
|
|
214
|
+
#boundHandleImageLoad = this.#handleImageLoad.bind(this);
|
|
215
|
+
#boundHandleImageError = this.#handleImageError.bind(this);
|
|
216
|
+
|
|
217
|
+
static get observedAttributes() {
|
|
218
|
+
return ["src", "name", "value", "removable", "disabled"];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
connectedCallback() {
|
|
222
|
+
if (!this.#image) this.#initialize();
|
|
223
|
+
this.#removeButton.removeEventListener("click", this.#boundHandleRemove);
|
|
224
|
+
this.#removeButton.addEventListener("click", this.#boundHandleRemove);
|
|
225
|
+
this.#bindMediaImage();
|
|
226
|
+
this.#sync();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
disconnectedCallback() {
|
|
230
|
+
this.#removeButton?.removeEventListener("click", this.#boundHandleRemove);
|
|
231
|
+
this.#unbindMediaImage();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
235
|
+
if (oldValue === newValue || !this.#image) return;
|
|
236
|
+
this.#sync();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
#initialize() {
|
|
240
|
+
this.#tooltip = document.createElement("fig-tooltip");
|
|
241
|
+
this.#tooltip.className = "fig-attachment-tooltip";
|
|
242
|
+
|
|
243
|
+
this.#image = document.createElement("fig-image");
|
|
244
|
+
this.#image.setAttribute("aspect-ratio", "1/1");
|
|
245
|
+
this.#image.setAttribute("fit", "cover");
|
|
246
|
+
this.#image.setAttribute("full", "");
|
|
247
|
+
|
|
248
|
+
this.#fallback = document.createElement("span");
|
|
249
|
+
this.#fallback.className = "fig-attachment-fallback";
|
|
250
|
+
this.#fallback.setAttribute("aria-hidden", "true");
|
|
251
|
+
|
|
252
|
+
this.#removeTooltip = document.createElement("fig-tooltip");
|
|
253
|
+
this.#removeTooltip.className = "fig-attachment-remove-tooltip";
|
|
254
|
+
this.#removeTooltip.setAttribute("text", "Remove attachment");
|
|
255
|
+
|
|
256
|
+
this.#removeButton = document.createElement("fig-button");
|
|
257
|
+
this.#removeButton.className = "fig-attachment-remove";
|
|
258
|
+
this.#removeButton.setAttribute("variant", "overlay");
|
|
259
|
+
this.#removeButton.setAttribute("size", "small");
|
|
260
|
+
this.#removeButton.setAttribute("icon", "");
|
|
261
|
+
const closeIcon = document.createElement("fig-icon");
|
|
262
|
+
closeIcon.setAttribute("name", "close");
|
|
263
|
+
closeIcon.setAttribute("size", "small");
|
|
264
|
+
this.#removeButton.append(closeIcon);
|
|
265
|
+
this.#removeTooltip.append(this.#removeButton);
|
|
266
|
+
|
|
267
|
+
this.#image.append(this.#fallback);
|
|
268
|
+
this.#tooltip.append(this.#image);
|
|
269
|
+
this.replaceChildren(this.#tooltip, this.#removeTooltip);
|
|
270
|
+
|
|
271
|
+
this.#removeButton.addEventListener("click", this.#boundHandleRemove);
|
|
272
|
+
this.#bindMediaImage();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
#bindMediaImage() {
|
|
276
|
+
const mediaImage = this.#image?.mediaEl;
|
|
277
|
+
if (!mediaImage || mediaImage === this.#mediaImage) return;
|
|
278
|
+
this.#unbindMediaImage();
|
|
279
|
+
this.#mediaImage = mediaImage;
|
|
280
|
+
this.#mediaImage.addEventListener("load", this.#boundHandleImageLoad);
|
|
281
|
+
this.#mediaImage.addEventListener("error", this.#boundHandleImageError);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
#unbindMediaImage() {
|
|
285
|
+
if (!this.#mediaImage) return;
|
|
286
|
+
this.#mediaImage.removeEventListener("load", this.#boundHandleImageLoad);
|
|
287
|
+
this.#mediaImage.removeEventListener("error", this.#boundHandleImageError);
|
|
288
|
+
this.#mediaImage = null;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
#sync() {
|
|
292
|
+
const src = this.getAttribute("src") || "";
|
|
293
|
+
const name = this.getAttribute("name") || "Attachment";
|
|
294
|
+
const removable =
|
|
295
|
+
!this.hasAttribute("removable") || figLabBooleanAttribute(this, "removable");
|
|
296
|
+
const disabled = figLabBooleanAttribute(this, "disabled");
|
|
297
|
+
|
|
298
|
+
this.#tooltip.setAttribute("text", name);
|
|
299
|
+
this.#image.setAttribute("alt", name);
|
|
300
|
+
if (src) {
|
|
301
|
+
this.#image.setAttribute("src", src);
|
|
302
|
+
} else {
|
|
303
|
+
this.#image.removeAttribute("src");
|
|
304
|
+
}
|
|
305
|
+
this.#bindMediaImage();
|
|
306
|
+
|
|
307
|
+
this.#fallback.textContent = this.#fallbackLabel(name);
|
|
308
|
+
this.#removeButton.hidden = !removable;
|
|
309
|
+
this.#removeButton.toggleAttribute("disabled", disabled);
|
|
310
|
+
this.#removeButton.setAttribute("aria-label", `Remove ${name}`);
|
|
311
|
+
this.toggleAttribute("data-fallback", !src);
|
|
312
|
+
if (disabled) {
|
|
313
|
+
this.setAttribute("aria-disabled", "true");
|
|
314
|
+
} else {
|
|
315
|
+
this.removeAttribute("aria-disabled");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
#fallbackLabel(name) {
|
|
320
|
+
const baseName = name.split(/[\\/]/).pop() || "";
|
|
321
|
+
const dotIndex = baseName.lastIndexOf(".");
|
|
322
|
+
const extension =
|
|
323
|
+
dotIndex > 0 && dotIndex < baseName.length - 1
|
|
324
|
+
? baseName.slice(dotIndex + 1).toUpperCase()
|
|
325
|
+
: "FILE";
|
|
326
|
+
return extension.slice(0, 4);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
#handleImageLoad() {
|
|
330
|
+
if (this.getAttribute("src")) this.removeAttribute("data-fallback");
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
#handleImageError() {
|
|
334
|
+
this.setAttribute("data-fallback", "");
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
#handleRemove(event) {
|
|
338
|
+
event.stopPropagation();
|
|
339
|
+
if (
|
|
340
|
+
figLabBooleanAttribute(this, "disabled") ||
|
|
341
|
+
(this.hasAttribute("removable") &&
|
|
342
|
+
!figLabBooleanAttribute(this, "removable"))
|
|
343
|
+
) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
this.dispatchEvent(
|
|
347
|
+
new CustomEvent("remove", {
|
|
348
|
+
bubbles: true,
|
|
349
|
+
cancelable: true,
|
|
350
|
+
composed: true,
|
|
351
|
+
detail: {
|
|
352
|
+
value: this.getAttribute("value"),
|
|
353
|
+
name: this.getAttribute("name") || "",
|
|
354
|
+
src: this.getAttribute("src") || "",
|
|
355
|
+
attachment: this,
|
|
356
|
+
},
|
|
357
|
+
}),
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
figLabDefineElement("fig-attachment", FigAttachment);
|
|
362
|
+
|
|
363
|
+
/* Wrapping presentation container for one or more attachments. */
|
|
364
|
+
class FigAttachments extends HTMLElement {
|
|
365
|
+
#observer = null;
|
|
366
|
+
|
|
367
|
+
connectedCallback() {
|
|
368
|
+
if (!this.hasAttribute("role")) {
|
|
369
|
+
this.setAttribute("role", "list");
|
|
370
|
+
this.setAttribute("data-generated-role", "");
|
|
371
|
+
}
|
|
372
|
+
this.#syncItems();
|
|
373
|
+
if (!this.#observer) {
|
|
374
|
+
this.#observer = new MutationObserver(() => this.#syncItems());
|
|
375
|
+
this.#observer.observe(this, { childList: true });
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
disconnectedCallback() {
|
|
380
|
+
this.#observer?.disconnect();
|
|
381
|
+
this.#observer = null;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
#syncItems() {
|
|
385
|
+
for (const attachment of this.querySelectorAll(":scope > fig-attachment")) {
|
|
386
|
+
if (!attachment.hasAttribute("role")) {
|
|
387
|
+
attachment.setAttribute("role", "listitem");
|
|
388
|
+
attachment.setAttribute("data-generated-role", "");
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
figLabDefineElement("fig-attachments", FigAttachments);
|
|
394
|
+
|
|
196
395
|
/* Field + Switch wrapper */
|
|
197
396
|
class PropskitSwitch extends HTMLElement {
|
|
198
397
|
#field = null;
|
package/fig.js
CHANGED
|
@@ -13455,6 +13455,7 @@ figDefineElement("fig-video", FigVideo);
|
|
|
13455
13455
|
* @attr {boolean} selected - Selected chrome (CSS only)
|
|
13456
13456
|
* @attr {boolean} disabled - Dim + non-interactive; no `<a>` when disabled
|
|
13457
13457
|
* @attr {boolean} full - Stretch to available width (CSS; default width is already 100%)
|
|
13458
|
+
* @attr {string} size - Set to `large` for spacer-2 card padding and spacer-1 label spacing
|
|
13458
13459
|
* @attr {string} aspect-ratio - Forwarded to fig-image (default `1/1`)
|
|
13459
13460
|
* @attr {string} fit - Forwarded to fig-image (default `contain`)
|
|
13460
13461
|
* @attr {string} label-line-clamp - `1` (default) or `2`
|
|
@@ -13472,6 +13473,7 @@ class FigCard extends HTMLElement {
|
|
|
13472
13473
|
"selected",
|
|
13473
13474
|
"disabled",
|
|
13474
13475
|
"full",
|
|
13476
|
+
"size",
|
|
13475
13477
|
"aspect-ratio",
|
|
13476
13478
|
"fit",
|
|
13477
13479
|
"label-line-clamp",
|
|
@@ -17448,6 +17450,7 @@ const FIG_ICON_TOKENS = {
|
|
|
17448
17450
|
more: { medium: "--icon-24-more", small: "--icon-16-more" },
|
|
17449
17451
|
visible: { medium: "--icon-24-visible", small: "--icon-16-visible" },
|
|
17450
17452
|
hidden: { medium: "--icon-24-hidden", small: "--icon-16-hidden" },
|
|
17453
|
+
globe: { medium: "--icon-24-globe", small: "--icon-16-globe" },
|
|
17451
17454
|
};
|
|
17452
17455
|
|
|
17453
17456
|
function figIconCssVar(name, size = "medium") {
|
package/package.json
CHANGED