@homebound/truss 2.19.3 → 2.20.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.
@@ -6,6 +6,23 @@ import { createHash } from "crypto";
6
6
  // src/plugin/emit-truss.ts
7
7
  import * as t from "@babel/types";
8
8
 
9
+ // src/plugin/types.ts
10
+ var _longhandCache = /* @__PURE__ */ new WeakMap();
11
+ function getLonghandLookup(mapping) {
12
+ let lookup = _longhandCache.get(mapping);
13
+ if (lookup) return lookup;
14
+ lookup = /* @__PURE__ */ new Map();
15
+ for (const [abbr, entry] of Object.entries(mapping.abbreviations)) {
16
+ if (entry.kind !== "static") continue;
17
+ const keys = Object.keys(entry.defs);
18
+ if (keys.length !== 1) continue;
19
+ const key = `${keys[0]}\0${entry.defs[keys[0]]}`;
20
+ if (!lookup.has(key)) lookup.set(key, abbr);
21
+ }
22
+ _longhandCache.set(mapping, lookup);
23
+ return lookup;
24
+ }
25
+
9
26
  // src/plugin/property-priorities.ts
10
27
  var longHandPhysical = /* @__PURE__ */ new Set();
11
28
  var longHandLogical = /* @__PURE__ */ new Set();
@@ -1067,30 +1084,6 @@ function cleanValueForClassName(value) {
1067
1084
  function getPropertyAbbreviation(cssProp) {
1068
1085
  return cssPropertyAbbreviations[cssProp] ?? cssProp;
1069
1086
  }
1070
- function buildLonghandLookup(mapping) {
1071
- const lookup = /* @__PURE__ */ new Map();
1072
- for (const [abbrev, entry] of Object.entries(mapping.abbreviations)) {
1073
- if (entry.kind !== "static") continue;
1074
- const props = Object.keys(entry.defs);
1075
- if (props.length !== 1) continue;
1076
- const prop = props[0];
1077
- const value = String(entry.defs[prop]);
1078
- const key = `${prop}\0${value}`;
1079
- if (!lookup.has(key)) {
1080
- lookup.set(key, abbrev);
1081
- }
1082
- }
1083
- return lookup;
1084
- }
1085
- var cachedMapping = null;
1086
- var cachedLookup = null;
1087
- function getLonghandLookup(mapping) {
1088
- if (cachedMapping !== mapping) {
1089
- cachedMapping = mapping;
1090
- cachedLookup = buildLonghandLookup(mapping);
1091
- }
1092
- return cachedLookup;
1093
- }
1094
1087
  function computeStaticBaseName(seg, cssProp, cssValue, isMultiProp, mapping) {
1095
1088
  const abbr = seg.abbr;
1096
1089
  if (seg.argResolved !== void 0) {
@@ -2036,10 +2029,9 @@ function resolveChain(ctx, chain) {
2036
2029
  context.mediaQuery = containerSelectorFromCall(node);
2037
2030
  continue;
2038
2031
  }
2039
- if (abbr === "add" || abbr === "addCss") {
2040
- const seg = resolveAddCall(
2032
+ if (abbr === "with") {
2033
+ const seg = resolveWithCall(
2041
2034
  node,
2042
- mapping,
2043
2035
  context.mediaQuery,
2044
2036
  context.pseudoClass,
2045
2037
  context.pseudoElement,
@@ -2048,6 +2040,18 @@ function resolveChain(ctx, chain) {
2048
2040
  segments.push(seg);
2049
2041
  continue;
2050
2042
  }
2043
+ if (abbr === "add") {
2044
+ const segs = resolveAddCall(
2045
+ node,
2046
+ mapping,
2047
+ context.mediaQuery,
2048
+ context.pseudoClass,
2049
+ context.pseudoElement,
2050
+ context.whenPseudo
2051
+ );
2052
+ segments.push(...segs);
2053
+ continue;
2054
+ }
2051
2055
  if (abbr === "className") {
2052
2056
  const seg = resolveClassNameCall(
2053
2057
  node,
@@ -2364,18 +2368,15 @@ function resolveStyleCall(node, mediaQuery, pseudoClass, pseudoElement, whenPseu
2364
2368
  styleArg: arg
2365
2369
  };
2366
2370
  }
2367
- function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
2368
- const isAddCss = node.name === "addCss";
2369
- if (isAddCss) {
2370
- if (node.args.length !== 1) {
2371
- throw new UnsupportedPatternError(
2372
- `addCss() requires exactly 1 argument (an existing CssProp/style hash expression)`
2373
- );
2374
- }
2375
- const styleArg = node.args[0];
2376
- if (styleArg.type === "SpreadElement") {
2377
- throw new UnsupportedPatternError(`addCss() does not support spread arguments`);
2378
- }
2371
+ function resolveWithCall(node, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
2372
+ if (node.args.length !== 1) {
2373
+ throw new UnsupportedPatternError(`with() requires exactly 1 argument`);
2374
+ }
2375
+ const styleArg = node.args[0];
2376
+ if (styleArg.type === "SpreadElement") {
2377
+ throw new UnsupportedPatternError(`with() does not support spread arguments`);
2378
+ }
2379
+ if (styleArg.type === "ObjectExpression") {
2379
2380
  return {
2380
2381
  abbr: "__composed_css_prop",
2381
2382
  defs: {},
@@ -2383,25 +2384,34 @@ function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, w
2383
2384
  isAddCss: true
2384
2385
  };
2385
2386
  }
2387
+ return {
2388
+ abbr: "__composed_css_prop",
2389
+ defs: {},
2390
+ styleArrayArg: styleArg
2391
+ };
2392
+ }
2393
+ function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
2394
+ const context = {
2395
+ mediaQuery,
2396
+ pseudoClass,
2397
+ pseudoElement,
2398
+ whenPseudo
2399
+ };
2386
2400
  if (node.args.length === 1) {
2387
2401
  const styleArg = node.args[0];
2388
2402
  if (styleArg.type === "SpreadElement") {
2389
2403
  throw new UnsupportedPatternError(`add() does not support spread arguments`);
2390
2404
  }
2391
2405
  if (styleArg.type === "ObjectExpression") {
2392
- throw new UnsupportedPatternError(
2393
- `add(cssProp) does not accept object literals -- pass an existing CssProp expression instead`
2394
- );
2406
+ return resolveAddObjectLiteral(styleArg, mapping, context);
2395
2407
  }
2396
- return {
2397
- abbr: "__composed_css_prop",
2398
- defs: {},
2399
- styleArrayArg: styleArg
2400
- };
2408
+ throw new UnsupportedPatternError(
2409
+ `add() requires 1 or 2 arguments (property name and value, or an object literal), got ${node.args.length}. Supported overloads are add({ prop: value }), add("propName", value), and with(cssProp)`
2410
+ );
2401
2411
  }
2402
2412
  if (node.args.length !== 2) {
2403
2413
  throw new UnsupportedPatternError(
2404
- `add() requires exactly 2 arguments (property name and value), got ${node.args.length}. Supported overloads are add(cssProp), addCss(cssProp), and add("propName", value)`
2414
+ `add() requires 1 or 2 arguments (property name and value, or an object literal), got ${node.args.length}. Supported overloads are add({ prop: value }), add("propName", value), and with(cssProp)`
2405
2415
  );
2406
2416
  }
2407
2417
  const propArg = node.args[0];
@@ -2411,19 +2421,13 @@ function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, w
2411
2421
  const propName = propArg.value;
2412
2422
  const valueArg = node.args[1];
2413
2423
  const literalValue = tryEvaluateAddLiteral(valueArg);
2414
- const context = {
2415
- mediaQuery,
2416
- pseudoClass,
2417
- pseudoElement,
2418
- whenPseudo
2419
- };
2420
2424
  if (literalValue !== null) {
2421
- return segmentWithConditionContext(
2425
+ return [segmentWithConditionContext(
2422
2426
  { abbr: propName, defs: { [propName]: literalValue }, argResolved: literalValue },
2423
2427
  context
2424
- );
2428
+ )];
2425
2429
  }
2426
- return segmentWithConditionContext(
2430
+ return [segmentWithConditionContext(
2427
2431
  {
2428
2432
  abbr: propName,
2429
2433
  defs: {},
@@ -2432,7 +2436,52 @@ function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, w
2432
2436
  argNode: valueArg
2433
2437
  },
2434
2438
  context
2435
- );
2439
+ )];
2440
+ }
2441
+ function resolveAddObjectLiteral(obj, mapping, context) {
2442
+ const segments = [];
2443
+ for (const property of obj.properties) {
2444
+ if (property.type === "SpreadElement") {
2445
+ throw new UnsupportedPatternError(`add({...}) does not support spread properties -- use with() instead`);
2446
+ }
2447
+ if (property.type !== "ObjectProperty" || property.computed) {
2448
+ throw new UnsupportedPatternError(`add({...}) only supports simple property keys`);
2449
+ }
2450
+ let propName;
2451
+ if (property.key.type === "Identifier") {
2452
+ propName = property.key.name;
2453
+ } else if (property.key.type === "StringLiteral") {
2454
+ propName = property.key.value;
2455
+ } else {
2456
+ throw new UnsupportedPatternError(`add({...}) property keys must be identifiers or string literals`);
2457
+ }
2458
+ const valueNode = property.value;
2459
+ const literalValue = tryEvaluateAddLiteral(valueNode);
2460
+ if (literalValue !== null) {
2461
+ const canonicalAbbr = findCanonicalAbbreviation(mapping, propName, literalValue);
2462
+ if (canonicalAbbr) {
2463
+ const entry = mapping.abbreviations[canonicalAbbr];
2464
+ segments.push(segmentWithConditionContext(
2465
+ { abbr: canonicalAbbr, defs: entry.defs },
2466
+ context
2467
+ ));
2468
+ } else {
2469
+ segments.push(segmentWithConditionContext(
2470
+ { abbr: propName, defs: { [propName]: literalValue }, argResolved: literalValue },
2471
+ context
2472
+ ));
2473
+ }
2474
+ } else {
2475
+ segments.push(segmentWithConditionContext(
2476
+ { abbr: propName, defs: {}, variableProps: [propName], incremented: false, argNode: valueNode },
2477
+ context
2478
+ ));
2479
+ }
2480
+ }
2481
+ return segments;
2482
+ }
2483
+ function findCanonicalAbbreviation(mapping, prop, value) {
2484
+ return getLonghandLookup(mapping).get(`${prop}\0${value}`) ?? null;
2436
2485
  }
2437
2486
  function tryEvaluateAddLiteral(node) {
2438
2487
  if (node.type === "StringLiteral") {