UNPKG

@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
"use strict"; 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/webpack.ts var webpack_exports = {}; __export(webpack_exports, { default: () => webpack_default }); module.exports = __toCommonJS(webpack_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/webpack.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/webpack.ts var webpack_default = (0, import_unplugin2.createWebpackPlugin)(unpluginFactory); exports.default = module.exports;