synthesisui 0.16.457 → 0.16.458

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.
@@ -58,6 +58,14 @@ export function readVocabulary(themeCss) {
58
58
  fontWeights: weights,
59
59
  };
60
60
  }
61
+ /**
62
+ * The type scale every Tailwind v4 project has, whether the system declares it or not. Oscilla's
63
+ * theme.css declares only `--text-display`, so `cn("text-xs", "text-2xl")` kept both and the
64
+ * stylesheet order decided (refinement round 1, 27/09).
65
+ */
66
+ const TAILWIND_TEXT_SIZES = [
67
+ "xs", "sm", "base", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "6xl", "7xl", "8xl", "9xl",
68
+ ];
61
69
  const set = (names) => `new Set([${names.map((n) => JSON.stringify(n)).join(", ")}])`;
62
70
  /** The `cn.ts` a project gets, written against ITS system's vocabulary. */
63
71
  export function emitCn(slug, vocab) {
@@ -84,7 +92,7 @@ export function emitCn(slug, vocab) {
84
92
 
85
93
  /** This system's own namespaces, so \`text-*\` and \`font-*\` are never a guess. */
86
94
  const COLORS = ${set(vocab.colors)};
87
- const TEXT_SIZES = ${set(vocab.textSizes)};
95
+ const TEXT_SIZES = ${set([...new Set([...TAILWIND_TEXT_SIZES, ...vocab.textSizes])])};
88
96
  const FONT_FAMILIES = ${set(vocab.fontFamilies)};
89
97
  const FONT_WEIGHTS = ${set(vocab.fontWeights)};
90
98
 
@@ -97,8 +105,6 @@ const PREFIXES = [
97
105
  "rounded-tl", "rounded-tr", "rounded-br", "rounded-bl",
98
106
  "rounded-t", "rounded-r", "rounded-b", "rounded-l",
99
107
  "rounded",
100
- "border-t", "border-r", "border-b", "border-l", "border-x", "border-y",
101
- "border",
102
108
  "px", "py", "pt", "pr", "pb", "pl", "ps", "pe", "p",
103
109
  "mx", "my", "mt", "mr", "mb", "ml", "ms", "me", "m",
104
110
  "gap-x", "gap-y", "gap",
@@ -124,6 +130,36 @@ const DISPLAYS = new Set([
124
130
  const FLEX_DIRECTIONS = new Set(["row", "col", "row-reverse", "col-reverse"]);
125
131
  const FLEX_WRAPS = new Set(["wrap", "nowrap", "wrap-reverse"]);
126
132
 
133
+ /**
134
+ * \`border\` heads THREE properties: the width (\`border\`, \`border-2\`), the style
135
+ * (\`border-dashed\`) and the colour (\`border-surface\`). Read as one prefix,
136
+ * \`border border-surface\` kept only the colour and the line vanished - every
137
+ * card, input and badge in the project, in silence (refinement round 1, 27/09).
138
+ */
139
+ const BORDER_SIDES = new Set(["t", "r", "b", "l", "x", "y", "s", "e"]);
140
+ const BORDER_STYLES = new Set(["solid", "dashed", "dotted", "double", "hidden", "none"]);
141
+ const COLOR_KEYWORDS = new Set(["transparent", "current", "inherit", "black", "white"]);
142
+
143
+ function borderGroup(variants: string, rest: string, cls: string): string {
144
+ const first = rest.split("-")[0];
145
+ const side = BORDER_SIDES.has(first) ? \`-\${first}\` : "";
146
+ const tail = side ? rest.slice(first.length + 1) : rest;
147
+ const isWidth =
148
+ tail === "" ||
149
+ [...tail].every((ch) => ch >= "0" && ch <= "9") ||
150
+ (tail.startsWith("[") && !isArbitraryColor(tail));
151
+ if (isWidth) return \`\${variants}border\${side}-width\`;
152
+ if (BORDER_STYLES.has(tail)) return \`\${variants}border-style\`;
153
+ if (COLORS.has(tail) || COLOR_KEYWORDS.has(tail) || isArbitraryColor(tail)) {
154
+ return \`\${variants}border\${side}-color\`;
155
+ }
156
+ return \`\${variants}\${cls}\`;
157
+ }
158
+
159
+ function isArbitraryColor(v: string): boolean {
160
+ return /^\\[(color:|#|rgba?\\(|hsla?\\(|oklch\\(|oklab\\(|var\\(--color)/.test(v);
161
+ }
162
+
127
163
  /**
128
164
  * The property this class sets, or the class itself when we cannot tell.
129
165
  *
@@ -169,6 +205,7 @@ function groupOf(cls: string): string {
169
205
  if (FONT_FAMILIES.has(rest)) return \`\${variants}font-family\`;
170
206
  return \`\${variants}\${cls}\`;
171
207
  }
208
+ if (head === "border") return borderGroup(variants, rest, cls);
172
209
 
173
210
  for (const p of PREFIXES) {
174
211
  if (base === p || base.startsWith(\`\${p}-\`)) return \`\${variants}\${p}\`;
@@ -409,7 +409,15 @@ async function checkFile(root, path) {
409
409
  for (const f of d.findings.slice(0, 40)) {
410
410
  out.push(nameToWrite(f)
411
411
  ? ` ${f.file}:${f.line} ${f.literal} - this repo calls it ${nameToWrite(f)}`
412
- : ` ${f.file}:${f.line} ${f.literal} - no token holds this value`);
412
+ : /**
413
+ * O SISTEMA SEGURA, O PROJETO AINDA NÃO NOMEIA - rodada 1 do refinamento, 27/09. Dizer "no
414
+ * token holds this value" sobre o `160ms` que o sistema declara fez o leigo concluir que o
415
+ * sistema discordava dele mesmo. O nome continua fora da frase: a grafia `--ds-*` é nossa
416
+ * (`INV-GERAL-13`), e batizar o valor no código dele é decisão dele.
417
+ */
418
+ f.token
419
+ ? ` ${f.file}:${f.line} ${f.literal} - the system holds this value, and your code has no name for it yet`
420
+ : ` ${f.file}:${f.line} ${f.literal} - no token holds this value`);
413
421
  }
414
422
  out.push("", "Replace the ones that have a token. For a value with none, do NOT invent a token: say which value it is and what you would call it, and let a person decide.");
415
423
  }
@@ -515,6 +515,15 @@ function scanCore(file, source, table) {
515
515
  };
516
516
  }
517
517
  let svgDepth = 0;
518
+ /**
519
+ * DENTRO DE `@theme` OU `:root`, UMA DECLARAÇÃO É O VOCABULÁRIO, NÃO UM USO - rodada 1 do refinamento,
520
+ * 27/09. O leigo copiou os valores do sistema para o `@theme` do projeto novo, como o GUIDE ensina, e o
521
+ * `check_file` respondeu "17% (...) 19 written by hand", linha por linha, com o conserto circular
522
+ * "#0a100d - this repo calls it --color-canvas" na própria linha `--color-canvas: #0a100d;`.
523
+ * Profundidade de chaves, e não uma flag, porque `@theme` pode abrir bloco dentro de bloco.
524
+ */
525
+ let tokenBlockDepth = 0;
526
+ let braceDepth = 0;
518
527
  source.split("\n").forEach((raw, i) => {
519
528
  const line = raw.trim();
520
529
  /**
@@ -528,6 +537,14 @@ function scanCore(file, source, table) {
528
537
  */
529
538
  const indent = line ? raw.indexOf(line) : 0;
530
539
  const at = i + 1;
540
+ const depthBefore = braceDepth;
541
+ const opensTokenBlock = /^(@theme\b|:root\b)/.test(line) && line.includes("{");
542
+ if (opensTokenBlock && tokenBlockDepth === 0)
543
+ tokenBlockDepth = depthBefore + 1;
544
+ const inTokenBlock = tokenBlockDepth > 0 && (opensTokenBlock || depthBefore >= tokenBlockDepth);
545
+ braceDepth = Math.max(0, braceDepth + (line.match(/\{/g) ?? []).length - (line.match(/\}/g) ?? []).length);
546
+ if (tokenBlockDepth > 0 && braceDepth < tokenBlockDepth)
547
+ tokenBlockDepth = 0;
531
548
  tokenUses += countTokenUses(line, table);
532
549
  /**
533
550
  * O QUE ESTE ARQUIVO DECLARA E O QUE ELE USA DE FORA DO SISTEMA - ver `FileReport.ownDeclared`.
@@ -577,6 +594,8 @@ function scanCore(file, source, table) {
577
594
  const declares = DECLARES_TOKEN.exec(line);
578
595
  if (declares && table.byName.has(declares[1].toLowerCase()))
579
596
  return;
597
+ if (declares && inTokenBlock)
598
+ return;
580
599
  // `rgba(${r}, ${g}, ${b}, ${a})` is code computing a colour, not a colour
581
600
  // written by hand - flagging it would be telling someone to tokenize a
582
601
  // variable. And the same literal twice in one declaration (a two-stop
@@ -402,7 +402,13 @@ export const COUNTED_DIFFERENTLY = "this run counts a value as named only when Y
402
402
  * mesma jornada, e o hook fixado nela manda só o registro em todo turno - nunca o censo, nem com a
403
403
  * main limpa num commit novo. Quem está nela não vê o sistema mudar depois do commit, e precisa saber.
404
404
  */
405
- export const CHECKER_SINCE = "0.16.457";
405
+ /**
406
+ * 0.16.457 -> 0.16.458 em 27/09, e o passo 1 dá **SIM**: a varredura que o hook roda deixa de acusar as
407
+ * declarações dentro de `@theme` e `:root` (rodada 1 do refinamento - o `check_file` dava "19 written by
408
+ * hand" no `@theme` que o leigo copiou do GUIDE). Um hook fixado antes continua acusando o vocabulário do
409
+ * projeto como valor à mão, em todo turno.
410
+ */
411
+ export const CHECKER_SINCE = "0.16.458";
406
412
  /**
407
413
  * A ÚLTIMA VERSÃO EM QUE OS LEITORES PASSARAM A PRODUZIR UM CENSO DIFERENTE.
408
414
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.457",
3
+ "version": "0.16.458",
4
4
  "description": "Bring SynthesisUI design systems into any project - tokens, typed components, whole pages and an agent-ready CLAUDE.md manifest.",
5
5
  "type": "module",
6
6
  "bin": {