UNPKG

bootstrap-vue-next

Version:

Seamless integration of Vue 3, Bootstrap 5, and TypeScript for modern, type-safe UI development

1 lines 6.74 kB
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/directives/BToggle/index.ts"],"sourcesContent":["import {RX_HASH, RX_HASH_ID, RX_SPACE_SPLIT} from '../../utils/constants'\nimport {type Directive, type DirectiveBinding, type VNode} from 'vue'\nimport {findProvides} from '../utils'\nimport {type RegisterShowHideValue, showHideRegistryKey} from '../../utils/keys'\nimport {getActiveShowHide} from '../../utils/registryAccess'\nimport {warn} from '../../utils/console'\n\nconst getTargets = (\n binding: DirectiveBinding<string | readonly string[] | undefined>,\n el: Readonly<Element>\n) => {\n const {modifiers, arg, value} = binding\n // Any modifiers are considered target Ids\n const targets = Object.keys(modifiers || {})\n\n // If value is a string, split out individual targets (if space delimited)\n const localValue = typeof value === 'string' ? value.split(RX_SPACE_SPLIT) : value\n\n // Support target Id as link href (`href=\"#id\"`)\n if (el.tagName.toLowerCase() === 'a') {\n const href = el.getAttribute('href') || ''\n if (RX_HASH_ID.test(href)) {\n targets.push(href.replace(RX_HASH, ''))\n }\n }\n\n // Add Id from `arg` (if provided), and support value\n // as a single string Id or an array of string Ids\n // If `value` is not an array or string, then it gets filtered out\n Array.prototype.concat\n .apply([], [arg, localValue])\n .forEach((t) => typeof t === 'string' && targets.push(t))\n\n // Return only unique and truthy target Ids\n return targets.filter((t, index, arr) => t && arr.indexOf(t) === index)\n}\n\nconst handleUpdate = (\n el: Element,\n binding: DirectiveBinding<string | readonly string[] | undefined>,\n vnode: VNode\n) => {\n // Determine targets\n const targets = getTargets(binding, el)\n if (targets.length === 0) return\n const targetsSet = new Set(targets)\n\n const provides = findProvides(binding, vnode)\n const showHideMap =\n (provides as Record<symbol, RegisterShowHideValue>)[showHideRegistryKey]?.values ?? null\n if ((el as HTMLElement).dataset.bvtoggle) {\n const oldTargets = ((el as HTMLElement).dataset.bvtoggle || '').split(' ')\n if (oldTargets.length === 0) return\n for (const targetId of oldTargets) {\n const showHide = getActiveShowHide(showHideMap, targetId)\n if (!showHide) {\n continue\n }\n if (!targetsSet.has(targetId)) {\n showHide.unregisterTrigger('click', el, false)\n }\n }\n }\n ;(el as HTMLElement).dataset.bvtoggle = targets.join(' ')\n\n targets.forEach(async (targetId) => {\n let count = 0\n const maxAttempts = 5\n const delayMs = 100\n\n // Keep looking until showHide is found, giving up after 500ms or directive is unmounted\n while (count < maxAttempts) {\n // Check if element is still mounted before each iteration\n if (!(el as HTMLElement).dataset.bvtoggle) {\n // Element was unmounted, stop trying\n return\n }\n\n const showHide = getActiveShowHide(showHideMap, targetId)\n if (!showHide) {\n count++\n if (count < maxAttempts) {\n await new Promise((resolve) => setTimeout(resolve, delayMs))\n continue\n }\n // Only warn if element is still mounted after all attempts\n if ((el as HTMLElement).dataset.bvtoggle) {\n warn(\n 'v-b-toggle',\n `Target with ID ${targetId} not found after ${maxAttempts * delayMs}ms`\n )\n }\n break\n }\n\n // Final check before registration\n if (!(el as HTMLElement).dataset.bvtoggle) return\n\n // Register the trigger element\n showHide.unregisterTrigger('click', el, false)\n showHide.registerTrigger('click', el)\n break\n }\n })\n\n el.setAttribute('aria-controls', targets.join(' '))\n}\nconst handleUnmount = (\n el: Element,\n binding: DirectiveBinding<string | readonly string[] | undefined>,\n vnode: VNode\n) => {\n // Determine targets\n const targets = getTargets(binding, el)\n if (targets.length === 0) return\n const provides = findProvides(binding, vnode, true)\n const showHideMap =\n (provides as Record<symbol, RegisterShowHideValue>)[showHideRegistryKey]?.values ?? null\n\n targets.forEach((targetId) => {\n const showHide = getActiveShowHide(showHideMap, targetId)\n if (!showHide) {\n return\n }\n // Pass clean=true to let the composable handle cleanup of aria-expanded and classes\n showHide.unregisterTrigger('click', el, true)\n })\n\n // Only remove what the directive manages (aria-controls)\n // aria-expanded and classes are managed by useShowHide composable\n el.removeAttribute('aria-controls')\n delete (el as HTMLElement).dataset.bvtoggle\n}\n\nexport const vBToggle: Directive<Element> = {\n mounted: handleUpdate,\n updated: handleUpdate,\n unmounted: handleUnmount,\n}\n"],"mappings":";;;;;;;AAOA,IAAM,cACJ,SACA,OACG;CACH,MAAM,EAAC,WAAW,KAAK,UAAS;CAEhC,MAAM,UAAU,OAAO,KAAK,aAAa,CAAC,CAAC;CAG3C,MAAM,aAAa,OAAO,UAAU,WAAW,MAAM,MAAM,cAAc,IAAI;CAG7E,IAAI,GAAG,QAAQ,YAAY,MAAM,KAAK;EACpC,MAAM,OAAO,GAAG,aAAa,MAAM,KAAK;EACxC,IAAI,WAAW,KAAK,IAAI,GACtB,QAAQ,KAAK,KAAK,QAAQ,SAAS,EAAE,CAAC;CAE1C;CAKA,MAAM,UAAU,OACb,MAAM,CAAC,GAAG,CAAC,KAAK,UAAU,CAAC,CAAC,CAC5B,SAAS,MAAM,OAAO,MAAM,YAAY,QAAQ,KAAK,CAAC,CAAC;CAG1D,OAAO,QAAQ,QAAQ,GAAG,OAAO,QAAQ,KAAK,IAAI,QAAQ,CAAC,MAAM,KAAK;AACxE;AAEA,IAAM,gBACJ,IACA,SACA,UACG;CAEH,MAAM,UAAU,WAAW,SAAS,EAAE;CACtC,IAAI,QAAQ,WAAW,GAAG;CAC1B,MAAM,aAAa,IAAI,IAAI,OAAO;CAGlC,MAAM,cADW,aAAa,SAAS,KAEpC,CAAA,CAAmD,oBAAoB,EAAE,UAAU;CACtF,IAAK,GAAmB,QAAQ,UAAU;EACxC,MAAM,cAAe,GAAmB,QAAQ,YAAY,GAAA,CAAI,MAAM,GAAG;EACzE,IAAI,WAAW,WAAW,GAAG;EAC7B,KAAK,MAAM,YAAY,YAAY;GACjC,MAAM,WAAW,kBAAkB,aAAa,QAAQ;GACxD,IAAI,CAAC,UACH;GAEF,IAAI,CAAC,WAAW,IAAI,QAAQ,GAC1B,SAAS,kBAAkB,SAAS,IAAI,KAAK;EAEjD;CACF;CACC,GAAoB,QAAQ,WAAW,QAAQ,KAAK,GAAG;CAExD,QAAQ,QAAQ,OAAO,aAAa;EAClC,IAAI,QAAQ;EACZ,MAAM,cAAc;EACpB,MAAM,UAAU;EAGhB,OAAO,QAAQ,aAAa;GAE1B,IAAI,CAAE,GAAmB,QAAQ,UAE/B;GAGF,MAAM,WAAW,kBAAkB,aAAa,QAAQ;GACxD,IAAI,CAAC,UAAU;IACb;IACA,IAAI,QAAQ,aAAa;KACvB,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,OAAO,CAAC;KAC3D;IACF;IAEA,IAAK,GAAmB,QAAQ,UAC9B,KACE,cACA,kBAAkB,SAAS,uBAC7B;IAEF;GACF;GAGA,IAAI,CAAE,GAAmB,QAAQ,UAAU;GAG3C,SAAS,kBAAkB,SAAS,IAAI,KAAK;GAC7C,SAAS,gBAAgB,SAAS,EAAE;GACpC;EACF;CACF,CAAC;CAED,GAAG,aAAa,iBAAiB,QAAQ,KAAK,GAAG,CAAC;AACpD;AACA,IAAM,iBACJ,IACA,SACA,UACG;CAEH,MAAM,UAAU,WAAW,SAAS,EAAE;CACtC,IAAI,QAAQ,WAAW,GAAG;CAE1B,MAAM,cADW,aAAa,SAAS,OAAO,IAE3C,CAAA,CAAmD,oBAAoB,EAAE,UAAU;CAEtF,QAAQ,SAAS,aAAa;EAC5B,MAAM,WAAW,kBAAkB,aAAa,QAAQ;EACxD,IAAI,CAAC,UACH;EAGF,SAAS,kBAAkB,SAAS,IAAI,IAAI;CAC9C,CAAC;CAID,GAAG,gBAAgB,eAAe;CAClC,OAAQ,GAAmB,QAAQ;AACrC;AAEA,IAAa,WAA+B;CAC1C,SAAS;CACT,SAAS;CACT,WAAW;AACb"}