@ptcwebops/ptcw-design 6.4.11-beta → 6.4.12-beta

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.
@@ -0,0 +1,429 @@
1
+ import { r as registerInstance, h, H as Host, g as getElement } from './index-c83db688.js';
2
+
3
+ const ptcSubnavV2Css = "h1,h2,h3,h4,h5,h6,p,ul,li,ptc-subnav,ptc-tab-list,ptc-link,ptc-square-card,.hyphenate-text,ptc-footer{word-break:break-word;hyphens:manual;-webkit-hyphens:manual;-moz-hyphens:manual;-ms-hyphens:manual}@supports (hyphenate-limit-chars: 12 3 3){h1,h2,h3,h4,h5,h6,p,ul,li,ptc-subnav,ptc-tab-list,ptc-link,ptc-square-card,.hyphenate-text,ptc-footer{hyphens:auto;-webkit-hyphenate-limit-before:3;-webkit-hyphenate-limit-after:3;hyphenate-limit-chars:12 3 3;hyphenate-limit-lines:2;hyphenate-limit-last:always;hyphenate-limit-zone:6%;-webkit-hyphens:auto;-webkit-hyphenate-limit-before:3;-webkit-hyphenate-limit-after:3;-webkit-hyphenate-limit-chars:12 3 3;-webkit-hyphenate-limit-lines:2;-moz-hyphens:auto;-moz-hyphenate-limit-chars:12 3 3;-moz-hyphenate-limit-lines:2;-ms-hyphens:auto;-ms-hyphenate-limit-chars:12 3 3;-ms-hyphenate-limit-lines:2}}:host{display:block;font-family:var(--ptc-font-latin);position:sticky;top:0;z-index:105;background-color:var(--color-standard-gray);box-shadow:var(--ptc-shadow-small)}:host .subnav-container{display:flex;flex-direction:row;justify-content:space-between;align-items:center;padding:0 24px;margin:0 auto;max-width:1200px;gap:24px}@media only screen and (min-width: 768px){:host .subnav-container{flex-wrap:wrap;gap:48px}}@media only screen and (min-width: 1200px){:host .subnav-container{padding-left:0;padding-right:0;max-width:1136px}}@media only screen and (min-width: 1440px){:host .subnav-container{padding-left:0;padding-right:0;max-width:1200px}}:host .subnav-menu-left{display:flex;align-items:center;flex:1}@media only screen and (min-width: 768px){:host .subnav-menu-left{justify-content:flex-start}}:host .subnav-menu-left ul.desktop-menu{list-style:none;padding:0;margin:0;display:flex;align-items:center;justify-content:center;gap:4px;flex-wrap:wrap;margin-bottom:-2px}@media only screen and (min-width: 768px){:host .subnav-menu-left ul.desktop-menu{justify-content:flex-start;gap:32px}}:host .subnav-menu-left ul.desktop-menu li{display:inline-block}:host .subnav-menu-left ul.desktop-menu li a{color:var(--color-gray-07);text-decoration:none;padding:8px 12px;font-size:var(--ptc-font-size-xx-small);font-weight:var(--ptc-font-weight-bold);line-height:var(--ptc-line-height-densest);display:block;position:relative;border-bottom:3px solid transparent}@media only screen and (min-width: 768px){:host .subnav-menu-left ul.desktop-menu li a{padding:20px 0 17px 0}}:host .subnav-menu-left ul.desktop-menu li a:hover{color:var(--color-gray-10)}:host .subnav-menu-left ul.desktop-menu li a.active{color:var(--color-gray-10);border-bottom:3px solid var(--color-green-07)}:host .subnav-menu-left ul.desktop-menu li a:focus-visible{border-radius:var(--ptc-border-radius-standard);outline:5px solid var(--keyboard-nav-outline)}:host .subnav-menu-left .overflow-menu-container{position:relative;display:none}@media only screen and (min-width: 768px){:host .subnav-menu-left .overflow-menu-container{display:inline-block}}:host .subnav-menu-left .overflow-menu-container .overflow-button{background:none;border:none;padding:20px 0 17px 0;font-size:var(--ptc-font-size-xx-small);font-weight:var(--ptc-font-weight-bold);color:var(--color-gray-07);cursor:pointer;display:flex;align-items:center;justify-content:center;min-width:32px;border-bottom:3px solid transparent;transition:all 0.2s ease}:host .subnav-menu-left .overflow-menu-container .overflow-button:hover{color:var(--color-gray-10)}:host .subnav-menu-left .overflow-menu-container .overflow-button:focus-visible{border-radius:var(--ptc-border-radius-standard);outline:5px solid var(--keyboard-nav-outline)}:host .subnav-menu-left .overflow-menu-container .overflow-button .overflow-dots{border-radius:2px;border:1px solid var(--color-gray-07);line-height:1;width:18px;height:18px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all 0.2s ease}:host .subnav-menu-left .overflow-menu-container .overflow-button .overflow-dots:hover{background-color:var(--color-gray-04);border-color:var(--color-gray-04)}:host .subnav-menu-left .overflow-menu-container .overflow-button .overflow-dots:hover svg circle{fill:var(--color-gray-10)}:host .subnav-menu-left .overflow-menu-container .overflow-button .overflow-dots:focus-visible{border-radius:var(--ptc-border-radius-standard);outline:5px solid var(--keyboard-nav-outline)}:host .subnav-menu-left .overflow-menu-container .overflow-button[aria-expanded],:host .subnav-menu-left .overflow-menu-container .overflow-button.selected-active{border-bottom:3px solid var(--color-green-07)}:host .subnav-menu-left .overflow-menu-container .overflow-button[aria-expanded] .overflow-dots,:host .subnav-menu-left .overflow-menu-container .overflow-button.selected-active .overflow-dots{background-color:var(--color-green-07);border-color:var(--color-green-07)}:host .subnav-menu-left .overflow-menu-container .overflow-button[aria-expanded] .overflow-dots svg circle,:host .subnav-menu-left .overflow-menu-container .overflow-button.selected-active .overflow-dots svg circle{fill:var(--color-white)}:host .subnav-menu-left .overflow-menu-container .overflow-dropdown{position:absolute;top:100%;right:0;background:var(--color-white);border-radius:var(--ptc-border-radius-standard);box-shadow:var(--ptc-shadow-x-large);min-width:200px;z-index:1001;padding:14px 0;margin-top:-4px;max-width:312px;width:-moz-max-content;width:max-content}:host .subnav-menu-left .overflow-menu-container .overflow-dropdown a{display:block;padding:12px 32px 12px 24px;color:var(--color-gray-07);text-decoration:none;font-size:var(--ptc-font-size-xx-small);font-weight:var(--ptc-font-weight-bold);line-height:var(--ptc-line-height-densest);transition:all 0.2s ease;position:relative;border:none}:host .subnav-menu-left .overflow-menu-container .overflow-dropdown a:hover{background-color:var(--color-gray-02);color:var(--color-gray-10)}:host .subnav-menu-left .overflow-menu-container .overflow-dropdown a.active{color:var(--color-gray-10);border-bottom:none}:host .subnav-menu-left .overflow-menu-container .overflow-dropdown a.active::before{content:\"\";display:block;width:2px;height:calc(100% - 0px);background-color:var(--color-green-07);position:absolute;left:16px;top:0}:host .subnav-menu-left .overflow-menu-container .overflow-dropdown a:focus-visible{border-radius:var(--ptc-border-radius-standard);outline:5px solid var(--keyboard-nav-outline)}:host .mobile-dropdown-container{position:relative;display:block}@media only screen and (min-width: 768px){:host .mobile-dropdown-container{display:none !important}}@media (min-width: 768px){:host .mobile-dropdown-container{display:none !important}}:host .mobile-dropdown-container .mobile-dropdown-button{display:flex;padding:20px 0 17px 0;justify-content:center;align-items:center;gap:10px;align-self:stretch;border:none;cursor:pointer;transition:all 0.2s ease;background-color:transparent;border-bottom:3px solid var(--color-green-07)}:host .mobile-dropdown-container .mobile-dropdown-button .mobile-selected-item{color:var(--color-gray-07);font-size:var(--ptc-font-size-xx-small);font-style:normal;font-weight:var(--ptc-font-weight-bold);line-height:var(--ptc-line-height-densest);display:-webkit-box;line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;max-width:100%}:host .mobile-dropdown-container .mobile-dropdown-button:hover{border-color:var(--color-gray-04);color:var(--color-gray-10)}:host .mobile-dropdown-container .mobile-dropdown-button:focus-visible{border-radius:var(--ptc-border-radius-standard);outline:5px solid var(--keyboard-nav-outline)}:host .mobile-dropdown-container .mobile-dropdown-button[aria-expanded]{border-color:var(--color-green-07);color:var(--color-gray-10)}:host .mobile-dropdown-container .mobile-dropdown-button .mobile-selected-item{flex:1;text-align:left}:host .mobile-dropdown-container .mobile-dropdown-button .mobile-arrow{display:flex;align-items:center;justify-content:center;transition:transform 0.2s ease}:host .mobile-dropdown-container .mobile-dropdown-button .mobile-arrow svg{transition:transform 0.2s ease}:host .mobile-dropdown-container .mobile-dropdown-button .mobile-arrow.rotated svg{transform:rotate(180deg)}:host .mobile-dropdown-container .mobile-dropdown{position:absolute;top:calc(100% - 4px);left:auto;right:auto;background:var(--color-white);border:1px solid var(--color-gray-02);border-radius:var(--ptc-border-radius-standard);box-shadow:var(--ptc-shadow-medium);z-index:1001;margin-top:4px;overflow-y:auto;min-width:280px;width:-moz-fit-content;width:fit-content;list-style:none;padding:0;margin:4px 0 0 0}:host .mobile-dropdown-container .mobile-dropdown li{display:block;border-bottom:1px solid var(--color-gray-01)}:host .mobile-dropdown-container .mobile-dropdown li:last-child{border-bottom:none}:host .mobile-dropdown-container .mobile-dropdown li .mobile-dropdown-item{width:100%;background:none;border:none;padding:12px 16px;color:var(--color-gray-07);text-decoration:none;font-size:var(--ptc-font-size-xx-small);font-weight:var(--ptc-font-weight-bold);line-height:var(--ptc-line-height-densest);text-align:left;cursor:pointer;transition:all 0.2s ease;word-break:break-word;display:block}:host .mobile-dropdown-container .mobile-dropdown li .mobile-dropdown-item:hover{background-color:var(--color-gray-01);color:var(--color-gray-10)}:host .mobile-dropdown-container .mobile-dropdown li .mobile-dropdown-item.active{background-color:var(--color-gray-01);color:var(--color-gray-10);border-left:3px solid var(--color-green-07)}:host .mobile-dropdown-container .mobile-dropdown li .mobile-dropdown-item:focus-visible{border-radius:var(--ptc-border-radius-standard);outline:5px solid var(--keyboard-nav-outline)}:host .subnav-menu-right{max-width:300px;padding:12px 0}@media only screen and (min-width: 768px){:host .subnav-menu-right{margin-left:48px;width:auto}}:host .subnav-menu-right ptc-button{max-width:300px}";
4
+
5
+ const PtcSubnavV2 = class {
6
+ constructor(hostRef) {
7
+ registerInstance(this, hostRef);
8
+ this.handleClickOutside = (event) => {
9
+ const target = event.target;
10
+ if (!this.el.contains(target)) {
11
+ this.showOverflowMenu = false;
12
+ }
13
+ };
14
+ this.handleKeyDown = (event) => {
15
+ // Handle Escape key to close dropdowns
16
+ if (event.key === "Escape" && this.showOverflowMenu) {
17
+ this.showOverflowMenu = false;
18
+ // Return focus to the button that opened the menu
19
+ if (this.overflowButton) {
20
+ this.overflowButton.focus();
21
+ }
22
+ }
23
+ };
24
+ this.handleScroll = () => {
25
+ // Throttle scroll events for better performance
26
+ if (this.scrollThrottleTimeout) {
27
+ return;
28
+ }
29
+ this.scrollThrottleTimeout = window.setTimeout(() => {
30
+ // Don't update active state if user just manually navigated
31
+ if (this.isManualNavigation) {
32
+ this.scrollThrottleTimeout = null;
33
+ return;
34
+ }
35
+ // Fallback scroll handler to ensure active state is updated
36
+ const navItems = this.getNavItems();
37
+ const subnavHeight = this.el.offsetHeight;
38
+ const scrollPosition = window.scrollY + subnavHeight + 100; // Offset for better detection
39
+ // Find the section that should be active based on scroll position
40
+ let activeSection = navItems[0].id; // Default to first section
41
+ for (let i = navItems.length - 1; i >= 0; i--) {
42
+ const section = document.getElementById(navItems[i].id);
43
+ if (section && section.offsetTop <= scrollPosition) {
44
+ activeSection = navItems[i].id;
45
+ break;
46
+ }
47
+ }
48
+ // Only update if different from current active
49
+ if (activeSection !== this.currentActive) {
50
+ this.currentActive = activeSection;
51
+ // Update mobile selected item if in mobile mode
52
+ if (this.isMobile) {
53
+ const activeItem = navItems.find((item) => item.id === activeSection);
54
+ if (activeItem) {
55
+ this.selectedMobileItem = activeItem;
56
+ }
57
+ }
58
+ }
59
+ this.scrollThrottleTimeout = null;
60
+ }, 16); // ~60fps throttling
61
+ };
62
+ this.handleResize = () => {
63
+ if (this.navContainer) {
64
+ // Add a small delay to ensure DOM has been updated
65
+ setTimeout(() => {
66
+ this.calculateVisibleItems();
67
+ }, 10);
68
+ }
69
+ };
70
+ this.setupIntersectionObserver = () => {
71
+ // Get all sections that correspond to our navigation items
72
+ const navItems = this.getNavItems();
73
+ // Create intersection observer
74
+ this.intersectionObserver = new IntersectionObserver((entries) => {
75
+ // Clear any existing timeout
76
+ if (this.scrollTimeout) {
77
+ clearTimeout(this.scrollTimeout);
78
+ }
79
+ // Debounce the intersection changes
80
+ this.scrollTimeout = window.setTimeout(() => {
81
+ // Don't update active state if user just manually navigated
82
+ if (this.isManualNavigation) {
83
+ return;
84
+ }
85
+ // Find all intersecting sections
86
+ const intersectingSections = entries.filter((entry) => entry.isIntersecting);
87
+ if (intersectingSections.length > 0) {
88
+ // Sort by intersection ratio (how much of the section is visible)
89
+ // and then by position (top to bottom)
90
+ intersectingSections.sort((a, b) => {
91
+ // First sort by intersection ratio (higher = more visible)
92
+ if (b.intersectionRatio !== a.intersectionRatio) {
93
+ return (b.intersectionRatio - a.intersectionRatio);
94
+ }
95
+ // If intersection ratios are equal, sort by position
96
+ return (a.boundingClientRect.top -
97
+ b.boundingClientRect.top);
98
+ });
99
+ // Get the most visible section
100
+ const mostVisibleSection = intersectingSections[0];
101
+ const sectionId = mostVisibleSection.target.id;
102
+ if (sectionId && sectionId !== this.currentActive) {
103
+ this.currentActive = sectionId;
104
+ // Update mobile selected item if in mobile mode
105
+ if (this.isMobile) {
106
+ const activeItem = navItems.find((item) => item.id === sectionId);
107
+ if (activeItem) {
108
+ this.selectedMobileItem = activeItem;
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }, 100); // Increased debounce time for better performance
114
+ }, {
115
+ root: null,
116
+ rootMargin: "-20% 0px -60% 0px",
117
+ threshold: [0, 0.1, 0.25, 0.5, 0.75, 1.0], // Multiple thresholds for better detection
118
+ });
119
+ // Observe all sections
120
+ navItems.forEach((item) => {
121
+ const section = document.getElementById(item.id);
122
+ if (section) {
123
+ this.intersectionObserver.observe(section);
124
+ }
125
+ });
126
+ };
127
+ this.extractNavItemsFromSlots = () => {
128
+ // Look for slot content with nav-items in the light DOM
129
+ const slotElement = this.el.querySelector('[slot="nav-items"]');
130
+ if (slotElement) {
131
+ const links = slotElement.querySelectorAll("a");
132
+ const items = Array.from(links)
133
+ .map((link) => {
134
+ var _a, _b;
135
+ return ({
136
+ id: ((_a = link.getAttribute("href")) === null || _a === void 0 ? void 0 : _a.substring(1)) || "",
137
+ label: ((_b = link.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || "",
138
+ title: link.getAttribute("title") || "",
139
+ trackerId: link.getAttribute("tracker-id") || "",
140
+ });
141
+ })
142
+ .filter((item) => item.id && item.label);
143
+ if (items.length > 0) {
144
+ return items;
145
+ }
146
+ }
147
+ return null;
148
+ };
149
+ this.getNavItems = () => {
150
+ // Extract navigation items from slots (SEO-friendly approach)
151
+ const slotItems = this.extractNavItemsFromSlots();
152
+ if (slotItems) {
153
+ return slotItems;
154
+ }
155
+ // If navItems prop is provided, parse and use it (fallback)
156
+ if (this.navItems && this.navItems.trim()) {
157
+ try {
158
+ const parsedItems = JSON.parse(this.navItems);
159
+ // Validate that it's an array with proper structure
160
+ if (Array.isArray(parsedItems) && parsedItems.length > 0) {
161
+ // Ensure each item has required properties
162
+ const validItems = parsedItems.filter((item) => item &&
163
+ typeof item.id === "string" &&
164
+ typeof item.label === "string");
165
+ if (validItems.length > 0) {
166
+ return validItems;
167
+ }
168
+ }
169
+ }
170
+ catch (error) {
171
+ console.warn("Invalid navItems JSON provided to ptc-subnav-v2:", error);
172
+ }
173
+ }
174
+ // Return empty array if no navigation items found
175
+ console.warn("No navigation items found in slots or props for ptc-subnav-v2");
176
+ return [];
177
+ };
178
+ this.calculateMobileDropdownItems = () => {
179
+ const navItems = this.getNavItems();
180
+ // Handle case where no navigation items are found
181
+ if (navItems.length === 0) {
182
+ this.mobileDropdownItems = [];
183
+ return;
184
+ }
185
+ const currentItem = this.selectedMobileItem || {
186
+ id: this.currentActive,
187
+ };
188
+ // Filter out the currently selected item from all nav items
189
+ this.mobileDropdownItems = navItems.filter((item) => item.id !== currentItem.id);
190
+ };
191
+ this.hasActiveOverflowItem = () => {
192
+ return this.overflowItems.some((item) => item.id === this.currentActive);
193
+ };
194
+ this.calculateVisibleItems = () => {
195
+ const navItems = this.getNavItems();
196
+ // Handle case where no navigation items are found
197
+ if (navItems.length === 0) {
198
+ this.visibleItems = [];
199
+ this.overflowItems = [];
200
+ this.selectedMobileItem = null;
201
+ return;
202
+ }
203
+ // Check if we're in mobile mode (below 767px)
204
+ const wasMobile = this.isMobile;
205
+ this.isMobile = window.innerWidth <= 767;
206
+ // Force re-render if mobile state changed
207
+ if (wasMobile !== this.isMobile) {
208
+ this.showOverflowMenu = false; // Close any open menus when switching modes
209
+ }
210
+ if (this.isMobile) {
211
+ // On mobile, show only the current active item
212
+ const activeItem = navItems.find((item) => item.id === this.currentActive) ||
213
+ navItems[0];
214
+ this.selectedMobileItem = activeItem;
215
+ this.visibleItems = [activeItem];
216
+ this.overflowItems = navItems.filter((item) => item.id !== activeItem.id);
217
+ }
218
+ else {
219
+ // Desktop behavior - calculate based on available width
220
+ const containerWidth = this.navContainer
221
+ ? this.navContainer.offsetWidth
222
+ : 0;
223
+ const buttonWidth = this.overflowButton
224
+ ? this.overflowButton.offsetWidth + 32
225
+ : 0; // 32px for gap
226
+ const availableWidth = containerWidth - buttonWidth - 48; // 48px for right margin
227
+ // Fallback if container width is not available yet
228
+ if (containerWidth === 0) {
229
+ this.visibleItems = navItems;
230
+ this.overflowItems = [];
231
+ return;
232
+ }
233
+ let visibleCount = 0;
234
+ let totalWidth = 0;
235
+ // Create temporary elements to measure width
236
+ const tempContainer = document.createElement("div");
237
+ tempContainer.style.position = "absolute";
238
+ tempContainer.style.visibility = "hidden";
239
+ tempContainer.style.whiteSpace = "nowrap";
240
+ tempContainer.style.fontSize = "14px";
241
+ tempContainer.style.fontWeight = "700";
242
+ tempContainer.style.padding = "20px 0 17px 0";
243
+ document.body.appendChild(tempContainer);
244
+ for (let i = 0; i < navItems.length; i++) {
245
+ const item = navItems[i];
246
+ tempContainer.textContent = item.label;
247
+ const itemWidth = tempContainer.offsetWidth + 32; // 32px for gap
248
+ if (totalWidth + itemWidth <= availableWidth) {
249
+ totalWidth += itemWidth;
250
+ visibleCount++;
251
+ }
252
+ else {
253
+ break;
254
+ }
255
+ }
256
+ document.body.removeChild(tempContainer);
257
+ this.visibleItems = navItems.slice(0, visibleCount);
258
+ this.overflowItems = navItems.slice(visibleCount);
259
+ }
260
+ // Don't automatically show overflow menu - it should be closed by default
261
+ // this.showOverflowMenu = this.overflowItems.length > 0;
262
+ };
263
+ this.toggleOverflowMenu = () => {
264
+ this.showOverflowMenu = !this.showOverflowMenu;
265
+ };
266
+ this.handleNavClick = (event, section) => {
267
+ event.preventDefault();
268
+ this.currentActive = section;
269
+ // Update mobile selected item if in mobile mode
270
+ if (this.isMobile) {
271
+ const navItems = this.getNavItems();
272
+ const activeItem = navItems.find((item) => item.id === section);
273
+ if (activeItem) {
274
+ this.selectedMobileItem = activeItem;
275
+ this.calculateMobileDropdownItems();
276
+ }
277
+ }
278
+ // Set manual navigation flag to prevent intersection observer from overriding
279
+ this.isManualNavigation = true;
280
+ // Clear any existing manual navigation timeout
281
+ if (this.manualNavigationTimeout) {
282
+ clearTimeout(this.manualNavigationTimeout);
283
+ }
284
+ // Reset manual navigation flag after scroll animation completes
285
+ this.manualNavigationTimeout = window.setTimeout(() => {
286
+ this.isManualNavigation = false;
287
+ }, 1500); // Give enough time for smooth scroll to complete
288
+ // Emit custom event for parent components
289
+ const customEvent = new CustomEvent("sectionChange", {
290
+ detail: { section },
291
+ bubbles: true,
292
+ composed: true,
293
+ });
294
+ this.el.dispatchEvent(customEvent);
295
+ // Smooth scroll to section if it exists
296
+ const targetElement = document.querySelector(`#${section}`);
297
+ if (targetElement) {
298
+ targetElement.scrollIntoView({
299
+ behavior: "smooth",
300
+ block: "start",
301
+ });
302
+ }
303
+ };
304
+ this.activeSection = "overview";
305
+ this.navItems = "";
306
+ this.currentActive = "overview";
307
+ this.visibleItems = [];
308
+ this.overflowItems = [];
309
+ this.showOverflowMenu = false;
310
+ this.containerWidth = 0;
311
+ this.isMobile = false;
312
+ this.selectedMobileItem = null;
313
+ this.isManualNavigation = false;
314
+ this.mobileDropdownItems = [];
315
+ }
316
+ componentWillLoad() {
317
+ this.currentActive = this.activeSection;
318
+ // Initialize selected mobile item with the current active section
319
+ const navItems = this.getNavItems();
320
+ if (navItems.length > 0) {
321
+ this.selectedMobileItem =
322
+ navItems.find((item) => item.id === this.activeSection) ||
323
+ navItems[0];
324
+ }
325
+ else {
326
+ this.selectedMobileItem = null;
327
+ }
328
+ this.calculateMobileDropdownItems();
329
+ }
330
+ componentDidLoad() {
331
+ // Bind the functions once
332
+ this.boundHandleResize = this.handleResize.bind(this);
333
+ this.boundHandleClickOutside = this.handleClickOutside.bind(this);
334
+ this.boundHandleScroll = this.handleScroll.bind(this);
335
+ this.boundHandleKeyDown = this.handleKeyDown.bind(this);
336
+ // Recalculate navigation items in case slots are used
337
+ this.calculateMobileDropdownItems();
338
+ this.handleResize();
339
+ window.addEventListener("resize", this.boundHandleResize);
340
+ document.addEventListener("click", this.boundHandleClickOutside);
341
+ document.addEventListener("keydown", this.boundHandleKeyDown);
342
+ // Setup intersection observer for scroll-based active state
343
+ this.setupIntersectionObserver();
344
+ // Add scroll listener as fallback
345
+ window.addEventListener("scroll", this.boundHandleScroll, {
346
+ passive: true,
347
+ });
348
+ }
349
+ disconnectedCallback() {
350
+ window.removeEventListener("resize", this.boundHandleResize);
351
+ document.removeEventListener("click", this.boundHandleClickOutside);
352
+ document.removeEventListener("keydown", this.boundHandleKeyDown);
353
+ window.removeEventListener("scroll", this.boundHandleScroll);
354
+ // Clean up intersection observer
355
+ if (this.intersectionObserver) {
356
+ this.intersectionObserver.disconnect();
357
+ }
358
+ // Clean up scroll timeout
359
+ if (this.scrollTimeout) {
360
+ clearTimeout(this.scrollTimeout);
361
+ }
362
+ // Clean up scroll throttle timeout
363
+ if (this.scrollThrottleTimeout) {
364
+ clearTimeout(this.scrollThrottleTimeout);
365
+ }
366
+ // Clean up manual navigation timeout
367
+ if (this.manualNavigationTimeout) {
368
+ clearTimeout(this.manualNavigationTimeout);
369
+ }
370
+ }
371
+ render() {
372
+ var _a, _b;
373
+ const navItems = this.getNavItems();
374
+ // If no navigation items, don't render the navigation
375
+ if (navItems.length === 0) {
376
+ return (h(Host, null, h("div", { class: "subnav-container" }, h("div", { class: "subnav-menu-right" }, h("slot", { name: "subnav-menu-right" })))));
377
+ }
378
+ return (h(Host, null, h("div", { class: "subnav-container" }, h("nav", { class: "subnav-menu-left", role: "navigation", "aria-label": "Sub navigation", ref: (el) => (this.navContainer = el) }, this.isMobile ? (
379
+ // Mobile layout - dropdown with arrows
380
+ h("div", { class: "mobile-dropdown-container" }, h("button", { class: "mobile-dropdown-button", onClick: this.toggleOverflowMenu, onKeyDown: (e) => {
381
+ if (e.key === "Enter" ||
382
+ e.key === " ") {
383
+ e.preventDefault();
384
+ this.toggleOverflowMenu();
385
+ }
386
+ }, "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) ||
387
+ "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
388
+ .currentActive ===
389
+ item.id
390
+ ? "active"
391
+ : ""}`, role: "menuitem", "aria-current": this
392
+ .currentActive ===
393
+ item.id
394
+ ? "page"
395
+ : undefined, "tracker-id": item.trackerId ||
396
+ `mobile-nav-${item.id}`, title: item.title || "", onClick: (e) => {
397
+ this.handleNavClick(e, item.id);
398
+ this.showOverflowMenu = false;
399
+ } }, item.label)))))))) : (
400
+ // Desktop layout - original behavior
401
+ 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
402
+ ? "active"
403
+ : "", title: item.title || "", onClick: (e) => this.handleNavClick(e, item.id), "aria-current": this.currentActive === item.id
404
+ ? "page"
405
+ : 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) => {
406
+ if (e.key === "Enter" ||
407
+ e.key === " ") {
408
+ e.preventDefault();
409
+ this.toggleOverflowMenu();
410
+ }
411
+ }, "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
412
+ .currentActive ===
413
+ item.id
414
+ ? "active"
415
+ : ""}`, title: item.title || "", "tracker-id": item.trackerId ||
416
+ `overflow-link-${item.id}`, role: "menuitem", onClick: (e) => {
417
+ this.handleNavClick(e, item.id);
418
+ this.showOverflowMenu = false;
419
+ }, "aria-current": this
420
+ .currentActive ===
421
+ item.id
422
+ ? "page"
423
+ : undefined }, item.label)))))))))), h("div", { class: "subnav-menu-right" }, h("slot", { name: "subnav-menu-right" })))));
424
+ }
425
+ get el() { return getElement(this); }
426
+ };
427
+ PtcSubnavV2.style = ptcSubnavV2Css;
428
+
429
+ export { PtcSubnavV2 as ptc_subnav_v2 };