@uix-ai/stream 0.0.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.
@@ -0,0 +1,128 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ClassValue } from 'clsx';
3
+ export { Streamdown } from 'streamdown';
4
+
5
+ interface CodeBlockProps {
6
+ /**
7
+ * The code content to display
8
+ */
9
+ children: string;
10
+ /**
11
+ * Programming language for syntax highlighting
12
+ */
13
+ language?: string;
14
+ /**
15
+ * Show line numbers
16
+ */
17
+ showLineNumbers?: boolean;
18
+ /**
19
+ * Show copy button
20
+ */
21
+ showCopyButton?: boolean;
22
+ /**
23
+ * Additional CSS classes
24
+ */
25
+ className?: string;
26
+ }
27
+ /**
28
+ * CodeBlock Component
29
+ *
30
+ * Displays code with syntax highlighting and optional features like
31
+ * line numbers and copy button.
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * <CodeBlock language="typescript">
36
+ * const hello = "world"
37
+ * </CodeBlock>
38
+ * ```
39
+ */
40
+ declare function CodeBlock({ children, language, showLineNumbers, showCopyButton, className, }: CodeBlockProps): react_jsx_runtime.JSX.Element;
41
+
42
+ interface StreamMarkdownProps {
43
+ /**
44
+ * The markdown content to render
45
+ */
46
+ content: string;
47
+ /**
48
+ * Whether content is still streaming
49
+ * Note: Streamdown handles streaming automatically via Remend
50
+ */
51
+ isStreaming?: boolean;
52
+ /**
53
+ * Additional CSS classes
54
+ */
55
+ className?: string;
56
+ }
57
+ /**
58
+ * StreamMarkdown Component
59
+ *
60
+ * Renders markdown content with full streaming support.
61
+ * Powered by Vercel Streamdown for optimal AI streaming scenarios.
62
+ *
63
+ * Features:
64
+ * - GitHub Flavored Markdown (tables, task lists, strikethrough)
65
+ * - Syntax highlighted code blocks (Shiki)
66
+ * - LaTeX math equations (KaTeX)
67
+ * - Mermaid diagrams
68
+ * - Automatic self-healing for incomplete markdown (Remend)
69
+ * - Memoized rendering for performance
70
+ * - Security hardening (rehype-harden)
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * <StreamMarkdown
75
+ * content={streamingContent}
76
+ * isStreaming={true}
77
+ * />
78
+ * ```
79
+ */
80
+ declare function StreamMarkdown({ content, isStreaming, className, }: StreamMarkdownProps): react_jsx_runtime.JSX.Element;
81
+
82
+ interface StreamTextProps {
83
+ /**
84
+ * The text content to display
85
+ */
86
+ children: string;
87
+ /**
88
+ * Whether to show typing cursor
89
+ */
90
+ showCursor?: boolean;
91
+ /**
92
+ * Cursor style
93
+ */
94
+ cursorStyle?: 'block' | 'line' | 'underscore';
95
+ /**
96
+ * Additional CSS classes
97
+ */
98
+ className?: string;
99
+ }
100
+ /**
101
+ * StreamText Component
102
+ *
103
+ * Simple streaming text display with optional typing cursor.
104
+ * Use this for plain text streaming without markdown.
105
+ *
106
+ * @example
107
+ * ```tsx
108
+ * <StreamText showCursor={isStreaming}>
109
+ * {streamingText}
110
+ * </StreamText>
111
+ * ```
112
+ */
113
+ declare function StreamText({ children, showCursor, cursorStyle, className, }: StreamTextProps): react_jsx_runtime.JSX.Element;
114
+
115
+ /**
116
+ * Merge Tailwind CSS classes with clsx
117
+ */
118
+ declare function cn(...inputs: ClassValue[]): string;
119
+ /**
120
+ * Fix incomplete markdown for streaming scenarios
121
+ * Handles unclosed code blocks, bold, italic, etc.
122
+ *
123
+ * @deprecated Streamdown now handles this automatically via Remend.
124
+ * This function is kept for backward compatibility.
125
+ */
126
+ declare function healMarkdown(content: string): string;
127
+
128
+ export { CodeBlock, type CodeBlockProps, StreamMarkdown, type StreamMarkdownProps, StreamText, type StreamTextProps, cn, healMarkdown };
package/dist/index.js ADDED
@@ -0,0 +1,132 @@
1
+ // src/components/CodeBlock.tsx
2
+ import * as React from "react";
3
+
4
+ // src/utils.ts
5
+ import { clsx } from "clsx";
6
+ import { twMerge } from "tailwind-merge";
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ function healMarkdown(content) {
11
+ let result = content;
12
+ const codeBlockMatches = result.match(/```/g);
13
+ if (codeBlockMatches && codeBlockMatches.length % 2 !== 0) {
14
+ result += "\n```";
15
+ }
16
+ const inlineCodeMatches = result.match(/(?<!`)`(?!`)/g);
17
+ if (inlineCodeMatches && inlineCodeMatches.length % 2 !== 0) {
18
+ result += "`";
19
+ }
20
+ const boldMatches = result.match(/\*\*/g);
21
+ if (boldMatches && boldMatches.length % 2 !== 0) {
22
+ result += "**";
23
+ }
24
+ const italicMatches = result.match(/(?<!\*)\*(?!\*)/g);
25
+ if (italicMatches && italicMatches.length % 2 !== 0) {
26
+ result += "*";
27
+ }
28
+ return result;
29
+ }
30
+
31
+ // src/components/CodeBlock.tsx
32
+ import { jsx, jsxs } from "react/jsx-runtime";
33
+ function CodeBlock({
34
+ children,
35
+ language,
36
+ showLineNumbers = false,
37
+ showCopyButton = true,
38
+ className
39
+ }) {
40
+ const [copied, setCopied] = React.useState(false);
41
+ const handleCopy = async () => {
42
+ await navigator.clipboard.writeText(children);
43
+ setCopied(true);
44
+ setTimeout(() => setCopied(false), 2e3);
45
+ };
46
+ const lines = children.split("\n");
47
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative group rounded-lg overflow-hidden", className), children: [
48
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2 bg-gray-800 text-gray-400 text-xs", children: [
49
+ /* @__PURE__ */ jsx("span", { children: language || "text" }),
50
+ showCopyButton && /* @__PURE__ */ jsx(
51
+ "button",
52
+ {
53
+ onClick: handleCopy,
54
+ className: "opacity-0 group-hover:opacity-100 transition-opacity px-2 py-1 rounded hover:bg-gray-700",
55
+ children: copied ? "Copied!" : "Copy"
56
+ }
57
+ )
58
+ ] }),
59
+ /* @__PURE__ */ jsx("div", { className: "bg-gray-900 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "p-4 text-sm", children: /* @__PURE__ */ jsx("code", { className: `language-${language || "text"}`, children: showLineNumbers ? /* @__PURE__ */ jsx("table", { className: "border-collapse", children: /* @__PURE__ */ jsx("tbody", { children: lines.map((line, index) => /* @__PURE__ */ jsxs("tr", { children: [
60
+ /* @__PURE__ */ jsx("td", { className: "pr-4 text-gray-500 select-none text-right w-8", children: index + 1 }),
61
+ /* @__PURE__ */ jsx("td", { className: "text-gray-100", children: line || " " })
62
+ ] }, index)) }) }) : /* @__PURE__ */ jsx("span", { className: "text-gray-100", children }) }) }) })
63
+ ] });
64
+ }
65
+
66
+ // src/components/StreamMarkdown.tsx
67
+ import { Streamdown } from "streamdown";
68
+ import { Streamdown as Streamdown2 } from "streamdown";
69
+ import { jsx as jsx2 } from "react/jsx-runtime";
70
+ function StreamMarkdown({
71
+ content,
72
+ isStreaming = false,
73
+ className
74
+ }) {
75
+ return /* @__PURE__ */ jsx2(
76
+ "div",
77
+ {
78
+ className: cn(
79
+ "prose prose-gray max-w-none",
80
+ // Lucid UI typography styles
81
+ "prose-headings:text-foreground prose-headings:font-semibold",
82
+ "prose-p:text-foreground prose-p:leading-relaxed",
83
+ "prose-a:text-primary-600 prose-a:no-underline hover:prose-a:underline",
84
+ "prose-strong:text-foreground prose-strong:font-semibold",
85
+ "prose-code:text-primary-700 prose-code:bg-gray-100 prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-code:text-sm",
86
+ "prose-pre:p-0 prose-pre:bg-transparent",
87
+ "prose-blockquote:border-l-primary-500 prose-blockquote:text-gray-600",
88
+ "prose-ul:text-foreground prose-ol:text-foreground",
89
+ "prose-li:marker:text-gray-400",
90
+ "prose-table:text-sm",
91
+ "prose-th:bg-gray-50 prose-th:text-foreground prose-th:font-medium",
92
+ "prose-td:text-foreground",
93
+ className
94
+ ),
95
+ children: /* @__PURE__ */ jsx2(Streamdown, { mode: isStreaming ? "streaming" : "static", children: content })
96
+ }
97
+ );
98
+ }
99
+
100
+ // src/components/StreamText.tsx
101
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
102
+ function StreamText({
103
+ children,
104
+ showCursor = false,
105
+ cursorStyle = "line",
106
+ className
107
+ }) {
108
+ const cursorClasses = {
109
+ block: "inline-block w-2 h-5 bg-primary-500 animate-pulse ml-0.5 align-middle",
110
+ line: "inline-block w-0.5 h-5 bg-primary-500 animate-pulse ml-0.5 align-middle",
111
+ underscore: "inline-block w-2 h-0.5 bg-primary-500 animate-pulse ml-0.5 align-bottom"
112
+ };
113
+ return /* @__PURE__ */ jsxs2("span", { className: cn("text-foreground", className), children: [
114
+ children,
115
+ showCursor && /* @__PURE__ */ jsx3(
116
+ "span",
117
+ {
118
+ className: cursorClasses[cursorStyle],
119
+ "aria-hidden": "true"
120
+ }
121
+ )
122
+ ] });
123
+ }
124
+ export {
125
+ CodeBlock,
126
+ StreamMarkdown,
127
+ StreamText,
128
+ Streamdown2 as Streamdown,
129
+ cn,
130
+ healMarkdown
131
+ };
132
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/CodeBlock.tsx","../src/utils.ts","../src/components/StreamMarkdown.tsx","../src/components/StreamText.tsx"],"sourcesContent":["import * as React from 'react'\nimport { cn } from '../utils'\n\nexport interface CodeBlockProps {\n /**\n * The code content to display\n */\n children: string\n /**\n * Programming language for syntax highlighting\n */\n language?: string\n /**\n * Show line numbers\n */\n showLineNumbers?: boolean\n /**\n * Show copy button\n */\n showCopyButton?: boolean\n /**\n * Additional CSS classes\n */\n className?: string\n}\n\n/**\n * CodeBlock Component\n *\n * Displays code with syntax highlighting and optional features like\n * line numbers and copy button.\n *\n * @example\n * ```tsx\n * <CodeBlock language=\"typescript\">\n * const hello = \"world\"\n * </CodeBlock>\n * ```\n */\nexport function CodeBlock({\n children,\n language,\n showLineNumbers = false,\n showCopyButton = true,\n className,\n}: CodeBlockProps) {\n const [copied, setCopied] = React.useState(false)\n\n const handleCopy = async () => {\n await navigator.clipboard.writeText(children)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n\n const lines = children.split('\\n')\n\n return (\n <div className={cn('relative group rounded-lg overflow-hidden', className)}>\n {/* Header with language label and copy button */}\n <div className=\"flex items-center justify-between px-4 py-2 bg-gray-800 text-gray-400 text-xs\">\n <span>{language || 'text'}</span>\n {showCopyButton && (\n <button\n onClick={handleCopy}\n className=\"opacity-0 group-hover:opacity-100 transition-opacity px-2 py-1 rounded hover:bg-gray-700\"\n >\n {copied ? 'Copied!' : 'Copy'}\n </button>\n )}\n </div>\n\n {/* Code content */}\n <div className=\"bg-gray-900 overflow-x-auto\">\n <pre className=\"p-4 text-sm\">\n <code className={`language-${language || 'text'}`}>\n {showLineNumbers ? (\n <table className=\"border-collapse\">\n <tbody>\n {lines.map((line, index) => (\n <tr key={index}>\n <td className=\"pr-4 text-gray-500 select-none text-right w-8\">\n {index + 1}\n </td>\n <td className=\"text-gray-100\">{line || ' '}</td>\n </tr>\n ))}\n </tbody>\n </table>\n ) : (\n <span className=\"text-gray-100\">{children}</span>\n )}\n </code>\n </pre>\n </div>\n </div>\n )\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\n/**\n * Merge Tailwind CSS classes with clsx\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n/**\n * Fix incomplete markdown for streaming scenarios\n * Handles unclosed code blocks, bold, italic, etc.\n *\n * @deprecated Streamdown now handles this automatically via Remend.\n * This function is kept for backward compatibility.\n */\nexport function healMarkdown(content: string): string {\n let result = content\n\n // Count backticks for code blocks\n const codeBlockMatches = result.match(/```/g)\n if (codeBlockMatches && codeBlockMatches.length % 2 !== 0) {\n // Unclosed code block - add closing\n result += '\\n```'\n }\n\n // Count inline code backticks\n const inlineCodeMatches = result.match(/(?<!`)`(?!`)/g)\n if (inlineCodeMatches && inlineCodeMatches.length % 2 !== 0) {\n result += '`'\n }\n\n // Count bold markers (**)\n const boldMatches = result.match(/\\*\\*/g)\n if (boldMatches && boldMatches.length % 2 !== 0) {\n result += '**'\n }\n\n // Count italic markers (single *)\n // This is tricky because * is also used in lists\n const italicMatches = result.match(/(?<!\\*)\\*(?!\\*)/g)\n if (italicMatches && italicMatches.length % 2 !== 0) {\n result += '*'\n }\n\n return result\n}\n","import * as React from 'react'\nimport { Streamdown } from 'streamdown'\nimport { cn } from '../utils'\n\nexport interface StreamMarkdownProps {\n /**\n * The markdown content to render\n */\n content: string\n /**\n * Whether content is still streaming\n * Note: Streamdown handles streaming automatically via Remend\n */\n isStreaming?: boolean\n /**\n * Additional CSS classes\n */\n className?: string\n}\n\n/**\n * StreamMarkdown Component\n *\n * Renders markdown content with full streaming support.\n * Powered by Vercel Streamdown for optimal AI streaming scenarios.\n *\n * Features:\n * - GitHub Flavored Markdown (tables, task lists, strikethrough)\n * - Syntax highlighted code blocks (Shiki)\n * - LaTeX math equations (KaTeX)\n * - Mermaid diagrams\n * - Automatic self-healing for incomplete markdown (Remend)\n * - Memoized rendering for performance\n * - Security hardening (rehype-harden)\n *\n * @example\n * ```tsx\n * <StreamMarkdown\n * content={streamingContent}\n * isStreaming={true}\n * />\n * ```\n */\nexport function StreamMarkdown({\n content,\n isStreaming = false,\n className,\n}: StreamMarkdownProps) {\n return (\n <div\n className={cn(\n 'prose prose-gray max-w-none',\n // Lucid UI typography styles\n 'prose-headings:text-foreground prose-headings:font-semibold',\n 'prose-p:text-foreground prose-p:leading-relaxed',\n 'prose-a:text-primary-600 prose-a:no-underline hover:prose-a:underline',\n 'prose-strong:text-foreground prose-strong:font-semibold',\n 'prose-code:text-primary-700 prose-code:bg-gray-100 prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-code:text-sm',\n 'prose-pre:p-0 prose-pre:bg-transparent',\n 'prose-blockquote:border-l-primary-500 prose-blockquote:text-gray-600',\n 'prose-ul:text-foreground prose-ol:text-foreground',\n 'prose-li:marker:text-gray-400',\n 'prose-table:text-sm',\n 'prose-th:bg-gray-50 prose-th:text-foreground prose-th:font-medium',\n 'prose-td:text-foreground',\n className\n )}\n >\n <Streamdown mode={isStreaming ? 'streaming' : 'static'}>{content}</Streamdown>\n </div>\n )\n}\n\n/**\n * Re-export Streamdown component for advanced usage\n */\nexport { Streamdown } from 'streamdown'\n","import * as React from 'react'\nimport { cn } from '../utils'\n\nexport interface StreamTextProps {\n /**\n * The text content to display\n */\n children: string\n /**\n * Whether to show typing cursor\n */\n showCursor?: boolean\n /**\n * Cursor style\n */\n cursorStyle?: 'block' | 'line' | 'underscore'\n /**\n * Additional CSS classes\n */\n className?: string\n}\n\n/**\n * StreamText Component\n *\n * Simple streaming text display with optional typing cursor.\n * Use this for plain text streaming without markdown.\n *\n * @example\n * ```tsx\n * <StreamText showCursor={isStreaming}>\n * {streamingText}\n * </StreamText>\n * ```\n */\nexport function StreamText({\n children,\n showCursor = false,\n cursorStyle = 'line',\n className,\n}: StreamTextProps) {\n const cursorClasses = {\n block: 'inline-block w-2 h-5 bg-primary-500 animate-pulse ml-0.5 align-middle',\n line: 'inline-block w-0.5 h-5 bg-primary-500 animate-pulse ml-0.5 align-middle',\n underscore: 'inline-block w-2 h-0.5 bg-primary-500 animate-pulse ml-0.5 align-bottom',\n }\n\n return (\n <span className={cn('text-foreground', className)}>\n {children}\n {showCursor && (\n <span\n className={cursorClasses[cursorStyle]}\n aria-hidden=\"true\"\n />\n )}\n </span>\n )\n}\n"],"mappings":"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","names":["Streamdown","jsx","jsx","jsxs"]}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@uix-ai/stream",
3
+ "version": "0.0.1",
4
+ "description": "Streaming content renderer for UIX blocks - powered by Vercel Streamdown",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "clean": "rm -rf dist"
22
+ },
23
+ "dependencies": {
24
+ "@uix-ai/core": "workspace:*",
25
+ "@uix-ai/lucid-tokens": "workspace:*",
26
+ "clsx": "^2.1.0",
27
+ "tailwind-merge": "^2.2.0",
28
+ "streamdown": "^1.6.0"
29
+ },
30
+ "peerDependencies": {
31
+ "react": "^18.0.0 || ^19.0.0",
32
+ "react-dom": "^18.0.0 || ^19.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/react": "^19.0.0",
36
+ "@types/react-dom": "^19.0.0",
37
+ "react": "^19.0.0",
38
+ "react-dom": "^19.0.0",
39
+ "tsup": "^8.0.0",
40
+ "typescript": "^5.3.0"
41
+ },
42
+ "keywords": [
43
+ "react",
44
+ "markdown",
45
+ "streaming",
46
+ "uix",
47
+ "declarative-ui",
48
+ "self-healing"
49
+ ],
50
+ "license": "MIT",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "https://github.com/Deepractice/UIX.git",
54
+ "directory": "packages/stream"
55
+ }
56
+ }