@homebound/truss 2.20.1 → 2.21.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.js CHANGED
@@ -1054,7 +1054,7 @@ class CssBuilder<T extends Properties> {
1054
1054
 
1055
1055
  ${lines.join("\n ").replace(/ +\n/g, "\n")}
1056
1056
 
1057
- get $(): T { maybeImportant(sortObject(this.rules), this.opts.important); }
1057
+ get $(): T { return maybeImportant(sortObject(this.rules), this.opts.important); }
1058
1058
 
1059
1059
  if(bp: Breakpoint): CssBuilder<T>;
1060
1060
  if(cond: boolean): CssBuilder<T>;
@@ -1289,11 +1289,10 @@ function generateStylexCssBuilder(config, sections) {
1289
1289
  // See your project's \`truss-config.ts\` to make configuration changes (fonts, increments, etc).
1290
1290
  // Target: native (build-time plugin)
1291
1291
 
1292
- import { trussProps } from "@homebound/truss/runtime";
1293
- export { RuntimeStyle, useRuntimeStyle } from "@homebound/truss/runtime";
1292
+ import { trussProps, useRuntimeStyle as _useRuntimeStyle } from "@homebound/truss/runtime";
1294
1293
 
1295
1294
  /** Given a type X, and the user's proposed type T, only allow keys in X and nothing else. */
1296
- export type Only<X, T> = X & Record<Exclude<keyof T, keyof X>, never>;
1295
+ export type Only<X, T> = X & Record<Exclude<keyof T, keyof X | "__kind">, never>;
1297
1296
 
1298
1297
  type UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends (value: infer I) => void
1299
1298
  ? I
@@ -1306,6 +1305,15 @@ export type ${def("InlineStyle")} = Record<string, string | number | undefined>;
1306
1305
  /** A marker token used with \`when\`/\`markerOf\` etc. */
1307
1306
  export type Marker = symbol;
1308
1307
 
1308
+ /** Discriminates between build-time and runtime Css expressions. */
1309
+ export type StyleKind = "buildtime" | "runtime";
1310
+
1311
+ /** The result of \`Css.*.$\` — for use in \`css=\` props (transformed at build time). */
1312
+ export type ${def("BuildtimeStyles")} = Properties & { readonly __kind: "buildtime" };
1313
+
1314
+ /** The result of \`RuntimeCss.*.$\` — for use in \`useRuntimeStyle\`. */
1315
+ export type ${def("RuntimeStyles")} = Properties & { readonly __kind: "runtime" };
1316
+
1309
1317
  ${typographyType}
1310
1318
 
1311
1319
  // Augment React types so all JSX elements accept the \`css\` prop:
@@ -1313,14 +1321,14 @@ ${typographyType}
1313
1321
  // - JSX.IntrinsicAttributes covers custom components (Card, Page, etc.)
1314
1322
  declare module "react" {
1315
1323
  interface HTMLAttributes<T> {
1316
- css?: Properties;
1324
+ css?: BuildtimeStyles;
1317
1325
  }
1318
1326
  interface SVGAttributes<T> {
1319
- css?: Properties;
1327
+ css?: BuildtimeStyles;
1320
1328
  }
1321
1329
  namespace JSX {
1322
1330
  interface IntrinsicAttributes {
1323
- css?: Properties;
1331
+ css?: BuildtimeStyles;
1324
1332
  }
1325
1333
  }
1326
1334
  }
@@ -1333,12 +1341,12 @@ type Opts<T> = {
1333
1341
  runtimeError: string | undefined;
1334
1342
  };
1335
1343
 
1336
- class CssBuilder<T extends Properties> {
1344
+ class CssBuilder<T extends Properties, S extends StyleKind = "buildtime"> {
1337
1345
  constructor(private opts: Opts<T>) {}
1338
1346
 
1339
1347
  ${lines.join("\n ").replace(/ +\n/g, "\n")}
1340
1348
 
1341
- get $(): T {
1349
+ get $(): T & { readonly __kind: S } {
1342
1350
  if (this.opts.runtimeError) {
1343
1351
  throw new Error(this.opts.runtimeError);
1344
1352
  }
@@ -1374,12 +1382,12 @@ class CssBuilder<T extends Properties> {
1374
1382
  }
1375
1383
 
1376
1384
  /** Marks this element as a default hover marker (for ancestor pseudo selectors). */
1377
- get marker(): CssBuilder<T> {
1385
+ get marker(): CssBuilder<T, S> {
1378
1386
  return this.unsupportedRuntime("marker cannot be used in RuntimeStyle css expressions.");
1379
1387
  }
1380
1388
 
1381
1389
  /** Marks this element with a user-defined marker. */
1382
- markerOf(_marker: Marker): CssBuilder<T> {
1390
+ markerOf(_marker: Marker): CssBuilder<T, S> {
1383
1391
  return this.unsupportedRuntime("markerOf() cannot be used in RuntimeStyle css expressions.");
1384
1392
  }
1385
1393
 
@@ -1388,7 +1396,7 @@ class CssBuilder<T extends Properties> {
1388
1396
  return Symbol("truss-marker");
1389
1397
  }
1390
1398
 
1391
- typography(key: Typography): CssBuilder<T> {
1399
+ typography(key: Typography): CssBuilder<T, S> {
1392
1400
  return (this as any)[key];
1393
1401
  }
1394
1402
 
@@ -1398,25 +1406,25 @@ class CssBuilder<T extends Properties> {
1398
1406
  * \`when(\":hover\")\` — same semantics as \`onHover\`
1399
1407
  * \`when(\":hover:not(:disabled)\")\` — hover only while enabled
1400
1408
  */
1401
- when(selector: string): CssBuilder<T>;
1409
+ when(selector: string): CssBuilder<T, S>;
1402
1410
  /**
1403
1411
  * Styles after this \`when\` are applied based on a marker relationship + pseudo selector.
1404
1412
  *
1405
1413
  * \`when(marker, "ancestor", ":hover")\` — react to marker ancestor hover
1406
1414
  * \`when(row, "descendant", ":focus")\` — react to a marked descendant focus
1407
1415
  */
1408
- when(marker: Marker, relationship: "ancestor" | "descendant" | "anySibling" | "siblingBefore" | "siblingAfter", pseudo: string): CssBuilder<T>;
1416
+ when(marker: Marker, relationship: "ancestor" | "descendant" | "anySibling" | "siblingBefore" | "siblingAfter", pseudo: string): CssBuilder<T, S>;
1409
1417
  /**
1410
1418
  * Apply different styles for each selector in the object.
1411
1419
  *
1412
1420
  * \`when({ ":hover": Css.blue.$, ":focus": Css.red.$ })\`
1413
1421
  */
1414
- when<W extends Record<string, Properties>>(selectors: W): CssBuilder<T & UnionToIntersection<W[keyof W]>>;
1422
+ when<W extends Record<string, Properties>>(selectors: W): CssBuilder<T & UnionToIntersection<W[keyof W]>, S>;
1415
1423
  when(
1416
1424
  _selectorOrMarker: string | Marker | Record<string, Properties>,
1417
1425
  _relationship?: string,
1418
1426
  _pseudo?: string,
1419
- ): CssBuilder<T> {
1427
+ ): CssBuilder<T, S> {
1420
1428
  return this.unsupportedRuntime("when() cannot be used in RuntimeStyle css expressions.");
1421
1429
  }
1422
1430
 
@@ -1425,24 +1433,24 @@ class CssBuilder<T extends Properties> {
1425
1433
  }
1426
1434
 
1427
1435
  /** Apply styles within a pseudo-element (e.g. \`"::placeholder"\`, \`"::selection"\`). */
1428
- element(_pseudoElement: string): CssBuilder<T> {
1436
+ element(_pseudoElement: string): CssBuilder<T, S> {
1429
1437
  return this.unsupportedRuntime("element() cannot be used in RuntimeStyle css expressions.");
1430
1438
  }
1431
1439
 
1432
1440
  ${breakpointIfs}
1433
1441
 
1434
1442
  /** Conditionally apply styles when \`cond\` is true. */
1435
- if(cond: boolean): CssBuilder<T>;
1443
+ if(cond: boolean): CssBuilder<T, S>;
1436
1444
  /** Apply styles within a media query (e.g. \`Breakpoints.sm\` or a raw \`@media\` string). */
1437
- if(mediaQuery: string): CssBuilder<T>;
1438
- if(condOrMediaQuery: boolean | string): CssBuilder<T> {
1445
+ if(mediaQuery: string): CssBuilder<T, S>;
1446
+ if(condOrMediaQuery: boolean | string): CssBuilder<T, S> {
1439
1447
  if (typeof condOrMediaQuery === "boolean") {
1440
- return new CssBuilder({ ...this.opts, enabled: condOrMediaQuery, elseApplied: false });
1448
+ return new CssBuilder({ ...this.opts, enabled: condOrMediaQuery, elseApplied: false }) as CssBuilder<T, S>;
1441
1449
  }
1442
1450
  return this.unsupportedRuntime("if(mediaQuery) cannot be used in RuntimeStyle css expressions.");
1443
1451
  }
1444
1452
 
1445
- get else(): CssBuilder<T> {
1453
+ get else(): CssBuilder<T, S> {
1446
1454
  if (this.selector !== undefined) {
1447
1455
  if (this.opts.elseApplied) {
1448
1456
  throw new Error("else was already called");
@@ -1452,18 +1460,18 @@ class CssBuilder<T extends Properties> {
1452
1460
  if (this.opts.elseApplied) {
1453
1461
  throw new Error("else was already called");
1454
1462
  }
1455
- return new CssBuilder({ ...this.opts, enabled: !this.enabled, elseApplied: true });
1463
+ return new CssBuilder({ ...this.opts, enabled: !this.enabled, elseApplied: true }) as CssBuilder<T, S>;
1456
1464
  }
1457
1465
 
1458
1466
  /** Reset active conditional modifiers for subsequent styles. */
1459
- get end(): CssBuilder<T> {
1467
+ get end(): CssBuilder<T, S> {
1460
1468
  return this.newCss({ selector: undefined, elseApplied: false });
1461
1469
  }
1462
1470
 
1463
1471
  /** Add real CSS property/value pairs, either as add("prop", value) or add({ prop: value, ... }). */
1464
- add<P extends Properties>(props: P): CssBuilder<T & P>;
1465
- add<K extends keyof Properties>(prop: K, value: Properties[K]): CssBuilder<T & { [U in K]: Properties[K] }>;
1466
- add<K extends keyof Properties>(propOrStyles: K | Properties, value?: Properties[K]): CssBuilder<any> {
1472
+ add<P extends Properties>(props: P): CssBuilder<T & P, S>;
1473
+ add<K extends keyof Properties>(prop: K, value: Properties[K]): CssBuilder<T & { [U in K]: Properties[K] }, S>;
1474
+ add<K extends keyof Properties>(propOrStyles: K | Properties, value?: Properties[K]): CssBuilder<any, S> {
1467
1475
  if (!this.enabled) return this;
1468
1476
 
1469
1477
  const newRules = typeof propOrStyles === "string" ? { [propOrStyles]: value } : propOrStyles;
@@ -1477,8 +1485,8 @@ class CssBuilder<T extends Properties> {
1477
1485
  }
1478
1486
 
1479
1487
  /** Compose an existing Css expression or partial style hash into this builder, skipping undefined values. */
1480
- with<P extends Properties>(cssProp: P): CssBuilder<T & P>;
1481
- with(cssProp: Properties): CssBuilder<any> {
1488
+ with<P extends Properties>(cssProp: P): CssBuilder<T & P, S>;
1489
+ with(cssProp: Properties): CssBuilder<any, S> {
1482
1490
  if (!this.enabled) return this;
1483
1491
  const { $css, ...rest } = cssProp as any;
1484
1492
  const filtered = omitUndefinedValues(rest);
@@ -1490,13 +1498,13 @@ class CssBuilder<T extends Properties> {
1490
1498
 
1491
1499
 
1492
1500
  /** Marker for the build-time transform to append a raw className. */
1493
- className(className: string | undefined): CssBuilder<T> {
1501
+ className(className: string | undefined): CssBuilder<T, S> {
1494
1502
  void className;
1495
1503
  return this.unsupportedRuntime("className() cannot be used in RuntimeStyle css expressions.");
1496
1504
  }
1497
1505
 
1498
1506
  /** Marker for the build-time transform to append raw inline styles. */
1499
- style(inlineStyle: InlineStyle): CssBuilder<T> {
1507
+ style(inlineStyle: InlineStyle): CssBuilder<T, S> {
1500
1508
  void inlineStyle;
1501
1509
  return this.unsupportedRuntime("style() cannot be used in RuntimeStyle css expressions.");
1502
1510
  }
@@ -1520,11 +1528,11 @@ class CssBuilder<T extends Properties> {
1520
1528
  private get selector(): string | undefined {
1521
1529
  return this.opts.selector;
1522
1530
  }
1523
- private unsupportedRuntime(message: string): CssBuilder<T> {
1531
+ private unsupportedRuntime(message: string): CssBuilder<T, S> {
1524
1532
  return this.newCss({ runtimeError: message });
1525
1533
  }
1526
- private newCss(opts: Partial<Opts<T>>): CssBuilder<T> {
1527
- return new CssBuilder({ ...this.opts, ...opts });
1534
+ private newCss(opts: Partial<Opts<T>>): CssBuilder<T, S> {
1535
+ return new CssBuilder({ ...this.opts, ...opts }) as CssBuilder<T, S>;
1528
1536
  }
1529
1537
  }
1530
1538
 
@@ -1562,8 +1570,17 @@ export type Xss<P extends keyof Properties> = Pick<Properties, P>;
1562
1570
  /** The shared marker token for \`when(marker, relationship, pseudo)\`. */
1563
1571
  export const marker: Marker = Symbol.for("truss-default-marker");
1564
1572
 
1565
- /** An entry point for Css expressions. CssBuilder is immutable so this is safe to share. */
1566
- export const Css = new CssBuilder({
1573
+ /** An entry point for build-time Css expressions. Use with \`css=\` props. */
1574
+ export const Css = new CssBuilder<{}, "buildtime">({
1575
+ rules: {},
1576
+ enabled: true,
1577
+ selector: undefined,
1578
+ elseApplied: false,
1579
+ runtimeError: undefined,
1580
+ });
1581
+
1582
+ /** An entry point for runtime Css expressions. Use with \`useRuntimeStyle\`. */
1583
+ export const ${def("RuntimeCss")} = new CssBuilder<{}, "runtime">({
1567
1584
  rules: {},
1568
1585
  enabled: true,
1569
1586
  selector: undefined,
@@ -1571,6 +1588,11 @@ export const Css = new CssBuilder({
1571
1588
  runtimeError: undefined,
1572
1589
  });
1573
1590
 
1591
+ /** Hook that injects dynamic CSS at runtime. Only accepts \`RuntimeCss.*.$\` expressions. */
1592
+ export function ${def("useRuntimeStyle")}(css: Record<string, RuntimeStyles | string>): void {
1593
+ _useRuntimeStyle(css as any);
1594
+ }
1595
+
1574
1596
  ${typeAliasCode}
1575
1597
 
1576
1598
  ${breakpointCode}