@rogieking/figui3 3.5.0 → 3.7.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/components.css +240 -33
- package/dist/fig.js +29 -29
- package/fig.js +278 -5
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -4012,6 +4012,268 @@ class FigField extends HTMLElement {
|
|
|
4012
4012
|
}
|
|
4013
4013
|
customElements.define("fig-field", FigField);
|
|
4014
4014
|
|
|
4015
|
+
/* Field + Slider wrapper */
|
|
4016
|
+
class FigFieldSlider extends HTMLElement {
|
|
4017
|
+
#field = null;
|
|
4018
|
+
#label = null;
|
|
4019
|
+
#slider = null;
|
|
4020
|
+
#observer = null;
|
|
4021
|
+
#managedSliderAttrs = new Set();
|
|
4022
|
+
#steppersSyncFrame = 0;
|
|
4023
|
+
#boundHandleSliderInput = null;
|
|
4024
|
+
#boundHandleSliderChange = null;
|
|
4025
|
+
#ignoredSliderAttrs = new Set(["variant", "color", "text", "full"]);
|
|
4026
|
+
|
|
4027
|
+
static get observedAttributes() {
|
|
4028
|
+
return ["label", "direction"];
|
|
4029
|
+
}
|
|
4030
|
+
|
|
4031
|
+
connectedCallback() {
|
|
4032
|
+
if (!this.#field) {
|
|
4033
|
+
this.#initialize();
|
|
4034
|
+
}
|
|
4035
|
+
|
|
4036
|
+
this.#syncField();
|
|
4037
|
+
this.#syncSliderAttributes();
|
|
4038
|
+
this.#bindSliderEvents();
|
|
4039
|
+
|
|
4040
|
+
if (!this.#observer) {
|
|
4041
|
+
this.#observer = new MutationObserver((mutations) => {
|
|
4042
|
+
let syncField = false;
|
|
4043
|
+
let syncSlider = false;
|
|
4044
|
+
|
|
4045
|
+
for (const mutation of mutations) {
|
|
4046
|
+
if (mutation.type === "attributes") {
|
|
4047
|
+
if (
|
|
4048
|
+
mutation.attributeName &&
|
|
4049
|
+
this.#ignoredSliderAttrs.has(mutation.attributeName)
|
|
4050
|
+
) {
|
|
4051
|
+
continue;
|
|
4052
|
+
}
|
|
4053
|
+
if (
|
|
4054
|
+
mutation.attributeName === "label" ||
|
|
4055
|
+
mutation.attributeName === "direction"
|
|
4056
|
+
) {
|
|
4057
|
+
syncField = true;
|
|
4058
|
+
} else {
|
|
4059
|
+
syncSlider = true;
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
|
|
4064
|
+
if (syncField) this.#syncField();
|
|
4065
|
+
if (syncSlider) this.#syncSliderAttributes();
|
|
4066
|
+
});
|
|
4067
|
+
}
|
|
4068
|
+
|
|
4069
|
+
this.#observer.observe(this, { attributes: true });
|
|
4070
|
+
}
|
|
4071
|
+
|
|
4072
|
+
disconnectedCallback() {
|
|
4073
|
+
this.#observer?.disconnect();
|
|
4074
|
+
if (this.#steppersSyncFrame) {
|
|
4075
|
+
cancelAnimationFrame(this.#steppersSyncFrame);
|
|
4076
|
+
this.#steppersSyncFrame = 0;
|
|
4077
|
+
}
|
|
4078
|
+
this.#unbindSliderEvents();
|
|
4079
|
+
}
|
|
4080
|
+
|
|
4081
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
4082
|
+
if (oldValue === newValue || !this.#field) return;
|
|
4083
|
+
if (name === "label" || name === "direction") {
|
|
4084
|
+
this.#syncField();
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
|
|
4088
|
+
#initialize() {
|
|
4089
|
+
const initialChildren = Array.from(this.childNodes).filter((node) => {
|
|
4090
|
+
return (
|
|
4091
|
+
node.nodeType !== Node.TEXT_NODE || Boolean(node.textContent?.trim())
|
|
4092
|
+
);
|
|
4093
|
+
});
|
|
4094
|
+
|
|
4095
|
+
const field = document.createElement("fig-field");
|
|
4096
|
+
const label = document.createElement("label");
|
|
4097
|
+
const slider = document.createElement("fig-slider");
|
|
4098
|
+
slider.setAttribute("text", "true");
|
|
4099
|
+
for (const attrName of this.#getForwardedSliderAttrNames()) {
|
|
4100
|
+
const value = this.getAttribute(attrName);
|
|
4101
|
+
slider.setAttribute(attrName, value ?? "");
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
field.append(label, slider);
|
|
4105
|
+
|
|
4106
|
+
this.#field = field;
|
|
4107
|
+
this.#label = label;
|
|
4108
|
+
this.#slider = slider;
|
|
4109
|
+
|
|
4110
|
+
this.replaceChildren(field);
|
|
4111
|
+
|
|
4112
|
+
for (const node of initialChildren) {
|
|
4113
|
+
this.#slider.appendChild(node);
|
|
4114
|
+
}
|
|
4115
|
+
}
|
|
4116
|
+
|
|
4117
|
+
#syncField() {
|
|
4118
|
+
if (!this.#field || !this.#label) return;
|
|
4119
|
+
const hasLabelAttr = this.hasAttribute("label");
|
|
4120
|
+
const rawLabel = this.getAttribute("label");
|
|
4121
|
+
const isBlankLabel = hasLabelAttr && (rawLabel ?? "").trim() === "";
|
|
4122
|
+
|
|
4123
|
+
if (isBlankLabel) {
|
|
4124
|
+
if (this.#label.parentElement === this.#field) {
|
|
4125
|
+
this.#label.remove();
|
|
4126
|
+
}
|
|
4127
|
+
} else {
|
|
4128
|
+
this.#label.textContent = hasLabelAttr ? rawLabel ?? "" : "Label";
|
|
4129
|
+
if (this.#label.parentElement !== this.#field) {
|
|
4130
|
+
this.#field.prepend(this.#label);
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
|
|
4134
|
+
this.#field.setAttribute(
|
|
4135
|
+
"direction",
|
|
4136
|
+
this.getAttribute("direction") || "horizontal",
|
|
4137
|
+
);
|
|
4138
|
+
}
|
|
4139
|
+
|
|
4140
|
+
#syncSliderAttributes() {
|
|
4141
|
+
if (!this.#slider) return;
|
|
4142
|
+
const hostAttrs = this.#getForwardedSliderAttrNames();
|
|
4143
|
+
|
|
4144
|
+
const nextManaged = new Set(hostAttrs.filter((name) => name !== "text"));
|
|
4145
|
+
|
|
4146
|
+
for (const attrName of this.#managedSliderAttrs) {
|
|
4147
|
+
if (!nextManaged.has(attrName)) {
|
|
4148
|
+
this.#slider.removeAttribute(attrName);
|
|
4149
|
+
}
|
|
4150
|
+
}
|
|
4151
|
+
|
|
4152
|
+
for (const attrName of hostAttrs) {
|
|
4153
|
+
if (attrName === "text") continue;
|
|
4154
|
+
const value = this.getAttribute(attrName);
|
|
4155
|
+
this.#slider.setAttribute(attrName, value ?? "");
|
|
4156
|
+
}
|
|
4157
|
+
|
|
4158
|
+
this.#slider.removeAttribute("variant");
|
|
4159
|
+
this.#slider.removeAttribute("color");
|
|
4160
|
+
this.#slider.removeAttribute("transform");
|
|
4161
|
+
this.#slider.removeAttribute("full");
|
|
4162
|
+
this.#slider.setAttribute("text", "true");
|
|
4163
|
+
|
|
4164
|
+
const sliderType = (this.getAttribute("type") || "range").toLowerCase();
|
|
4165
|
+
if (sliderType === "delta" || sliderType === "stepper") {
|
|
4166
|
+
this.#slider.setAttribute(
|
|
4167
|
+
"default",
|
|
4168
|
+
this.getAttribute("default") ?? "50",
|
|
4169
|
+
);
|
|
4170
|
+
} else if (!this.hasAttribute("default")) {
|
|
4171
|
+
this.#slider.removeAttribute("default");
|
|
4172
|
+
}
|
|
4173
|
+
if (sliderType === "stepper") {
|
|
4174
|
+
this.#slider.setAttribute("step", this.getAttribute("step") ?? "10");
|
|
4175
|
+
} else if (!this.hasAttribute("step")) {
|
|
4176
|
+
this.#slider.removeAttribute("step");
|
|
4177
|
+
}
|
|
4178
|
+
if (sliderType === "opacity") {
|
|
4179
|
+
this.#slider.style.setProperty(
|
|
4180
|
+
"--color",
|
|
4181
|
+
"var(--figma-color-bg-tertiary)",
|
|
4182
|
+
);
|
|
4183
|
+
} else {
|
|
4184
|
+
this.#slider.style.removeProperty("--color");
|
|
4185
|
+
}
|
|
4186
|
+
|
|
4187
|
+
this.#managedSliderAttrs = nextManaged;
|
|
4188
|
+
this.#queueSteppersSync();
|
|
4189
|
+
}
|
|
4190
|
+
|
|
4191
|
+
#getForwardedSliderAttrNames() {
|
|
4192
|
+
const reserved = new Set([
|
|
4193
|
+
"label",
|
|
4194
|
+
"direction",
|
|
4195
|
+
"oninput",
|
|
4196
|
+
"onchange",
|
|
4197
|
+
"steppers",
|
|
4198
|
+
]);
|
|
4199
|
+
return this.getAttributeNames().filter(
|
|
4200
|
+
(name) => !reserved.has(name) && !this.#ignoredSliderAttrs.has(name),
|
|
4201
|
+
);
|
|
4202
|
+
}
|
|
4203
|
+
|
|
4204
|
+
#queueSteppersSync() {
|
|
4205
|
+
if (this.#steppersSyncFrame) {
|
|
4206
|
+
cancelAnimationFrame(this.#steppersSyncFrame);
|
|
4207
|
+
}
|
|
4208
|
+
this.#steppersSyncFrame = requestAnimationFrame(() => {
|
|
4209
|
+
this.#steppersSyncFrame = 0;
|
|
4210
|
+
this.#syncSteppersToNumberInput();
|
|
4211
|
+
});
|
|
4212
|
+
}
|
|
4213
|
+
|
|
4214
|
+
#syncSteppersToNumberInput() {
|
|
4215
|
+
if (!this.#slider) return;
|
|
4216
|
+
const numberInput = this.#slider.querySelector("fig-input-number");
|
|
4217
|
+
if (!numberInput) return;
|
|
4218
|
+
|
|
4219
|
+
const hasSteppers =
|
|
4220
|
+
this.hasAttribute("steppers") &&
|
|
4221
|
+
this.getAttribute("steppers") !== "false";
|
|
4222
|
+
if (!hasSteppers) {
|
|
4223
|
+
numberInput.removeAttribute("steppers");
|
|
4224
|
+
return;
|
|
4225
|
+
}
|
|
4226
|
+
|
|
4227
|
+
const steppersValue = this.getAttribute("steppers");
|
|
4228
|
+
numberInput.setAttribute("steppers", steppersValue ?? "");
|
|
4229
|
+
}
|
|
4230
|
+
|
|
4231
|
+
#bindSliderEvents() {
|
|
4232
|
+
if (!this.#slider) return;
|
|
4233
|
+
if (!this.#boundHandleSliderInput) {
|
|
4234
|
+
this.#boundHandleSliderInput = this.#forwardSliderEvent.bind(
|
|
4235
|
+
this,
|
|
4236
|
+
"input",
|
|
4237
|
+
);
|
|
4238
|
+
}
|
|
4239
|
+
if (!this.#boundHandleSliderChange) {
|
|
4240
|
+
this.#boundHandleSliderChange = this.#forwardSliderEvent.bind(
|
|
4241
|
+
this,
|
|
4242
|
+
"change",
|
|
4243
|
+
);
|
|
4244
|
+
}
|
|
4245
|
+
this.#slider.addEventListener("input", this.#boundHandleSliderInput);
|
|
4246
|
+
this.#slider.addEventListener("change", this.#boundHandleSliderChange);
|
|
4247
|
+
}
|
|
4248
|
+
|
|
4249
|
+
#unbindSliderEvents() {
|
|
4250
|
+
if (!this.#slider) return;
|
|
4251
|
+
if (this.#boundHandleSliderInput) {
|
|
4252
|
+
this.#slider.removeEventListener("input", this.#boundHandleSliderInput);
|
|
4253
|
+
}
|
|
4254
|
+
if (this.#boundHandleSliderChange) {
|
|
4255
|
+
this.#slider.removeEventListener("change", this.#boundHandleSliderChange);
|
|
4256
|
+
}
|
|
4257
|
+
}
|
|
4258
|
+
|
|
4259
|
+
#forwardSliderEvent(type, event) {
|
|
4260
|
+
event.stopPropagation();
|
|
4261
|
+
const detail =
|
|
4262
|
+
event instanceof CustomEvent && event.detail !== undefined
|
|
4263
|
+
? event.detail
|
|
4264
|
+
: this.#slider?.value;
|
|
4265
|
+
this.dispatchEvent(
|
|
4266
|
+
new CustomEvent(type, {
|
|
4267
|
+
detail,
|
|
4268
|
+
bubbles: true,
|
|
4269
|
+
cancelable: true,
|
|
4270
|
+
composed: true,
|
|
4271
|
+
}),
|
|
4272
|
+
);
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
customElements.define("fig-field-slider", FigFieldSlider);
|
|
4276
|
+
|
|
4015
4277
|
/* Color swatch */
|
|
4016
4278
|
class FigInputColor extends HTMLElement {
|
|
4017
4279
|
rgba;
|
|
@@ -5803,9 +6065,15 @@ class FigImage extends HTMLElement {
|
|
|
5803
6065
|
super();
|
|
5804
6066
|
}
|
|
5805
6067
|
#getInnerHTML() {
|
|
5806
|
-
const cb =
|
|
5807
|
-
|
|
5808
|
-
|
|
6068
|
+
const cb =
|
|
6069
|
+
this.hasAttribute("checkerboard") &&
|
|
6070
|
+
this.getAttribute("checkerboard") !== "false";
|
|
6071
|
+
const bg = this.src
|
|
6072
|
+
? `url(${this.src})`
|
|
6073
|
+
: cb
|
|
6074
|
+
? "url()"
|
|
6075
|
+
: "var(--figma-color-bg-secondary)";
|
|
6076
|
+
return `<fig-chit size="large" data-type="image" background="${bg}" disabled${cb ? " checkerboard" : ""}></fig-chit><div>${
|
|
5809
6077
|
this.upload
|
|
5810
6078
|
? `<fig-button variant="overlay" type="upload">
|
|
5811
6079
|
${this.label}
|
|
@@ -5980,11 +6248,16 @@ class FigImage extends HTMLElement {
|
|
|
5980
6248
|
if (name === "src") {
|
|
5981
6249
|
this.#src = newValue;
|
|
5982
6250
|
if (this.chit) {
|
|
5983
|
-
const hasCb =
|
|
6251
|
+
const hasCb =
|
|
6252
|
+
this.hasAttribute("checkerboard") &&
|
|
6253
|
+
this.getAttribute("checkerboard") !== "false";
|
|
5984
6254
|
if (this.#src) {
|
|
5985
6255
|
this.chit.setAttribute("background", `url(${this.#src})`);
|
|
5986
6256
|
} else {
|
|
5987
|
-
this.chit.setAttribute(
|
|
6257
|
+
this.chit.setAttribute(
|
|
6258
|
+
"background",
|
|
6259
|
+
hasCb ? "url()" : "var(--figma-color-bg-secondary)",
|
|
6260
|
+
);
|
|
5988
6261
|
}
|
|
5989
6262
|
}
|
|
5990
6263
|
if (this.#src) {
|
package/package.json
CHANGED