{"version":3,"file":"rendering.mjs","names":[],"sources":["../../../../src/tui/workflow/rendering.ts"],"sourcesContent":["import { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nconst THOUSAND = 1000;\nconst MILLION = 1_000_000;\n/** Below this many tokens the \"k\" form keeps a decimal, above it rounds. */\nconst K_DECIMAL_LIMIT = 10_000;\n\n/** Compact token count, e.g. `812`, `4.2k`, `186k`, `1.3M`. */\nexport function formatTokens(value: number): string {\n  if (value < THOUSAND) return String(value);\n  if (value < MILLION) return `${(value / THOUSAND).toFixed(value < K_DECIMAL_LIMIT ? 1 : 0)}k`;\n  return `${(value / MILLION).toFixed(1)}M`;\n}\n\nexport function fitLine(text: string, width: number): string {\n  return truncateToWidth(text, Math.max(0, width), '');\n}\n\nexport function padLine(text: string, width: number): string {\n  const safeWidth = Math.max(0, width);\n  const fitted = fitLine(text, safeWidth);\n  return `${fitted}${' '.repeat(Math.max(0, safeWidth - visibleWidth(fitted)))}`;\n}\n\nexport function alignLine(left: string, right: string, width: number): string {\n  const safeWidth = Math.max(0, width);\n  const rightWidth = visibleWidth(right);\n  if (!right || rightWidth >= safeWidth) return fitLine(right || left, safeWidth);\n\n  const maxLeftWidth = Math.max(0, safeWidth - rightWidth - 1);\n  const fittedLeft = fitLine(left, maxLeftWidth);\n  const gap = ' '.repeat(Math.max(1, safeWidth - visibleWidth(fittedLeft) - rightWidth));\n  return fitLine(`${fittedLeft}${gap}${right}`, safeWidth);\n}\n\nexport function frameLine(content: string, width: number, left = '│', right = '│'): string {\n  const safeWidth = Math.max(0, width);\n  const frameWidth = visibleWidth(left) + visibleWidth(right);\n  if (safeWidth <= frameWidth) return fitLine(`${left}${right}`, safeWidth);\n  return `${left}${padLine(content, safeWidth - frameWidth)}${right}`;\n}\n\nexport function packSegments(segments: string[], width: number, separator = '  '): string[] {\n  const safeWidth = Math.max(0, width);\n  if (safeWidth === 0) return [];\n\n  const lines: string[] = [];\n  let current = '';\n  for (const segment of segments) {\n    const candidate = current ? `${current}${separator}${segment}` : segment;\n    if (visibleWidth(candidate) <= safeWidth) {\n      current = candidate;\n      continue;\n    }\n    if (current) lines.push(fitLine(current, safeWidth));\n    current = fitLine(segment, safeWidth);\n  }\n  if (current) lines.push(current);\n  return lines;\n}\n"],"mappings":";;AAcA,SAAgB,QAAQ,MAAc,OAAuB;CAC3D,OAAO,gBAAgB,MAAM,KAAK,IAAI,GAAG,KAAK,GAAG,EAAE;AACrD;AAEA,SAAgB,QAAQ,MAAc,OAAuB;CAC3D,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK;CACnC,MAAM,SAAS,QAAQ,MAAM,SAAS;CACtC,OAAO,GAAG,SAAS,IAAI,OAAO,KAAK,IAAI,GAAG,YAAY,aAAa,MAAM,CAAC,CAAC;AAC7E;AAaA,SAAgB,UAAU,SAAiB,OAAe,OAAO,KAAK,QAAQ,KAAa;CACzF,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK;CACnC,MAAM,aAAa,aAAa,IAAI,IAAI,aAAa,KAAK;CAC1D,IAAI,aAAa,YAAY,OAAO,QAAQ,GAAG,OAAO,SAAS,SAAS;CACxE,OAAO,GAAG,OAAO,QAAQ,SAAS,YAAY,UAAU,IAAI;AAC9D"}