fix: renderSetter with template (#202)

* fix: renderSetter with template

* fix: update types
This commit is contained in:
Wells
2024-09-03 16:52:59 +08:00
committed by GitHub
parent a86e0e049c
commit ea96872261
9 changed files with 95 additions and 110 deletions
+45 -1
View File
@@ -48,7 +48,6 @@ const Snippet3ColumnLayout: IComponentPrototype = {
icon: 'icon-column-3',
type: 'snippet',
package: '@music163/antd',
// FIXME: Column 组件 需要更新为 defineComponent
initChildren: `
<Columns columns={12}>
<Column colSpan={4}>
@@ -169,6 +168,32 @@ const prototypes: Dict<IComponentPrototype> = {
Snippet2ColumnLayout,
Snippet3ColumnLayout,
SnippetButtonGroup,
Section: {
...basePrototypes['Section'],
props: [
// ...(basePrototypes['Section'].props as any),
{
name: 'title',
title: '标题',
setter: 'textSetter',
},
{
name: 'extra',
title: '额外内容',
setter: 'renderSetter',
options: [
{
label: '按钮组',
value: 'ButtonGroup',
renderBody:
'<ButtonGroup><Button>button1</Button><Button>button2</Button></ButtonGroup>',
relatedImports: ['ButtonGroup', 'Button'],
},
],
template: '(v) => {\n return {{content}};\n}',
},
],
},
Box: {
name: 'Box',
title: '盒子',
@@ -207,6 +232,25 @@ const prototypes: Dict<IComponentPrototype> = {
template: '(e) => {\n {{content}}\n}',
tip: '回调参数说明:e 为事件对象',
},
{
name: 'renderFoo',
title: 'foo自定义渲染',
setter: 'renderSetter',
options: [
{
label: '占位空间',
value: 'Box',
render: '() => <Box>test</Box>',
relatedImports: ['Box'],
},
{
label: '占位文本',
value: 'Text',
render: '() => <Text>text</Text>',
relatedImports: ['Text'],
},
],
},
],
},
Columns: {
@@ -1,11 +1,11 @@
import React, { useCallback } from 'react';
import { Radio, RadioProps, Tooltip } from 'antd';
import type { OptionType } from '@music163/tango-helpers';
import type { IOptionItem } from '@music163/tango-helpers';
import { FormItemComponentProps } from '@music163/tango-setting-form';
import { IconFont } from '@music163/tango-ui';
interface ChoiceSetterProps {
options?: OptionType[];
options?: IOptionItem[];
}
export function ChoiceSetter({
@@ -58,7 +58,7 @@ const suffixStyle = css`
}
`;
export interface ExpressionSetterProps extends FormItemComponentProps<string> {
export interface CodeSetterProps extends FormItemComponentProps<string> {
modalTitle?: string;
modalTip?: string;
autoCompleteOptions?: string[];
@@ -70,7 +70,7 @@ export interface ExpressionSetterProps extends FormItemComponentProps<string> {
expressionType?: 'cssObject';
}
export function ExpressionSetter(props: ExpressionSetterProps) {
export function CodeSetter(props: CodeSetterProps) {
const {
onChange,
modalTitle,
@@ -5,7 +5,7 @@ import { ActionSelect } from '@music163/tango-ui';
import { FormItemComponentProps } from '@music163/tango-setting-form';
import { useWorkspace, useWorkspaceData } from '@music163/tango-context';
import { Dict, wrapCode } from '@music163/tango-helpers';
import { ExpressionPopover, getCallbackValue } from './expression-setter';
import { ExpressionPopover, getCallbackValue } from './code-setter';
import { value2code } from '@music163/tango-core';
enum EventAction {
+5 -15
View File
@@ -5,14 +5,14 @@ import { CssSetter } from './css-setter';
import { DateRangeSetter, DateSetter, TimeRangeSetter } from './date-setter';
import { EnumSetter } from './enum-setter';
import { EventSetter } from './event-setter';
import { ExpressionSetter } from './expression-setter';
import { CodeSetter } from './code-setter';
import { JSONSetter } from './json-setter';
import { JsxSetter } from './jsx-setter';
import { ListSetter } from './list-setter';
import { ModelSetter } from './model-setter';
import { OptionSetter } from './option-setter';
import { PickerSetter } from './picker-setter';
import { RenderSetter, TableCellSetter, TableExpandableSetter } from './render-setter';
import { RenderSetter } from './render-setter';
import { RouterSetter } from './router-setter';
import {
SpacingSetter,
@@ -49,7 +49,7 @@ export const BUILT_IN_SETTERS: IFormItemCreateOptions[] = [
{
name: 'codeSetter',
alias: ['expSetter', 'expressionSetter'],
component: ExpressionSetter,
component: CodeSetter,
type: 'code',
validate: codeValidate,
},
@@ -126,22 +126,12 @@ export const BUILT_IN_SETTERS: IFormItemCreateOptions[] = [
component: PickerSetter,
},
{
name: 'renderPropsSetter',
name: 'renderSetter',
alias: ['renderPropsSetter'],
component: RenderSetter,
type: 'code',
validate: codeValidate,
},
{
name: 'tableCellSetter',
component: TableCellSetter,
type: 'code',
},
{
name: 'tableExpandableSetter',
component: TableExpandableSetter,
type: 'code',
validate: codeValidate,
},
{
name: 'routerSetter',
component: RouterSetter,
+10 -80
View File
@@ -2,22 +2,16 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { ActionSelect, InputCode } from '@music163/tango-ui';
import { FormItemComponentProps } from '@music163/tango-setting-form';
import { Box } from 'coral-system';
import { Dict } from '@music163/tango-helpers';
interface IRenderOption {
label: string;
value: string;
render?: string;
relatedImports?: string[];
}
import { Dict, IOptionItem } from '@music163/tango-helpers';
import { getCallbackValue } from './code-setter';
export interface RenderSetterProps {
text?: string;
options?: IRenderOption[];
fallbackOption?: IRenderOption;
options?: IOptionItem[];
fallbackOption?: IOptionItem;
}
const defaultOptions: IRenderOption[] = [
const defaultOptions: IOptionItem[] = [
{ label: '取消自定义', value: '' },
{ label: '自定义渲染', value: 'Box', render: '() => <Box></Box>' },
];
@@ -30,6 +24,7 @@ export function RenderSetter({
onChange,
text = '自定义渲染为',
options = defaultOptions,
template = `() => {{content}}`,
fallbackOption,
}: FormItemComponentProps & RenderSetterProps) {
const [inputValue, setInputValue] = useState(value || '');
@@ -47,13 +42,14 @@ export function RenderSetter({
const onSelect = useCallback(
(key: string) => {
const option = optionsMap[key] || fallbackOption;
if (option?.render) {
onChange(option.render, { relatedImports: option.relatedImports });
const next = option?.render || getCallbackValue(option.renderBody, template);
if (next) {
onChange(next, { relatedImports: option.relatedImports });
} else {
onChange(undefined);
}
},
[optionsMap, fallbackOption, onChange],
[optionsMap, fallbackOption, onChange, template],
);
return (
<Box>
@@ -68,69 +64,3 @@ export function RenderSetter({
</Box>
);
}
const getRender = (content: string, type?: 'tableCell' | 'tableExpandable') => {
let code;
switch (type) {
case 'tableCell':
code = `(value, record, index) => ${content}`;
break;
case 'tableExpandable':
code = `{
expandedRowRender: (record) => ${content},
rowExpandable: (record) => true
}`;
break;
default:
code = `() => ${content}`;
break;
}
return code;
};
const tableCellOptions: RenderSetterProps['options'] = [
{ label: '取消自定义', value: '' },
{
label: '自定义区域',
value: 'Box',
render: getRender('<Box></Box>', 'tableCell'),
relatedImports: ['Box'],
},
{
label: '标签',
value: 'Tag',
render: getRender('<Tag>tag</Tag>', 'tableCell'),
relatedImports: ['Tag'],
},
{
label: '按钮',
value: 'Button',
render: getRender('<Button>button</Button>', 'tableCell'),
relatedImports: ['Button'],
},
{
label: '图片',
value: 'Image',
render: getRender('<Image width={150} src="https://picsum.photos/100" />', 'tableCell'),
relatedImports: ['Image'],
},
];
const tableExpandableOptions: RenderSetterProps['options'] = [
{
label: '设置可展开行',
value: 'Box',
render: getRender('<Box></Box>', 'tableExpandable'),
relatedImports: ['Box'],
},
{ label: '取消可展开行', value: '' },
];
export function TableCellSetter(props: FormItemComponentProps) {
return <RenderSetter options={tableCellOptions} {...props} />;
}
// FIXME: 应该直接用 props 嵌套的模式
export function TableExpandableSetter(props: FormItemComponentProps) {
return <RenderSetter options={tableExpandableOptions} text="配置表格可展开行" {...props} />;
}
+20 -4
View File
@@ -10,11 +10,19 @@ export type MousePoint = {
y: number;
};
export type OptionType = {
/**
* @deprecated 使用 IOptionItem 代替
*/
export type OptionType = IOptionItem<any>;
/**
* 列表项
*/
export interface IOptionItem<T = string> {
/**
* 值
*/
value: any;
value: T;
/**
* 显示的文本
*/
@@ -28,10 +36,18 @@ export type OptionType = {
*/
tip?: string;
/**
* 关联的导入
* 自定义渲染函数,仅用于 renderSetter
*/
render?: string;
/**
* 自定义渲染函数的 body(可以用来和 template 配合),仅用于 renderSetter
*/
renderBody?: string;
/**
* 关联的导入,仅用于 renderSetter
*/
relatedImports?: string[];
};
}
/**
* 变量树节点类型
+2 -2
View File
@@ -2,7 +2,7 @@
* 物料描述类型
*/
import { OptionType } from './advanced';
import { IOptionItem } from './advanced';
import { PartialRecord } from './base';
/**
@@ -113,7 +113,7 @@ export interface IComponentProp<T = any> {
/**
* 配置项的可选值,setterProps.options 的简写
*/
options?: OptionType[];
options?: IOptionItem[];
/**
* 是否禁用变量绑定
*/
+8 -3
View File
@@ -231,9 +231,14 @@ export function createFormItem(options: IFormItemCreateOptions) {
// FIXME: 重新考虑这段代码的位置,外置这个逻辑
if (
['codeSetter', 'expressionSetter', 'expSetter', 'actionSetter', 'eventSetter'].includes(
setter,
)
[
'codeSetter',
'expressionSetter',
'expSetter',
'actionSetter',
'eventSetter',
'renderSetter',
].includes(setter)
) {
expProps = {
modalTitle: title,