@fastkit/plugboy-vanilla-extract-plugin 4.0.0-next.8 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # @fastkit/plugboy-vanilla-extract-plugin
2
+
3
+ 🌐 English | [日本語](https://github.com/dadajam4/fastkit/blob/main/packages/plugboy-vanilla-extract-plugin/README-ja.md)
4
+
5
+ A plugin that integrates [Vanilla Extract](https://vanilla-extract.style/) into [Plugboy](https://github.com/dadajam4/fastkit/blob/main/packages/plugboy/README.md) builds. It bundles the CSS extracted from `.css.ts` files into a single stylesheet per package, ships a Vite plugin for development, and provides helpers for working with cascade layers.
6
+
7
+ ## Features
8
+
9
+ - **Single CSS output**: Combines the styles extracted from a package's `.css.ts` files into one `dist/<package>.css`.
10
+ - **Automatic merge with plain CSS**: Merges tsdown's output for plain `.css` / `.scss` with the Vanilla Extract output into a single file (preventing the style loss caused by a file-name collision between the two).
11
+ - **Vite integration**: Ships a Vite plugin for use in dev servers, Storybook, and similar environments.
12
+ - **Layer helpers**: `@fastkit/plugboy-vanilla-extract-plugin/css` exposes utilities for defining cascade layers in a type-safe way.
13
+
14
+ > [!NOTE]
15
+ > Preserving external `@import`s (e.g. `@import url('material-symbols/rounded.css') layer(...)`) and ordering `@layer` declarations are handled by [Plugboy](https://github.com/dadajam4/fastkit/blob/main/packages/plugboy/README.md) itself, and apply to the CSS this plugin combines as well.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install -D @fastkit/plugboy-vanilla-extract-plugin
21
+ # or
22
+ pnpm add -D @fastkit/plugboy-vanilla-extract-plugin
23
+ ```
24
+
25
+ > [!NOTE]
26
+ > Requires `@fastkit/plugboy` (and `vite`, when using the Vite integration) as peer dependencies.
27
+
28
+ ## Usage
29
+
30
+ ### 1. Register in the build
31
+
32
+ Add it to the `plugins` of `plugboy.project.ts` (project-wide) or a per-workspace `plugboy.workspace.ts`. It activates automatically for packages that contain `.css.ts` files.
33
+
34
+ ```typescript
35
+ import { defineProjectConfig } from '@fastkit/plugboy';
36
+ import { createVanillaExtractPlugin } from '@fastkit/plugboy-vanilla-extract-plugin';
37
+
38
+ export default defineProjectConfig({
39
+ plugins: [
40
+ createVanillaExtractPlugin({
41
+ // Identifier format for class names etc. ('short' recommended for production)
42
+ identifiers: 'short',
43
+ }),
44
+ ],
45
+ });
46
+ ```
47
+
48
+ On build, the package styles are combined into `dist/<package>.css`.
49
+
50
+ ### 2. Use with Vite (dev / Storybook, etc.)
51
+
52
+ For environments that resolve Vanilla Extract without a Plugboy build (Vite dev server, Storybook, etc.), use the Vite plugin.
53
+
54
+ ```typescript
55
+ import { defineConfig } from 'vite';
56
+ import { ViteVanillaExtractPlugin } from '@fastkit/plugboy-vanilla-extract-plugin';
57
+
58
+ export default defineConfig({
59
+ plugins: [
60
+ ViteVanillaExtractPlugin({
61
+ identifiers: 'debug',
62
+ }),
63
+ ],
64
+ });
65
+ ```
66
+
67
+ ### 3. Cascade layer helpers (`/css`)
68
+
69
+ `@fastkit/plugboy-vanilla-extract-plugin/css` lets you define nestable cascade layers in a type-safe way.
70
+
71
+ ```typescript
72
+ import { defineLayerStyle } from '@fastkit/plugboy-vanilla-extract-plugin/css';
73
+
74
+ export const framework = defineLayerStyle({ globalName: 'my-ui' });
75
+
76
+ export const base = framework.defineNestedLayer({ globalName: 'base' });
77
+ export const component = framework.defineNestedLayer({ globalName: 'component' });
78
+ ```
79
+
80
+ ## Options
81
+
82
+ The main options accepted by `createVanillaExtractPlugin(options)` / `ViteVanillaExtractPlugin(options)`.
83
+
84
+ | Option | Type | Description |
85
+ | --- | --- | --- |
86
+ | `identifiers` | `'short' \| 'debug' \| ((meta) => string)` | Format of generated identifiers such as class names. Use `'short'` for production builds and `'debug'` while debugging. |
87
+ | `esbuildOptions` | `EsbuildOptions` | Options forwarded to esbuild when compiling `.css.ts` files. |
88
+
89
+ ## License
90
+
91
+ [MIT](https://github.com/dadajam4/fastkit/blob/main/LICENSE)
@@ -5,17 +5,7 @@ import { Plugin as Plugin$1 } from "vite";
5
5
 
6
6
  //#region src/types.d.ts
7
7
  type VanillaExtractPluginOptions = Omit<NonNullable<Parameters<typeof vanillaExtractPlugin>[0]>, 'extract'>;
8
- type PrependFnResultValue = string | void;
9
- type PrependFn = (ctx: {
10
- cssFileName: string;
11
- }) => PrependFnResultValue | Promise<PrependFnResultValue>;
12
- interface PluginOptions extends Pick<VanillaExtractPluginOptions, 'identifiers' | 'esbuildOptions'> {
13
- /**
14
- * Inserts arbitrary code at the beginning of the generated CSS bundle.
15
- * This is useful for injecting global directives or comments.
16
- */
17
- prepend?: string | PrependFn;
18
- }
8
+ type PluginOptions = Pick<VanillaExtractPluginOptions, 'identifiers' | 'esbuildOptions'>;
19
9
  declare const PLUGIN_NAME = "plugboy-vanilla-extract";
20
10
  interface VanillaExtractPlugin extends Plugin {
21
11
  name: typeof PLUGIN_NAME;
@@ -35,5 +25,5 @@ type VanillaExtractVitePluginOptions = NonNullable<Parameters<typeof vanillaExtr
35
25
  interface ViteVanillaExtractPluginOptions extends VanillaExtractVitePluginOptions {}
36
26
  declare function ViteVanillaExtractPlugin(options?: ViteVanillaExtractPluginOptions): Promise<Plugin$1[]>;
37
27
  //#endregion
38
- export { PLUGIN_NAME, PluginOptions, PrependFn, PrependFnResultValue, VanillaExtractPlugin, ViteVanillaExtractPlugin, ViteVanillaExtractPluginOptions, createVanillaExtractPlugin };
28
+ export { PLUGIN_NAME, PluginOptions, VanillaExtractPlugin, ViteVanillaExtractPlugin, ViteVanillaExtractPluginOptions, createVanillaExtractPlugin };
39
29
  //# sourceMappingURL=plugboy-vanilla-extract-plugin.d.mts.map
@@ -1,3 +1,5 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
1
3
  import { definePlugin, findFile, findProjectPlugin } from "@fastkit/plugboy";
2
4
  import { vanillaExtractPlugin } from "@vanilla-extract/rollup-plugin";
3
5
  import { vanillaExtractPlugin as vanillaExtractPlugin$1 } from "@vanilla-extract/vite-plugin";
@@ -17,7 +19,7 @@ const PLUGIN_NAME = "plugboy-vanilla-extract";
17
19
  * (`FILE_NAME_CONFLICT` — one silently overwrites the other, dropping all of
18
20
  * the vanilla-extract component CSS). To avoid that we route tsdown's CSS to
19
21
  * this temporary name and merge it into the vanilla-extract bundle in
20
- * `generateBundle`.
22
+ * `writeBundle`.
21
23
  */
22
24
  const TSDOWN_CSS_FILE_NAME = "__ve-tsdown__.css";
23
25
  async function createVanillaExtractPlugin(options = {}) {
@@ -27,12 +29,14 @@ async function createVanillaExtractPlugin(options = {}) {
27
29
  hooks: { async setupWorkspace(ctx, getWorkspace) {
28
30
  const entryIds = Object.keys(ctx.config.entries);
29
31
  const cssFileName = `${entryIds.includes(".") ? ctx.dir.basename : entryIds[0] ?? ctx.dir.basename}.css`;
32
+ const plainCssTargets = /* @__PURE__ */ new Set();
33
+ let plainCssFallback = cssFileName;
34
+ ctx.mergeExternals(/@vanilla-extract/);
35
+ ctx.meta.hasVanillaExtract = !!await findFile(ctx.dirs.src.value, /\.css\.ts$/);
30
36
  ctx.css = {
31
37
  splitting: false,
32
- fileName: TSDOWN_CSS_FILE_NAME
38
+ fileName: ctx.meta.hasVanillaExtract ? TSDOWN_CSS_FILE_NAME : cssFileName
33
39
  };
34
- ctx.mergeExternals(/@vanilla-extract/);
35
- ctx.meta.hasVanillaExtract = !!await findFile(ctx.dirs.src.value, /\.css\.ts$/);
36
40
  if (ctx.meta.hasVanillaExtract) {
37
41
  const originalPlugin = vanillaExtractPlugin({
38
42
  ...options,
@@ -53,18 +57,82 @@ async function createVanillaExtractPlugin(options = {}) {
53
57
  };
54
58
  return opts;
55
59
  },
56
- generateBundle(_opts, bundle) {
60
+ generateBundle(_options, bundle) {
61
+ const collectEntryCss = (root) => {
62
+ const visited = /* @__PURE__ */ new Set();
63
+ const seenCss = /* @__PURE__ */ new Set();
64
+ const out = [];
65
+ let hasPlain = false;
66
+ const walk = (id) => {
67
+ if (visited.has(id)) return;
68
+ visited.add(id);
69
+ const info = this.getModuleInfo(id);
70
+ if (!info) return;
71
+ for (const dep of info.importedIds ?? []) {
72
+ const css = this.getModuleInfo(dep)?.meta?.css;
73
+ if (typeof css === "string") {
74
+ if (!seenCss.has(dep)) {
75
+ seenCss.add(dep);
76
+ out.push(css);
77
+ }
78
+ } else if (/\.css(\?|$)/i.test(dep)) hasPlain = true;
79
+ walk(dep);
80
+ }
81
+ };
82
+ walk(root);
83
+ return {
84
+ css: out,
85
+ hasPlain
86
+ };
87
+ };
88
+ const entryCss = [];
89
+ for (const chunk of Object.values(bundle)) {
90
+ if (chunk.type !== "chunk" || !chunk.isEntry || !chunk.fileName.endsWith(".mjs") || !chunk.facadeModuleId) continue;
91
+ const { css, hasPlain } = collectEntryCss(chunk.facadeModuleId);
92
+ if (css.length) entryCss.push({
93
+ name: chunk.name,
94
+ source: css.join("\n"),
95
+ hasPlain
96
+ });
97
+ }
98
+ if (entryCss.length <= 1) return;
99
+ const reused = /* @__PURE__ */ new Set();
100
+ for (const { name, source } of entryCss) {
101
+ const fileName = `${name}.css`;
102
+ const existing = bundle[fileName];
103
+ if (existing && existing.type === "asset") {
104
+ existing.source = source;
105
+ reused.add(fileName);
106
+ } else this.emitFile({
107
+ type: "asset",
108
+ fileName,
109
+ source
110
+ });
111
+ }
112
+ const combined = bundle[cssFileName];
113
+ if (combined && combined.type === "asset" && !reused.has(cssFileName)) delete bundle[cssFileName];
114
+ plainCssTargets.clear();
115
+ plainCssFallback = `${entryCss[0].name}.css`;
116
+ for (const { name, hasPlain } of entryCss) if (hasPlain) plainCssTargets.add(`${name}.css`);
117
+ },
118
+ async writeBundle(outputOptions, bundle) {
57
119
  const tmp = bundle[TSDOWN_CSS_FILE_NAME];
58
- const tmpCss = tmp && tmp.type === "asset" ? tmp.source.toString() : "";
59
- if (tmp) delete bundle[TSDOWN_CSS_FILE_NAME];
60
- if (!tmpCss) return;
61
- const veAsset = bundle[cssFileName];
62
- if (veAsset && veAsset.type === "asset") veAsset.source = `${tmpCss}\n${veAsset.source.toString()}`;
63
- else this.emitFile({
64
- type: "asset",
65
- fileName: cssFileName,
66
- source: tmpCss
67
- });
120
+ if (!tmp) return;
121
+ const tmpCss = tmp.type === "asset" ? tmp.source.toString() : "";
122
+ const dir = outputOptions.dir ?? ".";
123
+ const tmpPath = path.join(dir, TSDOWN_CSS_FILE_NAME);
124
+ if (tmpCss) {
125
+ const targets = plainCssTargets.size ? [...plainCssTargets] : [plainCssFallback];
126
+ await Promise.all(targets.map(async (target) => {
127
+ const targetPath = path.join(dir, target);
128
+ let targetCss = "";
129
+ try {
130
+ targetCss = await fs.readFile(targetPath, "utf8");
131
+ } catch {}
132
+ await fs.writeFile(targetPath, targetCss ? `${tmpCss}\n${targetCss}` : tmpCss);
133
+ }));
134
+ }
135
+ await fs.rm(tmpPath, { force: true });
68
136
  }
69
137
  });
70
138
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugboy-vanilla-extract-plugin.mjs","names":["vanillaExtractPlugin"],"sources":["../src/types.ts","../src/plugin.ts","../src/vite.ts"],"sourcesContent":["import { Plugin } from '@fastkit/plugboy';\nimport type { vanillaExtractPlugin as rollupPlugin } from '@vanilla-extract/rollup-plugin';\n\ntype VanillaExtractPluginOptions = Omit<\n NonNullable<Parameters<typeof rollupPlugin>[0]>,\n 'extract'\n>;\n\nexport type PrependFnResultValue = string | void;\n\nexport type PrependFn = (ctx: {\n cssFileName: string;\n}) => PrependFnResultValue | Promise<PrependFnResultValue>;\n\nexport interface PluginOptions extends Pick<\n VanillaExtractPluginOptions,\n 'identifiers' | 'esbuildOptions'\n> {\n /**\n * Inserts arbitrary code at the beginning of the generated CSS bundle.\n * This is useful for injecting global directives or comments.\n */\n prepend?: string | PrependFn;\n}\n\nexport const PLUGIN_NAME = 'plugboy-vanilla-extract';\n\nexport interface VanillaExtractPlugin extends Plugin {\n name: typeof PLUGIN_NAME;\n _options: PluginOptions;\n}\n","import { definePlugin, findFile, type Plugin } from '@fastkit/plugboy';\nimport { vanillaExtractPlugin } from '@vanilla-extract/rollup-plugin';\nimport { VanillaExtractPlugin, PluginOptions, PLUGIN_NAME } from './types';\n\ndeclare module '@fastkit/plugboy' {\n export interface WorkspaceMeta {\n hasVanillaExtract: boolean;\n }\n}\n\n/**\n * Temporary file name for the CSS that tsdown's own CSS pipeline emits.\n *\n * A package can have two independent sources of CSS:\n * - tsdown's built-in CSS handling, for plain `.css` / `.scss` imports.\n * - `@vanilla-extract/rollup-plugin`, for `.css.ts` files (extracted into a\n * single bundle named after the package).\n *\n * If both are pointed at the same final file name they collide\n * (`FILE_NAME_CONFLICT` — one silently overwrites the other, dropping all of\n * the vanilla-extract component CSS). To avoid that we route tsdown's CSS to\n * this temporary name and merge it into the vanilla-extract bundle in\n * `generateBundle`.\n */\nconst TSDOWN_CSS_FILE_NAME = '__ve-tsdown__.css';\n\nexport async function createVanillaExtractPlugin(options: PluginOptions = {}) {\n return definePlugin<VanillaExtractPlugin>({\n name: PLUGIN_NAME,\n _options: options,\n hooks: {\n async setupWorkspace(ctx, getWorkspace) {\n // Derive the final CSS file name from the workspace entry, mirroring the\n // way plugboy names the JS output: the main entry (`.`) maps to the\n // package directory name (e.g. `vue-app-layout`), other entries keep\n // their id. Since `splitting: false` produces a single combined CSS for\n // the package, we base it on the main entry (falling back to the first).\n // Result: `dist/vue-app-layout.css` instead of `dist/__ve-tmp__.css`.\n const entryIds = Object.keys(ctx.config.entries);\n const cssBaseName = entryIds.includes('.')\n ? ctx.dir.basename\n : (entryIds[0] ?? ctx.dir.basename);\n const cssFileName = `${cssBaseName}.css`;\n\n // Keep tsdown's own CSS out of `cssFileName` so it doesn't collide with\n // the vanilla-extract bundle that also targets `cssFileName`. The two\n // are merged into a single `cssFileName` later (see the merge hook).\n ctx.css = {\n splitting: false,\n fileName: TSDOWN_CSS_FILE_NAME,\n };\n\n ctx.mergeExternals(/@vanilla-extract/);\n\n ctx.meta.hasVanillaExtract = !!(await findFile(\n ctx.dirs.src.value,\n /\\.css\\.ts$/,\n ));\n\n if (ctx.meta.hasVanillaExtract) {\n const originalPlugin = vanillaExtractPlugin({\n ...options,\n extract: {\n name: cssFileName,\n sourcemap: false,\n },\n });\n\n // `@vanilla-extract/rollup-plugin` returns a rollup `Plugin`, but\n // plugboy's `ctx.plugins` expects a tsdown (rolldown) `Plugin`. The two\n // are structurally almost identical, but hooks like `outputOptions`\n // type `this` as rollup's `PluginContext` vs rolldown's\n // `MinimalPluginContext`, which makes them unassignable (the `this`\n // type is contravariant). rolldown accepts rollup plugins at runtime,\n // so this is harmless — cast to work around the type mismatch.\n ctx.plugins.push(originalPlugin as unknown as Plugin);\n\n // `@vanilla-extract/rollup-plugin` emits the extracted CSS via\n // `emitFile({ type: 'asset', name: cssFileName })`. Because it uses\n // `name` (a hint) rather than `fileName`, rolldown runs it through the\n // default `assetFileNames` pattern (`assets/[name]-[hash][extname]`),\n // producing e.g. `dist/assets/vue-app-layout-dry0z-1l.css`.\n //\n // We can't *rename* an asset in `generateBundle` because rolldown\n // ignores mutations to a bundle entry's `fileName`. Instead, override\n // `assetFileNames` via the `outputOptions` hook so this single CSS\n // asset keeps its derived name verbatim (no hash, no `assets/` dir)\n // while every other asset keeps its original naming.\n ctx.plugins.push({\n name: `${PLUGIN_NAME}:rename-css`,\n outputOptions(opts) {\n const original = opts.assetFileNames;\n opts.assetFileNames = (assetInfo) => {\n if (assetInfo.names.includes(cssFileName)) {\n return cssFileName;\n }\n if (typeof original === 'function') return original(assetInfo);\n return original ?? 'assets/[name]-[hash][extname]';\n };\n return opts;\n },\n // Merge tsdown's own CSS (emitted to `TSDOWN_CSS_FILE_NAME`) into the\n // vanilla-extract bundle so the package ships a single `cssFileName`.\n // tsdown's CSS comes first so its `@layer` declarations / resets are\n // established before the extracted component styles. Unlike renaming,\n // mutating an asset's `source` IS honored by rolldown.\n generateBundle(_opts, bundle) {\n const tmp = bundle[TSDOWN_CSS_FILE_NAME];\n const tmpCss =\n tmp && tmp.type === 'asset' ? tmp.source.toString() : '';\n if (tmp) delete bundle[TSDOWN_CSS_FILE_NAME];\n if (!tmpCss) return;\n\n const veAsset = bundle[cssFileName];\n if (veAsset && veAsset.type === 'asset') {\n veAsset.source = `${tmpCss}\\n${veAsset.source.toString()}`;\n } else {\n // No vanilla-extract output (e.g. `.css.ts` produced no rules) —\n // promote tsdown's CSS to the final file name.\n this.emitFile({\n type: 'asset',\n fileName: cssFileName,\n source: tmpCss,\n });\n }\n },\n });\n }\n },\n },\n });\n}\n","import { findProjectPlugin } from '@fastkit/plugboy';\nimport { Plugin as VitePlugin } from 'vite';\nimport { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';\nimport { PLUGIN_NAME, VanillaExtractPlugin } from './types';\n\ntype VanillaExtractVitePluginOptions = NonNullable<\n Parameters<typeof vanillaExtractPlugin>[0]\n>;\n\nexport interface ViteVanillaExtractPluginOptions extends VanillaExtractVitePluginOptions {}\n\nexport async function ViteVanillaExtractPlugin(\n options: ViteVanillaExtractPluginOptions = {},\n): Promise<VitePlugin[]> {\n const plugin = await findProjectPlugin<VanillaExtractPlugin>(PLUGIN_NAME);\n const { identifiers: baseIdentifiers } = plugin?._options || {};\n\n return [\n ...vanillaExtractPlugin({\n identifiers: baseIdentifiers,\n ...options,\n }),\n // @MEMO\n // Plugin to prevent file scope mismatches when utilities using vanilla-extract\n // functions are placed in external files\n {\n name: 'vanilla-extract-fix-file-scope',\n config(viteConfig) {\n viteConfig.resolve ??= {};\n viteConfig.resolve.dedupe ??= [];\n viteConfig.resolve.dedupe.push(\n '@vanilla-extract/css',\n '@vanilla-extract/css/fileScope',\n );\n },\n },\n ];\n}\n"],"mappings":";;;;AAyBA,MAAa,cAAc;;;;;;;;;;;;;;;;;ACD3B,MAAM,uBAAuB;AAE7B,eAAsB,2BAA2B,UAAyB,CAAC,GAAG;CAC5E,OAAO,aAAmC;EACxC,MAAM;EACN,UAAU;EACV,OAAO,EACL,MAAM,eAAe,KAAK,cAAc;GAOtC,MAAM,WAAW,OAAO,KAAK,IAAI,OAAO,OAAO;GAI/C,MAAM,cAAc,GAHA,SAAS,SAAS,GAAG,IACrC,IAAI,IAAI,WACP,SAAS,MAAM,IAAI,IAAI,SACO;GAKnC,IAAI,MAAM;IACR,WAAW;IACX,UAAU;GACZ;GAEA,IAAI,eAAe,kBAAkB;GAErC,IAAI,KAAK,oBAAoB,CAAC,CAAE,MAAM,SACpC,IAAI,KAAK,IAAI,OACb,YACF;GAEA,IAAI,IAAI,KAAK,mBAAmB;IAC9B,MAAM,iBAAiB,qBAAqB;KAC1C,GAAG;KACH,SAAS;MACP,MAAM;MACN,WAAW;KACb;IACF,CAAC;IASD,IAAI,QAAQ,KAAK,cAAmC;IAapD,IAAI,QAAQ,KAAK;KACf,MAAM,GAAG,YAAY;KACrB,cAAc,MAAM;MAClB,MAAM,WAAW,KAAK;MACtB,KAAK,kBAAkB,cAAc;OACnC,IAAI,UAAU,MAAM,SAAS,WAAW,GACtC,OAAO;OAET,IAAI,OAAO,aAAa,YAAY,OAAO,SAAS,SAAS;OAC7D,OAAO,YAAY;MACrB;MACA,OAAO;KACT;KAMA,eAAe,OAAO,QAAQ;MAC5B,MAAM,MAAM,OAAO;MACnB,MAAM,SACJ,OAAO,IAAI,SAAS,UAAU,IAAI,OAAO,SAAS,IAAI;MACxD,IAAI,KAAK,OAAO,OAAO;MACvB,IAAI,CAAC,QAAQ;MAEb,MAAM,UAAU,OAAO;MACvB,IAAI,WAAW,QAAQ,SAAS,SAC9B,QAAQ,SAAS,GAAG,OAAO,IAAI,QAAQ,OAAO,SAAS;WAIvD,KAAK,SAAS;OACZ,MAAM;OACN,UAAU;OACV,QAAQ;MACV,CAAC;KAEL;IACF,CAAC;GACH;EACF,EACF;CACF,CAAC;AACH;;;ACxHA,eAAsB,yBACpB,UAA2C,CAAC,GACrB;CAEvB,MAAM,EAAE,aAAa,qBAAoB,MADpB,kBAAA,yBAAmD,EAAA,EACvB,YAAY,CAAC;CAE9D,OAAO,CACL,GAAGA,uBAAqB;EACtB,aAAa;EACb,GAAG;CACL,CAAC,GAID;EACE,MAAM;EACN,OAAO,YAAY;GACjB,WAAW,YAAY,CAAC;GACxB,WAAW,QAAQ,WAAW,CAAC;GAC/B,WAAW,QAAQ,OAAO,KACxB,wBACA,gCACF;EACF;CACF,CACF;AACF"}
1
+ {"version":3,"file":"plugboy-vanilla-extract-plugin.mjs","names":["vanillaExtractPlugin"],"sources":["../src/types.ts","../src/plugin.ts","../src/vite.ts"],"sourcesContent":["import { Plugin } from '@fastkit/plugboy';\nimport type { vanillaExtractPlugin as rollupPlugin } from '@vanilla-extract/rollup-plugin';\n\ntype VanillaExtractPluginOptions = Omit<\n NonNullable<Parameters<typeof rollupPlugin>[0]>,\n 'extract'\n>;\n\nexport type PluginOptions = Pick<\n VanillaExtractPluginOptions,\n 'identifiers' | 'esbuildOptions'\n>;\n\nexport const PLUGIN_NAME = 'plugboy-vanilla-extract';\n\nexport interface VanillaExtractPlugin extends Plugin {\n name: typeof PLUGIN_NAME;\n _options: PluginOptions;\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { definePlugin, findFile, type Plugin } from '@fastkit/plugboy';\nimport { vanillaExtractPlugin } from '@vanilla-extract/rollup-plugin';\nimport { VanillaExtractPlugin, PluginOptions, PLUGIN_NAME } from './types';\n\ndeclare module '@fastkit/plugboy' {\n export interface WorkspaceMeta {\n hasVanillaExtract: boolean;\n }\n}\n\n/**\n * Temporary file name for the CSS that tsdown's own CSS pipeline emits.\n *\n * A package can have two independent sources of CSS:\n * - tsdown's built-in CSS handling, for plain `.css` / `.scss` imports.\n * - `@vanilla-extract/rollup-plugin`, for `.css.ts` files (extracted into a\n * single bundle named after the package).\n *\n * If both are pointed at the same final file name they collide\n * (`FILE_NAME_CONFLICT` — one silently overwrites the other, dropping all of\n * the vanilla-extract component CSS). To avoid that we route tsdown's CSS to\n * this temporary name and merge it into the vanilla-extract bundle in\n * `writeBundle`.\n */\nconst TSDOWN_CSS_FILE_NAME = '__ve-tsdown__.css';\n\nexport async function createVanillaExtractPlugin(options: PluginOptions = {}) {\n return definePlugin<VanillaExtractPlugin>({\n name: PLUGIN_NAME,\n _options: options,\n hooks: {\n async setupWorkspace(ctx, getWorkspace) {\n // Derive the final CSS file name from the workspace entry, mirroring the\n // way plugboy names the JS output: the main entry (`.`) maps to the\n // package directory name (e.g. `vue-app-layout`), other entries keep\n // their id. Since `splitting: false` produces a single combined CSS for\n // the package, we base it on the main entry (falling back to the first).\n // Result: `dist/vue-app-layout.css` instead of `dist/__ve-tmp__.css`.\n const entryIds = Object.keys(ctx.config.entries);\n const cssBaseName = entryIds.includes('.')\n ? ctx.dir.basename\n : (entryIds[0] ?? ctx.dir.basename);\n const cssFileName = `${cssBaseName}.css`;\n\n // Routing for tsdown's plain-CSS blob (see `writeBundle`). plugboy's CSS\n // pipeline emits ALL plain (non-`.css.ts`) CSS — e.g. an `@font-face`\n // sheet `import`ed by an entry — into a single combined file\n // (`TSDOWN_CSS_FILE_NAME`); it cannot be split per entry (tsdown's own CSS\n // `splitting` drops the styles entirely when vanilla-extract is present).\n // The per-entry split in `generateBundle` fills these so the blob is\n // merged into the right entry CSS files instead of an orphan\n // `cssFileName`. Defaults (no split) keep the original single-file\n // behavior. `plainCssTargets`: entry CSS files (`a.css`) that import plain\n // CSS. `plainCssFallback`: where the blob goes when the split fired but no\n // entry with a CSS file owns the plain CSS (avoids re-creating an orphan).\n const plainCssTargets = new Set<string>();\n let plainCssFallback = cssFileName;\n\n ctx.mergeExternals(/@vanilla-extract/);\n\n ctx.meta.hasVanillaExtract = !!(await findFile(\n ctx.dirs.src.value,\n /\\.css\\.ts$/,\n ));\n\n // When vanilla-extract is in play, route tsdown's own CSS to a temporary\n // name so it doesn't collide with the vanilla-extract bundle that also\n // targets `cssFileName`; the two are merged into a single `cssFileName`\n // by the `writeBundle` hook below. Without vanilla-extract there is no\n // second producer, so tsdown emits `cssFileName` directly.\n ctx.css = {\n splitting: false,\n fileName: ctx.meta.hasVanillaExtract\n ? TSDOWN_CSS_FILE_NAME\n : cssFileName,\n };\n\n if (ctx.meta.hasVanillaExtract) {\n const originalPlugin = vanillaExtractPlugin({\n ...options,\n extract: {\n name: cssFileName,\n sourcemap: false,\n },\n });\n\n // `@vanilla-extract/rollup-plugin` returns a rollup `Plugin`, but\n // plugboy's `ctx.plugins` expects a tsdown (rolldown) `Plugin`. The two\n // are structurally almost identical, but hooks like `outputOptions`\n // type `this` as rollup's `PluginContext` vs rolldown's\n // `MinimalPluginContext`, which makes them unassignable (the `this`\n // type is contravariant). rolldown accepts rollup plugins at runtime,\n // so this is harmless — cast to work around the type mismatch.\n ctx.plugins.push(originalPlugin as unknown as Plugin);\n\n // `@vanilla-extract/rollup-plugin` emits the extracted CSS via\n // `emitFile({ type: 'asset', name: cssFileName })`. Because it uses\n // `name` (a hint) rather than `fileName`, rolldown runs it through the\n // default `assetFileNames` pattern (`assets/[name]-[hash][extname]`),\n // producing e.g. `dist/assets/vue-app-layout-dry0z-1l.css`.\n //\n // We can't *rename* an asset in `generateBundle` because rolldown\n // ignores mutations to a bundle entry's `fileName`. Instead, override\n // `assetFileNames` via the `outputOptions` hook so this single CSS\n // asset keeps its derived name verbatim (no hash, no `assets/` dir)\n // while every other asset keeps its original naming.\n ctx.plugins.push({\n name: `${PLUGIN_NAME}:rename-css`,\n outputOptions(opts) {\n const original = opts.assetFileNames;\n opts.assetFileNames = (assetInfo) => {\n if (assetInfo.names.includes(cssFileName)) {\n return cssFileName;\n }\n if (typeof original === 'function') return original(assetInfo);\n return original ?? 'assets/[name]-[hash][extname]';\n };\n return opts;\n },\n // Split vanilla-extract's single bundle into one CSS file per entry.\n //\n // `extract: { name }` mode collects the CSS of EVERY `.css.ts` in the\n // graph into one asset (`cssFileName`), which loses plugboy's per-entry\n // CSS contract: every entry with `css: true` declares a `./<entry>.css`\n // export, but only `cssFileName` is ever produced. We rebuild the\n // per-entry files from data vanilla-extract already exposes:\n // `moduleInfo.meta.css` (its public hand-off for extracted CSS, the\n // same field its own bundler reads).\n //\n // CSS is attributed to an entry by walking the INPUT module graph from\n // that entry's `facadeModuleId` via `getModuleInfo().importedIds`, NOT\n // by reading the output chunk's `imports`. `chunk.imports` lists output\n // chunk file names plus external ids, and whether vanilla-extract's\n // external virtual CSS ids appear there is rolldown-version-dependent\n // (some versions only list real output chunks, so the lookup finds\n // nothing and the split silently no-ops). The input graph is stable: it\n // always yields the `.css.ts` modules an entry reaches, regardless of\n // how rolldown chunks the output. A `.css.ts` shared by several entries\n // is included in each entry's file (self-contained per-entry CSS).\n //\n // We never parse vanilla-extract's asset names or re-add the import\n // statements it strips, so the only coupling is `meta.css`.\n //\n // Runs before `plugboy-optimize-css` (appended later in\n // `workspace.plugins`), so each emitted per-entry file still goes\n // through the postcss optimizations.\n //\n // Only splits when more than one entry actually has CSS. With a single\n // CSS entry (the common case) vanilla-extract's bundle is already the\n // correct, fully-ordered output, so it is left untouched and existing\n // single-entry packages are byte-for-byte unaffected.\n generateBundle(_options, bundle) {\n // Walk the input module graph from `root`, collecting (deduped, in\n // import order) the CSS of every `.css.ts` reached (`meta.css`), and\n // flagging whether any plain (non-`.css.ts`) CSS file is imported.\n const collectEntryCss = (\n root: string,\n ): { css: string[]; hasPlain: boolean } => {\n const visited = new Set<string>();\n const seenCss = new Set<string>();\n const out: string[] = [];\n let hasPlain = false;\n const walk = (id: string) => {\n if (visited.has(id)) return;\n visited.add(id);\n const info = this.getModuleInfo(id);\n if (!info) return;\n for (const dep of info.importedIds ?? []) {\n const css = this.getModuleInfo(dep)?.meta?.css;\n if (typeof css === 'string') {\n // vanilla-extract virtual CSS (`*.vanilla.css`).\n if (!seenCss.has(dep)) {\n seenCss.add(dep);\n out.push(css);\n }\n } else if (/\\.css(\\?|$)/i.test(dep)) {\n // Plain CSS import (no `meta.css`) — its content lives in\n // tsdown's combined blob, merged per entry in `writeBundle`.\n hasPlain = true;\n }\n walk(dep);\n }\n };\n walk(root);\n return { css: out, hasPlain };\n };\n\n const entryCss: {\n name: string;\n source: string;\n hasPlain: boolean;\n }[] = [];\n\n for (const chunk of Object.values(bundle)) {\n if (\n chunk.type !== 'chunk' ||\n !chunk.isEntry ||\n !chunk.fileName.endsWith('.mjs') ||\n !chunk.facadeModuleId\n ) {\n continue;\n }\n const { css, hasPlain } = collectEntryCss(chunk.facadeModuleId);\n if (css.length) {\n entryCss.push({\n name: chunk.name,\n source: css.join('\\n'),\n hasPlain,\n });\n }\n }\n\n // 0 or 1 CSS entry → vanilla-extract's bundle is already correct,\n // and the single-file `writeBundle` fallback applies unchanged.\n if (entryCss.length <= 1) return;\n\n // Replace vanilla-extract's combined bundle with per-entry files.\n // The entry whose file name matches `cssFileName` overwrites the\n // existing asset in place — re-`emitFile`ing the same name would\n // trip rolldown's FILE_NAME_CONFLICT, since deleting the bundle\n // entry does not release the reserved file name. Other entries are\n // emitted as new assets.\n const reused = new Set<string>();\n for (const { name, source } of entryCss) {\n const fileName = `${name}.css`;\n const existing = bundle[fileName];\n if (existing && existing.type === 'asset') {\n existing.source = source;\n reused.add(fileName);\n } else {\n this.emitFile({ type: 'asset', fileName, source });\n }\n }\n\n // Drop vanilla-extract's combined bundle if no entry reused it.\n const combined = bundle[cssFileName];\n if (\n combined &&\n combined.type === 'asset' &&\n !reused.has(cssFileName)\n ) {\n delete bundle[cssFileName];\n }\n\n // Tell `writeBundle` where to merge tsdown's plain-CSS blob: into\n // each entry CSS file whose entry imports plain CSS. Falling back to\n // the first entry's file keeps the blob attached to a real, exported\n // CSS file instead of resurrecting the now-deleted `cssFileName`.\n plainCssTargets.clear();\n plainCssFallback = `${entryCss[0].name}.css`;\n for (const { name, hasPlain } of entryCss) {\n if (hasPlain) plainCssTargets.add(`${name}.css`);\n }\n },\n // Merge tsdown's own plain-CSS blob (emitted to\n // `TSDOWN_CSS_FILE_NAME`) into the vanilla-extract CSS file(s).\n //\n // This has to happen in `writeBundle`, not `generateBundle`: tsdown\n // emits its CSS in a separate output pass, so `TSDOWN_CSS_FILE_NAME`\n // is absent from the bundle our `generateBundle` sees but present by\n // `writeBundle`. By then the vanilla-extract files are already on disk,\n // so we merge on disk rather than mutating bundle sources. tsdown's\n // CSS goes first so its `@layer` declarations / resets / `@font-face`\n // are established before the extracted component styles.\n //\n // Targets:\n // - Per-entry split fired → the entry CSS files whose entries import\n // plain CSS (`plainCssTargets`), falling back to the first entry's\n // file. Never `cssFileName`, which the split deleted (no orphan).\n // - No split (single CSS entry) → `cssFileName`, the one combined file.\n // The combined blob cannot be partitioned per entry, so when several\n // entries import distinct plain CSS each target receives the whole\n // blob; in practice plain CSS (fonts/resets) is imported by one entry.\n async writeBundle(outputOptions, bundle) {\n // Only the output pass that emitted tsdown's CSS performs the merge\n // (it is the one whose `bundle` contains `TSDOWN_CSS_FILE_NAME`).\n // This also prevents a second output from re-injecting the imports.\n const tmp = bundle[TSDOWN_CSS_FILE_NAME];\n if (!tmp) return;\n\n const tmpCss = tmp.type === 'asset' ? tmp.source.toString() : '';\n const dir = outputOptions.dir ?? '.';\n const tmpPath = path.join(dir, TSDOWN_CSS_FILE_NAME);\n\n if (tmpCss) {\n const targets = plainCssTargets.size\n ? [...plainCssTargets]\n : [plainCssFallback];\n\n await Promise.all(\n targets.map(async (target) => {\n const targetPath = path.join(dir, target);\n let targetCss = '';\n try {\n targetCss = await fs.readFile(targetPath, 'utf8');\n } catch {\n // No vanilla-extract file for this target (e.g. `.css.ts`\n // produced no rules) — tsdown's CSS becomes the whole file.\n }\n await fs.writeFile(\n targetPath,\n targetCss ? `${tmpCss}\\n${targetCss}` : tmpCss,\n );\n }),\n );\n }\n\n await fs.rm(tmpPath, { force: true });\n },\n });\n }\n },\n },\n });\n}\n","import { findProjectPlugin } from '@fastkit/plugboy';\nimport { Plugin as VitePlugin } from 'vite';\nimport { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';\nimport { PLUGIN_NAME, VanillaExtractPlugin } from './types';\n\ntype VanillaExtractVitePluginOptions = NonNullable<\n Parameters<typeof vanillaExtractPlugin>[0]\n>;\n\nexport interface ViteVanillaExtractPluginOptions extends VanillaExtractVitePluginOptions {}\n\nexport async function ViteVanillaExtractPlugin(\n options: ViteVanillaExtractPluginOptions = {},\n): Promise<VitePlugin[]> {\n const plugin = await findProjectPlugin<VanillaExtractPlugin>(PLUGIN_NAME);\n const { identifiers: baseIdentifiers } = plugin?._options || {};\n\n return [\n ...vanillaExtractPlugin({\n identifiers: baseIdentifiers,\n ...options,\n }),\n // @MEMO\n // Plugin to prevent file scope mismatches when utilities using vanilla-extract\n // functions are placed in external files\n {\n name: 'vanilla-extract-fix-file-scope',\n config(viteConfig) {\n viteConfig.resolve ??= {};\n viteConfig.resolve.dedupe ??= [];\n viteConfig.resolve.dedupe.push(\n '@vanilla-extract/css',\n '@vanilla-extract/css/fileScope',\n );\n },\n },\n ];\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastkit/plugboy-vanilla-extract-plugin",
3
- "version": "4.0.0-next.8",
3
+ "version": "4.0.0",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "repository": {
@@ -18,12 +18,6 @@
18
18
  "default": "./dist/plugboy-vanilla-extract-plugin.mjs"
19
19
  }
20
20
  },
21
- "./css": {
22
- "types": "./dist/css.d.mts",
23
- "import": {
24
- "default": "./dist/css.mjs"
25
- }
26
- },
27
21
  "./*": "./dist/*"
28
22
  },
29
23
  "main": "./dist/plugboy-vanilla-extract-plugin.mjs",
@@ -32,9 +26,6 @@
32
26
  "*": {
33
27
  ".": [
34
28
  "./dist/plugboy-vanilla-extract-plugin.d.mts"
35
- ],
36
- "css": [
37
- "./dist/css.d.mts"
38
29
  ]
39
30
  }
40
31
  },
@@ -42,17 +33,16 @@
42
33
  "dist"
43
34
  ],
44
35
  "dependencies": {
45
- "@vanilla-extract/css": "^1.20.1",
46
36
  "@vanilla-extract/rollup-plugin": "^1.5.3",
47
37
  "@vanilla-extract/vite-plugin": "^5.2.2"
48
38
  },
49
39
  "devDependencies": {
50
40
  "vite": "^8.0.16",
51
- "@fastkit/plugboy": "^1.0.0-next.5"
41
+ "@fastkit/plugboy": "^1.0.0"
52
42
  },
53
43
  "peerDependencies": {
54
44
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
55
- "@fastkit/plugboy": "^1.0.0-next.5"
45
+ "@fastkit/plugboy": "^1.0.0"
56
46
  },
57
47
  "peerDependenciesMeta": {
58
48
  "@vanilla-extract/vite-plugin": {
package/dist/css.d.mts DELETED
@@ -1,75 +0,0 @@
1
- import { GlobalStyleRule, StyleRule, createGlobalTheme } from "@vanilla-extract/css";
2
-
3
- //#region src/css/layer.d.ts
4
- type CustomStyleRules = Record<string, any>;
5
- type _LayerStyleRules = NonNullable<StyleRule['@layer']>[string];
6
- type LayerStyleRules<CustomRules extends CustomStyleRules | null = null> = CustomRules extends null ? _LayerStyleRules : _LayerStyleRules & CustomRules;
7
- type ClassNames = string | ClassNames[];
8
- type ComplexLayerStyleRule<CustomRules extends CustomStyleRules | null = null> = LayerStyleRules<CustomRules> | (LayerStyleRules<CustomRules> | ClassNames)[];
9
- type _LayerGlobalStyleRules = NonNullable<GlobalStyleRule['@layer']>[string];
10
- type LayerGlobalStyleRules<CustomRules extends CustomStyleRules | null = null> = CustomRules extends null ? _LayerGlobalStyleRules : _LayerGlobalStyleRules & CustomRules;
11
- type AnyStyleRule<CustomRules extends CustomStyleRules | null = null> = LayerStyleRules<CustomRules> | LayerGlobalStyleRules<CustomRules>;
12
- type LayerStyleHooks<CustomRules extends CustomStyleRules | null = null> = {
13
- style?: (rule: ComplexLayerStyleRule<CustomRules>, debugId?: string) => void;
14
- global?: (selector: string, rule: LayerGlobalStyleRules<CustomRules>) => void;
15
- anyStyle?: (style: AnyStyleRule<CustomRules>) => void;
16
- };
17
- interface LayerStyle<CustomRules extends CustomStyleRules | null = null> {
18
- layerName: string;
19
- parentLayerName: string | null;
20
- /**
21
- * @see {@link style}
22
- */
23
- (rule: ComplexLayerStyleRule<CustomRules>, debugId?: string): string;
24
- /**
25
- * @see {@link style}
26
- */
27
- style(rule: ComplexLayerStyleRule<CustomRules>, debugId?: string): string;
28
- /**
29
- * @see {@link globalStyle}
30
- */
31
- global(selector: string, rule: LayerGlobalStyleRules<CustomRules>): void;
32
- /**
33
- * @see {@link _createGlobalTheme}
34
- */
35
- globalTheme: typeof createGlobalTheme;
36
- defineNestedLayer(globalNameOrNestedOptions?: string | DefineLayerOptions<CustomRules>): LayerStyle<CustomRules>;
37
- /**
38
- * Add global CSS variable with layer
39
- *
40
- * @remarks The vanilla-extract API is buggy when handling layered css variables.
41
- *
42
- * @param selector - selector
43
- * @param vars - variables
44
- */
45
- pushGlobalVars(selector: string, vars: Record<string, string>): void;
46
- /**
47
- * Output variables accumulated by `pushGlobalVars`.
48
- *
49
- * @remarks The vanilla-extract API is buggy when handling layered css variables.
50
- */
51
- dumpGlobalVars(): void;
52
- hooks: LayerStyleHooks<CustomRules>;
53
- }
54
- interface DefineLayerParentOptions {
55
- parent?: string;
56
- }
57
- interface DefineLayerBaseOptions<CustomRules extends CustomStyleRules | null = null> {
58
- hooks?: LayerStyleHooks<CustomRules>;
59
- }
60
- interface DefineLayerScopedOptions<CustomRules extends CustomStyleRules | null = null> extends DefineLayerBaseOptions<CustomRules> {
61
- /** Debug ID */
62
- debugId?: string;
63
- globalName?: never;
64
- }
65
- interface DefineLayerGlobalOptions<CustomRules extends CustomStyleRules | null = null> extends DefineLayerBaseOptions<CustomRules> {
66
- debugId?: never;
67
- /** Parent layer name */
68
- globalName: string;
69
- }
70
- type DefineLayerOptions<CustomRules extends CustomStyleRules | null = null> = DefineLayerScopedOptions<CustomRules> | DefineLayerGlobalOptions<CustomRules>;
71
- type DefineNestableLayerOptions<CustomRules extends CustomStyleRules | null = null> = DefineLayerOptions<CustomRules> & DefineLayerParentOptions;
72
- declare function defineLayerStyle<CustomRules extends CustomStyleRules | null = null>(globalNameOrOptions?: string | DefineNestableLayerOptions<CustomRules>): LayerStyle<CustomRules>;
73
- //#endregion
74
- export { DefineLayerBaseOptions, DefineLayerGlobalOptions, DefineLayerOptions, DefineLayerParentOptions, DefineLayerScopedOptions, DefineNestableLayerOptions, LayerStyle, defineLayerStyle };
75
- //# sourceMappingURL=css.d.mts.map
package/dist/css.mjs DELETED
@@ -1,105 +0,0 @@
1
- import { createThemeContract, globalLayer, globalStyle, layer, style } from "@vanilla-extract/css";
2
- //#region src/css/utils.ts
3
- function get(obj, path) {
4
- let result = obj;
5
- for (const key of path) {
6
- if (!(key in result)) throw new Error(`Path ${path.join(" -> ")} does not exist in object`);
7
- result = result[key];
8
- }
9
- return result;
10
- }
11
- function walkObject(obj, fn, path = []) {
12
- const clone = obj.constructor();
13
- for (const key in obj) {
14
- const value = obj[key];
15
- const currentPath = [...path, key];
16
- if (typeof value === "string" || typeof value === "number" || value == null) clone[key] = fn(value, currentPath);
17
- else if (typeof value === "object" && !Array.isArray(value)) clone[key] = walkObject(value, fn, currentPath);
18
- else console.warn(`Skipping invalid key "${currentPath.join(".")}". Should be a string, number, null or object. Received: "${Array.isArray(value) ? "Array" : typeof value}"`);
19
- }
20
- return clone;
21
- }
22
- function assignVars(varContract, tokens) {
23
- const varSetters = {};
24
- walkObject(tokens, (value, path) => {
25
- varSetters[get(varContract, path)] = String(value);
26
- });
27
- return varSetters;
28
- }
29
- //#endregion
30
- //#region src/css/theme.ts
31
- function createGlobalTheme$1(layerName, selector, arg2, arg3) {
32
- const shouldCreateVars = Boolean(!arg3);
33
- const themeVars = shouldCreateVars ? createThemeContract(arg2) : arg2;
34
- const tokens = shouldCreateVars ? arg2 : arg3;
35
- globalStyle(selector, { "@layer": { [layerName]: { vars: assignVars(themeVars, tokens) } } });
36
- if (shouldCreateVars) return themeVars;
37
- }
38
- //#endregion
39
- //#region src/css/layer.ts
40
- function isGlobalOptions(options) {
41
- return "globalName" in options;
42
- }
43
- function normalizeToObject(source) {
44
- if (!source) return {};
45
- if (typeof source === "string") return { globalName: source };
46
- return source;
47
- }
48
- function defineLayerStyle(globalNameOrOptions) {
49
- const options = normalizeToObject(globalNameOrOptions);
50
- const { parent, hooks = {} } = options;
51
- const layerName = isGlobalOptions(options) ? globalLayer({ parent }, options.globalName) : layer({ parent }, options.debugId);
52
- const layerStyle = function layerStyle(rule, debugId) {
53
- const rules = Array.isArray(rule) ? rule : [rule];
54
- const layerAppliedRules = rules.map((_rule) => {
55
- if (typeof _rule === "string" || Array.isArray(_rule)) return _rule;
56
- return { "@layer": { [layerName]: _rule } };
57
- });
58
- if (hooks.anyStyle) for (const _rule of rules) {
59
- if (typeof _rule === "string" || Array.isArray(_rule)) continue;
60
- hooks.anyStyle(_rule);
61
- }
62
- hooks.style && hooks.style(rule, debugId);
63
- return style(layerAppliedRules, debugId);
64
- };
65
- layerStyle.layerName = layerName;
66
- layerStyle.parentLayerName = parent || null;
67
- layerStyle.style = layerStyle;
68
- layerStyle.hooks = hooks;
69
- layerStyle.global = function layerGlobalStyle(selector, rule) {
70
- hooks.anyStyle && hooks.anyStyle(rule);
71
- hooks.global && hooks.global(selector, rule);
72
- return globalStyle(selector, { "@layer": { [layerName]: rule } });
73
- };
74
- layerStyle.globalTheme = (...args) => createGlobalTheme$1(layerName, ...args);
75
- let _varQueues = [];
76
- layerStyle.pushGlobalVars = function pushGlobalVars(selector, vars) {
77
- let queue = _varQueues.find((q) => q[0] === selector);
78
- if (!queue) {
79
- queue = [selector, {}];
80
- _varQueues.push(queue);
81
- }
82
- Object.assign(queue[1], vars);
83
- };
84
- layerStyle.dumpGlobalVars = function dumpGlobalVars() {
85
- for (const [selector, vars] of _varQueues) layerStyle.global(selector, { vars });
86
- _varQueues = [];
87
- };
88
- layerStyle.defineNestedLayer = function defineNestedLayer(globalNameOrNestedOptions) {
89
- const _options = normalizeToObject(globalNameOrNestedOptions);
90
- const nestedHooks = _options.hooks;
91
- return defineLayerStyle({
92
- ..._options,
93
- hooks: {
94
- ...hooks,
95
- ...nestedHooks
96
- },
97
- parent: layerName
98
- });
99
- };
100
- return layerStyle;
101
- }
102
- //#endregion
103
- export { defineLayerStyle };
104
-
105
- //# sourceMappingURL=css.mjs.map
package/dist/css.mjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"css.mjs","names":["createGlobalTheme","createGlobalTheme"],"sources":["../src/css/utils.ts","../src/css/theme.ts","../src/css/layer.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { Contract, MapLeafNodes, CSSVarFunction } from './types';\n\ntype Primitive = string | number | null | undefined;\n\ntype Walkable = {\n [Key in string | number]: Primitive | Walkable;\n};\n\nexport function get(obj: any, path: Array<string>) {\n let result = obj;\n\n for (const key of path) {\n if (!(key in result)) {\n throw new Error(`Path ${path.join(' -> ')} does not exist in object`);\n }\n result = result[key];\n }\n\n return result;\n}\nexport function walkObject<T extends Walkable, MapTo>(\n obj: T,\n fn: (value: Primitive, path: Array<string>) => MapTo,\n path: Array<string> = [],\n): MapLeafNodes<T, MapTo> {\n const clone = obj.constructor();\n\n for (const key in obj) {\n const value = obj[key];\n const currentPath = [...path, key];\n\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n value == null\n ) {\n clone[key] = fn(value as Primitive, currentPath);\n } else if (typeof value === 'object' && !Array.isArray(value)) {\n clone[key] = walkObject(value as Walkable, fn, currentPath);\n } else {\n console.warn(\n `Skipping invalid key \"${currentPath.join(\n '.',\n )}\". Should be a string, number, null or object. Received: \"${\n Array.isArray(value) ? 'Array' : typeof value\n }\"`,\n );\n }\n }\n\n return clone;\n}\n\nexport function assignVars<VarContract extends Contract>(\n varContract: VarContract,\n tokens: MapLeafNodes<VarContract, string>,\n): Record<CSSVarFunction, string> {\n const varSetters: { [cssVarName: string]: string } = {};\n // const { valid, diffString } = validateContract(varContract, tokens);\n\n // if (!valid) {\n // throw new Error(`Tokens don't match contract.\\n${diffString}`);\n // }\n\n walkObject(tokens, (value, path) => {\n varSetters[get(varContract, path)] = String(value);\n });\n\n return varSetters;\n}\n","import { createThemeContract, globalStyle } from '@vanilla-extract/css';\nimport { Tokens, ThemeVars, Contract, MapLeafNodes } from './types';\nimport { assignVars } from './utils';\n\nexport function createGlobalTheme<ThemeTokens extends Tokens>(\n layerName: string,\n selector: string,\n tokens: ThemeTokens,\n): ThemeVars<ThemeTokens>;\nexport function createGlobalTheme<ThemeContract extends Contract>(\n layerName: string,\n selector: string,\n themeContract: ThemeContract,\n tokens: MapLeafNodes<ThemeContract, string>,\n): void;\nexport function createGlobalTheme(\n layerName: string,\n selector: string,\n arg2: any,\n arg3?: any,\n): any {\n const shouldCreateVars = Boolean(!arg3);\n\n const themeVars = shouldCreateVars\n ? createThemeContract(arg2)\n : (arg2 as ThemeVars<any>);\n\n const tokens = shouldCreateVars ? arg2 : arg3;\n\n globalStyle(selector, {\n '@layer': {\n [layerName]: {\n vars: assignVars(themeVars, tokens),\n },\n },\n });\n\n // appendCss(\n // {\n // type: 'global',\n // selector: selector,\n // rule: { vars: assignVars(themeVars, tokens) },\n // },\n // getFileScope(),\n // );\n\n if (shouldCreateVars) {\n return themeVars;\n }\n}\n","import {\n style,\n layer,\n globalLayer,\n StyleRule,\n globalStyle,\n GlobalStyleRule,\n createGlobalTheme as _createGlobalTheme,\n} from '@vanilla-extract/css';\nimport { createGlobalTheme } from './theme';\n\ntype CustomStyleRules = Record<string, any>;\n\ntype _LayerStyleRules = NonNullable<StyleRule['@layer']>[string];\n\ntype LayerStyleRules<CustomRules extends CustomStyleRules | null = null> =\n CustomRules extends null ? _LayerStyleRules : _LayerStyleRules & CustomRules;\n\ntype ClassNames = string | ClassNames[];\n\ntype ComplexLayerStyleRule<CustomRules extends CustomStyleRules | null = null> =\n | LayerStyleRules<CustomRules>\n | (LayerStyleRules<CustomRules> | ClassNames)[];\n\ntype _LayerGlobalStyleRules = NonNullable<GlobalStyleRule['@layer']>[string];\n\ntype LayerGlobalStyleRules<CustomRules extends CustomStyleRules | null = null> =\n CustomRules extends null\n ? _LayerGlobalStyleRules\n : _LayerGlobalStyleRules & CustomRules;\n\ntype AnyStyleRule<CustomRules extends CustomStyleRules | null = null> =\n | LayerStyleRules<CustomRules>\n | LayerGlobalStyleRules<CustomRules>;\n\ntype LayerStyleHooks<CustomRules extends CustomStyleRules | null = null> = {\n style?: (rule: ComplexLayerStyleRule<CustomRules>, debugId?: string) => void;\n global?: (selector: string, rule: LayerGlobalStyleRules<CustomRules>) => void;\n anyStyle?: (style: AnyStyleRule<CustomRules>) => void;\n};\n\nexport interface LayerStyle<\n CustomRules extends CustomStyleRules | null = null,\n> {\n layerName: string;\n parentLayerName: string | null;\n /**\n * @see {@link style}\n */\n (rule: ComplexLayerStyleRule<CustomRules>, debugId?: string): string;\n\n /**\n * @see {@link style}\n */\n style(rule: ComplexLayerStyleRule<CustomRules>, debugId?: string): string;\n\n /**\n * @see {@link globalStyle}\n */\n global(selector: string, rule: LayerGlobalStyleRules<CustomRules>): void;\n\n /**\n * @see {@link _createGlobalTheme}\n */\n globalTheme: typeof _createGlobalTheme;\n\n defineNestedLayer(\n globalNameOrNestedOptions?: string | DefineLayerOptions<CustomRules>,\n ): LayerStyle<CustomRules>;\n\n /**\n * Add global CSS variable with layer\n *\n * @remarks The vanilla-extract API is buggy when handling layered css variables.\n *\n * @param selector - selector\n * @param vars - variables\n */\n pushGlobalVars(selector: string, vars: Record<string, string>): void;\n\n /**\n * Output variables accumulated by `pushGlobalVars`.\n *\n * @remarks The vanilla-extract API is buggy when handling layered css variables.\n */\n dumpGlobalVars(): void;\n hooks: LayerStyleHooks<CustomRules>;\n}\n\nexport interface DefineLayerParentOptions {\n parent?: string;\n}\n\nexport interface DefineLayerBaseOptions<\n CustomRules extends CustomStyleRules | null = null,\n> {\n hooks?: LayerStyleHooks<CustomRules>;\n}\n\nexport interface DefineLayerScopedOptions<\n CustomRules extends CustomStyleRules | null = null,\n> extends DefineLayerBaseOptions<CustomRules> {\n /** Debug ID */\n debugId?: string;\n globalName?: never;\n}\n\nexport interface DefineLayerGlobalOptions<\n CustomRules extends CustomStyleRules | null = null,\n> extends DefineLayerBaseOptions<CustomRules> {\n debugId?: never;\n /** Parent layer name */\n globalName: string;\n}\n\nexport type DefineLayerOptions<\n CustomRules extends CustomStyleRules | null = null,\n> =\n | DefineLayerScopedOptions<CustomRules>\n | DefineLayerGlobalOptions<CustomRules>;\n\nexport type DefineNestableLayerOptions<\n CustomRules extends CustomStyleRules | null = null,\n> = DefineLayerOptions<CustomRules> & DefineLayerParentOptions;\n\nfunction isGlobalOptions(\n options: DefineLayerOptions<any>,\n): options is DefineLayerGlobalOptions {\n return 'globalName' in options;\n}\n\nfunction normalizeToObject<T extends DefineLayerOptions<any>>(\n source?: string | T,\n): T {\n if (!source) return {} as T;\n if (typeof source === 'string') return { globalName: source } as unknown as T;\n return source;\n}\n\nexport function defineLayerStyle<\n CustomRules extends CustomStyleRules | null = null,\n>(\n globalNameOrOptions?: string | DefineNestableLayerOptions<CustomRules>,\n): LayerStyle<CustomRules> {\n const options = normalizeToObject(globalNameOrOptions);\n const { parent, hooks = {} } = options;\n\n const layerName = isGlobalOptions(options)\n ? globalLayer({ parent }, options.globalName)\n : layer({ parent }, options.debugId);\n\n const layerStyle = function layerStyle(rule, debugId) {\n const rules = Array.isArray(rule) ? rule : [rule];\n const layerAppliedRules = rules.map((_rule) => {\n if (typeof _rule === 'string' || Array.isArray(_rule)) return _rule;\n return {\n '@layer': {\n [layerName]: _rule,\n },\n };\n });\n if (hooks.anyStyle) {\n for (const _rule of rules) {\n if (typeof _rule === 'string' || Array.isArray(_rule)) continue;\n hooks.anyStyle(_rule);\n }\n }\n hooks.style && hooks.style(rule, debugId);\n return style(layerAppliedRules, debugId);\n } as LayerStyle<CustomRules>;\n\n layerStyle.layerName = layerName;\n layerStyle.parentLayerName = parent || null;\n layerStyle.style = layerStyle;\n layerStyle.hooks = hooks;\n\n layerStyle.global = function layerGlobalStyle(\n selector: string,\n rule: LayerGlobalStyleRules<CustomRules>,\n ) {\n hooks.anyStyle && hooks.anyStyle(rule);\n hooks.global && hooks.global(selector, rule);\n\n return globalStyle(selector, {\n '@layer': {\n [layerName]: rule,\n },\n });\n };\n\n layerStyle.globalTheme = (...args: any) =>\n (createGlobalTheme as any)(layerName, ...args);\n\n let _varQueues: [string, Record<string, string>][] = [];\n\n layerStyle.pushGlobalVars = function pushGlobalVars(\n selector: string,\n vars: Record<string, string>,\n ) {\n let queue = _varQueues.find((q) => q[0] === selector);\n if (!queue) {\n queue = [selector, {}];\n _varQueues.push(queue);\n }\n Object.assign(queue[1], vars);\n };\n\n layerStyle.dumpGlobalVars = function dumpGlobalVars() {\n for (const [selector, vars] of _varQueues) {\n layerStyle.global(selector, {\n vars,\n } as any);\n }\n _varQueues = [];\n };\n\n layerStyle.defineNestedLayer = function defineNestedLayer(\n globalNameOrNestedOptions?: string | DefineLayerOptions<CustomRules>,\n ) {\n const _options = normalizeToObject(globalNameOrNestedOptions);\n const nestedHooks = _options.hooks;\n\n return defineLayerStyle({\n ..._options,\n hooks: {\n ...hooks,\n ...nestedHooks,\n },\n parent: layerName,\n });\n };\n\n return layerStyle;\n}\n"],"mappings":"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"}