@runtypelabs/ink-components 0.3.0 → 0.3.1

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.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as react from 'react';
2
3
  import { ComponentProps, ReactNode } from 'react';
3
4
  import InkSpinner from 'ink-spinner';
4
5
 
@@ -30,7 +31,7 @@ interface StreamOutputProps {
30
31
  * Uses the module-level `marked` + `marked-terminal` configuration.
31
32
  */
32
33
  declare function renderMarkdownToTerminal(content: string): string;
33
- declare function StreamOutput({ content, isStreaming, enableMarkdown, maxVisibleLines, scrollOffset, }: StreamOutputProps): react_jsx_runtime.JSX.Element;
34
+ declare const StreamOutput: react.NamedExoticComponent<StreamOutputProps>;
34
35
 
35
36
  interface ErrorDisplayProps {
36
37
  error: Error | string;
package/dist/index.js CHANGED
@@ -73,7 +73,7 @@ function StatusBar({ left, center, right }) {
73
73
  }
74
74
 
75
75
  // src/components/StreamOutput.tsx
76
- import { useMemo } from "react";
76
+ import { useMemo, memo } from "react";
77
77
  import { Box as Box3, Text as Text3 } from "ink";
78
78
  import chalk from "chalk";
79
79
  import InkSpinner2 from "ink-spinner";
@@ -160,7 +160,7 @@ function renderMarkdownToTerminal(content) {
160
160
  if (!stripped) return "";
161
161
  return marked.parse(stripped).trimEnd();
162
162
  }
163
- function StreamOutput({
163
+ var StreamOutput = memo(function StreamOutput2({
164
164
  content,
165
165
  isStreaming,
166
166
  enableMarkdown = true,
@@ -175,20 +175,20 @@ function StreamOutput({
175
175
  }
176
176
  return stripped;
177
177
  }, [content, enableMarkdown]);
178
+ const lines = useMemo(() => rendered.split("\n"), [rendered]);
178
179
  const visible = useMemo(() => {
179
180
  if (!maxVisibleLines) return rendered;
180
- const lines = rendered.split("\n");
181
181
  const totalLines = lines.length;
182
182
  const clampedOffset = Math.min(scrollOffset, Math.max(0, totalLines - maxVisibleLines));
183
183
  const end = totalLines - clampedOffset;
184
184
  const start = Math.max(0, end - maxVisibleLines);
185
185
  return lines.slice(start, end).join("\n");
186
- }, [rendered, maxVisibleLines, scrollOffset]);
186
+ }, [rendered, lines, maxVisibleLines, scrollOffset]);
187
187
  return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
188
188
  visible && /* @__PURE__ */ jsx3(Text3, { color: theme.text, children: visible }),
189
189
  isStreaming && /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsx3(Text3, { color: theme.textMuted, children: /* @__PURE__ */ jsx3(InkSpinner2, { type: "dots" }) }) })
190
190
  ] });
191
- }
191
+ });
192
192
 
193
193
  // src/components/ErrorDisplay.tsx
194
194
  import { Box as Box4, Text as Text4 } from "ink";
@@ -217,4 +217,3 @@ export {
217
217
  renderMarkdownToTerminal,
218
218
  theme
219
219
  };
220
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/ink-components",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Shared Ink (React for CLI) components for the Runtype CLI — spinners, status bars, streaming output, and error displays.",
5
5
  "license": "MIT",
6
6
  "author": "Runtype Labs",
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Spinner.tsx","../src/theme.ts","../src/components/StatusBar.tsx","../src/components/StreamOutput.tsx","../src/components/ErrorDisplay.tsx"],"sourcesContent":["import type { ComponentProps } from 'react'\nimport { Box, Text } from 'ink'\nimport InkSpinner from 'ink-spinner'\nimport { theme } from '../theme.js'\n\ntype InkSpinnerType = ComponentProps<typeof InkSpinner>['type']\n\nexport interface SpinnerProps {\n label?: string\n color?: string\n type?: InkSpinnerType\n}\n\nexport function Spinner({\n label = 'Loading...',\n color = theme.spinner,\n type = 'dots',\n}: SpinnerProps) {\n return (\n <Box>\n <Text color={color}>\n <InkSpinner type={type} />\n </Text>\n <Text color={theme.textMuted}> {label}</Text>\n </Box>\n )\n}\n","export const theme = {\n backgroundDeep: '#000000',\n background: '#1b212b',\n surface: '#202733',\n surfaceMuted: '#1d2430',\n surfaceElevated: '#252d3b',\n text: '#d8d3c9',\n textMuted: '#918b84',\n textSubtle: '#66625d',\n accent: '#8fc4bf',\n accentActive: '#a7d8d2',\n success: '#8ecb73',\n warning: '#d8ae63',\n danger: '#c97b73',\n border: '#394252',\n borderActive: '#546077',\n error: '#c97b73',\n info: '#8fc4bf',\n muted: '#918b84',\n primary: '#8fc4bf',\n secondary: '#a7d8d2',\n spinner: '#8fc4bf',\n progress: '#8fc4bf',\n label: '#d8d3c9',\n dimLabel: '#66625d',\n highlight: 'bold',\n separator: ' · ',\n sectionGap: 1,\n panelPaddingX: 1,\n panelPaddingY: 0,\n} as const\n\nexport type Theme = typeof theme\n","import type { ReactNode } from 'react'\nimport { Box, Text } from 'ink'\nimport { theme } from '../theme.js'\n\nexport interface StatusBarProps {\n left?: ReactNode\n center?: string\n right?: string\n}\n\nexport function StatusBar({ left, center, right }: StatusBarProps) {\n return (\n <Box\n borderStyle=\"single\"\n borderColor={theme.border}\n backgroundColor={theme.background}\n paddingX={theme.panelPaddingX}\n paddingY={theme.panelPaddingY}\n >\n <Box flexGrow={1}>\n {typeof left === 'string' ? (\n <Text color={theme.textMuted}>{left}</Text>\n ) : (\n left\n )}\n </Box>\n {center && (\n <Box flexGrow={1} justifyContent=\"center\">\n <Text color={theme.accent}>{center}</Text>\n </Box>\n )}\n {right && (\n <Box>\n <Text color={theme.textSubtle}>{right}</Text>\n </Box>\n )}\n </Box>\n )\n}\n","import { useMemo } from 'react'\nimport { Box, Text } from 'ink'\nimport chalk from 'chalk'\nimport InkSpinner from 'ink-spinner'\nimport { type MarkedExtension, marked } from 'marked'\n// @ts-expect-error marked-terminal has no type declarations\nimport { markedTerminal } from 'marked-terminal'\nimport stripAnsi from 'strip-ansi'\nimport { theme } from '../theme.js'\n\nexport interface StreamOutputProps {\n content: string\n isStreaming: boolean\n enableMarkdown?: boolean\n maxVisibleLines?: number\n /** Lines to scroll up from the bottom (0 = follow latest) */\n scrollOffset?: number\n}\n\nconst bodyText = chalk.hex(theme.text)\nconst mutedText = chalk.hex(theme.textMuted)\nconst subtleText = chalk.hex(theme.textSubtle)\nconst accentText = chalk.hex(theme.accent)\nconst accentActiveText = chalk.hex(theme.accentActive)\nconst successText = chalk.hex(theme.success)\nconst warningText = chalk.hex(theme.warning)\nconst dangerText = chalk.hex(theme.danger)\n\nconst markdownHighlightTheme = {\n default: bodyText,\n keyword: accentText,\n built_in: accentActiveText,\n type: accentActiveText,\n literal: accentText,\n number: successText,\n regexp: warningText,\n string: bodyText,\n subst: accentText,\n symbol: bodyText,\n class: accentActiveText,\n function: accentActiveText,\n title: accentActiveText,\n params: mutedText,\n comment: subtleText,\n doctag: subtleText,\n meta: subtleText,\n 'meta-keyword': accentText,\n 'meta-string': mutedText,\n section: accentText,\n tag: accentText,\n name: accentActiveText,\n 'builtin-name': accentActiveText,\n attr: accentText,\n attribute: accentText,\n variable: accentActiveText,\n bullet: mutedText,\n code: successText,\n emphasis: accentText,\n strong: accentActiveText,\n formula: accentText,\n link: accentActiveText,\n quote: mutedText,\n addition: successText,\n deletion: dangerText,\n} as const\n\n// Configure marked with terminal renderer once at module level.\nmarked.use(\n markedTerminal(\n {\n code: successText,\n blockquote: mutedText,\n html: subtleText,\n heading: accentText,\n firstHeading: accentActiveText.bold,\n hr: subtleText,\n listitem: bodyText,\n list: (body: string) => bodyText(body),\n table: mutedText,\n paragraph: bodyText,\n strong: accentActiveText.bold,\n em: accentText.italic,\n codespan: successText,\n del: subtleText.strikethrough,\n link: accentActiveText,\n href: mutedText.underline,\n text: bodyText,\n showSectionPrefix: false,\n reflowText: false,\n },\n {\n ignoreIllegals: true,\n theme: markdownHighlightTheme,\n }\n ) as MarkedExtension\n)\n\n/**\n * Render raw markdown content to terminal-styled text with ANSI color codes.\n * Uses the module-level `marked` + `marked-terminal` configuration.\n */\nexport function renderMarkdownToTerminal(content: string): string {\n const stripped = stripAnsi(content)\n if (!stripped) return ''\n return (marked.parse(stripped) as string).trimEnd()\n}\n\nexport function StreamOutput({\n content,\n isStreaming,\n enableMarkdown = true,\n maxVisibleLines,\n scrollOffset = 0,\n}: StreamOutputProps) {\n const rendered = useMemo(() => {\n // Strip incoming ANSI codes, then re-render via marked-terminal if enabled\n const stripped = stripAnsi(content)\n if (!stripped) return ''\n if (enableMarkdown) {\n return (marked.parse(stripped) as string).trimEnd()\n }\n return stripped\n }, [content, enableMarkdown])\n\n // Window to N lines with optional scroll offset from bottom\n const visible = useMemo(() => {\n if (!maxVisibleLines) return rendered\n const lines = rendered.split('\\n')\n const totalLines = lines.length\n const clampedOffset = Math.min(scrollOffset, Math.max(0, totalLines - maxVisibleLines))\n const end = totalLines - clampedOffset\n const start = Math.max(0, end - maxVisibleLines)\n return lines.slice(start, end).join('\\n')\n }, [rendered, maxVisibleLines, scrollOffset])\n\n return (\n <Box flexDirection=\"column\">\n {visible && <Text color={theme.text}>{visible}</Text>}\n {isStreaming && (\n <Box>\n <Text color={theme.textMuted}>\n <InkSpinner type=\"dots\" />\n </Text>\n </Box>\n )}\n </Box>\n )\n}\n","import { Box, Text } from 'ink'\nimport { theme } from '../theme.js'\n\nexport interface ErrorDisplayProps {\n error: Error | string\n context?: string\n}\n\nexport function ErrorDisplay({ error, context }: ErrorDisplayProps) {\n const message = error instanceof Error ? error.message : error\n const cause =\n error instanceof Error && error.cause ? String(error.cause) : undefined\n\n return (\n <Box flexDirection=\"column\" marginTop={theme.sectionGap}>\n <Text color={theme.danger} bold>\n Error{context ? ` ${context}` : ''}: {message}\n </Text>\n {cause && <Text color={theme.textMuted}>Cause: {cause}</Text>}\n </Box>\n )\n}\n"],"mappings":"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","names":["Box","Text","jsx","jsxs","Box","Text","Box","Text","InkSpinner","jsx","jsxs","Box","Text","InkSpinner","Box","Text","jsxs","Box","Text"]}