@rogieking/figui3 3.5.0 → 3.6.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 +215 -28
- package/dist/fig.js +29 -29
- package/fig.js +239 -5
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -4012,6 +4012,229 @@ 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
|
+
#boundHandleSliderInput = null;
|
|
4023
|
+
#boundHandleSliderChange = null;
|
|
4024
|
+
#ignoredSliderAttrs = new Set(["variant", "color", "text", "full"]);
|
|
4025
|
+
|
|
4026
|
+
static get observedAttributes() {
|
|
4027
|
+
return ["label", "direction"];
|
|
4028
|
+
}
|
|
4029
|
+
|
|
4030
|
+
connectedCallback() {
|
|
4031
|
+
if (!this.#field) {
|
|
4032
|
+
this.#initialize();
|
|
4033
|
+
}
|
|
4034
|
+
|
|
4035
|
+
this.#syncField();
|
|
4036
|
+
this.#syncSliderAttributes();
|
|
4037
|
+
this.#bindSliderEvents();
|
|
4038
|
+
|
|
4039
|
+
if (!this.#observer) {
|
|
4040
|
+
this.#observer = new MutationObserver((mutations) => {
|
|
4041
|
+
let syncField = false;
|
|
4042
|
+
let syncSlider = false;
|
|
4043
|
+
|
|
4044
|
+
for (const mutation of mutations) {
|
|
4045
|
+
if (mutation.type === "attributes") {
|
|
4046
|
+
if (
|
|
4047
|
+
mutation.attributeName &&
|
|
4048
|
+
this.#ignoredSliderAttrs.has(mutation.attributeName)
|
|
4049
|
+
) {
|
|
4050
|
+
continue;
|
|
4051
|
+
}
|
|
4052
|
+
if (
|
|
4053
|
+
mutation.attributeName === "label" ||
|
|
4054
|
+
mutation.attributeName === "direction"
|
|
4055
|
+
) {
|
|
4056
|
+
syncField = true;
|
|
4057
|
+
} else {
|
|
4058
|
+
syncSlider = true;
|
|
4059
|
+
}
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
|
|
4063
|
+
if (syncField) this.#syncField();
|
|
4064
|
+
if (syncSlider) this.#syncSliderAttributes();
|
|
4065
|
+
});
|
|
4066
|
+
}
|
|
4067
|
+
|
|
4068
|
+
this.#observer.observe(this, { attributes: true });
|
|
4069
|
+
}
|
|
4070
|
+
|
|
4071
|
+
disconnectedCallback() {
|
|
4072
|
+
this.#observer?.disconnect();
|
|
4073
|
+
this.#unbindSliderEvents();
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4076
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
4077
|
+
if (oldValue === newValue || !this.#field) return;
|
|
4078
|
+
if (name === "label" || name === "direction") {
|
|
4079
|
+
this.#syncField();
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
|
|
4083
|
+
#initialize() {
|
|
4084
|
+
const initialChildren = Array.from(this.childNodes).filter((node) => {
|
|
4085
|
+
return (
|
|
4086
|
+
node.nodeType !== Node.TEXT_NODE || Boolean(node.textContent?.trim())
|
|
4087
|
+
);
|
|
4088
|
+
});
|
|
4089
|
+
|
|
4090
|
+
const field = document.createElement("fig-field");
|
|
4091
|
+
const label = document.createElement("label");
|
|
4092
|
+
const slider = document.createElement("fig-slider");
|
|
4093
|
+
slider.setAttribute("text", "true");
|
|
4094
|
+
for (const attrName of this.#getForwardedSliderAttrNames()) {
|
|
4095
|
+
const value = this.getAttribute(attrName);
|
|
4096
|
+
slider.setAttribute(attrName, value ?? "");
|
|
4097
|
+
}
|
|
4098
|
+
|
|
4099
|
+
field.append(label, slider);
|
|
4100
|
+
|
|
4101
|
+
this.#field = field;
|
|
4102
|
+
this.#label = label;
|
|
4103
|
+
this.#slider = slider;
|
|
4104
|
+
|
|
4105
|
+
this.replaceChildren(field);
|
|
4106
|
+
|
|
4107
|
+
for (const node of initialChildren) {
|
|
4108
|
+
this.#slider.appendChild(node);
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
4111
|
+
|
|
4112
|
+
#syncField() {
|
|
4113
|
+
if (!this.#field || !this.#label) return;
|
|
4114
|
+
const hasLabelAttr = this.hasAttribute("label");
|
|
4115
|
+
const rawLabel = this.getAttribute("label");
|
|
4116
|
+
const isBlankLabel = hasLabelAttr && (rawLabel ?? "").trim() === "";
|
|
4117
|
+
|
|
4118
|
+
if (isBlankLabel) {
|
|
4119
|
+
if (this.#label.parentElement === this.#field) {
|
|
4120
|
+
this.#label.remove();
|
|
4121
|
+
}
|
|
4122
|
+
} else {
|
|
4123
|
+
this.#label.textContent = hasLabelAttr ? rawLabel ?? "" : "Label";
|
|
4124
|
+
if (this.#label.parentElement !== this.#field) {
|
|
4125
|
+
this.#field.prepend(this.#label);
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
|
|
4129
|
+
this.#field.setAttribute(
|
|
4130
|
+
"direction",
|
|
4131
|
+
this.getAttribute("direction") || "horizontal",
|
|
4132
|
+
);
|
|
4133
|
+
}
|
|
4134
|
+
|
|
4135
|
+
#syncSliderAttributes() {
|
|
4136
|
+
if (!this.#slider) return;
|
|
4137
|
+
const hostAttrs = this.#getForwardedSliderAttrNames();
|
|
4138
|
+
|
|
4139
|
+
const nextManaged = new Set(hostAttrs.filter((name) => name !== "text"));
|
|
4140
|
+
|
|
4141
|
+
for (const attrName of this.#managedSliderAttrs) {
|
|
4142
|
+
if (!nextManaged.has(attrName)) {
|
|
4143
|
+
this.#slider.removeAttribute(attrName);
|
|
4144
|
+
}
|
|
4145
|
+
}
|
|
4146
|
+
|
|
4147
|
+
for (const attrName of hostAttrs) {
|
|
4148
|
+
if (attrName === "text") continue;
|
|
4149
|
+
const value = this.getAttribute(attrName);
|
|
4150
|
+
this.#slider.setAttribute(attrName, value ?? "");
|
|
4151
|
+
}
|
|
4152
|
+
|
|
4153
|
+
this.#slider.removeAttribute("variant");
|
|
4154
|
+
this.#slider.removeAttribute("color");
|
|
4155
|
+
this.#slider.removeAttribute("transform");
|
|
4156
|
+
this.#slider.removeAttribute("full");
|
|
4157
|
+
this.#slider.setAttribute("text", "true");
|
|
4158
|
+
|
|
4159
|
+
const sliderType = (this.getAttribute("type") || "range").toLowerCase();
|
|
4160
|
+
if (sliderType === "delta" || sliderType === "stepper") {
|
|
4161
|
+
this.#slider.setAttribute(
|
|
4162
|
+
"default",
|
|
4163
|
+
this.getAttribute("default") ?? "50",
|
|
4164
|
+
);
|
|
4165
|
+
} else if (!this.hasAttribute("default")) {
|
|
4166
|
+
this.#slider.removeAttribute("default");
|
|
4167
|
+
}
|
|
4168
|
+
if (sliderType === "stepper") {
|
|
4169
|
+
this.#slider.setAttribute("step", this.getAttribute("step") ?? "10");
|
|
4170
|
+
} else if (!this.hasAttribute("step")) {
|
|
4171
|
+
this.#slider.removeAttribute("step");
|
|
4172
|
+
}
|
|
4173
|
+
if (sliderType === "opacity") {
|
|
4174
|
+
this.#slider.style.setProperty(
|
|
4175
|
+
"--color",
|
|
4176
|
+
"var(--figma-color-bg-tertiary)",
|
|
4177
|
+
);
|
|
4178
|
+
} else {
|
|
4179
|
+
this.#slider.style.removeProperty("--color");
|
|
4180
|
+
}
|
|
4181
|
+
|
|
4182
|
+
this.#managedSliderAttrs = nextManaged;
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
#getForwardedSliderAttrNames() {
|
|
4186
|
+
const reserved = new Set(["label", "direction", "oninput", "onchange"]);
|
|
4187
|
+
return this.getAttributeNames().filter(
|
|
4188
|
+
(name) => !reserved.has(name) && !this.#ignoredSliderAttrs.has(name),
|
|
4189
|
+
);
|
|
4190
|
+
}
|
|
4191
|
+
|
|
4192
|
+
#bindSliderEvents() {
|
|
4193
|
+
if (!this.#slider) return;
|
|
4194
|
+
if (!this.#boundHandleSliderInput) {
|
|
4195
|
+
this.#boundHandleSliderInput = this.#forwardSliderEvent.bind(
|
|
4196
|
+
this,
|
|
4197
|
+
"input",
|
|
4198
|
+
);
|
|
4199
|
+
}
|
|
4200
|
+
if (!this.#boundHandleSliderChange) {
|
|
4201
|
+
this.#boundHandleSliderChange = this.#forwardSliderEvent.bind(
|
|
4202
|
+
this,
|
|
4203
|
+
"change",
|
|
4204
|
+
);
|
|
4205
|
+
}
|
|
4206
|
+
this.#slider.addEventListener("input", this.#boundHandleSliderInput);
|
|
4207
|
+
this.#slider.addEventListener("change", this.#boundHandleSliderChange);
|
|
4208
|
+
}
|
|
4209
|
+
|
|
4210
|
+
#unbindSliderEvents() {
|
|
4211
|
+
if (!this.#slider) return;
|
|
4212
|
+
if (this.#boundHandleSliderInput) {
|
|
4213
|
+
this.#slider.removeEventListener("input", this.#boundHandleSliderInput);
|
|
4214
|
+
}
|
|
4215
|
+
if (this.#boundHandleSliderChange) {
|
|
4216
|
+
this.#slider.removeEventListener("change", this.#boundHandleSliderChange);
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
|
|
4220
|
+
#forwardSliderEvent(type, event) {
|
|
4221
|
+
event.stopPropagation();
|
|
4222
|
+
const detail =
|
|
4223
|
+
event instanceof CustomEvent && event.detail !== undefined
|
|
4224
|
+
? event.detail
|
|
4225
|
+
: this.#slider?.value;
|
|
4226
|
+
this.dispatchEvent(
|
|
4227
|
+
new CustomEvent(type, {
|
|
4228
|
+
detail,
|
|
4229
|
+
bubbles: true,
|
|
4230
|
+
cancelable: true,
|
|
4231
|
+
composed: true,
|
|
4232
|
+
}),
|
|
4233
|
+
);
|
|
4234
|
+
}
|
|
4235
|
+
}
|
|
4236
|
+
customElements.define("fig-field-slider", FigFieldSlider);
|
|
4237
|
+
|
|
4015
4238
|
/* Color swatch */
|
|
4016
4239
|
class FigInputColor extends HTMLElement {
|
|
4017
4240
|
rgba;
|
|
@@ -5803,9 +6026,15 @@ class FigImage extends HTMLElement {
|
|
|
5803
6026
|
super();
|
|
5804
6027
|
}
|
|
5805
6028
|
#getInnerHTML() {
|
|
5806
|
-
const cb =
|
|
5807
|
-
|
|
5808
|
-
|
|
6029
|
+
const cb =
|
|
6030
|
+
this.hasAttribute("checkerboard") &&
|
|
6031
|
+
this.getAttribute("checkerboard") !== "false";
|
|
6032
|
+
const bg = this.src
|
|
6033
|
+
? `url(${this.src})`
|
|
6034
|
+
: cb
|
|
6035
|
+
? "url()"
|
|
6036
|
+
: "var(--figma-color-bg-secondary)";
|
|
6037
|
+
return `<fig-chit size="large" data-type="image" background="${bg}" disabled${cb ? " checkerboard" : ""}></fig-chit><div>${
|
|
5809
6038
|
this.upload
|
|
5810
6039
|
? `<fig-button variant="overlay" type="upload">
|
|
5811
6040
|
${this.label}
|
|
@@ -5980,11 +6209,16 @@ class FigImage extends HTMLElement {
|
|
|
5980
6209
|
if (name === "src") {
|
|
5981
6210
|
this.#src = newValue;
|
|
5982
6211
|
if (this.chit) {
|
|
5983
|
-
const hasCb =
|
|
6212
|
+
const hasCb =
|
|
6213
|
+
this.hasAttribute("checkerboard") &&
|
|
6214
|
+
this.getAttribute("checkerboard") !== "false";
|
|
5984
6215
|
if (this.#src) {
|
|
5985
6216
|
this.chit.setAttribute("background", `url(${this.#src})`);
|
|
5986
6217
|
} else {
|
|
5987
|
-
this.chit.setAttribute(
|
|
6218
|
+
this.chit.setAttribute(
|
|
6219
|
+
"background",
|
|
6220
|
+
hasCb ? "url()" : "var(--figma-color-bg-secondary)",
|
|
6221
|
+
);
|
|
5988
6222
|
}
|
|
5989
6223
|
}
|
|
5990
6224
|
if (this.#src) {
|
package/package.json
CHANGED