Explorar el Código

Merge branch 'plus/done' into release

DaiQiangReal hace 1 año
padre
commit
e8ae83b416
Se han modificado 64 ficheros con 3395 adiciones y 706 borrados
  1. 3 1
      .eslintrc.js
  2. 1 0
      babel.config.js
  3. 208 0
      content/input/pincode/index.md
  4. 2 0
      content/order.js
  5. 137 0
      content/plus/codehighlight/index-en-US.md
  6. 142 0
      content/plus/codehighlight/index.md
  7. 163 0
      content/plus/lottie/index-en-US.md
  8. 163 0
      content/plus/lottie/index.md
  9. 151 0
      content/plus/markdownrender/index-en-US.md
  10. 190 0
      content/plus/markdownrender/index.md
  11. 26 4
      gatsby-node.js
  12. 3 3
      package.json
  13. 203 0
      packages/semi-foundation/codeHighlight/codeHighlight.scss
  14. 15 0
      packages/semi-foundation/codeHighlight/constants.ts
  15. 45 0
      packages/semi-foundation/codeHighlight/index.ts
  16. 0 0
      packages/semi-foundation/codeHighlight/variables.scss
  17. 17 0
      packages/semi-foundation/lottie/constants.ts
  18. 60 0
      packages/semi-foundation/lottie/foundation.ts
  19. 11 0
      packages/semi-foundation/markdownRender/constants.ts
  20. 69 0
      packages/semi-foundation/markdownRender/foundation.ts
  21. 43 0
      packages/semi-foundation/markdownRender/markdownRender.scss
  22. 16 0
      packages/semi-foundation/markdownRender/variables.scss
  23. 6 0
      packages/semi-foundation/package.json
  24. 13 0
      packages/semi-foundation/pincode/constants.ts
  25. 126 0
      packages/semi-foundation/pincode/foundation.ts
  26. 41 0
      packages/semi-foundation/pincode/pincode.scss
  27. 7 0
      packages/semi-foundation/pincode/variables.scss
  28. 1 0
      packages/semi-theme-default/package.json
  29. 8 2
      packages/semi-ui/_base/baseComponent.tsx
  30. 16 0
      packages/semi-ui/codeHighlight/_story/codeHighlight.stories.jsx
  31. 3 0
      packages/semi-ui/codeHighlight/_story/codeHighlight.stories.tsx
  32. 86 0
      packages/semi-ui/codeHighlight/index.tsx
  33. 7 1
      packages/semi-ui/index.ts
  34. 27 0
      packages/semi-ui/lottie/_story/lottie.stories.jsx
  35. 7 0
      packages/semi-ui/lottie/_story/lottie.stories.tsx
  36. 111 0
      packages/semi-ui/lottie/index.tsx
  37. 44 0
      packages/semi-ui/markdownRender/_story/markdownRender.stories.jsx
  38. 8 0
      packages/semi-ui/markdownRender/_story/markdownRender.stories.tsx
  39. 9 0
      packages/semi-ui/markdownRender/components/a.tsx
  40. 20 0
      packages/semi-ui/markdownRender/components/code.tsx
  41. 10 0
      packages/semi-ui/markdownRender/components/h1.tsx
  42. 10 0
      packages/semi-ui/markdownRender/components/h2.tsx
  43. 10 0
      packages/semi-ui/markdownRender/components/h3.tsx
  44. 10 0
      packages/semi-ui/markdownRender/components/h4.tsx
  45. 10 0
      packages/semi-ui/markdownRender/components/h5.tsx
  46. 10 0
      packages/semi-ui/markdownRender/components/h6.tsx
  47. 18 0
      packages/semi-ui/markdownRender/components/img.tsx
  48. 13 0
      packages/semi-ui/markdownRender/components/index.tsx
  49. 10 0
      packages/semi-ui/markdownRender/components/p.tsx
  50. 37 0
      packages/semi-ui/markdownRender/components/table.tsx
  51. 73 0
      packages/semi-ui/markdownRender/index.tsx
  52. 34 0
      packages/semi-ui/pincode/_story/pincode.stories.js
  53. 6 0
      packages/semi-ui/pincode/_story/pincode.stories.ts
  54. 137 0
      packages/semi-ui/pincode/index.tsx
  55. 10 10
      src/components/ChartContact/index.jsx
  56. 1 0
      src/components/layout.js
  57. 1 1
      src/components/side-nav.js
  58. 19 1
      src/styles/docDemo.scss
  59. 1 1
      src/styles/index.scss
  60. 13 3
      src/styles/layout.scss
  61. 3 3
      src/templates/scope.js
  62. 1 0
      src/utils/category.js
  63. 0 1
      tsconfig.json
  64. 750 675
      yarn.lock

+ 3 - 1
.eslintrc.js

@@ -43,9 +43,9 @@ module.exports = {
                 'jsx-a11y/mouse-events-have-key-events': ['warn'],
                 'object-curly-spacing': ['error', 'always'],
                 'space-before-blocks': ['error', 'always'],
+                "space-infix-ops": "error",
                 'max-len': 'off',
                 'react/forbid-foreign-prop-types': ['error', { "allowInPropTypes": true }]
-
             },
             globals: {
                 "sinon": "readonly",
@@ -117,7 +117,9 @@ module.exports = {
                 'object-curly-spacing': ['error', 'always'],
                 'prefer-const': 'off',
                 'semi-design/no-import': 'error',
+                "space-infix-ops": ["error", { "int32Hint": false }],
                 'space-before-blocks': ['error', 'always'],
+                "space-infix-ops": "error",
                 "@typescript-eslint/type-annotation-spacing": ['error', {"after": true}],
                 "@typescript-eslint/member-delimiter-style": [
                     "error",

+ 1 - 0
babel.config.js

@@ -13,6 +13,7 @@ module.exports = {
         '@babel/preset-typescript'
     ],
     plugins: [
+        "@babel/plugin-transform-numeric-separator",
         '@babel/plugin-transform-runtime',
         [
             '@babel/plugin-proposal-decorators',

+ 208 - 0
content/input/pincode/index.md

@@ -0,0 +1,208 @@
+---
+localeCode: zh-CN
+order: 0
+category: 输入类
+title: PinCode 验证码输入
+icon: doc-input
+width: 60%
+brief: 用于便捷直观地输入验证码
+---
+
+## 代码演示
+
+### 如何引入
+
+```jsx
+import { PinCode } from '@douyinfe/semi-ui';
+```
+
+### 基本使用
+
+```jsx live=true
+import { PinCode } from '@douyinfe/semi-ui';
+import React from 'react';
+
+function Demo() {
+    return (
+        <>
+            <PinCode
+                size={'small'}
+                defaultValue={'123456'}
+                onComplete={value => console.log('pincode: ', value)}
+                onChange={value => {
+                    console.log(value);
+                }}
+            />
+            <br />
+            <PinCode
+                size={'default'}
+                defaultValue={'123456'}
+                onComplete={value => console.log('pincode: ', value)}
+                onChange={value => {
+                    console.log(value);
+                }}
+            />
+            <br />
+            <PinCode
+                size={'large'}
+                defaultValue={'123456'}
+                onComplete={value => console.log('pincode: ', value)}
+                onChange={value => {
+                    console.log(value);
+                }}
+            />
+        </>
+    );
+}
+```
+
+### 受控
+
+使用 value 传入验证码字符串,配合 onChange 受控使用
+
+```jsx live=true
+import React from 'react';
+import { PinCode, Button } from '@douyinfe/semi-ui';
+
+function Demo() {
+    const [value, setValue] = useState('69af41');
+    return (
+        <>
+            <Button onClick={() => setValue(String(parseInt(Math.random() * 100000000)).slice(0, 6))}>
+                Set Random Value
+            </Button>
+            <br />
+            <br />
+            <PinCode
+                format={'mixed'}
+                onComplete={value => console.log('pincode: ', value)}
+                value={value}
+                onChange={v => {
+                    console.log(v);
+                    setValue(v);
+                }}
+            />
+        </>
+    );
+}
+```
+
+### 限制验证码格式
+
+#### 设置位数
+
+通过 count 设置位数,默认 6 位,下方 Demo 设置为 4 位
+
+```jsx live=true
+import React from 'react';
+import { PinCode } from '@douyinfe/semi-ui';
+
+function Demo() {
+    return (
+        <>
+            <PinCode
+                size={'large'}
+                defaultValue={'6688'}
+                count={4}
+                onComplete={value => console.log('pincode: ', value)}
+                onChange={value => {
+                    console.log(value);
+                }}
+            />
+        </>
+    );
+}
+```
+
+#### 设置字符范围
+
+使用 format 控制可输入的字符范围
+
+-   传入 "number" 只允许设置数字
+-   传入 “mixed” 允许数字和字母
+-   传入正则表达式,只允许输入可通过正则判定的字符
+-   传入函数,验证码会在输入的时候以字符为单位被依次作为参数分别单独传入进行校验,当函数返回 true 时,允许该字符被输入进 PinCode
+
+```jsx live=true
+import React from 'react';
+import { PinCode, Button, Typography } from '@douyinfe/semi-ui';
+
+function Demo() {
+    return (
+        <>
+            <Typography.Text>纯数字</Typography.Text>
+            <PinCode format={'number'} onComplete={value => console.log('pincode: ', value)} />
+            <br />
+            <Typography.Text>字母和数字</Typography.Text>
+            <PinCode format={'mixed'} onComplete={value => console.log('pincode: ', value)} />
+            <br />
+            <Typography.Text>只大写字母</Typography.Text>
+            <PinCode format={/[A-Z]/} onComplete={value => console.log('pincode: ', value)} />
+            <br />
+            <Typography.Text>只小写字母(函数判断)</Typography.Text>
+            <PinCode
+                format={char => {
+                    return /[a-z]/.test(char);
+                }}
+                onComplete={value => console.log('pincode: ', value)}
+            />
+        </>
+    );
+}
+```
+
+### 手动聚焦失焦
+
+使用 Ref 上方法 focus 与 blur,入参为对应 Input 的序号
+
+```jsx live=true
+import React from 'react';
+import { PinCode, Button } from '@douyinfe/semi-ui';
+
+function Demo() {
+    const [value, setValue] = useState('69af41');
+    const ref = useRef();
+    return (
+        <>
+            <Button onClick={() => ref.current.focus(2)}>Focus Third Input</Button>
+            <br />
+            <br />
+            <PinCode
+                format={'mixed'}
+                ref={ref}
+                onComplete={value => console.log('pincode: ', value)}
+                value={value}
+                onChange={v => {
+                    console.log(v);
+                    setValue(v);
+                }}
+            />
+        </>
+    );
+}
+```
+
+## API 参考
+
+| 属性 | 说明 | 类型 | 默认值 | 版本 |
+| --- | --- | --- | --- | --- |
+| autoFocus | 是否自动聚焦到第一个元素 | boolean | true |
+| className | 类名 | string |  |
+| count | 验证码位数 | number | 6 |
+| defaultValue | 输入框内容默认值 | string |  |
+| disabled | 禁用 | boolean | false |
+| format | 验证码单个字符格式限制 | 'number'\| 'mixed‘ \| RegExp \| (char:string)=>boolean | 'number' |
+| size | 输入框大小,large、default、small | string | 'default' |
+| style | 样式 | object |  |
+| value | 输入框内容 | string |  |
+| onChange | 输入回调 | (value:string)=>void |  |
+| onComplete | 验证码所有位数输入完毕回调 | (value: string) => void |  |
+
+## Methods
+
+绑定在组件实例上的方法,可以通过 ref 调用实现某些特殊交互
+
+| 属性  | 说明                         |
+| ----- | ---------------------------- |
+| focus | 聚焦,入参为验证码第几位     |
+| blur  | 移出焦点,入参为验证码第几位 | string |

+ 2 - 0
content/order.js

@@ -20,6 +20,8 @@ const order = [
     'button',
     'space',
     'typography',
+    "markdownrender",
+    "lottie",
     'autocomplete',
     'cascader',
     'checkbox',

+ 137 - 0
content/plus/codehighlight/index-en-US.md

@@ -0,0 +1,137 @@
+---
+localeCode: en-US
+order: 0
+category: Plus
+title:  CodeHighlight
+icon: doc-configprovider
+dir: column
+brief: Highlight code blocks in the page according to syntax
+---
+
+The Semi code highlighting component uses prismjs, which supports highlighting of 297 programming languages ​​(automatically configured `JavaScript` `CSS` `Class C` `html` `svg`, etc., other languages ​​need to be manually introduced), and has high scalability and rich plug-in ecology.
+
+Pass the code plain text to `code` props, and pass the programming language name to `language`. Supported programming languages ​​and corresponding names can be viewed on the [Prismjs official website](https://prismjs.com/#supported-languages)
+
+## Demos
+
+### How to introduce
+
+```jsx
+import { CodeHighlight } from '@douyinfe/semi-ui';
+```
+
+### Basic usage
+
+```jsx live=true dir=column
+import { CodeHighlight } from '@douyinfe/semi-ui';
+
+function Demo() {
+
+    return <CodeHighlight
+        language={"javascript"} code={
+        `
+import * as React from 'react"
+const Test = ()=>{
+    const handleClick = ()=>{
+        alert("Click")
+    }
+    return <div onClick={handleClick}>test</div>
+}`
+    }/>
+}
+
+```
+
+**CSS**
+
+```jsx live=true dir=column
+import { CodeHighlight } from '@douyinfe/semi-ui';
+
+function Demo() {
+
+    return <CodeHighlight
+        language={"css"} code={
+        `.grid {
+    .semi-row,
+    .semi-row-flex {
+        text-align: center;
+        .semi-col {
+            min-height: 30px;
+            line-height: 30px;
+            background: var(--semi-color-primary-light-default);
+            outline: 1px solid var(--semi-color-primary-light-active);
+        }
+    }
+}
+`
+    }/>
+}
+
+```
+
+
+### Support other languages
+
+Support 297 languages. Except for `JavaScript` `CSS` `Class C` `html` `svg`, support for other languages ​​needs to be manually imported and configured.
+
+For example, to highlight the Vala language used to write the front-end UI of GTK programs, you need to import `prism-vala.js`
+
+```javascript
+import "prismjs/components/prism-vala.js"
+```
+
+```jsx live=true dir=column
+import { CodeHighlight } from '@douyinfe/semi-ui';
+import "prismjs/components/prism-vala.js"
+
+function Demo() {
+    return <CodeHighlight
+        language={"vala"} code={
+        `public class ExampleApp : Gtk.Application {
+    public ExampleApp () {
+        Object (application_id: "com.example.App");
+    }
+
+    public override void activate () {
+        var win = new Gtk.ApplicationWindow (this);
+
+        var btn = new Gtk.Button.with_label ("Hello World");
+        btn.clicked.connect (win.close);
+
+        win.child = btn;
+        win.present ();
+    }
+
+    public static int main (string[] args) {
+        var app = new ExampleApp ();
+        return app.run (args);
+    }
+}
+`
+    }/>
+}
+
+```
+
+
+### Customize the theme
+
+Set `defaultTheme={false}` to turn off the default theme, then manually copy the css file of the required theme and import it into the project.
+Some themes can be found under prismjs/themes in node_modules, and you can also search for other themes you like on the Internet.
+
+### API
+
+| Property | Description | Type | Default value |
+|-----------|---------------------------|--------|------|
+| className | Class name | string | - |
+| code | Code text | string | - |
+| defaultTheme | Whether to use the default theme, set when adding your own theme false | bool | true |
+| language | Language type | string | - |
+|lineNumber | Whether to enable line number display | boolean | true |
+| style | Style | CSSProperties | - |
+
+## Design Tokens
+
+<DesignToken/>
+
+

+ 142 - 0
content/plus/codehighlight/index.md

@@ -0,0 +1,142 @@
+---
+localeCode: zh-CN
+order: 0
+category: Plus
+title:  CodeHighlight 代码高亮
+icon: doc-configprovider
+dir: column
+brief: 根据语法高亮页面中的代码块
+---
+
+Semi 代码高亮组件使用了 prismjs,支持297 种编程语言的高亮(已自动配置 `JavaScript` `CSS` `类 C` `html` `svg` 等,其他语言需要手动引入),同时具有高扩展性和丰富的插件生态。
+
+向 `code` props 传入代码纯文本,并在 `language` 传入编程语言名称。支持的编程语言和对应名称在 [Prismjs 官网](https://prismjs.com/#supported-languages) 查看
+
+
+## 代码演示
+
+### 如何引入
+
+
+```jsx
+import { CodeHighlight } from '@douyinfe/semi-ui';
+```
+
+### 基本用法
+
+```jsx live=true dir=column
+import { CodeHighlight } from '@douyinfe/semi-ui';
+
+function Demo() {
+
+    return <CodeHighlight
+        language={"javascript"} code={
+        `
+import * as React from 'react"
+const Test = ()=>{
+    const handleClick = ()=>{
+        alert("Click")
+    }
+    return <div onClick={handleClick}>test</div>
+}`
+    }/>
+}
+
+```
+
+**CSS**
+
+```jsx live=true dir=column
+import { CodeHighlight } from '@douyinfe/semi-ui';
+
+function Demo() {
+
+    return <CodeHighlight
+        language={"css"} code={
+        `.grid {
+    .semi-row,
+    .semi-row-flex {
+        text-align: center;
+        .semi-col {
+            min-height: 30px;
+            line-height: 30px;
+            background: var(--semi-color-primary-light-default);
+            outline: 1px solid var(--semi-color-primary-light-active);
+        }
+    }
+}
+`
+    }/>
+}
+
+```
+
+
+### 支持其他语言
+
+支持 297 种语言,除去 `JavaScript` `CSS` `类 C` `html` `svg` 外,支持其他语言需要手动引入配置。 
+
+
+例如,高亮用于编写 GTK 程序前端 UI 的 Vala 语言,需要引入 `prism-vala.js` 
+
+```javascript
+import "prismjs/components/prism-vala.js"
+```
+
+```jsx live=true dir=column
+import { CodeHighlight } from '@douyinfe/semi-ui';
+import "prismjs/components/prism-vala.js"
+
+function Demo() {
+    return <CodeHighlight
+        language={"vala"} code={
+        `public class ExampleApp : Gtk.Application {
+    public ExampleApp () {
+        Object (application_id: "com.example.App");
+    }
+
+    public override void activate () {
+        var win = new Gtk.ApplicationWindow (this);
+
+        var btn = new Gtk.Button.with_label ("Hello World");
+        btn.clicked.connect (win.close);
+
+        win.child = btn;
+        win.present ();
+    }
+
+    public static int main (string[] args) {
+        var app = new ExampleApp ();
+        return app.run (args);
+    }
+}
+`
+    }/>
+}
+
+```
+
+
+### 自定义主题
+
+设置 `defaultTheme={false}` 关闭默认主题,然后手动将需要的主题的 css 文件拷贝并放入项目中引入即可。
+一些主题可在 node_modules 内 prismjs/themes 下找到,你也可以在网上搜索其他中意的主题。
+
+
+
+### API
+
+| 属性        | 说明                        | 类型     | 默认值  |
+|-----------|---------------------------|--------|------|
+| className | 类名                        | string | -    |
+| code      | 代码纯文本                     | string | -    |
+| defaultTheme | 是否使用默认主题,添加自己的主题时设置 false | bool | true |
+| language  | 语言类型                      | string | -    |
+|lineNumber | 是否开启行数显示                  | boolean | true |
+| style | 样式                        | CSSProperties | -    |
+
+## 设计变量
+
+<DesignToken/>
+
+

+ 163 - 0
content/plus/lottie/index-en-US.md

@@ -0,0 +1,163 @@
+---
+localeCode: en-US
+order: 21
+category: Plus
+title: Lottie Animation
+icon: doc-configprovider
+dir: column
+brief: Display Lottie animation on the web page
+---
+
+## Overview
+
+The Lottie component can render Lottie animations conveniently and simply, and provides a way to obtain global Lottie and animation instances to meet a wider range of configuration needs.
+
+`lottie-web` is used internally to render Lottie animations.
+
+## Usage scenarios
+
+Compared to using `lottie-web` directly, use the Semi Lottie component
+
+- No need to worry about the creation and destruction of animation containers
+- No need to worry about the life cycle of the animation itself
+- Easier to use with React projects
+
+## Demos
+
+### How to import
+
+```jsx
+import { Lottie } from "@douyinfe/semi-ui";
+```
+
+
+
+### Basic Usage
+
+**When the Lottie animation resource JSON is on CDN**
+
+Pass path=your lottie json URL to the `params` props
+
+
+
+```jsx live=true
+import { Lottie } from "@douyinfe/semi-ui";
+import React from "react";
+
+() => {
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+
+    return  <div style={{background:"#e2dfdf"}}>
+        <Lottie params={{ path: jsonURL }} width={"300px"} />
+    </div>;
+};
+
+```
+
+
+**When Lottie animation resource JSON needs to be packaged into the website code**
+
+Pass animationData=your lottie json object into the `params` props (the Demo request JSON below is only for demonstration. In actual projects, json should be manually imported instead of obtained through network requests, so that JSON animation resources can be packaged into the website code)
+
+```jsx live=true
+import { Lottie } from "@douyinfe/semi-ui";
+import React from "react";
+
+() => {
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+    const [data, setData] = useState("");
+
+    useEffect(() => {
+        fetch(jsonURL)
+            .then(resp=>resp.json())
+            .then(setData);
+
+    }, []);
+
+    return <div style={{background:"#e2dfdf"}}>
+        <Lottie params={{ animationData: data }} width={"300px"} />
+    </div>;
+};
+
+```
+
+### Params Other common parameters
+
+`params` will be passed to `lottie.loadAnimation` of `lottie-web` by the component. Please refer to `lottie-web` [documentation](https://github.com/airbnb/lottie-web?tab=readme-ov-file#usage)
+
+Common parameters
+
+```json
+//params
+{
+  container: element, // Rendering container, if not passed, Semi Lottie component will automatically configure and generate
+  renderer: 'svg', // Rendering mode, default SVG
+  loop: true, // Whether to open loop, default true
+  autoplay: true, // Whether to play automatically, default true, when set to false, you need to manually play through the play method on the animation instance
+  path: 'data.json' // URL path of animation JSON file (mutually exclusive with animationData)
+  animationData: {/*...*/} // JSON object of animation (mutually exclusive with animationData)
+  /*...*/
+}
+```
+
+
+### Get the current animation instance
+
+Use `getAnimationInstance` to get the animation instance of the currently playing animation. The instance contains many methods for adjusting various parameters of the animation, such as playing and pausing, getting the current frame number, adjusting the playback speed, etc.
+
+For more information about the methods contained in the animation instance, please refer to the `lottie-web` [documentation](https://github.com/airbnb/lottie-web?tab=readme-ov-file#usage)
+
+```jsx live=true
+import { Lottie } from "@douyinfe/semi-ui";
+import React from "react";
+
+() => {
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+
+    return <div style={{background:"#e2dfdf"}}>
+        <Lottie getAnimationInstance={(animation )=>{console.log(animation);}} params={{ path: jsonURL }} width={"300px"} />;
+    </div>
+};
+```
+
+### Get global Lottie
+
+Use `getLottie` Props to get global lottie, or use the static method `Lottie.getLottie` on the Semi Lottie component to get global lottie
+
+For more information about the methods on the global lottie, please refer to the `lottie-web` [documentation](https://github.com/airbnb/lottie-web?tab=readme-ov-file#usage)
+
+```jsx live=true
+import { Lottie } from "@douyinfe/semi-ui";
+import React from "react";
+
+()=>{
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+
+    console.log("lottie", Lottie.getLottie());
+
+    return <div style={{background:"#e2dfdf"}}>
+        <Lottie getLottie={lottie=>console.log("lottie", lottie)} params={{ path: jsonURL }} width={"300px"} />;
+    </div>
+};
+
+```
+
+
+
+### API
+
+| Property | Description | Type | Default value |
+|-----------|----------------------|--------------------------------------|-----|
+| className | Class name | string | - |
+| params | Used to configure animation related parameters | Same as lottie-web lottie.loadAnimation input | - |
+| getAnimationInstance | Get the current animation AnimationItem | (animation:AnimationItem)=>void | - |
+| getLottie | Get the global Lottie | (lottie: Lottie)=>void | - |
+| style | Style | CSSProperties | - |
+
+## Design Tokens
+
+<DesignToken/>
+
+
+
+

+ 163 - 0
content/plus/lottie/index.md

@@ -0,0 +1,163 @@
+---
+localeCode: zh-CN
+order: 21
+category: Plus
+title: Lottie 动画
+icon: doc-configprovider
+dir: column
+brief: 在网页中展示 Lottie 动画
+---
+
+## 概述
+
+
+Lottie 组件能够便捷简单地渲染 Lottie 动画,同时提供方式获取到全局 Lottie 和 动画实例满足更广泛的配置需求。
+
+内部使用 `lottie-web` 渲染 Lottie 动画。
+
+## 使用场景
+
+相较于直接使用 `lottie-web`,使用 Semi Lottie 组件
+
+- 无需关心动画容器的创建与销毁
+- 无需关心动画本身的生命周期
+- 更易和 React 项目结合使用
+
+## 代码演示
+
+### 如何引入
+
+```jsx
+import { Lottie } from "@douyinfe/semi-ui";
+```
+
+
+
+### 基本用法
+
+
+**当 Lottie 动画资源 JSON 在 CDN 上时**
+
+向 `params` props 里传入 path= 你的 lottie json 的 URL 即可
+
+```jsx live=true
+import { Lottie } from "@douyinfe/semi-ui";
+import React from "react";
+
+() => {
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+
+    return  <div style={{background:"#e2dfdf"}}>
+            <Lottie params={{ path: jsonURL }} width={"300px"} />
+        </div>;
+};
+
+```
+
+**当 Lottie 动画资源 JSON 需要被打包到网站代码中时**
+
+向 `params` props 里传入 animationData= 你的 lottie json 对象即可 (下方 Demo 请求 JSON 是仅作为演示,实际项目中 json 应当被手动 import,而不是通过网络请求获取,这样 JSON 动画资源才会被打包进网站代码)
+
+```jsx live=true
+import { Lottie } from "@douyinfe/semi-ui";
+import React from "react";
+
+() => {
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+    const [data, setData] = useState("");
+
+    useEffect(() => {
+        fetch(jsonURL)
+            .then(resp=>resp.json())
+            .then(setData);
+       
+    }, []);
+
+    return <div style={{background:"#e2dfdf"}}>
+            <Lottie params={{ animationData: data }} width={"300px"} />
+        </div>;
+};
+
+```
+
+### Params 其他常用参数
+
+`params` 会被组件传入 `lottie-web` 的 `lottie.loadAnimation` 中,可以参考 `lottie-web` [文档](https://github.com/airbnb/lottie-web?tab=readme-ov-file#usage)
+
+常用参数
+
+```json
+//params
+{
+    container: element, // 渲染容器,不传则由 Semi Lottie 组件自动配置并生成
+    renderer: 'svg', // 渲染方式, 默认 SVG
+    loop: true, // 是否开启循环,默认 true
+    autoplay: true, // 是否自动播放,默认 true,设置为 false 时需要通过动画实例上的 play 方法手动播放
+    path: 'data.json' // 动画 JSON 文件的 URL 路径 (与 animationData 互斥)
+    animationData: {/*...*/} // 动画的 JSON 对象 (与 animationData 互斥)
+    /*...*/
+}
+```
+
+
+### 获取当前动画实例
+
+使用 `getAnimationInstance` 获取当前播放的动画的 animation 实例,实例上含有许多方法用于调整动画的各项参数,例如播放暂停,获取当前帧序号,调整播放速度等。
+
+关于动画实例上含有的方法,更多信息可以参考 `lottie-web` [文档](https://github.com/airbnb/lottie-web?tab=readme-ov-file#usage)
+
+```jsx live=true
+import { Lottie } from "@douyinfe/semi-ui";
+import React from "react";
+
+() => {
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+
+    return <div style={{background:"#e2dfdf"}}>
+        <Lottie getAnimationInstance={(animation )=>{console.log(animation);}} params={{ path: jsonURL }} width={"300px"} />;
+    </div>
+};
+```
+
+### 获取全局 Lottie
+
+使用 `getLottie` Props 获取全局 lottie,也可以使用 Semi Lottie 组件上的静态方法 `Lottie.getLottie` 来获取全局 lottie
+
+关于全局 lottie 上含有的方法,更多信息可以参考 `lottie-web` [文档](https://github.com/airbnb/lottie-web?tab=readme-ov-file#usage)
+
+
+```jsx live=true
+import { Lottie } from "@douyinfe/semi-ui";
+import React from "react";
+
+()=>{
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+    
+    console.log("lottie", Lottie.getLottie());
+    
+    return <div style={{background:"#e2dfdf"}}>
+        <Lottie getLottie={lottie=>console.log("lottie", lottie)} params={{ path: jsonURL }} width={"300px"} />;
+    </div>
+};
+
+```
+
+
+
+### API
+
+| 属性        | 说明                   | 类型                                   | 默认值 |
+|-----------|----------------------|--------------------------------------|-----|
+| className | 类名                   | string                               | -   |
+| params    | 用于配置动画相关参数           | 同 lottie-web lottie.loadAnimation 入参 | -   |
+| getAnimationInstance    | 获取当前动画 AnimationItem | (animation:AnimationItem)=>void      | -   |
+| getLottie       | 获取全局 Lottie          | (lottie: Lottie)=>void               | -   |
+| style     | 样式                   | CSSProperties                        | -   |
+
+## 设计变量
+
+<DesignToken/>
+
+
+
+

+ 151 - 0
content/plus/markdownrender/index-en-US.md

@@ -0,0 +1,151 @@
+---
+localeCode: en-US
+order: 20
+category: Plus
+title:  Markdown Render
+icon: doc-configprovider
+dir: column
+brief: Instantly render Markdown and MDX in web pages
+---
+
+## When to use
+
+Markdown is a document markup language that can implement basic common rich text functions such as titles, pictures, tables, links, bolding, etc. through simple tags.
+MDX is based on Markdown and allows the introduction of JSX to achieve more complex and customized document writing and display requirements.
+
+The MarkdownRender component provided by Semi supports rendering Markdown and MDX. No special configuration is required. By passing in plain text, rich text content that conforms to Semi style specifications can be rendered.
+
+
+Usually used in the following scenarios:
+- Document station writing and rendering
+- Front-end rendering when the server dynamically generates rich text content
+- A light interactive website that focuses on content display
+
+
+## Demos
+
+### How to import
+
+```jsx
+import { MarkdownRender } from '@douyinfe/semi-ui';
+import * as SemiMarkdownComponents from "@douyinfe/semi-ui/markdownRender/components"
+```
+
+
+
+### Basic usage
+After importing MarkdownRender, just pass in Markdown or MDX plain text directly.
+
+Introducing SemiMarkdownComponents and passing it into MarkdownRender, basic elements in the document such as text, titles, hyperlinks, pictures, tables, etc. will be rendered using Semi components. Not everyone needs these document elements, so in order to reduce the package size, they need to be introduced manually.
+
+```jsx live=true dir="column"
+import { MarkdownRender } from '@douyinfe/semi-ui';
+import * as SemiMarkdownComponents from "@douyinfe/semi-ui/markdownRender/components"
+
+
+function Demo(){
+    return <MarkdownRender components={SemiMarkdownComponents} mdxRaw={`
+# Title No. 1
+## Title No. 2
+### Title No. 3
+
+The main text content is ordinary text, and it can also be **bold**~~strikethrough~~ and <u>underline</u> [Hyperlink](https://semi.design) etc. Basic syntax of Markdown and HTML Supported rich text
+
+#### List syntax support
+- Eat well
+- sleep well
+- Have fun
+- Study hard
+- have a good chat
+- Have a good argument
+- Live an ordinary day
+
+![Colorful World](https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/colorful.jpg)
+    
+| Support | Markdown tables | c | d |
+| - | :- | -: | :-: |
+| 1 | 2 | 3 | 4 |
+| 21 | 22 | 23 | 24 |
+| 31 | 32 | 33 | 34 |
+| 41 | 42 | 43 | 44 |
+    `}/>
+}
+
+```
+
+### Modify element style
+
+You can arbitrarily replace the display effect of document elements in Markdown or MDX documents. Just pass your rendering component override to the `components` props.
+
+For example, now you need to set the color of all headings No. 1 to the main color
+
+```jsx live=true
+import { MarkdownRender, Typography } from '@douyinfe/semi-ui';
+import * as SemiMarkdownComponents from "@douyinfe/semi-ui/markdownRender/components"
+
+
+function Demo() {
+    const components ={...SemiMarkdownComponents};
+    
+    components['h1'] = ({children}) => <Typography.Title heading={1} style={{color:"var(--semi-color-primary)"}}>{children}</Typography.Title>
+    
+    return <MarkdownRender mdxRaw={`# Primary Color Title`} components={components} />
+}
+
+
+```
+
+Basic element tag support that can be overridden `a blockquote br code em h1 h2 h3 h4 h5 hr img li ol p pre strong ul table`
+
+
+
+### Add custom components
+
+By passing in custom components to `components` Props, you can write JSX directly in Markdown, and the component will be rendered to the final page, supporting JS events.
+The default Markdown components can be obtained from `MarkdownRender.defaultComponents` and can be used for secondary packaging.
+
+<Notice type="primary" title="Note">
+   <div>Try to ensure that the JSX code in the rendered Markdown is trustworthy to prevent XSS. </div>
+</Notice>
+
+
+```jsx live=true
+import { Button, MarkdownRender, Typography } from '@douyinfe/semi-ui';
+import * as SemiMarkdownComponents from "@douyinfe/semi-ui/markdownRender/components"
+
+
+function Demo() {
+    const components = { ...SemiMarkdownComponents };
+
+    components['MyButton'] = ({ children,onClick }) => {
+        return <Button type={"primary"} onClick={onClick} style={{marginBottom:"12px"}}> {children} </Button>
+    }
+
+    return <MarkdownRender 
+        mdxRaw={`
+#### Below is a button rendered in Markdown
+<MyButton onClick={()=>alert("MyButton is clicked")}>MyButton click me</MyButton>
+
+Just write JSX directly in Markdown
+        `}
+        components={{...MarkdownRender.defaultComponents,...components}} />
+}
+
+
+```
+
+
+### API
+
+| Properties | Description | Type | Default Value |
+|------------|-----------------------------|------ ------------------------|-------|
+| className | class name | string | - |
+| components | Used to override Markdown elements and add custom components | Record<string, JSXElementConstructor> | - |
+| format | The incoming raw type, whether it is pure Markdown | 'md'\|'mdx' | 'mdx' |
+| raw | plain text in Markdown or MDX | string | - |
+| style | style | CSSProperties | - |
+
+## Design Token
+
+<DesignToken/>
+

+ 190 - 0
content/plus/markdownrender/index.md

@@ -0,0 +1,190 @@
+---
+localeCode: zh-CN
+order: 20
+category: Plus
+title:  Markdown 渲染器
+icon: doc-configprovider
+dir: column
+brief: 在网页中即时渲染 Markdown 和 MDX
+---
+
+## 使用场景
+
+Markdown 是一种文档标记语言,可以通过简单的标记实现例如标题,图片,表格,链接,加粗等基本常用富文本功能。
+MDX 是在 Markdown 基础上,允许引入 JSX 实现更加复杂定制化的文档撰写与展示需求。
+
+Semi 提供的 MarkdownRender 组件支持渲染 Markdown 和 MDX,无需特别配置,传入纯文本即可渲染出符合 Semi 样式规范的富文本内容。
+
+
+通常用于下列场景:
+- 文档站编写与渲染
+- 服务端动态生成富文本内容时,前端渲染
+- 偏内容展示的轻交互网站
+
+
+## 代码演示
+
+### 如何引入
+
+```jsx
+import { MarkdownRender } from '@douyinfe/semi-ui';
+```
+
+
+
+### 基本用法
+导入 MarkdownRender 后,直接传入 Markdown 或 MDX 纯文本即可。
+
+注意因为 `<` `{` 等符号是合法的 JSX 符号会被判定为代码,无法直接渲染,需要使用 `\` 转义,如果你只需要渲染纯 Markdown,参考下方仅渲染 Markdown 一节。
+
+```jsx live=true dir="column"
+import { MarkdownRender } from '@douyinfe/semi-ui';
+
+
+function Demo(){
+    return <MarkdownRender raw={`
+## 
+
+正文内容是普通的文本,也可以**加粗**~~删除线~~和<u>下划线</u> [超链接](https://semi.design) 等 Markdown 与 HTML 的基本语法所支持的富文本,也支持 emoji 🍰
+
+
+部分符号需要转义 \\{\\} \\<\\> ...
+
+<br/>
+<br/>
+---
+#### Semi Design DSM
+[Semi DSM](https://semi.design/dsm) 是 Semi Design 提供的设计系统管理工具(Design System Management),支持全局、组件级别的样式定制,并在 Figma 和前端代码之间保持同步  
+适用于各种规模的团队,无论你是需要简化工作流程,提高团队协作,还是增加生产力,我们都有适合你的功能
+
+##### 中大型企业
+- 多达 3000+ Design Token,深入每一处细节的定制可能,色彩,阴影,边距,圆角,动效,渲染结构均可自由定制,告别 ~~CSS 硬编码~~
+- 功能强大,经过抖音内部数千项目验证过的 UI lib,轻松应对各类复杂场景
+- A11y 无障碍友好,国际化功能完备
+- 面向社区建设,完全开源,无使用限制
+- 从 designOps 到 devOps,自动化工作流,Figma UI Kit 一键刷入主题,生成 Style Guideline,研发一行 npm 代码配置接入
+
+##### 初创企业
+- 无需从 0 到 1 投入大量研发资源,快速复用开源社区优秀方案, 低成本快速定制具备品牌特色的设计系统。
+- 一键支持暗色模式生成,支持根据品牌色快速生成包含 320 个全色阶、兼容深/浅两种模式的色彩系统,并支持动态切换
+- 不断进化,DSM + Semi Design 组件由<u>抖音前端架构团队</u>专业维护,已稳定迭代五年+,值得信赖
+
+##### 自由设计师/个人开发者
+- 低成本快速创建风格各异的设计系统,更少时间,更快交付
+- 研发接入友好,无需反复沟通,交付npm包产物,一键完成代码接入
+
+
+![DSM](https://semi.design/dsm_manual/content/introduction/start/start-intro.png)
+
+---
+
+#### MarkdownRender 渲染列表语法
+- 好好地吃饭
+- 好好地睡觉
+- 好好地游玩
+- 好好地学习
+- 好好地聊天
+- 好好地吵架
+- 过着平凡普通的每日 
+
+| 支持 | Markdown 表格 |  c |  d  |
+| - | :- | -: | :-: |
+| 1 | 2 | 3 | 4 |
+| 21 | 22 | 23 | 24 |
+| 31 | 32 | 33 | 34 |
+| 41 | 42 | 43 | 44 |
+
+    `}/>
+}
+
+```
+
+### 修改元素样式
+
+你可以任意替换 Markdown 或 MDX 文档中的文档元素的显示效果,只需向 `components` props 中传入你的渲染组件覆盖即可
+
+比如,现在需要将所有1号标题的颜色设置成主色
+
+```jsx live=true
+import { MarkdownRender, Typography } from '@douyinfe/semi-ui';
+
+
+function Demo() {
+    const components = {}
+    
+    components['h1'] = ({children}) => <Typography.Title heading={1} style={{color:"var(--semi-color-primary)"}}>{children}</Typography.Title>
+    
+    return <MarkdownRender raw={`# 从 Semi Design 到 Any Design  快速定义你的设计系统,并应用在设计稿和代码中`} components={components} />
+}
+
+
+```
+
+可以覆盖的基本元素 tag 支持 `a blockquote br code em h1 h2 h3 h4 h5 hr img li ol p pre strong ul table`
+
+### 仅纯 Markdown
+当你渲染的 Markdown 仅仅是纯 markdown,不包含任何 JSX 代码时,可传入 `format="md"` 来开启仅 Markdown 模式,在这种模式下无需转义特殊字符
+
+```jsx live=true
+import { MarkdownRender, Typography } from '@douyinfe/semi-ui';
+
+
+function Demo() {
+    const components ={};
+    
+    components['h1'] = ({children}) => <Typography.Title heading={1} style={{color:"var(--semi-color-primary)"}}>{children}</Typography.Title>
+    
+    return <MarkdownRender raw={`无需转义的符号{}<> ...`} format="md" components={components} />
+}
+
+```
+
+### 添加自定义组件
+
+通过传入自定义组件到 `components` Props,能够实现在 Markdown 中直接书写 JSX,组件会被渲染到最终页面上,支持 JS 事件。
+默认的 Markdown 组件可从 `MarkdownRender.defaultComponents` 中获取,可以用于二次封装。
+
+<Notice type="primary" title="注意事项">
+  <div>注意尽量确保被渲染的 Markdown 内 JSX 代码可信,防止 XSS。</div>
+</Notice>
+
+
+```jsx live=true
+import { Button, MarkdownRender, Typography } from '@douyinfe/semi-ui';
+
+function Demo() {
+    const components = {};
+
+    components['MyButton'] = ({ children,onClick }) => {
+        return <Button type={"primary"} onClick={onClick} style={{marginBottom:"12px"}}> {children} </Button>
+    }
+
+    return <MarkdownRender 
+        raw={`
+#### 下面是一个渲染在 Markdown 中的按钮
+<MyButton onClick={()=>alert("点击了 MyButton")}>MyButton 点我</MyButton>
+
+直接在 Markdown 中书写 JSX 即可
+        `}
+        components={{...MarkdownRender.defaultComponents,...components}}
+        />
+}
+
+
+```
+
+
+### API
+
+| 属性         | 说明                         | 类型                                    | 默认值   |
+|------------|----------------------------|---------------------------------------|-------|
+| className | 类名    | string | -   |
+| components | 用于覆盖 Markdown 元素,也可添加自定义组件 | Record<string, JSXElementConstructor> | -     |
+| format     | 传入的 raw 类型,是否是纯 Markdown   | 'md'\|'mdx'                           | 'mdx' |
+| raw        | Markdown 或 MDX 的纯文本        | string                                | -     |
+| style | 样式 | CSSProperties | - |
+
+## 设计变量
+
+<DesignToken/>
+

+ 26 - 4
gatsby-node.js

@@ -15,8 +15,8 @@ const numHash = Math.round(Math.random()*1000000);
 const glob = require('glob');
 
 
-function resolve(dir) {
-    return path.resolve(__dirname, dir);
+function resolve(...dirs) {
+    return path.resolve(__dirname, ...dirs);
 }
 const getLocale = path => {
     let pathname = path || window.location.pathname;
@@ -91,10 +91,21 @@ exports.onCreateWebpackConfig = ({ stage, rules, loaders, plugins, actions }) =>
             }
         );
     }
-
+    console.log(["node_modules",resolve("node_modules")]);
     actions.setWebpackConfig({
+        externals:{
+          "node:url":"url",
+            "node:path":"path",
+            "node:process":"process",
+        },
         resolve: {
             alias: {
+                "vfile/do-not-use-conditional-minurl":isSSR ? "vfile/lib/minurl.js":"vfile/lib/minurl.browser.js",
+                "vfile/do-not-use-conditional-minproc":isSSR?"vfile/lib/minproc.js":"vfile/lib/minproc.browser.js",
+                "vfile/do-not-use-conditional-minpath": isSSR ? "vfile/lib/minpath.js":"vfile/lib/minpath.browser.js",
+                "estree-util-visit/do-not-use-color": isSSR ? "estree-util-visit/lib/color.node.js":"estree-util-visit/lib/color.js",
+                "devlop":"devlop/lib/default.js",
+                "unist-util-visit-parents/do-not-use-color": isSSR?"unist-util-visit-parents/lib/color.node.js":"unist-util-visit-parents/lib/color.js",
                 'semi-site-header': process.env.SEMI_SITE_HEADER || '@douyinfe/semi-site-header',
                 'semi-site-banner': process.env.SEMI_SITE_BANNER || '@douyinfe/semi-site-banner',
                 'univers-webview': process.env.SEMI_SITE_UNIVERS_WEBVIEW || resolve('packages/semi-ui'),
@@ -113,6 +124,7 @@ exports.onCreateWebpackConfig = ({ stage, rules, loaders, plugins, actions }) =>
                 'locale': resolve('src/locale'),
                 'src': resolve('src')
             },
+            extensions:["*",".mjs",".js",".json"]
         },
         module: {
             rules: [
@@ -139,7 +151,12 @@ exports.onCreateWebpackConfig = ({ stage, rules, loaders, plugins, actions }) =>
                     use: [...srcScssUse, resolve('packages/semi-webpack/lib/semi-theme-loader.js')],
                 },
                 {
-                    test: [/\.jsx?$/],
+                  test:/\.m?js/,
+                  include: [/micromark-util-sanitize-uri/,/mdast-util-from-markdown/,/micromark/,/mdast-util-to-markdown/,/semi-foundation\/node_modules\/@mdx-js/],
+                  use: ["esbuild-loader"]
+                },
+                {
+                    test: [/\.jsx?$/,/\.mjs/],
                     include: [path.resolve(__dirname, 'src')],
                     use: {
                         loader: 'esbuild-loader',
@@ -159,6 +176,11 @@ exports.onCreateWebpackConfig = ({ stage, rules, loaders, plugins, actions }) =>
                             target: 'esnext' // Syntax to compile to (see options below for possible values)
                         },
                     },
+                },
+                {
+                    test: /\.mjs$/,
+                    include: /node_modules/,
+                    type: "javascript/auto"
                 }
             ],
         },

+ 3 - 3
package.json

@@ -47,10 +47,10 @@
     },
     "dependencies": {
         "@dnd-kit/modifiers": "^7.0.0",
-        "@douyinfe/semi-site-banner": "^0.1.3",
-        "@douyinfe/semi-site-doc-style": "0.0.1",
+        "@douyinfe/semi-site-banner": "^0.1.5",
+        "@douyinfe/semi-site-doc-style": "0.0.4",
         "@douyinfe/semi-site-header": "^0.0.29",
-        "@douyinfe/semi-site-markdown-blocks": "^0.0.9",
+        "@douyinfe/semi-site-markdown-blocks": "^0.0.14",
         "@mdx-js/mdx": "1.6.22",
         "@mdx-js/react": "^1.6.22",
         "@storybook/react-webpack5": "^7.0.7",

+ 203 - 0
packages/semi-foundation/codeHighlight/codeHighlight.scss

@@ -0,0 +1,203 @@
+@import './variables.scss';
+
+$module: #{$prefix}-codeHighlight;
+
+.#{$module}{
+  &-defaultTheme{
+    /**
+     * prism.js default theme for JavaScript, CSS and HTML
+     * Based on dabblet (http://dabblet.com)
+     * @author Lea Verou
+     */
+
+    pre[class*="language-"],
+    code[class*="language-"]{
+      color: var(--semi-color-text-0);
+      font-size: 13px;
+      text-shadow: none;
+      // font-family: 'Inconsolata', Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
+      font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
+      direction: ltr;
+      text-align: left;
+      white-space: pre;
+      word-spacing: normal;
+      word-break: normal;
+      line-height: 1.5;
+      -moz-tab-size: 4;
+      -o-tab-size: 4;
+      tab-size: 4;
+
+      -moz-hyphens: none;
+      hyphens: none;
+    }
+
+    pre[class*="language-"]::selection,
+    code[class*="language-"]::selection,
+    pre[class*="language-"]::mozselection,
+    code[class*="language-"]::mozselection {
+      text-shadow: none;
+      background: #b3d4fc;
+    }
+
+
+    pre[class*="language-"]{
+      padding: 1em;
+      margin: .5em 0;
+      overflow: auto;
+      background: var(--semi-color-tertiary-light-default);
+    }
+
+    :not(pre)>code[class*="language-"] {
+      // padding: .1em .3em;
+      display: block;
+      border-radius: .3em;
+      color: #895fe2;
+      background: #f9f7f9;
+    }
+
+    pre{
+      .namespace {
+        opacity: .7;
+      }
+
+      .token.comment,
+      .token.prolog,
+      .token.doctype,
+      .token.cdata {
+        color: #6b7075;
+      }
+
+      .token.punctuation {
+        color: rgba(var(--semi-grey-8), 1),
+      }
+
+      .token.property,
+      .token.tag,
+      .token.boolean,
+      .token.number,
+      .token.constant,
+      .token.symbol,
+      .token.deleted {
+        color: rgba(var(--semi-purple-6), 1);
+      }
+
+      .token.selector,
+      .token.attr-name,
+      .token.string,
+      .token.char,
+      .token.builtin,
+      .token.inserted {
+        color: rgba(var(--semi-green-6), 1);
+      }
+
+      .token.operator,
+      .token.entity,
+      .token.url,
+      .language-css .token.string,
+      .style .token.string {
+        color: rgba(var(--semi-grey-8), 1),
+      }
+
+      .token.atrule,
+      .token.attr-value,
+      .token.keyword {
+        color: rgba(var(--semi-purple-6), 1);
+      }
+
+      .token.function {
+        color: rgba(var(--semi-violet-6), 1);
+      }
+
+      .token.regex,
+      .token.important,
+      .token.variable {
+        color: #d0955f;
+      }
+
+      .token.important,
+      .token.bold {
+        font-weight: bold;
+      }
+
+      .token.italic {
+        font-style: italic;
+      }
+
+      .token.entity {
+        cursor: help;
+      }
+
+    }
+
+    pre[data-line] {
+      position: relative;
+    }
+
+    pre[class*="language-"]>code[class*="language-"] {
+      position: relative;
+      z-index: 1;
+    }
+
+    .line-highlight {
+      position: absolute;
+      left: 0;
+      right: 0;
+      padding: inherit 0;
+      margin-top: 1em;
+      background: #ebf4ff;
+      box-shadow: inset 5px 0 0 #0064d2;
+      z-index: 0;
+      pointer-events: none;
+      line-height: inherit;
+      white-space: pre;
+    }
+  }
+
+  //---- line number ----
+
+
+  pre[class*="language-"].line-numbers {
+    position: relative;
+    padding-left: 3.8em;
+    counter-reset: linenumber;
+  }
+
+  pre[class*="language-"].line-numbers > code {
+    position: relative;
+    white-space: inherit;
+  }
+
+  .line-numbers .line-numbers-rows {
+    position: absolute;
+    pointer-events: none;
+    top: 0;
+    font-size: 100%;
+    left: -3.8em;
+    width: 3em; /* works for line-numbers below 1000 lines */
+    letter-spacing: -1px;
+    border-right: 1px solid #999;
+
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+
+  }
+
+  .line-numbers-rows > span {
+    display: block;
+    counter-increment: linenumber;
+  }
+
+  .line-numbers-rows > span:before {
+    content: counter(linenumber);
+    color: #999;
+    display: block;
+    padding-right: 0.8em;
+    text-align: right;
+  }
+
+}
+
+
+

+ 15 - 0
packages/semi-foundation/codeHighlight/constants.ts

@@ -0,0 +1,15 @@
+import { BASE_CLASS_PREFIX } from '../base/constants';
+
+const cssClasses = {
+    PREFIX: `${BASE_CLASS_PREFIX}-codeHighlight`,
+};
+
+const numbers = {
+
+};
+
+const strings = {
+
+} as const;
+
+export { cssClasses, numbers, strings };

+ 45 - 0
packages/semi-foundation/codeHighlight/index.ts

@@ -0,0 +1,45 @@
+import BaseFoundation, { DefaultAdapter } from '../base/foundation';
+import Prism from 'prismjs';
+import cls from "classnames";
+import "prismjs/plugins/line-numbers/prism-line-numbers.min.js";
+
+Prism.manual = true;
+
+export interface CodeHighlightBaseProps {
+    code: string;
+    language: string;
+    lineNumber: boolean
+}
+
+export interface CodeHighlightBaseState {
+
+}
+
+export interface CodeHighlightAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
+
+}
+
+
+class CodeHighlightFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<CodeHighlightAdapter<P, S>, P, S> {
+    constructor(adapter: CodeHighlightAdapter<P, S>) {
+        super({ ...adapter });
+    }
+
+
+    highlightCode = (ele: HTMLElement, language: string) => {
+        let className = ele.className;
+        const languageClassName = `language-${language}`;
+        if (!className.includes(languageClassName)) {
+            className = cls(className, languageClassName);
+        }
+        if (this.getProp("lineNumber")) {
+            className = cls(className, "line-numbers");
+        }
+        ele.className = className;
+        Prism.highlightElement(ele, false);
+    }
+
+}
+
+
+export default CodeHighlightFoundation;

+ 0 - 0
packages/semi-foundation/codeHighlight/variables.scss


+ 17 - 0
packages/semi-foundation/lottie/constants.ts

@@ -0,0 +1,17 @@
+import { BASE_CLASS_PREFIX } from '../base/constants';
+
+
+
+const cssClasses = {
+    PREFIX: `${BASE_CLASS_PREFIX}-lottie`,
+};
+
+const strings = {
+
+};
+
+const numbers = {
+
+};
+
+export { cssClasses, strings, numbers };

+ 60 - 0
packages/semi-foundation/lottie/foundation.ts

@@ -0,0 +1,60 @@
+import BaseFoundation, { DefaultAdapter } from "../base/foundation";
+import lottie, { AnimationItem } from "lottie-web";
+import { ArgsType } from "../collapse/foundation";
+
+export interface LottieAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
+    getContainer: () => Element;
+    getLoadParams: () => ArgsType<typeof lottie.loadAnimation>[0]
+}
+
+export interface LottieBaseProps {
+    width?: string;
+    height?: string;
+    params: ArgsType<typeof lottie.loadAnimation>[0];
+    getAnimationInstance?: (instance: AnimationItem|null) => void;
+    getLottie?: (lottiePKG: typeof lottie) => void
+
+}
+
+export interface LottieBaseState {
+
+
+}
+
+class LottieFoundation <P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<LottieAdapter<P, S>, P, S> {
+
+    animation: null|AnimationItem = null
+
+    constructor(adapter: LottieAdapter<P, S>) {
+        super({ ...LottieFoundation.defaultAdapter, ...adapter });
+    }
+
+
+    static getLottie = ()=>{
+        return lottie;
+    }
+
+    init(lifecycle?: any) {
+        super.init(lifecycle);
+        this.animation = lottie.loadAnimation(this._adapter.getLoadParams());
+        this.getProp("getAnimationInstance")?.(this.animation);
+        this.getProp("getLottie")?.(LottieFoundation.getLottie());
+    }
+
+    handleParamsUpdate = ()=>{
+        this.animation.destroy();
+        this.animation = lottie.loadAnimation(this._adapter.getLoadParams());
+        this.getProp("getAnimationInstance")?.(this.animation);
+    }
+
+    destroy() {
+        super.destroy();
+        this.animation.destroy();
+    }
+
+
+
+
+}
+
+export default LottieFoundation;

+ 11 - 0
packages/semi-foundation/markdownRender/constants.ts

@@ -0,0 +1,11 @@
+import { BASE_CLASS_PREFIX } from '../base/constants';
+
+const cssClasses = {
+    PREFIX: `${BASE_CLASS_PREFIX}-markdownRender`,
+};
+
+const strings = {
+
+};
+
+export { cssClasses, strings };

+ 69 - 0
packages/semi-foundation/markdownRender/foundation.ts

@@ -0,0 +1,69 @@
+import BaseFoundation, { DefaultAdapter } from '../base/foundation';
+import { CompileOptions, evaluate, compile, EvaluateOptions, evaluateSync, RunOptions } from '@mdx-js/mdx';
+import { MDXProps } from 'mdx/types';
+import remarkGfm from 'remark-gfm';
+export interface MarkdownRenderAdapter <P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
+    getRuntime: () => any
+
+}
+
+
+
+
+export interface MarkdownRenderBaseProps{
+    raw: string;
+    components: MDXProps['components'];
+    format: "md"|"mdx"
+}
+
+
+export interface MarkdownRenderBaseState{
+    MDXContentComponent: any
+}
+
+class MarkdownRenderFoundation extends BaseFoundation<MarkdownRenderAdapter> {
+
+    private getOptions = ()=>{
+        return {
+            evaluateOptions: {
+                remarkPlugins: [remarkGfm],
+                format: this.getProp("format")
+            },
+            compileOptions: {
+                format: this.getProp("format")
+            },
+            runOptions: {
+            }
+        } as {
+            evaluateOptions: EvaluateOptions;
+            compileOptions: CompileOptions;
+            runOptions: RunOptions
+        };
+    }
+
+    compile = async (mdxRaw: string)=>{
+        return await compile(mdxRaw, this.getOptions().compileOptions);
+    }
+
+    evaluate = async (mdxRaw: string)=>{
+        return (await evaluate(mdxRaw, {
+            ...this.getOptions().runOptions,
+            ...this.getOptions().evaluateOptions,
+            ...this._adapter.getRuntime()
+        })).default;
+    }
+
+    evaluateSync = (mdxRaw: string)=>{
+        return ( evaluateSync(mdxRaw, {
+            ...this.getOptions().runOptions,
+            ...this.getOptions().evaluateOptions,
+            ...this._adapter.getRuntime()
+        })).default;
+    }
+
+
+
+}
+
+export default MarkdownRenderFoundation;
+

+ 43 - 0
packages/semi-foundation/markdownRender/markdownRender.scss

@@ -0,0 +1,43 @@
+@import "./variables.scss";
+
+$module: #{$prefix}-markdownRender;
+
+.#{$module} {
+
+    &-simple-code{
+        background: $color-markdownRender_simpleCode-bg;
+        color:$color-markdownRender_simpleCode-text;
+    }
+
+    ul, li {
+        color: $color-markdownRender_component_list
+    }
+
+    &-component-image {
+        margin: $spacing-markdownRender_component_image-marginTop $spacing-markdownRender_component_image-marginRight $spacing-markdownRender_component_image-marginBottom $spacing-markdownRender_component_image-marginLeft;
+        max-width: $width-markdownRender_component_image-maxWidth;
+        max-height: $width-markdownRender_component_image-maxHeight;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+
+        &-alt {
+            margin-top: $spacing-markdownRender_component_image_alt-marginTop;
+            text-align: center;
+            color: $color-markdownRender_component_image_alt;
+        }
+    }
+
+    & &-component-header {
+        margin-top: $spacing-markdownRender_component_header-marginTop;
+        margin-bottom: $spacing-markdownRender_component_header-marginBottom;
+    }
+
+    &-component-p {
+        strong {
+            font-weight: $font-weight-bold;
+        }
+    }
+
+
+}

+ 16 - 0
packages/semi-foundation/markdownRender/variables.scss

@@ -0,0 +1,16 @@
+$spacing-markdownRender_component_image-marginLeft: 16px;
+$spacing-markdownRender_component_image-marginRight: 16px;
+$spacing-markdownRender_component_image-marginTop: 16px;
+$spacing-markdownRender_component_image-marginBottom: 16px;
+$width-markdownRender_component_image-maxWidth: 50%;
+$width-markdownRender_component_image-maxHeight: 500px;
+$spacing-markdownRender_component_image_alt-marginTop: 8px;
+
+
+$spacing-markdownRender_component_header-marginTop: 16px;
+$spacing-markdownRender_component_header-marginBottom: 16px;
+
+$color-markdownRender_simpleCode-bg: var(--semi-color-fill-0);
+$color-markdownRender_simpleCode-text: var(--semi-color-text-1);
+$color-markdownRender_component_list: var(--semi-color-text-0);
+$color-markdownRender_component_image_alt: var(--semi-color-tertiary);

+ 6 - 0
packages/semi-foundation/package.json

@@ -8,6 +8,8 @@
     },
     "dependencies": {
         "@douyinfe/semi-animation": "2.61.0",
+        "lottie-web": "^5.12.2",
+        "@mdx-js/mdx": "^3.0.1",
         "async-validator": "^3.5.0",
         "classnames": "^2.2.6",
         "date-fns": "^2.29.3",
@@ -15,6 +17,8 @@
         "fast-copy": "^3.0.1 ",
         "lodash": "^4.17.21",
         "memoize-one": "^5.2.1",
+        "prismjs": "^1.29.0",
+        "remark-gfm": "^4.0.0",
         "scroll-into-view-if-needed": "^2.2.24"
     },
     "keywords": [],
@@ -29,6 +33,8 @@
         "@babel/plugin-transform-runtime": "^7.15.8",
         "@babel/preset-env": "^7.15.8",
         "@types/lodash": "^4.14.176",
+        "@types/mdx": "^2.0.13",
+        "@types/prismjs": "^1.26.3",
         "babel-plugin-lodash": "^3.3.4",
         "del": "^6.0.0",
         "gulp": "^4.0.2",

+ 13 - 0
packages/semi-foundation/pincode/constants.ts

@@ -0,0 +1,13 @@
+import { BASE_CLASS_PREFIX } from '../base/constants';
+
+const cssClasses = {
+    PREFIX: `${BASE_CLASS_PREFIX}-pincode`
+} as const;
+
+const strings = {} as const;
+
+const numbers = {
+
+} as const;
+
+export { cssClasses, strings, numbers };

+ 126 - 0
packages/semi-foundation/pincode/foundation.ts

@@ -0,0 +1,126 @@
+import BaseFoundation, { DefaultAdapter } from '../base/foundation';
+
+
+export interface PinCodeBaseProps {
+    disabled?: boolean;
+    value?: string;
+    format?: "number" | "mixed" | RegExp | ((value: string) => boolean);
+    onChange: (value: string) => void;
+    defaultValue?: string;
+    count?: number;
+    autoFocus?: boolean;
+    onComplete?: (value: string) => void
+}
+
+export interface PinCodeBaseState {
+    valueList: string[];
+    currentActiveIndex: number
+}
+
+export interface PinCodeAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
+    onCurrentActiveIndexChange: (index: number) => Promise<void>|void;
+    notifyValueChange: (values: string[]) => void;
+    changeSpecificInputFocusState: (index: number, state: "blur" | "focus") => void;
+    updateValueList: (newValueList: PinCodeBaseState['valueList']) => Promise<void>|void
+}
+
+
+class PinCodeFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<PinCodeAdapter<P, S>, P, S> {
+
+    constructor(adapter: PinCodeAdapter<P, S>) {
+        super({ ...adapter });
+    }
+
+    static numberReg = /^\d*$/;
+    static mixedReg = /^[0-9a-zA-Z]$/;
+
+
+    handleCurrentActiveIndexChange = (index: number, state: "focus"|"blur")=>{
+        if (state === "focus") {
+            this._adapter.onCurrentActiveIndexChange(index);
+        }
+    }
+
+    completeSingleInput = async (i: number, singleInputValue: string) => {
+        const isControlledComponent = Boolean(this.getProp("value"));
+        await this._adapter.onCurrentActiveIndexChange(i + 1);
+        const valueList = [...this.getState("valueList")];
+        valueList[i] = singleInputValue;
+        if (isControlledComponent) {
+            this._adapter.notifyValueChange(valueList);
+        } else {
+            await this.updateValueList(valueList);
+        }
+
+        const count = this.getProp('count');
+        if (i + 1 > count - 1) {
+            this._adapter.changeSpecificInputFocusState(i, "blur");
+            this.getProp("onComplete")?.(valueList.join(""));
+        } else {
+            this._adapter.changeSpecificInputFocusState(i + 1, "focus");
+        }
+
+    }
+
+    validateValue = (value: string = "") => {
+        const format = this.getProp("format") as PinCodeBaseProps['format'];
+        let validateFunction = (value: string) => true;
+        if (typeof format === "string") {
+            if (format === "number") {
+                validateFunction = (value) => value.length === 0 || PinCodeFoundation.numberReg.test(value);
+            } else if (format === "mixed") {
+                validateFunction = (value: string) => value.length === 0 || PinCodeFoundation.mixedReg.test(value);
+            }
+        } else if (format instanceof RegExp) {
+            validateFunction = (value: string) => (format as RegExp).test(value);
+        } else if (typeof format === "function") {
+            validateFunction = format;
+        }
+        return validateFunction(value);
+    }
+
+    updateValueList = async (newValueList: PinCodeBaseState['valueList']) => {
+        this._adapter.updateValueList(newValueList);
+    }
+
+    handlePaste = async (e: ClipboardEvent, startInputIndex: number)=>{
+        const textWillPaste = e.clipboardData.getData("text");
+        const count = this.getProp("count");
+        for (let i = startInputIndex, charIndex = 0;i < count && charIndex < textWillPaste.length;i++, charIndex++) {
+            const currentChar = textWillPaste[charIndex];
+            if (this.validateValue(currentChar)) {
+                await this.completeSingleInput(i, currentChar);
+            } else {
+                break;
+            }
+        }
+        e.preventDefault();
+    }
+
+    handleKeyDownOnSingleInput = (e: KeyboardEvent, index: number)=>{
+        const valueList = [...this.getState("valueList")];
+        if (e.key === "Backspace") {
+            valueList[index] = "";
+            this.updateValueList(valueList);
+            this._adapter.changeSpecificInputFocusState(Math.max(0, index - 1), "focus");
+            e.preventDefault();
+        } else if (e.key === "Delete") {
+            valueList[index] = "";
+            this.updateValueList(valueList);
+            this._adapter.changeSpecificInputFocusState(Math.min(valueList.length - 1, index + 1), "focus");
+            e.preventDefault();
+        } else if (e.key === "ArrowLeft") {
+            this._adapter.changeSpecificInputFocusState(Math.max(0, index - 1), "focus");
+            e.preventDefault();
+        } else if (e.key === "ArrowRight") {
+            this._adapter.changeSpecificInputFocusState(Math.min(valueList.length - 1, index + 1), "focus");
+            e.preventDefault();
+        }
+
+    }
+
+
+}
+
+
+export default PinCodeFoundation;

+ 41 - 0
packages/semi-foundation/pincode/pincode.scss

@@ -0,0 +1,41 @@
+@import "./variables.scss";
+
+$module: #{$prefix}-pincode;
+
+
+
+.#{$module} {
+    &-wrapper{
+        display: flex;
+
+        .#{$prefix}-input-wrapper{
+            &-small{
+                width: $width-pinCode_input_small;
+                margin-right: $spacing-pinCode_small-marginRight;
+                &:last-child{
+                    margin-right: 0px;
+                }
+            }
+
+            &-default{
+                width: $width-pinCode_input_default;
+                margin-right: $spacing-pinCode_default-marginRight;
+                &:last-child{
+                    margin-right: 0px;
+                }
+            }
+
+            &-large{
+                width: $width-pinCode_input_large;
+                margin-right: $spacing-pinCode_large-marginRight;
+                &:last-child{
+                    margin-right: 0px;
+                }
+            }
+            input{
+                padding: 0;
+                text-align: center;
+            }
+        }
+    }
+}

+ 7 - 0
packages/semi-foundation/pincode/variables.scss

@@ -0,0 +1,7 @@
+$spacing-pinCode_small-marginRight:6px;
+$spacing-pinCode_default-marginRight:8px;
+$spacing-pinCode_large-marginRight:12px;
+
+$width-pinCode_input_small:24px;
+$width-pinCode_input_default:32px;
+$width-pinCode_input_large:42px;

+ 1 - 0
packages/semi-theme-default/package.json

@@ -1,6 +1,7 @@
 {
     "name": "@douyinfe/semi-theme-default",
     "version": "2.61.0",
+    "version": "2.59.0-alpha.6",
     "description": "semi-theme-default",
     "keywords": [
         "semi-theme",

+ 8 - 2
packages/semi-ui/_base/baseComponent.tsx

@@ -16,7 +16,7 @@ export type ValidateStatus = ArrayElement<typeof VALIDATE_STATUS>;
 export interface BaseProps {
     style?: React.CSSProperties;
     className?: string;
-    children?: ReactNode | undefined | any;
+    children?: ReactNode | undefined | any
 }
 
 // eslint-disable-next-line
@@ -81,7 +81,13 @@ export default class BaseComponent<P extends BaseProps = {}, S = {}> extends Com
         return log(text, ...rest);
     }
 
-    getDataAttr(props?: any) {
+    getDataAttr(props: any = this.props) {
         return getDataAttr(props);
     }
+
+    setStateAsync = (state: Partial<S>)=>{
+        return new Promise<void>(resolve=>{
+            this.setState(state as any, resolve);
+        });
+    }
 }

+ 16 - 0
packages/semi-ui/codeHighlight/_story/codeHighlight.stories.jsx

@@ -0,0 +1,16 @@
+import * as React from 'react'
+import CodeHighlight from '../index';
+export default {
+    title: 'CodeHighlightBasic',
+}
+
+export const CodeHighlightBasic = () => {
+
+    return <CodeHighlight language={"javascript"} code={
+        `import * as React from 'react"
+const Test = ()=>{
+return <div>test</div>
+}
+        `
+    }/>
+}

+ 3 - 0
packages/semi-ui/codeHighlight/_story/codeHighlight.stories.tsx

@@ -0,0 +1,3 @@
+import * as React from 'react';
+import { storiesOf } from '@storybook/react';
+

+ 86 - 0
packages/semi-ui/codeHighlight/index.tsx

@@ -0,0 +1,86 @@
+import * as React from 'react';
+import BaseComponent from '../_base/baseComponent';
+import CodeHighlightFoundation, {
+    CodeHighlightAdapter,
+    CodeHighlightBaseProps,
+    CodeHighlightBaseState,
+} from '@douyinfe/semi-foundation/codeHighlight';
+import { CSSProperties } from 'react';
+import "@douyinfe/semi-foundation/codeHighlight/codeHighlight.scss";
+import { getDefaultPropsFromGlobalConfig } from '../_utils';
+import PropTypes from 'prop-types';
+import cls from "classnames";
+import { cssClasses } from "@douyinfe/semi-foundation/codeHighlight/constants";
+
+
+interface CodeHighlightProps extends CodeHighlightBaseProps {
+    className?: string;
+    style?: CSSProperties;
+    defaultTheme?: boolean
+}
+
+
+interface CodeHighlightState extends CodeHighlightBaseState {
+
+}
+
+
+class CodeHighlight extends BaseComponent<CodeHighlightProps, CodeHighlightState> {
+
+    codeRef = React.createRef<HTMLElement>()
+    foundation = new CodeHighlightFoundation(this.adapter)
+    static __SemiComponentName__ = "CodeHighlight";
+
+    static propTypes = {
+        className: PropTypes.string,
+        style: PropTypes.any,
+        code: PropTypes.string,
+        language: PropTypes.string,
+        lineNumber: PropTypes.bool,
+        defaultTheme: PropTypes.bool,
+    }
+
+    static defaultProps = getDefaultPropsFromGlobalConfig(CodeHighlight.__SemiComponentName__, {
+        lineNumber: true,
+        defaultTheme: true
+    })
+
+    constructor(props: CodeHighlightProps) {
+        super(props);
+        this.state = {};
+
+    }
+
+    get adapter(): CodeHighlightAdapter<CodeHighlightProps, CodeHighlightState> {
+        return {
+            ...super.adapter
+        };
+    }
+
+    componentDidMount() {
+        super.componentDidMount();
+        if (this.codeRef.current) {
+            this.foundation.highlightCode(this.codeRef.current, this.props.language);
+        }
+    }
+
+    componentDidUpdate(prevProps: Readonly<CodeHighlightProps>, prevState: Readonly<CodeHighlightState>, snapshot?: any) {
+        if (this.codeRef.current && prevProps.code !== this.props.code || this.props.language !== this.props.language) {
+            this.foundation.highlightCode(this.codeRef.current, this.props.language);
+        }
+    }
+
+    render() {
+        return <div style={this.props.style} className={cls(this.props.className, cssClasses.PREFIX, "semi-light-scrollbar", { [`${cssClasses.PREFIX}-defaultTheme`]: this.props.defaultTheme })} {...this.getDataAttr(this.props)}>
+            <pre>
+                <code ref={this.codeRef}>
+                    {this.props.code}
+                </code>
+            </pre>
+        </div>;
+    }
+
+
+}
+
+export default CodeHighlight;

+ 7 - 1
packages/semi-ui/index.ts

@@ -99,7 +99,13 @@ export {
     ArrayField,
 } from './form';
 
-export { default as Image } from './image'; 
+export { default as Image } from './image';
 export { Preview as ImagePreview } from './image';
 
 export { default as semiGlobal } from "./_utils/semi-global";
+
+export { default as PinCode } from "./pincode";
+
+export { default as MarkdownRender } from "./markdownRender";
+export { default as CodeHighlight } from "./codeHighlight";
+export { default as Lottie } from "./lottie";

+ 27 - 0
packages/semi-ui/lottie/_story/lottie.stories.jsx

@@ -0,0 +1,27 @@
+import React, {useEffect, useState} from 'react';
+import Lottie from "../index";
+
+
+export default {
+  title: 'Lottie',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
+
+export const BasicLottieAnimation = ()=>{
+    const jsonURL = "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/icon-click.json";
+    const [data,setData] = useState("");
+
+    useEffect(() => {
+        (async ()=>{
+            const resp = await fetch(jsonURL);
+            const json = await resp.json();
+            setData(json)
+        })()
+    }, []);
+
+    return <Lottie params={{animationData:data}} width={"300px"}  getAnimationInstance={(animation )=>{console.log(animation)}}/>
+}
+
+

+ 7 - 0
packages/semi-ui/lottie/_story/lottie.stories.tsx

@@ -0,0 +1,7 @@
+import React, { useState } from 'react';
+import { storiesOf } from '@storybook/react';
+
+
+const stories = storiesOf('Lottie', module);
+
+

+ 111 - 0
packages/semi-ui/lottie/index.tsx

@@ -0,0 +1,111 @@
+import * as React from 'react';
+import LottieFoundation, { LottieAdapter, LottieBaseProps, LottieBaseState } from "@douyinfe/semi-foundation/lottie/foundation";
+import BaseComponent from '../_base/baseComponent';
+import { CSSProperties } from "react";
+import cls from "classnames";
+import { cssClasses } from "@douyinfe/semi-foundation/lottie/constants";
+import { isEqual } from "lodash";
+import PropTypes from "prop-types";
+import { getDefaultPropsFromGlobalConfig } from "../_utils";
+
+
+export interface LottieProps extends LottieBaseProps{
+    className?: string;
+    style?: CSSProperties
+}
+
+export interface LottieState extends LottieBaseState{
+
+}
+
+
+
+class Lottie extends BaseComponent<LottieProps, LottieState> {
+
+    container = React.createRef<HTMLDivElement>()
+    foundation: LottieFoundation
+
+    static __SemiComponentName__ = "Lottie";
+
+    constructor(props: LottieProps) {
+        super(props);
+        this.foundation = new LottieFoundation(this.adapter);
+    }
+
+    static getLottie = LottieFoundation.getLottie
+
+    static defaultProps = getDefaultPropsFromGlobalConfig(Lottie.__SemiComponentName__)
+    
+    
+    static propTypes= {
+        className: PropTypes.string,
+        style: PropTypes.object,
+        width: PropTypes.string,
+        height: PropTypes.string,
+        params: PropTypes.object,
+        getAnimationInstance: PropTypes.func
+    }
+
+    get adapter(): LottieAdapter<LottieProps, LottieState> {
+        const getContainer = ()=>{
+            return this.props.params.container ?? this.container.current;
+        };
+        return {
+            ...super.adapter,
+            getContainer,
+            getLoadParams: ()=>{
+                return {
+                    container: getContainer(),
+                    renderer: "svg",
+                    loop: true,
+                    autoplay: true,
+                    ...this.props.params,
+                };
+            }
+        };
+    }
+
+    componentDidMount() {
+        super.componentDidMount();
+        this.props.getAnimationInstance?.(this.foundation.animation);
+    }
+
+    componentDidUpdate(prevProps: Readonly<LottieProps>, prevState: Readonly<LottieState>, snapshot?: any) {
+        if (!isEqual(prevProps.params, this.props.params)) {
+            this.foundation.handleParamsUpdate();
+        }
+    }
+
+    private get wrapperStyle() {
+        return {
+            width: this.props.width,
+            height: this.props.height,
+            ...this.props.style
+        };
+    }
+
+    private get wrapperClassName() {
+        return cls(cssClasses.PREFIX, this.props.className);
+    }
+
+
+    render() {
+
+
+        if (this.props.params.container) {
+            return null;
+        } else {
+            return <div ref={this.container} style={this.wrapperStyle} className={this.wrapperClassName} {...this.getDataAttr(this.props)}>
+
+            </div>;
+        }
+
+    }
+
+
+
+}
+
+
+export default Lottie;
+

+ 44 - 0
packages/semi-ui/markdownRender/_story/markdownRender.stories.jsx

@@ -0,0 +1,44 @@
+import MarkdownRender from '../index';
+import * as semiComponents from "../components/index"
+export default {
+    title: 'MarkdownRender'
+}
+
+
+
+export const Basic = ()=>{
+    return <MarkdownRender raw={"# Two 🍰 is: {Math.PI * 2}"} components={semiComponents}/>
+}
+
+export const A = ()=>{
+    return  <MarkdownRender raw={"[Semi Design](https://semi.design)"} components={semiComponents}/>
+}
+
+export const Image = ()=>{
+    return <MarkdownRender raw={"![Semi Design](https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/colorful.jpg)"} components={semiComponents}/>
+}
+
+export const li = ()=>{
+    return <MarkdownRender raw={`
+- 列表1
+- 列表2
+- 列表3
+    `} components={semiComponents}/>
+}
+export const Table = ()=>{
+    return <MarkdownRender raw={`
+| a | b  |  c |  d  |
+| - | :- | -: | :-: |
+| 1 | 2 | 3 | 4 |
+| 21 | 22 | 23 | 24 |
+| 31 | 32 | 33 | 34 |
+| 41 | 42 | 43 | 44 |
+    `} components={semiComponents}/>
+}
+
+export const WithSymbol = ()=>{
+    return <MarkdownRender raw={`
+test \\\\{ cxode } test
+    `} components={semiComponents} format={"md"}/>
+}
+

+ 8 - 0
packages/semi-ui/markdownRender/_story/markdownRender.stories.tsx

@@ -0,0 +1,8 @@
+import React from 'react';
+import { storiesOf } from '@storybook/react';
+import MarkdownRender from '@douyinfe/semi-ui/markdownRender';
+
+
+const stories = storiesOf('MarkdownRender', module);
+
+stories.add('Markdown 渲染器', () => <MarkdownRender mdxRaw={"# test"} />);

+ 9 - 0
packages/semi-ui/markdownRender/components/a.tsx

@@ -0,0 +1,9 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Typography, { TextProps } from "../../typography";
+
+const a = (props: PropsWithChildren<TextProps>)=>{
+    return <Typography.Text link={{ ...props }} {...props}/>;
+};
+
+export default a;

+ 20 - 0
packages/semi-ui/markdownRender/components/code.tsx

@@ -0,0 +1,20 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import CodeHighlight from "../../codeHighlight";
+import { nth } from 'lodash';
+import { cssClasses } from "@douyinfe/semi-foundation/markdownRender/constants";
+
+const pre = (props: PropsWithChildren<{ className: string }>) => {
+    const language = nth(props.className?.split("-"), -1);
+    if (language) {
+        return <CodeHighlight code={props.children as string}
+            language={language} lineNumber={true}/>;
+    } else {
+        return <span className={`${cssClasses.PREFIX}-simple-code`}>
+            {props.children}
+        </span>;
+    }
+
+};
+
+export default pre;

+ 10 - 0
packages/semi-ui/markdownRender/components/h1.tsx

@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Typography, { TitleProps } from '../../typography';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+
+const h1 = (props: PropsWithChildren<TitleProps>)=>{
+    return <Typography.Title heading={1} className={`${cssClasses.PREFIX}-component-header`} {...props}/>;
+};
+
+export default h1;

+ 10 - 0
packages/semi-ui/markdownRender/components/h2.tsx

@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Typography, { TitleProps } from '../../typography';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+
+const h2 = (props: PropsWithChildren<TitleProps>)=>{
+    return <Typography.Title heading={2} className={`${cssClasses.PREFIX}-component-header`} {...props}/>;
+};
+
+export default h2;

+ 10 - 0
packages/semi-ui/markdownRender/components/h3.tsx

@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Typography, { TitleProps } from '../../typography';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+
+const h3 = (props: PropsWithChildren<TitleProps>)=>{
+    return <Typography.Title heading={3} className={`${cssClasses.PREFIX}-component-header`} {...props}/>;
+};
+
+export default h3;

+ 10 - 0
packages/semi-ui/markdownRender/components/h4.tsx

@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Typography, { TitleProps } from '../../typography';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+
+const h4 = (props: PropsWithChildren<TitleProps>)=>{
+    return <Typography.Title heading={4} className={`${cssClasses.PREFIX}-component-header`} {...props}/>;
+};
+
+export default h4;

+ 10 - 0
packages/semi-ui/markdownRender/components/h5.tsx

@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Typography, { TitleProps } from '../../typography';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+
+const h5 = (props: PropsWithChildren<TitleProps>)=>{
+    return <Typography.Title heading={5} className={`${cssClasses.PREFIX}-component-header`} {...props}/>;
+};
+
+export default h5;

+ 10 - 0
packages/semi-ui/markdownRender/components/h6.tsx

@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Typography, { TitleProps } from '../../typography';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+
+const h6 = (props: PropsWithChildren<TitleProps>)=>{
+    return <Typography.Title heading={6} className={`${cssClasses.PREFIX}-component-header`} {...props}/>;
+};
+
+export default h6;

+ 18 - 0
packages/semi-ui/markdownRender/components/img.tsx

@@ -0,0 +1,18 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Image, { ImageProps } from '../../image';
+import { IconUploadError } from "@douyinfe/semi-icons";
+import { omit } from 'lodash';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+
+
+const img = (props: PropsWithChildren<ImageProps>)=>{
+
+    return <div className={`${cssClasses.PREFIX}-component-image`}>
+
+        <Image fallback={<IconUploadError />} width={"100%"} {...omit(props, 'children')}/>
+        <div className={`${cssClasses.PREFIX}-component-image-alt`}>{props.alt}</div>
+    </div>;
+};
+
+export default img;

+ 13 - 0
packages/semi-ui/markdownRender/components/index.tsx

@@ -0,0 +1,13 @@
+export { default as h1 } from "./h1";
+export { default as h2 } from "./h2";
+export { default as h3 } from "./h3";
+export { default as h4 } from "./h4";
+export { default as h5 } from "./h5";
+export { default as h6 } from "./h6";
+export { default as a } from "./a";
+export { default as img } from "./img";
+export { default as table } from "./table";
+export { default as p } from "./p";
+export { default as code } from "./code";
+
+

+ 10 - 0
packages/semi-ui/markdownRender/components/p.tsx

@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import Typography, { TitleProps } from '../../typography';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+
+const p = (props: PropsWithChildren<TitleProps>)=>{
+    return <Typography.Paragraph className={`${cssClasses.PREFIX}-component-p`} {...props}/>;
+};
+
+export default p;

+ 37 - 0
packages/semi-ui/markdownRender/components/table.tsx

@@ -0,0 +1,37 @@
+import * as React from 'react';
+import { PropsWithChildren } from 'react';
+import { get } from 'lodash';
+import Table, { TableProps } from '../../table';
+import { omit } from 'lodash';
+
+
+
+const table = (props: PropsWithChildren<TableProps>)=>{
+
+    const { children } = props;
+    const toArray = value => Array.isArray(value) ? value : [value];
+    const columnsFiber = toArray(get(children[0], 'props.children.props.children'));
+    const dataFiber = toArray(get(children[1], 'props.children'));
+
+    const titles: string[] = columnsFiber.map(item=>item?.props?.children || "");
+    const tableDataSource: any[] = [];
+    for (let i = 0;i < dataFiber.length;i++) {
+        let item: Record<string, string> = {
+            key: String(i)
+        };
+        dataFiber[i].props.children.forEach((child, index)=>{
+            item[titles[index]] = child?.props?.children ?? "";
+        });
+        tableDataSource.push(item);
+    }
+
+
+    return <Table dataSource={tableDataSource} columns={titles.map(title=>{
+        return {
+            title,
+            dataIndex: title
+        };
+    })} {...omit(props, 'children')}/>;
+};
+
+export default table;

+ 73 - 0
packages/semi-ui/markdownRender/index.tsx

@@ -0,0 +1,73 @@
+import * as React from 'react';
+import BaseComponent from '../_base/baseComponent';
+import MarkdownRenderFoundation, {
+    MarkdownRenderAdapter,
+    MarkdownRenderBaseProps,
+    MarkdownRenderBaseState,
+} from '@douyinfe/semi-foundation/markdownRender/foundation';
+import "@douyinfe/semi-foundation/markdownRender/markdownRender.scss";
+import { CSSProperties } from 'react';
+import * as runtime from 'react/jsx-runtime';
+import { cssClasses } from '@douyinfe/semi-foundation/markdownRender/constants';
+import * as SemiMarkdownComponents from "./components";
+import cls from "classnames";
+import PropTypes from 'prop-types';
+import { getDefaultPropsFromGlobalConfig } from '../_utils';
+export interface MarkdownRenderProps extends MarkdownRenderBaseProps{
+    style?: CSSProperties;
+    className?: string
+}
+
+export interface MarkdownRenderState extends MarkdownRenderBaseState{
+
+}
+
+class MarkdownRender extends BaseComponent<MarkdownRenderProps, MarkdownRenderState> {
+
+    foundation = new MarkdownRenderFoundation(this.adapter)
+
+    constructor(props: MarkdownRenderProps) {
+        super(props);
+        this.state = {
+            MDXContentComponent: this.foundation.evaluateSync(this.props.raw)
+        };
+    }
+
+    static propTypes = {
+        className: PropTypes.string,
+        style: PropTypes.object,
+        format: PropTypes.string,
+        components: PropTypes.any,
+        raw: PropTypes.string
+    }
+
+    static __SemiComponentName__ = "MarkdownRender";
+    static defaultProps = getDefaultPropsFromGlobalConfig(MarkdownRender.__SemiComponentName__, {
+        format: "mdx"
+    })
+
+    componentDidUpdate(prevProps: Readonly<MarkdownRenderProps>, prevState: Readonly<MarkdownRenderState>, snapshot?: any) {
+        if (prevProps.raw !== this.props.raw) {
+            this.setState({ MDXContentComponent: this.foundation.evaluateSync(this.props.raw) });
+        }
+    }
+
+    get adapter(): MarkdownRenderAdapter<MarkdownRenderProps, MarkdownRenderState> {
+        return {
+            ...super.adapter,
+            getRuntime: ()=>runtime
+        };
+    }
+
+    render() {
+        const ComponentConstructor = this.state.MDXContentComponent;
+        return <div className={cls(cssClasses.PREFIX, this.props.className)} style={this.props.style} {...this.getDataAttr()}>
+            <ComponentConstructor components={{ ...SemiMarkdownComponents, ...this.props.components }} />
+        </div>;
+    }
+
+    static defaultComponents = SemiMarkdownComponents;
+}
+
+
+export default MarkdownRender;

+ 34 - 0
packages/semi-ui/pincode/_story/pincode.stories.js

@@ -0,0 +1,34 @@
+import React,{useState} from 'react';
+import PinCode from '../index';
+
+export default {
+    title: 'PinCode'
+}
+
+export const PinCodeBasic = () => (
+    <>
+      <PinCode size={'small'} onComplete={v=>alert(v)} onChange={v=>{
+          console.log(v)
+      }}/>
+        <PinCode size={'default'} onComplete={v=>alert(v)} onChange={v=>{
+            console.log(v)
+        }}/>
+        <PinCode size={'large'} onComplete={v=>alert(v)} onChange={v=>{
+            console.log(v)
+        }}/>
+    </>
+);
+
+export const PinCodeControl = () => {
+    const [value,setValue] = useState("123");
+    const ref = useRef();
+    return <>
+        <button onClick={()=>ref.current.focus(2)}>focus third</button>
+        <PinCode format={"mixed"}  ref={ref}
+                 onComplete={value=>console.log("pincode: ",value)}
+                 value={value} onChange={v=>{
+            console.log(v)
+            setValue(v)
+        }}/>
+    </>
+}

+ 6 - 0
packages/semi-ui/pincode/_story/pincode.stories.ts

@@ -0,0 +1,6 @@
+import React from 'react';
+import { storiesOf } from '@storybook/react';
+
+
+const stories = storiesOf('PinCode', module);
+

+ 137 - 0
packages/semi-ui/pincode/index.tsx

@@ -0,0 +1,137 @@
+import React, { CSSProperties, ReactElement } from 'react';
+import PropTypes from 'prop-types';
+import cls from 'classnames';
+import PinCodeFoundation, {
+    PinCodeAdapter,
+    PinCodeBaseProps,
+    PinCodeBaseState,
+} from '@douyinfe/semi-foundation/pincode/foundation';
+import { cssClasses } from '@douyinfe/semi-foundation/pincode/constants';
+import BaseComponent from '../_base/baseComponent';
+import { getDefaultPropsFromGlobalConfig } from '../_utils';
+import Input, { InputProps } from '../input';
+import "@douyinfe/semi-foundation/pincode/pincode.scss";
+
+export interface PinCodeProps extends PinCodeBaseProps {
+    className?: string;
+    style?: CSSProperties;
+    size?: InputProps['size']
+}
+
+export interface PinCodeState extends PinCodeBaseState {
+
+}
+
+class PinCode extends BaseComponent<PinCodeProps, PinCodeState> {
+
+    static __SemiComponentName__ = "PinCode";
+
+    static propTypes = {
+        value: PropTypes.string,
+        format: PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.func]),
+        onChange: PropTypes.func,
+        defaultValue: PropTypes.string,
+        count: PropTypes.number,
+        className: PropTypes.string,
+        style: PropTypes.object,
+        autoFocus: PropTypes.bool,
+        onComplete: PropTypes.func,
+    };
+
+    static defaultProps = getDefaultPropsFromGlobalConfig(PinCode.__SemiComponentName__, {
+        count: 6,
+        format: "number",
+        autoFocus: true,
+    })
+
+    inputDOMList: HTMLInputElement[] = []
+    foundation: PinCodeFoundation
+
+    constructor(props: PinCodeProps) {
+        super(props);
+        this.foundation = new PinCodeFoundation(this.adapter);
+        this.state = {
+            valueList: (this.props.value || this.props.defaultValue) && (this.props.value || this.props.defaultValue).split("") || [],
+            currentActiveIndex: 0
+        };
+    }
+
+    componentDidUpdate(prevProps: Readonly<PinCodeProps>, prevState: Readonly<PinCodeState>, snapshot?: any) {
+
+        if (prevProps.value !== this.props.value) {
+            this.foundation.updateValueList(this.props.value.split(""));
+        }
+    }
+
+    get adapter(): PinCodeAdapter<PinCodeProps, PinCodeState> {
+        return {
+            ...super.adapter,
+            onCurrentActiveIndexChange: async (i) => {
+                await this.setStateAsync({ currentActiveIndex: i });
+            },
+            notifyValueChange: (values: string[]) => {
+                this.props.onChange?.(values.join(""));
+            },
+
+            changeSpecificInputFocusState: (index, state) => {
+                if (state === "focus") {
+                    this.inputDOMList[index]?.focus?.();
+                } else if (state === "blur") {
+                    this.inputDOMList[index]?.blur?.();
+                }
+            },
+            updateValueList: async (valueList: PinCodeState['valueList']) => {
+                await this.setStateAsync({ valueList });
+            }
+        };
+    }
+
+
+    focus = (index: number) => {
+        const inputDOM = this.inputDOMList[index];
+        inputDOM?.focus();
+        inputDOM?.setSelectionRange(1, 1);
+    }
+
+    blur = (index: number) => {
+        this.inputDOMList[index]?.blur();
+    }
+
+
+    renderSingleInput = (index: number) => {
+        return <Input
+            ref={dom => this.inputDOMList[index] = dom}
+            key={`input-${index}`}
+            autoFocus={this.props.autoFocus && index === 0}
+            value={this.state.valueList[index]}
+            size={this.props.size}
+            disabled={this.props.disabled}
+            onBlur={()=>this.foundation.handleCurrentActiveIndexChange(index, "blur")}
+            onFocus={()=>this.foundation.handleCurrentActiveIndexChange(index, "focus")}
+            onPaste={e=>this.foundation.handlePaste(e.nativeEvent, index)}
+            onKeyDown={e=>{
+                this.foundation.handleKeyDownOnSingleInput(e.nativeEvent, index);
+            }}
+            onChange={v => {
+                const userInputChar = v[v.length - 1];
+                if (this.foundation.validateValue(userInputChar)) {
+                    this.foundation.completeSingleInput(index, userInputChar);
+                }
+            }}/>;
+    }
+
+
+    render() {
+        const inputElements: ReactElement[] = [];
+        for (let i = 0; i < this.props.count; i++) {
+            inputElements.push(this.renderSingleInput(i));
+        }
+        return <div className={cls(`${cssClasses.PREFIX}-wrapper`, this.props.className)} style={this.props.style}>
+            {inputElements}
+        </div>;
+    }
+
+
+}
+
+export default PinCode;

+ 10 - 10
src/components/ChartContact/index.jsx

@@ -1,15 +1,15 @@
 import React from 'react';
 
 const ChartContact = (props) => {
-    return <div style={{ display: 'flex', flexDirection: 'row'}}>
-    <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
-        <img src={'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/vchart/contact_wechat.jpeg'} style={{width:250, height:250}}/>
-        <span>{props.name1}</span>
-    </span>
-    <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
-        <img src={'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/vchart/contact_lark.jpeg'} style={{width:250, height:250}}/>
-        <span>{props.name2}</span>
-    </span>
-</div>};
+    return <div style={{ display: 'flex', flexDirection: 'row' }}>
+        <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
+            <img src={'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/vchart/contact_wechat.jpeg'} style={{ width: 250, height: 250 }}/>
+            <span>{props.name1}</span>
+        </span>
+        <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
+            <img src={'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/vchart/contact_lark.jpeg'} style={{ width: 250, height: 250 }}/>
+            <span>{props.name2}</span>
+        </span>
+    </div>;};
 
 export default ChartContact;

+ 1 - 0
src/components/layout.js

@@ -33,6 +33,7 @@ import Footer from './Footer';
 import { itemsArr } from 'utils/category';
 import { getLocale, _t } from 'utils/locale';
 import { useIde } from './useIde';
+import "prismjs/components/prism-vala.js";
 
 
 const insertScript = scriptText => {

+ 1 - 1
src/components/side-nav.js

@@ -49,7 +49,7 @@ const SideNav = ({ location = null, type = null, itemsArr, edges, style, hasBann
             const { items, ...rest } = category;
             return (
                 <Nav.Sub {...rest} key={rest.itemKey}>
-                    {items.map(item=>{
+                    {items?.map(item=>{
                         return (
                             <Link to={item.itemKey} key={item.itemKey} >
                                 <Nav.Item {...item} tabIndex={-1}/>

+ 19 - 1
src/styles/docDemo.scss

@@ -472,4 +472,22 @@ body > .component-list-demo-drag-item {
 
 .semi-select-option-list > div {
     will-change: unset!important;
-}
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 1 - 1
src/styles/index.scss

@@ -65,7 +65,7 @@ body[theme-mode='dark'] {
         }
     }
 
-    .markdown pre {
+    .markdown pre:not(.semi-codeHighlight *) {
         background-color: var(--semi-color-bg-1);
         border-color: transparent;
     }

+ 13 - 3
src/styles/layout.scss

@@ -32,8 +32,7 @@ body[theme-mode="dark"] {
     }
 }
 
-code,
-pre {
+pre,code:not(.semi-codeHighlight *) {
     font-family: Inconsolata, monospace;
     background-color: var(--semi-color-fill-1);
     margin-left: 4px;
@@ -41,6 +40,8 @@ pre {
     letter-spacing: -0.01em;
 }
 
+
+
 body[theme-mode="dark"] {
     font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB",
         "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
@@ -502,4 +503,13 @@ $spCol: var(--semi-color-primary);
     font-weight: 400;
     letter-spacing: unset;
     line-height: unset;
-}
+}
+
+
+
+
+
+
+
+
+

+ 3 - 3
src/templates/scope.js

@@ -36,7 +36,7 @@ import fr from '@douyinfe/semi-ui/locale/source/fr';
 import ro from '@douyinfe/semi-ui/locale/source/ro';
 import { SortableContainer, SortableElement, sortableHandle } from 'react-sortable-hoc';
 import GraphemeSplitter from 'grapheme-splitter';
-
+export * as SemiMarkdownComponents from "@douyinfe/semi-ui/markdownRender/components";
 export * from '@douyinfe/semi-ui';
 export * from '@douyinfe/semi-foundation/utils';
 export * from '@douyinfe/semi-icons';
@@ -164,7 +164,7 @@ export {
     IconBadgeStar, 
     IconBanner, 
     IconBreadcrumb,
-    IconButton,
+    // IconButton,
     // IconCalendar,
     IconCard,
     IconCascader,
@@ -233,4 +233,4 @@ export {
 } from '@douyinfe/semi-icons-lab';
 
 export { VChart } from "@visactor/react-vchart";
-export { initVChartSemiTheme } from '@visactor/vchart-semi-theme';
+export { initVChartSemiTheme } from '@visactor/vchart-semi-theme';

+ 1 - 0
src/utils/category.js

@@ -2,6 +2,7 @@
 export const itemsArr = [
     { itemKey: 'start', text: '开始', textUs: 'Start' },
     { itemKey: 'basic', text: '基础', textUs: 'Basic' },
+    { itemKey: 'plus', text: 'Plus 组件', textUs: 'Plus' },
     { itemKey: 'input', text: '输入类', textUs: 'Input' },
     { itemKey: 'navigation', text: '导航类', textUs: 'Navigation' },
     { itemKey: 'show', text: '展示类', textUs: 'show' },

+ 0 - 1
tsconfig.json

@@ -17,7 +17,6 @@
             "@douyinfe/semi-icons": ["./packages/semi-icons/src/index"],
             "@douyinfe/semi-illustrations": ["./packages/semi-illustrations/src/index"],
         },
-        "suppressImplicitAnyIndexErrors": true,
         "forceConsistentCasingInFileNames": true,
         "importHelpers": true,
         "allowSyntheticDefaultImports": true,

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 750 - 675
yarn.lock


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio