Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | import tippy from 'sveltejs-tippy';
import xss from 'xss';
import { displayPattern } from './KeyboardHint.svelte';
import { omit } from './utils';
/**
* @typedef {object} TooltipParameters
* @property {string} text - The text to display in the tooltip.
* @property {string} [keyboard] - The keyboard shortcut to display in the tooltip.
* @property {number} [delay] - The delay before showing the tooltip.
* @property {`${'top'|'right'|'bottom'|'left'}${''|`-${'start'|'end'}`}`} [placement] - The placement of the tooltip .
*/
/** @param {string | [string, number] | TooltipParameters | undefined} parameters */
function props(parameters) {
const base = { arrow: svgArrow };
let content = '';
let delay = 50;
if (!parameters) {
return {
...base,
content: '',
delay: [delay, 0]
};
}
if (typeof parameters === 'string') content = parameters;
else if (Array.isArray(parameters)) [content, delay] = parameters;
else {
return {
...base,
...omit(parameters, 'text', 'keyboard'),
delay: [delay, 0],
allowHTML: true,
content:
xss(parameters.text, {
allowList: {
kbd: ['class']
}
}) +
// XXX: needs :global styling from KeyboardHint.svelte
(parameters.keyboard
? ' <kbd class=hint>' +
displayPattern(parameters.keyboard)
.entries()
.map(([i, part]) =>
i % 2 === 0
? `<kbd>${part}</kbd>`
: `<span class=separator>${part}</span>`
)
.toArray()
.join('') +
'</kbd>'
: '')
};
}
return { ...base, content, delay: [delay, 0] };
}
/**
* Create a tooltip
* @param {HTMLElement & {_tippy?: {destroy: () => void; setProps: (props: unknown) => void}}} node
* @param {string | [string, number] | TooltipParameters | undefined} parameters text or [text, delay] or tippy.js options
*/
export function tooltip(node, parameters) {
const properties = props(parameters);
tippy(node, properties);
if (properties.content.length <= 0) {
delete node.dataset.tooltipContent;
node._tippy?.destroy();
}
return {
/** @param {string | [string, number] | TooltipParameters | undefined} parameters */
update(parameters) {
const properties = props(parameters);
node.dataset.tooltipContent = properties.content;
if (!node._tippy) tippy(node, properties);
if (properties.content.length <= 0) node._tippy?.destroy();
node._tippy?.setProps(properties);
},
destroy() {
delete node.dataset.tooltipContent;
node._tippy?.destroy();
}
};
}
const svgArrow =
'<svg width="16" height="6" xmlns="http://www.w3.org/2000/svg"><path d="M0 6s1.796-.013 4.67-3.615C5.851.9 6.93.006 8 0c1.07-.006 2.148.887 3.343 2.385C14.233 6.005 16 6 16 6H0z"></svg>';
|