@digdir/designsystemet-web 1.16.1 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/tooltip/tooltip.cjs +1 -1
- package/dist/cjs/tooltip/tooltip.cjs.map +1 -1
- package/dist/esm/tooltip/tooltip.js +1 -1
- package/dist/esm/tooltip/tooltip.js.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/umd/index.js +3 -3
- package/dist/umd/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../utils/utils.cjs");require("../popover/popover.cjs");let t,n,r=!1,i=0,a=0;const o=e.isBrowser()&&/iPad|iPhone|iPod/.test(navigator.userAgent),s=`data-tooltip`,c=`data-color`,l=`aria-label`,u=`aria-description`,d=`[${c}]`,f=`[${s}]`,p=`data-color-scheme`,m=`[${p}]`,h=o=>{o&&!(o instanceof HTMLElement)&&e.warn(`setTooltipElement expects an HTMLElement, got: `,o),clearTimeout(a),clearTimeout(i),n=void 0,r=!1,t=o||void 0},g=()=>{for(let r of document.querySelectorAll(f)){let i=e.attrOrCSS(r,s);if(!i)return;if(i!==(r.getAttribute(l)||r.getAttribute(u))){let t=e.attr(r,`role`)!==`img`&&r.textContent?.trim();e.attr(r,s,i),e.attr(r,l,t?null:i),e.attr(r,u,t?i:null),r.matches(`a,button,input,label,select,textarea,[tabindex]`)||e.warn(`Missing tabindex="0" attribute on: `,r)}let a=r===n&&t?.offsetHeight&&t?.offsetWidth,o=a&&i&&t?.textContent!==i;a&&o&&(t&&(t.textContent=i),document.activeElement===r&&e.announce(i))}},_=
|
|
1
|
+
const e=require("../utils/utils.cjs");require("../popover/popover.cjs");let t,n,r=!1,i=0,a=0;const o=e.isBrowser()&&/iPad|iPhone|iPod/.test(navigator.userAgent),s=`data-tooltip`,c=`data-color`,l=`aria-label`,u=`aria-description`,d=`[${c}]`,f=`[${s}]`,p=`data-color-scheme`,m=`[${p}]`,h=o=>{o&&!(o instanceof HTMLElement)&&e.warn(`setTooltipElement expects an HTMLElement, got: `,o),clearTimeout(a),clearTimeout(i),n=void 0,r=!1,t=o||void 0},g=()=>{for(let r of document.querySelectorAll(f)){let i=e.attrOrCSS(r,s);if(!i)return;if(i!==(r.getAttribute(l)||r.getAttribute(u))){let t=e.attr(r,`role`)!==`img`&&r.textContent?.trim();e.attr(r,s,i),e.attr(r,l,t?null:i),e.attr(r,u,t?i:null),r.matches(`a,button,input,label,select,textarea,[tabindex]`)||e.warn(`Missing tabindex="0" attribute on: `,r)}let a=r===n&&t?.offsetHeight&&t?.offsetWidth,o=a&&i&&t?.textContent!==i;a&&o&&(t&&(t.textContent=i),document.activeElement===r&&e.announce(i))}},_=l=>{let{type:u,target:h}=l;if(clearTimeout(i),h===t)return;let g=h?.closest?.(f);if(u===`blur`){let e=l.relatedTarget;g===n&&!e?.closest?.(f)&&v();return}if(u===`mouseover`&&!r&&!o){i=setTimeout(_,300,{target:h});return}if(g===n)return;if(!g)return v();t||=e.tag(`div`,{class:`ds-tooltip`}),t.isConnected||document.body.appendChild(t);let y=g.closest(d),b=g.closest(m),x=y!==b&&y?.contains(b);clearTimeout(a),e.attr(t,`popover`,`manual`),e.attr(t,p,b?.getAttribute(p)||null),e.attr(t,c,x&&y?.getAttribute(c)||null),t.textContent=e.attr(g,s),t.showPopover(),t.dispatchEvent(new CustomEvent(`ds-toggle-source`,{detail:g})),r=!0,n=g},v=()=>t?.isConnected&&t.popover&&t.hidePopover(),y=e=>{if(e?.type===`keydown`)return e?.key===`Escape`&&v();e?e.target===t&&e.newState===`closed`&&(n=void 0,a=setTimeout(y,300)):r=!1};e.onHotReload(`tooltip`,()=>[e.on(document,`blur focus mouseover`,_,e.QUICK_EVENT),e.on(document,`toggle keydown`,y,e.QUICK_EVENT),e.onMutation(document,g,{attributeFilter:[s],attributes:!0,childList:!0,subtree:!0})]),exports.setTooltipElement=h;
|
|
2
2
|
//# sourceMappingURL=tooltip.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.cjs","names":["isBrowser","attrOrCSS","attr","tag","onHotReload","on","QUICK_EVENT","onMutation"],"sources":["../../../src/tooltip/tooltip.ts"],"sourcesContent":["import '../popover/popover'; // Ensure popover is imported when using individual imports, since tooltip relies on it\nimport {\n announce,\n attr,\n attrOrCSS,\n isBrowser,\n on,\n onHotReload,\n onMutation,\n QUICK_EVENT,\n tag,\n warn,\n} from '../utils/utils';\n\nlet TIP: HTMLElement | undefined;\nlet SOURCE: Element | undefined;\nlet IS_HOVERING = false;\nlet HOVER_TIMER: number | ReturnType<typeof setTimeout> = 0;\nlet SKIP_TIMER: number | ReturnType<typeof setTimeout> = 0;\nconst IS_IOS = isBrowser() && /iPad|iPhone|iPod/.test(navigator.userAgent); // Needed to omit DELAY_HOVER since iOS triggers mouseover before click\nconst ATTR_TOOLTIP = 'data-tooltip';\nconst ATTR_COLOR = 'data-color';\nconst ARIA_LABEL = 'aria-label';\nconst ARIA_DESC = 'aria-description';\nconst SELECTOR_COLOR = `[${ATTR_COLOR}]`;\nconst SELECTOR_TOOLTIP = `[${ATTR_TOOLTIP}]`;\nconst ATTR_SCHEME = 'data-color-scheme';\nconst SELECTOR_SCHEME = `[${ATTR_SCHEME}]`;\nconst SELECTOR_INTERACTIVE = 'a,button,input,label,select,textarea,[tabindex]';\nconst DELAY_HOVER = 300;\nconst DELAY_SKIP = 300;\n\n/**\n * setTooltipElement\n * @description Allows setting a custom tooltip element. It does not need to, and should not, be injected to document.body, as we inject on hover to ensure React hydration works as expected.\n * @param el The HTMLElement to use as tooltip\n */\nexport const setTooltipElement = (el?: HTMLElement | null) => {\n if (el && !(el instanceof HTMLElement))\n warn('setTooltipElement expects an HTMLElement, got: ', el);\n clearTimeout(SKIP_TIMER); // Reset when changing source\n clearTimeout(HOVER_TIMER);\n SOURCE = undefined;\n IS_HOVERING = false;\n TIP = el || undefined;\n};\n\nconst handleAriaAttributes = () => {\n for (const el of document.querySelectorAll(SELECTOR_TOOLTIP)) {\n const text = attrOrCSS(el, ATTR_TOOLTIP);\n\n if (!text) return; // Early return if no tooltip text\n if (text !== (el.getAttribute(ARIA_LABEL) || el.getAttribute(ARIA_DESC))) {\n const hasText = attr(el, 'role') !== 'img' && el.textContent?.trim(); // If role=\"img\", ignore text\n attr(el, ATTR_TOOLTIP, text); // Set data-tooltip attribute to speed up future mutations\n attr(el, ARIA_LABEL, hasText ? null : text); // Set aria-label if element does not have text\n attr(el, ARIA_DESC, hasText ? text : null); // Set aria-description if element has text\n if (!el.matches(SELECTOR_INTERACTIVE))\n warn('Missing tabindex=\"0\" attribute on: ', el);\n }\n\n // If an existing tooltip has changed programmatically, update tooltip text and announce change\n const isCurrent = el === SOURCE && TIP?.offsetHeight && TIP?.offsetWidth; // Using offsetHeight+Width to check visibility as :popover-open is not well supported by JSDOM\n const isChanged = isCurrent && text && TIP?.textContent !== text; // Only update if mutation is on source element and tooltip is open to avoid unnecessary updates\n if (isCurrent && isChanged) {\n if (TIP) TIP.textContent = text;\n if (document.activeElement === el) announce(text); // Only announce if focus is on the button\n }\n }\n};\n\nconst handleInterest = ({ type, target }
|
|
1
|
+
{"version":3,"file":"tooltip.cjs","names":["isBrowser","attrOrCSS","attr","tag","onHotReload","on","QUICK_EVENT","onMutation"],"sources":["../../../src/tooltip/tooltip.ts"],"sourcesContent":["import '../popover/popover'; // Ensure popover is imported when using individual imports, since tooltip relies on it\nimport {\n announce,\n attr,\n attrOrCSS,\n isBrowser,\n on,\n onHotReload,\n onMutation,\n QUICK_EVENT,\n tag,\n warn,\n} from '../utils/utils';\n\nlet TIP: HTMLElement | undefined;\nlet SOURCE: Element | undefined;\nlet IS_HOVERING = false;\nlet HOVER_TIMER: number | ReturnType<typeof setTimeout> = 0;\nlet SKIP_TIMER: number | ReturnType<typeof setTimeout> = 0;\nconst IS_IOS = isBrowser() && /iPad|iPhone|iPod/.test(navigator.userAgent); // Needed to omit DELAY_HOVER since iOS triggers mouseover before click\nconst ATTR_TOOLTIP = 'data-tooltip';\nconst ATTR_COLOR = 'data-color';\nconst ARIA_LABEL = 'aria-label';\nconst ARIA_DESC = 'aria-description';\nconst SELECTOR_COLOR = `[${ATTR_COLOR}]`;\nconst SELECTOR_TOOLTIP = `[${ATTR_TOOLTIP}]`;\nconst ATTR_SCHEME = 'data-color-scheme';\nconst SELECTOR_SCHEME = `[${ATTR_SCHEME}]`;\nconst SELECTOR_INTERACTIVE = 'a,button,input,label,select,textarea,[tabindex]';\nconst DELAY_HOVER = 300;\nconst DELAY_SKIP = 300;\n\n/**\n * setTooltipElement\n * @description Allows setting a custom tooltip element. It does not need to, and should not, be injected to document.body, as we inject on hover to ensure React hydration works as expected.\n * @param el The HTMLElement to use as tooltip\n */\nexport const setTooltipElement = (el?: HTMLElement | null) => {\n if (el && !(el instanceof HTMLElement))\n warn('setTooltipElement expects an HTMLElement, got: ', el);\n clearTimeout(SKIP_TIMER); // Reset when changing source\n clearTimeout(HOVER_TIMER);\n SOURCE = undefined;\n IS_HOVERING = false;\n TIP = el || undefined;\n};\n\nconst handleAriaAttributes = () => {\n for (const el of document.querySelectorAll(SELECTOR_TOOLTIP)) {\n const text = attrOrCSS(el, ATTR_TOOLTIP);\n\n if (!text) return; // Early return if no tooltip text\n if (text !== (el.getAttribute(ARIA_LABEL) || el.getAttribute(ARIA_DESC))) {\n const hasText = attr(el, 'role') !== 'img' && el.textContent?.trim(); // If role=\"img\", ignore text\n attr(el, ATTR_TOOLTIP, text); // Set data-tooltip attribute to speed up future mutations\n attr(el, ARIA_LABEL, hasText ? null : text); // Set aria-label if element does not have text\n attr(el, ARIA_DESC, hasText ? text : null); // Set aria-description if element has text\n if (!el.matches(SELECTOR_INTERACTIVE))\n warn('Missing tabindex=\"0\" attribute on: ', el);\n }\n\n // If an existing tooltip has changed programmatically, update tooltip text and announce change\n const isCurrent = el === SOURCE && TIP?.offsetHeight && TIP?.offsetWidth; // Using offsetHeight+Width to check visibility as :popover-open is not well supported by JSDOM\n const isChanged = isCurrent && text && TIP?.textContent !== text; // Only update if mutation is on source element and tooltip is open to avoid unnecessary updates\n if (isCurrent && isChanged) {\n if (TIP) TIP.textContent = text;\n if (document.activeElement === el) announce(text); // Only announce if focus is on the button\n }\n }\n};\n\nconst handleInterest = (event: Event) => {\n const { type, target } = event;\n clearTimeout(HOVER_TIMER);\n\n if (target === TIP) return; // Allow tooltip to be hovered, following https://www.w3.org/TR/WCAG21/#content-on-hover-or-focus\n\n const source = (target as Element)?.closest?.(SELECTOR_TOOLTIP);\n\n // This prevents the tooltip from reappearing on mousedown/click\n if (type === 'blur') {\n const next = (event as FocusEvent).relatedTarget as Element | null;\n if (source === SOURCE && !next?.closest?.(SELECTOR_TOOLTIP)) hideTooltip();\n return;\n }\n\n if (type === 'mouseover' && !IS_HOVERING && !IS_IOS) {\n HOVER_TIMER = setTimeout(handleInterest, DELAY_HOVER, { target }); // Delay mouse showing tooltip if not already shown\n return;\n }\n\n if (source === SOURCE) return; // No need to update\n if (!source) return hideTooltip(); // If no new anchor, cleanup previous autoUpdate\n if (!TIP) TIP = tag('div', { class: 'ds-tooltip' });\n if (!TIP.isConnected) document.body.appendChild(TIP); // Ensure connected\n\n const color = source.closest(SELECTOR_COLOR); // Match source color of source element\n const scheme = source.closest(SELECTOR_SCHEME); // Match source color-scheme of source element\n const isReset = color !== scheme && color?.contains(scheme as Node); // If data-scheme is closer to target, it will reset data-color\n\n clearTimeout(SKIP_TIMER);\n attr(TIP, 'popover', 'manual'); // Ensure popover behavior\n attr(TIP, ATTR_SCHEME, scheme?.getAttribute(ATTR_SCHEME) || null); // Fallback to null to reset if not scheme found\n attr(TIP, ATTR_COLOR, (isReset && color?.getAttribute(ATTR_COLOR)) || null); // Fallback to null to reset if not scheme found\n TIP.textContent = attr(source, ATTR_TOOLTIP);\n TIP.showPopover();\n TIP.dispatchEvent(new CustomEvent('ds-toggle-source', { detail: source })); // Since showPopover({ source }) is not supported in all browsers yet\n IS_HOVERING = true;\n SOURCE = source;\n};\n\nconst hideTooltip = () => TIP?.isConnected && TIP.popover && TIP.hidePopover(); // Only hide if connected and activated\n\nconst handleClose = (event?: Partial<ToggleEvent & KeyboardEvent>) => {\n if (event?.type === 'keydown')\n return event?.key === 'Escape' && hideTooltip();\n if (!event) IS_HOVERING = false;\n else if (event.target === TIP && event.newState === 'closed') {\n SOURCE = undefined;\n SKIP_TIMER = setTimeout(handleClose, DELAY_SKIP);\n }\n};\n\nonHotReload('tooltip', () => [\n on(document, 'blur focus mouseover', handleInterest, QUICK_EVENT),\n on(document, 'toggle keydown', handleClose, QUICK_EVENT),\n onMutation(document, handleAriaAttributes, {\n attributeFilter: [ATTR_TOOLTIP],\n attributes: true,\n childList: true,\n subtree: true,\n }),\n]);\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{QUICK_EVENT as e,announce as t,attr as n,attrOrCSS as r,isBrowser as i,on as a,onHotReload as o,onMutation as s,tag as c,warn as l}from"../utils/utils.js";import"../popover/popover.js";let u,d,f=!1,p=0,m=0;const h=i()&&/iPad|iPhone|iPod/.test(navigator.userAgent),g=`data-tooltip`,_=`data-color`,v=`aria-label`,y=`aria-description`,b=`[${_}]`,x=`[${g}]`,S=`data-color-scheme`,C=`[${S}]`,w=e=>{e&&!(e instanceof HTMLElement)&&l(`setTooltipElement expects an HTMLElement, got: `,e),clearTimeout(m),clearTimeout(p),d=void 0,f=!1,u=e||void 0},T=()=>{for(let e of document.querySelectorAll(x)){let i=r(e,g);if(!i)return;if(i!==(e.getAttribute(v)||e.getAttribute(y))){let t=n(e,`role`)!==`img`&&e.textContent?.trim();n(e,g,i),n(e,v,t?null:i),n(e,y,t?i:null),e.matches(`a,button,input,label,select,textarea,[tabindex]`)||l(`Missing tabindex="0" attribute on: `,e)}let a=e===d&&u?.offsetHeight&&u?.offsetWidth,o=a&&i&&u?.textContent!==i;a&&o&&(u&&(u.textContent=i),document.activeElement===e&&t(i))}},E=
|
|
1
|
+
import{QUICK_EVENT as e,announce as t,attr as n,attrOrCSS as r,isBrowser as i,on as a,onHotReload as o,onMutation as s,tag as c,warn as l}from"../utils/utils.js";import"../popover/popover.js";let u,d,f=!1,p=0,m=0;const h=i()&&/iPad|iPhone|iPod/.test(navigator.userAgent),g=`data-tooltip`,_=`data-color`,v=`aria-label`,y=`aria-description`,b=`[${_}]`,x=`[${g}]`,S=`data-color-scheme`,C=`[${S}]`,w=e=>{e&&!(e instanceof HTMLElement)&&l(`setTooltipElement expects an HTMLElement, got: `,e),clearTimeout(m),clearTimeout(p),d=void 0,f=!1,u=e||void 0},T=()=>{for(let e of document.querySelectorAll(x)){let i=r(e,g);if(!i)return;if(i!==(e.getAttribute(v)||e.getAttribute(y))){let t=n(e,`role`)!==`img`&&e.textContent?.trim();n(e,g,i),n(e,v,t?null:i),n(e,y,t?i:null),e.matches(`a,button,input,label,select,textarea,[tabindex]`)||l(`Missing tabindex="0" attribute on: `,e)}let a=e===d&&u?.offsetHeight&&u?.offsetWidth,o=a&&i&&u?.textContent!==i;a&&o&&(u&&(u.textContent=i),document.activeElement===e&&t(i))}},E=e=>{let{type:t,target:r}=e;if(clearTimeout(p),r===u)return;let i=r?.closest?.(x);if(t===`blur`){let t=e.relatedTarget;i===d&&!t?.closest?.(x)&&D();return}if(t===`mouseover`&&!f&&!h){p=setTimeout(E,300,{target:r});return}if(i===d)return;if(!i)return D();u||=c(`div`,{class:`ds-tooltip`}),u.isConnected||document.body.appendChild(u);let a=i.closest(b),o=i.closest(C),s=a!==o&&a?.contains(o);clearTimeout(m),n(u,`popover`,`manual`),n(u,S,o?.getAttribute(S)||null),n(u,_,s&&a?.getAttribute(_)||null),u.textContent=n(i,g),u.showPopover(),u.dispatchEvent(new CustomEvent(`ds-toggle-source`,{detail:i})),f=!0,d=i},D=()=>u?.isConnected&&u.popover&&u.hidePopover(),O=e=>{if(e?.type===`keydown`)return e?.key===`Escape`&&D();e?e.target===u&&e.newState===`closed`&&(d=void 0,m=setTimeout(O,300)):f=!1};o(`tooltip`,()=>[a(document,`blur focus mouseover`,E,e),a(document,`toggle keydown`,O,e),s(document,T,{attributeFilter:[g],attributes:!0,childList:!0,subtree:!0})]);export{w as setTooltipElement};
|
|
2
2
|
//# sourceMappingURL=tooltip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.js","names":[],"sources":["../../../src/tooltip/tooltip.ts"],"sourcesContent":["import '../popover/popover'; // Ensure popover is imported when using individual imports, since tooltip relies on it\nimport {\n announce,\n attr,\n attrOrCSS,\n isBrowser,\n on,\n onHotReload,\n onMutation,\n QUICK_EVENT,\n tag,\n warn,\n} from '../utils/utils';\n\nlet TIP: HTMLElement | undefined;\nlet SOURCE: Element | undefined;\nlet IS_HOVERING = false;\nlet HOVER_TIMER: number | ReturnType<typeof setTimeout> = 0;\nlet SKIP_TIMER: number | ReturnType<typeof setTimeout> = 0;\nconst IS_IOS = isBrowser() && /iPad|iPhone|iPod/.test(navigator.userAgent); // Needed to omit DELAY_HOVER since iOS triggers mouseover before click\nconst ATTR_TOOLTIP = 'data-tooltip';\nconst ATTR_COLOR = 'data-color';\nconst ARIA_LABEL = 'aria-label';\nconst ARIA_DESC = 'aria-description';\nconst SELECTOR_COLOR = `[${ATTR_COLOR}]`;\nconst SELECTOR_TOOLTIP = `[${ATTR_TOOLTIP}]`;\nconst ATTR_SCHEME = 'data-color-scheme';\nconst SELECTOR_SCHEME = `[${ATTR_SCHEME}]`;\nconst SELECTOR_INTERACTIVE = 'a,button,input,label,select,textarea,[tabindex]';\nconst DELAY_HOVER = 300;\nconst DELAY_SKIP = 300;\n\n/**\n * setTooltipElement\n * @description Allows setting a custom tooltip element. It does not need to, and should not, be injected to document.body, as we inject on hover to ensure React hydration works as expected.\n * @param el The HTMLElement to use as tooltip\n */\nexport const setTooltipElement = (el?: HTMLElement | null) => {\n if (el && !(el instanceof HTMLElement))\n warn('setTooltipElement expects an HTMLElement, got: ', el);\n clearTimeout(SKIP_TIMER); // Reset when changing source\n clearTimeout(HOVER_TIMER);\n SOURCE = undefined;\n IS_HOVERING = false;\n TIP = el || undefined;\n};\n\nconst handleAriaAttributes = () => {\n for (const el of document.querySelectorAll(SELECTOR_TOOLTIP)) {\n const text = attrOrCSS(el, ATTR_TOOLTIP);\n\n if (!text) return; // Early return if no tooltip text\n if (text !== (el.getAttribute(ARIA_LABEL) || el.getAttribute(ARIA_DESC))) {\n const hasText = attr(el, 'role') !== 'img' && el.textContent?.trim(); // If role=\"img\", ignore text\n attr(el, ATTR_TOOLTIP, text); // Set data-tooltip attribute to speed up future mutations\n attr(el, ARIA_LABEL, hasText ? null : text); // Set aria-label if element does not have text\n attr(el, ARIA_DESC, hasText ? text : null); // Set aria-description if element has text\n if (!el.matches(SELECTOR_INTERACTIVE))\n warn('Missing tabindex=\"0\" attribute on: ', el);\n }\n\n // If an existing tooltip has changed programmatically, update tooltip text and announce change\n const isCurrent = el === SOURCE && TIP?.offsetHeight && TIP?.offsetWidth; // Using offsetHeight+Width to check visibility as :popover-open is not well supported by JSDOM\n const isChanged = isCurrent && text && TIP?.textContent !== text; // Only update if mutation is on source element and tooltip is open to avoid unnecessary updates\n if (isCurrent && isChanged) {\n if (TIP) TIP.textContent = text;\n if (document.activeElement === el) announce(text); // Only announce if focus is on the button\n }\n }\n};\n\nconst handleInterest = ({ type, target }
|
|
1
|
+
{"version":3,"file":"tooltip.js","names":[],"sources":["../../../src/tooltip/tooltip.ts"],"sourcesContent":["import '../popover/popover'; // Ensure popover is imported when using individual imports, since tooltip relies on it\nimport {\n announce,\n attr,\n attrOrCSS,\n isBrowser,\n on,\n onHotReload,\n onMutation,\n QUICK_EVENT,\n tag,\n warn,\n} from '../utils/utils';\n\nlet TIP: HTMLElement | undefined;\nlet SOURCE: Element | undefined;\nlet IS_HOVERING = false;\nlet HOVER_TIMER: number | ReturnType<typeof setTimeout> = 0;\nlet SKIP_TIMER: number | ReturnType<typeof setTimeout> = 0;\nconst IS_IOS = isBrowser() && /iPad|iPhone|iPod/.test(navigator.userAgent); // Needed to omit DELAY_HOVER since iOS triggers mouseover before click\nconst ATTR_TOOLTIP = 'data-tooltip';\nconst ATTR_COLOR = 'data-color';\nconst ARIA_LABEL = 'aria-label';\nconst ARIA_DESC = 'aria-description';\nconst SELECTOR_COLOR = `[${ATTR_COLOR}]`;\nconst SELECTOR_TOOLTIP = `[${ATTR_TOOLTIP}]`;\nconst ATTR_SCHEME = 'data-color-scheme';\nconst SELECTOR_SCHEME = `[${ATTR_SCHEME}]`;\nconst SELECTOR_INTERACTIVE = 'a,button,input,label,select,textarea,[tabindex]';\nconst DELAY_HOVER = 300;\nconst DELAY_SKIP = 300;\n\n/**\n * setTooltipElement\n * @description Allows setting a custom tooltip element. It does not need to, and should not, be injected to document.body, as we inject on hover to ensure React hydration works as expected.\n * @param el The HTMLElement to use as tooltip\n */\nexport const setTooltipElement = (el?: HTMLElement | null) => {\n if (el && !(el instanceof HTMLElement))\n warn('setTooltipElement expects an HTMLElement, got: ', el);\n clearTimeout(SKIP_TIMER); // Reset when changing source\n clearTimeout(HOVER_TIMER);\n SOURCE = undefined;\n IS_HOVERING = false;\n TIP = el || undefined;\n};\n\nconst handleAriaAttributes = () => {\n for (const el of document.querySelectorAll(SELECTOR_TOOLTIP)) {\n const text = attrOrCSS(el, ATTR_TOOLTIP);\n\n if (!text) return; // Early return if no tooltip text\n if (text !== (el.getAttribute(ARIA_LABEL) || el.getAttribute(ARIA_DESC))) {\n const hasText = attr(el, 'role') !== 'img' && el.textContent?.trim(); // If role=\"img\", ignore text\n attr(el, ATTR_TOOLTIP, text); // Set data-tooltip attribute to speed up future mutations\n attr(el, ARIA_LABEL, hasText ? null : text); // Set aria-label if element does not have text\n attr(el, ARIA_DESC, hasText ? text : null); // Set aria-description if element has text\n if (!el.matches(SELECTOR_INTERACTIVE))\n warn('Missing tabindex=\"0\" attribute on: ', el);\n }\n\n // If an existing tooltip has changed programmatically, update tooltip text and announce change\n const isCurrent = el === SOURCE && TIP?.offsetHeight && TIP?.offsetWidth; // Using offsetHeight+Width to check visibility as :popover-open is not well supported by JSDOM\n const isChanged = isCurrent && text && TIP?.textContent !== text; // Only update if mutation is on source element and tooltip is open to avoid unnecessary updates\n if (isCurrent && isChanged) {\n if (TIP) TIP.textContent = text;\n if (document.activeElement === el) announce(text); // Only announce if focus is on the button\n }\n }\n};\n\nconst handleInterest = (event: Event) => {\n const { type, target } = event;\n clearTimeout(HOVER_TIMER);\n\n if (target === TIP) return; // Allow tooltip to be hovered, following https://www.w3.org/TR/WCAG21/#content-on-hover-or-focus\n\n const source = (target as Element)?.closest?.(SELECTOR_TOOLTIP);\n\n // This prevents the tooltip from reappearing on mousedown/click\n if (type === 'blur') {\n const next = (event as FocusEvent).relatedTarget as Element | null;\n if (source === SOURCE && !next?.closest?.(SELECTOR_TOOLTIP)) hideTooltip();\n return;\n }\n\n if (type === 'mouseover' && !IS_HOVERING && !IS_IOS) {\n HOVER_TIMER = setTimeout(handleInterest, DELAY_HOVER, { target }); // Delay mouse showing tooltip if not already shown\n return;\n }\n\n if (source === SOURCE) return; // No need to update\n if (!source) return hideTooltip(); // If no new anchor, cleanup previous autoUpdate\n if (!TIP) TIP = tag('div', { class: 'ds-tooltip' });\n if (!TIP.isConnected) document.body.appendChild(TIP); // Ensure connected\n\n const color = source.closest(SELECTOR_COLOR); // Match source color of source element\n const scheme = source.closest(SELECTOR_SCHEME); // Match source color-scheme of source element\n const isReset = color !== scheme && color?.contains(scheme as Node); // If data-scheme is closer to target, it will reset data-color\n\n clearTimeout(SKIP_TIMER);\n attr(TIP, 'popover', 'manual'); // Ensure popover behavior\n attr(TIP, ATTR_SCHEME, scheme?.getAttribute(ATTR_SCHEME) || null); // Fallback to null to reset if not scheme found\n attr(TIP, ATTR_COLOR, (isReset && color?.getAttribute(ATTR_COLOR)) || null); // Fallback to null to reset if not scheme found\n TIP.textContent = attr(source, ATTR_TOOLTIP);\n TIP.showPopover();\n TIP.dispatchEvent(new CustomEvent('ds-toggle-source', { detail: source })); // Since showPopover({ source }) is not supported in all browsers yet\n IS_HOVERING = true;\n SOURCE = source;\n};\n\nconst hideTooltip = () => TIP?.isConnected && TIP.popover && TIP.hidePopover(); // Only hide if connected and activated\n\nconst handleClose = (event?: Partial<ToggleEvent & KeyboardEvent>) => {\n if (event?.type === 'keydown')\n return event?.key === 'Escape' && hideTooltip();\n if (!event) IS_HOVERING = false;\n else if (event.target === TIP && event.newState === 'closed') {\n SOURCE = undefined;\n SKIP_TIMER = setTimeout(handleClose, DELAY_SKIP);\n }\n};\n\nonHotReload('tooltip', () => [\n on(document, 'blur focus mouseover', handleInterest, QUICK_EVENT),\n on(document, 'toggle keydown', handleClose, QUICK_EVENT),\n onMutation(document, handleAriaAttributes, {\n attributeFilter: [ATTR_TOOLTIP],\n attributes: true,\n childList: true,\n subtree: true,\n }),\n]);\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1224,14 +1224,20 @@ const handleAriaAttributes = () => {
|
|
|
1224
1224
|
}
|
|
1225
1225
|
}
|
|
1226
1226
|
};
|
|
1227
|
-
const handleInterest = (
|
|
1227
|
+
const handleInterest = (event) => {
|
|
1228
|
+
const { type, target } = event;
|
|
1228
1229
|
clearTimeout(HOVER_TIMER);
|
|
1229
1230
|
if (target === TIP) return;
|
|
1231
|
+
const source = target?.closest?.(SELECTOR_TOOLTIP);
|
|
1232
|
+
if (type === "blur") {
|
|
1233
|
+
const next = event.relatedTarget;
|
|
1234
|
+
if (source === SOURCE && !next?.closest?.(SELECTOR_TOOLTIP)) hideTooltip();
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1230
1237
|
if (type === "mouseover" && !IS_HOVERING && !IS_IOS) {
|
|
1231
1238
|
HOVER_TIMER = setTimeout(handleInterest, DELAY_HOVER, { target });
|
|
1232
1239
|
return;
|
|
1233
1240
|
}
|
|
1234
|
-
const source = target?.closest?.(`[${ATTR_TOOLTIP}]`);
|
|
1235
1241
|
if (source === SOURCE) return;
|
|
1236
1242
|
if (!source) return hideTooltip();
|
|
1237
1243
|
if (!TIP) TIP = tag("div", { class: "ds-tooltip" });
|