@homebound/truss 2.22.0 → 2.23.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/build/index.d.ts CHANGED
@@ -7,6 +7,11 @@ import { Code } from 'ts-poet';
7
7
  * Or a set of properties, i.e. `f12` -> `{ fontFamily: ..., fontWeight: ... }`.
8
8
  */
9
9
  type FontConfig = Record<string, string | Properties>;
10
+ /**
11
+ * Maps a design token name (enum member / key) to a CSS custom property name.
12
+ * Values must be valid custom property identifiers (`--…`).
13
+ */
14
+ type TokenRegistry = Record<string, `--${string}`>;
10
15
  /**
11
16
  * Provides users with an easy way to configure the major/most-often configurable
12
17
  * aspect of a design system, i.e. the palette, fonts, and increments.
@@ -45,6 +50,11 @@ interface Config {
45
50
  typeAliases?: Record<string, Array<keyof Properties>>;
46
51
  /** Breakpoints, i.e. `{ sm: 0, md: 500 }`. */
47
52
  breakpoints?: Record<string, number>;
53
+ /**
54
+ * Optional design tokens: emitted as `Tokens` enum in generated `Css.ts` and available to
55
+ * `Css.setVar({ [Tokens.X]: … })` at build time (web target).
56
+ */
57
+ tokens?: TokenRegistry;
48
58
  /**
49
59
  * Which default methods to include.
50
60
  *
@@ -261,4 +271,4 @@ declare function newIncrementMethods(config: Config, abbr: UtilityName, prop: Pr
261
271
  declare function newCoreIncrementMethods(config: Config, abbr: UtilityName, props: Prop[]): UtilityMethod[];
262
272
  declare function newPxMethod(abbr: UtilityName, prop: Prop): UtilityMethod;
263
273
 
264
- export { type Aliases, type Config, type CreateMethodsFn, type FontConfig, type IncConfig, type SectionName, type Sections, type UtilityMethod, type UtilityName, type WebEntry, defaultSections, defineConfig, generate, newAliasesMethods, newCoreIncrementMethods, newIncrementMethods, newMethod, newMethodsForProp, newParamMethod, newPxMethod, newSetCssVariablesMethod, startWebCollection, stopWebCollection };
274
+ export { type Aliases, type Config, type CreateMethodsFn, type FontConfig, type IncConfig, type SectionName, type Sections, type TokenRegistry, type UtilityMethod, type UtilityName, type WebEntry, defaultSections, defineConfig, generate, newAliasesMethods, newCoreIncrementMethods, newIncrementMethods, newMethod, newMethodsForProp, newParamMethod, newPxMethod, newSetCssVariablesMethod, startWebCollection, stopWebCollection };
package/build/index.js CHANGED
@@ -940,6 +940,33 @@ var defaultTypeAliases = {
940
940
  Margin: ["margin", "marginTop", "marginRight", "marginBottom", "marginLeft"],
941
941
  Padding: ["padding", "paddingTop", "paddingRight", "paddingBottom", "paddingLeft"]
942
942
  };
943
+ function emitTokensEnumAndSetVarTypes(tokens) {
944
+ const entries = tokens && typeof tokens === "object" ? Object.entries(tokens).filter(([, v]) => typeof v === "string") : [];
945
+ const hasTokens = entries.length > 0;
946
+ const enumBlock = hasTokens ? `export enum Tokens {
947
+ ${entries.map(([name, value]) => ` ${name} = ${JSON.stringify(value)},`).join("\n")}
948
+ }
949
+
950
+ ` : "";
951
+ const keysType = hasTokens ? `export type CssSetVarKeys = Tokens | \`--\${string}\`;
952
+
953
+ ` : `export type CssSetVarKeys = \`--\${string}\`;
954
+
955
+ `;
956
+ const scalar = `export type CssSetVarScalar = string | number;
957
+
958
+ `;
959
+ const valueType = `export type CssSetVarValue =
960
+ | CssSetVarScalar
961
+ | {
962
+ default?: CssSetVarScalar;
963
+ media?: Partial<Record<Breakpoint, CssSetVarScalar>>;
964
+ container?: Array<{ name?: string; gt?: number; lt?: number; value: CssSetVarScalar }>;
965
+ };
966
+
967
+ `;
968
+ return enumBlock + keysType + scalar + valueType;
969
+ }
943
970
  async function generate(config) {
944
971
  const { outputPath } = config;
945
972
  const target = config.target ?? "web";
@@ -960,7 +987,7 @@ async function generate(config) {
960
987
  throw new Error(`Unsupported truss target "${target}". Use "web" (default) or "react-native".`);
961
988
  }
962
989
  function generateReactNativeBuilder(config) {
963
- const { fonts, increment, extras, typeAliases, breakpoints = {}, palette } = config;
990
+ const { fonts, increment, extras, typeAliases, breakpoints = {}, palette, tokens } = config;
964
991
  const sections = generateSections(config);
965
992
  const lines = Object.entries(sections).map(([name, value]) => [`// ${name}`, ...value, ""]).flat();
966
993
  const typeAliasCode = Object.entries({
@@ -1024,6 +1051,8 @@ export type ${def("InlineStyle")} = Record<string, string | number | undefined>;
1024
1051
 
1025
1052
  ${typographyType}
1026
1053
 
1054
+ ${emitTokensEnumAndSetVarTypes(tokens)}
1055
+
1027
1056
  type Opts<T> = {
1028
1057
  rules: T,
1029
1058
  enabled: boolean,
@@ -1155,6 +1184,12 @@ class CssBuilder<T extends Properties> {
1155
1184
  return this;
1156
1185
  }
1157
1186
 
1187
+ /** Set CSS custom properties (web build-time only; not supported on react-native). */
1188
+ setVar(_values: Partial<Record<CssSetVarKeys, CssSetVarValue>>): CssBuilder<T> {
1189
+ void _values;
1190
+ throw new Error("Css.setVar() is only supported when Truss target is \\\"web\\\" (build-time atomic CSS).");
1191
+ }
1192
+
1158
1193
  /** Tagged template literal for raw CSS in .css.ts files; passes through the string as-is. */
1159
1194
  raw(strings: TemplateStringsArray, ...values: unknown[]): string {
1160
1195
  return String.raw(strings, ...values);
@@ -1238,7 +1273,7 @@ function collectWebGenerationData(config) {
1238
1273
  }
1239
1274
  }
1240
1275
  function generateWebCssBuilder(config, sections) {
1241
- const { fonts, increment, extras, typeAliases, palette, breakpoints = {} } = config;
1276
+ const { fonts, increment, extras, typeAliases, palette, breakpoints = {}, tokens } = config;
1242
1277
  const lines = Object.entries(sections).map(([name, value]) => [`// ${name}`, ...value, ""]).flat();
1243
1278
  const typeAliasCode = Object.entries({
1244
1279
  ...defaultTypeAliases,
@@ -1313,6 +1348,8 @@ export type ${def("RuntimeStyles")} = RawCssProperties & { readonly __kind: "run
1313
1348
 
1314
1349
  ${typographyType}
1315
1350
 
1351
+ ${emitTokensEnumAndSetVarTypes(tokens)}
1352
+
1316
1353
  // Augment React types so all JSX elements accept the \`css\` prop:
1317
1354
  // - HTMLAttributes/SVGAttributes cover intrinsic elements (div, svg, etc.)
1318
1355
  // - JSX.IntrinsicAttributes covers custom components (Card, Page, etc.)
@@ -1484,6 +1521,12 @@ class CssBuilder<T extends Properties, S extends StyleKind = "buildtime"> {
1484
1521
  return this.unsupportedRuntime("style() cannot be used in RuntimeStyle css expressions.");
1485
1522
  }
1486
1523
 
1524
+ /** Set CSS custom properties via atomic classes (resolved at build time on web). */
1525
+ setVar(_values: Partial<Record<CssSetVarKeys, CssSetVarValue>>): CssBuilder<T, S> {
1526
+ void _values;
1527
+ return this.unsupportedRuntime("setVar() cannot be used in RuntimeStyle css expressions.");
1528
+ }
1529
+
1487
1530
  /** Convert a style hash into \`{ className, style }\` props for manual spreading into non-\`css=\` contexts. */
1488
1531
  props(styles: Properties): Record<string, unknown> {
1489
1532
  return trussProps(styles as any);
@@ -1619,10 +1662,12 @@ function generateTrussMapping(config, entries) {
1619
1662
  for (const [name, mediaQuery] of Object.entries(genBreakpointsMap)) {
1620
1663
  breakpointEntries[`if${pascalCase(name)}`] = mediaQuery;
1621
1664
  }
1665
+ const tokenEntries = config.tokens && Object.keys(config.tokens).length > 0 ? config.tokens : void 0;
1622
1666
  return {
1623
1667
  increment: config.increment,
1624
1668
  ...Object.keys(breakpointEntries).length > 0 ? { breakpoints: breakpointEntries } : {},
1625
1669
  ...Object.keys(config.fonts).length > 0 ? { typography: Object.keys(config.fonts) } : {},
1670
+ ...tokenEntries ? { tokens: tokenEntries } : {},
1626
1671
  abbreviations
1627
1672
  };
1628
1673
  }
@@ -1636,6 +1681,9 @@ function condensedJson(mapping) {
1636
1681
  if (mapping.typography && mapping.typography.length > 0) {
1637
1682
  lines.push(` "typography": ${JSON.stringify(mapping.typography)},`);
1638
1683
  }
1684
+ if (mapping.tokens && Object.keys(mapping.tokens).length > 0) {
1685
+ lines.push(` "tokens": ${JSON.stringify(mapping.tokens)},`);
1686
+ }
1639
1687
  lines.push(` "abbreviations": {`);
1640
1688
  const entries = Object.entries(mapping.abbreviations);
1641
1689
  for (let i = 0; i < entries.length; i++) {