{"version":3,"sources":["../src/utils/index.ts","/Users/aaroniker/Documents/GitHub/ease/web-kit/packages/core/src/utils/dismiss-controller.ts","/Users/aaroniker/Documents/GitHub/ease/web-kit/packages/core/src/utils/outside-click.ts","/Users/aaroniker/Documents/GitHub/ease/web-kit/packages/core/src/utils/template-helpers.ts"],"sourcesContent":["export { DismissController } from './dismiss-controller';\nexport { createOutsideClickHandle } from './outside-click';\nexport {\n  classMap,\n  ifDefined,\n  optionalAttribute,\n  renderIf,\n  renderList,\n  repeat,\n  styleMap,\n  styleObject,\n  unsafeHTML,\n  when\n} from './template-helpers';\n","export interface DismissContext {\n  owner: HTMLElement;\n  content?: HTMLElement | null;\n  triggers?: Array<HTMLElement | null | undefined>;\n}\n\nexport interface DismissControllerOptions {\n  onDismiss: (event: Event) => void;\n}\n\nexport class DismissController {\n  #onDismiss: (event: Event) => void;\n  #context: {\n    owner: HTMLElement;\n    content: HTMLElement | null;\n    triggers: HTMLElement[];\n  } | null = null;\n  #active = false;\n\n  constructor(options: DismissControllerOptions) {\n    this.#onDismiss = options.onDismiss;\n  }\n\n  connect(context: DismissContext): void {\n    this.#context = {\n      owner: context.owner,\n      content: context.content ?? null,\n      triggers: (context.triggers ?? []).filter((el): el is HTMLElement => el instanceof HTMLElement)\n    };\n\n    if (!this.#active) {\n      document.addEventListener('pointerdown', this.#handlePointerDown, true);\n      document.addEventListener('keydown', this.#handleKeyDown, true);\n      this.#active = true;\n    }\n  }\n\n  disconnect(): void {\n    if (!this.#active) {\n      return;\n    }\n\n    document.removeEventListener('pointerdown', this.#handlePointerDown, true);\n    document.removeEventListener('keydown', this.#handleKeyDown, true);\n    this.#active = false;\n    this.#context = null;\n  }\n\n  #handlePointerDown = (event: PointerEvent): void => {\n    if (!this.#context) {\n      return;\n    }\n\n    const { owner, content, triggers } = this.#context;\n    const path = event.composedPath();\n\n    if (path.some((node) => node instanceof Element && node.hasAttribute('data-select-ignore'))) {\n      return;\n    }\n\n    if (path.includes(owner)) {\n      return;\n    }\n\n    if (content && path.includes(content)) {\n      return;\n    }\n\n    if (triggers.some((trigger) => path.includes(trigger))) {\n      return;\n    }\n\n    this.#onDismiss(event);\n  };\n\n  #handleKeyDown = (event: KeyboardEvent): void => {\n    if (event.key !== 'Escape' || !this.#context) {\n      return;\n    }\n\n    event.preventDefault();\n\n    const active = document.activeElement as HTMLElement | null;\n\n    if (!active) {\n      this.#onDismiss(event);\n      return;\n    }\n\n    const { owner, content, triggers } = this.#context;\n    const path = event.composedPath();\n\n    if (path.includes(owner) || owner.contains(active)) {\n      this.#onDismiss(event);\n      return;\n    }\n\n    if (content && (path.includes(content) || content.contains(active))) {\n      this.#onDismiss(event);\n      return;\n    }\n\n    if (triggers.some((trigger) => path.includes(trigger) || trigger.contains(active))) {\n      this.#onDismiss(event);\n    }\n  };\n}\n","import type { DismissContext } from './dismiss-controller';\n\nimport { DismissController } from './dismiss-controller';\n\nexport interface OutsideClickResolution {\n  owner?: HTMLElement | null | undefined;\n  content?: HTMLElement | null | undefined;\n  triggers?: Array<HTMLElement | null | undefined>;\n}\n\nexport interface OutsideClickHandle {\n  update(): void;\n  disconnect(): void;\n}\n\nexport interface OutsideClickHandleOptions<THost extends HTMLElement> {\n  resolve: (host: THost) => OutsideClickResolution | null | undefined;\n  disabled?: (host: THost) => boolean;\n}\n\nconst registry = new WeakMap<HTMLElement, Set<OutsideClickHandle>>();\n\nconst toDismissContext = <THost extends HTMLElement>(\n  host: THost,\n  options: OutsideClickHandleOptions<THost>\n): DismissContext | null => {\n  if (options.disabled?.(host)) {\n    return null;\n  }\n\n  const resolved = options.resolve(host);\n\n  if (!resolved) {\n    return null;\n  }\n\n  const owner = resolved.owner ?? host ?? null;\n\n  if (!(owner instanceof HTMLElement)) {\n    return null;\n  }\n\n  const content = resolved.content && resolved.content instanceof HTMLElement ? resolved.content : null;\n\n  const triggers = resolved.triggers?.filter((element): element is HTMLElement => element instanceof HTMLElement) ?? [];\n\n  return {\n    owner,\n    content,\n    triggers\n  };\n};\n\nexport const createOutsideClickHandle = <THost extends HTMLElement>(\n  host: THost,\n  onDismiss: (this: THost, event: Event) => void,\n  options: OutsideClickHandleOptions<THost>\n): OutsideClickHandle => {\n  const controller = new DismissController({\n    onDismiss(event) {\n      if (options.disabled?.(host)) {\n        return;\n      }\n\n      onDismiss.call(host, event);\n    }\n  });\n\n  return {\n    update(): void {\n      const context = toDismissContext(host, options);\n      if (!context) {\n        controller.disconnect();\n        return;\n      }\n\n      controller.connect(context);\n    },\n    disconnect(): void {\n      controller.disconnect();\n    }\n  };\n};\n\nexport const registerOutsideClickHandle = (host: HTMLElement, handle: OutsideClickHandle): void => {\n  let handles = registry.get(host);\n\n  if (!handles) {\n    handles = new Set();\n    registry.set(host, handles);\n  }\n\n  handles.add(handle);\n};\n\nexport const updateOutsideClickHandles = (host: HTMLElement): void => {\n  const handles = registry.get(host);\n\n  if (!handles) {\n    return;\n  }\n\n  handles.forEach((handle) => {\n    handle.update();\n  });\n};\n\nexport const disconnectOutsideClickHandles = (host: HTMLElement): void => {\n  const handles = registry.get(host);\n\n  if (!handles) {\n    return;\n  }\n\n  handles.forEach((handle) => {\n    handle.disconnect();\n  });\n};\n\nexport const requestOutsideClickUpdate = (host: HTMLElement): void => {\n  updateOutsideClickHandles(host);\n};\n","import type { TemplateResult } from 'lit-html';\n\nimport { nothing } from 'lit-html';\nimport { classMap } from 'lit-html/directives/class-map.js';\nimport { ifDefined } from 'lit-html/directives/if-defined.js';\nimport { repeat } from 'lit-html/directives/repeat.js';\nimport { styleMap } from 'lit-html/directives/style-map.js';\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js';\nimport { when } from 'lit-html/directives/when.js';\n\nexport { classMap, ifDefined, repeat, styleMap, unsafeHTML, when };\n\nexport function renderIf<T>(\n  condition: T | undefined | null,\n  template: TemplateResult | (() => TemplateResult)\n): TemplateResult | typeof nothing {\n  if (!condition) {\n    return nothing;\n  }\n\n  return typeof template === 'function' ? template() : template;\n}\n\nexport function renderList<T>(\n  items: readonly T[],\n  template: (item: T, index: number) => TemplateResult,\n  key: (item: T, index: number) => unknown = (item) => item\n): ReturnType<typeof repeat> {\n  return repeat(items, key, template);\n}\n\nexport function styleObject(input: Record<string, string | number | null | undefined>): ReturnType<typeof styleMap> {\n  const definedEntries = Object.entries(input).reduce<Record<string, string>>((acc, [property, value]) => {\n    if (value === null || value === undefined || value === '') {\n      return acc;\n    }\n\n    acc[property] = typeof value === 'number' ? `${value}` : value;\n    return acc;\n  }, {});\n\n  return styleMap(definedEntries);\n}\n\nexport const optionalAttribute = ifDefined;\n"],"mappings":"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","names":["DismissController","options","event","owner","content","triggers","path","composedPath","some","node","Element","hasAttribute","includes","trigger","key","preventDefault","active","document","activeElement","contains","onDismiss","connect","context","filter","el","HTMLElement","addEventListener","disconnect","removeEventListener","toDismissContext","host","options","disabled","resolved","resolve","owner","HTMLElement","content","triggers","filter","element","createOutsideClickHandle","onDismiss","controller","DismissController","event","call","update","context","disconnect","connect","renderIf","condition","template","nothing","renderList","items","key","item","repeat","styleObject","input","definedEntries","Object","entries","reduce","acc","property","value","undefined","styleMap","optionalAttribute","ifDefined"]}