@ptcwebops/ptcw-design 6.4.4 → 6.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/dist/cjs/blog-detail-content_2.cjs.entry.js +1 -1
  2. package/dist/cjs/blog-detail-layout.cjs.entry.js +1 -1
  3. package/dist/cjs/blogs-search-section.cjs.entry.js +1 -1
  4. package/dist/cjs/homepage-jumbotron.cjs.entry.js +1 -1
  5. package/dist/cjs/homepage-toggled-content.cjs.entry.js +1 -1
  6. package/dist/cjs/innovator-toggle-container.cjs.entry.js +39 -3
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/cjs/most-popular-news.cjs.entry.js +1 -1
  9. package/dist/cjs/my-component.cjs.entry.js +1 -1
  10. package/dist/cjs/ptc-accordion-item.cjs.entry.js +1 -1
  11. package/dist/cjs/ptc-background-video.cjs.entry.js +99 -28
  12. package/dist/cjs/ptc-button_5.cjs.entry.js +597 -0
  13. package/dist/cjs/ptc-card_2.cjs.entry.js +1 -1
  14. package/dist/cjs/ptc-collapse-list.cjs.entry.js +1 -1
  15. package/dist/cjs/ptc-form-checkbox_2.cjs.entry.js +1 -1
  16. package/dist/cjs/ptc-homepage-image-feature.cjs.entry.js +1 -1
  17. package/dist/cjs/ptc-homepage-video-background.cjs.entry.js +1 -1
  18. package/dist/cjs/ptc-icon-card.cjs.entry.js +1 -1
  19. package/dist/cjs/ptc-jumbotron.cjs.entry.js +1 -1
  20. package/dist/cjs/ptc-link.cjs.entry.js +1 -1
  21. package/dist/cjs/ptc-media-card.cjs.entry.js +74 -6
  22. package/dist/cjs/ptc-multi-select_2.cjs.entry.js +1 -1
  23. package/dist/cjs/ptc-pricing-packaging-table.cjs.entry.js +1 -1
  24. package/dist/cjs/ptc-pricing-tabs.cjs.entry.js +1 -1
  25. package/dist/cjs/ptc-skeleton.cjs.entry.js +1 -1
  26. package/dist/cjs/ptc-social-icons-footer.cjs.entry.js +1 -1
  27. package/dist/cjs/ptc-subnav-v2.cjs.entry.js +430 -0
  28. package/dist/cjs/ptc-text-copy-with-background.cjs.entry.js +1 -1
  29. package/dist/cjs/ptcw-design.cjs.js +1 -1
  30. package/dist/cjs/{utils-b63aef52.js → utils-0ff09a53.js} +13 -0
  31. package/dist/collection/collection-manifest.json +1 -0
  32. package/dist/collection/components/innovator-toggle-container/innovator-toggle-container.js +39 -3
  33. package/dist/collection/components/ptc-background-video/ptc-background-video.css +21 -0
  34. package/dist/collection/components/ptc-background-video/ptc-background-video.js +110 -43
  35. package/dist/collection/components/ptc-jumbotron/ptc-jumbotron.css +5 -0
  36. package/dist/collection/components/ptc-media-card/ptc-media-card.js +78 -7
  37. package/dist/collection/components/ptc-preloader-section/ptc-preloader-section.css +16 -0
  38. package/dist/collection/components/ptc-seo-title/ptc-seo-title.js +3 -3
  39. package/dist/collection/components/ptc-skeleton/ptc-skeleton.css +6 -0
  40. package/dist/collection/components/ptc-subnav-v2/ptc-subnav-v2.css +394 -0
  41. package/dist/collection/components/ptc-subnav-v2/ptc-subnav-v2.js +483 -0
  42. package/dist/collection/components/ptc-text-copy-with-background/ptc-text-copy-with-background.css +19 -0
  43. package/dist/collection/stories/organisms/ptc/Subnav New/preview.stories.js +360 -0
  44. package/dist/collection/utils/utils.js +11 -0
  45. package/dist/custom-elements/index.d.ts +6 -0
  46. package/dist/custom-elements/index.js +654 -42
  47. package/dist/esm/blog-detail-content_2.entry.js +1 -1
  48. package/dist/esm/blog-detail-layout.entry.js +1 -1
  49. package/dist/esm/blogs-search-section.entry.js +1 -1
  50. package/dist/esm/homepage-jumbotron.entry.js +1 -1
  51. package/dist/esm/homepage-toggled-content.entry.js +1 -1
  52. package/dist/esm/innovator-toggle-container.entry.js +39 -3
  53. package/dist/esm/{interfaces-4caedd26.js → interfaces-7c0243be.js} +1 -1
  54. package/dist/esm/loader.js +1 -1
  55. package/dist/esm/most-popular-news.entry.js +1 -1
  56. package/dist/esm/my-component.entry.js +1 -1
  57. package/dist/esm/ptc-accordion-item.entry.js +1 -1
  58. package/dist/esm/ptc-background-video.entry.js +99 -28
  59. package/dist/esm/ptc-button_5.entry.js +589 -0
  60. package/dist/esm/ptc-card_2.entry.js +1 -1
  61. package/dist/esm/ptc-collapse-list.entry.js +1 -1
  62. package/dist/esm/ptc-form-checkbox_2.entry.js +1 -1
  63. package/dist/esm/ptc-homepage-image-feature.entry.js +1 -1
  64. package/dist/esm/ptc-homepage-video-background.entry.js +1 -1
  65. package/dist/esm/ptc-icon-card.entry.js +1 -1
  66. package/dist/esm/ptc-img.entry.js +1 -1
  67. package/dist/esm/ptc-jumbotron.entry.js +1 -1
  68. package/dist/esm/ptc-link.entry.js +1 -1
  69. package/dist/esm/ptc-media-card.entry.js +74 -6
  70. package/dist/esm/ptc-multi-select_2.entry.js +1 -1
  71. package/dist/esm/ptc-pricing-packaging-table.entry.js +1 -1
  72. package/dist/esm/ptc-pricing-tabs.entry.js +1 -1
  73. package/dist/esm/ptc-skeleton.entry.js +1 -1
  74. package/dist/esm/ptc-social-icons-footer.entry.js +1 -1
  75. package/dist/esm/ptc-subnav-v2.entry.js +426 -0
  76. package/dist/esm/ptc-text-copy-with-background.entry.js +1 -1
  77. package/dist/esm/ptcw-design.js +1 -1
  78. package/dist/esm/{utils-2f12c081.js → utils-a64ba942.js} +12 -1
  79. package/dist/ptcw-design/{p-9dbcfcee.entry.js → p-01497d7a.entry.js} +1 -1
  80. package/dist/ptcw-design/p-043be054.entry.js +1 -0
  81. package/dist/ptcw-design/{p-257267e3.entry.js → p-0df868d2.entry.js} +1 -1
  82. package/dist/ptcw-design/{p-fe8392c4.entry.js → p-1489b374.entry.js} +1 -1
  83. package/dist/ptcw-design/p-1c569057.entry.js +1 -0
  84. package/dist/ptcw-design/p-22cf00e7.js +1 -0
  85. package/dist/ptcw-design/p-28113014.entry.js +1 -0
  86. package/dist/ptcw-design/{p-d0fb9bfb.entry.js → p-2f21b69b.entry.js} +1 -1
  87. package/dist/ptcw-design/{p-45b1f3fc.entry.js → p-456c5cbb.entry.js} +1 -1
  88. package/dist/ptcw-design/{p-c3022c48.entry.js → p-54b589a6.entry.js} +1 -1
  89. package/dist/ptcw-design/{p-9b0df204.entry.js → p-5877f093.entry.js} +1 -1
  90. package/dist/ptcw-design/{p-78370e3d.entry.js → p-5a8e7557.entry.js} +1 -1
  91. package/dist/ptcw-design/{p-3ed4a7ed.entry.js → p-5ca42138.entry.js} +1 -1
  92. package/dist/ptcw-design/{p-901c31b3.entry.js → p-5cf5b9f8.entry.js} +1 -1
  93. package/dist/ptcw-design/{p-4fff8cc8.entry.js → p-6a1d9c7d.entry.js} +1 -1
  94. package/dist/ptcw-design/{p-a5fc048f.entry.js → p-82f766d2.entry.js} +1 -1
  95. package/dist/ptcw-design/{p-76dab076.entry.js → p-8aca7181.entry.js} +1 -1
  96. package/dist/ptcw-design/{p-52e17d34.entry.js → p-92ad78c5.entry.js} +1 -1
  97. package/dist/ptcw-design/p-9c8b739c.entry.js +1 -0
  98. package/dist/ptcw-design/{p-4098e953.entry.js → p-9f4ad29d.entry.js} +1 -1
  99. package/dist/ptcw-design/p-a8bfef4d.entry.js +1 -0
  100. package/dist/ptcw-design/{p-abadbe5b.entry.js → p-bd9d995b.entry.js} +1 -1
  101. package/dist/ptcw-design/{p-8c121480.entry.js → p-c160bda4.entry.js} +1 -1
  102. package/dist/ptcw-design/p-c555a45c.entry.js +1 -0
  103. package/dist/ptcw-design/{p-96163196.entry.js → p-d0ebcace.entry.js} +1 -1
  104. package/dist/ptcw-design/{p-81e5fa38.entry.js → p-d2998707.entry.js} +1 -1
  105. package/dist/ptcw-design/{p-19a407ff.entry.js → p-de650865.entry.js} +1 -1
  106. package/dist/ptcw-design/{p-54f5a5be.entry.js → p-e23bc4a1.entry.js} +1 -1
  107. package/dist/ptcw-design/{p-711bcdad.js → p-ee1183b2.js} +1 -1
  108. package/dist/ptcw-design/{p-9f01419b.entry.js → p-f2675bb0.entry.js} +1 -1
  109. package/dist/ptcw-design/ptcw-design.css +1 -1
  110. package/dist/ptcw-design/ptcw-design.esm.js +1 -1
  111. package/dist/types/components/innovator-toggle-container/innovator-toggle-container.d.ts +3 -0
  112. package/dist/types/components/ptc-background-video/ptc-background-video.d.ts +31 -47
  113. package/dist/types/components/ptc-media-card/ptc-media-card.d.ts +8 -2
  114. package/dist/types/components/ptc-subnav-v2/ptc-subnav-v2.d.ts +55 -0
  115. package/dist/types/components.d.ts +105 -88
  116. package/dist/types/utils/utils.d.ts +2 -0
  117. package/package.json +98 -98
  118. package/readme.md +19 -19
  119. package/dist/cjs/ptc-button.cjs.entry.js +0 -117
  120. package/dist/cjs/ptc-para.cjs.entry.js +0 -139
  121. package/dist/cjs/ptc-picture.cjs.entry.js +0 -168
  122. package/dist/cjs/ptc-spacer.cjs.entry.js +0 -38
  123. package/dist/cjs/ptc-title.cjs.entry.js +0 -161
  124. package/dist/esm/ptc-button.entry.js +0 -113
  125. package/dist/esm/ptc-para.entry.js +0 -135
  126. package/dist/esm/ptc-picture.entry.js +0 -164
  127. package/dist/esm/ptc-spacer.entry.js +0 -34
  128. package/dist/esm/ptc-title.entry.js +0 -157
  129. package/dist/ptcw-design/p-0c69ea52.entry.js +0 -1
  130. package/dist/ptcw-design/p-24776ca2.entry.js +0 -1
  131. package/dist/ptcw-design/p-605b13a2.entry.js +0 -1
  132. package/dist/ptcw-design/p-80122e26.js +0 -1
  133. package/dist/ptcw-design/p-8cea8943.entry.js +0 -1
  134. package/dist/ptcw-design/p-a8872ce3.entry.js +0 -1
  135. package/dist/ptcw-design/p-c6431ebc.entry.js +0 -1
  136. package/dist/ptcw-design/p-d51438de.entry.js +0 -1
  137. package/dist/ptcw-design/p-d875f96d.entry.js +0 -1
  138. package/dist/ptcw-design/p-e4eb925f.entry.js +0 -1
@@ -0,0 +1,483 @@
1
+ import { Host, h } from "@stencil/core";
2
+ export class PtcSubnavV2 {
3
+ constructor() {
4
+ this.cachedNavItems = null;
5
+ this.handleClickOutside = (event) => {
6
+ if (!this.el.contains(event.target)) {
7
+ this.showOverflowMenu = false;
8
+ }
9
+ };
10
+ this.handleKeyDown = (event) => {
11
+ var _a;
12
+ if (event.key === "Escape" && this.showOverflowMenu) {
13
+ this.showOverflowMenu = false;
14
+ (_a = this.overflowButton) === null || _a === void 0 ? void 0 : _a.focus();
15
+ }
16
+ };
17
+ this.handleScroll = () => {
18
+ // Throttle scroll events for better performance
19
+ if (this.scrollThrottleTimeout) {
20
+ return;
21
+ }
22
+ this.scrollThrottleTimeout = window.setTimeout(() => {
23
+ // Don't update active state if user just manually navigated
24
+ if (this.isManualNavigation) {
25
+ this.scrollThrottleTimeout = null;
26
+ return;
27
+ }
28
+ // Fallback scroll handler to ensure active state is updated
29
+ const navItems = this.getNavItems();
30
+ const subnavHeight = this.el.offsetHeight;
31
+ const scrollPosition = window.scrollY + subnavHeight + 100; // Offset for better detection
32
+ // Find the section that should be active based on scroll position
33
+ let activeSection = navItems[0].id; // Default to first section
34
+ for (let i = navItems.length - 1; i >= 0; i--) {
35
+ const section = document.getElementById(navItems[i].id);
36
+ if (section && section.offsetTop <= scrollPosition) {
37
+ activeSection = navItems[i].id;
38
+ break;
39
+ }
40
+ }
41
+ // Only update if different from current active
42
+ if (activeSection !== this.currentActive) {
43
+ this.currentActive = activeSection;
44
+ // Update mobile selected item if in mobile mode
45
+ if (this.isMobile) {
46
+ const activeItem = navItems.find((item) => item.id === activeSection);
47
+ if (activeItem) {
48
+ this.selectedMobileItem = activeItem;
49
+ }
50
+ }
51
+ }
52
+ this.scrollThrottleTimeout = null;
53
+ }, 16); // ~60fps throttling
54
+ };
55
+ this.handleResize = () => {
56
+ this.navContainer && setTimeout(() => this.calculateVisibleItems(), 10);
57
+ };
58
+ this.setupIntersectionObserver = () => {
59
+ // Get all sections that correspond to our navigation items
60
+ const navItems = this.getNavItems();
61
+ // Create intersection observer
62
+ this.intersectionObserver = new IntersectionObserver((entries) => {
63
+ // Clear any existing timeout
64
+ if (this.scrollTimeout) {
65
+ clearTimeout(this.scrollTimeout);
66
+ }
67
+ // Debounce the intersection changes
68
+ this.scrollTimeout = window.setTimeout(() => {
69
+ // Don't update active state if user just manually navigated
70
+ if (this.isManualNavigation) {
71
+ return;
72
+ }
73
+ // Find all intersecting sections
74
+ const intersectingSections = entries.filter((entry) => entry.isIntersecting);
75
+ if (intersectingSections.length > 0) {
76
+ // Sort by intersection ratio (how much of the section is visible)
77
+ // and then by position (top to bottom)
78
+ intersectingSections.sort((a, b) => {
79
+ // First sort by intersection ratio (higher = more visible)
80
+ if (b.intersectionRatio !== a.intersectionRatio) {
81
+ return (b.intersectionRatio - a.intersectionRatio);
82
+ }
83
+ // If intersection ratios are equal, sort by position
84
+ return (a.boundingClientRect.top -
85
+ b.boundingClientRect.top);
86
+ });
87
+ // Get the most visible section
88
+ const mostVisibleSection = intersectingSections[0];
89
+ const sectionId = mostVisibleSection.target.id;
90
+ if (sectionId && sectionId !== this.currentActive) {
91
+ this.currentActive = sectionId;
92
+ // Update mobile selected item if in mobile mode
93
+ if (this.isMobile) {
94
+ const activeItem = navItems.find((item) => item.id === sectionId);
95
+ if (activeItem) {
96
+ this.selectedMobileItem = activeItem;
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }, 100); // Increased debounce time for better performance
102
+ }, {
103
+ root: null,
104
+ rootMargin: "-20% 0px -60% 0px",
105
+ threshold: [0, 0.1, 0.25, 0.5, 0.75, 1.0], // Multiple thresholds for better detection
106
+ });
107
+ // Observe all sections
108
+ navItems.forEach((item) => {
109
+ const section = document.getElementById(item.id);
110
+ if (section) {
111
+ this.intersectionObserver.observe(section);
112
+ }
113
+ });
114
+ };
115
+ this.extractNavItemsFromSlots = () => {
116
+ const slotElement = this.el.querySelector('[slot="nav-items"]');
117
+ if (!slotElement)
118
+ return null;
119
+ const links = slotElement.querySelectorAll("a");
120
+ const items = Array.from(links)
121
+ .map((link) => {
122
+ var _a, _b;
123
+ return ({
124
+ id: ((_a = link.getAttribute("href")) === null || _a === void 0 ? void 0 : _a.substring(1)) || "",
125
+ label: ((_b = link.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || "",
126
+ title: link.getAttribute("title") || undefined,
127
+ trackerId: link.getAttribute("tracker-id") || undefined,
128
+ });
129
+ })
130
+ .filter((item) => Boolean(item.id && item.label));
131
+ return items.length > 0 ? items : null;
132
+ };
133
+ this.getNavItems = () => {
134
+ // Return cached items if available
135
+ if (this.cachedNavItems) {
136
+ return this.cachedNavItems;
137
+ }
138
+ // Extract navigation items from slots (SEO-friendly approach)
139
+ const slotItems = this.extractNavItemsFromSlots();
140
+ if (slotItems) {
141
+ this.cachedNavItems = slotItems;
142
+ return slotItems;
143
+ }
144
+ // If navItems prop is provided, parse and use it (fallback)
145
+ const propItems = this.parsePropNavItems();
146
+ if (propItems) {
147
+ this.cachedNavItems = propItems;
148
+ return propItems;
149
+ }
150
+ // Return empty array if no navigation items found
151
+ console.warn("No navigation items found in slots or props for ptc-subnav-v2");
152
+ return [];
153
+ };
154
+ this.calculateMobileDropdownItems = () => {
155
+ this.mobileDropdownItems = this.getNavItems();
156
+ };
157
+ this.hasActiveOverflowItem = () => {
158
+ return this.overflowItems.some((item) => item.id === this.currentActive);
159
+ };
160
+ this.hasSubnavMenuRightContent = () => {
161
+ const slotElement = this.el.querySelector('[slot="subnav-menu-right"]');
162
+ return Boolean(slotElement === null || slotElement === void 0 ? void 0 : slotElement.children.length);
163
+ };
164
+ this.calculateVisibleItems = () => {
165
+ const navItems = this.getNavItems();
166
+ // Handle case where no navigation items are found
167
+ if (navItems.length === 0) {
168
+ this.visibleItems = [];
169
+ this.overflowItems = [];
170
+ this.selectedMobileItem = null;
171
+ return;
172
+ }
173
+ // Check if we're in mobile mode (below 767px)
174
+ const wasMobile = this.isMobile;
175
+ this.isMobile = window.innerWidth <= 767;
176
+ // Force re-render if mobile state changed
177
+ if (wasMobile !== this.isMobile) {
178
+ this.showOverflowMenu = false; // Close any open menus when switching modes
179
+ }
180
+ if (this.isMobile) {
181
+ // On mobile, show only the current active item
182
+ const activeItem = navItems.find((item) => item.id === this.currentActive) ||
183
+ navItems[0];
184
+ this.selectedMobileItem = activeItem;
185
+ this.visibleItems = [activeItem];
186
+ this.overflowItems = navItems.filter((item) => item.id !== activeItem.id);
187
+ }
188
+ else {
189
+ // Desktop behavior - calculate based on available width
190
+ const containerWidth = this.navContainer
191
+ ? this.navContainer.offsetWidth
192
+ : 0;
193
+ const buttonWidth = this.overflowButton
194
+ ? this.overflowButton.offsetWidth + 32
195
+ : 0; // 32px for gap
196
+ const availableWidth = containerWidth - buttonWidth - 48; // 48px for right margin
197
+ // Fallback if container width is not available yet
198
+ if (containerWidth === 0) {
199
+ this.visibleItems = navItems;
200
+ this.overflowItems = [];
201
+ return;
202
+ }
203
+ let visibleCount = 0;
204
+ let totalWidth = 0;
205
+ // Create temporary elements to measure width
206
+ const tempContainer = document.createElement("div");
207
+ tempContainer.style.position = "absolute";
208
+ tempContainer.style.visibility = "hidden";
209
+ tempContainer.style.whiteSpace = "nowrap";
210
+ tempContainer.style.fontSize = "14px";
211
+ tempContainer.style.fontWeight = "700";
212
+ tempContainer.style.padding = "20px 0 20px 0";
213
+ document.body.appendChild(tempContainer);
214
+ for (let i = 0; i < navItems.length; i++) {
215
+ const item = navItems[i];
216
+ tempContainer.textContent = item.label;
217
+ const itemWidth = tempContainer.offsetWidth + 32; // 32px for gap
218
+ if (totalWidth + itemWidth <= availableWidth) {
219
+ totalWidth += itemWidth;
220
+ visibleCount++;
221
+ }
222
+ else {
223
+ break;
224
+ }
225
+ }
226
+ document.body.removeChild(tempContainer);
227
+ this.visibleItems = navItems.slice(0, visibleCount);
228
+ this.overflowItems = navItems.slice(visibleCount);
229
+ }
230
+ // Don't automatically show overflow menu - it should be closed by default
231
+ // this.showOverflowMenu = this.overflowItems.length > 0;
232
+ };
233
+ this.toggleOverflowMenu = () => {
234
+ this.showOverflowMenu = !this.showOverflowMenu;
235
+ };
236
+ this.handleNavClick = (event, section) => {
237
+ event.preventDefault();
238
+ this.currentActive = section;
239
+ // Update mobile selected item if in mobile mode
240
+ if (this.isMobile) {
241
+ const navItems = this.getNavItems();
242
+ const activeItem = navItems.find((item) => item.id === section);
243
+ if (activeItem) {
244
+ this.selectedMobileItem = activeItem;
245
+ this.calculateMobileDropdownItems();
246
+ }
247
+ }
248
+ // Set manual navigation flag to prevent intersection observer from overriding
249
+ this.isManualNavigation = true;
250
+ // Clear any existing manual navigation timeout
251
+ if (this.manualNavigationTimeout) {
252
+ clearTimeout(this.manualNavigationTimeout);
253
+ }
254
+ // Reset manual navigation flag after scroll animation completes
255
+ this.manualNavigationTimeout = window.setTimeout(() => {
256
+ this.isManualNavigation = false;
257
+ }, 1500); // Give enough time for smooth scroll to complete
258
+ // Emit custom event for parent components
259
+ const customEvent = new CustomEvent("sectionChange", {
260
+ detail: { section },
261
+ bubbles: true,
262
+ composed: true,
263
+ });
264
+ this.el.dispatchEvent(customEvent);
265
+ // Smooth scroll to section if it exists
266
+ const targetElement = document.querySelector(`#${section}`);
267
+ if (targetElement) {
268
+ targetElement.scrollIntoView({
269
+ behavior: "smooth",
270
+ block: "start",
271
+ });
272
+ }
273
+ };
274
+ this.activeSection = "overview";
275
+ this.navItems = "";
276
+ this.currentActive = "overview";
277
+ this.visibleItems = [];
278
+ this.overflowItems = [];
279
+ this.showOverflowMenu = false;
280
+ this.isMobile = false;
281
+ this.selectedMobileItem = null;
282
+ this.isManualNavigation = false;
283
+ this.mobileDropdownItems = [];
284
+ }
285
+ componentWillLoad() {
286
+ this.currentActive = this.activeSection;
287
+ this.initializeMobileItem();
288
+ this.calculateMobileDropdownItems();
289
+ }
290
+ initializeMobileItem() {
291
+ const navItems = this.getNavItems();
292
+ this.selectedMobileItem =
293
+ navItems.length > 0
294
+ ? navItems.find((item) => item.id === this.activeSection) ||
295
+ navItems[0]
296
+ : null;
297
+ }
298
+ componentDidLoad() {
299
+ this.bindEventHandlers();
300
+ this.calculateMobileDropdownItems();
301
+ this.handleResize();
302
+ this.addEventListeners();
303
+ this.setupIntersectionObserver();
304
+ }
305
+ bindEventHandlers() {
306
+ this.boundHandleResize = this.handleResize.bind(this);
307
+ this.boundHandleClickOutside = this.handleClickOutside.bind(this);
308
+ this.boundHandleScroll = this.handleScroll.bind(this);
309
+ this.boundHandleKeyDown = this.handleKeyDown.bind(this);
310
+ }
311
+ addEventListeners() {
312
+ window.addEventListener("resize", this.boundHandleResize);
313
+ document.addEventListener("click", this.boundHandleClickOutside);
314
+ document.addEventListener("keydown", this.boundHandleKeyDown);
315
+ window.addEventListener("scroll", this.boundHandleScroll, {
316
+ passive: true,
317
+ });
318
+ }
319
+ disconnectedCallback() {
320
+ this.removeEventListeners();
321
+ this.cleanupTimeouts();
322
+ this.cleanupIntersectionObserver();
323
+ }
324
+ removeEventListeners() {
325
+ window.removeEventListener("resize", this.boundHandleResize);
326
+ document.removeEventListener("click", this.boundHandleClickOutside);
327
+ document.removeEventListener("keydown", this.boundHandleKeyDown);
328
+ window.removeEventListener("scroll", this.boundHandleScroll);
329
+ }
330
+ cleanupTimeouts() {
331
+ [
332
+ this.scrollTimeout,
333
+ this.scrollThrottleTimeout,
334
+ this.manualNavigationTimeout,
335
+ ]
336
+ .filter(Boolean)
337
+ .forEach((timeout) => clearTimeout(timeout));
338
+ }
339
+ cleanupIntersectionObserver() {
340
+ if (this.intersectionObserver) {
341
+ this.intersectionObserver.disconnect();
342
+ }
343
+ }
344
+ parsePropNavItems() {
345
+ var _a;
346
+ if (!((_a = this.navItems) === null || _a === void 0 ? void 0 : _a.trim()))
347
+ return null;
348
+ try {
349
+ const parsedItems = JSON.parse(this.navItems);
350
+ if (Array.isArray(parsedItems) && parsedItems.length > 0) {
351
+ const validItems = parsedItems.filter((item) => Boolean(item &&
352
+ typeof item.id === "string" &&
353
+ typeof item.label === "string"));
354
+ return validItems.length > 0 ? validItems : null;
355
+ }
356
+ }
357
+ catch (error) {
358
+ console.warn("Invalid navItems JSON provided to ptc-subnav-v2:", error);
359
+ }
360
+ return null;
361
+ }
362
+ render() {
363
+ var _a, _b;
364
+ const navItems = this.getNavItems();
365
+ // If no navigation items, don't render the navigation
366
+ if (navItems.length === 0) {
367
+ const hasRightContent = this.hasSubnavMenuRightContent();
368
+ return (h(Host, null, h("div", { class: `subnav-container ${!hasRightContent ? "full-width" : ""}` }, hasRightContent && (h("div", { class: "subnav-menu-right" }, h("slot", { name: "subnav-menu-right" }))))));
369
+ }
370
+ const hasRightContent = this.hasSubnavMenuRightContent();
371
+ return (h(Host, null, h("div", { class: `subnav-container ${!hasRightContent ? "full-width" : ""}` }, h("nav", { class: `subnav-menu-left ${!hasRightContent ? "full-width" : ""}`, role: "navigation", "aria-label": "Sub navigation", ref: (el) => (this.navContainer = el) }, this.isMobile ? (
372
+ // Mobile layout - dropdown with arrows
373
+ h("div", { class: "mobile-dropdown-container" }, h("button", { class: "mobile-dropdown-button", onClick: this.toggleOverflowMenu, onKeyDown: (e) => {
374
+ if (e.key === "Enter" ||
375
+ e.key === " ") {
376
+ e.preventDefault();
377
+ this.toggleOverflowMenu();
378
+ }
379
+ }, "aria-expanded": this.showOverflowMenu, "aria-haspopup": "true", "aria-label": `${((_a = this.selectedMobileItem) === null || _a === void 0 ? void 0 : _a.label) || "Select Section"} - Choose navigation section`, "tracker-id": "mobile-dropdown-button", ref: (el) => (this.overflowButton = el) }, h("span", { class: "mobile-selected-item" }, ((_b = this.selectedMobileItem) === null || _b === void 0 ? void 0 : _b.label) ||
380
+ "Select Section"), h("span", { class: `mobile-arrow ${this.showOverflowMenu ? "rotated" : ""}`, "aria-hidden": "true" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "8", viewBox: "0 0 12 8", fill: "none", "aria-hidden": "true" }, h("path", { d: "M1 1.5L5.94975 6.44975L10.8995 1.5", stroke: "#00890B", "stroke-width": "2", "stroke-linecap": "round" })))), this.showOverflowMenu && (h("ul", { class: "mobile-dropdown", role: "menu", "aria-label": "Navigation sections" }, this.mobileDropdownItems.map((item) => (h("li", { key: item.id }, h("a", { href: `#${item.id}`, class: `mobile-dropdown-item mf-listen ${this
381
+ .currentActive ===
382
+ item.id
383
+ ? "active"
384
+ : ""}`, role: "menuitem", "aria-current": this
385
+ .currentActive ===
386
+ item.id
387
+ ? "page"
388
+ : undefined, "tracker-id": item.trackerId ||
389
+ `mobile-nav-${item.id}`, title: item.title || "", onClick: (e) => {
390
+ this.handleNavClick(e, item.id);
391
+ this.showOverflowMenu = false;
392
+ } }, item.label)))))))) : (
393
+ // Desktop layout - original behavior
394
+ h("ul", { class: "desktop-menu" }, this.visibleItems.map((item) => (h("li", { key: item.id, class: "mf-listen", "tracker-id": item.trackerId || `nav-${item.id}` }, h("a", { href: `#${item.id}`, class: this.currentActive === item.id
395
+ ? "active"
396
+ : "", title: item.title || "", onClick: (e) => this.handleNavClick(e, item.id), "aria-current": this.currentActive === item.id
397
+ ? "page"
398
+ : undefined }, item.label)))), this.overflowItems.length > 0 && (h("li", { class: "overflow-menu-container mf-listen", "tracker-id": "overflow-menu" }, h("button", { class: `overflow-button ${this.hasActiveOverflowItem() ? "selected-active" : ""}`, onClick: this.toggleOverflowMenu, onKeyDown: (e) => {
399
+ if (e.key === "Enter" ||
400
+ e.key === " ") {
401
+ e.preventDefault();
402
+ this.toggleOverflowMenu();
403
+ }
404
+ }, "aria-expanded": this.showOverflowMenu, "aria-haspopup": "true", "aria-label": "Show more navigation items", "tracker-id": "overflow-button", ref: (el) => (this.overflowButton = el) }, h("span", { class: "overflow-dots", "aria-hidden": "true" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", "aria-hidden": "true" }, h("circle", { cx: "1.25", cy: "5", r: "1.25", fill: "#617480" }), h("circle", { cx: "5", cy: "5", r: "1.25", fill: "#617480" }), h("circle", { cx: "8.75", cy: "5", r: "1.25", fill: "#617480" })))), this.showOverflowMenu && (h("div", { class: "overflow-dropdown", role: "menu", "aria-label": "Additional navigation sections" }, this.overflowItems.map((item) => (h("a", { key: item.id, href: `#${item.id}`, class: `mf-listen ${this
405
+ .currentActive ===
406
+ item.id
407
+ ? "active"
408
+ : ""}`, title: item.title || "", "tracker-id": item.trackerId ||
409
+ `overflow-link-${item.id}`, role: "menuitem", onClick: (e) => {
410
+ this.handleNavClick(e, item.id);
411
+ this.showOverflowMenu = false;
412
+ }, "aria-current": this
413
+ .currentActive ===
414
+ item.id
415
+ ? "page"
416
+ : undefined }, item.label)))))))))), hasRightContent && (h("div", { class: "subnav-menu-right" }, h("slot", { name: "subnav-menu-right" }))))));
417
+ }
418
+ static get is() { return "ptc-subnav-v2"; }
419
+ static get encapsulation() { return "shadow"; }
420
+ static get originalStyleUrls() {
421
+ return {
422
+ "$": ["ptc-subnav-v2.scss"]
423
+ };
424
+ }
425
+ static get styleUrls() {
426
+ return {
427
+ "$": ["ptc-subnav-v2.css"]
428
+ };
429
+ }
430
+ static get properties() {
431
+ return {
432
+ "activeSection": {
433
+ "type": "string",
434
+ "mutable": false,
435
+ "complexType": {
436
+ "original": "string",
437
+ "resolved": "string",
438
+ "references": {}
439
+ },
440
+ "required": false,
441
+ "optional": false,
442
+ "docs": {
443
+ "tags": [],
444
+ "text": ""
445
+ },
446
+ "attribute": "active-section",
447
+ "reflect": false,
448
+ "defaultValue": "\"overview\""
449
+ },
450
+ "navItems": {
451
+ "type": "string",
452
+ "mutable": false,
453
+ "complexType": {
454
+ "original": "string",
455
+ "resolved": "string",
456
+ "references": {}
457
+ },
458
+ "required": false,
459
+ "optional": false,
460
+ "docs": {
461
+ "tags": [],
462
+ "text": ""
463
+ },
464
+ "attribute": "nav-items",
465
+ "reflect": false,
466
+ "defaultValue": "\"\""
467
+ }
468
+ };
469
+ }
470
+ static get states() {
471
+ return {
472
+ "currentActive": {},
473
+ "visibleItems": {},
474
+ "overflowItems": {},
475
+ "showOverflowMenu": {},
476
+ "isMobile": {},
477
+ "selectedMobileItem": {},
478
+ "isManualNavigation": {},
479
+ "mobileDropdownItems": {}
480
+ };
481
+ }
482
+ static get elementRef() { return "el"; }
483
+ }
@@ -340,6 +340,25 @@ ptc-footer {
340
340
  max-width: 1200px;
341
341
  }
342
342
  }
343
+ @media (prefers-reduced-motion: reduce) {
344
+ :host(.case-studies) .card-wrap::after {
345
+ animation: none;
346
+ }
347
+ :host(.case-studies) .card-wrap::before {
348
+ animation: none;
349
+ }
350
+ :host(.case-studies) .card-wrap .card-animated-border::before {
351
+ animation: none;
352
+ }
353
+ :host(.case-studies) .card-wrap .card-animated-border::after {
354
+ animation: none;
355
+ }
356
+ :host(.case-studies) .card-wrap .card-content {
357
+ opacity: 1;
358
+ visibility: visible;
359
+ animation: none;
360
+ }
361
+ }
343
362
 
344
363
  :host(.bg-image-absent) {
345
364
  padding: 0rem;