All files / packages/fds-uif/generator-lwc/src/blocks createClassGetter.ts

93.33% Statements 14/15
50% Branches 1/2
100% Functions 1/1
93.33% Lines 14/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79                                                    6x   6x 6x 5x     6x 6x 27x 27x 27x                     6x                   6x 6x         6x           6x                
import ts from 'typescript';
import type { ClassNameRule } from '@fds-uif/generator-base';
import { conditionToExpression } from '../utils/conditionToExpr.js';
 
/**
 * Build a getter accessor that returns the joined class string for a node.
 *
 * Output shape:
 * ```ts
 * get computedClass() {
 *   return [
 *     'slds-button',
 *     this.disabled && 'slds-button_disabled',
 *     this.variant === 'brand' && 'slds-button_brand',
 *   ].filter(Boolean).join(' ');
 * }
 * ```
 *
 * `propNames` lists the component prop identifiers that conditions reference;
 * any matching identifier in a `condition` is rewritten to `this.<name>`.
 */
export function createClassGetter(
  getterName: string,
  rules: ClassNameRule[],
  propNames: ReadonlySet<string>,
): ts.GetAccessorDeclaration {
  const elements: ts.Expression[] = [];
 
  for (const rule of rules) {
    for (const cls of rule.base) {
      elements.push(ts.factory.createStringLiteral(cls));
    }
  }
  for (const rule of rules) {
    for (const c of rule.conditional) {
      const condExpr = conditionToExpression(c.condition, propNames);
      const classes = c.classes.join(' ');
      elements.push(
        ts.factory.createBinaryExpression(
          condExpr,
          ts.SyntaxKind.AmpersandAmpersandToken,
          ts.factory.createStringLiteral(classes),
        ),
      );
    }
  }
 
  // Edge case: rules contained no entries at all -> emit empty string.
  Iif (elements.length === 0) {
    return ts.factory.createGetAccessorDeclaration(
      undefined,
      ts.factory.createIdentifier(getterName),
      [],
      undefined,
      ts.factory.createBlock([ts.factory.createReturnStatement(ts.factory.createStringLiteral(''))], true),
    );
  }
 
  const arr = ts.factory.createArrayLiteralExpression(elements, true);
  const filtered = ts.factory.createCallExpression(
    ts.factory.createPropertyAccessExpression(arr, 'filter'),
    undefined,
    [ts.factory.createIdentifier('Boolean')],
  );
  const joined = ts.factory.createCallExpression(
    ts.factory.createPropertyAccessExpression(filtered, 'join'),
    undefined,
    [ts.factory.createStringLiteral(' ')],
  );
 
  return ts.factory.createGetAccessorDeclaration(
    undefined,
    ts.factory.createIdentifier(getterName),
    [],
    undefined,
    ts.factory.createBlock([ts.factory.createReturnStatement(joined)], true),
  );
}