{"version":3,"file":"disclosure.mjs","sources":["../../../../src/disclosure/footnote-processing.ts","../../../../src/disclosure/disclosure.ts"],"sourcesContent":["export interface FootnoteItem {\n  '#': string;           // e.g., \"<sup>1</sup>\"\n  '#-'?: string;        // Inline disclosure HTML, if present\n  id: string;           // e.g., \"sct-mvp-traditional-ira-page-magi-deductions-master\"\n  index: string;        // e.g., \"0\" (as string in the data)\n  disclosureText?: string; // Optional disclosure text content\n}\n\nexport interface FootnoteData {\n  count: string;        // e.g., \"2\"\n  [key: string]: FootnoteItem | string; // Dynamic keys for footnote items\n}\n\ninterface LoaderConfig {\n  cf: number;\n  investment: number;\n  footnote: number;\n  url: number;\n  account: number;\n  timestamp: number;\n}\n\ninterface Configuration {\n  restUrlPath: string;\n  loaders: LoaderConfig;\n}\n\nexport interface PlaceholderData {\n  data: {\n    footnote: FootnoteData;\n  };\n  warnings: string[];\n  configuration: Configuration;\n}\n\nexport interface ProcessedFootnoteData {\n  [id: string]: {\n    sup: string;\n    index: number;\n    disclosureText?: string;\n    inline: boolean;\n  };\n}\n\nexport function processFootnoteData(placeholderData: PlaceholderData): ProcessedFootnoteData {\n    const footnoteData: FootnoteData = placeholderData.data.footnote;\n    const processedData: ProcessedFootnoteData = {};\n\n    function collectFootnotes(obj: any) {\n        Object.keys(obj).forEach(key => {\n            if (key === 'count') return;\n            const value = obj[key];\n            if (value && typeof value === 'object' && 'id' in value && '#' in value && 'index' in value) {\n                processedData[value.id] = {\n                    sup: value['#'],\n                    index: parseInt(value.index),\n                    disclosureText: value.disclosureText,\n                    inline: '#-' in value,\n                };\n            } else if (value && typeof value === 'object') {\n                collectFootnotes(value);\n            }\n        });\n    }\n\n    collectFootnotes(footnoteData);\n    return processedData;\n}\n\nexport function addSuperscriptToElement(p: HTMLElement, footnoteSup: string): void {\n    const LEADING_WHITESPACE_REGEX = /^\\s+/;\n    if (!p.querySelector('sup')) { // Check if superscript is already added\n        p.innerHTML = p.innerHTML?.replace(LEADING_WHITESPACE_REGEX, '') ?? ''; // Trim leading whitespace\n        p.innerHTML = `${footnoteSup}` + p.innerHTML;\n    }\n}\n\nexport function getSuperscriptFromElement(element: HTMLElement): string | null {\n    const sup = element?.querySelector('sup');\n    return sup ? sup.outerHTML : null;\n}\n\nexport function findParagraphElement(element: HTMLElement): HTMLElement | null {\n    if (element.tagName.toLowerCase() === 'p') return element;\n    for (const child of Array.from(element.children)) {\n        const found = findParagraphElement(child as HTMLElement);\n        if (found) return found;\n    }\n    return null;\n}","import { html, LitElement, unsafeCSS, CSSResult } from 'lit';\nimport { customElement } from 'lit/decorators.js';\nimport { appendStylesheet } from '../core/utils';\nimport { attachCtaClickTracking } from '../core/cta-click-tracking';\nimport styles from './disclosure.scss?inline';\nimport slotStyles from './disclosure.slot.scss?inline';\nimport { processFootnoteData, findParagraphElement, getSuperscriptFromElement, addSuperscriptToElement  } from './footnote-processing';\nimport type { PlaceholderData, ProcessedFootnoteData } from './footnote-processing';\nimport { gridStyles } from '../styles';\n\n@customElement('pips-v1-disclosure')\nexport class Disclosure extends LitElement {\n  static override styles: CSSResult[] = [unsafeCSS(styles), unsafeCSS(gridStyles)];\n  static PLACEHOLDER_DATA_SELECTOR: string = 'script[data-placeholder-data=\"true\"]';\n  static MUTATION_OBSERVER_CONFIG: MutationObserverInit = { childList: true };\n\n  private footnoteData: ProcessedFootnoteData = {};\n  private mutationObserver?: MutationObserver;\n  private isProcessing = false;\n  private analyticsController: AbortController | null = null;\n\n  override connectedCallback(): void {\n    super.connectedCallback();\n    appendStylesheet({ // Apply styles to slotted elements\n      target: this,\n      styles: slotStyles,\n      name: `${this.tagName.toLowerCase()}-slot`\n    });\n    this.attachCtaAnalyticsListener();\n\n    // Setup MutationObserver to watch for changes in slotted content\n    this.mutationObserver = new MutationObserver(() => {\n      if (this.isProcessing) return;\n      this.isProcessing = true;\n      this.mutationObserver?.disconnect();\n      this.processSlottedContent();\n      this.mutationObserver?.observe(this, Disclosure.MUTATION_OBSERVER_CONFIG);\n      this.isProcessing = false;\n    });\n    this.mutationObserver.observe(this, Disclosure.MUTATION_OBSERVER_CONFIG)\n  }\n\n  override disconnectedCallback(): void {\n    super.disconnectedCallback();\n    this.mutationObserver?.disconnect();\n    this.analyticsController?.abort();\n    this.analyticsController = null;\n  }\n\n  private attachCtaAnalyticsListener(): void {\n    this.analyticsController?.abort();\n    this.analyticsController = new AbortController();\n    // Location is always the component's own tag. Scoped to the call-to-action slot so\n    // incidental links in the disclosure body text (the unnamed slot) aren't misreported.\n    attachCtaClickTracking(this, {\n      getLocation: () => this.tagName.toLowerCase(),\n      filter: (cta) => cta.closest('[slot=\"call-to-action\"]') !== null,\n    }, this.analyticsController.signal);\n  }\n\n  override async firstUpdated() {\n    try {\n      const placeholderDataScript: HTMLScriptElement = document.querySelector(Disclosure.PLACEHOLDER_DATA_SELECTOR) as HTMLScriptElement;\n      const placeholderJSONtext: string = placeholderDataScript?.textContent?.trim() ?? ''; // json from inside of script tag\n      const placeholderData: PlaceholderData = JSON.parse(placeholderJSONtext);\n      this.footnoteData = processFootnoteData(placeholderData);\n    } catch (error) {\n      console.error('Error processing disclosure data:', error);\n    }\n\n    if (this.isProcessing) return;\n    this.isProcessing = true;\n    this.mutationObserver?.disconnect();\n    this.processSlottedContent();\n    this.mutationObserver?.observe(this, Disclosure.MUTATION_OBSERVER_CONFIG);\n    this.isProcessing = false;\n  }\n\n  private processSlottedContent(): void {\n    const slot = this.shadowRoot?.querySelector('slot:not([name])') as HTMLSlotElement;\n    const existingSups = new Set<string>();\n    const existingIDs = new Set<string>();\n    \n    slot.assignedElements({ flatten: true }).forEach(element => { // Collect existing superscripts in assigned elements\n        const sup = element.querySelector('sup');\n        if (sup) existingSups.add(sup.outerHTML);\n        if (element.id) existingIDs.add(element.id);\n    });\n\n    // Iterate through retrieved footnote data, create disclosure and insert into slot if missing. Mark disclosure for removal if inline.\n    const toRemove = new Set<string>();\n    Object.entries(this.footnoteData).forEach(([id, item]) => {\n        if (!item.sup || !item.disclosureText) return; // Skip if missing required data\n        if (item.inline) {\n            toRemove.add(id);\n        } else if (!existingSups.has(item.sup) && !existingIDs.has(id)) { // If superscript and ID not already present, create disclosure.\n            const disclosureDiv = document.createElement('div');\n            const spanMatches = item.disclosureText.match(/<span[\\s\\S]*?<\\/span>/g) ?? [];\n            spanMatches.forEach((text, index) => {\n              const p = document.createElement('p');\n              if (index === 0) {\n                p.innerHTML = `${item.sup}${text}`;\n              } else {\n                p.innerHTML = text;\n              }\n              disclosureDiv.appendChild(p);\n            });\n            disclosureDiv.id = id;\n            this.appendChild(disclosureDiv);\n        }\n    });\n\n    // Update existing elements: Add superscripts, Remove disclosures that are inline or duplicate.\n    const duplicateIDs = new Set<string>();\n    \n    slot.assignedElements({ flatten: true }).forEach(element => {\n        if (element.id === \"\") return;\n        if (duplicateIDs.has(element.id)) {\n            element.remove();\n            return;\n        }\n        duplicateIDs.add(element.id);\n\n        if (!(element.id in this.footnoteData)) return;\n        if (toRemove.has(element.id)) {\n            element.remove();\n            return;\n        }\n\n        const paragraphElement = findParagraphElement(element as HTMLElement);\n        if (paragraphElement) {\n            addSuperscriptToElement(paragraphElement, this.footnoteData[element.id].sup);\n        }\n    });\n\n    const assignedElements = slot.assignedElements({ flatten: true });\n    this.style.display = assignedElements.length === 0 ? 'none' : '';\n    if (assignedElements.length === 0) return;\n\n    const sortedElements = assignedElements.slice().sort((a, b) => { //Sort remaining elements by superscript\n        const aSup = getSuperscriptFromElement(a as HTMLElement);\n        const bSup = getSuperscriptFromElement(b as HTMLElement);\n        if (aSup && bSup) return aSup.localeCompare(bSup);\n        if (aSup && !bSup) return -1;\n        if (!aSup && bSup)  return 1;\n        return 0; \n    });\n\n    const same: boolean = !sortedElements.some((el, index) => el !== assignedElements[index]);\n    if (same) return;\n\n    assignedElements.forEach(el => el.remove());\n    sortedElements.forEach(el => this.appendChild(el));\n}\n\n  override render() {\n    return html`\n      <div class=\"disclosure-container cmp-layout-container\">\n        <div class=\"disclosure layout-container\">\n          <slot></slot>\n          <slot name=\"call-to-action\"></slot>\n        </div>\n      </div>\n    `;\n  }\n}"],"names":["getSuperscriptFromElement","element","sup","querySelector","outerHTML","findParagraphElement","tagName","toLowerCase","child","Array","from","children","found","Disclosure","LitElement","constructor","super","arguments","this","footnoteData","isProcessing","analyticsController","connectedCallback","appendStylesheet","target","styles","name","attachCtaAnalyticsListener","mutationObserver","MutationObserver","disconnect","processSlottedContent","observe","MUTATION_OBSERVER_CONFIG","disconnectedCallback","abort","AbortController","attachCtaClickTracking","getLocation","filter","cta","closest","signal","firstUpdated","placeholderDataScript","document","PLACEHOLDER_DATA_SELECTOR","placeholderJSONtext","textContent","trim","placeholderData","JSON","parse","data","footnote","processedData","collectFootnotes","obj","Object","keys","forEach","key","value","id","index","parseInt","disclosureText","inline","error","console","slot","shadowRoot","existingSups","Set","existingIDs","assignedElements","flatten","add","toRemove","entries","item","has","disclosureDiv","createElement","match","text","p","innerHTML","appendChild","duplicateIDs","remove","paragraphElement","footnoteSup","LEADING_WHITESPACE_REGEX","replace","style","display","length","sortedElements","slice","sort","a","b","aSup","bSup","localeCompare","some","el","render","html","unsafeCSS","gridStyles","childList","customElement"],"mappings":"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"}