mirror of
https://github.com/NetEase/tango.git
synced 2026-09-01 15:03:03 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a3ab3c093 | |||
| 55602fc961 | |||
| a3c0e463ca | |||
| 79f9a8c179 | |||
| ea96872261 |
@@ -377,13 +377,16 @@ export default defineServices({
|
|||||||
add: {
|
add: {
|
||||||
url: 'https://nei.hz.netease.com/api/apimock-v2/c45109399a1d33d83e32a59984b25b00/api/users',
|
url: 'https://nei.hz.netease.com/api/apimock-v2/c45109399a1d33d83e32a59984b25b00/api/users',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
description: '新增用户'
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
url: 'https://nei.hz.netease.com/api/apimock-v2/c45109399a1d33d83e32a59984b25b00/api/users',
|
url: 'https://nei.hz.netease.com/api/apimock-v2/c45109399a1d33d83e32a59984b25b00/api/users',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
description: '更新用户'
|
||||||
},
|
},
|
||||||
delete: {
|
delete: {
|
||||||
url: 'https://nei.hz.netease.com/api/apimock-v2/c45109399a1d33d83e32a59984b25b00/api/users?id=1',
|
url: 'https://nei.hz.netease.com/api/apimock-v2/c45109399a1d33d83e32a59984b25b00/api/users?id=1',
|
||||||
|
description: '删除用户'
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ const Snippet3ColumnLayout: IComponentPrototype = {
|
|||||||
icon: 'icon-column-3',
|
icon: 'icon-column-3',
|
||||||
type: 'snippet',
|
type: 'snippet',
|
||||||
package: '@music163/antd',
|
package: '@music163/antd',
|
||||||
// FIXME: Column 组件 需要更新为 defineComponent
|
|
||||||
initChildren: `
|
initChildren: `
|
||||||
<Columns columns={12}>
|
<Columns columns={12}>
|
||||||
<Column colSpan={4}>
|
<Column colSpan={4}>
|
||||||
@@ -169,6 +168,32 @@ const prototypes: Dict<IComponentPrototype> = {
|
|||||||
Snippet2ColumnLayout,
|
Snippet2ColumnLayout,
|
||||||
Snippet3ColumnLayout,
|
Snippet3ColumnLayout,
|
||||||
SnippetButtonGroup,
|
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: {
|
Box: {
|
||||||
name: 'Box',
|
name: 'Box',
|
||||||
title: '盒子',
|
title: '盒子',
|
||||||
@@ -207,6 +232,25 @@ const prototypes: Dict<IComponentPrototype> = {
|
|||||||
template: '(e) => {\n {{content}}\n}',
|
template: '(e) => {\n {{content}}\n}',
|
||||||
tip: '回调参数说明:e 为事件对象',
|
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: {
|
Columns: {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { ClassNameInput } from '@music163/tango-ui';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'UI/ClassNameInput',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Basic() {
|
||||||
|
return <ClassNameInput defaultValue="hello world" onChange={console.log} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Controlled() {
|
||||||
|
const [value, setValue] = useState('');
|
||||||
|
return <ClassNameInput value={value} onChange={setValue} />;
|
||||||
|
}
|
||||||
@@ -3,6 +3,12 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.1.10](https://github.com/netease/tango/compare/@music163/tango-context@1.1.9...@music163/tango-context@1.1.10) (2024-09-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- service support set description field ([#206](https://github.com/netease/tango/issues/206)) ([79f9a8c](https://github.com/netease/tango/commit/79f9a8c1791424f35f194ab2a9aa7c263ef39f40))
|
||||||
|
|
||||||
## [1.1.9](https://github.com/netease/tango/compare/@music163/tango-context@1.1.8...@music163/tango-context@1.1.9) (2024-09-02)
|
## [1.1.9](https://github.com/netease/tango/compare/@music163/tango-context@1.1.8...@music163/tango-context@1.1.9) (2024-09-02)
|
||||||
|
|
||||||
**Note:** Version bump only for package @music163/tango-context
|
**Note:** Version bump only for package @music163/tango-context
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@music163/tango-context",
|
"name": "@music163/tango-context",
|
||||||
"version": "1.1.9",
|
"version": "1.1.10",
|
||||||
"description": "react context for tango-apps",
|
"description": "react context for tango-apps",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
"react": ">= 16.8"
|
"react": ">= 16.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@music163/tango-core": "^1.4.3",
|
"@music163/tango-core": "^1.4.4",
|
||||||
"@music163/tango-helpers": "^1.2.3",
|
"@music163/tango-helpers": "^1.2.4",
|
||||||
"mobx-react-lite": "4.0.7"
|
"mobx-react-lite": "4.0.7"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -90,12 +90,15 @@ export const useWorkspaceData = () => {
|
|||||||
key: prefix,
|
key: prefix,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
showAddButton: true,
|
showAddButton: true,
|
||||||
children: Object.keys(file.serviceFunctions || {}).map((key) => ({
|
children: Object.entries(file.serviceFunctions || {}).map(([key, value]) => {
|
||||||
title: key,
|
const title = value.description ? `${key}(${value.description})` : key;
|
||||||
key: [prefix, key].join('.'),
|
return {
|
||||||
type: 'function',
|
title,
|
||||||
showRemoveButton: true,
|
key: [prefix, key].join('.'),
|
||||||
})),
|
type: 'function',
|
||||||
|
showRemoveButton: true,
|
||||||
|
};
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.4.4](https://github.com/netease/tango/compare/@music163/tango-core@1.4.3...@music163/tango-core@1.4.4) (2024-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @music163/tango-core
|
||||||
|
|
||||||
## [1.4.3](https://github.com/netease/tango/compare/@music163/tango-core@1.4.2...@music163/tango-core@1.4.3) (2024-09-02)
|
## [1.4.3](https://github.com/netease/tango/compare/@music163/tango-core@1.4.2...@music163/tango-core@1.4.3) (2024-09-02)
|
||||||
|
|
||||||
**Note:** Version bump only for package @music163/tango-core
|
**Note:** Version bump only for package @music163/tango-core
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@music163/tango-core",
|
"name": "@music163/tango-core",
|
||||||
"version": "1.4.3",
|
"version": "1.4.4",
|
||||||
"description": "tango core",
|
"description": "tango core",
|
||||||
"author": "wwsun <ww.sun@outlook.com>",
|
"author": "wwsun <ww.sun@outlook.com>",
|
||||||
"homepage": "",
|
"homepage": "",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"@babel/parser": "^7.23.5",
|
"@babel/parser": "^7.23.5",
|
||||||
"@babel/traverse": "^7.23.5",
|
"@babel/traverse": "^7.23.5",
|
||||||
"@babel/types": "^7.23.5",
|
"@babel/types": "^7.23.5",
|
||||||
"@music163/tango-helpers": "^1.2.3",
|
"@music163/tango-helpers": "^1.2.4",
|
||||||
"@types/babel__generator": "^7.6.7",
|
"@types/babel__generator": "^7.6.7",
|
||||||
"@types/babel__traverse": "^7.20.4",
|
"@types/babel__traverse": "^7.20.4",
|
||||||
"mobx": "6.12.3",
|
"mobx": "6.12.3",
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.4.6](https://github.com/netease/tango/compare/@music163/tango-designer@1.4.5...@music163/tango-designer@1.4.6) (2024-09-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- add classNameSetter and classNameInput ([#207](https://github.com/netease/tango/issues/207)) ([55602fc](https://github.com/netease/tango/commit/55602fc961b5c20d923891ce13d7a51588bd047f))
|
||||||
|
- renderSetter with template ([#202](https://github.com/netease/tango/issues/202)) ([ea96872](https://github.com/netease/tango/commit/ea9687226123c839f7a9e001b4c01aa8315a135d))
|
||||||
|
- service support set description field ([#206](https://github.com/netease/tango/issues/206)) ([79f9a8c](https://github.com/netease/tango/commit/79f9a8c1791424f35f194ab2a9aa7c263ef39f40))
|
||||||
|
|
||||||
## [1.4.5](https://github.com/netease/tango/compare/@music163/tango-designer@1.4.4...@music163/tango-designer@1.4.5) (2024-09-02)
|
## [1.4.5](https://github.com/netease/tango/compare/@music163/tango-designer@1.4.4...@music163/tango-designer@1.4.5) (2024-09-02)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@music163/tango-designer",
|
"name": "@music163/tango-designer",
|
||||||
"version": "1.4.5",
|
"version": "1.4.6",
|
||||||
"description": "lowcode designer",
|
"description": "lowcode designer",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react"
|
"react"
|
||||||
@@ -33,12 +33,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^4.8.0",
|
"@ant-design/icons": "^4.8.0",
|
||||||
"@music163/request": "^0.2.0",
|
"@music163/request": "^0.2.0",
|
||||||
"@music163/tango-context": "^1.1.9",
|
"@music163/tango-context": "^1.1.10",
|
||||||
"@music163/tango-core": "^1.4.3",
|
"@music163/tango-core": "^1.4.4",
|
||||||
"@music163/tango-helpers": "^1.2.3",
|
"@music163/tango-helpers": "^1.2.4",
|
||||||
"@music163/tango-sandbox": "^1.0.12",
|
"@music163/tango-sandbox": "^1.0.13",
|
||||||
"@music163/tango-setting-form": "^1.2.14",
|
"@music163/tango-setting-form": "^1.2.15",
|
||||||
"@music163/tango-ui": "^1.4.4",
|
"@music163/tango-ui": "^1.4.5",
|
||||||
"antd": "^4.24.2",
|
"antd": "^4.24.2",
|
||||||
"cash-dom": "^8.1.2",
|
"cash-dom": "^8.1.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ export function AddServiceForm({
|
|||||||
>
|
>
|
||||||
<Input placeholder="请输入数据服务调用名称" disabled={disabled || isModifyMode} />
|
<Input placeholder="请输入数据服务调用名称" disabled={disabled || isModifyMode} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
{/* 备注 */}
|
||||||
|
<Form.Item label="备注" name="description">
|
||||||
|
<Input placeholder="请输入备注信息" />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item label="路径" name="url" rules={[{ required: true, type: 'url' }]}>
|
<Form.Item label="路径" name="url" rules={[{ required: true, type: 'url' }]}>
|
||||||
<Input placeholder="请输入数据服务调用名称" disabled={disabled || isModifyMode} />
|
<Input placeholder="请输入数据服务调用名称" disabled={disabled || isModifyMode} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Radio, RadioProps, Tooltip } from 'antd';
|
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 { FormItemComponentProps } from '@music163/tango-setting-form';
|
||||||
import { IconFont } from '@music163/tango-ui';
|
import { IconFont } from '@music163/tango-ui';
|
||||||
|
|
||||||
interface ChoiceSetterProps {
|
interface ChoiceSetterProps {
|
||||||
options?: OptionType[];
|
options?: IOptionItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ChoiceSetter({
|
export function ChoiceSetter({
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
||||||
|
import { ClassNameInput } from '@music163/tango-ui';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export function ClassNameSetter({ value, onChange }: FormItemComponentProps<string>) {
|
||||||
|
return <ClassNameInput value={value} onChange={onChange} />;
|
||||||
|
}
|
||||||
+2
-2
@@ -58,7 +58,7 @@ const suffixStyle = css`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export interface ExpressionSetterProps extends FormItemComponentProps<string> {
|
export interface CodeSetterProps extends FormItemComponentProps<string> {
|
||||||
modalTitle?: string;
|
modalTitle?: string;
|
||||||
modalTip?: string;
|
modalTip?: string;
|
||||||
autoCompleteOptions?: string[];
|
autoCompleteOptions?: string[];
|
||||||
@@ -70,7 +70,7 @@ export interface ExpressionSetterProps extends FormItemComponentProps<string> {
|
|||||||
expressionType?: 'cssObject';
|
expressionType?: 'cssObject';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExpressionSetter(props: ExpressionSetterProps) {
|
export function CodeSetter(props: CodeSetterProps) {
|
||||||
const {
|
const {
|
||||||
onChange,
|
onChange,
|
||||||
modalTitle,
|
modalTitle,
|
||||||
@@ -5,7 +5,7 @@ import { ActionSelect } from '@music163/tango-ui';
|
|||||||
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
||||||
import { useWorkspace, useWorkspaceData } from '@music163/tango-context';
|
import { useWorkspace, useWorkspaceData } from '@music163/tango-context';
|
||||||
import { Dict, wrapCode } from '@music163/tango-helpers';
|
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';
|
import { value2code } from '@music163/tango-core';
|
||||||
|
|
||||||
enum EventAction {
|
enum EventAction {
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import { CssSetter } from './css-setter';
|
|||||||
import { DateRangeSetter, DateSetter, TimeRangeSetter } from './date-setter';
|
import { DateRangeSetter, DateSetter, TimeRangeSetter } from './date-setter';
|
||||||
import { EnumSetter } from './enum-setter';
|
import { EnumSetter } from './enum-setter';
|
||||||
import { EventSetter } from './event-setter';
|
import { EventSetter } from './event-setter';
|
||||||
import { ExpressionSetter } from './expression-setter';
|
import { CodeSetter } from './code-setter';
|
||||||
import { JSONSetter } from './json-setter';
|
import { JSONSetter } from './json-setter';
|
||||||
import { JsxSetter } from './jsx-setter';
|
import { JsxSetter } from './jsx-setter';
|
||||||
import { ListSetter } from './list-setter';
|
import { ListSetter } from './list-setter';
|
||||||
import { ModelSetter } from './model-setter';
|
import { ModelSetter } from './model-setter';
|
||||||
import { OptionSetter } from './option-setter';
|
import { OptionSetter } from './option-setter';
|
||||||
import { PickerSetter } from './picker-setter';
|
import { PickerSetter } from './picker-setter';
|
||||||
import { RenderSetter, TableCellSetter, TableExpandableSetter } from './render-setter';
|
import { RenderSetter } from './render-setter';
|
||||||
import { RouterSetter } from './router-setter';
|
import { RouterSetter } from './router-setter';
|
||||||
import {
|
import {
|
||||||
SpacingSetter,
|
SpacingSetter,
|
||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
FlexDirectionSetter,
|
FlexDirectionSetter,
|
||||||
} from './style-setter';
|
} from './style-setter';
|
||||||
import { ChoiceSetter } from './choice-setter';
|
import { ChoiceSetter } from './choice-setter';
|
||||||
|
import { ClassNameSetter } from './classname-setter';
|
||||||
import { isValidExpressionCode } from '@music163/tango-core';
|
import { isValidExpressionCode } from '@music163/tango-core';
|
||||||
|
|
||||||
const codeValidate: IFormItemCreateOptions['validate'] = (value, field) => {
|
const codeValidate: IFormItemCreateOptions['validate'] = (value, field) => {
|
||||||
@@ -49,10 +50,14 @@ export const BUILT_IN_SETTERS: IFormItemCreateOptions[] = [
|
|||||||
{
|
{
|
||||||
name: 'codeSetter',
|
name: 'codeSetter',
|
||||||
alias: ['expSetter', 'expressionSetter'],
|
alias: ['expSetter', 'expressionSetter'],
|
||||||
component: ExpressionSetter,
|
component: CodeSetter,
|
||||||
type: 'code',
|
type: 'code',
|
||||||
validate: codeValidate,
|
validate: codeValidate,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'classNameSetter',
|
||||||
|
component: ClassNameSetter,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'radioGroupSetter',
|
name: 'radioGroupSetter',
|
||||||
alias: ['choiceSetter'],
|
alias: ['choiceSetter'],
|
||||||
@@ -126,22 +131,12 @@ export const BUILT_IN_SETTERS: IFormItemCreateOptions[] = [
|
|||||||
component: PickerSetter,
|
component: PickerSetter,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'renderPropsSetter',
|
name: 'renderSetter',
|
||||||
|
alias: ['renderPropsSetter'],
|
||||||
component: RenderSetter,
|
component: RenderSetter,
|
||||||
type: 'code',
|
type: 'code',
|
||||||
validate: codeValidate,
|
validate: codeValidate,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'tableCellSetter',
|
|
||||||
component: TableCellSetter,
|
|
||||||
type: 'code',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'tableExpandableSetter',
|
|
||||||
component: TableExpandableSetter,
|
|
||||||
type: 'code',
|
|
||||||
validate: codeValidate,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'routerSetter',
|
name: 'routerSetter',
|
||||||
component: RouterSetter,
|
component: RouterSetter,
|
||||||
|
|||||||
@@ -2,22 +2,16 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import { ActionSelect, InputCode } from '@music163/tango-ui';
|
import { ActionSelect, InputCode } from '@music163/tango-ui';
|
||||||
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
||||||
import { Box } from 'coral-system';
|
import { Box } from 'coral-system';
|
||||||
import { Dict } from '@music163/tango-helpers';
|
import { Dict, IOptionItem } from '@music163/tango-helpers';
|
||||||
|
import { getCallbackValue } from './code-setter';
|
||||||
interface IRenderOption {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
render?: string;
|
|
||||||
relatedImports?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RenderSetterProps {
|
export interface RenderSetterProps {
|
||||||
text?: string;
|
text?: string;
|
||||||
options?: IRenderOption[];
|
options?: IOptionItem[];
|
||||||
fallbackOption?: IRenderOption;
|
fallbackOption?: IOptionItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: IRenderOption[] = [
|
const defaultOptions: IOptionItem[] = [
|
||||||
{ label: '取消自定义', value: '' },
|
{ label: '取消自定义', value: '' },
|
||||||
{ label: '自定义渲染', value: 'Box', render: '() => <Box></Box>' },
|
{ label: '自定义渲染', value: 'Box', render: '() => <Box></Box>' },
|
||||||
];
|
];
|
||||||
@@ -30,6 +24,7 @@ export function RenderSetter({
|
|||||||
onChange,
|
onChange,
|
||||||
text = '自定义渲染为',
|
text = '自定义渲染为',
|
||||||
options = defaultOptions,
|
options = defaultOptions,
|
||||||
|
template = `() => {{content}}`,
|
||||||
fallbackOption,
|
fallbackOption,
|
||||||
}: FormItemComponentProps & RenderSetterProps) {
|
}: FormItemComponentProps & RenderSetterProps) {
|
||||||
const [inputValue, setInputValue] = useState(value || '');
|
const [inputValue, setInputValue] = useState(value || '');
|
||||||
@@ -47,13 +42,14 @@ export function RenderSetter({
|
|||||||
const onSelect = useCallback(
|
const onSelect = useCallback(
|
||||||
(key: string) => {
|
(key: string) => {
|
||||||
const option = optionsMap[key] || fallbackOption;
|
const option = optionsMap[key] || fallbackOption;
|
||||||
if (option?.render) {
|
const next = option?.render || getCallbackValue(option.renderBody, template);
|
||||||
onChange(option.render, { relatedImports: option.relatedImports });
|
if (next) {
|
||||||
|
onChange(next, { relatedImports: option.relatedImports });
|
||||||
} else {
|
} else {
|
||||||
onChange(undefined);
|
onChange(undefined);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[optionsMap, fallbackOption, onChange],
|
[optionsMap, fallbackOption, onChange, template],
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
@@ -68,69 +64,3 @@ export function RenderSetter({
|
|||||||
</Box>
|
</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} />;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.2.4](https://github.com/netease/tango/compare/@music163/tango-helpers@1.2.3...@music163/tango-helpers@1.2.4) (2024-09-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- renderSetter with template ([#202](https://github.com/netease/tango/issues/202)) ([ea96872](https://github.com/netease/tango/commit/ea9687226123c839f7a9e001b4c01aa8315a135d))
|
||||||
|
|
||||||
## [1.2.3](https://github.com/netease/tango/compare/@music163/tango-helpers@1.2.2...@music163/tango-helpers@1.2.3) (2024-09-02)
|
## [1.2.3](https://github.com/netease/tango/compare/@music163/tango-helpers@1.2.2...@music163/tango-helpers@1.2.3) (2024-09-02)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@music163/tango-helpers",
|
"name": "@music163/tango-helpers",
|
||||||
"version": "1.2.3",
|
"version": "1.2.4",
|
||||||
"description": "Shared types, helpers, and hooks of tango-apps",
|
"description": "Shared types, helpers, and hooks of tango-apps",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"shared",
|
"shared",
|
||||||
|
|||||||
@@ -10,11 +10,19 @@ export type MousePoint = {
|
|||||||
y: number;
|
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;
|
tip?: string;
|
||||||
/**
|
/**
|
||||||
* 关联的导入
|
* 自定义渲染函数,仅用于 renderSetter
|
||||||
|
*/
|
||||||
|
render?: string;
|
||||||
|
/**
|
||||||
|
* 自定义渲染函数的 body(可以用来和 template 配合),仅用于 renderSetter
|
||||||
|
*/
|
||||||
|
renderBody?: string;
|
||||||
|
/**
|
||||||
|
* 关联的导入,仅用于 renderSetter
|
||||||
*/
|
*/
|
||||||
relatedImports?: string[];
|
relatedImports?: string[];
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 变量树节点类型
|
* 变量树节点类型
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* 物料描述类型
|
* 物料描述类型
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { OptionType } from './advanced';
|
import { IOptionItem } from './advanced';
|
||||||
import { PartialRecord } from './base';
|
import { PartialRecord } from './base';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,7 +113,7 @@ export interface IComponentProp<T = any> {
|
|||||||
/**
|
/**
|
||||||
* 配置项的可选值,setterProps.options 的简写
|
* 配置项的可选值,setterProps.options 的简写
|
||||||
*/
|
*/
|
||||||
options?: OptionType[];
|
options?: IOptionItem[];
|
||||||
/**
|
/**
|
||||||
* 是否禁用变量绑定
|
* 是否禁用变量绑定
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.0.13](https://github.com/netease/tango/compare/@music163/tango-sandbox@1.0.12...@music163/tango-sandbox@1.0.13) (2024-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @music163/tango-sandbox
|
||||||
|
|
||||||
## [1.0.12](https://github.com/netease/tango/compare/@music163/tango-sandbox@1.0.11...@music163/tango-sandbox@1.0.12) (2024-09-02)
|
## [1.0.12](https://github.com/netease/tango/compare/@music163/tango-sandbox@1.0.11...@music163/tango-sandbox@1.0.12) (2024-09-02)
|
||||||
|
|
||||||
**Note:** Version bump only for package @music163/tango-sandbox
|
**Note:** Version bump only for package @music163/tango-sandbox
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@music163/tango-sandbox",
|
"name": "@music163/tango-sandbox",
|
||||||
"version": "1.0.12",
|
"version": "1.0.13",
|
||||||
"description": "sandbox of tango apps",
|
"description": "sandbox of tango apps",
|
||||||
"author": "wwsun <ww.sun@outlook.com>",
|
"author": "wwsun <ww.sun@outlook.com>",
|
||||||
"homepage": "",
|
"homepage": "",
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^4.8.0",
|
"@ant-design/icons": "^4.8.0",
|
||||||
"@music163/tango-core": "^1.4.3",
|
"@music163/tango-core": "^1.4.4",
|
||||||
"@music163/tango-helpers": "^1.2.3",
|
"@music163/tango-helpers": "^1.2.4",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"lodash.isequal": "4.5.0",
|
"lodash.isequal": "4.5.0",
|
||||||
"react-frame-component": "^5.2.4"
|
"react-frame-component": "^5.2.4"
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.2.15](https://github.com/netease/tango/compare/@music163/tango-setting-form@1.2.14...@music163/tango-setting-form@1.2.15) (2024-09-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- renderSetter with template ([#202](https://github.com/netease/tango/issues/202)) ([ea96872](https://github.com/netease/tango/commit/ea9687226123c839f7a9e001b4c01aa8315a135d))
|
||||||
|
|
||||||
## [1.2.14](https://github.com/netease/tango/compare/@music163/tango-setting-form@1.2.13...@music163/tango-setting-form@1.2.14) (2024-09-02)
|
## [1.2.14](https://github.com/netease/tango/compare/@music163/tango-setting-form@1.2.13...@music163/tango-setting-form@1.2.14) (2024-09-02)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@music163/tango-setting-form",
|
"name": "@music163/tango-setting-form",
|
||||||
"version": "1.2.14",
|
"version": "1.2.15",
|
||||||
"description": "setting form of tango-apps",
|
"description": "setting form of tango-apps",
|
||||||
"author": "wwsun <ww.sun@outlook.com>",
|
"author": "wwsun <ww.sun@outlook.com>",
|
||||||
"homepage": "",
|
"homepage": "",
|
||||||
@@ -28,9 +28,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^4.8.0",
|
"@ant-design/icons": "^4.8.0",
|
||||||
"@music163/tango-core": "^1.4.3",
|
"@music163/tango-core": "^1.4.4",
|
||||||
"@music163/tango-helpers": "^1.2.3",
|
"@music163/tango-helpers": "^1.2.4",
|
||||||
"@music163/tango-ui": "^1.4.4",
|
"@music163/tango-ui": "^1.4.5",
|
||||||
"antd": "^4.24.2",
|
"antd": "^4.24.2",
|
||||||
"coral-system": "^1.0.5",
|
"coral-system": "^1.0.5",
|
||||||
"mobx": "6.12.3",
|
"mobx": "6.12.3",
|
||||||
|
|||||||
@@ -231,9 +231,14 @@ export function createFormItem(options: IFormItemCreateOptions) {
|
|||||||
|
|
||||||
// FIXME: 重新考虑这段代码的位置,外置这个逻辑
|
// FIXME: 重新考虑这段代码的位置,外置这个逻辑
|
||||||
if (
|
if (
|
||||||
['codeSetter', 'expressionSetter', 'expSetter', 'actionSetter', 'eventSetter'].includes(
|
[
|
||||||
setter,
|
'codeSetter',
|
||||||
)
|
'expressionSetter',
|
||||||
|
'expSetter',
|
||||||
|
'actionSetter',
|
||||||
|
'eventSetter',
|
||||||
|
'renderSetter',
|
||||||
|
].includes(setter)
|
||||||
) {
|
) {
|
||||||
expProps = {
|
expProps = {
|
||||||
modalTitle: title,
|
modalTitle: title,
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.4.5](https://github.com/netease/tango/compare/@music163/tango-ui@1.4.4...@music163/tango-ui@1.4.5) (2024-09-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- add classNameSetter and classNameInput ([#207](https://github.com/netease/tango/issues/207)) ([55602fc](https://github.com/netease/tango/commit/55602fc961b5c20d923891ce13d7a51588bd047f))
|
||||||
|
|
||||||
## [1.4.4](https://github.com/netease/tango/compare/@music163/tango-ui@1.4.3...@music163/tango-ui@1.4.4) (2024-09-02)
|
## [1.4.4](https://github.com/netease/tango/compare/@music163/tango-ui@1.4.3...@music163/tango-ui@1.4.4) (2024-09-02)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@music163/tango-ui",
|
"name": "@music163/tango-ui",
|
||||||
"version": "1.4.4",
|
"version": "1.4.5",
|
||||||
"description": "ui widgets of tango",
|
"description": "ui widgets of tango",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"@codemirror/lang-javascript": "^6.2.2",
|
"@codemirror/lang-javascript": "^6.2.2",
|
||||||
"@codemirror/lint": "^6.7.1",
|
"@codemirror/lint": "^6.7.1",
|
||||||
"@codemirror/search": "^6.5.6",
|
"@codemirror/search": "^6.5.6",
|
||||||
"@music163/tango-helpers": "^1.2.3",
|
"@music163/tango-helpers": "^1.2.4",
|
||||||
"@uiw/react-codemirror": "^4.22.0",
|
"@uiw/react-codemirror": "^4.22.0",
|
||||||
"antd": "^4.24.2",
|
"antd": "^4.24.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
"eslint-linter-browserify": "^8.51.0",
|
"eslint-linter-browserify": "^8.51.0",
|
||||||
"react-draggable": "^4.4.5",
|
"react-draggable": "^4.4.5",
|
||||||
"react-json-view": "^1.21.3",
|
"react-json-view": "^1.21.3",
|
||||||
"react-monaco-editor-lite": "^1.3.11"
|
"react-monaco-editor-lite": "^1.3.16"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public",
|
"access": "public",
|
||||||
|
|||||||
@@ -0,0 +1,312 @@
|
|||||||
|
import React, { useState, useRef, KeyboardEvent, ChangeEvent, useEffect } from 'react';
|
||||||
|
import { Dropdown, Menu, Tag } from 'antd';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const InputWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 11px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
min-height: 32px;
|
||||||
|
&:hover {
|
||||||
|
border-color: #40a9ff;
|
||||||
|
}
|
||||||
|
&:focus-within {
|
||||||
|
border-color: #40a9ff;
|
||||||
|
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Input = styled.input`
|
||||||
|
flex: 1;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
min-width: 50px;
|
||||||
|
height: 24px;
|
||||||
|
line-height: 24px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTag = styled(Tag)`
|
||||||
|
margin: 2px 4px 2px 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Tailwind CSS 基础类名列表
|
||||||
|
const tailwindClasses = [
|
||||||
|
// 布局
|
||||||
|
'container',
|
||||||
|
'flex',
|
||||||
|
'grid',
|
||||||
|
'block',
|
||||||
|
'inline',
|
||||||
|
'inline-block',
|
||||||
|
'hidden',
|
||||||
|
// 弹性布局
|
||||||
|
'flex-row',
|
||||||
|
'flex-col',
|
||||||
|
'flex-wrap',
|
||||||
|
'flex-nowrap',
|
||||||
|
'justify-start',
|
||||||
|
'justify-end',
|
||||||
|
'justify-center',
|
||||||
|
'justify-between',
|
||||||
|
'justify-around',
|
||||||
|
'items-start',
|
||||||
|
'items-end',
|
||||||
|
'items-center',
|
||||||
|
'items-baseline',
|
||||||
|
'items-stretch',
|
||||||
|
// 网格布局
|
||||||
|
'grid-cols-1',
|
||||||
|
'grid-cols-2',
|
||||||
|
'grid-cols-3',
|
||||||
|
'grid-cols-4',
|
||||||
|
'grid-cols-5',
|
||||||
|
'grid-cols-6',
|
||||||
|
'grid-cols-12',
|
||||||
|
// 间距
|
||||||
|
'p-0',
|
||||||
|
'p-1',
|
||||||
|
'p-2',
|
||||||
|
'p-3',
|
||||||
|
'p-4',
|
||||||
|
'p-5',
|
||||||
|
'p-6',
|
||||||
|
'p-8',
|
||||||
|
'p-10',
|
||||||
|
'p-12',
|
||||||
|
'p-16',
|
||||||
|
'p-20',
|
||||||
|
'm-0',
|
||||||
|
'm-1',
|
||||||
|
'm-2',
|
||||||
|
'm-3',
|
||||||
|
'm-4',
|
||||||
|
'm-5',
|
||||||
|
'm-6',
|
||||||
|
'm-8',
|
||||||
|
'm-10',
|
||||||
|
'm-12',
|
||||||
|
'm-16',
|
||||||
|
'm-20',
|
||||||
|
// 尺寸
|
||||||
|
'w-full',
|
||||||
|
'w-auto',
|
||||||
|
'w-1/2',
|
||||||
|
'w-1/3',
|
||||||
|
'w-2/3',
|
||||||
|
'w-1/4',
|
||||||
|
'w-3/4',
|
||||||
|
'h-full',
|
||||||
|
'h-auto',
|
||||||
|
'h-screen',
|
||||||
|
// 字体
|
||||||
|
'text-xs',
|
||||||
|
'text-sm',
|
||||||
|
'text-base',
|
||||||
|
'text-lg',
|
||||||
|
'text-xl',
|
||||||
|
'text-2xl',
|
||||||
|
'text-3xl',
|
||||||
|
'text-4xl',
|
||||||
|
'text-5xl',
|
||||||
|
'font-thin',
|
||||||
|
'font-light',
|
||||||
|
'font-normal',
|
||||||
|
'font-medium',
|
||||||
|
'font-semibold',
|
||||||
|
'font-bold',
|
||||||
|
'font-extrabold',
|
||||||
|
// 文本颜色
|
||||||
|
'text-black',
|
||||||
|
'text-white',
|
||||||
|
'text-gray-100',
|
||||||
|
'text-gray-200',
|
||||||
|
'text-gray-300',
|
||||||
|
'text-gray-400',
|
||||||
|
'text-gray-500',
|
||||||
|
'text-red-500',
|
||||||
|
'text-blue-500',
|
||||||
|
'text-green-500',
|
||||||
|
'text-yellow-500',
|
||||||
|
'text-purple-500',
|
||||||
|
'text-pink-500',
|
||||||
|
// 背景颜色
|
||||||
|
'bg-transparent',
|
||||||
|
'bg-black',
|
||||||
|
'bg-white',
|
||||||
|
'bg-gray-100',
|
||||||
|
'bg-gray-200',
|
||||||
|
'bg-gray-300',
|
||||||
|
'bg-gray-400',
|
||||||
|
'bg-gray-500',
|
||||||
|
'bg-red-500',
|
||||||
|
'bg-blue-500',
|
||||||
|
'bg-green-500',
|
||||||
|
'bg-yellow-500',
|
||||||
|
'bg-purple-500',
|
||||||
|
'bg-pink-500',
|
||||||
|
// 边框
|
||||||
|
'border',
|
||||||
|
'border-0',
|
||||||
|
'border-2',
|
||||||
|
'border-4',
|
||||||
|
'border-8',
|
||||||
|
'border-black',
|
||||||
|
'border-white',
|
||||||
|
'border-gray-300',
|
||||||
|
'border-gray-400',
|
||||||
|
'border-gray-500',
|
||||||
|
// 圆角
|
||||||
|
'rounded-none',
|
||||||
|
'rounded-sm',
|
||||||
|
'rounded',
|
||||||
|
'rounded-lg',
|
||||||
|
'rounded-full',
|
||||||
|
// 阴影
|
||||||
|
'shadow-sm',
|
||||||
|
'shadow',
|
||||||
|
'shadow-md',
|
||||||
|
'shadow-lg',
|
||||||
|
'shadow-xl',
|
||||||
|
'shadow-2xl',
|
||||||
|
'shadow-none',
|
||||||
|
// 不透明度
|
||||||
|
'opacity-0',
|
||||||
|
'opacity-25',
|
||||||
|
'opacity-50',
|
||||||
|
'opacity-75',
|
||||||
|
'opacity-100',
|
||||||
|
];
|
||||||
|
|
||||||
|
interface ClassNameInputProps {
|
||||||
|
value?: string;
|
||||||
|
defaultValue?: string;
|
||||||
|
onChange?: (value: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ClassNameInput({ value, defaultValue, onChange }: ClassNameInputProps) {
|
||||||
|
const [inputValue, setInputValue] = useState('');
|
||||||
|
const [suggestions, setSuggestions] = useState<string[]>([]);
|
||||||
|
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
||||||
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const [internalValue, setInternalValue] = useState(defaultValue || '');
|
||||||
|
const isControlled = value !== undefined;
|
||||||
|
const classNames = (isControlled ? value : internalValue).split(' ').filter(Boolean);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isControlled) {
|
||||||
|
setInternalValue(value);
|
||||||
|
}
|
||||||
|
}, [isControlled, value]);
|
||||||
|
|
||||||
|
const isValidClassName = (className: string) => {
|
||||||
|
return /^[a-zA-Z0-9_-]+(?::[a-zA-Z0-9_-]+)*$/.test(className);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateValue = (newClassNames: string[]) => {
|
||||||
|
const newValue = newClassNames.join(' ');
|
||||||
|
if (isControlled) {
|
||||||
|
onChange?.(newValue);
|
||||||
|
} else {
|
||||||
|
setInternalValue(newValue);
|
||||||
|
onChange?.(newValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
if (highlightedIndex >= 0 && highlightedIndex < suggestions.length) {
|
||||||
|
addClassName(suggestions[highlightedIndex]);
|
||||||
|
} else {
|
||||||
|
addClassName(inputValue.trim());
|
||||||
|
}
|
||||||
|
} else if (event.key === 'ArrowDown') {
|
||||||
|
event.preventDefault();
|
||||||
|
setHighlightedIndex((prev) => (prev < suggestions.length - 1 ? prev + 1 : 0));
|
||||||
|
} else if (event.key === 'ArrowUp') {
|
||||||
|
event.preventDefault();
|
||||||
|
setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : suggestions.length - 1));
|
||||||
|
} else if (event.key === 'Backspace' && inputValue === '' && classNames.length > 0) {
|
||||||
|
event.preventDefault();
|
||||||
|
const newClassNames = [...classNames];
|
||||||
|
newClassNames.pop();
|
||||||
|
updateValue(newClassNames);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const input = event.target.value;
|
||||||
|
setInputValue(input);
|
||||||
|
if (input) {
|
||||||
|
const matchedSuggestions = tailwindClasses
|
||||||
|
.filter(
|
||||||
|
(className) =>
|
||||||
|
className.toLowerCase().includes(input.toLowerCase()) &&
|
||||||
|
!classNames.includes(className),
|
||||||
|
)
|
||||||
|
.slice(0, 10);
|
||||||
|
setSuggestions(matchedSuggestions);
|
||||||
|
setHighlightedIndex(-1);
|
||||||
|
} else {
|
||||||
|
setSuggestions([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addClassName = (className: string) => {
|
||||||
|
if (className && !classNames.includes(className) && isValidClassName(className)) {
|
||||||
|
updateValue([...classNames, className]);
|
||||||
|
setInputValue('');
|
||||||
|
setSuggestions([]);
|
||||||
|
setHighlightedIndex(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeClassName = (removedTag: string) => {
|
||||||
|
const newClassNames = classNames.filter((tag) => tag !== removedTag);
|
||||||
|
updateValue(newClassNames);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSuggestionClick = (suggestion: string) => {
|
||||||
|
addClassName(suggestion);
|
||||||
|
};
|
||||||
|
|
||||||
|
const menu = (
|
||||||
|
<Menu>
|
||||||
|
{suggestions.map((suggestion, index) => (
|
||||||
|
<Menu.Item
|
||||||
|
key={index}
|
||||||
|
onClick={() => handleSuggestionClick(suggestion)}
|
||||||
|
className={index === highlightedIndex ? 'ant-dropdown-menu-item-active' : ''}
|
||||||
|
>
|
||||||
|
{suggestion}
|
||||||
|
</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown overlay={menu} visible={suggestions.length > 0} placement="bottomLeft">
|
||||||
|
<InputWrapper onClick={() => inputRef.current?.focus()}>
|
||||||
|
{classNames.map((className) => (
|
||||||
|
<StyledTag key={className} closable onClose={() => removeClassName(className)}>
|
||||||
|
{className}
|
||||||
|
</StyledTag>
|
||||||
|
))}
|
||||||
|
<Input
|
||||||
|
ref={inputRef}
|
||||||
|
type="text"
|
||||||
|
value={inputValue}
|
||||||
|
onKeyDown={handleInputKeyDown}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
placeholder={classNames.length === 0 ? '输入 class 名称' : ''}
|
||||||
|
/>
|
||||||
|
</InputWrapper>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -26,3 +26,4 @@ export * from './tag-select';
|
|||||||
export * from './popover';
|
export * from './popover';
|
||||||
export * from './drag-panel';
|
export * from './drag-panel';
|
||||||
export * from './context-action';
|
export * from './context-action';
|
||||||
|
export * from './classname-input';
|
||||||
|
|||||||
@@ -16195,10 +16195,10 @@ react-merge-refs@^1.1.0:
|
|||||||
resolved "https://registry.npmmirror.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz"
|
resolved "https://registry.npmmirror.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz"
|
||||||
integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==
|
integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==
|
||||||
|
|
||||||
react-monaco-editor-lite@^1.3.11:
|
react-monaco-editor-lite@^1.3.16:
|
||||||
version "1.3.11"
|
version "1.3.16"
|
||||||
resolved "https://registry.npmmirror.com/react-monaco-editor-lite/-/react-monaco-editor-lite-1.3.11.tgz#b81b681d23f3ca46f54d4e01f13781bcff6a4a03"
|
resolved "https://registry.npmmirror.com/react-monaco-editor-lite/-/react-monaco-editor-lite-1.3.16.tgz#066d744c7414df3b08b4cda65750057c2dd42f45"
|
||||||
integrity sha512-+9xlIn98Yp2hD8OFjRNpQiBx+wLFzsvvT5EgNTxReFrDhFAPPjivdLUCiex1ktzpkGTdo3fxDFUokckvO7hVvQ==
|
integrity sha512-FP3DeGZ709XEz+ZRQiQvw/yAa9fhjJm0989kv85o6f0dKcNBmb4gCADGZdZpoqbYBrT+7wIXBxvH1LQ2N2AodQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
monaco-editor "^0.38.0"
|
monaco-editor "^0.38.0"
|
||||||
monaco-editor-textmate "^4.0.0"
|
monaco-editor-textmate "^4.0.0"
|
||||||
@@ -17697,16 +17697,7 @@ string-length@^4.0.1:
|
|||||||
char-regex "^1.0.2"
|
char-regex "^1.0.2"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.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:
|
||||||
version "4.2.3"
|
|
||||||
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz"
|
|
||||||
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@^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"
|
version "4.2.3"
|
||||||
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz"
|
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
@@ -17819,7 +17810,7 @@ string_decoder@~1.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.1.0"
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
@@ -17833,13 +17824,6 @@ strip-ansi@^3.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex "^2.0.0"
|
ansi-regex "^2.0.0"
|
||||||
|
|
||||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
|
||||||
version "6.0.1"
|
|
||||||
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^5.0.1"
|
|
||||||
|
|
||||||
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
|
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz"
|
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz"
|
||||||
@@ -19376,7 +19360,7 @@ workerpool@^9.1.1:
|
|||||||
resolved "https://registry.npmmirror.com/workerpool/-/workerpool-9.1.1.tgz#9ba4d534a79a5517c1e1b9d1014151516829be8d"
|
resolved "https://registry.npmmirror.com/workerpool/-/workerpool-9.1.1.tgz#9ba4d534a79a5517c1e1b9d1014151516829be8d"
|
||||||
integrity sha512-EFoFTSEo9m4V4wNrwzVRjxnf/E/oBpOzcI/R5CIugJhl9RsCiq525rszo4AtqcjQQoqFdu2E3H82AnbtpaQHvg==
|
integrity sha512-EFoFTSEo9m4V4wNrwzVRjxnf/E/oBpOzcI/R5CIugJhl9RsCiq525rszo4AtqcjQQoqFdu2E3H82AnbtpaQHvg==
|
||||||
|
|
||||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
|
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
@@ -19394,15 +19378,6 @@ wrap-ansi@^6.0.1:
|
|||||||
string-width "^4.1.0"
|
string-width "^4.1.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
wrap-ansi@^7.0.0:
|
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
|
|
||||||
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:
|
wrap-ansi@^8.1.0:
|
||||||
version "8.1.0"
|
version "8.1.0"
|
||||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
|
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user