{"version":3,"file":"sixbell-telco-sdk-directives-auto-focus.mjs","sources":["../../../projects/sdk/directives/auto-focus/src/auto-focus.directive.ts","../../../projects/sdk/directives/auto-focus/sixbell-telco-sdk-directives-auto-focus.ts"],"sourcesContent":["import { AfterRenderRef, DestroyRef, Directive, ElementRef, afterRenderEffect, effect, inject, input, signal } from '@angular/core';\n\n/**\n * Directive that automatically focuses an element when it becomes visible.\n *\n * This directive uses multiple strategies to detect when an element becomes visible:\n * - IntersectionObserver to detect when the element enters the viewport\n * - MutationObserver to detect DOM changes that might affect visibility\n * - Polling at regular intervals as a fallback mechanism\n *\n * The directive works reliably with modals, dialogs, accordions, and other UI components\n * that dynamically show and hide content.\n *\n * @example\n * ```html\n * <!-- Basic usage -->\n * <input [stAutofocus]=\"true\" />\n *\n * <!-- Conditional autofocus -->\n * <input [stAutofocus]=\"shouldFocus\" />\n *\n * <!-- In a form inside a dialog -->\n * <st-dialog>\n *   <input [stAutofocus]=\"true\" />\n * </st-dialog>\n * ```\n *\n * @usageNotes\n * The directive takes a boolean input that determines whether autofocus should be applied.\n * When this value is true, the directive will attempt to focus the element once it becomes visible,\n * and will continue to monitor the element's visibility state in case it changes.\n *\n * This is particularly useful for:\n * - Elements in modals that need focus when opened\n * - Elements in accordions/collapsible sections that should receive focus when expanded\n * - Elements that are conditionally rendered and need focus when they appear\n *\n * @publicApi\n */\n@Directive({\n\tselector: '[stAutofocus]',\n\tstandalone: true,\n})\nexport class AutofocusDirective {\n\t/**\n\t * Controls whether autofocus should be applied to the element.\n\t * Set to true to enable autofocus.\n\t */\n\tfocus = input<boolean>(false);\n\n\t/** Tracks the current visibility state of the element */\n\tprivate readonly isVisible = signal(false);\n\n\t/** Keeps a reference so the afterRenderEffect can be destroyed with the directive */\n\tprivate readonly focusAfterRenderRef: AfterRenderRef;\n\n\tprivate readonly destroyRef = inject(DestroyRef);\n\n\t/** Collection of observers for cleanup */\n\tprivate observers: (IntersectionObserver | MutationObserver)[] = [];\n\n\t/** Interval used for polling visibility */\n\tprivate pollingInterval: ReturnType<typeof globalThis.setInterval> | null = null;\n\n\t/** Flag to prevent concurrent visibility checks */\n\tprivate checkingVisibility = false;\n\n\tprivate readonly elementRef = inject(ElementRef);\n\n\tconstructor() {\n\t\tthis.focusAfterRenderRef = afterRenderEffect(() => {\n\t\t\tif (this.focus() && this.isVisible()) {\n\t\t\t\tthis.elementRef.nativeElement.focus();\n\t\t\t}\n\t\t});\n\n\t\teffect(() => {\n\t\t\tif (!this.focus()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.setupIntersectionObserver();\n\t\t\tthis.setupMutationObserver();\n\n\t\t\tthis.pollingInterval = globalThis.setInterval(() => {\n\t\t\t\tthis.checkVisibility(true);\n\t\t\t}, 500);\n\n\t\t\tthis.checkVisibility(true);\n\t\t});\n\n\t\tthis.destroyRef.onDestroy(() => {\n\t\t\tthis.cleanup();\n\t\t});\n\t}\n\n\t/**\n\t * Cleans up all observers and timers to prevent memory leaks\n\t */\n\tprivate cleanup() {\n\t\tfor (const observer of this.observers) {\n\t\t\tif (observer) {\n\t\t\t\tobserver.disconnect();\n\t\t\t}\n\t\t}\n\t\tthis.observers = [];\n\n\t\tif (this.pollingInterval !== null) {\n\t\t\tclearInterval(this.pollingInterval);\n\t\t\tthis.pollingInterval = null;\n\t\t}\n\n\t\tthis.focusAfterRenderRef.destroy();\n\t}\n\n\t/**\n\t * Sets up the IntersectionObserver to detect when the element enters or leaves the viewport\n\t * @private\n\t */\n\tprivate setupIntersectionObserver(): void {\n\t\tif ('IntersectionObserver' in globalThis) {\n\t\t\tconst intersectionObserver = new IntersectionObserver(\n\t\t\t\t(entries) => {\n\t\t\t\t\tif (entries[0].isIntersecting) {\n\t\t\t\t\t\tthis.checkVisibility(true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.updateVisibility(false);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{ threshold: 0.1 },\n\t\t\t);\n\n\t\t\tintersectionObserver.observe(this.elementRef.nativeElement);\n\t\t\tthis.observers.push(intersectionObserver);\n\t\t}\n\t}\n\n\t/**\n\t * Sets up MutationObserver to detect style/class changes that might affect visibility\n\t * Also monitors parent elements to detect when containers like modals appear/disappear\n\t * @private\n\t */\n\tprivate setupMutationObserver(): void {\n\t\tconst mutationObserver = new MutationObserver(() => {\n\t\t\tthis.checkVisibility(true);\n\t\t});\n\n\t\t// Watch this element\n\t\tmutationObserver.observe(this.elementRef.nativeElement, {\n\t\t\tattributes: true,\n\t\t\tattributeFilter: ['style', 'class'],\n\t\t});\n\n\t\t// Watch parent elements - important for modals, accordions, etc.\n\t\tlet parent = this.elementRef.nativeElement.parentElement;\n\t\tlet level = 0;\n\n\t\t// Watch up to 3 parent levels\n\t\twhile (parent && level < 3) {\n\t\t\tmutationObserver.observe(parent, {\n\t\t\t\tattributes: true,\n\t\t\t\tattributeFilter: ['style', 'class'],\n\t\t\t\tchildList: true,\n\t\t\t});\n\t\t\tparent = parent.parentElement;\n\t\t\tlevel++;\n\t\t}\n\n\t\tthis.observers.push(mutationObserver);\n\t}\n\n\t/**\n\t * Checks if the element is truly visible by examining computed style and dimensions\n\t * @param force Whether to force a check even if one is already in progress\n\t * @private\n\t */\n\tprivate checkVisibility(force = false): void {\n\t\tif (this.checkingVisibility && !force) return;\n\n\t\tthis.checkingVisibility = true;\n\t\tconst el = this.elementRef.nativeElement;\n\n\t\trequestAnimationFrame(() => {\n\t\t\tconst style = globalThis.getComputedStyle(el);\n\t\t\tconst isNowVisible = el.offsetWidth > 0 && el.offsetHeight > 0 && style.visibility !== 'hidden' && style.display !== 'none';\n\n\t\t\tthis.updateVisibility(isNowVisible);\n\t\t\tthis.checkingVisibility = false;\n\t\t});\n\t}\n\n\t/**\n\t * Updates the visibility signal that drives the autofocus effect\n\t * @param visible The new visibility state\n\t * @private\n\t */\n\tprivate updateVisibility(visible: boolean): void {\n\t\tif (this.isVisible() !== visible) {\n\t\t\tthis.isVisible.set(visible);\n\t\t}\n\t}\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}