synthesisui 0.16.87 → 0.16.88
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/doctor/css-modules.js +5 -0
- package/dist/doctor/transcribe.js +127 -1
- package/dist/skill-import.js +4 -0
- package/package.json +1 -1
|
@@ -527,6 +527,11 @@ function tokenRefFor(name) {
|
|
|
527
527
|
return `{spacing.${bare.slice(8)}}`;
|
|
528
528
|
if (bare.startsWith("shadow-"))
|
|
529
529
|
return `{shadow.${bare.slice(7)}}`;
|
|
530
|
+
if (bare.startsWith("background-image-gradient-")) {
|
|
531
|
+
return `{gradients.${bare.slice("background-image-gradient-".length)}}`;
|
|
532
|
+
}
|
|
533
|
+
if (bare.startsWith("gradient-"))
|
|
534
|
+
return `{gradients.${bare.slice(9)}}`;
|
|
530
535
|
if (bare.startsWith("text-"))
|
|
531
536
|
return `{typography.scale.${bare.slice(5)}.fontSize}`;
|
|
532
537
|
if (bare.startsWith("font-"))
|
|
@@ -271,8 +271,22 @@ export function readUtility(utility, declared) {
|
|
|
271
271
|
const bracket = core.indexOf("-[");
|
|
272
272
|
if (bracket !== -1 && core.endsWith("]")) {
|
|
273
273
|
const head = core.slice(0, bracket);
|
|
274
|
-
|
|
274
|
+
let inner = core.slice(bracket + 2, -1);
|
|
275
|
+
/**
|
|
276
|
+
* `bg-[image:var(--gradient-ui)]` - the datatype hint says which property, in
|
|
277
|
+
* Tailwind's own syntax. Two real usages of the signature gradient wear exactly
|
|
278
|
+
* this spelling (dono, 01/08).
|
|
279
|
+
*/
|
|
280
|
+
let hinted = null;
|
|
281
|
+
const hint = /^(image|color|length|size|position|url):/.exec(inner);
|
|
282
|
+
if (hint) {
|
|
283
|
+
hinted = hint[1] === "image" ? "backgroundImage" : null;
|
|
284
|
+
inner = inner.slice(hint[0].length);
|
|
285
|
+
}
|
|
275
286
|
const value = resolveArbitrary(inner, declared);
|
|
287
|
+
if (hinted && value) {
|
|
288
|
+
return { property: hinted, value: value.value, token: value.token };
|
|
289
|
+
}
|
|
276
290
|
/**
|
|
277
291
|
* `text-[…]` IS AMBIGUOUS AND THE VALUE DECIDES.
|
|
278
292
|
*
|
|
@@ -299,6 +313,24 @@ export function readUtility(utility, declared) {
|
|
|
299
313
|
const rest = core.slice(dash + 1);
|
|
300
314
|
const colorProp = COLOR_PROPERTY[prefix];
|
|
301
315
|
if (colorProp) {
|
|
316
|
+
/**
|
|
317
|
+
* `bg-gradient-ui` is the utility Tailwind v4 mints from their
|
|
318
|
+
* `--background-image-gradient-ui`, and the colour path read `gradient-ui` as a
|
|
319
|
+
* colour name and found nothing. The token they declared is the answer - and
|
|
320
|
+
* `bg-gradient-to-r` must NOT land here, because nobody declares `--gradient-to-r`;
|
|
321
|
+
* it falls through to the stop composer below.
|
|
322
|
+
*/
|
|
323
|
+
if (prefix === "bg" && rest.startsWith("gradient-")) {
|
|
324
|
+
const name = rest.slice(9);
|
|
325
|
+
if (declared.has(`--background-image-gradient-${name}`) ||
|
|
326
|
+
declared.has(`--gradient-${name}`)) {
|
|
327
|
+
return {
|
|
328
|
+
property: "backgroundImage",
|
|
329
|
+
value: `{gradients.${name}}`,
|
|
330
|
+
token: `--gradient-${name}`,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
302
334
|
// Their own token first: `--color-ocean-500` for `bg-ocean-500`, which is
|
|
303
335
|
// exactly how Tailwind v4's `@theme` publishes it.
|
|
304
336
|
const own = `--color-${rest}`;
|
|
@@ -488,6 +520,14 @@ function tokenRefFor(name) {
|
|
|
488
520
|
return `{spacing.${bare.slice(8)}}`;
|
|
489
521
|
if (bare.startsWith("shadow-"))
|
|
490
522
|
return `{shadow.${bare.slice(7)}}`;
|
|
523
|
+
// `--gradient-ui` and `--background-image-gradient-ui` are one token in two
|
|
524
|
+
// spellings - Tailwind v4's utility namespace wraps the first. Both reach
|
|
525
|
+
// `{gradients.ui}`, which is where the census files them.
|
|
526
|
+
if (bare.startsWith("background-image-gradient-")) {
|
|
527
|
+
return `{gradients.${bare.slice("background-image-gradient-".length)}}`;
|
|
528
|
+
}
|
|
529
|
+
if (bare.startsWith("gradient-"))
|
|
530
|
+
return `{gradients.${bare.slice(9)}}`;
|
|
491
531
|
if (bare.startsWith("text-")) {
|
|
492
532
|
return `{typography.scale.${bare.slice(5)}.fontSize}`;
|
|
493
533
|
}
|
|
@@ -561,6 +601,76 @@ const UNITLESS = /^(opacity|zIndex|flex|flexGrow|flexShrink|order|lineHeight|fon
|
|
|
561
601
|
* still reads as nothing is a failed DESIGN read, not layout plumbing.
|
|
562
602
|
*/
|
|
563
603
|
const DESIGN_PREFIX = /^(?:p|px|py|pt|pr|pb|pl|m|mx|my|gap|rounded|text|font|bg|border|shadow|w|h|size|min-w|min-h|max-w|max-h|leading|tracking|opacity|fill|stroke)-\S/;
|
|
604
|
+
/** `to-r` → `to right`: Tailwind's eight directions, spelled as CSS reads them. */
|
|
605
|
+
const GRADIENT_DIRECTION = {
|
|
606
|
+
"to-t": "to top",
|
|
607
|
+
"to-tr": "to top right",
|
|
608
|
+
"to-r": "to right",
|
|
609
|
+
"to-br": "to bottom right",
|
|
610
|
+
"to-b": "to bottom",
|
|
611
|
+
"to-bl": "to bottom left",
|
|
612
|
+
"to-l": "to left",
|
|
613
|
+
"to-tl": "to top left",
|
|
614
|
+
};
|
|
615
|
+
/** A colour stop's value: their token first, Tailwind's table second, a literal last. */
|
|
616
|
+
function stopValue(raw, declared) {
|
|
617
|
+
if (declared.has(`--color-${raw}`))
|
|
618
|
+
return refFor(raw);
|
|
619
|
+
if (TAILWIND_COLOR[raw])
|
|
620
|
+
return TAILWIND_COLOR[raw];
|
|
621
|
+
if (/^#[0-9a-fA-F]{3,8}$/.test(raw) ||
|
|
622
|
+
raw === "transparent" ||
|
|
623
|
+
raw === "white" ||
|
|
624
|
+
raw === "black") {
|
|
625
|
+
return raw;
|
|
626
|
+
}
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* A COMPOSED GRADIENT is one decision spread across four classes.
|
|
631
|
+
*
|
|
632
|
+
* `bg-gradient-to-r from-ocean-500 via-vivid-pink-500 to-purple-400` is nine real
|
|
633
|
+
* elements in one repo, and every piece read as nothing - `from-` is not a property
|
|
634
|
+
* table's prefix. Composed here because only the whole class list can see all the
|
|
635
|
+
* pieces at once; the stops resolve to their own tokens, so the gradient re-themes.
|
|
636
|
+
*
|
|
637
|
+
* `from-bottom-2` taught the guard: `slide-in-from-bottom-2` fragments wear the same
|
|
638
|
+
* prefix, so stops only count when a `bg-gradient-to-*` sits in the SAME class list -
|
|
639
|
+
* and a direction whose stops do not resolve is reported, never half-built.
|
|
640
|
+
*/
|
|
641
|
+
function composeGradient(utilities, declared) {
|
|
642
|
+
const dir = utilities.find((u) => GRADIENT_DIRECTION[u.replace(/^bg-gradient-/, "")] &&
|
|
643
|
+
u.startsWith("bg-gradient-"));
|
|
644
|
+
if (!dir)
|
|
645
|
+
return { value: null, consumed: new Set(), broken: [] };
|
|
646
|
+
const direction = GRADIENT_DIRECTION[dir.replace(/^bg-gradient-/, "")];
|
|
647
|
+
const consumed = new Set([dir]);
|
|
648
|
+
const broken = [];
|
|
649
|
+
const stops = [];
|
|
650
|
+
for (const kind of ["from", "via", "to"]) {
|
|
651
|
+
const cls = utilities.find((u) => u.startsWith(`${kind}-`));
|
|
652
|
+
if (!cls)
|
|
653
|
+
continue;
|
|
654
|
+
consumed.add(cls);
|
|
655
|
+
const value = stopValue(cls.slice(kind.length + 1), declared);
|
|
656
|
+
if (value)
|
|
657
|
+
stops.push(value);
|
|
658
|
+
else
|
|
659
|
+
broken.push(cls);
|
|
660
|
+
}
|
|
661
|
+
if (stops.length < 2 || broken.length > 0) {
|
|
662
|
+
return {
|
|
663
|
+
value: null,
|
|
664
|
+
consumed,
|
|
665
|
+
broken: broken.length > 0 ? broken : [dir],
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
return {
|
|
669
|
+
value: `linear-gradient(${direction}, ${stops.join(", ")})`,
|
|
670
|
+
consumed,
|
|
671
|
+
broken,
|
|
672
|
+
};
|
|
673
|
+
}
|
|
564
674
|
export function transcribe(classes, declared) {
|
|
565
675
|
const out = {
|
|
566
676
|
base: {},
|
|
@@ -572,8 +682,24 @@ export function transcribe(classes, declared) {
|
|
|
572
682
|
fromToken: 0,
|
|
573
683
|
fromLiteral: 0,
|
|
574
684
|
};
|
|
685
|
+
/**
|
|
686
|
+
* The composed gradient first: it is one decision spread across four classes, and
|
|
687
|
+
* only the whole list sees all the pieces. Base-level only - a per-scheme stop
|
|
688
|
+
* (`dark:from-x`) is a condition this pass does not attempt, and it lands in
|
|
689
|
+
* `unreadable` below rather than half-composing.
|
|
690
|
+
*/
|
|
691
|
+
const bareUtilities = classes
|
|
692
|
+
.filter((cls) => parseClass(cls).modifiers.length === 0)
|
|
693
|
+
.map((cls) => parseClass(cls).utility);
|
|
694
|
+
const gradient = composeGradient(bareUtilities, declared);
|
|
695
|
+
if (gradient.value)
|
|
696
|
+
out.base.backgroundImage = gradient.value;
|
|
697
|
+
for (const broke of gradient.broken)
|
|
698
|
+
out.unreadable.push(broke);
|
|
575
699
|
for (const cls of classes) {
|
|
576
700
|
const { modifiers, utility } = parseClass(cls);
|
|
701
|
+
if (gradient.consumed.has(utility) && modifiers.length === 0)
|
|
702
|
+
continue;
|
|
577
703
|
const isDark = modifiers.includes("dark");
|
|
578
704
|
const rest = modifiers.filter((m) => m !== "dark");
|
|
579
705
|
// THE SLOT IS DECIDED BEFORE THE VALUE IS READ. Resolving first meant a
|
package/dist/skill-import.js
CHANGED
|
@@ -672,6 +672,10 @@ found them wastes a turn and risks contradicting the measurement:
|
|
|
672
672
|
- **whether a component forwards the rest of its props**, and which it names
|
|
673
673
|
- **which components appear inside which** at their call sites, as pairs
|
|
674
674
|
- **the folder architecture**, and it will ask you which one has priority
|
|
675
|
+
- **their gradients**, as tokens: \`--gradient-ui\` and its Tailwind-namespace twin land on
|
|
676
|
+
\`{gradients.ui}\`, composed \`bg-gradient-to-r from-x to-y\` stops become one gradient in
|
|
677
|
+
their own colour tokens, and a signature gradient is no longer a string trapped in class
|
|
678
|
+
names
|
|
675
679
|
- **the theme**: how many dark utilities, in how many files, which library switches it, which
|
|
676
680
|
attribute it is bound to, what \`<html>\` carries, and how many \`prefers-color-scheme\` rules
|
|
677
681
|
- **the libraries and their versions** - motion, icons, primitives, charts, editors - with the
|
package/package.json
CHANGED