@salesforcedevs/mrkt-components 0.0.0-alpha.0

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.
Files changed (52) hide show
  1. package/lwc.config.json +21 -0
  2. package/package.json +18 -0
  3. package/src/assets/svg/mrkt-cta-section-img-left.svg +28 -0
  4. package/src/assets/svg/mrkt-cta-section-img-right.svg +18 -0
  5. package/src/assets/svg/mrkt-no-code-section-graphic.svg +23 -0
  6. package/src/assets/svg/mrkt-section-header-graphic.svg +110 -0
  7. package/src/assets/svg/mrkt-two-col-panel-section-graphic-1-light.svg +9 -0
  8. package/src/assets/svg/mrkt-two-col-panel-section-graphic-1.svg +9 -0
  9. package/src/assets/svg/mrkt-two-col-panel-section-graphic-2-light.svg +16 -0
  10. package/src/assets/svg/mrkt-two-col-panel-section-graphic-2.svg +16 -0
  11. package/src/assets/svg/mrkt-two-col-panel-section-graphic-3-light.svg +3 -0
  12. package/src/assets/svg/mrkt-two-col-panel-section-graphic-3.svg +3 -0
  13. package/src/assets/svg/mrkt-two-col-panel-section-swoop.svg +3 -0
  14. package/src/modules/mrkt/ctaSection/ctaSection.css +99 -0
  15. package/src/modules/mrkt/ctaSection/ctaSection.html +17 -0
  16. package/src/modules/mrkt/ctaSection/ctaSection.ts +44 -0
  17. package/src/modules/mrkt/fullImgSection/fullImgSection.css +54 -0
  18. package/src/modules/mrkt/fullImgSection/fullImgSection.html +11 -0
  19. package/src/modules/mrkt/fullImgSection/fullImgSection.ts +17 -0
  20. package/src/modules/mrkt/noCodeSection/noCodeSection.css +82 -0
  21. package/src/modules/mrkt/noCodeSection/noCodeSection.html +14 -0
  22. package/src/modules/mrkt/noCodeSection/noCodeSection.ts +8 -0
  23. package/src/modules/mrkt/rectangularHeading/rectangularHeading.css +97 -0
  24. package/src/modules/mrkt/rectangularHeading/rectangularHeading.html +10 -0
  25. package/src/modules/mrkt/rectangularHeading/rectangularHeading.ts +14 -0
  26. package/src/modules/mrkt/sectionHeader/sectionHeader.css +165 -0
  27. package/src/modules/mrkt/sectionHeader/sectionHeader.html +24 -0
  28. package/src/modules/mrkt/sectionHeader/sectionHeader.ts +35 -0
  29. package/src/modules/mrkt/socials/socials.css +65 -0
  30. package/src/modules/mrkt/socials/socials.html +16 -0
  31. package/src/modules/mrkt/socials/socials.ts +17 -0
  32. package/src/modules/mrkt/subNavBar/subNavBar.css +141 -0
  33. package/src/modules/mrkt/subNavBar/subNavBar.html +37 -0
  34. package/src/modules/mrkt/subNavBar/subNavBar.ts +130 -0
  35. package/src/modules/mrkt/tdxSection/tdxSection.css +115 -0
  36. package/src/modules/mrkt/tdxSection/tdxSection.html +14 -0
  37. package/src/modules/mrkt/tdxSection/tdxSection.ts +12 -0
  38. package/src/modules/mrkt/threeColListSection/threeColListSection.css +102 -0
  39. package/src/modules/mrkt/threeColListSection/threeColListSection.html +27 -0
  40. package/src/modules/mrkt/threeColListSection/threeColListSection.ts +24 -0
  41. package/src/modules/mrkt/twoColListSection/twoColListSection.css +65 -0
  42. package/src/modules/mrkt/twoColListSection/twoColListSection.html +19 -0
  43. package/src/modules/mrkt/twoColListSection/twoColListSection.ts +29 -0
  44. package/src/modules/mrkt/twoColPanelSection/twoColPanelSection.css +143 -0
  45. package/src/modules/mrkt/twoColPanelSection/twoColPanelSection.html +55 -0
  46. package/src/modules/mrkt/twoColPanelSection/twoColPanelSection.ts +15 -0
  47. package/src/modules/mrkt/twoColSection/twoColSection.css +67 -0
  48. package/src/modules/mrkt/twoColSection/twoColSection.html +9 -0
  49. package/src/modules/mrkt/twoColSection/twoColSection.ts +14 -0
  50. package/src/modules/mrkt/videoPlayerSection/videoPlayerSection.css +76 -0
  51. package/src/modules/mrkt/videoPlayerSection/videoPlayerSection.html +22 -0
  52. package/src/modules/mrkt/videoPlayerSection/videoPlayerSection.ts +6 -0
@@ -0,0 +1,165 @@
1
+ @import "dxHelpers/reset";
2
+ @import "dxHelpers/text";
3
+
4
+ :host {
5
+ --image-aspect-ratio: 1.43554006969;
6
+ --image-width: 350px;
7
+ --image-height: calc(var(--image-width) / var(--image-aspect-ratio));
8
+ --image-overlap: 44px;
9
+ --image-bottom: calc(var(--image-height) - var(--image-overlap));
10
+ --image-inset: calc(-1 * var(--dx-g-spacing-md));
11
+ --overlap-padding-top: calc(
12
+ var(--image-height) - var(--image-overlap) + var(--image-inset)
13
+ );
14
+ --icon-padding: var(--dx-g-spacing-lg);
15
+ --mrkt-c-section-header-padding-top: 76px;
16
+ --mrkt-c-section-header-padding-bottom: var(--dx-g-spacing-5xl);
17
+ }
18
+
19
+ .section-header {
20
+ position: relative;
21
+ background: white;
22
+ padding: var(--mrkt-c-section-header-padding-top) 0
23
+ var(--mrkt-c-section-header-padding-bottom) 0;
24
+ }
25
+
26
+ .section-header.has-images {
27
+ --mrkt-c-section-header-padding-top: var(--dx-g-spacing-lg);
28
+ }
29
+
30
+ .section-header.dark {
31
+ background: var(--dx-g-indigo-vibrant-15);
32
+ }
33
+
34
+ .section-header.light-gradient {
35
+ background: linear-gradient(
36
+ 180deg,
37
+ rgba(234, 245, 254) 42.08%,
38
+ rgba(234, 245, 254, 0) 100%
39
+ );
40
+ }
41
+
42
+ .header-img-container {
43
+ width: 100%;
44
+ margin-bottom: calc(-1 * var(--dx-g-spacing-xl));
45
+ display: flex;
46
+ justify-content: center;
47
+ align-items: center;
48
+ overflow-x: hidden;
49
+ }
50
+
51
+ .header-img {
52
+ width: 100%;
53
+ min-width: var(--dx-g-breakpoint-sm);
54
+ }
55
+
56
+ .page-margin-img-container {
57
+ display: flex;
58
+ flex-direction: row;
59
+ justify-content: space-between;
60
+ width: 100%;
61
+ }
62
+
63
+ .section-header:not(.overlap-images) .page-margin-img-container {
64
+ margin-bottom: var(--image-inset);
65
+ }
66
+
67
+ .page-margin-img-container img {
68
+ aspect-ratio: var(--image-aspect-ratio);
69
+ width: 350px;
70
+ max-width: 50%;
71
+ }
72
+
73
+ .text-container {
74
+ position: relative;
75
+ display: flex;
76
+ flex-direction: column;
77
+ align-items: center;
78
+ padding: 0 var(--dx-g-page-padding-horizontal);
79
+ z-index: 1;
80
+ text-align: center;
81
+ }
82
+
83
+ .section-header .title,
84
+ .section-header .subtitle {
85
+ max-width: 768px;
86
+ }
87
+
88
+ dx-icon-badge {
89
+ --dx-c-icon-badge-icon-size: var(--dx-g-icon-size-lg-b);
90
+ --dx-c-icon-badge-color: white;
91
+ --dx-c-icon-badge-background-color: var(--dx-g-blue-vibrant-20);
92
+
93
+ margin-bottom: var(--icon-padding);
94
+ }
95
+
96
+ .section-header.has-subtitle .title {
97
+ margin-bottom: var(--dx-g-spacing-md);
98
+ }
99
+
100
+ .section-header.dark .title,
101
+ .section-header.dark .subtitle {
102
+ color: white;
103
+ }
104
+
105
+ .section-header.dark dx-icon-badge {
106
+ --dx-c-icon-badge-color: var(--dx-g-blue-vibrant-20);
107
+ --dx-c-icon-badge-background-color: white;
108
+ }
109
+
110
+ @media (min-width: 1500px) {
111
+ .header-img {
112
+ padding: 0 var(--dx-g-page-padding-horizontal);
113
+ }
114
+ }
115
+
116
+ @media (min-width: 1024px) {
117
+ .section-header.overlap-images .page-margin-img-container {
118
+ position: absolute;
119
+ bottom: calc(100% - var(--image-bottom));
120
+ left: 0;
121
+ z-index: 0;
122
+ }
123
+
124
+ .section-header.section-header.overlap-images {
125
+ padding-top: var(--overlap-padding-top);
126
+ }
127
+ }
128
+
129
+ @media (max-width: 768px) {
130
+ :host {
131
+ --image-width: 50vw;
132
+ }
133
+
134
+ .header-img-container {
135
+ margin-bottom: 0;
136
+ }
137
+
138
+ .section-header .title {
139
+ font-size: var(--dx-g-text-2xl);
140
+ letter-spacing: -0.4px;
141
+ line-height: 40px;
142
+ }
143
+
144
+ .section-header.has-subtitle .title {
145
+ margin-bottom: var(--dx-g-spacing-mlg);
146
+ }
147
+
148
+ .section-header .subtitle {
149
+ font-size: var(--dx-g-text-lg);
150
+ letter-spacing: -0.1px;
151
+ line-height: 28px;
152
+ }
153
+ }
154
+
155
+ @media (max-width: 640px) {
156
+ .header-img {
157
+ width: var(--dx-g-breakpoint-sm);
158
+ }
159
+ }
160
+
161
+ @media (max-width: 360px) {
162
+ :host {
163
+ --overlap-padding-top: var(--mrkt-c-section-header-padding-top);
164
+ }
165
+ }
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <div class={className}>
3
+ <div class="header-img-container" if:true={imgSrc}>
4
+ <img class="header-img" src={imgSrc} alt="" />
5
+ </div>
6
+ <div class="page-margin-img-container" if:true={hasPageMarginGraphics}>
7
+ <img src={imgSrcLeft} alt="" />
8
+ <img src={imgSrcRight} alt="" />
9
+ </div>
10
+ <div class="text-container">
11
+ <dx-icon-badge
12
+ if:true={hasIcon}
13
+ color={iconColor}
14
+ symbol={iconSymbol}
15
+ sprite={iconSprite}
16
+ background-size="large"
17
+ ></dx-icon-badge>
18
+ <h2 if:true={title} class="title dx-text-heading-2b">{title}</h2>
19
+ <span if:true={subtitle} class="subtitle dx-text-body-1">
20
+ {subtitle}
21
+ </span>
22
+ </div>
23
+ </div>
24
+ </template>
@@ -0,0 +1,35 @@
1
+ import { api, LightningElement } from "lwc";
2
+ import cx from "classnames";
3
+
4
+ export default class SectionHeader extends LightningElement {
5
+ @api dark?: boolean;
6
+ @api iconColor?: string;
7
+ @api iconSymbol?: string;
8
+ @api iconSprite?: string = "utility";
9
+ @api imgSrc?: string;
10
+ @api imgSrcLeft?: string;
11
+ @api imgSrcRight?: string;
12
+ @api overlapImages?: boolean = false;
13
+ @api lightGradient?: boolean;
14
+ @api subtitle?: string;
15
+ @api title?: string;
16
+
17
+ private get hasPageMarginGraphics(): boolean {
18
+ return !!this.imgSrcLeft && !!this.imgSrcRight;
19
+ }
20
+
21
+ private get hasIcon(): boolean {
22
+ return !!this.title && !!this.iconSymbol;
23
+ }
24
+
25
+ private get className(): string {
26
+ return cx(
27
+ "section-header",
28
+ this.dark && "dark",
29
+ this.lightGradient && "light-gradient",
30
+ this.subtitle && "has-subtitle",
31
+ this.overlapImages && "overlap-images",
32
+ this.hasPageMarginGraphics && "has-images"
33
+ );
34
+ }
35
+ }
@@ -0,0 +1,65 @@
1
+ @import "dxHelpers/reset";
2
+ @import "dxHelpers/text";
3
+
4
+ .socials {
5
+ width: 100%;
6
+ position: relative;
7
+ display: flex;
8
+ flex-direction: column;
9
+ align-items: center;
10
+ background: white;
11
+ padding: var(--dx-g-spacing-3xl) var(--dx-g-page-padding-horizontal);
12
+ }
13
+
14
+ dx-hr {
15
+ /* --dx-c-hr-padding-horizontal: 0; */
16
+ width: 100%;
17
+ max-width: 1012px;
18
+ margin-bottom: var(--dx-g-spacing-3xl);
19
+ }
20
+
21
+ .socials-container {
22
+ width: 100%;
23
+ display: grid;
24
+ grid-template-columns: repeat(auto-fit, minmax(80px, min-content));
25
+ grid-gap: 100px;
26
+ justify-content: center;
27
+ }
28
+
29
+ a {
30
+ position: relative;
31
+ display: flex;
32
+ flex-direction: column;
33
+ align-items: center;
34
+ flex-shrink: 0;
35
+ }
36
+
37
+ a > dx-icon-badge {
38
+ --dx-c-icon-badge-size: var(--dx-g-spacing-xl);
39
+ --dx-c-icon-badge-icon-size: var(--dx-g-spacing-md);
40
+ --dx-c-icon-badge-background-color: var(--dx-g-text-heading-color);
41
+ --dx-c-icon-badge-transition: var(--dx-g-transition-hue-1x);
42
+ }
43
+
44
+ a > span {
45
+ padding-top: var(--dx-g-spacing-xs);
46
+ color: var(--dx-g-text-heading-color) !important;
47
+ white-space: nowrap;
48
+ }
49
+
50
+ a:hover > dx-icon-badge {
51
+ --dx-c-icon-badge-background-color: var(--dx-g-blue-vibrant-40);
52
+ }
53
+
54
+ @media (max-width: 1024px) {
55
+ .socials-container {
56
+ grid-gap: var(--dx-g-spacing-3xl);
57
+ }
58
+ }
59
+
60
+ @media (max-width: 768px) {
61
+ .socials-container {
62
+ grid-template-columns: auto;
63
+ grid-gap: var(--dx-g-spacing-2xl);
64
+ }
65
+ }
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div class="socials">
3
+ <dx-hr text={title} spacing="none"></dx-hr>
4
+ <div class="socials-container">
5
+ <template for:each={items} for:item="item">
6
+ <a key={item.id} href={item.link.href}>
7
+ <dx-icon-badge
8
+ sprite="brand"
9
+ symbol={item.iconSymbol}
10
+ ></dx-icon-badge>
11
+ <span class="dx-text-body-2">{item.label}</span>
12
+ </a>
13
+ </template>
14
+ </div>
15
+ </div>
16
+ </template>
@@ -0,0 +1,17 @@
1
+ import { api, LightningElement } from "lwc";
2
+ import { toJson } from "dxUtils/normalizers";
3
+ import type { OptionWithLink } from "typings/custom";
4
+
5
+ export default class Socials extends LightningElement {
6
+ @api title: string = "Our Socials";
7
+
8
+ @api
9
+ get items() {
10
+ return this._items;
11
+ }
12
+ set items(value) {
13
+ this._items = toJson(value);
14
+ }
15
+
16
+ private _items: OptionWithLink[] = [];
17
+ }
@@ -0,0 +1,141 @@
1
+ @import "dxHelpers/reset";
2
+ @import "dxHelpers/text";
3
+
4
+ :host {
5
+ --subnav-height: 60px;
6
+ --subnav-height-neg: calc(-1 * var(--subnav-height));
7
+ }
8
+
9
+ .subnav {
10
+ position: sticky;
11
+ top: -1px; /* necessary for intersection observer ux */
12
+ left: 0;
13
+ width: 100%;
14
+ height: var(--subnav-height);
15
+ background: white;
16
+ padding: 0 var(--dx-g-page-padding-horizontal);
17
+ display: flex;
18
+ flex-direction: row;
19
+ align-items: center;
20
+ justify-content: space-between;
21
+ z-index: var(--dx-g-z-index-100);
22
+ transition: var(--dx-g-transition-box-shadow-1x);
23
+ }
24
+
25
+ .subnav::after {
26
+ content: "";
27
+ z-index: 1;
28
+ position: absolute;
29
+ bottom: 0;
30
+ left: 0;
31
+ height: 2px;
32
+ width: 100%;
33
+ background: var(--dx-g-gray-95);
34
+ }
35
+
36
+ nav {
37
+ height: 100%;
38
+ overflow-y: auto;
39
+ margin: 0 var(--dx-g-spacing-smd);
40
+ z-index: 2;
41
+ }
42
+
43
+ ul {
44
+ height: 100%;
45
+ display: flex;
46
+ flex-direction: row;
47
+ align-items: center;
48
+ }
49
+
50
+ li {
51
+ height: 100%;
52
+ text-decoration: none;
53
+ }
54
+
55
+ ul > li:not(:last-of-type) {
56
+ margin-right: var(--dx-g-text-3xl);
57
+ }
58
+
59
+ a {
60
+ position: relative;
61
+ height: 100%;
62
+ display: flex;
63
+ align-items: center;
64
+ justify-content: center;
65
+ white-space: nowrap;
66
+ }
67
+
68
+ a::after {
69
+ content: "";
70
+ position: absolute;
71
+ bottom: 0;
72
+ left: 0;
73
+ width: 100%;
74
+ height: 0;
75
+ background: var(--dx-g-blue-vibrant-50);
76
+ transition: height 0.15s ease-in, var(--dx-g-transition-hue-1x);
77
+ }
78
+
79
+ a.active::after {
80
+ height: 4px;
81
+ }
82
+
83
+ a > dx-icon-badge {
84
+ --dx-c-icon-badge-size: 30px;
85
+ --dx-c-icon-badge-icon-size: 17px;
86
+ --dx-c-icon-badge-background-color: var(--dx-g-blue-vibrant-20);
87
+ --dx-c-icon-badge-transition: var(--dx-g-transition-hue-1x);
88
+
89
+ margin-right: var(--dx-g-spacing-sm);
90
+ }
91
+
92
+ a.active > dx-icon-badge {
93
+ --dx-c-icon-badge-background-color: var(--dx-g-blue-vibrant-50);
94
+ }
95
+
96
+ a.active > dx-icon-badge::part(badge),
97
+ a:not(.active):hover > dx-icon-badge::part(badge) {
98
+ --dx-c-icon-badge-color: white;
99
+ }
100
+
101
+ a:not(.active):hover > dx-icon-badge::part(badge) {
102
+ --dx-c-icon-badge-background-color: var(--dx-g-blue-vibrant-40);
103
+ }
104
+
105
+ /* accounts for font gap */
106
+ a > span {
107
+ transform: translateY(2px);
108
+ }
109
+
110
+ dx-button {
111
+ flex-shrink: 0;
112
+ }
113
+
114
+ .subnav.is-sticky {
115
+ box-shadow: 0 0 2px rgba(24, 24, 24, 0.08),
116
+ 0 2px 4px 1px rgba(24, 24, 24, 0.16);
117
+ }
118
+
119
+ .subnav.is-sticky dx-button {
120
+ visibility: visible;
121
+ }
122
+
123
+ @media (min-width: 640px) {
124
+ dx-button {
125
+ visibility: hidden;
126
+ }
127
+ }
128
+
129
+ @media (max-width: 1024px) {
130
+ ul > li:not(:last-of-type) {
131
+ margin-right: var(--dx-g-spacing-md);
132
+ }
133
+
134
+ a.active {
135
+ color: var(--dx-g-blue-vibrant-50) !important;
136
+ }
137
+
138
+ a:not(.active):hover {
139
+ color: var(--dx-g-blue-vibrant-40);
140
+ }
141
+ }
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <div class="subnav">
3
+ <template if:false={isMobile}>
4
+ <dx-button
5
+ variant="tertiary"
6
+ icon-symbol="arrowup"
7
+ onclick={scrollToTop}
8
+ >
9
+ Back to Top
10
+ </dx-button>
11
+ </template>
12
+ <template if:true={isMobile}>
13
+ <dx-button
14
+ variant="tertiary"
15
+ icon-symbol="arrowup"
16
+ onclick={scrollToTop}
17
+ ></dx-button>
18
+ </template>
19
+ <nav role="navigation" aria-label="Secondary Navigation">
20
+ <ul>
21
+ <template for:each={navItems} for:item="navItem">
22
+ <li key={navItem.id}>
23
+ <a class={navItem.className} href={navItem.link.href}>
24
+ <dx-icon-badge
25
+ symbol={navItem.iconSymbol}
26
+ color={navItem.iconColor}
27
+ if:true={isDesktop}
28
+ ></dx-icon-badge>
29
+ <span>{navItem.label}</span>
30
+ </a>
31
+ </li>
32
+ </template>
33
+ </ul>
34
+ </nav>
35
+ <dx-button href={subscribeHref}>Subscribe</dx-button>
36
+ </div>
37
+ </template>
@@ -0,0 +1,130 @@
1
+ import { api } from "lwc";
2
+ import cx from "classnames";
3
+ import { MatchMediaElement } from "dxBaseElements/matchMediaElement";
4
+ import type { OptionWithLink } from "typings/custom";
5
+ import { toJson } from "dxUtils/normalizers";
6
+
7
+ const SECTION_OBSERVER_OPTIONS = {
8
+ root: document,
9
+ threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
10
+ };
11
+
12
+ export default class SubNavBar extends MatchMediaElement {
13
+ @api subscribeHref!: string;
14
+ @api containerQuery: string = "body";
15
+
16
+ @api
17
+ get navItems() {
18
+ return this._navItems.map(this.normalizeItem);
19
+ }
20
+ set navItems(value) {
21
+ this._navItems = toJson(value);
22
+ }
23
+
24
+ private _navItems!: OptionWithLink[];
25
+ private sectionIntersectionEntryMap:
26
+ | {
27
+ [id: string]: IntersectionObserverEntry;
28
+ }
29
+ | {} = {};
30
+ private sectionsObserver!: IntersectionObserver;
31
+ private stickyNavObserver!: IntersectionObserver;
32
+
33
+ private get containerElement(): HTMLElement {
34
+ return document.querySelector(this.containerQuery) as HTMLElement;
35
+ }
36
+
37
+ private get hashIds(): string[] {
38
+ return this.navItems.map((item: OptionWithLink) =>
39
+ item.link.href.replace("#", "")
40
+ );
41
+ }
42
+
43
+ private get activeHash(): string | null {
44
+ const activeEntry = Object.values(
45
+ this.sectionIntersectionEntryMap
46
+ ).reduce(
47
+ (
48
+ acc: IntersectionObserverEntry | null,
49
+ val: IntersectionObserverEntry
50
+ ) => {
51
+ if (
52
+ val.intersectionRatio > 0 &&
53
+ (!acc || val.intersectionRatio > acc.intersectionRatio)
54
+ ) {
55
+ return val;
56
+ }
57
+ return acc;
58
+ },
59
+ null
60
+ );
61
+ return activeEntry ? `#${activeEntry?.target?.id}` : null;
62
+ }
63
+
64
+ connectedCallback(): void {
65
+ super.connectedCallback();
66
+ this.observeSectionIntersections();
67
+ }
68
+
69
+ renderedCallback(): void {
70
+ this.observeStickyNav();
71
+ }
72
+
73
+ disconnectedCallback(): void {
74
+ super.disconnectedCallback();
75
+ this.sectionsObserver?.disconnect();
76
+ this.stickyNavObserver?.disconnect();
77
+ }
78
+
79
+ normalizeItem = (item: OptionWithLink): object => ({
80
+ ...item,
81
+ className: cx(
82
+ "nav-item",
83
+ "dx-text-heading-6",
84
+ this.activeHash === item?.link?.href && "active"
85
+ )
86
+ });
87
+
88
+ private observeStickyNav() {
89
+ const el = this.template.querySelector(".subnav");
90
+ if (el && !this.stickyNavObserver) {
91
+ this.stickyNavObserver = new IntersectionObserver(
92
+ ([e]) => {
93
+ e.target.classList.toggle(
94
+ "is-sticky",
95
+ e.intersectionRatio < 1
96
+ );
97
+ },
98
+ { threshold: [1] }
99
+ );
100
+ this.stickyNavObserver.observe(el);
101
+ }
102
+ }
103
+
104
+ private observeSectionIntersections() {
105
+ this.sectionsObserver = new IntersectionObserver(
106
+ (entries) =>
107
+ entries.forEach((entry) => {
108
+ this.sectionIntersectionEntryMap = {
109
+ ...this.sectionIntersectionEntryMap,
110
+ [entry.target.id]: entry
111
+ };
112
+ }),
113
+ SECTION_OBSERVER_OPTIONS
114
+ );
115
+ this.hashIds.forEach((id) => {
116
+ const el = document.getElementById(id);
117
+ if (el) {
118
+ this.sectionsObserver.observe(el);
119
+ }
120
+ });
121
+ }
122
+
123
+ private scrollToTop() {
124
+ this.containerElement.scroll({
125
+ top: 0,
126
+ left: 0,
127
+ behavior: "smooth"
128
+ });
129
+ }
130
+ }