Merge pull request #100 from webzard-io/user-center

Some small features
This commit is contained in:
yz-yu 2021-11-01 17:23:34 +08:00 committed by GitHub
commit 2d7d22a9f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 2191 additions and 1926 deletions

View File

@ -45,7 +45,7 @@
"babel-jest": "^27.2.1",
"jest": "^27.2.1",
"typescript": "^4.4.3",
"vite": "^2.5.10"
"vite": "^2.6.13"
},
"husky": {
"hooks": {

View File

@ -1,6 +1,6 @@
import React from 'react';
import { flatten } from 'lodash-es';
import { FormControl, FormLabel, Input, VStack } from '@chakra-ui/react';
import { FormControl, FormLabel, Input, Textarea, VStack } from '@chakra-ui/react';
import { EmotionJSX } from '@emotion/react/types/jsx-namespace';
import { TSchema } from '@sinclair/typebox';
import { Application } from '@meta-ui/core';
@ -27,7 +27,7 @@ export const renderField = (properties: {
}) => {
const { value, type, fullKey, selectedId } = properties;
if (typeof value !== 'object') {
const ref = React.createRef<HTMLInputElement>();
const ref = React.createRef<HTMLTextAreaElement>();
const onBlur = () => {
const operation = type
? new ModifyTraitPropertyOperation(selectedId, type, fullKey, ref.current?.value)
@ -37,7 +37,7 @@ export const renderField = (properties: {
return (
<FormControl key={`${selectedId}-${fullKey}`}>
<FormLabel>{fullKey}</FormLabel>
<Input ref={ref} onBlur={onBlur} defaultValue={value as string} />
<Textarea ref={ref} onBlur={onBlur} defaultValue={value as string} />
</FormControl>
);
} else {

View File

@ -96,7 +96,7 @@ export const Editor = () => {
<Tab>UI Tree</Tab>
<Tab>State</Tab>
</TabList>
<TabPanels flex="1">
<TabPanels flex="1" overflow="auto">
<TabPanel p={0}>
<StructureTree
app={app}

View File

@ -12,121 +12,424 @@ export const DefaultAppSchema: Application = {
spec: {
components: [
{
id: 'root',
type: 'chakra_ui/v1/root',
properties: {},
id: 'grid_layout1',
type: 'core/v1/grid_layout',
properties: {
layout: [
{
w: 10,
h: 15,
x: 0,
y: 0,
i: 'tabs1',
moved: false,
static: false,
isDraggable: true,
},
],
},
traits: [],
},
{
id: 'btn',
type: 'plain/v1/button',
properties: {
text: {
raw: '**Open Dialog**',
format: 'md',
},
colorScheme: 'red',
},
id: 'fetchUsers',
type: 'core/v1/dummy',
properties: {},
traits: [
{
type: 'core/v1/slot',
type: 'core/v1/fetch',
properties: {
container: {
id: 'root',
slot: 'root',
},
},
},
{
type: 'core/v1/event',
properties: {
handlers: [
{
type: 'onClick',
componentId: 'dialog',
method: {
name: 'openDialog',
parameters: {
title: 'hi',
},
},
wait: {},
},
],
url: 'https://6177d4919c328300175f5b99.mockapi.io/users',
method: 'get',
lazy: false,
headers: {},
body: {},
onComplete: [],
},
},
],
},
{
id: 'dialog',
type: 'chakra_ui/v1/dialog',
id: 'usersTable',
type: 'chakra_ui/v1/table',
properties: {
title: 'This is a dialog',
confirmButton: {
text: 'hello',
colorScheme: 'pink',
},
cancelButton: {
text: 'thanks',
},
data: '{{fetchUsers.fetch.data}}',
columns: [
{ key: 'username', title: '用户名', type: 'link' },
{ key: 'job', title: '职位', type: 'text' },
{ key: 'area', title: '地区', type: 'text' },
{
key: 'createdTime',
title: '创建时间',
displayValue: "{{dayjs($listItem.createdTime).format('LL')}}",
},
],
majorKey: 'id',
rowsPerPage: '3',
isMultiSelect: 'false',
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: 'root',
slot: 'root',
},
},
},
// dialog events
{
type: 'core/v1/event',
properties: {
handlers: [
// when click confirm
{
type: 'confirmDialog',
componentId: 'dialog',
method: {
name: 'confirmDialog',
},
wait: {},
disabled: 'false',
},
// when cancel confirm
{
type: 'cancelDialog',
componentId: 'dialog',
method: {
name: 'cancelDialog',
},
wait: {},
disabled: 'false',
},
],
container: { id: 'tabContentVStack', slot: 'content' },
},
},
],
},
{
id: 'dialogContent',
id: 'userInfoContainer',
type: 'chakra_ui/v1/vstack',
properties: { spacing: '2', align: 'stretch' },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'tabContentVStack', slot: 'content' },
},
},
{
type: 'core/v1/style',
properties: {
styleSlot: 'content',
style: "{{!usersTable.selectedItem ? 'display: none' : ''}}",
},
},
],
},
{
id: 'userInfoTitle',
type: 'core/v1/text',
properties: { value: { raw: '**基本信息**', format: 'md' } },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'userInfoContainer', slot: 'content' },
},
},
],
},
{
id: 'hstack1',
type: 'chakra_ui/v1/hstack',
properties: { spacing: '24px', hideBorder: '' },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'userInfoContainer', slot: 'content' },
},
},
{
type: 'core/v1/style',
properties: {
styleSlot: 'content',
style: 'padding: 0; border: none',
},
},
],
},
{
id: 'usernameLabel',
type: 'core/v1/text',
properties: { value: { raw: '**用户名**', format: 'md' } },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'hstack1', slot: 'content' },
},
},
],
},
{
id: 'usernameValue',
type: 'core/v1/text',
properties: {
value: {
raw: '**This is a dialog**',
format: 'md',
raw: "{{usersTable.selectedItem ? usersTable.selectedItem.username : ''}}",
format: 'plain',
},
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: 'dialog',
slot: 'content',
},
container: { id: 'hstack1', slot: 'content' },
},
},
],
},
{
id: 'divider1',
type: 'chakra_ui/v1/divider',
properties: {},
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'userInfoContainer', slot: 'content' },
},
},
],
},
{
id: 'jobLabel',
type: 'core/v1/text',
properties: { value: { raw: '**职位**', format: 'md' } },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'hstack2', slot: 'content' },
},
},
],
},
{
id: 'hstack2',
type: 'chakra_ui/v1/hstack',
properties: { spacing: '24px', hideBorder: '' },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'userInfoContainer', slot: 'content' },
},
},
{
type: 'core/v1/style',
properties: {
styleSlot: 'content',
style: 'padding: 0; border: none',
},
},
],
},
{
id: 'areaLabel',
type: 'core/v1/text',
properties: { value: { raw: '**地区**', format: 'md' } },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'hstack3', slot: 'content' },
},
},
],
},
{
id: 'areaValue',
type: 'core/v1/text',
properties: {
value: {
raw: "{{usersTable.selectedItem ? usersTable.selectedItem.area : ''}}",
format: 'plain',
},
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'hstack3', slot: 'content' },
},
},
],
},
{
id: 'divider2',
type: 'chakra_ui/v1/divider',
properties: {},
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'userInfoContainer', slot: 'content' },
},
},
],
},
{
id: 'createdTimeLabel',
type: 'core/v1/text',
properties: { value: { raw: '**创建时间**', format: 'md' } },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'hstack4', slot: 'content' },
},
},
],
},
{
id: 'createdTimeValue',
type: 'core/v1/text',
properties: {
value: {
raw: "{{usersTable.selectedItem ? dayjs(usersTable.selectedItem.createdTime).format('LL') : ''}}",
format: 'plain',
},
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'hstack4', slot: 'content' },
},
},
{
type: 'core/v1/style',
properties: { string: { kind: {}, type: {} } },
},
],
},
{
id: 'hstack3',
type: 'chakra_ui/v1/hstack',
properties: { spacing: '24px', hideBorder: '' },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'userInfoContainer', slot: 'content' },
},
},
{
type: 'core/v1/style',
properties: {
styleSlot: 'content',
style: 'padding: 0; border: none',
},
},
],
},
{
id: 'divider3',
type: 'chakra_ui/v1/divider',
properties: {},
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'userInfoContainer', slot: 'content' },
},
},
],
},
{
id: 'hstack4',
type: 'chakra_ui/v1/hstack',
properties: { spacing: '24px', hideBorder: '' },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'userInfoContainer', slot: 'content' },
},
},
{
type: 'core/v1/style',
properties: {
styleSlot: 'content',
style: 'padding: 0; border: none',
},
},
],
},
{
id: 'tabs1',
type: 'chakra_ui/v1/tabs',
properties: {
tabNames: ['用户信息', '角色'],
initialSelectedTabIndex: 0,
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'grid_layout1', slot: 'content' },
},
},
],
},
{
id: 'tabContentVStack',
type: 'chakra_ui/v1/vstack',
properties: { spacing: '24px' },
traits: [
{
type: 'core/v1/slot',
properties: { container: { id: 'tabs1', slot: 'content' } },
},
],
},
{
id: 'testtext',
type: 'core/v1/text',
properties: { value: { raw: '**测试角色**', format: 'md' } },
traits: [
{
type: 'core/v1/slot',
properties: { container: { id: 'tabs1', slot: 'content' } },
},
],
},
{
id: 'jobValue',
type: 'chakra_ui/v1/vstack',
properties: { spacing: '1', align: 'stretch' },
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'hstack2', slot: 'content' },
},
},
{
type: 'core/v1/style',
properties: {
styleSlot: 'content',
style: 'padding: 0; border: none',
},
},
],
},
{
id: 'link1',
type: 'chakra_ui/v1/link',
properties: {
text: {
raw: "{{usersTable.selectedItem ? usersTable.selectedItem.job : ''}}",
format: 'plain',
},
href: 'https://www.google.com',
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'jobValue', slot: 'content' },
},
},
],
},
{
id: 'link2',
type: 'chakra_ui/v1/link',
properties: {
text: {
raw: "{{usersTable.selectedItem ? usersTable.selectedItem.job : ''}}",
format: 'plain',
},
href: 'https://www.google.com',
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: { id: 'jobValue', slot: 'content' },
},
},
],

View File

@ -43,18 +43,15 @@
{
type: 'core/v1/style',
properties: {
style: {
tabItem: {
'&:hover': {
color: 'red',
},
},
tabContent: {
'&:hover': {
color: 'green',
},
},
},
styleSlot: 'tabItem',
style: `color: red`,
},
},
{
type: 'core/v1/style',
properties: {
styleSlot: 'tabContent',
style: `color: green`,
},
},
],
@ -74,7 +71,7 @@
properties: {
container: {
id: 'tabs',
slot: 'tab_content_0',
slot: 'content',
},
},
},
@ -85,7 +82,7 @@
type: 'core/v1/text',
properties: {
value: {
raw: 'hover me',
raw: 'hover me2',
format: 'plain',
},
},
@ -95,7 +92,7 @@
properties: {
container: {
id: 'tabs',
slot: 'tab_content_1',
slot: 'content',
},
},
},

View File

@ -68,6 +68,6 @@
"jest": "^27.1.0",
"tsup": "^5.5.0",
"typescript": "^4.3.2",
"vite": "^2.3.8"
"vite": "^2.6.13"
}
}

View File

@ -7,10 +7,6 @@ import 'react-resizable/css/styles.css';
import { DROP_EXAMPLE_SIZE_PREFIX, GRID_HEIGHT } from '../../constants';
import { decodeDragDataTransfer } from '../../utils/encodeDragDataTransfer';
// hack: add onDropDragOver to ReactGridLayoutProps definition
const ReactGridLayout: React.FC<RGL.ReactGridLayoutProps & { onDropDragOver: any }> =
RGL as any;
const GridLayout: React.FC<RGL.ReactGridLayoutProps> = props => {
const { children } = props;
const spacing = 10;
@ -25,12 +21,12 @@ const GridLayout: React.FC<RGL.ReactGridLayoutProps> = props => {
background-position: 0px ${spacing / 2}px;
`;
const onDropDragOver = (e: React.DragEvent) => {
const onDropDragOver = (e: any) => {
// Here we need to get data in dataTransfer
// but normally we cannot access dataTransfer in onDragOver, so I use a hack
// I use the key of dataTransfer to store data, the key will look like 'exampleSize: [1,4]'
// https://stackoverflow.com/questions/28487352/dragndrop-datatransfer-getdata-empty
const key = e.dataTransfer.types
const key = (e as React.DragEvent).dataTransfer.types
.map(decodeDragDataTransfer)
.find(t => t.startsWith(DROP_EXAMPLE_SIZE_PREFIX));
const componentSize = JSON.parse(key?.replace(DROP_EXAMPLE_SIZE_PREFIX, '') || '');
@ -39,7 +35,7 @@ const GridLayout: React.FC<RGL.ReactGridLayoutProps> = props => {
return (
<div ref={ref} css={bgCss}>
<ReactGridLayout
<RGL
cols={12}
compactType={null}
preventCollision={true}
@ -51,7 +47,7 @@ const GridLayout: React.FC<RGL.ReactGridLayoutProps> = props => {
{...props}
>
{children}
</ReactGridLayout>
</RGL>
</div>
);
};

View File

@ -0,0 +1,31 @@
import { Divider } from '@chakra-ui/react';
import { createComponent } from '@meta-ui/core';
import { ComponentImplementation } from '../../services/registry';
const DividerImpl: ComponentImplementation = () => {
return <Divider />;
};
export default {
...createComponent({
version: 'chakra_ui/v1',
metadata: {
name: 'divider',
displayName: 'Divider',
description: 'chakra-ui divider',
isDraggable: true,
isResizable: true,
exampleProperties: {},
exampleSize: [4, 1],
},
spec: {
properties: {},
state: {},
methods: [],
slots: [],
styleSlots: [],
events: [],
},
}),
impl: DividerImpl,
};

View File

@ -1,4 +1,5 @@
import { createComponent } from '@meta-ui/core';
import { css } from '@emotion/react';
import { Static, Type } from '@sinclair/typebox';
import { HStack as BaseHStack } from '@chakra-ui/react';
import { ComponentImplementation } from '../../services/registry';
@ -18,6 +19,7 @@ const HStack: ComponentImplementation<Static<typeof PropsSchema>> = ({
justify,
spacing,
slotsMap,
customStyle,
}) => {
return (
<BaseHStack
@ -28,6 +30,9 @@ const HStack: ComponentImplementation<Static<typeof PropsSchema>> = ({
border="1px solid"
borderColor="gray.200"
borderRadius="4"
css={css`
${customStyle?.content}
`}
{...{ direction, wrap, align, justify, spacing }}
>
<Slot slotsMap={slotsMap} slot="content" />

View File

@ -0,0 +1,53 @@
import { Link } from '@chakra-ui/react';
import { Static, Type } from '@sinclair/typebox';
import { createComponent } from '@meta-ui/core';
import { ComponentImplementation } from '../../services/registry';
import Text, { TextPropertySchema } from '../_internal/Text';
const LinkImpl: ComponentImplementation<Static<typeof PropsSchema>> = ({
text,
href,
isExternal,
}) => {
return (
<Link href={href} isExternal={isExternal} color="blue.500">
<Text value={text} />
</Link>
);
};
const PropsSchema = Type.Object({
text: TextPropertySchema,
href: Type.String(),
isExternal: Type.Optional(Type.Boolean()),
});
export default {
...createComponent({
version: 'chakra_ui/v1',
metadata: {
name: 'link',
displayName: 'Link',
description: 'chakra-ui link',
isDraggable: true,
isResizable: true,
exampleProperties: {
text: {
raw: 'link',
format: 'plain',
},
href: 'https://www.google.com',
},
exampleSize: [2, 1],
},
spec: {
properties: PropsSchema,
state: {},
methods: [],
slots: [],
styleSlots: [],
events: [],
},
}),
impl: LinkImpl,
};

View File

@ -95,8 +95,8 @@ const List: ComponentImplementation<Static<typeof PropsSchema>> = ({
};
const PropsSchema = Type.Object({
listData: Type.Array(Type.Object(Type.String(), Type.String())),
template: Type.Object(Type.String(), Type.Array(Type.Object(Type.String()))),
listData: Type.Array(Type.Record(Type.String(), Type.String())),
template: Type.Array(Type.Any()),
});
const exampleProperties = {

View File

@ -1,6 +1,6 @@
import { Static } from '@sinclair/typebox';
import { ColumnSchema } from './TableTypes';
import { Button, Td } from '@chakra-ui/react';
import { Button, Link, Td } from '@chakra-ui/react';
import { LIST_ITEM_EXP } from '../../../constants';
import { MetaUIServices } from 'src/types/RuntimeSchema';
@ -20,11 +20,17 @@ export const TableTd: React.FC<{
}
let content = value;
switch (column.type) {
case 'image':
content = <img src={value} />;
break;
case 'link':
content = (
<Link href={value} color="blue.600">
{value}
</Link>
);
break;
case 'button':
const onClick = () => {
onClickItem();

View File

@ -16,6 +16,7 @@ export const TdTypeSchema = Type.KeyOf(
Type.Object({
text: Type.String(),
image: Type.String(),
link: Type.String(),
button: Type.String(),
})
);

View File

@ -1,23 +1,23 @@
import { useEffect, useState } from 'react';
import { css } from '@emotion/react';
import { createComponent } from '@meta-ui/core';
import { Tabs as BaseTabs, TabList, Tab, TabPanels, TabPanel } from '@chakra-ui/react';
import { Type, Static } from '@sinclair/typebox';
import { ComponentImplementation } from '../../services/registry';
import Slot from '../_internal/Slot';
import { getSlots } from '../_internal/Slot';
const Tabs: ComponentImplementation<Static<typeof PropsSchema>> = ({
tabNames,
mergeState,
initialSelectedTabIndex,
slotsMap,
style,
customStyle,
}) => {
const [selectedTabIndex, setSelectedTabIndex] = useState(initialSelectedTabIndex ?? 0);
useEffect(() => {
mergeState({ selectedTabIndex });
}, [selectedTabIndex]);
return (
<BaseTabs
defaultIndex={initialSelectedTabIndex}
@ -25,17 +25,24 @@ const Tabs: ComponentImplementation<Static<typeof PropsSchema>> = ({
>
<TabList>
{tabNames.map((name, idx) => (
<Tab key={idx} css={style?.tabItem}>
<Tab key={idx} css={css`${customStyle?.tabItem}}`}>
{name}
</Tab>
))}
</TabList>
<TabPanels>
{tabNames.map((_, idx) => (
<TabPanel key={idx} css={style?.tabContent}>
<Slot slotsMap={slotsMap} slot={`tab_content_${idx}`} />
</TabPanel>
))}
{getSlots(slotsMap, 'content').map((content, idx) => {
return (
<TabPanel
key={idx}
css={css`
${customStyle?.tabContent}
`}
>
{content}
</TabPanel>
);
})}
</TabPanels>
</BaseTabs>
);
@ -70,8 +77,8 @@ export default {
state: StateSchema,
methods: [],
// tab slot is dynamic
slots: [],
styleSlots: [],
slots: ['content'],
styleSlots: ['tabItem', 'tabContent'],
events: [],
},
}),

View File

@ -1,4 +1,5 @@
import { createComponent } from '@meta-ui/core';
import { css } from '@emotion/react';
import { Static, Type } from '@sinclair/typebox';
import { VStack as BaseVStack } from '@chakra-ui/react';
import { ComponentImplementation } from '../../services/registry';
@ -18,6 +19,7 @@ const VStack: ComponentImplementation<Static<typeof PropsSchema>> = ({
justify,
spacing,
slotsMap,
customStyle,
}) => {
return (
<BaseVStack
@ -28,6 +30,9 @@ const VStack: ComponentImplementation<Static<typeof PropsSchema>> = ({
border="1px solid"
borderColor="gray.200"
borderRadius="4"
css={css`
${customStyle?.content}
`}
{...{ direction, wrap, align, justify, spacing }}
>
<Slot slotsMap={slotsMap} slot="content" />

View File

@ -123,11 +123,8 @@ export const ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>(
if (result.props?.effects) {
effects = effects?.concat(result.props?.effects);
}
return {
...prevProps,
...result.props,
effects,
};
return merge(prevProps, result.props, { effects });
},
{} as TraitResult['props']
);

View File

@ -13,10 +13,12 @@ import ChakraUITabs from '../components/chakra-ui/Tabs';
import ChakraUITable from '../components/chakra-ui/Table';
import ChakraUIInput from '../components/chakra-ui/Input';
import ChakraUIBox from '../components/chakra-ui/Box';
import ChakraUIDivider from '../components/chakra-ui/Divider';
import ChakraUIFormControl from '../components/chakra-ui/Form/FormControl';
import ChakraUIForm from '../components/chakra-ui/Form/Form';
import ChakraUIKbd from '../components/chakra-ui/Kbd';
import ChakraUIList from '../components/chakra-ui/List';
import ChakraUILink from '../components/chakra-ui/Link';
import ChakraUINumberInput from '../components/chakra-ui/NumberInput';
import ChakraUICheckboxGroup from '../components/chakra-ui/CheckboxGroup';
import ChakraUICheckbox from '../components/chakra-ui/Checkbox';
@ -130,10 +132,12 @@ export function initRegistry(): Registry {
registry.registerComponent(ChakraUITable);
registry.registerComponent(ChakraUIInput);
registry.registerComponent(ChakraUIBox);
registry.registerComponent(ChakraUIDivider);
registry.registerComponent(ChakraUIFormControl);
registry.registerComponent(ChakraUIForm);
registry.registerComponent(ChakraUIKbd);
registry.registerComponent(ChakraUIList);
registry.registerComponent(ChakraUILink);
registry.registerComponent(ChakraUINumberInput);
registry.registerComponent(ChakraUICheckbox);
registry.registerComponent(ChakraUICheckboxGroup);

View File

@ -1,11 +1,17 @@
import { toNumber, mapValues, isArray, isPlainObject, set } from 'lodash-es';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import isLeapYear from 'dayjs/plugin/isLeapYear';
import relativeTime from 'dayjs/plugin/relativeTime';
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
import { reactive } from '@vue/reactivity';
import { watch } from '../utils/watchReactivity';
import { LIST_ITEM_EXP, LIST_ITEM_INDEX_EXP } from '../constants';
dayjs.extend(relativeTime);
dayjs.extend(isLeapYear);
dayjs.extend(LocalizedFormat);
dayjs.locale('zh-cn');
type ExpChunk = {
expression: string;

View File

@ -32,6 +32,14 @@ const useFetchTrait: TraitImplementation<Static<typeof FetchTraitPropertiesSchem
}
}
mergeState({
fetch: {
loading: true,
data: undefined,
error: undefined,
},
});
// fetch data
fetch(url, {
method,

View File

@ -1,16 +1,13 @@
import { CSSProperties } from 'react';
import { createTrait } from '@meta-ui/core';
import { Static, Type } from '@sinclair/typebox';
import { TraitImplementation } from 'src/types/RuntimeSchema';
const useHiddenTrait: TraitImplementation<Static<typeof PropsSchema>> = ({ hidden }) => {
const style: CSSProperties = {};
if (hidden) {
style.display = 'none';
}
return {
props: {
style,
customStyle: {
content: hidden ? 'display: none' : '',
},
},
};
};

View File

@ -2,19 +2,24 @@ import { createTrait } from '@meta-ui/core';
import { Static, Type } from '@sinclair/typebox';
import { TraitImplementation } from 'src/types/RuntimeSchema';
const StyleTrait: TraitImplementation<{
style: Static<typeof PropsSchema>;
}> = ({ style }) => {
const StyleTrait: TraitImplementation<Static<typeof PropsSchema>> = ({
styleSlot,
style,
}) => {
return {
props: {
style: style,
customStyle: {
[styleSlot]: style,
},
},
};
};
const PropsSchema = Type.Object({
string: Type.Object(Type.String()),
styleSlot: Type.String(),
style: Type.String(),
});
export default {
...createTrait({
version: 'core/v1',

View File

@ -74,7 +74,7 @@ export type ComponentImplementationProps = ImplWrapperProps &
export type TraitResult = {
props: {
data?: unknown;
style?: Record<string, any>;
customStyle?: Record<string, string>;
callbackMap?: CallbackMap;
effects?: Array<() => void>;
} | null;

3406
yarn.lock

File diff suppressed because it is too large Load Diff