sculpted 0.0.0 → 0.1.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.
Files changed (31) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +233 -0
  3. package/dist/index.d.mts +129 -0
  4. package/dist/index.mjs +3 -0
  5. package/dist/patcher-BAw2kF1Q.mjs +2594 -0
  6. package/dist/protocol-BJm-xGHP.mjs +54 -0
  7. package/dist/runtime-DwE3PVhB.d.mts +64 -0
  8. package/dist/runtime.d.mts +2 -0
  9. package/dist/runtime.mjs +613 -0
  10. package/dist/sourceSyntax-DanNzS7Y.d.mts +103 -0
  11. package/dist/types-CdByW0ji.d.mts +381 -0
  12. package/dist/ui.d.mts +54 -0
  13. package/dist/ui.mjs +11125 -0
  14. package/dist/vite.d.mts +85 -0
  15. package/dist/vite.mjs +2325 -0
  16. package/examples/manual-vite-preact-pandacss/README.md +75 -0
  17. package/examples/manual-vite-preact-pandacss/index.html +12 -0
  18. package/examples/manual-vite-preact-pandacss/package.json +23 -0
  19. package/examples/manual-vite-preact-pandacss/panda.config.ts +43 -0
  20. package/examples/manual-vite-preact-pandacss/pnpm-lock.yaml +3359 -0
  21. package/examples/manual-vite-preact-pandacss/pnpm-workspace.yaml +2 -0
  22. package/examples/manual-vite-preact-pandacss/postcss.config.cjs +5 -0
  23. package/examples/manual-vite-preact-pandacss/src/TsrxManualPanel.tsrx +47 -0
  24. package/examples/manual-vite-preact-pandacss/src/index.css +8 -0
  25. package/examples/manual-vite-preact-pandacss/src/main.style.ts +33 -0
  26. package/examples/manual-vite-preact-pandacss/src/main.tsx +484 -0
  27. package/examples/manual-vite-preact-pandacss/src/tsrx.d.ts +5 -0
  28. package/examples/manual-vite-preact-pandacss/tsconfig.json +21 -0
  29. package/examples/manual-vite-preact-pandacss/vite.config.ts +20 -0
  30. package/package.json +66 -8
  31. package/readme.md +0 -1
package/dist/vite.mjs ADDED
@@ -0,0 +1,2325 @@
1
+ import { _ as markerClassForEditId, c as DEFAULT_OPEN_SOURCE_ENDPOINT, d as DEFAULT_TOKEN_WRITEBACK_ENDPOINT, f as DEFAULT_WRITEBACK_ENDPOINT, p as PANDA_INSPECTOR_EVENTS, u as DEFAULT_STYLE_MODULE_ENDPOINT } from "./protocol-BJm-xGHP.mjs";
2
+ import { _ as hashSource, a as createStyleModuleSourcePatch, c as safeProjectSourcePath, d as trustedManifestFilePath, f as trustedTokenSourceFilePath, g as analyzePandaCssSource, h as createInlineCssSourcePatch, i as createStyleModuleDetachPatch, l as stripViteQuery, m as createStaticCssPatch, n as componentStyleModulePaths, o as readComponentStyleModule, p as createStaticCssBatchPatch, r as createStyleModuleAttachPatch, s as normalizePath$1, t as createTokenConfigPatch, u as toRelativeProjectPath$1, x as resolveSourceParserAdapter, y as parsePandaSource } from "./patcher-BAw2kF1Q.mjs";
3
+ import ts from "typescript";
4
+ import { dirname } from "node:path";
5
+ import { access, mkdir, readFile, writeFile } from "node:fs/promises";
6
+ import { loadConfigAndCreateContext } from "@pandacss/node";
7
+ //#region src/vite/constants.ts
8
+ const DEFAULT_EXCLUDE = ["node_modules/**", "styled-system/**"];
9
+ const DEFAULT_RUNTIME_BOOTSTRAP_ENDPOINT = "/@panda-inspector/runtime";
10
+ const DEFAULT_RUNTIME_MODULE_ENDPOINT = "/@panda-inspector/runtime-module";
11
+ const DEFAULT_UI_MODULE_ENDPOINT = "/@panda-inspector/ui-module";
12
+ const DEFAULT_RUNTIME_CHUNK_ENDPOINT = "/@panda-inspector/runtime-chunks/";
13
+ const DEFAULT_RUNTIME_MODULE_SOURCE_MAP_ENDPOINT = `${DEFAULT_RUNTIME_MODULE_ENDPOINT}.map`;
14
+ const DEFAULT_UI_MODULE_SOURCE_MAP_ENDPOINT = `${DEFAULT_UI_MODULE_ENDPOINT}.map`;
15
+ const DEFAULT_PANDA_CONFIG_FILES = [
16
+ "panda.config.ts",
17
+ "panda.config.mts",
18
+ "panda.config.js",
19
+ "panda.config.mjs",
20
+ "panda.config.cjs"
21
+ ];
22
+ //#endregion
23
+ //#region src/vite/editorProperties.ts
24
+ function editorProperty(name, label, category, cssProperty, aliases = [], tokenCategory) {
25
+ return {
26
+ name,
27
+ label,
28
+ category,
29
+ cssProperty,
30
+ aliases,
31
+ tokenCategory,
32
+ defaultUnit: defaultEditorPropertyUnit(name, category)
33
+ };
34
+ }
35
+ function defaultEditorPropertyUnit(name, category) {
36
+ if ([
37
+ "zIndex",
38
+ "opacity",
39
+ "fontWeight",
40
+ "lineHeight",
41
+ "aspectRatio",
42
+ "order"
43
+ ].includes(name)) return "";
44
+ if (name === "transitionDuration") return "ms";
45
+ if (category === "spacing" || category === "sizing" || [
46
+ "inset",
47
+ "top",
48
+ "right",
49
+ "bottom",
50
+ "left",
51
+ "fontSize",
52
+ "letterSpacing",
53
+ "flexBasis",
54
+ "borderWidth",
55
+ "borderRadius",
56
+ "borderTopRadius",
57
+ "borderRightRadius",
58
+ "borderBottomRadius",
59
+ "borderLeftRadius",
60
+ "borderTopWidth",
61
+ "borderRightWidth",
62
+ "borderBottomWidth",
63
+ "borderLeftWidth",
64
+ "outlineWidth",
65
+ "outlineOffset"
66
+ ].includes(name)) return "px";
67
+ }
68
+ const DEFAULT_EDITOR_PROPERTIES = [
69
+ editorProperty("display", "Display", "layout", "display"),
70
+ editorProperty("position", "Position", "layout", "position", ["pos"]),
71
+ editorProperty("overflow", "Overflow", "layout", "overflow"),
72
+ editorProperty("overflowX", "Overflow X", "layout", "overflow-x"),
73
+ editorProperty("overflowY", "Overflow Y", "layout", "overflow-y"),
74
+ editorProperty("visibility", "Visibility", "layout", "visibility"),
75
+ editorProperty("boxSizing", "Box sizing", "layout", "box-sizing"),
76
+ editorProperty("zIndex", "Z index", "layout", "z-index", [], "zIndex"),
77
+ editorProperty("inset", "Inset", "layout", "inset", [], "spacing"),
78
+ editorProperty("top", "Top", "layout", "top", [], "spacing"),
79
+ editorProperty("right", "Right", "layout", "right", [], "spacing"),
80
+ editorProperty("bottom", "Bottom", "layout", "bottom", [], "spacing"),
81
+ editorProperty("left", "Left", "layout", "left", [], "spacing"),
82
+ editorProperty("padding", "Padding", "spacing", "padding", ["p"], "spacing"),
83
+ editorProperty("paddingX", "Padding X", "spacing", "padding-inline", ["px"], "spacing"),
84
+ editorProperty("paddingY", "Padding Y", "spacing", "padding-block", ["py"], "spacing"),
85
+ editorProperty("paddingTop", "Padding top", "spacing", "padding-top", ["pt"], "spacing"),
86
+ editorProperty("paddingRight", "Padding right", "spacing", "padding-right", ["pr"], "spacing"),
87
+ editorProperty("paddingBottom", "Padding bottom", "spacing", "padding-bottom", ["pb"], "spacing"),
88
+ editorProperty("paddingLeft", "Padding left", "spacing", "padding-left", ["pl"], "spacing"),
89
+ editorProperty("margin", "Margin", "spacing", "margin", ["m"], "spacing"),
90
+ editorProperty("marginX", "Margin X", "spacing", "margin-inline", ["mx"], "spacing"),
91
+ editorProperty("marginY", "Margin Y", "spacing", "margin-block", ["my"], "spacing"),
92
+ editorProperty("marginTop", "Margin top", "spacing", "margin-top", ["mt"], "spacing"),
93
+ editorProperty("marginRight", "Margin right", "spacing", "margin-right", ["mr"], "spacing"),
94
+ editorProperty("marginBottom", "Margin bottom", "spacing", "margin-bottom", ["mb"], "spacing"),
95
+ editorProperty("marginLeft", "Margin left", "spacing", "margin-left", ["ml"], "spacing"),
96
+ editorProperty("gap", "Gap", "spacing", "gap", [], "spacing"),
97
+ editorProperty("rowGap", "Row gap", "spacing", "row-gap", [], "spacing"),
98
+ editorProperty("columnGap", "Column gap", "spacing", "column-gap", [], "spacing"),
99
+ editorProperty("width", "Width", "sizing", "width", ["w"], "sizes"),
100
+ editorProperty("height", "Height", "sizing", "height", ["h"], "sizes"),
101
+ editorProperty("minWidth", "Min width", "sizing", "min-width", ["minW"], "sizes"),
102
+ editorProperty("maxWidth", "Max width", "sizing", "max-width", ["maxW"], "sizes"),
103
+ editorProperty("minHeight", "Min height", "sizing", "min-height", ["minH"], "sizes"),
104
+ editorProperty("maxHeight", "Max height", "sizing", "max-height", ["maxH"], "sizes"),
105
+ editorProperty("aspectRatio", "Aspect ratio", "sizing", "aspect-ratio"),
106
+ editorProperty("fontFamily", "Font family", "typography", "font-family", [], "fonts"),
107
+ editorProperty("fontSize", "Font size", "typography", "font-size", [], "fontSizes"),
108
+ editorProperty("fontWeight", "Font weight", "typography", "font-weight", [], "fontWeights"),
109
+ editorProperty("lineHeight", "Line height", "typography", "line-height", [], "lineHeights"),
110
+ editorProperty("letterSpacing", "Letter spacing", "typography", "letter-spacing", [], "letterSpacings"),
111
+ editorProperty("textAlign", "Text align", "typography", "text-align"),
112
+ editorProperty("textDecoration", "Text decoration", "typography", "text-decoration"),
113
+ editorProperty("textTransform", "Text transform", "typography", "text-transform"),
114
+ editorProperty("whiteSpace", "White space", "typography", "white-space"),
115
+ editorProperty("wordBreak", "Word break", "typography", "word-break"),
116
+ editorProperty("overflowWrap", "Overflow wrap", "typography", "overflow-wrap"),
117
+ editorProperty("textOverflow", "Text overflow", "typography", "text-overflow"),
118
+ editorProperty("color", "Color", "color", "color", [], "colors"),
119
+ editorProperty("background", "Background", "color", "background", ["bg"], "colors"),
120
+ editorProperty("backgroundColor", "Background color", "color", "background-color", ["bgColor"], "colors"),
121
+ editorProperty("borderColor", "Border color", "color", "border-color", [
122
+ "borderTopColor",
123
+ "borderRightColor",
124
+ "borderBottomColor",
125
+ "borderLeftColor",
126
+ "borderXColor",
127
+ "borderYColor"
128
+ ], "colors"),
129
+ editorProperty("outlineColor", "Outline color", "color", "outline-color", [], "colors"),
130
+ editorProperty("fill", "Fill", "color", "fill", [], "colors"),
131
+ editorProperty("stroke", "Stroke", "color", "stroke", [], "colors"),
132
+ editorProperty("caretColor", "Caret color", "color", "caret-color", [], "colors"),
133
+ editorProperty("accentColor", "Accent color", "color", "accent-color", [], "colors"),
134
+ editorProperty("flex", "Flex", "layout", "flex"),
135
+ editorProperty("flexBasis", "Flex basis", "layout", "flex-basis", [], "sizes"),
136
+ editorProperty("flexDirection", "Flex direction", "layout", "flex-direction"),
137
+ editorProperty("flexWrap", "Flex wrap", "layout", "flex-wrap"),
138
+ editorProperty("alignItems", "Align items", "layout", "align-items"),
139
+ editorProperty("alignContent", "Align content", "layout", "align-content"),
140
+ editorProperty("alignSelf", "Align self", "layout", "align-self"),
141
+ editorProperty("justifyContent", "Justify content", "layout", "justify-content"),
142
+ editorProperty("justifyItems", "Justify items", "layout", "justify-items"),
143
+ editorProperty("justifySelf", "Justify self", "layout", "justify-self"),
144
+ editorProperty("order", "Order", "layout", "order"),
145
+ editorProperty("gridTemplateColumns", "Grid template columns", "layout", "grid-template-columns"),
146
+ editorProperty("gridTemplateRows", "Grid template rows", "layout", "grid-template-rows"),
147
+ editorProperty("gridColumn", "Grid column", "layout", "grid-column"),
148
+ editorProperty("gridRow", "Grid row", "layout", "grid-row"),
149
+ editorProperty("gridAutoFlow", "Grid auto flow", "layout", "grid-auto-flow"),
150
+ editorProperty("gridAutoColumns", "Grid auto columns", "layout", "grid-auto-columns"),
151
+ editorProperty("gridAutoRows", "Grid auto rows", "layout", "grid-auto-rows"),
152
+ editorProperty("border", "Border", "border", "border"),
153
+ editorProperty("borderWidth", "Border width", "border", "border-width", [], "borderWidths"),
154
+ editorProperty("borderStyle", "Border style", "border", "border-style"),
155
+ editorProperty("borderRadius", "Border radius", "border", "border-radius", ["rounded"], "radii"),
156
+ editorProperty("cornerShape", "Corner shape", "border", "corner-shape"),
157
+ editorProperty("borderTopRadius", "Rounded top", "border", "border-start-start-radius", ["roundedTop"], "radii"),
158
+ editorProperty("borderRightRadius", "Rounded right", "border", "border-start-end-radius", ["roundedRight"], "radii"),
159
+ editorProperty("borderBottomRadius", "Rounded bottom", "border", "border-end-end-radius", ["roundedBottom"], "radii"),
160
+ editorProperty("borderLeftRadius", "Rounded left", "border", "border-end-start-radius", ["roundedLeft"], "radii"),
161
+ editorProperty("borderTopWidth", "Border top width", "border", "border-top-width", [], "borderWidths"),
162
+ editorProperty("borderRightWidth", "Border right width", "border", "border-right-width", [], "borderWidths"),
163
+ editorProperty("borderBottomWidth", "Border bottom width", "border", "border-bottom-width", [], "borderWidths"),
164
+ editorProperty("borderLeftWidth", "Border left width", "border", "border-left-width", [], "borderWidths"),
165
+ editorProperty("backgroundImage", "Background image", "other", "background-image", ["bgImage"]),
166
+ editorProperty("backgroundSize", "Background size", "other", "background-size", ["bgSize"]),
167
+ editorProperty("backgroundPosition", "Background position", "other", "background-position", ["bgPosition"]),
168
+ editorProperty("backgroundRepeat", "Background repeat", "other", "background-repeat", ["bgRepeat"]),
169
+ editorProperty("backgroundAttachment", "Background attachment", "other", "background-attachment", ["bgAttachment"]),
170
+ editorProperty("backgroundClip", "Background clip", "other", "background-clip", ["bgClip"]),
171
+ editorProperty("opacity", "Opacity", "effects", "opacity", [], "opacity"),
172
+ editorProperty("boxShadow", "Box shadow", "effects", "box-shadow", [], "shadows"),
173
+ editorProperty("outline", "Outline", "effects", "outline"),
174
+ editorProperty("outlineWidth", "Outline width", "effects", "outline-width"),
175
+ editorProperty("outlineStyle", "Outline style", "effects", "outline-style"),
176
+ editorProperty("outlineOffset", "Outline offset", "effects", "outline-offset"),
177
+ editorProperty("transform", "Transform", "effects", "transform"),
178
+ editorProperty("filter", "Filter", "effects", "filter"),
179
+ editorProperty("backdropFilter", "Backdrop filter", "effects", "backdrop-filter"),
180
+ editorProperty("mixBlendMode", "Mix blend mode", "effects", "mix-blend-mode"),
181
+ editorProperty("cursor", "Cursor", "other", "cursor"),
182
+ editorProperty("pointerEvents", "Pointer events", "other", "pointer-events"),
183
+ editorProperty("userSelect", "User select", "other", "user-select"),
184
+ editorProperty("resize", "Resize", "other", "resize"),
185
+ editorProperty("scrollBehavior", "Scroll behavior", "other", "scroll-behavior"),
186
+ editorProperty("transition", "Transition", "other", "transition"),
187
+ editorProperty("transitionProperty", "Transition property", "other", "transition-property"),
188
+ editorProperty("transitionDuration", "Transition duration", "other", "transition-duration"),
189
+ editorProperty("transitionTimingFunction", "Transition timing function", "other", "transition-timing-function")
190
+ ];
191
+ //#endregion
192
+ //#region src/vite/editorMetadata.ts
193
+ async function createEditorMetadata(options) {
194
+ const config = await readPandaConfigSource(options.projectRoot, options.pandaConfigPath);
195
+ const properties = {
196
+ status: "available",
197
+ items: DEFAULT_EDITOR_PROPERTIES
198
+ };
199
+ if (!config.ok) {
200
+ const unavailable = unavailableMetadataSection(config.reason, config.message);
201
+ const unavailableFontTokens = unavailableMetadataSection(config.reason, config.message);
202
+ const unavailableSources = unavailableMetadataSection(config.reason, config.message);
203
+ return {
204
+ version: 1,
205
+ projectRoot: options.projectRoot,
206
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
207
+ tokenSources: unavailableSources,
208
+ colorTokens: unavailable,
209
+ semanticColorTokens: unavailable,
210
+ fontTokens: unavailableFontTokens,
211
+ properties
212
+ };
213
+ }
214
+ const parsed = parsePandaConfigEditorMetadata({
215
+ projectRoot: options.projectRoot,
216
+ filePath: config.filePath,
217
+ sourceText: config.sourceText
218
+ });
219
+ const resolved = await resolvePandaConfigEditorMetadata({
220
+ projectRoot: options.projectRoot,
221
+ pandaConfigPath: options.pandaConfigPath
222
+ });
223
+ if (!parsed.ok) {
224
+ const unavailable = unavailableMetadataSection(parsed.reason, parsed.message);
225
+ if (resolved.ok) return {
226
+ version: 1,
227
+ projectRoot: options.projectRoot,
228
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
229
+ tokenSources: {
230
+ status: "available",
231
+ items: parsed.tokenSources
232
+ },
233
+ colorTokens: {
234
+ status: "available",
235
+ items: resolved.colorTokens
236
+ },
237
+ semanticColorTokens: {
238
+ status: "available",
239
+ items: resolved.semanticColorTokens
240
+ },
241
+ fontTokens: {
242
+ status: "available",
243
+ items: resolved.fontTokens
244
+ },
245
+ properties
246
+ };
247
+ return {
248
+ version: 1,
249
+ projectRoot: options.projectRoot,
250
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
251
+ tokenSources: {
252
+ status: "available",
253
+ items: parsed.tokenSources
254
+ },
255
+ colorTokens: unavailable,
256
+ semanticColorTokens: unavailable,
257
+ fontTokens: unavailableMetadataSection(parsed.reason, parsed.message),
258
+ properties
259
+ };
260
+ }
261
+ return {
262
+ version: 1,
263
+ projectRoot: options.projectRoot,
264
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
265
+ tokenSources: {
266
+ status: "available",
267
+ items: parsed.tokenSources
268
+ },
269
+ colorTokens: {
270
+ status: "available",
271
+ items: mergeResolvedAndStaticColorTokens(resolved.ok ? resolved.colorTokens : [], parsed.colorTokens)
272
+ },
273
+ semanticColorTokens: {
274
+ status: "available",
275
+ items: mergeResolvedAndStaticColorTokens(resolved.ok ? resolved.semanticColorTokens : [], parsed.semanticColorTokens)
276
+ },
277
+ fontTokens: {
278
+ status: "available",
279
+ items: mergeResolvedAndStaticFontTokens(resolved.ok ? resolved.fontTokens : [], parsed.fontTokens)
280
+ },
281
+ properties
282
+ };
283
+ }
284
+ async function readPandaConfigSource(projectRoot, pandaConfigPath) {
285
+ const root = normalizePath(projectRoot).replace(/\/$/, "");
286
+ const candidates = pandaConfigPath ? [absoluteProjectPath(root, pandaConfigPath)] : DEFAULT_PANDA_CONFIG_FILES.map((fileName) => `${root}/${fileName}`);
287
+ for (const filePath of candidates) try {
288
+ return {
289
+ ok: true,
290
+ filePath,
291
+ sourceText: await readFile(filePath, "utf8")
292
+ };
293
+ } catch (error) {
294
+ if (isMissingFileError$2(error)) continue;
295
+ return {
296
+ ok: false,
297
+ reason: "panda-config-unreadable",
298
+ message: `Failed to read Panda config ${filePath}: ${errorMessage(error)}`
299
+ };
300
+ }
301
+ return {
302
+ ok: false,
303
+ reason: "panda-config-missing",
304
+ message: pandaConfigPath ? `Panda config was not found at ${candidates[0]}.` : `No Panda config was found in ${root}.`
305
+ };
306
+ }
307
+ function parsePandaConfigEditorMetadata(options) {
308
+ const configObject = findPandaConfigObject(ts.createSourceFile(options.filePath, options.sourceText, ts.ScriptTarget.Latest, true));
309
+ if (!configObject) return {
310
+ ok: false,
311
+ reason: "unsupported-panda-config",
312
+ message: "Panda config metadata can only be read from a static object or defineConfig({ ... }) call.",
313
+ tokenSources: []
314
+ };
315
+ const theme = objectProperty(configObject, "theme");
316
+ const themeObject = theme ? objectLiteralExpression(theme) : void 0;
317
+ if (!themeObject) return {
318
+ ok: true,
319
+ tokenSources: [],
320
+ colorTokens: [],
321
+ semanticColorTokens: [],
322
+ fontTokens: []
323
+ };
324
+ const colorMetadata = collectThemeColorTokenMetadata({
325
+ projectRoot: options.projectRoot,
326
+ filePath: options.filePath,
327
+ sourceText: options.sourceText,
328
+ themeObject,
329
+ section: "tokens",
330
+ kind: "token"
331
+ });
332
+ const semanticColorMetadata = collectThemeColorTokenMetadata({
333
+ projectRoot: options.projectRoot,
334
+ filePath: options.filePath,
335
+ sourceText: options.sourceText,
336
+ themeObject,
337
+ section: "semanticTokens",
338
+ kind: "semantic-token"
339
+ });
340
+ const fontTokens = collectThemeFontTokenMetadata(themeObject);
341
+ return {
342
+ ok: true,
343
+ tokenSources: [...colorMetadata.tokenSources, ...semanticColorMetadata.tokenSources],
344
+ colorTokens: colorMetadata.tokens,
345
+ semanticColorTokens: semanticColorMetadata.tokens,
346
+ fontTokens
347
+ };
348
+ }
349
+ function collectThemeColorTokenMetadata(options) {
350
+ const directExpression = colorTokenExpressionForThemeSection(options.themeObject, options.section);
351
+ const direct = objectLiteralExpression(directExpression);
352
+ const extend = objectProperty(options.themeObject, "extend");
353
+ const extendedExpression = extend ? colorTokenExpressionForThemeSection(objectLiteralExpression(extend), options.section) : void 0;
354
+ const extended = objectLiteralExpression(extendedExpression);
355
+ const tokenSources = [];
356
+ const tokens = [];
357
+ if (direct) {
358
+ const sourceTarget = editorTokenSourceTarget({
359
+ projectRoot: options.projectRoot,
360
+ filePath: options.filePath,
361
+ sourceText: options.sourceText,
362
+ object: direct,
363
+ section: tokenSourceSection(options.section),
364
+ extended: false
365
+ });
366
+ tokenSources.push(sourceTarget);
367
+ tokens.push(...collectColorTokenMetadata(direct, {
368
+ kind: options.kind,
369
+ sourceTargetId: sourceTarget.id,
370
+ writable: sourceTarget.writable
371
+ }));
372
+ } else if (directExpression) tokenSources.push(editorReadOnlyTokenSourceTarget({
373
+ projectRoot: options.projectRoot,
374
+ filePath: options.filePath,
375
+ sourceText: options.sourceText,
376
+ node: directExpression,
377
+ section: tokenSourceSection(options.section),
378
+ extended: false,
379
+ reason: "Token colors source is not a static object literal."
380
+ }));
381
+ if (extended) {
382
+ const sourceTarget = editorTokenSourceTarget({
383
+ projectRoot: options.projectRoot,
384
+ filePath: options.filePath,
385
+ sourceText: options.sourceText,
386
+ object: extended,
387
+ section: tokenSourceSection(options.section),
388
+ extended: true
389
+ });
390
+ tokenSources.push(sourceTarget);
391
+ tokens.push(...collectColorTokenMetadata(extended, {
392
+ kind: options.kind,
393
+ sourceTargetId: sourceTarget.id,
394
+ writable: sourceTarget.writable
395
+ }));
396
+ } else if (extendedExpression) tokenSources.push(editorReadOnlyTokenSourceTarget({
397
+ projectRoot: options.projectRoot,
398
+ filePath: options.filePath,
399
+ sourceText: options.sourceText,
400
+ node: extendedExpression,
401
+ section: tokenSourceSection(options.section),
402
+ extended: true,
403
+ reason: "Extended token colors source is not a static object literal."
404
+ }));
405
+ return {
406
+ tokenSources,
407
+ tokens
408
+ };
409
+ }
410
+ function colorTokenExpressionForThemeSection(themeObject, section) {
411
+ if (!themeObject) return void 0;
412
+ const tokenSection = objectProperty(themeObject, section);
413
+ const tokenSectionObject = tokenSection ? objectLiteralExpression(tokenSection) : void 0;
414
+ return tokenSectionObject ? objectProperty(tokenSectionObject, "colors") : void 0;
415
+ }
416
+ function tokenSourceSection(section) {
417
+ return section === "tokens" ? "tokens.colors" : "semanticTokens.colors";
418
+ }
419
+ function collectThemeFontTokenMetadata(themeObject) {
420
+ const tokens = [];
421
+ for (const expression of [fontTokenExpressionForThemeSection(themeObject), fontTokenExpressionForThemeSection(objectLiteralExpression(objectProperty(themeObject, "extend")))]) {
422
+ const object = objectLiteralExpression(expression);
423
+ if (!object) continue;
424
+ tokens.push(...collectFontTokenMetadata(object));
425
+ }
426
+ return tokens;
427
+ }
428
+ function fontTokenExpressionForThemeSection(themeObject) {
429
+ if (!themeObject) return void 0;
430
+ const tokens = objectLiteralExpression(objectProperty(themeObject, "tokens"));
431
+ return tokens ? objectProperty(tokens, "fonts") : void 0;
432
+ }
433
+ async function resolvePandaConfigEditorMetadata(options) {
434
+ try {
435
+ const context = await loadConfigAndCreateContext({
436
+ cwd: options.projectRoot,
437
+ configPath: options.pandaConfigPath ? absoluteProjectPath(options.projectRoot, options.pandaConfigPath) : void 0
438
+ });
439
+ const presetColorTokenOwners = presetColorTokenOwnersByKind(context.config.presets);
440
+ return {
441
+ ok: true,
442
+ colorTokens: resolvedTokenSpecColorMetadata(context.getSpecOfType("tokens"), "token", presetColorTokenOwners.token),
443
+ semanticColorTokens: resolvedTokenSpecColorMetadata(context.getSpecOfType("semantic-tokens"), "semantic-token", presetColorTokenOwners.semanticToken),
444
+ fontTokens: resolvedTokenSpecFontMetadata(context.getSpecOfType("tokens"), presetFontTokenOwners(context.config.presets))
445
+ };
446
+ } catch (error) {
447
+ return {
448
+ ok: false,
449
+ message: `Failed to resolve Panda token metadata: ${errorMessage(error)}`
450
+ };
451
+ }
452
+ }
453
+ function resolvedTokenSpecFontMetadata(spec, presetOwners) {
454
+ if (!isRecord$3(spec) || !Array.isArray(spec.data)) return [];
455
+ const fontGroup = spec.data.find((group) => isRecord$3(group) && group.type === "fonts" && Array.isArray(group.values));
456
+ if (!fontGroup) return [];
457
+ return fontGroup.values.map((value) => resolvedFontTokenMetadata(value, presetOwners)).filter((value) => value !== void 0);
458
+ }
459
+ function resolvedFontTokenMetadata(value, presetOwners) {
460
+ if (!isRecord$3(value) || typeof value.name !== "string" || value.name.length === 0) return;
461
+ return {
462
+ kind: "token",
463
+ category: "fonts",
464
+ path: value.name,
465
+ label: value.name,
466
+ value: jsonValueFromUnknown(value.value),
467
+ cssVariable: typeof value.cssVar === "string" ? value.cssVar : void 0,
468
+ presetName: presetOwners.get(value.name)
469
+ };
470
+ }
471
+ function resolvedTokenSpecColorMetadata(spec, kind, presetOwners) {
472
+ if (!isRecord$3(spec) || !Array.isArray(spec.data)) return [];
473
+ const colorGroup = spec.data.find((group) => isRecord$3(group) && group.type === "colors" && Array.isArray(group.values));
474
+ if (!colorGroup) return [];
475
+ return colorGroup.values.map((value) => resolvedColorTokenMetadata(value, kind, presetOwners)).filter((value) => value !== void 0);
476
+ }
477
+ function resolvedColorTokenMetadata(value, kind, presetOwners) {
478
+ if (!isRecord$3(value) || typeof value.name !== "string" || value.name.length === 0) return;
479
+ if (kind === "semantic-token") {
480
+ const conditions = Array.isArray(value.values) ? value.values.flatMap((condition) => {
481
+ if (!isRecord$3(condition) || typeof condition.condition !== "string") return [];
482
+ const conditionValue = jsonValueFromUnknown(condition.value);
483
+ if (conditionValue === void 0) return [];
484
+ const swatch = swatchFromJsonValue(conditionValue);
485
+ return [swatch ? {
486
+ condition: condition.condition,
487
+ value: conditionValue,
488
+ swatch
489
+ } : {
490
+ condition: condition.condition,
491
+ value: conditionValue
492
+ }];
493
+ }) : void 0;
494
+ return {
495
+ kind,
496
+ category: "colors",
497
+ path: value.name,
498
+ label: value.name,
499
+ cssVariable: typeof value.cssVar === "string" ? value.cssVar : void 0,
500
+ presetName: presetOwners.get(value.name),
501
+ conditions,
502
+ writable: false,
503
+ readonlyReason: "Resolved Panda token metadata is read-only."
504
+ };
505
+ }
506
+ const tokenValue = jsonValueFromUnknown(value.value);
507
+ if (tokenValue === void 0) return void 0;
508
+ return {
509
+ kind,
510
+ category: "colors",
511
+ path: value.name,
512
+ label: value.name,
513
+ value: tokenValue,
514
+ swatch: swatchFromJsonValue(tokenValue),
515
+ cssVariable: typeof value.cssVar === "string" ? value.cssVar : void 0,
516
+ presetName: presetOwners.get(value.name),
517
+ writable: false,
518
+ readonlyReason: "Resolved Panda token metadata is read-only."
519
+ };
520
+ }
521
+ function presetColorTokenOwnersByKind(presets) {
522
+ const token = /* @__PURE__ */ new Map();
523
+ const semanticToken = /* @__PURE__ */ new Map();
524
+ if (!Array.isArray(presets)) return {
525
+ token,
526
+ semanticToken
527
+ };
528
+ for (const preset of presets) {
529
+ if (!isRecord$3(preset) || typeof preset.name !== "string") continue;
530
+ const theme = isRecord$3(preset.theme) ? preset.theme : void 0;
531
+ const tokens = isRecord$3(theme?.tokens) ? theme.tokens : void 0;
532
+ const semanticTokens = isRecord$3(theme?.semanticTokens) ? theme.semanticTokens : void 0;
533
+ collectPresetColorTokenOwners(tokens?.colors, preset.name, token);
534
+ collectPresetColorTokenOwners(semanticTokens?.colors, preset.name, semanticToken);
535
+ }
536
+ return {
537
+ token,
538
+ semanticToken
539
+ };
540
+ }
541
+ function collectPresetColorTokenOwners(value, presetName, owners, path = []) {
542
+ if (!isRecord$3(value)) return;
543
+ for (const [key, child] of Object.entries(value)) {
544
+ const nextPath = key === "DEFAULT" ? path : [...path, key];
545
+ if (!isRecord$3(child)) continue;
546
+ if ("value" in child && nextPath.length > 0) {
547
+ owners.set(nextPath.join("."), presetName);
548
+ continue;
549
+ }
550
+ collectPresetColorTokenOwners(child, presetName, owners, nextPath);
551
+ }
552
+ }
553
+ function presetFontTokenOwners(presets) {
554
+ const token = /* @__PURE__ */ new Map();
555
+ if (!Array.isArray(presets)) return token;
556
+ for (const preset of presets) {
557
+ if (!isRecord$3(preset) || typeof preset.name !== "string") continue;
558
+ const theme = isRecord$3(preset.theme) ? preset.theme : void 0;
559
+ collectPresetFontTokenOwners((isRecord$3(theme?.tokens) ? theme.tokens : void 0)?.fonts, preset.name, token);
560
+ }
561
+ return token;
562
+ }
563
+ function collectPresetFontTokenOwners(value, presetName, owners, path = []) {
564
+ if (!isRecord$3(value)) return;
565
+ for (const [key, child] of Object.entries(value)) {
566
+ const nextPath = key === "DEFAULT" ? path : [...path, key];
567
+ if (!isRecord$3(child)) continue;
568
+ if ("value" in child && nextPath.length > 0) {
569
+ owners.set(nextPath.join("."), presetName);
570
+ continue;
571
+ }
572
+ collectPresetFontTokenOwners(child, presetName, owners, nextPath);
573
+ }
574
+ }
575
+ function mergeResolvedAndStaticColorTokens(resolved, staticTokens) {
576
+ const byKey = /* @__PURE__ */ new Map();
577
+ for (const token of staticTokens) byKey.set(`${token.kind}:${token.path}`, token);
578
+ for (const token of resolved) {
579
+ const key = `${token.kind}:${token.path}`;
580
+ if (!byKey.has(key)) byKey.set(key, token);
581
+ }
582
+ return [...byKey.values()];
583
+ }
584
+ function mergeResolvedAndStaticFontTokens(resolved, staticTokens) {
585
+ const byPath = /* @__PURE__ */ new Map();
586
+ for (const token of staticTokens) byPath.set(token.path, token);
587
+ for (const token of resolved) if (!byPath.has(token.path)) byPath.set(token.path, token);
588
+ return [...byPath.values()];
589
+ }
590
+ function editorTokenSourceTarget(options) {
591
+ const file = toRelativeProjectPath(options.filePath, options.projectRoot);
592
+ const rangeText = options.sourceText.slice(options.object.getStart(), options.object.getEnd());
593
+ const safety = tokenObjectWriteSafety(options.object);
594
+ const sourcePathPrefix = options.extended ? "theme.extend" : "theme";
595
+ return {
596
+ id: [
597
+ file,
598
+ sourcePathPrefix,
599
+ options.section,
600
+ options.object.getStart(),
601
+ options.object.getEnd()
602
+ ].join("#"),
603
+ kind: "panda-config",
604
+ file,
605
+ absoluteFile: options.filePath,
606
+ range: {
607
+ start: options.object.getStart(),
608
+ end: options.object.getEnd()
609
+ },
610
+ sourceHash: hashSource(rangeText),
611
+ configPath: options.extended ? `${sourcePathPrefix}.${options.section}` : `${sourcePathPrefix}.${options.section}`,
612
+ writableSections: safety.writable ? [options.section] : [],
613
+ confidence: safety.writable ? "high" : "low",
614
+ writable: safety.writable,
615
+ readonlyReason: safety.writable ? void 0 : safety.reason
616
+ };
617
+ }
618
+ function editorReadOnlyTokenSourceTarget(options) {
619
+ const file = toRelativeProjectPath(options.filePath, options.projectRoot);
620
+ const rangeText = options.sourceText.slice(options.node.getStart(), options.node.getEnd());
621
+ const sourcePathPrefix = options.extended ? "theme.extend" : "theme";
622
+ return {
623
+ id: [
624
+ file,
625
+ sourcePathPrefix,
626
+ options.section,
627
+ options.node.getStart(),
628
+ options.node.getEnd()
629
+ ].join("#"),
630
+ kind: "panda-config",
631
+ file,
632
+ absoluteFile: options.filePath,
633
+ range: {
634
+ start: options.node.getStart(),
635
+ end: options.node.getEnd()
636
+ },
637
+ sourceHash: hashSource(rangeText),
638
+ configPath: `${sourcePathPrefix}.${options.section}`,
639
+ writableSections: [],
640
+ confidence: "low",
641
+ writable: false,
642
+ readonlyReason: options.reason
643
+ };
644
+ }
645
+ function tokenObjectWriteSafety(object) {
646
+ const keys = /* @__PURE__ */ new Set();
647
+ for (const property of object.properties) {
648
+ if (!ts.isPropertyAssignment(property)) return {
649
+ writable: false,
650
+ reason: "Token object contains a spread, shorthand, method, or accessor."
651
+ };
652
+ const key = propertyNameText(property.name);
653
+ if (!key) return {
654
+ writable: false,
655
+ reason: "Token object contains a computed key."
656
+ };
657
+ if (keys.has(key)) return {
658
+ writable: false,
659
+ reason: "Token object contains duplicate keys."
660
+ };
661
+ keys.add(key);
662
+ const valueObject = objectLiteralExpression(property.initializer);
663
+ if (!valueObject) return {
664
+ writable: false,
665
+ reason: "Token object contains a non-object token branch."
666
+ };
667
+ if (!objectProperty(valueObject, "value")) {
668
+ const nestedSafety = tokenObjectWriteSafety(valueObject);
669
+ if (!nestedSafety.writable) return nestedSafety;
670
+ }
671
+ }
672
+ return { writable: true };
673
+ }
674
+ function collectColorTokenMetadata(object, options, path = []) {
675
+ const tokens = [];
676
+ for (const property of object.properties) {
677
+ if (!ts.isPropertyAssignment(property)) continue;
678
+ const key = propertyNameText(property.name);
679
+ if (!key) continue;
680
+ const valueObject = objectLiteralExpression(property.initializer);
681
+ if (!valueObject) continue;
682
+ const valueExpression = objectProperty(valueObject, "value");
683
+ const nextPath = key === "DEFAULT" ? path : [...path, key];
684
+ if (valueExpression) {
685
+ const value = jsonValueFromExpression(valueExpression);
686
+ if (value !== void 0 && nextPath.length > 0) {
687
+ const tokenPath = nextPath.join(".");
688
+ tokens.push({
689
+ kind: options.kind,
690
+ category: "colors",
691
+ path: tokenPath,
692
+ label: tokenPath,
693
+ value,
694
+ swatch: swatchFromJsonValue(value),
695
+ cssVariable: `var(--colors-${tokenPathToCssVariableSuffix(tokenPath)})`,
696
+ sourceTargetId: options.sourceTargetId,
697
+ sourcePath: nextPath,
698
+ writable: options.writable,
699
+ readonlyReason: options.writable ? void 0 : "Token source target is read-only.",
700
+ conditions: options.kind === "semantic-token" && isJsonObject(value) ? Object.entries(value).map(([condition, conditionValue]) => ({
701
+ condition,
702
+ value: conditionValue,
703
+ swatch: swatchFromJsonValue(conditionValue)
704
+ })) : void 0
705
+ });
706
+ }
707
+ continue;
708
+ }
709
+ tokens.push(...collectColorTokenMetadata(valueObject, options, nextPath));
710
+ }
711
+ return tokens;
712
+ }
713
+ function collectFontTokenMetadata(object, path = []) {
714
+ const tokens = [];
715
+ for (const property of object.properties) {
716
+ if (!ts.isPropertyAssignment(property)) continue;
717
+ const key = propertyNameText(property.name);
718
+ if (!key) continue;
719
+ const valueObject = objectLiteralExpression(property.initializer);
720
+ if (!valueObject) continue;
721
+ const valueExpression = objectProperty(valueObject, "value");
722
+ const nextPath = key === "DEFAULT" ? path : [...path, key];
723
+ if (valueExpression) {
724
+ const value = jsonValueFromExpression(valueExpression);
725
+ if (value !== void 0 && nextPath.length > 0) {
726
+ const tokenPath = nextPath.join(".");
727
+ tokens.push({
728
+ kind: "token",
729
+ category: "fonts",
730
+ path: tokenPath,
731
+ label: tokenPath,
732
+ value,
733
+ cssVariable: `var(--fonts-${tokenPathToCssVariableSuffix(tokenPath)})`,
734
+ sourcePath: nextPath
735
+ });
736
+ }
737
+ continue;
738
+ }
739
+ tokens.push(...collectFontTokenMetadata(valueObject, nextPath));
740
+ }
741
+ return tokens;
742
+ }
743
+ function findPandaConfigObject(sourceFile) {
744
+ let result;
745
+ const visit = (node) => {
746
+ if (result) return;
747
+ if (ts.isExportAssignment(node)) {
748
+ result = configObjectFromExpression(node.expression);
749
+ if (result) return;
750
+ }
751
+ if (ts.isCallExpression(node) && callExpressionName(node.expression) === "defineConfig") {
752
+ result = objectLiteralExpression(node.arguments[0]);
753
+ if (result) return;
754
+ }
755
+ ts.forEachChild(node, visit);
756
+ };
757
+ visit(sourceFile);
758
+ return result;
759
+ }
760
+ function configObjectFromExpression(expression) {
761
+ const unwrapped = unwrapExpression(expression);
762
+ if (ts.isObjectLiteralExpression(unwrapped)) return unwrapped;
763
+ if (ts.isCallExpression(unwrapped) && callExpressionName(unwrapped.expression) === "defineConfig") return objectLiteralExpression(unwrapped.arguments[0]);
764
+ }
765
+ function callExpressionName(expression) {
766
+ const unwrapped = unwrapExpression(expression);
767
+ if (ts.isIdentifier(unwrapped)) return unwrapped.text;
768
+ if (ts.isPropertyAccessExpression(unwrapped)) return unwrapped.name.text;
769
+ }
770
+ function objectProperty(object, name) {
771
+ for (const property of object.properties) {
772
+ if (!ts.isPropertyAssignment(property)) continue;
773
+ if (propertyNameText(property.name) === name) return property.initializer;
774
+ }
775
+ }
776
+ function propertyNameText(name) {
777
+ if (ts.isIdentifier(name)) return name.text;
778
+ if (ts.isStringLiteral(name) || ts.isNumericLiteral(name)) return name.text;
779
+ }
780
+ function objectLiteralExpression(expression) {
781
+ if (!expression) return void 0;
782
+ const unwrapped = unwrapExpression(expression);
783
+ return ts.isObjectLiteralExpression(unwrapped) ? unwrapped : void 0;
784
+ }
785
+ function unwrapExpression(expression) {
786
+ let current = expression;
787
+ while (ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current)) current = current.expression;
788
+ return current;
789
+ }
790
+ function jsonValueFromExpression(expression) {
791
+ const unwrapped = unwrapExpression(expression);
792
+ if (ts.isStringLiteral(unwrapped) || ts.isNoSubstitutionTemplateLiteral(unwrapped)) return unwrapped.text;
793
+ if (ts.isNumericLiteral(unwrapped)) return Number(unwrapped.text);
794
+ if (unwrapped.kind === ts.SyntaxKind.TrueKeyword) return true;
795
+ if (unwrapped.kind === ts.SyntaxKind.FalseKeyword) return false;
796
+ if (unwrapped.kind === ts.SyntaxKind.NullKeyword) return null;
797
+ if (ts.isArrayLiteralExpression(unwrapped)) {
798
+ const items = unwrapped.elements.map((item) => jsonValueFromExpression(item));
799
+ return items.every((item) => item !== void 0) ? items : void 0;
800
+ }
801
+ if (ts.isObjectLiteralExpression(unwrapped)) {
802
+ const value = {};
803
+ for (const property of unwrapped.properties) {
804
+ if (!ts.isPropertyAssignment(property)) return void 0;
805
+ const key = propertyNameText(property.name);
806
+ if (!key) return void 0;
807
+ const propertyValue = jsonValueFromExpression(property.initializer);
808
+ if (propertyValue === void 0) return void 0;
809
+ value[key] = propertyValue;
810
+ }
811
+ return value;
812
+ }
813
+ }
814
+ function jsonValueFromUnknown(value) {
815
+ return isJsonValue$1(value) ? value : void 0;
816
+ }
817
+ function unavailableMetadataSection(reason, message) {
818
+ return {
819
+ status: "unavailable",
820
+ items: [],
821
+ reason,
822
+ message
823
+ };
824
+ }
825
+ function isJsonObject(value) {
826
+ return typeof value === "object" && value !== null && !Array.isArray(value);
827
+ }
828
+ function swatchFromJsonValue(value) {
829
+ if (typeof value !== "string") return void 0;
830
+ const trimmed = value.trim();
831
+ if (/^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(trimmed)) return trimmed;
832
+ if (/^(rgb|rgba|hsl|hsla|oklch|oklab|lch|lab|color)\(/i.test(trimmed)) return trimmed;
833
+ }
834
+ function tokenPathToCssVariableSuffix(value) {
835
+ return value.replace(/\./g, "-");
836
+ }
837
+ function absoluteProjectPath(projectRoot, filePath) {
838
+ const normalized = normalizePath(filePath);
839
+ if (normalized.startsWith("/")) return normalized;
840
+ return `${projectRoot}/${normalized.replace(/^\.\//, "")}`;
841
+ }
842
+ function toRelativeProjectPath(filePath, projectRoot) {
843
+ const file = normalizePath(filePath);
844
+ const root = normalizePath(projectRoot).replace(/\/$/, "");
845
+ return file.startsWith(`${root}/`) ? file.slice(root.length + 1) : file;
846
+ }
847
+ function normalizePath(path) {
848
+ return path.replace(/\\/g, "/");
849
+ }
850
+ function isMissingFileError$2(error) {
851
+ return isRecord$3(error) && error.code === "ENOENT";
852
+ }
853
+ function errorMessage(error) {
854
+ return error instanceof Error ? error.message : String(error);
855
+ }
856
+ function isRecord$3(value) {
857
+ return typeof value === "object" && value !== null && !Array.isArray(value);
858
+ }
859
+ function isJsonValue$1(value) {
860
+ if (value === null) return true;
861
+ if ([
862
+ "string",
863
+ "number",
864
+ "boolean"
865
+ ].includes(typeof value)) return true;
866
+ if (Array.isArray(value)) return value.every(isJsonValue$1);
867
+ if (!isRecord$3(value)) return false;
868
+ return Object.values(value).every(isJsonValue$1);
869
+ }
870
+ //#endregion
871
+ //#region src/vite/sourceLocation.ts
872
+ async function readOpenSourceLocationRequest(request) {
873
+ try {
874
+ const body = await readRequestBody$2(request);
875
+ const parsed = JSON.parse(body);
876
+ if (!isOpenSourceLocationRequest(parsed)) return {
877
+ ok: false,
878
+ response: openSourceLocationFailure("invalid-request", "Request body is not a valid source location request.")
879
+ };
880
+ return {
881
+ ok: true,
882
+ request: parsed
883
+ };
884
+ } catch (error) {
885
+ return {
886
+ ok: false,
887
+ response: openSourceLocationFailure("invalid-request", `Failed to read source location request: ${error instanceof Error ? error.message : String(error)}`)
888
+ };
889
+ }
890
+ }
891
+ async function resolveOpenSourceLocation(options) {
892
+ const request = options.request;
893
+ if (request.kind === "component") {
894
+ const entry = options.manifest.entries.find((item) => item.id === request.editId);
895
+ if (!entry) return openSourceLocationFailure("missing-metadata", "No manifest entry exists for that component source location.");
896
+ const trustedPath = trustedManifestFilePath(options.manifest, entry);
897
+ if (!trustedPath.ok) return openSourceLocationFailure("path-outside-project", trustedPath.message, trustedPath.details);
898
+ const line = entry.loc?.start.line;
899
+ const column = entry.loc?.start.column;
900
+ try {
901
+ await access(trustedPath.file);
902
+ } catch {
903
+ return openSourceLocationFailure("file-not-found", "Component source file does not exist.", { file: toRelativeProjectPath$1(trustedPath.file, options.projectRoot) });
904
+ }
905
+ return openSourceLocationSuccess({
906
+ file: trustedPath.file,
907
+ line,
908
+ column,
909
+ projectRoot: options.projectRoot
910
+ });
911
+ }
912
+ const parsed = parseSourceLocationText(request.source);
913
+ if (!parsed.ok) return parsed.response;
914
+ const safePath = safeProjectSourcePath(options.projectRoot, parsed.file);
915
+ if (!safePath.ok) return openSourceLocationFailure(safePath.code, safePath.message, safePath.details);
916
+ try {
917
+ await access(safePath.file);
918
+ } catch {
919
+ return openSourceLocationFailure("file-not-found", "Source file does not exist.", { file: toRelativeProjectPath$1(safePath.file, options.projectRoot) });
920
+ }
921
+ return openSourceLocationSuccess({
922
+ file: safePath.file,
923
+ line: parsed.line,
924
+ column: parsed.column,
925
+ projectRoot: options.projectRoot
926
+ });
927
+ }
928
+ function parseSourceLocationText(source) {
929
+ const value = source.trim();
930
+ if (!value || /:\/\//.test(value)) return {
931
+ ok: false,
932
+ response: openSourceLocationFailure("invalid-request", "Source location must be a project file path.")
933
+ };
934
+ const match = /^(.*?)(?::(\d+)(?::(\d+))?)?$/.exec(value);
935
+ const file = match?.[1]?.trim();
936
+ if (!match || !file) return {
937
+ ok: false,
938
+ response: openSourceLocationFailure("invalid-request", "Source location must include a file path.")
939
+ };
940
+ const line = match[2] ? Number.parseInt(match[2], 10) : void 0;
941
+ const column = match[3] ? Number.parseInt(match[3], 10) : void 0;
942
+ if (line !== void 0 && line < 1 || column !== void 0 && column < 1) return {
943
+ ok: false,
944
+ response: openSourceLocationFailure("invalid-request", "Line and column numbers must be positive integers.")
945
+ };
946
+ return {
947
+ ok: true,
948
+ file,
949
+ line,
950
+ column
951
+ };
952
+ }
953
+ function openSourceLocationSuccess(options) {
954
+ const file = toRelativeProjectPath$1(options.file, options.projectRoot);
955
+ const location = [
956
+ options.file,
957
+ options.line === void 0 ? void 0 : String(options.line),
958
+ options.column === void 0 ? void 0 : String(options.column)
959
+ ].filter((part) => part !== void 0).join(":");
960
+ return {
961
+ ok: true,
962
+ file,
963
+ line: options.line,
964
+ column: options.column,
965
+ openEditorUrl: `/__open-in-editor?file=${encodeURIComponent(location)}`
966
+ };
967
+ }
968
+ function openSourceLocationFailure(code, message, details) {
969
+ return {
970
+ ok: false,
971
+ error: {
972
+ code,
973
+ message,
974
+ details
975
+ }
976
+ };
977
+ }
978
+ function isOpenSourceLocationRequest(value) {
979
+ if (!isRecord$2(value)) return false;
980
+ if (value.kind === "source") return typeof value.source === "string" && value.source.length > 0;
981
+ if (value.kind === "component") return typeof value.editId === "string" && value.editId.length > 0;
982
+ return false;
983
+ }
984
+ async function readRequestBody$2(request) {
985
+ if (!request[Symbol.asyncIterator]) return "";
986
+ let body = "";
987
+ for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
988
+ return body;
989
+ }
990
+ function isRecord$2(value) {
991
+ return typeof value === "object" && value !== null && !Array.isArray(value);
992
+ }
993
+ //#endregion
994
+ //#region src/vite/runtimeModules.ts
995
+ function registerRuntimeModuleRoutes(server, options) {
996
+ server.middlewares.use(options.runtimeBootstrapEndpoint, (_request, response) => {
997
+ response.statusCode = 200;
998
+ response.setHeader("content-type", "application/javascript");
999
+ response.setHeader("cache-control", "no-store");
1000
+ response.end(runtimeBootstrapSource({
1001
+ manifestEndpoint: options.manifestEndpoint,
1002
+ editorMetadataEndpoint: options.editorMetadataEndpoint,
1003
+ globalName: options.globalName,
1004
+ runtimeModuleEndpoint: options.runtimeModuleEndpoint,
1005
+ uiModuleEndpoint: options.uiModuleEndpoint
1006
+ }));
1007
+ });
1008
+ server.middlewares.use(DEFAULT_RUNTIME_MODULE_SOURCE_MAP_ENDPOINT, async (_request, response) => {
1009
+ try {
1010
+ const runtimeModuleSourceMap = await readFile(new URL("./runtime.mjs.map", import.meta.url), "utf8");
1011
+ response.statusCode = 200;
1012
+ response.setHeader("content-type", "application/json");
1013
+ response.setHeader("cache-control", "no-store");
1014
+ response.end(runtimeModuleSourceMap);
1015
+ } catch (error) {
1016
+ response.statusCode = 404;
1017
+ response.setHeader("content-type", "text/plain");
1018
+ response.setHeader("cache-control", "no-store");
1019
+ response.end(`Failed to load Panda inspector runtime module source map: ${error instanceof Error ? error.message : String(error)}`);
1020
+ }
1021
+ });
1022
+ server.middlewares.use(options.runtimeModuleEndpoint, async (_request, response) => {
1023
+ try {
1024
+ const runtimeModuleSource = rewriteInspectorModuleSource(await readFile(new URL("./runtime.mjs", import.meta.url), "utf8"), options.runtimeChunkEndpoint, DEFAULT_RUNTIME_MODULE_SOURCE_MAP_ENDPOINT);
1025
+ response.statusCode = 200;
1026
+ response.setHeader("content-type", "application/javascript");
1027
+ response.setHeader("cache-control", "no-store");
1028
+ response.end(runtimeModuleSource);
1029
+ } catch (error) {
1030
+ response.statusCode = 500;
1031
+ response.setHeader("content-type", "text/plain");
1032
+ response.setHeader("cache-control", "no-store");
1033
+ response.end(`Failed to load Panda inspector runtime module: ${error instanceof Error ? error.message : String(error)}`);
1034
+ }
1035
+ });
1036
+ server.middlewares.use(options.runtimeChunkEndpoint, async (request, response) => {
1037
+ const fileName = runtimeChunkFileName(request.url);
1038
+ if (!fileName) {
1039
+ response.statusCode = 404;
1040
+ response.setHeader("content-type", "text/plain");
1041
+ response.setHeader("cache-control", "no-store");
1042
+ response.end("Unknown Panda inspector runtime chunk.");
1043
+ return;
1044
+ }
1045
+ try {
1046
+ const runtimeChunkSource = await readFile(new URL(`./${fileName}`, import.meta.url), "utf8");
1047
+ response.statusCode = 200;
1048
+ response.setHeader("content-type", fileName.endsWith(".map") ? "application/json" : "application/javascript");
1049
+ response.setHeader("cache-control", "no-store");
1050
+ response.end(runtimeChunkSource);
1051
+ } catch (error) {
1052
+ response.statusCode = 404;
1053
+ response.setHeader("content-type", "text/plain");
1054
+ response.setHeader("cache-control", "no-store");
1055
+ response.end(`Failed to load Panda inspector runtime chunk: ${error instanceof Error ? error.message : String(error)}`);
1056
+ }
1057
+ });
1058
+ server.middlewares.use(DEFAULT_UI_MODULE_SOURCE_MAP_ENDPOINT, async (_request, response) => {
1059
+ try {
1060
+ const uiModuleSourceMap = await readFile(new URL("./ui.mjs.map", import.meta.url), "utf8");
1061
+ response.statusCode = 200;
1062
+ response.setHeader("content-type", "application/json");
1063
+ response.setHeader("cache-control", "no-store");
1064
+ response.end(uiModuleSourceMap);
1065
+ } catch (error) {
1066
+ response.statusCode = 404;
1067
+ response.setHeader("content-type", "text/plain");
1068
+ response.setHeader("cache-control", "no-store");
1069
+ response.end(`Failed to load Panda inspector UI module source map: ${error instanceof Error ? error.message : String(error)}`);
1070
+ }
1071
+ });
1072
+ server.middlewares.use(options.uiModuleEndpoint, async (_request, response) => {
1073
+ try {
1074
+ const uiModuleSource = rewriteInspectorModuleSource(await readFile(new URL("./ui.mjs", import.meta.url), "utf8"), options.runtimeChunkEndpoint, DEFAULT_UI_MODULE_SOURCE_MAP_ENDPOINT);
1075
+ response.statusCode = 200;
1076
+ response.setHeader("content-type", "application/javascript");
1077
+ response.setHeader("cache-control", "no-store");
1078
+ response.end(uiModuleSource);
1079
+ } catch (error) {
1080
+ response.statusCode = 500;
1081
+ response.setHeader("content-type", "text/plain");
1082
+ response.setHeader("cache-control", "no-store");
1083
+ response.end(`Failed to load Panda inspector UI module: ${error instanceof Error ? error.message : String(error)}`);
1084
+ }
1085
+ });
1086
+ }
1087
+ function runtimeBootstrapSource(options) {
1088
+ const runtimeOptions = JSON.stringify({
1089
+ globalName: options.globalName,
1090
+ manifestEndpoint: options.manifestEndpoint,
1091
+ editorMetadataEndpoint: options.editorMetadataEndpoint
1092
+ });
1093
+ return [
1094
+ `import { installPandaInspectorRuntime } from ${JSON.stringify(options.runtimeModuleEndpoint)};`,
1095
+ `import { installReadonlyInspectorPanel } from ${JSON.stringify(options.uiModuleEndpoint)};`,
1096
+ `const pandaInspectorRuntime = installPandaInspectorRuntime(${runtimeOptions});`,
1097
+ "installReadonlyInspectorPanel(pandaInspectorRuntime);"
1098
+ ].join("\n");
1099
+ }
1100
+ function rewriteInspectorModuleSource(source, runtimeChunkEndpoint, sourceMapEndpoint) {
1101
+ return source.replaceAll("from \"./", `from "${runtimeChunkEndpoint}`).replace(/\/\/# sourceMappingURL=[^\r\n]+/g, `//# sourceMappingURL=${sourceMapEndpoint}`);
1102
+ }
1103
+ function runtimeChunkFileName(url) {
1104
+ const fileName = (url ?? "").replace(/[?#].*$/, "").split("/").filter(Boolean).at(-1);
1105
+ if (!fileName || !/^[A-Za-z0-9._-]+\.mjs(?:\.map)?$/.test(fileName)) return void 0;
1106
+ return fileName;
1107
+ }
1108
+ //#endregion
1109
+ //#region src/vite/styleModuleEndpoint.ts
1110
+ function registerStyleModuleRoute(server, options) {
1111
+ server.middlewares.use(options.endpoint, async (request, response) => {
1112
+ if (request.method && request.method !== "POST") {
1113
+ response.statusCode = 405;
1114
+ response.setHeader("content-type", "application/json");
1115
+ response.setHeader("cache-control", "no-store");
1116
+ response.end(JSON.stringify(styleModuleFailure("invalid-edit", "Panda inspector style-module discovery requires POST.")));
1117
+ return;
1118
+ }
1119
+ const requestResult = await readStyleModuleRequest(request);
1120
+ if (!requestResult.ok) {
1121
+ response.statusCode = 400;
1122
+ response.setHeader("content-type", "application/json");
1123
+ response.setHeader("cache-control", "no-store");
1124
+ response.end(JSON.stringify(requestResult.response));
1125
+ return;
1126
+ }
1127
+ const paths = componentStyleModulePaths({
1128
+ projectRoot: options.projectRoot,
1129
+ componentSource: requestResult.componentSource
1130
+ });
1131
+ if (!paths.ok) {
1132
+ response.statusCode = 400;
1133
+ response.setHeader("content-type", "application/json");
1134
+ response.setHeader("cache-control", "no-store");
1135
+ response.end(JSON.stringify(styleModuleFailure(paths.code, paths.message, paths.details)));
1136
+ return;
1137
+ }
1138
+ let sourceText;
1139
+ try {
1140
+ sourceText = await readFile(paths.paths.styleFile, "utf8");
1141
+ } catch (error) {
1142
+ if (!isMissingFileError$1(error)) {
1143
+ response.statusCode = 400;
1144
+ response.setHeader("content-type", "application/json");
1145
+ response.setHeader("cache-control", "no-store");
1146
+ response.end(JSON.stringify(styleModuleFailure("write-failed", `Failed to read style module: ${error instanceof Error ? error.message : String(error)}`)));
1147
+ return;
1148
+ }
1149
+ }
1150
+ const result = readComponentStyleModule({
1151
+ projectRoot: options.projectRoot,
1152
+ componentSource: requestResult.componentSource,
1153
+ sourceText,
1154
+ cssImportSources: options.cssImportSources
1155
+ });
1156
+ response.statusCode = result.ok ? 200 : 400;
1157
+ response.setHeader("content-type", "application/json");
1158
+ response.setHeader("cache-control", "no-store");
1159
+ response.end(JSON.stringify(result));
1160
+ });
1161
+ }
1162
+ async function readStyleModuleRequest(request) {
1163
+ try {
1164
+ const body = await readRequestBody$1(request);
1165
+ const parsed = JSON.parse(body);
1166
+ if (!isRecord$1(parsed) || typeof parsed.componentSource !== "string") return {
1167
+ ok: false,
1168
+ response: styleModuleFailure("invalid-edit", "Request body is not a valid style-module request.")
1169
+ };
1170
+ return {
1171
+ ok: true,
1172
+ componentSource: parsed.componentSource
1173
+ };
1174
+ } catch (error) {
1175
+ return {
1176
+ ok: false,
1177
+ response: styleModuleFailure("invalid-edit", `Failed to read style-module request: ${error instanceof Error ? error.message : String(error)}`)
1178
+ };
1179
+ }
1180
+ }
1181
+ async function readRequestBody$1(request) {
1182
+ if (!request[Symbol.asyncIterator]) return "";
1183
+ let body = "";
1184
+ for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
1185
+ return body;
1186
+ }
1187
+ function styleModuleFailure(code, message, details) {
1188
+ return {
1189
+ ok: false,
1190
+ error: {
1191
+ code,
1192
+ message,
1193
+ details
1194
+ }
1195
+ };
1196
+ }
1197
+ function isMissingFileError$1(error) {
1198
+ return isRecord$1(error) && error.code === "ENOENT";
1199
+ }
1200
+ function isRecord$1(value) {
1201
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1202
+ }
1203
+ //#endregion
1204
+ //#region src/vite/tsxInstrumentation.ts
1205
+ function transformTsxSource(options) {
1206
+ const analysis = analyzePandaCssSource({
1207
+ filePath: options.filePath,
1208
+ projectRoot: options.projectRoot,
1209
+ sourceText: options.sourceText,
1210
+ cssImportSources: options.cssImportSources,
1211
+ sourceSyntax: options.sourceSyntax
1212
+ });
1213
+ const source = parsePandaSource(options.sourceSyntax, {
1214
+ filePath: options.filePath,
1215
+ sourceText: options.sourceText
1216
+ });
1217
+ const targets = source.astKind === "typescript" ? findEditableJsxTargets(source.root, options.projectRoot) : [];
1218
+ const jsxMetadataTargets = source.astKind === "typescript" ? findJsxMetadataTargets(source.root, options.projectRoot) : [];
1219
+ const targetsByObjectStart = new Map(targets.map((target) => [target.objectStart, target]));
1220
+ const cssCallTargets = findCssCallTargets(source);
1221
+ const cssCallsByCallStart = new Map(cssCallTargets.map((target) => [target.callStart, target]));
1222
+ const cssCallsByObjectStart = new Map(cssCallTargets.filter((target) => target.objectStart !== void 0).map((target) => [target.objectStart, target]));
1223
+ const helperName = availableHelperName(options.sourceText);
1224
+ const edits = [];
1225
+ const entries = [];
1226
+ const editableMetadataPositions = /* @__PURE__ */ new Set();
1227
+ let needsHelper = false;
1228
+ for (const entry of analysis.entries) {
1229
+ const markerClass = markerClassForEditId(entry.id);
1230
+ const target = entry.range ? targetsByObjectStart.get(entry.range.start) : void 0;
1231
+ const nextEntry = {
1232
+ ...entry,
1233
+ markerClass,
1234
+ component: target?.component,
1235
+ element: target?.element,
1236
+ attribute: target?.attribute,
1237
+ jsxSource: target?.jsxSource
1238
+ };
1239
+ entries.push(nextEntry);
1240
+ const callTarget = entry.kind === "panda-css" && entry.range ? cssCallsByObjectStart.get(entry.range.start) : entry.range ? cssCallsByCallStart.get(entry.range.start) : void 0;
1241
+ if (callTarget) {
1242
+ edits.push({
1243
+ position: callTarget.callStart,
1244
+ text: `${helperName}(`
1245
+ });
1246
+ edits.push({
1247
+ position: callTarget.callEnd,
1248
+ text: `, ${JSON.stringify(markerClass)})`
1249
+ });
1250
+ needsHelper = true;
1251
+ }
1252
+ if (target) {
1253
+ const attributeText = metadataAttributeText(nextEntry, target, options.attributes);
1254
+ if (attributeText.length > 0) edits.push({
1255
+ position: target.insertPosition,
1256
+ text: attributeText
1257
+ });
1258
+ editableMetadataPositions.add(target.insertPosition);
1259
+ }
1260
+ }
1261
+ for (const target of jsxMetadataTargets) {
1262
+ if (editableMetadataPositions.has(target.insertPosition)) continue;
1263
+ const attributeText = jsxMetadataAttributeText(target, options.attributes);
1264
+ if (attributeText.length > 0) edits.push({
1265
+ position: target.insertPosition,
1266
+ text: attributeText
1267
+ });
1268
+ }
1269
+ if (edits.length === 0) return {
1270
+ code: options.sourceText,
1271
+ entries
1272
+ };
1273
+ if (needsHelper) edits.push({
1274
+ position: source.ops.firstImportEnd(source.root),
1275
+ text: markerHelperSource(helperName)
1276
+ });
1277
+ let code = options.sourceText;
1278
+ for (const edit of edits.sort((left, right) => right.position - left.position)) code = `${code.slice(0, edit.position)}${edit.text}${code.slice(edit.position)}`;
1279
+ return {
1280
+ code,
1281
+ entries
1282
+ };
1283
+ }
1284
+ function findCssCallTargets(source) {
1285
+ const targets = [];
1286
+ source.ops.walk(source.root, (node) => {
1287
+ if (source.ops.isCallExpression(node)) {
1288
+ const firstArg = source.ops.getCallArguments(node)[0];
1289
+ const callRange = source.ops.getRange(node);
1290
+ targets.push({
1291
+ callStart: callRange.start,
1292
+ callEnd: callRange.end,
1293
+ objectStart: firstArg && source.ops.isObjectExpression(firstArg) ? source.ops.getRange(firstArg).start : void 0
1294
+ });
1295
+ }
1296
+ });
1297
+ return targets;
1298
+ }
1299
+ function availableHelperName(sourceText) {
1300
+ const base = "__pandaInspectorClass";
1301
+ if (!new RegExp(`\\b${base}\\b`).test(sourceText)) return base;
1302
+ let index = 1;
1303
+ while (new RegExp(`\\b${base}${index}\\b`).test(sourceText)) index += 1;
1304
+ return `${base}${index}`;
1305
+ }
1306
+ function markerHelperSource(helperName) {
1307
+ return [
1308
+ "",
1309
+ "",
1310
+ `function ${helperName}(className, markerClass) {`,
1311
+ " return className ? `${className} ${markerClass}` : markerClass;",
1312
+ "}",
1313
+ ""
1314
+ ].join("\n");
1315
+ }
1316
+ function findEditableJsxTargets(sourceFile, projectRoot) {
1317
+ const targets = [];
1318
+ const componentStack = [];
1319
+ const visit = (node) => {
1320
+ const component = componentNameForNode(node);
1321
+ if (component) {
1322
+ componentStack.push(component);
1323
+ ts.forEachChild(node, visit);
1324
+ componentStack.pop();
1325
+ return;
1326
+ }
1327
+ if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
1328
+ const target = targetForJsxElement(sourceFile, node, componentStack.at(-1), projectRoot);
1329
+ if (target) targets.push(target);
1330
+ }
1331
+ ts.forEachChild(node, visit);
1332
+ };
1333
+ visit(sourceFile);
1334
+ return targets;
1335
+ }
1336
+ function findJsxMetadataTargets(sourceFile, projectRoot) {
1337
+ const targets = [];
1338
+ const componentStack = [];
1339
+ const visit = (node) => {
1340
+ const component = componentNameForNode(node);
1341
+ if (component) {
1342
+ componentStack.push(component);
1343
+ ts.forEachChild(node, visit);
1344
+ componentStack.pop();
1345
+ return;
1346
+ }
1347
+ if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
1348
+ const existingAttributes = /* @__PURE__ */ new Set();
1349
+ for (const property of node.attributes.properties) if (ts.isJsxAttribute(property) && ts.isIdentifier(property.name)) existingAttributes.add(property.name.text);
1350
+ targets.push({
1351
+ insertPosition: node.getEnd() - (ts.isJsxSelfClosingElement(node) ? 2 : 1),
1352
+ component: componentStack.at(-1),
1353
+ jsxSource: sourceLocationText(sourceFile, node, projectRoot),
1354
+ existingAttributes
1355
+ });
1356
+ }
1357
+ ts.forEachChild(node, visit);
1358
+ };
1359
+ visit(sourceFile);
1360
+ return targets;
1361
+ }
1362
+ function targetForJsxElement(sourceFile, node, component, projectRoot) {
1363
+ const element = jsxTagNameText(node.tagName);
1364
+ const existingAttributes = /* @__PURE__ */ new Set();
1365
+ for (const property of node.attributes.properties) if (ts.isJsxAttribute(property) && ts.isIdentifier(property.name)) existingAttributes.add(property.name.text);
1366
+ for (const property of node.attributes.properties) {
1367
+ if (!ts.isJsxAttribute(property)) continue;
1368
+ if (!ts.isIdentifier(property.name)) continue;
1369
+ if (property.name.text !== "class" && property.name.text !== "className") continue;
1370
+ const expression = property.initializer && jsxAttributeExpression(property.initializer);
1371
+ if (!expression) continue;
1372
+ const objectStart = firstCssObjectLiteralStart(sourceFile, expression);
1373
+ if (objectStart === void 0) continue;
1374
+ return {
1375
+ objectStart,
1376
+ insertPosition: node.getEnd() - (ts.isJsxSelfClosingElement(node) ? 2 : 1),
1377
+ component,
1378
+ jsxSource: sourceLocationText(sourceFile, node, projectRoot),
1379
+ element,
1380
+ attribute: property.name.text,
1381
+ existingAttributes
1382
+ };
1383
+ }
1384
+ }
1385
+ function jsxAttributeExpression(initializer) {
1386
+ if (ts.isJsxExpression(initializer)) return initializer.expression;
1387
+ }
1388
+ function sourceLocationText(sourceFile, node, projectRoot) {
1389
+ const start = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
1390
+ return `${toRelativeProjectPath$1(sourceFile.fileName, projectRoot)}:${start.line + 1}:${start.character + 1}`;
1391
+ }
1392
+ function firstCssObjectLiteralStart(sourceFile, expression) {
1393
+ let result;
1394
+ const visit = (node) => {
1395
+ if (result !== void 0) return;
1396
+ if (ts.isCallExpression(node) && ts.isObjectLiteralExpression(node.arguments[0])) {
1397
+ result = node.arguments[0].getStart(sourceFile);
1398
+ return;
1399
+ }
1400
+ ts.forEachChild(node, visit);
1401
+ };
1402
+ visit(expression);
1403
+ return result;
1404
+ }
1405
+ function metadataAttributeText(entry, target, attributes) {
1406
+ const source = entry.id.split("#")[0] ?? entry.id;
1407
+ const metadata = [
1408
+ [attributes.editId, entry.id],
1409
+ [attributes.source, source],
1410
+ [attributes.jsxSource, target.jsxSource],
1411
+ [attributes.component, target.component]
1412
+ ];
1413
+ let text = "";
1414
+ for (const [name, value] of metadata) {
1415
+ if (!value || target.existingAttributes.has(name)) continue;
1416
+ text += ` ${name}="${escapeAttribute(value)}"`;
1417
+ }
1418
+ return text;
1419
+ }
1420
+ function jsxMetadataAttributeText(target, attributes) {
1421
+ const metadata = [[attributes.jsxSource, target.jsxSource], [attributes.component, target.component]];
1422
+ let text = "";
1423
+ for (const [name, value] of metadata) {
1424
+ if (!value || target.existingAttributes.has(name)) continue;
1425
+ text += ` ${name}="${escapeAttribute(value)}"`;
1426
+ }
1427
+ return text;
1428
+ }
1429
+ function componentNameForNode(node) {
1430
+ if (ts.isFunctionDeclaration(node) && node.name && isComponentName(node.name.text)) return node.name.text;
1431
+ if (!ts.isVariableDeclaration(node)) return void 0;
1432
+ if (!ts.isIdentifier(node.name) || !isComponentName(node.name.text)) return void 0;
1433
+ if (!node.initializer) return void 0;
1434
+ if (!ts.isArrowFunction(node.initializer) && !ts.isFunctionExpression(node.initializer)) return;
1435
+ return node.name.text;
1436
+ }
1437
+ function jsxTagNameText(name) {
1438
+ if (ts.isIdentifier(name)) return name.text;
1439
+ if (ts.isPropertyAccessExpression(name)) return name.name.text;
1440
+ }
1441
+ function isComponentName(name) {
1442
+ return /^[A-Z]/.test(name);
1443
+ }
1444
+ function shouldTransform(filePath, options) {
1445
+ if (filePath.endsWith(".d.ts")) return false;
1446
+ if (!resolveSourceParserAdapter(filePath, options.sourceSyntax).isSupportedFile(filePath)) return false;
1447
+ if ([...DEFAULT_EXCLUDE, ...options.exclude ?? []].some((pattern) => matchesGlob(filePath, pattern))) return false;
1448
+ if (!options.include || options.include.length === 0) return true;
1449
+ return options.include.some((pattern) => matchesGlob(filePath, pattern));
1450
+ }
1451
+ function matchesGlob(filePath, pattern) {
1452
+ const normalizedPattern = normalizePath$1(pattern);
1453
+ let regex = "";
1454
+ for (let index = 0; index < normalizedPattern.length; index += 1) {
1455
+ const char = normalizedPattern[index];
1456
+ const next = normalizedPattern[index + 1];
1457
+ if (char === "*" && next === "*") {
1458
+ if (normalizedPattern[index + 2] === "/") {
1459
+ regex += "(?:.*/)?";
1460
+ index += 2;
1461
+ continue;
1462
+ }
1463
+ regex += ".*";
1464
+ index += 1;
1465
+ continue;
1466
+ }
1467
+ if (char === "*") {
1468
+ regex += "[^/]*";
1469
+ continue;
1470
+ }
1471
+ if (char === "{") {
1472
+ const close = normalizedPattern.indexOf("}", index);
1473
+ if (close !== -1) {
1474
+ regex += `(${normalizedPattern.slice(index + 1, close).split(",").map(escapeRegExp).join("|")})`;
1475
+ index = close;
1476
+ continue;
1477
+ }
1478
+ }
1479
+ regex += escapeRegExp(char);
1480
+ }
1481
+ return new RegExp(`(^|/)${regex}$`).test(filePath);
1482
+ }
1483
+ function escapeAttribute(value) {
1484
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1485
+ }
1486
+ function escapeRegExp(value) {
1487
+ return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
1488
+ }
1489
+ //#endregion
1490
+ //#region src/vite/writebackEndpoints.ts
1491
+ function registerWritebackRoutes(server, options) {
1492
+ server.middlewares.use(DEFAULT_WRITEBACK_ENDPOINT, async (request, response) => {
1493
+ if (request.method && request.method !== "POST") {
1494
+ response.statusCode = 405;
1495
+ response.setHeader("content-type", "application/json");
1496
+ response.setHeader("cache-control", "no-store");
1497
+ response.end(JSON.stringify({
1498
+ ok: false,
1499
+ editId: "",
1500
+ written: false,
1501
+ error: {
1502
+ code: "invalid-edit",
1503
+ message: "Panda inspector writeback requires POST."
1504
+ }
1505
+ }));
1506
+ return;
1507
+ }
1508
+ const requestResult = await readStyleEditRequest(request);
1509
+ if (!requestResult.ok) {
1510
+ response.statusCode = 400;
1511
+ response.setHeader("content-type", "application/json");
1512
+ response.setHeader("cache-control", "no-store");
1513
+ response.end(JSON.stringify(requestResult.response));
1514
+ return;
1515
+ }
1516
+ const result = requestResult.request.kind === "panda-css-inline-source" ? await writeInlineCssSourcePatch({
1517
+ request: requestResult.request,
1518
+ projectRoot: options.projectRoot,
1519
+ cssImportSources: options.cssImportSources,
1520
+ sourceSyntax: options.sourceSyntax,
1521
+ attributes: options.attributes,
1522
+ onManifestEntries: options.onManifestEntries
1523
+ }) : requestResult.request.kind === "panda-css-style-module-source" || requestResult.request.kind === "panda-css-style-module-attach" || requestResult.request.kind === "panda-css-style-module-detach" ? await writeStyleModulePatch({
1524
+ request: requestResult.request,
1525
+ projectRoot: options.projectRoot,
1526
+ cssImportSources: options.cssImportSources,
1527
+ styledSystemPackageName: await inferStyledSystemPackageName(options.projectRoot),
1528
+ attributes: options.attributes,
1529
+ onManifestEntries: options.onManifestEntries
1530
+ }) : requestResult.request.kind === "panda-css-batch" ? await writeStaticCssBatchPatch({
1531
+ manifest: options.manifest(),
1532
+ request: requestResult.request,
1533
+ projectRoot: options.projectRoot,
1534
+ cssImportSources: options.cssImportSources,
1535
+ sourceSyntax: options.sourceSyntax,
1536
+ onManifestEntries: options.onManifestEntries
1537
+ }) : await writeStaticCssPatch({
1538
+ manifest: options.manifest(),
1539
+ request: requestResult.request,
1540
+ projectRoot: options.projectRoot,
1541
+ cssImportSources: options.cssImportSources,
1542
+ sourceSyntax: options.sourceSyntax,
1543
+ onManifestEntries: options.onManifestEntries
1544
+ });
1545
+ response.statusCode = result.ok ? 200 : 400;
1546
+ response.setHeader("content-type", "application/json");
1547
+ response.setHeader("cache-control", "no-store");
1548
+ response.end(JSON.stringify(result));
1549
+ if (result.ok && result.written && result.manifestUpdate) {
1550
+ notifyViteAboutWrittenFiles(server, options.projectRoot, result.manifestUpdate.changedFiles);
1551
+ server.ws?.send(PANDA_INSPECTOR_EVENTS.manifestUpdate, result.manifestUpdate);
1552
+ }
1553
+ });
1554
+ server.middlewares.use(DEFAULT_TOKEN_WRITEBACK_ENDPOINT, async (request, response) => {
1555
+ if (request.method && request.method !== "POST") {
1556
+ response.statusCode = 405;
1557
+ response.setHeader("content-type", "application/json");
1558
+ response.setHeader("cache-control", "no-store");
1559
+ response.end(JSON.stringify(tokenConfigEditFailure("", "invalid-edit", "Panda inspector token writeback requires POST.")));
1560
+ return;
1561
+ }
1562
+ const requestResult = await readTokenConfigEditRequest(request);
1563
+ if (!requestResult.ok) {
1564
+ response.statusCode = 400;
1565
+ response.setHeader("content-type", "application/json");
1566
+ response.setHeader("cache-control", "no-store");
1567
+ response.end(JSON.stringify(requestResult.response));
1568
+ return;
1569
+ }
1570
+ const result = await writeTokenConfigPatch({
1571
+ request: requestResult.request,
1572
+ projectRoot: options.projectRoot,
1573
+ pandaConfigPath: options.pandaConfigPath
1574
+ });
1575
+ response.statusCode = result.ok ? 200 : 400;
1576
+ response.setHeader("content-type", "application/json");
1577
+ response.setHeader("cache-control", "no-store");
1578
+ response.end(JSON.stringify(result));
1579
+ if (result.ok && result.written && result.metadataUpdate) {
1580
+ notifyViteAboutWrittenFiles(server, options.projectRoot, result.metadataUpdate.changedFiles);
1581
+ server.ws?.send(PANDA_INSPECTOR_EVENTS.metadataUpdate, result.metadataUpdate);
1582
+ }
1583
+ });
1584
+ }
1585
+ function notifyViteAboutWrittenFiles(server, projectRoot, changedFiles) {
1586
+ for (const changedFile of changedFiles) {
1587
+ const absoluteFile = normalizePath$1(`${projectRoot.replace(/\/$/, "")}/${changedFile}`);
1588
+ const modules = server.moduleGraph?.getModulesByFile?.(absoluteFile);
1589
+ if (modules) for (const module of modules) server.moduleGraph?.invalidateModule?.(module);
1590
+ server.watcher?.emit?.("change", absoluteFile);
1591
+ }
1592
+ }
1593
+ async function readStyleEditRequest(request) {
1594
+ try {
1595
+ const body = await readRequestBody(request);
1596
+ const parsed = JSON.parse(body);
1597
+ if (!isStyleEditRequest(parsed) && !isStyleEditBatchRequest(parsed) && !isInlineCssSourceCreateRequest(parsed) && !isStyleModuleEditRequest(parsed)) return {
1598
+ ok: false,
1599
+ response: styleEditFailure("", "invalid-edit", "Request body is not a valid style edit request.")
1600
+ };
1601
+ return {
1602
+ ok: true,
1603
+ request: parsed
1604
+ };
1605
+ } catch (error) {
1606
+ return {
1607
+ ok: false,
1608
+ response: styleEditFailure("", "invalid-edit", `Failed to read style edit request: ${error instanceof Error ? error.message : String(error)}`)
1609
+ };
1610
+ }
1611
+ }
1612
+ async function readTokenConfigEditRequest(request) {
1613
+ try {
1614
+ const body = await readRequestBody(request);
1615
+ const parsed = JSON.parse(body);
1616
+ if (!isTokenConfigEditRequest(parsed)) return {
1617
+ ok: false,
1618
+ response: tokenConfigEditFailure("", "invalid-edit", "Request body is not a valid token config edit request.")
1619
+ };
1620
+ return {
1621
+ ok: true,
1622
+ request: parsed
1623
+ };
1624
+ } catch (error) {
1625
+ return {
1626
+ ok: false,
1627
+ response: tokenConfigEditFailure("", "invalid-edit", `Failed to read token config edit request: ${error instanceof Error ? error.message : String(error)}`)
1628
+ };
1629
+ }
1630
+ }
1631
+ async function readRequestBody(request) {
1632
+ if (!request[Symbol.asyncIterator]) return "";
1633
+ let body = "";
1634
+ for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
1635
+ return body;
1636
+ }
1637
+ function isStyleEditRequest(value) {
1638
+ if (!isRecord(value)) return false;
1639
+ if (typeof value.editId !== "string" || value.editId.length === 0) return false;
1640
+ if (value.kind !== "panda-css") return false;
1641
+ if (!Array.isArray(value.edits) || value.edits.length === 0) return false;
1642
+ return value.edits.every((edit) => {
1643
+ if (!isRecord(edit)) return false;
1644
+ if (edit.op === "set") return isPath(edit.path) && isJsonValue(edit.value);
1645
+ if (edit.op === "delete") return isPath(edit.path);
1646
+ if (edit.op === "rename") return isPath(edit.from) && isPath(edit.to);
1647
+ if (edit.op === "replace-object") return isRecord(edit.value);
1648
+ return false;
1649
+ });
1650
+ }
1651
+ function isStyleEditBatchRequest(value) {
1652
+ if (!isRecord(value)) return false;
1653
+ if (value.kind !== "panda-css-batch") return false;
1654
+ if (!Array.isArray(value.requests) || value.requests.length === 0) return false;
1655
+ return value.requests.every(isStyleEditRequest);
1656
+ }
1657
+ function isInlineCssSourceCreateRequest(value) {
1658
+ if (!isRecord(value)) return false;
1659
+ if (typeof value.editId !== "string" || value.editId.length === 0) return false;
1660
+ if (value.kind !== "panda-css-inline-source") return false;
1661
+ if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
1662
+ return value.options === void 0 || isRecord(value.options);
1663
+ }
1664
+ function isStyleModuleEditRequest(value) {
1665
+ return isStyleModuleSourceCreateRequest(value) || isStyleModuleSourceAttachRequest(value) || isStyleModuleSourceDetachRequest(value);
1666
+ }
1667
+ function isStyleModuleSourceCreateRequest(value) {
1668
+ if (!isRecord(value)) return false;
1669
+ if (typeof value.editId !== "string" || value.editId.length === 0) return false;
1670
+ if (value.kind !== "panda-css-style-module-source") return false;
1671
+ if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
1672
+ if (typeof value.name !== "string" || value.name.length === 0) return false;
1673
+ if (value.edits !== void 0) {
1674
+ if (!Array.isArray(value.edits)) return false;
1675
+ if (!value.edits.every((edit) => {
1676
+ if (!isRecord(edit)) return false;
1677
+ if (edit.op === "set") return isPath(edit.path) && isJsonValue(edit.value);
1678
+ if (edit.op === "delete") return isPath(edit.path);
1679
+ return false;
1680
+ })) return false;
1681
+ }
1682
+ return value.options === void 0 || isRecord(value.options);
1683
+ }
1684
+ function isStyleModuleSourceAttachRequest(value) {
1685
+ if (!isRecord(value)) return false;
1686
+ if (typeof value.editId !== "string" || value.editId.length === 0) return false;
1687
+ if (value.kind !== "panda-css-style-module-attach") return false;
1688
+ if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
1689
+ if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
1690
+ if (typeof value.name !== "string" || value.name.length === 0) return false;
1691
+ return value.options === void 0 || isRecord(value.options);
1692
+ }
1693
+ function isStyleModuleSourceDetachRequest(value) {
1694
+ if (!isRecord(value)) return false;
1695
+ if (typeof value.editId !== "string" || value.editId.length === 0) return false;
1696
+ if (value.kind !== "panda-css-style-module-detach") return false;
1697
+ if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
1698
+ if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
1699
+ if (typeof value.name !== "string" || value.name.length === 0) return false;
1700
+ return value.options === void 0 || isRecord(value.options);
1701
+ }
1702
+ function isTokenConfigEditRequest(value) {
1703
+ if (!isRecord(value)) return false;
1704
+ if (typeof value.editId !== "string" || value.editId.length === 0) return false;
1705
+ if (value.kind !== "panda-token-config") return false;
1706
+ if (typeof value.sourceTargetId !== "string" || value.sourceTargetId.length === 0) return false;
1707
+ if (value.section !== "tokens.colors" && value.section !== "semanticTokens.colors") return false;
1708
+ if (!isPath(value.path)) return false;
1709
+ if (!isJsonPrimitive(value.value)) return false;
1710
+ return value.options === void 0 || isRecord(value.options);
1711
+ }
1712
+ function styleEditBatchFailure(response) {
1713
+ return {
1714
+ ok: false,
1715
+ editId: "",
1716
+ responses: [response],
1717
+ written: false,
1718
+ error: response.error
1719
+ };
1720
+ }
1721
+ function isNewEmptyInlineSourceEntry(entry) {
1722
+ return entry.kind === "panda-css" && (entry.attribute === "class" || entry.attribute === "className") && Object.keys(entry.styleObject).length === 0;
1723
+ }
1724
+ async function writeInlineCssSourcePatch(options) {
1725
+ const parsed = parseJsxSourceFile(options.request.jsxSource);
1726
+ if (!parsed.ok) return styleEditFailure(options.request.editId, parsed.code, parsed.message, parsed.details);
1727
+ const filePath = safeProjectSourcePath(options.projectRoot, parsed.file);
1728
+ if (!filePath.ok) return styleEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
1729
+ let sourceText;
1730
+ try {
1731
+ sourceText = await readFile(filePath.file, "utf8");
1732
+ } catch (error) {
1733
+ return styleEditFailure(options.request.editId, "write-failed", `Failed to read source file before inline source creation: ${error instanceof Error ? error.message : String(error)}`);
1734
+ }
1735
+ const patch = createInlineCssSourcePatch({
1736
+ projectRoot: options.projectRoot,
1737
+ request: {
1738
+ ...options.request,
1739
+ options: {
1740
+ ...options.request.options,
1741
+ write: true
1742
+ }
1743
+ },
1744
+ sourceText,
1745
+ filePath: filePath.file,
1746
+ cssImportSources: options.cssImportSources,
1747
+ sourceSyntax: options.sourceSyntax
1748
+ });
1749
+ if (!patch.ok || !patch.nextSource) return patch;
1750
+ if (options.request.options?.write !== true) return patch;
1751
+ try {
1752
+ await writeFile(filePath.file, patch.nextSource, "utf8");
1753
+ } catch (error) {
1754
+ return styleEditFailure(options.request.editId, "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`);
1755
+ }
1756
+ const nextEntries = transformTsxSource({
1757
+ sourceText: patch.nextSource,
1758
+ filePath: filePath.file,
1759
+ projectRoot: options.projectRoot,
1760
+ attributes: options.attributes,
1761
+ cssImportSources: options.cssImportSources,
1762
+ sourceSyntax: options.sourceSyntax
1763
+ }).entries.map((entry) => isNewEmptyInlineSourceEntry(entry) ? {
1764
+ ...entry,
1765
+ jsxSourceAliases: Array.from(new Set([...entry.jsxSourceAliases ?? [], options.request.jsxSource]))
1766
+ } : entry);
1767
+ options.onManifestEntries(filePath.file, nextEntries);
1768
+ const manifestUpdate = {
1769
+ version: 1,
1770
+ changedFiles: [toRelativeProjectPath$1(filePath.file, options.projectRoot)],
1771
+ entryIds: nextEntries.map((nextEntry) => nextEntry.id)
1772
+ };
1773
+ return {
1774
+ ...patch,
1775
+ written: true,
1776
+ manifestUpdate
1777
+ };
1778
+ }
1779
+ async function writeStyleModulePatch(options) {
1780
+ const paths = componentStyleModulePaths({
1781
+ projectRoot: options.projectRoot,
1782
+ componentSource: options.request.componentSource
1783
+ });
1784
+ if (!paths.ok) return styleEditFailure(options.request.editId, paths.code, paths.message, paths.details);
1785
+ const write = options.request.options?.write === true;
1786
+ if (options.request.kind === "panda-css-style-module-source") {
1787
+ let sourceText;
1788
+ try {
1789
+ sourceText = await readFile(paths.paths.styleFile, "utf8");
1790
+ } catch (error) {
1791
+ if (!isMissingFileError(error)) return styleEditFailure(options.request.editId, "write-failed", `Failed to read style module before writeback: ${error instanceof Error ? error.message : String(error)}`);
1792
+ }
1793
+ const patch = createStyleModuleSourcePatch({
1794
+ projectRoot: options.projectRoot,
1795
+ request: {
1796
+ ...options.request,
1797
+ options: {
1798
+ ...options.request.options,
1799
+ write
1800
+ }
1801
+ },
1802
+ sourceText,
1803
+ filePath: paths.paths.styleFile,
1804
+ cssImportSources: options.cssImportSources
1805
+ });
1806
+ if (!patch.ok || !patch.nextSource) return patch;
1807
+ if (!write) return patch;
1808
+ try {
1809
+ await mkdir(dirname(paths.paths.styleFile), { recursive: true });
1810
+ await writeFile(paths.paths.styleFile, patch.nextSource, "utf8");
1811
+ } catch (error) {
1812
+ return styleEditFailure(options.request.editId, "write-failed", `Failed to write style module: ${error instanceof Error ? error.message : String(error)}`);
1813
+ }
1814
+ const nextEntries = analyzePandaCssSource({
1815
+ sourceText: patch.nextSource,
1816
+ filePath: paths.paths.styleFile,
1817
+ projectRoot: options.projectRoot,
1818
+ cssImportSources: options.cssImportSources
1819
+ }).entries;
1820
+ options.onManifestEntries(paths.paths.styleFile, nextEntries);
1821
+ const manifestUpdate = {
1822
+ version: 1,
1823
+ changedFiles: [paths.paths.styleFileRelative],
1824
+ entryIds: nextEntries.map((nextEntry) => nextEntry.id)
1825
+ };
1826
+ return {
1827
+ ...patch,
1828
+ written: true,
1829
+ manifestUpdate
1830
+ };
1831
+ }
1832
+ let componentSourceText;
1833
+ try {
1834
+ componentSourceText = await readFile(paths.paths.componentFile, "utf8");
1835
+ } catch (error) {
1836
+ return styleEditFailure(options.request.editId, "write-failed", `Failed to read component module before style attachment: ${error instanceof Error ? error.message : String(error)}`);
1837
+ }
1838
+ let styleSourceText;
1839
+ try {
1840
+ styleSourceText = await readFile(paths.paths.styleFile, "utf8");
1841
+ } catch (error) {
1842
+ return styleEditFailure(options.request.editId, isMissingFileError(error) ? "manifest-entry-not-found" : "write-failed", isMissingFileError(error) ? "Style module does not exist yet." : `Failed to read style module before attachment: ${error instanceof Error ? error.message : String(error)}`);
1843
+ }
1844
+ const patch = options.request.kind === "panda-css-style-module-attach" ? createStyleModuleAttachPatch({
1845
+ projectRoot: options.projectRoot,
1846
+ request: {
1847
+ ...options.request,
1848
+ options: {
1849
+ ...options.request.options,
1850
+ write
1851
+ }
1852
+ },
1853
+ sourceText: componentSourceText,
1854
+ filePath: paths.paths.componentFile,
1855
+ styledSystemPackageName: options.styledSystemPackageName
1856
+ }) : createStyleModuleDetachPatch({
1857
+ projectRoot: options.projectRoot,
1858
+ request: {
1859
+ ...options.request,
1860
+ options: {
1861
+ ...options.request.options,
1862
+ write
1863
+ }
1864
+ },
1865
+ sourceText: componentSourceText,
1866
+ filePath: paths.paths.componentFile
1867
+ });
1868
+ if (!patch.ok || !patch.nextSource) return patch;
1869
+ if (!write) return patch;
1870
+ try {
1871
+ await writeFile(paths.paths.componentFile, patch.nextSource, "utf8");
1872
+ } catch (error) {
1873
+ return styleEditFailure(options.request.editId, "write-failed", `Failed to write component module: ${error instanceof Error ? error.message : String(error)}`);
1874
+ }
1875
+ const componentEntries = transformTsxSource({
1876
+ sourceText: patch.nextSource,
1877
+ filePath: paths.paths.componentFile,
1878
+ projectRoot: options.projectRoot,
1879
+ attributes: options.attributes,
1880
+ cssImportSources: options.cssImportSources
1881
+ }).entries;
1882
+ const analyzedStyleEntries = analyzePandaCssSource({
1883
+ sourceText: styleSourceText,
1884
+ filePath: paths.paths.styleFile,
1885
+ projectRoot: options.projectRoot,
1886
+ cssImportSources: options.cssImportSources
1887
+ }).entries;
1888
+ const styleEntries = styleModuleEntriesWithJsxAlias({
1889
+ entries: analyzedStyleEntries,
1890
+ request: options.request
1891
+ });
1892
+ options.onManifestEntries(paths.paths.componentFile, componentEntries);
1893
+ options.onManifestEntries(paths.paths.styleFile, styleEntries);
1894
+ const manifestUpdate = {
1895
+ version: 1,
1896
+ changedFiles: [toRelativeProjectPath$1(paths.paths.componentFile, options.projectRoot), paths.paths.styleFileRelative],
1897
+ entryIds: [...componentEntries, ...styleEntries].map((nextEntry) => nextEntry.id)
1898
+ };
1899
+ return {
1900
+ ...patch,
1901
+ written: true,
1902
+ manifestUpdate
1903
+ };
1904
+ }
1905
+ function styleModuleEntriesWithJsxAlias(options) {
1906
+ return options.entries.map((entry) => {
1907
+ if (entry.name !== options.request.name) return entry;
1908
+ if (options.request.kind === "panda-css-style-module-attach") return {
1909
+ ...entry,
1910
+ jsxSourceAliases: Array.from(new Set([...entry.jsxSourceAliases ?? [], options.request.jsxSource]))
1911
+ };
1912
+ const nextAliases = (entry.jsxSourceAliases ?? []).filter((source) => source !== options.request.jsxSource);
1913
+ const { jsxSourceAliases: _removed, ...entryWithoutAliases } = entry;
1914
+ return nextAliases.length === 0 ? entryWithoutAliases : {
1915
+ ...entry,
1916
+ jsxSourceAliases: nextAliases
1917
+ };
1918
+ });
1919
+ }
1920
+ async function writeStaticCssPatch(options) {
1921
+ const entry = options.manifest.entries.find((item) => item.id === options.request.editId);
1922
+ if (!entry) return styleEditFailure(options.request.editId, "manifest-entry-not-found", "No manifest entry exists for edit id.");
1923
+ const filePath = trustedManifestFilePath(options.manifest, entry);
1924
+ if (!filePath.ok) return styleEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
1925
+ let sourceText;
1926
+ try {
1927
+ sourceText = await readFile(filePath.file, "utf8");
1928
+ } catch (error) {
1929
+ return styleEditFailure(options.request.editId, "write-failed", `Failed to read source file before writeback: ${error instanceof Error ? error.message : String(error)}`);
1930
+ }
1931
+ const patch = createStaticCssPatch({
1932
+ manifest: options.manifest,
1933
+ request: {
1934
+ ...options.request,
1935
+ options: {
1936
+ ...options.request.options,
1937
+ write: true
1938
+ }
1939
+ },
1940
+ sourceText,
1941
+ filePath: filePath.file,
1942
+ styledSystemPackageName: await inferStyledSystemPackageName(options.projectRoot),
1943
+ sourceSyntax: options.sourceSyntax
1944
+ });
1945
+ if (!patch.ok || !patch.nextSource) return patch;
1946
+ if (options.request.options?.write !== true) return patch;
1947
+ try {
1948
+ await writeFile(filePath.file, patch.nextSource, "utf8");
1949
+ } catch (error) {
1950
+ return styleEditFailure(options.request.editId, "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`);
1951
+ }
1952
+ const nextEntries = analyzePandaCssSource({
1953
+ sourceText: patch.nextSource,
1954
+ filePath: filePath.file,
1955
+ projectRoot: options.projectRoot,
1956
+ cssImportSources: options.cssImportSources,
1957
+ sourceSyntax: options.sourceSyntax
1958
+ }).entries;
1959
+ options.onManifestEntries(filePath.file, nextEntries);
1960
+ const manifestUpdate = {
1961
+ version: 1,
1962
+ changedFiles: [toRelativeProjectPath$1(filePath.file, options.projectRoot)],
1963
+ entryIds: nextEntries.map((nextEntry) => nextEntry.id)
1964
+ };
1965
+ return {
1966
+ ...patch,
1967
+ written: true,
1968
+ manifestUpdate
1969
+ };
1970
+ }
1971
+ async function writeStaticCssBatchPatch(options) {
1972
+ const write = options.request.options?.write === true;
1973
+ const groups = /* @__PURE__ */ new Map();
1974
+ for (const request of options.request.requests) {
1975
+ const entry = options.manifest.entries.find((item) => item.id === request.editId);
1976
+ if (!entry) return styleEditBatchFailure(styleEditFailure(request.editId, "manifest-entry-not-found", "No manifest entry exists for edit id."));
1977
+ const filePath = trustedManifestFilePath(options.manifest, entry);
1978
+ if (!filePath.ok) return styleEditBatchFailure(styleEditFailure(request.editId, filePath.code, filePath.message, filePath.details));
1979
+ const changedFile = toRelativeProjectPath$1(filePath.file, options.projectRoot);
1980
+ const group = groups.get(filePath.file);
1981
+ if (group) group.requests.push(request);
1982
+ else groups.set(filePath.file, {
1983
+ file: filePath.file,
1984
+ changedFile,
1985
+ requests: [request]
1986
+ });
1987
+ }
1988
+ const prepared = [];
1989
+ for (const group of groups.values()) {
1990
+ let sourceText;
1991
+ try {
1992
+ sourceText = await readFile(group.file, "utf8");
1993
+ } catch (error) {
1994
+ return styleEditBatchFailure(styleEditFailure(group.requests[0]?.editId ?? "", "write-failed", `Failed to read source file before writeback: ${error instanceof Error ? error.message : String(error)}`));
1995
+ }
1996
+ const patch = createStaticCssBatchPatch({
1997
+ manifest: options.manifest,
1998
+ requests: group.requests.map((request) => ({
1999
+ ...request,
2000
+ options: {
2001
+ ...request.options,
2002
+ write
2003
+ }
2004
+ })),
2005
+ sourceText,
2006
+ filePath: group.file,
2007
+ styledSystemPackageName: await inferStyledSystemPackageName(options.projectRoot),
2008
+ sourceSyntax: options.sourceSyntax
2009
+ });
2010
+ if (!patch.ok || !patch.nextSource) return styleEditBatchFailure(patch);
2011
+ prepared.push({
2012
+ file: group.file,
2013
+ changedFile: group.changedFile,
2014
+ requests: group.requests,
2015
+ nextSource: patch.nextSource
2016
+ });
2017
+ }
2018
+ const changedFiles = prepared.map((item) => item.changedFile);
2019
+ const entryIds = [];
2020
+ if (write) for (const item of prepared) {
2021
+ try {
2022
+ await writeFile(item.file, item.nextSource, "utf8");
2023
+ } catch (error) {
2024
+ return styleEditBatchFailure(styleEditFailure(item.requests[0]?.editId ?? "", "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`));
2025
+ }
2026
+ const nextEntries = analyzePandaCssSource({
2027
+ sourceText: item.nextSource,
2028
+ filePath: item.file,
2029
+ projectRoot: options.projectRoot,
2030
+ cssImportSources: options.cssImportSources,
2031
+ sourceSyntax: options.sourceSyntax
2032
+ }).entries;
2033
+ options.onManifestEntries(item.file, nextEntries);
2034
+ entryIds.push(...nextEntries.map((nextEntry) => nextEntry.id));
2035
+ }
2036
+ const manifestUpdate = write ? {
2037
+ version: 1,
2038
+ changedFiles,
2039
+ entryIds
2040
+ } : void 0;
2041
+ const fileByEditId = /* @__PURE__ */ new Map();
2042
+ for (const item of prepared) for (const request of item.requests) fileByEditId.set(request.editId, item.changedFile);
2043
+ return {
2044
+ ok: true,
2045
+ editId: "",
2046
+ written: write,
2047
+ manifestUpdate,
2048
+ responses: options.request.requests.map((request) => ({
2049
+ ok: true,
2050
+ editId: request.editId,
2051
+ file: fileByEditId.get(request.editId),
2052
+ written: write,
2053
+ manifestUpdate
2054
+ }))
2055
+ };
2056
+ }
2057
+ async function writeTokenConfigPatch(options) {
2058
+ const metadata = await createEditorMetadata({
2059
+ projectRoot: options.projectRoot,
2060
+ pandaConfigPath: options.pandaConfigPath
2061
+ });
2062
+ if (metadata.tokenSources.status !== "available") return tokenConfigEditFailure(options.request.editId, "unsupported-source-shape", metadata.tokenSources.message);
2063
+ const tokenSource = metadata.tokenSources.items.find((item) => item.id === options.request.sourceTargetId);
2064
+ if (!tokenSource) return tokenConfigEditFailure(options.request.editId, "manifest-entry-not-found", "No token source exists for source target id.", { sourceTargetId: options.request.sourceTargetId });
2065
+ const filePath = trustedTokenSourceFilePath(options.projectRoot, tokenSource);
2066
+ if (!filePath.ok) return tokenConfigEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
2067
+ let sourceText;
2068
+ try {
2069
+ sourceText = await readFile(filePath.file, "utf8");
2070
+ } catch (error) {
2071
+ return tokenConfigEditFailure(options.request.editId, "write-failed", `Failed to read Panda config before token writeback: ${error instanceof Error ? error.message : String(error)}`);
2072
+ }
2073
+ const write = options.request.options?.write === true;
2074
+ const patch = createTokenConfigPatch({
2075
+ projectRoot: options.projectRoot,
2076
+ tokenSource,
2077
+ request: {
2078
+ ...options.request,
2079
+ options: {
2080
+ ...options.request.options,
2081
+ write
2082
+ }
2083
+ },
2084
+ sourceText,
2085
+ filePath: filePath.file
2086
+ });
2087
+ if (!patch.ok || !patch.nextSource) return patch;
2088
+ if (!write) return patch;
2089
+ try {
2090
+ await writeFile(filePath.file, patch.nextSource, "utf8");
2091
+ } catch (error) {
2092
+ return tokenConfigEditFailure(options.request.editId, "write-failed", `Failed to write Panda config: ${error instanceof Error ? error.message : String(error)}`);
2093
+ }
2094
+ const nextMetadata = await createEditorMetadata({
2095
+ projectRoot: options.projectRoot,
2096
+ pandaConfigPath: options.pandaConfigPath
2097
+ });
2098
+ const metadataUpdate = {
2099
+ version: 1,
2100
+ changedFiles: [toRelativeProjectPath$1(filePath.file, options.projectRoot)],
2101
+ tokenSourceIds: nextMetadata.tokenSources.status === "available" ? nextMetadata.tokenSources.items.map((item) => item.id) : []
2102
+ };
2103
+ return {
2104
+ ...patch,
2105
+ written: true,
2106
+ metadataUpdate
2107
+ };
2108
+ }
2109
+ async function inferStyledSystemPackageName(projectRoot) {
2110
+ try {
2111
+ const packageText = await readFile(`${projectRoot.replace(/\/$/, "")}/styled-system/package.json`, "utf8");
2112
+ const parsed = JSON.parse(packageText);
2113
+ return typeof parsed.name === "string" && parsed.name.trim() ? parsed.name : void 0;
2114
+ } catch {
2115
+ return;
2116
+ }
2117
+ }
2118
+ function styleEditFailure(editId, code, message, details) {
2119
+ return {
2120
+ ok: false,
2121
+ editId,
2122
+ written: false,
2123
+ error: {
2124
+ code,
2125
+ message,
2126
+ details
2127
+ }
2128
+ };
2129
+ }
2130
+ function tokenConfigEditFailure(editId, code, message, details) {
2131
+ return {
2132
+ ok: false,
2133
+ editId,
2134
+ written: false,
2135
+ error: {
2136
+ code,
2137
+ message,
2138
+ details
2139
+ }
2140
+ };
2141
+ }
2142
+ function parseJsxSourceFile(source) {
2143
+ const match = /^(.*):\d+:\d+$/.exec(source.trim());
2144
+ const file = match?.[1]?.trim();
2145
+ if (!match || !file) return {
2146
+ ok: false,
2147
+ code: "invalid-edit",
2148
+ message: "Inline source creation requires a JSX source path with line and column.",
2149
+ details: { source }
2150
+ };
2151
+ return {
2152
+ ok: true,
2153
+ file
2154
+ };
2155
+ }
2156
+ function isRecord(value) {
2157
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2158
+ }
2159
+ function isMissingFileError(error) {
2160
+ return isRecord(error) && error.code === "ENOENT";
2161
+ }
2162
+ function isPath(value) {
2163
+ return Array.isArray(value) && value.every((part) => typeof part === "string" && part.length > 0);
2164
+ }
2165
+ function isJsonValue(value) {
2166
+ if (value === null) return true;
2167
+ if ([
2168
+ "string",
2169
+ "number",
2170
+ "boolean"
2171
+ ].includes(typeof value)) return true;
2172
+ if (Array.isArray(value)) return value.every(isJsonValue);
2173
+ if (!isRecord(value)) return false;
2174
+ return Object.values(value).every(isJsonValue);
2175
+ }
2176
+ function isJsonPrimitive(value) {
2177
+ return value === null || [
2178
+ "string",
2179
+ "number",
2180
+ "boolean"
2181
+ ].includes(typeof value);
2182
+ }
2183
+ //#endregion
2184
+ //#region src/vite.ts
2185
+ function preactPandaInspector(options = {}) {
2186
+ const manifestByFile = /* @__PURE__ */ new Map();
2187
+ const endpoint = options.manifest?.virtualEndpoint ?? "/@panda-inspector/manifest";
2188
+ const editorMetadataEndpoint = options.metadata?.virtualEndpoint ?? "/@panda-inspector/editor-metadata";
2189
+ const runtimeBootstrapEndpoint = DEFAULT_RUNTIME_BOOTSTRAP_ENDPOINT;
2190
+ const runtimeModuleEndpoint = DEFAULT_RUNTIME_MODULE_ENDPOINT;
2191
+ const uiModuleEndpoint = DEFAULT_UI_MODULE_ENDPOINT;
2192
+ const runtimeChunkEndpoint = DEFAULT_RUNTIME_CHUNK_ENDPOINT;
2193
+ const attributes = {
2194
+ editId: options.attributes?.editId ?? "data-panda-edit-id",
2195
+ source: options.attributes?.source ?? "data-panda-source",
2196
+ jsxSource: options.attributes?.jsxSource ?? "data-panda-jsx-source",
2197
+ component: options.attributes?.component ?? "data-preact-component"
2198
+ };
2199
+ let projectRoot = normalizePath$1(options.projectRoot ?? "");
2200
+ let devEnabled = options.enabled !== false;
2201
+ let server;
2202
+ const manifest = () => ({
2203
+ version: 1,
2204
+ projectRoot,
2205
+ entries: [...manifestByFile.values()].flat()
2206
+ });
2207
+ return {
2208
+ name: "preact-panda-inspector",
2209
+ enforce: "pre",
2210
+ configResolved(config) {
2211
+ projectRoot = normalizePath$1(options.projectRoot ?? config.root ?? "");
2212
+ devEnabled = options.enabled !== false && config.command !== "build" && config.mode !== "production";
2213
+ },
2214
+ configureServer(nextServer) {
2215
+ server = nextServer;
2216
+ if (!devEnabled) return;
2217
+ nextServer.middlewares.use(endpoint, (_request, response) => {
2218
+ response.statusCode = 200;
2219
+ response.setHeader("content-type", "application/json");
2220
+ response.setHeader("cache-control", "no-store");
2221
+ response.end(JSON.stringify(manifest()));
2222
+ });
2223
+ nextServer.middlewares.use(editorMetadataEndpoint, async (_request, response) => {
2224
+ const metadata = await createEditorMetadata({
2225
+ projectRoot,
2226
+ pandaConfigPath: options.panda?.configPath
2227
+ });
2228
+ response.statusCode = 200;
2229
+ response.setHeader("content-type", "application/json");
2230
+ response.setHeader("cache-control", "no-store");
2231
+ response.end(JSON.stringify(metadata));
2232
+ });
2233
+ nextServer.middlewares.use(DEFAULT_OPEN_SOURCE_ENDPOINT, async (request, response) => {
2234
+ if (request.method && request.method !== "POST") {
2235
+ response.statusCode = 405;
2236
+ response.setHeader("content-type", "application/json");
2237
+ response.setHeader("cache-control", "no-store");
2238
+ response.end(JSON.stringify(openSourceLocationFailure("invalid-request", "Panda inspector source opening requires POST.")));
2239
+ return;
2240
+ }
2241
+ const requestResult = await readOpenSourceLocationRequest(request);
2242
+ if (!requestResult.ok) {
2243
+ response.statusCode = 400;
2244
+ response.setHeader("content-type", "application/json");
2245
+ response.setHeader("cache-control", "no-store");
2246
+ response.end(JSON.stringify(requestResult.response));
2247
+ return;
2248
+ }
2249
+ const result = await resolveOpenSourceLocation({
2250
+ request: requestResult.request,
2251
+ manifest: manifest(),
2252
+ projectRoot
2253
+ });
2254
+ response.statusCode = result.ok ? 200 : 400;
2255
+ response.setHeader("content-type", "application/json");
2256
+ response.setHeader("cache-control", "no-store");
2257
+ response.end(JSON.stringify(result));
2258
+ });
2259
+ registerWritebackRoutes(nextServer, {
2260
+ projectRoot,
2261
+ pandaConfigPath: options.panda?.configPath,
2262
+ cssImportSources: options.panda?.cssImportSources,
2263
+ sourceSyntax: options.sourceSyntax,
2264
+ attributes,
2265
+ manifest,
2266
+ onManifestEntries(filePath, entries) {
2267
+ manifestByFile.set(filePath, entries);
2268
+ }
2269
+ });
2270
+ registerStyleModuleRoute(nextServer, {
2271
+ endpoint: DEFAULT_STYLE_MODULE_ENDPOINT,
2272
+ projectRoot,
2273
+ cssImportSources: options.panda?.cssImportSources
2274
+ });
2275
+ registerRuntimeModuleRoutes(nextServer, {
2276
+ manifestEndpoint: endpoint,
2277
+ editorMetadataEndpoint,
2278
+ globalName: options.runtime?.globalName,
2279
+ runtimeBootstrapEndpoint,
2280
+ runtimeModuleEndpoint,
2281
+ uiModuleEndpoint,
2282
+ runtimeChunkEndpoint
2283
+ });
2284
+ },
2285
+ transformIndexHtml() {
2286
+ if (!devEnabled || options.runtime?.inject === false) return void 0;
2287
+ return [{
2288
+ tag: "script",
2289
+ attrs: {
2290
+ type: "module",
2291
+ src: runtimeBootstrapEndpoint
2292
+ },
2293
+ injectTo: "body"
2294
+ }];
2295
+ },
2296
+ transform(code, id) {
2297
+ const filePath = normalizePath$1(stripViteQuery(id));
2298
+ if (!devEnabled || !shouldTransform(filePath, options)) {
2299
+ manifestByFile.delete(filePath);
2300
+ return null;
2301
+ }
2302
+ const result = transformTsxSource({
2303
+ sourceText: code,
2304
+ filePath,
2305
+ projectRoot,
2306
+ attributes,
2307
+ cssImportSources: options.panda?.cssImportSources,
2308
+ sourceSyntax: options.sourceSyntax
2309
+ });
2310
+ manifestByFile.set(filePath, result.entries);
2311
+ if (result.entries.length > 0) server?.ws?.send(PANDA_INSPECTOR_EVENTS.manifestUpdate, {
2312
+ version: 1,
2313
+ changedFiles: [toRelativeProjectPath$1(filePath, projectRoot)],
2314
+ entryIds: result.entries.map((entry) => entry.id)
2315
+ });
2316
+ if (result.code === code) return null;
2317
+ return {
2318
+ code: result.code,
2319
+ map: null
2320
+ };
2321
+ }
2322
+ };
2323
+ }
2324
+ //#endregion
2325
+ export { preactPandaInspector };