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/ROADMAP.md ADDED
@@ -0,0 +1,31 @@
1
+
2
+ ## v3.0 Ideas
3
+
4
+ ### 1. Predictive & Self-Healing CSS
5
+ - Context-aware typo correction (not just fuzzy matching)
6
+ - Intent detection: `display: "flexbox"` → maps to `display: flex` + applies defaults
7
+ - Modes: strict (error), dev (auto-fix), smart (fix + log)
8
+ - Builds on: suggestions.ts, explain()
9
+
10
+ ### 2. Style Graph Compiler
11
+ - Instead of linear compilation, build a dependency graph of styles
12
+ - Dead style elimination
13
+ - Automatic merging of identical rules
14
+ - Predictive pre-compilation
15
+ - Order-safe CSS output
16
+ - Builds on: compile(), atomic optimizer
17
+
18
+ ### 3. Unit-Aware Math Engine
19
+ - Full CSS expression evaluator
20
+ - `add("10px", "2rem")` → resolves units → optimized calc()
21
+ - `fluidType(14, 20)` → responsive clamp()
22
+ - Context-aware scaling
23
+ - Builds on: helpers.ts
24
+
25
+ ### 4. IDE Intelligence Layer (VS Code Extension)
26
+ - Real-time invalid property detection
27
+ - Shorthand translation hints
28
+ - Animation suggestion
29
+ - Breakpoint inference
30
+ - Style conflict detection
31
+ - Builds on: suggestions.ts
package/dist/cli/index.js CHANGED
@@ -2612,6 +2612,431 @@ var init_content_addressable_cache = __esm({
2612
2612
  }
2613
2613
  });
2614
2614
 
2615
+ // src/compiler/style-graph.ts
2616
+ import crypto4 from "crypto";
2617
+ function calculateSpecificity(selector) {
2618
+ let a = 0;
2619
+ let b = 0;
2620
+ let c = 0;
2621
+ const idMatches = selector.match(/#[a-zA-Z0-9_-]+/g);
2622
+ if (idMatches) a += idMatches.length;
2623
+ const classMatches = selector.match(/\.[a-zA-Z0-9_-]+/g);
2624
+ if (classMatches) b += classMatches.length;
2625
+ const attrMatches = selector.match(/\[[^\]]+\]/g);
2626
+ if (attrMatches) b += attrMatches.length;
2627
+ const pseudoClassMatches = selector.match(/:[a-zA-Z-]+(?:\([^)]*\))?/g);
2628
+ if (pseudoClassMatches) {
2629
+ const notMatches = selector.match(/:not\(([^)]+)\)/g);
2630
+ const regularPseudoClasses = pseudoClassMatches.length - (notMatches?.length || 0);
2631
+ b += Math.max(0, regularPseudoClasses);
2632
+ }
2633
+ const elementMatches = selector.match(/^[a-zA-Z]+|[a-zA-Z]+(?=[.#[:])/g);
2634
+ if (elementMatches) c += elementMatches.length;
2635
+ return a * 1e4 + b * 100 + c;
2636
+ }
2637
+ function hashProperties(properties) {
2638
+ const sorted = Object.entries(properties).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`).join(";");
2639
+ return crypto4.createHash("md5").update(sorted).digest("hex").slice(0, 8);
2640
+ }
2641
+ function kebab2(prop) {
2642
+ return prop.replace(/([A-Z])/g, "-$1").toLowerCase();
2643
+ }
2644
+ function eliminateDeadStyles(graph, knownSelectors) {
2645
+ if (knownSelectors.length === 0) {
2646
+ return { eliminated: 0, graph };
2647
+ }
2648
+ const reachable = /* @__PURE__ */ new Set();
2649
+ const queue = [];
2650
+ for (const [id, node] of graph.nodes) {
2651
+ if (knownSelectors.some((ks) => node.selector.includes(ks) || ks.includes(node.selector))) {
2652
+ reachable.add(id);
2653
+ queue.push(id);
2654
+ }
2655
+ }
2656
+ while (queue.length > 0) {
2657
+ const current = queue.shift();
2658
+ const node = graph.nodes.get(current);
2659
+ if (!node) continue;
2660
+ for (const depId of node.dependents) {
2661
+ if (!reachable.has(depId)) {
2662
+ reachable.add(depId);
2663
+ queue.push(depId);
2664
+ }
2665
+ }
2666
+ }
2667
+ let eliminated = 0;
2668
+ for (const [id, node] of graph.nodes) {
2669
+ if (!reachable.has(id)) {
2670
+ node.isDead = true;
2671
+ eliminated++;
2672
+ }
2673
+ }
2674
+ return { eliminated, graph };
2675
+ }
2676
+ function mergeIdenticalRules(graph, threshold) {
2677
+ const hashGroups = /* @__PURE__ */ new Map();
2678
+ for (const [, node] of graph.nodes) {
2679
+ if (node.isDead) continue;
2680
+ if (Object.keys(node.properties).length < threshold) continue;
2681
+ const existing = hashGroups.get(node.hash) || [];
2682
+ existing.push(node);
2683
+ hashGroups.set(node.hash, existing);
2684
+ }
2685
+ let merged = 0;
2686
+ for (const [, group] of hashGroups) {
2687
+ if (group.length < 2) continue;
2688
+ const mergedSelector = group.map((n) => n.selector).join(", ");
2689
+ const primary = group[0];
2690
+ primary.selector = mergedSelector;
2691
+ for (let i = 1; i < group.length; i++) {
2692
+ group[i].isDead = true;
2693
+ merged++;
2694
+ }
2695
+ }
2696
+ return { merged, graph };
2697
+ }
2698
+ function topologicalSort(graph) {
2699
+ const visited = /* @__PURE__ */ new Set();
2700
+ const sorted = [];
2701
+ const visiting = /* @__PURE__ */ new Set();
2702
+ function visit(id) {
2703
+ if (visited.has(id)) return true;
2704
+ if (visiting.has(id)) return false;
2705
+ visiting.add(id);
2706
+ const node = graph.nodes.get(id);
2707
+ if (node) {
2708
+ for (const depId of node.dependencies) {
2709
+ if (!visit(depId)) return false;
2710
+ }
2711
+ }
2712
+ visiting.delete(id);
2713
+ visited.add(id);
2714
+ if (node && !node.isDead) {
2715
+ sorted.push(node);
2716
+ }
2717
+ return true;
2718
+ }
2719
+ for (const id of graph.rootNodes) {
2720
+ if (!visit(id)) {
2721
+ return Array.from(graph.nodes.values()).filter((n) => !n.isDead).sort((a, b) => a.sourceComponent?.localeCompare(b.sourceComponent || "") || 0);
2722
+ }
2723
+ }
2724
+ for (const [id] of graph.nodes) {
2725
+ if (!visited.has(id)) {
2726
+ visit(id);
2727
+ }
2728
+ }
2729
+ return sorted;
2730
+ }
2731
+ function generateCSSFromGraph(graph, sortOutput = "specificity") {
2732
+ let nodes;
2733
+ switch (sortOutput) {
2734
+ case "specificity":
2735
+ nodes = Array.from(graph.nodes.values()).filter((n) => !n.isDead).sort((a, b) => a.specificity - b.specificity);
2736
+ break;
2737
+ case "topological":
2738
+ nodes = topologicalSort(graph);
2739
+ break;
2740
+ case "source-order":
2741
+ default:
2742
+ nodes = Array.from(graph.nodes.values()).filter((n) => !n.isDead);
2743
+ break;
2744
+ }
2745
+ let css = "";
2746
+ let currentMediaQuery;
2747
+ for (const node of nodes) {
2748
+ if (node.isDead) continue;
2749
+ if (node.mediaQuery !== currentMediaQuery) {
2750
+ if (currentMediaQuery) {
2751
+ css += "}\n\n";
2752
+ }
2753
+ if (node.mediaQuery) {
2754
+ css += `@media ${node.mediaQuery} {
2755
+ `;
2756
+ }
2757
+ currentMediaQuery = node.mediaQuery;
2758
+ }
2759
+ const rules = Object.entries(node.properties).map(([prop, value]) => ` ${kebab2(prop)}: ${value};`).join("\n");
2760
+ if (rules) {
2761
+ css += `${node.selector} {
2762
+ ${rules}
2763
+ }
2764
+ `;
2765
+ }
2766
+ }
2767
+ if (currentMediaQuery) {
2768
+ css += "}\n";
2769
+ }
2770
+ return css;
2771
+ }
2772
+ var StyleGraphBuilder, StyleGraphCompiler;
2773
+ var init_style_graph = __esm({
2774
+ "src/compiler/style-graph.ts"() {
2775
+ "use strict";
2776
+ StyleGraphBuilder = class {
2777
+ entries = [];
2778
+ nodes = /* @__PURE__ */ new Map();
2779
+ edges = [];
2780
+ orderCounter = 0;
2781
+ addEntry(entry) {
2782
+ entry.sourceOrder = this.orderCounter++;
2783
+ this.entries.push(entry);
2784
+ }
2785
+ build() {
2786
+ this.nodes.clear();
2787
+ this.edges = [];
2788
+ for (const entry of this.entries) {
2789
+ const id = `node-${this.nodes.size}`;
2790
+ const node = {
2791
+ id,
2792
+ selector: entry.selector,
2793
+ properties: entry.properties,
2794
+ specificity: calculateSpecificity(entry.selector),
2795
+ dependencies: [],
2796
+ dependents: [],
2797
+ mediaQuery: entry.mediaQuery,
2798
+ isDead: false,
2799
+ hash: hashProperties(entry.properties),
2800
+ sourceComponent: entry.sourceComponent
2801
+ };
2802
+ this.nodes.set(id, node);
2803
+ }
2804
+ const nodeArray = Array.from(this.nodes.values());
2805
+ for (let i = 0; i < nodeArray.length; i++) {
2806
+ for (let j = i + 1; j < nodeArray.length; j++) {
2807
+ const a = nodeArray[i];
2808
+ const b = nodeArray[j];
2809
+ if (this.selectorsOverlap(a.selector, b.selector)) {
2810
+ if (a.specificity <= b.specificity) {
2811
+ this.edges.push({ from: a.id, to: b.id, type: "overrides" });
2812
+ a.dependents.push(b.id);
2813
+ b.dependencies.push(a.id);
2814
+ }
2815
+ if (b.specificity <= a.specificity) {
2816
+ this.edges.push({ from: b.id, to: a.id, type: "overrides" });
2817
+ b.dependents.push(a.id);
2818
+ a.dependencies.push(b.id);
2819
+ }
2820
+ }
2821
+ }
2822
+ }
2823
+ const rootNodes = nodeArray.filter((n) => n.dependencies.length === 0).map((n) => n.id);
2824
+ const leafNodes = nodeArray.filter((n) => n.dependents.length === 0).map((n) => n.id);
2825
+ return {
2826
+ nodes: this.nodes,
2827
+ edges: this.edges,
2828
+ rootNodes,
2829
+ leafNodes
2830
+ };
2831
+ }
2832
+ selectorsOverlap(a, b) {
2833
+ const partsA = a.split(/[\s>+~]+/).filter(Boolean);
2834
+ const partsB = b.split(/[\s>+~]+/).filter(Boolean);
2835
+ for (const pa of partsA) {
2836
+ for (const pb of partsB) {
2837
+ if (pa === pb) return true;
2838
+ if (pa.startsWith(".") && pb.startsWith(".") && pa === pb) return true;
2839
+ }
2840
+ }
2841
+ return false;
2842
+ }
2843
+ };
2844
+ StyleGraphCompiler = class {
2845
+ options;
2846
+ constructor(options = {}) {
2847
+ this.options = {
2848
+ eliminateDead: options.eliminateDead ?? false,
2849
+ knownSelectors: options.knownSelectors ?? [],
2850
+ mergeIdentical: options.mergeIdentical ?? false,
2851
+ mergeThreshold: options.mergeThreshold ?? 3,
2852
+ sortOutput: options.sortOutput ?? "specificity",
2853
+ verbose: options.verbose ?? false
2854
+ };
2855
+ }
2856
+ /**
2857
+ * Compile a set of style definitions through the graph compiler.
2858
+ */
2859
+ compile(styles) {
2860
+ const startTime = Date.now();
2861
+ const builder = new StyleGraphBuilder();
2862
+ let preOptimizationSize = 0;
2863
+ for (const [componentName, styleDef] of Object.entries(styles)) {
2864
+ if (!styleDef || !styleDef.selectors) continue;
2865
+ for (const selector of styleDef.selectors) {
2866
+ const properties = {};
2867
+ for (const [prop, value] of Object.entries(styleDef)) {
2868
+ if (prop === "selectors" || prop === "atRules" || prop === "nestedRules" || prop === "hover" || prop === "themes" || prop.startsWith("_")) {
2869
+ continue;
2870
+ }
2871
+ if (typeof value === "string" || typeof value === "number") {
2872
+ properties[prop] = String(value);
2873
+ preOptimizationSize += String(value).length + prop.length;
2874
+ }
2875
+ }
2876
+ if (Object.keys(properties).length > 0) {
2877
+ builder.addEntry({
2878
+ selector,
2879
+ properties,
2880
+ sourceComponent: componentName,
2881
+ sourceOrder: 0
2882
+ });
2883
+ }
2884
+ if (styleDef.hover && typeof styleDef.hover === "object") {
2885
+ const hoverProperties = {};
2886
+ for (const [prop, value] of Object.entries(styleDef.hover)) {
2887
+ if (typeof value === "string" || typeof value === "number") {
2888
+ hoverProperties[prop] = String(value);
2889
+ }
2890
+ }
2891
+ if (Object.keys(hoverProperties).length > 0) {
2892
+ builder.addEntry({
2893
+ selector: `${selector}:hover`,
2894
+ properties: hoverProperties,
2895
+ sourceComponent: componentName,
2896
+ sourceOrder: 0
2897
+ });
2898
+ }
2899
+ }
2900
+ if (styleDef.atRules) {
2901
+ for (const rule of styleDef.atRules) {
2902
+ if (rule.type === "media" && rule.styles && rule.query) {
2903
+ const mediaProperties = {};
2904
+ for (const [prop, value] of Object.entries(rule.styles)) {
2905
+ if (typeof value === "string" || typeof value === "number") {
2906
+ mediaProperties[prop] = String(value);
2907
+ }
2908
+ }
2909
+ if (Object.keys(mediaProperties).length > 0) {
2910
+ builder.addEntry({
2911
+ selector,
2912
+ properties: mediaProperties,
2913
+ sourceComponent: componentName,
2914
+ sourceOrder: 0,
2915
+ mediaQuery: rule.query
2916
+ });
2917
+ }
2918
+ }
2919
+ }
2920
+ }
2921
+ }
2922
+ }
2923
+ let graph = builder.build();
2924
+ let eliminatedDead = 0;
2925
+ if (this.options.eliminateDead && this.options.knownSelectors.length > 0) {
2926
+ const result = eliminateDeadStyles(graph, this.options.knownSelectors);
2927
+ eliminatedDead = result.eliminated;
2928
+ graph = result.graph;
2929
+ }
2930
+ let mergedRules = 0;
2931
+ if (this.options.mergeIdentical) {
2932
+ const result = mergeIdenticalRules(graph, this.options.mergeThreshold);
2933
+ mergedRules = result.merged;
2934
+ graph = result.graph;
2935
+ }
2936
+ const css = generateCSSFromGraph(graph, this.options.sortOutput);
2937
+ let postOptimizationSize = css.length;
2938
+ if (postOptimizationSize === 0) {
2939
+ postOptimizationSize = preOptimizationSize;
2940
+ }
2941
+ const classMap = {};
2942
+ for (const [, node] of graph.nodes) {
2943
+ if (!node.isDead && node.sourceComponent) {
2944
+ if (classMap[node.sourceComponent]) {
2945
+ classMap[node.sourceComponent] += ` ${node.selector.replace(/^\./, "")}`;
2946
+ } else {
2947
+ classMap[node.sourceComponent] = node.selector.replace(/^\./, "");
2948
+ }
2949
+ }
2950
+ }
2951
+ const totalNodes = graph.nodes.size;
2952
+ const aliveNodes = totalNodes - eliminatedDead;
2953
+ const savingsPercent = preOptimizationSize > 0 ? `${((preOptimizationSize - postOptimizationSize) / preOptimizationSize * 100).toFixed(1)}%` : "0%";
2954
+ const stats = {
2955
+ totalStyles: totalNodes,
2956
+ atomicStyles: 0,
2957
+ uniqueProperties: new Set(
2958
+ Array.from(graph.nodes.values()).filter((n) => !n.isDead).flatMap((n) => Object.keys(n.properties))
2959
+ ).size,
2960
+ savings: savingsPercent,
2961
+ compileTime: Date.now() - startTime
2962
+ };
2963
+ return {
2964
+ css,
2965
+ classMap,
2966
+ atomicClasses: [],
2967
+ stats,
2968
+ graph,
2969
+ eliminatedDead,
2970
+ mergedRules,
2971
+ optimizationTime: Date.now() - startTime,
2972
+ preOptimizationSize,
2973
+ postOptimizationSize
2974
+ };
2975
+ }
2976
+ /**
2977
+ * Analyze a style graph without generating CSS.
2978
+ */
2979
+ analyze(styles) {
2980
+ const builder = new StyleGraphBuilder();
2981
+ for (const [componentName, styleDef] of Object.entries(styles)) {
2982
+ if (!styleDef || !styleDef.selectors) continue;
2983
+ for (const selector of styleDef.selectors) {
2984
+ const properties = {};
2985
+ for (const [prop, value] of Object.entries(styleDef)) {
2986
+ if (prop === "selectors" || prop.startsWith("_")) continue;
2987
+ if (typeof value === "string" || typeof value === "number") {
2988
+ properties[prop] = String(value);
2989
+ }
2990
+ }
2991
+ if (Object.keys(properties).length > 0) {
2992
+ builder.addEntry({ selector, properties, sourceComponent: componentName, sourceOrder: 0 });
2993
+ }
2994
+ }
2995
+ }
2996
+ return builder.build();
2997
+ }
2998
+ /**
2999
+ * Get optimization statistics for a graph.
3000
+ */
3001
+ getStats(graph) {
3002
+ const nodes = Array.from(graph.nodes.values());
3003
+ const deadNodes = nodes.filter((n) => n.isDead).length;
3004
+ const averageSpecificity = nodes.length > 0 ? nodes.reduce((sum, n) => sum + n.specificity, 0) / nodes.length : 0;
3005
+ let maxDepth = 0;
3006
+ const depths = /* @__PURE__ */ new Map();
3007
+ function getDepth(id) {
3008
+ if (depths.has(id)) return depths.get(id);
3009
+ const node = graph.nodes.get(id);
3010
+ if (!node || node.dependencies.length === 0) {
3011
+ depths.set(id, 0);
3012
+ return 0;
3013
+ }
3014
+ const max = Math.max(...node.dependencies.map((d) => getDepth(d)));
3015
+ const depth = max + 1;
3016
+ depths.set(id, depth);
3017
+ return depth;
3018
+ }
3019
+ for (const [id] of graph.nodes) {
3020
+ maxDepth = Math.max(maxDepth, getDepth(id));
3021
+ }
3022
+ return {
3023
+ totalNodes: nodes.length,
3024
+ deadNodes,
3025
+ mergedGroups: 0,
3026
+ averageSpecificity: Math.round(averageSpecificity * 100) / 100,
3027
+ deepestDependencyChain: maxDepth
3028
+ };
3029
+ }
3030
+ /**
3031
+ * Update options.
3032
+ */
3033
+ configure(options) {
3034
+ this.options = { ...this.options, ...options };
3035
+ }
3036
+ };
3037
+ }
3038
+ });
3039
+
2615
3040
  // src/core/compiler.ts
2616
3041
  var compiler_exports = {};
2617
3042
  __export(compiler_exports, {
@@ -2620,7 +3045,7 @@ __export(compiler_exports, {
2620
3045
  });
2621
3046
  import fs7 from "fs";
2622
3047
  import path6 from "path";
2623
- import crypto4 from "crypto";
3048
+ import crypto5 from "crypto";
2624
3049
  import chalk2 from "chalk";
2625
3050
  import { fileURLToPath, pathToFileURL } from "url";
2626
3051
  async function compileChainCSS(inputFile, outputDir, config) {
@@ -2639,6 +3064,7 @@ var init_compiler = __esm({
2639
3064
  init_cache_manager();
2640
3065
  init_content_addressable_cache();
2641
3066
  init_shorthands();
3067
+ init_style_graph();
2642
3068
  __filename = typeof import.meta !== "undefined" ? (() => {
2643
3069
  try {
2644
3070
  return fileURLToPath(import.meta.url);
@@ -2689,6 +3115,35 @@ var init_compiler = __esm({
2689
3115
  this.initOptimizer();
2690
3116
  this.initPrefixer();
2691
3117
  }
3118
+ /**
3119
+ * Compile using the style graph compiler for advanced optimizations.
3120
+ *
3121
+ * @example
3122
+ * const result = compiler.compileWithGraph(styles, {
3123
+ * eliminateDead: true,
3124
+ * knownSelectors: ['.header', '.footer'],
3125
+ * mergeIdentical: true
3126
+ * });
3127
+ */
3128
+ compileWithGraph(styles, options) {
3129
+ const graphCompiler = new StyleGraphCompiler({
3130
+ ...options,
3131
+ verbose: this.config.verbose
3132
+ });
3133
+ const result = graphCompiler.compile(styles);
3134
+ if (this.config.verbose) {
3135
+ if (result.eliminatedDead > 0) {
3136
+ console.log(` \u{1F9F9} Eliminated ${result.eliminatedDead} dead styles`);
3137
+ }
3138
+ if (result.mergedRules > 0) {
3139
+ console.log(` \u{1F517} Merged ${result.mergedRules} identical rules`);
3140
+ }
3141
+ if (result.optimizationTime > 0) {
3142
+ console.log(` \u26A1 Graph compilation: ${result.optimizationTime}ms`);
3143
+ }
3144
+ }
3145
+ return result;
3146
+ }
2692
3147
  hasStyles() {
2693
3148
  const combined = this.getCombinedCSS();
2694
3149
  return !!(combined && combined.trim().length > 0);
@@ -2726,7 +3181,7 @@ var init_compiler = __esm({
2726
3181
  if (result.css && result.css.trim()) {
2727
3182
  this.accumulatedCSS += result.css + "\n";
2728
3183
  }
2729
- const cacheKey = crypto4.createHash("sha256").update(`${componentName}-${JSON.stringify(styleObj)}`).digest("hex").slice(0, 16);
3184
+ const cacheKey = crypto5.createHash("sha256").update(`${componentName}-${JSON.stringify(styleObj)}`).digest("hex").slice(0, 16);
2730
3185
  this.addToCache(cacheKey, {
2731
3186
  result: {
2732
3187
  css: result.css || "",
@@ -2854,7 +3309,7 @@ var init_compiler = __esm({
2854
3309
  // ============================================================================
2855
3310
  hashStyleDef(styleDef) {
2856
3311
  const { _componentName, _generateComponent, _framework, _propsDefinition, ...relevant } = styleDef;
2857
- return crypto4.createHash("sha256").update(JSON.stringify(relevant)).digest("hex").slice(0, 16);
3312
+ return crypto5.createHash("sha256").update(JSON.stringify(relevant)).digest("hex").slice(0, 16);
2858
3313
  }
2859
3314
  async importModule(filePath) {
2860
3315
  const absolutePath = path6.resolve(filePath);
@@ -0,0 +1,12 @@
1
+ import type { StyleDefinition, StyleDiagnostic, StyleAnalysis, BreakpointInference, DiagnosticSeverity } from '../core/types.js';
2
+ export type { StyleDiagnostic, StyleAnalysis, BreakpointInference, DiagnosticSeverity };
3
+ export declare class StyleAnalyzer {
4
+ private _diagnostics;
5
+ analyzeStyle(selector: string, styles: Record<string, any>, _opts?: any): StyleDiagnostic[];
6
+ analyze(sd: StyleDefinition): StyleAnalysis;
7
+ reset(): void;
8
+ getDiagnostics(): StyleDiagnostic[];
9
+ }
10
+ export declare function analyze(sd: StyleDefinition): StyleAnalysis;
11
+ export declare function analyzeStyle(sd: StyleDefinition): StyleAnalysis;
12
+ export default StyleAnalyzer;
@@ -0,0 +1,31 @@
1
+ import type { CorrectionResult, HealMode, HealResult, IntentContext } from '../core/types.js';
2
+ export type { CorrectionResult, HealMode, HealResult, IntentContext };
3
+ interface ValueCorrection {
4
+ wrong: string;
5
+ correct: string;
6
+ confidence: number;
7
+ }
8
+ export declare const intent: {
9
+ correct(property: string, value: string, context?: IntentContext): CorrectionResult | null;
10
+ heal(styles: Record<string, any>, mode?: HealMode, context?: IntentContext): HealResult;
11
+ getIntent(value: string, ctx?: IntentContext): string | null;
12
+ validate(property: string, value: string): {
13
+ valid: boolean;
14
+ suggestion?: string;
15
+ };
16
+ getCorrections(property: string): ValueCorrection[];
17
+ explain(correction: CorrectionResult): string;
18
+ getKnownProperties(): string[];
19
+ getIntents(): {
20
+ pattern: string;
21
+ description: string;
22
+ }[];
23
+ };
24
+ export declare const correct: (property: string, value: string, context?: IntentContext) => CorrectionResult | null;
25
+ export declare const heal: (styles: Record<string, any>, mode?: HealMode, context?: IntentContext) => HealResult;
26
+ export declare const validate: (property: string, value: string) => {
27
+ valid: boolean;
28
+ suggestion?: string;
29
+ };
30
+ export declare const getIntent: (value: string, ctx?: IntentContext) => string | null;
31
+ export default intent;
@@ -0,0 +1,89 @@
1
+ import type { CSSUnit, CSSMathValue, MathContext, MathResult, FluidTypeConfig } from '../core/types.js';
2
+ export type { CSSUnit, CSSMathValue, MathContext, MathResult, FluidTypeConfig };
3
+ export type MathOp = 'add' | 'subtract' | 'multiply' | 'divide';
4
+ export declare const math: {
5
+ /**
6
+ * Add two CSS values with unit resolution.
7
+ *
8
+ * @example
9
+ * math.add('10px', '2rem') // → '42px' (with default context)
10
+ * math.add('10px', '2rem', { rootFontSize: 16 }) // → '42px'
11
+ * math.add('10px', '2vw') // → 'calc(10px + 2vw)'
12
+ */
13
+ add(a: string | number, b: string | number, context?: MathContext): MathResult;
14
+ /**
15
+ * Subtract two CSS values with unit resolution.
16
+ */
17
+ subtract(a: string | number, b: string | number, context?: MathContext): MathResult;
18
+ /**
19
+ * Multiply two CSS values with unit resolution.
20
+ */
21
+ multiply(a: string | number, b: string | number, context?: MathContext): MathResult;
22
+ /**
23
+ * Divide two CSS values with unit resolution.
24
+ */
25
+ divide(a: string | number, b: string | number, context?: MathContext): MathResult;
26
+ /**
27
+ * Sum multiple CSS values.
28
+ */
29
+ sum(...values: (string | number)[]): MathResult;
30
+ /**
31
+ * Resolve a CSS value to pixels.
32
+ */
33
+ toPx(value: string | number, context?: MathContext): number;
34
+ /**
35
+ * Convert between CSS units.
36
+ */
37
+ convert(value: string | number, toUnit: CSSUnit, context?: MathContext): MathResult;
38
+ /**
39
+ * Create a fluid typography clamp() expression.
40
+ *
41
+ * @example
42
+ * math.fluidType({ minSize: 14, maxSize: 20 })
43
+ * // → 'clamp(14px, 0.625vw + 12px, 20px)'
44
+ * math.fluidType({ minSize: 14, maxSize: 20, unit: 'rem', rootFontSize: 16 })
45
+ * // → 'clamp(0.875rem, 0.625vw + 0.75rem, 1.25rem)'
46
+ */
47
+ fluidType(config: FluidTypeConfig): MathResult;
48
+ /**
49
+ * Scale a value by a factor with unit preservation.
50
+ */
51
+ scale(value: string | number, factor: number): MathResult;
52
+ /**
53
+ * Clamp a CSS value between min and max.
54
+ */
55
+ clampValue(value: string | number, min: string | number, max: string | number, context?: MathContext): MathResult;
56
+ /**
57
+ * Parse a CSS value into its numeric and unit parts.
58
+ */
59
+ parse(value: string | number): CSSMathValue;
60
+ /**
61
+ * Check if two values have compatible units for direct operations.
62
+ */
63
+ compatible(a: string | number, b: string | number): boolean;
64
+ /**
65
+ * Get the category of a CSS unit.
66
+ */
67
+ unitCategory(unit: CSSUnit): string;
68
+ /**
69
+ * Create a CSS min() expression.
70
+ */
71
+ cssMin(...values: (string | number)[]): string;
72
+ /**
73
+ * Create a CSS max() expression.
74
+ */
75
+ cssMax(...values: (string | number)[]): string;
76
+ /**
77
+ * Format a number with specified precision.
78
+ */
79
+ precision(value: number, decimals?: number): string;
80
+ };
81
+ export declare const add: (a: string | number, b: string | number, context?: MathContext) => MathResult;
82
+ export declare const subtract: (a: string | number, b: string | number, context?: MathContext) => MathResult;
83
+ export declare const multiply: (a: string | number, b: string | number, context?: MathContext) => MathResult;
84
+ export declare const divide: (a: string | number, b: string | number, context?: MathContext) => MathResult;
85
+ export declare const fluidType: (config: FluidTypeConfig) => MathResult;
86
+ export declare const convert: (value: string | number, toUnit: CSSUnit, context?: MathContext) => MathResult;
87
+ export declare const toPx: (value: string | number, context?: MathContext) => number;
88
+ export declare const scale: (value: string | number, factor: number) => MathResult;
89
+ export default math;
@@ -0,0 +1,30 @@
1
+ import type { StyleDefinition, StyleGraph, StyleGraphNode, StyleGraphEdge, GraphCompileOptions, GraphCompileResult } from '../core/types.js';
2
+ export type { StyleGraph, StyleGraphNode, StyleGraphEdge, GraphCompileOptions, GraphCompileResult };
3
+ export declare class StyleGraphCompiler {
4
+ private options;
5
+ constructor(options?: GraphCompileOptions);
6
+ /**
7
+ * Compile a set of style definitions through the graph compiler.
8
+ */
9
+ compile(styles: Record<string, StyleDefinition>): GraphCompileResult;
10
+ /**
11
+ * Analyze a style graph without generating CSS.
12
+ */
13
+ analyze(styles: Record<string, StyleDefinition>): StyleGraph;
14
+ /**
15
+ * Get optimization statistics for a graph.
16
+ */
17
+ getStats(graph: StyleGraph): {
18
+ totalNodes: number;
19
+ deadNodes: number;
20
+ mergedGroups: number;
21
+ averageSpecificity: number;
22
+ deepestDependencyChain: number;
23
+ };
24
+ /**
25
+ * Update options.
26
+ */
27
+ configure(options: Partial<GraphCompileOptions>): void;
28
+ }
29
+ export declare function compileGraph(styles: Record<string, StyleDefinition>, options?: GraphCompileOptions): GraphCompileResult;
30
+ export default StyleGraphCompiler;