mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-30 00:01:15 +00:00
fdeb9244db
* Avoid destroyed tippy warning Tippy doesn't remove its onDocumentPress listener when destroyed. Instead the listener removes itself after calling hide for hideOnClick. It doesn't look like there is a way to reliable work around this. This skips the warning for the first hide call on a destroyed tippy instance. Cleanup is only performed after at least ten tippy instances have been created. * Hide tooltips for elements that are no longer connected to the document * Only render action modals after first show * Only render action dropdown after first show * Modals fix for quick unmount Modals use `await import("bootstrap/js/dist/modal")` when being mounted. This means its possible that the component unmounts before the promise resolves. * bind() dropdown toggle click handler * Modal mixin
70 lines
2 KiB
TypeScript
70 lines
2 KiB
TypeScript
import { RefObject } from "inferno";
|
|
import {
|
|
DelegateInstance as TippyDelegateInstance,
|
|
Props as TippyProps,
|
|
Instance as TippyInstance,
|
|
delegate as tippyDelegate,
|
|
} from "tippy.js";
|
|
|
|
let instance: TippyDelegateInstance<TippyProps> | undefined;
|
|
const tippySelector = "[data-tippy-content]";
|
|
const shownInstances: Set<TippyInstance<TippyProps>> = new Set();
|
|
let instanceCounter = 0;
|
|
|
|
const tippyDelegateOptions: Partial<TippyProps> & { target: string } = {
|
|
delay: [500, 0],
|
|
// Display on "long press"
|
|
touch: ["hold", 500],
|
|
target: tippySelector,
|
|
onShow(i: TippyInstance<TippyProps>) {
|
|
shownInstances.add(i);
|
|
},
|
|
onHidden(i: TippyInstance<TippyProps>) {
|
|
shownInstances.delete(i);
|
|
},
|
|
onCreate() {
|
|
instanceCounter++;
|
|
},
|
|
onDestroy(i: TippyInstance<TippyProps>) {
|
|
// Tippy doesn't remove its onDocumentPress listener when destroyed.
|
|
// Instead the listener removes itself after calling hide for hideOnClick.
|
|
const origHide = i.hide;
|
|
// This silences the first warning when hiding a destroyed tippy instance.
|
|
// hide() is otherwise a noop for destroyed instances.
|
|
i.hide = () => {
|
|
i.hide = origHide;
|
|
};
|
|
},
|
|
};
|
|
|
|
export function setupTippy(root: RefObject<Element>) {
|
|
if (!instance && root.current) {
|
|
instance = tippyDelegate(root.current, tippyDelegateOptions);
|
|
}
|
|
}
|
|
|
|
export function cleanupTippy() {
|
|
// Hide tooltips for elements that are no longer connected to the document.
|
|
shownInstances.forEach(i => {
|
|
if (!i.reference.isConnected) {
|
|
console.assert(!i.state.isDestroyed, "hide called on destroyed tippy");
|
|
i.hide();
|
|
}
|
|
});
|
|
|
|
if (shownInstances.size || instanceCounter < 10) {
|
|
// Avoid randomly closing tooltips.
|
|
return;
|
|
}
|
|
instanceCounter = 0;
|
|
const current = instance?.reference ?? null;
|
|
// delegate from tippy.js creates tippy instances when needed, but only
|
|
// destroys them when the delegate instance is destroyed.
|
|
destroyTippy();
|
|
setupTippy({ current });
|
|
}
|
|
|
|
export function destroyTippy() {
|
|
instance?.destroy();
|
|
instance = undefined;
|
|
}
|