{"version":3,"file":"utils-D_vdhVDP.mjs","names":[],"sources":["../src/directives/utils.ts"],"sourcesContent":["import type {ComponentInternalInstance, Directive, DirectiveBinding, Ref, VNode} from 'vue'\nimport type {BPopoverProps} from '../types/ComponentProps'\nimport {\n  bind,\n  type ElementWithPopper,\n  resolveActiveStatus,\n  resolveContent,\n  resolveDirectiveProps,\n  unbind,\n} from '../utils/floatingUi'\nimport {defaultsKey} from '../utils/keys'\n\ninterface _ComponentInternalInstance extends ComponentInternalInstance {\n  provides?: Record<string, unknown>\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  setupState?: any\n}\n\ninterface _VNode extends VNode {\n  ctx?: _ComponentInternalInstance | null\n  ssContent?: VNode | null\n}\n\n/**\n * Represents per-instance state for directives using UID namespacing\n */\nexport interface DirectiveInstanceState {\n  binding: string // JSON.stringify cache for change detection\n  destroying: boolean // Flag to prevent race conditions during cleanup\n}\n\n/**\n * Gets the component instance UID from a directive binding\n * @throws Error if binding.instance is not available\n */\nexport function getDirectiveUid(binding: DirectiveBinding): number {\n  if (!binding.instance) {\n    throw new Error('[Bootstrap-Vue-Next] Directive binding.instance is not available')\n  }\n  return binding.instance.$.uid\n}\n\n/**\n * Initializes UID-namespaced storage on an element for a directive\n * @param el - The HTML element\n * @param propertyName - The property name (e.g., '$__tooltip', '$__popover')\n * @param uid - The component instance UID\n * @param binding - The directive binding value to cache\n * @returns The initialized instance state\n */\nexport function initDirectiveInstance(\n  el: HTMLElement & Record<string, unknown>,\n  propertyName: string,\n  uid: number,\n  binding: DirectiveBinding\n): DirectiveInstanceState {\n  // Initialize UID namespace for this directive\n  const elWithProps = el as Record<string, unknown>\n  elWithProps[propertyName] = elWithProps[propertyName] ?? Object.create(null)\n\n  // Store per-instance state with JSON cache for change detection\n  const state: DirectiveInstanceState = {\n    binding: JSON.stringify([binding.modifiers, binding.value]),\n    destroying: false,\n  }\n\n  ;(elWithProps[propertyName] as Record<string, unknown>)[uid] = state\n  return state\n}\n\n/**\n * Gets the instance state for a directive, if it exists\n * @param el - The HTML element\n * @param propertyName - The property name (e.g., '$__tooltip', '$__popover')\n * @param uid - The component instance UID\n * @returns The instance state or undefined if not found\n */\nexport function getDirectiveInstance(\n  el: HTMLElement & Record<string, unknown>,\n  propertyName: string,\n  uid: number\n): DirectiveInstanceState | undefined {\n  const elWithProps = el as Record<string, unknown>\n  return (elWithProps[propertyName] as Record<string, unknown> | undefined)?.[uid] as\n    | DirectiveInstanceState\n    | undefined\n}\n\n/**\n * Checks if the directive binding has changed for this instance\n * @param instance - The directive instance state\n * @param binding - The current directive binding\n * @returns true if the binding has changed, false otherwise\n */\nexport function hasBindingChanged(\n  instance: DirectiveInstanceState,\n  binding: DirectiveBinding\n): boolean {\n  const newBinding = JSON.stringify([binding.modifiers, binding.value])\n  return instance.binding !== newBinding\n}\n\n/**\n * Updates the cached binding value for a directive instance\n * @param instance - The directive instance state\n * @param binding - The new directive binding\n */\nexport function updateBindingCache(\n  instance: DirectiveInstanceState,\n  binding: DirectiveBinding\n): void {\n  instance.binding = JSON.stringify([binding.modifiers, binding.value])\n}\n\n/**\n * Cleans up a directive instance\n * @param el - The HTML element\n * @param propertyName - The property name (e.g., '$__tooltip', '$__popover')\n * @param uid - The component instance UID\n */\nexport function cleanupDirectiveInstance(\n  el: HTMLElement & Record<string, unknown>,\n  propertyName: string,\n  uid: number\n): void {\n  const elWithProps = el as Record<string, unknown>\n  const instance = (elWithProps[propertyName] as Record<string, unknown> | undefined)?.[uid] as\n    | DirectiveInstanceState\n    | undefined\n  if (instance) {\n    instance.destroying = true\n    delete (elWithProps[propertyName] as Record<string, unknown>)[uid]\n  }\n}\n\n// taken from vuetify https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/composables/directiveComponent.ts\n\nexport function findProvides(binding: DirectiveBinding, vnode: _VNode): Record<string, unknown> {\n  const provides =\n    (vnode.ctx === binding.instance!.$\n      ? findComponentParent(vnode, binding.instance!.$)?.provides\n      : vnode.ctx?.provides) ?? binding.instance!.$.provides\n\n  return provides\n}\n\nexport function findComponentParent(\n  vnode: VNode,\n  root: ComponentInternalInstance\n): _ComponentInternalInstance | null {\n  // Walk the tree from root until we find the child vnode\n  const stack = new Set<VNode>()\n  const walk = (children: _VNode[]): boolean => {\n    for (const child of children) {\n      if (!child) continue\n\n      if (child === vnode || (child.el && vnode.el && child.el === vnode.el)) {\n        return true\n      }\n\n      stack.add(child)\n      let result\n      if (child.suspense) {\n        result = walk([child.ssContent!])\n      } else if (Array.isArray(child.children)) {\n        result = walk(child.children as VNode[])\n      } else if (child.component?.vnode) {\n        result = walk([child.component?.subTree])\n      }\n      if (result) {\n        return result\n      }\n      stack.delete(child)\n    }\n\n    return false\n  }\n  if (!walk([root.subTree])) {\n    console.error('Could not find original vnode,  will not inherit provides')\n    return root\n  }\n\n  // Return the first component parent\n  const result = Array.from(stack).reverse()\n  for (const child of result) {\n    if (child.component) {\n      return child.component\n    }\n  }\n  return root\n}\n\n/**\n * Creates a floating UI directive (tooltip or popover) with UID-namespaced state management\n * @param propertyName - The property name for storing state (e.g., '$__tooltip', '$__popover')\n * @param componentDefaultsKey - The key for accessing component defaults (e.g., 'BTooltip', 'BPopover')\n * @param buildProps - Optional function to customize the props passed to bind()\n * @returns A Vue directive object\n */\nexport function createFloatingDirective(\n  propertyName: string,\n  componentDefaultsKey: string,\n  buildProps?: (\n    text: {title?: string; body?: string},\n    defaults: unknown,\n    binding: Readonly<DirectiveBinding>,\n    el: Readonly<HTMLElement>\n  ) => BPopoverProps\n): Directive<ElementWithPopper> {\n  return {\n    mounted(el, binding, vnode) {\n      const uid = getDirectiveUid(binding)\n      const defaultsMap = (findProvides(binding, vnode) as Record<symbol, Ref>)[defaultsKey]\n        ?.value as Record<string, unknown> | undefined\n      const isActive = resolveActiveStatus(binding.value)\n      if (!isActive) return\n\n      const text = resolveContent(binding.value, el)\n\n      if (!text.body && !text.title) return\n\n      // Initialize per-instance state with UID namespacing\n      initDirectiveInstance(el, propertyName, uid, binding)\n\n      const props = buildProps\n        ? buildProps(text, defaultsMap?.[componentDefaultsKey], binding, el)\n        : {\n            ...(defaultsMap?.[componentDefaultsKey] || undefined),\n            ...resolveDirectiveProps(binding, el),\n            ...text,\n          }\n\n      bind(el, binding, props)\n    },\n\n    updated(el, binding, vnode) {\n      const uid = getDirectiveUid(binding)\n      let instance = getDirectiveInstance(el, propertyName, uid)\n\n      const defaultsMap = (findProvides(binding, vnode) as Record<symbol, Ref>)[defaultsKey]\n        ?.value as Record<string, unknown> | undefined\n\n      const isActive = resolveActiveStatus(binding.value)\n\n      // If inactive, clean up existing instance if present\n      if (!isActive) {\n        if (instance && el.$__element) {\n          unbind(el)\n          cleanupDirectiveInstance(el, propertyName, uid)\n        }\n        return\n      }\n\n      const text = resolveContent(binding.value, el)\n\n      if (!text.body && !text.title) {\n        // Clean up if no content\n        if (instance && el.$__element) {\n          unbind(el)\n          cleanupDirectiveInstance(el, propertyName, uid)\n        }\n        return\n      }\n\n      // If instance doesn't exist, this is a transition from inactive/no-content to active\n      // Initialize the instance now (similar to mounted)\n      if (!instance) {\n        instance = initDirectiveInstance(el, propertyName, uid, binding)\n\n        const props = buildProps\n          ? buildProps(text, defaultsMap?.[componentDefaultsKey], binding, el)\n          : {\n              ...(defaultsMap?.[componentDefaultsKey] || undefined),\n              ...resolveDirectiveProps(binding, el),\n              ...text,\n            }\n\n        bind(el, binding, props)\n        return\n      }\n\n      // Check if binding changed for THIS instance\n      if (!hasBindingChanged(instance, binding)) return\n\n      // Prevent race conditions during update\n      if (instance.destroying) return\n\n      unbind(el)\n\n      const props = buildProps\n        ? buildProps(text, defaultsMap?.[componentDefaultsKey], binding, el)\n        : {\n            ...(defaultsMap?.[componentDefaultsKey] || undefined),\n            ...resolveDirectiveProps(binding, el),\n            ...text,\n          }\n\n      bind(el, binding, props)\n\n      // Update THIS instance's cache\n      updateBindingCache(instance, binding)\n    },\n\n    beforeUnmount(el, binding) {\n      const uid = getDirectiveUid(binding)\n      const instance = getDirectiveInstance(el, propertyName, uid)\n\n      if (!instance) return\n\n      unbind(el)\n      cleanupDirectiveInstance(el, propertyName, uid)\n    },\n  }\n}\n"],"mappings":"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"}