@rlx-ui/mcp 0.0.6 → 0.0.7

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.
@@ -1264,6 +1264,20 @@
1264
1264
  }
1265
1265
  ]
1266
1266
  },
1267
+ {
1268
+ "name": "Code Block",
1269
+ "exportName": "CodeBlock",
1270
+ "packageName": "@rlx-components/code-block",
1271
+ "slug": "code-block",
1272
+ "category": "component",
1273
+ "sourceCode": "import { cn } from \"@rlx-widgets/base\";\nimport { ReactNode } from \"react\";\n\nexport const CodeBlock = ({ className, code, children }: CodeBlockProps) => {\n return (\n <pre\n className={cn(\n \"bg-muted rounded p-3 overflow-x-auto text-sm\",\n className,\n \"dark-scroll\"\n )}\n >\n <code>{code ?? children}</code>\n </pre>\n );\n};\ntype CodeBlockProps =\n | { code: string; children?: never; className?: string }\n | { children: ReactNode; code?: never; className?: string };\n\nexport default CodeBlock;\n",
1274
+ "demos": [
1275
+ {
1276
+ "name": "default",
1277
+ "code": "\"use client\";\n\nimport { CodeBlock } from \"@rlx-components/code-block\";\n\nexport const Preview = () => {\n return (\n <div className=\"w-full\">\n <CodeBlock>{`console.log('Hello, world!');`}</CodeBlock>\n </div>\n );\n};\n"
1278
+ }
1279
+ ]
1280
+ },
1267
1281
  {
1268
1282
  "name": "Code Preview Tabs",
1269
1283
  "exportName": "CodePreviewTabs",
@@ -1289,6 +1303,20 @@
1289
1303
  "types/TabType.t.ts": "import { TabTypeEnum } from \"../enums\";\n\nexport type TabType = `${TabTypeEnum}`;\n"
1290
1304
  }
1291
1305
  },
1306
+ {
1307
+ "name": "Inline Code",
1308
+ "exportName": "InlineCode",
1309
+ "packageName": "@rlx-components/inline-code",
1310
+ "slug": "inline-code",
1311
+ "category": "component",
1312
+ "sourceCode": "import { cn } from \"@rlx-widgets/base\";\nimport { ReactNode } from \"react\";\n\nexport const InlineCode = ({ className, code, children }: InlineCodeProps) => {\n return (\n <span\n className={cn(\n \"bg-muted rounded px-1 py-0.5 overflow-x-auto text-sm\",\n className\n )}\n >\n <code>{code ?? children}</code>\n </span>\n );\n};\ntype InlineCodeProps =\n | { code: string; children?: never; className?: string }\n | { children: ReactNode; code?: never; className?: string };\n\nexport default InlineCode;\n",
1313
+ "demos": [
1314
+ {
1315
+ "name": "default",
1316
+ "code": "\"use client\";\n\nimport { InlineCode } from \"@rlx-components/inline-code\";\n\nexport const Preview = () => {\n return (\n <div className=\"w-full text-center\">\n In order to solve <InlineCode>x</InlineCode> in{\" \"}\n <InlineCode>x + 4 = 5</InlineCode>, we need to isolate{\" \"}\n <InlineCode>x</InlineCode> by subtracting 4 from both sides\n </div>\n );\n};\n"
1317
+ }
1318
+ ]
1319
+ },
1292
1320
  {
1293
1321
  "name": "Shiki Code Block",
1294
1322
  "exportName": "ShikiCodeBlock",
@@ -1327,6 +1355,25 @@
1327
1355
  "StackedCard.tsx": "import { cn } from \"@rlx-widgets/base\";\nimport { Card } from \"@rlx-widgets/card\";\nimport { forwardRef, MouseEventHandler } from \"react\";\n\nconst boxShadow =\n\t\"[box-shadow:0px_5px_10px_0px_#22215140,1px_1px_1px_1px_#75757526]\";\n\ntype StackedCardProps = {\n\tchildren: React.ReactNode;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\tonMouseEnter?: () => void;\n\tonMouseLeave?: () => void;\n\tonClick?: MouseEventHandler<HTMLDivElement> | undefined;\n};\n\nexport const StackedCard = forwardRef<HTMLDivElement, StackedCardProps>(\n\t({ children, className, style, ...props }, ref) => {\n\t\treturn (\n\t\t\t<Card\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"transition-transform duration-200 ease-in-out\",\n\t\t\t\t\t\"h-[175px] w-[260px]\",\n\t\t\t\t\t\"inline-flex gap-4\",\n\t\t\t\t\tboxShadow,\n\t\t\t\t\t\"border-0\",\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tstyle={style}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Card>\n\t\t);\n\t}\n);\n\nStackedCard.displayName = \"StackedCard\";\n\nexport default StackedCard;\n"
1328
1356
  }
1329
1357
  },
1358
+ {
1359
+ "name": "Streaming Text",
1360
+ "exportName": "StreamingText",
1361
+ "packageName": "@rlx-components/streaming-text",
1362
+ "slug": "streaming-text",
1363
+ "category": "component",
1364
+ "sourceCode": "\"use client\";\n\nimport { cn } from \"@rlx-widgets/base\";\nimport {\n ComponentProps,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport {\n type StreamingState,\n type StreamingTextControls,\n type StreamingTextProps,\n} from \"./types\";\n\nexport const StreamingText = forwardRef<\n StreamingTextControls,\n StreamingTextProps\n>(\n (\n {\n text,\n className,\n delay = 10,\n indicator,\n autoStart = false,\n onStateChange,\n },\n ref\n ) => {\n const intervalRef = useRef<NodeJS.Timeout | null>(null);\n const [displayedText, setDisplayedText] = useState(\"\");\n const streamingStateRef = useRef<StreamingState>(\"idle\");\n const charIndexRef = useRef(0);\n\n // Helper to clear interval\n const clearIntervalSafe = useCallback(() => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n }, []);\n\n // Update state and notify callback\n const updateState = useCallback(\n (newState: StreamingState) => {\n streamingStateRef.current = newState;\n onStateChange?.(newState);\n },\n [onStateChange]\n );\n\n // Helper to reset internal state\n const resetInternalState = useCallback(() => {\n charIndexRef.current = 0;\n setDisplayedText(\"\");\n }, []);\n\n const handleStreaming = useCallback(() => {\n // Don't stream if paused or completed\n if (streamingStateRef.current !== \"streaming\") {\n return;\n }\n\n if (charIndexRef.current >= text.length) {\n clearIntervalSafe();\n updateState(\"completed\");\n return;\n }\n const streamedText = text.slice(0, charIndexRef.current + 1);\n setDisplayedText(streamedText);\n ++charIndexRef.current;\n }, [text, clearIntervalSafe, updateState]);\n\n // Helper to start interval\n const startInterval = useCallback(\n (callback: () => void, delayMs: number) => {\n clearIntervalSafe();\n intervalRef.current = setInterval(callback, delayMs);\n },\n [clearIntervalSafe]\n );\n\n // Control methods\n const start = useCallback(() => {\n const currentState = streamingStateRef.current;\n const isCompleted =\n currentState === \"completed\" || charIndexRef.current >= text.length;\n\n if (isCompleted) {\n resetInternalState();\n updateState(\"idle\");\n }\n\n const newState = streamingStateRef.current;\n if (newState === \"idle\" || newState === \"paused\") {\n const validDelay = Math.max(0, delay);\n updateState(\"streaming\");\n\n // Start immediately and then set interval\n handleStreaming();\n startInterval(handleStreaming, validDelay);\n }\n }, [text, delay, handleStreaming, updateState, resetInternalState, startInterval]);\n\n const pause = useCallback(() => {\n if (streamingStateRef.current === \"streaming\") {\n clearIntervalSafe();\n updateState(\"paused\");\n }\n }, [clearIntervalSafe, updateState]);\n\n const reset = useCallback(() => {\n clearIntervalSafe();\n resetInternalState();\n updateState(\"idle\");\n }, [clearIntervalSafe, resetInternalState, updateState]);\n\n // Expose control methods via ref\n useImperativeHandle(\n ref,\n () => ({\n start,\n pause,\n reset,\n getState: () => streamingStateRef.current,\n }),\n [start, pause, reset]\n );\n\n // Reset when text or delay changes\n useEffect(() => {\n clearIntervalSafe();\n resetInternalState();\n updateState(\"idle\");\n\n // Handle empty text\n if (!text) {\n return;\n }\n\n // Start streaming if autoStart is enabled\n if (autoStart) {\n const validDelay = Math.max(0, delay);\n updateState(\"streaming\");\n\n // Start immediately and then set interval\n const initialText = text.slice(0, 1);\n setDisplayedText(initialText);\n charIndexRef.current = 1;\n\n startInterval(handleStreaming, validDelay);\n }\n }, [\n text,\n delay,\n autoStart,\n handleStreaming,\n updateState,\n clearIntervalSafe,\n resetInternalState,\n startInterval,\n ]);\n\n // Cleanup on unmount\n useEffect(() => {\n return clearIntervalSafe;\n }, [clearIntervalSafe]);\n\n return (\n <div className={cn(\"whitespace-pre-wrap\", className)}>\n {displayedText}\n {indicator}\n </div>\n );\n }\n);\n\nStreamingText.displayName = \"StreamingText\";\n\nexport type StreamingTextIndicatorProps = ComponentProps<\"span\">;\n\nexport const StreamingTextIndicator = ({\n className,\n children,\n ...props\n}: StreamingTextIndicatorProps) => {\n return (\n <span\n className={cn(\"inline-block animate-pulse\", className)}\n aria-hidden=\"true\"\n {...props}\n >\n {children ?? \" ▋\"}\n </span>\n );\n};\n",
1365
+ "demos": [
1366
+ {
1367
+ "name": "default",
1368
+ "code": "\"use client\";\n\nimport {\n StreamingText,\n StreamingTextIndicator,\n} from \"@rlx-components/streaming-text\";\nimport { Button } from \"@rlx-widgets/button\";\nimport { useRef } from \"react\";\nimport type { StreamingTextControls } from \"@rlx-components/streaming-text\";\n\nexport const Preview = () => {\n const controlsRef = useRef<StreamingTextControls>(null);\n\n return (\n <div className=\"w-full space-y-4\">\n <div className=\"flex items-center justify-center min-h-[100px]\">\n <StreamingText\n ref={controlsRef}\n text=\"Hello, world! This is a streaming text component that displays text character by character.\"\n autoStart={true}\n indicator={<StreamingTextIndicator />}\n />\n </div>\n <div className=\"flex gap-2 justify-center\">\n <Button onClick={() => controlsRef.current?.start()}>Start</Button>\n <Button onClick={() => controlsRef.current?.pause()}>Pause</Button>\n <Button onClick={() => controlsRef.current?.reset()}>Reset</Button>\n </div>\n </div>\n );\n};\n\n"
1369
+ }
1370
+ ],
1371
+ "sourceFiles": {
1372
+ "types/StreamingState.t.ts": "export type StreamingState = \"idle\" | \"streaming\" | \"paused\" | \"completed\";\n",
1373
+ "types/StreamingTextControls.t.ts": "import { StreamingState } from \"./StreamingState.t\";\n\nexport type StreamingTextControls = {\n /**\n * Start or resume streaming.\n */\n start: () => void;\n /**\n * Pause streaming (can be resumed later).\n */\n pause: () => void;\n /**\n * Reset streaming to the beginning (idle state).\n */\n reset: () => void;\n /**\n * Get the current streaming state.\n */\n getState: () => StreamingState;\n};\n",
1374
+ "types/StreamingTextProps.t.ts": "import { ReactNode } from \"react\";\nimport { StreamingState } from \"./StreamingState.t\";\n\nexport type StreamingTextProps = {\n text: string;\n className?: string;\n /**\n * The delay in milliseconds between each character.\n * @default 10\n */\n delay?: number;\n /**\n * Optional indicator to show while streaming (e.g., a blinking cursor).\n * Only displayed when streaming is in progress.\n */\n indicator?: ReactNode;\n /**\n * Whether to automatically start streaming on mount.\n * @default false\n */\n autoStart?: boolean;\n /**\n * Callback fired when streaming state changes.\n * Use this to handle state transitions (idle -> streaming -> paused -> completed).\n */\n onStateChange?: (state: StreamingState) => void;\n};\n"
1375
+ }
1376
+ },
1330
1377
  {
1331
1378
  "name": "Theme Toggle",
1332
1379
  "exportName": "ThemeToggle",
@@ -1439,5 +1486,5 @@
1439
1486
  "sourceCode": "export const isValidDate = (date: Date) => {\n return !Number.isNaN(date.getTime());\n};\n\nexport default isValidDate;\n"
1440
1487
  }
1441
1488
  ],
1442
- "extractedAt": "2025-11-24T06:31:33.379Z"
1489
+ "extractedAt": "2025-11-29T21:49:12.625Z"
1443
1490
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rlx-ui/mcp",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "MCP (Model Context Protocol) Server for RLX UI components",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rlx-ui/mcp",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "MCP (Model Context Protocol) Server for RLX UI components",
5
5
  "publishConfig": {
6
6
  "access": "public"