mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-04-06 21:40:23 +08:00
feat(arco-table): support render component and update example
This commit is contained in:
parent
ab9d8fd96f
commit
63971a46ae
@ -4,7 +4,7 @@ import { css, cx } from '@emotion/css';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { PaginationPropsSpec as BasePaginationPropsSpec } from '../generated/types/Pagination';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
import { useStateValue } from '../hooks/useStateValue';
|
||||
|
||||
const PaginationPropsSpec = Type.Object(BasePaginationPropsSpec);
|
||||
const PaginationStateSpec = Type.Object({
|
||||
|
@ -5,7 +5,7 @@ import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { RadioPropsSpec as BaseRadioPropsSpec } from '../generated/types/Radio';
|
||||
import { useEffect } from 'react';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
import { useStateValue } from '../hooks/useStateValue';
|
||||
|
||||
const RadioPropsSpec = Type.Object({
|
||||
...BaseRadioPropsSpec,
|
||||
|
@ -6,7 +6,7 @@ import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { SelectPropsSpec as BaseSelectPropsSpec } from '../generated/types/Select';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { SelectHandle } from '@arco-design/web-react/es/Select/interface';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
import { useStateValue } from '../hooks/useStateValue';
|
||||
|
||||
const SelectPropsSpec = Type.Object({
|
||||
...BaseSelectPropsSpec,
|
||||
|
@ -4,7 +4,7 @@ import { css } from '@emotion/css';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { SwitchPropsSpec as BaseSwitchPropsSpec } from '../generated/types/Switch';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
import { useStateValue } from '../hooks/useStateValue';
|
||||
|
||||
const SwitchPropsSpec = Type.Object({
|
||||
...BaseSwitchPropsSpec,
|
||||
|
@ -1,4 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { sortBy } from 'lodash-es';
|
||||
import { ResizeCallbackData } from 'react-resizable';
|
||||
import { TableInstance } from '@arco-design/web-react/es/Table/table';
|
||||
import { ColumnProps } from '@arco-design/web-react/es/Table';
|
||||
import { RefInputType } from '@arco-design/web-react/es/Input/interface';
|
||||
import {
|
||||
Button,
|
||||
Link,
|
||||
@ -11,19 +18,14 @@ import {
|
||||
LIST_ITEM_INDEX_EXP,
|
||||
ModuleRenderer,
|
||||
implementRuntimeComponent,
|
||||
ImplWrapper,
|
||||
} from '@sunmao-ui/runtime';
|
||||
import { css } from '@emotion/css';
|
||||
import { sortBy } from 'lodash-es';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { ResizableTitle } from './ResizableTitle';
|
||||
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../../sunmao-helper';
|
||||
import { TablePropsSpec, ColumnSpec } from '../../generated/types/Table';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { TableInstance } from '@arco-design/web-react/es/Table/table';
|
||||
import { ColumnProps } from '@arco-design/web-react/es/Table';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
import { ResizableTitle } from './ResizableTitle';
|
||||
import { RefInputType } from '@arco-design/web-react/es/Input/interface';
|
||||
import { ResizeCallbackData } from 'react-resizable';
|
||||
import { useStateValue } from '../../hooks/useStateValue';
|
||||
|
||||
const TableStateSpec = Type.Object({
|
||||
clickedRow: Type.Optional(Type.Any()),
|
||||
@ -80,6 +82,7 @@ export const exampleProperties: Static<typeof TablePropsSpec> = {
|
||||
type: 'text',
|
||||
filter: true,
|
||||
displayValue: '',
|
||||
componentSlotIndex: 0,
|
||||
},
|
||||
{
|
||||
title: 'Salary',
|
||||
@ -89,6 +92,7 @@ export const exampleProperties: Static<typeof TablePropsSpec> = {
|
||||
filter: false,
|
||||
type: 'text',
|
||||
displayValue: '',
|
||||
componentSlotIndex: 0,
|
||||
},
|
||||
{
|
||||
title: 'Link',
|
||||
@ -97,19 +101,7 @@ export const exampleProperties: Static<typeof TablePropsSpec> = {
|
||||
filter: true,
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
displayValue: '',
|
||||
},
|
||||
{
|
||||
title: 'CustomComponent',
|
||||
dataIndex: 'customComponent',
|
||||
type: 'module',
|
||||
filter: false,
|
||||
module: {
|
||||
id: 'clistItemName-{{$listItem.id}}',
|
||||
handlers: [],
|
||||
properties: [],
|
||||
type: 'core/v1/text',
|
||||
},
|
||||
displayValue: '',
|
||||
componentSlotIndex: 0,
|
||||
},
|
||||
],
|
||||
data: Array(13)
|
||||
@ -156,7 +148,14 @@ export const Table = implementRuntimeComponent({
|
||||
properties: TablePropsSpec,
|
||||
state: TableStateSpec,
|
||||
methods: {},
|
||||
slots: {},
|
||||
slots: {
|
||||
content: {
|
||||
slotProps: Type.Object({
|
||||
[LIST_ITEM_EXP]: Type.Any(),
|
||||
[LIST_ITEM_INDEX_EXP]: Type.Number(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
styleSlots: ['content'],
|
||||
events: ['onRowClick', 'onSearch', 'onPageChange', 'onFilter', 'onSort', 'onChange'],
|
||||
},
|
||||
@ -355,6 +354,46 @@ export const Table = implementRuntimeComponent({
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
||||
case 'component':
|
||||
const childrenSchema = app.spec.components.filter(c => {
|
||||
return c.traits.find(
|
||||
t =>
|
||||
t.type === 'core/v1/slot' &&
|
||||
(t.properties.container as any).id === component.id
|
||||
);
|
||||
});
|
||||
|
||||
const childSchema = childrenSchema[evaledColumn.componentSlotIndex || 0];
|
||||
if (!childSchema) {
|
||||
return (
|
||||
<div>
|
||||
Cannot find child with index {column.componentSlotIndex} in slot.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const _childrenSchema = {
|
||||
...childSchema,
|
||||
id: `${component.id}_${childSchema.id}_${index}`,
|
||||
};
|
||||
|
||||
colItem = (
|
||||
<ImplWrapper
|
||||
key={_childrenSchema.id}
|
||||
component={_childrenSchema}
|
||||
app={app}
|
||||
services={services}
|
||||
childrenMap={{}}
|
||||
isInModule
|
||||
evalListItem
|
||||
slotProps={{
|
||||
[LIST_ITEM_EXP]: record,
|
||||
[LIST_ITEM_INDEX_EXP]: index,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
default:
|
||||
const text = evaledColumn.displayValue || value;
|
||||
colItem = <span title={column.ellipsis ? text : ''}>{text}</span>;
|
||||
@ -365,7 +404,15 @@ export const Table = implementRuntimeComponent({
|
||||
return newColumn;
|
||||
})
|
||||
);
|
||||
}, [cProps.columns]);
|
||||
}, [
|
||||
app,
|
||||
cProps.columns,
|
||||
callbackMap,
|
||||
component.id,
|
||||
component.properties.columns,
|
||||
services,
|
||||
useDefaultFilter,
|
||||
]);
|
||||
|
||||
const handleChange = (
|
||||
pagination: PaginationProps,
|
||||
|
@ -5,7 +5,7 @@ import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { TabsPropsSpec as BaseTabsPropsSpec } from '../generated/types/Tabs';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
import { useStateValue } from '../hooks/useStateValue';
|
||||
|
||||
const TabsPropsSpec = Type.Object(BaseTabsPropsSpec);
|
||||
const TabsStateSpec = Type.Object({
|
||||
|
@ -6,7 +6,7 @@ import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { TextAreaPropsSpec as BaseTextAreaPropsSpec } from '../generated/types/TextArea';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { RefInputType } from '@arco-design/web-react/es/Input/interface';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
import { useStateValue } from '../hooks/useStateValue';
|
||||
|
||||
const TextAreaPropsSpec = Type.Object({
|
||||
...BaseTextAreaPropsSpec,
|
||||
|
@ -6,7 +6,7 @@ import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { TreeSelectPropsSpec as BaseTreeSelectPropsSpec } from '../generated/types/TreeSelect';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { RefTreeSelectType } from '@arco-design/web-react/es/TreeSelect';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
import { useStateValue } from '../hooks/useStateValue';
|
||||
|
||||
const TreeSelectPropsSpec = Type.Object(BaseTreeSelectPropsSpec);
|
||||
const TreeSelectStateSpec = Type.Object({
|
||||
|
209
packages/arco-lib/src/examples/pages/table/customComponent.ts
Normal file
209
packages/arco-lib/src/examples/pages/table/customComponent.ts
Normal file
@ -0,0 +1,209 @@
|
||||
import { Application } from '@sunmao-ui/core';
|
||||
|
||||
export const customComponent: Application = {
|
||||
version: 'sunmao/v1',
|
||||
kind: 'Application',
|
||||
metadata: {
|
||||
name: 'some App',
|
||||
},
|
||||
spec: {
|
||||
components: [
|
||||
{
|
||||
id: 'table',
|
||||
type: 'arco/v1/table',
|
||||
properties: {
|
||||
columns: [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
type: 'text',
|
||||
filter: true,
|
||||
displayValue: '',
|
||||
componentSlotIndex: 0,
|
||||
},
|
||||
{
|
||||
title: 'Salary',
|
||||
dataIndex: 'salary',
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
filter: false,
|
||||
type: 'text',
|
||||
displayValue: '',
|
||||
componentSlotIndex: 0,
|
||||
},
|
||||
{
|
||||
title: 'Link',
|
||||
dataIndex: 'link',
|
||||
type: 'link',
|
||||
filter: true,
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
displayValue: '',
|
||||
componentSlotIndex: 0,
|
||||
},
|
||||
{
|
||||
title: 'Hello',
|
||||
type: 'component',
|
||||
componentSlotIndex: 0,
|
||||
dataIndex: '',
|
||||
displayValue: '',
|
||||
filter: false,
|
||||
},
|
||||
],
|
||||
data: [
|
||||
{
|
||||
key: 'key 0',
|
||||
name: 'Naomi Cook0',
|
||||
link: 'link-A',
|
||||
salary: 272,
|
||||
},
|
||||
{
|
||||
key: 'key 1',
|
||||
name: 'Kevin Sandra1',
|
||||
link: 'link-B',
|
||||
salary: 911,
|
||||
},
|
||||
{
|
||||
key: 'key 2',
|
||||
name: 'Kevin Sandra2',
|
||||
link: 'link-B',
|
||||
salary: 527,
|
||||
},
|
||||
{
|
||||
key: 'key 3',
|
||||
name: 'Kevin Sandra3',
|
||||
link: 'link-B',
|
||||
salary: 906,
|
||||
},
|
||||
{
|
||||
key: 'key 4',
|
||||
name: 'Naomi Cook4',
|
||||
link: 'link-A',
|
||||
salary: 261,
|
||||
},
|
||||
{
|
||||
key: 'key 5',
|
||||
name: 'Naomi Cook5',
|
||||
link: 'link-A',
|
||||
salary: 134,
|
||||
},
|
||||
{
|
||||
key: 'key 6',
|
||||
name: 'Kevin Sandra6',
|
||||
link: 'link-A',
|
||||
salary: 877,
|
||||
},
|
||||
{
|
||||
key: 'key 7',
|
||||
name: 'Kevin Sandra7',
|
||||
link: 'link-A',
|
||||
salary: 287,
|
||||
},
|
||||
{
|
||||
key: 'key 8',
|
||||
name: 'Naomi Cook8',
|
||||
link: 'link-B',
|
||||
salary: 319,
|
||||
},
|
||||
{
|
||||
key: 'key 9',
|
||||
name: 'Kevin Sandra9',
|
||||
link: 'link-B',
|
||||
salary: 105,
|
||||
},
|
||||
{
|
||||
key: 'key 10',
|
||||
name: 'Naomi Cook10',
|
||||
link: 'link-B',
|
||||
salary: 468,
|
||||
},
|
||||
{
|
||||
key: 'key 11',
|
||||
name: 'Naomi Cook11',
|
||||
link: 'link-A',
|
||||
salary: 53,
|
||||
},
|
||||
{
|
||||
key: 'key 12',
|
||||
name: 'Naomi Cook12',
|
||||
link: 'link-A',
|
||||
salary: 195,
|
||||
},
|
||||
],
|
||||
checkCrossPage: true,
|
||||
pagination: {
|
||||
enablePagination: true,
|
||||
pageSize: 6,
|
||||
defaultCurrent: 1,
|
||||
updateWhenDefaultPageChanges: false,
|
||||
useCustomPagination: false,
|
||||
},
|
||||
rowClick: false,
|
||||
tableLayoutFixed: false,
|
||||
borderCell: false,
|
||||
stripe: false,
|
||||
size: 'default',
|
||||
useDefaultFilter: true,
|
||||
useDefaultSort: true,
|
||||
pagePosition: 'bottomCenter',
|
||||
rowSelectionType: 'single',
|
||||
border: true,
|
||||
loading: false,
|
||||
},
|
||||
traits: [],
|
||||
},
|
||||
{
|
||||
id: 'button4',
|
||||
type: 'arco/v1/button',
|
||||
properties: {
|
||||
type: 'primary',
|
||||
status: 'default',
|
||||
long: false,
|
||||
size: 'small',
|
||||
disabled: false,
|
||||
loading: false,
|
||||
shape: 'round',
|
||||
text: 'Click',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: {
|
||||
container: {
|
||||
id: 'table',
|
||||
slot: 'content',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'core/v1/event',
|
||||
properties: {
|
||||
handlers: [
|
||||
{
|
||||
type: 'onClick',
|
||||
componentId: '$utils',
|
||||
method: {
|
||||
name: 'arco/v1/message',
|
||||
parameters: {
|
||||
type: 'info',
|
||||
content: 'Hello{{$slot.$listItem.name}}',
|
||||
position: 'top',
|
||||
closable: false,
|
||||
duration: 1000,
|
||||
},
|
||||
},
|
||||
disabled: false,
|
||||
wait: {
|
||||
type: 'delay',
|
||||
time: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
@ -4,6 +4,7 @@ import { basicUsage } from './basicUsage';
|
||||
import { selection } from './selection';
|
||||
import { attributes } from './attributes';
|
||||
import { sortAndFilter } from './sortAndFilter';
|
||||
import { customComponent } from './customComponent';
|
||||
|
||||
const { Title, Text, Paragraph } = Typography;
|
||||
|
||||
@ -24,6 +25,12 @@ export const TableDemoPage: React.FC = () => {
|
||||
<Paragraph>You can easily open or close the properties of the table</Paragraph>
|
||||
<DemoWrapper application={attributes} />
|
||||
<Divider />
|
||||
<Title heading={3}>Custom Column Component</Title>
|
||||
<Paragraph>
|
||||
You can use any Sunmao component as column element instead of plain text.
|
||||
</Paragraph>
|
||||
<DemoWrapper application={customComponent} />
|
||||
<Divider />
|
||||
<Title heading={3}>Sort and filter</Title>
|
||||
<Paragraph>
|
||||
Configure the <Text code>sortable</Text> or <Text code>filterable</Text> of{' '}
|
||||
|
@ -182,12 +182,22 @@ export const ColumnSpec = Type.Object({
|
||||
link: Type.String(),
|
||||
button: Type.String(),
|
||||
module: Type.String(),
|
||||
component: Type.String(),
|
||||
}),
|
||||
{
|
||||
title: 'Type',
|
||||
category: Category.Basic,
|
||||
}
|
||||
),
|
||||
componentSlotIndex: Type.Number({
|
||||
title: 'Component Slot Index',
|
||||
conditions: [
|
||||
{
|
||||
key: 'type',
|
||||
value: 'component',
|
||||
},
|
||||
],
|
||||
}),
|
||||
dataIndex: Type.String({
|
||||
title: 'Key',
|
||||
category: Category.Basic,
|
||||
@ -198,6 +208,16 @@ export const ColumnSpec = Type.Object({
|
||||
title: 'Display Value',
|
||||
category: Category.Basic,
|
||||
description: 'The text you want to display instead of raw text',
|
||||
conditions: [
|
||||
{
|
||||
key: 'type',
|
||||
value: 'link',
|
||||
},
|
||||
{
|
||||
key: 'type',
|
||||
value: 'text',
|
||||
},
|
||||
],
|
||||
}),
|
||||
width: Type.Optional(
|
||||
Type.Number({
|
||||
|
Loading…
x
Reference in New Issue
Block a user