@nectary/components 5.41.0 → 5.41.1
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/bundle.js +44 -25
- package/package.json +1 -1
- package/pop/index.js +4 -20
- package/tooltip/index.js +36 -1
package/bundle.js
CHANGED
|
@@ -364,7 +364,7 @@ const typeValues$7 = ["m", "s", "xs", "xxs"];
|
|
|
364
364
|
const templateHTML$1k = '<style>:host{text-align:var(--sinch-comp-text-align);display:block;font:var(--sinch-comp-text-font);color:var(--sinch-global-color-text,var(--sinch-sys-color-text-default));--sinch-comp-text-font:var(--sinch-sys-font-body-m);--sinch-comp-text-align:unset}:host([inline]){display:inline}:host([type="s"]){--sinch-comp-text-font:var(--sinch-sys-font-body-s)}:host([type=xs]){--sinch-comp-text-font:var(--sinch-sys-font-body-xs)}:host([type=xxs]){--sinch-comp-text-font:var(--sinch-sys-font-body-xxs)}:host([type="m"][emphasized]){--sinch-comp-text-font:var(--sinch-sys-font-body-emphasize)}:host([type="s"][emphasized]){--sinch-comp-text-font:var(--sinch-sys-font-body-emphasize-s)}:host([type=xs][emphasized]){--sinch-comp-text-font:var(--sinch-sys-font-body-emphasize-xs)}:host([ellipsis]){overflow:hidden;text-overflow:ellipsis;white-space:nowrap;--sinch-global-text-white-space:nowrap}</style><slot></slot>';
|
|
365
365
|
const template$1k = document.createElement("template");
|
|
366
366
|
template$1k.innerHTML = templateHTML$1k;
|
|
367
|
-
|
|
367
|
+
let Text$1 = class Text2 extends NectaryElement {
|
|
368
368
|
constructor() {
|
|
369
369
|
super();
|
|
370
370
|
const shadowRoot = this.attachShadow();
|
|
@@ -423,8 +423,8 @@ class Text extends NectaryElement {
|
|
|
423
423
|
getBooleanAttribute(this, "inline") ? "text" : "paragraph"
|
|
424
424
|
);
|
|
425
425
|
}
|
|
426
|
-
}
|
|
427
|
-
defineCustomElement("sinch-text", Text);
|
|
426
|
+
};
|
|
427
|
+
defineCustomElement("sinch-text", Text$1);
|
|
428
428
|
const typeValues$6 = ["xl", "l", "m", "s", "xs"];
|
|
429
429
|
const templateHTML$1j = '<style>:host{display:block;--sinch-comp-title-font:var(--sinch-sys-font-desktop-title-m)}:host([type=xl]){--sinch-comp-title-font:var(--sinch-sys-font-desktop-title-xl)}:host([type="l"]){--sinch-comp-title-font:var(--sinch-sys-font-desktop-title-l)}:host([type="m"]){--sinch-comp-title-font:var(--sinch-sys-font-desktop-title-m)}:host([type="s"]){--sinch-comp-title-font:var(--sinch-sys-font-desktop-title-s)}:host([type=xs]){--sinch-comp-title-font:var(--sinch-sys-font-desktop-title-xs)}#text{letter-spacing:-2%;color:var(--sinch-global-color-text,var(--sinch-sys-color-text-default));font:var(--sinch-comp-title-font)}:host([ellipsis]) #text{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}</style><span id="text"></span>';
|
|
430
430
|
const template$1j = document.createElement("template");
|
|
@@ -3851,22 +3851,8 @@ class Pop extends NectaryElement {
|
|
|
3851
3851
|
const clampedPosition = shouldClamp ? clampPosition({ x: xPos, y: yPos, ...localViewportInfos }) : { x: xPos, y: yPos };
|
|
3852
3852
|
const clampedXPos = clampedPosition.x;
|
|
3853
3853
|
const clampedYPos = clampedPosition.y;
|
|
3854
|
-
if (this.hideOutsideViewport) {
|
|
3855
|
-
|
|
3856
|
-
const visibilityViewportInfos = {
|
|
3857
|
-
boundsWidth: window.innerWidth,
|
|
3858
|
-
boundsHeight: window.innerHeight,
|
|
3859
|
-
insetX: inset,
|
|
3860
|
-
insetY: inset,
|
|
3861
|
-
modalWidth: modalWidthViewport,
|
|
3862
|
-
modalHeight: modalHeightViewport
|
|
3863
|
-
};
|
|
3864
|
-
const isOutOfViewport = this.#isOutsideViewport(viewportPosition.x, viewportPosition.y, visibilityViewportInfos);
|
|
3865
|
-
if (isOutOfViewport) {
|
|
3866
|
-
this.#$dialog.style.setProperty("visibility", "hidden");
|
|
3867
|
-
} else {
|
|
3868
|
-
this.#$dialog.style.removeProperty("visibility");
|
|
3869
|
-
}
|
|
3854
|
+
if (this.hideOutsideViewport && this.#isTargetOutsideViewport(targetRectViewport, inset)) {
|
|
3855
|
+
this.#$dialog.style.setProperty("visibility", "hidden");
|
|
3870
3856
|
} else {
|
|
3871
3857
|
this.#$dialog.style.removeProperty("visibility");
|
|
3872
3858
|
}
|
|
@@ -3951,10 +3937,8 @@ class Pop extends NectaryElement {
|
|
|
3951
3937
|
this.#updateOrientation();
|
|
3952
3938
|
}
|
|
3953
3939
|
};
|
|
3954
|
-
#
|
|
3955
|
-
|
|
3956
|
-
const clampedPosition = clampPosition({ x, y, boundsWidth, boundsHeight, insetX, insetY, modalWidth, modalHeight });
|
|
3957
|
-
return Math.abs(clampedPosition.x - x) > 2 || Math.abs(clampedPosition.y - y) > 2;
|
|
3940
|
+
#isTargetOutsideViewport(targetRect, inset) {
|
|
3941
|
+
return targetRect.x + targetRect.width <= inset || targetRect.y + targetRect.height <= inset || targetRect.x >= window.innerWidth - inset || targetRect.y >= window.innerHeight - inset;
|
|
3958
3942
|
}
|
|
3959
3943
|
}
|
|
3960
3944
|
defineCustomElement("sinch-pop", Pop);
|
|
@@ -4122,6 +4106,7 @@ const SHOW_DELAY_FAST = 250;
|
|
|
4122
4106
|
const HIDE_DELAY = 0;
|
|
4123
4107
|
const ANIMATION_DURATION = 100;
|
|
4124
4108
|
const FOCUSABLE_OUTSIDE_TARGET_SELECTOR = 'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"]), [contenteditable=""], [contenteditable="true"]';
|
|
4109
|
+
const OPEN_FLOATING_LAYER_SELECTOR = "sinch-popover[open], sinch-pop[open], dialog[open]";
|
|
4125
4110
|
const OVERLAP_TOLERANCE = 1;
|
|
4126
4111
|
const MAX_ZERO_DIMENSION_PLACEMENT_RETRIES = 8;
|
|
4127
4112
|
const MIN_FIRST_REVEAL_STABILITY_FRAMES = 3;
|
|
@@ -4150,13 +4135,14 @@ class Tooltip extends NectaryElement {
|
|
|
4150
4135
|
#isSuspendedByHover = false;
|
|
4151
4136
|
#isSubscribed = false;
|
|
4152
4137
|
#controller;
|
|
4138
|
+
#childObserver = null;
|
|
4153
4139
|
#placementScheduled = false;
|
|
4154
4140
|
#zeroDimensionPlacementRetries = 0;
|
|
4155
4141
|
#revealRequestId = 0;
|
|
4156
4142
|
#hasCompletedFirstReveal = false;
|
|
4157
4143
|
constructor() {
|
|
4158
4144
|
super();
|
|
4159
|
-
const shadowRoot = this.attachShadow();
|
|
4145
|
+
const shadowRoot = this.attachShadow({ slotAssignment: "manual" });
|
|
4160
4146
|
shadowRoot.appendChild(template$Y.content.cloneNode(true));
|
|
4161
4147
|
this.#$pop = shadowRoot.querySelector("#pop");
|
|
4162
4148
|
this.#$tooltipText = shadowRoot.querySelector("#text");
|
|
@@ -4185,6 +4171,11 @@ class Tooltip extends NectaryElement {
|
|
|
4185
4171
|
this.setAttribute("role", "tooltip");
|
|
4186
4172
|
this.#$pop.addEventListener("-close", this.#onPopClose, options);
|
|
4187
4173
|
this.#$target.addEventListener("slotchange", this.#onTargetSlotChange, options);
|
|
4174
|
+
this.#assignTargetNodes();
|
|
4175
|
+
this.#childObserver = new MutationObserver(() => {
|
|
4176
|
+
this.#assignTargetNodes();
|
|
4177
|
+
});
|
|
4178
|
+
this.#childObserver.observe(this, { childList: true });
|
|
4188
4179
|
this.addEventListener("-show", this.#onShowReactHandler, options);
|
|
4189
4180
|
this.addEventListener("-hide", this.#onHideReactHandler, options);
|
|
4190
4181
|
this.#resizeObserver = new ResizeObserver(() => {
|
|
@@ -4216,6 +4207,8 @@ class Tooltip extends NectaryElement {
|
|
|
4216
4207
|
this.#controller = null;
|
|
4217
4208
|
this.#resizeObserver?.disconnect();
|
|
4218
4209
|
this.#resizeObserver = null;
|
|
4210
|
+
this.#childObserver?.disconnect();
|
|
4211
|
+
this.#childObserver = null;
|
|
4219
4212
|
}
|
|
4220
4213
|
static get observedAttributes() {
|
|
4221
4214
|
return [
|
|
@@ -4332,12 +4325,18 @@ class Tooltip extends NectaryElement {
|
|
|
4332
4325
|
this.#tooltipState.destroy();
|
|
4333
4326
|
};
|
|
4334
4327
|
#onMouseEnter = () => {
|
|
4328
|
+
if (this.#targetOwnsOpenFloatingLayer()) {
|
|
4329
|
+
return;
|
|
4330
|
+
}
|
|
4335
4331
|
this.#claimHoverOwnership();
|
|
4336
4332
|
this.#suspendFocusedTooltip();
|
|
4337
4333
|
this.#closeActiveTooltip();
|
|
4338
4334
|
this.#tooltipState.show();
|
|
4339
4335
|
};
|
|
4340
4336
|
#onContentMouseEnter = () => {
|
|
4337
|
+
if (this.#targetOwnsOpenFloatingLayer()) {
|
|
4338
|
+
return;
|
|
4339
|
+
}
|
|
4341
4340
|
this.#claimHoverOwnership();
|
|
4342
4341
|
if (this.#hasFocus) {
|
|
4343
4342
|
return;
|
|
@@ -4357,6 +4356,9 @@ class Tooltip extends NectaryElement {
|
|
|
4357
4356
|
this.#tooltipState.show();
|
|
4358
4357
|
};
|
|
4359
4358
|
#shouldOpenForFocus() {
|
|
4359
|
+
if (this.#targetOwnsOpenFloatingLayer()) {
|
|
4360
|
+
return false;
|
|
4361
|
+
}
|
|
4360
4362
|
const activeEl = getDeepActiveElement(this.ownerDocument);
|
|
4361
4363
|
if (!(activeEl instanceof HTMLElement) || !this.#targetContains(activeEl)) {
|
|
4362
4364
|
return false;
|
|
@@ -4472,6 +4474,12 @@ class Tooltip extends NectaryElement {
|
|
|
4472
4474
|
this.#tooltipState.hide();
|
|
4473
4475
|
});
|
|
4474
4476
|
};
|
|
4477
|
+
#assignTargetNodes() {
|
|
4478
|
+
const nodes = Array.from(this.childNodes).filter(
|
|
4479
|
+
(node) => node instanceof Element || node instanceof Text
|
|
4480
|
+
);
|
|
4481
|
+
this.#$target.assign(...nodes);
|
|
4482
|
+
}
|
|
4475
4483
|
#targetContains(node) {
|
|
4476
4484
|
return this.#$target.assignedElements().some((el) => composedContains(el, node));
|
|
4477
4485
|
}
|
|
@@ -4487,6 +4495,13 @@ class Tooltip extends NectaryElement {
|
|
|
4487
4495
|
#isFocusInFloatingLayer(el) {
|
|
4488
4496
|
return el.tagName === "SINCH-POP" || el.tagName === "SINCH-TOOLTIP";
|
|
4489
4497
|
}
|
|
4498
|
+
// Suppress while a target-owned floating layer (e.g. a sinch-popover triggered by the
|
|
4499
|
+
// target) is open, so the tooltip doesn't flicker over it or steal its focus.
|
|
4500
|
+
#targetOwnsOpenFloatingLayer() {
|
|
4501
|
+
return this.#getTargetElements().some((el) => {
|
|
4502
|
+
return el.matches(OPEN_FLOATING_LAYER_SELECTOR) || el.querySelector(OPEN_FLOATING_LAYER_SELECTOR) !== null;
|
|
4503
|
+
});
|
|
4504
|
+
}
|
|
4490
4505
|
#clearFocusSuppression() {
|
|
4491
4506
|
this.#suppressFocusIn = false;
|
|
4492
4507
|
this.#isSuspendedByHover = false;
|
|
@@ -4561,6 +4576,10 @@ class Tooltip extends NectaryElement {
|
|
|
4561
4576
|
};
|
|
4562
4577
|
// SHOW_DELAY ended, tooltip can be shown with animation
|
|
4563
4578
|
#onStateShowEnd = () => {
|
|
4579
|
+
if (this.#targetOwnsOpenFloatingLayer()) {
|
|
4580
|
+
this.#tooltipState.destroy();
|
|
4581
|
+
return;
|
|
4582
|
+
}
|
|
4564
4583
|
const revealRequestId = ++this.#revealRequestId;
|
|
4565
4584
|
activeTooltip = this;
|
|
4566
4585
|
this.#dispatchShowEvent();
|
|
@@ -17882,7 +17901,7 @@ export {
|
|
|
17882
17901
|
TabsIconOption,
|
|
17883
17902
|
TabsOption,
|
|
17884
17903
|
Tag,
|
|
17885
|
-
Text,
|
|
17904
|
+
Text$1 as Text,
|
|
17886
17905
|
Textarea,
|
|
17887
17906
|
TimePicker,
|
|
17888
17907
|
Title,
|
package/package.json
CHANGED
package/pop/index.js
CHANGED
|
@@ -381,22 +381,8 @@ class Pop extends NectaryElement {
|
|
|
381
381
|
const clampedPosition = shouldClamp ? clampPosition({ x: xPos, y: yPos, ...localViewportInfos }) : { x: xPos, y: yPos };
|
|
382
382
|
const clampedXPos = clampedPosition.x;
|
|
383
383
|
const clampedYPos = clampedPosition.y;
|
|
384
|
-
if (this.hideOutsideViewport) {
|
|
385
|
-
|
|
386
|
-
const visibilityViewportInfos = {
|
|
387
|
-
boundsWidth: window.innerWidth,
|
|
388
|
-
boundsHeight: window.innerHeight,
|
|
389
|
-
insetX: inset,
|
|
390
|
-
insetY: inset,
|
|
391
|
-
modalWidth: modalWidthViewport,
|
|
392
|
-
modalHeight: modalHeightViewport
|
|
393
|
-
};
|
|
394
|
-
const isOutOfViewport = this.#isOutsideViewport(viewportPosition.x, viewportPosition.y, visibilityViewportInfos);
|
|
395
|
-
if (isOutOfViewport) {
|
|
396
|
-
this.#$dialog.style.setProperty("visibility", "hidden");
|
|
397
|
-
} else {
|
|
398
|
-
this.#$dialog.style.removeProperty("visibility");
|
|
399
|
-
}
|
|
384
|
+
if (this.hideOutsideViewport && this.#isTargetOutsideViewport(targetRectViewport, inset)) {
|
|
385
|
+
this.#$dialog.style.setProperty("visibility", "hidden");
|
|
400
386
|
} else {
|
|
401
387
|
this.#$dialog.style.removeProperty("visibility");
|
|
402
388
|
}
|
|
@@ -481,10 +467,8 @@ class Pop extends NectaryElement {
|
|
|
481
467
|
this.#updateOrientation();
|
|
482
468
|
}
|
|
483
469
|
};
|
|
484
|
-
#
|
|
485
|
-
|
|
486
|
-
const clampedPosition = clampPosition({ x, y, boundsWidth, boundsHeight, insetX, insetY, modalWidth, modalHeight });
|
|
487
|
-
return Math.abs(clampedPosition.x - x) > 2 || Math.abs(clampedPosition.y - y) > 2;
|
|
470
|
+
#isTargetOutsideViewport(targetRect, inset) {
|
|
471
|
+
return targetRect.x + targetRect.width <= inset || targetRect.y + targetRect.height <= inset || targetRect.x >= window.innerWidth - inset || targetRect.y >= window.innerHeight - inset;
|
|
488
472
|
}
|
|
489
473
|
}
|
|
490
474
|
defineCustomElement("sinch-pop", Pop);
|
package/tooltip/index.js
CHANGED
|
@@ -14,6 +14,7 @@ const SHOW_DELAY_FAST = 250;
|
|
|
14
14
|
const HIDE_DELAY = 0;
|
|
15
15
|
const ANIMATION_DURATION = 100;
|
|
16
16
|
const FOCUSABLE_OUTSIDE_TARGET_SELECTOR = 'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"]), [contenteditable=""], [contenteditable="true"]';
|
|
17
|
+
const OPEN_FLOATING_LAYER_SELECTOR = "sinch-popover[open], sinch-pop[open], dialog[open]";
|
|
17
18
|
const OVERLAP_TOLERANCE = 1;
|
|
18
19
|
const MAX_ZERO_DIMENSION_PLACEMENT_RETRIES = 8;
|
|
19
20
|
const MIN_FIRST_REVEAL_STABILITY_FRAMES = 3;
|
|
@@ -42,13 +43,14 @@ class Tooltip extends NectaryElement {
|
|
|
42
43
|
#isSuspendedByHover = false;
|
|
43
44
|
#isSubscribed = false;
|
|
44
45
|
#controller;
|
|
46
|
+
#childObserver = null;
|
|
45
47
|
#placementScheduled = false;
|
|
46
48
|
#zeroDimensionPlacementRetries = 0;
|
|
47
49
|
#revealRequestId = 0;
|
|
48
50
|
#hasCompletedFirstReveal = false;
|
|
49
51
|
constructor() {
|
|
50
52
|
super();
|
|
51
|
-
const shadowRoot = this.attachShadow();
|
|
53
|
+
const shadowRoot = this.attachShadow({ slotAssignment: "manual" });
|
|
52
54
|
shadowRoot.appendChild(template.content.cloneNode(true));
|
|
53
55
|
this.#$pop = shadowRoot.querySelector("#pop");
|
|
54
56
|
this.#$tooltipText = shadowRoot.querySelector("#text");
|
|
@@ -77,6 +79,11 @@ class Tooltip extends NectaryElement {
|
|
|
77
79
|
this.setAttribute("role", "tooltip");
|
|
78
80
|
this.#$pop.addEventListener("-close", this.#onPopClose, options);
|
|
79
81
|
this.#$target.addEventListener("slotchange", this.#onTargetSlotChange, options);
|
|
82
|
+
this.#assignTargetNodes();
|
|
83
|
+
this.#childObserver = new MutationObserver(() => {
|
|
84
|
+
this.#assignTargetNodes();
|
|
85
|
+
});
|
|
86
|
+
this.#childObserver.observe(this, { childList: true });
|
|
80
87
|
this.addEventListener("-show", this.#onShowReactHandler, options);
|
|
81
88
|
this.addEventListener("-hide", this.#onHideReactHandler, options);
|
|
82
89
|
this.#resizeObserver = new ResizeObserver(() => {
|
|
@@ -108,6 +115,8 @@ class Tooltip extends NectaryElement {
|
|
|
108
115
|
this.#controller = null;
|
|
109
116
|
this.#resizeObserver?.disconnect();
|
|
110
117
|
this.#resizeObserver = null;
|
|
118
|
+
this.#childObserver?.disconnect();
|
|
119
|
+
this.#childObserver = null;
|
|
111
120
|
}
|
|
112
121
|
static get observedAttributes() {
|
|
113
122
|
return [
|
|
@@ -224,12 +233,18 @@ class Tooltip extends NectaryElement {
|
|
|
224
233
|
this.#tooltipState.destroy();
|
|
225
234
|
};
|
|
226
235
|
#onMouseEnter = () => {
|
|
236
|
+
if (this.#targetOwnsOpenFloatingLayer()) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
227
239
|
this.#claimHoverOwnership();
|
|
228
240
|
this.#suspendFocusedTooltip();
|
|
229
241
|
this.#closeActiveTooltip();
|
|
230
242
|
this.#tooltipState.show();
|
|
231
243
|
};
|
|
232
244
|
#onContentMouseEnter = () => {
|
|
245
|
+
if (this.#targetOwnsOpenFloatingLayer()) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
233
248
|
this.#claimHoverOwnership();
|
|
234
249
|
if (this.#hasFocus) {
|
|
235
250
|
return;
|
|
@@ -249,6 +264,9 @@ class Tooltip extends NectaryElement {
|
|
|
249
264
|
this.#tooltipState.show();
|
|
250
265
|
};
|
|
251
266
|
#shouldOpenForFocus() {
|
|
267
|
+
if (this.#targetOwnsOpenFloatingLayer()) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
252
270
|
const activeEl = getDeepActiveElement(this.ownerDocument);
|
|
253
271
|
if (!(activeEl instanceof HTMLElement) || !this.#targetContains(activeEl)) {
|
|
254
272
|
return false;
|
|
@@ -364,6 +382,12 @@ class Tooltip extends NectaryElement {
|
|
|
364
382
|
this.#tooltipState.hide();
|
|
365
383
|
});
|
|
366
384
|
};
|
|
385
|
+
#assignTargetNodes() {
|
|
386
|
+
const nodes = Array.from(this.childNodes).filter(
|
|
387
|
+
(node) => node instanceof Element || node instanceof Text
|
|
388
|
+
);
|
|
389
|
+
this.#$target.assign(...nodes);
|
|
390
|
+
}
|
|
367
391
|
#targetContains(node) {
|
|
368
392
|
return this.#$target.assignedElements().some((el) => composedContains(el, node));
|
|
369
393
|
}
|
|
@@ -379,6 +403,13 @@ class Tooltip extends NectaryElement {
|
|
|
379
403
|
#isFocusInFloatingLayer(el) {
|
|
380
404
|
return el.tagName === "SINCH-POP" || el.tagName === "SINCH-TOOLTIP";
|
|
381
405
|
}
|
|
406
|
+
// Suppress while a target-owned floating layer (e.g. a sinch-popover triggered by the
|
|
407
|
+
// target) is open, so the tooltip doesn't flicker over it or steal its focus.
|
|
408
|
+
#targetOwnsOpenFloatingLayer() {
|
|
409
|
+
return this.#getTargetElements().some((el) => {
|
|
410
|
+
return el.matches(OPEN_FLOATING_LAYER_SELECTOR) || el.querySelector(OPEN_FLOATING_LAYER_SELECTOR) !== null;
|
|
411
|
+
});
|
|
412
|
+
}
|
|
382
413
|
#clearFocusSuppression() {
|
|
383
414
|
this.#suppressFocusIn = false;
|
|
384
415
|
this.#isSuspendedByHover = false;
|
|
@@ -453,6 +484,10 @@ class Tooltip extends NectaryElement {
|
|
|
453
484
|
};
|
|
454
485
|
// SHOW_DELAY ended, tooltip can be shown with animation
|
|
455
486
|
#onStateShowEnd = () => {
|
|
487
|
+
if (this.#targetOwnsOpenFloatingLayer()) {
|
|
488
|
+
this.#tooltipState.destroy();
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
456
491
|
const revealRequestId = ++this.#revealRequestId;
|
|
457
492
|
activeTooltip = this;
|
|
458
493
|
this.#dispatchShowEvent();
|