@pandacss/config 1.11.3 → 2.0.0-beta.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/dist/index.js CHANGED
@@ -1,1149 +1,540 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all2) => {
9
- for (var name in all2)
10
- __defProp(target, name, { get: all2[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- bundleConfig: () => bundleConfig,
34
- convertTsPathsToRegexes: () => convertTsPathsToRegexes,
35
- diffConfigs: () => diffConfigs,
36
- findConfig: () => findConfig,
37
- getConfigDependencies: () => getConfigDependencies,
38
- getResolvedConfig: () => getResolvedConfig,
39
- loadConfig: () => loadConfig,
40
- mergeConfigs: () => mergeConfigs,
41
- mergeHooks: () => mergeHooks,
42
- resolveConfig: () => resolveConfig
43
- });
44
- module.exports = __toCommonJS(index_exports);
45
-
46
- // src/bundle-config.ts
47
- var import_logger = require("@pandacss/logger");
48
- var import_shared2 = require("@pandacss/shared");
49
-
50
- // src/bundle-n-require.ts
51
- var import_node_fs = require("fs");
52
- var import_node_module = require("module");
53
- var import_node_path = require("path");
54
- var import_esbuild = require("esbuild");
55
- var ModuleInternals = import_node_module.Module;
56
- async function bundleConfigFile(file, cwd, options) {
57
- const result = await (0, import_esbuild.build)({
1
+ import {
2
+ PandaError,
3
+ isPlainObject,
4
+ mergeConfigs,
5
+ mergeConfigsWithSources
6
+ } from "./chunk-LUSBBUHX.js";
7
+ import {
8
+ collectPluginHookHandlers,
9
+ createConfigSnapshot,
10
+ normalizeHook
11
+ } from "./chunk-VYX3JX5J.js";
12
+
13
+ // src/load.ts
14
+ import { applyConfigDefaults } from "@pandacss/compiler-shared";
15
+
16
+ // src/bundle.ts
17
+ import { parse } from "acorn";
18
+ import { simple } from "acorn-walk";
19
+ import MagicString from "magic-string";
20
+ import { realpathSync } from "fs";
21
+ import { builtinModules } from "module";
22
+ import { isAbsolute, normalize, relative } from "path";
23
+ import { pathToFileURL } from "url";
24
+ import { rolldown } from "rolldown";
25
+ var nodeBuiltins = /* @__PURE__ */ new Set([...builtinModules, ...builtinModules.map((mod) => `node:${mod}`)]);
26
+ async function bundleConfig(filepath, cwd) {
27
+ const build = await rolldown({
28
+ input: filepath,
29
+ cwd,
58
30
  platform: "node",
59
- format: "cjs",
60
- mainFields: ["module", "main"],
61
- ...options,
62
- absWorkingDir: cwd,
63
- entryPoints: [file],
64
- outfile: "out.js",
65
- write: false,
66
- bundle: true,
67
- sourcemap: false,
68
- metafile: true
31
+ external: (id) => nodeBuiltins.has(id),
32
+ treeshake: false,
33
+ plugins: [importMetaUrlPlugin()]
69
34
  });
70
- const { text } = result.outputFiles[0];
35
+ let chunks;
36
+ try {
37
+ chunks = await build.generate({ format: "esm", exports: "named", codeSplitting: false });
38
+ } finally {
39
+ await build.close?.();
40
+ }
41
+ const output = chunks.output.find((item) => item.type === "chunk");
42
+ if (!output || output.type !== "chunk") {
43
+ throw new PandaError("CONFIG_ERROR", "\u{1F4A5} Config bundle did not produce an executable module.");
44
+ }
45
+ const dependencies = collectDependencies(chunks.output, filepath, cwd);
46
+ const mod = await importBundledConfig(output.code);
47
+ const hasDefaultExport = Object.prototype.hasOwnProperty.call(mod ?? {}, "default");
48
+ const exported = hasDefaultExport ? mod.default : mod;
49
+ const config = hasDefaultExport && isPromiseLike(exported) ? await exported : exported;
50
+ return { config, dependencies };
51
+ }
52
+ async function importBundledConfig(code) {
53
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString("base64")}`;
54
+ return import(
55
+ /* @vite-ignore */
56
+ dataUrl
57
+ );
58
+ }
59
+ function importMetaUrlPlugin() {
71
60
  return {
72
- code: text,
73
- dependencies: result.metafile ? Object.keys(result.metafile.inputs) : []
61
+ name: "panda-import-meta-url",
62
+ transform(code, id) {
63
+ if (!isAbsolute(id) || !code.includes("import.meta.url")) return;
64
+ const replacement = JSON.stringify(pathToFileURL(id).href);
65
+ const patched = replaceImportMetaUrl(code, replacement);
66
+ if (patched === code) return;
67
+ return { code: patched, map: null };
68
+ }
74
69
  };
75
70
  }
76
- function loadBundledFile(req, file, code) {
77
- const extension = (0, import_node_path.extname)(file);
78
- const realFileName = import_node_fs.realpathSync.native(file);
79
- const loader = req.extensions[extension];
80
- req.extensions[extension] = (mod, filename) => {
81
- if (filename === realFileName) {
82
- ;
83
- mod._compile(code, filename);
84
- } else {
85
- loader?.(mod, filename);
71
+ function replaceImportMetaUrl(code, replacement) {
72
+ const ast = parse(code, {
73
+ ecmaVersion: "latest",
74
+ sourceType: "module"
75
+ });
76
+ const output = new MagicString(code);
77
+ let changed = false;
78
+ simple(ast, {
79
+ MemberExpression(node) {
80
+ if (!isImportMetaUrl(node)) return;
81
+ output.overwrite(node.start, node.end, replacement);
82
+ changed = true;
86
83
  }
87
- };
88
- try {
89
- delete req.cache[req.resolve(file)];
90
- const raw = req(file);
91
- return raw?.default ?? raw;
92
- } finally {
93
- if (loader) req.extensions[extension] = loader;
94
- else delete req.extensions[extension];
95
- }
84
+ });
85
+ return changed ? output.toString() : code;
86
+ }
87
+ function isImportMetaUrl(node) {
88
+ if (node.computed || !isIdentifier(node.property, "url")) return false;
89
+ const object = node.object;
90
+ return isNode(object, "MetaProperty") && isIdentifier(object.meta, "import") && isIdentifier(object.property, "meta");
96
91
  }
97
- function evalBundledFile(file, code) {
98
- const mod = new import_node_module.Module(file);
99
- mod.filename = file;
100
- mod.paths = ModuleInternals._nodeModulePaths((0, import_node_path.dirname)(file));
101
- mod._compile(code, file);
102
- const raw = mod.exports;
103
- return raw?.default ?? raw;
92
+ function isIdentifier(value, name) {
93
+ return isNode(value, "Identifier") && value.name === name;
104
94
  }
105
- async function bundleNRequire(file, opts = {}) {
106
- const { cwd = process.cwd() } = opts;
107
- const req = (0, import_node_module.createRequire)((0, import_node_path.join)(cwd, "index.js"));
108
- const absPath = req.resolve(file);
109
- const { code, dependencies } = await bundleConfigFile(absPath, cwd);
110
- let mod;
95
+ function isNode(value, type) {
96
+ return !!value && typeof value === "object" && value.type === type;
97
+ }
98
+ function isPromiseLike(value) {
99
+ return value != null && typeof value === "object" && typeof value.then === "function";
100
+ }
101
+ function collectDependencies(output, entry, cwd) {
102
+ const dependencies = /* @__PURE__ */ new Set();
103
+ const base = canonical(cwd);
104
+ const add = (id) => dependencies.add(normalize(relative(base, canonical(id))));
105
+ for (const item of output) {
106
+ if (item.type !== "chunk") continue;
107
+ Object.keys(item.modules ?? {}).forEach((id) => {
108
+ if (isAbsolute(id)) add(id);
109
+ });
110
+ }
111
+ if (isAbsolute(entry)) add(entry);
112
+ return Array.from(dependencies);
113
+ }
114
+ function canonical(filepath) {
111
115
  try {
112
- mod = loadBundledFile(req, absPath, code);
116
+ return realpathSync(filepath);
113
117
  } catch {
114
- mod = evalBundledFile(absPath, code);
118
+ return filepath;
115
119
  }
116
- return { mod, code, dependencies };
117
120
  }
118
121
 
119
- // src/find-config.ts
120
- var import_shared = require("@pandacss/shared");
121
- var import_sync = __toESM(require("escalade/sync"));
122
- var import_path = require("path");
123
-
124
- // src/is-panda-config.ts
125
- var configName = "panda";
126
- var pandaConfigFiles = /* @__PURE__ */ new Set([
127
- `${configName}.config.ts`,
128
- `${configName}.config.js`,
129
- `${configName}.config.mts`,
130
- `${configName}.config.mjs`,
131
- `${configName}.config.cts`,
132
- `${configName}.config.cjs`
122
+ // src/find.ts
123
+ import { readdirSync } from "fs";
124
+ import { dirname, resolve } from "path";
125
+ var configFiles = /* @__PURE__ */ new Set([
126
+ "panda.config.ts",
127
+ "panda.config.js",
128
+ "panda.config.mts",
129
+ "panda.config.mjs",
130
+ "panda.config.cts",
131
+ "panda.config.cjs"
133
132
  ]);
134
- var isPandaConfig = (file) => pandaConfigFiles.has(file);
135
-
136
- // src/find-config.ts
133
+ var isPandaConfig = (file) => configFiles.has(file);
134
+ function findUp(cwd) {
135
+ let dir = resolve(cwd);
136
+ while (true) {
137
+ let entries;
138
+ try {
139
+ entries = readdirSync(dir);
140
+ } catch {
141
+ entries = [];
142
+ }
143
+ const match = entries.find(isPandaConfig);
144
+ if (match) return resolve(dir, match);
145
+ const parent = dirname(dir);
146
+ if (parent === dir) return void 0;
147
+ dir = parent;
148
+ }
149
+ }
137
150
  function findConfig(options) {
138
- const { cwd = process.cwd(), file } = options;
151
+ const { cwd, file } = options;
139
152
  if (file) {
140
- return (0, import_path.resolve)(cwd, file);
153
+ return resolve(cwd, file);
141
154
  }
142
- const configPath = (0, import_sync.default)(cwd, (_dir, paths) => paths.find(isPandaConfig));
155
+ const configPath = findUp(cwd);
143
156
  if (!configPath) {
144
- throw new import_shared.PandaError(
157
+ throw new PandaError(
145
158
  "CONFIG_NOT_FOUND",
146
- `Cannot find config file \`panda.config.{ts,js,mjs,mts}\`. Did you forget to run \`panda init\`?`
159
+ "Cannot find config file `panda.config.{ts,js,mjs,mts}`. Did you forget to run `panda init`?"
147
160
  );
148
161
  }
149
162
  return configPath;
150
163
  }
151
164
 
152
- // src/bundle-config.ts
153
- async function bundle(filepath, cwd) {
154
- const { mod, dependencies } = await bundleNRequire(filepath, { cwd });
155
- const config = mod?.default ?? mod;
156
- return {
157
- config,
158
- dependencies
165
+ // src/preset.ts
166
+ import { normalize as normalize2, relative as relative2 } from "path";
167
+ async function resolveAuthoredPresets(config, cwd, options = {}) {
168
+ const ctx = {
169
+ cwd,
170
+ configs: [],
171
+ dependencies: /* @__PURE__ */ new Set(),
172
+ presetResolvedHooks: [],
173
+ ...options.trackSources ? { sourcedConfigs: [] } : {}
159
174
  };
160
- }
161
- async function bundleConfig(options) {
162
- const { cwd, file } = options;
163
- const filePath = findConfig({ cwd, file });
164
- import_logger.logger.debug("config:path", filePath);
165
- const result = await bundle(filePath, cwd);
166
- if (typeof result.config !== "object") {
167
- throw new import_shared2.PandaError("CONFIG_ERROR", `\u{1F4A5} Config must export or return an object.`);
175
+ const rootSource = { kind: "config" };
176
+ if (options.configFile) rootSource.file = normalize2(relative2(cwd, options.configFile));
177
+ await collectConfigs(config, rootSource, ctx, /* @__PURE__ */ new WeakSet());
178
+ if (ctx.sourcedConfigs) {
179
+ const merged = mergeConfigsWithSources(ctx.sourcedConfigs);
180
+ if (options.preserveRuntimeHooks) attachRuntimeHooks(merged.config, ctx.configs);
181
+ return {
182
+ config: merged.config,
183
+ dependencies: Array.from(ctx.dependencies),
184
+ metadata: { sources: merged.sources }
185
+ };
168
186
  }
169
- result.config.outdir ??= "styled-system";
170
- result.config.validation ??= "warn";
171
187
  return {
172
- ...result,
173
- config: result.config,
174
- path: filePath
188
+ config: options.preserveRuntimeHooks ? attachRuntimeHooks(mergeConfigs(ctx.configs), ctx.configs) : mergeConfigs(ctx.configs),
189
+ dependencies: Array.from(ctx.dependencies)
175
190
  };
176
191
  }
177
-
178
- // src/diff-config.ts
179
- var import_shared3 = require("@pandacss/shared");
180
- var import_microdiff = __toESM(require("microdiff"));
181
-
182
- // src/create-matcher.ts
183
- function createMatcher(id, patterns) {
184
- if (!patterns?.length) return () => void 0;
185
- const includePatterns = [];
186
- const excludePatterns = [];
187
- const deduped = new Set(patterns);
188
- deduped.forEach((pattern) => {
189
- const regexString = pattern.replace(/\*/g, ".*");
190
- if (pattern.startsWith("!")) {
191
- excludePatterns.push(regexString.slice(1));
192
- } else {
193
- includePatterns.push(regexString);
192
+ function attachRuntimeHooks(config, configs) {
193
+ const plugins = configs.flatMap((item) => {
194
+ if ("hooks" in item && item.hooks != null) {
195
+ throw new PandaError(
196
+ "CONFIG_ERROR",
197
+ '\u{1F4A5} `config.hooks` was removed in v2. Use `plugins: [{ name: "local", hooks: { ... } }]` instead.'
198
+ );
194
199
  }
200
+ return [...item.plugins ?? [], ...item.extend?.plugins ?? []];
195
201
  });
196
- const include = new RegExp(includePatterns.join("|"));
197
- const exclude = new RegExp(excludePatterns.join("|"));
198
- return (path2) => {
199
- if (excludePatterns.length && exclude.test(path2)) return;
200
- return include.test(path2) ? id : void 0;
201
- };
202
- }
203
-
204
- // src/config-deps.ts
205
- var all = [
206
- "clean",
207
- "cwd",
208
- "eject",
209
- "outdir",
210
- "forceConsistentTypeExtension",
211
- "outExtension",
212
- "emitTokensOnly",
213
- "presets",
214
- "plugins",
215
- "hooks"
216
- ];
217
- var format = [
218
- "syntax",
219
- "hash",
220
- "prefix",
221
- "separator",
222
- "strictTokens",
223
- "strictPropertyValues",
224
- "shorthands"
225
- ];
226
- var tokens = [
227
- "utilities",
228
- "conditions",
229
- "theme.tokens",
230
- "theme.semanticTokens",
231
- "theme.breakpoints",
232
- "theme.containerNames",
233
- "theme.containerSizes"
234
- ];
235
- var jsx = ["jsxFramework", "jsxFactory", "jsxStyleProps", "syntax"];
236
- var common = tokens.concat(jsx, format);
237
- var artifactConfigDeps = {
238
- helpers: ["syntax", "jsxFramework"],
239
- keyframes: ["theme.keyframes", "layers"],
240
- "design-tokens": ["layers", "!utilities.*.className"].concat(tokens),
241
- types: ["!utilities.*.className"].concat(common),
242
- "css-fn": common,
243
- cva: ["syntax"],
244
- sva: ["syntax"],
245
- cx: [],
246
- "create-recipe": ["separator", "prefix", "hash"],
247
- "recipes-index": ["theme.recipes", "theme.slotRecipes"],
248
- recipes: ["theme.recipes", "theme.slotRecipes"],
249
- "patterns-index": ["syntax", "patterns"],
250
- patterns: ["syntax", "patterns"],
251
- "jsx-is-valid-prop": common,
252
- "jsx-factory": jsx,
253
- "jsx-helpers": jsx,
254
- "jsx-patterns": jsx.concat("patterns"),
255
- "jsx-patterns-index": jsx.concat("patterns"),
256
- "jsx-create-style-context": jsx,
257
- "css-index": ["syntax"],
258
- "package.json": ["forceConsistentTypeExtension", "outExtension"],
259
- "types-styles": ["shorthands"],
260
- "types-conditions": ["conditions"],
261
- "types-jsx": jsx,
262
- "types-entry": [],
263
- "types-gen": [],
264
- "types-gen-system": [],
265
- themes: ["themes"].concat(tokens),
266
- // staticCss depends on tokens (for wildcards) and recipes (for recipe rules)
267
- "static-css": ["staticCss", "patterns", "theme.recipes", "theme.slotRecipes"].concat(tokens),
268
- // Split CSS artifacts (generated via cssgen --splitting)
269
- styles: [],
270
- "styles.css": []
271
- };
272
- var artifactMatchers = Object.entries(artifactConfigDeps).map(([key, paths]) => {
273
- if (!paths.length) return () => void 0;
274
- return createMatcher(key, paths.concat(all));
275
- });
276
-
277
- // src/diff-config.ts
278
- var runIfFn = (fn) => typeof fn === "function" ? fn() : fn;
279
- var hasRecipeStateTransition = (prevConfig, nextConfig) => {
280
- const prevRecipes = prevConfig.theme?.recipes ?? {};
281
- const prevSlotRecipes = prevConfig.theme?.slotRecipes ?? {};
282
- const prevHasRecipes = Object.keys(prevRecipes).length > 0 || Object.keys(prevSlotRecipes).length > 0;
283
- const nextRecipes = nextConfig.theme?.recipes ?? {};
284
- const nextSlotRecipes = nextConfig.theme?.slotRecipes ?? {};
285
- const nextHasRecipes = Object.keys(nextRecipes).length > 0 || Object.keys(nextSlotRecipes).length > 0;
286
- return prevHasRecipes !== nextHasRecipes;
287
- };
288
- function diffConfigs(config, prevConfig) {
289
- const affected = {
290
- artifacts: /* @__PURE__ */ new Set(),
291
- hasConfigChanged: false,
292
- diffs: []
293
- };
294
- if (!prevConfig) {
295
- affected.hasConfigChanged = true;
296
- return affected;
297
- }
298
- const configDiff = (0, import_microdiff.default)(prevConfig, runIfFn(config));
299
- if (!configDiff.length) {
300
- return affected;
301
- }
302
- affected.hasConfigChanged = true;
303
- affected.diffs = configDiff;
304
- configDiff.forEach((change) => {
305
- const changePath = change.path.join(".");
306
- artifactMatchers.forEach((matcher) => {
307
- const id = matcher(changePath);
308
- if (!id) return;
309
- if (id === "recipes") {
310
- const name = (0, import_shared3.dashCase)(change.path.slice(1, 3).join("."));
311
- affected.artifacts.add(name);
312
- }
313
- if (id === "patterns") {
314
- const name = (0, import_shared3.dashCase)(change.path.slice(0, 2).join("."));
315
- affected.artifacts.add(name);
316
- }
317
- affected.artifacts.add(id);
318
- });
319
- });
320
- if (affected.artifacts.has("recipes") || affected.artifacts.has("recipes-index")) {
321
- const nextConfig = runIfFn(config);
322
- if (hasRecipeStateTransition(prevConfig, nextConfig)) {
323
- affected.artifacts.add("create-recipe");
324
- }
325
- }
326
- return affected;
327
- }
328
-
329
- // src/get-mod-deps.ts
330
- var import_fs = __toESM(require("fs"));
331
- var import_path4 = __toESM(require("path"));
332
- var import_typescript = __toESM(require("typescript"));
333
-
334
- // src/resolve-ts-path-pattern.ts
335
- var import_path2 = require("path");
336
- var resolveTsPathPattern = (pathMappings, moduleSpecifier) => {
337
- for (const mapping of pathMappings) {
338
- const match = moduleSpecifier.match(mapping.pattern);
339
- if (!match) {
340
- continue;
341
- }
342
- for (const pathTemplate of mapping.paths) {
343
- let starCount = 0;
344
- const mappedId = pathTemplate.replace(/\*/g, () => {
345
- const matchIndex = Math.min(++starCount, match.length - 1);
346
- return match[matchIndex];
347
- });
348
- return mappedId.split(import_path2.sep).join(import_path2.posix.sep);
202
+ for (const plugin of plugins) {
203
+ if (!isPlainObject(plugin) || typeof plugin.name !== "string" || plugin.name.length === 0) {
204
+ throw new PandaError(
205
+ "CONFIG_ERROR",
206
+ "\u{1F4A5} Every plugin in `config.plugins` must be an object with a non-empty `name`."
207
+ );
349
208
  }
350
209
  }
351
- };
352
-
353
- // src/ts-config-paths.ts
354
- var import_path3 = require("path");
355
- function convertTsPathsToRegexes(paths, baseUrl) {
356
- const sortedPatterns = Object.keys(paths).sort((a, b) => getPrefixLength(b) - getPrefixLength(a));
357
- const resolved = [];
358
- for (let pattern of sortedPatterns) {
359
- const relativePaths = paths[pattern];
360
- pattern = escapeStringRegexp(pattern).replace(/\*/g, "(.+)");
361
- resolved.push({
362
- pattern: new RegExp("^" + pattern + "$"),
363
- paths: relativePaths.map((relativePath) => (0, import_path3.resolve)(baseUrl, relativePath))
364
- });
210
+ if (plugins.length > 0) {
211
+ config.plugins = plugins;
365
212
  }
366
- return resolved;
213
+ return config;
367
214
  }
368
- function getPrefixLength(pattern) {
369
- const prefixLength = pattern.indexOf("*");
370
- return pattern.substr(0, prefixLength).length;
215
+ async function collectConfigs(config, source, ctx, active) {
216
+ if (active.has(config)) {
217
+ throw new PandaError("CONFIG_ERROR", "\u{1F4A5} Circular preset dependency detected.");
218
+ }
219
+ active.add(config);
220
+ const hookCount = ctx.presetResolvedHooks.length;
221
+ ctx.presetResolvedHooks.push(...collectPresetResolvedHooks(config));
222
+ for (const preset of config.presets ?? []) {
223
+ const resolved = await resolvePreset(preset, ctx.cwd);
224
+ resolved.dependencies.forEach((dependency) => ctx.dependencies.add(dependency));
225
+ const config2 = await runPresetResolvedHooks(resolved.config, resolved.source, ctx.presetResolvedHooks);
226
+ await collectConfigs(config2, resolved.source, ctx, active);
227
+ }
228
+ ctx.configs.push(config);
229
+ ctx.sourcedConfigs?.push({ config, source });
230
+ ctx.presetResolvedHooks.length = hookCount;
231
+ active.delete(config);
371
232
  }
372
- function escapeStringRegexp(string) {
373
- return string.replace(/[|\\{}()[\]^$+?.]/g, "\\$&").replace(/-/g, "\\x2d");
233
+ function collectPresetResolvedHooks(config) {
234
+ return collectPluginHookHandlers(config, "preset:resolved");
374
235
  }
375
-
376
- // src/get-mod-deps.ts
377
- var jsExtensions = [".js", ".cjs", ".mjs"];
378
- var jsResolutionOrder = ["", ".js", ".cjs", ".mjs", ".ts", ".cts", ".mts", ".jsx", ".tsx"];
379
- var tsResolutionOrder = ["", ".ts", ".cts", ".mts", ".tsx", ".js", ".cjs", ".mjs", ".jsx"];
380
- function resolveWithExtension(file, extensions) {
381
- for (const ext of extensions) {
382
- const full = `${file}${ext}`;
383
- if (import_fs.default.existsSync(full) && import_fs.default.statSync(full).isFile()) {
384
- return full;
385
- }
386
- }
387
- for (const ext of extensions) {
388
- const full = `${file}/index${ext}`;
389
- if (import_fs.default.existsSync(full)) {
390
- return full;
236
+ async function runPresetResolvedHooks(preset, source, hooks) {
237
+ let current = preset;
238
+ const name = source.name ?? source.specifier ?? presetName(current) ?? "unknown-preset";
239
+ for (const entry of hooks) {
240
+ const hook = normalizeHook(entry.value, "preset:resolved");
241
+ const next = await hook.handler({ preset: current, name });
242
+ if (next !== void 0) {
243
+ current = ensureConfigObject(next, name);
391
244
  }
392
245
  }
393
- return null;
246
+ return current;
394
247
  }
395
- var importRegex = /import[\s\S]*?['"](.{3,}?)['"]/gi;
396
- var importFromRegex = /import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi;
397
- var requireRegex = /require\(['"`](.+)['"`]\)/gi;
398
- var exportRegex = /export[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi;
399
- function getDeps(opts, fromAlias) {
400
- const { filename, seen } = opts;
401
- const { moduleResolution: _, ...compilerOptions } = opts.compilerOptions ?? {};
402
- const absoluteFile = resolveWithExtension(
403
- import_path4.default.resolve(opts.cwd, filename),
404
- jsExtensions.includes(opts.ext) ? jsResolutionOrder : tsResolutionOrder
405
- );
406
- if (absoluteFile === null) return;
407
- if (fromAlias) {
408
- opts.foundModuleAliases.set(fromAlias, absoluteFile);
409
- }
410
- if (seen.size > 1 && seen.has(absoluteFile)) return;
411
- seen.add(absoluteFile);
412
- const contents = import_fs.default.readFileSync(absoluteFile, "utf-8");
413
- const fileDeps = [
414
- ...contents.matchAll(importRegex),
415
- ...contents.matchAll(importFromRegex),
416
- ...contents.matchAll(requireRegex),
417
- ...contents.matchAll(exportRegex)
418
- ];
419
- if (!fileDeps.length) return;
420
- const nextOpts = {
421
- // Resolve new base for new imports/requires
422
- cwd: import_path4.default.dirname(absoluteFile),
423
- ext: import_path4.default.extname(absoluteFile),
424
- seen,
425
- baseUrl: opts.baseUrl,
426
- pathMappings: opts.pathMappings,
427
- foundModuleAliases: opts.foundModuleAliases
428
- };
429
- fileDeps.forEach((match) => {
430
- const mod = match[1];
431
- if (mod[0] === ".") {
432
- getDeps(Object.assign({}, nextOpts, { filename: mod }));
433
- return;
434
- }
248
+ async function resolvePreset(preset, cwd) {
249
+ if (typeof preset === "string") {
435
250
  try {
436
- const found = import_typescript.default.resolveModuleName(mod, absoluteFile, compilerOptions, import_typescript.default.sys).resolvedModule;
437
- if (found && found.extension.endsWith("ts")) {
438
- getDeps(Object.assign({}, nextOpts, { filename: found.resolvedFileName }));
439
- return;
440
- }
441
- if (!opts.pathMappings) return;
442
- const filename2 = resolveTsPathPattern(opts.pathMappings, mod);
443
- if (!filename2) return;
444
- getDeps(Object.assign({}, nextOpts, { filename: filename2 }), mod);
445
- } catch {
251
+ const result = await bundleConfig(preset, cwd);
252
+ return {
253
+ config: ensureConfigObject(result.config, preset),
254
+ dependencies: result.dependencies,
255
+ source: presetSource(result.config, preset, result.dependencies[0])
256
+ };
257
+ } catch (error) {
258
+ if (error instanceof PandaError) throw error;
259
+ throw new PandaError(
260
+ "CONFIG_ERROR",
261
+ `\u{1F4A5} Failed to resolve preset ${JSON.stringify(preset)}: ${errorMessage(error)}`
262
+ );
446
263
  }
447
- });
264
+ }
265
+ try {
266
+ const config = await preset;
267
+ return {
268
+ config: ensureConfigObject(config, config?.name ?? "unknown-preset"),
269
+ dependencies: [],
270
+ source: presetSource(config)
271
+ };
272
+ } catch (error) {
273
+ if (error instanceof PandaError) throw error;
274
+ throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Failed to resolve preset "unknown-preset": ${errorMessage(error)}`);
275
+ }
448
276
  }
449
- function getConfigDependencies(filePath, tsOptions = { pathMappings: [] }, compilerOptions) {
450
- if (filePath === null) return { deps: /* @__PURE__ */ new Set(), aliases: /* @__PURE__ */ new Map() };
451
- const foundModuleAliases = /* @__PURE__ */ new Map();
452
- const deps = /* @__PURE__ */ new Set();
453
- deps.add(filePath);
454
- getDeps({
455
- filename: filePath,
456
- ext: import_path4.default.extname(filePath),
457
- cwd: import_path4.default.dirname(filePath),
458
- seen: deps,
459
- baseUrl: tsOptions.baseUrl,
460
- pathMappings: tsOptions.pathMappings ?? [],
461
- foundModuleAliases,
462
- compilerOptions
463
- });
464
- return { deps, aliases: foundModuleAliases };
277
+ function ensureConfigObject(config, name) {
278
+ if (isPlainObject(config)) return config;
279
+ throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Preset ${JSON.stringify(name)} must resolve to an object.`);
465
280
  }
466
-
467
- // src/get-resolved-config.ts
468
- var import_shared6 = require("@pandacss/shared");
469
-
470
- // src/merge-config.ts
471
- var import_shared5 = require("@pandacss/shared");
472
-
473
- // src/merge-hooks.ts
474
- var import_logger2 = require("@pandacss/logger");
475
- var mergeHooks = (plugins) => {
476
- const hooksFns = {};
477
- plugins.forEach(({ name, hooks }) => {
478
- Object.entries(hooks ?? {}).forEach(([key, value]) => {
479
- if (!hooksFns[key]) {
480
- hooksFns[key] = [];
481
- }
482
- hooksFns[key].push([name, value]);
483
- });
484
- });
485
- const mergedHooks = Object.fromEntries(
486
- Object.entries(hooksFns).map(([key, entries]) => {
487
- const fns = entries.map(([name, fn]) => tryCatch(name, fn));
488
- const reducer = key in reducers ? reducers[key] : void 0;
489
- if (reducer) {
490
- return [key, reducer(fns)];
491
- }
492
- return [key, syncHooks.includes(key) ? callAll(...fns) : callAllAsync(...fns)];
493
- })
494
- );
495
- return mergedHooks;
496
- };
497
- var createReducer = (reducer) => reducer;
498
- var reducers = {
499
- "config:resolved": createReducer((fns) => async (_args) => {
500
- const args = Object.assign({}, _args);
501
- const original = _args.config;
502
- let config = args.config;
503
- for (const hookFn of fns) {
504
- const result = await hookFn(Object.assign(args, { config, original }));
505
- if (result !== void 0) {
506
- config = result;
507
- }
508
- }
509
- return config;
510
- }),
511
- "parser:before": createReducer((fns) => (_args) => {
512
- const args = Object.assign({}, _args);
513
- const original = _args.content;
514
- let content = args.content;
515
- for (const hookFn of fns) {
516
- const result = hookFn(Object.assign(args, { content, original }));
517
- if (result !== void 0) {
518
- content = result;
519
- }
520
- }
521
- return content;
522
- }),
523
- "parser:preprocess": createReducer((fns) => (_args) => {
524
- const args = Object.assign({}, _args);
525
- const original = _args.data;
526
- let data = args.data;
527
- for (const hookFn of fns) {
528
- const result = hookFn(Object.assign(args, { data, original }));
529
- if (result !== void 0) {
530
- data = result;
531
- }
532
- }
533
- return data;
534
- }),
535
- "cssgen:done": createReducer((fns) => (_args) => {
536
- const args = Object.assign({}, _args);
537
- const original = _args.content;
538
- let content = args.content;
539
- for (const hookFn of fns) {
540
- const result = hookFn(Object.assign(args, { content, original }));
541
- if (result !== void 0) {
542
- content = result;
543
- }
544
- }
545
- return content;
546
- }),
547
- "codegen:prepare": createReducer((fns) => async (_args) => {
548
- const args = Object.assign({}, _args);
549
- const original = _args.artifacts;
550
- let artifacts = args.artifacts;
551
- for (const hookFn of fns) {
552
- const result = await hookFn(Object.assign(args, { artifacts, original }));
553
- if (result) {
554
- artifacts = result;
555
- }
556
- }
557
- return artifacts;
558
- }),
559
- "preset:resolved": createReducer((fns) => async (_args) => {
560
- const args = Object.assign({}, _args);
561
- const original = _args.preset;
562
- let preset = args.preset;
563
- for (const hookFn of fns) {
564
- const result = await hookFn(Object.assign(args, { preset, original }));
565
- if (result !== void 0) {
566
- preset = result;
567
- }
568
- }
569
- return preset;
570
- }),
571
- "css:optimize": createReducer((fns) => (_args) => {
572
- const args = Object.assign({}, _args);
573
- const original = _args.css;
574
- let css = args.css;
575
- for (const hookFn of fns) {
576
- const result = hookFn(Object.assign(args, { css, original }));
577
- if (result !== void 0) {
578
- css = result;
579
- }
580
- }
581
- return css;
582
- })
583
- };
584
- var syncHooks = [
585
- "context:created",
586
- "parser:before",
587
- "parser:preprocess",
588
- "parser:after",
589
- "cssgen:done",
590
- "css:optimize"
591
- ];
592
- var callAllAsync = (...fns) => async (...a) => {
593
- for (const fn of fns) {
594
- await fn?.(...a);
595
- }
596
- };
597
- var callAll = (...fns) => (...a) => {
598
- fns.forEach((fn) => fn?.(...a));
599
- };
600
- var tryCatch = (name, fn) => {
601
- return (...args) => {
602
- try {
603
- return fn(...args);
604
- } catch (e) {
605
- import_logger2.logger.caughtError("hooks", `Error in plugin "${name}"`, e);
606
- }
607
- };
608
- };
609
-
610
- // src/validation/utils.ts
611
- var import_shared4 = require("@pandacss/shared");
612
- var REFERENCE_REGEX = /({([^}]*)})/g;
613
- var curlyBracketRegex = /[{}]/g;
614
- var isValidToken = (token) => (0, import_shared4.isObject)(token) && Object.hasOwnProperty.call(token, "value");
615
- var isTokenReference = (value) => typeof value === "string" && REFERENCE_REGEX.test(value);
616
- var formatPath = (path2) => path2;
617
- var SEP = ".";
618
- function getReferences(value) {
619
- if (typeof value !== "string") return [];
620
- const matches = value.match(REFERENCE_REGEX);
621
- if (!matches) return [];
622
- return matches.map((match) => match.replace(curlyBracketRegex, "")).map((value2) => {
623
- return value2.trim().split("/")[0];
624
- });
281
+ function presetName(config) {
282
+ return isPlainObject(config) && typeof config.name === "string" ? config.name : void 0;
625
283
  }
626
- var serializeTokenValue = (value) => {
627
- if ((0, import_shared4.isString)(value)) {
628
- return value;
629
- }
630
- if ((0, import_shared4.isObject)(value)) {
631
- return Object.values(value).map((v) => serializeTokenValue(v)).join(" ");
632
- }
633
- if (Array.isArray(value)) {
634
- return value.map((v) => serializeTokenValue(v)).join(" ");
635
- }
636
- return value.toString();
637
- };
638
-
639
- // src/merge-config.ts
640
- function getExtends(items) {
641
- return items.reduce((merged, { extend }) => {
642
- if (!extend) return merged;
643
- return (0, import_shared5.mergeWith)(merged, extend, (originalValue, newValue) => {
644
- if (newValue === void 0) {
645
- return originalValue ?? [];
646
- }
647
- if (originalValue === void 0) {
648
- return [newValue];
649
- }
650
- if (Array.isArray(originalValue)) {
651
- return [newValue, ...originalValue];
652
- }
653
- return [newValue, originalValue];
654
- });
655
- }, {});
284
+ function presetSource(config, specifier, file) {
285
+ const source = { kind: "preset" };
286
+ const name = presetName(config);
287
+ if (name) source.name = name;
288
+ if (specifier) source.specifier = specifier;
289
+ if (file) source.file = file;
290
+ return source;
656
291
  }
657
- function mergeRecords(records) {
658
- return {
659
- ...records.reduce((acc, record) => (0, import_shared5.assign)(acc, record), {}),
660
- extend: getExtends(records)
661
- };
292
+ function errorMessage(error) {
293
+ return error instanceof Error ? error.message : String(error);
662
294
  }
663
- function mergeExtensions(records) {
664
- const { extend = [], ...restProps } = mergeRecords(records);
665
- return (0, import_shared5.mergeWith)(restProps, extend, (obj, extensions) => {
666
- return (0, import_shared5.mergeAndConcat)({}, obj, ...extensions);
295
+
296
+ // src/load.ts
297
+ async function loadConfig(options) {
298
+ const { cwd, file } = options;
299
+ const path = findConfig({ cwd, file });
300
+ const { config, dependencies } = await bundleConfig(path, cwd);
301
+ if (!isPlainObject(config)) {
302
+ throw new PandaError("CONFIG_ERROR", "\u{1F4A5} Config must export or return an object.");
303
+ }
304
+ const authored = await resolveAuthoredPresets(config, cwd, {
305
+ configFile: path,
306
+ trackSources: options.trackSources,
307
+ preserveRuntimeHooks: true
667
308
  });
668
- }
669
- var isEmptyObject = (obj) => typeof obj === "object" && Object.keys(obj).length === 0;
670
- var compact = (obj) => {
671
- return Object.keys(obj).reduce((acc, key) => {
672
- if (obj[key] !== void 0 && !isEmptyObject(obj[key])) {
673
- acc[key] = obj[key];
674
- }
675
- return acc;
676
- }, {});
677
- };
678
- var tokenKeys = ["description", "extensions", "type", "value", "deprecated"];
679
- function mergeConfigs(configs) {
680
- const userConfig = configs.at(-1);
681
- const pluginHooks = userConfig.plugins ?? [];
682
- if (userConfig.hooks) {
683
- pluginHooks.push({ name: import_shared5.PANDA_CONFIG_NAME, hooks: userConfig.hooks });
684
- }
685
- const reversed = Array.from(configs).reverse();
686
- const mergedResult = (0, import_shared5.assign)(
687
- {
688
- conditions: mergeExtensions(reversed.map((config) => config.conditions ?? {})),
689
- theme: mergeExtensions(reversed.map((config) => config.theme ?? {})),
690
- patterns: mergeExtensions(reversed.map((config) => config.patterns ?? {})),
691
- utilities: mergeExtensions(reversed.map((config) => config.utilities ?? {})),
692
- globalCss: mergeExtensions(reversed.map((config) => config.globalCss ?? {})),
693
- globalVars: mergeExtensions(reversed.map((config) => config.globalVars ?? {})),
694
- globalFontface: mergeExtensions(reversed.map((config) => config.globalFontface ?? {})),
695
- globalPositionTry: mergeExtensions(reversed.map((config) => config.globalPositionTry ?? {})),
696
- staticCss: mergeExtensions(reversed.map((config) => config.staticCss ?? {})),
697
- themes: mergeExtensions(reversed.map((config) => config.themes ?? {})),
698
- hooks: mergeHooks(pluginHooks)
699
- },
700
- ...reversed
309
+ const authoredDependencies = Array.from(
310
+ /* @__PURE__ */ new Set([...dependencies, ...authored.dependencies, ...authored.config.dependencies ?? []])
701
311
  );
702
- const withoutEmpty = compact(mergedResult);
703
- if (withoutEmpty.theme?.tokens) {
704
- (0, import_shared5.walkObject)(withoutEmpty.theme.tokens, (args) => args, {
705
- stop(token) {
706
- if (!isValidToken(token)) return false;
707
- const keys = Object.keys(token);
708
- const nestedKeys = keys.filter((k) => !tokenKeys.includes(k));
709
- const nested = nestedKeys.length > 0;
710
- if (nested) {
711
- token.DEFAULT ||= {};
712
- tokenKeys.forEach((key) => {
713
- if (token[key] == null) return;
714
- token.DEFAULT[key] ||= token[key];
715
- delete token[key];
716
- });
717
- }
718
- return true;
719
- }
720
- });
721
- }
722
- return withoutEmpty;
312
+ const userConfig = await runConfigResolvedHooks(authored.config, path, authoredDependencies);
313
+ const resolved = applyConfigDefaults(userConfig, cwd);
314
+ const dependencyList = Array.from(
315
+ /* @__PURE__ */ new Set([...dependencies, ...authored.dependencies, ...resolved.dependencies ?? []])
316
+ );
317
+ const snapshot = createConfigSnapshot(resolved);
318
+ return {
319
+ path,
320
+ config: snapshot.config,
321
+ callbacks: snapshot.callbacks,
322
+ ...snapshot.hooks ? { hooks: snapshot.hooks } : {},
323
+ hostHooks: {
324
+ "codegen:prepare": collectPluginHookHandlers(resolved, "codegen:prepare"),
325
+ "codegen:done": collectPluginHookHandlers(resolved, "codegen:done")
326
+ },
327
+ dependencies: dependencyList,
328
+ ...authored.metadata ? { metadata: authored.metadata } : {}
329
+ };
723
330
  }
724
-
725
- // src/get-resolved-config.ts
726
- var hookUtils = {
727
- omit: import_shared6.omit,
728
- pick: import_shared6.pick,
729
- traverse: import_shared6.traverse
730
- };
731
- async function getResolvedConfig(config, cwd, hooks) {
732
- const stack = [config];
733
- const configs = [];
734
- while (stack.length > 0) {
735
- const current = stack.pop();
736
- const subPresets = current.presets ?? [];
737
- for (const subPreset of subPresets) {
738
- let presetConfig;
739
- let presetName;
740
- if (typeof subPreset === "string") {
741
- const presetModule = await bundle(subPreset, cwd);
742
- presetConfig = presetModule.config;
743
- presetName = subPreset;
744
- } else {
745
- presetConfig = await subPreset;
746
- presetName = presetConfig.name || "unknown-preset";
747
- }
748
- if (hooks?.["preset:resolved"]) {
749
- const resolvedPreset = await hooks["preset:resolved"]({
750
- preset: presetConfig,
751
- name: presetName,
752
- utils: hookUtils
753
- });
754
- if (resolvedPreset !== void 0) {
755
- presetConfig = resolvedPreset;
756
- }
331
+ async function runConfigResolvedHooks(config, path, dependencies) {
332
+ let current = config;
333
+ for (const entry of collectPluginHookHandlers(current, "config:resolved")) {
334
+ const hook = normalizeHook(entry.value, "config:resolved");
335
+ const next = await hook.handler({ config: current, path, dependencies, utils: configResolvedUtils });
336
+ if (next !== void 0) {
337
+ if (!isPlainObject(next)) {
338
+ throw new PandaError("CONFIG_ERROR", "\u{1F4A5} config:resolved hook must return a config object or undefined.");
757
339
  }
758
- stack.push(presetConfig);
340
+ current = next;
759
341
  }
760
- configs.unshift(current);
761
342
  }
762
- const merged = mergeConfigs(configs);
763
- merged.presets = configs.slice(0, -1);
764
- return merged;
343
+ return current;
765
344
  }
766
-
767
- // src/resolve-config.ts
768
- var import_logger4 = require("@pandacss/logger");
769
- var import_shared11 = require("@pandacss/shared");
770
-
771
- // src/bundled-preset.ts
772
- var import_preset_base = require("@pandacss/preset-base");
773
- var import_preset_panda = require("@pandacss/preset-panda");
774
- var bundledPresets = {
775
- "@pandacss/preset-base": import_preset_base.preset,
776
- "@pandacss/preset-panda": import_preset_panda.preset,
777
- "@pandacss/dev/presets": import_preset_panda.preset
778
- };
779
- var bundledPresetsNames = Object.keys(bundledPresets);
780
- var isBundledPreset = (preset) => bundledPresetsNames.includes(preset);
781
- var getBundledPreset = (preset) => {
782
- return typeof preset === "string" && isBundledPreset(preset) ? bundledPresets[preset] : void 0;
783
- };
784
-
785
- // src/validate-config.ts
786
- var import_logger3 = require("@pandacss/logger");
787
- var import_shared10 = require("@pandacss/shared");
788
-
789
- // src/validation/validate-artifact.ts
790
- var validateArtifactNames = (names, addError) => {
791
- names.recipes.forEach((recipeName) => {
792
- if (names.slotRecipes.has(recipeName)) {
793
- addError("recipes", `This recipe name is already used in \`theme.slotRecipes\`: ${recipeName}`);
794
- }
795
- if (names.patterns.has(recipeName)) {
796
- addError("recipes", `This recipe name is already used in \`patterns\`: \`${recipeName}\``);
797
- }
798
- });
799
- names.slotRecipes.forEach((recipeName) => {
800
- if (names.patterns.has(recipeName)) {
801
- addError("recipes", `This recipe name is already used in \`patterns\`: ${recipeName}`);
345
+ var configResolvedUtils = {
346
+ omit(obj, paths) {
347
+ const clone = cloneValue(obj);
348
+ for (const path of paths) {
349
+ deleteAtPath(clone, path);
350
+ }
351
+ return clone;
352
+ },
353
+ pick(obj, paths) {
354
+ const result = {};
355
+ for (const path of paths) {
356
+ const value = getAtPath(obj, path);
357
+ if (value !== void 0) {
358
+ setAtPath(result, path, value);
359
+ }
802
360
  }
803
- });
804
- };
805
-
806
- // src/validation/validate-breakpoints.ts
807
- var import_shared7 = require("@pandacss/shared");
808
- var validateBreakpoints = (breakpoints, addError) => {
809
- if (!breakpoints) return;
810
- const units = /* @__PURE__ */ new Set();
811
- const values = Object.values(breakpoints);
812
- for (const value of values) {
813
- const unit = (0, import_shared7.getUnit)(value) ?? "px";
814
- units.add(unit);
815
- }
816
- if (units.size > 1) {
817
- addError("breakpoints", `All breakpoints must use the same unit: \`${values.join(", ")}\``);
361
+ return result;
362
+ },
363
+ traverse(obj, callback, options = {}) {
364
+ traverseValue(obj, callback, options);
818
365
  }
819
366
  };
820
-
821
- // src/validation/validate-condition.ts
822
- var import_shared8 = require("@pandacss/shared");
823
- var validateObjectCondition = (obj, addError) => {
824
- let hasSlot = false;
825
- for (const [key, value] of Object.entries(obj)) {
826
- if (!key.startsWith("@") && !key.includes("&")) {
827
- addError("conditions", `Selectors should contain the \`&\` character: \`${key}\``);
828
- }
829
- if (value === "@slot") {
830
- hasSlot = true;
831
- continue;
832
- }
833
- if (typeof value === "string") {
834
- addError(
835
- "conditions",
836
- `Object condition leaves must be the literal string \`'@slot'\`, got \`${JSON.stringify(value)}\` at \`${key}\``
837
- );
838
- continue;
839
- }
840
- if (typeof value === "object" && value !== null) {
841
- const nested = validateObjectCondition(value, addError);
842
- if (nested.hasSlot) hasSlot = true;
843
- }
367
+ function cloneValue(value) {
368
+ if (Array.isArray(value)) return value.map((item) => cloneValue(item));
369
+ if (!isPlainObject(value)) return value;
370
+ return Object.fromEntries(
371
+ Object.entries(value).map(([key, child]) => [key, cloneValue(child)])
372
+ );
373
+ }
374
+ function pathParts(path) {
375
+ return path.split(".").filter(Boolean);
376
+ }
377
+ function getAtPath(value, path) {
378
+ let current = value;
379
+ for (const part of pathParts(path)) {
380
+ if (!isPlainObject(current) && !Array.isArray(current)) return void 0;
381
+ current = current[part];
844
382
  }
845
- return { hasSlot };
846
- };
847
- var validateConditions = (conditions, addError) => {
848
- if (!conditions) return;
849
- Object.values(conditions).forEach((condition) => {
850
- if ((0, import_shared8.isString)(condition)) {
851
- if (!condition.startsWith("@") && !condition.includes("&")) {
852
- addError("conditions", `Selectors should contain the \`&\` character: \`${condition}\``);
853
- }
854
- return;
855
- }
856
- if (Array.isArray(condition)) {
857
- condition.forEach((c) => {
858
- if (!c.startsWith("@") && !c.includes("&")) {
859
- addError("conditions", `Selectors should contain the \`&\` character: \`${c}\``);
860
- }
861
- });
383
+ return current;
384
+ }
385
+ function setAtPath(target, path, value) {
386
+ const parts = pathParts(path);
387
+ let current = target;
388
+ parts.forEach((part, index) => {
389
+ if (index === parts.length - 1) {
390
+ current[part] = cloneValue(value);
862
391
  return;
863
392
  }
864
- const { hasSlot } = validateObjectCondition(condition, addError);
865
- if (!hasSlot) {
866
- addError("conditions", `Object conditions must contain at least one \`'@slot'\` marker`);
393
+ const next = current[part];
394
+ if (!isPlainObject(next)) {
395
+ current[part] = {};
867
396
  }
397
+ current = current[part];
868
398
  });
869
- };
870
-
871
- // src/validation/validate-patterns.ts
872
- var validatePatterns = (patterns, names) => {
873
- if (!patterns) return;
874
- Object.keys(patterns).forEach((patternName) => {
875
- names.patterns.add(patternName);
876
- });
877
- };
878
-
879
- // src/validation/validate-recipes.ts
880
- var validateRecipes = (options) => {
881
- const {
882
- config: { theme },
883
- artifacts
884
- } = options;
885
- if (!theme) return;
886
- if (theme.recipes) {
887
- Object.keys(theme.recipes).forEach((recipeName) => {
888
- artifacts.recipes.add(recipeName);
889
- });
890
- }
891
- if (theme.slotRecipes) {
892
- Object.keys(theme.slotRecipes).forEach((recipeName) => {
893
- artifacts.slotRecipes.add(recipeName);
894
- });
399
+ }
400
+ function deleteAtPath(target, path) {
401
+ const parts = pathParts(path);
402
+ const key = parts.pop();
403
+ if (!key) return;
404
+ let current = target;
405
+ for (const part of parts) {
406
+ if (!isPlainObject(current) && !Array.isArray(current)) return;
407
+ current = current[part];
408
+ }
409
+ if (isPlainObject(current) || Array.isArray(current)) {
410
+ delete current[key];
895
411
  }
896
- return artifacts;
897
- };
898
-
899
- // src/validation/validate-tokens.ts
900
- var import_shared9 = require("@pandacss/shared");
901
-
902
- // src/validation/validate-token-references.ts
903
- var validateTokenReferences = (props) => {
904
- const { valueAtPath, refsByPath, addError, typeByPath } = props;
905
- refsByPath.forEach((refs, path2) => {
906
- if (refs.has(path2)) {
907
- addError("tokens", `Self token reference: \`${path2}\``);
908
- }
909
- const stack = [path2];
910
- while (stack.length > 0) {
911
- let currentPath = stack.pop();
912
- if (currentPath.includes("/")) {
913
- const [tokenPath] = currentPath.split("/");
914
- currentPath = tokenPath;
915
- }
916
- const value = valueAtPath.get(currentPath);
917
- if (!value) {
918
- const configKey = typeByPath.get(path2);
919
- addError("tokens", `Missing token: \`${currentPath}\` used in \`theme.${configKey}.${path2}\``);
920
- }
921
- if (isTokenReference(value) && !refsByPath.has(value)) {
922
- addError("tokens", `Unknown token reference: \`${currentPath}\` used in \`${value}\``);
923
- }
924
- const deps = refsByPath.get(currentPath);
925
- if (!deps) continue;
926
- for (const transitiveDep of deps) {
927
- if (path2 === transitiveDep) {
928
- addError(
929
- "tokens",
930
- `Circular token reference: \`${transitiveDep}\` -> \`${currentPath}\` -> ... -> \`${path2}\``
931
- );
932
- break;
933
- }
934
- stack.push(transitiveDep);
935
- }
936
- }
412
+ }
413
+ function traverseValue(value, callback, options, parent, key, path = "", depth = 0) {
414
+ if (parent && key !== void 0) {
415
+ callback({ value, path, depth, parent, key });
416
+ }
417
+ if (options.maxDepth !== void 0 && depth >= options.maxDepth) return;
418
+ if (!isPlainObject(value) && !Array.isArray(value)) return;
419
+ const separator = options.separator ?? ".";
420
+ const container = value;
421
+ Object.entries(value).forEach(([childKey, child]) => {
422
+ traverseValue(child, callback, options, container, childKey, joinPath(path, childKey, separator), depth + 1);
937
423
  });
938
- };
424
+ }
425
+ function joinPath(parent, key, separator) {
426
+ return parent ? `${parent}${separator}${key}` : key;
427
+ }
939
428
 
940
- // src/validation/validate-tokens.ts
941
- var validateTokens = (options) => {
942
- const {
943
- config: { theme },
944
- tokens: tokens2,
945
- addError
946
- } = options;
947
- if (!theme) return;
948
- const { tokenNames, semanticTokenNames, valueAtPath, refsByPath, typeByPath } = tokens2;
949
- if (theme.tokens) {
950
- const tokenPaths = /* @__PURE__ */ new Set();
951
- (0, import_shared9.walkObject)(
952
- theme.tokens,
953
- (value, paths) => {
954
- const path2 = paths.join(SEP);
955
- tokenNames.add(path2);
956
- tokenPaths.add(path2);
957
- valueAtPath.set(path2, value);
958
- if (path2.includes("DEFAULT")) {
959
- valueAtPath.set(path2.replace(SEP + "DEFAULT", ""), value);
960
- }
961
- },
962
- {
963
- stop: isValidToken
964
- }
965
- );
966
- tokenPaths.forEach((path2) => {
967
- const itemValue = valueAtPath.get(path2);
968
- const formattedPath = formatPath(path2);
969
- typeByPath.set(formattedPath, "tokens");
970
- if (!isValidToken(itemValue)) {
971
- addError("tokens", `Token must contain 'value': \`theme.tokens.${formattedPath}\``);
972
- return;
973
- }
974
- if (path2.includes(" ")) {
975
- addError("tokens", `Token key must not contain spaces: \`theme.tokens.${formattedPath}\``);
976
- return;
977
- }
978
- const valueStr = serializeTokenValue(itemValue.value || itemValue);
979
- if (isTokenReference(valueStr)) {
980
- refsByPath.set(formattedPath, /* @__PURE__ */ new Set([]));
981
- }
982
- const references = refsByPath.get(formattedPath);
983
- if (!references) return;
984
- getReferences(valueStr).forEach((reference) => {
985
- references.add(reference);
986
- });
987
- });
988
- }
989
- if (theme.semanticTokens) {
990
- const tokenPaths = /* @__PURE__ */ new Set();
991
- (0, import_shared9.walkObject)(
992
- theme.semanticTokens,
993
- (value, paths) => {
994
- const path2 = paths.join(SEP);
995
- semanticTokenNames.add(path2);
996
- valueAtPath.set(path2, value);
997
- tokenPaths.add(path2);
998
- if (path2.includes("DEFAULT")) {
999
- valueAtPath.set(path2.replace(SEP + "DEFAULT", ""), value);
1000
- }
1001
- if (!isValidToken(value)) return;
1002
- (0, import_shared9.walkObject)(value, (itemValue, paths2) => {
1003
- const valuePath = paths2.join(SEP);
1004
- const formattedPath = formatPath(path2);
1005
- typeByPath.set(formattedPath, "semanticTokens");
1006
- const fullPath = formattedPath + "." + paths2.join(SEP);
1007
- if (valuePath.includes("value" + SEP + "value")) {
1008
- addError("tokens", `You used \`value\` twice resulting in an invalid token \`theme.tokens.${fullPath}\``);
1009
- }
1010
- const valueStr = serializeTokenValue(itemValue.value || itemValue);
1011
- if (isTokenReference(valueStr)) {
1012
- if (!refsByPath.has(formattedPath)) {
1013
- refsByPath.set(formattedPath, /* @__PURE__ */ new Set());
1014
- }
1015
- const references = refsByPath.get(formattedPath);
1016
- if (!references) return;
1017
- getReferences(valueStr).forEach((reference) => {
1018
- references.add(reference);
1019
- });
1020
- }
1021
- });
1022
- },
1023
- {
1024
- stop: isValidToken
1025
- }
1026
- );
1027
- tokenPaths.forEach((path2) => {
1028
- const formattedPath = formatPath(path2);
1029
- const value = valueAtPath.get(path2);
1030
- if (path2.includes(" ")) {
1031
- addError("tokens", `Token key must not contain spaces: \`theme.tokens.${formattedPath}\``);
1032
- return;
1033
- }
1034
- if (!(0, import_shared9.isObject)(value) && !path2.includes("value")) {
1035
- addError("tokens", `Token must contain 'value': \`theme.semanticTokens.${formattedPath}\``);
1036
- }
1037
- });
429
+ // src/diff.ts
430
+ import diff from "microdiff";
431
+ var ALL_DEPENDENCIES = [
432
+ "outExtension",
433
+ "forceImportExtension",
434
+ "conditions",
435
+ "hash",
436
+ "jsxFactory",
437
+ "jsxFramework",
438
+ "jsxStyleProps",
439
+ "patterns",
440
+ "prefix",
441
+ "recipes",
442
+ "separator",
443
+ "syntax",
444
+ "themes",
445
+ "tokens",
446
+ "utilities"
447
+ ];
448
+ function diffConfig(prev, next) {
449
+ if (!prev) {
450
+ return { hasChanged: true, dependencies: [...ALL_DEPENDENCIES], recipes: [], patterns: [], changes: [] };
451
+ }
452
+ const prevInput = diffInput(prev);
453
+ const nextInput = diffInput(next);
454
+ const changes = diff(prevInput, nextInput);
455
+ if (changes.length === 0) {
456
+ return { hasChanged: false, dependencies: [], recipes: [], patterns: [], changes };
457
+ }
458
+ const dependencies = /* @__PURE__ */ new Set();
459
+ const recipes = /* @__PURE__ */ new Set();
460
+ const patterns = /* @__PURE__ */ new Set();
461
+ for (const change of changes) {
462
+ const classified = classify(change.path.map(String));
463
+ classified.deps.forEach((dep) => dependencies.add(dep));
464
+ if (classified.recipe) recipes.add(classified.recipe);
465
+ if (classified.pattern) patterns.add(classified.pattern);
1038
466
  }
1039
- validateTokenReferences({ valueAtPath, refsByPath, addError, typeByPath });
1040
- };
1041
-
1042
- // src/validate-config.ts
1043
- var validateConfig = (config) => {
1044
- if (config.validation === "none") return;
1045
- const warnings = /* @__PURE__ */ new Set();
1046
- const addError = (scope, message) => {
1047
- warnings.add(`[${scope}] ` + message);
1048
- };
1049
- validateBreakpoints(config.theme?.breakpoints, addError);
1050
- validateConditions(config.conditions, addError);
1051
- const artifacts = {
1052
- recipes: /* @__PURE__ */ new Set(),
1053
- slotRecipes: /* @__PURE__ */ new Set(),
1054
- patterns: /* @__PURE__ */ new Set()
1055
- };
1056
- const tokens2 = {
1057
- tokenNames: /* @__PURE__ */ new Set(),
1058
- semanticTokenNames: /* @__PURE__ */ new Set(),
1059
- valueAtPath: /* @__PURE__ */ new Map(),
1060
- refsByPath: /* @__PURE__ */ new Map(),
1061
- typeByPath: /* @__PURE__ */ new Map()
467
+ return {
468
+ hasChanged: true,
469
+ dependencies: [...dependencies],
470
+ recipes: [...recipes],
471
+ patterns: [...patterns],
472
+ changes
1062
473
  };
1063
- if (config.theme) {
1064
- validateTokens({ config, tokens: tokens2, addError });
1065
- validateRecipes({ config, tokens: tokens2, artifacts, addError });
1066
- }
1067
- validatePatterns(config.patterns, artifacts);
1068
- validateArtifactNames(artifacts, addError);
1069
- if (warnings.size) {
1070
- const errors = `\u26A0\uFE0F Invalid config:
1071
- ${Array.from(warnings).map((err) => "- " + err).join("\n")}
1072
- `;
1073
- if (config.validation === "error") {
1074
- throw new import_shared10.PandaError("CONFIG_ERROR", errors);
1075
- }
1076
- import_logger3.logger.warn("config", errors);
1077
- return warnings;
1078
- }
1079
- };
1080
-
1081
- // src/resolve-config.ts
1082
- var hookUtils2 = {
1083
- omit: import_shared11.omit,
1084
- pick: import_shared11.pick,
1085
- traverse: import_shared11.traverse
1086
- };
1087
- async function resolveConfig(result, cwd) {
1088
- const presets = /* @__PURE__ */ new Set();
1089
- if (!result.config.eject) {
1090
- presets.add(import_preset_base.preset);
1091
- }
1092
- if (result.config.presets) {
1093
- result.config.presets.forEach((preset) => {
1094
- presets.add(getBundledPreset(preset) ?? preset);
1095
- });
1096
- } else if (!result.config.eject) {
1097
- presets.add(import_preset_panda.preset);
1098
- }
1099
- result.config.presets = Array.from(presets);
1100
- const userConfig = result.config;
1101
- const pluginHooks = userConfig.plugins ?? [];
1102
- if (userConfig.hooks) {
1103
- pluginHooks.push({ name: import_shared11.PANDA_CONFIG_NAME, hooks: userConfig.hooks });
1104
- }
1105
- const earlyHooks = mergeHooks(pluginHooks);
1106
- const mergedConfig = await getResolvedConfig(result.config, cwd, earlyHooks);
1107
- const hooks = mergedConfig.hooks ?? {};
1108
- if (mergedConfig.logLevel) {
1109
- import_logger4.logger.level = mergedConfig.logLevel;
474
+ }
475
+ function classify(path) {
476
+ const [head, second, third] = path;
477
+ if (head === "config") return classify(path.slice(1));
478
+ if (head === "hooks") return { deps: [] };
479
+ if (head === "theme") {
480
+ if (second === "recipes" || second === "slotRecipes") {
481
+ return { deps: ["recipes"], recipe: third };
482
+ }
483
+ if (second === "containers" || second === "containerNames") {
484
+ return { deps: ["tokens", "conditions"] };
485
+ }
486
+ return { deps: ["tokens"] };
487
+ }
488
+ switch (head) {
489
+ case "conditions":
490
+ return { deps: ["conditions"] };
491
+ case "utilities":
492
+ return { deps: ["utilities"] };
493
+ case "patterns":
494
+ return { deps: ["patterns"], pattern: second };
495
+ case "themes":
496
+ return { deps: ["themes"] };
497
+ case "syntax":
498
+ return { deps: ["syntax"] };
499
+ case "hash":
500
+ return { deps: ["hash"] };
501
+ case "prefix":
502
+ return { deps: ["prefix"] };
503
+ case "separator":
504
+ return { deps: ["separator"] };
505
+ case "jsxFramework":
506
+ return { deps: ["jsxFramework"] };
507
+ case "jsxFactory":
508
+ return { deps: ["jsxFactory"] };
509
+ case "jsxStyleProps":
510
+ return { deps: ["jsxStyleProps"] };
511
+ case "outExtension":
512
+ return { deps: ["outExtension"] };
513
+ case "forceImportExtension":
514
+ return { deps: ["forceImportExtension"] };
515
+ case "shorthands":
516
+ return { deps: ["utilities"] };
517
+ case "strictTokens":
518
+ case "strictPropertyValues":
519
+ return { deps: ["outExtension"] };
520
+ default:
521
+ return { deps: [] };
1110
522
  }
1111
- validateConfig(mergedConfig);
1112
- const loadConfigResult = {
1113
- ...result,
1114
- config: mergedConfig
1115
- };
1116
- if (hooks["config:resolved"]) {
1117
- const result2 = await hooks["config:resolved"]({
1118
- config: loadConfigResult.config,
1119
- path: loadConfigResult.path,
1120
- dependencies: loadConfigResult.dependencies,
1121
- utils: hookUtils2
1122
- });
1123
- if (result2) {
1124
- loadConfigResult.config = result2;
1125
- }
523
+ }
524
+ function diffInput(input) {
525
+ if (isConfigSnapshot(input)) {
526
+ return { config: input.config, ...input.hooks ? { hooks: input.hooks } : {} };
1126
527
  }
1127
- const serialized = (0, import_shared11.stringifyJson)(Object.assign({}, loadConfigResult.config, { name: import_shared11.PANDA_CONFIG_NAME, presets: [] }));
1128
- const deserialize = () => (0, import_shared11.parseJson)(serialized);
1129
- return { ...loadConfigResult, serialized, deserialize, hooks };
528
+ return { config: input };
1130
529
  }
1131
-
1132
- // src/load-config.ts
1133
- async function loadConfig(options) {
1134
- const result = await bundleConfig(options);
1135
- return resolveConfig(result, options.cwd);
530
+ function isConfigSnapshot(input) {
531
+ 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);
1136
532
  }
1137
- // Annotate the CommonJS export names for ESM import in node:
1138
- 0 && (module.exports = {
533
+ export {
1139
534
  bundleConfig,
1140
- convertTsPathsToRegexes,
1141
- diffConfigs,
535
+ createConfigSnapshot,
536
+ diffConfig,
1142
537
  findConfig,
1143
- getConfigDependencies,
1144
- getResolvedConfig,
1145
538
  loadConfig,
1146
- mergeConfigs,
1147
- mergeHooks,
1148
- resolveConfig
1149
- });
539
+ mergeConfigs
540
+ };