Browse Source

fix: fieldPath not support arrayIndex like a[1]/a.1

point.halo 7 months ago
parent
commit
25e0d130f4

+ 7 - 12
.vscode/settings.json

@@ -13,9 +13,6 @@
     "[javascriptreact]": {
         "editor.defaultFormatter": "dbaeumer.vscode-eslint"
     },
-    "[less]": {
-        "editor.defaultFormatter": "michelemelluso.code-beautifier"
-    },
     "[typescriptreact]": {
         "editor.defaultFormatter": "vscode.typescript-language-features"
     },
@@ -24,15 +21,8 @@
     "[json]": {
         "editor.defaultFormatter": "vscode.json-language-features"
     },
-    "[css]": {
-        "editor.defaultFormatter": "michelemelluso.code-beautifier"
-    },
     "editor.tabSize": 4,
-    "eden-develop-environment.loose": true,
-    "eden-develop-environment.temporaryHideWarnings": true,
     "git.ignoreLimitWarning": true,
-    "edenDevelopEnvironment.loose": true,
-    "edenDevelopEnvironment.temporaryHideWarnings": true,
     "i18n-ally.localesPaths": [
         "src/locale",
         "packages/semi-ui-react/locale",
@@ -43,6 +33,11 @@
     "cSpell.words": [
         "backtop",
         "douyinfe",
-        "Splited"
-    ]
+        "Splited",
+        "bytedance",
+        "cascader",
+        "Cascader",
+        "Commonexclude",
+    ],
+    "typescript.tsdk": "node_modules/typescript/lib"
 }

+ 2 - 2
content/input/form/index.md

@@ -2119,13 +2119,13 @@ FormState 存储了所有 Form 内部的状态值,包括各表单控件的值
 
 | Function      | 说明                                                                                                                                                                                                                             | example                                                                                                             |
 | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |---------------------------------------------------------------------------------------------------------------------|
-| getFormProps  | 获取 Form 组件上当前所有props的值,例如可用于读取 disabled 等。v 2.57.0 后提供                                                    | formApi.getFormProps(propNames?: string[])                                                                                              |
+| getFormProps  | 获取 Form 组件上当前所有props的值,例如可用于读取 disabled 等。v2.57.0 后提供                                                    | formApi.getFormProps(propNames?: string[])                                                                                              |
 | getFormState  | 获取 FormState                                                                                                                                                                                                                   | formApi.getFormState()                                                                                              |
 | submitForm    | 可手动触发 submit 提交操作                                                                                                                                                                                                       | formApi.submitForm()                                                                                                |
 | reset         | 可手动对 form 进行重置                                                                                                                                                                                                           | formApi.reset(fields?: Array <string\>)                                                                             |
 | validate      | 可手动触发对表单的校验,不传参时默认触发整全体Field的校验(配置Form级别校验器后,Field级别校验器在submit或formApi.validate()时不会再被触发),若想触发部分field的校验,将目标field数组传入即可                                                                                                                                                                                                       | formApi.validate()<br/>.then(values=>{})<br/>.catch(errors=>{}) <br/>或 formApi.validate(\['fieldA','fieldB'\])<br/> |
 | setValues     | 设置整个表单的值。第二个参数中的 isOverride 默认为 false<br/>默认情况下只会从`newValues`中取 Form 中已存在的 field 的值更新到`formState.values`中。<br/>当 isOverride 为`true`时,会直接以 newValues 覆盖赋值给 formState.values | formApi.setValues(newValues: object, { isOverride: boolean })                                                       |
-| setValue      | 提供直接修改 formState.values 方法,与 setValues 的区别是它仅修改单个 field                                                                                                                                                      | formApi.setValue(field: string, newFieldValue: any)                                                                 |
+| setValue      | 提供直接修改 formState.values 方法,与 setValues 的区别是它仅修改单个 field。注意首个参数 field 必须有对应的 FieldComponent DOM实体(即属于 Form.XX 或 ArrayField 对应的 field path)                                                                                                                                                | formApi.setValue(field: string, newFieldValue: any)                                                                 |
 | getValue      | 获取 单个 Field 的值                                                                                                                                                                                                             | formApi.getValue() <br/>formApi.getValue(field: string)                                                             |
 | getValues     | 获取 所有 Field 的值                                                                                                                                                                         | formApi.getValues()                                                                                                 |
 | setTouched    | 修改 formState.touched                                                                                                                                                                                                           | formApi.setTouched(field: string, isTouched: boolean) <br/>                                                         |

+ 1 - 1
package.json

@@ -213,7 +213,7 @@
         "svgo": "^2.7.0",
         "terser-webpack-plugin": "^4.2.3",
         "ts-loader": "^5.4.5",
-        "typescript": "^4.8.3",
+        "typescript": "4.9.5",
         "webpack": "^5.77.0",
         "webpack-cli": "^5.1.4",
         "webpack-dev-server": "^3.11.2",

+ 57 - 27
packages/semi-foundation/form/interface.ts

@@ -38,38 +38,69 @@ export interface setValuesConfig {
     isOverride: boolean
 }
 
-// FieldPath 类型定义,用于生成对象字段的路径字符串
-export type FieldPath<T> = T extends object ? {
-    // 遍历对象的每个键 K
-    [K in keyof T]: T[K] extends object
-        // 如果键 K 对应的值是对象,则生成嵌套路径(递归调用 FieldPath)
-        ? `${string & K}.${FieldPath<T[K]>}` | `${string & K}`
-        // 否则,仅生成当前键的路径
-        : `${string & K}`;
-}[keyof T]
-    : never;
-
-// FieldPathValue 类型定义,用于从路径字符串中推导出实际的类型
-export type FieldPathValue<T, P extends FieldPath<T>> =
-  // 如果路径字符串 P 包含嵌套路径(使用模板字符串类型进行匹配)
-  P extends `${infer K}.${infer Rest}`
-      ? K extends keyof T
-          // 递归解析嵌套路径,逐层深入对象结构
-          ? Rest extends FieldPath<T[K]>
-              ? FieldPathValue<T[K], Rest>
-              : never
-          : never
-      // 如果路径字符串 P 是顶层键
-      : P extends keyof T
-          ? T[P]
-          : never;
-
 export type ScrollToErrorOptions<K> = {
     field?: K;
     index?: number;
     scrollOpts?: ScrollIntoViewOptions
 }
 
+// FieldPath 类型定义,支持对象和数组字段路径
+export type FieldPath<T> = T extends Array<infer U>
+    ? | `${number}`                      // 如果是数组,支持数字索引(如 `[0]`)
+    | `${number}.${FieldPath<U>}`      // 支持数组嵌套路径(如 `[0].field`)
+    : T extends object
+        ? {
+            [K in keyof T]: K extends string
+                ? T[K] extends Array<infer U> | object
+                    ? | `${K}` 
+                    | `${K}.${FieldPath<T[K]>}`
+                    | ArrayIndexPath<K, U>
+                    : `${K}`                            // 只允许键路径
+                : never;
+        }[keyof T]
+        : never;
+
+// 支持 array[index] 和 array.index 两种形式
+type ArrayIndexPath<K extends string | number, U> = 
+    | `${K}[${number}]`
+    | `${K}[${number}].${FieldPath<U>}`
+    | `${K}.${number}`
+    | `${K}.${number}.${FieldPath<U>}`;
+
+// FieldPathValue 类型定义,支持从路径字符串中推导数组和对象的值
+export type FieldPathValue<T, P extends string> =
+  P extends `${infer K}[${infer I}]${infer Rest}` // 处理 array[index] 形式
+      ? K extends keyof T
+          ? T[K] extends Array<infer U>
+              ? I extends `${number}`
+                  ? Rest extends ''
+                      ? U
+                      : Rest extends `.${infer RestPath}`
+                          ? FieldPathValue<U, RestPath>
+                          : never
+                  : never
+              : never
+          : never
+      : P extends `${infer K}.${infer Rest}` // 处理 key.rest 或 array.index 形式
+          ? K extends keyof T
+              ? T[K] extends Array<infer U>
+                  ? Rest extends `${number}${infer IndexRest}`
+                      ? IndexRest extends ''
+                          ? U // 简单的数组索引访问 (array.0)
+                          : IndexRest extends `.${infer RestPath}`
+                              ? FieldPathValue<U, RestPath> // 嵌套路径 (array.0.field)
+                              : never
+                      : FieldPathValue<T[K], Rest> // 其他嵌套对象字段
+                  : FieldPathValue<T[K], Rest>
+              : never
+          : P extends keyof T // 简单的顶层键访问
+              ? T[P]
+              : P extends `${number}` // 对于顶层数组路径
+                  ? T extends Array<infer U>
+                      ? U
+                      : never
+                  : never;
+
 // use object replace Record<string, any>, fix issue 933
 export interface BaseFormApi<T extends object = any> {
     /** get value of field */
@@ -139,7 +170,6 @@ export interface InternalFieldApi {
     reset: () => void;
     validate: (val: any, opts: CallOpts) => Promise<unknown>
 }
-
 export interface FieldStaff {
     field: string;
     fieldApi: InternalFieldApi;

+ 38 - 60
packages/semi-ui/form/_story/form.stories.tsx

@@ -1,9 +1,5 @@
 import React, { FunctionComponent } from 'react';
-import { storiesOf } from '@storybook/react';
 import { Form, useFormState, useFormApi, withField, Input, Button, Upload, withFormApi, withFormState } from '../../index';
-const stories = storiesOf('Form', module);
-import { FormApiContext } from '../context';
-
 
 import type { FormApi, FormFCChild, FormState } from '../interface';
 
@@ -22,36 +18,9 @@ const treeData = [
                         label: '西湖区',
                         value: 'xihu',
                         key: '0-0-0',
-                    },
-                    {
-                        label: '萧山区',
-                        value: 'xiaoshan',
-                        key: '0-0-1',
-                    },
-                    {
-                        label: '临安区',
-                        value: 'linan',
-                        key: '0-0-2',
-                    },
+                    }
                 ],
-            },
-            {
-                label: '宁波市',
-                value: 'ningbo',
-                key: '0-1',
-                children: [
-                    {
-                        label: '海曙区',
-                        value: 'haishu',
-                        key: '0-1-0',
-                    },
-                    {
-                        label: '江北区',
-                        value: 'jiangbei',
-                        key: '0-1-1',
-                    },
-                ],
-            },
+            }
         ],
     },
 ];
@@ -73,7 +42,7 @@ const Fields: FunctionComponent<FormFCChild> = ({ formState, values, formApi })
 
         <Form.Input field='test'  ref={ref}  />
         <Input size='default' showClear insetLabel />
-        <FieldB insetLabel placeholder='fe' fieldClassName='fefe' field='custom' />
+        <FieldB insetLabel placeholder='fe' fieldClassName='fieldClass-test' field='custom' />
 
         {/* <Button onClick={() => formApi.setValue('fieldA', 'fe')}>set</Button> */}
         <Form.Select field='test' ref={ref}>
@@ -135,9 +104,6 @@ const Fields: FunctionComponent<FormFCChild> = ({ formState, values, formApi })
     </>
     )
 };
-
-stories.add('Form', () => <Form>{Fields}</Form>);
-
 interface IProps {
     [x:string]: any;
 }
@@ -154,11 +120,15 @@ interface FData {
     },
     test5: {
         kkk: {
-            jjj: number
+            jnumber: number
         }
     }
     testK: boolean;
-    // [x: string]: any;
+    array: [string, string],
+    nestedArray: Array<{
+        id: number;
+        name: string;
+    }>;
 }
 class Demo extends React.Component<IProps, IState> {
 
@@ -170,27 +140,38 @@ class Demo extends React.Component<IProps, IState> {
     }
 
     getFormApi(formApi) {
-        this.formApi = formApi;
+        (this.formApi as FormApi<FData>) = formApi;
     }
 
     setData() {
         const formApi = this.formApi;
-        // set
-        formApi.setValue('test3', 123);
+        // ✅ 应该合法的, 注意,setValue只对 fieldPath做校验,对 value 不做严格校验
+        formApi.setValue('test3', '123');
         formApi.setValue('test4.event', 123);
         formApi.setValue('test5.kkk', 123);
-        formApi.setValue('test5.kkk.jjj', 123);
+        formApi.setValue('test5.kkk.jnumber', 'abc');
+        formApi.setValue('array[0]', '2025')
+        formApi.setValue('array.0', '2025')
+        formApi.setValue('nestedArray[0].id', 123)
+        formApi.setValue('nestedArray[0].name', 'abc')
+
+
+        // ❌ 无法通过类型校验,应抛出错误的
+        formApi.setValue('test5.kkk.notExist', 123);
         formApi.setValue('keyNotExist', 123);
         formApi.setValue('test4.notExist', 123);
-        formApi.setValue('test5.kkk.notExist', 123);
+        formApi.setValue('test4.notExist', 123);
+        formApi.setValue('nestedArray[0].notExist', 123);
+
 
-        // get
+        // get 应该合法的
         let test3 = formApi.getValue('test3');
         let test4 = formApi.getValue('test4');
         let test4event = formApi.getValue('test4.event');
         let test5kkk = formApi.getValue('test5.kkk');
-        let test5kkkjjj = formApi.getValue('test5.kkk.jjj');
+        let test5kkkjnumber = formApi.getValue('test5.kkk.jnumber');
 
+        // ❌ 无法通过类型校验,应抛出错误的
         let a = formApi.getValue('keyNotExist');
         let b = formApi.getValue('test5.kkk.notExist');
         let c = formApi.getValue('test4.notExist');
@@ -251,10 +232,6 @@ class WithoutGenericsType extends React.Component<IProps, IState> {
 }
 
 
-stories.add('Form render', () => <Form render={({values, formApi, formState}) => <div></div>}></Form>);
-
-
-
 interface CodeProps {
     type?: 'email' | 'phone';
     test?: 'a' | 'b' | 'c';
@@ -280,19 +257,20 @@ const DoubleWrap = withFormState(withFormApi(CodeC));
 const OneWrap = withFormApi(CodeC);
 
 
-stories.add('Form children', () => <Form>
+const FormWithChildren = () => (<Form>
     {({ formState, formApi, values }) => (
         <>
-        <Form.Input field='fe'>
-        </Form.Input>
-        
-        <DoubleWrap type='email' test='c'></DoubleWrap>
-        <OneWrap type='email'></OneWrap>
-        <CodeC type='email'></CodeC>
-        
-        <Form.DatePicker field='role'/>
+            <Form.Input field='fe'>
+            </Form.Input>
+
+            <DoubleWrap type='email' test='c'></DoubleWrap>
+            <OneWrap type='email'></OneWrap>
+            <CodeC type='email'></CodeC>
+
+            <Form.DatePicker field='role' />
         </>
-        )
+    )
     }
 </Form>);
 
+

+ 0 - 195
packages/semi-ui/select/_story/select.stories.tsx

@@ -1,195 +0,0 @@
-import React from 'react';
-import { storiesOf } from '@storybook/react';
-import classNames from 'classnames';
-import { optionRenderProps, RenderMultipleSelectedItemFn, RenderSingleSelectedItemFn } from '@douyinfe/semi-ui/select/index';
-import { Checkbox } from '../../index';
-import { Select, Avatar, Tag, Space } from '../../index';
-
-const stories = storiesOf('Select', module);
-
-let optionList = [
-    { value: 'tony', label: 'Ironman' },
-    { value: 'Thor', label: 'Thor' },
-    { value: 'steve', label: 'Caption' },
-    { value: 'peter', label: 'SpiderBoy' },
-];
-
-stories.add('Select', () => (
-    <>
-        <Select style={{ width: 200 }}>
-            <Select.Option value="1"></Select.Option>
-            <Select.Option value="2"></Select.Option>
-        </Select>
-    </>
-));
-
-const RenderOptionDemo = () => {
-    const renderOptionItem = (renderProps: optionRenderProps) => {
-        const {
-            disabled,
-            selected,
-            label,
-            value,
-            focused,
-            className,
-            style,
-            onMouseEnter,
-            onClick,
-            ...rest
-        } = renderProps;
-
-        const optionCls = classNames({
-            ['custom-option-render']: true,
-            ['custom-option-render-focused']: focused,
-            ['custom-option-render-disabled']: disabled,
-            ['custom-option-render-selected']: selected,
-        });
-        // Notice:
-        // 1.props传入的style需在wrapper dom上进行消费,否则在虚拟化场景下会无法正常使用
-        // 2.选中(selected)、聚焦(focused)、禁用(disabled)等状态的样式需自行加上,你可以从props中获取到相对的boolean值
-        // 3.onMouseEnter需在wrapper dom上绑定,否则上下键盘操作时显示会有问题
-
-        return (
-            <div style={style} className={optionCls} onClick={(e) => onClick(e)} onMouseEnter={e => onMouseEnter(e)}>
-                <Checkbox checked={selected} />
-                <div className="option-right">{label}</div>
-            </div>
-        );
-    };
-
-    return (
-        <Select
-            filter
-            dropdownClassName="components-select-demo-renderOptionItem"
-            optionList={optionList}
-            style={{ width: 300 }}
-            renderOptionItem={renderOptionItem}
-        />
-    );
-};
-
-interface OptionNode {
-    name: string;
-    email: string;
-    avatar: string;
-}
-
-
-function CustomRender(props) {
-    const list = [
-        {
-            name: '夏可漫',
-            email: '[email protected]',
-            avatar:
-                'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png',
-        },
-        {
-            name: '申悦',
-            email: '[email protected]',
-            avatar:
-                'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bag.jpeg',
-        },
-        {
-            name: '曲晨一',
-            email: '[email protected]',
-            avatar:
-                'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/8bd8224511db085ed74fea37205aede5.jpg',
-        },
-        {
-            name: '文嘉茂',
-            email: '[email protected]',
-            avatar:
-                'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png',
-        },
-    ];
-
-    const renderCustomOption = (item) => {
-        let optionStyle = {
-            display: 'flex',
-            paddingLeft: 24,
-            paddingTop: 10,
-            paddingBottom: 10,
-        };
-        return (
-            <Select.Option value={item.name} style={optionStyle} showTick={true} {...item} key={item.email}>
-                <Avatar size="small" src={item.avatar} />
-                <div style={{ marginLeft: 8 }}>
-                    <div style={{ fontSize: 14 }}>{item.name}</div>
-                    <div
-                        style={{
-                            color: 'var(--semi-color-text-2)',
-                            fontSize: 12,
-                            lineHeight: '16px',
-                            fontWeight: 'normal',
-                        }}
-                    >
-                        {item.email}
-                    </div>
-                </div>
-            </Select.Option>
-        );
-    }
-
-    const renderSelectedItem: RenderSingleSelectedItemFn = (optionNode: OptionNode): React.ReactNode => {
-        return (
-            <div key={optionNode.email} style={{ display: 'flex', alignItems: 'center' }}>
-                <Avatar src={optionNode.avatar} size="small">
-                    {optionNode.avatar}
-                </Avatar>
-                <span style={{ marginLeft: 8 }}>{optionNode.email}</span>
-            </div>
-        );
-    }
-
-    const renderMultipleWithCustomTag: RenderMultipleSelectedItemFn = (optionNode: OptionNode, { onClose  }) => {
-        let content = (
-            <Tag
-                avatarSrc={optionNode.avatar}
-                avatarShape="circle"
-                closable={true}
-                onClose={onClose}
-                size="large"
-                key={optionNode.name}
-            >
-                {optionNode.name}
-            </Tag>
-        );
-        return {
-            isRenderInTag: false,
-            content,
-        };
-    }
-
-    return (
-        <Space>
-            <Select
-                style={{
-                    width: 300,
-                    height: 40,
-                }}
-                defaultValue={'夏可漫'}
-                renderSelectedItem={renderSelectedItem}
-            >
-                {list.map(item => renderCustomOption(item))}
-            </Select>
-            <Select
-                placeholder="请选择"
-                maxTagCount={2}
-                style={{ width: 280 }}
-                onChange={v => console.log(v)}
-                defaultValue={['夏可漫', '申悦']}
-                multiple
-                renderSelectedItem={renderMultipleWithCustomTag}
-            >
-                {list.map(item => renderCustomOption(item))}
-            </Select>
-        </Space>
-    );
-}
-
-stories.add('自定义已选标签渲染', () => (
-    <>
-        <div>renderSelectedItem</div>
-        <CustomRender />
-    </>
-));

+ 1 - 1
packages/semi-ui/tsconfig.json

@@ -28,5 +28,5 @@
         "strict": true
     },
     "include": ["**/*.tsx", "**/*.ts"],
-    "exclude": ["node_modules", "packages/rollup-plugin-semi-svg"]
+    "exclude": ["node_modules"]
 }

+ 29 - 102
yarn.lock

@@ -1585,25 +1585,11 @@
     "@douyinfe/semi-animation-styled" "2.65.0"
     classnames "^2.2.6"
 
-"@douyinfe/[email protected]":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-react/-/semi-animation-react-2.73.0.tgz#c76214146356446c72eff41eefba140c1ec4e177"
-  integrity sha512-QO/2Vl14Nt1VEUTj/KOn3jmV99HDKnnHUZqQOzIxNoAkGXKKuGW8WIEKm3r55GQhw0pI5Qs8JgKJ0qhlQLSg4A==
-  dependencies:
-    "@douyinfe/semi-animation" "2.73.0"
-    "@douyinfe/semi-animation-styled" "2.73.0"
-    classnames "^2.2.6"
-
 "@douyinfe/[email protected]":
   version "2.65.0"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.65.0.tgz#8c56047a5704a45b05cc9809a2a126cc24526ea1"
   integrity sha512-YFF8Ptcz/jwS0phm28XZV7ROqMQ233sjVR0Uy33FImCITr6EAPe5wcCeEmzVZoYS7x3tUFR30SF+0hSO01rQUg==
 
-"@douyinfe/[email protected]":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation-styled/-/semi-animation-styled-2.73.0.tgz#b7913e23dd579ff9ba9922e2da3b1d87612a4ee5"
-  integrity sha512-DC5meqG7Ooxpual6UEVrK0t6oo+PJQUv6r+TG7XMPaXmJRehwmd11L55aDq7h0xs6IO8TJEI3kfHCvnvcCCKBA==
-
 "@douyinfe/[email protected]":
   version "2.65.0"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.65.0.tgz#f544a6b420c3e948c09836019e6b63f1382cd12c"
@@ -1611,13 +1597,6 @@
   dependencies:
     bezier-easing "^2.1.0"
 
-"@douyinfe/[email protected]":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-animation/-/semi-animation-2.73.0.tgz#bec6192063ea2f9fcd49e82bc78643aaa6b47a68"
-  integrity sha512-oNJepL4gXcdB/poFbYoLke/lfmcrHq85oR/ax/xPeh8Z5A4816MYcqNXjW/nG7hXBnKeoE8TPpAYWDxqyINq5Q==
-  dependencies:
-    bezier-easing "^2.1.0"
-
 "@douyinfe/[email protected]":
   version "2.65.0"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.65.0.tgz#20466a9b4baacdde2249930fb709ba035c5a7bea"
@@ -1637,26 +1616,6 @@
     remark-gfm "^4.0.0"
     scroll-into-view-if-needed "^2.2.24"
 
-"@douyinfe/[email protected]":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-foundation/-/semi-foundation-2.73.0.tgz#7d84ba29a1cfccbfdcae7e92b4cd460c1e7f8784"
-  integrity sha512-9QfpGJs/iY7TUhuyXj85s2p7ILLJnptTO2LAfHoq9o0B3+nhptLb1sDIqG7BS1PJrTcABxavl0IbSrxcITln2w==
-  dependencies:
-    "@douyinfe/semi-animation" "2.73.0"
-    "@douyinfe/semi-json-viewer-core" "2.73.0"
-    "@mdx-js/mdx" "^3.0.1"
-    async-validator "^3.5.0"
-    classnames "^2.2.6"
-    date-fns "^2.29.3"
-    date-fns-tz "^1.3.8"
-    fast-copy "^3.0.1 "
-    lodash "^4.17.21"
-    lottie-web "^5.12.2"
-    memoize-one "^5.2.1"
-    prismjs "^1.29.0"
-    remark-gfm "^4.0.0"
-    scroll-into-view-if-needed "^2.2.24"
-
 "@douyinfe/[email protected]", "@douyinfe/semi-icons@latest":
   version "2.65.0"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.65.0.tgz#af39cbd5431ebccedcf7d9ce689646e54bebc432"
@@ -1664,30 +1623,11 @@
   dependencies:
     classnames "^2.2.6"
 
-"@douyinfe/[email protected]", "@douyinfe/semi-icons@^2.0.0":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-icons/-/semi-icons-2.73.0.tgz#c990449d3b70c3c94b9e644828a37869b3a6d11f"
-  integrity sha512-Gyv8z5Q7wMySzOr8S3a6DJxJaIdnidOnNqOZnm24Ok1bJcFiEA7EeUGf83IIcFfDsA3jGgzffP3zvc1HM1TjTA==
-  dependencies:
-    classnames "^2.2.6"
-
 "@douyinfe/[email protected]":
   version "2.65.0"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.65.0.tgz#9916c540c91222a1d9f48cd34a941d28b8a05d2f"
   integrity sha512-1IhOztyBYiSu8WrcvN+oWWtcJTC9+x6zbnYtufx4ToISs5UO1te1PQofABpkDzIJYFtW9yYLxg4uoL4wGjqYMA==
 
-"@douyinfe/[email protected]":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-illustrations/-/semi-illustrations-2.73.0.tgz#31fa15e6c08490a3c4a796a65ddf4e126370b10d"
-  integrity sha512-qeAK0QHubHQOjVSjeAlvqbCsnvvr5Qp+x50IAt0xzdsz5MABKg79At1oky/852BchG77InkQ6W0mJdPLdz6CaA==
-
-"@douyinfe/[email protected]":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-json-viewer-core/-/semi-json-viewer-core-2.73.0.tgz#e48a35e42f4d0f19a2aa65b5c875290afc11de1c"
-  integrity sha512-E7jzWuQl5OPMUkoyVeT9HHC9G3PiEG5yvas6c0Cw3jwFBRGgJ6X0FjYDJsUdcfuOkhMbly2AQvwN2cIe9cmBGA==
-  dependencies:
-    jsonc-parser "^3.3.1"
-
 "@douyinfe/[email protected]":
   version "2.23.2"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-scss-compile/-/semi-scss-compile-2.23.2.tgz#30884bb194ee9ae1e81877985e5663c3297c1ced"
@@ -1759,39 +1699,6 @@
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.61.0.tgz#a7e9bf9534721c12af1d0eeb5d5a2de615896a23"
   integrity sha512-obn/DOw4vZyKFAlWvZxHTpBLAK9FO9kygTSm2GROgvi+UDB2PPU6l20cuUCsdGUNWJRSqYlTTVZ1tNYIyFZ5Sg==
 
-"@douyinfe/[email protected]":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-theme-default/-/semi-theme-default-2.73.0.tgz#ede26af7223cbb71bebf6be4d45e97265e211b60"
-  integrity sha512-b8g4/l0p8m4iJHiHzw4kX2O8ZDT9QfDS+vB30olXlPnKUZ4QI6Slw8NeYoZUKKM8Xyf2fEcazYQuX4VBjUbMpA==
-
-"@douyinfe/semi-ui@^2.0.0":
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.73.0.tgz#ac243be9469998e2c29fc6fe64918ccd5be3ce62"
-  integrity sha512-mhOYWbNBzi7CjK2SSmLkeonMYv7LmY7EEWObbE6TKtds1FJxDM7rYYPRYJn4Jsf2qu5V/UO0tbDpbntLlUW0Eg==
-  dependencies:
-    "@dnd-kit/core" "^6.0.8"
-    "@dnd-kit/sortable" "^7.0.2"
-    "@dnd-kit/utilities" "^3.2.1"
-    "@douyinfe/semi-animation" "2.73.0"
-    "@douyinfe/semi-animation-react" "2.73.0"
-    "@douyinfe/semi-foundation" "2.73.0"
-    "@douyinfe/semi-icons" "2.73.0"
-    "@douyinfe/semi-illustrations" "2.73.0"
-    "@douyinfe/semi-theme-default" "2.73.0"
-    async-validator "^3.5.0"
-    classnames "^2.2.6"
-    copy-text-to-clipboard "^2.1.1"
-    date-fns "^2.29.3"
-    date-fns-tz "^1.3.8"
-    fast-copy "^3.0.1 "
-    jsonc-parser "^3.3.1"
-    lodash "^4.17.21"
-    prop-types "^15.7.2"
-    react-resizable "^3.0.5"
-    react-window "^1.8.2"
-    scroll-into-view-if-needed "^2.2.24"
-    utility-types "^3.10.0"
-
 "@douyinfe/semi-ui@latest":
   version "2.65.0"
   resolved "https://registry.yarnpkg.com/@douyinfe/semi-ui/-/semi-ui-2.65.0.tgz#295eb0dd8e9e961adb4ddd7c7bbce3468d1b7430"
@@ -12074,11 +11981,6 @@ eslint-plugin-react@^7.20.6, eslint-plugin-react@^7.24.0:
     string.prototype.matchall "^4.0.11"
     string.prototype.repeat "^1.0.0"
 
-eslint-plugin-semi-design@^2.33.0:
-  version "2.73.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-semi-design/-/eslint-plugin-semi-design-2.73.0.tgz#ea6d48a91a44759e5ac8f69c99f44dfdc6881a64"
-  integrity sha512-aqftX/wUoxzSG+V4vqvjK+H7Y8XWRxPySDS2IEZ2+G2wiRLS1KkUFWGnoKOOWgARA4G/a0V9zqJ20b57P4Uo9A==
-
 eslint-rule-composer@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9"
@@ -25284,7 +25186,7 @@ string-similarity@^1.2.2:
     lodash.map "^4.6.0"
     lodash.maxby "^4.6.0"
 
-"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -25302,6 +25204,15 @@ string-width@^1.0.1, string-width@^1.0.2:
     is-fullwidth-code-point "^1.0.0"
     strip-ansi "^3.0.0"
 
+"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.1"
+
 string-width@^2.0.0, string-width@^2.1.0:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
@@ -25445,7 +25356,7 @@ stringify-object@^3.3.0:
     is-obj "^1.0.1"
     is-regexp "^1.0.0"
 
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
   integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -25473,6 +25384,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
   dependencies:
     ansi-regex "^4.1.0"
 
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+  dependencies:
+    ansi-regex "^5.0.1"
+
 strip-ansi@^7.0.1:
   version "7.1.0"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@@ -26636,7 +26554,7 @@ types-ramda@^0.29.4:
   dependencies:
     ts-toolbelt "^9.6.0"
 
-typescript@^4, typescript@^4.4.4, typescript@^4.8.3:
+[email protected], typescript@^4, typescript@^4.4.4:
   version "4.9.5"
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
   integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
@@ -28067,7 +27985,7 @@ worker-loader@^3.0.8:
     loader-utils "^2.0.0"
     schema-utils "^3.0.0"
 
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
   integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -28102,6 +28020,15 @@ wrap-ansi@^6.2.0:
     string-width "^4.1.0"
     strip-ansi "^6.0.0"
 
+wrap-ansi@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+  dependencies:
+    ansi-styles "^4.0.0"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+
 wrap-ansi@^8.1.0:
   version "8.1.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"