UNPKG

@yuntijs/ui

Version:

☁️ Yunti UI - an open-source UI component library for building Cloud Native web apps

153 lines (151 loc) 6.56 kB
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import { getTokenStyleObject } from '@shikijs/core'; import { memo, useEffect, useRef } from 'react'; import { useStreamHighlight } from "../../hooks/useHighlight"; import { useStyles } from "./style"; import { jsx as _jsx } from "react/jsx-runtime"; var applyColorReplacement = function applyColorReplacement(color, replacements) { if (!color || !replacements) return color; return replacements[color.toLowerCase()] || color; }; var normalizeStyleKeys = function normalizeStyleKeys(style) { var normalized = {}; for (var _i = 0, _Object$entries = Object.entries(style); _i < _Object$entries.length; _i++) { var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), key = _Object$entries$_i[0], value = _Object$entries$_i[1]; var normalizedKey = key.replaceAll(/-([a-z])/g, function (_, char) { return char.toUpperCase(); }); normalized[normalizedKey] = value; } return normalized; }; var getTokenInlineStyle = function getTokenInlineStyle(token, replacements) { var rawStyle = token.htmlStyle || getTokenStyleObject(token); var baseStyle = normalizeStyleKeys(rawStyle); if (!replacements) return _objectSpread({}, baseStyle); var style = _objectSpread({}, baseStyle); if (style.color && typeof style.color === 'string') { style.color = applyColorReplacement(style.color, replacements); } if (style.backgroundColor && typeof style.backgroundColor === 'string') { style.backgroundColor = applyColorReplacement(style.backgroundColor, replacements); } return style; }; var TokenSpan = /*#__PURE__*/memo(function (_ref) { var token = _ref.token, replacements = _ref.replacements; return /*#__PURE__*/_jsx("span", { style: getTokenInlineStyle(token, replacements), children: token.content }, token.content); }, function (prev, next) { return prev.token === next.token; }); var TokenLine = /*#__PURE__*/memo(function (_ref2) { var line = _ref2.line, replacements = _ref2.replacements; if (line.length === 0) { return /*#__PURE__*/_jsx("span", { className: "line", children: /*#__PURE__*/_jsx("span", { children: "\xA0" }) }); } return /*#__PURE__*/_jsx("span", { className: "line", children: line.map(function (token, tokenIndex) { return /*#__PURE__*/_jsx(TokenSpan, { replacements: replacements, token: token }, "token-".concat(tokenIndex)); }) }); }, function (prev, next) { return prev.line === next.line; }); var StreamRenderer = /*#__PURE__*/memo(function (_ref3) { var _lines$length, _lines$reduce, _lines; var children = _ref3.children, className = _ref3.className, enableTransformer = _ref3.enableTransformer, fallbackClassName = _ref3.fallbackClassName, language = _ref3.language, style = _ref3.style, theme = _ref3.theme; var _useStyles = useStyles({ theme: theme }), styles = _useStyles.styles, cx = _useStyles.cx; var safeChildren = children !== null && children !== void 0 ? children : ''; var preRef = useRef(null); var result = useStreamHighlight(safeChildren, language, enableTransformer, theme); var lines = result === null || result === void 0 ? void 0 : result.lines; var replacements = result === null || result === void 0 ? void 0 : result.colorReplacements; var linesCount = (_lines$length = lines === null || lines === void 0 ? void 0 : lines.length) !== null && _lines$length !== void 0 ? _lines$length : 0; // 计算最后一行的内容长度,用于 wrap 模式下折行时也能触发滚动 var lastLineContentLength = linesCount > 0 ? (_lines$reduce = lines === null || lines === void 0 || (_lines = lines[linesCount - 1]) === null || _lines === void 0 ? void 0 : _lines.reduce(function (acc, token) { var _token$content$length, _token$content; return acc + ((_token$content$length = (_token$content = token.content) === null || _token$content === void 0 ? void 0 : _token$content.length) !== null && _token$content$length !== void 0 ? _token$content$length : 0); }, 0)) !== null && _lines$reduce !== void 0 ? _lines$reduce : 0 : 0; var rafIdRef = useRef(0); // 流式输出时自动滚动(使用 RAF 节流,每帧最多执行一次) useEffect(function () { if (!preRef.current || linesCount === 0) return; // 取消上一次未执行的 RAF if (rafIdRef.current) { cancelAnimationFrame(rafIdRef.current); } rafIdRef.current = requestAnimationFrame(function () { if (!preRef.current) return; preRef.current.scrollTop = preRef.current.scrollHeight; }); return function () { if (rafIdRef.current) { cancelAnimationFrame(rafIdRef.current); } }; }, [linesCount, lastLineContentLength]); if (!lines || lines.length === 0) { return /*#__PURE__*/_jsx("div", { className: cx(styles.shiki, fallbackClassName), dir: "ltr", style: style, children: /*#__PURE__*/_jsx("pre", { children: /*#__PURE__*/_jsx("code", { children: safeChildren }) }) }); } return /*#__PURE__*/_jsx("div", { className: cx(styles.shiki, className), dir: "ltr", style: style, children: /*#__PURE__*/_jsx("pre", { ref: preRef, tabIndex: 0, children: /*#__PURE__*/_jsx("code", { style: { display: 'flex', flexDirection: 'column' }, children: lines.map(function (line, index) { return /*#__PURE__*/_jsx(TokenLine, { line: line, replacements: replacements }, "line-".concat(index)); }) }) }) }); }); StreamRenderer.displayName = 'StreamRenderer'; export default StreamRenderer;