@rogieking/figui3 1.0.37 → 1.0.39

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.
Files changed (4) hide show
  1. package/example.html +29 -4
  2. package/fig.css +60 -9
  3. package/fig.js +181 -32
  4. package/package.json +1 -1
package/example.html CHANGED
@@ -69,10 +69,35 @@
69
69
  </fig-tooltip>
70
70
  </hstack>
71
71
  <br />
72
- <fig-dropdown>
73
- <option>One</option>
74
- <option>Two</option>
75
- </fig-dropdown>
72
+ <fig-field direction="horizontal">
73
+ <label>Dropdown</label>
74
+ <fig-dropdown>
75
+ <option>One</option>
76
+ <option>Two</option>
77
+ </fig-dropdown>
78
+ </fig-field>
79
+ <br />
80
+ <fig-combo-input options="House, Apartment, Condo, Other"
81
+ placeholder="Type of residence">
82
+
83
+ </fig-combo-input>
84
+ <br /><br />
85
+ <hstack>
86
+ <fig-chit type="color"
87
+ disabled="true"
88
+ value="#00FF00"></fig-chit>
89
+ <fig-chit type="color"
90
+ disabled="true"
91
+ value="#FF0000"></fig-chit>
92
+ <fig-chit type="image"
93
+ disabled="true"
94
+ size="large"
95
+ src="https://avatars.githubusercontent.com/u/12345678?v=4"></fig-chit>
96
+ <fig-chit type="image"
97
+ disabled="true"
98
+ size="large"
99
+ src="https://img.freepik.com/free-vector/gradient-grainy-gradient-background_23-2149922133.jpg?semt=ais_hybrid"></fig-chit>
100
+ </hstack>
76
101
  <br />
77
102
  <fig-tooltip text="Tooltip text">
78
103
  <p>Tooltip</p>
package/fig.css CHANGED
@@ -420,16 +420,19 @@
420
420
 
421
421
  color-scheme: light dark;
422
422
  /* Icons */
423
- --icon-chevron: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.87868 7.12132L8 9.24264L10.1213 7.12132' stroke='rgb(0 0 0 / 50%)' stroke-linecap='round'/%3E%3C/svg%3E%0A");
423
+ --icon-chevron: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.87868 7.12132L8 9.24264L10.1213 7.12132' stroke='rgb(0 0 0 / 90%)' stroke-linecap='round'/%3E%3C/svg%3E%0A");
424
424
 
425
425
  /* Elevations */
426
426
  --figma-elevation-100: 0px 0px 0.5px 0px rgba(0, 0, 0, 0.3),
427
427
  0px 1px 3px 0px rgba(0, 0, 0, 0.15);
428
+
429
+ --figma-elevation-200: 0px 1px 3px 0px rgba(0, 0, 0, 0.102),
430
+ 0px 3px 8px 0px rgba(0, 0, 0, 0.102), 0px 0px 0.5px 0px rgba(0, 0, 0, 0.18);
428
431
  }
429
432
 
430
433
  @media (prefers-color-scheme: dark) {
431
434
  :root {
432
- --icon-chevron: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.87868 7.12132L8 9.24264L10.1213 7.12132' stroke='rgb(255 255 255 / 50%)' stroke-linecap='round'/%3E%3C/svg%3E%0A");
435
+ --icon-chevron: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.87868 7.12132L8 9.24264L10.1213 7.12132' stroke='rgb(255 255 255 / 100%)' stroke-linecap='round'/%3E%3C/svg%3E%0A");
433
436
  --handle-shadow: 0px 0 0 0.75px rgba(255, 255, 255, 0.1),
434
437
  0px 0px 0.5px 0px rgba(255, 255, 255, 0.1);
435
438
  --figma-color-bg-ghost-hover: rgba(255, 255, 255, 0.05);
@@ -684,6 +687,12 @@ fig-button {
684
687
  }
685
688
  }
686
689
 
690
+ /* Variant: Input */
691
+ &[variant="input"] {
692
+ background-color: var(--figma-color-bg-secondary);
693
+ box-shadow: none;
694
+ }
695
+
687
696
  /* Icon only */
688
697
  &[icon],
689
698
  &[icon] > button {
@@ -876,15 +885,15 @@ fig-avatar::after,
876
885
 
877
886
  /* Color input */
878
887
  input[type="color"] {
879
- width: 14px;
880
- height: 14px;
888
+ width: 0.875rem;
889
+ height: 0.875rem;
881
890
  -webkit-appearance: none;
882
891
  appearance: none;
883
892
  border: 0;
884
893
  padding: 0;
885
894
  margin: 0;
886
895
  background: none;
887
- padding: 5px;
896
+ padding: 0.3125rem;
888
897
  flex-shrink: 0;
889
898
  box-sizing: content-box;
890
899
  border-radius: var(--radius-medium);
@@ -928,6 +937,49 @@ input[type="color"]::-webkit-color-swatch {
928
937
  );
929
938
  }
930
939
 
940
+ fig-chit {
941
+ display: inline-grid;
942
+ width: 1.5rem;
943
+ height: 1.5rem;
944
+ border-radius: var(--radius-medium);
945
+
946
+ &[size="large"] {
947
+ width: 1.75rem;
948
+ height: 1.75rem;
949
+
950
+ &[type="image"]::after,
951
+ input[type="color"] {
952
+ padding: 0;
953
+ width: 1.75rem;
954
+ height: 1.75rem;
955
+ border-radius: var(--radius-medium);
956
+ }
957
+ }
958
+
959
+ &[type="image"] {
960
+ &::after {
961
+ content: "";
962
+ width: 0.875rem;
963
+ height: 0.875rem;
964
+ background-image: var(--src);
965
+ border-radius: 0.125rem;
966
+ background-size: cover;
967
+ box-shadow: inset 0 0 0 1px var(--figma-color-bordertranslucent);
968
+ }
969
+ &::after,
970
+ input {
971
+ grid-area: 1/1;
972
+ place-self: center;
973
+ }
974
+ input[type="color"]::-webkit-color-swatch-wrapper {
975
+ background: none;
976
+ }
977
+ input[type="color"]::-webkit-color-swatch {
978
+ opacity: 0;
979
+ }
980
+ }
981
+ }
982
+
931
983
  /* Combo input */
932
984
  .input-combo {
933
985
  display: inline-flex;
@@ -1240,9 +1292,7 @@ fig-slider {
1240
1292
  --slider-tick-size: calc(var(--slider-height) / 4);
1241
1293
  --slider-handle-shadow: inset 0 0 0 calc(4px + 0.5rem * var(--unchanged))
1242
1294
  var(--figma-color-icon-onbrand),
1243
- inset 0 0 0 5px rgba(0, 0, 0, 0.1), 0px 0 0 0.75px rgba(0, 0, 0, 0.1),
1244
- 0px 1px 3px 0px rgba(0, 0, 0, 0.1), 0px 3px 8px 0px rgba(0, 0, 0, 0.1),
1245
- 0px 0px 0.5px 0px rgba(0, 0, 0, 0.18);
1295
+ inset 0 0 0 5px rgba(0, 0, 0, 0.1), var(--figma-elevation-200);
1246
1296
  --slider-handle-shadow-focus: inset 0 0 0 4px var(--figma-color-icon-onbrand),
1247
1297
  inset 0 0 0 5px rgba(0, 0, 0, 0.1), 0px 0 0 0.75px rgba(0, 0, 0, 0.1),
1248
1298
  0px 1px 3px 0px rgba(0, 0, 0, 0.1), 0px 3px 8px 0px rgba(0, 0, 0, 0.1),
@@ -1808,16 +1858,17 @@ fig-input-text {
1808
1858
  & [slot] {
1809
1859
  user-select: none;
1810
1860
  width: 1.5rem;
1811
- margin-right: calc(var(--spacer-2) * -1);
1812
1861
  color: var(--figma-color-text-secondary);
1813
1862
  }
1814
1863
 
1815
1864
  & [slot="prepend"] {
1816
1865
  padding-right: 0;
1866
+ margin-right: calc(var(--spacer-2) * -1);
1817
1867
  }
1818
1868
 
1819
1869
  & [slot="append"] {
1820
1870
  padding-left: 0;
1871
+ margin-left: calc(var(--spacer-2) * -1);
1821
1872
  }
1822
1873
 
1823
1874
  & input {
package/fig.js CHANGED
@@ -96,10 +96,8 @@ class FigDropdown extends HTMLElement {
96
96
  }
97
97
 
98
98
  connectedCallback() {
99
- this.render();
100
- }
101
-
102
- render() {
99
+ this.type = this.getAttribute("type") || "select";
100
+ this.value = this.getAttribute("value") || "";
103
101
  this.select = document.createElement("select");
104
102
  this.optionsSlot = document.createElement("slot");
105
103
 
@@ -108,16 +106,38 @@ class FigDropdown extends HTMLElement {
108
106
 
109
107
  // Move slotted options into the select element
110
108
  this.optionsSlot.addEventListener("slotchange", this.slotChange.bind(this));
109
+
110
+ this.select.addEventListener("input", this.handleDropdownInput.bind(this));
111
111
  }
112
+
112
113
  slotChange() {
113
114
  while (this.select.firstChild) {
114
115
  this.select.firstChild.remove();
115
116
  }
116
- this.optionsSlot.assignedNodes().forEach((node) => {
117
- if (node.nodeName === "OPTION") {
118
- this.select.appendChild(node.cloneNode(true));
117
+ if (this.type === "dropdown") {
118
+ const hiddenOption = document.createElement("option");
119
+ hiddenOption.setAttribute("hidden", "true");
120
+ hiddenOption.setAttribute("selected", "true");
121
+ this.select.appendChild(hiddenOption);
122
+ }
123
+ this.optionsSlot.assignedNodes().forEach((option) => {
124
+ if (option.nodeName === "OPTION") {
125
+ if (option.hasAttribute("value") && option.hasAttribute("selected")) {
126
+ this.value = option.getAttribute("value");
127
+ }
128
+ this.select.appendChild(option.cloneNode(true));
119
129
  }
120
130
  });
131
+ if (this.type === "dropdown") {
132
+ this.select.selectedIndex = -1;
133
+ }
134
+ }
135
+ handleDropdownInput() {
136
+ if (this.type === "dropdown") {
137
+ this.value = this.select.value;
138
+ this.setAttribute("value", this.value);
139
+ this.select.selectedIndex = -1;
140
+ }
121
141
  }
122
142
  }
123
143
 
@@ -318,7 +338,6 @@ class FigDialog extends HTMLElement {
318
338
 
319
339
  /* Public methods */
320
340
  show() {
321
- console.log("show dialog", this.dialog, this.dialog?.show);
322
341
  this.dialog.show();
323
342
  }
324
343
  close() {
@@ -682,7 +701,6 @@ class FigSlider extends HTMLElement {
682
701
 
683
702
  handleInput() {
684
703
  let val = Number(this.input.value);
685
- console.log(val);
686
704
  this.value = val;
687
705
  let complete = this.calculateNormal(val);
688
706
  let defaultValue = this.calculateNormal(this.default);
@@ -702,7 +720,7 @@ class FigInputText extends HTMLElement {
702
720
  }
703
721
  connectedCallback() {
704
722
  this.multiline = this.hasAttribute("multiline") || false;
705
- this.value = this.getAttribute("value");
723
+ this.value = this.getAttribute("value") || "";
706
724
  this.type = this.getAttribute("type") || "text";
707
725
  this.placeholder = this.getAttribute("placeholder");
708
726
 
@@ -714,14 +732,13 @@ class FigInputText extends HTMLElement {
714
732
  html = `<textarea
715
733
  placeholder="${this.placeholder}">${this.value}</textarea>`;
716
734
  }
717
- this.innerHTML = html;
718
735
 
719
736
  //child nodes hack
720
737
  requestAnimationFrame(() => {
721
738
  const append = this.querySelector("[slot=append]");
722
739
  const prepend = this.querySelector("[slot=prepend]");
723
740
 
724
- console.log(append, prepend);
741
+ this.innerHTML = html;
725
742
 
726
743
  if (prepend) {
727
744
  prepend.addEventListener("click", this.focus.bind(this));
@@ -819,7 +836,7 @@ class FigAvatar extends HTMLElement {
819
836
  attributeChangedCallback(name, oldValue, newValue) {
820
837
  this[name] = newValue;
821
838
  if (name === "name") {
822
- this.img.setAttribute("alt", newValue);
839
+ this.img?.setAttribute("alt", newValue);
823
840
  this.name = newValue;
824
841
  this.initials = this.getInitials(this.name);
825
842
  this.setAttribute("initials", this.initials);
@@ -894,36 +911,38 @@ class FigInputColor extends HTMLElement {
894
911
  </fig-tooltip>`;
895
912
  }
896
913
  html = `<div class="input-combo">
897
- <input type="color" value="${this.value}" />
914
+ <fig-chit type="color" disabled="false" value="${this.value}"></fig-chit>
898
915
  ${label}
899
916
  </div>`;
900
917
  } else {
901
- html = `<input type="color" value="${this.value}" />`;
918
+ html = `<fig-chit type="color" disabled="false" value="${this.value}"></fig-chit>`;
902
919
  }
903
920
  this.innerHTML = html;
904
921
 
905
922
  this.style.setProperty("--alpha", this.#rgba.a);
906
923
 
907
- this.#swatch = this.querySelector("[type=color]");
908
- this.textInput = this.querySelector("[type=text]");
909
- this.#alphaInput = this.querySelector("[type=number]");
924
+ requestAnimationFrame(() => {
925
+ this.#swatch = this.querySelector("input[type=color]");
926
+ this.textInput = this.querySelector("input[type=text]");
927
+ this.#alphaInput = this.querySelector("input[type=number]");
910
928
 
911
- this.#swatch.disabled = this.hasAttribute("disabled");
912
- this.#swatch.addEventListener("input", this.handleInput.bind(this));
929
+ this.#swatch.disabled = this.hasAttribute("disabled");
930
+ this.#swatch.addEventListener("input", this.handleInput.bind(this));
913
931
 
914
- if (this.textInput) {
915
- this.textInput.value = this.#swatch.value = this.rgbAlphaToHex(
916
- this.#rgba,
917
- 1
918
- );
919
- }
932
+ if (this.textInput) {
933
+ this.textInput.value = this.#swatch.value = this.rgbAlphaToHex(
934
+ this.#rgba,
935
+ 1
936
+ );
937
+ }
920
938
 
921
- if (this.#alphaInput) {
922
- this.#alphaInput.addEventListener(
923
- "input",
924
- this.handleAlphaInput.bind(this)
925
- );
926
- }
939
+ if (this.#alphaInput) {
940
+ this.#alphaInput.addEventListener(
941
+ "input",
942
+ this.handleAlphaInput.bind(this)
943
+ );
944
+ }
945
+ });
927
946
  }
928
947
  handleAlphaInput(event) {
929
948
  //do not propagate to onInput handler for web component
@@ -1176,3 +1195,133 @@ class FigSwitch extends FigCheckbox {
1176
1195
  }
1177
1196
  }
1178
1197
  window.customElements.define("fig-switch", FigSwitch);
1198
+
1199
+ /* Bell */
1200
+ class FigBell extends HTMLElement {
1201
+ constructor() {
1202
+ super();
1203
+ }
1204
+ }
1205
+ window.customElements.define("fig-bell", FigBell);
1206
+
1207
+ /* Badge */
1208
+ class FigBadge extends HTMLElement {
1209
+ constructor() {
1210
+ super();
1211
+ }
1212
+ }
1213
+ window.customElements.define("fig-badge", FigBadge);
1214
+
1215
+ /* Accordion */
1216
+ class FigAccordion extends HTMLElement {
1217
+ constructor() {
1218
+ super();
1219
+ }
1220
+ }
1221
+ window.customElements.define("fig-accordion", FigAccordion);
1222
+
1223
+ /* Combo Input */
1224
+ class FigComboInput extends HTMLElement {
1225
+ constructor() {
1226
+ super();
1227
+ }
1228
+ getOptionsFromAttribute() {
1229
+ return (this.getAttribute("options") || "").split(",");
1230
+ }
1231
+ connectedCallback() {
1232
+ this.options = this.getOptionsFromAttribute();
1233
+ this.placeholder = this.getAttribute("placeholder") || "";
1234
+ this.value = this.getAttribute("value") || "";
1235
+ this.innerHTML = `<div class="input-combo">
1236
+ <fig-input-text placeholder="${this.placeholder}">
1237
+ </fig-input-text>
1238
+ <fig-button type="select" variant="input" icon>
1239
+ <svg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
1240
+ <path d='M5.87868 7.12132L8 9.24264L10.1213 7.12132' stroke='currentColor' stroke-opacity="0.9" stroke-linecap='round'/>
1241
+ </svg>
1242
+ <fig-dropdown type="dropdown">
1243
+ ${this.options
1244
+ .map((option) => `<option>${option}</option>`)
1245
+ .join("")}
1246
+ </fig-dropdown>
1247
+ </fig-button>
1248
+ </div>`;
1249
+ requestAnimationFrame(() => {
1250
+ this.input = this.querySelector("fig-input-text");
1251
+ this.select = this.querySelector("fig-dropdown");
1252
+
1253
+ this.select.addEventListener("input", this.handleSelectInput.bind(this));
1254
+ });
1255
+ }
1256
+ handleSelectInput(e) {
1257
+ this.value = e.target.parentNode.value;
1258
+ this.setAttribute("value", this.value);
1259
+ }
1260
+ handleInput(e) {
1261
+ this.value = this.input.value;
1262
+ }
1263
+ static get observedAttributes() {
1264
+ return ["options", "placeholder", "value"];
1265
+ }
1266
+ attributeChangedCallback(name, oldValue, newValue) {
1267
+ if (name === "options") {
1268
+ this.options = newValue.split(",");
1269
+ if (this.dropdown) {
1270
+ this.dropdown.innerHTML = this.options
1271
+ .map((option) => `<option>${option}</option>`)
1272
+ .join("");
1273
+ }
1274
+ }
1275
+ if (name === "placeholder") {
1276
+ this.placeholder = newValue;
1277
+ }
1278
+ if (name === "value") {
1279
+ this.value = newValue;
1280
+ this.input.setAttribute("value", newValue);
1281
+ }
1282
+ }
1283
+ }
1284
+ window.customElements.define("fig-combo-input", FigComboInput);
1285
+
1286
+ /* Chit */
1287
+ class FigChit extends HTMLElement {
1288
+ constructor() {
1289
+ super();
1290
+ }
1291
+ connectedCallback() {
1292
+ this.type = this.getAttribute("type") || "color";
1293
+ this.src = this.getAttribute("src") || "";
1294
+ this.value = this.getAttribute("value") || "";
1295
+ this.size = this.getAttribute("size") || "small";
1296
+ this.disabled = this.getAttribute("disabled") === "true" ? true : false;
1297
+ this.variant = this.getAttribute("variant") || "square";
1298
+ this.innerHTML = `<input type="color" value="${this.value}" />`;
1299
+
1300
+ requestAnimationFrame(() => {
1301
+ this.input = this.querySelector("input");
1302
+ this.input.disabled = this.disabled;
1303
+ this.updateSrc(this.src);
1304
+ });
1305
+ }
1306
+ updateSrc(src) {
1307
+ if (src) {
1308
+ this.src = src;
1309
+ this.style.setProperty("--src", `url(${src})`);
1310
+ } else {
1311
+ this.style.removeProperty("--src");
1312
+ }
1313
+ }
1314
+ static get observedAttributes() {
1315
+ return ["type", "src", "size", "variant", "value", "disabled"];
1316
+ }
1317
+ attributeChangedCallback(name, oldValue, newValue) {
1318
+ if (name === "src") {
1319
+ this.updateSrc(newValue);
1320
+ }
1321
+ if (name === "disabled") {
1322
+ this.disabled = newValue.toLowerCase() === "true";
1323
+ this.input.disabled = this.disabled;
1324
+ }
1325
+ }
1326
+ }
1327
+ window.customElements.define("fig-chit", FigChit);
package/package.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "1.0.37"
3
+ "version": "1.0.39"
4
4
  }