{"version":3,"file":"usitsdasdesign-dds-ng-core-focus-handler.mjs","sources":["../../src/app/dds/core/focus-handler/focus-handler.service.ts","../../src/app/dds/core/focus-handler/focus-handler.directive.ts","../../src/app/dds/core/focus-handler/focus-handler.module.ts","../../src/app/dds/core/focus-handler/usitsdasdesign-dds-ng-core-focus-handler.ts"],"sourcesContent":["import { Injectable, Inject, DOCUMENT } from '@angular/core';\n\nimport { Observable, fromEvent } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\n// @dynamic\n@Injectable({\n  providedIn: 'root'\n})\nexport class FocusHandlerService {\n  public keyup$: Observable<KeyboardEvent>;\n  public keydown$: Observable<KeyboardEvent>;\n  public mousedown$: Observable<MouseEvent>;\n\n  constructor(@Inject(DOCUMENT) private document: Document) {\n    this.keyup$ = fromEvent<KeyboardEvent>(this.document, 'keyup').pipe(share());\n    this.keydown$ = fromEvent<KeyboardEvent>(this.document, 'keydown').pipe(share());\n    this.mousedown$ = fromEvent<MouseEvent>(this.document, 'mousedown').pipe(share());\n  }\n}\n","import {\n  AfterViewInit,\n  Directive,\n  ElementRef,\n  HostListener,\n  Input,\n  NgZone,\n  OnChanges,\n  OnDestroy,\n  Renderer2,\n  SimpleChanges,\n} from '@angular/core';\nimport { AdditionalClass, KeyCodes } from '@usitsdasdesign/dds-ng/shared';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { FocusHandlerService } from './focus-handler.service';\n\n@Directive({\n  selector: '[ddsFocus]',\n  standalone: true,\n  providers: [FocusHandlerService]\n})\nexport class FocusHandlerDirective implements OnDestroy, AfterViewInit, OnChanges {\n  @Input('ddsFocus') focusedEl: HTMLElement | string; // Element to be focused\n  @Input('ddsFocusCheck') focusCheck: boolean; // Boolean to check if element is focused (needed for radio buttons)\n  @Input() disabled: boolean; // Boolean to disable the directive\n\n  @HostListener('focus', ['$event.target'])\n  onFocus(target: EventTarget) {\n    if (this.isPrevKeyboardEvent) this.checkIfElementIsTarget(target); // Check if the target element is the focused element\n  }\n\n  private destroy = new Subject<void>(); // Subject to handle component destruction\n  private isPrevKeyboardEvent = false; // Flag to check if the previous event was a keyboard event\n\n  constructor(\n    private renderer: Renderer2,\n    private ngZone: NgZone,\n    private el: ElementRef,\n    private focusHandlerService: FocusHandlerService\n  ) { }\n\n  public ngAfterViewInit(): void {\n    this.ngZone.runOutsideAngular(() => {\n      // Subscribe to keyup events\n      this.focusHandlerService.keyup$.pipe(takeUntil(this.destroy)).subscribe((e: KeyboardEvent) => this.focus(e));\n      // Subscribe to keydown events\n      this.focusHandlerService.keydown$.pipe(takeUntil(this.destroy)).subscribe((e: KeyboardEvent) => this.handleKeydown(e));\n      // Subscribe to mousedown events\n      this.focusHandlerService.mousedown$.pipe(takeUntil(this.destroy)).subscribe((e: MouseEvent) => this.handleMousedown(e));\n    });\n  }\n\n  public ngOnChanges(changes: SimpleChanges): void {\n    if (changes.disabled) {\n      this.disabledDir(changes.disabled.currentValue); // Handle changes to the disabled input\n    }\n  }\n\n  public ngOnDestroy(): void {\n    this.destroy.next(); // Emit destroy event\n    this.destroy.complete(); // Complete the destroy subject\n  }\n\n  public isFakeMousedownFromScreenReader(event: MouseEvent): boolean {\n    return event.offsetX === 0 && event.offsetY === 0; // Check if the mousedown event is from a screen reader\n  }\n\n  public disabledDir(status: boolean): void {\n    this.el.nativeElement.tabIndex = status ? -1 : 0; // Set tabIndex based on disabled status\n    this.el.nativeElement.disabled = status; // Set disabled attribute based on status\n  }\n\n  // Handles the keydown event for the focus handler.\n  private handleKeydown(e: KeyboardEvent): void {\n    this.isPrevKeyboardEvent = true;\n    if (e.keyCode === KeyCodes.TAB) this.removeFocusedClass(); // Remove focused class on TAB key\n\n    // For radio buttons\n    if (\n      this.focusCheck &&\n      (e.keyCode === KeyCodes.ARROW_UP ||\n        e.keyCode === KeyCodes.ARROW_DOWN ||\n        e.keyCode === KeyCodes.ARROW_RIGHT ||\n        e.keyCode === KeyCodes.ARROW_LEFT)\n    )\n      this.removeFocusedClass(); // Remove focused class on arrow keys\n  }\n\n  // Handles the mousedown event.\n  private handleMousedown(e: MouseEvent): void {\n    if (!this.isFakeMousedownFromScreenReader(e)) {\n      this.isPrevKeyboardEvent = false;\n      this.removeFocusOnMousedown(); // Remove focus on mousedown\n    }\n  }\n\n  private focus(e: KeyboardEvent): void {\n    if (this.focusCheck) {\n      if (e.keyCode === KeyCodes.TAB || this.el.nativeElement.focus) {\n        this.checkIfElementIsTarget(e.target); // Check if the target element is the focused element\n      }\n    } else {\n      if (e.keyCode === KeyCodes.TAB) {\n        this.checkIfElementIsTarget(e.target); // Check if the target element is the focused element\n      }\n    }\n  }\n\n  private checkIfElementIsTarget(target: EventTarget | null): boolean {\n    if (this.disabled) return false;\n\n    if (this.el.nativeElement === target) {\n      this.addFocusedClass(); // Add focused class if the element is the target\n    }\n    return this.el.nativeElement === target;\n  }\n\n  private addFocusedClass(): void {\n    if (this.focusedEl) {\n      this.renderer.addClass(this.focusedEl, AdditionalClass.keyboardFocus); // Add focused class to the focused element\n    } else {\n      this.renderer.addClass(this.el.nativeElement, AdditionalClass.keyboardFocus); // Add focused class to the directive element\n    }\n  }\n\n  private removeFocusedClass(): void {\n    if (this.focusedEl) {\n      this.renderer.removeClass(this.focusedEl, AdditionalClass.keyboardFocus); // Remove focused class from the focused element\n    } else {\n      this.renderer.removeClass(this.el.nativeElement, AdditionalClass.keyboardFocus); // Remove focused class from the directive element\n    }\n  }\n\n  private removeFocusOnMousedown(): void {\n    this.removeFocusedClass(); // Remove focused class on mousedown\n  }\n}\n","import { NgModule } from '@angular/core';\nimport { FocusHandlerDirective } from './focus-handler.directive';\nimport { FocusHandlerService } from './focus-handler.service';\n\n@NgModule({\n  imports: [FocusHandlerDirective],\n  exports: [FocusHandlerDirective],\n  providers: [FocusHandlerService],\n})\nexport class FocusHandlerModule { }\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.FocusHandlerService"],"mappings":";;;;;;AAKA;MAIa,mBAAmB,CAAA;AAK9B,IAAA,WAAA,CAAsC,QAAkB,EAAA;QAAlB,IAAA,CAAA,QAAQ,GAAR,QAAQ;AAC5C,QAAA,IAAI,CAAC,MAAM,GAAG,SAAS,CAAgB,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;AAC5E,QAAA,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAgB,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;AAChF,QAAA,IAAI,CAAC,UAAU,GAAG,SAAS,CAAa,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACnF;AATW,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,kBAKV,QAAQ,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AALjB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,cAFlB,MAAM,EAAA,CAAA,CAAA;;2FAEP,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAH/B,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;0BAMc,MAAM;2BAAC,QAAQ;;;MCQjB,qBAAqB,CAAA;AAMhC,IAAA,OAAO,CAAC,MAAmB,EAAA;QACzB,IAAI,IAAI,CAAC,mBAAmB;AAAE,YAAA,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACpE;AAKA,IAAA,WAAA,CACU,QAAmB,EACnB,MAAc,EACd,EAAc,EACd,mBAAwC,EAAA;QAHxC,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACR,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,EAAE,GAAF,EAAE;QACF,IAAA,CAAA,mBAAmB,GAAnB,mBAAmB;AAPrB,QAAA,IAAA,CAAA,OAAO,GAAG,IAAI,OAAO,EAAQ,CAAC;AAC9B,QAAA,IAAA,CAAA,mBAAmB,GAAG,KAAK,CAAC;IAOhC;IAEG,eAAe,GAAA;AACpB,QAAA,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAK;;AAEjC,YAAA,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAgB,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;;AAE5G,YAAA,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAgB,KAAK,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;;AAEtH,YAAA,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAa,KAAK,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AACzH,QAAA,CAAC,CAAC;IACJ;AAEO,IAAA,WAAW,CAAC,OAAsB,EAAA;AACvC,QAAA,IAAI,OAAO,CAAC,QAAQ,EAAE;YACpB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAClD;IACF;IAEO,WAAW,GAAA;AAChB,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;AACpB,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC1B;AAEO,IAAA,+BAA+B,CAAC,KAAiB,EAAA;AACtD,QAAA,OAAO,KAAK,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC;IACpD;AAEO,IAAA,WAAW,CAAC,MAAe,EAAA;AAChC,QAAA,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACjD,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,GAAG,MAAM,CAAC;IAC1C;;AAGQ,IAAA,aAAa,CAAC,CAAgB,EAAA;AACpC,QAAA,IAAI,CAAC,mBAAmB,GAAG,IAAI;AAC/B,QAAA,IAAI,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,GAAG;AAAE,YAAA,IAAI,CAAC,kBAAkB,EAAE,CAAC;;QAG1D,IACE,IAAI,CAAC,UAAU;AACf,aAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,QAAQ;AAC9B,gBAAA,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,UAAU;AACjC,gBAAA,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,WAAW;AAClC,gBAAA,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,UAAU,CAAC;AAEpC,YAAA,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC9B;;AAGQ,IAAA,eAAe,CAAC,CAAa,EAAA;QACnC,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,CAAC,EAAE;AAC5C,YAAA,IAAI,CAAC,mBAAmB,GAAG,KAAK;AAChC,YAAA,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC;IACF;AAEQ,IAAA,KAAK,CAAC,CAAgB,EAAA;AAC5B,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,YAAA,IAAI,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE;gBAC7D,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACxC;QACF;aAAO;YACL,IAAI,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,GAAG,EAAE;gBAC9B,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACxC;QACF;IACF;AAEQ,IAAA,sBAAsB,CAAC,MAA0B,EAAA;QACvD,IAAI,IAAI,CAAC,QAAQ;AAAE,YAAA,OAAO,KAAK;QAE/B,IAAI,IAAI,CAAC,EAAE,CAAC,aAAa,KAAK,MAAM,EAAE;AACpC,YAAA,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB;AACA,QAAA,OAAO,IAAI,CAAC,EAAE,CAAC,aAAa,KAAK,MAAM;IACzC;IAEQ,eAAe,GAAA;AACrB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;QACxE;aAAO;AACL,YAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;QAC/E;IACF;IAEQ,kBAAkB,GAAA;AACxB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;QAC3E;aAAO;AACL,YAAA,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;QAClF;IACF;IAEQ,sBAAsB,GAAA;AAC5B,QAAA,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B;8GAlHW,qBAAqB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,SAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,MAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,EAAA,EAAA,KAAA,EAAAA,mBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;kGAArB,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,CAAA,UAAA,EAAA,WAAA,CAAA,EAAA,UAAA,EAAA,CAAA,eAAA,EAAA,YAAA,CAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,wBAAA,EAAA,EAAA,EAAA,SAAA,EAFrB,CAAC,mBAAmB,CAAC,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAErB,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBALjC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,YAAY;AACtB,oBAAA,UAAU,EAAE,IAAI;oBAChB,SAAS,EAAE,CAAC,mBAAmB;AAChC,iBAAA;;sBAEE,KAAK;uBAAC,UAAU;;sBAChB,KAAK;uBAAC,eAAe;;sBACrB;;sBAEA,YAAY;uBAAC,OAAO,EAAE,CAAC,eAAe,CAAC;;;MClB7B,kBAAkB,CAAA;8GAAlB,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,QAAA,EAAA,CAAA,CAAA;+GAAlB,kBAAkB,EAAA,OAAA,EAAA,CAJnB,qBAAqB,CAAA,EAAA,OAAA,EAAA,CACrB,qBAAqB,CAAA,EAAA,CAAA,CAAA;+GAGpB,kBAAkB,EAAA,SAAA,EAFlB,CAAC,mBAAmB,CAAC,EAAA,CAAA,CAAA;;2FAErB,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAL9B,QAAQ;AAAC,YAAA,IAAA,EAAA,CAAA;oBACR,OAAO,EAAE,CAAC,qBAAqB,CAAC;oBAChC,OAAO,EAAE,CAAC,qBAAqB,CAAC;oBAChC,SAAS,EAAE,CAAC,mBAAmB,CAAC;AACjC,iBAAA;;;ACRD;;AAEG;;;;"}