@homebound/truss 2.0.13 → 2.1.0-next.10
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 +85 -33
- package/build/index.js.map +1 -1
- package/build/plugin/index.d.ts +11 -10
- package/build/plugin/index.js +1653 -1192
- package/build/plugin/index.js.map +1 -1
- package/build/runtime.d.ts +20 -10
- package/build/runtime.js +57 -41
- package/build/runtime.js.map +1 -1
- package/cli.js +5 -10
- package/package.json +7 -3
package/build/index.js
CHANGED
|
@@ -850,6 +850,7 @@ function makeBreakpoints(breakpoints) {
|
|
|
850
850
|
const r = {
|
|
851
851
|
print: "@media print"
|
|
852
852
|
};
|
|
853
|
+
const screenMedia = "@media screen and";
|
|
853
854
|
const bps = Object.keys(breakpoints);
|
|
854
855
|
Object.entries(breakpoints).forEach(([bp, px], i) => {
|
|
855
856
|
const isFirst = i === 0;
|
|
@@ -857,11 +858,11 @@ function makeBreakpoints(breakpoints) {
|
|
|
857
858
|
const min = !isFirst ? `${px}px` : "0";
|
|
858
859
|
const max = !isLast ? `${breakpoints[bps[i + 1]] - 1}px` : "0";
|
|
859
860
|
if (isFirst) {
|
|
860
|
-
r[bp] =
|
|
861
|
+
r[bp] = `${screenMedia} (max-width: ${max})`;
|
|
861
862
|
} else if (isLast) {
|
|
862
|
-
r[bp] =
|
|
863
|
+
r[bp] = `${screenMedia} (min-width: ${min})`;
|
|
863
864
|
} else {
|
|
864
|
-
r[bp] =
|
|
865
|
+
r[bp] = `${screenMedia} (min-width: ${min}) and (max-width: ${max})`;
|
|
865
866
|
}
|
|
866
867
|
if (!isFirst) {
|
|
867
868
|
const isSecond = i === 1;
|
|
@@ -875,11 +876,11 @@ function makeBreakpoints(breakpoints) {
|
|
|
875
876
|
if (!isLast) {
|
|
876
877
|
parts.push(`(max-width: ${max})`);
|
|
877
878
|
}
|
|
878
|
-
r[name] =
|
|
879
|
+
r[name] = `${screenMedia} ${parts.join(" and ")}`;
|
|
879
880
|
}
|
|
880
881
|
if (!isFirst && !isLast) {
|
|
881
|
-
r[`${bp}AndUp`] =
|
|
882
|
-
r[`${bp}AndDown`] =
|
|
882
|
+
r[`${bp}AndUp`] = `${screenMedia} (min-width: ${min})`;
|
|
883
|
+
r[`${bp}AndDown`] = `${screenMedia} (max-width: ${max})`;
|
|
883
884
|
}
|
|
884
885
|
});
|
|
885
886
|
return r;
|
|
@@ -1009,9 +1010,32 @@ type Opts<T> = {
|
|
|
1009
1010
|
rules: T,
|
|
1010
1011
|
enabled: boolean,
|
|
1011
1012
|
important: boolean,
|
|
1012
|
-
selector: string | undefined
|
|
1013
|
+
selector: string | undefined,
|
|
1014
|
+
elseApplied: boolean,
|
|
1013
1015
|
};
|
|
1014
1016
|
|
|
1017
|
+
function invertMediaQuery(query: string): string {
|
|
1018
|
+
const screenPrefix = "@media screen and ";
|
|
1019
|
+
if (query.startsWith(screenPrefix)) {
|
|
1020
|
+
const conditions = query.slice(screenPrefix.length).trim();
|
|
1021
|
+
const rangeMatch = conditions.match(/^\(min-width: (\d+)px\) and \(max-width: (\d+)px\)$/);
|
|
1022
|
+
if (rangeMatch) {
|
|
1023
|
+
const min = Number(rangeMatch[1]);
|
|
1024
|
+
const max = Number(rangeMatch[2]);
|
|
1025
|
+
return \`@media screen and (max-width: \${min - 1}px), screen and (min-width: \${max + 1}px)\`;
|
|
1026
|
+
}
|
|
1027
|
+
const minMatch = conditions.match(/^\(min-width: (\d+)px\)$/);
|
|
1028
|
+
if (minMatch) {
|
|
1029
|
+
return \`@media screen and (max-width: \${Number(minMatch[1]) - 1}px)\`;
|
|
1030
|
+
}
|
|
1031
|
+
const maxMatch = conditions.match(/^\(max-width: (\d+)px\)$/);
|
|
1032
|
+
if (maxMatch) {
|
|
1033
|
+
return \`@media screen and (min-width: \${Number(maxMatch[1]) + 1}px)\`;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
return query.replace("@media", "@media not");
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1015
1039
|
class CssBuilder<T extends Properties> {
|
|
1016
1040
|
constructor(private opts: Opts<T>) {}
|
|
1017
1041
|
|
|
@@ -1055,13 +1079,13 @@ class CssBuilder<T extends Properties> {
|
|
|
1055
1079
|
|
|
1056
1080
|
get else() {
|
|
1057
1081
|
if (this.selector !== undefined) {
|
|
1058
|
-
if (this.
|
|
1082
|
+
if (this.opts.elseApplied) {
|
|
1059
1083
|
throw new Error("else was already called");
|
|
1060
1084
|
} else {
|
|
1061
|
-
return this.newCss({ selector: this.selector
|
|
1085
|
+
return this.newCss({ selector: invertMediaQuery(this.selector), elseApplied: true });
|
|
1062
1086
|
}
|
|
1063
1087
|
}
|
|
1064
|
-
return this.newCss({ enabled: !this.enabled });
|
|
1088
|
+
return this.newCss({ enabled: !this.enabled, elseApplied: true });
|
|
1065
1089
|
}
|
|
1066
1090
|
|
|
1067
1091
|
get important() { return this.newCss({ important: true }); }
|
|
@@ -1091,10 +1115,6 @@ class CssBuilder<T extends Properties> {
|
|
|
1091
1115
|
return this.newCss({ rules: rules as any });
|
|
1092
1116
|
}
|
|
1093
1117
|
|
|
1094
|
-
/** Marker helper for legacy object-spread composition. */
|
|
1095
|
-
spread<P extends object>(props: P): P {
|
|
1096
|
-
return props;
|
|
1097
|
-
}
|
|
1098
1118
|
}
|
|
1099
1119
|
|
|
1100
1120
|
/** Sort keys so equivalent rule objects have deterministic shape. */
|
|
@@ -1142,7 +1162,7 @@ export enum Palette {
|
|
|
1142
1162
|
export type Xss<P extends keyof Properties> = Pick<Properties, P>;
|
|
1143
1163
|
|
|
1144
1164
|
/** An entry point for Css expressions. CssBuilder is immutable so this is safe to share. */
|
|
1145
|
-
export const Css = new CssBuilder({ rules: {}, enabled: true, important: false, selector: undefined });
|
|
1165
|
+
export const Css = new CssBuilder({ rules: {}, enabled: true, important: false, selector: undefined, elseApplied: false });
|
|
1146
1166
|
|
|
1147
1167
|
${typeAliasCode}
|
|
1148
1168
|
|
|
@@ -1205,9 +1225,8 @@ function generateStylexCssBuilder(config, sections) {
|
|
|
1205
1225
|
return code`
|
|
1206
1226
|
// This file is auto-generated by truss: https://github.com/homebound-team/truss.
|
|
1207
1227
|
// See your project's \`truss-config.ts\` to make configuration changes (fonts, increments, etc).
|
|
1208
|
-
// Target:
|
|
1228
|
+
// Target: native (build-time plugin)
|
|
1209
1229
|
|
|
1210
|
-
import * as stylex from "@stylexjs/stylex";
|
|
1211
1230
|
import { trussProps } from "@homebound/truss/runtime";
|
|
1212
1231
|
|
|
1213
1232
|
/** Given a type X, and the user's proposed type T, only allow keys in X and nothing else. */
|
|
@@ -1215,8 +1234,8 @@ export type Only<X, T> = X & Record<Exclude<keyof T, keyof X>, never>;
|
|
|
1215
1234
|
|
|
1216
1235
|
export type ${def("Properties")} = ${CssProperties}<string | 0, string>;
|
|
1217
1236
|
|
|
1218
|
-
/** A marker
|
|
1219
|
-
export type Marker =
|
|
1237
|
+
/** A marker token used with \`when\`/\`markerOf\` etc. */
|
|
1238
|
+
export type Marker = symbol;
|
|
1220
1239
|
|
|
1221
1240
|
${typographyType}
|
|
1222
1241
|
|
|
@@ -1234,6 +1253,7 @@ type Opts<T> = {
|
|
|
1234
1253
|
rules: T;
|
|
1235
1254
|
enabled: boolean;
|
|
1236
1255
|
selector: string | undefined;
|
|
1256
|
+
elseApplied: boolean;
|
|
1237
1257
|
};
|
|
1238
1258
|
|
|
1239
1259
|
class CssBuilder<T extends Properties> {
|
|
@@ -1266,11 +1286,16 @@ class CssBuilder<T extends Properties> {
|
|
|
1266
1286
|
return this;
|
|
1267
1287
|
}
|
|
1268
1288
|
|
|
1269
|
-
/** Marks this element with a user-defined marker
|
|
1289
|
+
/** Marks this element with a user-defined marker. */
|
|
1270
1290
|
markerOf(_marker: Marker): CssBuilder<T> {
|
|
1271
1291
|
return this;
|
|
1272
1292
|
}
|
|
1273
1293
|
|
|
1294
|
+
/** Creates a marker token for use with markerOf() and when(). */
|
|
1295
|
+
newMarker(): Marker {
|
|
1296
|
+
return Symbol("truss-marker");
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1274
1299
|
typography(key: Typography): CssBuilder<T> {
|
|
1275
1300
|
return (this as any)[key];
|
|
1276
1301
|
}
|
|
@@ -1310,13 +1335,22 @@ class CssBuilder<T extends Properties> {
|
|
|
1310
1335
|
if(mediaQuery: string): CssBuilder<T>;
|
|
1311
1336
|
if(condOrMediaQuery: boolean | string): CssBuilder<T> {
|
|
1312
1337
|
if (typeof condOrMediaQuery === "boolean") {
|
|
1313
|
-
return new CssBuilder({ ...this.opts, enabled: condOrMediaQuery });
|
|
1338
|
+
return new CssBuilder({ ...this.opts, enabled: condOrMediaQuery, elseApplied: false });
|
|
1314
1339
|
}
|
|
1315
|
-
return this.newCss({ selector: condOrMediaQuery });
|
|
1340
|
+
return this.newCss({ selector: condOrMediaQuery, elseApplied: false });
|
|
1316
1341
|
}
|
|
1317
1342
|
|
|
1318
1343
|
get else(): CssBuilder<T> {
|
|
1319
|
-
|
|
1344
|
+
if (this.selector !== undefined) {
|
|
1345
|
+
if (this.opts.elseApplied) {
|
|
1346
|
+
throw new Error("else was already called");
|
|
1347
|
+
}
|
|
1348
|
+
return this.newCss({ selector: invertMediaQuery(this.selector), elseApplied: true });
|
|
1349
|
+
}
|
|
1350
|
+
if (this.opts.elseApplied) {
|
|
1351
|
+
throw new Error("else was already called");
|
|
1352
|
+
}
|
|
1353
|
+
return new CssBuilder({ ...this.opts, enabled: !this.enabled, elseApplied: true });
|
|
1320
1354
|
}
|
|
1321
1355
|
|
|
1322
1356
|
add<P extends Properties>(props: P): CssBuilder<T & P>;
|
|
@@ -1331,14 +1365,9 @@ class CssBuilder<T extends Properties> {
|
|
|
1331
1365
|
return this.newCss({ rules: rules as any });
|
|
1332
1366
|
}
|
|
1333
1367
|
|
|
1334
|
-
/**
|
|
1335
|
-
spread<P extends object>(props: P): P {
|
|
1336
|
-
return props;
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
/** Convert a style array into \`{ className, style }\` props for manual spreading into non-\`css=\` contexts. */
|
|
1368
|
+
/** Convert a style hash into \`{ className, style }\` props for manual spreading into non-\`css=\` contexts. */
|
|
1340
1369
|
props(styles: Properties): Record<string, unknown> {
|
|
1341
|
-
return trussProps(
|
|
1370
|
+
return trussProps(styles as any);
|
|
1342
1371
|
}
|
|
1343
1372
|
|
|
1344
1373
|
private get rules(): T {
|
|
@@ -1380,12 +1409,35 @@ export enum Palette {
|
|
|
1380
1409
|
export type Xss<P extends keyof Properties> = Pick<Properties, P>;
|
|
1381
1410
|
|
|
1382
1411
|
/** An entry point for Css expressions. CssBuilder is immutable so this is safe to share. */
|
|
1383
|
-
export const Css = new CssBuilder({ rules: {}, enabled: true, selector: undefined });
|
|
1412
|
+
export const Css = new CssBuilder({ rules: {}, enabled: true, selector: undefined, elseApplied: false });
|
|
1384
1413
|
|
|
1385
1414
|
${typeAliasCode}
|
|
1386
1415
|
|
|
1387
1416
|
${breakpointCode}
|
|
1388
1417
|
|
|
1418
|
+
function invertMediaQuery(query: string): string {
|
|
1419
|
+
const screenPrefix = "@media screen and ";
|
|
1420
|
+
if (query.startsWith(screenPrefix)) {
|
|
1421
|
+
const conditions = query.slice(screenPrefix.length).trim();
|
|
1422
|
+
const rangeMatch = conditions.match(/^\(min-width: (\d+)px\) and \(max-width: (\d+)px\)$/);
|
|
1423
|
+
if (rangeMatch) {
|
|
1424
|
+
const min = Number(rangeMatch[1]);
|
|
1425
|
+
const max = Number(rangeMatch[2]);
|
|
1426
|
+
return \`@media screen and (max-width: \${min - 1}px), screen and (min-width: \${max + 1}px)\`;
|
|
1427
|
+
}
|
|
1428
|
+
const minMatch = conditions.match(/^\(min-width: (\d+)px\)$/);
|
|
1429
|
+
if (minMatch) {
|
|
1430
|
+
return \`@media screen and (max-width: \${Number(minMatch[1]) - 1}px)\`;
|
|
1431
|
+
}
|
|
1432
|
+
const maxMatch = conditions.match(/^\(max-width: (\d+)px\)$/);
|
|
1433
|
+
if (maxMatch) {
|
|
1434
|
+
return \`@media screen and (min-width: \${Number(maxMatch[1]) + 1}px)\`;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
return query.replace("@media", "@media not");
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
|
|
1389
1441
|
${extras || ""}
|
|
1390
1442
|
`;
|
|
1391
1443
|
}
|
|
@@ -1400,7 +1452,7 @@ function generateTrussMapping(config, entries) {
|
|
|
1400
1452
|
break;
|
|
1401
1453
|
case "param":
|
|
1402
1454
|
abbreviations[entry.abbr] = {
|
|
1403
|
-
kind: "
|
|
1455
|
+
kind: "variable",
|
|
1404
1456
|
props: entry.props || [],
|
|
1405
1457
|
incremented: false,
|
|
1406
1458
|
extraDefs: entry.extraDefs
|
|
@@ -1408,7 +1460,7 @@ function generateTrussMapping(config, entries) {
|
|
|
1408
1460
|
break;
|
|
1409
1461
|
case "increment-param":
|
|
1410
1462
|
abbreviations[entry.abbr] = {
|
|
1411
|
-
kind: "
|
|
1463
|
+
kind: "variable",
|
|
1412
1464
|
props: entry.props || [],
|
|
1413
1465
|
incremented: true,
|
|
1414
1466
|
extraDefs: entry.extraDefs
|