@rogieking/figui3 4.1.0 → 4.1.3

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/base.css CHANGED
@@ -32,6 +32,7 @@ h3 {
32
32
  hr {
33
33
  height: 1px;
34
34
  border: none;
35
+ width: 100%;
35
36
  background-color: var(--figma-color-border);
36
37
  margin: var(--spacer-2) 0;
37
38
 
package/components.css CHANGED
@@ -319,7 +319,7 @@
319
319
  );
320
320
 
321
321
  /* Icons - colorless shapes for use with mask-image */
322
- --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='black' stroke-linecap='round'/%3E%3C/svg%3E%0A");
322
+ --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='grey' stroke-linecap='round'/%3E%3C/svg%3E%0A");
323
323
  --icon-checkmark: 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='M11.084 4.22266C11.2372 3.99292 11.5476 3.93084 11.7773 4.08398C12.0071 4.23716 12.0692 4.54758 11.916 4.77734L7.91602 10.7773C7.83292 10.902 7.6979 10.9833 7.54883 10.998C7.39993 11.0126 7.25229 10.9593 7.14648 10.8535L4.14648 7.85352C3.95126 7.65825 3.95123 7.34173 4.14648 7.14648C4.34174 6.95124 4.65825 6.95126 4.85352 7.14648L7.42188 9.71484L11.084 4.22266Z' fill='white'/%3E%3C/svg%3E%0A");
324
324
  --icon-reset: url("data:image/svg+xml,%3Csvg width='16' height='16' fill='none' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='black' fill-rule='evenodd' d='M6.354 2.146a.5.5 0 0 1 0 .708L5.207 4H8.5a5 5 0 1 1-5 5 .5.5 0 0 1 1 0 4 4 0 1 0 4-4H5.207l1.147 1.146a.5.5 0 1 1-.708.708l-2-2a.5.5 0 0 1 0-.708l2-2a.5.5 0 0 1 .708 0' clip-rule='evenodd'/%3E%3C/svg%3E");
325
325
  --icon-steppers: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11.7245 6.08191C11.9186 5.95386 12.1826 5.97562 12.3534 6.14637L14.3534 8.14637L14.4179 8.22449C14.546 8.41852 14.5242 8.68253 14.3534 8.8534C14.1826 9.02426 13.9186 9.04601 13.7245 8.91785L13.6464 8.8534L11.9999 7.20691L10.3534 8.8534C10.1582 9.04866 9.84166 9.04866 9.6464 8.8534C9.45123 8.65813 9.45117 8.3416 9.6464 8.14637L11.6464 6.14637L11.7245 6.08191Z' fill='black'/%3E%3Cpath d='M13.7248 15.0822C13.9189 14.9541 14.1829 14.9758 14.3537 15.1467C14.5246 15.3176 14.5463 15.5815 14.4182 15.7756L14.3537 15.8537L12.3537 17.8537C12.1829 18.0246 11.9189 18.0463 11.7248 17.9182L11.6467 17.8537L9.64669 15.8537L9.58224 15.7756C9.45407 15.5815 9.47583 15.3176 9.64669 15.1467C9.81756 14.9758 10.0815 14.9541 10.2756 15.0822L10.3537 15.1467L12.0002 16.7932L13.6467 15.1467L13.7248 15.0822Z' fill='black' /%3E%3C/svg%3E%0A");
@@ -481,10 +481,12 @@ input[type="text"][list] {
481
481
  display: flex;
482
482
  appearance: none;
483
483
  align-items: center;
484
- flex: 1 0 0;
485
484
  border: 0;
486
485
  color: var(--figma-color-text);
487
486
  background-color: var(--figma-color-bg);
487
+ background: calc(100% - var(--spacer-1)) 50% / 1rem no-repeat
488
+ var(--icon-chevron);
489
+
488
490
  box-shadow: inset 0 0 0 1px var(--figma-color-border);
489
491
  accent-color: var(--figma-color-bg-brand);
490
492
  overflow: hidden;
@@ -637,7 +639,7 @@ input[type="text"][list] {
637
639
  padding-left: 0;
638
640
  }
639
641
  & > button {
640
- display: flex;
642
+ display: inline-block;
641
643
  align-items: center;
642
644
  gap: var(--spacer-1);
643
645
  width: 100%;
@@ -696,14 +698,16 @@ select {
696
698
  }
697
699
 
698
700
  /* Dropdown */
701
+ fig-dropdown {
702
+ & > *:not(select) {
703
+ display: none !important;
704
+ }
705
+ }
699
706
  fig-dropdown,
707
+ select,
700
708
  .fig-dropdown {
701
709
  display: inline-flex;
702
710
  position: relative;
703
-
704
- & > *:not(select) {
705
- display: none !important;
706
- }
707
711
  > select {
708
712
  display: flex;
709
713
  align-items: center;
@@ -736,6 +740,7 @@ fig-dropdown,
736
740
 
737
741
  /* Button */
738
742
  .fig-button,
743
+ button,
739
744
  fig-button {
740
745
  color: var(--figma-color-text-onbrand);
741
746
  display: flex;
@@ -939,7 +944,7 @@ fig-button {
939
944
  box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
940
945
  }
941
946
  svg {
942
- *[fill] {
947
+ *[fill]:not([fill="none"]) {
943
948
  fill: currentColor;
944
949
  }
945
950
  *[stroke]:not([stroke="none"]) {
@@ -2036,6 +2041,7 @@ input[type="checkbox"].switch:checked:focus {
2036
2041
  /* Checkbox */
2037
2042
  input[type="checkbox"]:not(.switch) {
2038
2043
  contain: strict;
2044
+ vertical-align: middle;
2039
2045
  --size: 1rem;
2040
2046
  appearance: none;
2041
2047
  border-radius: var(--radius-medium);
@@ -2170,11 +2176,7 @@ fieldset {
2170
2176
  padding: var(--spacer-2) 0;
2171
2177
 
2172
2178
  & > legend {
2173
- margin-top: 0.125rem;
2174
- font-weight: 500;
2175
- font-size: 0.625rem;
2176
- line-height: 0.875rem;
2177
- color: var(--figma-color-text-secondary);
2179
+ padding: 0;
2178
2180
  }
2179
2181
 
2180
2182
  & > label {
@@ -2188,6 +2190,9 @@ fieldset {
2188
2190
 
2189
2191
  /* Details */
2190
2192
  details {
2193
+ padding: 0 var(--spacer-3);
2194
+ display: block;
2195
+ width: 100%;
2191
2196
  & > summary {
2192
2197
  font-weight: var(--body-medium-strong-fontWeight);
2193
2198
  cursor: default;
@@ -2197,6 +2202,7 @@ details {
2197
2202
  height: var(--spacer-5);
2198
2203
  user-select: none;
2199
2204
  color: var(--figma-color-text-secondary);
2205
+ margin-left: calc(var(--spacer-3) * -1);
2200
2206
 
2201
2207
  &::before {
2202
2208
  content: "";
@@ -2722,6 +2728,9 @@ dialog[is="fig-popup"] {
2722
2728
  background-color: var(--figma-color-bg-menu);
2723
2729
  color: var(--figma-color-text-menu);
2724
2730
  color-scheme: dark;
2731
+ padding: var(--spacer-2) 0;
2732
+ min-width: 6rem;
2733
+ box-shadow: var(--figma-elevation-100);
2725
2734
  }
2726
2735
 
2727
2736
  &[variant="popover"] {
@@ -3887,12 +3896,13 @@ fig-joystick {
3887
3896
 
3888
3897
  /* Layer */
3889
3898
  fig-layer {
3890
- --indent: var(--spacer-2);
3899
+ --indent: var(--spacer-3);
3891
3900
  display: block;
3892
3901
  color: var(--figma-color-text);
3893
3902
  position: relative;
3894
3903
  user-select: none;
3895
3904
  width: 100%;
3905
+ padding: 0 var(--spacer-3);
3896
3906
  border-radius: var(--radius-medium);
3897
3907
 
3898
3908
  /* When layer has children */
@@ -3909,7 +3919,6 @@ fig-layer {
3909
3919
  align-items: center;
3910
3920
  gap: var(--spacer-1);
3911
3921
  padding: var(--spacer-1) var(--spacer-2);
3912
- margin-left: 0;
3913
3922
  height: var(--spacer-4);
3914
3923
  border-radius: var(--radius-medium);
3915
3924
  position: relative;
@@ -3975,8 +3984,11 @@ fig-layer {
3975
3984
 
3976
3985
  /* Nested layers indentation */
3977
3986
  > fig-layer {
3978
- padding-left: var(--indent);
3987
+ padding: 0;
3979
3988
  margin-top: 1px;
3989
+ .fig-layer-row {
3990
+ padding-left: var(--indent);
3991
+ }
3980
3992
  }
3981
3993
 
3982
3994
  /* Collapsed state - hide children */
@@ -4531,10 +4543,11 @@ fig-preview {
4531
4543
  /* Chooser */
4532
4544
  fig-chooser {
4533
4545
  --chooser-fade-size: var(--spacer-4);
4546
+ --fig-chooser-gap: var(--spacer-2);
4534
4547
 
4535
4548
  display: flex;
4536
4549
  flex-direction: column;
4537
- gap: 1px;
4550
+ gap: var(--fig-chooser-gap);
4538
4551
  overflow: visible auto;
4539
4552
  scrollbar-width: none;
4540
4553
  scroll-snap-type: y mandatory;
@@ -4544,7 +4557,7 @@ fig-chooser {
4544
4557
  }
4545
4558
 
4546
4559
  &[padding="false"] {
4547
- gap: var(--spacer-2);
4560
+ gap: var(--fig-chooser-gap);
4548
4561
  fig-choice {
4549
4562
  --fig-choice-padding: 0px;
4550
4563
  }
@@ -4716,8 +4729,8 @@ fig-chooser {
4716
4729
  }
4717
4730
 
4718
4731
  fig-choice {
4719
- --fig-choice-selection-ring-width: 1.25px;
4720
- --fig-choice-padding: var(--spacer-2);
4732
+ --fig-choice-selection-ring-width: 1.5px;
4733
+ --fig-choice-padding: 0px;
4721
4734
  --fig-choice-border-radius: calc(
4722
4735
  var(--radius-medium) + var(--fig-choice-padding)
4723
4736
  );
@@ -4727,7 +4740,6 @@ fig-choice {
4727
4740
  border-radius: var(--fig-choice-border-radius);
4728
4741
  gap: var(--spacer-2);
4729
4742
  outline: none;
4730
- border: 1px solid transparent;
4731
4743
  cursor: default;
4732
4744
 
4733
4745
  padding: var(--fig-choice-padding);
@@ -4944,3 +4956,51 @@ fig-color-tip {
4944
4956
  }
4945
4957
  }
4946
4958
 
4959
+ /* Menu */
4960
+ fig-menu {
4961
+ display: contents;
4962
+ }
4963
+
4964
+ fig-menu-item {
4965
+ --fig-menu-item-padding: var(--spacer-3);
4966
+ display: flex;
4967
+ align-items: center;
4968
+ gap: var(--spacer-2);
4969
+ padding: 0 var(--fig-menu-item-padding);
4970
+ height: var(--spacer-4);
4971
+ cursor: default;
4972
+ border-radius: var(--radius-medium);
4973
+ color: var(--figma-color-text-menu);
4974
+ font-weight: var(--body-medium-fontWeight);
4975
+ position: relative;
4976
+
4977
+ &::before {
4978
+ content: "";
4979
+ display: block;
4980
+ position: absolute;
4981
+ inset: 0 var(--spacer-2);
4982
+ border-radius: var(--radius-medium);
4983
+ z-index: -1;
4984
+ background-color: transparent;
4985
+ }
4986
+
4987
+ &:hover,
4988
+ &:focus-visible {
4989
+ outline: none;
4990
+ &::before {
4991
+ background-color: var(--figma-color-bg-menu-hover);
4992
+ }
4993
+ }
4994
+
4995
+ &[disabled]:not([disabled="false"]) {
4996
+ opacity: 0.4;
4997
+ pointer-events: none;
4998
+ }
4999
+ }
5000
+
5001
+ fig-menu-separator {
5002
+ display: block;
5003
+ height: 1px;
5004
+ background: var(--figma-color-border);
5005
+ margin: var(--spacer-2) 0;
5006
+ }
package/fig.js CHANGED
@@ -14237,3 +14237,334 @@ class FigHandle extends HTMLElement {
14237
14237
  }
14238
14238
  }
14239
14239
  customElements.define("fig-handle", FigHandle);
14240
+
14241
+ // ─── Menu ────────────────────────────────────────────────────────────────────
14242
+
14243
+ class FigMenuItem extends HTMLElement {
14244
+ static get observedAttributes() {
14245
+ return ["value", "disabled"];
14246
+ }
14247
+
14248
+ get value() {
14249
+ return this.getAttribute("value") || "";
14250
+ }
14251
+
14252
+ set value(val) {
14253
+ this.setAttribute("value", val ?? "");
14254
+ }
14255
+
14256
+ connectedCallback() {
14257
+ if (!this.hasAttribute("role")) {
14258
+ this.setAttribute("role", "menuitem");
14259
+ }
14260
+ if (!this.hasAttribute("tabindex")) {
14261
+ this.setAttribute("tabindex", "-1");
14262
+ }
14263
+ }
14264
+
14265
+ attributeChangedCallback() {}
14266
+ }
14267
+ customElements.define("fig-menu-item", FigMenuItem);
14268
+
14269
+ class FigMenuSeparator extends HTMLElement {
14270
+ connectedCallback() {
14271
+ if (!this.hasAttribute("role")) {
14272
+ this.setAttribute("role", "separator");
14273
+ }
14274
+ }
14275
+ }
14276
+ customElements.define("fig-menu-separator", FigMenuSeparator);
14277
+
14278
+ class FigMenu extends HTMLElement {
14279
+ #popup = null;
14280
+ #trigger = null;
14281
+ #observer = null;
14282
+ #boundTriggerClick;
14283
+ #boundPopupClick;
14284
+ #boundPopupKeydown;
14285
+ #boundPopupClose;
14286
+ #focusedIndex = -1;
14287
+
14288
+ static get observedAttributes() {
14289
+ return ["position", "offset", "closedby", "disabled", "open"];
14290
+ }
14291
+
14292
+ constructor() {
14293
+ super();
14294
+ this.#boundTriggerClick = this.#handleTriggerClick.bind(this);
14295
+ this.#boundPopupClick = this.#handlePopupClick.bind(this);
14296
+ this.#boundPopupKeydown = this.#handlePopupKeydown.bind(this);
14297
+ this.#boundPopupClose = this.#handlePopupClose.bind(this);
14298
+ }
14299
+
14300
+ get value() {
14301
+ return this.getAttribute("value") || "";
14302
+ }
14303
+
14304
+ set value(val) {
14305
+ this.setAttribute("value", val ?? "");
14306
+ }
14307
+
14308
+ get open() {
14309
+ return this.hasAttribute("open") && this.getAttribute("open") !== "false";
14310
+ }
14311
+
14312
+ set open(val) {
14313
+ if (val) {
14314
+ this.setAttribute("open", "");
14315
+ } else {
14316
+ this.removeAttribute("open");
14317
+ }
14318
+ }
14319
+
14320
+ connectedCallback() {
14321
+ this.style.display = "contents";
14322
+
14323
+ this.#detectTrigger();
14324
+ this.#createPopup();
14325
+ this.#moveItemsToPopup();
14326
+ this.#setupListeners();
14327
+ this.#setupObserver();
14328
+ this.#syncDisabled();
14329
+
14330
+ if (this.open) {
14331
+ this.#openMenu();
14332
+ }
14333
+ }
14334
+
14335
+ disconnectedCallback() {
14336
+ this.#teardownListeners();
14337
+ if (this.#observer) {
14338
+ this.#observer.disconnect();
14339
+ this.#observer = null;
14340
+ }
14341
+ if (this.#popup) {
14342
+ this.#popup.removeEventListener("close", this.#boundPopupClose);
14343
+ this.#popup.remove();
14344
+ this.#popup = null;
14345
+ }
14346
+ }
14347
+
14348
+ attributeChangedCallback(name, oldValue, newValue) {
14349
+ if (oldValue === newValue) return;
14350
+
14351
+ if (name === "open") {
14352
+ if (newValue === null || newValue === "false") {
14353
+ this.#closeMenu();
14354
+ } else {
14355
+ this.#openMenu();
14356
+ }
14357
+ return;
14358
+ }
14359
+
14360
+ if (name === "disabled") {
14361
+ if (this.#trigger) {
14362
+ if (newValue !== null && newValue !== "false") {
14363
+ this.#trigger.setAttribute("disabled", "");
14364
+ } else {
14365
+ this.#trigger.removeAttribute("disabled");
14366
+ }
14367
+ }
14368
+ return;
14369
+ }
14370
+
14371
+ if (this.#popup && (name === "position" || name === "offset" || name === "closedby")) {
14372
+ if (newValue !== null) {
14373
+ this.#popup.setAttribute(name, newValue);
14374
+ } else {
14375
+ this.#popup.removeAttribute(name);
14376
+ }
14377
+ }
14378
+ }
14379
+
14380
+ #detectTrigger() {
14381
+ this.#trigger =
14382
+ this.querySelector("[fig-menu-trigger]") ||
14383
+ this.querySelector(":scope > :not(fig-menu-item):not(fig-menu-separator)");
14384
+ }
14385
+
14386
+ #createPopup() {
14387
+ this.#popup = document.createElement("dialog", { is: "fig-popup" });
14388
+ this.#popup.setAttribute("is", "fig-popup");
14389
+ this.#popup.setAttribute("theme", "menu");
14390
+ this.#popup.setAttribute("role", "menu");
14391
+
14392
+ const position = this.getAttribute("position") || "bottom left";
14393
+ this.#popup.setAttribute("position", position);
14394
+
14395
+ const offset = this.getAttribute("offset");
14396
+ if (offset) this.#popup.setAttribute("offset", offset);
14397
+
14398
+ const closedby = this.getAttribute("closedby");
14399
+ if (closedby) this.#popup.setAttribute("closedby", closedby);
14400
+
14401
+ if (this.#trigger) {
14402
+ this.#popup.anchor = this.#trigger;
14403
+ }
14404
+
14405
+ this.#popup.addEventListener("close", this.#boundPopupClose);
14406
+ this.appendChild(this.#popup);
14407
+ }
14408
+
14409
+ #moveItemsToPopup() {
14410
+ const items = Array.from(this.querySelectorAll(
14411
+ ":scope > fig-menu-item, :scope > fig-menu-separator"
14412
+ ));
14413
+ for (const item of items) {
14414
+ this.#popup.appendChild(item);
14415
+ }
14416
+ }
14417
+
14418
+ #setupListeners() {
14419
+ if (this.#trigger) {
14420
+ this.#trigger.addEventListener("click", this.#boundTriggerClick);
14421
+ this.#trigger.setAttribute("aria-haspopup", "menu");
14422
+ this.#trigger.setAttribute("aria-expanded", "false");
14423
+ }
14424
+ if (this.#popup) {
14425
+ this.#popup.addEventListener("click", this.#boundPopupClick);
14426
+ this.#popup.addEventListener("keydown", this.#boundPopupKeydown);
14427
+ }
14428
+ }
14429
+
14430
+ #teardownListeners() {
14431
+ if (this.#trigger) {
14432
+ this.#trigger.removeEventListener("click", this.#boundTriggerClick);
14433
+ }
14434
+ if (this.#popup) {
14435
+ this.#popup.removeEventListener("click", this.#boundPopupClick);
14436
+ this.#popup.removeEventListener("keydown", this.#boundPopupKeydown);
14437
+ }
14438
+ }
14439
+
14440
+ #setupObserver() {
14441
+ this.#observer = new MutationObserver((mutations) => {
14442
+ for (const mutation of mutations) {
14443
+ for (const node of mutation.addedNodes) {
14444
+ if (
14445
+ node.nodeType === 1 &&
14446
+ (node.tagName === "FIG-MENU-ITEM" || node.tagName === "FIG-MENU-SEPARATOR") &&
14447
+ node.parentElement === this
14448
+ ) {
14449
+ this.#popup.appendChild(node);
14450
+ }
14451
+ }
14452
+ }
14453
+ });
14454
+ this.#observer.observe(this, { childList: true });
14455
+ }
14456
+
14457
+ #getItems() {
14458
+ if (!this.#popup) return [];
14459
+ return Array.from(this.#popup.querySelectorAll("fig-menu-item:not([disabled]):not([disabled='true'])"));
14460
+ }
14461
+
14462
+ #syncDisabled() {
14463
+ if (!this.#trigger) return;
14464
+ const disabled = this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false";
14465
+ if (disabled) {
14466
+ this.#trigger.setAttribute("disabled", "");
14467
+ } else {
14468
+ this.#trigger.removeAttribute("disabled");
14469
+ }
14470
+ }
14471
+
14472
+ #handleTriggerClick(e) {
14473
+ if (this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false") return;
14474
+ e.stopPropagation();
14475
+ if (this.open) {
14476
+ this.open = false;
14477
+ } else {
14478
+ this.open = true;
14479
+ }
14480
+ }
14481
+
14482
+ #handlePopupClick(e) {
14483
+ const item = e.target.closest("fig-menu-item");
14484
+ if (!item) return;
14485
+ if (item.hasAttribute("disabled") && item.getAttribute("disabled") !== "false") return;
14486
+
14487
+ this.#selectItem(item);
14488
+ }
14489
+
14490
+ #handlePopupKeydown(e) {
14491
+ const items = this.#getItems();
14492
+ if (!items.length) return;
14493
+
14494
+ switch (e.key) {
14495
+ case "ArrowDown": {
14496
+ e.preventDefault();
14497
+ this.#focusedIndex = Math.min(this.#focusedIndex + 1, items.length - 1);
14498
+ items[this.#focusedIndex]?.focus();
14499
+ break;
14500
+ }
14501
+ case "ArrowUp": {
14502
+ e.preventDefault();
14503
+ this.#focusedIndex = Math.max(this.#focusedIndex - 1, 0);
14504
+ items[this.#focusedIndex]?.focus();
14505
+ break;
14506
+ }
14507
+ case "Home": {
14508
+ e.preventDefault();
14509
+ this.#focusedIndex = 0;
14510
+ items[0]?.focus();
14511
+ break;
14512
+ }
14513
+ case "End": {
14514
+ e.preventDefault();
14515
+ this.#focusedIndex = items.length - 1;
14516
+ items[this.#focusedIndex]?.focus();
14517
+ break;
14518
+ }
14519
+ case "Enter":
14520
+ case " ": {
14521
+ e.preventDefault();
14522
+ const focused = items[this.#focusedIndex];
14523
+ if (focused) this.#selectItem(focused);
14524
+ break;
14525
+ }
14526
+ }
14527
+ }
14528
+
14529
+ #handlePopupClose() {
14530
+ if (this.hasAttribute("open")) {
14531
+ this.removeAttribute("open");
14532
+ }
14533
+ if (this.#trigger) {
14534
+ this.#trigger.setAttribute("aria-expanded", "false");
14535
+ this.#trigger.focus();
14536
+ }
14537
+ this.#focusedIndex = -1;
14538
+ }
14539
+
14540
+ #selectItem(item) {
14541
+ const value = item.getAttribute("value") || item.textContent.trim();
14542
+ this.setAttribute("value", value);
14543
+ this.dispatchEvent(
14544
+ new CustomEvent("change", {
14545
+ detail: { value, item },
14546
+ bubbles: true,
14547
+ })
14548
+ );
14549
+ this.open = false;
14550
+ }
14551
+
14552
+ #openMenu() {
14553
+ if (!this.#popup) return;
14554
+ this.#popup.open = true;
14555
+ if (this.#trigger) {
14556
+ this.#trigger.setAttribute("aria-expanded", "true");
14557
+ }
14558
+ this.#focusedIndex = 0;
14559
+ requestAnimationFrame(() => {
14560
+ const items = this.#getItems();
14561
+ if (items.length) items[0].focus();
14562
+ });
14563
+ }
14564
+
14565
+ #closeMenu() {
14566
+ if (!this.#popup) return;
14567
+ this.#popup.open = false;
14568
+ }
14569
+ }
14570
+ customElements.define("fig-menu", FigMenu);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogieking/figui3",
3
- "version": "4.1.0",
3
+ "version": "4.1.3",
4
4
  "description": "A lightweight web components library for building Figma plugin and widget UIs with native look and feel",
5
5
  "author": "Rogie King",
6
6
  "license": "MIT",