@nectary/components 5.29.0 → 5.29.2
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 +463 -105
- package/package.json +3 -3
- package/pop/index.d.ts +6 -0
- package/pop/index.js +140 -93
- package/pop/utils.d.ts +20 -0
- package/pop/utils.js +46 -0
- package/skeleton/index.js +1 -1
- package/skeleton-item/index.js +1 -1
- package/tooltip/index.js +176 -12
- package/utils/dom.d.ts +2 -0
- package/utils/dom.js +34 -0
- package/utils/index.js +3 -1
- package/utils/placement.d.ts +13 -0
- package/utils/placement.js +78 -0
package/bundle.js
CHANGED
|
@@ -143,6 +143,38 @@ const getScrollableParents = (node) => {
|
|
|
143
143
|
scrollableParents.push(document);
|
|
144
144
|
return scrollableParents;
|
|
145
145
|
};
|
|
146
|
+
const isTransformedElement = (element) => {
|
|
147
|
+
if (element == null) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
const style = getComputedStyle(element);
|
|
151
|
+
const backdropFilter = style.getPropertyValue("backdrop-filter");
|
|
152
|
+
const hasTransform = style.transform !== "none" || style.perspective !== "none" || style.filter !== "none" || backdropFilter !== "" && backdropFilter !== "none";
|
|
153
|
+
const hasWillChange = style.willChange.split(",").map((value) => value.trim().toLowerCase()).some((value) => value === "transform" || value === "perspective" || value === "filter" || value === "backdrop-filter");
|
|
154
|
+
return hasTransform || hasWillChange;
|
|
155
|
+
};
|
|
156
|
+
const getTransformedAncestor = (node) => {
|
|
157
|
+
let current = node;
|
|
158
|
+
while (current != null) {
|
|
159
|
+
if (current !== node) {
|
|
160
|
+
if (isTransformedElement(current)) {
|
|
161
|
+
return current;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const parent = current.parentElement;
|
|
165
|
+
if (parent != null) {
|
|
166
|
+
current = parent;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const root = current.getRootNode();
|
|
170
|
+
if (root instanceof ShadowRoot && root.host instanceof HTMLElement) {
|
|
171
|
+
current = root.host;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
};
|
|
146
178
|
class NectaryElementBase extends HTMLElement {
|
|
147
179
|
static _isGlobal = false;
|
|
148
180
|
static get elementName() {
|
|
@@ -3138,6 +3170,79 @@ const createThrottle = (delayFn, cancelFn) => (cb) => {
|
|
|
3138
3170
|
};
|
|
3139
3171
|
};
|
|
3140
3172
|
const throttleAnimationFrame = createThrottle(globalThis.requestAnimationFrame, globalThis.cancelAnimationFrame);
|
|
3173
|
+
const resolveTransformedAncestor = (node, ancestorHint) => {
|
|
3174
|
+
if (node != null && ancestorHint != null && ancestorHint.isConnected && isTransformedElement(ancestorHint) && (ancestorHint === node || ancestorHint.contains(node))) {
|
|
3175
|
+
return ancestorHint;
|
|
3176
|
+
}
|
|
3177
|
+
return getTransformedAncestor(node);
|
|
3178
|
+
};
|
|
3179
|
+
const getTransformedAncestorScale = (ancestor) => {
|
|
3180
|
+
if (ancestor == null) {
|
|
3181
|
+
return { scaleX: 1, scaleY: 1 };
|
|
3182
|
+
}
|
|
3183
|
+
const transform = getComputedStyle(ancestor).transform;
|
|
3184
|
+
let matrixScaleX = null;
|
|
3185
|
+
let matrixScaleY = null;
|
|
3186
|
+
if (transform !== "none") {
|
|
3187
|
+
try {
|
|
3188
|
+
const matrix = new DOMMatrixReadOnly(transform);
|
|
3189
|
+
matrixScaleX = Math.hypot(matrix.a, matrix.b);
|
|
3190
|
+
matrixScaleY = Math.hypot(matrix.c, matrix.d);
|
|
3191
|
+
} catch {
|
|
3192
|
+
matrixScaleX = null;
|
|
3193
|
+
matrixScaleY = null;
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
if (matrixScaleX !== null && matrixScaleY !== null) {
|
|
3197
|
+
return {
|
|
3198
|
+
scaleX: Number.isFinite(matrixScaleX) && matrixScaleX > 0 ? matrixScaleX : 1,
|
|
3199
|
+
scaleY: Number.isFinite(matrixScaleY) && matrixScaleY > 0 ? matrixScaleY : 1
|
|
3200
|
+
};
|
|
3201
|
+
}
|
|
3202
|
+
const rect = ancestor.getBoundingClientRect();
|
|
3203
|
+
const baseWidth = ancestor.offsetWidth;
|
|
3204
|
+
const baseHeight = ancestor.offsetHeight;
|
|
3205
|
+
const scaleX = baseWidth > 0 ? rect.width / baseWidth : 1;
|
|
3206
|
+
const scaleY = baseHeight > 0 ? rect.height / baseHeight : 1;
|
|
3207
|
+
return {
|
|
3208
|
+
scaleX: Number.isFinite(scaleX) && scaleX > 0 ? scaleX : 1,
|
|
3209
|
+
scaleY: Number.isFinite(scaleY) && scaleY > 0 ? scaleY : 1
|
|
3210
|
+
};
|
|
3211
|
+
};
|
|
3212
|
+
const getPlacementContext = (node, ancestorHint) => {
|
|
3213
|
+
const transformedAncestor = resolveTransformedAncestor(node, ancestorHint);
|
|
3214
|
+
const ancestorRect = transformedAncestor?.getBoundingClientRect() ?? null;
|
|
3215
|
+
const ancestorClientLeft = transformedAncestor?.clientLeft ?? 0;
|
|
3216
|
+
const ancestorClientTop = transformedAncestor?.clientTop ?? 0;
|
|
3217
|
+
const ancestorClientWidth = transformedAncestor?.clientWidth ?? 0;
|
|
3218
|
+
const ancestorClientHeight = transformedAncestor?.clientHeight ?? 0;
|
|
3219
|
+
const { scaleX, scaleY } = getTransformedAncestorScale(transformedAncestor);
|
|
3220
|
+
const boundsLeft = ancestorRect != null ? ancestorRect.x + ancestorClientLeft * scaleX : 0;
|
|
3221
|
+
const boundsTop = ancestorRect != null ? ancestorRect.y + ancestorClientTop * scaleY : 0;
|
|
3222
|
+
const boundsWidth = ancestorRect != null && ancestorClientWidth > 0 ? ancestorClientWidth : ancestorRect != null ? ancestorRect.width / scaleX : window.innerWidth;
|
|
3223
|
+
const boundsHeight = ancestorRect != null && ancestorClientHeight > 0 ? ancestorClientHeight : ancestorRect != null ? ancestorRect.height / scaleY : window.innerHeight;
|
|
3224
|
+
return {
|
|
3225
|
+
transformedAncestor,
|
|
3226
|
+
ancestorRect,
|
|
3227
|
+
scaleX,
|
|
3228
|
+
scaleY,
|
|
3229
|
+
boundsLeft,
|
|
3230
|
+
boundsTop,
|
|
3231
|
+
boundsWidth,
|
|
3232
|
+
boundsHeight
|
|
3233
|
+
};
|
|
3234
|
+
};
|
|
3235
|
+
const toLocalRect = (rect, placementContext) => {
|
|
3236
|
+
if (placementContext.transformedAncestor == null) {
|
|
3237
|
+
return rect;
|
|
3238
|
+
}
|
|
3239
|
+
return {
|
|
3240
|
+
x: (rect.x - placementContext.boundsLeft) / placementContext.scaleX,
|
|
3241
|
+
y: (rect.y - placementContext.boundsTop) / placementContext.scaleY,
|
|
3242
|
+
width: rect.width / placementContext.scaleX,
|
|
3243
|
+
height: rect.height / placementContext.scaleY
|
|
3244
|
+
};
|
|
3245
|
+
};
|
|
3141
3246
|
const orientationValues$2 = [
|
|
3142
3247
|
"top-left",
|
|
3143
3248
|
"top-right",
|
|
@@ -3150,6 +3255,50 @@ const orientationValues$2 = [
|
|
|
3150
3255
|
"center-left",
|
|
3151
3256
|
"center-right"
|
|
3152
3257
|
];
|
|
3258
|
+
const getAnchorPosition = (rect, width, height, orient) => {
|
|
3259
|
+
let x = 0;
|
|
3260
|
+
let y = 0;
|
|
3261
|
+
if (orient === "bottom-right" || orient === "top-right" || orient === "top-stretch" || orient === "bottom-stretch") {
|
|
3262
|
+
x = rect.x;
|
|
3263
|
+
}
|
|
3264
|
+
if (orient === "bottom-left" || orient === "top-left") {
|
|
3265
|
+
x = rect.x + rect.width - width;
|
|
3266
|
+
}
|
|
3267
|
+
if (orient === "bottom-center" || orient === "top-center") {
|
|
3268
|
+
x = rect.x + rect.width / 2 - width / 2;
|
|
3269
|
+
}
|
|
3270
|
+
if (orient === "center-right") {
|
|
3271
|
+
x = rect.x + rect.width;
|
|
3272
|
+
}
|
|
3273
|
+
if (orient === "center-left") {
|
|
3274
|
+
x = rect.x - width;
|
|
3275
|
+
}
|
|
3276
|
+
if (orient === "bottom-left" || orient === "bottom-right" || orient === "bottom-stretch" || orient === "bottom-center") {
|
|
3277
|
+
y = rect.y + rect.height;
|
|
3278
|
+
}
|
|
3279
|
+
if (orient === "top-left" || orient === "top-right" || orient === "top-stretch" || orient === "top-center") {
|
|
3280
|
+
y = rect.y - height;
|
|
3281
|
+
}
|
|
3282
|
+
if (orient === "center-left" || orient === "center-right") {
|
|
3283
|
+
y = rect.y + rect.height / 2 - height / 2;
|
|
3284
|
+
}
|
|
3285
|
+
return { x, y };
|
|
3286
|
+
};
|
|
3287
|
+
const clampPosition = ({
|
|
3288
|
+
x,
|
|
3289
|
+
y,
|
|
3290
|
+
boundsWidth,
|
|
3291
|
+
boundsHeight,
|
|
3292
|
+
insetX,
|
|
3293
|
+
insetY,
|
|
3294
|
+
modalWidth,
|
|
3295
|
+
modalHeight
|
|
3296
|
+
}) => {
|
|
3297
|
+
return {
|
|
3298
|
+
x: Math.max(insetX, Math.min(x, boundsWidth - modalWidth - insetX)),
|
|
3299
|
+
y: Math.max(insetY, Math.min(y, boundsHeight - modalHeight - insetY))
|
|
3300
|
+
};
|
|
3301
|
+
};
|
|
3153
3302
|
const bodyEl$1 = document.body;
|
|
3154
3303
|
const disableOverscroll = () => {
|
|
3155
3304
|
bodyEl$1.__pop_counter__ = (bodyEl$1.__pop_counter__ ?? 0) + 1;
|
|
@@ -3165,7 +3314,7 @@ const enableOverscroll = () => {
|
|
|
3165
3314
|
document.documentElement.style.removeProperty("overscroll-behavior");
|
|
3166
3315
|
}
|
|
3167
3316
|
};
|
|
3168
|
-
const templateHTML$U = '<style>:host{display:contents;position:relative}dialog{position:fixed;left:0;top:0;margin:0;outline:0;padding:0;border:none;box-sizing:border-box;max-width:unset;max-height:unset;z-index:1;background:0 0;overflow:visible}dialog:not([open]){display:none}dialog::backdrop{background-color:transparent}#content{position:relative;z-index:1}#target-open{display:flex;flex-direction:column;position:absolute;left:0;top:0}#focus{display:none;position:absolute;width:0;height:0}</style><slot id="target" name="target" aria-haspopup="dialog" aria-expanded="false"></slot><div id="focus"></div><dialog id="dialog"><div id="target-open"><slot name="target-open"></slot></div><div id="content"><slot name="content"></slot></div></dialog>';
|
|
3317
|
+
const templateHTML$U = '<style>:host{display:contents;position:relative}dialog{position:fixed;left:0;top:0;transform:translate(var(--sinch-pop-offset-x),var(--sinch-pop-offset-y));margin:0;outline:0;padding:0;border:none;box-sizing:border-box;max-width:unset;max-height:unset;z-index:1;background:0 0;overflow:visible}dialog:not([open]){display:none}dialog::backdrop{background-color:transparent}#content{position:relative;z-index:1}#target-open{display:flex;flex-direction:column;position:absolute;left:0;top:0}#focus{display:none;position:absolute;width:0;height:0}</style><slot id="target" name="target" aria-haspopup="dialog" aria-expanded="false"></slot><div id="focus"></div><dialog id="dialog"><div id="target-open"><slot name="target-open"></slot></div><div id="content"><slot name="content"></slot></div></dialog>';
|
|
3169
3318
|
const template$U = document.createElement("template");
|
|
3170
3319
|
template$U.innerHTML = templateHTML$U;
|
|
3171
3320
|
class Pop extends NectaryElement {
|
|
@@ -3173,6 +3322,7 @@ class Pop extends NectaryElement {
|
|
|
3173
3322
|
#$focus;
|
|
3174
3323
|
#$dialog;
|
|
3175
3324
|
#resizeThrottle;
|
|
3325
|
+
#scrollPositionThrottle;
|
|
3176
3326
|
#resizeObserver;
|
|
3177
3327
|
#$targetSlot;
|
|
3178
3328
|
#$targetOpenSlot;
|
|
@@ -3182,10 +3332,15 @@ class Pop extends NectaryElement {
|
|
|
3182
3332
|
#controller;
|
|
3183
3333
|
#keydownContext;
|
|
3184
3334
|
#visibilityContext;
|
|
3185
|
-
#targetStyleValue = null;
|
|
3186
3335
|
#modalWidth = 0;
|
|
3187
3336
|
#modalHeight = 0;
|
|
3188
3337
|
#scrollableParents = [];
|
|
3338
|
+
#openSession = {
|
|
3339
|
+
effectiveAllowScroll: false,
|
|
3340
|
+
modalSemantics: false,
|
|
3341
|
+
targetStyleValue: null,
|
|
3342
|
+
transformedAncestor: null
|
|
3343
|
+
};
|
|
3189
3344
|
constructor() {
|
|
3190
3345
|
super();
|
|
3191
3346
|
const shadowRoot = this.attachShadow();
|
|
@@ -3198,6 +3353,9 @@ class Pop extends NectaryElement {
|
|
|
3198
3353
|
this.#$contentSlot = shadowRoot.querySelector('slot[name="content"]');
|
|
3199
3354
|
this.#$targetOpenWrapper = shadowRoot.querySelector("#target-open");
|
|
3200
3355
|
this.#resizeThrottle = throttleAnimationFrame(this.#updateOrientation);
|
|
3356
|
+
this.#scrollPositionThrottle = throttleAnimationFrame(() => {
|
|
3357
|
+
this.#updatePosition(false);
|
|
3358
|
+
});
|
|
3201
3359
|
this.#resizeObserver = new ResizeObserver(() => {
|
|
3202
3360
|
this.#resizeThrottle.fn();
|
|
3203
3361
|
});
|
|
@@ -3227,6 +3385,7 @@ class Pop extends NectaryElement {
|
|
|
3227
3385
|
this.#controller.abort();
|
|
3228
3386
|
this.#controller = null;
|
|
3229
3387
|
this.#resizeThrottle.cancel();
|
|
3388
|
+
this.#scrollPositionThrottle.cancel();
|
|
3230
3389
|
this.#resizeObserver.disconnect();
|
|
3231
3390
|
this.#onCollapse();
|
|
3232
3391
|
}
|
|
@@ -3322,10 +3481,68 @@ class Pop extends NectaryElement {
|
|
|
3322
3481
|
}
|
|
3323
3482
|
return item;
|
|
3324
3483
|
}
|
|
3484
|
+
#prepareTransferredTarget() {
|
|
3485
|
+
const targetEl = this.#getFirstTargetElement(this.#$targetSlot);
|
|
3486
|
+
const targetElComputedStyle = getComputedStyle(targetEl);
|
|
3487
|
+
const marginLeft = parseInt(targetElComputedStyle.marginLeft, 10);
|
|
3488
|
+
const marginRight = parseInt(targetElComputedStyle.marginRight, 10);
|
|
3489
|
+
const marginTop = parseInt(targetElComputedStyle.marginTop, 10);
|
|
3490
|
+
const marginBottom = parseInt(targetElComputedStyle.marginBottom, 10);
|
|
3491
|
+
const targetRect = this.#getTargetRect();
|
|
3492
|
+
this.#$targetWrapper.style.setProperty("display", "block");
|
|
3493
|
+
this.#$targetWrapper.style.setProperty("width", `${targetRect.width + marginLeft + marginRight}px`);
|
|
3494
|
+
this.#$targetWrapper.style.setProperty("height", `${targetRect.height + marginTop + marginBottom}px`);
|
|
3495
|
+
this.#$targetOpenWrapper.style.setProperty("width", `${targetRect.width}px`);
|
|
3496
|
+
this.#$targetOpenWrapper.style.setProperty("height", `${targetRect.height}px`);
|
|
3497
|
+
this.#openSession.targetStyleValue = targetEl.getAttribute("style");
|
|
3498
|
+
targetEl.style.setProperty("margin", "0");
|
|
3499
|
+
targetEl.style.setProperty("position", "static");
|
|
3500
|
+
if (targetElComputedStyle.transform !== "none") {
|
|
3501
|
+
const matrix = new DOMMatrixReadOnly(targetElComputedStyle.transform);
|
|
3502
|
+
targetEl.style.setProperty("transform", matrix.translate(-matrix.e, -matrix.f).toString());
|
|
3503
|
+
}
|
|
3504
|
+
getFirstSlotElement(this.#$targetSlot)?.setAttribute("slot", "target-open");
|
|
3505
|
+
}
|
|
3506
|
+
#restoreTransferredTarget() {
|
|
3507
|
+
const targetEl = this.#getFirstTargetElement(this.#$targetOpenSlot);
|
|
3508
|
+
const { targetStyleValue } = this.#openSession;
|
|
3509
|
+
if (targetStyleValue === null) {
|
|
3510
|
+
targetEl.style.removeProperty("margin");
|
|
3511
|
+
targetEl.style.removeProperty("position");
|
|
3512
|
+
targetEl.style.removeProperty("transform");
|
|
3513
|
+
} else {
|
|
3514
|
+
targetEl.setAttribute("style", targetStyleValue);
|
|
3515
|
+
}
|
|
3516
|
+
getFirstSlotElement(this.#$targetOpenSlot)?.setAttribute("slot", "target");
|
|
3517
|
+
this.#$targetWrapper.style.removeProperty("display");
|
|
3518
|
+
this.#$targetWrapper.style.removeProperty("width");
|
|
3519
|
+
this.#$targetWrapper.style.removeProperty("height");
|
|
3520
|
+
}
|
|
3521
|
+
#subscribeScrollTracking() {
|
|
3522
|
+
this.#scrollableParents = getScrollableParents(this.#getFirstTargetElement(this.#$targetSlot));
|
|
3523
|
+
this.#scrollableParents.forEach((el) => {
|
|
3524
|
+
el.addEventListener("scroll", this.#onScrollableParentScroll, { passive: true, capture: true });
|
|
3525
|
+
});
|
|
3526
|
+
}
|
|
3527
|
+
#unsubscribeScrollTracking() {
|
|
3528
|
+
this.#scrollableParents.forEach((el) => {
|
|
3529
|
+
el.removeEventListener("scroll", this.#onScrollableParentScroll, { capture: true });
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3325
3532
|
#onExpand() {
|
|
3326
3533
|
if (!this.isDomConnected || this.#$dialog.open) {
|
|
3327
3534
|
return;
|
|
3328
3535
|
}
|
|
3536
|
+
const transformedAncestor = getTransformedAncestor(this);
|
|
3537
|
+
const effectiveAllowScroll = this.allowScroll || transformedAncestor != null;
|
|
3538
|
+
const shouldUseModal = this.modal && transformedAncestor == null;
|
|
3539
|
+
const openAsModal = shouldUseModal || !effectiveAllowScroll;
|
|
3540
|
+
this.#openSession = {
|
|
3541
|
+
effectiveAllowScroll,
|
|
3542
|
+
modalSemantics: shouldUseModal,
|
|
3543
|
+
targetStyleValue: null,
|
|
3544
|
+
transformedAncestor
|
|
3545
|
+
};
|
|
3329
3546
|
this.#$targetSlot.addEventListener("blur", this.#stopEventPropagation, true);
|
|
3330
3547
|
this.#$focus.setAttribute("tabindex", "-1");
|
|
3331
3548
|
this.#$focus.style.display = "block";
|
|
@@ -3335,7 +3552,7 @@ class Pop extends NectaryElement {
|
|
|
3335
3552
|
this.#$targetSlot.removeEventListener("blur", this.#stopEventPropagation, true);
|
|
3336
3553
|
this.#$focus.removeAttribute("tabindex");
|
|
3337
3554
|
this.#$focus.removeAttribute("style");
|
|
3338
|
-
if (
|
|
3555
|
+
if (openAsModal) {
|
|
3339
3556
|
this.#$dialog.showModal();
|
|
3340
3557
|
} else {
|
|
3341
3558
|
this.#$dialog.show();
|
|
@@ -3343,32 +3560,13 @@ class Pop extends NectaryElement {
|
|
|
3343
3560
|
this.#$targetWrapper.setAttribute("aria-expanded", "true");
|
|
3344
3561
|
this.#updateOrientation();
|
|
3345
3562
|
this.#resizeObserver.observe(this.#$dialog);
|
|
3346
|
-
if (
|
|
3563
|
+
if (shouldUseModal) {
|
|
3347
3564
|
getFirstFocusableElement(this.#$contentSlot)?.focus();
|
|
3348
3565
|
} else {
|
|
3349
|
-
if (!
|
|
3350
|
-
|
|
3351
|
-
const targetElComputedStyle = getComputedStyle($targetEl);
|
|
3352
|
-
const marginLeft = parseInt(targetElComputedStyle.marginLeft);
|
|
3353
|
-
const marginRight = parseInt(targetElComputedStyle.marginRight);
|
|
3354
|
-
const marginTop = parseInt(targetElComputedStyle.marginTop);
|
|
3355
|
-
const marginBottom = parseInt(targetElComputedStyle.marginBottom);
|
|
3356
|
-
const targetRect = this.#getTargetRect();
|
|
3357
|
-
this.#$targetWrapper.style.setProperty("display", "block");
|
|
3358
|
-
this.#$targetWrapper.style.setProperty("width", `${targetRect.width + marginLeft + marginRight}px`);
|
|
3359
|
-
this.#$targetWrapper.style.setProperty("height", `${targetRect.height + marginTop + marginBottom}px`);
|
|
3360
|
-
this.#$targetOpenWrapper.style.setProperty("width", `${targetRect.width}px`);
|
|
3361
|
-
this.#$targetOpenWrapper.style.setProperty("height", `${targetRect.height}px`);
|
|
3362
|
-
this.#targetStyleValue = $targetEl.getAttribute("style");
|
|
3363
|
-
$targetEl.style.setProperty("margin", "0");
|
|
3364
|
-
$targetEl.style.setProperty("position", "static");
|
|
3365
|
-
if (targetElComputedStyle.transform !== "none") {
|
|
3366
|
-
const matrix = new DOMMatrixReadOnly(targetElComputedStyle.transform);
|
|
3367
|
-
$targetEl.style.setProperty("transform", matrix.translate(-matrix.e, -matrix.f).toString());
|
|
3368
|
-
}
|
|
3369
|
-
getFirstSlotElement(this.#$targetSlot)?.setAttribute("slot", "target-open");
|
|
3566
|
+
if (!effectiveAllowScroll) {
|
|
3567
|
+
this.#prepareTransferredTarget();
|
|
3370
3568
|
}
|
|
3371
|
-
const activeSlot =
|
|
3569
|
+
const activeSlot = effectiveAllowScroll ? this.#$targetSlot : this.#$targetOpenSlot;
|
|
3372
3570
|
activeSlot.addEventListener("keydown", this.#onTargetKeydown);
|
|
3373
3571
|
if (this.#targetActiveElement !== null) {
|
|
3374
3572
|
activeSlot.addEventListener("focus", this.#stopEventPropagation, true);
|
|
@@ -3385,13 +3583,10 @@ class Pop extends NectaryElement {
|
|
|
3385
3583
|
}
|
|
3386
3584
|
}
|
|
3387
3585
|
}
|
|
3388
|
-
if (!
|
|
3586
|
+
if (!effectiveAllowScroll) {
|
|
3389
3587
|
disableOverscroll();
|
|
3390
3588
|
} else {
|
|
3391
|
-
this.#
|
|
3392
|
-
this.#scrollableParents.forEach((el) => {
|
|
3393
|
-
el.addEventListener("scroll", () => this.#updatePosition(false), { passive: true, capture: true });
|
|
3394
|
-
});
|
|
3589
|
+
this.#subscribeScrollTracking();
|
|
3395
3590
|
}
|
|
3396
3591
|
window.addEventListener("resize", this.#onResize);
|
|
3397
3592
|
requestAnimationFrame(() => {
|
|
@@ -3406,9 +3601,11 @@ class Pop extends NectaryElement {
|
|
|
3406
3601
|
if (!this.#$dialog.open) {
|
|
3407
3602
|
return;
|
|
3408
3603
|
}
|
|
3604
|
+
const openSession = this.#openSession;
|
|
3605
|
+
const effectiveAllowScroll = openSession.effectiveAllowScroll;
|
|
3409
3606
|
this.#resizeObserver.disconnect();
|
|
3410
|
-
const isNonModal = !
|
|
3411
|
-
const activeSlot =
|
|
3607
|
+
const isNonModal = !openSession.modalSemantics;
|
|
3608
|
+
const activeSlot = effectiveAllowScroll ? this.#$targetSlot : this.#$targetOpenSlot;
|
|
3412
3609
|
this.#dispatchContentVisibility(false);
|
|
3413
3610
|
activeSlot.removeEventListener("keydown", this.#onTargetKeydown);
|
|
3414
3611
|
if (isNonModal) {
|
|
@@ -3419,19 +3616,8 @@ class Pop extends NectaryElement {
|
|
|
3419
3616
|
if (isNonModal) {
|
|
3420
3617
|
activeSlot.removeEventListener("blur", this.#captureActiveElement, true);
|
|
3421
3618
|
}
|
|
3422
|
-
if (isNonModal && !
|
|
3423
|
-
|
|
3424
|
-
targetEl.style.removeProperty("margin");
|
|
3425
|
-
targetEl.style.removeProperty("position");
|
|
3426
|
-
targetEl.style.removeProperty("transform");
|
|
3427
|
-
if (this.#targetStyleValue !== null) {
|
|
3428
|
-
targetEl.setAttribute("style", this.#targetStyleValue);
|
|
3429
|
-
this.#targetStyleValue = null;
|
|
3430
|
-
}
|
|
3431
|
-
getFirstSlotElement(this.#$targetOpenSlot)?.setAttribute("slot", "target");
|
|
3432
|
-
this.#$targetWrapper.style.removeProperty("display");
|
|
3433
|
-
this.#$targetWrapper.style.removeProperty("width");
|
|
3434
|
-
this.#$targetWrapper.style.removeProperty("height");
|
|
3619
|
+
if (isNonModal && !effectiveAllowScroll) {
|
|
3620
|
+
this.#restoreTransferredTarget();
|
|
3435
3621
|
}
|
|
3436
3622
|
if (this.#targetActiveElement !== null) {
|
|
3437
3623
|
if (!isElementFocused(this.#targetActiveElement)) {
|
|
@@ -3451,57 +3637,69 @@ class Pop extends NectaryElement {
|
|
|
3451
3637
|
this.#targetActiveElement = null;
|
|
3452
3638
|
}
|
|
3453
3639
|
}
|
|
3454
|
-
if (!
|
|
3640
|
+
if (!effectiveAllowScroll) {
|
|
3455
3641
|
enableOverscroll();
|
|
3456
3642
|
} else {
|
|
3457
|
-
this.#
|
|
3458
|
-
el.removeEventListener("scroll", () => this.#updatePosition(false), { capture: true });
|
|
3459
|
-
});
|
|
3643
|
+
this.#unsubscribeScrollTracking();
|
|
3460
3644
|
}
|
|
3461
3645
|
this.#resizeThrottle.cancel();
|
|
3646
|
+
this.#scrollPositionThrottle.cancel();
|
|
3462
3647
|
window.removeEventListener("resize", this.#onResize);
|
|
3463
3648
|
this.#scrollableParents = [];
|
|
3464
3649
|
this.#$contentSlot.removeEventListener("slotchange", this.#onContentSlotChange);
|
|
3650
|
+
this.#openSession = {
|
|
3651
|
+
effectiveAllowScroll: false,
|
|
3652
|
+
modalSemantics: false,
|
|
3653
|
+
targetStyleValue: null,
|
|
3654
|
+
transformedAncestor: null
|
|
3655
|
+
};
|
|
3465
3656
|
}
|
|
3466
3657
|
#onResize = () => {
|
|
3467
3658
|
this.#resizeThrottle.fn();
|
|
3468
3659
|
};
|
|
3660
|
+
#onScrollableParentScroll = () => {
|
|
3661
|
+
this.#scrollPositionThrottle.fn();
|
|
3662
|
+
};
|
|
3469
3663
|
#updatePosition = (updateWidth) => {
|
|
3470
|
-
const
|
|
3664
|
+
const placementContext = getPlacementContext(this, this.#openSession.transformedAncestor);
|
|
3665
|
+
const { scaleX, scaleY, boundsWidth, boundsHeight } = placementContext;
|
|
3666
|
+
const { modalSemantics, effectiveAllowScroll } = this.#openSession;
|
|
3667
|
+
const shouldClamp = !effectiveAllowScroll;
|
|
3668
|
+
const targetRectViewport = modalSemantics || effectiveAllowScroll ? this.#getTargetRect() : this.#$targetWrapper.getBoundingClientRect();
|
|
3471
3669
|
const orient = this.orientation;
|
|
3472
|
-
const modalWidth = this.#modalWidth;
|
|
3473
|
-
const modalHeight = this.#modalHeight;
|
|
3474
3670
|
const inset = this.inset;
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
}
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3671
|
+
const insetX = inset / scaleX;
|
|
3672
|
+
const insetY = inset / scaleY;
|
|
3673
|
+
const targetRect = toLocalRect(targetRectViewport, placementContext);
|
|
3674
|
+
const liveRect = this.#$dialog.open ? this.#$dialog.getBoundingClientRect() : null;
|
|
3675
|
+
const isStretch = orient === "top-stretch" || orient === "bottom-stretch";
|
|
3676
|
+
const modalWidthViewport = isStretch ? this.#modalWidth : liveRect?.width ?? this.#modalWidth;
|
|
3677
|
+
const modalHeightViewport = liveRect?.height ?? this.#modalHeight;
|
|
3678
|
+
const modalWidth = modalWidthViewport / scaleX;
|
|
3679
|
+
const modalHeight = modalHeightViewport / scaleY;
|
|
3680
|
+
const localPos = getAnchorPosition(targetRect, modalWidth, modalHeight, orient);
|
|
3681
|
+
const xPos = localPos.x;
|
|
3682
|
+
const yPos = localPos.y;
|
|
3683
|
+
const localViewportInfos = { boundsWidth, boundsHeight, insetX, insetY, modalWidth, modalHeight };
|
|
3684
|
+
const clampedPosition = shouldClamp ? clampPosition({ x: xPos, y: yPos, ...localViewportInfos }) : { x: xPos, y: yPos };
|
|
3685
|
+
const clampedXPos = clampedPosition.x;
|
|
3686
|
+
const clampedYPos = clampedPosition.y;
|
|
3687
|
+
if (this.hideOutsideViewport) {
|
|
3688
|
+
const viewportPosition = getAnchorPosition(targetRectViewport, modalWidthViewport, modalHeightViewport, orient);
|
|
3689
|
+
const visibilityViewportInfos = {
|
|
3690
|
+
boundsWidth: window.innerWidth,
|
|
3691
|
+
boundsHeight: window.innerHeight,
|
|
3692
|
+
insetX: inset,
|
|
3693
|
+
insetY: inset,
|
|
3694
|
+
modalWidth: modalWidthViewport,
|
|
3695
|
+
modalHeight: modalHeightViewport
|
|
3696
|
+
};
|
|
3697
|
+
const isOutOfViewport = this.#isOutsideViewport(viewportPosition.x, viewportPosition.y, visibilityViewportInfos);
|
|
3698
|
+
if (isOutOfViewport) {
|
|
3699
|
+
this.#$dialog.style.setProperty("visibility", "hidden");
|
|
3700
|
+
} else {
|
|
3701
|
+
this.#$dialog.style.removeProperty("visibility");
|
|
3702
|
+
}
|
|
3505
3703
|
} else {
|
|
3506
3704
|
this.#$dialog.style.removeProperty("visibility");
|
|
3507
3705
|
}
|
|
@@ -3510,7 +3708,7 @@ class Pop extends NectaryElement {
|
|
|
3510
3708
|
if (updateWidth === true) {
|
|
3511
3709
|
this.#$dialog.style.setProperty("width", `${modalWidth}px`);
|
|
3512
3710
|
}
|
|
3513
|
-
if (!
|
|
3711
|
+
if (!modalSemantics && !effectiveAllowScroll) {
|
|
3514
3712
|
const targetLeftPos = targetRect.x - clampedXPos;
|
|
3515
3713
|
const targetTopPos = targetRect.y - clampedYPos;
|
|
3516
3714
|
this.#$targetOpenWrapper.style.setProperty("left", `${targetLeftPos}px`);
|
|
@@ -3586,13 +3784,10 @@ class Pop extends NectaryElement {
|
|
|
3586
3784
|
this.#updateOrientation();
|
|
3587
3785
|
}
|
|
3588
3786
|
};
|
|
3589
|
-
#
|
|
3590
|
-
const
|
|
3591
|
-
const
|
|
3592
|
-
|
|
3593
|
-
const clampedX = Math.max(inset, Math.min(x, window.innerWidth - modalWidth - inset));
|
|
3594
|
-
const clampedY = Math.max(inset, Math.min(y, window.innerHeight - modalHeight - inset));
|
|
3595
|
-
return Math.abs(clampedX - x) > 2 || Math.abs(clampedY - y) > 2;
|
|
3787
|
+
#isOutsideViewport(x, y, viewportInfos) {
|
|
3788
|
+
const { boundsWidth, boundsHeight, insetX, insetY, modalWidth, modalHeight } = viewportInfos;
|
|
3789
|
+
const clampedPosition = clampPosition({ x, y, boundsWidth, boundsHeight, insetX, insetY, modalWidth, modalHeight });
|
|
3790
|
+
return Math.abs(clampedPosition.x - x) > 2 || Math.abs(clampedPosition.y - y) > 2;
|
|
3596
3791
|
}
|
|
3597
3792
|
}
|
|
3598
3793
|
defineCustomElement("sinch-pop", Pop);
|
|
@@ -3756,6 +3951,10 @@ const SHOW_DELAY_SLOW = 1e3;
|
|
|
3756
3951
|
const SHOW_DELAY_FAST = 250;
|
|
3757
3952
|
const HIDE_DELAY = 0;
|
|
3758
3953
|
const ANIMATION_DURATION = 100;
|
|
3954
|
+
const OVERLAP_TOLERANCE = 1;
|
|
3955
|
+
const MAX_ZERO_DIMENSION_PLACEMENT_RETRIES = 8;
|
|
3956
|
+
const MIN_FIRST_REVEAL_STABILITY_FRAMES = 3;
|
|
3957
|
+
const MAX_FIRST_REVEAL_STABILITY_FRAMES = 6;
|
|
3759
3958
|
const template$T = document.createElement("template");
|
|
3760
3959
|
template$T.innerHTML = templateHTML$T;
|
|
3761
3960
|
class Tooltip extends NectaryElement {
|
|
@@ -3765,11 +3964,16 @@ class Tooltip extends NectaryElement {
|
|
|
3765
3964
|
#$contentWrapper;
|
|
3766
3965
|
#$tip;
|
|
3767
3966
|
#$target;
|
|
3768
|
-
#
|
|
3967
|
+
#resizeObserver = null;
|
|
3769
3968
|
#tooltipState;
|
|
3770
3969
|
#animation = null;
|
|
3771
3970
|
#shouldReduceMotion = false;
|
|
3772
3971
|
#isSubscribed = false;
|
|
3972
|
+
#controller;
|
|
3973
|
+
#placementScheduled = false;
|
|
3974
|
+
#zeroDimensionPlacementRetries = 0;
|
|
3975
|
+
#revealRequestId = 0;
|
|
3976
|
+
#hasCompletedFirstReveal = false;
|
|
3773
3977
|
constructor() {
|
|
3774
3978
|
super();
|
|
3775
3979
|
const shadowRoot = this.attachShadow();
|
|
@@ -3781,6 +3985,7 @@ class Tooltip extends NectaryElement {
|
|
|
3781
3985
|
this.#$tip = shadowRoot.querySelector("#tip");
|
|
3782
3986
|
this.#$target = shadowRoot.querySelector("#target");
|
|
3783
3987
|
this.#shouldReduceMotion = shouldReduceMotion();
|
|
3988
|
+
this.#controller = null;
|
|
3784
3989
|
this.#tooltipState = new TooltipState({
|
|
3785
3990
|
showDelay: SHOW_DELAY_SLOW,
|
|
3786
3991
|
hideDelay: this.#shouldReduceMotion ? HIDE_DELAY + ANIMATION_DURATION : HIDE_DELAY,
|
|
@@ -3801,6 +4006,10 @@ class Tooltip extends NectaryElement {
|
|
|
3801
4006
|
this.#$pop.addEventListener("-close", this.#onPopClose, options);
|
|
3802
4007
|
this.addEventListener("-show", this.#onShowReactHandler, options);
|
|
3803
4008
|
this.addEventListener("-hide", this.#onHideReactHandler, options);
|
|
4009
|
+
this.#resizeObserver = new ResizeObserver(() => {
|
|
4010
|
+
this.#schedulePlacement();
|
|
4011
|
+
});
|
|
4012
|
+
this.#resizeObserver.observe(this.#$content);
|
|
3804
4013
|
updateAttribute(this.#$pop, "orientation", getPopOrientation$1(this.orientation));
|
|
3805
4014
|
updateBooleanAttribute(this.#$pop, "hide-outside-viewport", !this.showOutsideViewport);
|
|
3806
4015
|
this.#updateText();
|
|
@@ -3810,6 +4019,8 @@ class Tooltip extends NectaryElement {
|
|
|
3810
4019
|
this.#tooltipState.destroy();
|
|
3811
4020
|
this.#controller.abort();
|
|
3812
4021
|
this.#controller = null;
|
|
4022
|
+
this.#resizeObserver?.disconnect();
|
|
4023
|
+
this.#resizeObserver = null;
|
|
3813
4024
|
}
|
|
3814
4025
|
static get observedAttributes() {
|
|
3815
4026
|
return [
|
|
@@ -3941,9 +4152,13 @@ class Tooltip extends NectaryElement {
|
|
|
3941
4152
|
};
|
|
3942
4153
|
// SHOW_DELAY ended, tooltip can be shown with animation
|
|
3943
4154
|
#onStateShowEnd = () => {
|
|
4155
|
+
const revealRequestId = ++this.#revealRequestId;
|
|
3944
4156
|
this.#dispatchShowEvent();
|
|
3945
4157
|
updateBooleanAttribute(this.#$pop, "open", true);
|
|
3946
|
-
|
|
4158
|
+
this.#schedulePlacement();
|
|
4159
|
+
this.#scheduleReveal(revealRequestId);
|
|
4160
|
+
};
|
|
4161
|
+
#playShowAnimation() {
|
|
3947
4162
|
if (this.#animation !== null) {
|
|
3948
4163
|
this.#animation.updatePlaybackRate(1);
|
|
3949
4164
|
this.#animation.play();
|
|
@@ -3956,20 +4171,64 @@ class Tooltip extends NectaryElement {
|
|
|
3956
4171
|
fill: "forwards"
|
|
3957
4172
|
});
|
|
3958
4173
|
}
|
|
3959
|
-
}
|
|
4174
|
+
}
|
|
4175
|
+
#isRectStable(previousRect, nextRect) {
|
|
4176
|
+
return Math.abs(previousRect.x - nextRect.x) < 0.5 && Math.abs(previousRect.y - nextRect.y) < 0.5 && Math.abs(previousRect.width - nextRect.width) < 0.5 && Math.abs(previousRect.height - nextRect.height) < 0.5;
|
|
4177
|
+
}
|
|
4178
|
+
#scheduleReveal(revealRequestId) {
|
|
4179
|
+
const reveal = () => {
|
|
4180
|
+
if (!this.isDomConnected || !this.#isOpen() || this.#revealRequestId !== revealRequestId) {
|
|
4181
|
+
return;
|
|
4182
|
+
}
|
|
4183
|
+
this.#playShowAnimation();
|
|
4184
|
+
this.#hasCompletedFirstReveal = true;
|
|
4185
|
+
};
|
|
4186
|
+
if (this.#hasCompletedFirstReveal) {
|
|
4187
|
+
reveal();
|
|
4188
|
+
return;
|
|
4189
|
+
}
|
|
4190
|
+
let previousRect = null;
|
|
4191
|
+
let observedFrames = 0;
|
|
4192
|
+
let remainingFrames = MAX_FIRST_REVEAL_STABILITY_FRAMES;
|
|
4193
|
+
const waitForStableRect = () => {
|
|
4194
|
+
if (!this.isDomConnected || !this.#isOpen() || this.#revealRequestId !== revealRequestId) {
|
|
4195
|
+
return;
|
|
4196
|
+
}
|
|
4197
|
+
const nextRect = this.#$pop.popoverRect;
|
|
4198
|
+
if (observedFrames >= MIN_FIRST_REVEAL_STABILITY_FRAMES && previousRect !== null && this.#isRectStable(previousRect, nextRect)) {
|
|
4199
|
+
reveal();
|
|
4200
|
+
return;
|
|
4201
|
+
}
|
|
4202
|
+
if (remainingFrames === 0) {
|
|
4203
|
+
reveal();
|
|
4204
|
+
return;
|
|
4205
|
+
}
|
|
4206
|
+
previousRect = nextRect;
|
|
4207
|
+
observedFrames += 1;
|
|
4208
|
+
remainingFrames -= 1;
|
|
4209
|
+
requestAnimationFrame(waitForStableRect);
|
|
4210
|
+
};
|
|
4211
|
+
requestAnimationFrame(waitForStableRect);
|
|
4212
|
+
}
|
|
3960
4213
|
// HIDE_DELAY ended, begin tooltip hide animation
|
|
3961
4214
|
#onStateHideStart = () => {
|
|
4215
|
+
this.#revealRequestId += 1;
|
|
4216
|
+
if (this.#animation === null) {
|
|
4217
|
+
return;
|
|
4218
|
+
}
|
|
3962
4219
|
this.#animation.updatePlaybackRate(-1);
|
|
3963
4220
|
this.#animation.play();
|
|
3964
4221
|
};
|
|
3965
4222
|
// Hide animation ended, tooltip can be hidden
|
|
3966
4223
|
#onStateHideEnd = () => {
|
|
3967
4224
|
if (this.#isOpen()) {
|
|
3968
|
-
this.#animation
|
|
4225
|
+
this.#animation?.finish();
|
|
3969
4226
|
this.#dispatchHideEvent();
|
|
3970
4227
|
updateBooleanAttribute(this.#$pop, "open", false);
|
|
3971
4228
|
}
|
|
3972
4229
|
this.#resetTipOrientation();
|
|
4230
|
+
this.#resetContentOffset();
|
|
4231
|
+
this.#zeroDimensionPlacementRetries = 0;
|
|
3973
4232
|
this.#unsubscribeMouseLeaveEvents();
|
|
3974
4233
|
this.#unsubscribeScroll();
|
|
3975
4234
|
};
|
|
@@ -3977,26 +4236,125 @@ class Tooltip extends NectaryElement {
|
|
|
3977
4236
|
this.#$tip.style.top = "";
|
|
3978
4237
|
this.#$tip.style.left = "";
|
|
3979
4238
|
}
|
|
3980
|
-
#
|
|
4239
|
+
#resetContentOffset() {
|
|
4240
|
+
this.#$pop.style.removeProperty("--sinch-pop-offset-x");
|
|
4241
|
+
this.#$pop.style.removeProperty("--sinch-pop-offset-y");
|
|
4242
|
+
}
|
|
4243
|
+
#schedulePlacement(resetZeroDimensionRetries = true) {
|
|
4244
|
+
if (!this.#isOpen() || this.#placementScheduled) {
|
|
4245
|
+
return;
|
|
4246
|
+
}
|
|
4247
|
+
if (resetZeroDimensionRetries) {
|
|
4248
|
+
this.#zeroDimensionPlacementRetries = 0;
|
|
4249
|
+
}
|
|
4250
|
+
this.#placementScheduled = true;
|
|
4251
|
+
requestAnimationFrame(() => {
|
|
4252
|
+
this.#placementScheduled = false;
|
|
4253
|
+
if (!this.isDomConnected || !this.#isOpen()) {
|
|
4254
|
+
return;
|
|
4255
|
+
}
|
|
4256
|
+
this.#updatePlacement();
|
|
4257
|
+
});
|
|
4258
|
+
}
|
|
4259
|
+
#applyContentOffset(offsetX, offsetY) {
|
|
4260
|
+
if (offsetX === 0 && offsetY === 0) {
|
|
4261
|
+
this.#$pop.style.removeProperty("--sinch-pop-offset-x");
|
|
4262
|
+
this.#$pop.style.removeProperty("--sinch-pop-offset-y");
|
|
4263
|
+
return;
|
|
4264
|
+
}
|
|
4265
|
+
this.#$pop.style.setProperty("--sinch-pop-offset-x", `${offsetX}px`);
|
|
4266
|
+
this.#$pop.style.setProperty("--sinch-pop-offset-y", `${offsetY}px`);
|
|
4267
|
+
}
|
|
4268
|
+
#updatePlacement = () => {
|
|
4269
|
+
if (!this.isDomConnected || !this.#isOpen()) {
|
|
4270
|
+
return;
|
|
4271
|
+
}
|
|
4272
|
+
const popRect = this.#$pop.popoverRect;
|
|
4273
|
+
if (popRect.width === 0 || popRect.height === 0) {
|
|
4274
|
+
if (this.#zeroDimensionPlacementRetries >= MAX_ZERO_DIMENSION_PLACEMENT_RETRIES) {
|
|
4275
|
+
return;
|
|
4276
|
+
}
|
|
4277
|
+
this.#zeroDimensionPlacementRetries += 1;
|
|
4278
|
+
this.#schedulePlacement(false);
|
|
4279
|
+
return;
|
|
4280
|
+
}
|
|
4281
|
+
this.#zeroDimensionPlacementRetries = 0;
|
|
4282
|
+
const placementContext = getPlacementContext(this.#$pop);
|
|
4283
|
+
this.#resetContentOffset();
|
|
4284
|
+
this.#updateTipOrientation(placementContext);
|
|
4285
|
+
const didOffset = this.#resolveOverlap(placementContext);
|
|
4286
|
+
if (didOffset) {
|
|
4287
|
+
requestAnimationFrame(() => {
|
|
4288
|
+
if (!this.isDomConnected || !this.#isOpen()) {
|
|
4289
|
+
return;
|
|
4290
|
+
}
|
|
4291
|
+
this.#updateTipOrientation(placementContext);
|
|
4292
|
+
});
|
|
4293
|
+
}
|
|
4294
|
+
};
|
|
4295
|
+
#resolveOverlap(placementContext) {
|
|
4296
|
+
const orientation = this.orientation;
|
|
4297
|
+
const targetRect = toLocalRect(this.#$pop.footprintRect, placementContext);
|
|
4298
|
+
const contentRect = toLocalRect(this.#$content.getBoundingClientRect(), placementContext);
|
|
4299
|
+
const tipRect = toLocalRect(this.#$tip.getBoundingClientRect(), placementContext);
|
|
4300
|
+
const targetBottom = targetRect.y + targetRect.height;
|
|
4301
|
+
const targetRight = targetRect.x + targetRect.width;
|
|
4302
|
+
const bottomEdge = Math.max(contentRect.y + contentRect.height, tipRect.y + tipRect.height);
|
|
4303
|
+
const topEdge = Math.min(contentRect.y, tipRect.y);
|
|
4304
|
+
const rightEdge = Math.max(contentRect.x + contentRect.width, tipRect.x + tipRect.width);
|
|
4305
|
+
const leftEdge = Math.min(contentRect.x, tipRect.x);
|
|
4306
|
+
let offsetX = 0;
|
|
4307
|
+
let offsetY = 0;
|
|
4308
|
+
if (orientation.startsWith("top")) {
|
|
4309
|
+
if (bottomEdge > targetRect.y + OVERLAP_TOLERANCE) {
|
|
4310
|
+
offsetY = targetRect.y - bottomEdge;
|
|
4311
|
+
}
|
|
4312
|
+
} else if (orientation.startsWith("bottom")) {
|
|
4313
|
+
if (topEdge < targetBottom - OVERLAP_TOLERANCE) {
|
|
4314
|
+
offsetY = targetBottom - topEdge;
|
|
4315
|
+
}
|
|
4316
|
+
} else if (orientation === "left") {
|
|
4317
|
+
if (rightEdge > targetRect.x + OVERLAP_TOLERANCE) {
|
|
4318
|
+
offsetX = targetRect.x - rightEdge;
|
|
4319
|
+
}
|
|
4320
|
+
} else if (orientation === "right") {
|
|
4321
|
+
if (leftEdge < targetRight - OVERLAP_TOLERANCE) {
|
|
4322
|
+
offsetX = targetRight - leftEdge;
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
this.#applyContentOffset(offsetX, offsetY);
|
|
4326
|
+
return offsetX !== 0 || offsetY !== 0;
|
|
4327
|
+
}
|
|
4328
|
+
#updateTipOrientation = (placementContext) => {
|
|
3981
4329
|
const orient = this.orientation;
|
|
3982
4330
|
if (!("footprintRect" in this.#$pop)) {
|
|
3983
|
-
requestAnimationFrame(
|
|
4331
|
+
requestAnimationFrame(() => {
|
|
4332
|
+
if (!this.isDomConnected || !this.#isOpen()) {
|
|
4333
|
+
return;
|
|
4334
|
+
}
|
|
4335
|
+
this.#updateTipOrientation();
|
|
4336
|
+
});
|
|
3984
4337
|
return;
|
|
3985
4338
|
}
|
|
3986
|
-
const
|
|
3987
|
-
const
|
|
4339
|
+
const ctx = placementContext ?? getPlacementContext(this.#$pop);
|
|
4340
|
+
const targetRect = toLocalRect(this.#$pop.footprintRect, ctx);
|
|
4341
|
+
const contentRect = toLocalRect(this.#$content.getBoundingClientRect(), ctx);
|
|
3988
4342
|
const diffX = targetRect.x - contentRect.x;
|
|
3989
4343
|
const diffY = targetRect.y - contentRect.y;
|
|
4344
|
+
const targetWidth = targetRect.width;
|
|
4345
|
+
const targetHeight = targetRect.height;
|
|
4346
|
+
const contentWidth = contentRect.width;
|
|
4347
|
+
const contentHeight = contentRect.height;
|
|
3990
4348
|
if (orient === "left" || orient === "right") {
|
|
3991
|
-
const yPos = Math.max(TIP_SIZE$1, Math.min(diffY +
|
|
4349
|
+
const yPos = Math.max(TIP_SIZE$1, Math.min(diffY + targetHeight / 2, contentHeight - TIP_SIZE$1));
|
|
3992
4350
|
this.#$tip.style.top = `${yPos}px`;
|
|
3993
4351
|
} else {
|
|
3994
|
-
let xPos = Math.max(TIP_SIZE$1, Math.min(diffX +
|
|
4352
|
+
let xPos = Math.max(TIP_SIZE$1, Math.min(diffX + targetWidth / 2, contentWidth - TIP_SIZE$1));
|
|
3995
4353
|
if (orient === "bottom-left" || orient === "top-left") {
|
|
3996
|
-
xPos = Math.max(xPos,
|
|
4354
|
+
xPos = Math.max(xPos, contentWidth * 0.75);
|
|
3997
4355
|
}
|
|
3998
4356
|
if (orient === "bottom-right" || orient === "top-right") {
|
|
3999
|
-
xPos = Math.min(xPos,
|
|
4357
|
+
xPos = Math.min(xPos, contentWidth * 0.25);
|
|
4000
4358
|
}
|
|
4001
4359
|
this.#$tip.style.left = `${xPos}px`;
|
|
4002
4360
|
}
|
|
@@ -13019,7 +13377,7 @@ class SheetTitle extends NectaryElement {
|
|
|
13019
13377
|
};
|
|
13020
13378
|
}
|
|
13021
13379
|
defineCustomElement("sinch-sheet-title", SheetTitle);
|
|
13022
|
-
const templateHTML$e = '<style>:host{display:block;box-sizing:border-box;--sinch-local-shape-radius:var(--sinch-sys-shape-radius-m, 4px)}#content{width:100%;height:100%;min-height:100%;box-sizing:border-box;background-color:var(--sinch-
|
|
13380
|
+
const templateHTML$e = '<style>:host{display:block;box-sizing:border-box;--sinch-local-shape-radius:var(--sinch-sys-shape-radius-m, 4px)}#content{width:100%;height:100%;min-height:100%;box-sizing:border-box;background-color:var(--sinch-comp-skeleton-color-background);overflow:hidden;position:relative;border-radius:var(--sinch-local-shape-radius)}:host([size=xs]){height:var(--sinch-sys-size-xs,24px);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-xs, 4px)}:host([size="s"]){height:var(--sinch-sys-size-s,32px);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-s, 4px)}:host(:not([size])),:host([size="m"]){height:var(--sinch-sys-size-m,40px);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-m, 4px)}:host([size="l"]){height:var(--sinch-sys-size-l,48px);--sinch-local-shape-radius:var(--sinch-sys-shape-radius-l, 4px)}</style><div id="content"></div>';
|
|
13023
13381
|
const template$e = document.createElement("template");
|
|
13024
13382
|
template$e.innerHTML = templateHTML$e;
|
|
13025
13383
|
class SkeletonItem extends NectaryElement {
|
|
@@ -13043,7 +13401,7 @@ const getUid = () => crypto.getRandomValues(new Uint8Array(21)).reduce((id, byte
|
|
|
13043
13401
|
}
|
|
13044
13402
|
return `${id}_`;
|
|
13045
13403
|
}, "");
|
|
13046
|
-
const templateHTML$d = '<style>:host{display:block;position:relative}#wrapper{position:relative;display:flex;flex-direction:column;gap:16px;overflow:hidden;box-sizing:border-box}:host([card]:not([card=false])) #wrapper{background-color:var(--sinch-sys-color-surface-primary-default);border:1px solid var(--sinch-sys-color-border-subtle);border-radius:var(--sinch-sys-shape-radius-l);padding:16px}#shimmer{position:absolute;inset:0;overflow:hidden;pointer-events:none}#shimmer-inner{position:absolute;left:0;top:0;width:400%;height:100%;background-image:linear-gradient(90deg,transparent 0,transparent
|
|
13404
|
+
const templateHTML$d = '<style>:host{display:block;position:relative}#wrapper{position:relative;display:flex;flex-direction:column;gap:16px;overflow:hidden;box-sizing:border-box}:host([card]:not([card=false])) #wrapper{background-color:var(--sinch-sys-color-surface-primary-default);border:1px solid var(--sinch-sys-color-border-subtle);border-radius:var(--sinch-sys-shape-radius-l);padding:16px}#shimmer{position:absolute;inset:0;overflow:hidden;pointer-events:none}#shimmer-inner{position:absolute;left:0;top:0;width:400%;height:100%;background-image:linear-gradient(90deg,transparent 0,transparent 30%,var(--sinch-comp-skeleton-color-shimmer) 50%,transparent 53%,transparent 100%);background-size:100% 100%}#shimmer.animated #shimmer-inner{animation:nectary-skeleton-shimmer 2s linear infinite}@media (prefers-reduced-motion:reduce){#shimmer.animated #shimmer-inner{animation:none}}@keyframes nectary-skeleton-shimmer{0%{transform:translateX(-75%)}100%{transform:translateX(0)}}#svg{display:block;width:0;height:0}</style><svg id="svg"><defs><clipPath id="clip"></clipPath></defs></svg><div id="wrapper"><slot></slot><div id="shimmer"><div id="shimmer-inner"></div></div></div>';
|
|
13047
13405
|
const template$d = document.createElement("template");
|
|
13048
13406
|
template$d.innerHTML = templateHTML$d;
|
|
13049
13407
|
const BORDER_WIDTH = 1;
|