@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 +1 -0
- package/components.css +81 -21
- package/fig.js +331 -0
- package/package.json +1 -1
package/base.css
CHANGED
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='
|
|
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:
|
|
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
|
-
|
|
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-
|
|
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
|
|
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:
|
|
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(--
|
|
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.
|
|
4720
|
-
--fig-choice-padding:
|
|
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