{"version":3,"names":["AtomicFocusTrap","this","active","shouldHideSelf","scope","document","body","hiddenElements","hide","element","hasAttribute","tagName","toLowerCase","setAttribute","push","showAll","el","pop","removeAttribute","hideSiblingsRecursively","parent","getParent","Array","from","children","forEach","sibling","assignedSlot","isAncestorOf","host","showSelf","parentToHide","hideSelf","onDeactivated","isInitialLoad","defer","_a","source","focus","onActivated","getFirstFocusableDescendant","activeChanged","wasActive","onFocusChanged","e","elementIsPartOfHost","focusedElement","elementIsPartOfScope","target","getFocusedElement","connectedCallback","disconnectedCallback","container","atomicModalCss","AtomicModal","fullscreen","isOpen","close","boundary","wasEverOpened","headerId","randomID","currentWatchToggleOpenExecution","updateBreakpoints","once","watchToggleOpen","watchToggleOpenExecution","modalOpenedClass","classList","add","bindings","interfaceElement","waitForAnimationEnded","focusTrap","remove","isIOS","handleCloseOnEscape","key","Promise","resolve","listenOnce","animatableContainer","getClasses","classes","onWindowTouchMove","preventDefault","componentDidLoad","render","Content","h","part","class","onAnimationEnd","animationEnded","emit","ref","id","name","addEventListener","stopPropagation","passive","Host","join","onClick","currentTarget","role","toString","__decorate","InitializeBindings"],"sources":["src/components/common/atomic-focus-trap.tsx","src/components/common/atomic-modal/atomic-modal.pcss?tag=atomic-modal&encapsulation=shadow","src/components/common/atomic-modal/atomic-modal.tsx"],"sourcesContent":["import {Component, Element, Listen, Prop, Watch} from '@stencil/core';\nimport {getFirstFocusableDescendant} from '../../utils/accessibility-utils';\nimport {\n  isAncestorOf,\n  defer,\n  getFocusedElement,\n  getParent,\n} from '../../utils/utils';\n\n/**\n * @internal\n */\n@Component({\n  tag: 'atomic-focus-trap',\n  shadow: false,\n})\nexport class AtomicFocusTrap {\n  @Element() private host!: HTMLElement;\n  @Prop() public active = false;\n  /**\n   * The source to focus when the focus trap becomes inactive.\n   */\n  @Prop({mutable: true}) source?: HTMLElement;\n  /**\n   * The container to hide from the tabindex and accessibility DOM when the focus trap is inactive.\n   */\n  @Prop({mutable: true}) container?: HTMLElement;\n\n  /**\n   * Whether the element should be hidden from screen readers & not interactive with the tab, when not active.\n   */\n  @Prop() shouldHideSelf = true;\n\n  /**\n   * The common ancestor of the focus trap and of all the elements that should be inaccessible when inside the focus trap.\n   */\n  @Prop() scope = document.body;\n\n  private readonly hiddenElements: Element[] = [];\n\n  hide(element: Element) {\n    // aria-hidden -> already hidden\n    // aria-live or atomic-aria-live -> must not be hidden otherwise it won't announce dynamic changes in the live region\n    if (\n      element.hasAttribute('aria-hidden') ||\n      element.hasAttribute('aria-live') ||\n      element.tagName.toLowerCase() === 'atomic-aria-live'\n    ) {\n      return;\n    }\n    element.setAttribute('aria-hidden', 'true');\n    this.hiddenElements.push(element);\n  }\n\n  showAll() {\n    let el: Element | undefined;\n    while ((el = this.hiddenElements.pop())) {\n      el.removeAttribute('aria-hidden');\n    }\n  }\n\n  hideSiblingsRecursively(element: Element | ShadowRoot) {\n    const parent = getParent(element);\n    if (parent === null) {\n      return;\n    }\n    Array.from(parent.children as HTMLCollection).forEach((sibling) => {\n      if (sibling === element) {\n        return;\n      }\n      if (\n        sibling.assignedSlot &&\n        isAncestorOf(this.host, sibling.assignedSlot)\n      ) {\n        return;\n      }\n      this.hide(sibling);\n    });\n    if (parent !== this.scope) {\n      this.hideSiblingsRecursively(parent);\n    }\n  }\n\n  showSelf() {\n    this.parentToHide.removeAttribute('aria-hidden');\n    this.parentToHide.removeAttribute('tabindex');\n  }\n\n  hideSelf() {\n    if (this.shouldHideSelf) {\n      this.parentToHide.setAttribute('aria-hidden', 'true');\n      this.parentToHide.setAttribute('tabindex', '-1');\n    }\n  }\n\n  async onDeactivated(isInitialLoad: boolean) {\n    this.showAll();\n    if (!isInitialLoad) {\n      await defer();\n      this.source?.focus();\n    }\n    this.hideSelf();\n  }\n\n  async onActivated(isInitialLoad: boolean) {\n    this.showSelf();\n    if (!isInitialLoad) {\n      await defer();\n      getFirstFocusableDescendant(this.host)?.focus();\n    }\n    this.hideSiblingsRecursively(this.host);\n  }\n\n  @Watch('active')\n  async activeChanged(active: boolean, wasActive: boolean) {\n    const isInitialLoad = active === wasActive;\n    if (active) {\n      await this.onActivated(isInitialLoad);\n    } else {\n      await this.onDeactivated(isInitialLoad);\n    }\n  }\n\n  @Listen('focusin', {target: 'document'})\n  onFocusChanged(e: FocusEvent) {\n    const elementIsPartOfHost = (focusedElement: Element | ShadowRoot) =>\n      isAncestorOf(this.host, focusedElement);\n\n    const elementIsPartOfScope = (focusedElement: Element | ShadowRoot) =>\n      isAncestorOf(this.scope, focusedElement);\n\n    if (!e.target || !this.active) {\n      return;\n    }\n\n    const focusedElement = getFocusedElement();\n\n    if (\n      focusedElement &&\n      (elementIsPartOfHost(focusedElement) ||\n        !elementIsPartOfScope(focusedElement))\n    ) {\n      return;\n    }\n\n    getFirstFocusableDescendant(this.host)?.focus();\n  }\n\n  connectedCallback() {\n    this.activeChanged(this.active, this.active);\n  }\n\n  disconnectedCallback() {\n    this.showAll();\n  }\n\n  private get parentToHide() {\n    return this.container ?? this.host;\n  }\n}\n","@import '../../../global/global.pcss';\n\n[part='backdrop'] {\n  @apply pointer-events-none;\n}\n\natomic-focus-trap {\n  @apply contents;\n}\n\n[part='container'] {\n  @apply overflow-hidden;\n  grid-area: modal;\n}\n\n.animate-scaleUpModalIPX[part='container'] {\n  @apply rounded shadow;\n}\n\n:host(.open) {\n  [part='backdrop'] {\n    @apply pointer-events-auto;\n  }\n}\n\n:host(.open.dialog) {\n  [part='backdrop'] {\n    background-color: rgba(40, 40, 40, 0.8);\n  }\n}\n\n:host(.dialog) {\n  [part='backdrop'] {\n    @apply grid p-6;\n    transition: background-color 500ms ease-in-out;\n\n    grid-template-areas:\n      '. .     .'\n      '. modal .'\n      '. .     .';\n\n    grid-template-columns: 1fr min(30rem, 100%) 1fr;\n    grid-template-rows: 1fr auto 3fr;\n  }\n\n  [part='container'] {\n    @apply rounded shadow;\n  }\n\n  [part='header-wrapper'] {\n    @apply px-6 py-4;\n  }\n\n  [part='header'] {\n    @apply font-bold;\n  }\n\n  [part='body-wrapper'] {\n    @apply p-6;\n  }\n\n  [part='footer-wrapper'] {\n    @apply bg-neutral-light;\n    padding: 1rem 1.125rem;\n  }\n}\n\n:host(.fullscreen) {\n  [part='container'] {\n    @apply absolute inset-0;\n  }\n\n  [part='header-wrapper'] {\n    @apply p-6;\n  }\n\n  [part='body-wrapper'] {\n    @apply px-6 pt-8 pb-5;\n  }\n\n  [part='footer-wrapper'] {\n    @apply shadow-t-lg px-6 py-4;\n  }\n}\n","import {\n  Component,\n  h,\n  State,\n  Prop,\n  Element,\n  Watch,\n  Event,\n  EventEmitter,\n  Host,\n  Listen,\n} from '@stencil/core';\nimport {isIOS} from '../../../utils/device-utils';\nimport {listenOnce} from '../../../utils/event-utils';\nimport {\n  InitializableComponent,\n  InitializeBindings,\n} from '../../../utils/initialization-utils';\nimport {updateBreakpoints} from '../../../utils/replace-breakpoint';\nimport {once, randomID} from '../../../utils/utils';\nimport {AnyBindings} from '../interface/bindings';\n\n/**\n * When the modal is opened, the class `atomic-modal-opened` is added to the interfaceElement and the body, allowing further customization.\n *\n * @part backdrop - The transparent backdrop hiding the content behind the modal.\n * @part container - The modal's outermost container with the outline and background.\n * @part header-wrapper - The wrapper around the header.\n * @part header - The header at the top of the modal.\n * @part header-ruler - The horizontal ruler underneath the header.\n * @part body-wrapper - The wrapper around the body.\n * @part body - The body of the modal, between the header and the footer.\n * @part footer-wrapper - The wrapper with a shadow or background color around the footer.\n * @part footer - The footer at the bottom of the modal.\n * @internal\n */\n@Component({\n  tag: 'atomic-modal',\n  styleUrl: 'atomic-modal.pcss',\n  shadow: true,\n})\nexport class AtomicModal implements InitializableComponent<AnyBindings> {\n  @InitializeBindings() public bindings!: AnyBindings;\n  @Element() public host!: HTMLElement;\n\n  @State() public error!: Error;\n\n  @Prop({reflect: true, mutable: true}) fullscreen = false;\n  @Prop({mutable: true}) source?: HTMLElement;\n  /**\n   * The container to hide from the tabindex and accessibility DOM when the modal is closed.\n   */\n  @Prop({mutable: true}) container?: HTMLElement;\n  @Prop({reflect: true, mutable: true}) isOpen = false;\n  @Prop({mutable: true}) close: () => void = () => (this.isOpen = false);\n  @Prop({reflect: true}) scope?: HTMLElement;\n  /**\n   * Whether to display the open and close animations over the entire page or the atomic-modal only.\n   */\n  @Prop({reflect: true}) boundary: 'page' | 'element' = 'page';\n\n  @Event() animationEnded!: EventEmitter<never>;\n\n  private wasEverOpened = false;\n  private headerId = randomID('atomic-modal-header-');\n  private focusTrap?: HTMLAtomicFocusTrapElement;\n  private animatableContainer?: HTMLElement;\n  private currentWatchToggleOpenExecution = 0;\n\n  @Watch('isOpen')\n  async watchToggleOpen(isOpen: boolean) {\n    const watchToggleOpenExecution = ++this.currentWatchToggleOpenExecution;\n    const modalOpenedClass = 'atomic-modal-opened';\n\n    if (isOpen) {\n      this.wasEverOpened = true;\n      //TODO: remove the addition of a class to the body in atomicV3\n      document.body.classList.add(modalOpenedClass);\n      this.bindings.interfaceElement.classList.add(modalOpenedClass);\n      await this.waitForAnimationEnded();\n      if (watchToggleOpenExecution !== this.currentWatchToggleOpenExecution) {\n        return;\n      }\n      this.focusTrap!.active = true;\n    } else {\n      //TODO: remove the removal of a class to the body in atomicV3\n      document.body.classList.remove(modalOpenedClass);\n      this.bindings.interfaceElement.classList.remove(modalOpenedClass);\n      if (isIOS()) {\n        await this.waitForAnimationEnded();\n      }\n      if (watchToggleOpenExecution !== this.currentWatchToggleOpenExecution) {\n        return;\n      }\n      this.focusTrap!.active = false;\n    }\n  }\n\n  @Listen('keyup', {target: 'body'})\n  handleCloseOnEscape(e: KeyboardEvent) {\n    if (e.key?.toLowerCase() === 'escape') {\n      this.close();\n    }\n  }\n\n  private waitForAnimationEnded() {\n    // The focus trap focuses its first child when active. It cannot do that while an animation is ongoing.\n    return new Promise((resolve) =>\n      listenOnce(this.animatableContainer!, 'animationend', resolve)\n    );\n  }\n\n  private getClasses() {\n    const classes: string[] = [];\n    if (this.isOpen) {\n      classes.push('open');\n    }\n    if (this.fullscreen) {\n      classes.push('fullscreen');\n    } else {\n      classes.push('dialog');\n    }\n    return classes;\n  }\n\n  @Listen('touchmove', {passive: false})\n  onWindowTouchMove(e: Event) {\n    this.isOpen && e.preventDefault();\n  }\n\n  public componentDidLoad() {\n    this.watchToggleOpen(this.isOpen);\n  }\n\n  private updateBreakpoints = once(() => updateBreakpoints(this.host));\n\n  public render() {\n    this.updateBreakpoints();\n\n    const Content = () => (\n      <article\n        part=\"container\"\n        class={`flex flex-col justify-between bg-background text-on-background\n          ${this.isOpen ? 'animate-scaleUpModal' : 'animate-slideDownModal'}\n          ${this.wasEverOpened ? '' : 'invisible'}`}\n        onAnimationEnd={() => this.animationEnded.emit()}\n        ref={(ref) => (this.animatableContainer = ref)}\n      >\n        <header part=\"header-wrapper\" class=\"flex flex-col items-center\">\n          <div\n            part=\"header\"\n            class=\"flex justify-between text-xl w-full max-w-lg\"\n            id={this.headerId}\n          >\n            <slot name=\"header\"></slot>\n          </div>\n        </header>\n        <hr part=\"header-ruler\" class=\"border-neutral\"></hr>\n        <div\n          part=\"body-wrapper\"\n          class=\"overflow-auto grow flex flex-col items-center w-full\"\n        >\n          <div\n            part=\"body\"\n            class=\"w-full max-w-lg\"\n            ref={(element) =>\n              element?.addEventListener(\n                'touchmove',\n                (e) => this.isOpen && e.stopPropagation(),\n                {passive: false}\n              )\n            }\n          >\n            <slot name=\"body\"></slot>\n          </div>\n        </div>\n        <footer\n          part=\"footer-wrapper\"\n          class=\"border-neutral border-t bg-background z-10 flex flex-col items-center w-full\"\n        >\n          <div part=\"footer\" class=\"w-full max-w-lg\">\n            <slot name=\"footer\"></slot>\n          </div>\n        </footer>\n      </article>\n    );\n\n    return (\n      <Host class={this.getClasses().join(' ')}>\n        <div\n          part=\"backdrop\"\n          class={`\n            ${this.boundary === 'page' ? 'fixed' : 'absolute'}\n            left-0 top-0 right-0 bottom-0 z-[9999]\n          `}\n          onClick={(e) => e.target === e.currentTarget && this.close()}\n        >\n          <atomic-focus-trap\n            role=\"dialog\"\n            aria-modal={this.isOpen.toString()}\n            aria-labelledby={this.headerId}\n            source={this.source}\n            container={this.container ?? this.host}\n            ref={(ref) => (this.focusTrap = ref)}\n            scope={this.scope}\n          >\n            <Content />\n          </atomic-focus-trap>\n        </div>\n      </Host>\n    );\n  }\n}\n"],"mappings":"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"}