mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-19 13:01:19 +00:00
refactor: replace popperjs with floating-ui
This commit is contained in:
parent
02557539e6
commit
ad5cd2c2e9
@ -1,4 +1,10 @@
|
||||
import { createPopper, Instance, Placement } from "@popperjs/core";
|
||||
import {
|
||||
computePosition,
|
||||
flip,
|
||||
offset,
|
||||
Placement,
|
||||
shift,
|
||||
} from "@floating-ui/dom";
|
||||
|
||||
const Dropdown = (): void => {
|
||||
const dropdownButtons: NodeListOf<HTMLButtonElement> =
|
||||
@ -16,46 +22,46 @@ const Dropdown = (): void => {
|
||||
// place the menu at then end of the body to prevent any overflow cuts
|
||||
document.body.appendChild(menu);
|
||||
|
||||
let popperInstance: Instance | null = null;
|
||||
|
||||
const create = () => {
|
||||
const update = () => {
|
||||
const offsetX = menu.dataset.dropdownOffsetX
|
||||
? parseInt(menu.dataset.dropdownOffsetX)
|
||||
: 0;
|
||||
const offsetY = menu.dataset.dropdownOffsetY
|
||||
? parseInt(menu.dataset.dropdownOffsetY)
|
||||
: 0;
|
||||
popperInstance = createPopper(button, menu, {
|
||||
computePosition(button, menu, {
|
||||
placement: menu.dataset.dropdownPlacement as Placement,
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [offsetX, offsetY],
|
||||
},
|
||||
},
|
||||
middleware: [
|
||||
offset({ mainAxis: offsetY, crossAxis: offsetX }),
|
||||
flip(),
|
||||
shift(),
|
||||
],
|
||||
}).then(({ x, y }) => {
|
||||
Object.assign(menu.style, {
|
||||
left: `${x}px`,
|
||||
top: `${y}px`,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const destroy = () => {
|
||||
if (popperInstance) {
|
||||
popperInstance.destroy();
|
||||
popperInstance = null;
|
||||
}
|
||||
const showMenu = () => {
|
||||
menu.setAttribute("data-show", "");
|
||||
button.setAttribute("aria-expanded", "true");
|
||||
update();
|
||||
};
|
||||
|
||||
const hideMenu = () => {
|
||||
menu.removeAttribute("data-show");
|
||||
button.setAttribute("aria-expanded", "false");
|
||||
};
|
||||
|
||||
const dropdownToggle = () => {
|
||||
const isExpanded = menu.hasAttribute("data-show");
|
||||
|
||||
if (isExpanded) {
|
||||
menu.removeAttribute("data-show");
|
||||
button.setAttribute("aria-expanded", "false");
|
||||
destroy();
|
||||
hideMenu();
|
||||
} else {
|
||||
menu.setAttribute("data-show", "");
|
||||
button.setAttribute("aria-expanded", "true");
|
||||
create();
|
||||
showMenu();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,12 @@
|
||||
import { createPopper, Placement } from "@popperjs/core";
|
||||
import { Coords } from "@floating-ui/core";
|
||||
import {
|
||||
arrow,
|
||||
computePosition,
|
||||
flip,
|
||||
offset,
|
||||
Placement,
|
||||
shift,
|
||||
} from "@floating-ui/dom";
|
||||
|
||||
const Tooltip = (): void => {
|
||||
const tooltipContainers: NodeListOf<HTMLElement> =
|
||||
@ -12,30 +20,60 @@ const Tooltip = (): void => {
|
||||
tooltip.setAttribute("id", "tooltip" + i);
|
||||
tooltip.setAttribute(
|
||||
"class",
|
||||
"px-2 py-1 text-sm bg-gray-900 text-white rounded max-w-xs z-50"
|
||||
"absolute px-2 py-1 text-sm bg-gray-900 text-white rounded max-w-xs z-50"
|
||||
);
|
||||
tooltip.innerHTML = tooltipContent;
|
||||
const arrowElement = document.createElement("div");
|
||||
arrowElement.setAttribute(
|
||||
"class",
|
||||
"absolute bg-gray-900 w-2 h-2 rotate-45"
|
||||
);
|
||||
arrowElement.setAttribute("id", "arrow" + i);
|
||||
tooltip.appendChild(arrowElement);
|
||||
|
||||
const popper = createPopper(tooltipReference, tooltip, {
|
||||
placement: tooltipReference.dataset.tooltip as Placement,
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, 8],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const update = () => {
|
||||
computePosition(tooltipReference, tooltip, {
|
||||
placement: tooltipReference.dataset.tooltip as Placement,
|
||||
middleware: [
|
||||
flip(),
|
||||
shift(),
|
||||
offset(8),
|
||||
arrow({ element: arrowElement }),
|
||||
],
|
||||
}).then(({ x, y, placement, middlewareData }) => {
|
||||
Object.assign(tooltip.style, {
|
||||
left: `${x}px`,
|
||||
top: `${y}px`,
|
||||
});
|
||||
|
||||
const show = () => {
|
||||
// Accessing the data
|
||||
const { x: arrowX, y: arrowY } = middlewareData.arrow as Coords;
|
||||
|
||||
const staticSide = {
|
||||
top: "bottom",
|
||||
right: "left",
|
||||
bottom: "top",
|
||||
left: "right",
|
||||
}[placement.split("-")[0]];
|
||||
|
||||
Object.assign(arrowElement.style, {
|
||||
left: arrowX != null ? `${arrowX}px` : "",
|
||||
top: arrowY != null ? `${arrowY}px` : "",
|
||||
right: "",
|
||||
bottom: "",
|
||||
[staticSide as string]: "-4px",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const showTooltip = () => {
|
||||
tooltipReference.removeAttribute("title");
|
||||
tooltipReference.setAttribute("aria-describedby", "tooltip" + i);
|
||||
document.body.appendChild(tooltip);
|
||||
popper.update();
|
||||
update();
|
||||
};
|
||||
|
||||
const hide = () => {
|
||||
const hideTooltip = () => {
|
||||
const element = document.getElementById("tooltip" + i);
|
||||
tooltipReference.removeAttribute("aria-describedby");
|
||||
tooltipReference.setAttribute("title", tooltipContent);
|
||||
@ -48,11 +86,11 @@ const Tooltip = (): void => {
|
||||
const hideEvents = ["mouseleave", "blur"];
|
||||
|
||||
showEvents.forEach((event) => {
|
||||
tooltipReference.addEventListener(event, show);
|
||||
tooltipReference.addEventListener(event, showTooltip);
|
||||
});
|
||||
|
||||
hideEvents.forEach((event) => {
|
||||
tooltipReference.addEventListener(event, hide);
|
||||
tooltipReference.addEventListener(event, hideTooltip);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,8 +1,8 @@
|
||||
@layer base {
|
||||
[data-dropdown="menu"] {
|
||||
@apply z-50;
|
||||
@apply absolute z-50;
|
||||
}
|
||||
[data-dropdown="menu"]:not([data-show]) {
|
||||
@apply absolute top-0 left-0 invisible pointer-events-none;
|
||||
@apply hidden;
|
||||
}
|
||||
}
|
||||
|
39
package-lock.json
generated
39
package-lock.json
generated
@ -16,11 +16,11 @@
|
||||
"@codemirror/lang-xml": "^0.19.2",
|
||||
"@codemirror/state": "^0.19.6",
|
||||
"@codemirror/view": "^0.19.32",
|
||||
"@floating-ui/dom": "^0.1.10",
|
||||
"@github/clipboard-copy-element": "^1.1.2",
|
||||
"@github/hotkey": "^1.6.1",
|
||||
"@github/markdown-toolbar-element": "^2.1.0",
|
||||
"@github/time-elements": "^3.1.2",
|
||||
"@popperjs/core": "^2.11.0",
|
||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||
"@vime/core": "^5.3.0",
|
||||
"choices.js": "^9.0.1",
|
||||
@ -2355,6 +2355,19 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.3.1.tgz",
|
||||
"integrity": "sha512-ensKY7Ub59u16qsVIFEo2hwTCqZ/r9oZZFh51ivcLGHfUwTn8l1Xzng8RJUe91H/UP8PeqeBronAGx0qmzwk2g=="
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "0.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.1.10.tgz",
|
||||
"integrity": "sha512-4kAVoogvQm2N0XE0G6APQJuCNuErjOfPW8Ux7DFxh8+AfugWflwVJ5LDlHOwrwut7z/30NUvdtHzQ3zSip4EzQ==",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@foliojs-fork/fontkit": {
|
||||
"version": "1.9.1",
|
||||
"license": "MIT",
|
||||
@ -2606,14 +2619,6 @@
|
||||
"@octokit/openapi-types": "^11.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.0",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-babel": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz",
|
||||
@ -18285,6 +18290,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@floating-ui/core": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.3.1.tgz",
|
||||
"integrity": "sha512-ensKY7Ub59u16qsVIFEo2hwTCqZ/r9oZZFh51ivcLGHfUwTn8l1Xzng8RJUe91H/UP8PeqeBronAGx0qmzwk2g=="
|
||||
},
|
||||
"@floating-ui/dom": {
|
||||
"version": "0.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.1.10.tgz",
|
||||
"integrity": "sha512-4kAVoogvQm2N0XE0G6APQJuCNuErjOfPW8Ux7DFxh8+AfugWflwVJ5LDlHOwrwut7z/30NUvdtHzQ3zSip4EzQ==",
|
||||
"requires": {
|
||||
"@floating-ui/core": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"@foliojs-fork/fontkit": {
|
||||
"version": "1.9.1",
|
||||
"requires": {
|
||||
@ -18491,9 +18509,6 @@
|
||||
"@octokit/openapi-types": "^11.2.0"
|
||||
}
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.11.0"
|
||||
},
|
||||
"@rollup/plugin-babel": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz",
|
||||
|
@ -34,11 +34,11 @@
|
||||
"@codemirror/lang-xml": "^0.19.2",
|
||||
"@codemirror/state": "^0.19.6",
|
||||
"@codemirror/view": "^0.19.32",
|
||||
"@floating-ui/dom": "^0.1.10",
|
||||
"@github/clipboard-copy-element": "^1.1.2",
|
||||
"@github/hotkey": "^1.6.1",
|
||||
"@github/markdown-toolbar-element": "^2.1.0",
|
||||
"@github/time-elements": "^3.1.2",
|
||||
"@popperjs/core": "^2.11.0",
|
||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||
"@vime/core": "^5.3.0",
|
||||
"choices.js": "^9.0.1",
|
||||
|
Loading…
x
Reference in New Issue
Block a user