chaincss 2.1.39 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compiler/css-if-transpiler.d.ts +33 -0
- package/dist/compiler/design-orchestrator.d.ts +119 -0
- package/dist/compiler/intent-engine.d.ts +19 -1
- package/dist/compiler/scroll-timeline.d.ts +91 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +651 -2
- package/package.json +1 -1
- package/src/compiler/css-if-transpiler.ts +117 -0
- package/src/compiler/design-orchestrator.ts +322 -0
- package/src/compiler/intent-engine.ts +291 -1
- package/src/compiler/scroll-timeline.ts +284 -0
- package/src/index.ts +34 -0
package/dist/index.js
CHANGED
|
@@ -7330,6 +7330,317 @@ init_shorthands();
|
|
|
7330
7330
|
init_helpers();
|
|
7331
7331
|
init_animations();
|
|
7332
7332
|
init_suggestions();
|
|
7333
|
+
|
|
7334
|
+
// src/compiler/design-orchestrator.ts
|
|
7335
|
+
function parseColor(color) {
|
|
7336
|
+
const trimmed = color.trim().toLowerCase();
|
|
7337
|
+
const hexMatch = trimmed.match(/^#([a-f0-9]{3}|[a-f0-9]{6}|[a-f0-9]{8})$/);
|
|
7338
|
+
if (hexMatch) {
|
|
7339
|
+
let hex = hexMatch[1];
|
|
7340
|
+
if (hex.length === 3) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
7341
|
+
if (hex.length === 8) {
|
|
7342
|
+
return {
|
|
7343
|
+
r: parseInt(hex.slice(0, 2), 16),
|
|
7344
|
+
g: parseInt(hex.slice(2, 4), 16),
|
|
7345
|
+
b: parseInt(hex.slice(4, 6), 16),
|
|
7346
|
+
a: parseInt(hex.slice(6, 8), 16) / 255
|
|
7347
|
+
};
|
|
7348
|
+
}
|
|
7349
|
+
return {
|
|
7350
|
+
r: parseInt(hex.slice(0, 2), 16),
|
|
7351
|
+
g: parseInt(hex.slice(2, 4), 16),
|
|
7352
|
+
b: parseInt(hex.slice(4, 6), 16),
|
|
7353
|
+
a: 1
|
|
7354
|
+
};
|
|
7355
|
+
}
|
|
7356
|
+
const rgbMatch = trimmed.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)$/);
|
|
7357
|
+
if (rgbMatch) {
|
|
7358
|
+
return {
|
|
7359
|
+
r: parseInt(rgbMatch[1]),
|
|
7360
|
+
g: parseInt(rgbMatch[2]),
|
|
7361
|
+
b: parseInt(rgbMatch[3]),
|
|
7362
|
+
a: rgbMatch[4] ? parseFloat(rgbMatch[4]) : 1
|
|
7363
|
+
};
|
|
7364
|
+
}
|
|
7365
|
+
const named = {
|
|
7366
|
+
white: [255, 255, 255],
|
|
7367
|
+
black: [0, 0, 0],
|
|
7368
|
+
red: [255, 0, 0],
|
|
7369
|
+
green: [0, 128, 0],
|
|
7370
|
+
blue: [0, 0, 255],
|
|
7371
|
+
gray: [128, 128, 128],
|
|
7372
|
+
grey: [128, 128, 128],
|
|
7373
|
+
transparent: [0, 0, 0]
|
|
7374
|
+
};
|
|
7375
|
+
if (named[trimmed]) {
|
|
7376
|
+
const [r, g, b] = named[trimmed];
|
|
7377
|
+
return { r, g, b, a: trimmed === "transparent" ? 0 : 1 };
|
|
7378
|
+
}
|
|
7379
|
+
return null;
|
|
7380
|
+
}
|
|
7381
|
+
function relativeLuminance(r, g, b) {
|
|
7382
|
+
const rsrgb = r / 255;
|
|
7383
|
+
const gsrgb = g / 255;
|
|
7384
|
+
const bsrgb = b / 255;
|
|
7385
|
+
const rLin = rsrgb <= 0.04045 ? rsrgb / 12.92 : Math.pow((rsrgb + 0.055) / 1.055, 2.4);
|
|
7386
|
+
const gLin = gsrgb <= 0.04045 ? gsrgb / 12.92 : Math.pow((gsrgb + 0.055) / 1.055, 2.4);
|
|
7387
|
+
const bLin = bsrgb <= 0.04045 ? bsrgb / 12.92 : Math.pow((bsrgb + 0.055) / 1.055, 2.4);
|
|
7388
|
+
return 0.2126 * rLin + 0.7152 * gLin + 0.0722 * bLin;
|
|
7389
|
+
}
|
|
7390
|
+
function contrastRatio(foreground, background) {
|
|
7391
|
+
const fg = parseColor(foreground);
|
|
7392
|
+
const bg = parseColor(background);
|
|
7393
|
+
if (!fg || !bg) return -1;
|
|
7394
|
+
const lumFg = relativeLuminance(fg.r, fg.g, fg.b) + 0.05;
|
|
7395
|
+
const lumBg = relativeLuminance(bg.r, bg.g, bg.b) + 0.05;
|
|
7396
|
+
const lighter = Math.max(lumFg, lumBg);
|
|
7397
|
+
const darker = Math.min(lumFg, lumBg);
|
|
7398
|
+
return lighter / darker;
|
|
7399
|
+
}
|
|
7400
|
+
function checkContrast(foreground, background) {
|
|
7401
|
+
const ratio = contrastRatio(foreground, background);
|
|
7402
|
+
return {
|
|
7403
|
+
foreground,
|
|
7404
|
+
background,
|
|
7405
|
+
ratio: Math.round(ratio * 100) / 100,
|
|
7406
|
+
passes: {
|
|
7407
|
+
AA: ratio >= 4.5,
|
|
7408
|
+
AALarge: ratio >= 3,
|
|
7409
|
+
AAA: ratio >= 7,
|
|
7410
|
+
AAALarge: ratio >= 4.5
|
|
7411
|
+
},
|
|
7412
|
+
suggestion: ratio < 4.5 ? `Contrast ratio ${Math.round(ratio * 100) / 100} fails AA. Need ${Math.round((4.5 - ratio) * 100) / 100} more. Consider darkening/lightening.` : void 0
|
|
7413
|
+
};
|
|
7414
|
+
}
|
|
7415
|
+
function auditContrast(styles) {
|
|
7416
|
+
const checks = [];
|
|
7417
|
+
for (const style of styles) {
|
|
7418
|
+
if (style.color && style.backgroundColor) {
|
|
7419
|
+
checks.push(checkContrast(style.color, style.backgroundColor));
|
|
7420
|
+
}
|
|
7421
|
+
}
|
|
7422
|
+
const failures = checks.filter((c) => !c.passes.AA);
|
|
7423
|
+
const warnings = checks.filter((c) => c.passes.AA && !c.passes.AAA);
|
|
7424
|
+
return {
|
|
7425
|
+
checks,
|
|
7426
|
+
failures,
|
|
7427
|
+
warnings,
|
|
7428
|
+
passCount: checks.length - failures.length,
|
|
7429
|
+
failCount: failures.length,
|
|
7430
|
+
summary: failures.length === 0 ? "All " + checks.length + " contrast checks pass AA." : failures.length + " of " + checks.length + " contrast checks FAIL AA."
|
|
7431
|
+
};
|
|
7432
|
+
}
|
|
7433
|
+
function createContextualToken(defaultValue, contexts = {}) {
|
|
7434
|
+
const name = "ctx-" + Math.random().toString(36).slice(2, 8);
|
|
7435
|
+
return { name, default: defaultValue, contexts };
|
|
7436
|
+
}
|
|
7437
|
+
function resolveContextual(token, selectorPath) {
|
|
7438
|
+
let bestMatch = token.default;
|
|
7439
|
+
let bestLength = 0;
|
|
7440
|
+
for (const [context, value] of Object.entries(token.contexts)) {
|
|
7441
|
+
if (selectorPath.includes(context) && context.length > bestLength) {
|
|
7442
|
+
bestMatch = value;
|
|
7443
|
+
bestLength = context.length;
|
|
7444
|
+
}
|
|
7445
|
+
}
|
|
7446
|
+
return bestMatch;
|
|
7447
|
+
}
|
|
7448
|
+
function generateContextualCSS(propertyName, token, baseSelector) {
|
|
7449
|
+
let css = "";
|
|
7450
|
+
css += baseSelector + " { " + propertyName + ": " + token.default + "; }\n";
|
|
7451
|
+
for (const [context, value] of Object.entries(token.contexts)) {
|
|
7452
|
+
css += context + " " + baseSelector + " { " + propertyName + ": " + value + "; }\n";
|
|
7453
|
+
}
|
|
7454
|
+
return css;
|
|
7455
|
+
}
|
|
7456
|
+
function validateTokenRelationships(tokens3, pairs) {
|
|
7457
|
+
const styles = [];
|
|
7458
|
+
for (const pair of pairs) {
|
|
7459
|
+
const fg = resolveTokenPath2(tokens3, pair.foreground);
|
|
7460
|
+
const bg = resolveTokenPath2(tokens3, pair.background);
|
|
7461
|
+
if (fg && bg) {
|
|
7462
|
+
styles.push({ selector: pair.label, color: fg, backgroundColor: bg });
|
|
7463
|
+
}
|
|
7464
|
+
}
|
|
7465
|
+
return auditContrast(styles);
|
|
7466
|
+
}
|
|
7467
|
+
function resolveTokenPath2(tokens3, path6) {
|
|
7468
|
+
const parts = path6.split(".");
|
|
7469
|
+
let current = tokens3;
|
|
7470
|
+
for (const part of parts) {
|
|
7471
|
+
if (current === void 0 || current === null) return null;
|
|
7472
|
+
current = current[part];
|
|
7473
|
+
}
|
|
7474
|
+
return typeof current === "string" ? current : null;
|
|
7475
|
+
}
|
|
7476
|
+
var orchestrator = {
|
|
7477
|
+
contrastRatio,
|
|
7478
|
+
checkContrast,
|
|
7479
|
+
auditContrast,
|
|
7480
|
+
createContextualToken,
|
|
7481
|
+
resolveContextual,
|
|
7482
|
+
generateContextualCSS,
|
|
7483
|
+
validateTokenRelationships,
|
|
7484
|
+
parseColor
|
|
7485
|
+
};
|
|
7486
|
+
|
|
7487
|
+
// src/compiler/scroll-timeline.ts
|
|
7488
|
+
var SCROLL_PRESETS = {
|
|
7489
|
+
fadeIn: {
|
|
7490
|
+
selector: "",
|
|
7491
|
+
timeline: { name: "fade-in", source: "view", range: "entry" },
|
|
7492
|
+
keyframes: [
|
|
7493
|
+
{ offset: "0%", properties: { opacity: "0", transform: "translateY(20px)" } },
|
|
7494
|
+
{ offset: "100%", properties: { opacity: "1", transform: "translateY(0)" } }
|
|
7495
|
+
]
|
|
7496
|
+
},
|
|
7497
|
+
fadeOut: {
|
|
7498
|
+
selector: "",
|
|
7499
|
+
timeline: { name: "fade-out", source: "view", range: "exit" },
|
|
7500
|
+
keyframes: [
|
|
7501
|
+
{ offset: "0%", properties: { opacity: "1" } },
|
|
7502
|
+
{ offset: "100%", properties: { opacity: "0" } }
|
|
7503
|
+
]
|
|
7504
|
+
},
|
|
7505
|
+
scaleIn: {
|
|
7506
|
+
selector: "",
|
|
7507
|
+
timeline: { name: "scale-in", source: "view", range: "entry" },
|
|
7508
|
+
keyframes: [
|
|
7509
|
+
{ offset: "0%", properties: { opacity: "0", transform: "scale(0.8)" } },
|
|
7510
|
+
{ offset: "100%", properties: { opacity: "1", transform: "scale(1)" } }
|
|
7511
|
+
]
|
|
7512
|
+
},
|
|
7513
|
+
slideLeft: {
|
|
7514
|
+
selector: "",
|
|
7515
|
+
timeline: { name: "slide-left", source: "view", range: "entry" },
|
|
7516
|
+
keyframes: [
|
|
7517
|
+
{ offset: "0%", properties: { opacity: "0", transform: "translateX(-40px)" } },
|
|
7518
|
+
{ offset: "100%", properties: { opacity: "1", transform: "translateX(0)" } }
|
|
7519
|
+
]
|
|
7520
|
+
},
|
|
7521
|
+
slideRight: {
|
|
7522
|
+
selector: "",
|
|
7523
|
+
timeline: { name: "slide-right", source: "view", range: "entry" },
|
|
7524
|
+
keyframes: [
|
|
7525
|
+
{ offset: "0%", properties: { opacity: "0", transform: "translateX(40px)" } },
|
|
7526
|
+
{ offset: "100%", properties: { opacity: "1", transform: "translateX(0)" } }
|
|
7527
|
+
]
|
|
7528
|
+
},
|
|
7529
|
+
parallax: {
|
|
7530
|
+
selector: "",
|
|
7531
|
+
timeline: { name: "parallax", source: "scroll", scroller: "root" },
|
|
7532
|
+
keyframes: [
|
|
7533
|
+
{ offset: "0%", properties: { transform: "translateY(0)" } },
|
|
7534
|
+
{ offset: "100%", properties: { transform: "translateY(-20%)" } }
|
|
7535
|
+
]
|
|
7536
|
+
},
|
|
7537
|
+
stickyReveal: {
|
|
7538
|
+
selector: "",
|
|
7539
|
+
timeline: { name: "sticky-reveal", source: "view", range: "contain" },
|
|
7540
|
+
keyframes: [
|
|
7541
|
+
{ offset: "0%", properties: { opacity: "0", clipPath: "inset(0 0 100% 0)" } },
|
|
7542
|
+
{ offset: "50%", properties: { opacity: "1", clipPath: "inset(0 0 0% 0)" } },
|
|
7543
|
+
{ offset: "100%", properties: { opacity: "1", clipPath: "inset(0 0 0% 0)" } }
|
|
7544
|
+
]
|
|
7545
|
+
}
|
|
7546
|
+
};
|
|
7547
|
+
var animCounter = 0;
|
|
7548
|
+
function generateName(prefix) {
|
|
7549
|
+
return prefix + "-" + (animCounter++).toString(36);
|
|
7550
|
+
}
|
|
7551
|
+
function compileScrollAnimation(animation) {
|
|
7552
|
+
const animName = animation.timeline.name || generateName("scroll-anim");
|
|
7553
|
+
const timelineName = "--" + animName + "-tl";
|
|
7554
|
+
let css = "";
|
|
7555
|
+
css += "/* Scroll Timeline: " + animName + " */\n";
|
|
7556
|
+
if (animation.timeline.source === "view") {
|
|
7557
|
+
const range = animation.timeline.range || "entry";
|
|
7558
|
+
css += animation.selector + " {\n";
|
|
7559
|
+
css += " view-timeline-name: " + timelineName + ";\n";
|
|
7560
|
+
css += " view-timeline-axis: " + (animation.timeline.axis || "block") + ";\n";
|
|
7561
|
+
if (animation.timeline.inset) {
|
|
7562
|
+
const inset = typeof animation.timeline.inset === "string" ? animation.timeline.inset : animation.timeline.inset.start + " " + animation.timeline.inset.end;
|
|
7563
|
+
css += " view-timeline-inset: " + inset + ";\n";
|
|
7564
|
+
}
|
|
7565
|
+
css += "}\n\n";
|
|
7566
|
+
} else {
|
|
7567
|
+
const scroller = animation.timeline.scroller === "root" ? "root" : animation.timeline.scroller === "self" ? "self" : animation.timeline.scroller || "nearest";
|
|
7568
|
+
css += animation.selector + " {\n";
|
|
7569
|
+
if (scroller === "root" || scroller === "self" || scroller === "nearest") {
|
|
7570
|
+
css += " scroll-timeline-name: " + timelineName + ";\n";
|
|
7571
|
+
css += " scroll-timeline-axis: " + (animation.timeline.axis || "block") + ";\n";
|
|
7572
|
+
}
|
|
7573
|
+
css += "}\n\n";
|
|
7574
|
+
}
|
|
7575
|
+
css += "@keyframes " + animName + " {\n";
|
|
7576
|
+
for (const step of animation.keyframes) {
|
|
7577
|
+
css += " " + step.offset + " {\n";
|
|
7578
|
+
for (const [prop, value] of Object.entries(step.properties)) {
|
|
7579
|
+
const kebabProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
7580
|
+
css += " " + kebabProp + ": " + value + ";\n";
|
|
7581
|
+
}
|
|
7582
|
+
css += " }\n";
|
|
7583
|
+
}
|
|
7584
|
+
css += "}\n\n";
|
|
7585
|
+
const targetSelector = animation.selector + " > *" || animation.selector;
|
|
7586
|
+
css += "/* Apply animation to children */\n";
|
|
7587
|
+
css += targetSelector + " {\n";
|
|
7588
|
+
css += " animation: " + animName + " linear both;\n";
|
|
7589
|
+
css += " animation-timeline: " + timelineName + ";\n";
|
|
7590
|
+
if (animation.timeline.source === "view") {
|
|
7591
|
+
const range = animation.timeline.range || "entry";
|
|
7592
|
+
css += " animation-range: " + range + ";\n";
|
|
7593
|
+
}
|
|
7594
|
+
if (animation.delay) css += " animation-delay: " + animation.delay + ";\n";
|
|
7595
|
+
css += "}\n\n";
|
|
7596
|
+
css += "/* Fallback for browsers without scroll-timeline */\n";
|
|
7597
|
+
css += "@supports not (animation-timeline: scroll()) {\n";
|
|
7598
|
+
css += " " + targetSelector + " {\n";
|
|
7599
|
+
css += " /* Use JS polyfill: https://github.com/flackr/scroll-timeline */\n";
|
|
7600
|
+
css += " animation: " + animName + " 1s ease both;\n";
|
|
7601
|
+
css += " }\n";
|
|
7602
|
+
css += "}\n";
|
|
7603
|
+
return {
|
|
7604
|
+
css,
|
|
7605
|
+
animationName: animName,
|
|
7606
|
+
timelineName,
|
|
7607
|
+
fallback: ""
|
|
7608
|
+
};
|
|
7609
|
+
}
|
|
7610
|
+
function compileScrollAnimations(animations) {
|
|
7611
|
+
let css = "/* ============================================================\n";
|
|
7612
|
+
css += " ChainCSS Scroll-Driven Animations\n";
|
|
7613
|
+
css += " Generated: " + (/* @__PURE__ */ new Date()).toISOString() + "\n";
|
|
7614
|
+
css += " ============================================================ */\n\n";
|
|
7615
|
+
for (const animation of animations) {
|
|
7616
|
+
const result = compileScrollAnimation(animation);
|
|
7617
|
+
css += result.css;
|
|
7618
|
+
}
|
|
7619
|
+
return css;
|
|
7620
|
+
}
|
|
7621
|
+
function createScrollAnimation(preset, selector, overrides) {
|
|
7622
|
+
const base = SCROLL_PRESETS[preset];
|
|
7623
|
+
if (!base) throw new Error("Unknown scroll preset: " + preset);
|
|
7624
|
+
return {
|
|
7625
|
+
...base,
|
|
7626
|
+
selector,
|
|
7627
|
+
timeline: { ...base.timeline, ...overrides?.timeline },
|
|
7628
|
+
keyframes: overrides?.keyframes || base.keyframes,
|
|
7629
|
+
...overrides
|
|
7630
|
+
};
|
|
7631
|
+
}
|
|
7632
|
+
function getScrollPresets() {
|
|
7633
|
+
return Object.keys(SCROLL_PRESETS);
|
|
7634
|
+
}
|
|
7635
|
+
var scrollTimeline = {
|
|
7636
|
+
compile: compileScrollAnimation,
|
|
7637
|
+
compileAll: compileScrollAnimations,
|
|
7638
|
+
create: createScrollAnimation,
|
|
7639
|
+
presets: SCROLL_PRESETS,
|
|
7640
|
+
getPresets: getScrollPresets
|
|
7641
|
+
};
|
|
7642
|
+
|
|
7643
|
+
// src/index.ts
|
|
7333
7644
|
init_Chain();
|
|
7334
7645
|
|
|
7335
7646
|
// src/compiler/math-engine.ts
|
|
@@ -7765,6 +8076,76 @@ var convert = math.convert.bind(math);
|
|
|
7765
8076
|
var toPx = math.toPx.bind(math);
|
|
7766
8077
|
var scale = math.scale.bind(math);
|
|
7767
8078
|
|
|
8079
|
+
// src/compiler/css-if-transpiler.ts
|
|
8080
|
+
function detectIfPatterns(styles) {
|
|
8081
|
+
const conditions = [];
|
|
8082
|
+
if (!styles._conditions) return conditions;
|
|
8083
|
+
const condEntries = Object.entries(styles._conditions || {});
|
|
8084
|
+
for (const [variable, branches] of condEntries) {
|
|
8085
|
+
const branch = branches;
|
|
8086
|
+
const trueStyles = branch.true || {};
|
|
8087
|
+
const falseStyles = branch.false || {};
|
|
8088
|
+
const allProps = /* @__PURE__ */ new Set([...Object.keys(trueStyles), ...Object.keys(falseStyles)]);
|
|
8089
|
+
for (const prop of allProps) {
|
|
8090
|
+
if (prop.startsWith("_") || prop === "selectors") continue;
|
|
8091
|
+
const trueVal = trueStyles[prop];
|
|
8092
|
+
const falseVal = falseStyles[prop];
|
|
8093
|
+
if (trueVal !== void 0 && falseVal !== void 0 && trueVal !== falseVal) {
|
|
8094
|
+
conditions.push({
|
|
8095
|
+
property: prop,
|
|
8096
|
+
variable: variable.startsWith("--") ? variable : "--" + variable,
|
|
8097
|
+
conditions: { true: trueVal },
|
|
8098
|
+
defaultValue: falseVal
|
|
8099
|
+
});
|
|
8100
|
+
}
|
|
8101
|
+
}
|
|
8102
|
+
}
|
|
8103
|
+
return conditions;
|
|
8104
|
+
}
|
|
8105
|
+
function emitCSSIf(selector, detectedConditions, baseProperties = {}) {
|
|
8106
|
+
if (detectedConditions.length === 0) return "";
|
|
8107
|
+
let css = "";
|
|
8108
|
+
css += "/* Native CSS if() \u2014 Chrome 137+ */\n";
|
|
8109
|
+
css += selector + " {\n";
|
|
8110
|
+
for (const [prop, value] of Object.entries(baseProperties)) {
|
|
8111
|
+
css += " " + prop + ": " + value + ";\n";
|
|
8112
|
+
}
|
|
8113
|
+
for (const cond of detectedConditions) {
|
|
8114
|
+
const entries = Object.entries(cond.conditions);
|
|
8115
|
+
if (entries.length === 1) {
|
|
8116
|
+
const [condition, val] = entries[0];
|
|
8117
|
+
css += " " + cond.property + ": if(style(" + cond.variable + ": " + condition + "): " + val + " else " + cond.defaultValue + ");\n";
|
|
8118
|
+
} else {
|
|
8119
|
+
let chain3 = "";
|
|
8120
|
+
for (let i = 0; i < entries.length; i++) {
|
|
8121
|
+
const [condition, val] = entries[i];
|
|
8122
|
+
chain3 += i === 0 ? "if(style(" + cond.variable + ": " + condition + "): " + val : " else if(style(" + cond.variable + ": " + condition + "): " + val;
|
|
8123
|
+
}
|
|
8124
|
+
chain3 += " else " + cond.defaultValue + ")".repeat(entries.length);
|
|
8125
|
+
css += " " + cond.property + ": " + chain3 + ";\n";
|
|
8126
|
+
}
|
|
8127
|
+
}
|
|
8128
|
+
css += "}\n\n";
|
|
8129
|
+
css += "/* Fallback for browsers without CSS if() */\n";
|
|
8130
|
+
css += "@supports not (property: if()) {\n";
|
|
8131
|
+
css += " " + selector + " {\n";
|
|
8132
|
+
for (const [prop, value] of Object.entries(baseProperties)) {
|
|
8133
|
+
css += " " + prop + ": " + value + ";\n";
|
|
8134
|
+
}
|
|
8135
|
+
for (const cond of detectedConditions) {
|
|
8136
|
+
css += " " + cond.property + ": " + cond.defaultValue + ";\n";
|
|
8137
|
+
}
|
|
8138
|
+
css += " }\n";
|
|
8139
|
+
for (const cond of detectedConditions) {
|
|
8140
|
+
for (const [condition, val] of Object.entries(cond.conditions)) {
|
|
8141
|
+
const modClass = selector + "--" + cond.variable.replace("--", "") + "-" + condition;
|
|
8142
|
+
css += " " + modClass + " { " + cond.property + ": " + val + "; }\n";
|
|
8143
|
+
}
|
|
8144
|
+
}
|
|
8145
|
+
css += "}\n";
|
|
8146
|
+
return css;
|
|
8147
|
+
}
|
|
8148
|
+
|
|
7768
8149
|
// src/compiler/intent-engine.ts
|
|
7769
8150
|
var SEMANTIC_INTENTS = [
|
|
7770
8151
|
{ 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" },
|
|
@@ -7774,6 +8155,222 @@ var SEMANTIC_INTENTS = [
|
|
|
7774
8155
|
{ 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
8156
|
{ 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
8157
|
];
|
|
8158
|
+
var LAYOUT_MACROS = {
|
|
8159
|
+
stickyHeader: {
|
|
8160
|
+
name: "stickyHeader",
|
|
8161
|
+
description: "Sticky header with scroll shadow and entrance animation",
|
|
8162
|
+
properties: {
|
|
8163
|
+
position: "sticky",
|
|
8164
|
+
top: "0",
|
|
8165
|
+
zIndex: "50",
|
|
8166
|
+
backgroundColor: "var(--header-bg, white)",
|
|
8167
|
+
backdropFilter: "blur(8px)",
|
|
8168
|
+
borderBottom: "1px solid transparent"
|
|
8169
|
+
},
|
|
8170
|
+
defaults: {
|
|
8171
|
+
"--header-bg": "white",
|
|
8172
|
+
"--header-shadow": "0 4px 12px rgba(0,0,0,0.1)"
|
|
8173
|
+
},
|
|
8174
|
+
mediaQueries: {
|
|
8175
|
+
"(max-width: 768px)": {
|
|
8176
|
+
padding: "12px 16px"
|
|
8177
|
+
},
|
|
8178
|
+
"(min-width: 769px)": {
|
|
8179
|
+
padding: "16px 32px"
|
|
8180
|
+
}
|
|
8181
|
+
}
|
|
8182
|
+
},
|
|
8183
|
+
card: {
|
|
8184
|
+
name: "card",
|
|
8185
|
+
description: "Standard card container with hover lift effect",
|
|
8186
|
+
properties: {
|
|
8187
|
+
display: "flex",
|
|
8188
|
+
flexDirection: "column",
|
|
8189
|
+
borderRadius: "12px",
|
|
8190
|
+
backgroundColor: "var(--card-bg, white)",
|
|
8191
|
+
boxShadow: "0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08)",
|
|
8192
|
+
transition: "box-shadow 0.2s ease, transform 0.2s ease",
|
|
8193
|
+
overflow: "hidden"
|
|
8194
|
+
},
|
|
8195
|
+
defaults: {
|
|
8196
|
+
"--card-bg": "white",
|
|
8197
|
+
"--card-hover-shadow": "0 10px 30px rgba(0,0,0,0.15)"
|
|
8198
|
+
},
|
|
8199
|
+
mediaQueries: {
|
|
8200
|
+
"(hover: hover)": {
|
|
8201
|
+
"&:hover": {
|
|
8202
|
+
boxShadow: "var(--card-hover-shadow)",
|
|
8203
|
+
transform: "translateY(-2px)"
|
|
8204
|
+
}
|
|
8205
|
+
}
|
|
8206
|
+
}
|
|
8207
|
+
},
|
|
8208
|
+
hero: {
|
|
8209
|
+
name: "hero",
|
|
8210
|
+
description: "Full-width hero section with centered content",
|
|
8211
|
+
properties: {
|
|
8212
|
+
display: "flex",
|
|
8213
|
+
flexDirection: "column",
|
|
8214
|
+
justifyContent: "center",
|
|
8215
|
+
alignItems: "center",
|
|
8216
|
+
width: "100%",
|
|
8217
|
+
minHeight: "60vh",
|
|
8218
|
+
padding: "48px 24px",
|
|
8219
|
+
textAlign: "center"
|
|
8220
|
+
},
|
|
8221
|
+
defaults: {},
|
|
8222
|
+
mediaQueries: {
|
|
8223
|
+
"(max-width: 768px)": {
|
|
8224
|
+
minHeight: "40vh",
|
|
8225
|
+
padding: "32px 16px"
|
|
8226
|
+
}
|
|
8227
|
+
}
|
|
8228
|
+
},
|
|
8229
|
+
container: {
|
|
8230
|
+
name: "container",
|
|
8231
|
+
description: "Responsive centered container with max-width",
|
|
8232
|
+
properties: {
|
|
8233
|
+
width: "100%",
|
|
8234
|
+
maxWidth: "1200px",
|
|
8235
|
+
marginLeft: "auto",
|
|
8236
|
+
marginRight: "auto",
|
|
8237
|
+
paddingLeft: "16px",
|
|
8238
|
+
paddingRight: "16px"
|
|
8239
|
+
},
|
|
8240
|
+
defaults: {},
|
|
8241
|
+
mediaQueries: {
|
|
8242
|
+
"(min-width: 768px)": {
|
|
8243
|
+
paddingLeft: "24px",
|
|
8244
|
+
paddingRight: "24px"
|
|
8245
|
+
},
|
|
8246
|
+
"(min-width: 1024px)": {
|
|
8247
|
+
paddingLeft: "32px",
|
|
8248
|
+
paddingRight: "32px"
|
|
8249
|
+
}
|
|
8250
|
+
}
|
|
8251
|
+
},
|
|
8252
|
+
center: {
|
|
8253
|
+
name: "center",
|
|
8254
|
+
description: "Absolute centering using flexbox",
|
|
8255
|
+
properties: {
|
|
8256
|
+
display: "flex",
|
|
8257
|
+
justifyContent: "center",
|
|
8258
|
+
alignItems: "center"
|
|
8259
|
+
},
|
|
8260
|
+
defaults: {}
|
|
8261
|
+
},
|
|
8262
|
+
gridList: {
|
|
8263
|
+
name: "gridList",
|
|
8264
|
+
description: "Responsive grid list with auto-fit columns",
|
|
8265
|
+
properties: {
|
|
8266
|
+
display: "grid",
|
|
8267
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))",
|
|
8268
|
+
gap: "24px"
|
|
8269
|
+
},
|
|
8270
|
+
defaults: {},
|
|
8271
|
+
mediaQueries: {
|
|
8272
|
+
"(max-width: 640px)": {
|
|
8273
|
+
gridTemplateColumns: "1fr",
|
|
8274
|
+
gap: "16px"
|
|
8275
|
+
}
|
|
8276
|
+
}
|
|
8277
|
+
},
|
|
8278
|
+
sidebar: {
|
|
8279
|
+
name: "sidebar",
|
|
8280
|
+
description: "Two-column layout: sidebar + main content",
|
|
8281
|
+
properties: {
|
|
8282
|
+
display: "grid",
|
|
8283
|
+
gridTemplateColumns: "280px 1fr",
|
|
8284
|
+
gap: "32px",
|
|
8285
|
+
minHeight: "100vh"
|
|
8286
|
+
},
|
|
8287
|
+
defaults: {},
|
|
8288
|
+
mediaQueries: {
|
|
8289
|
+
"(max-width: 1024px)": {
|
|
8290
|
+
gridTemplateColumns: "1fr",
|
|
8291
|
+
gap: "24px"
|
|
8292
|
+
}
|
|
8293
|
+
}
|
|
8294
|
+
},
|
|
8295
|
+
pill: {
|
|
8296
|
+
name: "pill",
|
|
8297
|
+
description: "Pill-shaped element (fully rounded)",
|
|
8298
|
+
properties: {
|
|
8299
|
+
borderRadius: "9999px",
|
|
8300
|
+
padding: "8px 20px",
|
|
8301
|
+
display: "inline-flex",
|
|
8302
|
+
alignItems: "center",
|
|
8303
|
+
justifyContent: "center"
|
|
8304
|
+
},
|
|
8305
|
+
defaults: {}
|
|
8306
|
+
},
|
|
8307
|
+
glass: {
|
|
8308
|
+
name: "glass",
|
|
8309
|
+
description: "Frosted glass morphism effect",
|
|
8310
|
+
properties: {
|
|
8311
|
+
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
8312
|
+
backdropFilter: "blur(16px)",
|
|
8313
|
+
border: "1px solid rgba(255, 255, 255, 0.2)",
|
|
8314
|
+
borderRadius: "16px"
|
|
8315
|
+
},
|
|
8316
|
+
defaults: {}
|
|
8317
|
+
},
|
|
8318
|
+
truncate: {
|
|
8319
|
+
name: "truncate",
|
|
8320
|
+
description: "Single-line text truncation with ellipsis",
|
|
8321
|
+
properties: {
|
|
8322
|
+
overflow: "hidden",
|
|
8323
|
+
textOverflow: "ellipsis",
|
|
8324
|
+
whiteSpace: "nowrap"
|
|
8325
|
+
},
|
|
8326
|
+
defaults: {}
|
|
8327
|
+
},
|
|
8328
|
+
srOnly: {
|
|
8329
|
+
name: "srOnly",
|
|
8330
|
+
description: "Screen-reader only (visually hidden but accessible)",
|
|
8331
|
+
properties: {
|
|
8332
|
+
position: "absolute",
|
|
8333
|
+
width: "1px",
|
|
8334
|
+
height: "1px",
|
|
8335
|
+
padding: "0",
|
|
8336
|
+
margin: "-1px",
|
|
8337
|
+
overflow: "hidden",
|
|
8338
|
+
clip: "rect(0, 0, 0, 0)",
|
|
8339
|
+
whiteSpace: "nowrap",
|
|
8340
|
+
borderWidth: "0"
|
|
8341
|
+
},
|
|
8342
|
+
defaults: {}
|
|
8343
|
+
}
|
|
8344
|
+
};
|
|
8345
|
+
function resolveLayoutMacro(name) {
|
|
8346
|
+
return LAYOUT_MACROS[name] || null;
|
|
8347
|
+
}
|
|
8348
|
+
function expandLayoutMacro(name) {
|
|
8349
|
+
const macro2 = resolveLayoutMacro(name);
|
|
8350
|
+
if (!macro2) return null;
|
|
8351
|
+
const result = { ...macro2.properties };
|
|
8352
|
+
if (macro2.defaults) {
|
|
8353
|
+
Object.assign(result, macro2.defaults);
|
|
8354
|
+
}
|
|
8355
|
+
if (macro2.mediaQueries) {
|
|
8356
|
+
result.atRules = result.atRules || [];
|
|
8357
|
+
for (const [query, props] of Object.entries(macro2.mediaQueries)) {
|
|
8358
|
+
result.atRules.push({
|
|
8359
|
+
type: "media",
|
|
8360
|
+
query,
|
|
8361
|
+
styles: props
|
|
8362
|
+
});
|
|
8363
|
+
}
|
|
8364
|
+
}
|
|
8365
|
+
return result;
|
|
8366
|
+
}
|
|
8367
|
+
function getAvailableMacros() {
|
|
8368
|
+
return Object.keys(LAYOUT_MACROS);
|
|
8369
|
+
}
|
|
8370
|
+
function getMacroDescription(name) {
|
|
8371
|
+
const macro2 = resolveLayoutMacro(name);
|
|
8372
|
+
return macro2?.description || null;
|
|
8373
|
+
}
|
|
7777
8374
|
var VALUE_CORRECTIONS = {
|
|
7778
8375
|
"display": [{ wrong: "flexbox", correct: "flex", confidence: 0.95 }, { wrong: "inline-flexbox", correct: "inline-flex", confidence: 0.95 }],
|
|
7779
8376
|
"position": [{ wrong: "abs", correct: "absolute", confidence: 0.9 }, { wrong: "rel", correct: "relative", confidence: 0.9 }],
|
|
@@ -7889,17 +8486,55 @@ var intent = {
|
|
|
7889
8486
|
explain(correction) {
|
|
7890
8487
|
return correction.explanation;
|
|
7891
8488
|
},
|
|
8489
|
+
cssIf: { detect: detectIfPatterns, emit: emitCSSIf },
|
|
8490
|
+
getIntents() {
|
|
8491
|
+
return SEMANTIC_INTENTS.map((r) => ({ pattern: r.pattern.toString(), description: r.description }));
|
|
8492
|
+
},
|
|
7892
8493
|
getKnownProperties() {
|
|
7893
8494
|
return [...KNOWN_PROPERTIES];
|
|
7894
8495
|
},
|
|
7895
|
-
|
|
7896
|
-
|
|
8496
|
+
// Layout Macros
|
|
8497
|
+
macro(name) {
|
|
8498
|
+
return expandLayoutMacro(name);
|
|
8499
|
+
},
|
|
8500
|
+
getMacros() {
|
|
8501
|
+
return getAvailableMacros();
|
|
8502
|
+
},
|
|
8503
|
+
getMacroDescription(name) {
|
|
8504
|
+
return getMacroDescription(name);
|
|
8505
|
+
},
|
|
8506
|
+
hasMacro(name) {
|
|
8507
|
+
return name in LAYOUT_MACROS;
|
|
8508
|
+
},
|
|
8509
|
+
/**
|
|
8510
|
+
* Apply a layout macro to an existing styles object.
|
|
8511
|
+
* Merges macro properties with user overrides.
|
|
8512
|
+
*/
|
|
8513
|
+
applyMacro(name, overrides) {
|
|
8514
|
+
const macro2 = expandLayoutMacro(name);
|
|
8515
|
+
if (!macro2) return null;
|
|
8516
|
+
if (!overrides) return macro2;
|
|
8517
|
+
const merged = { ...macro2 };
|
|
8518
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
8519
|
+
if (key === "atRules" && Array.isArray(value) && Array.isArray(merged.atRules)) {
|
|
8520
|
+
merged.atRules = [...merged.atRules, ...value];
|
|
8521
|
+
} else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
8522
|
+
merged[key] = { ...merged[key] || {}, ...value };
|
|
8523
|
+
} else {
|
|
8524
|
+
merged[key] = value;
|
|
8525
|
+
}
|
|
8526
|
+
}
|
|
8527
|
+
return merged;
|
|
7897
8528
|
}
|
|
7898
8529
|
};
|
|
7899
8530
|
var correct = intent.correct.bind(intent);
|
|
7900
8531
|
var heal = intent.heal.bind(intent);
|
|
7901
8532
|
var validate = intent.validate.bind(intent);
|
|
7902
8533
|
var getIntent = intent.getIntent.bind(intent);
|
|
8534
|
+
var macro = intent.macro.bind(intent);
|
|
8535
|
+
var applyMacro = intent.applyMacro.bind(intent);
|
|
8536
|
+
var getMacros = intent.getMacros.bind(intent);
|
|
8537
|
+
var hasMacro = intent.hasMacro.bind(intent);
|
|
7903
8538
|
|
|
7904
8539
|
// src/compiler/analyzer.ts
|
|
7905
8540
|
var CONFLICTS = [
|
|
@@ -7984,6 +8619,7 @@ export {
|
|
|
7984
8619
|
ChainCSSPrefixer,
|
|
7985
8620
|
DesignTokens,
|
|
7986
8621
|
PersistentCache,
|
|
8622
|
+
SCROLL_PRESETS,
|
|
7987
8623
|
StyleAnalyzer,
|
|
7988
8624
|
StyleGraphCompiler,
|
|
7989
8625
|
Theme,
|
|
@@ -7991,18 +8627,25 @@ export {
|
|
|
7991
8627
|
add,
|
|
7992
8628
|
analyze as analyzeStyle,
|
|
7993
8629
|
animationPresets,
|
|
8630
|
+
auditContrast,
|
|
7994
8631
|
autoDetector,
|
|
7995
8632
|
buildChain,
|
|
7996
8633
|
chain,
|
|
7997
8634
|
smartChain as chainV3,
|
|
8635
|
+
checkContrast,
|
|
7998
8636
|
clearTimeline,
|
|
7999
8637
|
compileChainCSS,
|
|
8000
8638
|
compileGraph,
|
|
8639
|
+
compileScrollAnimation,
|
|
8640
|
+
compileScrollAnimations,
|
|
8001
8641
|
configureAtomic,
|
|
8642
|
+
contrastRatio,
|
|
8002
8643
|
convert,
|
|
8003
8644
|
correct,
|
|
8004
8645
|
createAnimation,
|
|
8646
|
+
createContextualToken,
|
|
8005
8647
|
createTokens as createDesignTokens,
|
|
8648
|
+
createScrollAnimation,
|
|
8006
8649
|
createSmartComponent,
|
|
8007
8650
|
createTheme,
|
|
8008
8651
|
createThemeContract,
|
|
@@ -8014,11 +8657,13 @@ export {
|
|
|
8014
8657
|
expandShorthand,
|
|
8015
8658
|
exportTimeline,
|
|
8016
8659
|
fluidType,
|
|
8660
|
+
generateContextualCSS,
|
|
8017
8661
|
getAnimationPreset,
|
|
8018
8662
|
getAnimationPresetNames,
|
|
8019
8663
|
getAvailableShorthands,
|
|
8020
8664
|
getIntent,
|
|
8021
8665
|
getPropertySuggestion,
|
|
8666
|
+
getScrollPresets,
|
|
8022
8667
|
getShorthandSuggestion,
|
|
8023
8668
|
getStyleChanges,
|
|
8024
8669
|
getStyleDiff,
|
|
@@ -8035,9 +8680,12 @@ export {
|
|
|
8035
8680
|
macros,
|
|
8036
8681
|
math,
|
|
8037
8682
|
multiply,
|
|
8683
|
+
orchestrator,
|
|
8038
8684
|
recipe,
|
|
8685
|
+
resolveContextual,
|
|
8039
8686
|
runtimeChain,
|
|
8040
8687
|
scale,
|
|
8688
|
+
scrollTimeline,
|
|
8041
8689
|
setBreakpoints,
|
|
8042
8690
|
shorthandMap,
|
|
8043
8691
|
smartChain,
|
|
@@ -8046,6 +8694,7 @@ export {
|
|
|
8046
8694
|
tokens2 as tokens,
|
|
8047
8695
|
useSmartStyles,
|
|
8048
8696
|
validateTheme,
|
|
8697
|
+
validateTokenRelationships,
|
|
8049
8698
|
validate as validateValue,
|
|
8050
8699
|
withSmartStyles
|
|
8051
8700
|
};
|