import { Id, type Optional } from '@ephox/katamari'; import { Attribute, PredicateFind, SelectorFind, type SugarElement, SugarNode, SugarShadowDom } from '@ephox/sugar'; export interface AriaManager { readonly id: string; readonly link: (elem: SugarElement) => void; readonly unlink: (elem: SugarElement) => void; } const attribute = 'aria-controls'; const find = (queryElem: SugarElement): Optional> => { const dependent = PredicateFind.closest(queryElem, (elem): elem is SugarElement => { if (!SugarNode.isElement(elem)) { return false; } const id = Attribute.get(elem, 'id'); return id !== undefined && id.indexOf(attribute) > -1; }); return dependent.bind((dep) => { const id = Attribute.get(dep, 'id'); const dos = SugarShadowDom.getRootNode(dep); return SelectorFind.descendant(dos, `[${attribute}="${id}"]`); }); }; const manager = (): AriaManager => { const ariaId = Id.generate(attribute); const link = (elem: SugarElement) => { Attribute.set(elem, attribute, ariaId); }; const unlink = (elem: SugarElement) => { Attribute.remove(elem, attribute); }; return { id: ariaId, link, unlink, }; }; export { find, manager };