@hortonstudio/main 1.9.24 → 1.9.25

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 (89) hide show
  1. package/dist/assets/hs-animations-tvD4W7u0.js +3 -0
  2. package/dist/assets/hs-animations-tvD4W7u0.js.br +0 -0
  3. package/dist/assets/hs-animations-tvD4W7u0.js.gz +0 -0
  4. package/dist/assets/hs-animations-tvD4W7u0.js.map +1 -0
  5. package/dist/assets/hs-counter-DmspKHOV.js +2 -0
  6. package/dist/assets/hs-counter-DmspKHOV.js.br +0 -0
  7. package/dist/assets/hs-counter-DmspKHOV.js.gz +0 -0
  8. package/dist/assets/{hs-counter-Bfh7_P60.js.map → hs-counter-DmspKHOV.js.map} +1 -1
  9. package/dist/assets/hs-default-Dxg7WNGx.js +2 -0
  10. package/dist/assets/hs-default-Dxg7WNGx.js.br +0 -0
  11. package/dist/assets/hs-default-Dxg7WNGx.js.gz +0 -0
  12. package/dist/assets/hs-default-Dxg7WNGx.js.map +1 -0
  13. package/dist/assets/hs-marquee-Dwenaw7L.js +2 -0
  14. package/dist/assets/hs-marquee-Dwenaw7L.js.br +0 -0
  15. package/dist/assets/hs-marquee-Dwenaw7L.js.gz +0 -0
  16. package/dist/assets/{hs-marquee-CZ9pmCbT.js.map → hs-marquee-Dwenaw7L.js.map} +1 -1
  17. package/dist/assets/hs-normalize-iTnWVIjq.js +2 -0
  18. package/dist/assets/hs-normalize-iTnWVIjq.js.br +0 -0
  19. package/dist/assets/hs-normalize-iTnWVIjq.js.gz +0 -0
  20. package/dist/assets/{hs-normalize-CTwtG5-a.js.map → hs-normalize-iTnWVIjq.js.map} +1 -1
  21. package/dist/assets/hs-utils-CNwAFmmK.js +2 -0
  22. package/dist/assets/hs-utils-CNwAFmmK.js.br +0 -0
  23. package/dist/assets/hs-utils-CNwAFmmK.js.gz +0 -0
  24. package/dist/assets/hs-utils-CNwAFmmK.js.map +1 -0
  25. package/dist/main.js +2 -2
  26. package/dist/main.js.br +0 -0
  27. package/dist/main.js.gz +0 -0
  28. package/dist/main.js.map +1 -1
  29. package/package.json +2 -2
  30. package/dist/assets/hs-animations-BDMqlbof.js +0 -3
  31. package/dist/assets/hs-animations-BDMqlbof.js. +0 -3
  32. package/dist/assets/hs-animations-BDMqlbof.js.gz +0 -0
  33. package/dist/assets/hs-animations-BDMqlbof.js.map +0 -1
  34. package/dist/assets/hs-attributeSelector-6pGcDBo-.js +0 -2
  35. package/dist/assets/hs-attributeSelector-6pGcDBo-.js.map +0 -1
  36. package/dist/assets/hs-comparison-Ja8EiSGD.js +0 -2
  37. package/dist/assets/hs-comparison-Ja8EiSGD.js. +0 -2
  38. package/dist/assets/hs-comparison-Ja8EiSGD.js.gz +0 -0
  39. package/dist/assets/hs-comparison-Ja8EiSGD.js.map +0 -1
  40. package/dist/assets/hs-counter-Bfh7_P60.js +0 -2
  41. package/dist/assets/hs-counter-Bfh7_P60.js. +0 -2
  42. package/dist/assets/hs-counter-Bfh7_P60.js.gz +0 -0
  43. package/dist/assets/hs-cssVariables-BjuwJfDJ.js +0 -2
  44. package/dist/assets/hs-cssVariables-BjuwJfDJ.js.map +0 -1
  45. package/dist/assets/hs-default-CLmDRb9d.js +0 -2
  46. package/dist/assets/hs-default-CLmDRb9d.js. +0 -2
  47. package/dist/assets/hs-default-CLmDRb9d.js.gz +0 -0
  48. package/dist/assets/hs-default-CLmDRb9d.js.map +0 -1
  49. package/dist/assets/hs-form-COFGgawz.js +0 -2
  50. package/dist/assets/hs-form-COFGgawz.js. +0 -2
  51. package/dist/assets/hs-form-COFGgawz.js.gz +0 -0
  52. package/dist/assets/hs-form-COFGgawz.js.map +0 -1
  53. package/dist/assets/hs-marquee-CZ9pmCbT.js +0 -2
  54. package/dist/assets/hs-marquee-CZ9pmCbT.js. +0 -2
  55. package/dist/assets/hs-marquee-CZ9pmCbT.js.gz +0 -0
  56. package/dist/assets/hs-modalManager-H_YegPAO.js +0 -2
  57. package/dist/assets/hs-modalManager-H_YegPAO.js. +0 -2
  58. package/dist/assets/hs-modalManager-H_YegPAO.js.gz +0 -0
  59. package/dist/assets/hs-modalManager-H_YegPAO.js.map +0 -1
  60. package/dist/assets/hs-normalize-CTwtG5-a.js +0 -2
  61. package/dist/assets/hs-normalize-CTwtG5-a.js. +0 -2
  62. package/dist/assets/hs-normalize-CTwtG5-a.js.gz +0 -0
  63. package/dist/assets/hs-orchestrator-J8b7XRk1.js +0 -2
  64. package/dist/assets/hs-orchestrator-J8b7XRk1.js. +0 -2
  65. package/dist/assets/hs-orchestrator-J8b7XRk1.js.gz +0 -0
  66. package/dist/assets/hs-orchestrator-J8b7XRk1.js.map +0 -1
  67. package/dist/assets/hs-pagination-DcOxmDPJ.js +0 -2
  68. package/dist/assets/hs-pagination-DcOxmDPJ.js. +0 -2
  69. package/dist/assets/hs-pagination-DcOxmDPJ.js.gz +0 -0
  70. package/dist/assets/hs-pagination-DcOxmDPJ.js.map +0 -1
  71. package/dist/assets/hs-structure-DhNix64P.js +0 -3
  72. package/dist/assets/hs-structure-DhNix64P.js. +0 -3
  73. package/dist/assets/hs-structure-DhNix64P.js.gz +0 -0
  74. package/dist/assets/hs-structure-DhNix64P.js.map +0 -1
  75. package/dist/assets/hs-tabs-CaxqHoGW.js +0 -2
  76. package/dist/assets/hs-tabs-CaxqHoGW.js. +0 -2
  77. package/dist/assets/hs-tabs-CaxqHoGW.js.gz +0 -0
  78. package/dist/assets/hs-tabs-CaxqHoGW.js.map +0 -1
  79. package/dist/assets/hs-toc-fxIQS7tz.js +0 -2
  80. package/dist/assets/hs-toc-fxIQS7tz.js. +0 -2
  81. package/dist/assets/hs-toc-fxIQS7tz.js.gz +0 -0
  82. package/dist/assets/hs-toc-fxIQS7tz.js.map +0 -1
  83. package/dist/assets/hs-transition-CDNuGJNq.js +0 -2
  84. package/dist/assets/hs-transition-CDNuGJNq.js. +0 -2
  85. package/dist/assets/hs-transition-CDNuGJNq.js.gz +0 -0
  86. package/dist/assets/hs-transition-CDNuGJNq.js.map +0 -1
  87. package/dist/assets/hs-utils-CKm6QhLw.js +0 -2
  88. package/dist/assets/hs-utils-CKm6QhLw.js.map +0 -1
  89. package/dist/main.js. +0 -3
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":["config","API_NAME","_global","apiName","async","window","Array","isArray","loaded","document","documentElement","classList","add","classes","initialized","queuedModules","moduleMap","normalize","__vitePreload","import","__VITE_PRELOAD__","structure","default","animations","scripts","querySelectorAll","url","length","filter","script","scriptSrc","src","currentSrc","scriptPackage","match","currentPackage","split","settings","isSPA","some","getAttribute","PHASES","modules","parallel","loadModule","moduleName","instance","process","has","loading","moduleData","destroy","Promise","resolve","reject","init","resultData","initResult","result","delete","restart","load","error","executePhase","phaseName","phase","initPromises","map","name","allSettled","initializeInPhases","event","CustomEvent","dispatchEvent","triggerDomReady","readyCallbacks","Set","push","items","callback","this","then","reinitialize","scanForEmbedModules","forEach","embed","moduleType","moduleKey","afterReady","status","Object","keys","phases","finalize","catch","initializeHsMain"],"ignoreList":[],"sources":["../src/config.ts","../index.ts"],"sourcesContent":["/**\n * Master Configuration\n *\n * Single source of truth for all module configs with TypeScript type safety.\n * Provides autocomplete and type checking for all configuration access.\n */\nimport configData from './config.json';\n\n// TypeScript interfaces for autocomplete and type safety\n\nexport interface AttributeConfig {\n primary: string;\n aliases: string[];\n}\n\nexport interface ModuleConfig {\n module: string;\n description?: string;\n attributes?: {\n elements?: Record<string, AttributeConfig>;\n properties?: Record<string, string>;\n placeholders?: Record<string, string>;\n note?: string;\n };\n modes?: Record<string, string>;\n modifiers?: Record<string, string>;\n limits?: Record<string, number>;\n types?: Record<string, string>;\n defaults?: Record<string, string>;\n}\n\nexport interface GlobalConfig {\n version: string;\n apiName: string;\n attributes: {\n height: string;\n heightValue: string;\n heightDuration: string;\n heightEase: string;\n moduleType: string;\n module: string;\n };\n classes: {\n modalOpen: string;\n overflowHidden: string;\n initialized: string;\n displayContents: string;\n active: string;\n gsap: string;\n };\n cssVars: {\n prefix: string;\n state: {\n name: string;\n values: {\n active: string;\n inactive: string;\n };\n };\n clip: {\n name: string;\n };\n };\n clickable: ModuleConfig;\n}\n\nexport interface Config {\n _global: GlobalConfig;\n normalize?: {\n sync?: ModuleConfig;\n clickable?: ModuleConfig & {\n normalize?: ModuleConfig;\n };\n dupe?: ModuleConfig;\n };\n structure?: {\n 'year-replacement'?: ModuleConfig;\n toc?: ModuleConfig;\n pagination?: ModuleConfig;\n comparison?: ModuleConfig;\n tabs?: ModuleConfig & {\n cssVars?: {\n progress?: string;\n };\n };\n 'site-settings'?: ModuleConfig;\n form?: {\n honeypot?: ModuleConfig;\n range?: ModuleConfig;\n test?: ModuleConfig;\n select?: ModuleConfig & {\n states?: ModuleConfig;\n 'custom-select'?: ModuleConfig;\n };\n };\n };\n transition?: ModuleConfig;\n default?: {\n 'smooth-scroll'?: ModuleConfig;\n accordion?: ModuleConfig;\n counter?: ModuleConfig;\n comparison?: ModuleConfig;\n navbar?: ModuleConfig & {\n dropdown?: ModuleConfig;\n menu?: ModuleConfig;\n 'arrow-navigation'?: ModuleConfig;\n };\n };\n animations?: {\n transition?: ModuleConfig;\n };\n [key: string]: unknown;\n}\n\n// Export typed config\nexport const config = configData as Config;\nexport default config;\n","/**\n * Main Entry Point\n *\n * 3-phase initialization system: Normalize → Structure → Default + Animations.\n * Handles module loading, lifecycle management, and SPA coordination.\n */\nimport config from '@config';\n\nconst API_NAME = config._global.apiName;\n\nconst initializeHsMain = async (): Promise<void> => {\n if (window[API_NAME] && !Array.isArray(window[API_NAME]) && window[API_NAME].loaded) {\n return;\n }\n\n // Add initialized class to HTML element immediately\n document.documentElement.classList.add(config._global.classes.initialized);\n\n const queuedModules = Array.isArray(window[API_NAME]) ? window[API_NAME] : [];\n\n const moduleMap = {\n normalize: () => import('./src/modules/normalize/normalize.ts'),\n structure: () => import('./src/modules/structure/structure.ts'),\n default: () => import('./src/modules/default/default.ts'),\n animations: () => import('./src/animations/animations.ts'),\n };\n\n let scripts = [...document.querySelectorAll(`script[type=\"module\"][src=\"${import.meta.url}\"]`)];\n\n if (scripts.length === 0) {\n scripts = [\n ...document.querySelectorAll('script[type=\"module\"][src*=\"@hortonstudio/main\"]'),\n ].filter((script) => {\n const scriptSrc = (script as HTMLScriptElement).src;\n const currentSrc = import.meta.url;\n const scriptPackage = scriptSrc.match(/@hortonstudio\\/main(@[\\d.]+)?/)?.[0];\n const currentPackage = currentSrc.match(/@hortonstudio\\/main(@[\\d.]+)?/)?.[0];\n return (\n scriptPackage &&\n currentPackage &&\n scriptPackage.split('@')[0] === currentPackage.split('@')[0]\n );\n });\n }\n\n // Read settings from script tag attributes\n const settings = {\n isSPA: scripts.some((script) => script.getAttribute('data-hs-spa') === 'true'),\n };\n\n // Define 3-phase initialization system\n const PHASES = {\n normalize: {\n modules: ['normalize'],\n parallel: false, // Sequential execution critical for DOM fixes\n },\n structure: {\n modules: ['structure'],\n parallel: false, // Must complete before default\n },\n default: {\n modules: ['default', 'animations'],\n parallel: true, // Run default and animations in parallel\n },\n };\n\n const loadModule = async (moduleName: string): Promise<unknown> => {\n const instance = window[API_NAME];\n if (instance.process.has(moduleName)) {\n return instance.modules[moduleName]?.loading;\n }\n\n instance.process.add(moduleName);\n\n const moduleData = instance.modules[moduleName] || {};\n instance.modules[moduleName] = moduleData;\n\n moduleData.loading = new Promise((resolve, reject) => {\n moduleData.resolve = resolve;\n moduleData.reject = reject;\n });\n\n let destroy: (() => void) | undefined;\n try {\n const { init } = await moduleMap[moduleName]();\n const result = await init();\n const resultData = result || {};\n destroy = resultData.destroy as (() => void) | undefined;\n const initResult = resultData.result;\n\n moduleData.destroy = () => {\n destroy?.();\n instance.process.delete(moduleName);\n };\n moduleData.restart = () => {\n moduleData.destroy?.();\n instance.load(moduleName);\n };\n\n moduleData.resolve?.(initResult);\n delete moduleData.resolve;\n delete moduleData.reject;\n\n return initResult;\n } catch (error) {\n destroy?.();\n moduleData.reject?.(error);\n instance.process.delete(moduleName);\n throw error;\n }\n };\n\n // Helper to execute a phase (modules already downloaded)\n const executePhase = async (phaseName: string): Promise<void> => {\n const phase = PHASES[phaseName];\n\n // Execute based on parallel setting\n if (phase.parallel) {\n const initPromises = phase.modules.map((name: string) => loadModule(name));\n await Promise.allSettled(initPromises);\n } else {\n // Sequential execution\n for (const name of phase.modules) {\n await loadModule(name);\n }\n }\n };\n\n // Trigger DOM ready event\n const triggerDomReady = () => {\n const event = new CustomEvent('hsmain:dom-ready');\n window.dispatchEvent(event);\n };\n\n // Initialize all modules in 3 phases\n const initializeInPhases = async (): Promise<void> => {\n // Step 1: Download ALL modules in parallel (before any init)\n await Promise.allSettled([\n moduleMap['normalize'](),\n moduleMap['structure'](),\n moduleMap['default'](),\n moduleMap['animations'](),\n ]);\n\n // Step 2: Init in phases\n // Phase 1: Normalize (critical DOM fixes)\n await executePhase('normalize');\n\n // Phase 2: Structure (DOM modifications)\n await executePhase('structure');\n\n // Phase 3: Default + Animations (parallel)\n await executePhase('default');\n\n // Trigger DOM ready after everything initialized\n triggerDomReady();\n };\n\n const readyCallbacks: (() => void)[] = [];\n\n window[API_NAME] = {\n scripts,\n settings,\n modules: {},\n process: new Set(),\n load: loadModule,\n loaded: false,\n push(...items: [string, ((result: unknown) => void)?][]) {\n for (const [moduleName, callback] of items) {\n if (typeof callback === 'function') {\n this.modules[moduleName]?.loading?.then(callback);\n } else {\n this.load(moduleName);\n }\n }\n },\n destroy() {\n for (const moduleName in this.modules) {\n this.modules[moduleName]?.destroy?.();\n }\n },\n async reinitialize() {\n // Complete teardown\n this.loaded = false;\n this.destroy();\n this.modules = {};\n this.process = new Set();\n\n // Re-scan for modules including in w-embeds\n await this.scanForEmbedModules();\n\n // Use same phased initialization flow\n await initializeInPhases();\n\n this.loaded = true;\n },\n async scanForEmbedModules() {\n const embeds = document.querySelectorAll('.w-embed');\n embeds.forEach((embed) => {\n const scripts = embed.querySelectorAll('script[data-hs-module]');\n scripts.forEach((script) => {\n // Extract module info from data attributes\n const moduleType = script.getAttribute('data-hs-module-type');\n const moduleName = script.getAttribute('data-hs-module');\n\n if (moduleType && moduleName) {\n const moduleKey = `data-hs-${moduleType}-${moduleName}`;\n if (moduleMap[moduleKey]) {\n this.load(moduleKey);\n }\n }\n });\n });\n },\n afterReady(callback: () => void) {\n if (typeof callback === 'function') {\n if (this.loaded) {\n callback();\n } else {\n readyCallbacks.push(callback);\n }\n }\n },\n status(moduleName?: string) {\n if (moduleName) {\n return {\n loaded: !!this.modules[moduleName],\n loading: this.process.has(moduleName),\n };\n }\n return {\n loaded: Object.keys(this.modules),\n loading: [...this.process],\n phases: PHASES,\n };\n },\n };\n\n const finalize = async (): Promise<void> => {\n window[API_NAME].push(...queuedModules);\n\n // Run phased initialization\n await initializeInPhases();\n\n window[API_NAME].loaded = true;\n readyCallbacks.forEach((callback) => {\n try {\n callback();\n } catch {\n // Silent error handling\n }\n });\n readyCallbacks.length = 0; // Clear array after execution\n };\n\n finalize().catch(() => {});\n};\n\ninitializeHsMain();\n"],"file":"main.js"}
1
+ {"version":3,"mappings":";8qCAQMA,EAAWC,EAAOC,QAAQC,QAEPC,WACvB,GAAIC,OAAOL,KAAcM,MAAMC,QAAQF,OAAOL,KAAcK,OAAOL,GAAUQ,OAC3E,OAIFC,SAASC,gBAAgBC,UAAUC,IAAIX,EAAOC,QAAQW,QAAQC,aAE9D,MAAMC,EAAgBT,MAAMC,QAAQF,OAAOL,IAAaK,OAAOL,GAAY,GAErEgB,EAAY,CAChBC,UAAW,IAAAC,EAAA,IAAMC,OAAO,qCAAsCC,wBAC9DC,QAAS,IAAAH,EAAA,IAAMC,OAAO,mCAAkCC,wBACxDE,WAAY,IAAAJ,EAAA,IAAMC,OAAO,sCAAgCC,yBAG3D,IAAIG,EAAU,IAAId,SAASe,iBAAiB,0CAA0CC,UAE/D,IAAnBF,EAAQG,SACVH,EAAU,IACLd,SAASe,iBAAiB,qDAC7BG,OAAQC,IACR,MAAMC,EAAaD,EAA6BE,IAC1CC,cAAyBN,IACzBO,EAAgBH,EAAUI,MAAM,mCAAmC,GACnEC,EAAiBH,EAAWE,MAAM,mCAAmC,GAC3E,OACED,GACAE,GACAF,EAAcG,MAAM,KAAK,KAAOD,EAAeC,MAAM,KAAK,MAMhE,MAAMC,EAAW,CACfC,MAAOd,EAAQe,KAAMV,GAAkD,SAAvCA,EAAOW,aAAa,iBAIhDC,EAAS,CACbvB,UAAW,CACTwB,QAAS,CAAC,aACVC,UAAU,GAEZrB,QAAS,CACPoB,QAAS,CAAC,UAAW,cACrBC,UAAU,IAIRC,EAAavC,MAAOwC,IACxB,MAAMC,EAAWxC,OAAOL,GACxB,GAAI6C,EAASC,QAAQC,IAAIH,GACvB,OAAOC,EAASJ,QAAQG,IAAaI,QAGvCH,EAASC,QAAQlC,IAAIgC,GAErB,MAAMK,EAAaJ,EAASJ,QAAQG,IAAe,GAQnD,IAAIM,EAPJL,EAASJ,QAAQG,GAAcK,EAE/BA,EAAWD,QAAU,IAAIG,QAAQ,CAACC,EAASC,KACzCJ,EAAWG,QAAUA,EACrBH,EAAWI,OAASA,IAItB,IACE,MAAMC,KAAEA,SAAetC,EAAU4B,KAE3BW,QADeD,KACQ,GAC7BJ,EAAUK,EAAWL,QACrB,MAAMM,EAAaD,EAAWE,OAe9B,OAbAR,EAAWC,QAAU,KACnBA,MACAL,EAASC,QAAQY,OAAOd,IAE1BK,EAAWU,QAAU,KACnBV,EAAWC,YACXL,EAASe,KAAKhB,IAGhBK,EAAWG,UAAUI,UACdP,EAAWG,eACXH,EAAWI,OAEXG,CACT,OAASK,GAIP,MAHAX,MACAD,EAAWI,SAASQ,GACpBhB,EAASC,QAAQY,OAAOd,GAClBiB,CACR,GAIIC,EAAe1D,MAAO2D,IAC1B,MAAMC,EAAQxB,EAAOuB,GAGrB,GAAIC,EAAMtB,SAAU,CAClB,MAAMuB,EAAeD,EAAMvB,QAAQyB,IAAKC,GAAiBxB,EAAWwB,UAC9DhB,QAAQiB,WAAWH,EAC3B,MAEE,UAAWE,KAAQH,EAAMvB,cACjBE,EAAWwB,IAYjBE,EAAqBjE,gBAEnB+C,QAAQiB,WAAW,CACvBpD,EAAqB,YACrBA,EAAmB,UACnBA,EAAsB,qBAKlB8C,EAAa,mBAGbA,EAAa,WAnBG,MACtB,MAAMQ,EAAQ,IAAIC,YAAY,oBAC9BlE,OAAOmE,cAAcF,IAoBrBG,IAGIC,EAAiC,GAEvCrE,OAAOL,GAAY,CACjBuB,UACAa,WACAK,QAAS,GACTK,YAAa6B,IACbf,KAAMjB,EACNnC,QAAQ,EACR,IAAAoE,IAAQC,GACN,UAAYjC,EAAYkC,KAAaD,EACX,mBAAbC,EACTC,KAAKtC,QAAQG,IAAaI,SAASgC,KAAKF,GAExCC,KAAKnB,KAAKhB,EAGhB,EACA,OAAAM,GACE,UAAWN,KAAcmC,KAAKtC,QAC5BsC,KAAKtC,QAAQG,IAAaM,WAE9B,EACA,kBAAM+B,GAEJF,KAAKvE,QAAS,EACduE,KAAK7B,UACL6B,KAAKtC,QAAU,GACfsC,KAAKjC,YAAc6B,UAGbI,KAAKG,4BAGLb,IAENU,KAAKvE,QAAS,CAChB,EACA,yBAAM0E,GACWzE,SAASe,iBAAiB,YAClC2D,QAASC,IACEA,EAAM5D,iBAAiB,0BAC/B2D,QAASvD,IAEf,MAAMyD,EAAazD,EAAOW,aAAa,uBACjCK,EAAahB,EAAOW,aAAa,kBAEvC,GAAI8C,GAAczC,EAAY,CAC5B,MAAM0C,EAAY,WAAWD,KAAczC,IACvC5B,EAAUsE,IACZP,KAAKnB,KAAK0B,EAEd,KAGN,EACA,UAAAC,CAAWT,GACe,mBAAbA,IACLC,KAAKvE,OACPsE,IAEAJ,EAAeE,KAAKE,GAG1B,EACA,MAAAU,CAAO5C,GACL,OAAIA,EACK,CACLpC,SAAUuE,KAAKtC,QAAQG,GACvBI,QAAS+B,KAAKjC,QAAQC,IAAIH,IAGvB,CACLpC,OAAQiF,OAAOC,KAAKX,KAAKtC,SACzBO,QAAS,IAAI+B,KAAKjC,SAClB6C,OAAQnD,EAEZ,GAGepC,WACfC,OAAOL,GAAU4E,QAAQ7D,SAGnBsD,IAENhE,OAAOL,GAAUQ,QAAS,EAC1BkE,EAAeS,QAASL,IACtB,IACEA,GACF,OAEA,IAEFJ,EAAehD,OAAS,GAG1BkE,GAAWC,MAAM,SAGnBC","names":["API_NAME","config","_global","apiName","async","window","Array","isArray","loaded","document","documentElement","classList","add","classes","initialized","queuedModules","moduleMap","normalize","__vitePreload","import","__VITE_PRELOAD__","default","animations","scripts","querySelectorAll","url","length","filter","script","scriptSrc","src","currentSrc","scriptPackage","match","currentPackage","split","settings","isSPA","some","getAttribute","PHASES","modules","parallel","loadModule","moduleName","instance","process","has","loading","moduleData","destroy","Promise","resolve","reject","init","resultData","initResult","result","delete","restart","load","error","executePhase","phaseName","phase","initPromises","map","name","allSettled","initializeInPhases","event","CustomEvent","dispatchEvent","triggerDomReady","readyCallbacks","Set","push","items","callback","this","then","reinitialize","scanForEmbedModules","forEach","embed","moduleType","moduleKey","afterReady","status","Object","keys","phases","finalize","catch","initializeHsMain"],"ignoreList":[],"sources":["../index.ts"],"sourcesContent":["/**\n * Main Entry Point\n *\n * 2-phase initialization system: Normalize → Default + Animations.\n * Handles module loading, lifecycle management, and SPA coordination.\n */\nimport config from '@config';\n\nconst API_NAME = config._global.apiName;\n\nconst initializeHsMain = async (): Promise<void> => {\n if (window[API_NAME] && !Array.isArray(window[API_NAME]) && window[API_NAME].loaded) {\n return;\n }\n\n // Add initialized class to HTML element immediately\n document.documentElement.classList.add(config._global.classes.initialized);\n\n const queuedModules = Array.isArray(window[API_NAME]) ? window[API_NAME] : [];\n\n const moduleMap = {\n normalize: () => import('./src/modules/normalize/normalize.ts'),\n default: () => import('./src/modules/default/default.ts'),\n animations: () => import('./src/animations/animations.ts'),\n };\n\n let scripts = [...document.querySelectorAll(`script[type=\"module\"][src=\"${import.meta.url}\"]`)];\n\n if (scripts.length === 0) {\n scripts = [\n ...document.querySelectorAll('script[type=\"module\"][src*=\"@hortonstudio/main\"]'),\n ].filter((script) => {\n const scriptSrc = (script as HTMLScriptElement).src;\n const currentSrc = import.meta.url;\n const scriptPackage = scriptSrc.match(/@hortonstudio\\/main(@[\\d.]+)?/)?.[0];\n const currentPackage = currentSrc.match(/@hortonstudio\\/main(@[\\d.]+)?/)?.[0];\n return (\n scriptPackage &&\n currentPackage &&\n scriptPackage.split('@')[0] === currentPackage.split('@')[0]\n );\n });\n }\n\n // Read settings from script tag attributes\n const settings = {\n isSPA: scripts.some((script) => script.getAttribute('data-hs-spa') === 'true'),\n };\n\n // Define 2-phase initialization system\n const PHASES = {\n normalize: {\n modules: ['normalize'],\n parallel: false, // Sequential execution critical for DOM fixes\n },\n default: {\n modules: ['default', 'animations'],\n parallel: true, // Run default and animations in parallel\n },\n };\n\n const loadModule = async (moduleName: string): Promise<unknown> => {\n const instance = window[API_NAME];\n if (instance.process.has(moduleName)) {\n return instance.modules[moduleName]?.loading;\n }\n\n instance.process.add(moduleName);\n\n const moduleData = instance.modules[moduleName] || {};\n instance.modules[moduleName] = moduleData;\n\n moduleData.loading = new Promise((resolve, reject) => {\n moduleData.resolve = resolve;\n moduleData.reject = reject;\n });\n\n let destroy: (() => void) | undefined;\n try {\n const { init } = await moduleMap[moduleName]();\n const result = await init();\n const resultData = result || {};\n destroy = resultData.destroy as (() => void) | undefined;\n const initResult = resultData.result;\n\n moduleData.destroy = () => {\n destroy?.();\n instance.process.delete(moduleName);\n };\n moduleData.restart = () => {\n moduleData.destroy?.();\n instance.load(moduleName);\n };\n\n moduleData.resolve?.(initResult);\n delete moduleData.resolve;\n delete moduleData.reject;\n\n return initResult;\n } catch (error) {\n destroy?.();\n moduleData.reject?.(error);\n instance.process.delete(moduleName);\n throw error;\n }\n };\n\n // Helper to execute a phase (modules already downloaded)\n const executePhase = async (phaseName: string): Promise<void> => {\n const phase = PHASES[phaseName];\n\n // Execute based on parallel setting\n if (phase.parallel) {\n const initPromises = phase.modules.map((name: string) => loadModule(name));\n await Promise.allSettled(initPromises);\n } else {\n // Sequential execution\n for (const name of phase.modules) {\n await loadModule(name);\n }\n }\n };\n\n // Trigger DOM ready event\n const triggerDomReady = () => {\n const event = new CustomEvent('hsmain:dom-ready');\n window.dispatchEvent(event);\n };\n\n // Initialize all modules in 2 phases\n const initializeInPhases = async (): Promise<void> => {\n // Step 1: Download ALL modules in parallel (before any init)\n await Promise.allSettled([\n moduleMap['normalize'](),\n moduleMap['default'](),\n moduleMap['animations'](),\n ]);\n\n // Step 2: Init in phases\n // Phase 1: Normalize (critical DOM fixes)\n await executePhase('normalize');\n\n // Phase 2: Default + Animations (parallel)\n await executePhase('default');\n\n // Trigger DOM ready after everything initialized\n triggerDomReady();\n };\n\n const readyCallbacks: (() => void)[] = [];\n\n window[API_NAME] = {\n scripts,\n settings,\n modules: {},\n process: new Set(),\n load: loadModule,\n loaded: false,\n push(...items: [string, ((result: unknown) => void)?][]) {\n for (const [moduleName, callback] of items) {\n if (typeof callback === 'function') {\n this.modules[moduleName]?.loading?.then(callback);\n } else {\n this.load(moduleName);\n }\n }\n },\n destroy() {\n for (const moduleName in this.modules) {\n this.modules[moduleName]?.destroy?.();\n }\n },\n async reinitialize() {\n // Complete teardown\n this.loaded = false;\n this.destroy();\n this.modules = {};\n this.process = new Set();\n\n // Re-scan for modules including in w-embeds\n await this.scanForEmbedModules();\n\n // Use same phased initialization flow\n await initializeInPhases();\n\n this.loaded = true;\n },\n async scanForEmbedModules() {\n const embeds = document.querySelectorAll('.w-embed');\n embeds.forEach((embed) => {\n const scripts = embed.querySelectorAll('script[data-hs-module]');\n scripts.forEach((script) => {\n // Extract module info from data attributes\n const moduleType = script.getAttribute('data-hs-module-type');\n const moduleName = script.getAttribute('data-hs-module');\n\n if (moduleType && moduleName) {\n const moduleKey = `data-hs-${moduleType}-${moduleName}`;\n if (moduleMap[moduleKey]) {\n this.load(moduleKey);\n }\n }\n });\n });\n },\n afterReady(callback: () => void) {\n if (typeof callback === 'function') {\n if (this.loaded) {\n callback();\n } else {\n readyCallbacks.push(callback);\n }\n }\n },\n status(moduleName?: string) {\n if (moduleName) {\n return {\n loaded: !!this.modules[moduleName],\n loading: this.process.has(moduleName),\n };\n }\n return {\n loaded: Object.keys(this.modules),\n loading: [...this.process],\n phases: PHASES,\n };\n },\n };\n\n const finalize = async (): Promise<void> => {\n window[API_NAME].push(...queuedModules);\n\n // Run phased initialization\n await initializeInPhases();\n\n window[API_NAME].loaded = true;\n readyCallbacks.forEach((callback) => {\n try {\n callback();\n } catch {\n // Silent error handling\n }\n });\n readyCallbacks.length = 0; // Clear array after execution\n };\n\n finalize().catch(() => {});\n};\n\ninitializeHsMain();\n"],"file":"main.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hortonstudio/main",
3
- "version": "1.9.24",
3
+ "version": "1.9.25",
4
4
  "description": "Animation and utility library for client websites",
5
5
  "main": "dist/main.js",
6
6
  "type": "module",
@@ -33,6 +33,6 @@
33
33
  "terser": "^5.44.1",
34
34
  "typescript": "^5.9.3",
35
35
  "vite": "^7.2.2",
36
- "vite-plugin-compression": "^0.5.1"
36
+ "vite-plugin-compression2": "^2.3.1"
37
37
  }
38
38
  }
@@ -1,3 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/hs-counter-Bfh7_P60.js","assets/hs-modalManager-H_YegPAO.js","main.js","assets/hs-marquee-CZ9pmCbT.js","assets/hs-utils-CKm6QhLw.js","assets/hs-transition-CDNuGJNq.js"])))=>i.map(i=>d[i]);
2
- import{_ as t}from"../main.js";import"./hs-modalManager-H_YegPAO.js";import{c as e}from"./hs-orchestrator-J8b7XRk1.js";const o=[{name:"counter",selector:'[data-hs-anim="counter"]',import:()=>t(()=>import("./hs-counter-Bfh7_P60.js"),__vite__mapDeps([0,1,2]))},{name:"marquee",selector:'[data-hs-marquee="wrapper"]',import:()=>t(()=>import("./hs-marquee-CZ9pmCbT.js"),__vite__mapDeps([3,4,1,2]))},{name:"transition",selector:'[data-hs-transition="wrapper"]',import:()=>t(()=>import("./hs-transition-CDNuGJNq.js"),__vite__mapDeps([5,4,1,2]))}],a=(()=>{const t=o.filter(t=>document.querySelector(t.selector)).map(t=>t.import().catch(e=>(console.error(`[animations] Failed to preload ${t.name}:`,e),null)));return Promise.allSettled(t)})();async function r(){if(document.documentElement.getAttributeNames().some(t=>t.startsWith("data-wf-"))){if(!(await async function(t=3e3){return console.log("[Webflow] Waiting for IX3, timeout:",t,"ms"),new Promise(e=>{const o=Date.now(),a=()=>{const r=document.documentElement,n=r.classList.contains("w-mod-ix3"),s=r.hasAttribute("data-wf-ix-ready"),i=n||s,m=Date.now()-o;i?(console.log("[Webflow] IX3 detected after",m,"ms"),e(!0)):m>t?(console.warn(`[Webflow] IX3 timeout after ${m}ms - proceeding without IX3 coordination`),e(!1)):setTimeout(a,50)};a()})}(3e3))){const t=document.querySelector('[data-hs-transition="wrapper"]');t&&(console.warn("[animations] Webflow IX3 timeout - removing transition wrapper to prevent FOUC"),t.remove())}}await a;const t=e(o),{loaded:r}=await t.scan();return{result:`animations initialized (${r.length} active)`,rescan:t.scan,destroy:t.destroy}}export{r as init};
3
- //# sourceMappingURL=hs-animations-BDMqlbof.js.map
@@ -1,3 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/hs-counter-Bfh7_P60.js","assets/hs-modalManager-H_YegPAO.js","main.js","assets/hs-marquee-CZ9pmCbT.js","assets/hs-utils-CKm6QhLw.js","assets/hs-transition-CDNuGJNq.js"])))=>i.map(i=>d[i]);
2
- import{_ as t}from"../main.js";import"./hs-modalManager-H_YegPAO.js";import{c as e}from"./hs-orchestrator-J8b7XRk1.js";const o=[{name:"counter",selector:'[data-hs-anim="counter"]',import:()=>t(()=>import("./hs-counter-Bfh7_P60.js"),__vite__mapDeps([0,1,2]))},{name:"marquee",selector:'[data-hs-marquee="wrapper"]',import:()=>t(()=>import("./hs-marquee-CZ9pmCbT.js"),__vite__mapDeps([3,4,1,2]))},{name:"transition",selector:'[data-hs-transition="wrapper"]',import:()=>t(()=>import("./hs-transition-CDNuGJNq.js"),__vite__mapDeps([5,4,1,2]))}],a=(()=>{const t=o.filter(t=>document.querySelector(t.selector)).map(t=>t.import().catch(e=>(console.error(`[animations] Failed to preload ${t.name}:`,e),null)));return Promise.allSettled(t)})();async function r(){if(document.documentElement.getAttributeNames().some(t=>t.startsWith("data-wf-"))){if(!(await async function(t=3e3){return console.log("[Webflow] Waiting for IX3, timeout:",t,"ms"),new Promise(e=>{const o=Date.now(),a=()=>{const r=document.documentElement,n=r.classList.contains("w-mod-ix3"),s=r.hasAttribute("data-wf-ix-ready"),i=n||s,m=Date.now()-o;i?(console.log("[Webflow] IX3 detected after",m,"ms"),e(!0)):m>t?(console.warn(`[Webflow] IX3 timeout after ${m}ms - proceeding without IX3 coordination`),e(!1)):setTimeout(a,50)};a()})}(3e3))){const t=document.querySelector('[data-hs-transition="wrapper"]');t&&(console.warn("[animations] Webflow IX3 timeout - removing transition wrapper to prevent FOUC"),t.remove())}}await a;const t=e(o),{loaded:r}=await t.scan();return{result:`animations initialized (${r.length} active)`,rescan:t.scan,destroy:t.destroy}}export{r as init};
3
- //# sourceMappingURL=hs-animations-BDMqlbof.js.map
@@ -1 +0,0 @@
1
- {"version":3,"mappings":";uHAiCA,MAAMA,EAA4C,CAChD,CACEC,KAAM,UACNC,SAAU,2BACVC,OAAQ,UAAMA,OAAO,4BAAwBC,2BAE/C,CACEH,KAAM,UACNC,SAAU,8BACVC,OAAQ,UAAMA,OAAO,4BAAwBC,6BAE/C,CACEH,KAAM,aACNC,SAAU,iCACVC,OAAQ,UAAMA,OAAO,+BAA2BC,8BAQ9CC,QACJ,MAKMC,EALmBN,EAAmBO,OAAQC,GAClDC,SAASC,cAAcF,EAAON,WAISS,IAAKH,GAC5CA,EAAOL,SAASS,MAAOC,IACrBC,QAAQD,MAAM,kCAAkCL,EAAOP,QAASY,GACzD,QAIX,OAAOE,QAAQC,WAAWV,EAC5B,KAEAW,eAAsBC,IAIpB,GC1DaT,SAASU,gBACEC,oBACNC,KAAMC,GAASA,EAAKC,WAAW,aDwDvC,CAGR,WClDJN,eAAiCO,EAAkB,KAEjD,OADAV,QAAQW,IAAI,sCAAuCD,EAAS,MACrD,IAAIT,QAASW,IAClB,MAAMC,EAAYC,KAAKC,MAEjBC,EAAW,KACf,MAAMC,EAAOtB,SAASU,gBAGhBa,EAAeD,EAAKE,UAAUC,SAAS,aACvCC,EAAiBJ,EAAKK,aAAa,oBACnCC,EAAiBL,GAAgBG,EAEjCG,EAAUV,KAAKC,MAAQF,EAEzBU,GACFvB,QAAQW,IAAI,+BAAgCa,EAAS,MACrDZ,GAAQ,IACCY,EAAUd,GAEnBV,QAAQyB,KACN,+BAA+BD,6CAEjCZ,GAAQ,IAERc,WAAWV,EAAU,KAGzBA,KAEJ,CDkB2BW,CAAW,MAEnB,CAEb,MAAMC,EAAoBjC,SAASC,cAAc,kCAC7CgC,IACF5B,QAAQyB,KACN,kFAEFG,EAAkBC,SAEtB,CACF,OAGMtC,EAGN,MAAMuC,EAAeC,EAAmB7C,IAClC8C,OAAEA,SAAiBF,EAAaG,OAEtC,MAAO,CACLC,OAAQ,2BAA2BF,EAAOG,iBAC1CC,OAAQN,EAAaG,KACrBI,QAASP,EAAaO,QAE1B","names":["ANIMATION_REGISTRY","name","selector","import","__VITE_PRELOAD__","preloadAnimations","preloadPromises","filter","module","document","querySelector","map","catch","error","console","Promise","allSettled","async","init","documentElement","getAttributeNames","some","attr","startsWith","timeout","log","resolve","startTime","Date","now","checkIx3","html","hasLegacyIx3","classList","contains","hasNewIxSignal","hasAttribute","hasAnyIxSignal","elapsed","warn","setTimeout","waitForIx3","transitionWrapper","remove","orchestrator","createOrchestrator","loaded","scan","result","length","rescan","destroy"],"ignoreList":[],"sources":["../../src/animations/animations.ts","../../src/utils/webflow.ts"],"sourcesContent":["/**\n * Animations Orchestrator\n *\n * Conditionally loads animation modules based on DOM presence.\n * Uses registry pattern for scalable animation management.\n *\n * Features:\n * - Self-registering animation system (add new animations in one line)\n * - Dynamic imports for code-splitting\n * - Prevents duplicate initialization\n * - SPA-friendly rescan() method\n * - Centralized destroy cleanup\n * - Webflow IX3 coordination with timeout fallback\n *\n * Architecture:\n * - Registry-based discovery (scales to 100s of animations)\n * - Scans DOM for registered selectors\n * - Dynamically imports only the animations found\n * - Waits for Webflow IX3 before initializing (prevents FOUC)\n * - Removes transition wrapper on IX3 timeout (graceful degradation)\n * - Exposes rescan() for SPA page transitions\n *\n * Adding new animations:\n * 1. Add entry to ANIMATION_REGISTRY below\n * 2. That's it - orchestrator handles the rest\n */\n\nimport { createOrchestrator, type ModuleRegistryEntry, isWebflow, waitForIx3 } from '@utils';\n\n/**\n * Animation Registry\n * Add new animations here - one line per animation\n */\nconst ANIMATION_REGISTRY: ModuleRegistryEntry[] = [\n {\n name: 'counter',\n selector: '[data-hs-anim=\"counter\"]',\n import: () => import('./functions/counter.ts'),\n },\n {\n name: 'marquee',\n selector: '[data-hs-marquee=\"wrapper\"]',\n import: () => import('./functions/marquee.ts'),\n },\n {\n name: 'transition',\n selector: '[data-hs-transition=\"wrapper\"]',\n import: () => import('./functions/transition.ts'),\n },\n // Add more animations here:\n // { name: 'hamburger', selector: '[data-hs-hamburger=\"squeeze\"]', import: () => import('./functions/hamburger.ts') },\n];\n\n// Pre-download animation modules as soon as this file loads (before init is called)\n// This allows parallel downloads while still respecting IX3 timing for initialization\nconst preloadAnimations = (() => {\n const modulesToPreload = ANIMATION_REGISTRY.filter((module) =>\n document.querySelector(module.selector)\n );\n\n // Download all found modules in parallel\n const preloadPromises = modulesToPreload.map((module) =>\n module.import().catch((error) => {\n console.error(`[animations] Failed to preload ${module.name}:`, error);\n return null;\n })\n );\n\n return Promise.allSettled(preloadPromises);\n})();\n\nexport async function init() {\n // Wait for Webflow IX3 before initializing animations (prevents FOUC and conflicts)\n const isWf = isWebflow();\n\n if (isWf) {\n const ix3Ready = await waitForIx3(3000); // 3 second timeout\n\n if (!ix3Ready) {\n // IX3 didn't load in time - remove transition wrapper to prevent FOUC\n const transitionWrapper = document.querySelector('[data-hs-transition=\"wrapper\"]');\n if (transitionWrapper) {\n console.warn(\n '[animations] Webflow IX3 timeout - removing transition wrapper to prevent FOUC'\n );\n transitionWrapper.remove();\n }\n }\n }\n\n // Wait for preloading to complete (modules are already downloaded)\n await preloadAnimations;\n\n // Initialize all animations (transition will skip if wrapper was removed)\n const orchestrator = createOrchestrator(ANIMATION_REGISTRY);\n const { loaded } = await orchestrator.scan();\n\n return {\n result: `animations initialized (${loaded.length} active)`,\n rescan: orchestrator.scan,\n destroy: orchestrator.destroy,\n };\n}\n","/**\n * Webflow Platform Utility\n *\n * Handles Webflow-specific initialization requirements including IX3 detection.\n * Auto-detects Webflow via data-wf-* attributes on <html> element.\n *\n * Features:\n * - Auto-detects Webflow platform\n * - Waits for IX3 initialization\n * - Manual override with data-hs-wf-off\n */\n\n/**\n * Detect if running on Webflow platform\n * Checks for any data-wf-* attribute on <html> element\n */\nexport function isWebflow(): boolean {\n const html = document.documentElement;\n const attributes = html.getAttributeNames();\n return attributes.some((attr) => attr.startsWith('data-wf-'));\n}\n\n/**\n * Wait for Webflow IX3 to be ready\n * Polls for multiple IX ready signals with timeout fallback\n * @param timeout - Maximum time to wait in milliseconds (default: 3000ms)\n * @returns Promise<boolean> - true if IX3 loaded, false if timeout\n */\nexport async function waitForIx3(timeout: number = 3000): Promise<boolean> {\n console.log('[Webflow] Waiting for IX3, timeout:', timeout, 'ms');\n return new Promise((resolve) => {\n const startTime = Date.now();\n\n const checkIx3 = () => {\n const html = document.documentElement;\n\n // Check all known IX ready signals (supports old and new Webflow versions)\n const hasLegacyIx3 = html.classList.contains('w-mod-ix3');\n const hasNewIxSignal = html.hasAttribute('data-wf-ix-ready');\n const hasAnyIxSignal = hasLegacyIx3 || hasNewIxSignal;\n\n const elapsed = Date.now() - startTime;\n\n if (hasAnyIxSignal) {\n console.log('[Webflow] IX3 detected after', elapsed, 'ms');\n resolve(true); // IX3 loaded successfully\n } else if (elapsed > timeout) {\n // Timeout reached - proceed without IX3\n console.warn(\n `[Webflow] IX3 timeout after ${elapsed}ms - proceeding without IX3 coordination`\n );\n resolve(false);\n } else {\n setTimeout(checkIx3, 50);\n }\n };\n checkIx3();\n });\n}\n\n/**\n * Check if Webflow waiting should be disabled via script attribute\n * Looks for data-hs-wf-off on module script tag\n */\nexport function shouldSkipWebflow(scripts: Element[]): boolean {\n return scripts.some((script) => script.hasAttribute('data-hs-wf-off'));\n}\n"],"file":"hs-animations-BDMqlbof.js"}
@@ -1,2 +0,0 @@
1
- function e(e,t){const n=e.attributes?.elements?.[t];if(!n)return console.warn(`[attributeSelector] No config for element: ${t}`),"";return[`[${n.primary}]`,...(n.aliases||[]).map(e=>`[${e}]`)].join(", ")}function t(t,n,r=document){const o=e(t,n);return r.querySelectorAll(o)}function n(t,n,r=document){const o=e(t,n);return r.querySelector(o)}export{n as a,e as g,t as q};
2
- //# sourceMappingURL=hs-attributeSelector-6pGcDBo-.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hs-attributeSelector-6pGcDBo-.js","sources":["../../src/utils/attributeSelector.ts"],"sourcesContent":["/**\n * Attribute Selector Utility\n *\n * Builds CSS selectors from module config to support primary attributes + aliases.\n * Enables easy rebranding and backward compatibility.\n */\n\ninterface AttributeSelectorConfig {\n module?: string;\n attributes?: {\n elements?: {\n [key: string]: {\n primary: string;\n aliases?: string[];\n };\n };\n };\n}\n\n/**\n * Builds a CSS selector from config attribute patterns\n */\nexport function getSelector(config: AttributeSelectorConfig, elementKey: string): string {\n const element = config.attributes?.elements?.[elementKey];\n if (!element) {\n console.warn(`[attributeSelector] No config for element: ${elementKey}`);\n return '';\n }\n\n const selectors = [\n `[${element.primary}]`,\n ...(element.aliases || []).map((alias: string) => `[${alias}]`),\n ];\n\n return selectors.join(', ');\n}\n\n/**\n * Gets all matching elements for a given element type\n */\nexport function querySelectorAll(\n config: AttributeSelectorConfig,\n elementKey: string,\n root: Document | Element = document\n): NodeListOf<Element> {\n const selector = getSelector(config, elementKey);\n return root.querySelectorAll(selector);\n}\n\n/**\n * Gets first matching element for a given element type\n */\nexport function querySelector(\n config: AttributeSelectorConfig,\n elementKey: string,\n root: Document | Element = document\n): Element | null {\n const selector = getSelector(config, elementKey);\n return root.querySelector(selector);\n}\n\n/**\n * Logs deprecation warning if using non-primary attributes\n */\nexport function checkDeprecated(\n element: Element | null,\n config: AttributeSelectorConfig,\n elementKey: string\n): void {\n if (!element) return;\n\n const elementConfig = config.attributes.elements[elementKey];\n const elementAttrs = element.getAttributeNames();\n\n elementConfig.aliases?.forEach((alias: string) => {\n const attrName = alias.split('=')[0].replace(/[\\[\\]']/g, '');\n if (elementAttrs.includes(attrName)) {\n console.warn(\n `[${config.module}] Using deprecated attribute \"${alias}\". ` +\n `Please use \"${elementConfig.primary}\" instead. ` +\n `Support for deprecated attributes will be removed in v3.0.0`\n );\n }\n });\n}\n"],"names":["getSelector","config","elementKey","element","attributes","elements","console","warn","primary","aliases","map","alias","join","querySelectorAll","root","document","selector","querySelector"],"mappings":"AAsBO,SAASA,EAAYC,EAAiCC,GAC3D,MAAMC,EAAUF,EAAOG,YAAYC,WAAWH,GAC9C,IAAKC,EAEH,OADAG,QAAQC,KAAK,8CAA8CL,KACpD,GAQT,MALkB,CAChB,IAAIC,EAAQK,eACRL,EAAQM,SAAW,IAAIC,IAAKC,GAAkB,IAAIA,OAGvCC,KAAK,KACxB,CAKO,SAASC,EACdZ,EACAC,EACAY,EAA2BC,UAE3B,MAAMC,EAAWhB,EAAYC,EAAQC,GACrC,OAAOY,EAAKD,iBAAiBG,EAC/B,CAKO,SAASC,EACdhB,EACAC,EACAY,EAA2BC,UAE3B,MAAMC,EAAWhB,EAAYC,EAAQC,GACrC,OAAOY,EAAKG,cAAcD,EAC5B"}
@@ -1,2 +0,0 @@
1
- import{g as e}from"./hs-utils-CKm6QhLw.js";import{g as t,w as r}from"./hs-modalManager-H_YegPAO.js";import{q as a,g as n,a as s}from"./hs-attributeSelector-6pGcDBo-.js";import{c as o}from"./hs-cssVariables-BjuwJfDJ.js";import"../main.js";async function i(i){const l=t("comparison");if(!l)return{result:"comparison skipped - GSAP not loaded"};const{gsap:c,Draggable:p}=l;r("comparison",["Draggable"],"error");const d=a(i,"wrapper"),m={draggables:[],handlers:[]},u=n(i,"template-name"),g=n(i,"template-description"),f=n(i,"template-before-image"),h=n(i,"template-after-image");function b(e,t){e.style.setProperty(o.clip,`${t}%`)}function y(t,r){const a=t.templateItems[r];if(!a)return;const n=a.querySelector(u);t.nameElement&&n&&(t.nameElement.textContent=n.textContent);const o=a.querySelector(g);t.descElement&&o&&(t.descElement.textContent=o.textContent);const l=a.querySelector(f);t.beforeImage&&l&&(t.beforeImage.src=l.src,t.beforeImage.alt=l.alt||"");const c=a.querySelector(h);t.afterImage&&c&&(t.afterImage.src=c.src,t.afterImage.alt=c.alt||"",v(t)),t.currentIndex=r,function(t,r){const a=s(i,"pagination",t);if(!a)return;const n=e.classes.active;Array.from(a.children).forEach((e,t)=>{t===r?e.classList.add(n):e.classList.remove(n)})}(t.wrapper,r)}function v(e){const t=e.slider,r=e.wrapper;switch(e.mode){case"before":r.style.setProperty(o.clip,"100%"),t.style.display="none";break;case"after":r.style.setProperty(o.clip,"0%"),t.style.display="none";break;case"split":b(r,e.sliderPosition),t.style.display="flex"}}function w(e,t){const r=e.currentIndex+t,a=e.templateItems.length-1;let n;n=r>a?0:r<0?a:r,y(e,n)}return d.forEach(t=>{const r=s(i,"template-list",t);if(!r)return void console.warn("[comparison] No template list found in wrapper");const a=n(i,"template-item"),o=Array.from(r.querySelectorAll(a));if(0===o.length)return void console.warn("[comparison] No template items found");t.setAttribute("aria-live","polite"),t.setAttribute("aria-label","Before and after image comparison");const l=s(i,"image-wrapper",t),d=s(i,"slider",t),u=s(i,"before-image",t),g=s(i,"after-image",t),f=s(i,"name",t),h=s(i,"description",t);if(!l||!d||!g){const e=[];return l||e.push('image-wrapper (data-hs-comparison="image-wrapper")'),d||e.push('slider (data-hs-comparison="slider")'),g||e.push('after-image (data-hs-comparison-image="after")'),void console.warn(`[comparison] Missing required elements: ${e.join(", ")}`)}const k={wrapper:t,templateItems:o,currentIndex:0,mode:"split",sliderPosition:50,slider:d,beforeImage:u?.querySelector("img"),afterImage:g?.querySelector("img"),nameElement:f,descElement:h,draggable:null};if(y(k,0),b(t,50),p){const e=p.create(d,{type:"x",bounds:l,onDrag:function(){const e=l.getBoundingClientRect(),r=d.getBoundingClientRect().left-e.left,a=Math.max(0,Math.min(100,r/e.width*100));b(t,a),k.sliderPosition=a}});m.draggables.push(e),k.draggable=e[0];const r=e=>{if("split"!==k.mode)return;const r=l.getBoundingClientRect(),a=e.clientX-r.left,n=Math.max(0,Math.min(100,a/r.width*100)),s=a-r.width/2;k.draggable&&(c.set(d,{x:s}),k.draggable.update()),b(t,n),k.sliderPosition=n};l.addEventListener("click",r),m.handlers.push({element:l,event:"click",handler:r})}t.querySelectorAll(`[${i.attributes.properties.modeType}]`).forEach(t=>{const r=t.getAttribute(i.attributes.properties.modeType),a=n(e.clickable,"button"),s=t.querySelector(a)||t;r===k.mode&&t.classList.add(e.classes.active);const o=t=>{t.preventDefault(),function(t,r){const a=t.wrapper.querySelectorAll(`[${i.attributes.properties.modeType}]`),n=e.classes.active;a.forEach(e=>{e.getAttribute(i.attributes.properties.modeType)===r?e.classList.add(n):e.classList.remove(n)}),t.mode=r,v(t)}(k,r)};s.addEventListener("click",o),m.handlers.push({element:s,event:"click",handler:o})}),function(t,r){const a=r.querySelector(`[${i.attributes.properties.navType}="previous"]`),s=r.querySelector(`[${i.attributes.properties.navType}="next"]`);if(a){const r=n(e.clickable,"button"),s=a.querySelector(r)||a;s.setAttribute("aria-label","Previous image");const o=e=>{e.preventDefault(),w(t,-1)};s.addEventListener("click",o),m.handlers.push({element:s,event:"click",handler:o})}if(s){const r=n(e.clickable,"button"),a=s.querySelector(r)||s;a.setAttribute("aria-label","Next image");const o=e=>{e.preventDefault(),w(t,1)};a.addEventListener("click",o),m.handlers.push({element:a,event:"click",handler:o})}}(k,t);const E=s(i,"pagination",t);E&&o.length>1&&function(t,r){const a=r.children[0];if(!a)return;const n=e.classes.active;r.innerHTML="",t.templateItems.forEach((e,s)=>{const o=a.cloneNode(!0);o.classList.remove(n),0===s&&o.classList.add(n);const i=()=>{y(t,s)};o.addEventListener("click",i),m.handlers.push({element:o,event:"click",handler:i}),r.appendChild(o)})}(k,E),function(e){const t=t=>{"ArrowLeft"===t.key||"ArrowUp"===t.key?(t.preventDefault(),w(e,-1)):"ArrowRight"!==t.key&&"ArrowDown"!==t.key||(t.preventDefault(),w(e,1))};e.wrapper.addEventListener("keydown",t),e.wrapper.setAttribute("tabindex","0"),m.handlers.push({element:e.wrapper,event:"keydown",handler:t})}(k)}),{result:`comparison initialized (${d.length} instances)`,destroy:()=>{m.draggables.forEach(e=>{e&&e[0]&&e[0].kill&&e[0].kill()}),m.handlers.forEach(({element:e,event:t,handler:r})=>{e.removeEventListener(t,r)}),m.draggables.length=0,m.handlers.length=0}}}export{i as init};
2
- //# sourceMappingURL=hs-comparison-Ja8EiSGD.js.map
@@ -1,2 +0,0 @@
1
- import{g as e}from"./hs-utils-CKm6QhLw.js";import{g as t,w as r}from"./hs-modalManager-H_YegPAO.js";import{q as a,g as n,a as s}from"./hs-attributeSelector-6pGcDBo-.js";import{c as o}from"./hs-cssVariables-BjuwJfDJ.js";import"../main.js";async function i(i){const l=t("comparison");if(!l)return{result:"comparison skipped - GSAP not loaded"};const{gsap:c,Draggable:p}=l;r("comparison",["Draggable"],"error");const d=a(i,"wrapper"),m={draggables:[],handlers:[]},u=n(i,"template-name"),g=n(i,"template-description"),f=n(i,"template-before-image"),h=n(i,"template-after-image");function b(e,t){e.style.setProperty(o.clip,`${t}%`)}function y(t,r){const a=t.templateItems[r];if(!a)return;const n=a.querySelector(u);t.nameElement&&n&&(t.nameElement.textContent=n.textContent);const o=a.querySelector(g);t.descElement&&o&&(t.descElement.textContent=o.textContent);const l=a.querySelector(f);t.beforeImage&&l&&(t.beforeImage.src=l.src,t.beforeImage.alt=l.alt||"");const c=a.querySelector(h);t.afterImage&&c&&(t.afterImage.src=c.src,t.afterImage.alt=c.alt||"",v(t)),t.currentIndex=r,function(t,r){const a=s(i,"pagination",t);if(!a)return;const n=e.classes.active;Array.from(a.children).forEach((e,t)=>{t===r?e.classList.add(n):e.classList.remove(n)})}(t.wrapper,r)}function v(e){const t=e.slider,r=e.wrapper;switch(e.mode){case"before":r.style.setProperty(o.clip,"100%"),t.style.display="none";break;case"after":r.style.setProperty(o.clip,"0%"),t.style.display="none";break;case"split":b(r,e.sliderPosition),t.style.display="flex"}}function w(e,t){const r=e.currentIndex+t,a=e.templateItems.length-1;let n;n=r>a?0:r<0?a:r,y(e,n)}return d.forEach(t=>{const r=s(i,"template-list",t);if(!r)return void console.warn("[comparison] No template list found in wrapper");const a=n(i,"template-item"),o=Array.from(r.querySelectorAll(a));if(0===o.length)return void console.warn("[comparison] No template items found");t.setAttribute("aria-live","polite"),t.setAttribute("aria-label","Before and after image comparison");const l=s(i,"image-wrapper",t),d=s(i,"slider",t),u=s(i,"before-image",t),g=s(i,"after-image",t),f=s(i,"name",t),h=s(i,"description",t);if(!l||!d||!g){const e=[];return l||e.push('image-wrapper (data-hs-comparison="image-wrapper")'),d||e.push('slider (data-hs-comparison="slider")'),g||e.push('after-image (data-hs-comparison-image="after")'),void console.warn(`[comparison] Missing required elements: ${e.join(", ")}`)}const k={wrapper:t,templateItems:o,currentIndex:0,mode:"split",sliderPosition:50,slider:d,beforeImage:u?.querySelector("img"),afterImage:g?.querySelector("img"),nameElement:f,descElement:h,draggable:null};if(y(k,0),b(t,50),p){const e=p.create(d,{type:"x",bounds:l,onDrag:function(){const e=l.getBoundingClientRect(),r=d.getBoundingClientRect().left-e.left,a=Math.max(0,Math.min(100,r/e.width*100));b(t,a),k.sliderPosition=a}});m.draggables.push(e),k.draggable=e[0];const r=e=>{if("split"!==k.mode)return;const r=l.getBoundingClientRect(),a=e.clientX-r.left,n=Math.max(0,Math.min(100,a/r.width*100)),s=a-r.width/2;k.draggable&&(c.set(d,{x:s}),k.draggable.update()),b(t,n),k.sliderPosition=n};l.addEventListener("click",r),m.handlers.push({element:l,event:"click",handler:r})}t.querySelectorAll(`[${i.attributes.properties.modeType}]`).forEach(t=>{const r=t.getAttribute(i.attributes.properties.modeType),a=n(e.clickable,"button"),s=t.querySelector(a)||t;r===k.mode&&t.classList.add(e.classes.active);const o=t=>{t.preventDefault(),function(t,r){const a=t.wrapper.querySelectorAll(`[${i.attributes.properties.modeType}]`),n=e.classes.active;a.forEach(e=>{e.getAttribute(i.attributes.properties.modeType)===r?e.classList.add(n):e.classList.remove(n)}),t.mode=r,v(t)}(k,r)};s.addEventListener("click",o),m.handlers.push({element:s,event:"click",handler:o})}),function(t,r){const a=r.querySelector(`[${i.attributes.properties.navType}="previous"]`),s=r.querySelector(`[${i.attributes.properties.navType}="next"]`);if(a){const r=n(e.clickable,"button"),s=a.querySelector(r)||a;s.setAttribute("aria-label","Previous image");const o=e=>{e.preventDefault(),w(t,-1)};s.addEventListener("click",o),m.handlers.push({element:s,event:"click",handler:o})}if(s){const r=n(e.clickable,"button"),a=s.querySelector(r)||s;a.setAttribute("aria-label","Next image");const o=e=>{e.preventDefault(),w(t,1)};a.addEventListener("click",o),m.handlers.push({element:a,event:"click",handler:o})}}(k,t);const E=s(i,"pagination",t);E&&o.length>1&&function(t,r){const a=r.children[0];if(!a)return;const n=e.classes.active;r.innerHTML="",t.templateItems.forEach((e,s)=>{const o=a.cloneNode(!0);o.classList.remove(n),0===s&&o.classList.add(n);const i=()=>{y(t,s)};o.addEventListener("click",i),m.handlers.push({element:o,event:"click",handler:i}),r.appendChild(o)})}(k,E),function(e){const t=t=>{"ArrowLeft"===t.key||"ArrowUp"===t.key?(t.preventDefault(),w(e,-1)):"ArrowRight"!==t.key&&"ArrowDown"!==t.key||(t.preventDefault(),w(e,1))};e.wrapper.addEventListener("keydown",t),e.wrapper.setAttribute("tabindex","0"),m.handlers.push({element:e.wrapper,event:"keydown",handler:t})}(k)}),{result:`comparison initialized (${d.length} instances)`,destroy:()=>{m.draggables.forEach(e=>{e&&e[0]&&e[0].kill&&e[0].kill()}),m.handlers.forEach(({element:e,event:t,handler:r})=>{e.removeEventListener(t,r)}),m.draggables.length=0,m.handlers.length=0}}}export{i as init};
2
- //# sourceMappingURL=hs-comparison-Ja8EiSGD.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hs-comparison-Ja8EiSGD.js","sources":["../../src/modules/structure/functions/comparison.ts"],"sourcesContent":["/**\n * Comparison Module\n *\n * Before/after image comparison slider with GSAP Draggable.\n * Uses template list to manage multiple slides with a single persistent slider.\n *\n * Structure:\n * <!-- Template list (hidden, inside wrapper) -->\n * <div data-hs-comparison=\"wrapper\">\n * <div data-hs-comparison-template=\"list\" class=\"u-display-none\">\n * <div data-hs-comparison-template=\"item\">\n * <h3 data-hs-comparison-template=\"name\">Project 1</h3>\n * <div data-hs-comparison-template=\"description\">Description 1</div>\n * <img data-hs-comparison-template=\"before\" src=\"before1.jpg\" alt=\"Before\">\n * <img data-hs-comparison-template=\"after\" src=\"after1.jpg\" alt=\"After\">\n * </div>\n * </div>\n *\n * <!-- Visible slider elements -->\n * <div data-hs-comparison=\"image-wrapper\">\n * <div data-hs-comparison-image=\"before\">\n * <img src=\"placeholder.jpg\">\n * </div>\n * <div data-hs-comparison-image=\"after\">\n * <img src=\"placeholder.jpg\">\n * </div>\n * </div>\n * <div data-hs-comparison=\"slider\"></div>\n * <span data-hs-comparison=\"name\">Placeholder</span>\n * <span data-hs-comparison=\"description\">Placeholder</span>\n * </div>\n */\n\nimport {\n querySelector,\n querySelectorAll,\n getSelector,\n globalConfig,\n getGsap,\n warnMissingDependencies,\n cssVariables,\n} from '@utils';\n\nexport async function init(config: any) {\n const gsapLib = getGsap('comparison');\n if (!gsapLib) {\n return { result: 'comparison skipped - GSAP not loaded' };\n }\n\n const { gsap, Draggable } = gsapLib;\n\n // Warn about missing required dependencies\n warnMissingDependencies('comparison', ['Draggable'], 'error');\n\n const wrappers = querySelectorAll(config, 'wrapper');\n const cleanup = {\n draggables: [] as any[],\n handlers: [] as Array<{ element: Element; event: string; handler: EventListener }>,\n };\n\n // Cache template selectors once (they never change)\n const templateNameSelector = getSelector(config, 'template-name');\n const templateDescSelector = getSelector(config, 'template-description');\n const templateBeforeImageSelector = getSelector(config, 'template-before-image');\n const templateAfterImageSelector = getSelector(config, 'template-after-image');\n\n // Helper functions with access to config and gsap via closure\n function updateClipPath(wrapper: HTMLElement, percentage: number) {\n // Set CSS variable on wrapper, CSS handles the actual clip-path\n wrapper.style.setProperty(cssVariables.clip, `${percentage}%`);\n }\n\n function loadSlide(instance: any, index: number) {\n const templateItem = instance.templateItems[index];\n if (!templateItem) return;\n\n // Update name\n const templateName = templateItem.querySelector(templateNameSelector);\n if (instance.nameElement && templateName) {\n instance.nameElement.textContent = templateName.textContent;\n }\n\n // Update description\n const templateDesc = templateItem.querySelector(templateDescSelector);\n if (instance.descElement && templateDesc) {\n instance.descElement.textContent = templateDesc.textContent;\n }\n\n // Update before image\n const templateBeforeImage = templateItem.querySelector(\n templateBeforeImageSelector\n ) as HTMLImageElement;\n\n if (instance.beforeImage && templateBeforeImage) {\n instance.beforeImage.src = templateBeforeImage.src;\n instance.beforeImage.alt = templateBeforeImage.alt || '';\n }\n\n // Update after image\n const templateAfterImage = templateItem.querySelector(\n templateAfterImageSelector\n ) as HTMLImageElement;\n\n if (instance.afterImage && templateAfterImage) {\n instance.afterImage.src = templateAfterImage.src;\n instance.afterImage.alt = templateAfterImage.alt || '';\n\n // Apply current mode to maintain slider state\n applyMode(instance);\n }\n\n instance.currentIndex = index;\n\n // Update pagination\n updatePagination(instance.wrapper, index);\n }\n\n function applyMode(instance: any) {\n const slider = instance.slider;\n const wrapper = instance.wrapper;\n\n switch (instance.mode) {\n case 'before':\n // Set variable to 100% (hide after image completely)\n wrapper.style.setProperty(cssVariables.clip, '100%');\n slider.style.display = 'none';\n break;\n case 'after':\n // Set variable to 0% (show after image completely)\n wrapper.style.setProperty(cssVariables.clip, '0%');\n slider.style.display = 'none';\n break;\n case 'split':\n // Restore slider position without resetting\n updateClipPath(wrapper, instance.sliderPosition);\n slider.style.display = 'flex';\n break;\n }\n }\n\n function setMode(instance: any, mode: string) {\n const wrapper = instance.wrapper;\n const modeButtons = wrapper.querySelectorAll(`[${config.attributes.properties.modeType}]`);\n const activeClass = globalConfig.classes.active;\n\n // Update button states\n modeButtons.forEach((btn: Element) => {\n const btnMode = btn.getAttribute(config.attributes.properties.modeType);\n if (btnMode === mode) {\n btn.classList.add(activeClass);\n } else {\n btn.classList.remove(activeClass);\n }\n });\n\n instance.mode = mode;\n applyMode(instance);\n }\n\n function updatePagination(wrapper: HTMLElement, index: number) {\n const paginationContainer = querySelector(config, 'pagination', wrapper);\n if (!paginationContainer) return;\n\n const activeClass = globalConfig.classes.active;\n const dots = Array.from(paginationContainer.children);\n dots.forEach((dot, dotIndex) => {\n if (dotIndex === index) {\n dot.classList.add(activeClass);\n } else {\n dot.classList.remove(activeClass);\n }\n });\n }\n\n function navigateSlide(instance: any, direction: number) {\n const newIndex = instance.currentIndex + direction;\n const maxIndex = instance.templateItems.length - 1;\n\n let targetIndex: number;\n if (newIndex > maxIndex) {\n targetIndex = 0;\n } else if (newIndex < 0) {\n targetIndex = maxIndex;\n } else {\n targetIndex = newIndex;\n }\n\n loadSlide(instance, targetIndex);\n }\n\n function setupNavigation(instance: any, wrapper: HTMLElement) {\n const leftArrow = wrapper.querySelector(`[${config.attributes.properties.navType}=\"previous\"]`);\n const rightArrow = wrapper.querySelector(`[${config.attributes.properties.navType}=\"next\"]`);\n\n if (leftArrow) {\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const button = (leftArrow.querySelector(clickableSelector) || leftArrow) as HTMLElement;\n button.setAttribute('aria-label', 'Previous image');\n\n const handler = (e: Event) => {\n e.preventDefault();\n navigateSlide(instance, -1);\n };\n\n button.addEventListener('click', handler);\n cleanup.handlers.push({ element: button, event: 'click', handler });\n }\n\n if (rightArrow) {\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const button = (rightArrow.querySelector(clickableSelector) || rightArrow) as HTMLElement;\n button.setAttribute('aria-label', 'Next image');\n\n const handler = (e: Event) => {\n e.preventDefault();\n navigateSlide(instance, 1);\n };\n\n button.addEventListener('click', handler);\n cleanup.handlers.push({ element: button, event: 'click', handler });\n }\n }\n\n function setupPagination(instance: any, paginationContainer: HTMLElement) {\n const templateDot = paginationContainer.children[0];\n if (!templateDot) return;\n\n const activeClass = globalConfig.classes.active;\n paginationContainer.innerHTML = '';\n\n instance.templateItems.forEach((_: any, index: number) => {\n const dot = templateDot.cloneNode(true) as HTMLElement;\n\n // Remove active class from all dots, then add only to first\n dot.classList.remove(activeClass);\n if (index === 0) {\n dot.classList.add(activeClass);\n }\n\n const clickHandler = () => {\n loadSlide(instance, index);\n };\n\n dot.addEventListener('click', clickHandler);\n cleanup.handlers.push({ element: dot, event: 'click', handler: clickHandler });\n\n paginationContainer.appendChild(dot);\n });\n }\n\n function setupKeyboardNav(instance: any) {\n const keydownHandler = (e: KeyboardEvent) => {\n if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault();\n navigateSlide(instance, -1);\n } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault();\n navigateSlide(instance, 1);\n }\n };\n\n instance.wrapper.addEventListener('keydown', keydownHandler);\n instance.wrapper.setAttribute('tabindex', '0');\n cleanup.handlers.push({ element: instance.wrapper, event: 'keydown', handler: keydownHandler });\n }\n\n // Main initialization loop\n wrappers.forEach((wrapper) => {\n // Find template list inside wrapper\n const templateList = querySelector(config, 'template-list', wrapper);\n if (!templateList) {\n console.warn('[comparison] No template list found in wrapper');\n return;\n }\n\n const templateItemsSelector = getSelector(config, 'template-item');\n const templateItems = Array.from(templateList.querySelectorAll(templateItemsSelector));\n\n if (templateItems.length === 0) {\n console.warn('[comparison] No template items found');\n return;\n }\n\n // Add simple aria-live for screen reader announcements\n wrapper.setAttribute('aria-live', 'polite');\n wrapper.setAttribute('aria-label', 'Before and after image comparison');\n\n // Get references to visible elements and cache them\n const imageWrapper = querySelector(config, 'image-wrapper', wrapper) as HTMLElement;\n const slider = querySelector(config, 'slider', wrapper) as HTMLElement;\n const beforeImageWrapper = querySelector(config, 'before-image', wrapper) as HTMLElement;\n const afterImageWrapper = querySelector(config, 'after-image', wrapper) as HTMLElement;\n const nameElement = querySelector(config, 'name', wrapper) as HTMLElement;\n const descElement = querySelector(config, 'description', wrapper) as HTMLElement;\n\n if (!imageWrapper || !slider || !afterImageWrapper) {\n const missing = [];\n if (!imageWrapper) missing.push('image-wrapper (data-hs-comparison=\"image-wrapper\")');\n if (!slider) missing.push('slider (data-hs-comparison=\"slider\")');\n if (!afterImageWrapper) missing.push('after-image (data-hs-comparison-image=\"after\")');\n console.warn(`[comparison] Missing required elements: ${missing.join(', ')}`);\n return;\n }\n\n const instance = {\n wrapper: wrapper as HTMLElement,\n templateItems,\n currentIndex: 0,\n mode: 'split',\n sliderPosition: 50,\n imageWrapper,\n slider,\n beforeImage: beforeImageWrapper?.querySelector('img') as HTMLImageElement,\n afterImage: afterImageWrapper?.querySelector('img') as HTMLImageElement,\n nameElement,\n descElement,\n draggable: null as any,\n };\n\n // Load first slide\n loadSlide(instance, 0);\n\n // Set initial clip path to 50%\n updateClipPath(wrapper as HTMLElement, 50);\n\n // Setup GSAP Draggable for slider\n if (Draggable) {\n const draggableInstance = Draggable.create(slider, {\n type: 'x',\n bounds: imageWrapper,\n onDrag: function () {\n const rect = imageWrapper.getBoundingClientRect();\n const sliderRect = slider.getBoundingClientRect();\n const x = sliderRect.left - rect.left;\n const percentage = Math.max(0, Math.min(100, (x / rect.width) * 100));\n\n updateClipPath(wrapper as HTMLElement, percentage);\n instance.sliderPosition = percentage;\n },\n });\n\n cleanup.draggables.push(draggableInstance);\n instance.draggable = draggableInstance[0]; // Store reference to draggable\n\n // Click on image wrapper to jump slider\n const clickHandler = (e: MouseEvent) => {\n if (instance.mode !== 'split') return;\n\n const rect = imageWrapper.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const percentage = Math.max(0, Math.min(100, (clickX / rect.width) * 100));\n\n // Calculate target position accounting for slider's center point\n // Draggable starts from slider's initial position (50% = center)\n const centerX = rect.width / 2;\n const offsetX = clickX - centerX;\n\n // Update Draggable's x position from center\n if (instance.draggable) {\n gsap.set(slider, { x: offsetX });\n instance.draggable.update();\n }\n\n updateClipPath(wrapper as HTMLElement, percentage);\n instance.sliderPosition = percentage;\n };\n\n imageWrapper.addEventListener('click', clickHandler);\n cleanup.handlers.push({ element: imageWrapper, event: 'click', handler: clickHandler });\n }\n\n // Setup mode buttons\n const modeButtons = wrapper.querySelectorAll(`[${config.attributes.properties.modeType}]`);\n modeButtons.forEach((modeWrapper) => {\n const mode = modeWrapper.getAttribute(config.attributes.properties.modeType);\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const button = (modeWrapper.querySelector(clickableSelector) || modeWrapper) as HTMLElement;\n\n // Set initial state\n if (mode === instance.mode) {\n modeWrapper.classList.add(globalConfig.classes.active);\n }\n\n const clickHandler = (e: Event) => {\n e.preventDefault();\n setMode(instance, mode!);\n };\n\n button.addEventListener('click', clickHandler);\n cleanup.handlers.push({ element: button, event: 'click', handler: clickHandler });\n });\n\n // Setup navigation\n setupNavigation(instance, wrapper as HTMLElement);\n\n // Setup pagination\n const paginationContainer = querySelector(config, 'pagination', wrapper);\n if (paginationContainer && templateItems.length > 1) {\n setupPagination(instance, paginationContainer as HTMLElement);\n }\n\n // Setup keyboard navigation\n setupKeyboardNav(instance);\n });\n\n return {\n result: `comparison initialized (${wrappers.length} instances)`,\n destroy: () => {\n // Kill all draggables\n cleanup.draggables.forEach((d) => {\n if (d && d[0] && d[0].kill) d[0].kill();\n });\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler);\n });\n\n // Clear arrays\n cleanup.draggables.length = 0;\n cleanup.handlers.length = 0;\n },\n };\n}\n"],"names":["async","init","config","gsapLib","getGsap","result","gsap","Draggable","warnMissingDependencies","wrappers","querySelectorAll","cleanup","draggables","handlers","templateNameSelector","getSelector","templateDescSelector","templateBeforeImageSelector","templateAfterImageSelector","updateClipPath","wrapper","percentage","style","setProperty","cssVariables","clip","loadSlide","instance","index","templateItem","templateItems","templateName","querySelector","nameElement","textContent","templateDesc","descElement","templateBeforeImage","beforeImage","src","alt","templateAfterImage","afterImage","applyMode","currentIndex","paginationContainer","activeClass","globalConfig","classes","active","Array","from","children","forEach","dot","dotIndex","classList","add","remove","updatePagination","slider","mode","display","sliderPosition","navigateSlide","direction","newIndex","maxIndex","length","targetIndex","templateList","console","warn","templateItemsSelector","setAttribute","imageWrapper","beforeImageWrapper","afterImageWrapper","missing","push","join","draggable","draggableInstance","create","type","bounds","onDrag","rect","getBoundingClientRect","x","left","Math","max","min","width","clickHandler","e","clickX","clientX","offsetX","set","update","addEventListener","element","event","handler","attributes","properties","modeType","modeWrapper","getAttribute","clickableSelector","clickable","button","preventDefault","modeButtons","btn","setMode","leftArrow","navType","rightArrow","setupNavigation","templateDot","innerHTML","_","cloneNode","appendChild","setupPagination","keydownHandler","key","setupKeyboardNav","destroy","d","kill","removeEventListener"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{p as e,g as t,w as r}from"./hs-modalManager-H_YegPAO.js";import"../main.js";const n='[data-hs-anim="counter"]';async function o(){if(e())return{result:"counter skipped - prefers-reduced-motion enabled"};const o=t("counter");if(!o)return{result:"counter skipped - GSAP not loaded"};const{gsap:i,ScrollTrigger:s}=o;if(!s)return r("counter",["ScrollTrigger"],"error"),{result:"counter skipped - ScrollTrigger not loaded"};i.registerPlugin(s);const l=Array.from(document.querySelectorAll(n)),u={timelines:[],scrollTriggers:[]};return l.forEach(e=>{const t=e,r=t.textContent?.trim()||"",n=function(e){const t=e.replace(/,/g,"").match(/([^\d.]*)(\d*\.?\d+)(.*)/);return t?{prefix:t[1]||"",number:parseFloat(t[2]),suffix:t[3]||""}:{prefix:"",number:0,suffix:""}}(r),o=(n.number.toString().split(".")[1]||"").length,l=r.includes(",");t.setAttribute("aria-live","polite"),t.setAttribute("aria-atomic","true");const a={value:0},c=i.timeline({paused:!0});c.to(a,{value:n.number,duration:3,ease:"power4.out",onUpdate:function(){const e=a.value;let r=o>0?e.toFixed(o):Math.round(e).toString();l&&(r=r.replace(/\B(?=(\d{3})+(?!\d))/g,",")),t.textContent=`${n.prefix}${r}${n.suffix}`},onComplete:function(){t.textContent=r}}),u.timelines.push(c);const g=s.create({trigger:e,start:"top bottom",once:!0,onEnter:()=>{c.play()}});u.scrollTriggers.push(g)}),{result:`counter initialized (${l.length} instances)`,destroy:()=>{u.timelines.forEach(e=>{e&&e.kill()}),u.scrollTriggers.forEach(e=>{e&&e.kill()}),u.timelines.length=0,u.scrollTriggers.length=0}}}export{o as init};
2
- //# sourceMappingURL=hs-counter-Bfh7_P60.js.map
@@ -1,2 +0,0 @@
1
- import{p as e,g as t,w as r}from"./hs-modalManager-H_YegPAO.js";import"../main.js";const n='[data-hs-anim="counter"]';async function o(){if(e())return{result:"counter skipped - prefers-reduced-motion enabled"};const o=t("counter");if(!o)return{result:"counter skipped - GSAP not loaded"};const{gsap:i,ScrollTrigger:s}=o;if(!s)return r("counter",["ScrollTrigger"],"error"),{result:"counter skipped - ScrollTrigger not loaded"};i.registerPlugin(s);const l=Array.from(document.querySelectorAll(n)),u={timelines:[],scrollTriggers:[]};return l.forEach(e=>{const t=e,r=t.textContent?.trim()||"",n=function(e){const t=e.replace(/,/g,"").match(/([^\d.]*)(\d*\.?\d+)(.*)/);return t?{prefix:t[1]||"",number:parseFloat(t[2]),suffix:t[3]||""}:{prefix:"",number:0,suffix:""}}(r),o=(n.number.toString().split(".")[1]||"").length,l=r.includes(",");t.setAttribute("aria-live","polite"),t.setAttribute("aria-atomic","true");const a={value:0},c=i.timeline({paused:!0});c.to(a,{value:n.number,duration:3,ease:"power4.out",onUpdate:function(){const e=a.value;let r=o>0?e.toFixed(o):Math.round(e).toString();l&&(r=r.replace(/\B(?=(\d{3})+(?!\d))/g,",")),t.textContent=`${n.prefix}${r}${n.suffix}`},onComplete:function(){t.textContent=r}}),u.timelines.push(c);const g=s.create({trigger:e,start:"top bottom",once:!0,onEnter:()=>{c.play()}});u.scrollTriggers.push(g)}),{result:`counter initialized (${l.length} instances)`,destroy:()=>{u.timelines.forEach(e=>{e&&e.kill()}),u.scrollTriggers.forEach(e=>{e&&e.kill()}),u.timelines.length=0,u.scrollTriggers.length=0}}}export{o as init};
2
- //# sourceMappingURL=hs-counter-Bfh7_P60.js.map
@@ -1,2 +0,0 @@
1
- import{c as a}from"../main.js";const s=a._global.cssVars,e={state:s.prefix+s.state.name,clip:s.prefix+s.clip?.name};export{e as c};
2
- //# sourceMappingURL=hs-cssVariables-BjuwJfDJ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hs-cssVariables-BjuwJfDJ.js","sources":["../../src/utils/cssVariables.ts"],"sourcesContent":["/**\n * CSS Variables\n *\n * Centralized CSS variable names built from global config.\n * Ensures consistency across all modules.\n *\n * Usage:\n * import cssVariables from '@utils/cssVariables';\n * const value = getComputedStyle(el).getPropertyValue(cssVariables.state);\n */\n\nimport config from '@config';\n\nconst globalCssVars = config._global.cssVars as {\n prefix: string;\n state: { name: string };\n clip?: { name: string };\n};\n\nconst cssVariables = {\n prefix: globalCssVars.prefix,\n state: globalCssVars.prefix + globalCssVars.state.name,\n clip: globalCssVars.prefix + (globalCssVars.clip?.name || 'clip'),\n};\n\nexport default cssVariables;\n"],"names":["globalCssVars","config","_global","cssVars","cssVariables","state","prefix","name","clip"],"mappings":"+BAaA,MAAMA,EAAgBC,EAAOC,QAAQC,QAM/BC,EAAe,CAEnBC,MAAOL,EAAcM,OAASN,EAAcK,MAAME,KAClDC,KAAMR,EAAcM,OAAUN,EAAcQ,MAAMD"}
@@ -1,2 +0,0 @@
1
- import{c as e}from"../main.js";import{a as t,q as n,g as r}from"./hs-attributeSelector-6pGcDBo-.js";import{g as s,p as o,s as a,a as i,o as l,c}from"./hs-modalManager-H_YegPAO.js";import{g as u}from"./hs-utils-CKm6QhLw.js";import{c as d}from"./hs-cssVariables-BjuwJfDJ.js";async function f(e){let n=null,r=null;function a(n){const r=n.target.closest('a[href^="#"]');if(!r)return;const a=r.getAttribute("href");if(!a||"#"===a)return;const i=a.substring(1),l=document.getElementById(i);if(l){n.preventDefault(),history.replaceState&&history.replaceState(null,null,`#${l.id}`);!function(e,t=0){if(!e)return;const n=s("smooth-scroll",!1);if(o()||!n){const n=e.getBoundingClientRect().top+window.scrollY-t;return window.scrollTo(0,n),e.setAttribute("tabindex","-1"),void e.focus({preventScroll:!0})}n.gsap.to(window,{duration:1,scrollTo:{y:e,offsetY:t},ease:"power2.out",onComplete:function(){e.setAttribute("tabindex","-1"),e.focus({preventScroll:!0})}})}(l,function(){const n=t(e,"offset-proxy");if(console.log("[smooth-scroll] Proxy element:",n),n&&n instanceof HTMLElement){const e=getComputedStyle(n).top,t=parseFloat(e)||0;return console.log("[smooth-scroll] Computed top:",e,"-> offset:",t),t}return console.log("[smooth-scroll] No proxy element found, using offset: 0"),0}())}}"undefined"!=typeof $&&$(document).off("click.wf-scroll"),document.documentElement.style.scrollBehavior="auto",document.body.style.scrollBehavior="auto",n=a,r=e=>{"Enter"!==e.key&&" "!==e.key||a(e)},document.addEventListener("click",n),document.addEventListener("keydown",r);const i=s("smooth-scroll",!1);return i&&document.body.scrollHeight>window.innerHeight&&(i.gsap.set(window,{scrollTo:1}),i.gsap.set(window,{scrollTo:0})),{result:"autoInit-smooth-scroll initialized",destroy:()=>{n&&(document.removeEventListener("click",n),n=null),r&&(document.removeEventListener("keydown",r),r=null),document.documentElement.style.scrollBehavior="",document.body.style.scrollBehavior=""}}}let p=null;function v(e){p=e;const s={observers:[],handlers:[]};return function(e,s){const o=n(p,"wrapper"),l=[];o.forEach(n=>{const o=r(u.clickable,"button"),c=n.querySelector(o),d=t(p,"list",n);if(!c||!d)return void console.warn("[dropdown] Dropdown wrapper missing required elements:",n);const f=n.getAttribute("data-hs-nav-dropdown-type")||"hover",v=n.querySelector('[data-hs-height="element"]'),m=v?v.parentElement:null,h=c.textContent?.trim()||"dropdown",y=h.toLowerCase().replace(/[^a-z0-9\s]/g,"").replace(/\s+/g,"-").replace(/^-+|-+$/g,"").substring(0,50);const b=`navbar-dropdown-${y}-toggle`,g=`navbar-dropdown-${y}-list`;c.id=b,c.setAttribute("aria-haspopup","menu"),c.setAttribute("aria-expanded","false"),c.setAttribute("aria-controls",g),d.id=g,d.setAttribute("role","menu"),d.inert=!0;const w=Array.from(d.querySelectorAll(o));w.forEach((e,t)=>{if(e.setAttribute("role","menuitem"),e.setAttribute("tabindex","-1"),0===t){const t=c.textContent?.trim()||"menu";e.getAttribute("aria-label")||e.setAttribute("aria-label",`${e.textContent?.trim()}, ${t} submenu`)}});let A=-1;function E(){return n.classList.contains(u.classes.active)}function k(){const e=E();"true"===c.getAttribute("aria-expanded")&&!e&&d.contains(document.activeElement)&&c.focus(),c.setAttribute("aria-expanded",e?"true":"false"),d.inert=!e,w.forEach(t=>{t.setAttribute("tabindex",e?"0":"-1")}),e||(A=-1),i(m,e,{duration:"hover"===f?200:300,ease:"power2.inOut"})}a(m,E()),k();const L=new MutationObserver(()=>{k()});if(L.observe(n,{attributes:!0,attributeFilter:["class"]}),e(L),"hover"===f){l.push(n);const e=()=>{n.classList.add("is-active")},t=()=>{n.classList.remove("is-active")};s(n,"mouseenter",e),s(n,"mouseleave",t);s(c,"keydown",e=>{"ArrowDown"===e.key?(e.preventDefault(),E()||(n.classList.add(u.classes.active),w.length>0&&setTimeout(()=>{A=0,w[0].focus()},100))):" "===e.key||"Enter"===e.key?(e.preventDefault(),E()?n.classList.remove(u.classes.active):(n.classList.add(u.classes.active),w.length>0&&setTimeout(()=>{A=0,w[0].focus()},100))):"ArrowUp"===e.key?(e.preventDefault(),E()||(n.classList.add(u.classes.active),w.length>0&&setTimeout(()=>{A=w.length-1,w[A].focus()},100))):"Escape"===e.key&&(e.preventDefault(),E()&&n.classList.remove(u.classes.active))});const r=e=>{E()&&n.contains(document.activeElement)&&("ArrowDown"===e.key?(e.preventDefault(),A<w.length-1&&(A++,w[A].focus())):"ArrowUp"===e.key?(e.preventDefault(),0===A?(n.classList.remove(u.classes.active),c.focus(),A=-1):A>0?(A--,w[A].focus()):(c.focus(),A=-1)):"Escape"===e.key&&(e.preventDefault(),n.classList.remove("is-active")))};s(n,"keydown",r)}else if("click"===f){s(c,"click",e=>{e.preventDefault(),n.classList.toggle(u.classes.active)});s(c,"keydown",e=>{" "===e.key||"Enter"===e.key?(e.preventDefault(),n.classList.toggle(u.classes.active)):"Escape"===e.key&&(e.preventDefault(),E()&&n.classList.remove(u.classes.active))})}});const c=e=>{l.forEach(t=>{t.classList.contains("is-active")&&!t.contains(e.target)&&t.classList.remove("is-active")})};l.length>0&&s(document.body,"focusin",c)}(e=>{s.observers.push(e)},(e,t,n,r)=>{e.addEventListener(t,n,r),s.handlers.push({element:e,event:t,handler:n,options:r})}),{result:"dropdown initialized",destroy:()=>{s.observers.forEach(e=>e.disconnect()),s.observers.length=0,s.handlers.forEach(({element:e,event:t,handler:n,options:r})=>{e.removeEventListener(t,n,r)}),s.handlers.length=0,p=null}}}function m(e,s){const o={observers:[],handlers:[],state:{focusTrapHandler:null}},f=e=>{o.observers.push(e)};return function(d,f){const p=n(e,"button"),v=t(e,"wrapper");if(!p.length||!v)return;const m=s?t(s,"wrapper"):null,h=`menu-${Date.now()}`;v.id=h,v.setAttribute("role","dialog"),v.setAttribute("aria-modal","true"),v.inert=!0;const y=v.querySelector('[data-hs-height="element"]'),b=y?y.parentElement:null;p.forEach(e=>{e.setAttribute("aria-expanded","false"),e.setAttribute("aria-controls",h),e.setAttribute("aria-label","Open navigation menu");let n=null,y=!1;function g(){return e.classList.contains(u.classes.active)}function w(){const o=g(),a="true"===e.getAttribute("aria-expanded");o&&!a?(l(),v.classList.add(u.classes.active),v.inert=!1,m&&m.classList.add("hs-menu-open"),p.forEach(e=>{e.setAttribute("aria-expanded","true"),e.setAttribute("aria-label","Close navigation menu")}),b&&i(b,!0,{duration:300,ease:"power2.inOut"}),n=function(){const e=s?t(s,"wrapper"):document.querySelector('[data-hs-nav="wrapper"]');if(!e)return;const n=t=>{if("Tab"===t.key){const n=r(u.clickable,"button"),s=Array.from(e.querySelectorAll(n)),o=e.querySelectorAll('input, select, textarea, [tabindex]:not([tabindex="-1"])'),a=[...s,...Array.from(o)],i=a[0],l=a[a.length-1];t.shiftKey?document.activeElement===i&&(t.preventDefault(),l.focus()):document.activeElement===l&&(t.preventDefault(),i.focus())}};return document.addEventListener("keydown",n),n}(),y&&(setTimeout(()=>{const e=r(u.clickable,"button"),t=Array.from(v.querySelectorAll(e));if("last"===y){const e=t[t.length-1];e&&e.focus()}else{const e=t[0];e&&e.focus()}},100),y=!1)):!o&&a&&(v.contains(document.activeElement)&&e.focus(),c(),v.classList.remove(u.classes.active),v.inert=!0,m&&m.classList.remove("hs-menu-open"),p.forEach(e=>{e.setAttribute("aria-expanded","false"),e.setAttribute("aria-label","Open navigation menu")}),b&&i(b,!1,{duration:300,ease:"power2.inOut"}),function(e){e&&document.removeEventListener("keydown",e)}(n),n=null)}b&&a(b,g()),w();const A=new MutationObserver(()=>{w()});A.observe(e,{attributes:!0,attributeFilter:["class"]}),d(A);f(e,"click",function(t){t.preventDefault(),e.classList.toggle("is-active")});f(e,"keydown",function(t){" "===t.key||"Enter"===t.key?(t.preventDefault(),y=!0,e.classList.toggle(u.classes.active)):"ArrowDown"===t.key?(t.preventDefault(),g()||(y=!0,e.classList.add(u.classes.active))):"ArrowUp"===t.key?(t.preventDefault(),g()||(y="last",e.classList.add(u.classes.active))):"Escape"===t.key&&(t.preventDefault(),g()&&e.classList.remove(u.classes.active))}),o.state.focusTrapHandler=n})}(f,(e,t,n,r)=>{e.addEventListener(t,n,r),o.handlers.push({element:e,event:t,handler:n,options:r})}),function(n){const r=t(e,"wrapper");if(!r)return;let s=null;function o(){const e=window.getComputedStyle(r).getPropertyValue(d.state).trim();if(s===u.cssVars.state.values.active&&e===u.cssVars.state.values.inactive){const e=document.querySelector('[data-hs-nav-menu="button"]');e&&"true"===e.getAttribute("aria-expanded")&&e&&e.classList.remove("is-active")}s=e}const a=new ResizeObserver(o);a.observe(r),n(a),o()}(f),{result:"menu initialized",destroy:()=>{o.state.focusTrapHandler&&(document.removeEventListener("keydown",o.state.focusTrapHandler),o.state.focusTrapHandler=null),o.observers.forEach(e=>e.disconnect()),o.observers.length=0,o.handlers.forEach(({element:e,event:t,handler:n,options:r})=>{e.removeEventListener(t,n,r)}),o.handlers.length=0,document.body.classList.remove("u-overflow-hidden")}}}function h(e,n){const s={handlers:[]},o=(e,t,n,r)=>{e.addEventListener(t,n,r),s.handlers.push({element:e,event:t,handler:n,options:r})};return o(document,"keydown",e=>{if("ArrowLeft"!==e.key&&"ArrowRight"!==e.key)return;const s=n?t(n.menu,"wrapper"):document.querySelector('[data-hs-nav-menu="wrapper"]');if(s&&s.contains(document.activeElement))return;const o=n?t(n,"wrapper"):document.querySelector('[data-hs-nav="wrapper"]');if(!o||!o.contains(document.activeElement))return;const a=o.querySelector(`.${u.classes.active}[data-hs-nav-dropdown]`);if(a&&a.contains(document.activeElement))return;e.preventDefault();const i=r(u.clickable,"button"),l=Array.from(o.querySelectorAll(i)),c=Array.from(l).filter(e=>{if("-1"===e.getAttribute("tabindex"))return!1;if(e.closest('[role="menu"]'))return!1;const t=n?n.menu.attributes.elements.wrapper.primary.split("=")[0]:"data-hs-nav-menu";if(e.closest(`[${t}="wrapper"]`))return!1;const r=n?n.attributes.elements["skip-link"].primary.split("=")[0]:"data-hs-nav";if(e.closest(`[${r}="skip-link"]`))return!1;const s=window.getComputedStyle(e),a=e;if("none"===s.display||"hidden"===s.visibility||"0"===s.opacity||0===a.offsetWidth||0===a.offsetHeight)return!1;let i=e.parentElement;for(;i&&i!==o;){const e=window.getComputedStyle(i),t=i;if("none"===e.display||"hidden"===e.visibility||0===t.offsetWidth||0===t.offsetHeight)return!1;i=i.parentElement}return!0}),d=c.indexOf(document.activeElement);-1!==d&&("ArrowRight"===e.key?d<c.length-1&&c[d+1].focus():d>0&&c[d-1].focus())}),function(e){const s=n?t(n.menu,"wrapper"):document.querySelector('[data-hs-nav-menu="wrapper"]');if(!s)return;let o=-1;e(s,"keydown",e=>{const a=function(){const e=r(u.clickable,"button"),t=Array.from(s.querySelectorAll(e));return Array.from(t).filter(e=>{let t=e;for(;t&&t!==s;){if(t.inert)return!1;t=t.parentElement}return!0})}();if(0===a.length)return;const i=document.activeElement;if(o=a.indexOf(i),"ArrowDown"===e.key)e.preventDefault(),o<a.length-1&&(o+=1,a[o].focus());else if("ArrowUp"===e.key)e.preventDefault(),o>0&&(o-=1,a[o].focus());else if("ArrowRight"===e.key){if(e.preventDefault(),i&&"BUTTON"===i.tagName&&i.hasAttribute("aria-controls")){return void("true"===i.getAttribute("aria-expanded")||i.click())}}else if("ArrowLeft"===e.key){if(e.preventDefault(),i&&"BUTTON"===i.tagName&&i.hasAttribute("aria-controls")){return void("true"===i.getAttribute("aria-expanded")&&i.click())}}else if("Home"===e.key)e.preventDefault(),o=0,a[0].focus();else if("End"===e.key)e.preventDefault(),o=a.length-1,a[a.length-1].focus();else if(" "===e.key&&i&&"A"===i.tagName)e.preventDefault();else if("Escape"===e.key){const e=n?t(n.menu,"button"):document.querySelector('[data-hs-nav-menu="button"]');e&&(e.click(),e.focus())}})}(o),{result:"arrow-navigation initialized",destroy:()=>{s.handlers.forEach(({element:e,event:t,handler:n,options:r})=>{e.removeEventListener(t,n,r)}),s.handlers.length=0}}}async function y(e){const t={destroyFunctions:[]},n=await Promise.allSettled([v(e.dropdown),m(e.menu,e),h(e["arrow-navigation"],e)]);n.forEach(e=>{"fulfilled"===e.status&&e.value?.destroy&&t.destroyFunctions.push(e.value.destroy)});const r=n.filter(e=>"fulfilled"===e.status).length,s=n.length-r;return s>0&&console.warn(`[navbar] ${r}/${n.length} functions loaded successfully. ${s} failed but won't affect other functions.`),{result:"navbar initialized",destroy:()=>{t.destroyFunctions.forEach(e=>{try{e()}catch(t){console.error("[navbar] Error during cleanup:",t)}}),t.destroyFunctions.length=0}}}function b(e){const s={observers:[],handlers:[]};return function(s,o){const l=n(e,"wrapper");if(0===l.length)return 0;let c=0;l.forEach((n,l)=>{const d=t(e,"toggle",n),f=t(e,"content",n);if(!d||!f)return;c++;const p=`[${u.attributes.height}="${u.attributes.heightValue}"]`,v=n.querySelector(p),m=v?v.parentElement:f,h=`hs-accordion-btn-${l}`,y=`hs-accordion-content-${l}`,b=n.getAttribute(e.attributes.properties.open),g=n.getAttribute(e.attributes.properties.closed),w=b&&g;let A=[];if(w){const t=r(e,"state");A=Array.from(d.querySelectorAll(t))}function E(){return n.classList.contains(u.classes.active)}function k(){const e=E();if("true"===d.getAttribute("aria-expanded")&&!e&&f.contains(document.activeElement)){d.focus()}d.setAttribute("aria-expanded",e?"true":"false");var t;f.inert=!e,w&&A.length>0&&(t=e?b:g,w&&A.forEach(e=>{e.textContent=t})),i(m,e,{duration:300,ease:"power2.inOut"})}d.setAttribute("id",h),f.setAttribute("id",y),f.setAttribute("role","region"),f.setAttribute("aria-labelledby",h),d.setAttribute("aria-controls",y);const L=n.getAttribute(e.attributes.properties.default);L&&"open"===L.toLowerCase()&&n.classList.add(u.classes.active),a(m,E()),k();o(d,"click",e=>{e.preventDefault(),n.classList.toggle(u.classes.active)});const D=new MutationObserver(()=>{k()});D.observe(n,{attributes:!0,attributeFilter:["class"]}),s(D)})}(e=>s.observers.push(e),(e,t,n,r)=>{e.addEventListener(t,n,r),s.handlers.push({element:e,event:t,handler:n,options:r})}),{result:"accordion initialized",destroy:()=>{s.observers.forEach(e=>e.disconnect()),s.observers.length=0,s.handlers.forEach(({element:e,event:t,handler:n,options:r})=>{e.removeEventListener(t,n,r)}),s.handlers.length=0}}}async function g(){const t={destroyFunctions:[]},n=e.default,r=[f(n["smooth-scroll"]),y(n.navbar),b(n.accordion)],s=await Promise.allSettled(r);s.forEach(e=>{"fulfilled"===e.status&&e.value?.destroy&&t.destroyFunctions.push(e.value.destroy)});const o=s.filter(e=>"fulfilled"===e.status).length,a=s.length-o;return a>0&&console.warn(`[default] ${o}/${s.length} functions loaded successfully. ${a} failed but won't affect other functions.`),{result:"default initialized",destroy:()=>{t.destroyFunctions.forEach(e=>{try{e()}catch(t){console.error("[default] Error during cleanup:",t)}}),t.destroyFunctions.length=0}}}export{g as init};
2
- //# sourceMappingURL=hs-default-CLmDRb9d.js.map
@@ -1,2 +0,0 @@
1
- import{c as e}from"../main.js";import{a as t,q as n,g as r}from"./hs-attributeSelector-6pGcDBo-.js";import{g as s,p as o,s as a,a as i,o as l,c}from"./hs-modalManager-H_YegPAO.js";import{g as u}from"./hs-utils-CKm6QhLw.js";import{c as d}from"./hs-cssVariables-BjuwJfDJ.js";async function f(e){let n=null,r=null;function a(n){const r=n.target.closest('a[href^="#"]');if(!r)return;const a=r.getAttribute("href");if(!a||"#"===a)return;const i=a.substring(1),l=document.getElementById(i);if(l){n.preventDefault(),history.replaceState&&history.replaceState(null,null,`#${l.id}`);!function(e,t=0){if(!e)return;const n=s("smooth-scroll",!1);if(o()||!n){const n=e.getBoundingClientRect().top+window.scrollY-t;return window.scrollTo(0,n),e.setAttribute("tabindex","-1"),void e.focus({preventScroll:!0})}n.gsap.to(window,{duration:1,scrollTo:{y:e,offsetY:t},ease:"power2.out",onComplete:function(){e.setAttribute("tabindex","-1"),e.focus({preventScroll:!0})}})}(l,function(){const n=t(e,"offset-proxy");if(console.log("[smooth-scroll] Proxy element:",n),n&&n instanceof HTMLElement){const e=getComputedStyle(n).top,t=parseFloat(e)||0;return console.log("[smooth-scroll] Computed top:",e,"-> offset:",t),t}return console.log("[smooth-scroll] No proxy element found, using offset: 0"),0}())}}"undefined"!=typeof $&&$(document).off("click.wf-scroll"),document.documentElement.style.scrollBehavior="auto",document.body.style.scrollBehavior="auto",n=a,r=e=>{"Enter"!==e.key&&" "!==e.key||a(e)},document.addEventListener("click",n),document.addEventListener("keydown",r);const i=s("smooth-scroll",!1);return i&&document.body.scrollHeight>window.innerHeight&&(i.gsap.set(window,{scrollTo:1}),i.gsap.set(window,{scrollTo:0})),{result:"autoInit-smooth-scroll initialized",destroy:()=>{n&&(document.removeEventListener("click",n),n=null),r&&(document.removeEventListener("keydown",r),r=null),document.documentElement.style.scrollBehavior="",document.body.style.scrollBehavior=""}}}let p=null;function v(e){p=e;const s={observers:[],handlers:[]};return function(e,s){const o=n(p,"wrapper"),l=[];o.forEach(n=>{const o=r(u.clickable,"button"),c=n.querySelector(o),d=t(p,"list",n);if(!c||!d)return void console.warn("[dropdown] Dropdown wrapper missing required elements:",n);const f=n.getAttribute("data-hs-nav-dropdown-type")||"hover",v=n.querySelector('[data-hs-height="element"]'),m=v?v.parentElement:null,h=c.textContent?.trim()||"dropdown",y=h.toLowerCase().replace(/[^a-z0-9\s]/g,"").replace(/\s+/g,"-").replace(/^-+|-+$/g,"").substring(0,50);const b=`navbar-dropdown-${y}-toggle`,g=`navbar-dropdown-${y}-list`;c.id=b,c.setAttribute("aria-haspopup","menu"),c.setAttribute("aria-expanded","false"),c.setAttribute("aria-controls",g),d.id=g,d.setAttribute("role","menu"),d.inert=!0;const w=Array.from(d.querySelectorAll(o));w.forEach((e,t)=>{if(e.setAttribute("role","menuitem"),e.setAttribute("tabindex","-1"),0===t){const t=c.textContent?.trim()||"menu";e.getAttribute("aria-label")||e.setAttribute("aria-label",`${e.textContent?.trim()}, ${t} submenu`)}});let A=-1;function E(){return n.classList.contains(u.classes.active)}function k(){const e=E();"true"===c.getAttribute("aria-expanded")&&!e&&d.contains(document.activeElement)&&c.focus(),c.setAttribute("aria-expanded",e?"true":"false"),d.inert=!e,w.forEach(t=>{t.setAttribute("tabindex",e?"0":"-1")}),e||(A=-1),i(m,e,{duration:"hover"===f?200:300,ease:"power2.inOut"})}a(m,E()),k();const L=new MutationObserver(()=>{k()});if(L.observe(n,{attributes:!0,attributeFilter:["class"]}),e(L),"hover"===f){l.push(n);const e=()=>{n.classList.add("is-active")},t=()=>{n.classList.remove("is-active")};s(n,"mouseenter",e),s(n,"mouseleave",t);s(c,"keydown",e=>{"ArrowDown"===e.key?(e.preventDefault(),E()||(n.classList.add(u.classes.active),w.length>0&&setTimeout(()=>{A=0,w[0].focus()},100))):" "===e.key||"Enter"===e.key?(e.preventDefault(),E()?n.classList.remove(u.classes.active):(n.classList.add(u.classes.active),w.length>0&&setTimeout(()=>{A=0,w[0].focus()},100))):"ArrowUp"===e.key?(e.preventDefault(),E()||(n.classList.add(u.classes.active),w.length>0&&setTimeout(()=>{A=w.length-1,w[A].focus()},100))):"Escape"===e.key&&(e.preventDefault(),E()&&n.classList.remove(u.classes.active))});const r=e=>{E()&&n.contains(document.activeElement)&&("ArrowDown"===e.key?(e.preventDefault(),A<w.length-1&&(A++,w[A].focus())):"ArrowUp"===e.key?(e.preventDefault(),0===A?(n.classList.remove(u.classes.active),c.focus(),A=-1):A>0?(A--,w[A].focus()):(c.focus(),A=-1)):"Escape"===e.key&&(e.preventDefault(),n.classList.remove("is-active")))};s(n,"keydown",r)}else if("click"===f){s(c,"click",e=>{e.preventDefault(),n.classList.toggle(u.classes.active)});s(c,"keydown",e=>{" "===e.key||"Enter"===e.key?(e.preventDefault(),n.classList.toggle(u.classes.active)):"Escape"===e.key&&(e.preventDefault(),E()&&n.classList.remove(u.classes.active))})}});const c=e=>{l.forEach(t=>{t.classList.contains("is-active")&&!t.contains(e.target)&&t.classList.remove("is-active")})};l.length>0&&s(document.body,"focusin",c)}(e=>{s.observers.push(e)},(e,t,n,r)=>{e.addEventListener(t,n,r),s.handlers.push({element:e,event:t,handler:n,options:r})}),{result:"dropdown initialized",destroy:()=>{s.observers.forEach(e=>e.disconnect()),s.observers.length=0,s.handlers.forEach(({element:e,event:t,handler:n,options:r})=>{e.removeEventListener(t,n,r)}),s.handlers.length=0,p=null}}}function m(e,s){const o={observers:[],handlers:[],state:{focusTrapHandler:null}},f=e=>{o.observers.push(e)};return function(d,f){const p=n(e,"button"),v=t(e,"wrapper");if(!p.length||!v)return;const m=s?t(s,"wrapper"):null,h=`menu-${Date.now()}`;v.id=h,v.setAttribute("role","dialog"),v.setAttribute("aria-modal","true"),v.inert=!0;const y=v.querySelector('[data-hs-height="element"]'),b=y?y.parentElement:null;p.forEach(e=>{e.setAttribute("aria-expanded","false"),e.setAttribute("aria-controls",h),e.setAttribute("aria-label","Open navigation menu");let n=null,y=!1;function g(){return e.classList.contains(u.classes.active)}function w(){const o=g(),a="true"===e.getAttribute("aria-expanded");o&&!a?(l(),v.classList.add(u.classes.active),v.inert=!1,m&&m.classList.add("hs-menu-open"),p.forEach(e=>{e.setAttribute("aria-expanded","true"),e.setAttribute("aria-label","Close navigation menu")}),b&&i(b,!0,{duration:300,ease:"power2.inOut"}),n=function(){const e=s?t(s,"wrapper"):document.querySelector('[data-hs-nav="wrapper"]');if(!e)return;const n=t=>{if("Tab"===t.key){const n=r(u.clickable,"button"),s=Array.from(e.querySelectorAll(n)),o=e.querySelectorAll('input, select, textarea, [tabindex]:not([tabindex="-1"])'),a=[...s,...Array.from(o)],i=a[0],l=a[a.length-1];t.shiftKey?document.activeElement===i&&(t.preventDefault(),l.focus()):document.activeElement===l&&(t.preventDefault(),i.focus())}};return document.addEventListener("keydown",n),n}(),y&&(setTimeout(()=>{const e=r(u.clickable,"button"),t=Array.from(v.querySelectorAll(e));if("last"===y){const e=t[t.length-1];e&&e.focus()}else{const e=t[0];e&&e.focus()}},100),y=!1)):!o&&a&&(v.contains(document.activeElement)&&e.focus(),c(),v.classList.remove(u.classes.active),v.inert=!0,m&&m.classList.remove("hs-menu-open"),p.forEach(e=>{e.setAttribute("aria-expanded","false"),e.setAttribute("aria-label","Open navigation menu")}),b&&i(b,!1,{duration:300,ease:"power2.inOut"}),function(e){e&&document.removeEventListener("keydown",e)}(n),n=null)}b&&a(b,g()),w();const A=new MutationObserver(()=>{w()});A.observe(e,{attributes:!0,attributeFilter:["class"]}),d(A);f(e,"click",function(t){t.preventDefault(),e.classList.toggle("is-active")});f(e,"keydown",function(t){" "===t.key||"Enter"===t.key?(t.preventDefault(),y=!0,e.classList.toggle(u.classes.active)):"ArrowDown"===t.key?(t.preventDefault(),g()||(y=!0,e.classList.add(u.classes.active))):"ArrowUp"===t.key?(t.preventDefault(),g()||(y="last",e.classList.add(u.classes.active))):"Escape"===t.key&&(t.preventDefault(),g()&&e.classList.remove(u.classes.active))}),o.state.focusTrapHandler=n})}(f,(e,t,n,r)=>{e.addEventListener(t,n,r),o.handlers.push({element:e,event:t,handler:n,options:r})}),function(n){const r=t(e,"wrapper");if(!r)return;let s=null;function o(){const e=window.getComputedStyle(r).getPropertyValue(d.state).trim();if(s===u.cssVars.state.values.active&&e===u.cssVars.state.values.inactive){const e=document.querySelector('[data-hs-nav-menu="button"]');e&&"true"===e.getAttribute("aria-expanded")&&e&&e.classList.remove("is-active")}s=e}const a=new ResizeObserver(o);a.observe(r),n(a),o()}(f),{result:"menu initialized",destroy:()=>{o.state.focusTrapHandler&&(document.removeEventListener("keydown",o.state.focusTrapHandler),o.state.focusTrapHandler=null),o.observers.forEach(e=>e.disconnect()),o.observers.length=0,o.handlers.forEach(({element:e,event:t,handler:n,options:r})=>{e.removeEventListener(t,n,r)}),o.handlers.length=0,document.body.classList.remove("u-overflow-hidden")}}}function h(e,n){const s={handlers:[]},o=(e,t,n,r)=>{e.addEventListener(t,n,r),s.handlers.push({element:e,event:t,handler:n,options:r})};return o(document,"keydown",e=>{if("ArrowLeft"!==e.key&&"ArrowRight"!==e.key)return;const s=n?t(n.menu,"wrapper"):document.querySelector('[data-hs-nav-menu="wrapper"]');if(s&&s.contains(document.activeElement))return;const o=n?t(n,"wrapper"):document.querySelector('[data-hs-nav="wrapper"]');if(!o||!o.contains(document.activeElement))return;const a=o.querySelector(`.${u.classes.active}[data-hs-nav-dropdown]`);if(a&&a.contains(document.activeElement))return;e.preventDefault();const i=r(u.clickable,"button"),l=Array.from(o.querySelectorAll(i)),c=Array.from(l).filter(e=>{if("-1"===e.getAttribute("tabindex"))return!1;if(e.closest('[role="menu"]'))return!1;const t=n?n.menu.attributes.elements.wrapper.primary.split("=")[0]:"data-hs-nav-menu";if(e.closest(`[${t}="wrapper"]`))return!1;const r=n?n.attributes.elements["skip-link"].primary.split("=")[0]:"data-hs-nav";if(e.closest(`[${r}="skip-link"]`))return!1;const s=window.getComputedStyle(e),a=e;if("none"===s.display||"hidden"===s.visibility||"0"===s.opacity||0===a.offsetWidth||0===a.offsetHeight)return!1;let i=e.parentElement;for(;i&&i!==o;){const e=window.getComputedStyle(i),t=i;if("none"===e.display||"hidden"===e.visibility||0===t.offsetWidth||0===t.offsetHeight)return!1;i=i.parentElement}return!0}),d=c.indexOf(document.activeElement);-1!==d&&("ArrowRight"===e.key?d<c.length-1&&c[d+1].focus():d>0&&c[d-1].focus())}),function(e){const s=n?t(n.menu,"wrapper"):document.querySelector('[data-hs-nav-menu="wrapper"]');if(!s)return;let o=-1;e(s,"keydown",e=>{const a=function(){const e=r(u.clickable,"button"),t=Array.from(s.querySelectorAll(e));return Array.from(t).filter(e=>{let t=e;for(;t&&t!==s;){if(t.inert)return!1;t=t.parentElement}return!0})}();if(0===a.length)return;const i=document.activeElement;if(o=a.indexOf(i),"ArrowDown"===e.key)e.preventDefault(),o<a.length-1&&(o+=1,a[o].focus());else if("ArrowUp"===e.key)e.preventDefault(),o>0&&(o-=1,a[o].focus());else if("ArrowRight"===e.key){if(e.preventDefault(),i&&"BUTTON"===i.tagName&&i.hasAttribute("aria-controls")){return void("true"===i.getAttribute("aria-expanded")||i.click())}}else if("ArrowLeft"===e.key){if(e.preventDefault(),i&&"BUTTON"===i.tagName&&i.hasAttribute("aria-controls")){return void("true"===i.getAttribute("aria-expanded")&&i.click())}}else if("Home"===e.key)e.preventDefault(),o=0,a[0].focus();else if("End"===e.key)e.preventDefault(),o=a.length-1,a[a.length-1].focus();else if(" "===e.key&&i&&"A"===i.tagName)e.preventDefault();else if("Escape"===e.key){const e=n?t(n.menu,"button"):document.querySelector('[data-hs-nav-menu="button"]');e&&(e.click(),e.focus())}})}(o),{result:"arrow-navigation initialized",destroy:()=>{s.handlers.forEach(({element:e,event:t,handler:n,options:r})=>{e.removeEventListener(t,n,r)}),s.handlers.length=0}}}async function y(e){const t={destroyFunctions:[]},n=await Promise.allSettled([v(e.dropdown),m(e.menu,e),h(e["arrow-navigation"],e)]);n.forEach(e=>{"fulfilled"===e.status&&e.value?.destroy&&t.destroyFunctions.push(e.value.destroy)});const r=n.filter(e=>"fulfilled"===e.status).length,s=n.length-r;return s>0&&console.warn(`[navbar] ${r}/${n.length} functions loaded successfully. ${s} failed but won't affect other functions.`),{result:"navbar initialized",destroy:()=>{t.destroyFunctions.forEach(e=>{try{e()}catch(t){console.error("[navbar] Error during cleanup:",t)}}),t.destroyFunctions.length=0}}}function b(e){const s={observers:[],handlers:[]};return function(s,o){const l=n(e,"wrapper");if(0===l.length)return 0;let c=0;l.forEach((n,l)=>{const d=t(e,"toggle",n),f=t(e,"content",n);if(!d||!f)return;c++;const p=`[${u.attributes.height}="${u.attributes.heightValue}"]`,v=n.querySelector(p),m=v?v.parentElement:f,h=`hs-accordion-btn-${l}`,y=`hs-accordion-content-${l}`,b=n.getAttribute(e.attributes.properties.open),g=n.getAttribute(e.attributes.properties.closed),w=b&&g;let A=[];if(w){const t=r(e,"state");A=Array.from(d.querySelectorAll(t))}function E(){return n.classList.contains(u.classes.active)}function k(){const e=E();if("true"===d.getAttribute("aria-expanded")&&!e&&f.contains(document.activeElement)){d.focus()}d.setAttribute("aria-expanded",e?"true":"false");var t;f.inert=!e,w&&A.length>0&&(t=e?b:g,w&&A.forEach(e=>{e.textContent=t})),i(m,e,{duration:300,ease:"power2.inOut"})}d.setAttribute("id",h),f.setAttribute("id",y),f.setAttribute("role","region"),f.setAttribute("aria-labelledby",h),d.setAttribute("aria-controls",y);const L=n.getAttribute(e.attributes.properties.default);L&&"open"===L.toLowerCase()&&n.classList.add(u.classes.active),a(m,E()),k();o(d,"click",e=>{e.preventDefault(),n.classList.toggle(u.classes.active)});const D=new MutationObserver(()=>{k()});D.observe(n,{attributes:!0,attributeFilter:["class"]}),s(D)})}(e=>s.observers.push(e),(e,t,n,r)=>{e.addEventListener(t,n,r),s.handlers.push({element:e,event:t,handler:n,options:r})}),{result:"accordion initialized",destroy:()=>{s.observers.forEach(e=>e.disconnect()),s.observers.length=0,s.handlers.forEach(({element:e,event:t,handler:n,options:r})=>{e.removeEventListener(t,n,r)}),s.handlers.length=0}}}async function g(){const t={destroyFunctions:[]},n=e.default,r=[f(n["smooth-scroll"]),y(n.navbar),b(n.accordion)],s=await Promise.allSettled(r);s.forEach(e=>{"fulfilled"===e.status&&e.value?.destroy&&t.destroyFunctions.push(e.value.destroy)});const o=s.filter(e=>"fulfilled"===e.status).length,a=s.length-o;return a>0&&console.warn(`[default] ${o}/${s.length} functions loaded successfully. ${a} failed but won't affect other functions.`),{result:"default initialized",destroy:()=>{t.destroyFunctions.forEach(e=>{try{e()}catch(t){console.error("[default] Error during cleanup:",t)}}),t.destroyFunctions.length=0}}}export{g as init};
2
- //# sourceMappingURL=hs-default-CLmDRb9d.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hs-default-CLmDRb9d.js","sources":["../../src/modules/default/functions/smooth-scroll.ts","../../src/modules/default/functions/navbar/functions/dropdown.ts","../../src/modules/default/functions/navbar/functions/menu.ts","../../src/modules/default/functions/navbar/functions/arrow-navigation.ts","../../src/modules/default/functions/navbar/navbar.ts","../../src/modules/default/functions/accordion.ts","../../src/modules/default/default.ts"],"sourcesContent":["/**\n * Smooth Scroll\n *\n * Provides smooth animated scrolling for anchor links with optional offset.\n * Automatically intercepts anchor link clicks, animates scroll with GSAP,\n * and handles accessibility (focus management, keyboard navigation).\n *\n * Features:\n * - Auto-detects and handles all anchor links (a[href^=\"#\"])\n * - Dynamic offset via proxy element's computed CSS top value\n * - GSAP animation with reduced motion support\n * - Keyboard navigation (Enter/Space on links)\n * - Focus management for screen readers\n * - Disables Webflow's native scroll behavior\n * - Triggers scroll-based animations on init\n *\n * Structure:\n * Optional offset proxy element with CSS top value:\n * <div data-hs-scroll-offset=\"proxy\" style=\"top: var(--_hs---scroll-offset)\"></div>\n */\n\nimport { getGsap, prefersReducedMotion, querySelector } from '@utils';\n\n// Type declaration for jQuery (runtime dependency)\ndeclare const $: any;\n\ninterface ModuleConfig {\n attributes: {\n elements: {\n 'offset-proxy': {\n primary: string;\n aliases: string[];\n };\n };\n };\n}\n\nexport async function init(config: ModuleConfig) {\n // Store event handlers for cleanup\n let clickHandler: ((e: Event) => void) | null = null;\n let keydownHandler: ((e: KeyboardEvent) => void) | null = null;\n\n // Disable Webflow's native scroll behavior (jQuery-based)\n // This runs immediately since default module already waits for IX3\n if (typeof $ !== 'undefined') {\n $(document).off('click.wf-scroll');\n }\n\n // Disable CSS smooth scrolling\n document.documentElement.style.scrollBehavior = 'auto';\n document.body.style.scrollBehavior = 'auto';\n\n function getScrollOffset(): number {\n // Find element with data-hs-scroll-offset=\"proxy\" and read its computed top value\n const proxyElement = querySelector(config, 'offset-proxy');\n console.log('[smooth-scroll] Proxy element:', proxyElement);\n if (proxyElement && proxyElement instanceof HTMLElement) {\n const computedTop = getComputedStyle(proxyElement).top;\n const offset = parseFloat(computedTop) || 0;\n console.log('[smooth-scroll] Computed top:', computedTop, '-> offset:', offset);\n return offset;\n }\n console.log('[smooth-scroll] No proxy element found, using offset: 0');\n return 0;\n }\n\n // Smooth scroll to element with offset\n function scrollToElement(target: HTMLElement, offset = 0): void {\n if (!target) return;\n\n const gsapLib = getGsap('smooth-scroll', false);\n\n // Skip animation if user prefers reduced motion or GSAP not available\n if (prefersReducedMotion() || !gsapLib) {\n const targetPosition = target.getBoundingClientRect().top + window.scrollY - offset;\n window.scrollTo(0, targetPosition);\n target.setAttribute('tabindex', '-1');\n target.focus({ preventScroll: true });\n return;\n }\n\n gsapLib.gsap.to(window, {\n duration: 1,\n scrollTo: {\n y: target,\n offsetY: offset,\n },\n ease: 'power2.out',\n onComplete: function () {\n target.setAttribute('tabindex', '-1');\n target.focus({ preventScroll: true });\n },\n });\n }\n\n function handleAnchorActivation(e: Event): void {\n const link = (e.target as Element).closest('a[href^=\"#\"]');\n if (!link) return;\n\n const href = link.getAttribute('href');\n if (!href || href === '#') return;\n\n const targetId = href.substring(1);\n const targetElement = document.getElementById(targetId);\n\n if (targetElement) {\n e.preventDefault();\n if (history.replaceState) {\n history.replaceState(null, null, `#${targetElement.id}`);\n }\n const offset = getScrollOffset();\n scrollToElement(targetElement, offset);\n }\n }\n\n // Handle anchor link clicks and keyboard activation\n function handleAnchorClicks(): void {\n clickHandler = handleAnchorActivation;\n keydownHandler = (e: KeyboardEvent): void => {\n if (e.key === 'Enter' || e.key === ' ') {\n handleAnchorActivation(e);\n }\n };\n\n document.addEventListener('click', clickHandler);\n document.addEventListener('keydown', keydownHandler);\n }\n\n // Initialize anchor link handling\n handleAnchorClicks();\n\n // Mock scroll to trigger scroll-based animations\n const gsapLib = getGsap('smooth-scroll', false);\n if (gsapLib && document.body.scrollHeight > window.innerHeight) {\n gsapLib.gsap.set(window, { scrollTo: 1 });\n gsapLib.gsap.set(window, { scrollTo: 0 });\n }\n\n return {\n result: 'autoInit-smooth-scroll initialized',\n destroy: () => {\n // Remove event listeners\n if (clickHandler) {\n document.removeEventListener('click', clickHandler);\n clickHandler = null;\n }\n if (keydownHandler) {\n document.removeEventListener('keydown', keydownHandler);\n keydownHandler = null;\n }\n\n // Re-enable CSS smooth scrolling\n document.documentElement.style.scrollBehavior = '';\n document.body.style.scrollBehavior = '';\n },\n };\n}\n","/**\n * Dropdown\n *\n * Provides accessible navigation dropdowns with hover or click behavior.\n * Handles ARIA states, keyboard navigation, optional height animation,\n * and automatic focus management for both desktop hover and mobile click modes.\n *\n * Features:\n * - Hover mode: Desktop hover with full keyboard navigation (ArrowDown/Up, Escape)\n * - Click mode: Mobile/accordion click-only with simple keyboard (Space, Enter, Escape)\n * - Automatic ARIA state management (aria-expanded, aria-controls, role=menu)\n * - Optional height animation via data-hs-height wrapper\n * - Inert state for collapsed dropdowns (non-interactive)\n * - MutationObserver syncs ARIA with visual state changes\n * - Focus management for keyboard and screen reader users\n *\n * Structure:\n * <div data-hs-nav-dropdown=\"wrapper\" data-hs-nav-dropdown-type=\"hover\">\n * <button data-hs-clickable=\"button\">Menu</button>\n * <div data-hs-nav-dropdown=\"list\" role=\"menu\">\n * <a href=\"#\" data-hs-clickable=\"button\" role=\"menuitem\">Item 1</a>\n * <a href=\"#\" data-hs-clickable=\"button\" role=\"menuitem\">Item 2</a>\n * </div>\n * </div>\n */\n\nimport {\n querySelectorAll,\n querySelector,\n getSelector,\n globalConfig,\n animateHeight,\n setHeight,\n} from '@utils';\n\ninterface EventHandler {\n element: Element;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface ModuleConfig {\n attributes: {\n elements: Record<string, { primary: string; aliases?: string[] }>;\n properties?: Record<string, string>;\n };\n}\n\n// Module-scoped config (set during init)\nlet moduleConfig: ModuleConfig | null = null;\n\nexport function init(config: ModuleConfig) {\n // Store config at module scope for helper functions\n moduleConfig = config;\n\n const cleanup = {\n observers: [] as MutationObserver[],\n handlers: [] as EventHandler[],\n };\n\n const addObserver = (observer: MutationObserver): void => {\n cleanup.observers.push(observer);\n };\n const addHandler = (\n element: Element,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n function sanitizeForID(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/^-+|-+$/g, '')\n .substring(0, 50);\n }\n\n function setupDropdown(\n addObserver: (observer: MutationObserver) => void,\n addHandler: (\n element: Element,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): void {\n const dropdownWrappers = querySelectorAll(moduleConfig as any, 'wrapper');\n const hoverDropdowns: Element[] = []; // Track hover-type dropdowns for focus-loss handling\n\n dropdownWrappers.forEach((wrapper) => {\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const toggle = wrapper.querySelector(clickableSelector);\n const dropdownList = querySelector(moduleConfig as any, 'list', wrapper);\n\n if (!toggle || !dropdownList) {\n console.warn('[dropdown] Dropdown wrapper missing required elements:', wrapper);\n return;\n }\n\n // Get dropdown type (hover or click)\n const type = wrapper.getAttribute('data-hs-nav-dropdown-type') || 'hover';\n\n // Check for visual height wrapper (contains data-hs-height=\"element\")\n // If found, animate that instead of the list (list is for ARIA only)\n // If not found, no height animation (optional feature)\n const heightWrapper = wrapper.querySelector('[data-hs-height=\"element\"]');\n const animationTarget = heightWrapper ? heightWrapper.parentElement : null;\n\n const toggleText = toggle.textContent?.trim() || 'dropdown';\n const sanitizedText = sanitizeForID(toggleText);\n const toggleId = `navbar-dropdown-${sanitizedText}-toggle`;\n const listId = `navbar-dropdown-${sanitizedText}-list`;\n\n toggle.id = toggleId;\n toggle.setAttribute('aria-haspopup', 'menu');\n toggle.setAttribute('aria-expanded', 'false');\n toggle.setAttribute('aria-controls', listId);\n\n dropdownList.id = listId;\n dropdownList.setAttribute('role', 'menu');\n (dropdownList as HTMLElement).inert = true; // Initial state: hidden and non-interactive\n\n const menuItems = Array.from(dropdownList.querySelectorAll(clickableSelector));\n menuItems.forEach((item, index) => {\n item.setAttribute('role', 'menuitem');\n item.setAttribute('tabindex', '-1');\n\n // Add context for first item to help screen readers understand dropdown content\n if (index === 0) {\n const toggleText = toggle.textContent?.trim() || 'menu';\n const existingLabel = item.getAttribute('aria-label');\n if (!existingLabel) {\n item.setAttribute('aria-label', `${item.textContent?.trim()}, ${toggleText} submenu`);\n }\n }\n });\n\n let currentMenuItemIndex = -1;\n\n // Function to check if dropdown is open\n function isDropdownOpen() {\n return wrapper.classList.contains(globalConfig.classes.active);\n }\n\n // Update ARIA states based on current visual state\n function updateARIAStates() {\n const isOpen = isDropdownOpen();\n const wasOpen = toggle.getAttribute('aria-expanded') === 'true';\n\n // If dropdown is closing (was open, now closed), focus the toggle first\n if (wasOpen && !isOpen && dropdownList.contains(document.activeElement)) {\n (toggle as HTMLElement).focus();\n }\n\n toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');\n (dropdownList as HTMLElement).inert = !isOpen; // Enable/disable interaction based on state\n menuItems.forEach((item) => {\n item.setAttribute('tabindex', isOpen ? '0' : '-1');\n });\n\n if (!isOpen) {\n currentMenuItemIndex = -1;\n }\n\n // Animate height wrapper (visual container, not ARIA list)\n animateHeight(animationTarget, isOpen, {\n duration: type === 'hover' ? 200 : 300,\n ease: 'power2.inOut',\n });\n }\n\n // Set initial height without animation\n setHeight(animationTarget, isDropdownOpen());\n\n // Set initial ARIA states\n updateARIAStates();\n\n // Monitor for class changes and update ARIA states\n const observer = new MutationObserver(() => {\n updateARIAStates();\n });\n\n observer.observe(wrapper, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n addObserver(observer);\n\n // ========================================\n // TYPE-SPECIFIC HANDLERS\n // ========================================\n\n if (type === 'hover') {\n // HOVER TYPE: Desktop behavior with hover + full keyboard navigation\n\n // Track this as a hover dropdown for focus-loss handling\n hoverDropdowns.push(wrapper);\n\n // Hover handlers\n const mouseenterHandler = () => {\n wrapper.classList.add('is-active');\n };\n\n const mouseleaveHandler = () => {\n wrapper.classList.remove('is-active');\n };\n\n addHandler(wrapper, 'mouseenter', mouseenterHandler);\n addHandler(wrapper, 'mouseleave', mouseleaveHandler);\n\n // Full keyboard navigation for toggle\n const toggleKeydownHandler = (e: KeyboardEvent): void => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n\n if (!isDropdownOpen()) {\n wrapper.classList.add(globalConfig.classes.active);\n\n // Focus first menu item after brief delay\n if (menuItems.length > 0) {\n setTimeout(() => {\n currentMenuItemIndex = 0;\n (menuItems[0] as HTMLElement).focus();\n }, 100);\n }\n }\n } else if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n\n if (!isDropdownOpen()) {\n wrapper.classList.add(globalConfig.classes.active);\n\n // Focus first menu item after brief delay\n if (menuItems.length > 0) {\n setTimeout(() => {\n currentMenuItemIndex = 0;\n (menuItems[0] as HTMLElement).focus();\n }, 100);\n }\n } else {\n wrapper.classList.remove(globalConfig.classes.active);\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n\n if (!isDropdownOpen()) {\n wrapper.classList.add(globalConfig.classes.active);\n\n // Focus last menu item after brief delay\n if (menuItems.length > 0) {\n setTimeout(() => {\n currentMenuItemIndex = menuItems.length - 1;\n (menuItems[currentMenuItemIndex] as HTMLElement).focus();\n }, 100);\n }\n }\n } else if (e.key === 'Escape') {\n e.preventDefault();\n\n if (isDropdownOpen()) {\n wrapper.classList.remove(globalConfig.classes.active);\n }\n }\n };\n\n addHandler(toggle, 'keydown', toggleKeydownHandler);\n\n // Handle navigation within open dropdown (arrow keys)\n const dropdownKeydownHandler = (e: KeyboardEvent): void => {\n if (!isDropdownOpen()) return;\n if (!wrapper.contains(document.activeElement)) return;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (currentMenuItemIndex < menuItems.length - 1) {\n currentMenuItemIndex++;\n (menuItems[currentMenuItemIndex] as HTMLElement).focus();\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (currentMenuItemIndex === 0) {\n wrapper.classList.remove(globalConfig.classes.active);\n (toggle as HTMLElement).focus();\n currentMenuItemIndex = -1;\n } else if (currentMenuItemIndex > 0) {\n currentMenuItemIndex--;\n (menuItems[currentMenuItemIndex] as HTMLElement).focus();\n } else {\n (toggle as HTMLElement).focus();\n currentMenuItemIndex = -1;\n }\n } else if (e.key === 'Escape') {\n e.preventDefault();\n wrapper.classList.remove('is-active');\n }\n };\n\n addHandler(wrapper, 'keydown', dropdownKeydownHandler);\n } else if (type === 'click') {\n // CLICK TYPE: Mobile/accordion behavior with click only + simple keyboard\n\n // Click handler to toggle\n const clickHandler = (e: MouseEvent): void => {\n e.preventDefault();\n wrapper.classList.toggle(globalConfig.classes.active);\n };\n\n addHandler(toggle, 'click', clickHandler);\n\n // Simple keyboard navigation (NO arrow keys)\n const toggleKeydownHandler = (e: KeyboardEvent): void => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n wrapper.classList.toggle(globalConfig.classes.active);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n if (isDropdownOpen()) {\n wrapper.classList.remove(globalConfig.classes.active);\n }\n }\n };\n\n addHandler(toggle, 'keydown', toggleKeydownHandler);\n }\n });\n\n // Close hover dropdowns when focus leaves (click dropdowns stay open)\n const focusinHandler = (e: FocusEvent): void => {\n hoverDropdowns.forEach((wrapper) => {\n if (wrapper.classList.contains('is-active') && !wrapper.contains(e.target as Node)) {\n wrapper.classList.remove('is-active');\n }\n });\n };\n\n // Only add handler if there are hover dropdowns\n if (hoverDropdowns.length > 0) {\n addHandler(document.body, 'focusin', focusinHandler);\n }\n }\n\n setupDropdown(addObserver, addHandler);\n\n return {\n result: 'dropdown initialized',\n destroy: () => {\n // Disconnect all observers\n cleanup.observers.forEach((obs) => obs.disconnect());\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n\n // Clear module config\n moduleConfig = null;\n },\n };\n}\n","/**\n * Menu\n *\n * Provides mobile menu button and modal behavior for navigation.\n * Handles menu toggle with modal overlay, focus trap, ARIA states,\n * and automatic inert management for collapsed dropdowns in the menu.\n *\n * Features:\n * - Modal behavior with overlay and body scroll lock\n * - Focus trap keeps keyboard navigation within open menu\n * - ARIA state management (aria-expanded, aria-controls)\n * - Inert state for collapsed menu dropdowns (non-interactive)\n * - MutationObserver syncs inert state with dropdown visual state\n * - Escape key to close menu\n * - Returns focus to menu button on close\n *\n * Structure:\n * <button data-hs-nav-menu=\"button\">Menu</button>\n * <div data-hs-nav-menu=\"wrapper\" aria-labelledby=\"menu-button\">\n * <!-- Menu content with dropdowns -->\n * </div>\n */\n\nimport {\n querySelectorAll,\n querySelector,\n getSelector,\n globalConfig,\n cssVariables,\n animateHeight,\n setHeight,\n openModal,\n closeModal,\n} from '@utils';\n\ninterface EventHandler {\n element: Element | Document;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface ModuleConfig {\n attributes: {\n elements: Record<string, { primary: string; aliases?: string[] }>;\n };\n}\n\nexport function init(config: ModuleConfig, navbarConfig?: ModuleConfig) {\n const cleanup = {\n observers: [] as MutationObserver[],\n handlers: [] as EventHandler[],\n state: {\n focusTrapHandler: null as ((e: KeyboardEvent) => void) | null,\n },\n };\n\n const addObserver = (observer: MutationObserver): void => {\n cleanup.observers.push(observer);\n };\n const addHandler = (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n function createFocusTrap(menuButton: Element): ((e: KeyboardEvent) => void) | undefined {\n const navbarWrapper = navbarConfig\n ? querySelector(navbarConfig as any, 'wrapper')\n : document.querySelector('[data-hs-nav=\"wrapper\"]');\n\n if (!navbarWrapper) return;\n\n const focusTrapHandler = (e: KeyboardEvent): void => {\n if (e.key === 'Tab') {\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const clickableItems = Array.from(navbarWrapper.querySelectorAll(clickableSelector));\n const formElements = navbarWrapper.querySelectorAll(\n 'input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n );\n const focusableArray = [...clickableItems, ...Array.from(formElements)];\n const firstElement = focusableArray[0];\n const lastElement = focusableArray[focusableArray.length - 1];\n\n if (e.shiftKey) {\n // Shift+Tab: moving backwards\n if (document.activeElement === firstElement) {\n e.preventDefault();\n (lastElement as HTMLElement).focus();\n }\n } else {\n // Tab: moving forwards\n if (document.activeElement === lastElement) {\n e.preventDefault();\n (firstElement as HTMLElement).focus();\n }\n }\n }\n };\n\n document.addEventListener('keydown', focusTrapHandler);\n return focusTrapHandler;\n }\n\n function removeFocusTrap(focusTrapHandler: ((e: KeyboardEvent) => void) | null): void {\n if (focusTrapHandler) {\n document.removeEventListener('keydown', focusTrapHandler);\n }\n }\n\n function setupMenu(\n addObserver: (observer: MutationObserver) => void,\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): void {\n const menuButtons = querySelectorAll(config as any, 'button');\n const menu = querySelector(config as any, 'wrapper');\n\n if (!menuButtons.length || !menu) return;\n\n // Get navbar wrapper for styling (e.g., backdrop blur)\n const navbarWrapper = navbarConfig ? querySelector(navbarConfig as any, 'wrapper') : null;\n\n const menuId = `menu-${Date.now()}`;\n\n menu.id = menuId;\n menu.setAttribute('role', 'dialog');\n menu.setAttribute('aria-modal', 'true');\n (menu as HTMLElement).inert = true; // Initial state: hidden and non-interactive\n\n // Check for visual height wrapper (optional)\n // Only look for a descendant with data-hs-height=\"element\"\n // If found, animate that element's parent. If not found, no height animation.\n const heightWrapper = menu.querySelector('[data-hs-height=\"element\"]');\n const animationTarget = heightWrapper ? heightWrapper.parentElement : null;\n\n menuButtons.forEach((menuButton) => {\n menuButton.setAttribute('aria-expanded', 'false');\n menuButton.setAttribute('aria-controls', menuId);\n menuButton.setAttribute('aria-label', 'Open navigation menu');\n\n let focusTrapHandler: ((e: KeyboardEvent) => void) | null = null;\n let shouldAutoFocus: boolean | 'last' = false; // Track if menu should autofocus (keyboard activation)\n\n // Check if menu is open by looking for is-active class on button\n function isMenuOpen() {\n return menuButton.classList.contains(globalConfig.classes.active);\n }\n\n // Update ARIA states and menu behavior based on current visual state\n function updateMenuState() {\n const isOpen = isMenuOpen();\n const wasOpen = menuButton.getAttribute('aria-expanded') === 'true';\n\n if (isOpen && !wasOpen) {\n // Opening\n openModal();\n\n // Add is-active to menu wrapper and enable interaction\n menu.classList.add(globalConfig.classes.active);\n (menu as HTMLElement).inert = false; // Enable interaction\n\n // Add class to navbar wrapper for styling (e.g., backdrop blur)\n if (navbarWrapper) {\n navbarWrapper.classList.add('hs-menu-open');\n }\n\n menuButtons.forEach((btn) => {\n btn.setAttribute('aria-expanded', 'true');\n btn.setAttribute('aria-label', 'Close navigation menu');\n });\n\n // Animate height if configured\n if (animationTarget) {\n animateHeight(animationTarget, true, { duration: 300, ease: 'power2.inOut' });\n }\n\n // Create focus trap for navbar\n focusTrapHandler = createFocusTrap(menuButton);\n\n // Only autofocus for keyboard activation\n if (shouldAutoFocus) {\n setTimeout(() => {\n const menuClickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const allElements = Array.from(menu.querySelectorAll(menuClickableSelector));\n\n if (shouldAutoFocus === 'last') {\n // Focus last item (ArrowUp)\n const lastElement = allElements[allElements.length - 1];\n if (lastElement) {\n (lastElement as HTMLElement).focus();\n }\n } else {\n // Focus first item (Space/Enter/ArrowDown)\n const firstElement = allElements[0];\n if (firstElement) {\n (firstElement as HTMLElement).focus();\n }\n }\n }, 100);\n shouldAutoFocus = false; // Reset flag\n }\n } else if (!isOpen && wasOpen) {\n // Closing - focus button BEFORE updating ARIA\n if (menu.contains(document.activeElement)) {\n (menuButton as HTMLElement).focus();\n }\n\n // Now update ARIA and visual state\n closeModal();\n\n // Remove is-active from menu wrapper and disable interaction\n menu.classList.remove(globalConfig.classes.active);\n (menu as HTMLElement).inert = true; // Disable interaction\n\n // Remove class from navbar wrapper\n if (navbarWrapper) {\n navbarWrapper.classList.remove('hs-menu-open');\n }\n\n menuButtons.forEach((btn) => {\n btn.setAttribute('aria-expanded', 'false');\n btn.setAttribute('aria-label', 'Open navigation menu');\n });\n\n // Animate height if configured\n if (animationTarget) {\n animateHeight(animationTarget, false, { duration: 300, ease: 'power2.inOut' });\n }\n\n // Remove focus trap\n removeFocusTrap(focusTrapHandler);\n focusTrapHandler = null;\n }\n }\n\n // Set initial height without animation (if configured)\n if (animationTarget) {\n setHeight(animationTarget, isMenuOpen());\n }\n\n // Set initial ARIA states\n updateMenuState();\n\n // Monitor for class changes on button and update menu state\n const observer = new MutationObserver(() => {\n updateMenuState();\n });\n\n observer.observe(menuButton, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n addObserver(observer);\n\n // Click handler\n const clickHandler = function (e) {\n e.preventDefault();\n menuButton.classList.toggle('is-active');\n };\n\n addHandler(menuButton, 'click', clickHandler);\n\n // Keyboard navigation (dialog/modal pattern)\n const keydownHandler = function (e) {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n shouldAutoFocus = true; // Set flag for keyboard activation\n menuButton.classList.toggle(globalConfig.classes.active);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (!isMenuOpen()) {\n shouldAutoFocus = true; // Open and focus first item\n menuButton.classList.add(globalConfig.classes.active);\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (!isMenuOpen()) {\n shouldAutoFocus = 'last'; // Open and focus last item\n menuButton.classList.add(globalConfig.classes.active);\n }\n } else if (e.key === 'Escape') {\n e.preventDefault();\n\n if (isMenuOpen()) {\n menuButton.classList.remove(globalConfig.classes.active);\n }\n }\n };\n\n addHandler(menuButton, 'keydown', keydownHandler);\n\n // Store focus trap handler for cleanup\n cleanup.state.focusTrapHandler = focusTrapHandler;\n });\n }\n\n function setupMenuDisplayObserver(addObserver) {\n const menu = querySelector(config, 'wrapper');\n if (!menu) return;\n\n let previousState = null;\n\n function handleStateChange() {\n const computedStyle = window.getComputedStyle(menu);\n const currentState = computedStyle.getPropertyValue(cssVariables.state).trim();\n\n // Detect state change from active (1) to inactive (0)\n if (\n previousState === globalConfig.cssVars.state.values.active &&\n currentState === globalConfig.cssVars.state.values.inactive\n ) {\n // Get menu button to check if menu is open\n const menuButton = document.querySelector('[data-hs-nav-menu=\"button\"]');\n const isMenuOpen = menuButton && menuButton.getAttribute('aria-expanded') === 'true';\n\n // If menu is open, close it cleanly (triggers animation and proper cleanup)\n if (isMenuOpen && menuButton) {\n menuButton.classList.remove('is-active');\n }\n }\n\n previousState = currentState;\n }\n\n const stateObserver = new ResizeObserver(handleStateChange);\n stateObserver.observe(menu);\n addObserver(stateObserver);\n // Initial check\n handleStateChange();\n }\n\n setupMenu(addObserver, addHandler);\n setupMenuDisplayObserver(addObserver);\n\n return {\n result: 'menu initialized',\n destroy: () => {\n // Clean up focus trap\n if (cleanup.state.focusTrapHandler) {\n document.removeEventListener('keydown', cleanup.state.focusTrapHandler);\n cleanup.state.focusTrapHandler = null;\n }\n\n // Disconnect all observers\n cleanup.observers.forEach((obs) => obs.disconnect());\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n\n // Remove body overflow class if present\n document.body.classList.remove('u-overflow-hidden');\n },\n };\n}\n","/**\n * Arrow Navigation\n *\n * Provides keyboard arrow navigation for navbar and mobile menu.\n * Handles ArrowLeft/Right in desktop navbar and ArrowUp/Down in mobile menu,\n * plus Home/End/Escape keys for complete keyboard accessibility.\n *\n * Features:\n * - Desktop: ArrowLeft/Right to navigate navbar items\n * - Mobile menu: ArrowUp/Down, Home/End navigation\n * - Skips hidden elements and inactive dropdowns\n * - Respects inert state for collapsed accordions\n * - Escape to close mobile menu\n * - ArrowLeft/Right to collapse/expand mobile dropdowns\n */\n\nimport { getSelector, globalConfig, querySelector } from '@utils';\n\ninterface EventHandler {\n element: Element | Document;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface ModuleConfig {\n attributes: {\n elements: Record<string, { primary: string; aliases?: string[] }>;\n };\n}\n\ninterface NavbarConfig {\n attributes: {\n elements: {\n wrapper: { primary: string; aliases?: string[] };\n 'skip-link': { primary: string; aliases?: string[] };\n };\n };\n menu: ModuleConfig;\n}\n\nexport function init(config: ModuleConfig, navbarConfig?: NavbarConfig) {\n const cleanup = {\n handlers: [] as EventHandler[],\n };\n\n const addHandler = (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n function setupDesktopArrowNavigation(\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): void {\n const keydownHandler = (e: KeyboardEvent): void => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n\n const menu = navbarConfig\n ? querySelector(navbarConfig.menu as any, 'wrapper')\n : document.querySelector('[data-hs-nav-menu=\"wrapper\"]');\n if (menu && menu.contains(document.activeElement)) return;\n\n const navbar = navbarConfig\n ? querySelector(navbarConfig as any, 'wrapper')\n : document.querySelector('[data-hs-nav=\"wrapper\"]');\n\n if (!navbar || !navbar.contains(document.activeElement)) return;\n\n // Check if focus is inside an open dropdown (using .is-active class)\n const openDropdown = navbar.querySelector(\n `.${globalConfig.classes.active}[data-hs-nav-dropdown]`\n );\n if (openDropdown && openDropdown.contains(document.activeElement)) return;\n\n e.preventDefault();\n\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const allNavbarElements = Array.from(navbar.querySelectorAll(clickableSelector));\n const focusableElements = Array.from(allNavbarElements).filter((el) => {\n if (el.getAttribute('tabindex') === '-1') return false;\n\n const isInDropdownList = el.closest('[role=\"menu\"]');\n if (isInDropdownList) return false;\n\n const menuSelector = navbarConfig\n ? navbarConfig.menu.attributes.elements.wrapper.primary.split('=')[0]\n : 'data-hs-nav-menu';\n const isInMenu = el.closest(`[${menuSelector}=\"wrapper\"]`);\n if (isInMenu) return false;\n\n const skipSelector = navbarConfig\n ? navbarConfig.attributes.elements['skip-link'].primary.split('=')[0]\n : 'data-hs-nav';\n const isInSkipLink = el.closest(`[${skipSelector}=\"skip-link\"]`);\n if (isInSkipLink) return false;\n\n const computedStyle = window.getComputedStyle(el);\n const htmlEl = el as HTMLElement;\n const isHidden =\n computedStyle.display === 'none' ||\n computedStyle.visibility === 'hidden' ||\n computedStyle.opacity === '0' ||\n htmlEl.offsetWidth === 0 ||\n htmlEl.offsetHeight === 0;\n if (isHidden) return false;\n\n let parent = el.parentElement;\n while (parent && parent !== navbar) {\n const parentStyle = window.getComputedStyle(parent);\n const parentHtmlEl = parent as HTMLElement;\n const parentHidden =\n parentStyle.display === 'none' ||\n parentStyle.visibility === 'hidden' ||\n parentHtmlEl.offsetWidth === 0 ||\n parentHtmlEl.offsetHeight === 0;\n if (parentHidden) return false;\n parent = parent.parentElement;\n }\n\n return true;\n });\n\n const currentIndex = focusableElements.indexOf(document.activeElement as Element);\n if (currentIndex === -1) return;\n\n if (e.key === 'ArrowRight') {\n if (currentIndex < focusableElements.length - 1) {\n const nextIndex = currentIndex + 1;\n (focusableElements[nextIndex] as HTMLElement).focus();\n }\n } else {\n if (currentIndex > 0) {\n const nextIndex = currentIndex - 1;\n (focusableElements[nextIndex] as HTMLElement).focus();\n }\n }\n };\n\n addHandler(document, 'keydown', keydownHandler);\n }\n\n function setupMenuArrowNavigation(\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): void {\n const menuContainer = navbarConfig\n ? querySelector(navbarConfig.menu as any, 'wrapper')\n : document.querySelector('[data-hs-nav-menu=\"wrapper\"]');\n if (!menuContainer) return;\n\n function getFocusableElements(): Element[] {\n const menuClickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const allElements = Array.from(menuContainer.querySelectorAll(menuClickableSelector));\n return Array.from(allElements).filter((el) => {\n // Check if element or any ancestor is inert (inactive dropdown)\n let current: Element | null = el;\n while (current && current !== menuContainer) {\n if ((current as HTMLElement).inert) {\n return false;\n }\n current = current.parentElement;\n }\n return true;\n });\n }\n\n let currentFocusIndex = -1;\n\n const keydownHandler = (e: KeyboardEvent): void => {\n const focusableElements = getFocusableElements();\n if (focusableElements.length === 0) return;\n\n const activeElement = document.activeElement;\n currentFocusIndex = focusableElements.indexOf(activeElement as Element);\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (currentFocusIndex < focusableElements.length - 1) {\n currentFocusIndex = currentFocusIndex + 1;\n (focusableElements[currentFocusIndex] as HTMLElement).focus();\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (currentFocusIndex > 0) {\n currentFocusIndex = currentFocusIndex - 1;\n (focusableElements[currentFocusIndex] as HTMLElement).focus();\n }\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n if (\n activeElement &&\n (activeElement as HTMLElement).tagName === 'BUTTON' &&\n activeElement.hasAttribute('aria-controls')\n ) {\n const isExpanded = activeElement.getAttribute('aria-expanded') === 'true';\n if (!isExpanded) {\n (activeElement as HTMLElement).click();\n }\n return;\n }\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n if (\n activeElement &&\n (activeElement as HTMLElement).tagName === 'BUTTON' &&\n activeElement.hasAttribute('aria-controls')\n ) {\n const isExpanded = activeElement.getAttribute('aria-expanded') === 'true';\n if (isExpanded) {\n (activeElement as HTMLElement).click();\n }\n return;\n }\n } else if (e.key === 'Home') {\n e.preventDefault();\n currentFocusIndex = 0;\n (focusableElements[0] as HTMLElement).focus();\n } else if (e.key === 'End') {\n e.preventDefault();\n currentFocusIndex = focusableElements.length - 1;\n (focusableElements[focusableElements.length - 1] as HTMLElement).focus();\n } else if (e.key === ' ' && activeElement && (activeElement as HTMLElement).tagName === 'A') {\n e.preventDefault();\n } else if (e.key === 'Escape') {\n const menuButton = navbarConfig\n ? querySelector(navbarConfig.menu as any, 'button')\n : document.querySelector('[data-hs-nav-menu=\"button\"]');\n if (menuButton) {\n (menuButton as HTMLElement).click();\n (menuButton as HTMLElement).focus();\n }\n }\n };\n\n addHandler(menuContainer, 'keydown', keydownHandler);\n }\n\n setupDesktopArrowNavigation(addHandler);\n setupMenuArrowNavigation(addHandler);\n\n return {\n result: 'arrow-navigation initialized',\n destroy: () => {\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n },\n };\n}\n","/**\n * Navbar Orchestrator\n * Manages navigation functions in parallel\n *\n * Uses static imports and passes config down to functions\n */\nimport { init as dropdownInit } from './functions/dropdown.ts';\nimport { init as menuInit } from './functions/menu.ts';\nimport { init as arrowNavigationInit } from './functions/arrow-navigation.ts';\n\nexport async function init(navbarConfig) {\n const cleanup = { destroyFunctions: [] };\n\n // Load all functions in parallel - use allSettled for resilient loading\n const results = await Promise.allSettled([\n dropdownInit(navbarConfig.dropdown),\n menuInit(navbarConfig.menu, navbarConfig),\n arrowNavigationInit(navbarConfig['arrow-navigation'], navbarConfig),\n ]);\n\n // Collect destroy functions from successful inits\n results.forEach((result) => {\n if (result.status === 'fulfilled' && result.value?.destroy) {\n cleanup.destroyFunctions.push(result.value.destroy);\n }\n });\n\n // Log summary\n const succeeded = results.filter((r) => r.status === 'fulfilled').length;\n const failed = results.length - succeeded;\n if (failed > 0) {\n console.warn(\n `[navbar] ${succeeded}/${results.length} functions loaded successfully. ${failed} failed but won't affect other functions.`\n );\n }\n\n return {\n result: 'navbar initialized',\n destroy: () => {\n cleanup.destroyFunctions.forEach((destroyFn) => {\n try {\n destroyFn();\n } catch (error) {\n console.error('[navbar] Error during cleanup:', error);\n }\n });\n cleanup.destroyFunctions.length = 0;\n },\n };\n}\n","/**\n * Accordion Module\n *\n * Accessible accordion/collapsible panels with smooth height animations.\n * Syncs ARIA states with visual state via class changes and MutationObserver.\n *\n * Features:\n * - ARIA-compliant (aria-expanded, aria-controls, inert)\n * - Optional button text state swap (open/closed text)\n * - Smooth GSAP height animations\n * - Focus management (returns focus to button when closing)\n * - Default open state support\n *\n * Structure:\n * <div data-hs-accordion=\"wrapper\" data-hs-accordion-default=\"open\">\n * <button data-hs-accordion=\"toggle\">\n * Question\n * <span data-hs-accordion=\"state\">Open</span>\n * </button>\n * <div data-hs-accordion=\"content\">\n * <div data-hs-height=\"element\">Answer content</div>\n * </div>\n * </div>\n */\n\nimport {\n querySelectorAll,\n querySelector,\n getSelector,\n globalConfig,\n animateHeight,\n setHeight,\n} from '@utils';\n\ninterface EventHandler {\n element: Element | Document;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\nexport function init(config: any) {\n const cleanup = {\n observers: [] as MutationObserver[],\n handlers: [] as EventHandler[],\n };\n\n const addObserver = (observer: MutationObserver): number => cleanup.observers.push(observer);\n const addHandler = (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n function setupAccordionAccessibility(\n addObserver: (observer: MutationObserver) => number,\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): number {\n const accordionWrappers = querySelectorAll(config, 'wrapper');\n\n if (accordionWrappers.length === 0) {\n return 0;\n }\n\n let initializedCount = 0;\n\n accordionWrappers.forEach((wrapper, index) => {\n const button = querySelector(config, 'toggle', wrapper);\n const content = querySelector(config, 'content', wrapper);\n\n if (!button || !content) {\n return;\n }\n\n initializedCount++;\n\n // Check for visual height wrapper (contains data-hs-height=\"element\")\n // If found, animate that instead of the content (content is for ARIA only)\n const heightSelector = `[${globalConfig.attributes.height}=\"${globalConfig.attributes.heightValue}\"]`;\n const heightWrapper = wrapper.querySelector(heightSelector);\n const animationTarget = heightWrapper ? heightWrapper.parentElement : content;\n\n // Generate unique IDs\n const buttonId = `hs-accordion-btn-${index}`;\n const contentId = `hs-accordion-content-${index}`;\n\n // Get text state attributes (optional)\n const openText = wrapper.getAttribute(config.attributes.properties.open);\n const closedText = wrapper.getAttribute(config.attributes.properties.closed);\n const hasTextSwap = openText && closedText;\n\n // Find all state text elements (if text swap enabled)\n let stateElements = [];\n if (hasTextSwap) {\n const stateSelector = getSelector(config, 'state');\n stateElements = Array.from(button.querySelectorAll(stateSelector));\n }\n\n // Function to update state text elements\n function updateStateText(text: string): void {\n if (!hasTextSwap) return;\n stateElements.forEach((el) => {\n el.textContent = text;\n });\n }\n\n // Set initial IDs and ARIA attributes\n button.setAttribute('id', buttonId);\n content.setAttribute('id', contentId);\n content.setAttribute('role', 'region');\n content.setAttribute('aria-labelledby', buttonId);\n button.setAttribute('aria-controls', contentId);\n\n // Function to check if accordion is open\n function isAccordionOpen() {\n return wrapper.classList.contains(globalConfig.classes.active);\n }\n\n // Update ARIA states based on current visual state\n function updateARIAStates() {\n const isOpen = isAccordionOpen();\n const wasOpen = button.getAttribute('aria-expanded') === 'true';\n\n // If closing and focus is inside content, return focus first\n if (wasOpen && !isOpen && content.contains(document.activeElement)) {\n const buttonEl = button as HTMLElement;\n buttonEl.focus();\n }\n\n // Update ARIA attributes\n button.setAttribute('aria-expanded', isOpen ? 'true' : 'false');\n const contentEl = content as HTMLElement;\n contentEl.inert = !isOpen; // Use inert instead of aria-hidden\n\n // Update state text if text swap enabled\n if (hasTextSwap && stateElements.length > 0) {\n updateStateText(isOpen ? openText : closedText);\n }\n\n // Animate height wrapper (visual container, not ARIA content)\n animateHeight(animationTarget, isOpen, { duration: 300, ease: 'power2.inOut' });\n }\n\n // Handle default open state\n const defaultState = wrapper.getAttribute(config.attributes.properties.default);\n if (defaultState && defaultState.toLowerCase() === 'open') {\n wrapper.classList.add(globalConfig.classes.active);\n }\n\n // Set initial height without animation\n setHeight(animationTarget, isAccordionOpen());\n\n // Set initial state based on existing is-active class\n updateARIAStates();\n\n // Add click handler to button\n const clickHandler = (e: Event) => {\n e.preventDefault();\n wrapper.classList.toggle(globalConfig.classes.active);\n };\n addHandler(button, 'click', clickHandler);\n\n // Monitor for class changes on wrapper\n const observer = new MutationObserver(() => {\n updateARIAStates();\n });\n\n observer.observe(wrapper, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n addObserver(observer);\n });\n\n return initializedCount;\n }\n\n setupAccordionAccessibility(addObserver, addHandler);\n\n return {\n result: 'accordion initialized',\n destroy: () => {\n // Disconnect all observers\n cleanup.observers.forEach((obs) => obs.disconnect());\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n },\n };\n}\n","/**\n * Default Orchestrator\n * Manages default interactive modules in parallel (Phase 3)\n *\n * Uses static imports and passes config down to functions\n */\nimport config from '@config';\nimport { init as smoothScrollInit } from './functions/smooth-scroll.ts';\nimport { init as navbarInit } from './functions/navbar/navbar.ts';\nimport { init as accordionInit } from './functions/accordion.ts';\n\nconst CONFIG_ROOT = 'default';\n\nexport async function init() {\n const cleanup = { destroyFunctions: [] };\n const moduleConfig = config[CONFIG_ROOT];\n\n // Start all functions in parallel\n const modulePromises = [\n smoothScrollInit(moduleConfig['smooth-scroll'] as any),\n navbarInit(moduleConfig.navbar),\n accordionInit(moduleConfig.accordion),\n ];\n\n const results = await Promise.allSettled(modulePromises);\n\n // Collect destroy functions from successful inits\n results.forEach((result) => {\n if (result.status === 'fulfilled' && result.value?.destroy) {\n cleanup.destroyFunctions.push(result.value.destroy);\n }\n });\n\n // Log summary\n const succeeded = results.filter((r) => r.status === 'fulfilled').length;\n const failed = results.length - succeeded;\n if (failed > 0) {\n console.warn(\n `[default] ${succeeded}/${results.length} functions loaded successfully. ${failed} failed but won't affect other functions.`\n );\n }\n\n return {\n result: 'default initialized',\n destroy: () => {\n cleanup.destroyFunctions.forEach((destroyFn) => {\n try {\n destroyFn();\n } catch (error) {\n console.error('[default] Error during cleanup:', error);\n }\n });\n cleanup.destroyFunctions.length = 0;\n },\n };\n}\n"],"names":["async","init","config","clickHandler","keydownHandler","handleAnchorActivation","e","link","target","closest","href","getAttribute","targetId","substring","targetElement","document","getElementById","preventDefault","history","replaceState","id","offset","gsapLib","getGsap","prefersReducedMotion","targetPosition","getBoundingClientRect","top","window","scrollY","scrollTo","setAttribute","focus","preventScroll","gsap","to","duration","y","offsetY","ease","onComplete","scrollToElement","proxyElement","querySelector","console","log","HTMLElement","computedTop","getComputedStyle","parseFloat","getScrollOffset","$","off","documentElement","style","scrollBehavior","body","key","addEventListener","scrollHeight","innerHeight","set","result","destroy","removeEventListener","moduleConfig","cleanup","observers","handlers","addObserver","addHandler","dropdownWrappers","querySelectorAll","hoverDropdowns","forEach","wrapper","clickableSelector","getSelector","globalConfig","clickable","toggle","dropdownList","warn","type","heightWrapper","animationTarget","parentElement","toggleText","textContent","trim","sanitizedText","toLowerCase","replace","toggleId","listId","inert","menuItems","Array","from","item","index","currentMenuItemIndex","isDropdownOpen","classList","contains","classes","active","updateARIAStates","isOpen","activeElement","animateHeight","setHeight","observer","MutationObserver","observe","attributes","attributeFilter","push","mouseenterHandler","add","mouseleaveHandler","remove","length","setTimeout","dropdownKeydownHandler","focusinHandler","setupDropdown","element","event","handler","options","obs","disconnect","navbarConfig","state","focusTrapHandler","menuButtons","menu","navbarWrapper","menuId","Date","now","menuButton","shouldAutoFocus","isMenuOpen","updateMenuState","wasOpen","openModal","btn","clickableItems","formElements","focusableArray","firstElement","lastElement","shiftKey","createFocusTrap","menuClickableSelector","allElements","closeModal","removeFocusTrap","setupMenu","previousState","handleStateChange","currentState","getPropertyValue","cssVariables","cssVars","values","inactive","stateObserver","ResizeObserver","setupMenuDisplayObserver","navbar","openDropdown","allNavbarElements","focusableElements","filter","el","menuSelector","elements","primary","split","skipSelector","computedStyle","htmlEl","display","visibility","opacity","offsetWidth","offsetHeight","parent","parentStyle","parentHtmlEl","currentIndex","indexOf","menuContainer","currentFocusIndex","current","getFocusableElements","tagName","hasAttribute","click","setupMenuArrowNavigation","destroyFunctions","results","Promise","allSettled","dropdownInit","dropdown","menuInit","arrowNavigationInit","status","value","succeeded","r","failed","destroyFn","error","accordionWrappers","initializedCount","button","content","heightSelector","height","heightValue","buttonId","contentId","openText","properties","open","closedText","closed","hasTextSwap","stateElements","stateSelector","isAccordionOpen","text","defaultState","default","setupAccordionAccessibility","modulePromises","smoothScrollInit","navbarInit","accordionInit","accordion"],"mappings":"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"}