@pandacss/config 2.0.0-beta.2 → 2.0.0-beta.20

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/dist/index.js CHANGED
@@ -1,33 +1,39 @@
1
1
  import {
2
- PandaError,
3
- isPlainObject,
4
2
  mergeConfigs,
5
3
  mergeConfigsWithSources
6
- } from "./chunk-LUSBBUHX.js";
4
+ } from "./chunk-LDC4ZCDS.js";
7
5
  import {
8
6
  collectPluginHookHandlers,
9
7
  createConfigSnapshot,
10
8
  normalizeHook
11
- } from "./chunk-VYX3JX5J.js";
9
+ } from "./chunk-Y642H6DU.js";
10
+ import {
11
+ PandaError,
12
+ clone,
13
+ createConfigDiagnostic,
14
+ createConfigError,
15
+ ensureConfigObject,
16
+ errorMessage,
17
+ isPlainObject
18
+ } from "./chunk-R4R5RHIS.js";
12
19
 
13
20
  // src/load.ts
14
- import { applyConfigDefaults } from "@pandacss/compiler-shared";
21
+ import { applyConfigDefaults as applyConfigDefaults2 } from "@pandacss/compiler-shared";
15
22
 
16
23
  // src/bundle.ts
17
- import { existsSync, realpathSync } from "fs";
18
- import { mkdir, unlink, writeFile } from "fs/promises";
19
- import { builtinModules } from "module";
20
- import { tmpdir } from "os";
21
- import { dirname, isAbsolute as isAbsolute2, join, normalize, relative } from "path";
22
- import { pathToFileURL as pathToFileURL2 } from "url";
23
- import { rolldown } from "rolldown";
24
+ import { existsSync, realpathSync } from "node:fs";
25
+ import { mkdir, unlink, writeFile } from "node:fs/promises";
26
+ import { builtinModules } from "node:module";
27
+ import { tmpdir } from "node:os";
28
+ import { basename, dirname, isAbsolute as isAbsolute2, join, normalize, relative } from "node:path";
29
+ import { pathToFileURL as pathToFileURL2 } from "node:url";
24
30
 
25
31
  // src/bundle-plugins.ts
26
32
  import { parse } from "acorn";
27
33
  import { simple } from "acorn-walk";
28
34
  import MagicString from "magic-string";
29
- import { isAbsolute } from "path";
30
- import { pathToFileURL } from "url";
35
+ import { isAbsolute } from "node:path";
36
+ import { pathToFileURL } from "node:url";
31
37
  function importMetaUrlPlugin() {
32
38
  return {
33
39
  name: "panda-import-meta-url",
@@ -71,6 +77,7 @@ function isNode(value, type) {
71
77
  // src/bundle.ts
72
78
  var nodeBuiltins = /* @__PURE__ */ new Set([...builtinModules, ...builtinModules.map((mod) => `node:${mod}`)]);
73
79
  async function bundleConfig(filepath, cwd) {
80
+ const { rolldown } = await import("rolldown");
74
81
  const build = await rolldown({
75
82
  input: filepath,
76
83
  cwd,
@@ -98,6 +105,7 @@ async function bundleConfig(filepath, cwd) {
98
105
  }
99
106
  async function loadBundledModule(filepath, code) {
100
107
  const target = tempTargetFor(filepath);
108
+ let evalError;
101
109
  if (target) {
102
110
  try {
103
111
  await mkdir(dirname(target), { recursive: true });
@@ -110,14 +118,23 @@ async function loadBundledModule(filepath, code) {
110
118
  } finally {
111
119
  void unlink(target).catch(() => void 0);
112
120
  }
113
- } catch {
121
+ } catch (error) {
122
+ if (!isUnresolvedTempModule(error, target)) evalError = error;
114
123
  }
115
124
  }
116
125
  const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString("base64")}`;
117
- return await import(
118
- /* @vite-ignore */
119
- dataUrl
120
- );
126
+ try {
127
+ return await import(
128
+ /* @vite-ignore */
129
+ dataUrl
130
+ );
131
+ } catch (error) {
132
+ throw evalError ?? error;
133
+ }
134
+ }
135
+ function isUnresolvedTempModule(error, target) {
136
+ const message = error instanceof Error ? error.message : "";
137
+ return message.includes("Cannot find module") && message.includes(basename(target));
121
138
  }
122
139
  function tempTargetFor(filepath) {
123
140
  const unique = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
@@ -161,8 +178,8 @@ function canonical(filepath) {
161
178
  }
162
179
 
163
180
  // src/find.ts
164
- import { readdirSync } from "fs";
165
- import { dirname as dirname2, resolve } from "path";
181
+ import { readdirSync } from "node:fs";
182
+ import { dirname as dirname2, resolve } from "node:path";
166
183
  var configFiles = /* @__PURE__ */ new Set([
167
184
  "panda.config.ts",
168
185
  "panda.config.js",
@@ -206,11 +223,11 @@ function findConfig(options) {
206
223
  // src/hook-utils.ts
207
224
  var configResolvedUtils = {
208
225
  omit(obj, paths) {
209
- const clone = cloneValue(obj);
226
+ const next = clone(obj);
210
227
  for (const path of paths) {
211
- deleteAtPath(clone, path);
228
+ deleteAtPath(next, path);
212
229
  }
213
- return clone;
230
+ return next;
214
231
  },
215
232
  pick(obj, paths) {
216
233
  const result = {};
@@ -226,23 +243,6 @@ var configResolvedUtils = {
226
243
  traverseValue(obj, callback, options);
227
244
  }
228
245
  };
229
- function cloneValue(value) {
230
- if (Array.isArray(value)) {
231
- const len = value.length;
232
- const out2 = new Array(len);
233
- for (let i = 0; i < len; i++) out2[i] = cloneValue(value[i]);
234
- return out2;
235
- }
236
- if (!isPlainObject(value)) return value;
237
- const source = value;
238
- const out = {};
239
- const keys = Object.keys(source);
240
- for (let i = 0; i < keys.length; i++) {
241
- const key = keys[i];
242
- out[key] = cloneValue(source[key]);
243
- }
244
- return out;
245
- }
246
246
  function pathParts(path) {
247
247
  return path.split(".").filter(Boolean);
248
248
  }
@@ -259,7 +259,7 @@ function setAtPath(target, path, value) {
259
259
  let current = target;
260
260
  parts.forEach((part, index) => {
261
261
  if (index === parts.length - 1) {
262
- current[part] = cloneValue(value);
262
+ current[part] = clone(value);
263
263
  return;
264
264
  }
265
265
  const next = current[part];
@@ -307,56 +307,985 @@ function traverseValue(value, callback, options, parent, key, path = "", depth =
307
307
  function joinPath(parent, key, separator) {
308
308
  return parent ? `${parent}${separator}${key}` : key;
309
309
  }
310
+ function attachRuntimeHooks(config, configs) {
311
+ const plugins = configs.flatMap((item) => {
312
+ if ("hooks" in item && item.hooks != null) {
313
+ const message = '`config.hooks` was removed in v2. Use `plugins: [{ name: "local", hooks: { ... } }]` instead.';
314
+ throw createConfigError(message, [
315
+ createConfigDiagnostic("config_hooks_removed", message, [
316
+ 'Move root `hooks` into `plugins: [{ name: "local", hooks: { ... } }]`.'
317
+ ])
318
+ ]);
319
+ }
320
+ return [...item.plugins ?? [], ...item.extend?.plugins ?? []];
321
+ });
322
+ for (const plugin of plugins) {
323
+ if (!isPlainObject(plugin) || typeof plugin.name !== "string" || plugin.name.length === 0) {
324
+ throw new PandaError(
325
+ "CONFIG_ERROR",
326
+ "\u{1F4A5} Every plugin in `config.plugins` must be an object with a non-empty `name`."
327
+ );
328
+ }
329
+ }
330
+ if (plugins.length > 0) {
331
+ config.plugins = plugins;
332
+ }
333
+ return config;
334
+ }
335
+
336
+ // src/design-system/overlay-input.ts
337
+ import { applyConfigDefaults } from "@pandacss/compiler-shared";
338
+
339
+ // src/normalize.ts
340
+ var CLASS_NAME_OPTION_KEYS = ["hash", "prefix", "separator"];
341
+ function normalizeClassNameOptions(config) {
342
+ return {
343
+ hash: normalizeHash(config.hash),
344
+ prefix: normalizePrefix(config.prefix),
345
+ separator: config.separator ?? "_"
346
+ };
347
+ }
348
+ function diffClassNameOptions(consumer, designSystem, scope) {
349
+ const normalized = normalizeClassNameOptions(consumer);
350
+ return CLASS_NAME_OPTION_KEYS.filter((key) => {
351
+ if (scope === "explicit" && consumer[key] === void 0) {
352
+ return false;
353
+ }
354
+ if (key === "separator") {
355
+ return normalized.separator !== designSystem.separator;
356
+ }
357
+ return normalized[key].cssVar !== designSystem[key].cssVar || normalized[key].className !== designSystem[key].className;
358
+ });
359
+ }
360
+ function normalizeHash(value) {
361
+ if (typeof value === "boolean") {
362
+ return { cssVar: value, className: value };
363
+ }
364
+ if (value && typeof value === "object") {
365
+ return { cssVar: value.cssVar === true, className: value.className === true };
366
+ }
367
+ return { cssVar: false, className: false };
368
+ }
369
+ function normalizePrefix(value) {
370
+ if (typeof value === "string") {
371
+ return { cssVar: value, className: value };
372
+ }
373
+ if (value && typeof value === "object") {
374
+ return { cssVar: value.cssVar ?? "", className: value.className ?? "" };
375
+ }
376
+ return { cssVar: "", className: "" };
377
+ }
378
+
379
+ // src/design-system/overlay-input.ts
380
+ var CLASS_NAME_OPTION_KEYS2 = ["hash", "prefix", "separator"];
381
+ var RUNTIME_OPTION_KEYS = [
382
+ ...CLASS_NAME_OPTION_KEYS2,
383
+ "jsxFramework",
384
+ "jsxFactory",
385
+ "jsxStyleProps",
386
+ "strictTokens",
387
+ "strictPropertyValues",
388
+ "shorthands"
389
+ ];
390
+ function designSystemSourceIds(chain) {
391
+ const ids = /* @__PURE__ */ new Set();
392
+ for (const ds of chain) {
393
+ ids.add(ds.name);
394
+ ids.add(ds.specifier);
395
+ }
396
+ return ids;
397
+ }
398
+ function authoredByApp(sources, prefix, dsIds) {
399
+ return Object.entries(sources.paths).some(([path, ids]) => {
400
+ if (path !== prefix && !path.startsWith(`${prefix}.`)) return false;
401
+ const idList = Array.isArray(ids) ? ids : [ids];
402
+ return idList.some((id) => isAppSource(sources.entries[id], dsIds));
403
+ });
404
+ }
405
+ function isAppSource(entry, dsIds) {
406
+ if (!entry) return false;
407
+ if (entry.kind === "config") return true;
408
+ if (entry.kind !== "preset") return false;
409
+ return entry.specifier === void 0 || !dsIds.has(entry.specifier);
410
+ }
411
+ function buildOverlayInput(sources, appConfig, chain, leafPreset, cwd) {
412
+ const dsIds = designSystemSourceIds(chain);
413
+ const authored = {
414
+ conditions: authoredByApp(sources, "conditions", dsIds),
415
+ breakpoints: authoredByApp(sources, "theme.breakpoints", dsIds),
416
+ utilities: authoredByApp(sources, "utilities", dsIds),
417
+ tokens: authoredByApp(sources, "theme.tokens", dsIds) || authoredByApp(sources, "theme.semanticTokens", dsIds)
418
+ };
419
+ const mismatches = diffRuntimeOptions(appConfig, leafPreset, sources, dsIds, cwd);
420
+ return { authored, compatible: mismatches.length === 0 };
421
+ }
422
+ function diffRuntimeOptions(appConfig, leafPreset, sources, dsIds, cwd) {
423
+ const app = applyConfigDefaults({ ...appConfig }, cwd);
424
+ const ds = applyConfigDefaults({ ...leafPreset }, cwd);
425
+ const appClass = normalizeClassNameOptions(app);
426
+ const dsClass = normalizeClassNameOptions(ds);
427
+ return RUNTIME_OPTION_KEYS.filter((key) => {
428
+ if (!authoredByApp(sources, key, dsIds)) return false;
429
+ if (key === "hash" || key === "prefix" || key === "separator") {
430
+ if (key === "separator") return appClass.separator !== dsClass.separator;
431
+ return appClass[key].cssVar !== dsClass[key].cssVar || appClass[key].className !== dsClass[key].className;
432
+ }
433
+ return JSON.stringify(app[key]) !== JSON.stringify(ds[key]);
434
+ });
435
+ }
310
436
 
311
437
  // src/preset.ts
312
- import { normalize as normalize2, relative as relative2 } from "path";
313
- async function resolveAuthoredPresets(config, cwd, options = {}) {
438
+ import { normalize as normalize2, relative as relative5 } from "node:path";
439
+
440
+ // src/design-system/chain.ts
441
+ import {
442
+ outdirBasename
443
+ } from "@pandacss/compiler-shared";
444
+ import { readFileSync as readFileSync2, statSync } from "node:fs";
445
+ import { dirname as dirname4, resolve as resolve4 } from "node:path";
446
+ import { pathToFileURL as pathToFileURL3 } from "node:url";
447
+
448
+ // src/resolve.ts
449
+ import { createRequire } from "node:module";
450
+ import { resolve as resolve2 } from "node:path";
451
+ function tryResolveFrom(request, fromDir) {
452
+ try {
453
+ return createRequire(resolve2(fromDir, "noop.js")).resolve(request, { paths: [fromDir] });
454
+ } catch (error) {
455
+ if (isResolveMiss(error)) return void 0;
456
+ throw error;
457
+ }
458
+ }
459
+ function isResolveMiss(error) {
460
+ const code = errorCode(error);
461
+ return code === "MODULE_NOT_FOUND" || code === "ERR_PACKAGE_PATH_NOT_EXPORTED";
462
+ }
463
+ function resolveFrom(request, fromDir) {
464
+ try {
465
+ return { kind: "resolved", path: createRequire(resolve2(fromDir, "noop.js")).resolve(request, { paths: [fromDir] }) };
466
+ } catch (error) {
467
+ const code = errorCode(error);
468
+ if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED") return { kind: "not-exported" };
469
+ if (code === "MODULE_NOT_FOUND") return { kind: "not-installed" };
470
+ throw error;
471
+ }
472
+ }
473
+ function errorCode(error) {
474
+ return typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
475
+ }
476
+
477
+ // src/design-system/package.ts
478
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
479
+ import { dirname as dirname3, join as join2 } from "node:path";
480
+
481
+ // src/design-system/publishable-files.ts
482
+ import { relative as relative3, resolve as resolve3 } from "node:path";
483
+
484
+ // src/paths.ts
485
+ import { isAbsolute as isAbsolute3, relative as relative2 } from "node:path";
486
+ function toPosixPath(path) {
487
+ return path.includes("\\") ? path.split("\\").join("/") : path;
488
+ }
489
+ function toPosixRelative(from, to) {
490
+ const rel = toPosixPath(relative2(from, to));
491
+ return rel.startsWith(".") ? rel : `./${rel}`;
492
+ }
493
+ function toRelativeKey(key, cwd) {
494
+ return toPosixPath(isAbsolute3(key) ? relative2(cwd, key) : key);
495
+ }
496
+
497
+ // src/design-system/publishable-files.ts
498
+ var GLOB_START = /[*?{]/;
499
+ var HAS_WILDCARD = /[*?]/;
500
+ var TRAILING_SLASH = /\/$/;
501
+ var REGEX_META = /[.+^${}()|[\]\\]/g;
502
+ var GLOBSTAR = /\*\*/g;
503
+ var GLOB_STAR = /\*/g;
504
+ var GLOB_QMARK = /\?/g;
505
+ var GLOBSTAR_TOKEN = /<<<DS>>>/g;
506
+ function filterPublishableLibFiles(options) {
507
+ const { files, packageRoot, outRoot, publishFiles } = options;
508
+ if (!publishFiles?.length) {
509
+ return { files, unpublished: [] };
510
+ }
511
+ const rules = compilePackageFilesRules(publishFiles);
512
+ const kept = [];
513
+ const unpublished = [];
514
+ for (const file of files) {
515
+ const packageRelative = libFileToPackageRelative(file, packageRoot, outRoot);
516
+ if (packageRelative !== void 0 && matchesCompiledRules(packageRelative, rules)) {
517
+ kept.push(file);
518
+ } else {
519
+ unpublished.push(file);
520
+ }
521
+ }
522
+ return { files: kept, unpublished };
523
+ }
524
+ function readPublishFilesField(value) {
525
+ if (!Array.isArray(value) || value.length === 0) return void 0;
526
+ for (const entry of value) {
527
+ if (typeof entry !== "string") return void 0;
528
+ }
529
+ return value;
530
+ }
531
+ function libFileToPackageRelative(file, packageRoot, outRoot) {
532
+ const normalized = toPosixPath(file);
533
+ const withoutDot = normalized.startsWith("./") ? normalized.slice(2) : normalized;
534
+ const globAt = withoutDot.search(GLOB_START);
535
+ const literalPrefix = globAt === -1 ? withoutDot : withoutDot.slice(0, globAt);
536
+ const abs = resolve3(outRoot, literalPrefix || ".");
537
+ const rel = toPosixPath(relative3(packageRoot, abs));
538
+ if (rel === "") return "";
539
+ if (rel.startsWith("..")) return void 0;
540
+ return rel;
541
+ }
542
+ function compilePackageFilesRules(patterns) {
543
+ const rules = [];
544
+ for (const raw of patterns) {
545
+ const negated = raw.startsWith("!");
546
+ const pattern = toPosixPath(negated ? raw.slice(1) : raw);
547
+ const normalized = pattern.startsWith("./") ? pattern.slice(2) : pattern;
548
+ if (!normalized) continue;
549
+ if (!HAS_WILDCARD.test(normalized)) {
550
+ rules.push({ kind: "prefix", negated, value: normalized.replace(TRAILING_SLASH, "") });
551
+ continue;
552
+ }
553
+ const escaped = normalized.replace(REGEX_META, "\\$&").replace(GLOBSTAR, "<<<DS>>>").replace(GLOB_STAR, "[^/]*").replace(GLOB_QMARK, "[^/]").replace(GLOBSTAR_TOKEN, ".*");
554
+ rules.push({ kind: "regex", negated, value: new RegExp(`^${escaped}(?:/.*)?$`) });
555
+ }
556
+ return rules;
557
+ }
558
+ function matchesCompiledRules(packageRelativePath, rules) {
559
+ const path = packageRelativePath.startsWith("./") ? packageRelativePath.slice(2) : packageRelativePath;
560
+ let included = false;
561
+ for (const rule of rules) {
562
+ const hit = rule.kind === "prefix" ? path === rule.value || path.startsWith(`${rule.value}/`) : rule.value.test(path);
563
+ if (!hit) continue;
564
+ included = !rule.negated;
565
+ }
566
+ return included;
567
+ }
568
+
569
+ // src/design-system/package.ts
570
+ var PACKAGE_MANAGER_RANGE_PATTERN = /^(?:workspace|catalog):/;
571
+ var PORTABLE_WORKSPACE_RANGE_PATTERN = /^[~^]?\d/;
572
+ var VERSION_CORE_PATTERN = /^(\d+)\.(\d+)\.(\d+)/;
573
+ function resolvePublishedPandaRange(range, currentVersion) {
574
+ const authored = range?.trim();
575
+ if (!authored) return "*";
576
+ if (authored.startsWith("npm:")) {
577
+ return resolveNpmAliasRange(authored) ?? portableRangeFromInstalled(currentVersion, "^");
578
+ }
579
+ if (!PACKAGE_MANAGER_RANGE_PATTERN.test(authored)) return authored;
580
+ if (authored.startsWith("workspace:")) {
581
+ const workspaceRange = authored.slice("workspace:".length);
582
+ if (PORTABLE_WORKSPACE_RANGE_PATTERN.test(workspaceRange)) return workspaceRange;
583
+ }
584
+ const operator = authored === "workspace:~" ? "~" : "^";
585
+ return portableRangeFromInstalled(currentVersion, operator);
586
+ }
587
+ function resolveNpmAliasRange(spec) {
588
+ const at = spec.lastIndexOf("@");
589
+ if (at <= "npm:".length) return void 0;
590
+ return spec.slice(at + 1);
591
+ }
592
+ function portableRangeFromInstalled(currentVersion, operator) {
593
+ const core = currentVersion?.match(VERSION_CORE_PATTERN)?.[0];
594
+ return core ? `${operator}${core}` : "*";
595
+ }
596
+ function readPackageIdentity(cwd) {
597
+ const packagePath = nearestPackageJson(cwd);
598
+ if (packagePath === void 0) {
599
+ throw new Error(`Could not find a package.json from ${JSON.stringify(cwd)} to build the design system manifest.`);
600
+ }
601
+ const pkg = JSON.parse(readFileSync(packagePath, "utf8"));
602
+ const name = pkg.name;
603
+ if (typeof name !== "string" || name.length === 0) {
604
+ throw new Error(`${JSON.stringify(packagePath)} has no "name"; a design system must be a named package.`);
605
+ }
606
+ const peer = pkg.peerDependencies?.["@pandacss/dev"];
607
+ return {
608
+ name,
609
+ version: typeof pkg.version === "string" ? pkg.version : void 0,
610
+ pandaPeer: typeof peer === "string" ? peer : void 0,
611
+ packagePath,
612
+ publishFiles: readPublishFilesField(pkg.files)
613
+ };
614
+ }
615
+ function defaultImportMap(name) {
616
+ return {
617
+ css: `${name}/css`,
618
+ recipes: `${name}/recipes`,
619
+ patterns: `${name}/patterns`,
620
+ jsx: `${name}/jsx`,
621
+ tokens: `${name}/tokens`
622
+ };
623
+ }
624
+ function syncExports(options) {
625
+ const { packageJson, entries } = options;
626
+ const pkg = JSON.parse(packageJson);
627
+ const existing = normalizeExports(pkg.exports);
628
+ const merged = { ...existing };
629
+ const conflicts = [];
630
+ for (const [key, value] of Object.entries(entries)) {
631
+ if (key in merged && !exportsValueEqual(merged[key], value)) {
632
+ conflicts.push(key);
633
+ }
634
+ merged[key] = value;
635
+ }
636
+ const changed = JSON.stringify(pkg.exports) !== JSON.stringify(merged);
637
+ const out = { ...pkg, exports: merged };
638
+ return { changed, json: `${JSON.stringify(out, null, 2)}
639
+ `, conflicts };
640
+ }
641
+ function exportsValueEqual(left, right) {
642
+ return JSON.stringify(left) === JSON.stringify(right);
643
+ }
644
+ function normalizeExports(exports) {
645
+ if (exports === void 0) return {};
646
+ if (typeof exports === "string") return { ".": exports };
647
+ if (Array.isArray(exports)) return { ".": exports };
648
+ if (!isPlainObject(exports)) return {};
649
+ if (isSubpathExportMap(exports)) return exports;
650
+ return { ".": exports };
651
+ }
652
+ function isSubpathExportMap(exports) {
653
+ return Object.keys(exports).some((key) => key === "." || key.startsWith("./"));
654
+ }
655
+ function nearestPackageJson(start) {
656
+ let current = start;
657
+ while (true) {
658
+ const candidate = join2(current, "package.json");
659
+ if (existsSync2(candidate)) return candidate;
660
+ const parent = dirname3(current);
661
+ if (parent === current) return void 0;
662
+ current = parent;
663
+ }
664
+ }
665
+
666
+ // src/design-system/chain.ts
667
+ var SPECIFIER_PROTOCOL = /^([a-z][a-z0-9+.-]*):/i;
668
+ async function loadDesignSystemChain(spec, cwd, deps) {
669
+ const levels = [];
670
+ const seenAt = /* @__PURE__ */ new Map();
671
+ const seenNames = /* @__PURE__ */ new Map();
672
+ let currentSpec = spec;
673
+ let fromDir = cwd;
674
+ let declaredBy;
675
+ while (true) {
676
+ const manifestPath = resolveManifestPath(currentSpec, fromDir);
677
+ if (manifestPath === void 0) {
678
+ throw declaredBy === void 0 ? notResolvedError(currentSpec) : parentNotResolvedError(declaredBy, currentSpec);
679
+ }
680
+ const seen = seenAt.get(manifestPath);
681
+ if (seen !== void 0) {
682
+ throw cycleError([...levels.slice(seen).map((level2) => level2.info.name), levels[seen].info.name]);
683
+ }
684
+ seenAt.set(manifestPath, levels.length);
685
+ deps.add(manifestPath);
686
+ const { level, parent } = await loadManifestLevel(currentSpec, manifestPath, deps);
687
+ const priorPath = seenNames.get(level.info.name);
688
+ if (priorPath !== void 0 && priorPath !== manifestPath) {
689
+ throw duplicateNameError(level.info.name, priorPath, manifestPath);
690
+ }
691
+ seenNames.set(level.info.name, manifestPath);
692
+ levels.push(level);
693
+ if (parent === void 0) break;
694
+ declaredBy = level.info.name;
695
+ fromDir = dirname4(manifestPath);
696
+ currentSpec = parent;
697
+ }
698
+ return levels.reverse();
699
+ }
700
+ function withDesignSystemImportMap(config, infos) {
701
+ const existing = config.importMap === void 0 ? [] : Array.isArray(config.importMap) ? config.importMap : [config.importMap];
702
+ const roots = infos.map(
703
+ (info) => info.importMap ? designSystemImportMap(info.importMap, info.specifier) : info.specifier
704
+ );
705
+ return { ...config, importMap: [...roots, outdirBasename(config.outdir ?? "styled-system"), ...existing] };
706
+ }
707
+ function buildCodegenOverlay(metadata) {
708
+ const chain = metadata?.designSystem;
709
+ if (!chain || chain.length !== 1) return void 0;
710
+ if (metadata?.overlayInput && !metadata.overlayInput.compatible) return void 0;
711
+ const [ds] = chain;
712
+ const appRecipes = new Set(metadata?.userRecipeNames ?? []);
713
+ const appPatterns = new Set(metadata?.userPatternNames ?? []);
714
+ const authored = metadata?.overlayInput?.authored;
715
+ const runtimeDirty = !!(authored?.conditions || authored?.breakpoints || authored?.utilities || authored?.tokens);
716
+ return {
717
+ ...overlayRoots(ds),
718
+ ownedRecipes: ds.recipeNames.filter((name) => !appRecipes.has(name)),
719
+ ownedPatterns: ds.patternNames.filter((name) => !appPatterns.has(name)),
720
+ virtualizeHelpers: true,
721
+ virtualizeCss: !runtimeDirty
722
+ };
723
+ }
724
+ function collectArtifactConflicts(metadata) {
725
+ const appRecipes = new Set(metadata?.userRecipeNames ?? []);
726
+ const appPatterns = new Set(metadata?.userPatternNames ?? []);
727
+ return (metadata?.designSystem ?? []).map((ds) => ({
728
+ name: ds.name,
729
+ recipes: ds.recipeNames.filter((name) => appRecipes.has(name)),
730
+ patterns: ds.patternNames.filter((name) => appPatterns.has(name))
731
+ })).filter((entry) => entry.recipes.length > 0 || entry.patterns.length > 0);
732
+ }
733
+ function collectExportMissingDiagnostics(metadata) {
734
+ const overlay = buildCodegenOverlay(metadata);
735
+ if (!overlay) return [];
736
+ const [ds] = metadata.designSystem;
737
+ const required = [];
738
+ if (overlay.virtualizeHelpers) required.push("./helpers");
739
+ if (overlay.virtualizeCss) {
740
+ required.push("./css", "./css/*");
741
+ }
742
+ if (overlay.ownedRecipes.length > 0) {
743
+ required.push("./recipes", "./recipes/*");
744
+ }
745
+ if (overlay.ownedPatterns.length > 0) {
746
+ required.push("./patterns", "./patterns/*");
747
+ }
748
+ const appPatterns = metadata?.userPatternNames?.length ?? 0;
749
+ const dsPatterns = ds.patternNames?.length ?? 0;
750
+ if (overlay.ownedPatterns.length > 0 || overlay.virtualizeCss && (appPatterns > 0 || dsPatterns > 0)) {
751
+ required.push("./jsx", "./jsx/*");
752
+ }
753
+ return required.filter((subpath) => !hasExport(ds.packageExports, subpath)).map((subpath) => exportMissingDiagnostic(ds.name, subpath));
754
+ }
755
+ function collectNameCollisionDiagnostics(metadata) {
756
+ const overlay = buildCodegenOverlay(metadata);
757
+ if (!overlay) return [];
758
+ return [
759
+ ...identCollisions("recipe", [...overlay.ownedRecipes, ...metadata?.userRecipeNames ?? []]),
760
+ ...identCollisions("pattern", [...overlay.ownedPatterns, ...metadata?.userPatternNames ?? []])
761
+ ];
762
+ }
763
+ function jsIdent(value) {
764
+ let out = "";
765
+ for (let i = 0; i < value.length; i++) {
766
+ const code = value.charCodeAt(i);
767
+ const isIdent = code === 36 || // $
768
+ code === 95 || // _
769
+ code >= 48 && code <= 57 || // 0-9
770
+ code >= 65 && code <= 90 || // A-Z
771
+ code >= 97 && code <= 122;
772
+ if (isIdent) {
773
+ if (i === 0 && code >= 48 && code <= 57) out += "_";
774
+ out += value[i];
775
+ } else {
776
+ out += "_";
777
+ }
778
+ }
779
+ return out === "" ? "_" : out;
780
+ }
781
+ function identCollisions(kind, names) {
782
+ const byIdent = /* @__PURE__ */ new Map();
783
+ for (const name of names) {
784
+ const ident = jsIdent(name);
785
+ const set = byIdent.get(ident) ?? /* @__PURE__ */ new Set();
786
+ set.add(name);
787
+ byIdent.set(ident, set);
788
+ }
789
+ const collisions = [];
790
+ for (const [ident, raw] of byIdent) {
791
+ if (raw.size < 2) continue;
792
+ const list = [...raw].map((name) => JSON.stringify(name)).join(", ");
793
+ const message = `${kind} names ${list} both generate the export ${JSON.stringify(ident)}; one would overwrite the other in the generated barrel. Rename one so they produce distinct identifiers.`;
794
+ collisions.push(createConfigDiagnostic("design_system_name_collision", message));
795
+ }
796
+ return collisions;
797
+ }
798
+ function hasExport(packageExports, subpath) {
799
+ return packageExports != null && Object.prototype.hasOwnProperty.call(packageExports, subpath);
800
+ }
801
+ function exportMissingDiagnostic(dsName, subpath) {
802
+ const message = `designSystem ${JSON.stringify(dsName)} doesn't export ${JSON.stringify(subpath)}, which this app's codegen needs. Rebuild it with \`panda lib\`.`;
803
+ return createConfigDiagnostic("design_system_export_missing", message, [
804
+ `Rebuild ${JSON.stringify(dsName)} with \`panda lib\` to add the ${JSON.stringify(subpath)} export.`
805
+ ]);
806
+ }
807
+ function overlayRoots(ds) {
808
+ const map = ds.importMap;
809
+ const root = (value, subpath) => {
810
+ const resolved = Array.isArray(value) ? value[0] : value;
811
+ return resolved ?? `${ds.specifier}/${subpath}`;
812
+ };
813
+ return {
814
+ jsx: root(map?.jsx, "jsx"),
815
+ recipes: root(map?.recipes, "recipes"),
816
+ patterns: root(map?.patterns, "patterns"),
817
+ css: root(map?.css, "css"),
818
+ helpers: `${ds.specifier}/helpers`
819
+ };
820
+ }
821
+ function resolveManifestPath(spec, fromDir) {
822
+ const protocol = specifierProtocol(spec);
823
+ if (protocol) throw unsupportedSpecifierError(spec, protocol);
824
+ let outcome;
825
+ try {
826
+ outcome = resolveFrom(`${spec}/panda/lib.json`, fromDir);
827
+ } catch (error) {
828
+ const message = `Failed to resolve designSystem ${JSON.stringify(spec)} from ${JSON.stringify(fromDir)}: ${errorMessage(error)}`;
829
+ throw createConfigError(message, [createConfigDiagnostic("design_system_resolve_failed", message)]);
830
+ }
831
+ if (outcome.kind === "resolved") return outcome.path;
832
+ if (outcome.kind === "not-exported") throw manifestNotExportedError(spec);
833
+ return void 0;
834
+ }
835
+ function manifestNotExportedError(spec) {
836
+ const message = `designSystem ${JSON.stringify(spec)} is installed but doesn't expose \`./panda/*\` (missing \`panda/lib.json\`). If it's a Panda design system, rebuild it with \`panda lib\`; otherwise it can't be consumed as a design system.`;
837
+ return createConfigError(message, [
838
+ createConfigDiagnostic("design_system_manifest_not_exported", message, [
839
+ `Rebuild ${JSON.stringify(spec)} with \`panda lib\`, or check its package.json \`exports\` includes \`./panda/*\`.`
840
+ ])
841
+ ]);
842
+ }
843
+ async function loadManifestLevel(spec, manifestPath, deps) {
844
+ let parsed;
845
+ try {
846
+ parsed = JSON.parse(readFileSync2(manifestPath, "utf8"));
847
+ } catch (error) {
848
+ const message = `Failed to parse ${JSON.stringify(manifestPath)} as JSON: ${errorMessage(error)}. This file must be generated by \`panda lib\`, not hand-written or added to \`include\`.`;
849
+ throw createConfigError(message, [
850
+ { ...createConfigDiagnostic("design_system_manifest_invalid", message), file: manifestPath }
851
+ ]);
852
+ }
853
+ const manifest = validateManifest(spec, manifestPath, parsed);
854
+ const presetPath = resolve4(dirname4(manifestPath), manifest.preset);
855
+ const buildInfoPath = resolve4(dirname4(manifestPath), manifest.buildInfo);
856
+ deps.add(presetPath);
857
+ deps.add(buildInfoPath);
858
+ let preset;
859
+ try {
860
+ const mod = await import(presetImportUrl(presetPath));
861
+ preset = ensureConfigObject("default" in mod ? mod.default : mod, manifest.name ?? spec);
862
+ } catch (error) {
863
+ if (error instanceof PandaError && error.diagnostics?.length) throw error;
864
+ const message = `Failed to load the preset for designSystem ${JSON.stringify(spec)} (${JSON.stringify(manifest.preset)}): ${errorMessage(error)}`;
865
+ throw createConfigError(message, [
866
+ createConfigDiagnostic("design_system_preset_load_failed", message, [
867
+ `Check that ${JSON.stringify(manifest.preset)} is valid and rebuild ${JSON.stringify(spec)} with \`panda lib\`.`
868
+ ])
869
+ ]);
870
+ }
871
+ const parent = typeof manifest.designSystem === "string" && manifest.designSystem.length > 0 ? manifest.designSystem : void 0;
872
+ const packageExports = readPackageExports(manifestPath);
873
+ return {
874
+ parent,
875
+ level: {
876
+ preset,
877
+ info: {
878
+ name: manifest.name ?? spec,
879
+ specifier: spec,
880
+ manifest,
881
+ manifestPath,
882
+ buildInfoPath,
883
+ files: manifest.files ?? [],
884
+ tokenPaths: [],
885
+ recipeNames: [],
886
+ patternNames: [],
887
+ ...manifest.importMap ? { importMap: manifest.importMap } : {},
888
+ ...packageExports ? { packageExports } : {}
889
+ }
890
+ }
891
+ };
892
+ }
893
+ function readPackageExports(manifestPath) {
894
+ try {
895
+ const packageJsonPath = nearestPackageJson(dirname4(manifestPath));
896
+ if (packageJsonPath === void 0) return void 0;
897
+ const pkg = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
898
+ return isExportsMap(pkg.exports) ? pkg.exports : void 0;
899
+ } catch {
900
+ return void 0;
901
+ }
902
+ }
903
+ function isExportsMap(value) {
904
+ return typeof value === "object" && value !== null && !Array.isArray(value);
905
+ }
906
+ function presetImportUrl(path) {
907
+ const url = pathToFileURL3(path);
908
+ url.searchParams.set("mtime", String(statSync(path).mtimeMs));
909
+ return url.href;
910
+ }
911
+ function designSystemImportMap(map, spec) {
912
+ return {
913
+ css: map.css ?? `${spec}/css`,
914
+ recipes: map.recipes ?? `${spec}/recipes`,
915
+ patterns: map.patterns ?? `${spec}/patterns`,
916
+ jsx: map.jsx ?? `${spec}/jsx`,
917
+ tokens: map.tokens ?? `${spec}/tokens`
918
+ };
919
+ }
920
+ var IMPORT_MAP_FIELDS = ["css", "recipes", "patterns", "jsx", "tokens"];
921
+ function validateManifest(spec, manifestPath, value) {
922
+ if (!isPlainObject(value)) {
923
+ throw invalidManifestError(spec, manifestPath, ["must contain a JSON object"]);
924
+ }
925
+ const issues = [];
926
+ requiredString(value, "name", issues);
927
+ requiredString(value, "panda", issues);
928
+ requiredString(value, "preset", issues);
929
+ requiredString(value, "buildInfo", issues);
930
+ if (!Number.isInteger(value.schemaVersion) || value.schemaVersion < 1) {
931
+ issues.push('must contain a positive integer "schemaVersion" entry');
932
+ }
933
+ if (value.version !== void 0 && typeof value.version !== "string") {
934
+ issues.push('has a "version" entry that must be a string');
935
+ }
936
+ if (value.designSystem !== void 0 && !isNonEmptyString(value.designSystem)) {
937
+ issues.push('has a "designSystem" entry that must be a non-empty string');
938
+ }
939
+ if (value.files !== void 0 && (!Array.isArray(value.files) || !value.files.every((file) => isNonEmptyString(file)))) {
940
+ issues.push('has a "files" entry that must be an array of non-empty strings');
941
+ }
942
+ if (value.importMap !== void 0) {
943
+ if (!isPlainObject(value.importMap)) {
944
+ issues.push('has an "importMap" entry that must be an object');
945
+ } else {
946
+ for (const field of IMPORT_MAP_FIELDS) {
947
+ const entry = value.importMap[field];
948
+ if (entry !== void 0 && !isNonEmptyString(entry)) {
949
+ issues.push(`has an "importMap.${field}" entry that must be a non-empty string`);
950
+ }
951
+ }
952
+ }
953
+ }
954
+ if (issues.length > 0) {
955
+ throw invalidManifestError(spec, manifestPath, issues);
956
+ }
957
+ return value;
958
+ }
959
+ function requiredString(value, field, issues) {
960
+ if (!isNonEmptyString(value[field])) {
961
+ issues.push(`is missing a "${field}" entry or it is empty`);
962
+ }
963
+ }
964
+ function isNonEmptyString(value) {
965
+ return typeof value === "string" && value.trim().length > 0;
966
+ }
967
+ function notResolvedError(spec) {
968
+ const message = `designSystem ${JSON.stringify(spec)} could not be resolved. Install it, or \u2014 if it isn't a Panda design system \u2014 build it with \`panda lib\`.`;
969
+ return createConfigError(message, [
970
+ createConfigDiagnostic("design_system_manifest_not_found", message, [
971
+ `Install ${JSON.stringify(spec)}, or build it with \`panda lib\` if it is a Panda design system.`
972
+ ])
973
+ ]);
974
+ }
975
+ function parentNotResolvedError(child, parent) {
976
+ const message = `designSystem ${JSON.stringify(child)} extends ${JSON.stringify(parent)}, which isn't installed alongside it. Install it where ${JSON.stringify(child)} can resolve it, or rebuild that library with \`panda lib\`.`;
977
+ return createConfigError(message, [
978
+ createConfigDiagnostic("design_system_parent_not_found", message, [
979
+ `Install ${JSON.stringify(parent)} where ${JSON.stringify(child)} can resolve it, or rebuild ${JSON.stringify(child)} with \`panda lib\`.`
980
+ ])
981
+ ]);
982
+ }
983
+ function cycleError(cycle) {
984
+ const message = `Design-system cycle: ${cycle.join(" \u2192 ")}. A design system can't depend on itself.`;
985
+ return createConfigError(message, [createConfigDiagnostic("design_system_cycle", message)]);
986
+ }
987
+ function invalidManifestError(spec, manifestPath, issues) {
988
+ const message = `${JSON.stringify(spec)} manifest ${issues.join("; ")}.`;
989
+ return createConfigError(message, [
990
+ {
991
+ ...createConfigDiagnostic("design_system_manifest_invalid", message, [
992
+ `Rebuild ${JSON.stringify(spec)} with \`panda lib\`.`
993
+ ]),
994
+ file: manifestPath
995
+ }
996
+ ]);
997
+ }
998
+ function duplicateNameError(name, firstPath, secondPath) {
999
+ const message = `Two different packages in the design-system chain are both named ${JSON.stringify(name)} (${JSON.stringify(firstPath)} and ${JSON.stringify(secondPath)}). Their styles would overwrite each other; give each package a unique name.`;
1000
+ return createConfigError(message, [createConfigDiagnostic("design_system_duplicate_name", message)]);
1001
+ }
1002
+ function specifierProtocol(spec) {
1003
+ const match = spec.match(SPECIFIER_PROTOCOL);
1004
+ return match ? match[1] : void 0;
1005
+ }
1006
+ function unsupportedSpecifierError(spec, protocol) {
1007
+ const message = `designSystem ${JSON.stringify(spec)} uses the "${protocol}:" protocol, which isn't supported. Use the published package name (e.g. "@acme/design-system") that resolves to its \`panda/lib.json\`.`;
1008
+ return createConfigError(message, [createConfigDiagnostic("design_system_unsupported_specifier", message)]);
1009
+ }
1010
+
1011
+ // src/design-system/smart-include.ts
1012
+ import { existsSync as existsSync3 } from "node:fs";
1013
+ import { dirname as dirname5, isAbsolute as isAbsolute4, join as join3, relative as relative4, resolve as resolve5, sep } from "node:path";
1014
+ var SMART_INCLUDE_EXTENSIONS = ["js", "mjs", "cjs", "jsx", "ts", "cts", "mts", "tsx", "vue", "svelte", "astro"];
1015
+ var MANIFEST_SUBPATH = "panda/lib.json";
1016
+ var PACKAGE_SPECIFIER = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/i;
1017
+ function resolveSmartInclude(include, cwd, deps) {
1018
+ const offenders = [];
1019
+ const next = [];
1020
+ const excludes = [];
1021
+ let changed = false;
1022
+ for (const entry of include) {
1023
+ if (!PACKAGE_SPECIFIER.test(entry)) {
1024
+ next.push(entry);
1025
+ continue;
1026
+ }
1027
+ if (isLocalPath(entry, cwd)) {
1028
+ next.push(entry);
1029
+ continue;
1030
+ }
1031
+ if (tryResolveFrom(`${entry}/${MANIFEST_SUBPATH}`, cwd) !== void 0) {
1032
+ offenders.push(entry);
1033
+ continue;
1034
+ }
1035
+ const packageDir = resolvePackageDir(entry, cwd);
1036
+ if (packageDir === void 0) {
1037
+ next.push(entry);
1038
+ continue;
1039
+ }
1040
+ if (existsSync3(join3(packageDir, ...MANIFEST_SUBPATH.split("/")))) {
1041
+ offenders.push(entry);
1042
+ continue;
1043
+ }
1044
+ deps.add(join3(packageDir, "package.json"));
1045
+ const base = globBase(packageDir, cwd);
1046
+ next.push(`${base}/**/*.{${SMART_INCLUDE_EXTENSIONS.join(",")}}`);
1047
+ excludes.push(`${base}/**/node_modules/**`);
1048
+ changed = true;
1049
+ }
1050
+ if (offenders.length > 0) throw inIncludeError(offenders);
1051
+ return { include: changed ? next : include, excludes, changed };
1052
+ }
1053
+ function expandSmartInclude(config, cwd, deps) {
1054
+ if (!config.include || config.include.length === 0) return config;
1055
+ const resolved = resolveSmartInclude(config.include, cwd, deps);
1056
+ if (!resolved.changed) return config;
1057
+ return { ...config, include: resolved.include, exclude: mergeExcludes(config.exclude, resolved.excludes) };
1058
+ }
1059
+ function mergeExcludes(existing, additions) {
1060
+ return [...existing ?? [], ...additions];
1061
+ }
1062
+ function isLocalPath(entry, cwd) {
1063
+ return existsSync3(isAbsolute4(entry) ? entry : resolve5(cwd, entry));
1064
+ }
1065
+ function resolvePackageDir(spec, cwd) {
1066
+ const fromPackageJson = tryResolve(`${spec}/package.json`, cwd);
1067
+ if (fromPackageJson !== void 0) return dirname5(fromPackageJson);
1068
+ const fromEntry = tryResolve(spec, cwd);
1069
+ return fromEntry === void 0 ? void 0 : nearestPackageDir(fromEntry);
1070
+ }
1071
+ function tryResolve(request, cwd) {
1072
+ try {
1073
+ return tryResolveFrom(request, cwd);
1074
+ } catch (error) {
1075
+ const message = `Failed to resolve include package ${JSON.stringify(request)} from ${JSON.stringify(cwd)}: ${errorMessage(error)}`;
1076
+ throw createConfigError(message, [createConfigDiagnostic("include_package_resolution_failed", message)]);
1077
+ }
1078
+ }
1079
+ function isInsideCwd(relativePath) {
1080
+ if (relativePath === "" || relativePath === "..") return false;
1081
+ if (isAbsolute4(relativePath)) return false;
1082
+ return !relativePath.startsWith(`..${sep}`);
1083
+ }
1084
+ function nearestPackageDir(from) {
1085
+ let dir = dirname5(from);
1086
+ while (true) {
1087
+ if (existsSync3(join3(dir, "package.json"))) return dir;
1088
+ const parent = dirname5(dir);
1089
+ if (parent === dir) return void 0;
1090
+ dir = parent;
1091
+ }
1092
+ }
1093
+ function globBase(packageDir, cwd) {
1094
+ const rel = relative4(cwd, packageDir);
1095
+ const base = isInsideCwd(rel) ? rel : packageDir;
1096
+ return toPosixPath(base);
1097
+ }
1098
+ function inIncludeError(specs) {
1099
+ const list = specs.map((spec) => JSON.stringify(spec)).join(", ");
1100
+ const plural = specs.length > 1;
1101
+ const message = `Design system${plural ? "s" : ""} in \`include\`: ${list}. ${plural ? "They each ship" : "It ships"} a ${MANIFEST_SUBPATH}, so ${plural ? "they belong" : "it belongs"} in \`designSystem\`, not \`include\`. \`include\` is for files, not design systems.`;
1102
+ return createConfigError(
1103
+ message,
1104
+ specs.map(
1105
+ (spec) => createConfigDiagnostic(
1106
+ "design_system_in_include",
1107
+ `Design system ${JSON.stringify(spec)} is listed in \`include\`. Move it to \`designSystem\`; \`include\` is for files, not design systems.`,
1108
+ [`Move ${JSON.stringify(spec)} to \`designSystem\`.`]
1109
+ )
1110
+ )
1111
+ );
1112
+ }
1113
+
1114
+ // src/design-system/token-paths.ts
1115
+ import { isDeepStrictEqual } from "node:util";
1116
+ function collectTokenPaths(config) {
1117
+ return [...collectTokenEntries(config).keys()].sort();
1118
+ }
1119
+ function collectTokenEntries(config) {
1120
+ const entries = /* @__PURE__ */ new Map();
1121
+ if (!isPlainObject(config?.theme)) {
1122
+ return entries;
1123
+ }
1124
+ collect(config.theme.tokens, [], entries);
1125
+ collect(config.theme.semanticTokens, [], entries);
1126
+ return entries;
1127
+ }
1128
+ function resolveUserTokenPathsAfterHooks(userTokenPaths, beforeHooks, afterHooks) {
1129
+ const paths = new Set(userTokenPaths);
1130
+ const after = collectTokenEntries(afterHooks);
1131
+ for (const path of paths) {
1132
+ if (!after.has(path)) {
1133
+ paths.delete(path);
1134
+ }
1135
+ }
1136
+ for (const [path, values] of after) {
1137
+ if (!beforeHooks.has(path) || !isDeepStrictEqual(beforeHooks.get(path), values)) {
1138
+ paths.add(path);
1139
+ }
1140
+ }
1141
+ return [...paths].sort();
1142
+ }
1143
+ function collect(node, trail, out) {
1144
+ if (!isPlainObject(node)) {
1145
+ return;
1146
+ }
1147
+ if ("value" in node) {
1148
+ if (trail.length > 0) {
1149
+ const path = trail.join(".");
1150
+ const entries = out.get(path) ?? [];
1151
+ entries.push(node.value);
1152
+ out.set(path, entries);
1153
+ }
1154
+ return;
1155
+ }
1156
+ for (const [key, child] of Object.entries(node)) {
1157
+ collect(child, [...trail, key], out);
1158
+ }
1159
+ }
1160
+
1161
+ // src/artifact-names.ts
1162
+ function collectRecipeNames(config) {
1163
+ const theme = config?.theme;
1164
+ if (!theme) return [];
1165
+ const names = /* @__PURE__ */ new Set([...Object.keys(theme.recipes ?? {}), ...Object.keys(theme.slotRecipes ?? {})]);
1166
+ return [...names].sort();
1167
+ }
1168
+ function collectPatternNames(config) {
1169
+ return Object.keys(config?.patterns ?? {}).sort();
1170
+ }
1171
+
1172
+ // src/preset.ts
1173
+ async function resolveAuthoredPresetsForLoad(config, cwd, options = {}) {
1174
+ const designSystem = config.designSystem;
1175
+ const hasDesignSystem = typeof designSystem === "string" && designSystem.length > 0;
1176
+ const trackSources = options.trackSources ?? hasDesignSystem;
314
1177
  const ctx = {
315
1178
  cwd,
316
1179
  configs: [],
317
1180
  dependencies: /* @__PURE__ */ new Set(),
318
1181
  presetResolvedHooks: [],
319
- ...options.trackSources ? { sourcedConfigs: [] } : {}
1182
+ ...trackSources ? { sourcedConfigs: [] } : {}
320
1183
  };
321
1184
  const rootSource = { kind: "config" };
322
- if (options.configFile) rootSource.file = normalize2(relative2(cwd, options.configFile));
323
- await collectConfigs(config, rootSource, ctx, /* @__PURE__ */ new WeakSet());
1185
+ if (options.configFile) {
1186
+ rootSource.file = normalize2(relative5(cwd, options.configFile));
1187
+ }
1188
+ let dsChain = [];
1189
+ const designSystemCompatibility = [];
1190
+ if (hasDesignSystem) {
1191
+ dsChain = await loadDesignSystemChain(designSystem, cwd, ctx.dependencies);
1192
+ for (const level of dsChain) {
1193
+ const dsSource = { kind: "preset", specifier: level.info.name, name: level.info.name };
1194
+ const resolution = await resolveConfigEntry(level.preset, dsSource, cwd, ctx.dependencies, trackSources);
1195
+ if (resolution.sourcedConfigs) {
1196
+ for (const sourced of resolution.sourcedConfigs) {
1197
+ sourced.source = dsSource;
1198
+ }
1199
+ }
1200
+ level.info.tokenPaths = collectTokenPaths(resolution.config);
1201
+ level.info.recipeNames = collectRecipeNames(resolution.config);
1202
+ level.info.patternNames = collectPatternNames(resolution.config);
1203
+ appendConfigResolution(ctx, resolution);
1204
+ designSystemCompatibility.push({
1205
+ designSystem: level.info,
1206
+ classNameOptions: normalizeClassNameOptions(mergeConfigs(ctx.configs)),
1207
+ presetConfig: resolution.config
1208
+ });
1209
+ }
1210
+ }
1211
+ const rootResolution = await resolveConfigEntry(config, rootSource, cwd, ctx.dependencies, trackSources);
1212
+ appendConfigResolution(ctx, rootResolution);
1213
+ for (const { designSystem: designSystem2, classNameOptions } of designSystemCompatibility) {
1214
+ const mismatch = diffClassNameOptions(rootResolution.config, classNameOptions, "explicit");
1215
+ if (mismatch.length > 0) {
1216
+ designSystem2.optionMismatch = mismatch;
1217
+ }
1218
+ }
1219
+ const dsInfos = dsChain.map((level) => level.info);
1220
+ const finalize = (resolved) => {
1221
+ const withImportMap = dsInfos.length > 0 ? withDesignSystemImportMap(resolved, dsInfos) : resolved;
1222
+ return expandSmartInclude(withImportMap, cwd, ctx.dependencies);
1223
+ };
1224
+ const leafCompatibility = designSystemCompatibility[designSystemCompatibility.length - 1];
324
1225
  if (ctx.sourcedConfigs) {
325
1226
  const merged = mergeConfigsWithSources(ctx.sourcedConfigs);
326
- if (options.preserveRuntimeHooks) attachRuntimeHooks(merged.config, ctx.configs);
1227
+ if (options.preserveRuntimeHooks) {
1228
+ attachRuntimeHooks(merged.config, ctx.configs);
1229
+ }
1230
+ const finalized2 = finalize(merged.config);
1231
+ let overlayInput;
1232
+ if (leafCompatibility) {
1233
+ const input = buildOverlayInput(merged.sources, finalized2, dsInfos, leafCompatibility.presetConfig, cwd);
1234
+ const leafClassMismatch = leafCompatibility.designSystem.optionMismatch ?? [];
1235
+ overlayInput = {
1236
+ authored: input.authored,
1237
+ compatible: input.compatible && leafClassMismatch.length === 0
1238
+ };
1239
+ }
1240
+ const dsMetadata2 = dsInfos.length > 0 ? {
1241
+ designSystem: dsInfos,
1242
+ userTokenPaths: collectTokenPaths(rootResolution.config),
1243
+ userRecipeNames: collectRecipeNames(rootResolution.config),
1244
+ userPatternNames: collectPatternNames(rootResolution.config),
1245
+ ...overlayInput ? { overlayInput } : {}
1246
+ } : void 0;
327
1247
  return {
328
- config: merged.config,
1248
+ config: finalized2,
329
1249
  dependencies: Array.from(ctx.dependencies),
330
- metadata: { sources: merged.sources }
1250
+ metadata: { sources: merged.sources, ...dsMetadata2 },
1251
+ designSystemCompatibility
331
1252
  };
332
1253
  }
1254
+ const mergedConfig = options.preserveRuntimeHooks ? attachRuntimeHooks(mergeConfigs(ctx.configs), ctx.configs) : mergeConfigs(ctx.configs);
1255
+ const finalized = finalize(mergedConfig);
1256
+ const dsMetadata = dsInfos.length > 0 ? {
1257
+ designSystem: dsInfos,
1258
+ userTokenPaths: collectTokenPaths(rootResolution.config),
1259
+ userRecipeNames: collectRecipeNames(rootResolution.config),
1260
+ userPatternNames: collectPatternNames(rootResolution.config)
1261
+ } : void 0;
333
1262
  return {
334
- config: options.preserveRuntimeHooks ? attachRuntimeHooks(mergeConfigs(ctx.configs), ctx.configs) : mergeConfigs(ctx.configs),
335
- dependencies: Array.from(ctx.dependencies)
1263
+ config: finalized,
1264
+ dependencies: Array.from(ctx.dependencies),
1265
+ ...dsMetadata ? { metadata: dsMetadata } : {},
1266
+ designSystemCompatibility
336
1267
  };
337
1268
  }
338
- function attachRuntimeHooks(config, configs) {
339
- const plugins = configs.flatMap((item) => {
340
- if ("hooks" in item && item.hooks != null) {
341
- throw new PandaError(
342
- "CONFIG_ERROR",
343
- '\u{1F4A5} `config.hooks` was removed in v2. Use `plugins: [{ name: "local", hooks: { ... } }]` instead.'
344
- );
345
- }
346
- return [...item.plugins ?? [], ...item.extend?.plugins ?? []];
347
- });
348
- for (const plugin of plugins) {
349
- if (!isPlainObject(plugin) || typeof plugin.name !== "string" || plugin.name.length === 0) {
350
- throw new PandaError(
351
- "CONFIG_ERROR",
352
- "\u{1F4A5} Every plugin in `config.plugins` must be an object with a non-empty `name`."
353
- );
354
- }
355
- }
356
- if (plugins.length > 0) {
357
- config.plugins = plugins;
1269
+ async function resolveConfigEntry(config, source, cwd, dependencies, trackSources) {
1270
+ const ctx = {
1271
+ cwd,
1272
+ configs: [],
1273
+ dependencies,
1274
+ presetResolvedHooks: [],
1275
+ ...trackSources ? { sourcedConfigs: [] } : {}
1276
+ };
1277
+ await collectConfigs(config, source, ctx, /* @__PURE__ */ new WeakSet());
1278
+ return {
1279
+ configs: ctx.configs,
1280
+ ...ctx.sourcedConfigs ? { sourcedConfigs: ctx.sourcedConfigs } : {},
1281
+ config: mergeConfigs(ctx.configs)
1282
+ };
1283
+ }
1284
+ function appendConfigResolution(ctx, resolution) {
1285
+ ctx.configs.push(...resolution.configs);
1286
+ if (ctx.sourcedConfigs && resolution.sourcedConfigs) {
1287
+ ctx.sourcedConfigs.push(...resolution.sourcedConfigs);
358
1288
  }
359
- return config;
360
1289
  }
361
1290
  async function collectConfigs(config, source, ctx, active) {
362
1291
  if (active.has(config)) {
@@ -402,10 +1331,7 @@ async function resolvePreset(preset, cwd) {
402
1331
  };
403
1332
  } catch (error) {
404
1333
  if (error instanceof PandaError) throw error;
405
- throw new PandaError(
406
- "CONFIG_ERROR",
407
- `\u{1F4A5} Failed to resolve preset ${JSON.stringify(preset)}: ${errorMessage(error)}`
408
- );
1334
+ throw presetResolutionError(JSON.stringify(preset), error);
409
1335
  }
410
1336
  }
411
1337
  try {
@@ -417,12 +1343,12 @@ async function resolvePreset(preset, cwd) {
417
1343
  };
418
1344
  } catch (error) {
419
1345
  if (error instanceof PandaError) throw error;
420
- throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Failed to resolve preset "unknown-preset": ${errorMessage(error)}`);
1346
+ throw presetResolutionError('"unknown-preset"', error);
421
1347
  }
422
1348
  }
423
- function ensureConfigObject(config, name) {
424
- if (isPlainObject(config)) return config;
425
- throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Preset ${JSON.stringify(name)} must resolve to an object.`);
1349
+ function presetResolutionError(name, error) {
1350
+ const message = `Failed to resolve preset ${name}: ${errorMessage(error)}`;
1351
+ return createConfigError(message, [createConfigDiagnostic("preset_resolution_failed", message)]);
426
1352
  }
427
1353
  function presetName(config) {
428
1354
  return isPlainObject(config) && typeof config.name === "string" ? config.name : void 0;
@@ -435,9 +1361,6 @@ function presetSource(config, specifier, file) {
435
1361
  if (file) source.file = file;
436
1362
  return source;
437
1363
  }
438
- function errorMessage(error) {
439
- return error instanceof Error ? error.message : String(error);
440
- }
441
1364
 
442
1365
  // src/load.ts
443
1366
  async function loadConfig(options) {
@@ -447,7 +1370,7 @@ async function loadConfig(options) {
447
1370
  if (!isPlainObject(config)) {
448
1371
  throw new PandaError("CONFIG_ERROR", "\u{1F4A5} Config must export or return an object.");
449
1372
  }
450
- const authored = await resolveAuthoredPresets(config, cwd, {
1373
+ const authored = await resolveAuthoredPresetsForLoad(config, cwd, {
451
1374
  configFile: path,
452
1375
  trackSources: options.trackSources,
453
1376
  preserveRuntimeHooks: true
@@ -455,8 +1378,16 @@ async function loadConfig(options) {
455
1378
  const authoredDependencies = Array.from(
456
1379
  /* @__PURE__ */ new Set([...dependencies, ...authored.dependencies, ...authored.config.dependencies ?? []])
457
1380
  );
1381
+ const tokenEntriesBeforeHooks = collectTokenEntries(authored.config);
458
1382
  const userConfig = await runConfigResolvedHooks(authored.config, path, authoredDependencies);
459
- const resolved = applyConfigDefaults(userConfig, cwd);
1383
+ const resolved = applyConfigDefaults2(userConfig, cwd);
1384
+ refreshDesignSystemMetadata(
1385
+ authored.metadata,
1386
+ authored.designSystemCompatibility,
1387
+ resolved,
1388
+ tokenEntriesBeforeHooks,
1389
+ cwd
1390
+ );
460
1391
  const dependencyList = Array.from(
461
1392
  /* @__PURE__ */ new Set([...dependencies, ...authored.dependencies, ...resolved.dependencies ?? []])
462
1393
  );
@@ -468,12 +1399,40 @@ async function loadConfig(options) {
468
1399
  ...snapshot.hooks ? { hooks: snapshot.hooks } : {},
469
1400
  hostHooks: {
470
1401
  "codegen:prepare": collectPluginHookHandlers(resolved, "codegen:prepare"),
471
- "codegen:done": collectPluginHookHandlers(resolved, "codegen:done")
1402
+ "codegen:done": collectPluginHookHandlers(resolved, "codegen:done"),
1403
+ "cssgen:done": collectPluginHookHandlers(resolved, "cssgen:done")
472
1404
  },
473
1405
  dependencies: dependencyList,
474
1406
  ...authored.metadata ? { metadata: authored.metadata } : {}
475
1407
  };
476
1408
  }
1409
+ function refreshDesignSystemMetadata(metadata, designSystemCompatibility, config, tokenEntriesBeforeHooks, cwd) {
1410
+ if (!metadata?.designSystem?.length) return;
1411
+ metadata.userTokenPaths = resolveUserTokenPathsAfterHooks(
1412
+ metadata.userTokenPaths ?? [],
1413
+ tokenEntriesBeforeHooks,
1414
+ config
1415
+ );
1416
+ const chain = metadata.designSystem;
1417
+ const sources = metadata.sources;
1418
+ const leaf = designSystemCompatibility[designSystemCompatibility.length - 1];
1419
+ for (const { designSystem, classNameOptions } of designSystemCompatibility) {
1420
+ const mismatch = diffClassNameOptions(config, classNameOptions, "effective");
1421
+ if (mismatch.length > 0) {
1422
+ designSystem.optionMismatch = mismatch;
1423
+ } else {
1424
+ delete designSystem.optionMismatch;
1425
+ }
1426
+ }
1427
+ if (sources && leaf) {
1428
+ const input = buildOverlayInput(sources, config, chain, leaf.presetConfig, cwd);
1429
+ const leafClassMismatch = leaf.designSystem.optionMismatch ?? [];
1430
+ metadata.overlayInput = {
1431
+ authored: input.authored,
1432
+ compatible: input.compatible && leafClassMismatch.length === 0
1433
+ };
1434
+ }
1435
+ }
477
1436
  async function runConfigResolvedHooks(config, path, dependencies) {
478
1437
  let current = config;
479
1438
  for (const entry of collectPluginHookHandlers(current, "config:resolved")) {
@@ -503,7 +1462,6 @@ var ALL_DEPENDENCIES = [
503
1462
  "prefix",
504
1463
  "recipes",
505
1464
  "separator",
506
- "syntax",
507
1465
  "themes",
508
1466
  "tokens",
509
1467
  "utilities"
@@ -557,8 +1515,6 @@ function classify(path) {
557
1515
  return { deps: ["patterns"], pattern: second };
558
1516
  case "themes":
559
1517
  return { deps: ["themes"] };
560
- case "syntax":
561
- return { deps: ["syntax"] };
562
1518
  case "hash":
563
1519
  return { deps: ["hash"] };
564
1520
  case "prefix":
@@ -593,11 +1549,118 @@ function diffInput(input) {
593
1549
  function isConfigSnapshot(input) {
594
1550
  return !!input && typeof input === "object" && !Array.isArray(input) && ("callbacks" in input || "hooks" in input) && "config" in input && !!input.config && typeof input.config === "object" && !Array.isArray(input.config);
595
1551
  }
1552
+
1553
+ // src/version.ts
1554
+ import { readFileSync as readFileSync3 } from "node:fs";
1555
+ import { dirname as dirname6, join as join4 } from "node:path";
1556
+ import { fileURLToPath } from "node:url";
1557
+ var MAJOR_VERSION_RE = /\d+/;
1558
+ var STAMPABLE_PANDA_RANGE_RE = /^[v=><~^]|^\d/;
1559
+ function readPandaVersion() {
1560
+ try {
1561
+ const pkgPath = join4(dirname6(fileURLToPath(import.meta.url)), "../package.json");
1562
+ return JSON.parse(readFileSync3(pkgPath, "utf8")).version;
1563
+ } catch {
1564
+ return void 0;
1565
+ }
1566
+ }
1567
+ function getPandaMajorRange() {
1568
+ const match = readPandaVersion()?.match(MAJOR_VERSION_RE);
1569
+ return match ? `^${match[0]}.0.0` : void 0;
1570
+ }
1571
+ function isStampablePandaRange(range) {
1572
+ return range !== void 0 && STAMPABLE_PANDA_RANGE_RE.test(range.trim());
1573
+ }
1574
+
1575
+ // src/design-system/compile-preset.ts
1576
+ import { builtinModules as builtinModules2 } from "node:module";
1577
+ var APP_FIELDS = ["designSystem", "include", "exclude", "outdir", "cwd", "watch", "clean", "gitignore", "importMap"];
1578
+ var VIRTUAL_ENTRY = "\0panda-lib-preset-entry";
1579
+ var nodeBuiltins2 = /* @__PURE__ */ new Set([...builtinModules2, ...builtinModules2.map((mod) => `node:${mod}`)]);
1580
+ async function compilePreset(options) {
1581
+ const { configPath, cwd } = options;
1582
+ const { rolldown } = await import("rolldown");
1583
+ const build = await rolldown({
1584
+ input: VIRTUAL_ENTRY,
1585
+ cwd,
1586
+ platform: "node",
1587
+ external: (id) => nodeBuiltins2.has(id),
1588
+ treeshake: true,
1589
+ plugins: [importMetaUrlPlugin(), presetEntryPlugin(configPath)]
1590
+ });
1591
+ let chunks;
1592
+ try {
1593
+ chunks = await build.generate({ format: "esm", exports: "named", codeSplitting: false });
1594
+ } finally {
1595
+ await build.close?.();
1596
+ }
1597
+ const output = chunks.output.find((item) => item.type === "chunk");
1598
+ if (!output || output.type !== "chunk") {
1599
+ throw new PandaError("CONFIG_ERROR", "\u{1F4A5} Preset bundle did not produce an executable module.");
1600
+ }
1601
+ await validatePreset(output.code);
1602
+ const dependencies = Object.keys(output.modules ?? {}).filter((id) => id !== VIRTUAL_ENTRY);
1603
+ return { code: output.code, dependencies };
1604
+ }
1605
+ function presetEntryPlugin(configPath) {
1606
+ return {
1607
+ name: "panda-lib-preset-entry",
1608
+ resolveId(id) {
1609
+ return id === VIRTUAL_ENTRY ? VIRTUAL_ENTRY : null;
1610
+ },
1611
+ load(id) {
1612
+ if (id !== VIRTUAL_ENTRY) return null;
1613
+ const fields = APP_FIELDS.join(", ");
1614
+ return `import __panda_lib_config from ${JSON.stringify(configPath)}
1615
+ const __panda_lib_resolved = await __panda_lib_config
1616
+ if (!${isPlainObjectSource()}(__panda_lib_resolved)) throw new Error('Config must export or return an object.')
1617
+ const { ${fields}, ...preset } = __panda_lib_resolved
1618
+ export default preset
1619
+ `;
1620
+ }
1621
+ };
1622
+ }
1623
+ function isPlainObjectSource() {
1624
+ return `((value) => {
1625
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false
1626
+ const proto = Object.getPrototypeOf(value)
1627
+ return proto === Object.prototype || proto === null
1628
+ })`;
1629
+ }
1630
+ async function validatePreset(code) {
1631
+ try {
1632
+ await import(`data:text/javascript;base64,${Buffer.from(code).toString("base64")}`);
1633
+ } catch (error) {
1634
+ throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Failed to compile design system preset: ${errorMessage(error)}`);
1635
+ }
1636
+ }
596
1637
  export {
1638
+ buildCodegenOverlay,
597
1639
  bundleConfig,
1640
+ collectArtifactConflicts,
1641
+ collectExportMissingDiagnostics,
1642
+ collectNameCollisionDiagnostics,
1643
+ collectPatternNames,
1644
+ collectRecipeNames,
1645
+ collectTokenPaths,
1646
+ compilePreset,
598
1647
  createConfigSnapshot,
1648
+ defaultImportMap,
599
1649
  diffConfig,
1650
+ filterPublishableLibFiles,
600
1651
  findConfig,
1652
+ getPandaMajorRange,
1653
+ isStampablePandaRange,
601
1654
  loadConfig,
602
- mergeConfigs
1655
+ mergeConfigs,
1656
+ mergeExcludes,
1657
+ readPackageIdentity,
1658
+ readPandaVersion,
1659
+ readPublishFilesField,
1660
+ resolvePublishedPandaRange,
1661
+ resolveSmartInclude,
1662
+ syncExports,
1663
+ toPosixPath,
1664
+ toPosixRelative,
1665
+ toRelativeKey
603
1666
  };