@salty-css/core 0.1.0-feat-define-import.0 → 0.1.0-feat-template-variants.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 CHANGED
@@ -57,7 +57,6 @@ To get help with problems, [Join Salty CSS Discord server](https://discord.gg/R6
57
57
  - [defineVariables](#variables) - create CSS variables (tokens) that can be used in any styling function
58
58
  - [defineMediaQuery](#media-queries) - create CSS media queries and use them in any styling function
59
59
  - [defineTemplates](#templates) - create reusable templates that can be applied when same styles are used over and over again
60
- - [defineImport](#importing-additional-css) - pull in external CSS files (relative, public, node_modules, or URL)
61
60
  - [keyframes](#keyframes-animations) - create CSS keyframes animation that can be used and imported in any styling function
62
61
 
63
62
  ### Styling helpers & utility
@@ -320,49 +319,6 @@ Example usage:
320
319
  styled('div', { base: { textStyle: 'headline.large', card: '20px' } });
321
320
  ```
322
321
 
323
- ## Importing additional CSS
324
-
325
- Use `defineImport` to pull in CSS that lives outside of Salty's authoring API — a reset stylesheet from npm, a Google Fonts URL, an asset in your app's `public/` folder, or a sibling `.css` file. The compiler turns each spec into an `@import` rule in the generated `saltygen/index.css`, so the imported stylesheets travel with the rest of your build.
326
-
327
- ```ts
328
- // /styles/imports.css.ts
329
- import { defineImport } from '@salty-css/core/factories';
330
-
331
- export default defineImport(
332
- // Relative to this file
333
- './reset.css',
334
- // From node_modules (bare specifier — same as Vite / native CSS @import)
335
- 'modern-normalize/modern-normalize.css',
336
- // From node_modules (~ prefix — same resolver, webpack-style)
337
- '~normalize.css/normalize.css',
338
- // From your app's public/ folder (served at the host root)
339
- '/fonts/inter.css',
340
- // External URL
341
- 'https://fonts.googleapis.com/css2?family=Inter&display=swap',
342
- // Object form — attach media or supports() conditions
343
- { url: './print.css', media: 'print' },
344
- { url: './p3.css', supports: 'color(display-p3 1 1 1)' }
345
- );
346
- ```
347
-
348
- Path resolution:
349
-
350
- | Pattern | Behaviour |
351
- | --------------------------- | ---------------------------------------------------------------------------------------- |
352
- | `http://`, `https://`, `//` | Emitted verbatim |
353
- | Starts with `/` | Public-folder URL — emitted verbatim, the browser resolves it against your host |
354
- | Starts with `./` or `../` | Resolved at build time relative to the file that called `defineImport` |
355
- | `~package/file.css` | Stripped of the leading `~`, then resolved from `node_modules` and copied into the build |
356
- | `package/file.css` (bare) | Same `node_modules` resolution as the `~` form |
357
-
358
- All imports are placed inside a new `imports` cascade layer that sits **before** `reset`, `global`, `templates`, and your component styles. This means your own styles always win over third-party CSS you pull in — which is what most teams expect when they drop in something like `modern-normalize`.
359
-
360
- The full layer order in the generated `index.css` is:
361
-
362
- ```css
363
- @layer imports, reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
364
- ```
365
-
366
322
  ## Keyframes animations
367
323
 
368
324
  ```ts
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { p as parseAndJoinStyles } from "./parse-styles-CLMTHo2H.js";
4
+ import { p as parseAndJoinStyles } from "./parse-styles-DSyVPjDG.js";
5
5
  import { d as dashCase } from "./dash-case-DblXvymC.js";
6
6
  import { t as toHash } from "./to-hash-DAN2LcHK.js";
7
7
  class StylesGenerator {
@@ -2,7 +2,7 @@
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
- const parseStyles = require("./parse-styles-C54MOrPg.cjs");
5
+ const parseStyles = require("./parse-styles-DxyVq07D.cjs");
6
6
  const dashCase = require("./dash-case-DIwKaYgE.cjs");
7
7
  const toHash = require("./to-hash-C05Y906F.cjs");
8
8
  class StylesGenerator {
@@ -11,14 +11,14 @@ const fs = require("fs");
11
11
  const child_process = require("child_process");
12
12
  const compiler_helpers = require("./helpers.cjs");
13
13
  const defineTemplates = require("../define-templates-Deq1aCbN.cjs");
14
- const module$1 = require("module");
15
- const toHash = require("../to-hash-C05Y906F.cjs");
16
14
  const dashCase = require("../dash-case-DIwKaYgE.cjs");
17
- const parseStyles = require("../parse-styles-C54MOrPg.cjs");
15
+ const toHash = require("../to-hash-C05Y906F.cjs");
16
+ const parseStyles = require("../parse-styles-DxyVq07D.cjs");
18
17
  const css_merge = require("../css/merge.cjs");
19
18
  const parsers_index = require("../parsers/index.cjs");
20
- const moduleType = require("../util/module-type");
19
+ const compiler_getFiles = require("./get-files.cjs");
21
20
  const console = require("console");
21
+ var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
22
22
  function _interopNamespaceDefault(e) {
23
23
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
24
24
  if (e) {
@@ -44,53 +44,19 @@ const logger = winston.createLogger({
44
44
  const logError = (message) => {
45
45
  logger.error(message);
46
46
  };
47
- const EXTERNAL_URL = /^(?:[a-z][a-z0-9+.-]*:)?\/\//i;
48
- const normaliseSpec = (spec) => {
49
- if (typeof spec === "string") return { url: spec };
50
- return spec;
51
- };
52
- const ensureRelativePrefix = (path2) => {
53
- if (path2.startsWith(".") || path2.startsWith("/")) return path2;
54
- return `./${path2}`;
55
- };
56
- const toPosix = (path2) => path2.split("\\").join("/");
57
- const defaultResolveModule = (specifier, sourceFile) => {
58
- return module$1.createRequire(sourceFile).resolve(specifier);
59
- };
60
- const defaultCopyAsset = (from, to) => {
61
- const dir = path.dirname(to);
62
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
63
- fs.copyFileSync(from, to);
47
+ const readPackageJsonModule = async (dirname) => {
48
+ const packageJsonContent = await compiler_getFiles.getPackageJson(dirname);
49
+ if (!packageJsonContent) return void 0;
50
+ return packageJsonContent.type;
64
51
  };
65
- const buildRule = (url, { media, supports }) => {
66
- let rule = `@import url('${url}')`;
67
- if (supports) rule += ` supports(${supports})`;
68
- if (media) rule += ` ${media}`;
69
- return `${rule};`;
70
- };
71
- const resolveImport = (spec, sourceFile, destDir, options = {}) => {
72
- const opts = normaliseSpec(spec);
73
- const { url } = opts;
74
- const resolveModule = options.resolveModule ?? defaultResolveModule;
75
- const copyAsset = options.copyAsset ?? defaultCopyAsset;
76
- if (EXTERNAL_URL.test(url)) {
77
- return { rule: buildRule(url, opts) };
78
- }
79
- if (url.startsWith("/")) {
80
- return { rule: buildRule(url, opts) };
81
- }
82
- if (url.startsWith("./") || url.startsWith("../")) {
83
- const absolute2 = path.resolve(path.dirname(sourceFile), url);
84
- const fromImportsFile = path.relative(path.join(destDir, "css"), absolute2);
85
- return { rule: buildRule(ensureRelativePrefix(toPosix(fromImportsFile)), opts) };
86
- }
87
- const specifier = url.startsWith("~") ? url.slice(1) : url;
88
- const absolute = resolveModule(specifier, sourceFile);
89
- const hash = toHash.toHash(absolute, 6);
90
- const fileName = `${hash}-${path.basename(absolute)}`;
91
- const destPath = path.join(destDir, "imports", fileName);
92
- copyAsset(absolute, destPath);
93
- return { rule: buildRule(`../imports/${fileName}`, opts) };
52
+ let cachedModuleType;
53
+ const detectCurrentModuleType = async (dirname) => {
54
+ if (cachedModuleType) return cachedModuleType;
55
+ const packageJsonModule = await readPackageJsonModule(dirname);
56
+ if (packageJsonModule === "module") cachedModuleType = "esm";
57
+ else if (packageJsonModule === "commonjs") cachedModuleType = "cjs";
58
+ else if ((typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("compiler/salty-compiler.cjs", document.baseURI).href).endsWith(".cjs")) cachedModuleType = "cjs";
59
+ return cachedModuleType || "esm";
94
60
  };
95
61
  function dotCase(str) {
96
62
  if (!str) return "";
@@ -207,7 +173,7 @@ class SaltyCompiler {
207
173
  const destDir = await this.getDestDir();
208
174
  const coreConfigPath = path.join(this.projectRootDir, (rcProject == null ? void 0 : rcProject.configDir) || "", "salty.config.ts");
209
175
  const coreConfigDest = path.join(destDir, "salty.config.js");
210
- const moduleType$1 = await moduleType.detectCurrentModuleType(this.projectRootDir);
176
+ const moduleType = await detectCurrentModuleType(this.projectRootDir);
211
177
  const externalModules = this.getExternalModules(coreConfigPath);
212
178
  await esbuild__namespace.build({
213
179
  entryPoints: [coreConfigPath],
@@ -215,7 +181,7 @@ class SaltyCompiler {
215
181
  treeShaking: true,
216
182
  bundle: true,
217
183
  outfile: coreConfigDest,
218
- format: moduleType$1,
184
+ format: moduleType,
219
185
  external: externalModules
220
186
  });
221
187
  const { config } = await this.importFile(coreConfigDest);
@@ -267,7 +233,6 @@ ${currentFile}`;
267
233
  fs.mkdirSync(path.join(destDir, "types"));
268
234
  fs.mkdirSync(path.join(destDir, "js"));
269
235
  fs.mkdirSync(path.join(destDir, "cache"));
270
- fs.mkdirSync(path.join(destDir, "imports"));
271
236
  };
272
237
  if (clean) clearDistDir();
273
238
  const files = /* @__PURE__ */ new Set();
@@ -383,7 +348,7 @@ ${currentFile}`;
383
348
  });
384
349
  }
385
350
  const otherGlobalCssFiles = globalCssFiles.map((file) => `@import url('./css/${file}');`).join("\n");
386
- const globalCssFilenames = ["_imports.css", "_variables.css", "_reset.css", "_global.css", "_templates.css"];
351
+ const globalCssFilenames = ["_variables.css", "_reset.css", "_global.css", "_templates.css"];
387
352
  const importsWithData = globalCssFilenames.filter((file) => {
388
353
  try {
389
354
  const data = fs.readFileSync(path.join(destDir, "css", file), "utf8");
@@ -392,12 +357,9 @@ ${currentFile}`;
392
357
  return false;
393
358
  }
394
359
  });
395
- const globalImports = importsWithData.map((file) => {
396
- const layerSuffix = file === "_imports.css" ? " layer(imports)" : "";
397
- return `@import url('./css/${file}')${layerSuffix};`;
398
- });
360
+ const globalImports = importsWithData.map((file) => `@import url('./css/${file}');`);
399
361
  const generatorText = "/*!\n * Generated with Salty CSS (https://salty-css.dev)\n * Do not edit this file directly\n */\n";
400
- let cssContent = `${generatorText}@layer imports, reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
362
+ let cssContent = `${generatorText}@layer reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
401
363
 
402
364
  ${globalImports.join(
403
365
  "\n"
@@ -443,8 +405,7 @@ ${css}
443
405
  mediaQueries: [],
444
406
  globalStyles: [],
445
407
  variables: [],
446
- templates: [],
447
- imports: []
408
+ templates: []
448
409
  };
449
410
  await Promise.all(
450
411
  [...configFiles].map(async (src) => {
@@ -454,7 +415,6 @@ ${css}
454
415
  else if (value.isGlobalDefine) generationResults.globalStyles.push(value);
455
416
  else if (value.isDefineVariables) generationResults.variables.push(value);
456
417
  else if (value.isDefineTemplates) generationResults.templates.push(value._setPath(`${name};;${outputFilePath}`));
457
- else if (value.isDefineImport) generationResults.imports.push(value._setPath(src));
458
418
  });
459
419
  })
460
420
  );
@@ -551,39 +511,46 @@ ${css}
551
511
  const templates = css_merge.mergeObjects(config.templates, generationResults.templates);
552
512
  const templateStylesString = await parsers_index.parseTemplates(templates);
553
513
  const templateTokens = parsers_index.getTemplateTypes(templates);
514
+ const templateVariantMaps = parsers_index.getTemplateVariantMaps(templates);
554
515
  fs.writeFileSync(templateStylesPath, `@layer templates { ${templateStylesString} }`);
555
516
  configCacheContent.templates = templates;
556
- const importsPath = path.join(destDir, "css/_imports.css");
557
- const importRules = [];
558
- for (const factory of generationResults.imports) {
559
- const sourceFile = factory._path;
560
- if (!sourceFile) continue;
561
- for (const spec of factory._current) {
562
- try {
563
- const { rule } = resolveImport(spec, sourceFile, destDir);
564
- importRules.push(rule);
565
- } catch (e) {
566
- const url = typeof spec === "string" ? spec : spec.url;
567
- logger.error(`Failed to resolve defineImport(${JSON.stringify(url)}) from ${sourceFile}: ${e.message}`);
568
- }
569
- }
570
- }
571
- fs.writeFileSync(importsPath, importRules.join("\n"));
572
517
  const configTemplateFactories = config.templates ? [defineTemplates.defineTemplates(config.templates)._setPath(`config;;${configPath}`)] : [];
573
518
  const templateFactories = css_merge.mergeFactories(generationResults.templates, configTemplateFactories);
574
519
  configCacheContent.templatePaths = Object.fromEntries(Object.entries(templateFactories).map(([key, faktory]) => [key, faktory._path]));
575
520
  const tsTokensPath = path.join(destDir, "types/css-tokens.d.ts");
576
521
  const tsVariableTokens = [...variableTokens].join("|");
522
+ const pascal = (str) => str.split(/[.\-_]/).filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
523
+ const templateVariantMapEntries = Object.entries(templateVariantMaps);
524
+ const hasVariantMaps = templateVariantMapEntries.some(([, pathMap]) => Object.keys(pathMap).length > 0);
525
+ const tsTemplateVariantMap = hasVariantMaps ? `type TemplateVariantTokens = {
526
+ ${templateVariantMapEntries.filter(([, pathMap]) => Object.keys(pathMap).length > 0).map(([templateKey, pathMap]) => {
527
+ const pathEntries = Object.entries(pathMap).map(
528
+ ([dotPath, axes]) => `'${dotPath}': { ${Object.entries(axes).map(([axis, valueType]) => `${axis}?: ${valueType}`).join("; ")} }`
529
+ ).join(";\n ");
530
+ return `${templateKey}: {
531
+ ${pathEntries}
532
+ }`;
533
+ }).join(";\n ")}
534
+ }` : `type TemplateVariantTokens = Record<string, Record<string, Record<string, never>>>;`;
535
+ const tsTemplateVariantAliases = templateVariantMapEntries.flatMap(
536
+ ([templateKey, pathMap]) => Object.keys(pathMap).map(
537
+ (dotPath) => `type ${pascal(templateKey)}${pascal(dotPath)}Variants = TemplateVariantTokens['${templateKey}']['${dotPath}'];`
538
+ )
539
+ ).join("\n ");
577
540
  const tsTokensTypes = `
578
541
  // Variable types
579
- type VariableTokens = ${tsVariableTokens || `''`};
542
+ type VariableTokens = ${tsVariableTokens || `''`};
580
543
  type PropertyValueToken = \`{\${VariableTokens}}\`;
581
-
544
+
582
545
  // Template types
583
546
  type TemplateTokens = {
584
547
  ${Object.entries(templateTokens).map(([key, value]) => `${key}?: ${value}`).join("\n")}
585
548
  }
586
-
549
+
550
+ // Template variant types (per docs/template-variants-spec.md §7)
551
+ ${tsTemplateVariantMap}
552
+ ${tsTemplateVariantAliases}
553
+
587
554
  // Media query types
588
555
  type MediaQueryKeys = ${mediaQueryKeys || `''`};
589
556
  `;
@@ -607,7 +574,7 @@ ${css}
607
574
  const rcProject = await this.getRCProjectConfig(this.projectRootDir);
608
575
  const coreConfigPath = path.join(this.projectRootDir, (rcProject == null ? void 0 : rcProject.configDir) || "", "salty.config.ts");
609
576
  const externalModules = this.getExternalModules(coreConfigPath);
610
- const moduleType$1 = await moduleType.detectCurrentModuleType(this.projectRootDir);
577
+ const moduleType = await detectCurrentModuleType(this.projectRootDir);
611
578
  await esbuild__namespace.build({
612
579
  stdin: {
613
580
  contents: currentFile,
@@ -619,7 +586,7 @@ ${css}
619
586
  treeShaking: true,
620
587
  bundle: true,
621
588
  outfile: outputFilePath,
622
- format: moduleType$1,
589
+ format: moduleType,
623
590
  target: ["node20"],
624
591
  keepNames: true,
625
592
  external: externalModules,
@@ -44,7 +44,6 @@ export declare class SaltyCompiler {
44
44
  isGlobalDefine?: boolean;
45
45
  isDefineVariables?: boolean;
46
46
  isDefineTemplates?: boolean;
47
- isDefineImport?: boolean;
48
47
  isKeyframes?: boolean;
49
48
  animationName?: string;
50
49
  css?: Promise<string>;
@@ -2,20 +2,19 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import * as esbuild from "esbuild";
5
- import { resolve, dirname, relative, join, basename, parse } from "path";
5
+ import { join, parse } from "path";
6
6
  import { createLogger, transports, format } from "winston";
7
7
  import { readFile } from "fs/promises";
8
- import { existsSync, mkdirSync, copyFileSync, readFileSync, statSync, readdirSync, writeFileSync } from "fs";
8
+ import { readFileSync, existsSync, mkdirSync, statSync, readdirSync, writeFileSync } from "fs";
9
9
  import { execSync } from "child_process";
10
10
  import { isSaltyFile, resolveExportValue, getCorePackageRoot, saltyFileExtensions } from "./helpers.js";
11
11
  import { d as defineTemplates } from "../define-templates-CVhhgPnd.js";
12
- import { createRequire } from "module";
13
- import { t as toHash } from "../to-hash-DAN2LcHK.js";
14
12
  import { d as dashCase } from "../dash-case-DblXvymC.js";
15
- import { p as parseAndJoinStyles, b as parseVariableTokens } from "../parse-styles-CLMTHo2H.js";
13
+ import { t as toHash } from "../to-hash-DAN2LcHK.js";
14
+ import { p as parseAndJoinStyles, b as parseVariableTokens } from "../parse-styles-DSyVPjDG.js";
16
15
  import { mergeObjects, mergeFactories } from "../css/merge.js";
17
- import { parseTemplates, getTemplateTypes } from "../parsers/index.js";
18
- import { detectCurrentModuleType } from "../util/module-type";
16
+ import { parseTemplates, getTemplateTypes, getTemplateVariantMaps } from "../parsers/index.js";
17
+ import { getPackageJson } from "./get-files.js";
19
18
  import console from "console";
20
19
  const logger = createLogger({
21
20
  level: "debug",
@@ -25,53 +24,19 @@ const logger = createLogger({
25
24
  const logError = (message) => {
26
25
  logger.error(message);
27
26
  };
28
- const EXTERNAL_URL = /^(?:[a-z][a-z0-9+.-]*:)?\/\//i;
29
- const normaliseSpec = (spec) => {
30
- if (typeof spec === "string") return { url: spec };
31
- return spec;
32
- };
33
- const ensureRelativePrefix = (path) => {
34
- if (path.startsWith(".") || path.startsWith("/")) return path;
35
- return `./${path}`;
36
- };
37
- const toPosix = (path) => path.split("\\").join("/");
38
- const defaultResolveModule = (specifier, sourceFile) => {
39
- return createRequire(sourceFile).resolve(specifier);
40
- };
41
- const defaultCopyAsset = (from, to) => {
42
- const dir = dirname(to);
43
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
44
- copyFileSync(from, to);
27
+ const readPackageJsonModule = async (dirname) => {
28
+ const packageJsonContent = await getPackageJson(dirname);
29
+ if (!packageJsonContent) return void 0;
30
+ return packageJsonContent.type;
45
31
  };
46
- const buildRule = (url, { media, supports }) => {
47
- let rule = `@import url('${url}')`;
48
- if (supports) rule += ` supports(${supports})`;
49
- if (media) rule += ` ${media}`;
50
- return `${rule};`;
51
- };
52
- const resolveImport = (spec, sourceFile, destDir, options = {}) => {
53
- const opts = normaliseSpec(spec);
54
- const { url } = opts;
55
- const resolveModule = options.resolveModule ?? defaultResolveModule;
56
- const copyAsset = options.copyAsset ?? defaultCopyAsset;
57
- if (EXTERNAL_URL.test(url)) {
58
- return { rule: buildRule(url, opts) };
59
- }
60
- if (url.startsWith("/")) {
61
- return { rule: buildRule(url, opts) };
62
- }
63
- if (url.startsWith("./") || url.startsWith("../")) {
64
- const absolute2 = resolve(dirname(sourceFile), url);
65
- const fromImportsFile = relative(join(destDir, "css"), absolute2);
66
- return { rule: buildRule(ensureRelativePrefix(toPosix(fromImportsFile)), opts) };
67
- }
68
- const specifier = url.startsWith("~") ? url.slice(1) : url;
69
- const absolute = resolveModule(specifier, sourceFile);
70
- const hash = toHash(absolute, 6);
71
- const fileName = `${hash}-${basename(absolute)}`;
72
- const destPath = join(destDir, "imports", fileName);
73
- copyAsset(absolute, destPath);
74
- return { rule: buildRule(`../imports/${fileName}`, opts) };
32
+ let cachedModuleType;
33
+ const detectCurrentModuleType = async (dirname) => {
34
+ if (cachedModuleType) return cachedModuleType;
35
+ const packageJsonModule = await readPackageJsonModule(dirname);
36
+ if (packageJsonModule === "module") cachedModuleType = "esm";
37
+ else if (packageJsonModule === "commonjs") cachedModuleType = "cjs";
38
+ else if (import.meta.url.endsWith(".cjs")) cachedModuleType = "cjs";
39
+ return cachedModuleType || "esm";
75
40
  };
76
41
  function dotCase(str) {
77
42
  if (!str) return "";
@@ -156,10 +121,10 @@ class SaltyCompiler {
156
121
  * Get the project configuration from the .saltyrc.json file based on the current directory.
157
122
  * If no specific project configuration is found, it falls back to the default project.
158
123
  */
159
- __publicField(this, "getRCProjectConfig", async (dirname2) => {
124
+ __publicField(this, "getRCProjectConfig", async (dirname) => {
160
125
  var _a, _b;
161
- const rcFile = await this.readRCFile(dirname2);
162
- const projectConfig = (_a = rcFile.projects) == null ? void 0 : _a.find((project) => dirname2.endsWith(project.dir || ""));
126
+ const rcFile = await this.readRCFile(dirname);
127
+ const projectConfig = (_a = rcFile.projects) == null ? void 0 : _a.find((project) => dirname.endsWith(project.dir || ""));
163
128
  if (!projectConfig) return (_b = rcFile.projects) == null ? void 0 : _b.find((project) => project.dir === rcFile.defaultProject);
164
129
  return projectConfig;
165
130
  });
@@ -248,7 +213,6 @@ ${currentFile}`;
248
213
  mkdirSync(join(destDir, "types"));
249
214
  mkdirSync(join(destDir, "js"));
250
215
  mkdirSync(join(destDir, "cache"));
251
- mkdirSync(join(destDir, "imports"));
252
216
  };
253
217
  if (clean) clearDistDir();
254
218
  const files = /* @__PURE__ */ new Set();
@@ -364,7 +328,7 @@ ${currentFile}`;
364
328
  });
365
329
  }
366
330
  const otherGlobalCssFiles = globalCssFiles.map((file) => `@import url('./css/${file}');`).join("\n");
367
- const globalCssFilenames = ["_imports.css", "_variables.css", "_reset.css", "_global.css", "_templates.css"];
331
+ const globalCssFilenames = ["_variables.css", "_reset.css", "_global.css", "_templates.css"];
368
332
  const importsWithData = globalCssFilenames.filter((file) => {
369
333
  try {
370
334
  const data = readFileSync(join(destDir, "css", file), "utf8");
@@ -373,12 +337,9 @@ ${currentFile}`;
373
337
  return false;
374
338
  }
375
339
  });
376
- const globalImports = importsWithData.map((file) => {
377
- const layerSuffix = file === "_imports.css" ? " layer(imports)" : "";
378
- return `@import url('./css/${file}')${layerSuffix};`;
379
- });
340
+ const globalImports = importsWithData.map((file) => `@import url('./css/${file}');`);
380
341
  const generatorText = "/*!\n * Generated with Salty CSS (https://salty-css.dev)\n * Do not edit this file directly\n */\n";
381
- let cssContent = `${generatorText}@layer imports, reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
342
+ let cssContent = `${generatorText}@layer reset, global, templates, l0, l1, l2, l3, l4, l5, l6, l7, l8;
382
343
 
383
344
  ${globalImports.join(
384
345
  "\n"
@@ -424,8 +385,7 @@ ${css}
424
385
  mediaQueries: [],
425
386
  globalStyles: [],
426
387
  variables: [],
427
- templates: [],
428
- imports: []
388
+ templates: []
429
389
  };
430
390
  await Promise.all(
431
391
  [...configFiles].map(async (src) => {
@@ -435,7 +395,6 @@ ${css}
435
395
  else if (value.isGlobalDefine) generationResults.globalStyles.push(value);
436
396
  else if (value.isDefineVariables) generationResults.variables.push(value);
437
397
  else if (value.isDefineTemplates) generationResults.templates.push(value._setPath(`${name};;${outputFilePath}`));
438
- else if (value.isDefineImport) generationResults.imports.push(value._setPath(src));
439
398
  });
440
399
  })
441
400
  );
@@ -532,39 +491,46 @@ ${css}
532
491
  const templates = mergeObjects(config.templates, generationResults.templates);
533
492
  const templateStylesString = await parseTemplates(templates);
534
493
  const templateTokens = getTemplateTypes(templates);
494
+ const templateVariantMaps = getTemplateVariantMaps(templates);
535
495
  writeFileSync(templateStylesPath, `@layer templates { ${templateStylesString} }`);
536
496
  configCacheContent.templates = templates;
537
- const importsPath = join(destDir, "css/_imports.css");
538
- const importRules = [];
539
- for (const factory of generationResults.imports) {
540
- const sourceFile = factory._path;
541
- if (!sourceFile) continue;
542
- for (const spec of factory._current) {
543
- try {
544
- const { rule } = resolveImport(spec, sourceFile, destDir);
545
- importRules.push(rule);
546
- } catch (e) {
547
- const url = typeof spec === "string" ? spec : spec.url;
548
- logger.error(`Failed to resolve defineImport(${JSON.stringify(url)}) from ${sourceFile}: ${e.message}`);
549
- }
550
- }
551
- }
552
- writeFileSync(importsPath, importRules.join("\n"));
553
497
  const configTemplateFactories = config.templates ? [defineTemplates(config.templates)._setPath(`config;;${configPath}`)] : [];
554
498
  const templateFactories = mergeFactories(generationResults.templates, configTemplateFactories);
555
499
  configCacheContent.templatePaths = Object.fromEntries(Object.entries(templateFactories).map(([key, faktory]) => [key, faktory._path]));
556
500
  const tsTokensPath = join(destDir, "types/css-tokens.d.ts");
557
501
  const tsVariableTokens = [...variableTokens].join("|");
502
+ const pascal = (str) => str.split(/[.\-_]/).filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
503
+ const templateVariantMapEntries = Object.entries(templateVariantMaps);
504
+ const hasVariantMaps = templateVariantMapEntries.some(([, pathMap]) => Object.keys(pathMap).length > 0);
505
+ const tsTemplateVariantMap = hasVariantMaps ? `type TemplateVariantTokens = {
506
+ ${templateVariantMapEntries.filter(([, pathMap]) => Object.keys(pathMap).length > 0).map(([templateKey, pathMap]) => {
507
+ const pathEntries = Object.entries(pathMap).map(
508
+ ([dotPath, axes]) => `'${dotPath}': { ${Object.entries(axes).map(([axis, valueType]) => `${axis}?: ${valueType}`).join("; ")} }`
509
+ ).join(";\n ");
510
+ return `${templateKey}: {
511
+ ${pathEntries}
512
+ }`;
513
+ }).join(";\n ")}
514
+ }` : `type TemplateVariantTokens = Record<string, Record<string, Record<string, never>>>;`;
515
+ const tsTemplateVariantAliases = templateVariantMapEntries.flatMap(
516
+ ([templateKey, pathMap]) => Object.keys(pathMap).map(
517
+ (dotPath) => `type ${pascal(templateKey)}${pascal(dotPath)}Variants = TemplateVariantTokens['${templateKey}']['${dotPath}'];`
518
+ )
519
+ ).join("\n ");
558
520
  const tsTokensTypes = `
559
521
  // Variable types
560
- type VariableTokens = ${tsVariableTokens || `''`};
522
+ type VariableTokens = ${tsVariableTokens || `''`};
561
523
  type PropertyValueToken = \`{\${VariableTokens}}\`;
562
-
524
+
563
525
  // Template types
564
526
  type TemplateTokens = {
565
527
  ${Object.entries(templateTokens).map(([key, value]) => `${key}?: ${value}`).join("\n")}
566
528
  }
567
-
529
+
530
+ // Template variant types (per docs/template-variants-spec.md §7)
531
+ ${tsTemplateVariantMap}
532
+ ${tsTemplateVariantAliases}
533
+
568
534
  // Media query types
569
535
  type MediaQueryKeys = ${mediaQueryKeys || `''`};
570
536
  `;
package/config/index.cjs CHANGED
@@ -6,10 +6,8 @@ const defineConfig = (config) => {
6
6
  return config;
7
7
  };
8
8
  exports.GlobalStylesFactory = factories_index.GlobalStylesFactory;
9
- exports.ImportFactory = factories_index.ImportFactory;
10
9
  exports.VariablesFactory = factories_index.VariablesFactory;
11
10
  exports.defineGlobalStyles = factories_index.defineGlobalStyles;
12
- exports.defineImport = factories_index.defineImport;
13
11
  exports.defineMediaQuery = factories_index.defineMediaQuery;
14
12
  exports.defineVariables = factories_index.defineVariables;
15
13
  exports.TemplateFactory = defineTemplates.TemplateFactory;
package/config/index.js CHANGED
@@ -1,17 +1,15 @@
1
- import { GlobalStylesFactory, ImportFactory, VariablesFactory, defineGlobalStyles, defineImport, defineMediaQuery, defineVariables } from "../factories/index.js";
1
+ import { GlobalStylesFactory, VariablesFactory, defineGlobalStyles, defineMediaQuery, defineVariables } from "../factories/index.js";
2
2
  import { T, a, d } from "../define-templates-CVhhgPnd.js";
3
3
  const defineConfig = (config) => {
4
4
  return config;
5
5
  };
6
6
  export {
7
7
  GlobalStylesFactory,
8
- ImportFactory,
9
8
  T as TemplateFactory,
10
9
  a as TemplatesFactory,
11
10
  VariablesFactory,
12
11
  defineConfig,
13
12
  defineGlobalStyles,
14
- defineImport,
15
13
  defineMediaQuery,
16
14
  d as defineTemplates,
17
15
  defineVariables
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const parseStyles = require("../parse-styles-C54MOrPg.cjs");
3
+ const parseStyles = require("../parse-styles-DxyVq07D.cjs");
4
4
  const toHash = require("../to-hash-C05Y906F.cjs");
5
5
  const cache_resolveDynamicConfigCache = require("../cache/resolve-dynamic-config-cache.cjs");
6
6
  const getDynamicStylesClassName = (styles) => {
@@ -1,4 +1,4 @@
1
- import { a as parseStyles } from "../parse-styles-CLMTHo2H.js";
1
+ import { a as parseStyles } from "../parse-styles-DSyVPjDG.js";
2
2
  import { t as toHash } from "../to-hash-DAN2LcHK.js";
3
3
  import { resolveDynamicConfigCache } from "../cache/resolve-dynamic-config-cache.js";
4
4
  const getDynamicStylesClassName = (styles) => {
package/css/keyframes.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const parseStyles = require("../parse-styles-C54MOrPg.cjs");
3
+ const parseStyles = require("../parse-styles-DxyVq07D.cjs");
4
4
  const toHash = require("../to-hash-C05Y906F.cjs");
5
5
  const keyframes = ({ animationName: _name, params: _params, appendInitialStyles, ...keyframes2 }) => {
6
6
  const modifyKeyframes = async (params = {}) => {
package/css/keyframes.js CHANGED
@@ -1,4 +1,4 @@
1
- import { p as parseAndJoinStyles } from "../parse-styles-CLMTHo2H.js";
1
+ import { p as parseAndJoinStyles } from "../parse-styles-DSyVPjDG.js";
2
2
  import { t as toHash } from "../to-hash-DAN2LcHK.js";
3
3
  const keyframes = ({ animationName: _name, params: _params, appendInitialStyles, ...keyframes2 }) => {
4
4
  const modifyKeyframes = async (params = {}) => {
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
6
3
  const css_media = require("../css/media.cjs");
7
4
  const defineTemplates = require("../define-templates-Deq1aCbN.cjs");
@@ -16,20 +13,6 @@ class GlobalStylesFactory {
16
13
  const defineGlobalStyles = (styles) => {
17
14
  return new GlobalStylesFactory(styles);
18
15
  };
19
- class ImportFactory {
20
- constructor(_current) {
21
- __publicField(this, "_path");
22
- this._current = _current;
23
- }
24
- get isDefineImport() {
25
- return true;
26
- }
27
- _setPath(path) {
28
- this._path = path;
29
- return this;
30
- }
31
- }
32
- const defineImport = (...specs) => new ImportFactory(specs);
33
16
  const defineMediaQuery = (mediaFactory) => {
34
17
  return mediaFactory(css_media.media);
35
18
  };
@@ -48,9 +31,7 @@ exports.TemplateFactory = defineTemplates.TemplateFactory;
48
31
  exports.TemplatesFactory = defineTemplates.TemplatesFactory;
49
32
  exports.defineTemplates = defineTemplates.defineTemplates;
50
33
  exports.GlobalStylesFactory = GlobalStylesFactory;
51
- exports.ImportFactory = ImportFactory;
52
34
  exports.VariablesFactory = VariablesFactory;
53
35
  exports.defineGlobalStyles = defineGlobalStyles;
54
- exports.defineImport = defineImport;
55
36
  exports.defineMediaQuery = defineMediaQuery;
56
37
  exports.defineVariables = defineVariables;