chaincss 2.1.38 → 2.1.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -545,10 +545,10 @@ var init_shorthands = __esm({
545
545
  c.overflowX = "hidden";
546
546
  c.overflowY = "auto";
547
547
  if (!c.nestedRules) c.nestedRules = [];
548
- const scale = typeof v === "number" ? v : 2;
548
+ const scale2 = typeof v === "number" ? v : 2;
549
549
  c.nestedRules.push({
550
550
  selector: "& > *",
551
- styles: { transform: `translateZ(-1px) scale(${scale})` }
551
+ styles: { transform: `translateZ(-1px) scale(${scale2})` }
552
552
  });
553
553
  },
554
554
  lineClamp: (v, c) => {
@@ -2371,7 +2371,7 @@ var init_Chain = __esm({
2371
2371
  if (prop === "pressable") return () => this.macroHandler("pressable");
2372
2372
  if (prop === "focusRing") return (color) => this.macroHandler("focusRing", color);
2373
2373
  if (prop === "outlineDebug") return () => this.macroHandler("outlineDebug");
2374
- if (prop === "parallax") return (scale) => this.macroHandler("parallax", scale);
2374
+ if (prop === "parallax") return (scale2) => this.macroHandler("parallax", scale2);
2375
2375
  if (prop === "lineClamp") return (lines) => this.macroHandler("lineClamp", lines);
2376
2376
  if (prop === "frostedNav") return (blur) => this.macroHandler("frostedNav", blur);
2377
2377
  if (prop === "gap") return (value) => this.setProperty("gap", value);
@@ -3545,7 +3545,7 @@ function withSmartStyles(WrappedComponent, styles) {
3545
3545
  // src/core/compiler.ts
3546
3546
  import fs6 from "fs";
3547
3547
  import path5 from "path";
3548
- import crypto4 from "crypto";
3548
+ import crypto5 from "crypto";
3549
3549
  import chalk2 from "chalk";
3550
3550
  import { fileURLToPath, pathToFileURL } from "url";
3551
3551
 
@@ -6167,6 +6167,431 @@ var PersistentCache = class {
6167
6167
 
6168
6168
  // src/core/compiler.ts
6169
6169
  init_shorthands();
6170
+
6171
+ // src/compiler/style-graph.ts
6172
+ import crypto4 from "crypto";
6173
+ function calculateSpecificity(selector) {
6174
+ let a = 0;
6175
+ let b = 0;
6176
+ let c = 0;
6177
+ const idMatches = selector.match(/#[a-zA-Z0-9_-]+/g);
6178
+ if (idMatches) a += idMatches.length;
6179
+ const classMatches = selector.match(/\.[a-zA-Z0-9_-]+/g);
6180
+ if (classMatches) b += classMatches.length;
6181
+ const attrMatches = selector.match(/\[[^\]]+\]/g);
6182
+ if (attrMatches) b += attrMatches.length;
6183
+ const pseudoClassMatches = selector.match(/:[a-zA-Z-]+(?:\([^)]*\))?/g);
6184
+ if (pseudoClassMatches) {
6185
+ const notMatches = selector.match(/:not\(([^)]+)\)/g);
6186
+ const regularPseudoClasses = pseudoClassMatches.length - (notMatches?.length || 0);
6187
+ b += Math.max(0, regularPseudoClasses);
6188
+ }
6189
+ const elementMatches = selector.match(/^[a-zA-Z]+|[a-zA-Z]+(?=[.#[:])/g);
6190
+ if (elementMatches) c += elementMatches.length;
6191
+ return a * 1e4 + b * 100 + c;
6192
+ }
6193
+ function hashProperties(properties) {
6194
+ const sorted = Object.entries(properties).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`).join(";");
6195
+ return crypto4.createHash("md5").update(sorted).digest("hex").slice(0, 8);
6196
+ }
6197
+ function kebab2(prop) {
6198
+ return prop.replace(/([A-Z])/g, "-$1").toLowerCase();
6199
+ }
6200
+ var StyleGraphBuilder = class {
6201
+ entries = [];
6202
+ nodes = /* @__PURE__ */ new Map();
6203
+ edges = [];
6204
+ orderCounter = 0;
6205
+ addEntry(entry) {
6206
+ entry.sourceOrder = this.orderCounter++;
6207
+ this.entries.push(entry);
6208
+ }
6209
+ build() {
6210
+ this.nodes.clear();
6211
+ this.edges = [];
6212
+ for (const entry of this.entries) {
6213
+ const id = `node-${this.nodes.size}`;
6214
+ const node = {
6215
+ id,
6216
+ selector: entry.selector,
6217
+ properties: entry.properties,
6218
+ specificity: calculateSpecificity(entry.selector),
6219
+ dependencies: [],
6220
+ dependents: [],
6221
+ mediaQuery: entry.mediaQuery,
6222
+ isDead: false,
6223
+ hash: hashProperties(entry.properties),
6224
+ sourceComponent: entry.sourceComponent
6225
+ };
6226
+ this.nodes.set(id, node);
6227
+ }
6228
+ const nodeArray = Array.from(this.nodes.values());
6229
+ for (let i = 0; i < nodeArray.length; i++) {
6230
+ for (let j = i + 1; j < nodeArray.length; j++) {
6231
+ const a = nodeArray[i];
6232
+ const b = nodeArray[j];
6233
+ if (this.selectorsOverlap(a.selector, b.selector)) {
6234
+ if (a.specificity <= b.specificity) {
6235
+ this.edges.push({ from: a.id, to: b.id, type: "overrides" });
6236
+ a.dependents.push(b.id);
6237
+ b.dependencies.push(a.id);
6238
+ }
6239
+ if (b.specificity <= a.specificity) {
6240
+ this.edges.push({ from: b.id, to: a.id, type: "overrides" });
6241
+ b.dependents.push(a.id);
6242
+ a.dependencies.push(b.id);
6243
+ }
6244
+ }
6245
+ }
6246
+ }
6247
+ const rootNodes = nodeArray.filter((n) => n.dependencies.length === 0).map((n) => n.id);
6248
+ const leafNodes = nodeArray.filter((n) => n.dependents.length === 0).map((n) => n.id);
6249
+ return {
6250
+ nodes: this.nodes,
6251
+ edges: this.edges,
6252
+ rootNodes,
6253
+ leafNodes
6254
+ };
6255
+ }
6256
+ selectorsOverlap(a, b) {
6257
+ const partsA = a.split(/[\s>+~]+/).filter(Boolean);
6258
+ const partsB = b.split(/[\s>+~]+/).filter(Boolean);
6259
+ for (const pa of partsA) {
6260
+ for (const pb of partsB) {
6261
+ if (pa === pb) return true;
6262
+ if (pa.startsWith(".") && pb.startsWith(".") && pa === pb) return true;
6263
+ }
6264
+ }
6265
+ return false;
6266
+ }
6267
+ };
6268
+ function eliminateDeadStyles(graph, knownSelectors) {
6269
+ if (knownSelectors.length === 0) {
6270
+ return { eliminated: 0, graph };
6271
+ }
6272
+ const reachable = /* @__PURE__ */ new Set();
6273
+ const queue = [];
6274
+ for (const [id, node] of graph.nodes) {
6275
+ if (knownSelectors.some((ks) => node.selector.includes(ks) || ks.includes(node.selector))) {
6276
+ reachable.add(id);
6277
+ queue.push(id);
6278
+ }
6279
+ }
6280
+ while (queue.length > 0) {
6281
+ const current = queue.shift();
6282
+ const node = graph.nodes.get(current);
6283
+ if (!node) continue;
6284
+ for (const depId of node.dependents) {
6285
+ if (!reachable.has(depId)) {
6286
+ reachable.add(depId);
6287
+ queue.push(depId);
6288
+ }
6289
+ }
6290
+ }
6291
+ let eliminated = 0;
6292
+ for (const [id, node] of graph.nodes) {
6293
+ if (!reachable.has(id)) {
6294
+ node.isDead = true;
6295
+ eliminated++;
6296
+ }
6297
+ }
6298
+ return { eliminated, graph };
6299
+ }
6300
+ function mergeIdenticalRules(graph, threshold) {
6301
+ const hashGroups = /* @__PURE__ */ new Map();
6302
+ for (const [, node] of graph.nodes) {
6303
+ if (node.isDead) continue;
6304
+ if (Object.keys(node.properties).length < threshold) continue;
6305
+ const existing = hashGroups.get(node.hash) || [];
6306
+ existing.push(node);
6307
+ hashGroups.set(node.hash, existing);
6308
+ }
6309
+ let merged = 0;
6310
+ for (const [, group] of hashGroups) {
6311
+ if (group.length < 2) continue;
6312
+ const mergedSelector = group.map((n) => n.selector).join(", ");
6313
+ const primary = group[0];
6314
+ primary.selector = mergedSelector;
6315
+ for (let i = 1; i < group.length; i++) {
6316
+ group[i].isDead = true;
6317
+ merged++;
6318
+ }
6319
+ }
6320
+ return { merged, graph };
6321
+ }
6322
+ function topologicalSort(graph) {
6323
+ const visited = /* @__PURE__ */ new Set();
6324
+ const sorted = [];
6325
+ const visiting = /* @__PURE__ */ new Set();
6326
+ function visit(id) {
6327
+ if (visited.has(id)) return true;
6328
+ if (visiting.has(id)) return false;
6329
+ visiting.add(id);
6330
+ const node = graph.nodes.get(id);
6331
+ if (node) {
6332
+ for (const depId of node.dependencies) {
6333
+ if (!visit(depId)) return false;
6334
+ }
6335
+ }
6336
+ visiting.delete(id);
6337
+ visited.add(id);
6338
+ if (node && !node.isDead) {
6339
+ sorted.push(node);
6340
+ }
6341
+ return true;
6342
+ }
6343
+ for (const id of graph.rootNodes) {
6344
+ if (!visit(id)) {
6345
+ return Array.from(graph.nodes.values()).filter((n) => !n.isDead).sort((a, b) => a.sourceComponent?.localeCompare(b.sourceComponent || "") || 0);
6346
+ }
6347
+ }
6348
+ for (const [id] of graph.nodes) {
6349
+ if (!visited.has(id)) {
6350
+ visit(id);
6351
+ }
6352
+ }
6353
+ return sorted;
6354
+ }
6355
+ function generateCSSFromGraph(graph, sortOutput = "specificity") {
6356
+ let nodes;
6357
+ switch (sortOutput) {
6358
+ case "specificity":
6359
+ nodes = Array.from(graph.nodes.values()).filter((n) => !n.isDead).sort((a, b) => a.specificity - b.specificity);
6360
+ break;
6361
+ case "topological":
6362
+ nodes = topologicalSort(graph);
6363
+ break;
6364
+ case "source-order":
6365
+ default:
6366
+ nodes = Array.from(graph.nodes.values()).filter((n) => !n.isDead);
6367
+ break;
6368
+ }
6369
+ let css = "";
6370
+ let currentMediaQuery;
6371
+ for (const node of nodes) {
6372
+ if (node.isDead) continue;
6373
+ if (node.mediaQuery !== currentMediaQuery) {
6374
+ if (currentMediaQuery) {
6375
+ css += "}\n\n";
6376
+ }
6377
+ if (node.mediaQuery) {
6378
+ css += `@media ${node.mediaQuery} {
6379
+ `;
6380
+ }
6381
+ currentMediaQuery = node.mediaQuery;
6382
+ }
6383
+ const rules = Object.entries(node.properties).map(([prop, value]) => ` ${kebab2(prop)}: ${value};`).join("\n");
6384
+ if (rules) {
6385
+ css += `${node.selector} {
6386
+ ${rules}
6387
+ }
6388
+ `;
6389
+ }
6390
+ }
6391
+ if (currentMediaQuery) {
6392
+ css += "}\n";
6393
+ }
6394
+ return css;
6395
+ }
6396
+ var StyleGraphCompiler = class {
6397
+ options;
6398
+ constructor(options = {}) {
6399
+ this.options = {
6400
+ eliminateDead: options.eliminateDead ?? false,
6401
+ knownSelectors: options.knownSelectors ?? [],
6402
+ mergeIdentical: options.mergeIdentical ?? false,
6403
+ mergeThreshold: options.mergeThreshold ?? 3,
6404
+ sortOutput: options.sortOutput ?? "specificity",
6405
+ verbose: options.verbose ?? false
6406
+ };
6407
+ }
6408
+ /**
6409
+ * Compile a set of style definitions through the graph compiler.
6410
+ */
6411
+ compile(styles) {
6412
+ const startTime = Date.now();
6413
+ const builder = new StyleGraphBuilder();
6414
+ let preOptimizationSize = 0;
6415
+ for (const [componentName, styleDef] of Object.entries(styles)) {
6416
+ if (!styleDef || !styleDef.selectors) continue;
6417
+ for (const selector of styleDef.selectors) {
6418
+ const properties = {};
6419
+ for (const [prop, value] of Object.entries(styleDef)) {
6420
+ if (prop === "selectors" || prop === "atRules" || prop === "nestedRules" || prop === "hover" || prop === "themes" || prop.startsWith("_")) {
6421
+ continue;
6422
+ }
6423
+ if (typeof value === "string" || typeof value === "number") {
6424
+ properties[prop] = String(value);
6425
+ preOptimizationSize += String(value).length + prop.length;
6426
+ }
6427
+ }
6428
+ if (Object.keys(properties).length > 0) {
6429
+ builder.addEntry({
6430
+ selector,
6431
+ properties,
6432
+ sourceComponent: componentName,
6433
+ sourceOrder: 0
6434
+ });
6435
+ }
6436
+ if (styleDef.hover && typeof styleDef.hover === "object") {
6437
+ const hoverProperties = {};
6438
+ for (const [prop, value] of Object.entries(styleDef.hover)) {
6439
+ if (typeof value === "string" || typeof value === "number") {
6440
+ hoverProperties[prop] = String(value);
6441
+ }
6442
+ }
6443
+ if (Object.keys(hoverProperties).length > 0) {
6444
+ builder.addEntry({
6445
+ selector: `${selector}:hover`,
6446
+ properties: hoverProperties,
6447
+ sourceComponent: componentName,
6448
+ sourceOrder: 0
6449
+ });
6450
+ }
6451
+ }
6452
+ if (styleDef.atRules) {
6453
+ for (const rule of styleDef.atRules) {
6454
+ if (rule.type === "media" && rule.styles && rule.query) {
6455
+ const mediaProperties = {};
6456
+ for (const [prop, value] of Object.entries(rule.styles)) {
6457
+ if (typeof value === "string" || typeof value === "number") {
6458
+ mediaProperties[prop] = String(value);
6459
+ }
6460
+ }
6461
+ if (Object.keys(mediaProperties).length > 0) {
6462
+ builder.addEntry({
6463
+ selector,
6464
+ properties: mediaProperties,
6465
+ sourceComponent: componentName,
6466
+ sourceOrder: 0,
6467
+ mediaQuery: rule.query
6468
+ });
6469
+ }
6470
+ }
6471
+ }
6472
+ }
6473
+ }
6474
+ }
6475
+ let graph = builder.build();
6476
+ let eliminatedDead = 0;
6477
+ if (this.options.eliminateDead && this.options.knownSelectors.length > 0) {
6478
+ const result = eliminateDeadStyles(graph, this.options.knownSelectors);
6479
+ eliminatedDead = result.eliminated;
6480
+ graph = result.graph;
6481
+ }
6482
+ let mergedRules = 0;
6483
+ if (this.options.mergeIdentical) {
6484
+ const result = mergeIdenticalRules(graph, this.options.mergeThreshold);
6485
+ mergedRules = result.merged;
6486
+ graph = result.graph;
6487
+ }
6488
+ const css = generateCSSFromGraph(graph, this.options.sortOutput);
6489
+ let postOptimizationSize = css.length;
6490
+ if (postOptimizationSize === 0) {
6491
+ postOptimizationSize = preOptimizationSize;
6492
+ }
6493
+ const classMap = {};
6494
+ for (const [, node] of graph.nodes) {
6495
+ if (!node.isDead && node.sourceComponent) {
6496
+ if (classMap[node.sourceComponent]) {
6497
+ classMap[node.sourceComponent] += ` ${node.selector.replace(/^\./, "")}`;
6498
+ } else {
6499
+ classMap[node.sourceComponent] = node.selector.replace(/^\./, "");
6500
+ }
6501
+ }
6502
+ }
6503
+ const totalNodes = graph.nodes.size;
6504
+ const aliveNodes = totalNodes - eliminatedDead;
6505
+ const savingsPercent = preOptimizationSize > 0 ? `${((preOptimizationSize - postOptimizationSize) / preOptimizationSize * 100).toFixed(1)}%` : "0%";
6506
+ const stats = {
6507
+ totalStyles: totalNodes,
6508
+ atomicStyles: 0,
6509
+ uniqueProperties: new Set(
6510
+ Array.from(graph.nodes.values()).filter((n) => !n.isDead).flatMap((n) => Object.keys(n.properties))
6511
+ ).size,
6512
+ savings: savingsPercent,
6513
+ compileTime: Date.now() - startTime
6514
+ };
6515
+ return {
6516
+ css,
6517
+ classMap,
6518
+ atomicClasses: [],
6519
+ stats,
6520
+ graph,
6521
+ eliminatedDead,
6522
+ mergedRules,
6523
+ optimizationTime: Date.now() - startTime,
6524
+ preOptimizationSize,
6525
+ postOptimizationSize
6526
+ };
6527
+ }
6528
+ /**
6529
+ * Analyze a style graph without generating CSS.
6530
+ */
6531
+ analyze(styles) {
6532
+ const builder = new StyleGraphBuilder();
6533
+ for (const [componentName, styleDef] of Object.entries(styles)) {
6534
+ if (!styleDef || !styleDef.selectors) continue;
6535
+ for (const selector of styleDef.selectors) {
6536
+ const properties = {};
6537
+ for (const [prop, value] of Object.entries(styleDef)) {
6538
+ if (prop === "selectors" || prop.startsWith("_")) continue;
6539
+ if (typeof value === "string" || typeof value === "number") {
6540
+ properties[prop] = String(value);
6541
+ }
6542
+ }
6543
+ if (Object.keys(properties).length > 0) {
6544
+ builder.addEntry({ selector, properties, sourceComponent: componentName, sourceOrder: 0 });
6545
+ }
6546
+ }
6547
+ }
6548
+ return builder.build();
6549
+ }
6550
+ /**
6551
+ * Get optimization statistics for a graph.
6552
+ */
6553
+ getStats(graph) {
6554
+ const nodes = Array.from(graph.nodes.values());
6555
+ const deadNodes = nodes.filter((n) => n.isDead).length;
6556
+ const averageSpecificity = nodes.length > 0 ? nodes.reduce((sum, n) => sum + n.specificity, 0) / nodes.length : 0;
6557
+ let maxDepth = 0;
6558
+ const depths = /* @__PURE__ */ new Map();
6559
+ function getDepth(id) {
6560
+ if (depths.has(id)) return depths.get(id);
6561
+ const node = graph.nodes.get(id);
6562
+ if (!node || node.dependencies.length === 0) {
6563
+ depths.set(id, 0);
6564
+ return 0;
6565
+ }
6566
+ const max = Math.max(...node.dependencies.map((d) => getDepth(d)));
6567
+ const depth = max + 1;
6568
+ depths.set(id, depth);
6569
+ return depth;
6570
+ }
6571
+ for (const [id] of graph.nodes) {
6572
+ maxDepth = Math.max(maxDepth, getDepth(id));
6573
+ }
6574
+ return {
6575
+ totalNodes: nodes.length,
6576
+ deadNodes,
6577
+ mergedGroups: 0,
6578
+ averageSpecificity: Math.round(averageSpecificity * 100) / 100,
6579
+ deepestDependencyChain: maxDepth
6580
+ };
6581
+ }
6582
+ /**
6583
+ * Update options.
6584
+ */
6585
+ configure(options) {
6586
+ this.options = { ...this.options, ...options };
6587
+ }
6588
+ };
6589
+ function compileGraph(styles, options) {
6590
+ const compiler = new StyleGraphCompiler(options);
6591
+ return compiler.compile(styles);
6592
+ }
6593
+
6594
+ // src/core/compiler.ts
6170
6595
  var __filename = typeof import.meta !== "undefined" ? (() => {
6171
6596
  try {
6172
6597
  return fileURLToPath(import.meta.url);
@@ -6217,6 +6642,35 @@ var ChainCSSCompiler = class {
6217
6642
  this.initOptimizer();
6218
6643
  this.initPrefixer();
6219
6644
  }
6645
+ /**
6646
+ * Compile using the style graph compiler for advanced optimizations.
6647
+ *
6648
+ * @example
6649
+ * const result = compiler.compileWithGraph(styles, {
6650
+ * eliminateDead: true,
6651
+ * knownSelectors: ['.header', '.footer'],
6652
+ * mergeIdentical: true
6653
+ * });
6654
+ */
6655
+ compileWithGraph(styles, options) {
6656
+ const graphCompiler = new StyleGraphCompiler({
6657
+ ...options,
6658
+ verbose: this.config.verbose
6659
+ });
6660
+ const result = graphCompiler.compile(styles);
6661
+ if (this.config.verbose) {
6662
+ if (result.eliminatedDead > 0) {
6663
+ console.log(` \u{1F9F9} Eliminated ${result.eliminatedDead} dead styles`);
6664
+ }
6665
+ if (result.mergedRules > 0) {
6666
+ console.log(` \u{1F517} Merged ${result.mergedRules} identical rules`);
6667
+ }
6668
+ if (result.optimizationTime > 0) {
6669
+ console.log(` \u26A1 Graph compilation: ${result.optimizationTime}ms`);
6670
+ }
6671
+ }
6672
+ return result;
6673
+ }
6220
6674
  hasStyles() {
6221
6675
  const combined = this.getCombinedCSS();
6222
6676
  return !!(combined && combined.trim().length > 0);
@@ -6254,7 +6708,7 @@ var ChainCSSCompiler = class {
6254
6708
  if (result.css && result.css.trim()) {
6255
6709
  this.accumulatedCSS += result.css + "\n";
6256
6710
  }
6257
- const cacheKey = crypto4.createHash("sha256").update(`${componentName}-${JSON.stringify(styleObj)}`).digest("hex").slice(0, 16);
6711
+ const cacheKey = crypto5.createHash("sha256").update(`${componentName}-${JSON.stringify(styleObj)}`).digest("hex").slice(0, 16);
6258
6712
  this.addToCache(cacheKey, {
6259
6713
  result: {
6260
6714
  css: result.css || "",
@@ -6382,7 +6836,7 @@ var ChainCSSCompiler = class {
6382
6836
  // ============================================================================
6383
6837
  hashStyleDef(styleDef) {
6384
6838
  const { _componentName, _generateComponent, _framework, _propsDefinition, ...relevant } = styleDef;
6385
- return crypto4.createHash("sha256").update(JSON.stringify(relevant)).digest("hex").slice(0, 16);
6839
+ return crypto5.createHash("sha256").update(JSON.stringify(relevant)).digest("hex").slice(0, 16);
6386
6840
  }
6387
6841
  async importModule(filePath) {
6388
6842
  const absolutePath = path5.resolve(filePath);
@@ -6810,7 +7264,7 @@ function createThemeContract(contractShape) {
6810
7264
  }
6811
7265
  function validateTheme(contract, theme = {}, path6 = "") {
6812
7266
  const errors = [];
6813
- function validate(contractPart, themePart, currentPath) {
7267
+ function validate2(contractPart, themePart, currentPath) {
6814
7268
  if (typeof contractPart === "object" && contractPart !== null) {
6815
7269
  const requiredKeys = Object.keys(contractPart);
6816
7270
  const themeKeys = Object.keys(themePart || {});
@@ -6819,7 +7273,7 @@ function validateTheme(contract, theme = {}, path6 = "") {
6819
7273
  if (!themePart || !(key in themePart)) {
6820
7274
  errors.push(` \u2717 Missing required token: "${newPath}"`);
6821
7275
  } else {
6822
- validate(
7276
+ validate2(
6823
7277
  contractPart[key],
6824
7278
  themePart[key],
6825
7279
  newPath
@@ -6838,7 +7292,7 @@ function validateTheme(contract, theme = {}, path6 = "") {
6838
7292
  }
6839
7293
  }
6840
7294
  }
6841
- validate(contract, theme, path6);
7295
+ validate2(contract, theme, path6);
6842
7296
  if (errors.length > 0) {
6843
7297
  throw new Error(`Theme Contract Validation Failed:
6844
7298
  ${errors.join("\n")}`);
@@ -6877,6 +7331,641 @@ init_helpers();
6877
7331
  init_animations();
6878
7332
  init_suggestions();
6879
7333
  init_Chain();
7334
+
7335
+ // src/compiler/math-engine.ts
7336
+ var DEFAULT_CONTEXT = {
7337
+ rootFontSize: 16,
7338
+ viewportWidth: 1920,
7339
+ viewportHeight: 1080,
7340
+ parentFontSize: 16,
7341
+ dpi: 96,
7342
+ elementWidth: 1920,
7343
+ elementHeight: 1080
7344
+ };
7345
+ var UNIT_CATEGORIES = {
7346
+ absolute: ["px", "cm", "mm", "in", "pt", "pc"],
7347
+ relative: ["rem", "em", "%", "ch", "ex"],
7348
+ viewport: ["vw", "vh", "vmin", "vmax"],
7349
+ angle: ["deg", "rad", "turn", "grad"],
7350
+ time: ["s", "ms"],
7351
+ resolution: ["dpi", "dpcm", "dppx"]
7352
+ };
7353
+ var PX_CONVERSIONS = {
7354
+ "cm": 37.795,
7355
+ "mm": 3.7795,
7356
+ "in": 96,
7357
+ "pt": 1.333,
7358
+ "pc": 16
7359
+ };
7360
+ function parseCSSValue(input) {
7361
+ if (typeof input === "number") {
7362
+ return { value: input, unit: "px" };
7363
+ }
7364
+ const trimmed = input.trim();
7365
+ const match = trimmed.match(/^(-?\d+(?:\.\d+)?)\s*(px|rem|em|%|vw|vh|vmin|vmax|ch|ex|cm|mm|in|pt|pc|deg|rad|turn|grad|s|ms|dpi|dpcm|dppx)?$/i);
7366
+ if (match) {
7367
+ return {
7368
+ value: parseFloat(match[1]),
7369
+ unit: match[2]?.toLowerCase() || "px"
7370
+ };
7371
+ }
7372
+ const numMatch = trimmed.match(/(-?\d+(?:\.\d+)?)/);
7373
+ return {
7374
+ value: numMatch ? parseFloat(numMatch[1]) : 0,
7375
+ unit: "px"
7376
+ };
7377
+ }
7378
+ function getUnitCategory(unit) {
7379
+ for (const [category, units] of Object.entries(UNIT_CATEGORIES)) {
7380
+ if (units.includes(unit)) return category;
7381
+ }
7382
+ return "unknown";
7383
+ }
7384
+ function resolveToPx(value, context) {
7385
+ const { value: v, unit } = value;
7386
+ switch (unit) {
7387
+ case "px":
7388
+ return v;
7389
+ case "rem":
7390
+ return v * context.rootFontSize;
7391
+ case "em":
7392
+ return v * context.parentFontSize;
7393
+ case "%":
7394
+ return v / 100 * context.parentFontSize;
7395
+ // Default to font-relative
7396
+ case "vw":
7397
+ return v / 100 * context.viewportWidth;
7398
+ case "vh":
7399
+ return v / 100 * context.viewportHeight;
7400
+ case "vmin":
7401
+ return v / 100 * Math.min(context.viewportWidth, context.viewportHeight);
7402
+ case "vmax":
7403
+ return v / 100 * Math.max(context.viewportWidth, context.viewportHeight);
7404
+ case "cm":
7405
+ return v * (PX_CONVERSIONS["cm"] || 37.795);
7406
+ case "mm":
7407
+ return v * (PX_CONVERSIONS["mm"] || 3.7795);
7408
+ case "in":
7409
+ return v * (PX_CONVERSIONS["in"] || 96);
7410
+ case "pt":
7411
+ return v * (PX_CONVERSIONS["pt"] || 1.333);
7412
+ case "pc":
7413
+ return v * (PX_CONVERSIONS["pc"] || 16);
7414
+ // ch/ex are approximate
7415
+ case "ch":
7416
+ return v * (context.parentFontSize * 0.5);
7417
+ case "ex":
7418
+ return v * (context.parentFontSize * 0.45);
7419
+ default:
7420
+ return v;
7421
+ }
7422
+ }
7423
+ function resolveFromPx(px, targetUnit, context) {
7424
+ switch (targetUnit) {
7425
+ case "px":
7426
+ return px;
7427
+ case "rem":
7428
+ return px / context.rootFontSize;
7429
+ case "em":
7430
+ return px / context.parentFontSize;
7431
+ case "%":
7432
+ return px / context.parentFontSize * 100;
7433
+ case "vw":
7434
+ return px / context.viewportWidth * 100;
7435
+ case "vh":
7436
+ return px / context.viewportHeight * 100;
7437
+ case "vmin":
7438
+ return px / Math.min(context.viewportWidth, context.viewportHeight) * 100;
7439
+ case "vmax":
7440
+ return px / Math.max(context.viewportWidth, context.viewportHeight) * 100;
7441
+ case "cm":
7442
+ return px / (PX_CONVERSIONS["cm"] || 37.795);
7443
+ case "mm":
7444
+ return px / (PX_CONVERSIONS["mm"] || 3.7795);
7445
+ case "in":
7446
+ return px / (PX_CONVERSIONS["in"] || 96);
7447
+ case "pt":
7448
+ return px / (PX_CONVERSIONS["pt"] || 1.333);
7449
+ case "pc":
7450
+ return px / (PX_CONVERSIONS["pc"] || 16);
7451
+ case "ch":
7452
+ return px / (context.parentFontSize * 0.5);
7453
+ case "ex":
7454
+ return px / (context.parentFontSize * 0.45);
7455
+ default:
7456
+ return px;
7457
+ }
7458
+ }
7459
+ function canResolve(a, b, context) {
7460
+ const catA = getUnitCategory(a.unit);
7461
+ const catB = getUnitCategory(b.unit);
7462
+ if (catA === catB) return true;
7463
+ if ((catA === "absolute" || catA === "relative") && (catB === "absolute" || catB === "relative")) return true;
7464
+ return false;
7465
+ }
7466
+ function createResult(value, unit, expression, resolved, explanations = []) {
7467
+ return {
7468
+ value,
7469
+ unit,
7470
+ expression,
7471
+ resolved,
7472
+ explanations,
7473
+ toString() {
7474
+ return this.expression;
7475
+ },
7476
+ toCalc() {
7477
+ return unit === "calc" ? expression : `calc(${expression})`;
7478
+ }
7479
+ };
7480
+ }
7481
+ function operate(a, op, b, context) {
7482
+ const ctx = { ...DEFAULT_CONTEXT, ...context };
7483
+ const valA = parseCSSValue(a);
7484
+ const valB = parseCSSValue(b);
7485
+ const explanations = [];
7486
+ if (valA.unit === valB.unit) {
7487
+ let result;
7488
+ switch (op) {
7489
+ case "add":
7490
+ result = valA.value + valB.value;
7491
+ break;
7492
+ case "subtract":
7493
+ result = valA.value - valB.value;
7494
+ break;
7495
+ case "multiply":
7496
+ result = valA.value * valB.value;
7497
+ break;
7498
+ case "divide":
7499
+ result = valA.value / valB.value;
7500
+ break;
7501
+ }
7502
+ const rounded = Math.round(result * 100) / 100;
7503
+ explanations.push(`Same unit (${valA.unit}) \u2014 direct ${op}`);
7504
+ return createResult(
7505
+ rounded,
7506
+ valA.unit,
7507
+ `${rounded}${valA.unit}`,
7508
+ { value: rounded, unit: valA.unit },
7509
+ explanations
7510
+ );
7511
+ }
7512
+ if (canResolve(valA, valB, ctx)) {
7513
+ const pxA = resolveToPx(valA, ctx);
7514
+ const pxB = resolveToPx(valB, ctx);
7515
+ let pxResult;
7516
+ switch (op) {
7517
+ case "add":
7518
+ pxResult = pxA + pxB;
7519
+ break;
7520
+ case "subtract":
7521
+ pxResult = pxA - pxB;
7522
+ break;
7523
+ case "multiply":
7524
+ pxResult = pxA * pxB;
7525
+ break;
7526
+ case "divide":
7527
+ pxResult = pxA / pxB;
7528
+ break;
7529
+ }
7530
+ const rounded = Math.round(pxResult * 100) / 100;
7531
+ explanations.push(`Resolved ${valA.value}${valA.unit} \u2192 ${Math.round(pxA * 100) / 100}px`);
7532
+ explanations.push(`Resolved ${valB.value}${valB.unit} \u2192 ${Math.round(pxB * 100) / 100}px`);
7533
+ explanations.push(`${op} \u2192 ${rounded}px`);
7534
+ return createResult(
7535
+ rounded,
7536
+ "px",
7537
+ `${rounded}px`,
7538
+ { value: rounded, unit: "px" },
7539
+ explanations
7540
+ );
7541
+ }
7542
+ const expr = `${valA.value}${valA.unit} ${getOpSymbol(op)} ${valB.value}${valB.unit}`;
7543
+ explanations.push(`Cannot resolve ${valA.unit} \u2194 ${valB.unit} \u2014 using calc()`);
7544
+ return createResult(
7545
+ 0,
7546
+ "calc",
7547
+ `calc(${expr})`,
7548
+ null,
7549
+ explanations
7550
+ );
7551
+ }
7552
+ function getOpSymbol(op) {
7553
+ switch (op) {
7554
+ case "add":
7555
+ return "+";
7556
+ case "subtract":
7557
+ return "-";
7558
+ case "multiply":
7559
+ return "*";
7560
+ case "divide":
7561
+ return "/";
7562
+ }
7563
+ }
7564
+ var math = {
7565
+ /**
7566
+ * Add two CSS values with unit resolution.
7567
+ *
7568
+ * @example
7569
+ * math.add('10px', '2rem') // → '42px' (with default context)
7570
+ * math.add('10px', '2rem', { rootFontSize: 16 }) // → '42px'
7571
+ * math.add('10px', '2vw') // → 'calc(10px + 2vw)'
7572
+ */
7573
+ add(a, b, context) {
7574
+ return operate(a, "add", b, context);
7575
+ },
7576
+ /**
7577
+ * Subtract two CSS values with unit resolution.
7578
+ */
7579
+ subtract(a, b, context) {
7580
+ return operate(a, "subtract", b, context);
7581
+ },
7582
+ /**
7583
+ * Multiply two CSS values with unit resolution.
7584
+ */
7585
+ multiply(a, b, context) {
7586
+ return operate(a, "multiply", b, context);
7587
+ },
7588
+ /**
7589
+ * Divide two CSS values with unit resolution.
7590
+ */
7591
+ divide(a, b, context) {
7592
+ return operate(a, "divide", b, context);
7593
+ },
7594
+ /**
7595
+ * Sum multiple CSS values.
7596
+ */
7597
+ sum(...values) {
7598
+ if (values.length === 0) {
7599
+ return createResult(0, "px", "0px", { value: 0, unit: "px" });
7600
+ }
7601
+ if (values.length === 1) {
7602
+ const parsed = parseCSSValue(values[0]);
7603
+ return createResult(parsed.value, parsed.unit, `${parsed.value}${parsed.unit}`, parsed);
7604
+ }
7605
+ let result = this.add(values[0], values[1]);
7606
+ for (let i = 2; i < values.length; i++) {
7607
+ result = this.add(result.expression, values[i]);
7608
+ }
7609
+ return result;
7610
+ },
7611
+ /**
7612
+ * Resolve a CSS value to pixels.
7613
+ */
7614
+ toPx(value, context) {
7615
+ const ctx = { ...DEFAULT_CONTEXT, ...context };
7616
+ const parsed = parseCSSValue(value);
7617
+ return resolveToPx(parsed, ctx);
7618
+ },
7619
+ /**
7620
+ * Convert between CSS units.
7621
+ */
7622
+ convert(value, toUnit, context) {
7623
+ const ctx = { ...DEFAULT_CONTEXT, ...context };
7624
+ const parsed = parseCSSValue(value);
7625
+ const px = resolveToPx(parsed, ctx);
7626
+ const converted = resolveFromPx(px, toUnit, ctx);
7627
+ const rounded = Math.round(converted * 1e3) / 1e3;
7628
+ return createResult(
7629
+ rounded,
7630
+ toUnit,
7631
+ `${rounded}${toUnit}`,
7632
+ { value: rounded, unit: toUnit },
7633
+ [`${parsed.value}${parsed.unit} \u2192 ${rounded}${toUnit}`]
7634
+ );
7635
+ },
7636
+ /**
7637
+ * Create a fluid typography clamp() expression.
7638
+ *
7639
+ * @example
7640
+ * math.fluidType({ minSize: 14, maxSize: 20 })
7641
+ * // → 'clamp(14px, 0.625vw + 12px, 20px)'
7642
+ * math.fluidType({ minSize: 14, maxSize: 20, unit: 'rem', rootFontSize: 16 })
7643
+ * // → 'clamp(0.875rem, 0.625vw + 0.75rem, 1.25rem)'
7644
+ */
7645
+ fluidType(config) {
7646
+ const {
7647
+ minSize,
7648
+ maxSize,
7649
+ minWidth = 320,
7650
+ maxWidth = 1280,
7651
+ unit = "px",
7652
+ rootFontSize = 16
7653
+ } = config;
7654
+ const slope = (maxSize - minSize) / (maxWidth - minWidth);
7655
+ const intercept = minSize - slope * minWidth;
7656
+ const slopeVw = Math.round(slope * 100 * 1e4) / 1e4;
7657
+ const interceptRounded = Math.round(intercept * 100) / 100;
7658
+ const minStr = unit === "rem" ? `${minSize / rootFontSize}rem` : `${minSize}${unit}`;
7659
+ const maxStr = unit === "rem" ? `${maxSize / rootFontSize}rem` : `${maxSize}${unit}`;
7660
+ const prefStr = `${slopeVw}vw + ${unit === "rem" ? interceptRounded / rootFontSize + "rem" : interceptRounded + unit}`;
7661
+ const expression = `clamp(${minStr}, ${prefStr}, ${maxStr})`;
7662
+ return createResult(
7663
+ 0,
7664
+ "calc",
7665
+ expression,
7666
+ null,
7667
+ [`Fluid type: ${minSize}${unit} \u2192 ${maxSize}${unit} between ${minWidth}px and ${maxWidth}px`]
7668
+ );
7669
+ },
7670
+ /**
7671
+ * Scale a value by a factor with unit preservation.
7672
+ */
7673
+ scale(value, factor) {
7674
+ const parsed = parseCSSValue(value);
7675
+ const scaled = Math.round(parsed.value * factor * 100) / 100;
7676
+ return createResult(
7677
+ scaled,
7678
+ parsed.unit,
7679
+ `${scaled}${parsed.unit}`,
7680
+ { value: scaled, unit: parsed.unit },
7681
+ [`Scaled ${parsed.value}${parsed.unit} \xD7 ${factor} = ${scaled}${parsed.unit}`]
7682
+ );
7683
+ },
7684
+ /**
7685
+ * Clamp a CSS value between min and max.
7686
+ */
7687
+ clampValue(value, min, max, context) {
7688
+ const parsed = parseCSSValue(value);
7689
+ const parsedMin = parseCSSValue(min);
7690
+ const parsedMax = parseCSSValue(max);
7691
+ if (parsed.unit === parsedMin.unit && parsed.unit === parsedMax.unit) {
7692
+ const clamped = Math.max(parsedMin.value, Math.min(parsedMax.value, parsed.value));
7693
+ return createResult(
7694
+ clamped,
7695
+ parsed.unit,
7696
+ `${clamped}${parsed.unit}`,
7697
+ { value: clamped, unit: parsed.unit },
7698
+ [`Clamped ${parsed.value} between ${parsedMin.value} and ${parsedMax.value}`]
7699
+ );
7700
+ }
7701
+ const valStr = `${parsed.value}${parsed.unit}`;
7702
+ const minStr = `${parsedMin.value}${parsedMin.unit}`;
7703
+ const maxStr = `${parsedMax.value}${parsedMax.unit}`;
7704
+ return createResult(
7705
+ 0,
7706
+ "calc",
7707
+ `clamp(${minStr}, ${valStr}, ${maxStr})`,
7708
+ null,
7709
+ ["Mixed units \u2014 using clamp()"]
7710
+ );
7711
+ },
7712
+ /**
7713
+ * Parse a CSS value into its numeric and unit parts.
7714
+ */
7715
+ parse(value) {
7716
+ return parseCSSValue(value);
7717
+ },
7718
+ /**
7719
+ * Check if two values have compatible units for direct operations.
7720
+ */
7721
+ compatible(a, b) {
7722
+ const valA = parseCSSValue(a);
7723
+ const valB = parseCSSValue(b);
7724
+ return valA.unit === valB.unit || getUnitCategory(valA.unit) === getUnitCategory(valB.unit);
7725
+ },
7726
+ /**
7727
+ * Get the category of a CSS unit.
7728
+ */
7729
+ unitCategory(unit) {
7730
+ return getUnitCategory(unit);
7731
+ },
7732
+ /**
7733
+ * Create a CSS min() expression.
7734
+ */
7735
+ cssMin(...values) {
7736
+ const formatted = values.map((v) => {
7737
+ const parsed = parseCSSValue(v);
7738
+ return `${parsed.value}${parsed.unit}`;
7739
+ });
7740
+ return `min(${formatted.join(", ")})`;
7741
+ },
7742
+ /**
7743
+ * Create a CSS max() expression.
7744
+ */
7745
+ cssMax(...values) {
7746
+ const formatted = values.map((v) => {
7747
+ const parsed = parseCSSValue(v);
7748
+ return `${parsed.value}${parsed.unit}`;
7749
+ });
7750
+ return `max(${formatted.join(", ")})`;
7751
+ },
7752
+ /**
7753
+ * Format a number with specified precision.
7754
+ */
7755
+ precision(value, decimals = 2) {
7756
+ return value.toFixed(decimals);
7757
+ }
7758
+ };
7759
+ var add = math.add.bind(math);
7760
+ var subtract = math.subtract.bind(math);
7761
+ var multiply = math.multiply.bind(math);
7762
+ var divide = math.divide.bind(math);
7763
+ var fluidType = math.fluidType.bind(math);
7764
+ var convert = math.convert.bind(math);
7765
+ var toPx = math.toPx.bind(math);
7766
+ var scale = math.scale.bind(math);
7767
+
7768
+ // src/compiler/intent-engine.ts
7769
+ var SEMANTIC_INTENTS = [
7770
+ { pattern: /^flexbox$/i, handler: (v, ctx) => ({ original: v, property: ctx.property || "display", corrected: "flex", defaults: { display: "flex", justifyContent: "center", alignItems: "center" }, confidence: 0.95, intent: "flexbox-centering", explanation: '"flexbox" mapped to display: flex with centering defaults.' }), description: "flexbox -> flex + centering" },
7771
+ { pattern: /^(absolutely|abs)$/i, handler: (v, ctx) => ({ original: v, property: ctx.property || "position", corrected: "absolute", defaults: { position: "absolute" }, confidence: 0.9, intent: "absolute-position", explanation: '"abs/absolutely" -> position: absolute' }), description: "abs -> absolute" },
7772
+ { pattern: /^(rel|relatively)$/i, handler: (v, ctx) => ({ original: v, property: ctx.property || "position", corrected: "relative", defaults: { position: "relative" }, confidence: 0.9, intent: "relative-position", explanation: '"rel/relatively" -> position: relative' }), description: "rel -> relative" },
7773
+ { pattern: /^(hidden|invisible)$/i, handler: (v, ctx) => ({ original: v, property: ctx.property || "visibility", corrected: v.toLowerCase() === "invisible" ? "hidden" : v.toLowerCase(), defaults: { visibility: "hidden" }, confidence: 0.9, intent: "visibility-toggle", explanation: '"' + v + '" -> visibility: hidden' }), description: "invisible -> hidden" },
7774
+ { pattern: /^(full|fullscreen|full-screen)$/i, handler: (v, ctx) => ({ original: v, property: ctx.property || "size", corrected: "100%", defaults: { width: "100%", height: "100%" }, confidence: 0.85, intent: "full-size", explanation: '"full/fullscreen" -> width/height: 100%' }), description: "full -> 100%" },
7775
+ { pattern: /^(rounded|round)$/i, handler: (v, ctx) => ({ original: v, property: ctx.property || "border-radius", corrected: "9999px", defaults: { borderRadius: "9999px" }, confidence: 0.8, intent: "rounded-pill", explanation: '"rounded" -> border-radius: 9999px (pill)' }), description: "rounded -> pill" }
7776
+ ];
7777
+ var VALUE_CORRECTIONS = {
7778
+ "display": [{ wrong: "flexbox", correct: "flex", confidence: 0.95 }, { wrong: "inline-flexbox", correct: "inline-flex", confidence: 0.95 }],
7779
+ "position": [{ wrong: "abs", correct: "absolute", confidence: 0.9 }, { wrong: "rel", correct: "relative", confidence: 0.9 }],
7780
+ "text-align": [{ wrong: "centered", correct: "center", confidence: 0.85 }, { wrong: "justified", correct: "justify", confidence: 0.85 }],
7781
+ "overflow": [{ wrong: "scrollable", correct: "auto", confidence: 0.8 }],
7782
+ "cursor": [{ wrong: "hand", correct: "pointer", confidence: 0.9 }],
7783
+ "user-select": [{ wrong: "unselectable", correct: "none", confidence: 0.85 }]
7784
+ };
7785
+ var KNOWN_PROPERTIES = ["display", "position", "color", "background", "width", "height", "font-size", "text-align", "cursor", "opacity", "z-index", "overflow", "visibility", "flex", "flex-direction", "justify-content", "align-items", "gap", "grid", "transition", "transform", "animation", "box-shadow", "pointer-events", "user-select", "line-height"];
7786
+ function levenshtein(a, b) {
7787
+ const m = [];
7788
+ for (let i = 0; i <= b.length; i++) m[i] = [i];
7789
+ for (let j = 0; j <= a.length; j++) m[0][j] = j;
7790
+ for (let i = 1; i <= b.length; i++)
7791
+ for (let j = 1; j <= a.length; j++)
7792
+ m[i][j] = Math.min(m[i - 1][j] + 1, m[i][j - 1] + 1, m[i - 1][j - 1] + (a[j - 1] === b[i - 1] ? 0 : 1));
7793
+ return m[b.length][a.length];
7794
+ }
7795
+ function findClosestProperty(prop) {
7796
+ const lp = prop.toLowerCase();
7797
+ let best = null, bestDist = Infinity;
7798
+ for (const k of KNOWN_PROPERTIES) {
7799
+ const d = levenshtein(lp, k);
7800
+ if (d < bestDist && d <= 3) {
7801
+ bestDist = d;
7802
+ best = k;
7803
+ }
7804
+ }
7805
+ return best;
7806
+ }
7807
+ function detectIntent(value, ctx = {}) {
7808
+ const lv = value.toLowerCase();
7809
+ for (const rule of SEMANTIC_INTENTS) {
7810
+ if (rule.pattern.test(lv)) {
7811
+ const r = rule.handler(value, ctx);
7812
+ if (r) return r;
7813
+ }
7814
+ }
7815
+ return null;
7816
+ }
7817
+ var intent = {
7818
+ correct(property, value, context) {
7819
+ const ctx = { property, value, ...context };
7820
+ const si = detectIntent(value, ctx);
7821
+ if (si) return si;
7822
+ if (VALUE_CORRECTIONS[property]) {
7823
+ const c = VALUE_CORRECTIONS[property].find((c2) => c2.wrong === value.toLowerCase());
7824
+ if (c) return { original: value, property, corrected: c.correct, defaults: { [property]: c.correct }, confidence: c.confidence, intent: "value-correction", explanation: `"${value}" is not valid for ${property}. Did you mean "${c.correct}"?` };
7825
+ }
7826
+ const pc = findClosestProperty(property);
7827
+ if (pc && pc !== property.toLowerCase()) {
7828
+ const d = levenshtein(property.toLowerCase(), pc);
7829
+ return { original: property, property, corrected: pc, defaults: {}, confidence: Math.max(0, 1 - d / Math.max(property.length, pc.length)), intent: "property-correction", explanation: `Unknown property "${property}". Did you mean "${pc}"?` };
7830
+ }
7831
+ return null;
7832
+ },
7833
+ heal(styles, mode = "smart", context) {
7834
+ const corrections = [], warnings = [], fixed = {};
7835
+ for (const [prop, value] of Object.entries(styles)) {
7836
+ if (prop.startsWith("_") || prop === "selectors") {
7837
+ fixed[prop] = value;
7838
+ continue;
7839
+ }
7840
+ if (typeof value === "object" && value !== null && prop === "hover") {
7841
+ const hr = this.heal(value, mode, { ...context, property: prop });
7842
+ fixed[prop] = hr.fixed;
7843
+ corrections.push(...hr.corrections);
7844
+ warnings.push(...hr.warnings);
7845
+ continue;
7846
+ }
7847
+ if (typeof value !== "string" && typeof value !== "number") {
7848
+ fixed[prop] = value;
7849
+ continue;
7850
+ }
7851
+ const sv = String(value), corr = this.correct(prop, sv, { ...context, property: prop, value: sv });
7852
+ if (corr) {
7853
+ corrections.push(corr);
7854
+ if (mode === "strict") {
7855
+ warnings.push("[strict] " + corr.explanation);
7856
+ fixed[prop] = sv;
7857
+ } else if (mode === "dev") {
7858
+ fixed[prop] = corr.corrected;
7859
+ Object.assign(fixed, corr.defaults);
7860
+ } else {
7861
+ warnings.push("[auto-fix] " + corr.explanation);
7862
+ fixed[prop] = corr.corrected;
7863
+ Object.assign(fixed, corr.defaults);
7864
+ }
7865
+ } else {
7866
+ fixed[prop] = value;
7867
+ }
7868
+ }
7869
+ return { fixed, corrections, warnings, mode };
7870
+ },
7871
+ getIntent(value, ctx) {
7872
+ const r = detectIntent(value, ctx);
7873
+ return r?.intent || null;
7874
+ },
7875
+ validate(property, value) {
7876
+ if (VALUE_CORRECTIONS[property]) {
7877
+ const c = VALUE_CORRECTIONS[property].find((c2) => c2.wrong === value.toLowerCase());
7878
+ if (c) return c.confidence < 1 ? { valid: false, suggestion: c.correct } : { valid: true };
7879
+ }
7880
+ if (!KNOWN_PROPERTIES.includes(property.toLowerCase())) {
7881
+ const s = findClosestProperty(property);
7882
+ return s ? { valid: false, suggestion: s } : { valid: false };
7883
+ }
7884
+ return { valid: true };
7885
+ },
7886
+ getCorrections(property) {
7887
+ return VALUE_CORRECTIONS[property] || [];
7888
+ },
7889
+ explain(correction) {
7890
+ return correction.explanation;
7891
+ },
7892
+ getKnownProperties() {
7893
+ return [...KNOWN_PROPERTIES];
7894
+ },
7895
+ getIntents() {
7896
+ return SEMANTIC_INTENTS.map((r) => ({ pattern: r.pattern.toString(), description: r.description }));
7897
+ }
7898
+ };
7899
+ var correct = intent.correct.bind(intent);
7900
+ var heal = intent.heal.bind(intent);
7901
+ var validate = intent.validate.bind(intent);
7902
+ var getIntent = intent.getIntent.bind(intent);
7903
+
7904
+ // src/compiler/analyzer.ts
7905
+ var CONFLICTS = [
7906
+ { props: ["position", "z-index", "zIndex"], msg: "z-index only works on positioned elements (not static)", sev: "warning" },
7907
+ { props: ["flex-direction", "align-items", "justify-content"], msg: "Flex properties require display: flex", sev: "warning" },
7908
+ { props: ["grid-template-columns", "grid-template-rows"], msg: "Grid properties require display: grid", sev: "warning" },
7909
+ { props: ["overflow", "overflow-x", "overflow-y"], msg: "Consider using the overflow shorthand", sev: "hint" }
7910
+ ];
7911
+ function detectShorthands(styles) {
7912
+ const d = [];
7913
+ const m = ["margin-top", "margin-right", "margin-bottom", "margin-left"].filter((p) => p in styles);
7914
+ if (m.length >= 3) d.push({ property: "margin", severity: "hint", message: 'Use "margin" shorthand instead of: ' + m.join(", "), suggestion: "margin" });
7915
+ return d;
7916
+ }
7917
+ var StyleAnalyzer = class {
7918
+ _diagnostics = [];
7919
+ analyzeStyle(selector, styles, _opts) {
7920
+ const r = [];
7921
+ for (const [p, v] of Object.entries(styles)) {
7922
+ if (p === "selectors" || p.startsWith("_") || typeof v === "object") continue;
7923
+ const val = intent.validate(p, String(v));
7924
+ if (!val.valid) r.push({ property: p, value: String(v), selector, severity: "warning", message: `"${v}" unrecognized for "${p}"`, suggestion: val.suggestion });
7925
+ }
7926
+ r.push(...detectShorthands(styles));
7927
+ this._diagnostics.push(...r);
7928
+ const sp = Object.keys(styles).filter((k) => typeof styles[k] !== "object");
7929
+ for (const c of CONFLICTS) {
7930
+ const ix = c.props.filter((k) => sp.includes(k));
7931
+ if (ix.length >= 2) r.push({ property: c.props.join(", "), selector, severity: c.sev, message: c.msg });
7932
+ }
7933
+ return r;
7934
+ }
7935
+ analyze(sd) {
7936
+ const ad = [];
7937
+ const sels = sd.selectors || ["&"];
7938
+ for (const s of sels) ad.push(...this.analyzeStyle(s, sd));
7939
+ if (sd.hover && typeof sd.hover === "object") for (const s of sels) ad.push(...this.analyzeStyle(s + ":hover", sd.hover));
7940
+ return {
7941
+ diagnostics: ad,
7942
+ conflicts: [],
7943
+ breakpoints: [],
7944
+ unusedSelectors: [],
7945
+ deadStyles: [],
7946
+ duplicationWarnings: [],
7947
+ optimizationSuggestions: [],
7948
+ stats: {
7949
+ totalProperties: Object.keys(sd).filter((k) => !["selectors", "atRules", "nestedRules", "hover", "themes"].includes(k) && !k.startsWith("_")).length,
7950
+ totalSelectors: sels.length,
7951
+ shorthandOpportunities: ad.filter((d) => d.message.includes("shorthand")).length,
7952
+ animationSuggestions: 0,
7953
+ responsiveIssues: 0
7954
+ }
7955
+ };
7956
+ }
7957
+ reset() {
7958
+ this._diagnostics = [];
7959
+ }
7960
+ getDiagnostics() {
7961
+ return [...this._diagnostics];
7962
+ }
7963
+ };
7964
+ function analyze(sd) {
7965
+ return new StyleAnalyzer().analyze(sd);
7966
+ }
7967
+
7968
+ // src/index.ts
6880
7969
  var VERSION2 = "3.0.0";
6881
7970
  var index_default = chain;
6882
7971
  if (typeof process !== "undefined" && process.env?.NODE_ENV !== "test") {
@@ -6895,8 +7984,12 @@ export {
6895
7984
  ChainCSSPrefixer,
6896
7985
  DesignTokens,
6897
7986
  PersistentCache,
7987
+ StyleAnalyzer,
7988
+ StyleGraphCompiler,
6898
7989
  Theme,
6899
7990
  VERSION2 as VERSION,
7991
+ add,
7992
+ analyze as analyzeStyle,
6900
7993
  animationPresets,
6901
7994
  autoDetector,
6902
7995
  buildChain,
@@ -6904,7 +7997,10 @@ export {
6904
7997
  smartChain as chainV3,
6905
7998
  clearTimeline,
6906
7999
  compileChainCSS,
8000
+ compileGraph,
6907
8001
  configureAtomic,
8002
+ convert,
8003
+ correct,
6908
8004
  createAnimation,
6909
8005
  createTokens as createDesignTokens,
6910
8006
  createSmartComponent,
@@ -6912,13 +8008,16 @@ export {
6912
8008
  createThemeContract,
6913
8009
  createTokens2 as createTokens,
6914
8010
  index_default as default,
8011
+ divide,
6915
8012
  enableDebug,
6916
8013
  enableTimeline,
6917
8014
  expandShorthand,
6918
8015
  exportTimeline,
8016
+ fluidType,
6919
8017
  getAnimationPreset,
6920
8018
  getAnimationPresetNames,
6921
8019
  getAvailableShorthands,
8020
+ getIntent,
6922
8021
  getPropertySuggestion,
6923
8022
  getShorthandSuggestion,
6924
8023
  getStyleChanges,
@@ -6928,17 +8027,25 @@ export {
6928
8027
  getSuggestions,
6929
8028
  handleShorthand,
6930
8029
  hasAnimationPreset,
8030
+ heal,
6931
8031
  helpers,
6932
8032
  injectChainStyles,
8033
+ intent,
6933
8034
  isShorthand,
6934
8035
  macros,
8036
+ math,
8037
+ multiply,
6935
8038
  recipe,
6936
8039
  runtimeChain,
8040
+ scale,
6937
8041
  setBreakpoints,
6938
8042
  shorthandMap,
6939
8043
  smartChain,
8044
+ subtract,
8045
+ toPx,
6940
8046
  tokens2 as tokens,
6941
8047
  useSmartStyles,
6942
8048
  validateTheme,
8049
+ validate as validateValue,
6943
8050
  withSmartStyles
6944
8051
  };