mirror of
https://github.com/NetEase/tango.git
synced 2026-08-29 02:01:34 +08:00
fix: refactor setting formItem
This commit is contained in:
@@ -11,7 +11,7 @@ const packageJson = {
|
||||
},
|
||||
};
|
||||
|
||||
const tangoJson = {
|
||||
const tangoConfigJson = {
|
||||
packages: {
|
||||
react: {
|
||||
version: '17.0.2',
|
||||
@@ -221,7 +221,7 @@ p {
|
||||
export const sampleFiles = [
|
||||
{ filename: '/package.json', code: JSON.stringify(packageJson) },
|
||||
{ filename: '/appJson.json', code: JSON.stringify(appJson) },
|
||||
{ filename: '/tango.config.json', code: JSON.stringify(tangoJson) },
|
||||
{ filename: '/tango.config.json', code: JSON.stringify(tangoConfigJson) },
|
||||
{ filename: '/README.md', code: '# readme' },
|
||||
{ filename: '/src/index.less', code: lessCode },
|
||||
{ filename: '/src/style.css', code: cssCode },
|
||||
|
||||
@@ -43,7 +43,7 @@ import { IWorkspace } from './interfaces';
|
||||
import { SelectSource } from './select-source';
|
||||
import { DragSource } from './drag-source';
|
||||
|
||||
export type WorkspaceOptionsType = {
|
||||
export interface IWorkspaceOptions {
|
||||
/**
|
||||
* 入口文件
|
||||
*/
|
||||
@@ -225,7 +225,7 @@ export class Workspace extends EventTarget implements IWorkspace {
|
||||
return Object.keys(this.localBlocks);
|
||||
}
|
||||
|
||||
constructor(options?: WorkspaceOptionsType) {
|
||||
constructor(options?: IWorkspaceOptions) {
|
||||
super();
|
||||
this.history = new TangoHistory(this);
|
||||
this.selectSource = new SelectSource(this);
|
||||
|
||||
@@ -12,4 +12,6 @@ export * from './sidebar';
|
||||
export * from './toolbar';
|
||||
export * from './selection-menu';
|
||||
|
||||
export { register as registerSetter, FormItemComponentProps, FormItemCreateOptionsType } from '@music163/tango-setting-form';
|
||||
export { register as registerSetter } from '@music163/tango-setting-form';
|
||||
|
||||
export type { FormItemComponentProps, IFormItemCreateOptions } from '@music163/tango-setting-form';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useImperativeHandle, ForwardedRef, useRef, useState, useEffect } from 'react';
|
||||
import { Box } from 'coral-system';
|
||||
import { CodeSandbox, CodeSandboxProps } from '@music163/tango-sandbox';
|
||||
import { getValue, logger, pick, setValue } from '@music163/tango-helpers';
|
||||
import { getValue, isFunction, logger, pick, setValue } from '@music163/tango-helpers';
|
||||
import { observer, useWorkspace, useDesigner } from '@music163/tango-context';
|
||||
import { Simulator, Viewport } from '../simulator';
|
||||
import { useSandboxQuery } from '../context';
|
||||
@@ -491,7 +491,9 @@ function mergeTangoConfigJson(
|
||||
setValue(json, 'sandbox.externals', externals);
|
||||
setValue(json, 'sandbox.externalResources', [...new Set(externalResources)]);
|
||||
|
||||
json = formatter?.(json);
|
||||
if (isFunction(formatter)) {
|
||||
json = formatter?.(json);
|
||||
}
|
||||
|
||||
return JSON.stringify(json);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ import { SingleMonacoEditor } from '@music163/tango-ui';
|
||||
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
||||
|
||||
/**
|
||||
* 废弃掉,直接使用 ExpressionSetter 代替
|
||||
* @deprecated
|
||||
* JSON Setter
|
||||
*/
|
||||
export function JSONSetter({ value, onChange }: FormItemComponentProps) {
|
||||
return (
|
||||
|
||||
@@ -4,6 +4,7 @@ import { SettingForm, FormModel, SettingFormProps } from '@music163/tango-settin
|
||||
import { Panel } from '@music163/tango-ui';
|
||||
import { clone } from '@music163/tango-helpers';
|
||||
import { observer, useDesigner, useWorkspace } from '@music163/tango-context';
|
||||
import './setters';
|
||||
|
||||
export interface SettingPanelProps extends SettingFormProps {
|
||||
title?: React.ReactNode;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import { Button, Space } from 'antd';
|
||||
import { EditableVariableTree, EditableVariableTreeProps } from '@music163/tango-setting-form';
|
||||
import { useBoolean } from '@music163/tango-helpers';
|
||||
import { Panel, Form, IconButton } from '@music163/tango-ui';
|
||||
import { FileAddOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { observer, useWorkspace, useWorkspaceData } from '@music163/tango-context';
|
||||
import { EditableVariableTree, EditableVariableTreeProps } from '../components';
|
||||
|
||||
export interface VariablePanelProps extends EditableVariableTreeProps {
|
||||
wrapperHeight?: number | string;
|
||||
|
||||
@@ -14,7 +14,7 @@ import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { InputProps, Tooltip } from 'antd';
|
||||
import { INTERNAL_SETTERS } from './setters';
|
||||
import { useFormModel, useFormVariable } from './context';
|
||||
import { FormControl, FormControlProps } from './form-ui';
|
||||
import { FormControl } from './form-ui';
|
||||
|
||||
export interface FormItemProps extends ComponentPropType {
|
||||
extra?: React.ReactNode;
|
||||
@@ -50,10 +50,6 @@ export interface IFormItemCreateOptions {
|
||||
* 是否禁用变量设置器
|
||||
*/
|
||||
disableVariableSetter?: boolean;
|
||||
/**
|
||||
* 表单项类型
|
||||
*/
|
||||
type?: FormControlProps['type'];
|
||||
/**
|
||||
* 子表单是否默认折叠
|
||||
*/
|
||||
@@ -64,25 +60,12 @@ export interface IFormItemCreateOptions {
|
||||
validate?: (value: string) => string | Promise<any>;
|
||||
}
|
||||
|
||||
function normalizeCreateOptions(
|
||||
options: IFormItemCreateOptions,
|
||||
): Required<Omit<IFormItemCreateOptions, 'component' | 'alias'>> {
|
||||
const render = options.render ?? ((props: any) => React.createElement(options.component, props));
|
||||
return {
|
||||
name: options.name,
|
||||
render,
|
||||
disableVariableSetter: options.disableVariableSetter ?? false,
|
||||
type: options.type || 'formItem',
|
||||
defaultCollapsed: options.defaultCollapsed ?? true,
|
||||
validate: options.validate,
|
||||
};
|
||||
}
|
||||
|
||||
const defaultGetSetterProps = () => ({});
|
||||
const defaultGetVisible = () => true;
|
||||
|
||||
export function createFormItem(options: IFormItemCreateOptions) {
|
||||
const _options = normalizeCreateOptions(options);
|
||||
const renderSetter =
|
||||
options.render ?? ((props: any) => React.createElement(options.component, props));
|
||||
|
||||
function FormItem({
|
||||
name,
|
||||
@@ -95,7 +78,7 @@ export function createFormItem(options: IFormItemCreateOptions) {
|
||||
setterProps,
|
||||
defaultValue,
|
||||
options: setterOptions,
|
||||
disableVariableSetter: disableVariableSetterProp,
|
||||
disableVariableSetter: disableVariableSetterProp = options.disableVariableSetter,
|
||||
getVisible: getVisibleProp,
|
||||
getSetterProps: getSetterPropsProp,
|
||||
extra,
|
||||
@@ -104,16 +87,15 @@ export function createFormItem(options: IFormItemCreateOptions) {
|
||||
const model = useFormModel();
|
||||
const field = model.getField(name);
|
||||
const value = toJS(field.value ?? defaultValue);
|
||||
const disableVariableSetter =
|
||||
disableSwitchExpressionSetter || disableVariableSetterProp || _options.disableVariableSetter;
|
||||
const disableVariableSetter = disableSwitchExpressionSetter ?? disableVariableSetterProp;
|
||||
const [isVariable, { toggle: toggleIsVariable }] = useBoolean(
|
||||
() => !disableVariableSetter && isVariableString(value),
|
||||
);
|
||||
|
||||
const setterName = isVariable ? 'expressionSetter' : setter;
|
||||
const validate = SETTERS_VALIDATE_DICT[setterName];
|
||||
|
||||
field.setConfig({
|
||||
validate,
|
||||
validate: options.validate,
|
||||
});
|
||||
|
||||
const baseComponentProps = clone(
|
||||
@@ -140,12 +122,13 @@ export function createFormItem(options: IFormItemCreateOptions) {
|
||||
}
|
||||
|
||||
const getSetterProps = getSetterPropsProp || defaultGetSetterProps;
|
||||
const ExpressionSetter = SETTERS_DICT['expressionSetter'];
|
||||
// 从注册表中获取 expSetter
|
||||
const ExpressionSetter = REGISTERED_FORM_ITEM_MAP['expressionSetter']?.config?.component;
|
||||
|
||||
const setterNode = isVariable ? (
|
||||
<ExpressionSetter {...expProps} {...baseComponentProps} />
|
||||
) : (
|
||||
_options.render({
|
||||
renderSetter({
|
||||
...expProps,
|
||||
...baseComponentProps,
|
||||
...setterProps, // setterProps 优先级大于快捷属性
|
||||
@@ -158,8 +141,7 @@ export function createFormItem(options: IFormItemCreateOptions) {
|
||||
return (
|
||||
<FormControl
|
||||
visible={getVisible(model)}
|
||||
type={_options.type}
|
||||
defaultCollapsed={_options.defaultCollapsed}
|
||||
defaultCollapsed={options.defaultCollapsed}
|
||||
label={title}
|
||||
note={name}
|
||||
tip={tip}
|
||||
@@ -192,28 +174,27 @@ export function createFormItem(options: IFormItemCreateOptions) {
|
||||
);
|
||||
}
|
||||
|
||||
FormItem.displayName = `FormItem_${_options.name}`;
|
||||
FormItem.displayName = `FormItem_${options.name}`;
|
||||
FormItem.config = options;
|
||||
|
||||
return observer(FormItem);
|
||||
}
|
||||
|
||||
// setter 查找表
|
||||
const SETTERS_DICT: Record<string, React.FunctionComponent<any>> = {};
|
||||
// setter 校验函数查找表
|
||||
const SETTERS_VALIDATE_DICT: Record<string, IFormItemCreateOptions['validate']> = {};
|
||||
// 已注册的 setter 查找表
|
||||
const REGISTERED_FORM_ITEM_MAP: Record<string, ReturnType<typeof createFormItem>> = {};
|
||||
|
||||
INTERNAL_SETTERS.forEach((config) => {
|
||||
const ret = createFormItem(config);
|
||||
/**
|
||||
* Setter 注册
|
||||
* @param config 注册选项
|
||||
*/
|
||||
export function register(config: IFormItemCreateOptions) {
|
||||
const names = [config.name, ...(config.alias ?? [])];
|
||||
names.forEach((name) => {
|
||||
SETTERS_DICT[name] = ret;
|
||||
REGISTERED_FORM_ITEM_MAP[name] = createFormItem(config);
|
||||
});
|
||||
if (config.validate) {
|
||||
names.forEach((name) => {
|
||||
SETTERS_VALIDATE_DICT[name] = config.validate;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
INTERNAL_SETTERS.forEach(register);
|
||||
|
||||
const iconStyle = {
|
||||
color: 'red',
|
||||
@@ -221,9 +202,9 @@ const iconStyle = {
|
||||
|
||||
export function SettingFormItem(props: FormItemProps) {
|
||||
const { setter } = props;
|
||||
const Comp = SETTERS_DICT[setter];
|
||||
const Comp = REGISTERED_FORM_ITEM_MAP[setter];
|
||||
if (Comp == null) {
|
||||
const Fallback = SETTERS_DICT.expressionSetter;
|
||||
const Fallback = REGISTERED_FORM_ITEM_MAP.expressionSetter;
|
||||
return (
|
||||
<Fallback
|
||||
{...props}
|
||||
@@ -237,14 +218,3 @@ export function SettingFormItem(props: FormItemProps) {
|
||||
}
|
||||
return React.createElement(Comp, props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter 注册
|
||||
* @param options
|
||||
*/
|
||||
export function register(options: IFormItemCreateOptions) {
|
||||
if (SETTERS_DICT[options.name]) {
|
||||
logger.log(`Internal setter override: <${options.name}>`);
|
||||
}
|
||||
SETTERS_DICT[options.name] = createFormItem(options);
|
||||
}
|
||||
|
||||
@@ -5539,7 +5539,7 @@
|
||||
resolved "https://registry.npmmirror.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz"
|
||||
integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
|
||||
|
||||
"@yarnpkg/parsers@^3.0.0-rc.18":
|
||||
"@yarnpkg/parsers@3.0.0-rc.48.1", "@yarnpkg/parsers@^3.0.0-rc.18":
|
||||
version "3.0.0-rc.48.1"
|
||||
resolved "https://registry.npmmirror.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.48.1.tgz#8636c24c02c888f2602a464edfd7fb113d75e937"
|
||||
integrity sha512-qEewJouhRvaecGjbkjz9kMKn96UASbDodNrE5MYy2TrXkHcisIkbMxZdGBYfAq+s1dFtCSx/5H4k5bEkfakM+A==
|
||||
@@ -13946,12 +13946,7 @@ modify-values@^1.0.0:
|
||||
resolved "https://registry.npmmirror.com/modify-values/-/modify-values-1.0.1.tgz"
|
||||
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
|
||||
|
||||
moment@^2.24.0, moment@^2.29.2:
|
||||
version "2.29.4"
|
||||
resolved "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz"
|
||||
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
|
||||
|
||||
moment@^2.29.4:
|
||||
moment@^2.24.0, moment@^2.29.2, moment@^2.29.4:
|
||||
version "2.29.4"
|
||||
resolved "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
|
||||
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
|
||||
|
||||
Reference in New Issue
Block a user