@fynd-design-engineering/fynd-one-v2 1.1.0 → 2.0.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.
- package/dist/home/index.js.map +7 -0
- package/dist/navigation/announcement/index.js.map +7 -0
- package/dist/navigation/context-menu/index.js.map +7 -0
- package/dist/navigation/desktop/index.js.map +7 -0
- package/dist/navigation/mobile/index.js.map +7 -0
- package/dist/navigation/scroll/index.js +1 -1
- package/dist/navigation/scroll/index.js.map +7 -0
- package/dist/navigation/style.css.map +7 -0
- package/dist/test/sample.js.map +7 -0
- package/dist/tracking/page-categories.js +1 -0
- package/dist/tracking/page-categories.js.map +7 -0
- package/dist/tracking/user-journey.js +1 -0
- package/dist/tracking/user-journey.js.map +7 -0
- package/dist/tracking/utm-links.js +1 -0
- package/dist/tracking/utm-links.js.map +7 -0
- package/dist/utils/sample.js.map +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../bin/live-reload.js", "../../../src/navigation/mobile/index.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "// Types and interfaces\ninterface MenuState {\n isMainMenuOpen: boolean;\n isNestedMenuOpen: boolean;\n}\n\ninterface MenuElements {\n nestedMenu: HTMLElement;\n mainMenu: HTMLElement;\n toggleMainMenuButtons: NodeListOf<HTMLElement>;\n toggleNestedMenuButtons: NodeListOf<HTMLElement>;\n mainMenuLinks: NodeListOf<HTMLElement>;\n navOverlay: HTMLElement;\n openIcons: NodeListOf<HTMLElement>;\n closeIcons: NodeListOf<HTMLElement>;\n}\n\n// Constants\nconst ANIMATION_TIMINGS = {\n NESTED_MENU_DELAY: 10,\n NESTED_MENU_CLOSE_DELAY: 500,\n MAIN_MENU_CLOSE_TIMEOUT: 300, // Add timeout for main menu close\n} as const;\n\nconst SELECTORS = {\n NESTED_MENU: '[data-mobile-nav=\"nested-menu\"]',\n MAIN_MENU: '[data-mobile-nav=\"main-menu\"]',\n TOGGLE_MAIN_MENU: '[data-nav-toggle=\"main-menu\"]',\n TOGGLE_NESTED_MENU: '[data-nav-toggle=\"nested-menu\"]',\n MAIN_MENU_LINKS: '[data-mobile-link]',\n NAV_OVERLAY: '[data-nav-element=\"overlay\"]',\n OPEN_ICON: '[data-menu-icon=\"open\"]',\n CLOSE_ICON: '[data-menu-icon=\"close\"]',\n MOBILE_MENU: '[data-mobile-menu]',\n} as const;\n\n// Main navigation class\nclass MobileNavigation {\n private state: MenuState = {\n isMainMenuOpen: false,\n isNestedMenuOpen: false,\n };\n\n private isAnimating = false; // Add animation lock\n\n private elements: MenuElements;\n\n constructor() {\n this.elements = this.getElements();\n this.init();\n }\n\n private getElements(): MenuElements {\n const nestedMenu = document.querySelector<HTMLElement>(SELECTORS.NESTED_MENU);\n const mainMenu = document.querySelector<HTMLElement>(SELECTORS.MAIN_MENU);\n const navOverlay = document.querySelector<HTMLElement>(SELECTORS.NAV_OVERLAY);\n const openIcons = document.querySelectorAll<HTMLElement>(SELECTORS.OPEN_ICON);\n const closeIcons = document.querySelectorAll<HTMLElement>(SELECTORS.CLOSE_ICON);\n\n if (!nestedMenu || !mainMenu || !navOverlay || openIcons.length === 0 || closeIcons.length === 0) {\n throw new Error('Required navigation elements not found');\n }\n\n return {\n nestedMenu,\n mainMenu,\n toggleMainMenuButtons: document.querySelectorAll<HTMLElement>(SELECTORS.TOGGLE_MAIN_MENU),\n toggleNestedMenuButtons: document.querySelectorAll<HTMLElement>(SELECTORS.TOGGLE_NESTED_MENU),\n mainMenuLinks: document.querySelectorAll<HTMLElement>(SELECTORS.MAIN_MENU_LINKS),\n navOverlay,\n openIcons,\n closeIcons,\n };\n }\n\n private init(): void {\n this.setupInitialStyles();\n this.bindEventListeners();\n }\n\n private setupInitialStyles(): void {\n // Setup nested menu initial styles\n this.elements.nestedMenu.style.display = 'none';\n this.elements.nestedMenu.style.transform = 'translateX(100%)';\n this.elements.nestedMenu.style.transition = 'transform 0.5s ease';\n\n // Setup main menu initial styles\n this.elements.mainMenu.style.display = 'block';\n this.elements.mainMenu.style.height = '0dvh';\n this.elements.mainMenu.style.transition = 'height 0.3s ease-in-out';\n\n // Setup icon initial styles for all icons\n this.elements.openIcons.forEach(icon => {\n icon.style.transition = 'opacity 0.2s ease';\n });\n \n this.elements.closeIcons.forEach(icon => {\n icon.style.transition = 'opacity 0.2s ease';\n });\n \n this.updateMenuIcons(false); // Start with open icons visible\n }\n\n private bindEventListeners(): void {\n // Main menu toggle buttons\n this.elements.toggleMainMenuButtons.forEach((button, index) => {\n button.addEventListener('click', (e) => {\n e.preventDefault();\n console.log(`Main menu button ${index} clicked, current state:`, this.state.isMainMenuOpen);\n this.handleMainMenuToggle(button);\n });\n });\n\n // Nested menu toggle buttons\n this.elements.toggleNestedMenuButtons.forEach((button, index) => {\n button.addEventListener('click', (e) => {\n e.preventDefault();\n console.log(`Nested menu button ${index} clicked, current state:`, this.state.isNestedMenuOpen);\n this.handleNestedMenuToggle(button);\n });\n });\n\n // Main menu links\n this.elements.mainMenuLinks.forEach((link) => {\n link.addEventListener('click', (event) => {\n const target = event.currentTarget as HTMLElement;\n const attrValue = target.getAttribute('data-mobile-link');\n \n if (attrValue) {\n console.log(`Menu link clicked: ${attrValue}`);\n this.replaceContent(attrValue);\n this.toggleNestedMenu();\n }\n });\n });\n }\n\n private openMainMenu(): void {\n if (this.state.isMainMenuOpen) {\n console.log('Main menu already open, skipping');\n return;\n }\n\n const { mainMenu } = this.elements;\n \n this.isAnimating = true;\n mainMenu.style.overflow = 'hidden';\n mainMenu.style.display = 'block';\n mainMenu.style.height = '0dvh';\n\n // Update state and icons immediately\n this.state.isMainMenuOpen = true;\n this.updateMenuIcons(true);\n\n requestAnimationFrame(() => {\n mainMenu.style.height = '100dvh';\n \n // Listen for animation completion\n const handleOpenComplete = () => {\n this.isAnimating = false;\n console.log('\uD83C\uDF54 Main menu OPENED (animation complete)');\n };\n\n mainMenu.addEventListener('transitionend', handleOpenComplete, { once: true });\n \n // Fallback timeout\n setTimeout(() => {\n this.isAnimating = false;\n }, 350); // Slightly longer than transition time\n });\n\n console.log('\uD83C\uDF54 Main menu OPENING...');\n }\n\n private closeMainMenu(): void {\n if (!this.state.isMainMenuOpen) {\n console.log('Main menu already closed, skipping');\n return;\n }\n\n const { mainMenu } = this.elements;\n \n this.isAnimating = true;\n \n // Update state and icons immediately\n this.state.isMainMenuOpen = false;\n this.updateMenuIcons(false);\n \n mainMenu.style.height = '0dvh';\n\n // Use both transitionend and setTimeout as fallback\n let animationCompleted = false;\n \n const completeClose = () => {\n if (animationCompleted) return;\n animationCompleted = true;\n \n mainMenu.style.display = 'none';\n this.isAnimating = false;\n console.log('\uD83C\uDF54 Main menu CLOSED (animation complete)');\n };\n\n // Primary method: listen for transition end\n const handleTransitionEnd = (e: TransitionEvent) => {\n if (e.target === mainMenu && e.propertyName === 'height') {\n completeClose();\n }\n };\n\n mainMenu.addEventListener('transitionend', handleTransitionEnd, { once: true });\n\n // Fallback method: timeout\n setTimeout(() => {\n completeClose();\n }, ANIMATION_TIMINGS.MAIN_MENU_CLOSE_TIMEOUT);\n\n console.log('\uD83C\uDF54 Main menu CLOSING...');\n }\n\n private handleMainMenuToggle(clickedButton: HTMLElement): void {\n console.log('Handling main menu toggle. Current state:', this.state.isMainMenuOpen, 'Is animating:', this.isAnimating);\n \n // Prevent multiple rapid clicks during animation\n if (this.isAnimating) {\n console.log('Animation in progress, ignoring click');\n return;\n }\n \n // Always toggle based on current state, regardless of which button was clicked\n if (this.state.isMainMenuOpen) {\n this.closeMainMenu();\n if (this.state.isNestedMenuOpen) {\n this.closeNestedMenu();\n }\n } else {\n this.openMainMenu();\n }\n }\n\n private handleNestedMenuToggle(clickedButton: HTMLElement): void {\n console.log('Handling nested menu toggle. Current state:', this.state.isNestedMenuOpen, 'Is animating:', this.isAnimating);\n \n // Prevent multiple rapid clicks during animation\n if (this.isAnimating) {\n console.log('Animation in progress, ignoring click');\n return;\n }\n \n // Always toggle based on current state, regardless of which button was clicked\n if (this.state.isNestedMenuOpen) {\n this.closeNestedMenu();\n } else {\n this.openNestedMenu();\n }\n }\n\n private toggleMainMenu(): void {\n console.log('Toggling main menu. Current state:', this.state.isMainMenuOpen);\n \n if (this.state.isMainMenuOpen) {\n this.closeMainMenu();\n if (this.state.isNestedMenuOpen) {\n this.closeNestedMenu();\n }\n } else {\n this.openMainMenu();\n }\n }\n\n private openNestedMenu(): void {\n if (this.state.isNestedMenuOpen) {\n console.log('Nested menu already open, skipping');\n return;\n }\n\n const { nestedMenu, navOverlay } = this.elements;\n \n nestedMenu.style.display = 'block';\n navOverlay.style.opacity = '1';\n \n setTimeout(() => {\n nestedMenu.style.transform = 'translateX(0%)';\n }, ANIMATION_TIMINGS.NESTED_MENU_DELAY);\n\n this.state.isNestedMenuOpen = true;\n console.log('\uD83D\uDCC2 Nested menu OPENED');\n }\n\n private closeNestedMenu(): void {\n if (!this.state.isNestedMenuOpen) {\n console.log('Nested menu already closed, skipping');\n return;\n }\n\n const { nestedMenu, navOverlay } = this.elements;\n \n nestedMenu.style.transform = 'translateX(100%)';\n navOverlay.style.opacity = '0';\n this.state.isNestedMenuOpen = false;\n \n setTimeout(() => {\n nestedMenu.style.display = 'none';\n console.log('\uD83D\uDCC2 Nested menu CLOSED (animation complete)');\n }, ANIMATION_TIMINGS.NESTED_MENU_CLOSE_DELAY);\n\n console.log('\uD83D\uDCC2 Nested menu closing...');\n }\n\n private toggleNestedMenu(): void {\n console.log('Toggling nested menu. Current state:', this.state.isNestedMenuOpen);\n \n if (this.state.isNestedMenuOpen) {\n this.closeNestedMenu();\n } else {\n this.openNestedMenu();\n }\n }\n\n private updateMenuIcons(isOpen: boolean): void {\n const { openIcons, closeIcons } = this.elements;\n \n console.log('Updating menu icons. isOpen:', isOpen);\n \n if (isOpen) {\n openIcons.forEach(icon => {\n icon.style.opacity = '0';\n });\n closeIcons.forEach(icon => {\n icon.style.opacity = '1';\n });\n } else {\n openIcons.forEach(icon => {\n icon.style.opacity = '1';\n });\n closeIcons.forEach(icon => {\n icon.style.opacity = '0';\n });\n }\n }\n\n private replaceContent(attrValue: string): void {\n // Hide all mobile menu content\n document.querySelectorAll<HTMLElement>(SELECTORS.MOBILE_MENU).forEach((div) => {\n div.style.display = 'none';\n });\n\n // Show target content\n const targetDiv = document.querySelector<HTMLElement>(`[data-mobile-menu=\"${attrValue}\"]`);\n if (targetDiv) {\n targetDiv.style.display = 'block';\n console.log(`\uD83D\uDCC4 Content switched to: ${attrValue}`);\n } else {\n console.warn(`Content element with data-mobile-menu=\"${attrValue}\" not found`);\n }\n }\n\n // Public methods for external access if needed\n public getState(): Readonly<MenuState> {\n return { ...this.state };\n }\n\n public closeAllMenus(): void {\n if (this.state.isMainMenuOpen) {\n this.closeMainMenu();\n }\n if (this.state.isNestedMenuOpen) {\n this.closeNestedMenu();\n }\n }\n}\n\n// Initialize navigation when DOM is ready\ndocument.addEventListener('DOMContentLoaded', () => {\n try {\n new MobileNavigation();\n } catch (error) {\n console.error('Failed to initialize mobile navigation:', error);\n }\n});\n\n// Export for potential use in other modules\nexport { MobileNavigation };"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";(()=>{var
|
|
1
|
+
"use strict";(()=>{var e=document.querySelector("[navigation-scrolled]"),n=document.querySelectorAll("[navigation-scrolled-menu]");function o(){let t=window.scrollY||document.documentElement.scrollTop;if(!e){console.warn("Navigation element not found");return}e.setAttribute("navigation-scrolled",t>350?"true":"false"),n&&n.forEach(i=>{i.setAttribute("navigation-scrolled-menu",t>350?"true":"false")})}e.setAttribute("navigation-scrolled","true");document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>{o()},100)});window.addEventListener("scroll",o);})();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../bin/live-reload.js", "../../../src/navigation/scroll/index.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "const navigationDiv = document.querySelector('[navigation-scrolled]') as HTMLElement;\nconst mobileNavigationMenus = document.querySelectorAll('[navigation-scrolled-menu]') as NodeListOf<HTMLElement>;\n\nfunction setNavigationScrolled(): void {\n const scrollTop = window.scrollY || document.documentElement.scrollTop;\n if (!navigationDiv) {\n console.warn('Navigation element not found');\n return;\n }\n navigationDiv.setAttribute('navigation-scrolled', scrollTop > 350 ? 'true' : 'false');\n\n if (mobileNavigationMenus) {\n mobileNavigationMenus.forEach((menu) => {\n menu.setAttribute('navigation-scrolled-menu', scrollTop > 350 ? 'true' : 'false');\n });\n }\n // console.log(scrollTop)\n}\n\nnavigationDiv.setAttribute('navigation-scrolled', 'true');\n\ndocument.addEventListener('DOMContentLoaded', () => {\n setTimeout(() => {\n setNavigationScrolled();\n }, 100);\n});\n\n// Handle scroll events\nwindow.addEventListener('scroll', setNavigationScrolled);"],
|
|
5
|
+
"mappings": ";;;AACA,MACE,OAAO,SAAS,aAAa,eAC7B,OAAO,SAAS,aAAa,aAC7B;AACA,QAAI,YAAY,GAAG,uBAAY,UAAU,EAAE;AAAA,MAAiB;AAAA,MAAU,MACpE,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,gDAAgD;AAAA,EAC9D;;;ACVA,MAAM,gBAAgB,SAAS,cAAc,uBAAuB;AACpE,MAAM,wBAAwB,SAAS,iBAAiB,4BAA4B;AAEpF,WAAS,wBAA8B;AACnC,UAAM,YAAY,OAAO,WAAW,SAAS,gBAAgB;AAC7D,QAAI,CAAC,eAAe;AAChB,cAAQ,KAAK,8BAA8B;AAC3C;AAAA,IACJ;AACA,kBAAc,aAAa,uBAAuB,YAAY,MAAM,SAAS,OAAO;AAEpF,QAAI,uBAAuB;AACvB,4BAAsB,QAAQ,CAAC,SAAS;AACpC,aAAK,aAAa,4BAA4B,YAAY,MAAM,SAAS,OAAO;AAAA,MACpF,CAAC;AAAA,IACL;AAAA,EAEJ;AAEA,gBAAc,aAAa,uBAAuB,MAAM;AAExD,WAAS,iBAAiB,oBAAoB,MAAM;AAChD,eAAW,MAAM;AACb,4BAAsB;AAAA,IAC1B,GAAG,GAAG;AAAA,EACV,CAAC;AAGD,SAAO,iBAAiB,UAAU,qBAAqB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/navigation/style.css"],
|
|
4
|
+
"sourcesContent": ["[data-tab-link-active=\"true\"] {\n border-right-color: #404040;\n background-color: #f8f8f9;\n opacity: 1;\n}\n\n\n\n[data-tab-content-active] {\n display: none;\n}\n\n[data-tab-content-active=\"true\"] {\n display: block;\n}\n\n[data-tab-content-active=\"false\"] {\n display: none;\n}\n\n[data-nav-element=\"mover\"] {\n height: 0;\n overflow: hidden;\n}\n\n[data-nav-element=\"overlay\"] {\n opacity: 0;\n display: none;\n}\n\n[data-nav-element=\"wrapper\"] {\n top: 100px;\n}\n[data-nav-toggle=\"main-menu\"]{\nz-index: 10 !important; /* z-index: 999; if we need to show in nested menu too */\n \n \n}\n\n[data-mobile-nav=\"main-menu\"] {\n z-index: 999; /* z-index: 999; if we need to show in nested menu too */\n}\n\n[data-nav-element=\"mover\"] {\n border-radius: 0px 0px 12px 12px;\n box-shadow: rgba(0, 0, 0, 0.03) 0px 12px 16px 6px;\n}\n\n[data-dropdown-item] {\n width: 100%;\n}\n\n[data-dropdown-item=\"resources\"] {\n width: 100%;\n}\n\n[data-dropdown-item=\"company\"] {\n width: 100%;\n}\n\n[data-desktop-content] {\n display: none;\n}\n\n@media (max-width: 992px) {\n [data-desktop-content] {\n display: block;\n }\n}\n\n/* announcement bar */\n\n.announcement-pagination.swiper-pagination-clickable.swiper-pagination-bullets.swiper-pagination-horizontal {\n display: none;\n flex-direction: column;\n height: 100%;\n bottom: 0px;\n justify-content: center;\n gap: 4px;\n padding-left: 20px;\n padding-right: 20px;\n}\n\nspan.swiper-pagination-bullet {\n width: 6px;\n height: 6px;\n background: rgba(255, 255, 255, 0.80);\n pointer-events: auto;\n}\n\nspan.swiper-pagination-bullet.swiper-pagination-bullet-active {\n background: white;\n}\n\n@media screen and (max-width: 1024px) {\n .announcement-pagination.swiper-pagination-clickable.swiper-pagination-bullets.swiper-pagination-horizontal {\n left: -16px;\n }\n}\n\n\n/* navigation scrolled up */\n[navigation-scrolled=\"true\"] {\n transform: translateY(-32px);\n box-shadow: rgba(0, 0, 0, 0.03) 0px 12px 16px 10px;\n}\n[navigation-scrolled-menu=\"false\"] {\n top: 0px;\n }\n\n[navigation-scrolled=\"false\"] {\n transform: translateY(0);\n}\n\n@media screen and (max-width: 991px) {\n [navigation-scrolled=\"true\"] {\n transform: translateY(-50px);\n }\n\n [navigation-scrolled-menu=\"true\"] {\n top: 46px;\n }\n}"],
|
|
5
|
+
"mappings": ";AAAA,CAAC;AACC,sBAAoB;AACpB,oBAAkB;AAClB,WAAS;AACX;AAIA,CAAC;AACC,WAAS;AACX;AAEA,CAAC;AACC,WAAS;AACX;AAEA,CAAC;AACC,WAAS;AACX;AAEA,CAAC;AACC,UAAQ;AACR,YAAU;AACZ;AAEA,CAAC;AACC,WAAS;AACT,WAAS;AACX;AAEA,CAAC;AACC,OAAK;AACP;AACA,CAAC;AACD,WAAS;AAGT;AAEA,CAAC;AACC,WAAS;AACX;AAEA,CAAC;AACC,iBAAe,IAAI,IAAI,KAAK;AAC5B,cAAY,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,IAAI,KAAK,KAAK;AAChD;AAEA,CAAC;AACC,SAAO;AACT;AAEA,CAAC;AACC,SAAO;AACT;AAEA,CAAC;AACC,SAAO;AACT;AAEA,CAAC;AACC,WAAS;AACX;AAEA,OAAO,CAAC,SAAS,EAAE;AACjB,GAAC;AACC,aAAS;AACX;AACF;AAIA,CAAC,uBAAuB,CAAC,2BAA2B,CAAC,yBAAyB,CAAC;AAC7E,WAAS;AACT,kBAAgB;AAChB,UAAQ;AACR,UAAQ;AACR,mBAAiB;AACjB,OAAK;AACL,gBAAc;AACd,iBAAe;AACjB;AAEA,IAAI,CAAC;AACH,SAAO;AACP,UAAQ;AACR,cAAY,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAChC,kBAAgB;AAClB;AAEA,IAAI,CAPC,wBAOwB,CAAC;AAC5B,cAAY;AACd;AAEA,OAAO,OAAO,IAAI,CAAC,SAAS,EAAE;AAC5B,GAvBD,uBAuByB,CAvBD,2BAuB6B,CAvBD,yBAuB2B,CAvBD;AAwB3E,UAAM;AACR;AACF;AAIA,CAAC;AACC,aAAW,WAAW;AACrB,cAAY,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,IAAI,KAAK,KAAK;AACjD;AACA,CAAC;AACG,OAAK;AACP;AAEF,CAAC;AACC,aAAW,WAAW;AACxB;AAEA,OAAO,OAAO,IAAI,CAAC,SAAS,EAAE;AAC5B,GAAC;AACC,eAAW,WAAW;AACxB;AAEA,GAAC;AACC,SAAK;AACP;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../bin/live-reload.js", "../../src/test/sample.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "console.log('script is running always');"],
|
|
5
|
+
"mappings": ";;;AACA,MACE,OAAO,SAAS,aAAa,eAC7B,OAAO,SAAS,aAAa,aAC7B;AACA,QAAI,YAAY,GAAG,uBAAY,UAAU,EAAE;AAAA,MAAiB;AAAA,MAAU,MACpE,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,gDAAgD;AAAA,EAC9D;;;ACVA,UAAQ,IAAI,0BAA0B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>{let t=document.querySelectorAll('[data-page-category="true"]');window.pageCategories=Array.from(t).map(e=>e.textContent?.trim()||"").filter(e=>e.length>0)},100)});})();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../bin/live-reload.js", "../../src/tracking/page-categories.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "document.addEventListener('DOMContentLoaded', () => {\n setTimeout(() => {\n const categoryDivs: NodeListOf<HTMLDivElement> = document.querySelectorAll('[data-page-category=\"true\"]');\n (window as any).pageCategories = Array.from(categoryDivs)\n .map((div: HTMLDivElement) => div.textContent?.trim() || '')\n .filter((text: string) => text.length > 0);\n }, 100);\n});"],
|
|
5
|
+
"mappings": ";;;AACA,MACE,OAAO,SAAS,aAAa,eAC7B,OAAO,SAAS,aAAa,aAC7B;AACA,QAAI,YAAY,GAAG,uBAAY,UAAU,EAAE;AAAA,MAAiB;AAAA,MAAU,MACpE,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,gDAAgD;AAAA,EAC9D;;;ACVA,WAAS,iBAAiB,oBAAoB,MAAM;AAChD,eAAW,MAAM;AACb,YAAM,eAA2C,SAAS,iBAAiB,6BAA6B;AACxG,MAAC,OAAe,iBAAiB,MAAM,KAAK,YAAY,EACnD,IAAI,CAAC,QAAwB,IAAI,aAAa,KAAK,KAAK,EAAE,EAC1D,OAAO,CAAC,SAAiB,KAAK,SAAS,CAAC;AAAA,IACjD,GAAG,GAAG;AAAA,EACV,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{async function c(){let t="userJourney";function i(){let e=navigator.userAgent;return/tablet|ipad|playbook|silk/i.test(e)?"tablet":/mobile|iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(e)?"mobile":"desktop"}function l(){let e=navigator.userAgent;return e.includes("Chrome")&&!e.includes("Edg")?"Chrome":e.includes("Firefox")?"Firefox":e.includes("Safari")&&!e.includes("Chrome")?"Safari":e.includes("Edg")?"Edge":e.includes("Opera")?"Opera":"Unknown"}function y(e){if(!e)return"Unknown";try{let s=new URL(e).hostname.replace(/^www\./,""),a=s.split(".");return a.length>=2?a[0]:s||"Unknown"}catch{return"Unknown"}}function d(e,r){let o=new URLSearchParams(window.location.search),s=o.has("utm_source")||o.has("utm_medium")||o.has("utm_campaign");return e||s?s?{source:o.get("utm_source")||"",medium:o.get("utm_medium")||"",campaign:o.get("utm_campaign")||""}:{source:y(document.referrer),medium:"organic",campaign:"unknown"}:r||{source:"Unknown",medium:"organic",campaign:"unknown"}}function p(){try{return typeof window.pageCategories<"u"&&Array.isArray(window.pageCategories)&&window.pageCategories.length>0?window.pageCategories:["Not applicable"]}catch(e){return console.warn("Error accessing pageCategories:",e),["Not applicable"]}}function f(){let e=new URLSearchParams(window.location.search);return e.has("utm_source")||e.has("utm_medium")||e.has("utm_campaign")}function h(e){let r=e.split("?")[0].toLowerCase(),o={exactMatches:{"/":"Home","/home":"Home","/blog":"Blog listing","/about-us":"About us","/contact-us":"Contact","/privacy-policy":"Privacy policy","/terms-of-service":"Terms of service","/careers":"Careers","/customer-stories":"Customer stories listing","/events":"Events listing","/infographics":"Infographics listing","/newsroom":"Newsroom","/releases":"Releases listing"},pathStartsWith:[{pattern:"/blog/",type:"Blog"},{pattern:"/customer-stories/",type:"Customer story"},{pattern:"/case-studies/",type:"Case study"},{pattern:"/solutions/",type:"Solution"},{pattern:"/events/",type:"Event"},{pattern:"/news/",type:"News"},{pattern:"/press-releases/",type:"Press release"},{pattern:"/releases/",type:"Release"}]};if(o.exactMatches[r])return o.exactMatches[r];for(let s of o.pathStartsWith)if(r.startsWith(s.pattern))return s.type;return"Other"}function w(e){if(!e.userJourney||e.userJourney.length===0)return!1;let r=new Date(e.userJourney[e.userJourney.length-1].time);return new Date().getTime()-r.getTime()<18e5}return new Promise(e=>{setTimeout(()=>{try{let r=null,o=sessionStorage.getItem(t);if(o){let u=JSON.parse(o);w(u)&&(r=u)}r||(r={userJourney:[],origin:window.location.hostname,deviceCategory:i(),browser:l()});let s=window.location.pathname,a=new Date().toISOString(),m=r.userJourney[r.userJourney.length-1];if(m&&m.page===s)m.time=a;else{let u=r.userJourney.length===0,J=u?void 0:r.userJourney[0].utm,P={touchPoint:r.userJourney.length+1,page:s,title:document.title||"Untitled",type:h(s),category:p(),time:a,utmVisibility:f()?"visible":"hidden",utm:d(u,J)};r.userJourney.push(P)}sessionStorage.setItem(t,JSON.stringify(r)),e(r)}catch(r){console.error("Error tracking user journey:",r),e(null)}},200)})}function g(){try{let t=sessionStorage.getItem("userJourney");return t?JSON.parse(t):null}catch(t){return console.error("Error getting user journey:",t),null}}function b(){sessionStorage.removeItem("userJourney")}function U(t){try{let n=g();if(!n||n.userJourney.length===0)return!1;let i=n.userJourney[n.userJourney.length-1];return i.category=t.length>0?t:["Not applicable"],sessionStorage.setItem("userJourney",JSON.stringify(n)),!0}catch(n){return console.error("Error updating page categories:",n),!1}}function S(t){try{let n=g();if(!n||n.userJourney.length===0)return!1;let i=n.userJourney[n.userJourney.length-1];return i.type=t,sessionStorage.setItem("userJourney",JSON.stringify(n)),!0}catch(n){return console.error("Error updating page type:",n),!1}}function T(){let t=g();if(!t||t.userJourney.length===0)return null;let n=t.userJourney[0],i=t.userJourney[t.userJourney.length-1],l=new Date(i.time).getTime()-new Date(n.time).getTime();return{totalPages:t.userJourney.length,sessionDuration:Math.floor(l/1e3),firstPage:n.page,lastPage:i.page}}document.addEventListener("DOMContentLoaded",()=>{c()});document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{c()}):c();window.trackUserJourney=c;window.getUserJourney=g;window.clearUserJourney=b;window.updatePageType=S;window.updatePageCategories=U;window.getJourneyStats=T;})();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../bin/live-reload.js", "../../src/tracking/user-journey.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "export { };\n\n// Type definitions\ninterface UTMParameters {\n source: string;\n medium: string;\n campaign: string;\n}\n\ninterface TouchPoint {\n touchPoint: number;\n page: string;\n title: string;\n type: string;\n category: string[];\n time: string;\n utmVisibility: 'visible' | 'hidden';\n utm: UTMParameters;\n}\n\ninterface UserJourney {\n userJourney: TouchPoint[];\n origin: string;\n deviceCategory: 'desktop' | 'mobile' | 'tablet';\n browser: string;\n}\n\ntype DeviceCategory = 'desktop' | 'mobile' | 'tablet';\ntype UTMVisibility = 'visible' | 'hidden';\n\nasync function trackUserJourney(): Promise<UserJourney | null> {\n const STORAGE_KEY: string = 'userJourney';\n const SESSION_TIMEOUT: number = 30 * 60 * 1000; // 30 minutes\n\n // Helper function to get device category\n function getDeviceCategory(): DeviceCategory {\n const userAgent: string = navigator.userAgent;\n if (/tablet|ipad|playbook|silk/i.test(userAgent)) return 'tablet';\n if (/mobile|iphone|ipod|android|blackberry|opera|mini|windows\\sce|palm|smartphone|iemobile/i.test(userAgent)) return 'mobile';\n return 'desktop';\n }\n\n // Helper function to get browser\n function getBrowser(): string {\n const userAgent: string = navigator.userAgent;\n if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) return 'Chrome';\n if (userAgent.includes('Firefox')) return 'Firefox';\n if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) return 'Safari';\n if (userAgent.includes('Edg')) return 'Edge';\n if (userAgent.includes('Opera')) return 'Opera';\n return 'Unknown';\n }\n\n // Helper function to extract domain from referrer\n function extractDomainFromReferrer(referrer: string): string {\n if (!referrer) return 'Unknown';\n\n try {\n const url = new URL(referrer);\n const hostname = url.hostname;\n\n // Remove www. prefix if present\n const domain = hostname.replace(/^www\\./, '');\n\n // Extract the main domain name (remove TLD)\n const domainParts = domain.split('.');\n if (domainParts.length >= 2) {\n return domainParts[0];\n }\n\n return domain || 'Unknown';\n } catch (error) {\n return 'Unknown';\n }\n }\n\n // Helper function to get UTM parameters\n function getUTMParameters(isFirstVisit: boolean, firstVisitUTM?: UTMParameters): UTMParameters {\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n const hasCurrentUTM: boolean = urlParams.has('utm_source') || urlParams.has('utm_medium') || urlParams.has('utm_campaign');\n\n if (isFirstVisit || hasCurrentUTM) {\n // If UTM parameters are present in URL, use them\n if (hasCurrentUTM) {\n return {\n source: urlParams.get('utm_source') || '',\n medium: urlParams.get('utm_medium') || '',\n campaign: urlParams.get('utm_campaign') || ''\n };\n } else {\n // No UTM parameters in URL, use referrer-based defaults\n const referrerDomain = extractDomainFromReferrer(document.referrer);\n return {\n source: referrerDomain,\n medium: 'organic',\n campaign: 'unknown'\n };\n }\n } else {\n // Inherit from first visit\n return firstVisitUTM || {\n source: 'Unknown',\n medium: 'organic',\n campaign: 'unknown'\n };\n }\n }\n\n // Helper function to get page categories from global variable\n function getPageCategories(): string[] {\n try {\n // Check if global pageCategories variable exists and is an array\n if (typeof (window as any).pageCategories !== 'undefined' &&\n Array.isArray((window as any).pageCategories) &&\n (window as any).pageCategories.length > 0) {\n return (window as any).pageCategories;\n }\n\n // Return default if not available or empty\n return ['Not applicable'];\n } catch (error) {\n console.warn('Error accessing pageCategories:', error);\n return ['Not applicable'];\n }\n }\n function hasVisibleUTM(): boolean {\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n return urlParams.has('utm_source') || urlParams.has('utm_medium') || urlParams.has('utm_campaign');\n }\n\n // Helper function to get page type (customize as needed)\n function getPageType(url: string): string {\n const path: string = url.split('?')[0].toLowerCase();\n\n // Type configuration - easy to maintain and extend\n const typeConfig = {\n // Exact path matches (highest priority)\n exactMatches: {\n '/': 'Home',\n '/home': 'Home',\n '/blog': 'Blog listing',\n '/about-us': 'About us',\n '/contact-us': 'Contact',\n '/privacy-policy': 'Privacy policy',\n '/terms-of-service': 'Terms of service',\n '/careers': 'Careers',\n '/customer-stories': 'Customer stories listing',\n '/events': 'Events listing',\n '/infographics': 'Infographics listing',\n '/newsroom': 'Newsroom',\n '/releases': 'Releases listing',\n } as Record<string, string>,\n\n // Path pattern matches\n // These will match if the path starts with the pattern\n pathStartsWith: [\n { pattern: '/blog/', type: 'Blog' },\n { pattern: '/customer-stories/', type: 'Customer story' },\n { pattern: '/case-studies/', type: 'Case study' },\n { pattern: '/solutions/', type: 'Solution' },\n { pattern: '/events/', type: 'Event' },\n { pattern: '/news/', type: 'News' },\n { pattern: '/press-releases/', type: 'Press release' },\n { pattern: '/releases/', type: 'Release' },\n ]\n };\n\n // 1. Check exact matches first\n if (typeConfig.exactMatches[path]) {\n return typeConfig.exactMatches[path];\n }\n\n // 2. Check path starts with patterns\n for (const item of typeConfig.pathStartsWith) {\n if (path.startsWith(item.pattern)) {\n return item.type;\n }\n }\n\n // 3. Default fallback\n return 'Other';\n }\n\n // Check if session is still valid\n function isValidSession(journey: UserJourney): boolean {\n if (!journey.userJourney || journey.userJourney.length === 0) return false;\n\n const lastVisit: Date = new Date(journey.userJourney[journey.userJourney.length - 1].time);\n const now: Date = new Date();\n\n return (now.getTime() - lastVisit.getTime()) < SESSION_TIMEOUT;\n }\n\n // Add 200ms delay before executing the main logic\n return new Promise((resolve) => {\n setTimeout(() => {\n try {\n // Get existing journey from sessionStorage\n let journey: UserJourney | null = null;\n const storedData: string | null = sessionStorage.getItem(STORAGE_KEY);\n\n if (storedData) {\n const parsedData: UserJourney = JSON.parse(storedData);\n\n // Check if session is still valid\n if (isValidSession(parsedData)) {\n journey = parsedData;\n }\n }\n\n // Initialize new journey if none exists or session expired\n if (!journey) {\n journey = {\n userJourney: [],\n origin: window.location.hostname,\n deviceCategory: getDeviceCategory(),\n browser: getBrowser()\n };\n }\n\n // Get current page info\n const currentUrl: string = window.location.pathname;\n const currentTime: string = new Date().toISOString();\n\n // Check if this is the same page as the last visit (avoid duplicates)\n const lastVisit: TouchPoint | undefined = journey.userJourney[journey.userJourney.length - 1];\n if (lastVisit && lastVisit.page === currentUrl) {\n // Same page, just update the time\n lastVisit.time = currentTime;\n } else {\n // New page visit\n const isFirstVisit: boolean = journey.userJourney.length === 0;\n const firstVisitUTM: UTMParameters | undefined = isFirstVisit ? undefined : journey.userJourney[0].utm;\n\n const touchPoint: TouchPoint = {\n touchPoint: journey.userJourney.length + 1,\n page: currentUrl,\n title: document.title || 'Untitled',\n type: getPageType(currentUrl),\n category: getPageCategories(),\n time: currentTime,\n utmVisibility: hasVisibleUTM() ? 'visible' : 'hidden',\n utm: getUTMParameters(isFirstVisit, firstVisitUTM)\n };\n\n journey.userJourney.push(touchPoint);\n }\n\n // Save updated journey to sessionStorage\n sessionStorage.setItem(STORAGE_KEY, JSON.stringify(journey));\n\n // // Optional: Log for debugging\n // console.log('User journey updated:', journey);\n\n resolve(journey);\n\n } catch (error: unknown) {\n console.error('Error tracking user journey:', error);\n resolve(null);\n }\n }, 200); // 200ms delay\n });\n}\n\n// Helper function to get current journey data\nfunction getUserJourney(): UserJourney | null {\n try {\n const storedData: string | null = sessionStorage.getItem('userJourney');\n return storedData ? JSON.parse(storedData) as UserJourney : null;\n } catch (error: unknown) {\n console.error('Error getting user journey:', error);\n return null;\n }\n}\n\n// Helper function to clear journey data\nfunction clearUserJourney(): void {\n sessionStorage.removeItem('userJourney');\n}\n\n// Helper function to update page categories manually\nfunction updatePageCategories(categories: string[]): boolean {\n try {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return false;\n\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n lastVisit.category = categories.length > 0 ? categories : ['Not applicable'];\n\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n return true;\n } catch (error: unknown) {\n console.error('Error updating page categories:', error);\n return false;\n }\n}\nfunction updatePageType(type: string): boolean {\n try {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return false;\n\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n lastVisit.type = type;\n\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n return true;\n } catch (error: unknown) {\n console.error('Error updating page type:', error);\n return false;\n }\n}\n\n// Helper function to get journey statistics\nfunction getJourneyStats(): {\n totalPages: number;\n sessionDuration: number;\n firstPage: string;\n lastPage: string;\n} | null {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return null;\n\n const firstVisit: TouchPoint = journey.userJourney[0];\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n\n const sessionDuration: number = new Date(lastVisit.time).getTime() - new Date(firstVisit.time).getTime();\n\n return {\n totalPages: journey.userJourney.length,\n sessionDuration: Math.floor(sessionDuration / 1000), // in seconds\n firstPage: firstVisit.page,\n lastPage: lastVisit.page\n };\n}\n\n// Auto-execute on page load\ndocument.addEventListener('DOMContentLoaded', (): void => {\n trackUserJourney();\n});\n\n// Also execute immediately if DOM is already loaded\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', (): void => {\n trackUserJourney();\n });\n} else {\n trackUserJourney();\n}\n\n// Make functions globally accessible\ndeclare global {\n interface Window {\n trackUserJourney: () => Promise<UserJourney | null>;\n getUserJourney: () => UserJourney | null;\n clearUserJourney: () => void;\n updatePageType: (type: string) => boolean;\n updatePageCategories: (categories: string[]) => boolean;\n getJourneyStats: () => {\n totalPages: number;\n sessionDuration: number;\n firstPage: string;\n lastPage: string;\n } | null;\n }\n}\n\n// Attach functions to window object for global access\nwindow.trackUserJourney = trackUserJourney;\nwindow.getUserJourney = getUserJourney;\nwindow.clearUserJourney = clearUserJourney;\nwindow.updatePageType = updatePageType;\nwindow.updatePageCategories = updatePageCategories;\nwindow.getJourneyStats = getJourneyStats;\n\n// Export functions for module usage (optional)\n// export { trackUserJourney, getUserJourney, clearUserJourney, updatePageType, updatePageCategories, getJourneyStats };"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{(function(){"use strict";let e={utmKeys:["utm_source","utm_medium","utm_campaign","utm_term","utm_content","utm_id"],selectors:["a[href]",'button[onclick*="location"]','button[onclick*="window.open"]','button[onclick*="href"]',"[data-href]"]};function a(){let t=new URLSearchParams(window.location.search),s={};return e.utmKeys.forEach(r=>{if(t.has(r)){let n=t.get(r);n&&(s[r]=n)}}),s}function c(t,s){try{return t.startsWith("/")||t.startsWith("./")||t.startsWith("../")?!0:t.startsWith("http")?new URL(t).hostname===s:t.startsWith("//")?new URL("http:"+t).hostname===s:!t.includes("://")}catch(r){return console.warn("Error parsing URL:",t,r),!0}}function u(t,s){try{let r=new URL(t,window.location.origin);return Object.keys(s).forEach(n=>{r.searchParams.has(n)||r.searchParams.set(n,s[n])}),r.toString()}catch(r){return console.warn("Error processing URL:",t,r),t}}function f(t){return t.hasAttribute("data-utm-exception")&&t.getAttribute("data-utm-exception")==="true"}function g(t){let s=t.match(/["'](https?:\/\/[^"']+|\/[^"']*|[^"']*\.html?[^"']*)["']/);return s?s[1]:null}function m(t,s,r){if(!(t instanceof HTMLElement)||!t.onclick)return;let o=t.onclick.toString().replace(s,r),i=o.slice(o.indexOf("{")+1,o.lastIndexOf("}"));t.setAttribute("onclick",i)}function h(){let t=a();if(Object.keys(t).length===0)return;let s=window.location.hostname;document.querySelectorAll(e.selectors.join(", ")).forEach(n=>{if(f(n))return;let o=null;if(n instanceof HTMLAnchorElement&&n.href)o=n.href;else if(n instanceof HTMLElement&&n.dataset.href)o=n.dataset.href;else if(n instanceof HTMLElement&&n.onclick){let i=n.onclick.toString();o=g(i)}if(o&&c(o,s)){let i=u(o,t);n instanceof HTMLAnchorElement&&n.href?n.href=i:n instanceof HTMLElement&&n.dataset.href&&(n.dataset.href=i),n instanceof HTMLElement&&n.onclick&&o!==i&&m(n,o,i)}}),console.log("UTM parameters propagated to internal links:",t)}function d(){let t=a();if(Object.keys(t).length===0)return;new MutationObserver(function(r){r.forEach(function(n){n.addedNodes.forEach(function(o){if(o.nodeType===Node.ELEMENT_NODE){let i=o;i.matches&&i.matches(e.selectors.join(", "))&&l(i,t),"querySelectorAll"in i&&i.querySelectorAll(e.selectors.join(", ")).forEach(E=>l(E,t))}})})}).observe(document.body,{childList:!0,subtree:!0})}function l(t,s){if(f(t))return;let r=window.location.hostname,n=null;if(t instanceof HTMLAnchorElement&&t.href?n=t.href:t instanceof HTMLElement&&t.dataset.href&&(n=t.dataset.href),n&&c(n,r)){let o=u(n,s);t instanceof HTMLAnchorElement&&t.href?t.href=o:t instanceof HTMLElement&&t.dataset.href&&(t.dataset.href=o)}}function M(){document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){h(),d()}):(h(),d())}M()})();})();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../bin/live-reload.js", "../../src/tracking/utm-links.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "// UTM Parameter Propagation Script (TypeScript)\n// Automatically adds UTM parameters from current page to all internal links\n\ninterface UTMParams {\n [key: string]: string;\n}\n\ninterface UTMConfig {\n utmKeys: string[];\n selectors: string[];\n}\n\n(function (): void {\n 'use strict';\n\n const config: UTMConfig = {\n utmKeys: [\n 'utm_source',\n 'utm_medium',\n 'utm_campaign',\n 'utm_term',\n 'utm_content',\n 'utm_id'\n ],\n selectors: [\n 'a[href]',\n 'button[onclick*=\"location\"]',\n 'button[onclick*=\"window.open\"]',\n 'button[onclick*=\"href\"]',\n '[data-href]'\n ]\n };\n\n // Get current URL parameters\n function getCurrentUTMParams(): UTMParams {\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n const utmParams: UTMParams = {};\n\n config.utmKeys.forEach((key: string) => {\n if (urlParams.has(key)) {\n const value: string | null = urlParams.get(key);\n if (value) {\n utmParams[key] = value;\n }\n }\n });\n\n return utmParams;\n }\n\n // Check if URL is internal (same domain)\n function isInternalLink(url: string, currentHost: string): boolean {\n try {\n // Handle relative URLs\n if (url.startsWith('/') || url.startsWith('./') || url.startsWith('../')) {\n return true;\n }\n\n // Handle absolute URLs\n if (url.startsWith('http')) {\n const linkHost: string = new URL(url).hostname;\n return linkHost === currentHost;\n }\n\n // Handle protocol-relative URLs\n if (url.startsWith('//')) {\n const linkHost: string = new URL('http:' + url).hostname;\n return linkHost === currentHost;\n }\n\n // Handle anchor links and other relative paths\n if (!url.includes('://')) {\n return true;\n }\n\n return false;\n } catch (e: unknown) {\n // If URL parsing fails, assume it's internal to be safe\n console.warn('Error parsing URL:', url, e);\n return true;\n }\n }\n\n // Add UTM parameters to a URL\n function addUTMToURL(url: string, utmParams: UTMParams): string {\n try {\n const urlObj: URL = new URL(url, window.location.origin);\n\n // Add UTM parameters\n Object.keys(utmParams).forEach((key: string) => {\n // Only add if parameter doesn't already exist\n if (!urlObj.searchParams.has(key)) {\n urlObj.searchParams.set(key, utmParams[key]);\n }\n });\n\n return urlObj.toString();\n } catch (e: unknown) {\n console.warn('Error processing URL:', url, e);\n return url;\n }\n }\n\n // Check if element has UTM exception attribute\n function hasUTMException(element: Element): boolean {\n return element.hasAttribute('data-utm-exception') &&\n element.getAttribute('data-utm-exception') === 'true';\n }\n\n // Extract URL from onclick attribute\n function extractURLFromOnclick(onclickStr: string): string | null {\n const urlMatch: RegExpMatchArray | null = onclickStr.match(\n /[\"'](https?:\\/\\/[^\"']+|\\/[^\"']*|[^\"']*\\.html?[^\"']*)[\"']/\n );\n return urlMatch ? urlMatch[1] : null;\n }\n\n // Update element onclick attribute\n function updateOnclickAttribute(element: Element, oldUrl: string, newUrl: string): void {\n if (!(element instanceof HTMLElement) || !element.onclick) return;\n\n const onclickStr: string = element.onclick.toString();\n const newOnclick: string = onclickStr.replace(oldUrl, newUrl);\n const funcBody: string = newOnclick.slice(\n newOnclick.indexOf('{') + 1,\n newOnclick.lastIndexOf('}')\n );\n element.setAttribute('onclick', funcBody);\n }\n\n // Process all links and buttons\n function propagateUTMParameters(): void {\n const utmParams: UTMParams = getCurrentUTMParams();\n\n // Exit if no UTM parameters found\n if (Object.keys(utmParams).length === 0) {\n return;\n }\n\n const currentHost: string = window.location.hostname;\n const elements: NodeListOf<Element> = document.querySelectorAll(config.selectors.join(', '));\n\n elements.forEach((element: Element) => {\n // Skip elements with utm exception attribute\n if (hasUTMException(element)) {\n return;\n }\n\n let url: string | null = null;\n\n // Get URL from different sources\n if (element instanceof HTMLAnchorElement && element.href) {\n url = element.href;\n } else if (element instanceof HTMLElement && element.dataset.href) {\n url = element.dataset.href;\n } else if (element instanceof HTMLElement && element.onclick) {\n // Try to extract URL from onclick\n const onclickStr: string = element.onclick.toString();\n url = extractURLFromOnclick(onclickStr);\n }\n\n // Process if URL found and is internal\n if (url && isInternalLink(url, currentHost)) {\n const updatedURL: string = addUTMToURL(url, utmParams);\n\n // Update the element\n if (element instanceof HTMLAnchorElement && element.href) {\n element.href = updatedURL;\n } else if (element instanceof HTMLElement && element.dataset.href) {\n element.dataset.href = updatedURL;\n }\n\n // Handle onclick updates (basic cases)\n if (element instanceof HTMLElement && element.onclick && url !== updatedURL) {\n updateOnclickAttribute(element, url, updatedURL);\n }\n }\n });\n\n console.log(`UTM parameters propagated to internal links:`, utmParams);\n }\n\n // Handle dynamically added content\n function observeNewContent(): void {\n const utmParams: UTMParams = getCurrentUTMParams();\n\n if (Object.keys(utmParams).length === 0) {\n return;\n }\n\n const observer: MutationObserver = new MutationObserver(function (mutations: MutationRecord[]): void {\n mutations.forEach(function (mutation: MutationRecord): void {\n mutation.addedNodes.forEach(function (node: Node): void {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as Element;\n\n // Check if the added node itself is a link\n if (element.matches && element.matches(config.selectors.join(', '))) {\n processElement(element, utmParams);\n }\n\n // Check for links within the added node\n if ('querySelectorAll' in element) {\n const links: NodeListOf<Element> = element.querySelectorAll(config.selectors.join(', '));\n links.forEach((link: Element) => processElement(link, utmParams));\n }\n }\n });\n });\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n\n // Process individual element\n function processElement(element: Element, utmParams: UTMParams): void {\n // Skip elements with utm exception attribute\n if (hasUTMException(element)) {\n return;\n }\n\n const currentHost: string = window.location.hostname;\n let url: string | null = null;\n\n if (element instanceof HTMLAnchorElement && element.href) {\n url = element.href;\n } else if (element instanceof HTMLElement && element.dataset.href) {\n url = element.dataset.href;\n }\n\n if (url && isInternalLink(url, currentHost)) {\n const updatedURL: string = addUTMToURL(url, utmParams);\n\n if (element instanceof HTMLAnchorElement && element.href) {\n element.href = updatedURL;\n } else if (element instanceof HTMLElement && element.dataset.href) {\n element.dataset.href = updatedURL;\n }\n }\n }\n\n // Initialize when DOM is ready\n function init(): void {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', function (): void {\n propagateUTMParameters();\n observeNewContent();\n });\n } else {\n propagateUTMParameters();\n observeNewContent();\n }\n }\n\n // Start the process\n init();\n\n})();\n\n// Alternative: If you prefer a more targeted approach for specific elements\n// You can also use this function to manually add UTM params to specific links:\nfunction addUTMToElement(element: HTMLElement | HTMLAnchorElement): void {\n // Skip elements with utm exception attribute\n if (element.hasAttribute('data-utm-exception') &&\n element.getAttribute('data-utm-exception') === 'true') {\n return;\n }\n\n const getCurrentUTMParams = (): UTMParams => {\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n const utmParams: UTMParams = {};\n const utmKeys: string[] = [\n 'utm_source', 'utm_medium', 'utm_campaign',\n 'utm_term', 'utm_content', 'utm_id'\n ];\n\n utmKeys.forEach((key: string) => {\n const value: string | null = urlParams.get(key);\n if (value) {\n utmParams[key] = value;\n }\n });\n\n return utmParams;\n };\n\n const isInternalLink = (url: string, currentHost: string): boolean => {\n try {\n if (url.startsWith('/') || url.startsWith('./') || url.startsWith('../')) {\n return true;\n }\n if (url.startsWith('http')) {\n return new URL(url).hostname === currentHost;\n }\n return !url.includes('://');\n } catch {\n return true;\n }\n };\n\n const addUTMToURL = (url: string, utmParams: UTMParams): string => {\n try {\n const urlObj: URL = new URL(url, window.location.origin);\n Object.keys(utmParams).forEach((key: string) => {\n if (!urlObj.searchParams.has(key)) {\n urlObj.searchParams.set(key, utmParams[key]);\n }\n });\n return urlObj.toString();\n } catch {\n return url;\n }\n };\n\n const utmParams: UTMParams = getCurrentUTMParams();\n if (Object.keys(utmParams).length > 0) {\n const currentHost: string = window.location.hostname;\n\n if (element instanceof HTMLAnchorElement && element.href &&\n isInternalLink(element.href, currentHost)) {\n element.href = addUTMToURL(element.href, utmParams);\n }\n }\n}\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../bin/live-reload.js", "../../src/utils/sample.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "export function logMessage(message: string): void {\n console.log(\"Logged message:\", message);\n}\n"],
|
|
5
|
+
"mappings": ";;;AACA,MACE,OAAO,SAAS,aAAa,eAC7B,OAAO,SAAS,aAAa,aAC7B;AACA,QAAI,YAAY,GAAG,uBAAY,UAAU,EAAE;AAAA,MAAiB;AAAA,MAAU,MACpE,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,gDAAgD;AAAA,EAC9D;;;ACVO,WAAS,WAAW,SAAuB;AAChD,YAAQ,IAAI,mBAAmB,OAAO;AAAA,EACxC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED