{"version":3,"file":"utils-BfbvBFtw.mjs","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    // eslint-disable-next-line no-console\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"],"names":["result","props"],"mappings":"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"}