Repository: motion-canvas/motion-canvas
File: packages/2d/src/components/Layout.ts (TypeScript)

Code before:
  public declare readonly rowGap: SimpleSignal<Length, this>;
  @initial(null)
  @signal()
  public declare readonly columnGap: SimpleSignal<Length, this>;

  @initial(null)
  @signal()
  public declare readonly fontFamily: SimpleSignal<string | null, this>;
  @signal()
  public declare readonly fontSize: SimpleSignal<number, this>;

  protected computeFontSize(): number {
    this.requestLayoutUpdate();
    return Number(this.styles.getPropertyValue('font-size').slice(0, -2));
  }

  @initial(null)
  @signal()
  public declare readonly fontStyle: SimpleSignal<string | null, this>;
  @initial(null)
  @signal()
  public declare readonly fontWeight: SimpleSignal<number | null, this>;
  @signal()
  public declare readonly lineHeight: SimpleSignal<number, this>;

  protected computeLineHeight(): number {
    this.requestLayoutUpdate();
    const styleHeight = Number(
      this.styles.getPropertyValue('line-height').slice(0, -2),
    );
    const minHeight = this.fontSize() * 1.2;
    return styleHeight < minHeight ? minHeight : styleHeight;
  }

  @initial(null)
  @signal()
  public declare readonly letterSpacing: SimpleSignal<number | null, this>;
  @initial(null)
  @signal()
  public declare readonly textWrap: SimpleSignal<TextWrap, this>;

  @cloneable(false)
  @inspectable(false)
  @signal()
  protected declare readonly customX: SimpleSignal<number, this>;
  protected getX(): number {
    if (this.isLayoutRoot()) {
      return this.customX();
    }

    return this.computedPosition().x;

Review comment (suggestion):
There's already a way to make the line height depend on the font size in CSS. I believe that's how we should do that, similarly to how `width` can have different units.

Code after:
  @signal()
  public declare readonly rowGap: SimpleSignal<Length, this>;
  @initial(null)
  @signal()
  public declare readonly columnGap: SimpleSignal<Length, this>;

  @defaultStyle('font-family')
  @signal()
  public declare readonly fontFamily: SimpleSignal<string, this>;
  @defaultStyle('font-size', parseFloat)
  @signal()
  public declare readonly fontSize: SimpleSignal<number, this>;
  @defaultStyle('font-style')
  @signal()
  public declare readonly fontStyle: SimpleSignal<string, this>;
  @defaultStyle('font-weight', parseInt)
  @signal()
  public declare readonly fontWeight: SimpleSignal<number, this>;
  @initial('120%')
  @signal()
  public declare readonly lineHeight: SimpleSignal<Length, this>;
  @defaultStyle('letter-spacing', i => {
    if (i === 'normal') {
      return 'normal';
    }
    return parseFloat(i);
  })
  @signal()
  public declare readonly letterSpacing: SimpleSignal<LetterSpacing, this>;

  @defaultStyle('white-space', i => {
    return i === 'pre' ? 'pre' : i === 'normal';
  })
  @signal()
  public declare readonly textWrap: SimpleSignal<TextWrap, this>;

  @cloneable(false)
  @inspectable(false)
  @signal()
  protected declare readonly customX: SimpleSignal<number, this>;
  protected getX(): number {
    if (this.isLayoutRoot()) {
      return this.customX();
    }

    return this.computedPosition().x;
  }
  protected setX(value: SignalValue<number>) {
    this.customX(value);
  }