@kanton-basel-stadt/designsystem
Version:
Unplugin to install the digital design system of the canton of Basel-Stadt
850 lines (826 loc) • 24.6 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/esbuild.ts
var esbuild_exports = {};
__export(esbuild_exports, {
default: () => esbuild_default
});
module.exports = __toCommonJS(esbuild_exports);
// node_modules/tsup/assets/cjs_shims.js
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
// src/esbuild.ts
var import_unplugin2 = require("unplugin");
// src/index.ts
var import_unplugin = require("unplugin");
// src/core/unplugins/postcssTailwind.ts
var import_node_fs2 = __toESM(require("fs"), 1);
var import_node_path5 = __toESM(require("path"), 1);
// src/core/utils/getConfigsPath.ts
var import_node_path2 = __toESM(require("path"), 1);
// src/core/utils/getDirName.ts
var import_node_path = __toESM(require("path"), 1);
var import_node_url = require("url");
function getDirName() {
return import_node_path.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
}
// src/core/utils/getConfigsPath.ts
function getConfigsPath() {
const dirname = getDirName();
return import_node_path2.default.resolve(`${dirname}/configs/`);
}
// src/core/utils/getPostcssConfig.ts
var import_lodash = __toESM(require("lodash.merge"), 1);
var import_options = __toESM(require("postcss-load-config/src/options.js"), 1);
var import_plugins = __toESM(require("postcss-load-config/src/plugins.js"), 1);
// src/core/configs/tailwind.config.ts
var import_node_fs = __toESM(require("fs"), 1);
var import_node_path3 = __toESM(require("path"), 1);
var import_plugin = __toESM(require("tailwindcss/plugin.js"), 1);
// src/core/configs/colors.ts
var colors = {
green: {
50: "#F2F7F3",
100: "#DDECDE",
200: "#B8D6BE",
300: "#7BB589",
400: "#469A5D",
500: "#2A9749",
600: "#32834A",
700: "#2A713F",
800: "#245333",
900: "#1F402A"
},
blue: {
50: "#F2FDFF",
100: "#DBF9FF",
200: "#B6EDFA",
300: "#85D4EE",
400: "#51b9da",
500: "#079BCA",
600: "#0E81A7",
700: "#146C8B",
800: "#1B5268",
900: "#1E4557"
},
purple: {
50: "#F9F6FD",
100: "#F4EDFA",
200: "#E8DAF4",
300: "#D7BDEA",
400: "#C196DC",
500: "#A56CC9",
600: "#9156B4",
700: "#723D8E",
800: "#5F3375",
900: "#512E61"
},
red: {
50: "#FFF1EF",
100: "#FFE0DC",
200: "#FFC7BF",
300: "#FF9F92",
400: "#FF6854",
500: "#FF3A1F",
600: "#FF1E00",
700: "#DB1A00",
800: "#B81600",
900: "#941908"
},
gray: {
20: "#F8F8F8",
50: "#F2F2F2",
100: "#EBEBEB",
200: "#E3E3E3",
300: "#BABABA",
400: "#A5A5A5",
500: "#949494",
600: "#777777",
700: "#535353",
800: "#403F3F",
900: "#333333"
},
brown: {
50: "#FAF6F4",
100: "#F0E4DD",
200: "#DCC3B0",
300: "#BF9A7A",
400: "#A57251",
500: "#8B5734",
600: "#73472A",
700: "#5B3821",
800: "#45301B",
900: "#362718"
},
yellow: {
50: "#FFFDF2",
100: "#FFF5CC",
200: "#FFE699",
300: "#FFCF4D",
400: "#FFBB1A",
500: "#FFAA00",
600: "#E69500",
700: "#B37700",
800: "#805900",
900: "#664700"
},
teal: {
50: "#F2FCFA",
100: "#CFF5EF",
200: "#9AEADC",
300: "#5BDCC5",
400: "#29C9A9",
500: "#00B590",
600: "#009A79",
700: "#007D63",
800: "#005F4A",
900: "#004C3B"
}
};
var colors_default = colors;
// src/core/configs/tailwind.config.ts
var customContent = {
"arrow-east": '"\u2192"',
"arrow-west": '"\u2190"',
"arrow-north-east": '"\u2197"',
"arrow-south": '"\u2193"',
"underscore-long": '"\uE08A"',
"cross": '"\u2717"',
"plus": '"\uE09D"',
"reload": '"\u21BB"',
"check": '"\u2713"',
"caret-south": '"\u2304"',
"caret-north": '"\u2303"',
"dot": '"\u2022"',
"empty": '""'
};
var zIndex = ["app-top", "alva", "search-input-suggestions"].reduce((acc, key, index) => {
acc[key] = (300 + index * 10).toString();
return acc;
}, {});
var fontSize = {
"9xl": ["128px", "128px"],
"8xl": ["96px", "96px"],
"7xl": ["72px", "72px"],
"6xl": ["60px", "60px"],
"5xl": ["48px", "48px"],
"4xl": ["36px", "40px"],
"3xl": ["30px", "34px"],
"2xl": ["24px", "32px"],
"xl": ["20px", "28px"],
"lg": ["18px", "24px"],
"base": ["16px", "22px"],
"sm": ["14px", "20px"],
"xs": ["12px", "18px"]
};
var colorsShaded = Object.keys(colors_default).reduce(
(acc, color) => {
const shades = colors_default[color];
Object.entries(shades).forEach(([shade, hex]) => {
acc[`${color}-${shade}`] = hex;
});
return acc;
},
{}
);
var projectRoot = import_node_path3.default.resolve(".");
function getContentDependencies(path7) {
const fileEndings = [
"html",
"js",
"ts",
"jsx",
"tsx",
"vue",
"astro",
"svelte",
"mdx",
"twig",
"hbs",
// Short form of handlebars
"handlebars",
"pug",
"blade.php",
// Laravel Blade
"tpl"
// Smarty
].join(",");
const dirCandidates = [
"components",
"pages",
"layouts",
"helpers",
"stories",
// Storybook
"dist",
"src"
];
return [
`./*.{${fileEndings}}`,
...dirCandidates.map((d) => `${path7}/${d}`).filter((d) => import_node_fs.default.existsSync(d)).map((d) => `${d}/**/*.{${fileEndings}}`)
];
}
var config = {
content: getContentDependencies(projectRoot),
safelist: ["h-0"],
blocklist: [],
plugins: [
/**
* Various additional variants
*/
(0, import_plugin.default)(({ addVariant }) => {
addVariant(
"mobile-only",
"@media screen and (max-width: theme('screens.md'))"
);
addVariant("not-last", "&:not(:last-child)");
addVariant("not-first", "&:not(:first-child)");
}),
(0, import_plugin.default)(({ matchUtilities, theme }) => {
matchUtilities(
{
"animation-rotation": (value) => ({
"--animation-rotation": value
})
},
{
values: theme("rotate"),
type: "any"
}
);
matchUtilities(
{
"animation-duration": (value) => ({
"--animation-duration": value
})
},
{
values: theme("transitionDuration"),
type: "any"
}
);
matchUtilities(
{
content: (content) => {
return {
// `/ ""` acts as an alt text for the `content`, which is then read by screen readers instead.
// If empty, the content will be ignored. See https://developer.mozilla.org/en-US/docs/Web/CSS/content
// Defining an array here will create two CSS content properties, where the first one is the fallback
// for browsers that don't support the syntax with alt text.
content: [content, `${content} / ""`]
};
}
},
{
values: theme("customContent")
}
);
})
],
corePlugins: {
textOpacity: false,
container: false,
// Disabled because we have our own implementation that adds a fallback.
content: false
},
theme: {
customContent,
screens: {
sm: "480px",
md: "768px",
lg: "1024px",
xl: "1210px",
xxl: "1920px"
},
spacing: {
"220": "220px",
"140": "140px",
"120": "120px",
"100": "100px",
"90": "90px",
"80": "80px",
"70": "70px",
"60": "60px",
"50": "50px",
"40": "40px",
"35": "35px",
"30": "30px",
"25": "25px",
"20": "20px",
"15": "15px",
"10": "10px",
"8": "8px",
"6": "6px",
"5": "5px",
"3": "3px",
"2": "2px",
"1": "1px",
"0": "0px",
"sticky-top": "var(--base-sticky-top)"
},
borderWidth: {
DEFAULT: "1px",
0: "0",
2: "2px",
3: "3px",
4: "4px"
},
maxWidth: {
reduced: "970px",
// @todo: Consolidate sizing with container, max-width and other layout classes.
prose: "836px",
box: "610px",
fit: "fit-content"
},
lineHeight: {
none: "1",
tight: "1.2",
snug: "1.3",
normal: "1.4"
},
fontSize,
fontFamily: {
sans: [
"Inter",
"Inter Fallback",
"Helvetica Neue",
"Helvetica",
"Arial",
"sans-serif"
]
},
fontWeight: {
normal: "400",
medium: "500",
bold: "700"
},
borderRadius: {
none: "0px",
full: "9999px",
large: "10px",
DEFAULT: "4px"
},
colors: {
// Monochrome colors.
white: "#ffffff",
current: "currentColor",
transparent: "transparent",
body: "black",
...colorsShaded,
// The dynamic CSS variable based primary color which is overridden by the Bettingen site at runtime.
primary: {
50: "rgb(var(--color-primary-50) / <alpha-value>)",
100: "rgb(var(--color-primary-100) / <alpha-value>)",
200: "rgb(var(--color-primary-200) / <alpha-value>)",
300: "rgb(var(--color-primary-300) / <alpha-value>)",
400: "rgb(var(--color-primary-400) / <alpha-value>)",
500: "rgb(var(--color-primary-500) / <alpha-value>)",
600: "rgb(var(--color-primary-600) / <alpha-value>)",
700: "rgb(var(--color-primary-700) / <alpha-value>)",
800: "rgb(var(--color-primary-800) / <alpha-value>)",
900: "rgb(var(--color-primary-900) / <alpha-value>)"
}
},
extend: {
zIndex,
gap: {
DEFAULT: "20px"
},
transitionDuration: {
250: "250ms"
},
transitionTimingFunction: {
swing: "cubic-bezier(0.56, 0.04, 0.25, 1)",
momentum: "cubic-bezier(1,-0.76,.46,1.01)"
},
boxShadow: {
"purple-600": "0 0 10px 0 #9156B4",
"purple-600-small": "0 0 5px 0 #9156B4",
"white": "0 0 10px 0 #fff",
"none": "0 0 0 0 #000"
},
keyframes: {
"jump-x": {
"0%": {
transform: "translateX(0)"
},
"20%": {
transform: "translateX(0.15em)"
},
"60%": {
transform: "translateX(-0.15em)"
},
"100%": {
transform: "translateX(0)"
}
},
"jump-y": {
"0%": {
transform: "translateY(0)"
},
"20%": {
transform: "translateY(0.15em)"
},
"60%": {
transform: "translateY(-0.15em)"
},
"100%": {
transform: "translateY(0)"
}
},
"jump-x-reverse": {
"0%": {
transform: "translateX(0)"
},
"20%": {
transform: "translateX(-0.15em)"
},
"60%": {
transform: "translateX(0.15em)"
},
"100%": {
transform: "translateX(0)"
}
},
"jump-xy": {
"0%": {
transform: "translate(0, 0)"
},
"20%": {
transform: "translate(0.15em, -0.15em)"
},
"60%": {
transform: "translate(-0.1em, 0.1em)"
},
"100%": {
transform: "translate(0, 0)"
}
},
"jump-scale": {
"0%": {
transform: "scale(1)"
},
"20%": {
transform: "scale(1.3)"
},
"60%": {
transform: "scale(0.9)"
},
"100%": {
transform: "scale(1)"
}
},
"wiggle": {
"0%": {
transform: "rotate(0deg)"
},
"20%": {
transform: "rotate(var(--animation-rotation, 15deg))"
},
"40%": {
transform: "rotate(calc(-1 * var(--animation-rotation, 15deg)))"
},
"60%": {
transform: "rotate(var(--animation-rotation, 15deg))"
},
"80%": {
transform: "rotate(calc(-1 * var(--animation-rotation, 15deg)))"
},
"100%": {
transform: "rotate(0deg)"
}
},
"rotate": {
from: {
transform: "rotate(0deg)"
},
to: {
transform: "rotate(var(--animation-rotation, 360deg))"
}
}
},
animation: {
"jump-x": `jump-x var(--animation-duration, 0.4s) ease-in-out`,
"jump-y": `jump-y var(--animation-duration, 0.5s) ease-in-out`,
"jump-scale": `jump-scale var(--animation-duration, 0.5s) ease-in-out`,
"jump-x-reverse": "jump-x-reverse var(--animation-duration, 0.5s) ease-in-out",
"jump-xy": "jump-xy var(--animation-duration, 0.5s) ease-in-out",
"wiggle": "wiggle var(--animation-duration, 0.5s) linear",
"rotate": "rotate var(--animation-duration, 0.5s) ease-in-out",
"rotate-infinite": "rotate var(--animation-duration, 0.5s) linear infinite"
}
}
}
};
var tailwind_config_default = config;
// src/core/configs/postcss.config.ts
var postcss_config_default = {
plugins: {
"postcss-import": {},
"postcss-mixins": {},
"tailwindcss/nesting": {},
"tailwindcss": {
config: tailwind_config_default
},
"postcss-inline-svg": {},
"postcss-hexrgba": {
colorFunctionNotation: "modern",
transformToBareValue: true
},
"cssnano": {
preset: "default"
}
}
};
// src/core/utils/getPostcssConfig.ts
async function getPostcssConfig(configPath, tailwindConfig) {
if (tailwindConfig) {
postcss_config_default.plugins.tailwindcss.config = (0, import_lodash.default)(postcss_config_default.plugins.tailwindcss.config, tailwindConfig);
}
const file = `${configPath}/postcss.config.ts`;
return {
file,
options: await (0, import_options.default)(postcss_config_default, file),
plugins: await (0, import_plugins.default)(postcss_config_default, file)
};
}
// src/core/utils/transformIdsInCode.ts
var import_node_path4 = __toESM(require("path"), 1);
var import_magic_string = __toESM(require("magic-string"), 1);
function transformIdsInCode(code, id) {
let dirname = getDirName();
if (dirname.endsWith(import_node_path4.default.sep)) {
dirname = dirname.replace(/[\\/]+$/, "");
}
if (dirname.endsWith("dist")) {
dirname = dirname.replace(/[\\/]+dist$/, "");
}
const s = new import_magic_string.default(code);
s.replace(/(['"(]+)(@{1,2})kanton-basel-stadt\/designsystem\/(icons\/symbols\/(\w+)|([^"')]+))(['")]+)/g, (_, surroundingStart, ats, fullPathMatch, _2, iconMatch, surroundingEnd) => {
if (ats.length === 2) {
return `${surroundingStart}@kanton-basel-stadt/designsystem/${fullPathMatch}${surroundingEnd}`;
}
if (fullPathMatch.startsWith(import_node_path4.default.sep) || fullPathMatch.startsWith("/")) {
fullPathMatch = fullPathMatch.replace(/^[\\/]+/, "");
}
if (fullPathMatch.startsWith("icons/symbol/")) {
return `${surroundingStart}~${iconMatch}${surroundingEnd}`;
}
if (fullPathMatch.startsWith("dist")) {
fullPathMatch = fullPathMatch.replace(/^dist[\\/]+/, "");
}
fullPathMatch = fullPathMatch.replace(/\//g, import_node_path4.default.sep);
return `${surroundingStart}${dirname}${import_node_path4.default.sep}dist${import_node_path4.default.sep}${fullPathMatch}${surroundingEnd}`;
});
if (!s.hasChanged()) {
return;
}
return {
code: s.toString(),
map: s.generateMap({ source: id, includeContent: true, hires: true })
};
}
// src/core/unplugins/postcssTailwind.ts
function getPostcssTailwindUnplugin(options) {
const postcssConfig = getPostcssConfig(getConfigsPath(), options.tailwindOptions?.config);
return {
name: "@kanton-basel-stadt/designsystem/postcss-tailwind",
esbuild: {
async setup(build) {
build.onLoad({ filter: /\.woff2?$/i }, () => {
return { loader: "copy" };
});
const postcss = (await import("postcss")).default;
const loadedPostcss = await postcssConfig;
const postcssInstance = postcss(loadedPostcss.plugins);
build.onLoad({ filter: /\.css$/i }, async (args) => {
const code = import_node_fs2.default.readFileSync(args.path, "utf-8");
const transformed = transformIdsInCode(code, args.path);
const processed = await postcssInstance.process(transformed ? transformed.code : code, {
from: args.path,
to: options.tailwindOptions?.targetDir || "dist",
map: {
absolute: true,
from: args.path
}
});
return { contents: processed.content, loader: "css" };
});
}
},
webpack(compiler) {
compiler.hooks.beforeRun.tapPromise("@kanton-basel-stadt/designsystem", async (params) => {
let initialLoader = "style-loader";
if (params.options.mode === "production") {
const MiniCssExtractPlugin = (await import("mini-css-extract-plugin")).default;
new MiniCssExtractPlugin({
filename: "app.css"
}).apply(params);
initialLoader = {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "../"
// adjust based on where fonts are output relative to your CSS
}
};
}
const postcssConfigLoaded = await postcssConfig;
const cssLoaders = [
initialLoader,
{
loader: "css-loader",
options: {
url: true,
modules: false,
importLoaders: 1
}
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: postcssConfigLoaded.plugins,
to: options.tailwindOptions?.targetDir || "dist",
modules: false
}
}
}
];
params.options.module.rules.push({
test: /\.css$/,
use: cssLoaders
});
params.options.module.rules.unshift({
test: /\.(woff2?)$/i,
type: "asset/resource"
});
});
},
rollup: {
async options(rollupOptions) {
const postcss = (await import("rollup-plugin-postcss")).default;
const urlCopy = (await import("postcss-url-copy")).default;
if (!rollupOptions.plugins) {
rollupOptions.plugins = [];
}
const fullTargetDir = import_node_path5.default.resolve(options.tailwindOptions?.targetDir || "dist");
const plugins = [
...(await postcssConfig).plugins,
urlCopy({
destPath: fullTargetDir,
assetsDestPath: `${fullTargetDir}${import_node_path5.default.sep}assets`,
transformUrlBeforeLoad(url) {
return url.replace(/@kanton-basel-stadt\/designsystem\//g, `.${import_node_path5.default.sep}node_modules${import_node_path5.default.sep}@kanton-basel-stadt${import_node_path5.default.sep}designsystem${import_node_path5.default.sep}dist${import_node_path5.default.sep}`);
},
transformUrlBeforeWrite(url) {
return url.replace(fullTargetDir, ".");
}
})
];
if (Array.isArray(rollupOptions.plugins)) {
rollupOptions.plugins.unshift(postcss({
extract: true,
modules: false,
to: options.tailwindOptions?.targetDir || "dist/",
plugins
}));
}
return rollupOptions;
}
},
vite: {
async config() {
return {
css: {
postcss: await postcssConfig
}
};
}
}
};
}
// src/core/unplugins/transformIds.ts
function getTransformIdsUnplugin() {
return {
name: "@kanton-basel-stadt/designsystem/transform-ids",
enforce: "pre",
transform: transformIdsInCode,
transformInclude(id) {
return !id.endsWith(".woff") && !id.endsWith(".woff2");
},
esbuild: {
onLoadFilter: /\.(?!woff2?$)[^.]+$/i
},
vite: {
config() {
return {
optimizeDeps: {
exclude: ["@kanton-basel-stadt/designsystem/dist/configs/icons-index"]
}
};
}
}
};
}
// src/core/unplugins/unpluginIconsPatched.ts
var import_lodash2 = __toESM(require("lodash.merge"), 1);
var import_svgo = require("svgo");
var import_unplugin_icons = __toESM(require("unplugin-icons"), 1);
var import_loaders = require("unplugin-icons/loaders");
// src/core/utils/getAssetsPath.ts
var import_node_path6 = __toESM(require("path"), 1);
function getAssetsPath() {
const dirname = getDirName();
return import_node_path6.default.resolve(`${dirname}${import_node_path6.default.sep}assets${import_node_path6.default.sep}`);
}
// src/core/utils/consts.ts
var ICON_PATH_ALIAS = "@kanton-basel-stadt/designsystem/icons/symbol";
var ICON_PATH = "~icons/symbol";
// src/core/utils/transformIconId.ts
function transformIconId(id) {
return id.replace(ICON_PATH_ALIAS, ICON_PATH);
}
// src/core/unplugins/unpluginIconsPatched.ts
function getUnpluginIconsPatchedUnplugin(options, meta) {
const unpluginIconsConfig = {
customCollections: {
symbol: (0, import_loaders.FileSystemIconLoader)(`${getAssetsPath()}/symbols`, (svg) => {
const res = (0, import_svgo.optimize)(svg, {
plugins: [
"removeEmptyAttrs",
"removeDimensions",
// Width and height can mess with the rendering in some browsers.
"removeComments"
// Not needed for the final icon.
]
});
return res.data;
})
},
compiler: "web-components",
webComponents: {
autoDefine: true
}
};
const mergedUnpluginIconsConfig = (0, import_lodash2.default)(unpluginIconsConfig, options.iconOptions);
if (mergedUnpluginIconsConfig.compiler !== "web-components") {
delete mergedUnpluginIconsConfig.webComponents;
}
let builtUnpluginIcons = import_unplugin_icons.default;
if ("default" in import_unplugin_icons.default)
builtUnpluginIcons = import_unplugin_icons.default.default;
const usableUnpluginIcons = builtUnpluginIcons.raw(mergedUnpluginIconsConfig, meta);
return {
...usableUnpluginIcons,
name: "unplugin-icons-patched",
resolveId(id) {
return usableUnpluginIcons.resolveId(transformIconId(id));
},
loadInclude(id) {
return usableUnpluginIcons.loadInclude(transformIconId(id));
},
async load(id) {
return await usableUnpluginIcons.load(transformIconId(id));
}
};
}
// src/index.ts
var unpluginFactory = (options, meta) => {
if (options === void 0) {
options = {};
}
return [
getTransformIdsUnplugin(),
getUnpluginIconsPatchedUnplugin(options, meta),
getPostcssTailwindUnplugin(options)
];
};
// src/esbuild.ts
var esbuild_default = (0, import_unplugin2.createEsbuildPlugin)(unpluginFactory);
exports.default = module.exports;