mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
173 lines
4.7 KiB
JavaScript
173 lines
4.7 KiB
JavaScript
import {
|
|
registerScope,
|
|
setVariables,
|
|
releaseScope,
|
|
getScopeAttributeName,
|
|
} from "../../designSystem/dynamicStyles.js";
|
|
|
|
const DEFAULT_STATE = {
|
|
placement: "bottom",
|
|
alignment: "start",
|
|
strategy: "fixed",
|
|
direction: "ltr",
|
|
mode: "fallback",
|
|
fallbackTop: null,
|
|
fallbackLeft: null,
|
|
};
|
|
|
|
const FALLBACK_TOP_VAR = "--floating-fallback-top";
|
|
const FALLBACK_LEFT_VAR = "--floating-fallback-left";
|
|
const SCOPE_BASE_ID = "floating-panel";
|
|
const SCOPE_SELECTORS = [":scope"];
|
|
|
|
function toCssPixel(value) {
|
|
if (Number.isFinite(value)) {
|
|
return `${value}px`;
|
|
}
|
|
if (typeof value === "string" && value.trim() !== "") {
|
|
return value;
|
|
}
|
|
return "auto";
|
|
}
|
|
|
|
function normalizeDirection(value) {
|
|
return value === "rtl" ? "rtl" : "ltr";
|
|
}
|
|
|
|
function ensureDatasetValue(element, key, value) {
|
|
if (!element) {
|
|
return;
|
|
}
|
|
if (value === undefined || value === null || value === "") {
|
|
delete element.dataset[key];
|
|
return;
|
|
}
|
|
element.dataset[key] = value;
|
|
}
|
|
|
|
function applyFallbackVariables(scopeId, variables) {
|
|
if (!scopeId) {
|
|
return;
|
|
}
|
|
setVariables(scopeId, variables);
|
|
}
|
|
|
|
export function createFloatingPanelStyles(panel) {
|
|
const safePanel = panel || null;
|
|
const state = { ...DEFAULT_STATE };
|
|
|
|
const documentRef = safePanel?.ownerDocument || null;
|
|
const scopeId = safePanel
|
|
? registerScope(SCOPE_BASE_ID, SCOPE_SELECTORS, { documentRef })
|
|
: null;
|
|
|
|
if (safePanel) {
|
|
safePanel.dataset.floatingPanel = "true";
|
|
if (scopeId) {
|
|
safePanel.setAttribute(getScopeAttributeName(), scopeId);
|
|
applyFallbackVariables(scopeId, {
|
|
[FALLBACK_TOP_VAR]: "auto",
|
|
[FALLBACK_LEFT_VAR]: "auto",
|
|
});
|
|
}
|
|
}
|
|
|
|
const api = {
|
|
element: safePanel,
|
|
scopeId,
|
|
setPlacement(value) {
|
|
state.placement = typeof value === "string" && value ? value : DEFAULT_STATE.placement;
|
|
ensureDatasetValue(safePanel, "floatingPlacement", state.placement);
|
|
return state.placement;
|
|
},
|
|
getPlacement() {
|
|
return state.placement;
|
|
},
|
|
setAlignment(value) {
|
|
state.alignment = typeof value === "string" && value ? value : DEFAULT_STATE.alignment;
|
|
ensureDatasetValue(safePanel, "floatingAlignment", state.alignment);
|
|
return state.alignment;
|
|
},
|
|
getAlignment() {
|
|
return state.alignment;
|
|
},
|
|
setStrategy(value) {
|
|
state.strategy = value === "absolute" ? "absolute" : DEFAULT_STATE.strategy;
|
|
ensureDatasetValue(safePanel, "floatingStrategy", state.strategy);
|
|
return state.strategy;
|
|
},
|
|
getStrategy() {
|
|
return state.strategy;
|
|
},
|
|
setDirection(value) {
|
|
state.direction = normalizeDirection(value);
|
|
ensureDatasetValue(safePanel, "floatingDir", state.direction);
|
|
return state.direction;
|
|
},
|
|
getDirection() {
|
|
return state.direction;
|
|
},
|
|
setMode(value) {
|
|
state.mode = value === "anchor" ? "anchor" : DEFAULT_STATE.mode;
|
|
ensureDatasetValue(safePanel, "floatingMode", state.mode);
|
|
return state.mode;
|
|
},
|
|
getMode() {
|
|
return state.mode;
|
|
},
|
|
setFallbackPosition({ top, left }) {
|
|
state.fallbackTop = Number.isFinite(top) ? Number(top) : null;
|
|
state.fallbackLeft = Number.isFinite(left) ? Number(left) : null;
|
|
if (scopeId) {
|
|
applyFallbackVariables(scopeId, {
|
|
[FALLBACK_TOP_VAR]: toCssPixel(state.fallbackTop),
|
|
[FALLBACK_LEFT_VAR]: toCssPixel(state.fallbackLeft),
|
|
});
|
|
}
|
|
return { ...api.getFallbackPosition() };
|
|
},
|
|
getFallbackPosition() {
|
|
return {
|
|
top: state.fallbackTop,
|
|
left: state.fallbackLeft,
|
|
};
|
|
},
|
|
teardown() {
|
|
if (scopeId) {
|
|
applyFallbackVariables(scopeId, {
|
|
[FALLBACK_TOP_VAR]: "auto",
|
|
[FALLBACK_LEFT_VAR]: "auto",
|
|
});
|
|
releaseScope(scopeId);
|
|
}
|
|
if (!safePanel) {
|
|
return;
|
|
}
|
|
safePanel.removeAttribute(getScopeAttributeName());
|
|
delete safePanel.dataset.floatingPanel;
|
|
delete safePanel.dataset.floatingPlacement;
|
|
delete safePanel.dataset.floatingAlignment;
|
|
delete safePanel.dataset.floatingStrategy;
|
|
delete safePanel.dataset.floatingDir;
|
|
delete safePanel.dataset.floatingMode;
|
|
state.placement = DEFAULT_STATE.placement;
|
|
state.alignment = DEFAULT_STATE.alignment;
|
|
state.strategy = DEFAULT_STATE.strategy;
|
|
state.direction = DEFAULT_STATE.direction;
|
|
state.mode = DEFAULT_STATE.mode;
|
|
state.fallbackTop = DEFAULT_STATE.fallbackTop;
|
|
state.fallbackLeft = DEFAULT_STATE.fallbackLeft;
|
|
},
|
|
};
|
|
|
|
api.setPlacement(state.placement);
|
|
api.setAlignment(state.alignment);
|
|
api.setStrategy(state.strategy);
|
|
api.setDirection(state.direction);
|
|
api.setMode(state.mode);
|
|
|
|
return api;
|
|
}
|
|
|
|
export default createFloatingPanelStyles;
|