@nectary/components 5.37.2 → 5.37.5
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/accordion-item/index.d.ts +4 -1
- package/accordion-item/index.js +21 -6
- package/action-menu/index.js +2 -9
- package/bundle.js +57 -23
- package/bundle.ts +1 -0
- package/package.json +2 -2
- package/tooltip/index.js +10 -3
- package/utils/control-keyboard-navigation.js +2 -8
- package/utils/dom.d.ts +2 -0
- package/utils/dom.js +28 -0
- package/utils/index.js +3 -1
- package/utils/shared/cdn-loader.js +9 -2
|
@@ -7,6 +7,7 @@ export * from './types';
|
|
|
7
7
|
export declare class AccordionItem extends NectaryElement {
|
|
8
8
|
#private;
|
|
9
9
|
constructor();
|
|
10
|
+
connectedCallback(): void;
|
|
10
11
|
disconnectedCallback(): void;
|
|
11
12
|
static get observedAttributes(): string[];
|
|
12
13
|
attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
|
|
@@ -16,10 +17,12 @@ export declare class AccordionItem extends NectaryElement {
|
|
|
16
17
|
get label(): string;
|
|
17
18
|
set disabled(isDisabled: boolean);
|
|
18
19
|
get disabled(): boolean;
|
|
19
|
-
get status(): TSinchAccordionStatusType | null;
|
|
20
20
|
set status(value: TSinchAccordionStatusType | null);
|
|
21
|
+
get status(): TSinchAccordionStatusType | null;
|
|
21
22
|
set optionalText(value: string | null);
|
|
22
23
|
get optionalText(): string | null;
|
|
24
|
+
set ellipsis(isEllipsis: boolean);
|
|
25
|
+
get ellipsis(): boolean;
|
|
23
26
|
get focusable(): boolean;
|
|
24
27
|
focus(): void;
|
|
25
28
|
blur(): void;
|
package/accordion-item/index.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import "../icon/index.js";
|
|
2
2
|
import "../text/index.js";
|
|
3
3
|
import "../title/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import { updateBooleanAttribute, isAttrEqual, isAttrTrue, updateExplicitBooleanAttribute, updateAttribute, getAttribute, getBooleanAttribute, updateLiteralAttribute, getLiteralAttribute } from "../utils/dom.js";
|
|
5
5
|
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
6
6
|
import { statusValues } from "./utils.js";
|
|
7
|
-
const templateHTML = '<style>:host{display:block;outline:0;min-height:48px}#wrapper{display:flex;flex-direction:column;position:relative;width:100%;height:100%;box-sizing:border-box;overflow:hidden;border-bottom:1px solid var(--sinch-comp-accordion-color-default-border-initial)}:host(:last-child)>#wrapper{border-bottom:none}#button{all:initial;display:flex;position:relative;align-items:flex-start;gap:8px;box-sizing:border-box;width:100%;min-height:48px;padding:12px 4px 12px 8px;cursor:pointer;--sinch-global-color-icon:var(--sinch-comp-accordion-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-accordion-size-icon)}#button>*{pointer-events:none}#button:disabled{cursor:initial;--sinch-global-color-icon:var(--sinch-comp-accordion-color-disabled-icon-initial)}#button:focus-visible::after{content:"";position:absolute;inset:0;border:2px solid var(--sinch-comp-accordion-color-default-outline-focus);pointer-events:none}#status-wrapper{display:none;width:18px;height:24px;padding:8px 8px 8px 2px;box-sizing:border-box}#status{width:8px;height:8px;border-radius:50%}:host([status]:not([status=""])) #status-wrapper{display:block}:host([status=success]) #status{background-color:var(--sinch-comp-accordion-color-default-status-success)}:host([status=warn]) #status{background-color:var(--sinch-comp-accordion-color-default-status-warning)}:host([status=error]) #status{background-color:var(--sinch-comp-accordion-color-default-status-error)}:host([status=info]) #status{background-color:var(--sinch-comp-accordion-color-default-status-info)}#title{flex:1;min-width:0;--sinch-comp-title-font:var(--sinch-comp-accordion-font-title);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-title-initial)}#button:disabled>#title{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-title-initial)}#content{display:none;overflow-y:auto;flex-shrink:1;min-height:0;padding:0 8px 12px}#dropdown-icon{flex-shrink:0;margin-top:2px;transform:rotate(0);will-change:transform;transition:transform .25s ease-in-out}#button[aria-expanded=true]>#dropdown-icon{transform:rotate(180deg)}#button[aria-expanded=true]+#content{display:block}#optional{flex-shrink:0;--sinch-comp-text-font:var(--sinch-comp-accordion-font-optional-text);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-optional-text-initial)}#button:disabled>#optional{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-optional-text-initial)}</style><div id="wrapper"><button id="button" aria-controls="content" aria-expanded="false"><div id="status-wrapper"><div id="status"></div></div><slot name="icon"></slot><sinch-title id="title" level="3" type="m"
|
|
7
|
+
const templateHTML = '<style>:host{display:block;outline:0;min-height:48px}#wrapper{display:flex;flex-direction:column;position:relative;width:100%;height:100%;box-sizing:border-box;overflow:hidden;border-bottom:1px solid var(--sinch-comp-accordion-color-default-border-initial)}:host(:last-child)>#wrapper{border-bottom:none}#button{all:initial;display:flex;position:relative;align-items:flex-start;gap:8px;box-sizing:border-box;width:100%;min-height:48px;padding:12px 4px 12px 8px;cursor:pointer;--sinch-global-color-icon:var(--sinch-comp-accordion-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-accordion-size-icon)}#button>*{pointer-events:none}#button:disabled{cursor:initial;--sinch-global-color-icon:var(--sinch-comp-accordion-color-disabled-icon-initial)}#button:focus-visible::after{content:"";position:absolute;inset:0;border:2px solid var(--sinch-comp-accordion-color-default-outline-focus);pointer-events:none}#status-wrapper{display:none;width:18px;height:24px;padding:8px 8px 8px 2px;box-sizing:border-box}#status{width:8px;height:8px;border-radius:50%}:host([status]:not([status=""])) #status-wrapper{display:block}:host([status=success]) #status{background-color:var(--sinch-comp-accordion-color-default-status-success)}:host([status=warn]) #status{background-color:var(--sinch-comp-accordion-color-default-status-warning)}:host([status=error]) #status{background-color:var(--sinch-comp-accordion-color-default-status-error)}:host([status=info]) #status{background-color:var(--sinch-comp-accordion-color-default-status-info)}#title{flex:1;min-width:0;--sinch-comp-title-font:var(--sinch-comp-accordion-font-title);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-title-initial)}#button:disabled>#title{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-title-initial)}#content{display:none;overflow-y:auto;flex-shrink:1;min-height:0;padding:0 8px 12px}#dropdown-icon{flex-shrink:0;margin-top:2px;transform:rotate(0);will-change:transform;transition:transform .25s ease-in-out}#button[aria-expanded=true]>#dropdown-icon{transform:rotate(180deg)}#button[aria-expanded=true]+#content{display:block}#optional{flex-shrink:0;--sinch-comp-text-font:var(--sinch-comp-accordion-font-optional-text);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-optional-text-initial)}#button:disabled>#optional{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-optional-text-initial)}</style><div id="wrapper"><button id="button" aria-controls="content" aria-expanded="false"><div id="status-wrapper"><div id="status"></div></div><slot name="icon"></slot><sinch-title id="title" level="3" type="m"></sinch-title><sinch-text id="optional" type="m"></sinch-text><sinch-icon icons-version="2" name="fa-chevron-down" id="dropdown-icon"></sinch-icon></button><div id="content" role="region" aria-labelledby="button"><slot name="content"></slot></div></div>';
|
|
8
8
|
const template = document.createElement("template");
|
|
9
9
|
template.innerHTML = templateHTML;
|
|
10
10
|
class AccordionItem extends NectaryElement {
|
|
11
11
|
#$button;
|
|
12
12
|
#$title;
|
|
13
13
|
#$optionalText;
|
|
14
|
+
#hasExplicitEllipsis = false;
|
|
14
15
|
constructor() {
|
|
15
16
|
super();
|
|
16
17
|
const shadowRoot = this.attachShadow({ delegatesFocus: true });
|
|
@@ -19,7 +20,14 @@ class AccordionItem extends NectaryElement {
|
|
|
19
20
|
this.#$title = shadowRoot.querySelector("#title");
|
|
20
21
|
this.#$optionalText = shadowRoot.querySelector("#optional");
|
|
21
22
|
}
|
|
23
|
+
connectedCallback() {
|
|
24
|
+
super.connectedCallback();
|
|
25
|
+
if (this.hasAttribute("ellipsis") === false && this.#hasExplicitEllipsis === false) {
|
|
26
|
+
updateBooleanAttribute(this, "ellipsis", true);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
22
29
|
disconnectedCallback() {
|
|
30
|
+
super.disconnectedCallback();
|
|
23
31
|
}
|
|
24
32
|
static get observedAttributes() {
|
|
25
33
|
return [
|
|
@@ -27,7 +35,6 @@ class AccordionItem extends NectaryElement {
|
|
|
27
35
|
"disabled",
|
|
28
36
|
"data-checked",
|
|
29
37
|
"optionaltext",
|
|
30
|
-
// eslint-disable-next-line @nectary/observed-attribute-accessor -- baseline backlog: ellipsis missing set/get pair, fixed by MR !597
|
|
31
38
|
"ellipsis"
|
|
32
39
|
];
|
|
33
40
|
}
|
|
@@ -58,6 +65,7 @@ class AccordionItem extends NectaryElement {
|
|
|
58
65
|
break;
|
|
59
66
|
}
|
|
60
67
|
case "ellipsis": {
|
|
68
|
+
this.#hasExplicitEllipsis = true;
|
|
61
69
|
updateBooleanAttribute(this.#$title, name, isAttrTrue(newVal));
|
|
62
70
|
break;
|
|
63
71
|
}
|
|
@@ -81,18 +89,25 @@ class AccordionItem extends NectaryElement {
|
|
|
81
89
|
get disabled() {
|
|
82
90
|
return getBooleanAttribute(this, "disabled");
|
|
83
91
|
}
|
|
84
|
-
get status() {
|
|
85
|
-
return getLiteralAttribute(this, statusValues, "status", null);
|
|
86
|
-
}
|
|
87
92
|
set status(value) {
|
|
88
93
|
updateLiteralAttribute(this, statusValues, "status", value);
|
|
89
94
|
}
|
|
95
|
+
get status() {
|
|
96
|
+
return getLiteralAttribute(this, statusValues, "status", null);
|
|
97
|
+
}
|
|
90
98
|
set optionalText(value) {
|
|
91
99
|
updateAttribute(this, "optionaltext", value);
|
|
92
100
|
}
|
|
93
101
|
get optionalText() {
|
|
94
102
|
return getAttribute(this, "optionaltext");
|
|
95
103
|
}
|
|
104
|
+
set ellipsis(isEllipsis) {
|
|
105
|
+
this.#hasExplicitEllipsis = true;
|
|
106
|
+
updateBooleanAttribute(this, "ellipsis", isEllipsis);
|
|
107
|
+
}
|
|
108
|
+
get ellipsis() {
|
|
109
|
+
return getBooleanAttribute(this, "ellipsis");
|
|
110
|
+
}
|
|
96
111
|
get focusable() {
|
|
97
112
|
return true;
|
|
98
113
|
}
|
package/action-menu/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isSinchActionMenuOption } from "../action-menu-option/utils.js";
|
|
2
2
|
import { subscribeContext } from "../utils/context.js";
|
|
3
|
-
import { attrValueToPixels, updateIntegerAttribute, getIntegerAttribute, getBooleanAttribute, updateBooleanAttribute } from "../utils/dom.js";
|
|
3
|
+
import { attrValueToPixels, updateIntegerAttribute, getIntegerAttribute, getDeepActiveElement, getBooleanAttribute, updateBooleanAttribute } from "../utils/dom.js";
|
|
4
4
|
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
5
5
|
const templateHTML = '<style>:host{display:block;outline:0}#listbox{overflow-y:auto}</style><div id="listbox" role="presentation"><slot></slot></div>';
|
|
6
6
|
const ITEM_HEIGHT = 40;
|
|
@@ -69,7 +69,7 @@ class ActionMenu extends NectaryElement {
|
|
|
69
69
|
this.#selectOption(null);
|
|
70
70
|
this.#$listbox.scrollTo({ top: 0, behavior: "auto" });
|
|
71
71
|
} else {
|
|
72
|
-
const activeElement =
|
|
72
|
+
const activeElement = getDeepActiveElement(this.ownerDocument);
|
|
73
73
|
const isTextInput = activeElement !== null && activeElement.tagName === "INPUT";
|
|
74
74
|
if (!isTextInput) {
|
|
75
75
|
this.focus();
|
|
@@ -146,13 +146,6 @@ class ActionMenu extends NectaryElement {
|
|
|
146
146
|
}
|
|
147
147
|
return this.#getLastOption();
|
|
148
148
|
}
|
|
149
|
-
#getDeepActiveElement() {
|
|
150
|
-
let activeElement = this.ownerDocument.activeElement;
|
|
151
|
-
while (activeElement !== null && activeElement.shadowRoot !== null && activeElement.shadowRoot.activeElement !== null) {
|
|
152
|
-
activeElement = activeElement.shadowRoot.activeElement;
|
|
153
|
-
}
|
|
154
|
-
return activeElement;
|
|
155
|
-
}
|
|
156
149
|
#selectOption($option) {
|
|
157
150
|
const hasRows = this.hasAttribute("rows");
|
|
158
151
|
for (const $op of this.#getOptionElements()) {
|
package/bundle.js
CHANGED
|
@@ -124,6 +124,32 @@ const cloneNode = (el, deep) => {
|
|
|
124
124
|
return el.cloneNode(deep);
|
|
125
125
|
};
|
|
126
126
|
const shouldReduceMotion = () => window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
127
|
+
const getDeepActiveElement = (ownerDocument = document) => {
|
|
128
|
+
let activeElement = ownerDocument.activeElement;
|
|
129
|
+
while (activeElement !== null && activeElement.shadowRoot !== null && activeElement.shadowRoot.activeElement !== null) {
|
|
130
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
131
|
+
}
|
|
132
|
+
return activeElement;
|
|
133
|
+
};
|
|
134
|
+
const composedContains = (container, node) => {
|
|
135
|
+
let current = node;
|
|
136
|
+
while (current !== null) {
|
|
137
|
+
if (current === container) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
if (current.parentNode !== null) {
|
|
141
|
+
current = current.parentNode;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const root = current.getRootNode();
|
|
145
|
+
if (root instanceof ShadowRoot) {
|
|
146
|
+
current = root.host;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
current = null;
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
};
|
|
127
153
|
const isAttrEqual = (oldVal, newVal) => {
|
|
128
154
|
return oldVal === newVal || newVal === null && oldVal === "false" || newVal === "" && oldVal === "true";
|
|
129
155
|
};
|
|
@@ -436,13 +462,14 @@ class Title extends NectaryElement {
|
|
|
436
462
|
}
|
|
437
463
|
defineCustomElement("sinch-title", Title);
|
|
438
464
|
const statusValues$1 = ["info", "success", "warn", "error"];
|
|
439
|
-
const templateHTML$1g = '<style>:host{display:block;outline:0;min-height:48px}#wrapper{display:flex;flex-direction:column;position:relative;width:100%;height:100%;box-sizing:border-box;overflow:hidden;border-bottom:1px solid var(--sinch-comp-accordion-color-default-border-initial)}:host(:last-child)>#wrapper{border-bottom:none}#button{all:initial;display:flex;position:relative;align-items:flex-start;gap:8px;box-sizing:border-box;width:100%;min-height:48px;padding:12px 4px 12px 8px;cursor:pointer;--sinch-global-color-icon:var(--sinch-comp-accordion-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-accordion-size-icon)}#button>*{pointer-events:none}#button:disabled{cursor:initial;--sinch-global-color-icon:var(--sinch-comp-accordion-color-disabled-icon-initial)}#button:focus-visible::after{content:"";position:absolute;inset:0;border:2px solid var(--sinch-comp-accordion-color-default-outline-focus);pointer-events:none}#status-wrapper{display:none;width:18px;height:24px;padding:8px 8px 8px 2px;box-sizing:border-box}#status{width:8px;height:8px;border-radius:50%}:host([status]:not([status=""])) #status-wrapper{display:block}:host([status=success]) #status{background-color:var(--sinch-comp-accordion-color-default-status-success)}:host([status=warn]) #status{background-color:var(--sinch-comp-accordion-color-default-status-warning)}:host([status=error]) #status{background-color:var(--sinch-comp-accordion-color-default-status-error)}:host([status=info]) #status{background-color:var(--sinch-comp-accordion-color-default-status-info)}#title{flex:1;min-width:0;--sinch-comp-title-font:var(--sinch-comp-accordion-font-title);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-title-initial)}#button:disabled>#title{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-title-initial)}#content{display:none;overflow-y:auto;flex-shrink:1;min-height:0;padding:0 8px 12px}#dropdown-icon{flex-shrink:0;margin-top:2px;transform:rotate(0);will-change:transform;transition:transform .25s ease-in-out}#button[aria-expanded=true]>#dropdown-icon{transform:rotate(180deg)}#button[aria-expanded=true]+#content{display:block}#optional{flex-shrink:0;--sinch-comp-text-font:var(--sinch-comp-accordion-font-optional-text);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-optional-text-initial)}#button:disabled>#optional{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-optional-text-initial)}</style><div id="wrapper"><button id="button" aria-controls="content" aria-expanded="false"><div id="status-wrapper"><div id="status"></div></div><slot name="icon"></slot><sinch-title id="title" level="3" type="m"
|
|
465
|
+
const templateHTML$1g = '<style>:host{display:block;outline:0;min-height:48px}#wrapper{display:flex;flex-direction:column;position:relative;width:100%;height:100%;box-sizing:border-box;overflow:hidden;border-bottom:1px solid var(--sinch-comp-accordion-color-default-border-initial)}:host(:last-child)>#wrapper{border-bottom:none}#button{all:initial;display:flex;position:relative;align-items:flex-start;gap:8px;box-sizing:border-box;width:100%;min-height:48px;padding:12px 4px 12px 8px;cursor:pointer;--sinch-global-color-icon:var(--sinch-comp-accordion-color-default-icon-initial);--sinch-global-size-icon:var(--sinch-comp-accordion-size-icon)}#button>*{pointer-events:none}#button:disabled{cursor:initial;--sinch-global-color-icon:var(--sinch-comp-accordion-color-disabled-icon-initial)}#button:focus-visible::after{content:"";position:absolute;inset:0;border:2px solid var(--sinch-comp-accordion-color-default-outline-focus);pointer-events:none}#status-wrapper{display:none;width:18px;height:24px;padding:8px 8px 8px 2px;box-sizing:border-box}#status{width:8px;height:8px;border-radius:50%}:host([status]:not([status=""])) #status-wrapper{display:block}:host([status=success]) #status{background-color:var(--sinch-comp-accordion-color-default-status-success)}:host([status=warn]) #status{background-color:var(--sinch-comp-accordion-color-default-status-warning)}:host([status=error]) #status{background-color:var(--sinch-comp-accordion-color-default-status-error)}:host([status=info]) #status{background-color:var(--sinch-comp-accordion-color-default-status-info)}#title{flex:1;min-width:0;--sinch-comp-title-font:var(--sinch-comp-accordion-font-title);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-title-initial)}#button:disabled>#title{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-title-initial)}#content{display:none;overflow-y:auto;flex-shrink:1;min-height:0;padding:0 8px 12px}#dropdown-icon{flex-shrink:0;margin-top:2px;transform:rotate(0);will-change:transform;transition:transform .25s ease-in-out}#button[aria-expanded=true]>#dropdown-icon{transform:rotate(180deg)}#button[aria-expanded=true]+#content{display:block}#optional{flex-shrink:0;--sinch-comp-text-font:var(--sinch-comp-accordion-font-optional-text);--sinch-global-color-text:var(--sinch-comp-accordion-color-default-optional-text-initial)}#button:disabled>#optional{--sinch-global-color-text:var(--sinch-comp-accordion-color-disabled-optional-text-initial)}</style><div id="wrapper"><button id="button" aria-controls="content" aria-expanded="false"><div id="status-wrapper"><div id="status"></div></div><slot name="icon"></slot><sinch-title id="title" level="3" type="m"></sinch-title><sinch-text id="optional" type="m"></sinch-text><sinch-icon icons-version="2" name="fa-chevron-down" id="dropdown-icon"></sinch-icon></button><div id="content" role="region" aria-labelledby="button"><slot name="content"></slot></div></div>';
|
|
440
466
|
const template$1g = document.createElement("template");
|
|
441
467
|
template$1g.innerHTML = templateHTML$1g;
|
|
442
468
|
class AccordionItem extends NectaryElement {
|
|
443
469
|
#$button;
|
|
444
470
|
#$title;
|
|
445
471
|
#$optionalText;
|
|
472
|
+
#hasExplicitEllipsis = false;
|
|
446
473
|
constructor() {
|
|
447
474
|
super();
|
|
448
475
|
const shadowRoot = this.attachShadow({ delegatesFocus: true });
|
|
@@ -451,7 +478,14 @@ class AccordionItem extends NectaryElement {
|
|
|
451
478
|
this.#$title = shadowRoot.querySelector("#title");
|
|
452
479
|
this.#$optionalText = shadowRoot.querySelector("#optional");
|
|
453
480
|
}
|
|
481
|
+
connectedCallback() {
|
|
482
|
+
super.connectedCallback();
|
|
483
|
+
if (this.hasAttribute("ellipsis") === false && this.#hasExplicitEllipsis === false) {
|
|
484
|
+
updateBooleanAttribute(this, "ellipsis", true);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
454
487
|
disconnectedCallback() {
|
|
488
|
+
super.disconnectedCallback();
|
|
455
489
|
}
|
|
456
490
|
static get observedAttributes() {
|
|
457
491
|
return [
|
|
@@ -459,7 +493,6 @@ class AccordionItem extends NectaryElement {
|
|
|
459
493
|
"disabled",
|
|
460
494
|
"data-checked",
|
|
461
495
|
"optionaltext",
|
|
462
|
-
// eslint-disable-next-line @nectary/observed-attribute-accessor -- baseline backlog: ellipsis missing set/get pair, fixed by MR !597
|
|
463
496
|
"ellipsis"
|
|
464
497
|
];
|
|
465
498
|
}
|
|
@@ -490,6 +523,7 @@ class AccordionItem extends NectaryElement {
|
|
|
490
523
|
break;
|
|
491
524
|
}
|
|
492
525
|
case "ellipsis": {
|
|
526
|
+
this.#hasExplicitEllipsis = true;
|
|
493
527
|
updateBooleanAttribute(this.#$title, name, isAttrTrue(newVal));
|
|
494
528
|
break;
|
|
495
529
|
}
|
|
@@ -513,18 +547,25 @@ class AccordionItem extends NectaryElement {
|
|
|
513
547
|
get disabled() {
|
|
514
548
|
return getBooleanAttribute(this, "disabled");
|
|
515
549
|
}
|
|
516
|
-
get status() {
|
|
517
|
-
return getLiteralAttribute(this, statusValues$1, "status", null);
|
|
518
|
-
}
|
|
519
550
|
set status(value) {
|
|
520
551
|
updateLiteralAttribute(this, statusValues$1, "status", value);
|
|
521
552
|
}
|
|
553
|
+
get status() {
|
|
554
|
+
return getLiteralAttribute(this, statusValues$1, "status", null);
|
|
555
|
+
}
|
|
522
556
|
set optionalText(value) {
|
|
523
557
|
updateAttribute(this, "optionaltext", value);
|
|
524
558
|
}
|
|
525
559
|
get optionalText() {
|
|
526
560
|
return getAttribute(this, "optionaltext");
|
|
527
561
|
}
|
|
562
|
+
set ellipsis(isEllipsis2) {
|
|
563
|
+
this.#hasExplicitEllipsis = true;
|
|
564
|
+
updateBooleanAttribute(this, "ellipsis", isEllipsis2);
|
|
565
|
+
}
|
|
566
|
+
get ellipsis() {
|
|
567
|
+
return getBooleanAttribute(this, "ellipsis");
|
|
568
|
+
}
|
|
528
569
|
get focusable() {
|
|
529
570
|
return true;
|
|
530
571
|
}
|
|
@@ -892,7 +933,7 @@ class ActionMenu extends NectaryElement {
|
|
|
892
933
|
this.#selectOption(null);
|
|
893
934
|
this.#$listbox.scrollTo({ top: 0, behavior: "auto" });
|
|
894
935
|
} else {
|
|
895
|
-
const activeElement =
|
|
936
|
+
const activeElement = getDeepActiveElement(this.ownerDocument);
|
|
896
937
|
const isTextInput = activeElement !== null && activeElement.tagName === "INPUT";
|
|
897
938
|
if (!isTextInput) {
|
|
898
939
|
this.focus();
|
|
@@ -969,13 +1010,6 @@ class ActionMenu extends NectaryElement {
|
|
|
969
1010
|
}
|
|
970
1011
|
return this.#getLastOption();
|
|
971
1012
|
}
|
|
972
|
-
#getDeepActiveElement() {
|
|
973
|
-
let activeElement = this.ownerDocument.activeElement;
|
|
974
|
-
while (activeElement !== null && activeElement.shadowRoot !== null && activeElement.shadowRoot.activeElement !== null) {
|
|
975
|
-
activeElement = activeElement.shadowRoot.activeElement;
|
|
976
|
-
}
|
|
977
|
-
return activeElement;
|
|
978
|
-
}
|
|
979
1013
|
#selectOption($option) {
|
|
980
1014
|
const hasRows = this.hasAttribute("rows");
|
|
981
1015
|
for (const $op of this.#getOptionElements()) {
|
|
@@ -4266,7 +4300,7 @@ class Tooltip extends NectaryElement {
|
|
|
4266
4300
|
this.#tooltipState.show();
|
|
4267
4301
|
};
|
|
4268
4302
|
#onFocusIn = () => {
|
|
4269
|
-
if (this.#suppressFocusIn) {
|
|
4303
|
+
if (this.#suppressFocusIn || !this.#shouldOpenForFocus()) {
|
|
4270
4304
|
return;
|
|
4271
4305
|
}
|
|
4272
4306
|
this.#closeFocusedTooltip();
|
|
@@ -4275,6 +4309,13 @@ class Tooltip extends NectaryElement {
|
|
|
4275
4309
|
focusedTooltip = this;
|
|
4276
4310
|
this.#tooltipState.show();
|
|
4277
4311
|
};
|
|
4312
|
+
#shouldOpenForFocus() {
|
|
4313
|
+
const activeEl = getDeepActiveElement(this.ownerDocument);
|
|
4314
|
+
if (!(activeEl instanceof HTMLElement) || !this.#targetContains(activeEl)) {
|
|
4315
|
+
return false;
|
|
4316
|
+
}
|
|
4317
|
+
return activeEl.matches(":focus-visible");
|
|
4318
|
+
}
|
|
4278
4319
|
#closeFocusedTooltip() {
|
|
4279
4320
|
if (!this.#isOtherUncontrolledTooltip(focusedTooltip)) {
|
|
4280
4321
|
return;
|
|
@@ -4385,7 +4426,7 @@ class Tooltip extends NectaryElement {
|
|
|
4385
4426
|
});
|
|
4386
4427
|
};
|
|
4387
4428
|
#targetContains(node) {
|
|
4388
|
-
return this.#$target.assignedElements().some((el) => el
|
|
4429
|
+
return this.#$target.assignedElements().some((el) => composedContains(el, node));
|
|
4389
4430
|
}
|
|
4390
4431
|
#getTargetElements() {
|
|
4391
4432
|
return this.#$target.assignedElements().filter((el) => el instanceof HTMLElement);
|
|
@@ -13017,13 +13058,6 @@ class SegmentedControlOption extends NectaryElement {
|
|
|
13017
13058
|
};
|
|
13018
13059
|
}
|
|
13019
13060
|
defineCustomElement("sinch-segmented-control-option", SegmentedControlOption);
|
|
13020
|
-
function getActualActiveElement() {
|
|
13021
|
-
let activeElement = document.activeElement;
|
|
13022
|
-
while (activeElement?.shadowRoot?.activeElement != null) {
|
|
13023
|
-
activeElement = activeElement.shadowRoot.activeElement;
|
|
13024
|
-
}
|
|
13025
|
-
return activeElement;
|
|
13026
|
-
}
|
|
13027
13061
|
function createKeyboardNavigation() {
|
|
13028
13062
|
return {
|
|
13029
13063
|
navigateToNextOption(enabledOptions, forward) {
|
|
@@ -13031,7 +13065,7 @@ function createKeyboardNavigation() {
|
|
|
13031
13065
|
if (optionsLength === 0) {
|
|
13032
13066
|
return;
|
|
13033
13067
|
}
|
|
13034
|
-
const currentIndex = enabledOptions.findIndex((option) => option ===
|
|
13068
|
+
const currentIndex = enabledOptions.findIndex((option) => option === getDeepActiveElement());
|
|
13035
13069
|
let nextIndex;
|
|
13036
13070
|
if (currentIndex !== -1) {
|
|
13037
13071
|
if (forward) {
|
package/bundle.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nectary/components",
|
|
3
|
-
"version": "5.37.
|
|
3
|
+
"version": "5.37.5",
|
|
4
4
|
"files": [
|
|
5
5
|
"**/*/*.css",
|
|
6
6
|
"**/*/*.json",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@babel/runtime": "^7.22.15",
|
|
27
|
-
"@nectary/assets": "3.6.
|
|
27
|
+
"@nectary/assets": "3.6.12"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@babel/cli": "^7.22.15",
|
package/tooltip/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../text/index.js";
|
|
2
2
|
import "../pop/index.js";
|
|
3
|
-
import { shouldReduceMotion, updateAttribute, updateBooleanAttribute, getAttribute, getBooleanAttribute, getLiteralAttribute, updateLiteralAttribute, setClass } from "../utils/dom.js";
|
|
3
|
+
import { shouldReduceMotion, updateAttribute, updateBooleanAttribute, getAttribute, getBooleanAttribute, getLiteralAttribute, updateLiteralAttribute, getDeepActiveElement, composedContains, setClass } from "../utils/dom.js";
|
|
4
4
|
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
5
5
|
import { rectOverlap } from "../utils/rect.js";
|
|
6
6
|
import { getReactEventHandler } from "../utils/get-react-event-handler.js";
|
|
@@ -239,7 +239,7 @@ class Tooltip extends NectaryElement {
|
|
|
239
239
|
this.#tooltipState.show();
|
|
240
240
|
};
|
|
241
241
|
#onFocusIn = () => {
|
|
242
|
-
if (this.#suppressFocusIn) {
|
|
242
|
+
if (this.#suppressFocusIn || !this.#shouldOpenForFocus()) {
|
|
243
243
|
return;
|
|
244
244
|
}
|
|
245
245
|
this.#closeFocusedTooltip();
|
|
@@ -248,6 +248,13 @@ class Tooltip extends NectaryElement {
|
|
|
248
248
|
focusedTooltip = this;
|
|
249
249
|
this.#tooltipState.show();
|
|
250
250
|
};
|
|
251
|
+
#shouldOpenForFocus() {
|
|
252
|
+
const activeEl = getDeepActiveElement(this.ownerDocument);
|
|
253
|
+
if (!(activeEl instanceof HTMLElement) || !this.#targetContains(activeEl)) {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
return activeEl.matches(":focus-visible");
|
|
257
|
+
}
|
|
251
258
|
#closeFocusedTooltip() {
|
|
252
259
|
if (!this.#isOtherUncontrolledTooltip(focusedTooltip)) {
|
|
253
260
|
return;
|
|
@@ -358,7 +365,7 @@ class Tooltip extends NectaryElement {
|
|
|
358
365
|
});
|
|
359
366
|
};
|
|
360
367
|
#targetContains(node) {
|
|
361
|
-
return this.#$target.assignedElements().some((el) => el
|
|
368
|
+
return this.#$target.assignedElements().some((el) => composedContains(el, node));
|
|
362
369
|
}
|
|
363
370
|
#getTargetElements() {
|
|
364
371
|
return this.#$target.assignedElements().filter((el) => el instanceof HTMLElement);
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
+
import { getDeepActiveElement } from "./dom.js";
|
|
1
2
|
import { getTargetByAttribute } from "./event-target.js";
|
|
2
|
-
function getActualActiveElement() {
|
|
3
|
-
let activeElement = document.activeElement;
|
|
4
|
-
while (activeElement?.shadowRoot?.activeElement != null) {
|
|
5
|
-
activeElement = activeElement.shadowRoot.activeElement;
|
|
6
|
-
}
|
|
7
|
-
return activeElement;
|
|
8
|
-
}
|
|
9
3
|
function createKeyboardNavigation() {
|
|
10
4
|
return {
|
|
11
5
|
navigateToNextOption(enabledOptions, forward) {
|
|
@@ -13,7 +7,7 @@ function createKeyboardNavigation() {
|
|
|
13
7
|
if (optionsLength === 0) {
|
|
14
8
|
return;
|
|
15
9
|
}
|
|
16
|
-
const currentIndex = enabledOptions.findIndex((option) => option ===
|
|
10
|
+
const currentIndex = enabledOptions.findIndex((option) => option === getDeepActiveElement());
|
|
17
11
|
let nextIndex;
|
|
18
12
|
if (currentIndex !== -1) {
|
|
19
13
|
if (forward) {
|
package/utils/dom.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ export declare const getCssVar: (element: Element, variableName: string) => stri
|
|
|
31
31
|
export declare const getCssVars: (element: Element, variableNames: string[]) => (string | null)[];
|
|
32
32
|
export declare const cloneNode: (el: Element, deep: boolean) => Element;
|
|
33
33
|
export declare const shouldReduceMotion: () => boolean;
|
|
34
|
+
export declare const getDeepActiveElement: (ownerDocument?: Document) => Element | null;
|
|
35
|
+
export declare const composedContains: (container: Node, node: Node | null) => boolean;
|
|
34
36
|
export declare const isAttrEqual: (oldVal: string | null, newVal: string | null) => boolean;
|
|
35
37
|
export declare const getScrollableParents: (node: HTMLElement | null) => (HTMLElement | Document)[];
|
|
36
38
|
export declare const isTransformedElement: (element: HTMLElement | null) => element is HTMLElement;
|
package/utils/dom.js
CHANGED
|
@@ -134,6 +134,32 @@ const cloneNode = (el, deep) => {
|
|
|
134
134
|
return el.cloneNode(deep);
|
|
135
135
|
};
|
|
136
136
|
const shouldReduceMotion = () => window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
137
|
+
const getDeepActiveElement = (ownerDocument = document) => {
|
|
138
|
+
let activeElement = ownerDocument.activeElement;
|
|
139
|
+
while (activeElement !== null && activeElement.shadowRoot !== null && activeElement.shadowRoot.activeElement !== null) {
|
|
140
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
141
|
+
}
|
|
142
|
+
return activeElement;
|
|
143
|
+
};
|
|
144
|
+
const composedContains = (container, node) => {
|
|
145
|
+
let current = node;
|
|
146
|
+
while (current !== null) {
|
|
147
|
+
if (current === container) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if (current.parentNode !== null) {
|
|
151
|
+
current = current.parentNode;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const root = current.getRootNode();
|
|
155
|
+
if (root instanceof ShadowRoot) {
|
|
156
|
+
current = root.host;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
current = null;
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
};
|
|
137
163
|
const isAttrEqual = (oldVal, newVal) => {
|
|
138
164
|
return oldVal === newVal || newVal === null && oldVal === "false" || newVal === "" && oldVal === "true";
|
|
139
165
|
};
|
|
@@ -190,10 +216,12 @@ export {
|
|
|
190
216
|
attrValueToPixels,
|
|
191
217
|
clampNumber,
|
|
192
218
|
cloneNode,
|
|
219
|
+
composedContains,
|
|
193
220
|
getAttribute,
|
|
194
221
|
getBooleanAttribute,
|
|
195
222
|
getCssVar,
|
|
196
223
|
getCssVars,
|
|
224
|
+
getDeepActiveElement,
|
|
197
225
|
getIntegerAttribute,
|
|
198
226
|
getLiteralAttribute,
|
|
199
227
|
getScrollableParents,
|
package/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context, subscribeContext } from "./context.js";
|
|
2
2
|
import { CSV_DELIMITER, getFirstCsvValue, packCsv, unpackCsv, updateCsv } from "./csv.js";
|
|
3
|
-
import { attrValueToInteger, attrValueToPixels, clampNumber, cloneNode, getAttribute, getBooleanAttribute, getCssVar, getCssVars, getIntegerAttribute, getLiteralAttribute, getScrollableParents, getTransformedAncestor, hasClass, isAttrEqual, isAttrTrue, isLiteralValue, isTransformedElement, setClass, shouldReduceMotion, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateIntegerAttribute, updateLiteralAttribute } from "./dom.js";
|
|
3
|
+
import { attrValueToInteger, attrValueToPixels, clampNumber, cloneNode, composedContains, getAttribute, getBooleanAttribute, getCssVar, getCssVars, getDeepActiveElement, getIntegerAttribute, getLiteralAttribute, getScrollableParents, getTransformedAncestor, hasClass, isAttrEqual, isAttrTrue, isLiteralValue, isTransformedElement, setClass, shouldReduceMotion, updateAttribute, updateBooleanAttribute, updateExplicitBooleanAttribute, updateIntegerAttribute, updateLiteralAttribute } from "./dom.js";
|
|
4
4
|
import { NectaryElement, defineCustomElement, pascalToKebabCase, registerComponent, resetNectaryRegistry, setNectaryRegistry } from "./element.js";
|
|
5
5
|
import { getRect, getTargetRect, rectOverlap } from "./rect.js";
|
|
6
6
|
import { getFirstFocusableElement, getFirstSlotElement, isElementFocused } from "./slot.js";
|
|
@@ -18,6 +18,7 @@ export {
|
|
|
18
18
|
attrValueToPixels,
|
|
19
19
|
clampNumber,
|
|
20
20
|
cloneNode,
|
|
21
|
+
composedContains,
|
|
21
22
|
debounceAnimationFrame,
|
|
22
23
|
debounceTimeout,
|
|
23
24
|
defineCustomElement,
|
|
@@ -25,6 +26,7 @@ export {
|
|
|
25
26
|
getBooleanAttribute,
|
|
26
27
|
getCssVar,
|
|
27
28
|
getCssVars,
|
|
29
|
+
getDeepActiveElement,
|
|
28
30
|
getFirstCsvValue,
|
|
29
31
|
getFirstFocusableElement,
|
|
30
32
|
getFirstSlotElement,
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
const getNonEsmShModuleFile = (modulePath) => {
|
|
2
|
+
if (modulePath === "bundle") {
|
|
3
|
+
return "bundle.js";
|
|
4
|
+
}
|
|
5
|
+
return `${modulePath}/index.js`;
|
|
6
|
+
};
|
|
1
7
|
const getImportPath = (cdnUrl, version, modulePath) => {
|
|
2
8
|
if (cdnUrl.length === 0) {
|
|
3
9
|
return null;
|
|
@@ -9,10 +15,11 @@ const getImportPath = (cdnUrl, version, modulePath) => {
|
|
|
9
15
|
}
|
|
10
16
|
return `${cdnUrl}/${modulePath}`;
|
|
11
17
|
}
|
|
18
|
+
const moduleFile = getNonEsmShModuleFile(modulePath);
|
|
12
19
|
if (version.length !== 0) {
|
|
13
|
-
return `${cdnUrl}/${version}/${
|
|
20
|
+
return `${cdnUrl}/${version}/${moduleFile}`;
|
|
14
21
|
}
|
|
15
|
-
return `${cdnUrl}/latest/${
|
|
22
|
+
return `${cdnUrl}/latest/${moduleFile}`;
|
|
16
23
|
};
|
|
17
24
|
const getCssImportPath = (cdnUrl, version, modulePath) => {
|
|
18
25
|
if (cdnUrl.length === 0) {
|