UNPKG

tailwindcss-anchors

Version:

Anchors for Tailwind CSS provides a simple API for working with CSS anchor positioning, enabling flexible, declarative positioning relative to custom anchors.

135 lines (134 loc) 3.98 kB
//#region index.ts const getStyleVarName = (modifier) => modifier.startsWith("--") || modifier.startsWith("var(--") ? modifier : modifier.startsWith("[var(--") ? modifier.slice(1, -1) : `--tw-anchor_${modifier}`; const generateViewTransitionId = (str) => `--tw-anchor-view-transition-${encodeString(str)}`; const EMPTY_VALUES = { values: { DEFAULT: "" } }; var anchors_default = ({ matchUtilities, theme }) => { matchUtilities({ anchor: (_, { modifier }) => { const styles = {}; if (modifier) { const anchorName = getStyleVarName(modifier); if (anchorName) styles["anchor-name"] = anchorName; } return styles; } }, { ...EMPTY_VALUES, modifiers: "any" }); matchUtilities({ anchored: (value, { modifier }) => { if (!value && !modifier) return {}; const baseStyles = {}; if (value) baseStyles["position-area"] = value; if (modifier) { const viewTransitionName = generateViewTransitionId(modifier); baseStyles["position-anchor"] = getStyleVarName(modifier); baseStyles[":where(&)"] = { position: "absolute", ...viewTransitionName && { "view-transition-name": viewTransitionName } }; } return baseStyles; } }, { values: { DEFAULT: "", "top-center": "top center", "top-span-left": "top span-left", "top-span-right": "top span-right", top: "top", "left-center": "left center", "left-span-top": "left span-top", "left-span-bottom": "left span-bottom", left: "left", "right-center": "right center", "right-span-top": "right span-top", "right-span-bottom": "right span-bottom", right: "right", "bottom-center": "bottom center", "bottom-span-left": "bottom span-left", "bottom-span-right": "bottom span-right", bottom: "bottom", "top-left": "top left", "top-right": "top right", "bottom-left": "bottom left", "bottom-right": "bottom right" }, modifiers: "any" }); [ ["top", theme("top")], ["right", theme("right")], ["bottom", theme("bottom")], ["left", theme("left")], ["inset", theme("inset")] ].forEach(([property, themeValues]) => { [ "top", "right", "bottom", "left", "start", "end", "self-start", "self-end", "center" ].forEach((anchorSide) => { matchUtilities({ [`${property}-anchor-${anchorSide}`]: (offset, { modifier }) => { const anchorRef = modifier ? `${getStyleVarName(modifier)} ` : ""; const anchorFnExpr = `anchor-size(${anchorRef}${anchorSide})`; const value = offset ? `calc(${anchorFnExpr} + ${offset})` : anchorFnExpr; return { [property]: value }; } }, { values: themeValues, modifiers: "any" }); }); }); [[ "w", "width", theme("width") ], [ "h", "height", theme("height") ]].forEach(([propertyAbbr, property, themeValues]) => { [ "", "width", "height", "block", "inline", "self-block", "self-inline" ].forEach((anchorSize) => { const anchorSizeUtilitySuffix = anchorSize ? `-${anchorSize}` : anchorSize; matchUtilities({ [`${propertyAbbr}-anchor${anchorSizeUtilitySuffix}`]: (offset, { modifier }) => { const anchorRef = modifier ? `${getStyleVarName(modifier)} ` : ""; const anchorFnExpr = `anchor-size(${anchorRef}${anchorSize})`; const value = offset ? `calc(${anchorFnExpr} + ${offset})` : anchorFnExpr; return { [property]: value }; } }, { values: themeValues, modifiers: "any" }); }); }); }; function encodeString(str) { let encoded = ""; for (let i = 0; i < str.length; i++) encoded += str.charCodeAt(i).toString(36); return encoded; } function decodeString(encodedStr) { const decodedChars = []; let charCode = ""; for (let i = 0; i < encodedStr.length; i++) { charCode += encodedStr[i]; if (parseInt(charCode, 36) >= 32 && parseInt(charCode, 36) <= 126) { decodedChars.push(String.fromCharCode(parseInt(charCode, 36))); charCode = ""; } } return decodedChars.join(""); } //#endregion export { decodeString, anchors_default as default, encodeString };