@orangesk/orange-design-system 2.0.0-beta.40 → 2.0.0-beta.41
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/build/components/AnchorNavigation/style.css +1 -1
- package/build/components/AnchorNavigation/style.css.map +1 -1
- package/build/components/index.js +1 -1
- package/build/components/index.js.map +1 -1
- package/build/components/tsconfig.tsbuildinfo +1 -1
- package/build/components/types/src/components/AnchorNavigation/AnchorNavigation.static.d.ts +2 -0
- package/build/lib/components.css +1 -1
- package/build/lib/components.css.map +1 -1
- package/build/lib/scripts.js +1 -1
- package/build/lib/scripts.js.map +1 -1
- package/build/lib/style.css +1 -1
- package/build/lib/style.css.map +1 -1
- package/package.json +1 -1
- package/src/components/AnchorNavigation/AnchorNavigation.static.ts +57 -9
- package/src/components/AnchorNavigation/styles/mixins.scss +2 -1
- package/src/components/AnchorNavigation/tests/AnchorNavigation.unit.test.jsx +68 -6
package/package.json
CHANGED
|
@@ -16,6 +16,7 @@ export default class AnchorNavigation {
|
|
|
16
16
|
private scrollEndHandler: () => void;
|
|
17
17
|
private scrollEndFallbackHandler: () => void;
|
|
18
18
|
private resizeHandler: () => void;
|
|
19
|
+
private mouseDownHandler: (event: MouseEvent) => void;
|
|
19
20
|
private dragStartHandler: (event: MouseEvent) => void;
|
|
20
21
|
private dragMoveHandler: (event: MouseEvent) => void;
|
|
21
22
|
private dragEndHandler: () => void;
|
|
@@ -50,6 +51,7 @@ export default class AnchorNavigation {
|
|
|
50
51
|
this.scrollEndHandler = this.handleScrollEnd.bind(this);
|
|
51
52
|
this.scrollEndFallbackHandler = this.handleScrollEndFallback.bind(this);
|
|
52
53
|
this.resizeHandler = this.handleResize.bind(this);
|
|
54
|
+
this.mouseDownHandler = this.handleMouseDown.bind(this);
|
|
53
55
|
this.dragStartHandler = this.handleDragStart.bind(this);
|
|
54
56
|
this.dragMoveHandler = this.handleDragMove.bind(this);
|
|
55
57
|
this.dragEndHandler = this.handleDragEnd.bind(this);
|
|
@@ -116,6 +118,7 @@ export default class AnchorNavigation {
|
|
|
116
118
|
this.teardownScrollSpyListeners();
|
|
117
119
|
|
|
118
120
|
this.element.addEventListener("click", this.anchorClickHandler);
|
|
121
|
+
this.element.addEventListener("mousedown", this.mouseDownHandler);
|
|
119
122
|
window.addEventListener("scroll", this.scrollSpyHandler, { passive: true });
|
|
120
123
|
|
|
121
124
|
if (this.supportsScrollEnd) {
|
|
@@ -133,6 +136,7 @@ export default class AnchorNavigation {
|
|
|
133
136
|
|
|
134
137
|
private teardownScrollSpyListeners(): void {
|
|
135
138
|
this.element.removeEventListener("click", this.anchorClickHandler);
|
|
139
|
+
this.element.removeEventListener("mousedown", this.mouseDownHandler);
|
|
136
140
|
window.removeEventListener("scroll", this.scrollSpyHandler);
|
|
137
141
|
window.removeEventListener("resize", this.resizeHandler);
|
|
138
142
|
|
|
@@ -148,20 +152,35 @@ export default class AnchorNavigation {
|
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
154
|
|
|
151
|
-
private
|
|
155
|
+
private handleMouseDown(event: MouseEvent): void {
|
|
156
|
+
if (event.button !== 0) return;
|
|
157
|
+
|
|
152
158
|
const target = event.target as HTMLElement | null;
|
|
153
|
-
|
|
154
|
-
".anchor-navigation__item",
|
|
155
|
-
) as HTMLAnchorElement | null;
|
|
159
|
+
if (!target || !this.element.contains(target)) return;
|
|
156
160
|
|
|
157
|
-
|
|
161
|
+
const interactiveSelector =
|
|
162
|
+
"a, button, input, select, textarea, label, [role='button'], [contenteditable='true']";
|
|
163
|
+
if (target.closest(interactiveSelector)) return;
|
|
164
|
+
|
|
165
|
+
// Prevent native text-selection drag from triggering page autoscroll.
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
}
|
|
158
168
|
|
|
169
|
+
private handleAnchorClick(event: Event): void {
|
|
159
170
|
if (this.suppressClick) {
|
|
160
171
|
event.preventDefault();
|
|
172
|
+
event.stopPropagation();
|
|
161
173
|
this.suppressClick = false;
|
|
162
174
|
return;
|
|
163
175
|
}
|
|
164
176
|
|
|
177
|
+
const target = event.target as HTMLElement | null;
|
|
178
|
+
const anchor = target?.closest(
|
|
179
|
+
".anchor-navigation__item",
|
|
180
|
+
) as HTMLAnchorElement | null;
|
|
181
|
+
|
|
182
|
+
if (!anchor || !this.element.contains(anchor)) return;
|
|
183
|
+
|
|
165
184
|
event.preventDefault();
|
|
166
185
|
|
|
167
186
|
const href = anchor.getAttribute("href");
|
|
@@ -300,18 +319,47 @@ export default class AnchorNavigation {
|
|
|
300
319
|
activeLink: HTMLElement,
|
|
301
320
|
forceCenter: boolean = false,
|
|
302
321
|
): void {
|
|
322
|
+
const maxScrollLeft = Math.max(
|
|
323
|
+
0,
|
|
324
|
+
contentLeft.scrollWidth - contentLeft.clientWidth,
|
|
325
|
+
);
|
|
326
|
+
const navLinks = this.navLinks;
|
|
327
|
+
let firstNavLink: HTMLAnchorElement | null = null;
|
|
328
|
+
let lastNavLink: HTMLAnchorElement | null = null;
|
|
329
|
+
|
|
330
|
+
if (navLinks && navLinks.length > 0) {
|
|
331
|
+
firstNavLink = navLinks[0];
|
|
332
|
+
lastNavLink = navLinks[navLinks.length - 1];
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const isFirstItem = activeLink === firstNavLink;
|
|
336
|
+
const isLastItem = activeLink === lastNavLink;
|
|
337
|
+
|
|
338
|
+
let targetScrollLeft: number | null = null;
|
|
339
|
+
if (isFirstItem) {
|
|
340
|
+
targetScrollLeft = 0;
|
|
341
|
+
} else if (isLastItem) {
|
|
342
|
+
targetScrollLeft = maxScrollLeft;
|
|
343
|
+
}
|
|
344
|
+
|
|
303
345
|
const itemLeft = activeLink.offsetLeft;
|
|
304
346
|
const itemRight = itemLeft + activeLink.clientWidth;
|
|
305
347
|
const viewportLeft = contentLeft.scrollLeft;
|
|
306
348
|
const viewportRight = viewportLeft + contentLeft.clientWidth;
|
|
307
349
|
const isVisible = itemLeft >= viewportLeft && itemRight <= viewportRight;
|
|
308
350
|
|
|
309
|
-
if (!forceCenter && isVisible) return;
|
|
351
|
+
if (targetScrollLeft === null && !forceCenter && isVisible) return;
|
|
352
|
+
|
|
353
|
+
if (targetScrollLeft === null) {
|
|
354
|
+
targetScrollLeft =
|
|
355
|
+
itemLeft - contentLeft.clientWidth / 2 + activeLink.clientWidth / 2;
|
|
356
|
+
}
|
|
310
357
|
|
|
311
|
-
const targetScrollLeft =
|
|
312
|
-
itemLeft - contentLeft.clientWidth / 2 + activeLink.clientWidth / 2;
|
|
313
358
|
const behavior = window.innerWidth < 768 ? "auto" : "smooth";
|
|
314
|
-
const nextScrollLeft = Math.
|
|
359
|
+
const nextScrollLeft = Math.min(
|
|
360
|
+
maxScrollLeft,
|
|
361
|
+
Math.max(0, targetScrollLeft),
|
|
362
|
+
);
|
|
315
363
|
|
|
316
364
|
if (typeof contentLeft.scrollTo === "function") {
|
|
317
365
|
contentLeft.scrollTo({
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
@include breakpoint.get("sm", "down") {
|
|
47
|
-
margin-right:
|
|
47
|
+
margin-right: convert.to-rem(10px) !important;
|
|
48
48
|
padding: convert.to-rem(15px) 0 !important;
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
display: flex;
|
|
135
135
|
flex: 1 1 auto;
|
|
136
136
|
min-width: 0;
|
|
137
|
+
scroll-snap-type: none !important;
|
|
137
138
|
|
|
138
139
|
&.is-draggable {
|
|
139
140
|
user-select: none;
|
|
@@ -274,9 +274,63 @@ describe("rendering AnchorNavigation", () => {
|
|
|
274
274
|
section.remove();
|
|
275
275
|
});
|
|
276
276
|
|
|
277
|
+
it("prevents mousedown default on non-interactive content-right area", () => {
|
|
278
|
+
const { container } = render(
|
|
279
|
+
<AnchorNavigation items={basicItems}>
|
|
280
|
+
<div className="align-lg-right mb-none">
|
|
281
|
+
<span>16 €</span>
|
|
282
|
+
<span className="text-secondary">S viazanostou 24 mesiacov</span>
|
|
283
|
+
</div>
|
|
284
|
+
<a href="/senior-pausal/chcem-senior">Kupit Senior pausal</a>
|
|
285
|
+
</AnchorNavigation>,
|
|
286
|
+
);
|
|
287
|
+
const anchorNavigationElement = initializeAnchorNavigation(container);
|
|
288
|
+
const anchorNavigation = AnchorNavigationStatic.getInstance(
|
|
289
|
+
anchorNavigationElement,
|
|
290
|
+
);
|
|
291
|
+
const infoBlock = container.querySelector(".align-lg-right");
|
|
292
|
+
|
|
293
|
+
const downEvent = new MouseEvent("mousedown", {
|
|
294
|
+
bubbles: true,
|
|
295
|
+
cancelable: true,
|
|
296
|
+
button: 0,
|
|
297
|
+
});
|
|
298
|
+
infoBlock?.dispatchEvent(downEvent);
|
|
299
|
+
|
|
300
|
+
expect(downEvent.defaultPrevented).toBe(true);
|
|
301
|
+
|
|
302
|
+
anchorNavigation?.destroy();
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("does not prevent mousedown default on interactive content-right link", () => {
|
|
306
|
+
const { container } = render(
|
|
307
|
+
<AnchorNavigation items={basicItems}>
|
|
308
|
+
<a href="/senior-pausal/chcem-senior">Kupit Senior pausal</a>
|
|
309
|
+
</AnchorNavigation>,
|
|
310
|
+
);
|
|
311
|
+
const anchorNavigationElement = initializeAnchorNavigation(container);
|
|
312
|
+
const anchorNavigation = AnchorNavigationStatic.getInstance(
|
|
313
|
+
anchorNavigationElement,
|
|
314
|
+
);
|
|
315
|
+
const ctaLink = container.querySelector(
|
|
316
|
+
'a[href="/senior-pausal/chcem-senior"]',
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
const downEvent = new MouseEvent("mousedown", {
|
|
320
|
+
bubbles: true,
|
|
321
|
+
cancelable: true,
|
|
322
|
+
button: 0,
|
|
323
|
+
});
|
|
324
|
+
ctaLink?.dispatchEvent(downEvent);
|
|
325
|
+
|
|
326
|
+
expect(downEvent.defaultPrevented).toBe(false);
|
|
327
|
+
|
|
328
|
+
anchorNavigation?.destroy();
|
|
329
|
+
});
|
|
330
|
+
|
|
277
331
|
it("scrolls active item using the left content viewport width", () => {
|
|
278
332
|
const section = document.createElement("section");
|
|
279
|
-
section.id = "
|
|
333
|
+
section.id = "pricing";
|
|
280
334
|
document.body.appendChild(section);
|
|
281
335
|
|
|
282
336
|
const { container } = render(
|
|
@@ -292,13 +346,17 @@ describe("rendering AnchorNavigation", () => {
|
|
|
292
346
|
const contentLeft = container.querySelector(
|
|
293
347
|
".anchor-navigation__content-left",
|
|
294
348
|
);
|
|
295
|
-
const activeLink = container.querySelector('a[href="#
|
|
349
|
+
const activeLink = container.querySelector('a[href="#pricing"]');
|
|
296
350
|
const scrollToSpy = vi.fn();
|
|
297
351
|
|
|
298
352
|
Object.defineProperty(contentLeft, "clientWidth", {
|
|
299
353
|
configurable: true,
|
|
300
354
|
value: 180,
|
|
301
355
|
});
|
|
356
|
+
Object.defineProperty(contentLeft, "scrollWidth", {
|
|
357
|
+
configurable: true,
|
|
358
|
+
value: 600,
|
|
359
|
+
});
|
|
302
360
|
Object.defineProperty(contentLeft, "scrollLeft", {
|
|
303
361
|
configurable: true,
|
|
304
362
|
value: 0,
|
|
@@ -314,7 +372,7 @@ describe("rendering AnchorNavigation", () => {
|
|
|
314
372
|
});
|
|
315
373
|
contentLeft.scrollTo = scrollToSpy;
|
|
316
374
|
|
|
317
|
-
anchorNavigation.initScrollSpy("
|
|
375
|
+
anchorNavigation.initScrollSpy("pricing");
|
|
318
376
|
|
|
319
377
|
expect(scrollToSpy).toHaveBeenCalledWith({
|
|
320
378
|
left: 170,
|
|
@@ -327,7 +385,7 @@ describe("rendering AnchorNavigation", () => {
|
|
|
327
385
|
|
|
328
386
|
it("centers clicked active item even when it is already visible", () => {
|
|
329
387
|
const section = document.createElement("section");
|
|
330
|
-
section.id = "
|
|
388
|
+
section.id = "pricing";
|
|
331
389
|
document.body.appendChild(section);
|
|
332
390
|
|
|
333
391
|
const { container } = render(<AnchorNavigation items={basicItems} />);
|
|
@@ -338,13 +396,17 @@ describe("rendering AnchorNavigation", () => {
|
|
|
338
396
|
const contentLeft = container.querySelector(
|
|
339
397
|
".anchor-navigation__content-left",
|
|
340
398
|
);
|
|
341
|
-
const activeLink = container.querySelector('a[href="#
|
|
399
|
+
const activeLink = container.querySelector('a[href="#pricing"]');
|
|
342
400
|
const scrollToSpy = vi.fn();
|
|
343
401
|
|
|
344
402
|
Object.defineProperty(contentLeft, "clientWidth", {
|
|
345
403
|
configurable: true,
|
|
346
404
|
value: 200,
|
|
347
405
|
});
|
|
406
|
+
Object.defineProperty(contentLeft, "scrollWidth", {
|
|
407
|
+
configurable: true,
|
|
408
|
+
value: 600,
|
|
409
|
+
});
|
|
348
410
|
Object.defineProperty(contentLeft, "scrollLeft", {
|
|
349
411
|
configurable: true,
|
|
350
412
|
value: 180,
|
|
@@ -360,7 +422,7 @@ describe("rendering AnchorNavigation", () => {
|
|
|
360
422
|
});
|
|
361
423
|
contentLeft.scrollTo = scrollToSpy;
|
|
362
424
|
|
|
363
|
-
anchorNavigation.initScrollSpy("
|
|
425
|
+
anchorNavigation.initScrollSpy("pricing");
|
|
364
426
|
|
|
365
427
|
expect(scrollToSpy).toHaveBeenCalledWith({
|
|
366
428
|
left: 160,
|