@rojaostudio/ds-core 1.1.0-next.8 → 1.1.0-next.9

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/LICENSE CHANGED
@@ -19,3 +19,14 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
+
23
+ ---
24
+
25
+ Arquivos gerados
26
+
27
+ Os arquivos que esta ferramenta escreve no seu projeto (o tema CSS e o bloco
28
+ entre os marcadores <!-- rojao-ds:start --> e <!-- rojao-ds:end --> em
29
+ CLAUDE.md, AGENTS.md ou .cursorrules) são de quem usa a ferramenta. Você pode
30
+ usá-los, alterá-los e distribuí-los como quiser, sem obrigação de manter aviso
31
+ de licença ou atribuição. A licença MIT acima vale para o código da ferramenta,
32
+ não para o que ela gera.
@@ -675,12 +675,114 @@ function resolveTheme(def, opts) {
675
675
  return { tokens: isDark ? __spreadValues(__spreadValues({}, light2), dark) : light2, isDark };
676
676
  }
677
677
 
678
+ // generate/validate.ts
679
+ var HEX = /^#[0-9a-f]{3,8}$/i;
680
+ var CH = String.raw`(?:[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?(?:%|deg)?|none)`;
681
+ var COLOR_FN = new RegExp(String.raw`^(?:rgba?|oklch)\(\s*${CH}(?:\s*[,/]?\s*${CH}){2,3}\s*\)$`, "i");
682
+ var VAR_NAME = /^[a-z0-9]+(?:[/-][a-z0-9]+)*$/;
683
+ var FONT_BAD = /["';{}\\<>\u0000-\u001f\u007f]/;
684
+ var isSafeColor = (v) => typeof v === "string" && (HEX.test(v) || COLOR_FN.test(v));
685
+ var isSafeVarName = (v) => typeof v === "string" && VAR_NAME.test(v);
686
+ var isSafeFont = (v) => typeof v === "string" && v.trim().length > 0 && v.length <= 100 && !FONT_BAD.test(v);
687
+ var isSafeCustomProperty = (k) => k.startsWith("--") && isSafeVarName(k.slice(2));
688
+ var FONT_ROLE_VAR = "--type-font-mono";
689
+ function preview(v) {
690
+ var _a;
691
+ const s = typeof v === "string" ? v : (_a = JSON.stringify(v)) != null ? _a : String(v);
692
+ const one = s.replace(/[\r\n\t]+/g, " ");
693
+ return JSON.stringify(one.length > 60 ? `${one.slice(0, 60)}\u2026` : one);
694
+ }
695
+ var RdsValidationError = class extends Error {
696
+ constructor(where, problems) {
697
+ super(`${where}: invalid input
698
+ ${problems.join("\n ")}`);
699
+ this.problems = problems;
700
+ this.name = "RdsValidationError";
701
+ }
702
+ };
703
+ function collector(where) {
704
+ const problems = [];
705
+ return {
706
+ problems,
707
+ color(field, v) {
708
+ if (!isSafeColor(v)) problems.push(`${field}: ${preview(v)} is not a colour (hex, rgb(), rgba() or oklch())`);
709
+ },
710
+ name(field, v) {
711
+ if (!isSafeVarName(v)) problems.push(`${field}: ${preview(v)} is not a valid name (lowercase letters, digits, "-" and "/")`);
712
+ },
713
+ font(field, v) {
714
+ if (!isSafeFont(v)) problems.push(`${field}: ${preview(v)} is not a valid font family (no quotes, ";", braces, "\\" or line breaks)`);
715
+ },
716
+ done() {
717
+ if (problems.length) throw new RdsValidationError(where, problems);
718
+ }
719
+ };
720
+ }
721
+ function assertSafeTheme(theme, where) {
722
+ const c = collector(where);
723
+ if (!theme || typeof theme !== "object") {
724
+ c.problems.push("the theme is not an object");
725
+ c.done();
726
+ }
727
+ const check = (label, map, fontRole) => {
728
+ if (!map || typeof map !== "object" || Array.isArray(map)) {
729
+ c.problems.push(`${label}: not an object`);
730
+ return;
731
+ }
732
+ for (const [k, v] of Object.entries(map)) {
733
+ if (!isSafeCustomProperty(k)) {
734
+ c.problems.push(`${label}: ${preview(k)} is not a valid CSS variable name`);
735
+ continue;
736
+ }
737
+ if (fontRole && k === FONT_ROLE_VAR) c.font(`${label}.${k}`, v);
738
+ else c.color(`${label}.${k}`, v);
739
+ }
740
+ };
741
+ for (const mode of ["light", "dark", "brand"]) check(mode, theme[mode], true);
742
+ if (theme.vars !== void 0) check("vars", theme.vars, false);
743
+ c.done();
744
+ }
745
+ var isSafeSelectorList = (v) => (
746
+ // eslint-disable-next-line no-control-regex -- control characters are exactly what is refused
747
+ typeof v === "string" && v.trim().length > 0 && !/[{};\\<@\u0000-\u001f\u007f]|\/\*|\*\//.test(v)
748
+ );
749
+ function oneLine(v, max = 200) {
750
+ if (typeof v !== "string") return "";
751
+ let s = v.replace(/[\u0000-\u001f\u007f\u2028\u2029]+/g, " ").replace(/[<>`]/g, "").replace(/rojao-ds:(start|end)/gi, "").replace(/\s+/g, " ").trim();
752
+ if (s.length > max) s = `${s.slice(0, max - 1).trimEnd()}\u2026`;
753
+ return s;
754
+ }
755
+
678
756
  // generate/rdsTheme.ts
679
757
  var palettes = primitives.color;
680
758
  var WHITE = "#ffffff";
681
759
  var BLACK = "#000000";
682
760
  var black = (pct) => BLACK + Math.round(pct / 100 * 255).toString(16).padStart(2, "0");
683
761
  var white = (pct) => WHITE + Math.round(pct / 100 * 255).toString(16).padStart(2, "0");
762
+ var PALETTE_STEPS2 = /* @__PURE__ */ new Set([...SCALE_STEPS.map(String), "950"]);
763
+ function checkPalettes(custom, where) {
764
+ if (custom === void 0) return;
765
+ const c = collector(where);
766
+ if (!custom || typeof custom !== "object" || Array.isArray(custom)) {
767
+ c.problems.push("palettes: not an object");
768
+ c.done();
769
+ }
770
+ for (const [name, value] of Object.entries(custom)) {
771
+ if (!/^[a-z][a-z0-9]*$/i.test(name)) {
772
+ c.problems.push(`palettes: ${preview(name)} is not a valid palette name (letters and digits)`);
773
+ continue;
774
+ }
775
+ if (typeof value === "string") {
776
+ if (!isHex(value)) c.problems.push(`palettes.${name}: ${preview(value)} is not a hex colour`);
777
+ } else if (value && typeof value === "object" && !Array.isArray(value)) {
778
+ for (const [step2, v] of Object.entries(value)) {
779
+ if (!PALETTE_STEPS2.has(step2)) c.problems.push(`palettes.${name}: ${preview(step2)} is not a scale step (50\u2013900)`);
780
+ else c.color(`palettes.${name}.${step2}`, v);
781
+ }
782
+ } else c.problems.push(`palettes.${name}: expected a hex or a scale of steps 50\u2013900`);
783
+ }
784
+ c.done();
785
+ }
684
786
  function palette(name, custom) {
685
787
  const own = custom == null ? void 0 : custom[name];
686
788
  if (typeof own === "string") {
@@ -839,6 +941,9 @@ var roleVar = (role) => `--${role.replaceAll("/", "-")}`;
839
941
  function generateRdsTheme(def, opts = {}) {
840
942
  var _a, _b;
841
943
  const warn = (_a = opts.warn) != null ? _a : defaultWarn;
944
+ const where = `generateRdsTheme(${preview(def == null ? void 0 : def.name)})`;
945
+ if (!(def == null ? void 0 : def.brand) || typeof def.brand !== "object") throw new Error(`${where}: brand is missing`);
946
+ checkPalettes(def.palettes, where);
842
947
  const b = def.brand;
843
948
  const own = def.palettes;
844
949
  const P = ramp(b.primary, own);
@@ -1117,6 +1222,7 @@ function generateRdsTheme(def, opts = {}) {
1117
1222
  out.brand[roleVar(role)] = pick(brandSrc, role);
1118
1223
  }
1119
1224
  out.brand[roleVar("border/error")] = brandError;
1225
+ assertSafeTheme(out, where);
1120
1226
  return out;
1121
1227
  }
1122
1228
  var RDS_SCOPE_SELECTORS = [
@@ -1142,6 +1248,12 @@ var covered = (sel) => {
1142
1248
  };
1143
1249
  function emitRdsCss(theme, opts = {}) {
1144
1250
  var _a, _b, _c;
1251
+ assertSafeTheme(theme, "emitRdsCss");
1252
+ const badSel = ["scope", "dark", "plate"].filter((k) => opts[k] !== void 0 && !isSafeSelectorList(opts[k]));
1253
+ if (badSel.length)
1254
+ throw new Error(
1255
+ `emitRdsCss: invalid selector in ${badSel.map((k) => `${k} ${preview(opts[k])}`).join(", ")} (no braces, ";", comments, backslash, "@", "<" or line breaks).`
1256
+ );
1145
1257
  const scopes = split((_a = opts.scope) != null ? _a : ":root, .ds-scope, [data-rds-scope]");
1146
1258
  const darks = split((_b = opts.dark) != null ? _b : '.dark, [data-rds-mode="dark"]');
1147
1259
  const plates = split((_c = opts.plate) != null ? _c : ".ds-plate, [data-rds-plate]");
@@ -1214,6 +1326,25 @@ var ADDED_ROLES = {
1214
1326
  };
1215
1327
  function rdsThemeFromTable(table, opts = {}) {
1216
1328
  var _a, _b, _c;
1329
+ const where = `rdsThemeFromTable(${preview(table == null ? void 0 : table.name)})`;
1330
+ if (!table || typeof table !== "object") throw new Error(`${where}: the table is not an object`);
1331
+ const check = collector(where);
1332
+ if (!table.primitives || typeof table.primitives !== "object" || Array.isArray(table.primitives))
1333
+ check.problems.push("primitives: not an object");
1334
+ else
1335
+ for (const [name, value] of Object.entries(table.primitives)) {
1336
+ check.name(`primitives ${preview(name)}`, name);
1337
+ check.color(`primitives.${name}`, value);
1338
+ }
1339
+ if (table.vars !== void 0) {
1340
+ if (!table.vars || typeof table.vars !== "object" || Array.isArray(table.vars)) check.problems.push("vars: not an object");
1341
+ else
1342
+ for (const [name, value] of Object.entries(table.vars)) {
1343
+ check.name(`vars ${preview(name)}`, name);
1344
+ if (typeof value !== "string") check.problems.push(`vars.${name}: not a string`);
1345
+ }
1346
+ }
1347
+ check.done();
1217
1348
  const out = { light: {}, dark: {}, brand: {} };
1218
1349
  const problems = [];
1219
1350
  const derived = /* @__PURE__ */ new Set();
@@ -1238,10 +1369,10 @@ function rdsThemeFromTable(table, opts = {}) {
1238
1369
  } else out[mode][roleVar(role)] = ref2;
1239
1370
  }
1240
1371
  }
1241
- const valueOf = (where, ref2) => {
1372
+ const valueOf = (field, ref2) => {
1242
1373
  if (!isColourRef(ref2)) return ref2;
1243
1374
  const value = table.primitives[ref2];
1244
- if (value === void 0) problems.push(`${where} points to unknown primitive "${ref2}"`);
1375
+ if (value === void 0) problems.push(`${field} points to unknown primitive "${ref2}"`);
1245
1376
  return value == null ? void 0 : value.toLowerCase();
1246
1377
  };
1247
1378
  if (table.vars) {
@@ -1251,17 +1382,18 @@ function rdsThemeFromTable(table, opts = {}) {
1251
1382
  if (value !== void 0) out.vars[roleVar(name)] = value;
1252
1383
  }
1253
1384
  }
1254
- if (problems.length) throw new Error(`rdsThemeFromTable(${table.name}):
1385
+ if (problems.length) throw new Error(`${where}:
1255
1386
  ${problems.join("\n ")}`);
1387
+ assertSafeTheme(out, where);
1256
1388
  const warn = (_c = opts.warn) != null ? _c : defaultWarn;
1257
1389
  if (derived.size)
1258
1390
  warn(
1259
- `rdsThemeFromTable(${table.name}): the table was exported before ${[...derived].map((r) => `"${r}"`).join(", ")} existed in the [RDS] theme. Taken from the tokens Figma aliases it to (` + [...derived].map((r) => Object.entries(ADDED_ROLES[r]).map(([m, src]) => `${m}: ${src}`).join(", ")).join("; ") + `). Export the table again with figma/export-brand.js.`
1391
+ `${where}: the table was exported before ${[...derived].map((r) => `"${r}"`).join(", ")} existed in the [RDS] theme. Taken from the tokens Figma aliases it to (` + [...derived].map((r) => Object.entries(ADDED_ROLES[r]).map(([m, src]) => `${m}: ${src}`).join(", ")).join("; ") + `). Export the table again with figma/export-brand.js.`
1260
1392
  );
1261
1393
  const fails = rdsContrastReport(out);
1262
1394
  if (fails.length)
1263
1395
  warn(
1264
- `rdsThemeFromTable(${table.name}): ${fails.length} text pair(s) below 4.5:1
1396
+ `${where}: ${fails.length} text pair(s) below 4.5:1
1265
1397
  ` + fails.map((f) => `${f.mode}: ${f.fg} on ${f.bg} ${f.ratio}:1`).join("\n ")
1266
1398
  );
1267
1399
  return out;
@@ -1338,6 +1470,11 @@ ${lightBlock}${darkBlock}
1338
1470
  }
1339
1471
 
1340
1472
  // generate/emitClaudeMd.ts
1473
+ var MARKERS = /rojao-ds:(start|end)/i;
1474
+ var NAME = /^[a-z0-9][a-z0-9 _-]{0,63}$/i;
1475
+ var CSS_FILE = /^[a-z0-9_@./-]+\.css$/i;
1476
+ var CSS_URL = /^https?:\/\/[^\s"'`<>()\\]+$/i;
1477
+ var INSTALL = /^(?:pnpm add|yarn add|bun add|npm install|npm i) @rojaostudio\/ds(?:@[a-z0-9][a-z0-9.+-]*)?$/;
1341
1478
  var ROLE_DOCS = [
1342
1479
  { role: "colors/primary/default", use: "primary action, brand fills" },
1343
1480
  { role: "text/on/primary", use: "text/icon on the primary fill" },
@@ -1397,8 +1534,9 @@ var CLAUDE_MD_FOUNDATION = {
1397
1534
  function isTable(x) {
1398
1535
  return typeof x === "object" && x !== null && "modes" in x && "primitives" in x;
1399
1536
  }
1537
+ var TARGET_FILES = { claude: "CLAUDE.md", cursor: ".cursorrules", agents: "AGENTS.md" };
1400
1538
  function fileLabel(target) {
1401
- return target === "cursor" ? ".cursorrules" : target === "agents" ? "AGENTS.md" : "CLAUDE.md";
1539
+ return TARGET_FILES[target];
1402
1540
  }
1403
1541
  function roleTable(theme) {
1404
1542
  const rows = ROLE_DOCS.filter((r) => roleVar(r.role) in theme.light).map((r) => {
@@ -1409,19 +1547,29 @@ function roleTable(theme) {
1409
1547
  return ["| Token | Use for | Light | Dark |", "|---|---|---|---|", ...rows].join("\n");
1410
1548
  }
1411
1549
  function emitClaudeMd(source, opts = {}) {
1412
- var _a, _b, _c;
1550
+ var _a, _b, _c, _d;
1413
1551
  const theme = (_a = opts.theme) != null ? _a : isTable(source) ? rdsThemeFromTable(source) : generateRdsTheme(source);
1552
+ assertSafeTheme(theme, "emitClaudeMd");
1414
1553
  const name = source.name;
1554
+ if (name !== void 0 && name !== "" && !(typeof name === "string" && NAME.test(name)))
1555
+ throw new Error(`emitClaudeMd: name ${preview(name)} is not valid (letters, digits, space, "-" and "_", up to 64)`);
1415
1556
  const Name = name ? name[0].toUpperCase() + name.slice(1) : "Brand";
1416
- const description = !isTable(source) && source.description ? ` \u2014 ${source.description}` : "";
1557
+ const desc = !isTable(source) ? oneLine(source.description) : "";
1558
+ const description = desc ? ` \u2014 ${desc}` : "";
1417
1559
  const cssFile = (_b = opts.cssFile) != null ? _b : "rds-theme.css";
1418
- const target = (_c = opts.target) != null ? _c : "claude";
1560
+ if (!CSS_FILE.test(cssFile)) throw new Error(`emitClaudeMd: cssFile ${preview(cssFile)} is not a valid .css path`);
1561
+ if (opts.cssUrl !== void 0 && !CSS_URL.test(opts.cssUrl))
1562
+ throw new Error(`emitClaudeMd: cssUrl ${preview(opts.cssUrl)} is not a valid http(s) URL`);
1563
+ const install = (_c = opts.install) != null ? _c : "pnpm add @rojaostudio/ds";
1564
+ if (!INSTALL.test(install)) throw new Error(`emitClaudeMd: install ${preview(install)} is not an install command of @rojaostudio/ds`);
1565
+ const target = (_d = opts.target) != null ? _d : "claude";
1566
+ if (!Object.prototype.hasOwnProperty.call(TARGET_FILES, target)) throw new Error(`emitClaudeMd: unknown target ${preview(target)}`);
1419
1567
  const f = CLAUDE_MD_FOUNDATION;
1420
1568
  const own = theme.vars ? Object.keys(theme.vars) : [];
1421
1569
  const themeImport = opts.cssUrl ? `@import "@rojaostudio/ds/styles/rds.css";
1422
1570
  @import url("${opts.cssUrl}"); /* the brand theme, AFTER rds.css */` : `@import "@rojaostudio/ds/styles/rds.css";
1423
1571
  @import "./${cssFile}"; /* the brand theme, AFTER rds.css */`;
1424
- return `# Design System \u2014 ${Name}
1572
+ const text = `# Design System \u2014 ${Name}
1425
1573
 
1426
1574
  > This project uses **Roj\xE3o DS 2.0** with the **${Name}** brand${description}. When you build any
1427
1575
  > UI \u2014 components, pages, screens \u2014 follow the rules below so every screen looks like the same
@@ -1429,7 +1577,7 @@ function emitClaudeMd(source, opts = {}) {
1429
1577
 
1430
1578
  ## Setup (once per app)
1431
1579
  \`\`\`bash
1432
- pnpm add @rojaostudio/ds
1580
+ ${install}
1433
1581
  \`\`\`
1434
1582
  \`\`\`css
1435
1583
  /* root stylesheet */
@@ -1489,6 +1637,8 @@ Brand's own variables (same value in every mode): ${own.map((v) => `\`${v}\``).j
1489
1637
 
1490
1638
  <!-- Generated by Roj\xE3o DS (npx rojao-ds init) \u2014 file: ${fileLabel(target)}. Claude Code, Cursor and other agents read it from the project root. -->
1491
1639
  `;
1640
+ if (MARKERS.test(text)) throw new Error("emitClaudeMd: the generated text contains a rojao-ds marker");
1641
+ return text;
1492
1642
  }
1493
1643
 
1494
- export { RDS_CONTRAST_PAIRS, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, ROLES, SCALE_STEPS, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, generateTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, resolveTheme, roleVar };
1644
+ export { RDS_CONTRAST_PAIRS, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, ROLES, RdsValidationError, SCALE_STEPS, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, generateTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, isSafeColor, isSafeFont, isSafeVarName, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, resolveTheme, roleVar };
@@ -91,6 +91,26 @@ type RdsBrandTable = {
91
91
  */
92
92
  declare function rdsThemeFromTable(table: RdsBrandTable, opts?: RdsThemeOptions): RdsTheme;
93
93
 
94
+ /**
95
+ * validate.ts — what the emitters accept from the outside (a recipe, a brand table, a theme object).
96
+ *
97
+ * ds-core is a public API, and its output lands in a stylesheet (`emitRdsCss`) and in the rules file an AI agent
98
+ * reads (`emitClaudeMd`). A value that is not a colour could close the CSS rule and open another one, pull an
99
+ * `url()`, or carry an instruction into CLAUDE.md. So every value is checked against an allow list before it is
100
+ * written, and the check runs again in each emitter (defence in depth: a theme object can be built by hand).
101
+ *
102
+ * Allow lists, never deny lists: a colour is a hex or a closed `rgb()/rgba()/oklch()`; a variable name is lowercase
103
+ * words joined by `-` or `/`; a font family has no quote, semicolon, brace, backslash or line break.
104
+ */
105
+ declare const isSafeColor: (v: unknown) => v is string;
106
+ declare const isSafeVarName: (v: unknown) => v is string;
107
+ declare const isSafeFont: (v: unknown) => v is string;
108
+ /** Thrown when an input fails the allow list. The message lists every field that failed. */
109
+ declare class RdsValidationError extends Error {
110
+ readonly problems: string[];
111
+ constructor(where: string, problems: string[]);
112
+ }
113
+
94
114
  /**
95
115
  * emitCss.ts — formata o output do generateTheme num theme.css legível.
96
116
  * Header + bloco light (.theme-<name>) + bloco dark (seletor duplo), agrupado
@@ -124,6 +144,11 @@ interface ClaudeMdOptions {
124
144
  theme?: RdsTheme;
125
145
  /** File the text is written to (only the footer changes). Default `claude`. */
126
146
  target?: ClaudeMdTarget;
147
+ /**
148
+ * The install command shown in the setup, as the consumer's package manager runs it
149
+ * (`npm install @rojaostudio/ds@next`). Default `pnpm add @rojaostudio/ds`.
150
+ */
151
+ install?: string;
127
152
  }
128
153
  declare function emitClaudeMd(source: BrandDef | RdsBrandTable, opts?: ClaudeMdOptions): string;
129
154
 
@@ -193,4 +218,4 @@ declare function isNeutralBrand(def: {
193
218
  palettes?: PaletteDefs;
194
219
  }): boolean;
195
220
 
196
- export { BrandDef, type ClaudeMdOptions, type ClaudeMdTarget, RDS_CONTRAST_PAIRS, ROLES as RDS_ROLES, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, type RdsBrandTable, type RdsContrastFailure, type RdsCssOptions, type RdsMode, type RdsTheme, type RdsThemeOptions, SCALE_STEPS, type Scale, type ScaleStep, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, roleVar };
221
+ export { BrandDef, type ClaudeMdOptions, type ClaudeMdTarget, RDS_CONTRAST_PAIRS, ROLES as RDS_ROLES, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, type RdsBrandTable, type RdsContrastFailure, type RdsCssOptions, type RdsMode, type RdsTheme, type RdsThemeOptions, RdsValidationError, SCALE_STEPS, type Scale, type ScaleStep, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, isSafeColor, isSafeFont, isSafeVarName, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, roleVar };
package/dist/generate.js CHANGED
@@ -1,3 +1,3 @@
1
- export { RDS_CONTRAST_PAIRS, ROLES as RDS_ROLES, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, SCALE_STEPS, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, generateTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, resolveTheme, roleVar } from './chunk-6XIFYDSU.js';
1
+ export { RDS_CONTRAST_PAIRS, ROLES as RDS_ROLES, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, RdsValidationError, SCALE_STEPS, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, generateTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, isSafeColor, isSafeFont, isSafeVarName, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, resolveTheme, roleVar } from './chunk-N3HPD3U5.js';
2
2
  import './chunk-FRWRLCYM.js';
3
3
  import './chunk-ORMEWXMH.js';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { G as GenResult, R as ResolvedTheme, T as TokenMap, g as generateTheme, r as resolveTheme } from './generateTheme-CUfNpsKs.js';
2
- export { ClaudeMdOptions, ClaudeMdTarget, RDS_CONTRAST_PAIRS, RDS_ROLES, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, RdsBrandTable, RdsContrastFailure, RdsCssOptions, RdsMode, RdsTheme, RdsThemeOptions, SCALE_STEPS, Scale, ScaleStep, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, roleVar } from './generate.js';
2
+ export { ClaudeMdOptions, ClaudeMdTarget, RDS_CONTRAST_PAIRS, RDS_ROLES, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, RdsBrandTable, RdsContrastFailure, RdsCssOptions, RdsMode, RdsTheme, RdsThemeOptions, RdsValidationError, SCALE_STEPS, Scale, ScaleStep, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, isSafeColor, isSafeFont, isSafeVarName, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, roleVar } from './generate.js';
3
3
  export { A as Archetype, B as BrandColors, a as BrandDef, C as ColorRef, D as DarkStrategy, F as FontDef, P as PaletteRef, S as ScaleToken, T as TextStyle, b as TextStyleName, c as TypeScale } from './recipe.schema-Cq7e82nx.js';
4
4
  export { primitives, tokens } from './tokens.js';
5
5
  export { RecipeName, recipes } from './recipes.js';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { recipes } from './chunk-PV6GFEAM.js';
2
- export { RDS_CONTRAST_PAIRS, ROLES as RDS_ROLES, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, SCALE_STEPS, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, generateTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, resolveTheme, roleVar } from './chunk-6XIFYDSU.js';
2
+ export { RDS_CONTRAST_PAIRS, ROLES as RDS_ROLES, RDS_SCOPE_SELECTORS, RDS_TOKEN_SCOPE, RdsValidationError, SCALE_STEPS, brandTones, buildScale, contrastRatio, emitClaudeMd, emitCss, emitRdsCss, generateRdsTheme, generateTheme, hexToHsl, hslToHex, isHex, isNeutralBrand, isSafeColor, isSafeFont, isSafeVarName, onColor, rdsContrast, rdsContrastReport, rdsThemeFromTable, refToHex, relativeLuminance, resolveTheme, roleVar } from './chunk-N3HPD3U5.js';
3
3
  export { primitives, tokens } from './chunk-FRWRLCYM.js';
4
4
  import './chunk-ORMEWXMH.js';
package/dist/themes.js CHANGED
@@ -1,4 +1,4 @@
1
- import { generateTheme } from './chunk-6XIFYDSU.js';
1
+ import { generateTheme } from './chunk-N3HPD3U5.js';
2
2
  import './chunk-FRWRLCYM.js';
3
3
  import { __spreadValues, __objRest } from './chunk-ORMEWXMH.js';
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rojaostudio/ds-core",
3
- "version": "1.1.0-next.8",
3
+ "version": "1.1.0-next.9",
4
4
  "description": "O motor do Rojão DS — tokens, derivação de tema e emissores. Sem React, sem Tailwind, sem CSS.",
5
5
  "license": "MIT",
6
6
  "author": "Rojão Studio (https://rojao.studio)",