bootstrap-vue-next
Version:
Seamless integration of Vue 3, Bootstrap 5, and TypeScript for modern, type-safe UI development
187 lines (186 loc) • 6.93 kB
JavaScript
const require_keys = require("./keys-durSVUrO.js");
const require_floatingUi = require("./floatingUi-Cs4rDXmO.js");
//#region src/directives/utils.ts
/**
* Gets the component instance UID from a directive binding
* @throws Error if binding.instance is not available
*/
function getDirectiveUid(binding) {
if (!binding.instance) throw new Error("[Bootstrap-Vue-Next] Directive binding.instance is not available");
return binding.instance.$.uid;
}
/**
* Initializes UID-namespaced storage on an element for a directive
* @param el - The HTML element
* @param propertyName - The property name (e.g., '$__tooltip', '$__popover')
* @param uid - The component instance UID
* @param binding - The directive binding value to cache
* @returns The initialized instance state
*/
function initDirectiveInstance(el, propertyName, uid, binding) {
const elWithProps = el;
elWithProps[propertyName] = elWithProps[propertyName] ?? Object.create(null);
const state = {
binding: JSON.stringify([binding.modifiers, binding.value]),
destroying: false
};
elWithProps[propertyName][uid] = state;
return state;
}
/**
* Gets the instance state for a directive, if it exists
* @param el - The HTML element
* @param propertyName - The property name (e.g., '$__tooltip', '$__popover')
* @param uid - The component instance UID
* @returns The instance state or undefined if not found
*/
function getDirectiveInstance(el, propertyName, uid) {
return el[propertyName]?.[uid];
}
/**
* Checks if the directive binding has changed for this instance
* @param instance - The directive instance state
* @param binding - The current directive binding
* @returns true if the binding has changed, false otherwise
*/
function hasBindingChanged(instance, binding) {
const newBinding = JSON.stringify([binding.modifiers, binding.value]);
return instance.binding !== newBinding;
}
/**
* Updates the cached binding value for a directive instance
* @param instance - The directive instance state
* @param binding - The new directive binding
*/
function updateBindingCache(instance, binding) {
instance.binding = JSON.stringify([binding.modifiers, binding.value]);
}
/**
* Cleans up a directive instance
* @param el - The HTML element
* @param propertyName - The property name (e.g., '$__tooltip', '$__popover')
* @param uid - The component instance UID
*/
function cleanupDirectiveInstance(el, propertyName, uid) {
const elWithProps = el;
const instance = elWithProps[propertyName]?.[uid];
if (instance) {
instance.destroying = true;
delete elWithProps[propertyName][uid];
}
}
function findProvides(binding, vnode) {
return (vnode.ctx === binding.instance.$ ? findComponentParent(vnode, binding.instance.$)?.provides : vnode.ctx?.provides) ?? binding.instance.$.provides;
}
function findComponentParent(vnode, root) {
const stack = /* @__PURE__ */ new Set();
const walk = (children) => {
for (const child of children) {
if (!child) continue;
if (child === vnode || child.el && vnode.el && child.el === vnode.el) return true;
stack.add(child);
let result;
if (child.suspense) result = walk([child.ssContent]);
else if (Array.isArray(child.children)) result = walk(child.children);
else if (child.component?.vnode) result = walk([child.component?.subTree]);
if (result) return result;
stack.delete(child);
}
return false;
};
if (!walk([root.subTree])) {
console.error("Could not find original vnode, will not inherit provides");
return root;
}
const result = Array.from(stack).reverse();
for (const child of result) if (child.component) return child.component;
return root;
}
/**
* Creates a floating UI directive (tooltip or popover) with UID-namespaced state management
* @param propertyName - The property name for storing state (e.g., '$__tooltip', '$__popover')
* @param componentDefaultsKey - The key for accessing component defaults (e.g., 'BTooltip', 'BPopover')
* @param buildProps - Optional function to customize the props passed to bind()
* @returns A Vue directive object
*/
function createFloatingDirective(propertyName, componentDefaultsKey, buildProps) {
return {
mounted(el, binding, vnode) {
const uid = getDirectiveUid(binding);
const defaultsMap = findProvides(binding, vnode)[require_keys.defaultsKey]?.value;
if (!require_floatingUi.resolveActiveStatus(binding.value)) return;
const text = require_floatingUi.resolveContent(binding.value, el);
if (!text.body && !text.title) return;
initDirectiveInstance(el, propertyName, uid, binding);
require_floatingUi.bind(el, binding, buildProps ? buildProps(text, defaultsMap?.[componentDefaultsKey], binding, el) : {
...defaultsMap?.[componentDefaultsKey] || void 0,
...require_floatingUi.resolveDirectiveProps(binding, el),
...text
});
},
updated(el, binding, vnode) {
const uid = getDirectiveUid(binding);
let instance = getDirectiveInstance(el, propertyName, uid);
const defaultsMap = findProvides(binding, vnode)[require_keys.defaultsKey]?.value;
if (!require_floatingUi.resolveActiveStatus(binding.value)) {
if (instance && el.$__element) {
require_floatingUi.unbind(el);
cleanupDirectiveInstance(el, propertyName, uid);
}
return;
}
const text = require_floatingUi.resolveContent(binding.value, el);
if (!text.body && !text.title) {
if (instance && el.$__element) {
require_floatingUi.unbind(el);
cleanupDirectiveInstance(el, propertyName, uid);
}
return;
}
if (!instance) {
instance = initDirectiveInstance(el, propertyName, uid, binding);
require_floatingUi.bind(el, binding, buildProps ? buildProps(text, defaultsMap?.[componentDefaultsKey], binding, el) : {
...defaultsMap?.[componentDefaultsKey] || void 0,
...require_floatingUi.resolveDirectiveProps(binding, el),
...text
});
return;
}
if (!hasBindingChanged(instance, binding)) return;
if (instance.destroying) return;
require_floatingUi.unbind(el);
require_floatingUi.bind(el, binding, buildProps ? buildProps(text, defaultsMap?.[componentDefaultsKey], binding, el) : {
...defaultsMap?.[componentDefaultsKey] || void 0,
...require_floatingUi.resolveDirectiveProps(binding, el),
...text
});
updateBindingCache(instance, binding);
},
beforeUnmount(el, binding) {
const uid = getDirectiveUid(binding);
if (!getDirectiveInstance(el, propertyName, uid)) return;
require_floatingUi.unbind(el);
cleanupDirectiveInstance(el, propertyName, uid);
}
};
}
//#endregion
Object.defineProperty(exports, "createFloatingDirective", {
enumerable: true,
get: function() {
return createFloatingDirective;
}
});
Object.defineProperty(exports, "findProvides", {
enumerable: true,
get: function() {
return findProvides;
}
});
Object.defineProperty(exports, "getDirectiveUid", {
enumerable: true,
get: function() {
return getDirectiveUid;
}
});
//# sourceMappingURL=utils-CaC78Zdk.js.map