render method

  1. @override
String render()
override

Renders the component as a string.

Implementation

@override
String render() {
  final lines = _normalizeLines(content);
  final effectiveBorderStyle = renderConfig.configureStyle(
    borderStyle ?? Style().dim(),
  );
  final titleStyle = renderConfig.configureStyle(Style().bold());
  String border(String s) => effectiveBorderStyle.render(s);
  String titleFn(String s) => titleStyle.render(s);

  // Calculate width
  final contentWidth = lines
      .map((l) => Style.visibleLength(l))
      .fold<int>(0, (m, v) => v > m ? v : m);
  final titleWidth = title != null ? Style.visibleLength(title!) + 4 : 0;
  final minWidth = [
    contentWidth,
    titleWidth,
    10,
  ].reduce((a, b) => a > b ? a : b);
  // Ensure minBound doesn't exceed maxBound for clamp
  final minBound = minWidth + padding * 2 + 2;
  final maxBound = renderConfig.terminalWidth;
  final boxWidth = (width ?? minBound).clamp(
    minBound < maxBound ? minBound : maxBound,
    maxBound,
  );
  final innerWidth = boxWidth - 2;

  final buffer = StringBuffer();
  final pad = ' ' * padding;

  // Top border with optional title
  if (title != null) {
    final styledTitle = ' ${titleFn(title!)} ';
    final titleLen = Style.visibleLength(styledTitle);
    final remainingWidth = innerWidth - titleLen;

    String topLine;
    switch (titleAlign) {
      case PanelAlignment.left:
        final rightFill = chars.horizontal * (remainingWidth - 1);
        topLine =
            '${chars.topLeft}${chars.horizontal}$styledTitle$rightFill${chars.topRight}';
      case PanelAlignment.center:
        final leftFill = chars.horizontal * (remainingWidth ~/ 2);
        final rightFill =
            chars.horizontal * (remainingWidth - remainingWidth ~/ 2);
        topLine =
            '${chars.topLeft}$leftFill$styledTitle$rightFill${chars.topRight}';
      case PanelAlignment.right:
        final leftFill = chars.horizontal * (remainingWidth - 1);
        topLine =
            '${chars.topLeft}$leftFill$styledTitle${chars.horizontal}${chars.topRight}';
    }
    buffer.writeln(border(topLine));
  } else {
    buffer.writeln(
      border(
        '${chars.topLeft}${chars.horizontal * innerWidth}${chars.topRight}',
      ),
    );
  }

  // Content lines
  for (final line in lines) {
    final visible = Style.visibleLength(line);
    final available = innerWidth - padding * 2;
    final fill = available - visible;

    String paddedLine;
    switch (contentAlign) {
      case PanelAlignment.left:
        paddedLine = '$pad$line${' ' * (fill > 0 ? fill : 0)}$pad';
      case PanelAlignment.center:
        final leftPad = ' ' * (fill ~/ 2);
        final rightPad = ' ' * (fill - fill ~/ 2);
        paddedLine = '$pad$leftPad$line$rightPad$pad';
      case PanelAlignment.right:
        paddedLine = '$pad${' ' * (fill > 0 ? fill : 0)}$line$pad';
    }

    buffer.writeln(
      '${border(chars.vertical)}$paddedLine${border(chars.vertical)}',
    );
  }

  // Bottom border
  buffer.write(
    border(
      '${chars.bottomLeft}${chars.horizontal * innerWidth}${chars.bottomRight}',
    ),
  );

  return buffer.toString();
}