implement list custom template

This commit is contained in:
Bowen Tan 2021-08-30 15:03:12 +08:00
parent b9de19bd56
commit 1c9e1c9a99
3 changed files with 121 additions and 62 deletions

View File

@ -68,39 +68,100 @@
sales: 243,
},
],
template: {
id: 'listItemTemplate',
type: 'chakra_ui/v1/button',
properties: {
text: {
raw: '`name: ${$listItem.name} email: ${$listItem.email}`',
format: 'plain',
template: [
{
id: '`listItemTemplate-${$listItem.id}`',
type: 'chakra_ui/v1/hstack',
properties: {
spacing: '24px',
},
traits: [],
},
traits: [
{
type: 'core/v1/event',
parsedType: {
version: 'core/v1',
name: 'event',
},
properties: {
events: [
{
event: 'click',
componentId: '$utils',
method: {
name: 'alert',
parameters: '`click: ${$listItem.name}`',
},
wait: {},
disabled: 'false',
},
],
{
id: '`listItemName-${$listItem.id}`',
type: 'core/v1/text',
properties: {
value: {
raw: '`姓名:${$listItem.name}`',
format: 'plain',
},
},
],
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: '`listItemTemplate-${$listItem.id}`',
slot: 'content',
},
},
},
],
},
{
id: '`listItemEmail-${$listItem.id}`',
type: 'core/v1/text',
properties: {
value: {
raw: '`email${$listItem.email}`',
format: 'plain',
},
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: '`listItemTemplate-${$listItem.id}`',
slot: 'content',
},
},
},
],
},
{
id: '`listItemButton-${$listItem.id}`',
type: 'chakra_ui/v1/button',
properties: {
text: {
raw: '打招呼',
format: 'plain',
},
},
traits: [
{
type: 'core/v1/event',
parsedType: {
version: 'core/v1',
name: 'event',
},
properties: {
events: [
{
event: 'click',
componentId: '$utils',
method: {
name: 'alert',
parameters: '`click: ${$listItem.name}`',
},
wait: {},
disabled: 'false',
},
],
},
},
{
type: 'core/v1/slot',
properties: {
container: {
id: '`listItemTemplate-${$listItem.id}`',
slot: 'content',
},
},
},
],
},
],
},
traits: [
{

View File

@ -26,7 +26,8 @@ import { globalHandlerMap } from './handler';
type ArrayElement<ArrayType extends readonly unknown[]> =
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
type ApplicationComponent = RuntimeApplication['spec']['components'][0];
type ApplicationComponents = RuntimeApplication['spec']['components'];
type ApplicationComponent = ApplicationComponents[0];
type ApplicationTrait = ArrayElement<ApplicationComponent['traits']>;
export const ImplWrapper = React.forwardRef<
@ -153,10 +154,11 @@ export const ImplWrapper = React.forwardRef<
mergeState={mergeState}
subscribeMethods={subscribeMethods}
slotsMap={slotsMap}
app={app}
/>
);
if (targetSlot) {
if (targetSlot && app) {
const targetC = app.spec.components.find(c => c.id === targetSlot.id);
if (targetC?.parsedType.name === 'grid_layout') {
return (

View File

@ -1,14 +1,10 @@
import React, { useEffect, useRef } from 'react';
import { createComponent } from '@meta-ui/core';
import React, { useEffect, useMemo, useRef } from 'react';
import { createApplication, createComponent } from '@meta-ui/core';
import { Static, Type } from '@sinclair/typebox';
import {
List as BaseList,
ListItem as BaseListItem,
ListIcon,
} from '@chakra-ui/react';
import { List as BaseList, ListItem as BaseListItem } from '@chakra-ui/react';
import Text, { TextProps, TextPropertySchema } from '../_internal/Text';
import { ComponentImplementation } from '../../registry';
import { ImplWrapper } from '../../App';
import { ImplWrapper, resolveAppComponents } from '../../App';
import { mapValuesDeep } from '../../store';
import { values } from 'lodash';
import { parseType } from '../../util-methods';
@ -18,42 +14,42 @@ const List: ComponentImplementation<{
template: Static<typeof TemplatePropertySchema>;
onClick?: () => void;
}> = ({ listData, template, mergeState, subscribeMethods, app }) => {
// useEffect(() => {
// mergeState({ value: text.raw });
// }, [text.raw]);
// const ref = useRef<HTMLListElement>(null);
// useEffect(() => {
// subscribeMethods({
// click() {
// ref.current?.click();
// },
// });
// }, []);
const templateAsApp = useMemo(() => {
return createApplication({
...app,
spec: {
components: template as any,
},
});
}, [app, template]);
const listItems = listData.map((listItem, i) => {
// const evaledText = eval(template.properties.value.raw)
const evaledComponent = mapValuesDeep(template, ({ value, key }) => {
console.log(value);
const evaledTemplate = mapValuesDeep(templateAsApp, ({ value, key }) => {
// what will happen if listData was uglified?
if (typeof value === 'string' && value.includes('$listItem')) {
const expression = value.replaceAll('$listItem', 'listData[i]');
console.log('expression', expression);
return eval(expression);
}
return value;
});
evaledComponent.parsedType = parseType(evaledComponent.type);
console.log('evaled', evaledComponent);
return (
<BaseListItem key={listItem.name} spacing={3}>
<ListIcon color="green.500" />
const { topLevelComponents, slotComponentsMap } =
resolveAppComponents(evaledTemplate);
const componentElements = topLevelComponents.map(c => {
return (
<ImplWrapper
component={evaledComponent}
slotsMap={undefined}
key={c.id}
component={c}
slotsMap={slotComponentsMap.get(c.id)}
targetSlot={null}
app={app}
/>
);
});
return (
<BaseListItem key={listItem.name} spacing={3}>
{componentElements}
</BaseListItem>
);
});