Merge branch 'main' of https://github.com/webzard-io/sunmao-ui into feat/windlike-patch

This commit is contained in:
MrWindlike 2022-04-21 10:23:27 +08:00
commit b64777f1ca
101 changed files with 3099 additions and 3058 deletions

View File

@ -24,7 +24,7 @@
"react/prop-types": "off",
"no-case-declarations": "off",
"no-unused-vars":"off",
"@typescript-eslint/no-unused-vars": ["error"],
"@typescript-eslint/no-unused-vars": ["error",{"argsIgnorePattern":"^_"}],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",

View File

@ -1,70 +1,61 @@
import { Alert as BaseAlert } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { AlertPropsSpec as BaseAlertPropsSpec } from "../generated/types/Alert";
import { Alert as BaseAlert } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { AlertPropsSpec as BaseAlertPropsSpec } from '../generated/types/Alert';
const AlertPropsSpec = Type.Object(BaseAlertPropsSpec);
const AlertStateSpec = Type.Object({});
const AlertImpl: ComponentImpl<Static<typeof AlertPropsSpec>> = (props) => {
const { visible, content, title, elementRef, ...cProps } =
getComponentProps(props);
const { customStyle, slotsElements } = props;
const AlertImpl: ComponentImpl<Static<typeof AlertPropsSpec>> = props => {
const { elementRef, ...cProps } = getComponentProps(props);
const { customStyle, slotsElements, callbackMap } = props;
return visible ? (
return (
<BaseAlert
ref={elementRef}
action={slotsElements.action}
icon={slotsElements.icon}
content={
<>
{content}
{slotsElements.content}
</>
}
title={
<>
{title}
{slotsElements.title}
</>
}
onClose={_e => {
callbackMap?.onClose?.();
}}
afterClose={() => {
callbackMap?.afterClose?.();
}}
className={css(customStyle?.content)}
{...cProps}
/>
) : null;
);
};
const exampleProperties: Static<typeof AlertPropsSpec> = {
disabled: false,
closable: true,
title: "info",
content: "Here is an example text",
visible: true,
title: 'info',
content: 'Here is an example text',
showIcon: true,
banner: false,
type: "info",
type: 'info',
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "alert",
displayName: "Alert",
name: 'alert',
displayName: 'Alert',
exampleProperties,
annotations: {
category: "Display",
category: 'Display',
},
},
spec: {
properties: AlertPropsSpec,
state: AlertStateSpec,
methods: {},
slots: ["content", "action", "icon", "title"],
styleSlots: ["content"],
events: [],
slots: ['action', 'icon'],
styleSlots: ['content'],
events: ['onClose', 'afterClose'],
},
};

View File

@ -11,7 +11,7 @@ const AvatarPropsSpec = Type.Object({
const AvatarStateSpec = Type.Object({});
const AvatarImpl: ComponentImpl<Static<typeof AvatarPropsSpec>> = props => {
const { slotsElements, elementRef, customStyle } = props;
const { slotsElements, elementRef, callbackMap, customStyle } = props;
const { type, src, text, ...cProps } = getComponentProps(props);
return (
@ -20,6 +20,9 @@ const AvatarImpl: ComponentImpl<Static<typeof AvatarPropsSpec>> = props => {
className={css(customStyle?.content)}
{...cProps}
triggerIcon={slotsElements.triggerIcon}
onClick={_e => {
callbackMap?.onClick?.();
}}
>
{type === 'img' ? <img src={src} /> : text}
</BaseAvatar>
@ -50,7 +53,7 @@ const options = {
methods: {},
slots: ['triggerIcon'],
styleSlots: ['content'],
events: [],
events: ['onClick'],
},
};

View File

@ -1,14 +1,14 @@
import { Badge as BaseBadge } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { BadgePropsSpec as BaseBadgePropsSpec } from "../generated/types/Badge";
import { Badge as BaseBadge } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { BadgePropsSpec as BaseBadgePropsSpec } from '../generated/types/Badge';
const BadgePropsSpec = Type.Object(BaseBadgePropsSpec);
const BadgeStateSpec = Type.Object({});
const BadgeImpl: ComponentImpl<Static<typeof BadgePropsSpec>> = (props) => {
const BadgeImpl: ComponentImpl<Static<typeof BadgePropsSpec>> = props => {
const { ...cProps } = getComponentProps(props);
const { elementRef, customStyle, slotsElements } = props;
@ -17,43 +17,46 @@ const BadgeImpl: ComponentImpl<Static<typeof BadgePropsSpec>> = (props) => {
// which will cause some confusion and bug
// If `dot` is not set, delete status and color from props
if (!cProps.dot) {
Reflect.deleteProperty(cProps, "status");
Reflect.deleteProperty(cProps, "dotColor");
Reflect.deleteProperty(cProps, 'status');
Reflect.deleteProperty(cProps, 'dotColor');
}
return (
<BaseBadge ref={elementRef} className={css(customStyle?.content)} {...cProps} color={cProps.dotColor}>
<BaseBadge
ref={elementRef}
className={css(customStyle?.content)}
{...cProps}
color={cProps.dotColor}
>
{slotsElements.content}
</BaseBadge>
);
};
const exampleProperties: Static<typeof BadgePropsSpec> = {
// TODO handle dotStyle and color
text: "",
text: '',
dot: true,
count: 1,
dotColor: "red",
maxCount: 99,
offset: [6, -2],
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "badge",
displayName: "Badge",
name: 'badge',
displayName: 'Badge',
exampleProperties,
annotations: {
category: "Display",
}
category: 'Display',
},
},
spec: {
properties: BadgePropsSpec,
state: BadgeStateSpec,
methods: {},
slots: ["content"],
styleSlots: ["content"],
slots: ['content'],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,16 +1,16 @@
import { Button as BaseButton } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { ButtonPropsSpec as BaseButtonPropsSpec } from "../generated/types/Button";
import { Button as BaseButton } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { ButtonPropsSpec as BaseButtonPropsSpec } from '../generated/types/Button';
const ButtonPropsSpec = Type.Object({
...BaseButtonPropsSpec,
});
const ButtonStateSpec = Type.Object({});
const ButtonImpl: ComponentImpl<Static<typeof ButtonPropsSpec>> = (props) => {
const ButtonImpl: ComponentImpl<Static<typeof ButtonPropsSpec>> = props => {
const { elementRef, slotsElements, customStyle, text, callbackMap } = props;
const { ...cProps } = getComponentProps(props);
@ -19,43 +19,44 @@ const ButtonImpl: ComponentImpl<Static<typeof ButtonPropsSpec>> = (props) => {
ref={elementRef}
className={css(customStyle?.content)}
onClick={callbackMap?.onClick}
icon={slotsElements.icon}
{...cProps}
loadingFixedWidth
>
{slotsElements.content}
{text}
{text || null}
</BaseButton>
);
};
const exampleProperties: Static<typeof ButtonPropsSpec> = {
type: "default",
status: "default",
type: 'default',
status: 'default',
long: false,
size: "default",
size: 'default',
disabled: false,
loading: false,
shape: "square",
text: "button",
shape: 'square',
text: 'button',
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "button",
displayName: "Button",
name: 'button',
displayName: 'Button',
exampleProperties,
annotations: {
category: "Input",
}
category: 'Input',
},
},
spec: {
properties: ButtonPropsSpec,
state: ButtonStateSpec,
methods: {},
slots: ["content"],
styleSlots: ["content"],
events: ["onClick"],
slots: ['icon'],
styleSlots: ['content'],
events: ['onClick'],
},
};

View File

@ -1,15 +1,15 @@
import { Cascader as BaseCascader } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { Cascader as BaseCascader } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import {
CascaderPropsSpec as BaseCascaderPropsSpec,
CascaderValueSpec,
} from "../generated/types/Cascader";
import { useState, useEffect , useRef } from "react";
import { isArray } from "lodash-es";
import { SelectViewHandle } from "@arco-design/web-react/es/_class/select-view";
} from '../generated/types/Cascader';
import { useState, useEffect, useRef } from 'react';
import { isArray } from 'lodash-es';
import { SelectViewHandle } from '@arco-design/web-react/es/_class/select-view';
const CascaderPropsSpec = Type.Object(BaseCascaderPropsSpec);
const CascaderStateSpec = Type.Object({
@ -52,8 +52,8 @@ const convertArrToTree = (arr: Array<Array<string>>) => {
}
// convert object to tree
const getTree: (map: MapItem) => CascaderOptions[] = (map) => {
return Object.keys(map).map((key) => ({
const getTree: (map: MapItem) => CascaderOptions[] = map => {
return Object.keys(map).map(key => ({
label: key,
value: key,
children: getTree(map[key]),
@ -63,9 +63,7 @@ const convertArrToTree = (arr: Array<Array<string>>) => {
return getTree(map);
};
const CascaderImpl: ComponentImpl<Static<typeof CascaderPropsSpec>> = (
props
) => {
const CascaderImpl: ComponentImpl<Static<typeof CascaderPropsSpec>> = props => {
const { getElement, callbackMap, multiple, placeholder, ...cProps } =
getComponentProps(props);
const { mergeState, slotsElements, customStyle, options } = props;
@ -75,10 +73,10 @@ const CascaderImpl: ComponentImpl<Static<typeof CascaderPropsSpec>> = (
? slotsElements.content[0]
: slotsElements.content;
const mode: "multiple" | undefined = multiple ? "multiple" : undefined;
const mode = multiple ? 'multiple' : undefined;
let defaultValue = cProps.defaultValue;
if (mode === "multiple" && !Array.isArray(cProps.defaultValue[0])) {
if (mode === 'multiple' && !Array.isArray(cProps.defaultValue[0])) {
defaultValue = [cProps.defaultValue as string[]];
}
@ -86,7 +84,7 @@ const CascaderImpl: ComponentImpl<Static<typeof CascaderPropsSpec>> = (
// optimize the display when switching from single selection to multiple selection
useEffect(() => {
if (mode === "multiple" && !Array.isArray(value[0])) {
if (mode === 'multiple' && !Array.isArray(value[0])) {
_setValue([value as string[]]);
}
}, [mode]);
@ -124,22 +122,22 @@ const CascaderImpl: ComponentImpl<Static<typeof CascaderPropsSpec>> = (
};
const CascaderExampleOptions = [
["beijing", "chaoyang", "datunli"],
["beijing", "haidian", "smartx"],
["beijing", "changping"],
["beijing", "wangjing", "soho"],
["shanghai", "huangpu"],
["shanghai", "pukou", "chuansha", "disney"],
["jiangsu", "nanjing", "qinhuai", "yuhuatai", "andemen"],
["jiangsu", "nanjing", "qinhuai", "yuhuatai", "tiexinqiao"],
['beijing', 'chaoyang', 'datunli'],
['beijing', 'haidian', 'smartx'],
['beijing', 'changping'],
['beijing', 'wangjing', 'soho'],
['shanghai', 'huangpu'],
['shanghai', 'pukou', 'chuansha', 'disney'],
['jiangsu', 'nanjing', 'qinhuai', 'yuhuatai', 'andemen'],
['jiangsu', 'nanjing', 'qinhuai', 'yuhuatai', 'tiexinqiao'],
];
const exampleProperties: Static<typeof CascaderPropsSpec> = {
defaultValue: ["beijing", "haidian", "smartx"],
expandTrigger: "click",
defaultValue: ['beijing', 'haidian', 'smartx'],
expandTrigger: 'click',
multiple: false,
placeholder: "Please select ...",
placeholder: 'Please select ...',
bordered: true,
size: "default",
size: 'default',
showSearch: true,
disabled: false,
loading: false,
@ -150,20 +148,20 @@ const exampleProperties: Static<typeof CascaderPropsSpec> = {
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "cascader",
displayName: "Cascader",
name: 'cascader',
displayName: 'Cascader',
exampleProperties,
},
spec: {
properties: CascaderPropsSpec,
state: CascaderStateSpec,
methods: {},
slots: ["content"],
styleSlots: ["content"],
events: ["onChange"],
slots: ['content'],
styleSlots: ['content'],
events: ['onChange'],
},
};

View File

@ -1,28 +1,24 @@
import { Collapse as BaseCollapse } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { Collapse as BaseCollapse } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import {
CollapsePropsSpec as BaseCollapsePropsSpec,
CollapseItemPropsSpec as BaseCollapseItemPropsSpec,
} from "../generated/types/Collapse";
import { useEffect, useState } from "react";
} from '../generated/types/Collapse';
import { useEffect, useState } from 'react';
const CollapsePropsSpec = Type.Object(BaseCollapsePropsSpec);
const CollapseStateSpec = Type.Object({
activeKey: Type.Array(Type.String()),
});
const CollapseImpl: ComponentImpl<Static<typeof CollapsePropsSpec>> = (
props
) => {
const CollapseImpl: ComponentImpl<Static<typeof CollapsePropsSpec>> = props => {
const { defaultActiveKey, ...cProps } = getComponentProps(props);
const { elementRef, mergeState, slotsElements, customStyle, callbackMap } = props;
const [activeKey, setActiveKey] = useState<string[]>(
defaultActiveKey.map(String)
);
const [activeKey, setActiveKey] = useState<string[]>(defaultActiveKey.map(String));
useEffect(() => {
mergeState({ activeKey });
@ -47,18 +43,18 @@ const CollapseImpl: ComponentImpl<Static<typeof CollapsePropsSpec>> = (
);
};
const exampleProperties: Static<typeof CollapsePropsSpec> = {
defaultActiveKey: ["1"],
defaultActiveKey: ['1'],
accordion: false,
expandIconPosition: "left",
expandIconPosition: 'left',
bordered: false,
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "collapse",
displayName: "Collapse",
name: 'collapse',
displayName: 'Collapse',
exampleProperties,
},
spec: {
@ -67,8 +63,8 @@ const options = {
methods: {
setActiveKey: Type.String(),
},
slots: ["collapseItems"],
styleSlots: ["content"],
slots: ['collapseItems'],
styleSlots: ['content'],
events: [],
},
};
@ -80,43 +76,42 @@ export const Collapse = implementRuntimeComponent(options)(
const CollapseItemPropsSpec = Type.Object(BaseCollapseItemPropsSpec);
const CollapseItemStateSpec = Type.Object({});
const CollapseItemImpl: ComponentImpl<Static<typeof CollapseItemPropsSpec>> =
(props) => {
const { elementRef, name, ...cProps } = getComponentProps(props);
const { slotsElements, customStyle } = props;
const CollapseItemImpl: ComponentImpl<Static<typeof CollapseItemPropsSpec>> = props => {
const { elementRef, name, ...cProps } = getComponentProps(props);
const { slotsElements, customStyle } = props;
return (
<BaseCollapse.Item
ref={elementRef}
name={String(name)}
className={css(customStyle?.content)}
{...cProps}
>
{slotsElements.content}
</BaseCollapse.Item>
);
};
return (
<BaseCollapse.Item
ref={elementRef}
name={String(name)}
className={css(customStyle?.content)}
{...cProps}
>
{slotsElements.content}
</BaseCollapse.Item>
);
};
export const CollapseItem = implementRuntimeComponent({
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "CollapseItem",
displayName: "CollapseItem",
name: 'CollapseItem',
displayName: 'CollapseItem',
exampleProperties: {
name: "1",
name: '1',
disabled: false,
showExpandIcon: true,
destroyOnHide: true,
header: "header",
header: 'header',
},
},
spec: {
properties: CollapseItemPropsSpec,
state: CollapseItemStateSpec,
methods: {},
slots: ["content"],
styleSlots: ["content"],
events: ["onChange"],
slots: ['content'],
styleSlots: ['content'],
events: ['onChange'],
},
})(CollapseItemImpl);

View File

@ -1,52 +1,46 @@
import { Divider as BaseDivider } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { DividerPropsSpec as BaseDividerPropsSpec } from "../generated/types/Divider";
import { Divider as BaseDivider } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { DividerPropsSpec as BaseDividerPropsSpec } from '../generated/types/Divider';
const DividerPropsSpec = Type.Object({
...BaseDividerPropsSpec,
});
const DividerStateSpec = Type.Object({});
const DividerImpl: ComponentImpl<Static<typeof DividerPropsSpec>> = (
props
) => {
const DividerImpl: ComponentImpl<Static<typeof DividerPropsSpec>> = props => {
const { elementRef, customStyle } = props;
const { ...cProps } = getComponentProps(props);
return (
<BaseDivider
ref={elementRef}
className={css(customStyle?.content)}
{...cProps}
/>
<BaseDivider ref={elementRef} className={css(customStyle?.content)} {...cProps} />
);
};
const exampleProperties: Static<typeof DividerPropsSpec> = {
type: "horizontal",
orientation: "center",
type: 'horizontal',
orientation: 'center',
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "divider",
displayName: "Divider",
name: 'divider',
displayName: 'Divider',
exampleProperties,
annotations: {
category: "Layout",
}
category: 'Layout',
},
},
spec: {
properties: DividerPropsSpec,
state: DividerStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
styleSlots: ['content'],
events: [],
},
};

View File

@ -2,11 +2,11 @@ import {
Dropdown as BaseDropdown,
Menu as BaseMenu,
Button,
} from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { DropdownPropsSpec as BaseDropdownPropsSpec } from "../generated/types/Dropdown";
} from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { DropdownPropsSpec as BaseDropdownPropsSpec } from '../generated/types/Dropdown';
const DropdownPropsSpec = Type.Object(BaseDropdownPropsSpec);
const DropdownStateSpec = Type.Object({
@ -15,9 +15,7 @@ const DropdownStateSpec = Type.Object({
visible: Type.Boolean(),
});
const DropdownImpl: ComponentImpl<Static<typeof DropdownPropsSpec>> = (
props
) => {
const DropdownImpl: ComponentImpl<Static<typeof DropdownPropsSpec>> = props => {
const { elementRef, slotsElements, callbackMap, mergeState } = props;
const cProps = getComponentProps(props);
const { list, dropdownType, ...restProps } = cProps;
@ -43,7 +41,7 @@ const DropdownImpl: ComponentImpl<Static<typeof DropdownPropsSpec>> = (
const Dropdown = typeMap[dropdownType];
const droplist = (
<BaseMenu onClickMenuItem={onClickMenuItem}>
{(list || []).map((item) => (
{(list || []).map(item => (
<BaseMenu.Item key={item.key}>{item.label}</BaseMenu.Item>
))}
</BaseMenu>
@ -57,42 +55,42 @@ const DropdownImpl: ComponentImpl<Static<typeof DropdownPropsSpec>> = (
onClick={callbackMap?.onButtonClick}
unmountOnExit={false}
>
<div ref={elementRef}>{slotsElements.trigger||<Button>Click</Button>}</div>
<div ref={elementRef}>{slotsElements.trigger || <Button>Click</Button>}</div>
</Dropdown>
);
};
const exampleProperties: Static<typeof DropdownPropsSpec> = {
dropdownType: "default",
trigger: "click",
position: "bl",
dropdownType: 'default',
trigger: 'click',
position: 'bl',
disabled: false,
defaultPopupVisible: false,
list: [
{ key: "1", label: "smartx" },
{ key: "2", label: "baidu" },
{ key: "3", label: "tencent" },
{ key: '1', label: 'smartx' },
{ key: '2', label: 'baidu' },
{ key: '3', label: 'tencent' },
],
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "dropdown",
displayName: "Dropdown",
name: 'dropdown',
displayName: 'Dropdown',
exampleProperties,
annotations: {
category: "Input",
category: 'Input',
},
},
spec: {
properties: DropdownPropsSpec,
state: DropdownStateSpec,
methods: {},
slots: ["trigger"],
slots: ['trigger'],
styleSlots: [],
events: ["onClickMenuItem", "onVisibleChange", "onButtonClick"],
events: ['onClickMenuItem', 'onVisibleChange', 'onButtonClick'],
},
};

View File

@ -1,47 +1,41 @@
import * as Icons from "@arco-design/web-react/icon";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css, cx } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA } from "../sunmao-helper";
import * as Icons from '@arco-design/web-react/icon';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css, cx } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA } from '../sunmao-helper';
const IconPropsSpec = Type.Object({
name: Type.KeyOf(Type.Object(Icons as Record<keyof typeof Icons, any>)),
spin: Type.Boolean(),
});
const impl: ComponentImpl<Static<typeof IconPropsSpec>> = (props) => {
const impl: ComponentImpl<Static<typeof IconPropsSpec>> = props => {
const { elementRef, name, spin, customStyle } = props;
const _Icon = Icons[name];
return (
<_Icon
ref={elementRef}
className={cx(css(customStyle?.content))}
spin={spin}
/>
);
return <_Icon ref={elementRef} className={cx(css(customStyle?.content))} spin={spin} />;
};
export const Icon = implementRuntimeComponent({
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "icon",
displayName: "Icon",
name: 'icon',
displayName: 'Icon',
exampleProperties: {
name: "IconArrowUp",
name: 'IconArrowUp',
spin: false,
},
annotations: {
category: "Display",
}
category: 'Display',
},
},
spec: {
properties: IconPropsSpec,
state: Type.Object({}),
methods: {},
slots: ["slot"],
styleSlots: ["content"],
events: ["event"],
slots: ['slot'],
styleSlots: ['content'],
events: ['event'],
},
})(impl);

View File

@ -1,14 +1,14 @@
import { Image as BaseImage } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { ImagePropsSpec as BaseImagePropsSpec } from "../generated/types/Image";
import { Image as BaseImage } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { ImagePropsSpec as BaseImagePropsSpec } from '../generated/types/Image';
const ImagePropsSpec = Type.Object(BaseImagePropsSpec);
const ImageStateSpec = Type.Object({});
const ImageImpl: ComponentImpl<Static<typeof ImagePropsSpec>> = (props) => {
const ImageImpl: ComponentImpl<Static<typeof ImagePropsSpec>> = props => {
const { elementRef, customStyle, callbackMap } = props;
const cProps = getComponentProps(props);
@ -22,31 +22,31 @@ const ImageImpl: ComponentImpl<Static<typeof ImagePropsSpec>> = (props) => {
);
};
const exampleProperties: Static<typeof ImagePropsSpec> = {
src :'https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a8c8cdb109cb051163646151a4a5083b.png~tplv-uwbnlip3yd-webp.webp',
title:"A users avatar",
description:"Present by Arco Design",
footerPosition:'inner',
simple:false,
preview:false,
src: 'https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a8c8cdb109cb051163646151a4a5083b.png~tplv-uwbnlip3yd-webp.webp',
title: 'A users avatar',
description: 'Present by Arco Design',
footerPosition: 'inner',
simple: false,
preview: false,
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "image",
displayName: "Image",
name: 'image',
displayName: 'Image',
exampleProperties,
annotations: {
category: "Display",
}
category: 'Display',
},
},
spec: {
properties: ImagePropsSpec,
state: ImageStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,11 +1,11 @@
import { Input as BaseInput } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { InputPropsSpec as BaseInputPropsSpec } from "../generated/types/Input";
import { useEffect, useState, useRef } from "react";
import { RefInputType } from "@arco-design/web-react/es/Input/interface";
import { Input as BaseInput } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { InputPropsSpec as BaseInputPropsSpec } from '../generated/types/Input';
import { useEffect, useState, useRef } from 'react';
import { RefInputType } from '@arco-design/web-react/es/Input/interface';
const InputPropsSpec = Type.Object({
...BaseInputPropsSpec,
@ -14,9 +14,8 @@ const InputStateSpec = Type.Object({
value: Type.String(),
});
const InputImpl: ComponentImpl<Static<typeof InputPropsSpec>> = (props) => {
const { getElement, slotsElements, customStyle, callbackMap, mergeState } =
props;
const InputImpl: ComponentImpl<Static<typeof InputPropsSpec>> = props => {
const { getElement, slotsElements, customStyle, callbackMap, mergeState } = props;
const { defaultValue, ...cProps } = getComponentProps(props);
const ref = useRef<RefInputType | null>(null);
const [value, setValue] = useState(defaultValue);
@ -42,7 +41,7 @@ const InputImpl: ComponentImpl<Static<typeof InputPropsSpec>> = (props) => {
prefix={slotsElements.prefix}
suffix={slotsElements.suffix}
value={value}
onChange={(value) => {
onChange={value => {
setValue(value);
callbackMap?.onChange?.();
}}
@ -57,30 +56,30 @@ const exampleProperties: Static<typeof InputPropsSpec> = {
allowClear: false,
disabled: false,
readOnly: false,
defaultValue: "",
placeholder: "please input",
defaultValue: '',
placeholder: 'please input',
error: false,
size: "default",
size: 'default',
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "input",
displayName: "Input",
name: 'input',
displayName: 'Input',
exampleProperties,
annotations: {
category: "Input",
category: 'Input',
},
},
spec: {
properties: InputPropsSpec,
state: InputStateSpec,
methods: {},
slots: ["addAfter", "prefix", "suffix", "addBefore"],
styleSlots: ["input"],
events: ["onChange", "onBlur", "onFocus"],
slots: ['addAfter', 'prefix', 'suffix', 'addBefore'],
styleSlots: ['input'],
events: ['onChange', 'onBlur', 'onFocus'],
},
};

View File

@ -1,14 +1,14 @@
import { Link as BaseLink } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { LinkPropsSpec as BaseLinkPropsSpec } from "../generated/types/Link";
import { Link as BaseLink } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { LinkPropsSpec as BaseLinkPropsSpec } from '../generated/types/Link';
const LinkPropsSpec = Type.Object(BaseLinkPropsSpec);
const LinkStateSpec = Type.Object({});
const LinkImpl: ComponentImpl<Static<typeof LinkPropsSpec>> = (props) => {
const LinkImpl: ComponentImpl<Static<typeof LinkPropsSpec>> = props => {
const { elementRef, content, status, ...cProps } = getComponentProps(props);
const { customStyle } = props;
@ -27,19 +27,19 @@ const LinkImpl: ComponentImpl<Static<typeof LinkPropsSpec>> = (props) => {
const exampleProperties: Static<typeof LinkPropsSpec> = {
disabled: false,
hoverable: true,
status: "warning",
href: "https://www.smartx.com/",
content: "Link",
status: 'warning',
href: 'https://www.smartx.com/',
content: 'Link',
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "link",
displayName: "Link",
name: 'link',
displayName: 'Link',
annotations: {
category: "Input",
category: 'Input',
},
exampleProperties,
},
@ -48,7 +48,7 @@ const options = {
state: LinkStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,19 +1,17 @@
import { Mentions as BaseMentions } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { MentionsPropsSpec as BaseMentionsPropsSpec } from "../generated/types/Mentions";
import { useState, useEffect } from "react";
import { Mentions as BaseMentions } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { MentionsPropsSpec as BaseMentionsPropsSpec } from '../generated/types/Mentions';
import { useState, useEffect } from 'react';
const MentionsPropsSpec = Type.Object(BaseMentionsPropsSpec);
const MentionsStateSpec = Type.Object({
value: Type.String(),
});
const MentionsImpl: ComponentImpl<Static<typeof MentionsPropsSpec>> = (
props
) => {
const MentionsImpl: ComponentImpl<Static<typeof MentionsPropsSpec>> = props => {
const { elementRef, defaultValue, ...cProps } = getComponentProps(props);
const { mergeState, customStyle, callbackMap } = props;
@ -39,7 +37,7 @@ const MentionsImpl: ComponentImpl<Static<typeof MentionsPropsSpec>> = (
return (
<BaseMentions
ref={elementRef}
ref={elementRef}
onPressEnter={onPressEnter}
onClear={onClear}
className={css(customStyle?.content)}
@ -50,11 +48,11 @@ const MentionsImpl: ComponentImpl<Static<typeof MentionsPropsSpec>> = (
);
};
const exampleProperties: Static<typeof MentionsPropsSpec> = {
defaultValue: "smartx",
options: ["smartx", "byte and dance", "baidu"],
prefix: "@",
position: "bl",
split: " ",
defaultValue: 'smartx',
options: ['smartx', 'byte and dance', 'baidu'],
prefix: '@',
position: 'bl',
split: ' ',
error: false,
allowClear: true,
disabled: false,
@ -62,11 +60,11 @@ const exampleProperties: Static<typeof MentionsPropsSpec> = {
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "mentions",
displayName: "Mentions",
name: 'mentions',
displayName: 'Mentions',
exampleProperties,
},
spec: {
@ -74,8 +72,8 @@ const options = {
state: MentionsStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
events: ["onChange", "onClear", "onPressEnter"],
styleSlots: ['content'],
events: ['onChange', 'onClear', 'onPressEnter'],
},
};

View File

@ -1,19 +1,19 @@
import { Modal as BaseModal, ConfigProvider } from "@arco-design/web-react";
import { Modal as BaseModal, ConfigProvider } from '@arco-design/web-react';
import {
ComponentImpl,
DIALOG_CONTAINER_ID,
implementRuntimeComponent,
} from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { ModalPropsSpec as BaseModalPropsSpec } from "../generated/types/Modal";
import { useEffect, useRef, useState } from "react";
} from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { ModalPropsSpec as BaseModalPropsSpec } from '../generated/types/Modal';
import { useEffect, useRef, useState } from 'react';
const ModalPropsSpec = Type.Object(BaseModalPropsSpec);
const ModalStateSpec = Type.Object({});
const ModalImpl: ComponentImpl<Static<typeof ModalPropsSpec>> = (props) => {
const ModalImpl: ComponentImpl<Static<typeof ModalPropsSpec>> = props => {
const { subscribeMethods, slotsElements, customStyle, callbackMap } = props;
const { getElement, title, ...cProps } = getComponentProps(props);
const [visible, setVisible] = useState(true);
@ -70,24 +70,24 @@ const ModalImpl: ComponentImpl<Static<typeof ModalPropsSpec>> = (props) => {
};
const exampleProperties: Static<typeof ModalPropsSpec> = {
title: "Modal title",
title: 'Modal title',
mask: true,
simple: false,
okText: "confirm",
cancelText: "cancel",
okText: 'confirm',
cancelText: 'cancel',
closable: true,
maskClosable: true,
confirmLoading: false,
};
export const Modal = implementRuntimeComponent({
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
exampleProperties,
name: "modal",
displayName: "Modal",
name: 'modal',
displayName: 'Modal',
annotations: {
category: "Display",
category: 'Display',
},
},
spec: {
@ -97,8 +97,8 @@ export const Modal = implementRuntimeComponent({
openModal: Type.String(),
closeModal: Type.String(),
} as Record<string, any>,
slots: ["content", "footer"],
styleSlots: ["content"],
events: ["afterOpen", "afterClose", "onCancel", "onOk"],
slots: ['content', 'footer'],
styleSlots: ['content'],
events: ['afterOpen', 'afterClose', 'onCancel', 'onOk'],
},
})(ModalImpl);

View File

@ -1,26 +1,24 @@
import { Pagination as BasePagination } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
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 { useState } from "react";
import { Pagination as BasePagination } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
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 { useState } from 'react';
const PaginationPropsSpec = Type.Object(BasePaginationPropsSpec);
const PaginationStateSpec = Type.Object({
currentPage: Type.Number(),
});
const PaginationImpl: ComponentImpl<Static<typeof PaginationPropsSpec>> = (
props
) => {
const PaginationImpl: ComponentImpl<Static<typeof PaginationPropsSpec>> = props => {
const { elementRef, defaultCurrent, ...cProps } = getComponentProps(props);
const { customStyle, mergeState, callbackMap } = props;
const [current, setCurrent] = useState<number>(defaultCurrent || 0);
if (cProps.sizeCanChange) {
Reflect.deleteProperty(cProps, "pageSize");
Reflect.deleteProperty(cProps, 'pageSize');
}
const handleChange = (pageNum: number) => {
@ -46,30 +44,30 @@ const exampleProperties: Static<typeof PaginationPropsSpec> = {
defaultCurrent: 3,
disabled: false,
hideOnSinglePage: true,
size: "default",
size: 'default',
sizeCanChange: false,
simple: false,
showJumper: false,
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "pagination",
displayName: "Pagination",
name: 'pagination',
displayName: 'Pagination',
exampleProperties,
annotations: {
category: "Display",
}
category: 'Display',
},
},
spec: {
properties: PaginationPropsSpec,
state: PaginationStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
events: ["onChange"],
styleSlots: ['content'],
events: ['onChange'],
},
};

View File

@ -1,11 +1,11 @@
import { Input } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { PasswordInputPropsSpec as BasePasswordInputPropsSpec } from "../generated/types/PasswordInput";
import { useEffect, useState, useRef } from "react";
import { RefInputType } from "@arco-design/web-react/es/Input/interface";
import { Input } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { PasswordInputPropsSpec as BasePasswordInputPropsSpec } from '../generated/types/PasswordInput';
import { useEffect, useState, useRef } from 'react';
import { RefInputType } from '@arco-design/web-react/es/Input/interface';
const InputPropsSpec = Type.Object({
...BasePasswordInputPropsSpec,
@ -16,12 +16,10 @@ const InputStateSpec = Type.Object({
const BasePasswordInput = Input.Password;
const PasswordInputImpl: ComponentImpl<Static<typeof InputPropsSpec>> = (
props
) => {
const { getElement,customStyle, callbackMap, mergeState } = props;
const PasswordInputImpl: ComponentImpl<Static<typeof InputPropsSpec>> = props => {
const { getElement, customStyle, callbackMap, mergeState } = props;
const { ...cProps } = getComponentProps(props);
const [value, setValue] = useState("");
const [value, setValue] = useState('');
const ref = useRef<RefInputType | null>(null);
useEffect(() => {
@ -42,7 +40,7 @@ const PasswordInputImpl: ComponentImpl<Static<typeof InputPropsSpec>> = (
ref={ref}
className={css(customStyle?.input)}
value={value}
onChange={(value) => {
onChange={value => {
setValue(value);
callbackMap?.onChange?.();
}}
@ -53,21 +51,21 @@ const PasswordInputImpl: ComponentImpl<Static<typeof InputPropsSpec>> = (
const exampleProperties: Static<typeof InputPropsSpec> = {
disabled: false,
placeholder: "please input",
placeholder: 'please input',
error: false,
size: "default",
size: 'default',
visibilityToggle: true,
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "passwordInput",
displayName: "Password Input",
name: 'passwordInput',
displayName: 'Password Input',
exampleProperties,
annotations: {
category: "Input",
category: 'Input',
},
},
spec: {
@ -75,10 +73,9 @@ const options = {
state: InputStateSpec,
methods: {},
slots: [],
styleSlots: ["input"],
events: ["onChange"],
styleSlots: ['input'],
events: ['onChange'],
},
};
export const PasswordInput =
implementRuntimeComponent(options)(PasswordInputImpl);
export const PasswordInput = implementRuntimeComponent(options)(PasswordInputImpl);

View File

@ -1,18 +1,16 @@
import { Popover as BasePopover, Button } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { PopoverPropsSpec as BasePopoverPropsSpec } from "../generated/types/Popover";
import { useEffect, useState } from "react";
import { isArray } from "lodash-es";
import { Popover as BasePopover, Button } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { PopoverPropsSpec as BasePopoverPropsSpec } from '../generated/types/Popover';
import { useEffect, useState } from 'react';
import { isArray } from 'lodash-es';
const PopoverPropsSpec = Type.Object(BasePopoverPropsSpec);
const PopoverStateSpec = Type.Object({});
const PopoverImpl: ComponentImpl<Static<typeof PopoverPropsSpec>> = (
props
) => {
const PopoverImpl: ComponentImpl<Static<typeof PopoverPropsSpec>> = props => {
const { elementRef, controlled, ...cProps } = getComponentProps(props);
const { subscribeMethods, slotsElements, customStyle } = props;
@ -48,7 +46,7 @@ const PopoverImpl: ComponentImpl<Static<typeof PopoverPropsSpec>> = (
{...cProps}
content={slotsElements.popupContent}
popupVisible={popupVisible}
onVisibleChange={(visible) => {
onVisibleChange={visible => {
setPopupVisible(visible);
}}
>
@ -57,24 +55,24 @@ const PopoverImpl: ComponentImpl<Static<typeof PopoverPropsSpec>> = (
);
};
const exampleProperties: Static<typeof PopoverPropsSpec> = {
color: "#eee",
position: "bottom",
color: '#eee',
position: 'bottom',
disabled: false,
controlled: false,
// TODO There are some problems with hover mode that need to be verified later
trigger: "click",
title: "Title",
trigger: 'click',
title: 'Title',
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "popover",
displayName: "Popover",
name: 'popover',
displayName: 'Popover',
exampleProperties,
annotations: {
category: "Display",
category: 'Display',
},
},
spec: {
@ -84,8 +82,8 @@ const options = {
openPopover: Type.String(),
closePopover: Type.String(),
} as Record<string, any>,
slots: ["popupContent", "content"],
styleSlots: ["content"],
slots: ['popupContent', 'content'],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,55 +1,49 @@
import { Progress as BaseProgress } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { ProgressPropsSpec as BaseProgressPropsSpec } from "../generated/types/Progress";
import { Progress as BaseProgress } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { ProgressPropsSpec as BaseProgressPropsSpec } from '../generated/types/Progress';
const ProgressPropsSpec = Type.Object(BaseProgressPropsSpec);
const ProgressStateSpec = Type.Object({});
const ProgressImpl: ComponentImpl<Static<typeof ProgressPropsSpec>> = (
props
) => {
const ProgressImpl: ComponentImpl<Static<typeof ProgressPropsSpec>> = props => {
const { elementRef, ...cProps } = getComponentProps(props);
const { customStyle } = props;
return (
<BaseProgress
ref={elementRef}
className={css(customStyle?.content)}
{...cProps}
/>
<BaseProgress ref={elementRef} className={css(customStyle?.content)} {...cProps} />
);
};
const exampleProperties: Static<typeof ProgressPropsSpec> = {
type: "line",
status: "normal",
color: "#3c92dc",
trailColor: "",
type: 'line',
status: 'normal',
color: '#3c92dc',
trailColor: '',
showText: true,
percent: 20,
width: 100,
size: "default",
size: 'default',
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "progress",
displayName: "Progress",
name: 'progress',
displayName: 'Progress',
exampleProperties,
annotations: {
category: "Display",
}
category: 'Display',
},
},
spec: {
properties: ProgressPropsSpec,
state: ProgressStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,25 +1,19 @@
import { Skeleton as BaseSkeleton } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { SkeletonPropsSpec as BaseSkeletonPropsSpec } from "../generated/types/Skeleton";
import { Skeleton as BaseSkeleton } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { SkeletonPropsSpec as BaseSkeletonPropsSpec } from '../generated/types/Skeleton';
const SkeletonPropsSpec = Type.Object(BaseSkeletonPropsSpec);
const SkeletonStateSpec = Type.Object({});
const SkeletonImpl: ComponentImpl<Static<typeof SkeletonPropsSpec>> = (
props
) => {
const SkeletonImpl: ComponentImpl<Static<typeof SkeletonPropsSpec>> = props => {
const { elementRef, ...cProps } = getComponentProps(props);
const { customStyle, slotsElements } = props;
return (
<BaseSkeleton
ref={elementRef}
className={css(customStyle?.content)}
{...cProps}
>
<BaseSkeleton ref={elementRef} className={css(customStyle?.content)} {...cProps}>
{slotsElements.content}
</BaseSkeleton>
);
@ -29,26 +23,26 @@ const exampleProperties: Static<typeof SkeletonPropsSpec> = {
animation: true,
loading: true,
image: false,
text: { rows: 3, width: ["100%", 600, 400] },
text: { rows: 3, width: ['100%', 600, 400] },
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "skeleton",
displayName: "Skeleton",
name: 'skeleton',
displayName: 'Skeleton',
exampleProperties,
annotations: {
category: "Display",
}
category: 'Display',
},
},
spec: {
properties: SkeletonPropsSpec,
state: SkeletonStateSpec,
methods: {},
slots: ["content"],
styleSlots: ["content"],
slots: ['content'],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,19 +1,16 @@
import { Space as BaseSpace } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import {
FALLBACK_METADATA,
getComponentProps,
} from "../sunmao-helper";
import { SpacePropsSpec as BaseSpacePropsSpec } from "../generated/types/Space";
import { Space as BaseSpace } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { SpacePropsSpec as BaseSpacePropsSpec } from '../generated/types/Space';
const SpacePropsSpec = Type.Object({
...BaseSpacePropsSpec,
});
const SpaceStateSpec = Type.Object({});
const SpaceImpl: ComponentImpl<Static<typeof SpacePropsSpec>> = (props) => {
const SpaceImpl: ComponentImpl<Static<typeof SpacePropsSpec>> = props => {
const { elementRef, slotsElements, customStyle } = props;
const cProps = getComponentProps(props);
@ -25,28 +22,28 @@ const SpaceImpl: ComponentImpl<Static<typeof SpacePropsSpec>> = (props) => {
};
const exampleProperties: Static<typeof SpacePropsSpec> = {
align: "center",
direction: "vertical",
align: 'center',
direction: 'vertical',
wrap: false,
size: "large",
size: 'large',
};
export const Space = implementRuntimeComponent({
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
exampleProperties,
annotations: {
category: "Layout",
category: 'Layout',
},
name: "space",
displayName: "Space",
name: 'space',
displayName: 'Space',
},
spec: {
properties: SpacePropsSpec,
state: SpaceStateSpec,
methods: {},
slots: ["content"],
styleSlots: ["content"],
events: ["onClick"],
slots: ['content'],
styleSlots: ['content'],
events: ['onClick'],
},
})(SpaceImpl);

View File

@ -1,24 +1,23 @@
import { Steps as BaseSteps } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { Steps as BaseSteps } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import {
StepsPropsSpec as BaseStepsPropsSpec,
StepItemSpec,
} from "../generated/types/Steps";
} from '../generated/types/Steps';
const StepsPropsSpec = Type.Object(BaseStepsPropsSpec);
const StepsStateSpec = Type.Object({});
type StepItem = Static<typeof StepItemSpec>;
const StepsImpl: ComponentImpl<Static<typeof StepsPropsSpec>> = (props) => {
const StepsImpl: ComponentImpl<Static<typeof StepsPropsSpec>> = props => {
const { items, ...cProps } = getComponentProps(props);
const { elementRef, customStyle, slotsElements } = props;
const labelPlacement =
cProps.direction === "horizontal" ? "vertical" : "horizontal";
const labelPlacement = cProps.direction === 'horizontal' ? 'vertical' : 'horizontal';
return (
<BaseSteps
@ -43,36 +42,36 @@ const StepsImpl: ComponentImpl<Static<typeof StepsPropsSpec>> = (props) => {
};
const exampleProperties: Static<typeof StepsPropsSpec> = {
type: "default",
size: "default",
direction: "horizontal",
status: "finish",
type: 'default',
size: 'default',
direction: 'horizontal',
status: 'finish',
current: 2,
lineless: false,
items: [
{ title: "Succeeded", description: "This is a description" },
{ title: "Processing", description: "" },
{ title: "Pending", description: "This is a description" },
{ title: 'Succeeded', description: 'This is a description' },
{ title: 'Processing', description: '' },
{ title: 'Pending', description: 'This is a description' },
],
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "steps",
displayName: "Steps",
name: 'steps',
displayName: 'Steps',
exampleProperties,
annotations: {
category: "Display",
category: 'Display',
},
},
spec: {
properties: StepsPropsSpec,
state: StepsStateSpec,
methods: {},
slots: ["icons"],
styleSlots: ["content"],
slots: ['icons'],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,10 +1,10 @@
import { Switch as BaseSwitch } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
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 { useEffect, useState } from "react";
import { Switch as BaseSwitch } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
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 { useEffect, useState } from 'react';
const SwitchPropsSpec = Type.Object({
...BaseSwitchPropsSpec,
@ -13,8 +13,8 @@ const SwitchStateSpec = Type.Object({
value: Type.Boolean(),
});
const SwitchImpl: ComponentImpl<Static<typeof SwitchPropsSpec>> = (props) => {
const {elementRef, customStyle, mergeState } = props;
const SwitchImpl: ComponentImpl<Static<typeof SwitchPropsSpec>> = props => {
const { elementRef, customStyle, mergeState } = props;
const { defaultChecked, ...cProps } = getComponentProps(props);
const [value, setValue] = useState<boolean>(defaultChecked);
@ -34,7 +34,7 @@ const SwitchImpl: ComponentImpl<Static<typeof SwitchPropsSpec>> = (props) => {
className={css(customStyle?.content)}
checked={value}
{...cProps}
onChange={(value) => setValue(value)}
onChange={value => setValue(value)}
/>
);
};
@ -43,19 +43,19 @@ const exampleProperties: Static<typeof SwitchPropsSpec> = {
defaultChecked: false,
disabled: false,
loading: false,
type: "circle",
size: "default",
type: 'circle',
size: 'default',
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "switch",
displayName: "Switch",
name: 'switch',
displayName: 'Switch',
exampleProperties,
annotations: {
category: "Input",
category: 'Input',
},
},
spec: {

View File

@ -10,13 +10,7 @@ import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { TablePropsSpec, ColumnSpec } from '../generated/types/Table';
import React, {
CSSProperties,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import React, { CSSProperties, useEffect, useMemo, useRef, useState } from 'react';
import { sortBy } from 'lodash-es';
import {
LIST_ITEM_EXP,
@ -29,7 +23,7 @@ import { ColumnProps } from '@arco-design/web-react/es/Table';
import { Resizable, ResizeCallbackData } from 'react-resizable';
const TableStateSpec = Type.Object({
clickedRow:Type.Optional(Type.Any()),
clickedRow: Type.Optional(Type.Any()),
selectedRows: Type.Array(Type.Any()),
selectedRow: Type.Optional(Type.Any()),
selectedRowKeys: Type.Array(Type.String()),
@ -40,7 +34,7 @@ type SortRule = {
direction?: 'ascend' | 'descend';
};
type ColumnProperty = Static<typeof ColumnSpec> & ColumnProps
type ColumnProperty = Static<typeof ColumnSpec> & ColumnProps;
type filterDropdownParam = {
filterKeys?: string[];
@ -312,12 +306,15 @@ export const Table = implementRuntimeComponent({
}
newColumn.render = (ceilValue: any, record: any, index: number) => {
const evalOptions = {
evalListItem: true,
scopeObject: {
[LIST_ITEM_EXP]: record,
},
};
const evaledColumn: ColumnProperty = services.stateManager.deepEval(
column,
true,
{
[LIST_ITEM_EXP]: record,
}
evalOptions
);
const value = record[evaledColumn.dataIndex];
@ -330,8 +327,7 @@ export const Table = implementRuntimeComponent({
if (!rawColumn.btnCfg) return;
const evaledButtonConfig = services.stateManager.deepEval(
rawColumn.btnCfg,
true,
{ [LIST_ITEM_EXP]: record }
evalOptions
);
evaledButtonConfig.handlers.forEach(handler => {

View File

@ -1,11 +1,11 @@
import { Input } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { TextAreaPropsSpec as BaseTextAreaPropsSpec } from "../generated/types/TextArea";
import { useEffect, useState, useRef } from "react";
import { RefInputType } from "@arco-design/web-react/es/Input/interface";
import { Input } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { TextAreaPropsSpec as BaseTextAreaPropsSpec } from '../generated/types/TextArea';
import { useEffect, useState, useRef } from 'react';
import { RefInputType } from '@arco-design/web-react/es/Input/interface';
const TextAreaPropsSpec = Type.Object({
...BaseTextAreaPropsSpec,
@ -16,9 +16,7 @@ const TextAreaStateSpec = Type.Object({
const BaseTextArea = Input.TextArea;
const TextAreaImpl: ComponentImpl<Static<typeof TextAreaPropsSpec>> = (
props
) => {
const TextAreaImpl: ComponentImpl<Static<typeof TextAreaPropsSpec>> = props => {
const { getElement, customStyle, callbackMap, mergeState } = props;
const { defaultValue, ...cProps } = getComponentProps(props);
const [value, setValue] = useState(defaultValue);
@ -42,7 +40,7 @@ const TextAreaImpl: ComponentImpl<Static<typeof TextAreaPropsSpec>> = (
ref={ref}
className={css(customStyle?.TextArea)}
value={value}
onChange={(value) => {
onChange={value => {
setValue(value);
callbackMap?.onChange?.();
}}
@ -54,22 +52,22 @@ const TextAreaImpl: ComponentImpl<Static<typeof TextAreaPropsSpec>> = (
const exampleProperties: Static<typeof TextAreaPropsSpec> = {
allowClear: false,
disabled: false,
defaultValue: "",
placeholder: "please input",
defaultValue: '',
placeholder: 'please input',
error: false,
size: "default",
size: 'default',
autoSize: true,
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "textArea",
displayName: "TextArea",
name: 'textArea',
displayName: 'TextArea',
exampleProperties,
annotations: {
category: "TextArea",
category: 'TextArea',
},
},
spec: {
@ -77,8 +75,8 @@ const options = {
state: TextAreaStateSpec,
methods: {},
slots: [],
styleSlots: ["TextArea"],
events: ["onChange"],
styleSlots: ['TextArea'],
events: ['onChange'],
},
};

View File

@ -1,16 +1,14 @@
import { Timeline as BaseTimeline } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { TimelinePropsSpec as BaseTimelinePropsSpec } from "../generated/types/Timeline";
import { Timeline as BaseTimeline } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { TimelinePropsSpec as BaseTimelinePropsSpec } from '../generated/types/Timeline';
const TimelinePropsSpec = Type.Object(BaseTimelinePropsSpec);
const TimelineStateSpec = Type.Object({});
const TimelineImpl: ComponentImpl<Static<typeof TimelinePropsSpec>> = (
props
) => {
const TimelineImpl: ComponentImpl<Static<typeof TimelinePropsSpec>> = props => {
const { items, ...cProps } = getComponentProps(props);
const { elementRef, customStyle } = props;
@ -33,51 +31,51 @@ const TimelineImpl: ComponentImpl<Static<typeof TimelinePropsSpec>> = (
};
const exampleProperties: Static<typeof TimelinePropsSpec> = {
reverse: false,
direction: "vertical",
mode: "alternate",
labelPosition: "same",
direction: 'vertical',
mode: 'alternate',
labelPosition: 'same',
items: [
{
label: "2017-03-10",
content: "The first milestone",
dotColor: "#00B42A",
lineType: "dashed",
lineColor: "#00B42A",
dotType: "hollow",
label: '2017-03-10',
content: 'The first milestone',
dotColor: '#00B42A',
lineType: 'dashed',
lineColor: '#00B42A',
dotType: 'hollow',
},
{
label: "2018-05-12",
content: "The second milestone",
dotColor: "",
lineType: "solid",
lineColor: "",
dotType: "hollow",
label: '2018-05-12',
content: 'The second milestone',
dotColor: '',
lineType: 'solid',
lineColor: '',
dotType: 'hollow',
},
{
label: "2020-06-22",
content: "The third milestone",
dotColor: "#F53F3F",
lineType: "dotted",
dotType: "solid",
lineColor: "",
label: '2020-06-22',
content: 'The third milestone',
dotColor: '#F53F3F',
lineType: 'dotted',
dotType: 'solid',
lineColor: '',
},
{
label: "2020-09-30",
content: "The fourth milestone",
dotColor: "#C9CDD4",
lineType: "dotted",
dotType: "solid",
lineColor: "",
label: '2020-09-30',
content: 'The fourth milestone',
dotColor: '#C9CDD4',
lineType: 'dotted',
dotType: 'solid',
lineColor: '',
},
],
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "timeline",
displayName: "Timeline",
name: 'timeline',
displayName: 'Timeline',
exampleProperties,
},
spec: {
@ -85,7 +83,7 @@ const options = {
state: TimelineStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,18 +1,16 @@
import { Tooltip as BaseTooltip, Button } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { TooltipPropsSpec as BaseTooltipPropsSpec } from "../generated/types/Tooltip";
import { isArray } from "lodash-es";
import { useState, useEffect } from "react";
import { Tooltip as BaseTooltip, Button } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { TooltipPropsSpec as BaseTooltipPropsSpec } from '../generated/types/Tooltip';
import { isArray } from 'lodash-es';
import { useState, useEffect } from 'react';
const TooltipPropsSpec = Type.Object(BaseTooltipPropsSpec);
const TooltipStateSpec = Type.Object({});
const TooltipImpl: ComponentImpl<Static<typeof TooltipPropsSpec>> = (
props
) => {
const TooltipImpl: ComponentImpl<Static<typeof TooltipPropsSpec>> = props => {
const { controlled, ...cProps } = getComponentProps(props);
const { elementRef, subscribeMethods, slotsElements, customStyle } = props;
@ -52,22 +50,22 @@ const TooltipImpl: ComponentImpl<Static<typeof TooltipPropsSpec>> = (
);
};
const exampleProperties: Static<typeof TooltipPropsSpec> = {
color: "#bbb",
position: "bottom",
color: '#bbb',
position: 'bottom',
mini: false,
disabled: false,
content: "This is tooltip",
content: 'This is tooltip',
// TODO There are some problems with hover mode that need to be verified later
trigger: "click",
trigger: 'click',
controlled: false,
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "tooltip",
displayName: "Tooltip",
name: 'tooltip',
displayName: 'Tooltip',
exampleProperties,
},
spec: {
@ -77,8 +75,8 @@ const options = {
openTooltip: Type.String(),
closeTooltip: Type.String(),
} as Record<string, any>,
slots: ["content"],
styleSlots: ["content"],
slots: ['content'],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,29 +1,20 @@
import { Tree as BaseTree } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA } from "../sunmao-helper";
import { TreePropsSpec, TreeNodeSpec } from "../generated/types/Tree";
import { useEffect, useState } from "react";
import { NodeInstance } from "@arco-design/web-react/es/Tree/interface";
import { Tree as BaseTree } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA } from '../sunmao-helper';
import { TreePropsSpec, TreeNodeSpec } from '../generated/types/Tree';
import { useEffect, useState } from 'react';
import { NodeInstance } from '@arco-design/web-react/es/Tree/interface';
const TreeStateSpec = Type.Object({
selectedNode: TreeNodeSpec,
selectedNodes: Type.Array(TreeNodeSpec),
});
const TreeImpl: ComponentImpl<Static<typeof TreePropsSpec>> = (props) => {
const {
elementRef,
data,
multiple,
autoExpandParent,
customStyle,
mergeState,
} = props;
const [selectedNodes, setSelectedNodes] = useState<
Static<typeof TreeNodeSpec>[]
>([]);
const TreeImpl: ComponentImpl<Static<typeof TreePropsSpec>> = props => {
const { elementRef, data, multiple, autoExpandParent, customStyle, mergeState } = props;
const [selectedNodes, setSelectedNodes] = useState<Static<typeof TreeNodeSpec>[]>([]);
useEffect(() => {
mergeState({
@ -52,37 +43,36 @@ function formatNode(node: NodeInstance): Static<typeof TreeNodeSpec> {
key: node.props._key!,
selectable: node.props.selectable,
checkable: node.props.checkable,
path:[...node.props.pathParentKeys!,node.props._key!],
children:
node.props.dataRef?.children || ([] as Static<typeof TreeNodeSpec>[]),
path: [...node.props.pathParentKeys!, node.props._key!],
children: node.props.dataRef?.children || ([] as Static<typeof TreeNodeSpec>[]),
};
}
const exampleProperties: Static<typeof TreePropsSpec> = {
multiple: false,
size: "medium",
size: 'medium',
autoExpandParent: true,
data: [
{
title: "Asia",
key: "asia",
title: 'Asia',
key: 'asia',
children: [
{
title: "China",
key: "China",
title: 'China',
key: 'China',
selectable: false,
children: [
{
title: "Guangdong",
key: "Guangdong",
title: 'Guangdong',
key: 'Guangdong',
children: [
{
title: "Guangzhou",
key: "Guangzhou",
title: 'Guangzhou',
key: 'Guangzhou',
},
{
title: "Shenzhen",
key: "Shenzhen",
title: 'Shenzhen',
key: 'Shenzhen',
},
],
},
@ -91,16 +81,16 @@ const exampleProperties: Static<typeof TreePropsSpec> = {
],
},
{
title: "Europe",
key: "Europe",
title: 'Europe',
key: 'Europe',
children: [
{
title: "France",
key: "France",
title: 'France',
key: 'France',
},
{
title: "Germany",
key: "Germany",
title: 'Germany',
key: 'Germany',
},
],
},
@ -108,13 +98,13 @@ const exampleProperties: Static<typeof TreePropsSpec> = {
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "tree",
displayName: "Tree",
name: 'tree',
displayName: 'Tree',
annotations: {
category: "Display",
category: 'Display',
},
exampleProperties,
},
@ -123,7 +113,7 @@ const options = {
state: TreeStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
styleSlots: ['content'],
events: [],
},
};

View File

@ -1,27 +1,23 @@
import { TreeSelect as BaseTreeSelect } from "@arco-design/web-react";
import { ComponentImpl, implementRuntimeComponent } from "@sunmao-ui/runtime";
import { css } from "@emotion/css";
import { Type, Static } from "@sinclair/typebox";
import { FALLBACK_METADATA, getComponentProps } from "../sunmao-helper";
import { TreeSelectPropsSpec as BaseTreeSelectPropsSpec } from "../generated/types/TreeSelect";
import { useState, useEffect , useRef } from "react";
import { RefTreeSelectType } from "@arco-design/web-react/es/TreeSelect";
import { TreeSelect as BaseTreeSelect } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
import { TreeSelectPropsSpec as BaseTreeSelectPropsSpec } from '../generated/types/TreeSelect';
import { useState, useEffect, useRef } from 'react';
import { RefTreeSelectType } from '@arco-design/web-react/es/TreeSelect';
const TreeSelectPropsSpec = Type.Object(BaseTreeSelectPropsSpec);
const TreeSelectStateSpec = Type.Object({
selectedOptions: Type.String(),
});
const TreeSelectImpl: ComponentImpl<Static<typeof TreeSelectPropsSpec>> = (
props
) => {
const TreeSelectImpl: ComponentImpl<Static<typeof TreeSelectPropsSpec>> = props => {
const { defaultValue, ...cProps } = getComponentProps(props);
const { getElement, customStyle, mergeState, callbackMap } = props;
const ref = useRef<RefTreeSelectType | null>(null);
const [selectedOptions, setSelectedOptions] = useState<string[]>(
defaultValue!
);
const [selectedOptions, setSelectedOptions] = useState<string[]>(defaultValue!);
useEffect(() => {
// arco definition doesn't declare dom, but it actually has.
@ -41,9 +37,7 @@ const TreeSelectImpl: ComponentImpl<Static<typeof TreeSelectPropsSpec>> = (
};
const filterTreeNode = (inputText: string, treeNode: any) => {
return (
treeNode.props.title.toLowerCase().indexOf(inputText.toLowerCase()) > -1
);
return treeNode.props.title.toLowerCase().indexOf(inputText.toLowerCase()) > -1;
};
return (
@ -61,39 +55,39 @@ const TreeSelectImpl: ComponentImpl<Static<typeof TreeSelectPropsSpec>> = (
const exampleProperties: Static<typeof TreeSelectPropsSpec> = {
multiple: false,
defaultValue: ["node1"],
defaultValue: ['node1'],
treeData: [
{
key: "node1",
title: "Trunk",
key: 'node1',
title: 'Trunk',
disabled: true,
children: [
{
key: "node2",
title: "Leaf1",
key: 'node2',
title: 'Leaf1',
},
],
},
{
key: "node3",
title: "Trunk2",
key: 'node3',
title: 'Trunk2',
disabled: false,
children: [
{
key: "node4",
title: "Leaf2",
key: 'node4',
title: 'Leaf2',
},
{
key: "node5",
title: "Leaf3",
key: 'node5',
title: 'Leaf3',
},
],
},
],
bordered: true,
placeholder: "Select option(s)",
placeholder: 'Select option(s)',
labelInValue: true,
size: "default",
size: 'default',
disabled: false,
error: false,
showSearch: true,
@ -102,11 +96,11 @@ const exampleProperties: Static<typeof TreeSelectPropsSpec> = {
};
const options = {
version: "arco/v1",
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: "treeSelect",
displayName: "TreeSelect",
name: 'treeSelect',
displayName: 'TreeSelect',
exampleProperties,
},
spec: {
@ -114,8 +108,8 @@ const options = {
state: TreeSelectStateSpec,
methods: {},
slots: [],
styleSlots: ["content"],
events: ["onChange"],
styleSlots: ['content'],
events: ['onChange'],
},
};

View File

@ -1,11 +1,10 @@
import { Layout, Menu, Typography } from "@arco-design/web-react";
import React, { useState } from "react";
import { ButtonDemoPage } from "./pages/button";
import { TreeDemoPage } from "./pages/tree";
import { TableDemoPage } from "./pages/table";
import { LayoutDemoPage } from "./pages/layout";
import { TabDemoPage } from "./pages/tab";
import { Layout, Menu, Typography } from '@arco-design/web-react';
import React, { useState } from 'react';
import { ButtonDemoPage } from './pages/button';
import { TreeDemoPage } from './pages/tree';
import { TableDemoPage } from './pages/table';
import { LayoutDemoPage } from './pages/layout';
import { TabDemoPage } from './pages/tab';
const { Sider, Content, Header } = Layout;
const ContentMap: Record<string, React.FC> = {
@ -17,13 +16,13 @@ const ContentMap: Record<string, React.FC> = {
};
export const ExampleIndexPage: React.FC = () => {
const [selectedKey, setSelectedKey] = useState("Button");
const [selectedKey, setSelectedKey] = useState('Button');
const ContentComponent: React.FC = ContentMap[selectedKey];
return (
<Layout>
<Sider collapsed={false}>
<Menu selectedKeys={[selectedKey]}>
{Object.keys(ContentMap).map((name) => {
{Object.keys(ContentMap).map(name => {
return (
<Menu.Item key={name} onClick={() => setSelectedKey(name)}>
{name}
@ -36,10 +35,8 @@ export const ExampleIndexPage: React.FC = () => {
<Header style={{ paddingLeft: 20 }}>
<Typography.Title>{selectedKey}</Typography.Title>
</Header>
<Layout style={{ padding: "0 24px" }}>
<Content>
{ContentComponent ? <ContentComponent /> : undefined}
</Content>
<Layout style={{ padding: '0 24px' }}>
<Content>{ContentComponent ? <ContentComponent /> : undefined}</Content>
</Layout>
</Layout>
</Layout>

View File

@ -1,4 +1,4 @@
import ReactDOM from "react-dom";
import { ExampleIndexPage } from "./ExampleIndexPage";
import ReactDOM from 'react-dom';
import { ExampleIndexPage } from './ExampleIndexPage';
ReactDOM.render(<ExampleIndexPage />, document.getElementById("root"));
ReactDOM.render(<ExampleIndexPage />, document.getElementById('root'));

View File

@ -1,150 +1,150 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const basicUsage: Application = {
kind: "Application",
version: "example/v1",
kind: 'Application',
version: 'example/v1',
metadata: {
name: "buttonBasicUsage",
description: "buttonBasicUsage",
name: 'buttonBasicUsage',
description: 'buttonBasicUsage',
},
spec: {
components: [
{
id: "space",
type: "arco/v1/space",
id: 'space',
type: 'arco/v1/space',
properties: {},
traits: [],
},
{
id: "button1",
type: "arco/v1/button",
id: 'button1',
type: 'arco/v1/button',
properties: {
text: "primary",
type: "primary",
text: 'primary',
type: 'primary',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button2",
type: "arco/v1/button",
id: 'button2',
type: 'arco/v1/button',
properties: {
text: "secondary",
type: "secondary",
text: 'secondary',
type: 'secondary',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button3",
type: "arco/v1/button",
id: 'button3',
type: 'arco/v1/button',
properties: {
text: "dashed",
type: "dashed",
text: 'dashed',
type: 'dashed',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button4",
type: "arco/v1/button",
id: 'button4',
type: 'arco/v1/button',
properties: {
text: "outline",
type: "outline",
text: 'outline',
type: 'outline',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button5",
type: "arco/v1/button",
id: 'button5',
type: 'arco/v1/button',
properties: {
text: "text",
type: "text",
text: 'text',
type: 'text',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button6",
type: "arco/v1/button",
id: 'button6',
type: 'arco/v1/button',
properties: {
text: "disabled",
type: "primary",
text: 'disabled',
type: 'primary',
disabled: true,
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button7",
type: "arco/v1/button",
id: 'button7',
type: 'arco/v1/button',
properties: {
text: "loading",
type: "primary",
text: 'loading',
type: 'primary',
loading: true,
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},

View File

@ -1,46 +1,46 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const buttonEvent: Application = {
kind: "Application",
version: "example/v1",
kind: 'Application',
version: 'example/v1',
metadata: {
name: "buttonEvent",
description: "buttonEvent",
name: 'buttonEvent',
description: 'buttonEvent',
},
spec: {
components: [
{
id: "space",
type: "arco/v1/space",
id: 'space',
type: 'arco/v1/space',
properties: {},
traits: [],
},
{
id: "button1",
type: "arco/v1/button",
id: 'button1',
type: 'arco/v1/button',
properties: {
text: "Click",
type: "primary",
text: 'Click',
type: 'primary',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: { id: "space", slot: "content" },
container: { id: 'space', slot: 'content' },
},
},
{
type: "core/v1/event",
type: 'core/v1/event',
properties: {
handlers: [
{
type: "onClick",
componentId: "count",
type: 'onClick',
componentId: 'count',
method: {
name: "setValue",
name: 'setValue',
parameters: {
key: "value",
value: "{{count.value + 1}}",
key: 'value',
value: '{{count.value + 1}}',
},
},
},
@ -50,28 +50,28 @@ const buttonEvent: Application = {
],
},
{
id: "text1",
type: "core/v1/text",
id: 'text1',
type: 'core/v1/text',
properties: {
value: { raw: "click count: {{count.value}}", format: "plain" },
value: { raw: 'click count: {{count.value}}', format: 'plain' },
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: { id: "space", slot: "content" },
container: { id: 'space', slot: 'content' },
},
},
],
},
{
id: "count",
type: "core/v1/dummy",
id: 'count',
type: 'core/v1/dummy',
properties: {},
traits: [
{
type: "core/v1/state",
properties: { key: "value", initialValue: 0 },
type: 'core/v1/state',
properties: { key: 'value', initialValue: 0 },
},
],
},

View File

@ -1,126 +1,126 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const buttonShape: Application = {
kind: "Application",
version: "example/v1",
kind: 'Application',
version: 'example/v1',
metadata: {
name: "buttonShape",
description: "buttonShape",
name: 'buttonShape',
description: 'buttonShape',
},
spec: {
components: [
{
id: "space",
type: "arco/v1/space",
id: 'space',
type: 'arco/v1/space',
properties: {},
traits: [],
},
{
id: "button1",
type: "arco/v1/button",
id: 'button1',
type: 'arco/v1/button',
properties: {
type: "primary",
type: 'primary',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "iconplus",
type: "arco/v1/icon",
id: 'iconplus',
type: 'arco/v1/icon',
properties: {
name: "IconPlus",
name: 'IconPlus',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "button1",
slot: "content",
id: 'button1',
slot: 'content',
},
},
},
],
},
{
id: "button2",
type: "arco/v1/button",
id: 'button2',
type: 'arco/v1/button',
properties: {
type: "primary",
shape: "circle",
type: 'primary',
shape: 'circle',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "iconplus2",
type: "arco/v1/icon",
id: 'iconplus2',
type: 'arco/v1/icon',
properties: {
name: "IconPlus",
name: 'IconPlus',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "button2",
slot: "content",
id: 'button2',
slot: 'content',
},
},
},
],
},
{
id: "button3",
type: "arco/v1/button",
id: 'button3',
type: 'arco/v1/button',
properties: {
text: "delete",
type: "primary",
shape: "round",
text: 'delete',
type: 'primary',
shape: 'round',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "iconplus3",
type: "arco/v1/icon",
id: 'iconplus3',
type: 'arco/v1/icon',
properties: {
name: "IconDelete",
name: 'IconDelete',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "button3",
slot: "content",
id: 'button3',
slot: 'content',
},
},
},

View File

@ -1,94 +1,94 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const buttonSize: Application = {
kind: "Application",
version: "example/v1",
kind: 'Application',
version: 'example/v1',
metadata: {
name: "buttonSize",
description: "buttonSize",
name: 'buttonSize',
description: 'buttonSize',
},
spec: {
components: [
{
id: "space",
type: "arco/v1/space",
id: 'space',
type: 'arco/v1/space',
properties: {},
traits: [],
},
{
id: "button1",
type: "arco/v1/button",
id: 'button1',
type: 'arco/v1/button',
properties: {
text: "primary",
type: "primary",
size: "mini",
text: 'primary',
type: 'primary',
size: 'mini',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button2",
type: "arco/v1/button",
id: 'button2',
type: 'arco/v1/button',
properties: {
text: "primary",
type: "primary",
size: "small",
text: 'primary',
type: 'primary',
size: 'small',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button3",
type: "arco/v1/button",
id: 'button3',
type: 'arco/v1/button',
properties: {
text: "primary",
type: "primary",
text: 'primary',
type: 'primary',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button4",
type: "arco/v1/button",
id: 'button4',
type: 'arco/v1/button',
properties: {
text: "primary",
type: "primary",
size: "large",
text: 'primary',
type: 'primary',
size: 'large',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},

View File

@ -1,72 +1,72 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const buttonStatus: Application = {
kind: "Application",
version: "example/v1",
kind: 'Application',
version: 'example/v1',
metadata: {
name: "buttonStatus",
description: "buttonStatus",
name: 'buttonStatus',
description: 'buttonStatus',
},
spec: {
components: [
{
id: "space",
type: "arco/v1/space",
id: 'space',
type: 'arco/v1/space',
properties: {},
traits: [],
},
{
id: "button1",
type: "arco/v1/button",
id: 'button1',
type: 'arco/v1/button',
properties: {
text: "warning",
status: "warning",
text: 'warning',
status: 'warning',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button2",
type: "arco/v1/button",
id: 'button2',
type: 'arco/v1/button',
properties: {
text: "danger",
status: "danger",
text: 'danger',
status: 'danger',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button3",
type: "arco/v1/button",
id: 'button3',
type: 'arco/v1/button',
properties: {
text: "success",
status: "success",
text: 'success',
status: 'success',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},

View File

@ -1,88 +1,88 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const buttonWithIcon: Application = {
kind: "Application",
version: "example/v1",
kind: 'Application',
version: 'example/v1',
metadata: {
name: "buttonWithIcon",
description: "buttonWithIcon",
name: 'buttonWithIcon',
description: 'buttonWithIcon',
},
spec: {
components: [
{
id: "space",
type: "arco/v1/space",
id: 'space',
type: 'arco/v1/space',
properties: {},
traits: [],
},
{
id: "button1",
type: "arco/v1/button",
id: 'button1',
type: 'arco/v1/button',
properties: {
type: "primary",
type: 'primary',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "iconplus",
type: "arco/v1/icon",
id: 'iconplus',
type: 'arco/v1/icon',
properties: {
name: "IconPlus",
name: 'IconPlus',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "button1",
slot: "content",
id: 'button1',
slot: 'content',
},
},
},
],
},
{
id: "button2",
type: "arco/v1/button",
id: 'button2',
type: 'arco/v1/button',
properties: {
text: "delete",
type: "primary",
text: 'delete',
type: 'primary',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "iconplus2",
type: "arco/v1/icon",
id: 'iconplus2',
type: 'arco/v1/icon',
properties: {
name: "IconDelete",
name: 'IconDelete',
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "button2",
slot: "content",
id: 'button2',
slot: 'content',
},
},
},

View File

@ -1,12 +1,12 @@
import { Divider, Typography } from "@arco-design/web-react";
import { DemoWrapper } from "../../DemoWrapper";
import basicUsage from "./basicUsage";
import buttonEvent from "./buttonEvent";
import buttonWithIcon from "./buttonWithIcon";
import buttonSize from "./buttonSize";
import buttonShape from "./buttonShape";
import buttonStatus from "./buttonStatus";
import longButton from "./longButton";
import { Divider, Typography } from '@arco-design/web-react';
import { DemoWrapper } from '../../DemoWrapper';
import basicUsage from './basicUsage';
import buttonEvent from './buttonEvent';
import buttonWithIcon from './buttonWithIcon';
import buttonSize from './buttonSize';
import buttonShape from './buttonShape';
import buttonStatus from './buttonStatus';
import longButton from './longButton';
export const ButtonDemoPage: React.FC = () => {
return (

View File

@ -1,28 +1,28 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const longButton: Application = {
kind: "Application",
version: "example/v1",
kind: 'Application',
version: 'example/v1',
metadata: {
name: "longButton",
description: "longButton",
name: 'longButton',
description: 'longButton',
},
spec: {
components: [
{
id: "space",
type: "arco/v1/space",
id: 'space',
type: 'arco/v1/space',
properties: {
direction: "vertical",
direction: 'vertical',
},
traits: [
{
type: "core/v1/style",
type: 'core/v1/style',
properties: {
styles: [
{
styleSlot: "content",
style: "width: 360px; border: 1px solid #ddd; padding: 32px",
styleSlot: 'content',
style: 'width: 360px; border: 1px solid #ddd; padding: 32px',
},
],
},
@ -30,40 +30,40 @@ const longButton: Application = {
],
},
{
id: "button1",
type: "arco/v1/button",
id: 'button1',
type: 'arco/v1/button',
properties: {
text: "primary",
type: "primary",
text: 'primary',
type: 'primary',
long: true,
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},
],
},
{
id: "button2",
type: "arco/v1/button",
id: 'button2',
type: 'arco/v1/button',
properties: {
text: "primary",
type: "primary",
text: 'primary',
type: 'primary',
long: true,
},
traits: [
{
type: "core/v1/slot",
type: 'core/v1/slot',
properties: {
container: {
id: "space",
slot: "content",
id: 'space',
slot: 'content',
},
},
},

View File

@ -1,189 +1,189 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const layoutWithMenu: Application = {
"version": "sunmao/v1",
"kind": "Application",
"metadata": {
"name": "some App"
version: 'sunmao/v1',
kind: 'Application',
metadata: {
name: 'some App',
},
"spec": {
"components": [
spec: {
components: [
{
"id": "layout4",
"type": "arco/v1/layout",
"properties": {
"showHeader": true,
"showSideBar": true,
"sidebarCollapsible": false,
"sidebarDefaultCollapsed": false,
"showFooter": true
id: 'layout4',
type: 'arco/v1/layout',
properties: {
showHeader: true,
showSideBar: true,
sidebarCollapsible: false,
sidebarDefaultCollapsed: false,
showFooter: true,
},
"traits": []
traits: [],
},
{
"id": "text6",
"type": "core/v1/text",
"properties": {
"value": {
"raw": "XXX Manage Panel",
"format": "plain"
}
id: 'text6',
type: 'core/v1/text',
properties: {
value: {
raw: 'XXX Manage Panel',
format: 'plain',
},
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "layout4",
"slot": "header"
}
}
}
]
type: 'core/v1/slot',
properties: {
container: {
id: 'layout4',
slot: 'header',
},
},
},
],
},
{
"id": "menu5",
"type": "arco/v1/menu",
"properties": {
"mode": "vertical",
"autoOpen": false,
"collapse": false,
"accordion": false,
"ellipsis": false,
"autoScrollIntoView": false,
"hasCollapseButton": false,
"items": [
id: 'menu5',
type: 'arco/v1/menu',
properties: {
mode: 'vertical',
autoOpen: false,
collapse: false,
accordion: false,
ellipsis: false,
autoScrollIntoView: false,
hasCollapseButton: false,
items: [
{
"key": "dashboard",
"text": "DashBorad"
key: 'dashboard',
text: 'DashBorad',
},
{
"key": "users",
"text": "Users"
key: 'users',
text: 'Users',
},
{
"key": "settings",
"text": "Settings"
}
key: 'settings',
text: 'Settings',
},
],
"defaultActiveKey": "dashboard"
defaultActiveKey: 'dashboard',
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "layout4",
"slot": "sidebar"
}
}
}
]
type: 'core/v1/slot',
properties: {
container: {
id: 'layout4',
slot: 'sidebar',
},
},
},
],
},
{
"id": "text7",
"type": "core/v1/text",
"properties": {
"value": {
"raw": "I am dashboard.",
"format": "plain"
}
id: 'text7',
type: 'core/v1/text',
properties: {
value: {
raw: 'I am dashboard.',
format: 'plain',
},
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "layout4",
"slot": "content"
}
}
type: 'core/v1/slot',
properties: {
container: {
id: 'layout4',
slot: 'content',
},
},
},
{
"type": "core/v1/hidden",
"properties": {
"hidden": "{{menu5.activeKey !== 'dashboard'}}"
}
}
]
type: 'core/v1/hidden',
properties: {
hidden: "{{menu5.activeKey !== 'dashboard'}}",
},
},
],
},
{
"id": "text8",
"type": "core/v1/text",
"properties": {
"value": {
"raw": "I am Users.",
"format": "plain"
}
id: 'text8',
type: 'core/v1/text',
properties: {
value: {
raw: 'I am Users.',
format: 'plain',
},
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "layout4",
"slot": "content"
}
}
type: 'core/v1/slot',
properties: {
container: {
id: 'layout4',
slot: 'content',
},
},
},
{
"type": "core/v1/hidden",
"properties": {
"hidden": "{{menu5.activeKey !== 'users'}}"
}
}
]
type: 'core/v1/hidden',
properties: {
hidden: "{{menu5.activeKey !== 'users'}}",
},
},
],
},
{
"id": "text9",
"type": "core/v1/text",
"properties": {
"value": {
"raw": "I am Settings.",
"format": "plain"
}
id: 'text9',
type: 'core/v1/text',
properties: {
value: {
raw: 'I am Settings.',
format: 'plain',
},
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "layout4",
"slot": "content"
}
}
type: 'core/v1/slot',
properties: {
container: {
id: 'layout4',
slot: 'content',
},
},
},
{
"type": "core/v1/hidden",
"properties": {
"hidden": "{{menu5.activeKey !== 'settings'}}"
}
}
]
type: 'core/v1/hidden',
properties: {
hidden: "{{menu5.activeKey !== 'settings'}}",
},
},
],
},
{
"id": "text10",
"type": "core/v1/text",
"properties": {
"value": {
"raw": "XXX Company All rights reserved",
"format": "plain"
}
id: 'text10',
type: 'core/v1/text',
properties: {
value: {
raw: 'XXX Company All rights reserved',
format: 'plain',
},
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "layout4",
"slot": "footer"
}
}
}
]
}
]
}
}
type: 'core/v1/slot',
properties: {
container: {
id: 'layout4',
slot: 'footer',
},
},
},
],
},
],
},
};
export default layoutWithMenu;

View File

@ -1,187 +1,183 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const tabBasicUsage: Application = {
"version": "sunmao/v1",
"kind": "Application",
"metadata": {
"name": "some App"
version: 'sunmao/v1',
kind: 'Application',
metadata: {
name: 'some App',
},
"spec": {
"components": [
spec: {
components: [
{
"id": "formControl8",
"type": "arco/v1/formControl",
"properties": {
"label": {
"format": "md",
"raw": "Tab Position"
id: 'formControl8',
type: 'arco/v1/formControl',
properties: {
label: {
format: 'md',
raw: 'Tab Position',
},
"layout": "horizontal",
"required": false,
"hidden": false,
"extra": "",
"errorMsg": "",
"labelAlign": "left",
"colon": false,
"labelCol": {
"span": 5,
"offset": 0
layout: 'horizontal',
required: false,
hidden: false,
extra: '',
errorMsg: '',
labelAlign: 'left',
colon: false,
labelCol: {
span: 5,
offset: 0,
},
"wrapperCol": {
"span": 19,
"offset": 0
wrapperCol: {
span: 19,
offset: 0,
},
"help": ""
help: '',
},
"traits": [
traits: [
{
"type": "core/v1/style",
"properties": {
"styles": [
type: 'core/v1/style',
properties: {
styles: [
{
"styleSlot": "content",
"style": "width: 400px !important;"
}
]
}
}
]
styleSlot: 'content',
style: 'width: 400px !important;',
},
],
},
},
],
},
{
"id": "select7",
"type": "arco/v1/select",
"properties": {
"allowClear": false,
"multiple": false,
"allowCreate": false,
"bordered": true,
"defaultValue": "top",
"disabled": false,
"labelInValue": false,
"loading": false,
"options": [
id: 'select7',
type: 'arco/v1/select',
properties: {
allowClear: false,
multiple: false,
allowCreate: false,
bordered: true,
defaultValue: 'top',
disabled: false,
labelInValue: false,
loading: false,
options: [
{
"value": "left",
"text": "left"
value: 'left',
text: 'left',
},
{
"value": "right",
"text": "right"
value: 'right',
text: 'right',
},
{
"value": "bottom",
"text": "bottom"
value: 'bottom',
text: 'bottom',
},
{
"value": "top",
"text": "top"
}
value: 'top',
text: 'top',
},
],
"placeholder": "Please select",
"size": "default"
placeholder: 'Please select',
size: 'default',
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "formControl8",
"slot": "content"
}
}
}
]
type: 'core/v1/slot',
properties: {
container: {
id: 'formControl8',
slot: 'content',
},
},
},
],
},
{
"id": "divider6",
"type": "arco/v1/divider",
"properties": {
"type": "horizontal",
"orientation": "center"
id: 'divider6',
type: 'arco/v1/divider',
properties: {
type: 'horizontal',
orientation: 'center',
},
"traits": []
traits: [],
},
{
"id": "tabs7",
"type": "arco/v1/tabs",
"properties": {
"type": "line",
"defaultActiveTab": "0",
"tabPosition": "{{select7.value}}",
"size": "default",
"tabNames": [
"Dashboard",
"Users",
"Settings"
]
id: 'tabs7',
type: 'arco/v1/tabs',
properties: {
type: 'line',
defaultActiveTab: '0',
tabPosition: '{{select7.value}}',
size: 'default',
tabNames: ['Dashboard', 'Users', 'Settings'],
},
"traits": []
traits: [],
},
{
"id": "text7",
"type": "core/v1/text",
"properties": {
"value": {
"raw": "I am dashboard.",
"format": "plain"
}
id: 'text7',
type: 'core/v1/text',
properties: {
value: {
raw: 'I am dashboard.',
format: 'plain',
},
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "tabs7",
"slot": "content"
}
}
}
]
type: 'core/v1/slot',
properties: {
container: {
id: 'tabs7',
slot: 'content',
},
},
},
],
},
{
"id": "text8",
"type": "core/v1/text",
"properties": {
"value": {
"raw": "I am Users.",
"format": "plain"
}
id: 'text8',
type: 'core/v1/text',
properties: {
value: {
raw: 'I am Users.',
format: 'plain',
},
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "tabs7",
"slot": "content"
}
}
}
]
type: 'core/v1/slot',
properties: {
container: {
id: 'tabs7',
slot: 'content',
},
},
},
],
},
{
"id": "text9",
"type": "core/v1/text",
"properties": {
"value": {
"raw": "I am Settings.",
"format": "plain"
}
id: 'text9',
type: 'core/v1/text',
properties: {
value: {
raw: 'I am Settings.',
format: 'plain',
},
},
"traits": [
traits: [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "tabs7",
"slot": "content"
}
}
}
]
}
]
}
}
type: 'core/v1/slot',
properties: {
container: {
id: 'tabs7',
slot: 'content',
},
},
},
],
},
],
},
};
export default tabBasicUsage;

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
import { Divider, Typography } from "@arco-design/web-react";
import { DemoWrapper } from "../../DemoWrapper";
import { basicUsage } from "./basicUsage";
import { selection } from "./selection";
import { attributes } from "./attributes";
import { sortAndFilter } from "./sortAndFilter";
import { Divider, Typography } from '@arco-design/web-react';
import { DemoWrapper } from '../../DemoWrapper';
import { basicUsage } from './basicUsage';
import { selection } from './selection';
import { attributes } from './attributes';
import { sortAndFilter } from './sortAndFilter';
const { Title, Text, Paragraph } = Typography;
@ -15,31 +15,28 @@ export const TableDemoPage: React.FC = () => {
<Divider />
<Title heading={3}>Selection</Title>
<Paragraph>
To enable selection, you can use radio or checkbox by setting the{" "}
To enable selection, you can use radio or checkbox by setting the{' '}
<Text code>Row Selection Type</Text>
</Paragraph>
<DemoWrapper application={selection} />
<Divider />
<Title heading={3}>Attributes</Title>
<Paragraph>
You can easily open or close the properties of the table
</Paragraph>
<Paragraph>You can easily open or close the properties of the table</Paragraph>
<DemoWrapper application={attributes} />
<Divider />
<Title heading={3}>Sort and filter</Title>
<Paragraph>
Configure the <Text code>sortable</Text> or <Text code>filterable</Text>{" "}
of <Text code>Column</Text> to sort or filter the table
Configure the <Text code>sortable</Text> or <Text code>filterable</Text> of{' '}
<Text code>Column</Text> to sort or filter the table
</Paragraph>
<Paragraph>
You can provide only <Text code>ascending</Text> or{" "}
<Text code>descending</Text> order or both by setting the sortDirections
value to <Text code>[&rsquo;ascend&rsquo;]</Text>,
<Text code>[&rsquo;descend&rsquo;]</Text>,
<Text code>[&rsquo;ascend&rsquo;,&rsquo;descend&rsquo;]</Text>
You can provide only <Text code>ascending</Text> or <Text code>descending</Text>{' '}
order or both by setting the sortDirections value to{' '}
<Text code>[&rsquo;ascend&rsquo;]</Text>,<Text code>[&rsquo;descend&rsquo;]</Text>
,<Text code>[&rsquo;ascend&rsquo;,&rsquo;descend&rsquo;]</Text>
</Paragraph>
<Paragraph>
After that you can pick one of them as the default sort by setting{" "}
After that you can pick one of them as the default sort by setting{' '}
<Text code>defaultSortOrder</Text>
</Paragraph>
<DemoWrapper application={sortAndFilter} />

View File

@ -1,183 +1,179 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
export const sortAndFilter: Application = {
"kind": "Application",
"version": "example/v1",
"metadata": {
"name": "sortAndFilter",
"description": "sort and filter usage"
},
"spec": {
"components": [
kind: 'Application',
version: 'example/v1',
metadata: {
name: 'sortAndFilter',
description: 'sort and filter usage',
},
spec: {
components: [
{
id: 'space32',
type: 'arco/v1/space',
properties: {
align: 'center',
direction: 'vertical',
wrap: false,
size: 'mini',
},
traits: [],
},
{
id: 'table31',
type: 'arco/v1/table',
properties: {
columns: [
{
"id": "space32",
"type": "arco/v1/space",
"properties": {
"align": "center",
"direction": "vertical",
"wrap": false,
"size": "mini"
},
"traits": []
title: 'Name',
dataIndex: 'name',
sorter: true,
sortDirections: ['ascend', 'descend'],
defaultSortOrder: 'descend',
type: 'text',
filter: true,
},
{
"id": "table31",
"type": "arco/v1/table",
"properties": {
"columns": [
{
"title": "Name",
"dataIndex": "name",
"sorter": true,
"sortDirections": [
"ascend",
"descend"
],
"defaultSortOrder": "descend",
"type": "text",
"filter": true
},
{
"title": "Salary",
"dataIndex": "salary",
"sorter": true,
"filter": false,
"type": "text",
"sortDirections": "{{['ascend']}}"
},
{
"title": "Time",
"dataIndex": "time",
"sorter": false,
"filter": false,
"type": "text"
},
{
"title": "Link",
"dataIndex": "link",
"type": "link",
"filter": true,
"sorter": false
}
],
"data": [
{
"key": "key 0",
"name": "Kevin Sandra0",
"link": "link-A",
"salary": 181,
"time": "2021-0-11T2:10:45.437Z"
},
{
"key": "key 1",
"name": "Kevin Sandra1",
"link": "link-B",
"salary": 387,
"time": "2021-3-11T1:10:45.437Z"
},
{
"key": "key 2",
"name": "Kevin Sandra2",
"link": "link-B",
"salary": 215,
"time": "2021-5-11T14:10:45.437Z"
},
{
"key": "key 3",
"name": "xzdry3",
"link": "link-B",
"salary": 427,
"time": "2021-10-11T9:10:45.437Z"
},
{
"key": "key 4",
"name": "Kevin Sandra4",
"link": "link-A",
"salary": 950,
"time": "2021-10-11T6:10:45.437Z"
},
{
"key": "key 5",
"name": "xzdry5",
"link": "link-B",
"salary": 811,
"time": "2021-8-11T5:10:45.437Z"
},
{
"key": "key 6",
"name": "Kevin Sandra6",
"link": "link-A",
"salary": 805,
"time": "2021-5-11T5:10:45.437Z"
},
{
"key": "key 7",
"name": "Kevin Sandra7",
"link": "link-B",
"salary": 782,
"time": "2021-8-11T14:10:45.437Z"
},
{
"key": "key 8",
"name": "xzdry8",
"link": "link-A",
"salary": 87,
"time": "2021-3-11T6:10:45.437Z"
},
{
"key": "key 9",
"name": "Kevin Sandra9",
"link": "link-A",
"salary": 805,
"time": "2021-0-11T11:10:45.437Z"
},
{
"key": "key 10",
"name": "xzdry10",
"link": "link-B",
"salary": 935,
"time": "2021-10-11T4:10:45.437Z"
},
{
"key": "key 11",
"name": "xzdry11",
"link": "link-A",
"salary": 381,
"time": "2021-0-11T14:10:45.437Z"
},
{
"key": "key 12",
"name": "Kevin Sandra12",
"link": "link-B",
"salary": 406,
"time": "2021-2-11T13:10:45.437Z"
}
],
"pagination": {
"pageSize": 6
},
"tableLayoutFixed": false,
"borderCell": false,
"stripe": false,
"size": "default",
"pagePosition": "bottomCenter",
"rowSelectionType": "disable",
"border": false,
"loading": false
},
"traits": [
{
"type": "core/v1/slot",
"properties": {
"container": {
"id": "space32",
"slot": "content"
}
}
}
]
}
]
}
}
title: 'Salary',
dataIndex: 'salary',
sorter: true,
filter: false,
type: 'text',
sortDirections: "{{['ascend']}}",
},
{
title: 'Time',
dataIndex: 'time',
sorter: false,
filter: false,
type: 'text',
},
{
title: 'Link',
dataIndex: 'link',
type: 'link',
filter: true,
sorter: false,
},
],
data: [
{
key: 'key 0',
name: 'Kevin Sandra0',
link: 'link-A',
salary: 181,
time: '2021-0-11T2:10:45.437Z',
},
{
key: 'key 1',
name: 'Kevin Sandra1',
link: 'link-B',
salary: 387,
time: '2021-3-11T1:10:45.437Z',
},
{
key: 'key 2',
name: 'Kevin Sandra2',
link: 'link-B',
salary: 215,
time: '2021-5-11T14:10:45.437Z',
},
{
key: 'key 3',
name: 'xzdry3',
link: 'link-B',
salary: 427,
time: '2021-10-11T9:10:45.437Z',
},
{
key: 'key 4',
name: 'Kevin Sandra4',
link: 'link-A',
salary: 950,
time: '2021-10-11T6:10:45.437Z',
},
{
key: 'key 5',
name: 'xzdry5',
link: 'link-B',
salary: 811,
time: '2021-8-11T5:10:45.437Z',
},
{
key: 'key 6',
name: 'Kevin Sandra6',
link: 'link-A',
salary: 805,
time: '2021-5-11T5:10:45.437Z',
},
{
key: 'key 7',
name: 'Kevin Sandra7',
link: 'link-B',
salary: 782,
time: '2021-8-11T14:10:45.437Z',
},
{
key: 'key 8',
name: 'xzdry8',
link: 'link-A',
salary: 87,
time: '2021-3-11T6:10:45.437Z',
},
{
key: 'key 9',
name: 'Kevin Sandra9',
link: 'link-A',
salary: 805,
time: '2021-0-11T11:10:45.437Z',
},
{
key: 'key 10',
name: 'xzdry10',
link: 'link-B',
salary: 935,
time: '2021-10-11T4:10:45.437Z',
},
{
key: 'key 11',
name: 'xzdry11',
link: 'link-A',
salary: 381,
time: '2021-0-11T14:10:45.437Z',
},
{
key: 'key 12',
name: 'Kevin Sandra12',
link: 'link-B',
salary: 406,
time: '2021-2-11T13:10:45.437Z',
},
],
pagination: {
pageSize: 6,
},
tableLayoutFixed: false,
borderCell: false,
stripe: false,
size: 'default',
pagePosition: 'bottomCenter',
rowSelectionType: 'disable',
border: false,
loading: false,
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: 'space32',
slot: 'content',
},
},
},
],
},
],
},
};

View File

@ -1,70 +1,70 @@
import { Application } from "@sunmao-ui/core";
import { Application } from '@sunmao-ui/core';
const basicUsage: Application = {
kind: "Application",
version: "example/v1",
kind: 'Application',
version: 'example/v1',
metadata: {
name: "buttonBasicUsage",
description: "buttonBasicUsage",
name: 'buttonBasicUsage',
description: 'buttonBasicUsage',
},
spec: {
components: [
{
id: "text",
type: "core/v1/text",
id: 'text',
type: 'core/v1/text',
properties: {
value: {
raw: "Multiple Select",
format: "plain",
raw: 'Multiple Select',
format: 'plain',
},
},
traits: [],
},
{
id: "multiple",
type: "arco/v1/switch",
id: 'multiple',
type: 'arco/v1/switch',
properties: {},
traits: [],
},
{
id: "text",
type: "core/v1/text",
id: 'text',
type: 'core/v1/text',
properties: {
value: {
raw: "Selected Nodes: {{tree.selectedNodes.map(n => n.title).join(', ')}}",
format: "plain",
format: 'plain',
},
},
traits: [],
},
{
id: "tree",
type: "arco/v1/tree",
id: 'tree',
type: 'arco/v1/tree',
properties: {
multiple: "{{multiple.value}}",
size: "medium",
multiple: '{{multiple.value}}',
size: 'medium',
autoExpandParent: true,
data: [
{
title: "Asia",
key: "asia",
title: 'Asia',
key: 'asia',
children: [
{
title: "China",
key: "China",
title: 'China',
key: 'China',
children: [
{
title: "Guangdong",
key: "Guangdong",
title: 'Guangdong',
key: 'Guangdong',
selectable: false,
children: [
{
title: "Guangzhou",
key: "Guangzhou",
title: 'Guangzhou',
key: 'Guangzhou',
},
{
title: "Shenzhen",
key: "Shenzhen",
title: 'Shenzhen',
key: 'Shenzhen',
},
],
},
@ -73,17 +73,17 @@ const basicUsage: Application = {
],
},
{
title: "Europe",
key: "Europe",
title: 'Europe',
key: 'Europe',
children: [
{
title: "France",
key: "France",
title: 'France',
key: 'France',
selectable: false,
},
{
title: "Germany",
key: "Germany",
title: 'Germany',
key: 'Germany',
},
],
},

View File

@ -1,6 +1,6 @@
import { Divider, Typography } from "@arco-design/web-react";
import { DemoWrapper } from "../../DemoWrapper";
import basicUsage from "./basicUsage";
import { Divider, Typography } from '@arco-design/web-react';
import { DemoWrapper } from '../../DemoWrapper';
import basicUsage from './basicUsage';
export const TreeDemoPage: React.FC = () => {
return (

View File

@ -3,39 +3,31 @@ import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const AlertPropsSpec = {
disabled: Type.Boolean({
title:'Disabled',
category:Category.Basic
}),
type: StringUnion(['info', 'success', 'warning', 'error'], {
title:'Type',
category: Category.Style
}),
showIcon: Type.Boolean({
title:'Show Icon',
category: Category.Style
}),
banner: Type.Boolean({
title:'Banner',
category: Category.Style,
description:'Whether to show as banner on top of the page'
}),
content: Type.String({
title:'Content',
weight: 1,
category:Category.Basic
}),
title: Type.String({
title:'Title',
weight: 2,
category:Category.Basic
}),
visible: Type.Boolean({
title:'Visible',
category: Category.Basic
}),
closable: Type.Boolean({
title:'Closable',
category:Category.Basic
}),
}
type: StringUnion(['info', 'success', 'warning', 'error'], {
title: 'Type',
category: Category.Basic,
}),
showIcon: Type.Boolean({
title: 'Show Icon',
category: Category.Basic,
}),
banner: Type.Boolean({
title: 'Banner',
category: Category.Style,
description: 'Whether to show as banner on top of the page',
}),
content: Type.String({
title: 'Content',
weight: 1,
category: Category.Basic,
}),
title: Type.String({
title: 'Title',
weight: 2,
category: Category.Basic,
}),
closable: Type.Boolean({
title: 'Closable',
category: Category.Basic,
}),
};

View File

@ -1,54 +1,59 @@
import { Type } from "@sinclair/typebox";
import { Category } from "../../constants/category";
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const AvatarPropsSpec = {
shape: StringUnion(['circle', 'square'], {
title: 'Shape',
category: Category.Style
category: Category.Style,
}),
size: Type.Number({
title: 'Size',
category: Category.Style
category: Category.Style,
}),
type: StringUnion(['img', 'text'], {
title: 'Type',
category: Category.Basic
category: Category.Basic,
}),
src: Type.Optional(Type.String({
title: 'Src',
category: Category.Basic,
conditions: [
{
key: 'type',
value: 'img'
}
]
})),
text: Type.Optional(Type.String({
title: 'Text',
category: Category.Basic,
conditions: [
{
key: 'type',
value: 'text'
}
]
})),
autoFixFontSize: Type.Optional(Type.Boolean({
title: 'Auto Fix Font Size',
category: Category.Basic,
conditions: [
{
key: 'type',
value: 'text'
}
]
})),
src: Type.Optional(
Type.String({
title: 'Src',
category: Category.Basic,
conditions: [
{
key: 'type',
value: 'img',
},
],
})
),
text: Type.Optional(
Type.String({
title: 'Text',
category: Category.Basic,
conditions: [
{
key: 'type',
value: 'text',
},
],
})
),
autoFixFontSize: Type.Optional(
Type.Boolean({
title: 'Auto Fix Font Size',
category: Category.Basic,
conditions: [
{
key: 'type',
value: 'text',
},
],
})
),
triggerType: StringUnion(['button', 'mask'], {
title: 'Trigger Type',
category: Category.Basic,
description: 'Clickable avatar interaction type'
})
description: 'Clickable avatar interaction type',
}),
};

View File

@ -1,34 +1,59 @@
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const BadgePropsSpec = {
text: Type.String({
title:'Text',
category: Category.Basic,
description: 'Set the display text of the status dot'
}),
count: Type.Number({
title:'Count',
category: Category.Basic,
}),
dot: Type.Boolean({
title:'Dot Mode',
category: Category.Style,
}),
maxCount: Type.Number({
title: 'Max Count',
category: Category.Basic,
description: 'Max count to show. If count is larger than this value, it will be displayed as ${maxCount}+'
}),
offset: Type.Tuple([Type.Number(), Type.Number()], {
title: 'Offset',
category: Category.Layout,
}),
dotColor: StringUnion(['red', 'orangered', 'orange', 'gold', 'lime', 'green', 'cyan', 'arcoblue', 'purple', 'pinkpurple', 'magenta', 'gray'], {
text: Type.String({
title: 'Text',
category: Category.Basic,
description: 'Set the display text of the status dot',
}),
count: Type.Number({
title: 'Count',
category: Category.Basic,
}),
maxCount: Type.Number({
title: 'Max Count',
category: Category.Basic,
// eslint-disable-next-line no-template-curly-in-string
description:
'Max count to show. If count is larger than this value, it will be displayed as ${maxCount}+',
}),
dot: Type.Boolean({
title: 'Dot Mode',
category: Category.Basic,
}),
offset: Type.Tuple([Type.Number(), Type.Number()], {
title: 'Offset',
category: Category.Layout,
}),
dotColor: Type.Optional(
StringUnion(
[
'red',
'orangered',
'orange',
'gold',
'lime',
'green',
'cyan',
'arcoblue',
'purple',
'pinkpurple',
'magenta',
'gray',
],
{
title: 'Dot Color',
description: 'Set the badge color in dot mode',
category: Category.Style,
}),
}
category: Category.Basic,
conditions: [
{
key: 'dot',
value: true,
},
],
}
)
),
};

View File

@ -1,40 +1,39 @@
import { Type } from "@sinclair/typebox";
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const ButtonPropsSpec = {
text: Type.String({
title:'Text',
category:Category.Basic,
title: 'Text',
category: Category.Basic,
}),
type: StringUnion(['default', 'primary', 'secondary', 'dashed', 'text', 'outline'], {
title:'Type',
category: Category.Style
title: 'Type',
category: Category.Style,
}),
status: StringUnion(['default', 'warning', 'danger', 'success'], {
title:'Status',
category: Category.Style
title: 'Status',
category: Category.Style,
}),
size: StringUnion(['default', 'mini', 'small', 'large'], {
title:'Size',
category: Category.Style
title: 'Size',
category: Category.Style,
}),
shape: StringUnion(['circle', 'round', 'square'], {
title:'Shape',
category: Category.Style
title: 'Shape',
category: Category.Style,
}),
disabled: Type.Boolean({
title:'Disabled',
category:Category.Basic
title: 'Disabled',
category: Category.Basic,
}),
loading: Type.Boolean({
title:'Loading',
category:Category.Basic
title: 'Loading',
category: Category.Basic,
}),
long: Type.Boolean({
title:'Long',
description:'Whether the width of the button should adapt to the container',
category: Category.Basic
})
title: 'Long',
description: 'Whether the width of the button should adapt to the container',
category: Category.Basic,
}),
};

View File

@ -1,44 +1,43 @@
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const CollapsePropsSpec = {
defaultActiveKey: Type.Array(Type.String(), {
title:'Default Active Key',
category: Category.Basic
}),
accordion: Type.Boolean({
title:'Accordion',
category: Category.Style
}),
expandIconPosition: StringUnion(['left', 'right'], {
title:'Expand Icon Position',
category: Category.Layout
}),
bordered: Type.Boolean({
title:'Bordered',
category: Category.Style
})
}
defaultActiveKey: Type.Array(Type.String(), {
title: 'Default Active Key',
category: Category.Basic,
}),
accordion: Type.Boolean({
title: 'Accordion',
category: Category.Style,
}),
expandIconPosition: StringUnion(['left', 'right'], {
title: 'Expand Icon Position',
category: Category.Layout,
}),
bordered: Type.Boolean({
title: 'Bordered',
category: Category.Style,
}),
};
export const CollapseItemPropsSpec = {
name: Type.String({
title:'Name',
category: Category.Basic,
weight: 2
}),
disabled: Type.Boolean({
title:'Disabled',
category: Category.Basic
}),
showExpandIcon: Type.Boolean({
title:'Show Expand Icon',
category: Category.Basic
}),
header: Type.String({
title:'Header',
category: Category.Basic,
weight: 1
})
}
name: Type.String({
title: 'Name',
category: Category.Basic,
weight: 2,
}),
disabled: Type.Boolean({
title: 'Disabled',
category: Category.Basic,
}),
showExpandIcon: Type.Boolean({
title: 'Show Expand Icon',
category: Category.Basic,
}),
header: Type.String({
title: 'Header',
category: Category.Basic,
weight: 1,
}),
};

View File

@ -1,12 +1,11 @@
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const DividerPropsSpec = {
type: StringUnion(['vertical', 'horizontal'], {
category: Category.Layout
category: Category.Layout,
}),
orientation: StringUnion(['center', 'left', 'right'], {
category: Category.Layout
})
category: Category.Layout,
}),
};

View File

@ -1,39 +1,41 @@
import { Type } from "@sinclair/typebox";
import { Category } from "../../constants/category";
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const DropdownPropsSpec = {
dropdownType: StringUnion(['default', 'button'], {
title:'Type',
category: Category.Basic
title: 'Type',
category: Category.Basic,
}),
position: StringUnion(['top', 'tl', 'tr', 'bottom', 'bl', 'br'], {
title:'Position',
category: Category.Layout
title: 'Position',
category: Category.Layout,
}),
trigger: StringUnion(['hover', 'click'], {
title:'Trigger',
category: Category.Basic
title: 'Trigger',
category: Category.Basic,
}),
disabled: Type.Boolean({
title:'Disabled',
category: Category.Basic
title: 'Disabled',
category: Category.Basic,
}),
defaultPopupVisible: Type.Boolean({
title:'Default Visible',
category: Category.Basic
}),
list: Type.Array(Type.Object({
key: Type.String({
title:'Key'
}),
label: Type.String({
title:'Label'
}),
}), {
title:'List',
title: 'Default Visible',
category: Category.Basic,
weight: 10
})
}),
list: Type.Array(
Type.Object({
key: Type.String({
title: 'Key',
}),
label: Type.String({
title: 'Label',
}),
}),
{
title: 'List',
category: Category.Basic,
weight: 10,
}
),
};

View File

@ -1,69 +1,75 @@
import { Type } from "@sinclair/typebox";
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category';
import { TextPropertySpec } from "@sunmao-ui/runtime";
import { TextPropertySpec } from '@sunmao-ui/runtime';
export const FormControlPropsSpec = {
label: TextPropertySpec,
required: Type.Boolean({
title: 'Required',
category: Category.Basic
}),
hidden: Type.Boolean({
title: 'Hidden',
category: Category.Basic
}),
layout: StringUnion(['vertical', 'horizontal'], {
title: 'Layout',
category: Category.Layout,
}),
extra: Type.String({
title: 'Extra',
category: Category.Basic
}),
errorMsg: Type.String({
title: 'Error Message',
category: Category.Basic
}),
help: Type.String({
title: 'Help Message',
category: Category.Basic
}),
labelAlign: StringUnion(['left', 'right'], {
title: 'Label Align',
category: Category.Layout
}),
colon: Type.Boolean({
title: 'Colon',
category: Category.Style
}),
labelCol: Type.Object({
span: Type.Number(),
offset: Type.Number()
}, {
title: 'Label Col',
category: Category.Layout
}),
wrapperCol: Type.Object({
span: Type.Number(),
offset: Type.Number()
}, {
title: 'Wrapper Col',
category: Category.Layout
})
}
label: TextPropertySpec,
required: Type.Boolean({
title: 'Required',
category: Category.Basic,
}),
hidden: Type.Boolean({
title: 'Hidden',
category: Category.Basic,
}),
layout: StringUnion(['vertical', 'horizontal'], {
title: 'Layout',
category: Category.Layout,
}),
extra: Type.String({
title: 'Extra',
category: Category.Basic,
}),
errorMsg: Type.String({
title: 'Error Message',
category: Category.Basic,
}),
help: Type.String({
title: 'Help Message',
category: Category.Basic,
}),
labelAlign: StringUnion(['left', 'right'], {
title: 'Label Align',
category: Category.Layout,
}),
colon: Type.Boolean({
title: 'Colon',
category: Category.Style,
}),
labelCol: Type.Object(
{
span: Type.Number(),
offset: Type.Number(),
},
{
title: 'Label Col',
category: Category.Layout,
}
),
wrapperCol: Type.Object(
{
span: Type.Number(),
offset: Type.Number(),
},
{
title: 'Wrapper Col',
category: Category.Layout,
}
),
};
export const FormPropsSpec = {
inline: Type.Boolean({
title: 'Inline',
category: Category.Layout
}),
size: StringUnion(['mini', 'small', 'default', 'large'], {
title: 'Size',
category: Category.Layout
}),
bordered: Type.Boolean({
title: 'Bordered',
category: Category.Layout
}),
inline: Type.Boolean({
title: 'Inline',
category: Category.Layout,
}),
size: StringUnion(['mini', 'small', 'default', 'large'], {
title: 'Size',
category: Category.Layout,
}),
bordered: Type.Boolean({
title: 'Bordered',
category: Category.Layout,
}),
};

View File

@ -1,31 +1,30 @@
import { Type } from "@sinclair/typebox";
import { Category } from "../../constants/category";
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const ImagePropsSpec = {
src: Type.String({
title:'Src',
category: Category.Basic
title: 'Src',
category: Category.Basic,
}),
title: Type.String({
title:'Title',
category: Category.Basic
title: 'Title',
category: Category.Basic,
}),
description: Type.String({
title:'Description',
category: Category.Basic
title: 'Description',
category: Category.Basic,
}),
footerPosition: StringUnion(['inner', 'outer'], {
title:'Footer Position',
category: Category.Layout
title: 'Footer Position',
category: Category.Layout,
}),
simple: Type.Boolean({
title:'Simple',
category: Category.Style
title: 'Simple',
category: Category.Style,
}),
preview: Type.Boolean({
title:'Preview',
category: Category.Basic
})
title: 'Preview',
category: Category.Basic,
}),
};

View File

@ -1,37 +1,36 @@
import { Type } from "@sinclair/typebox";
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const InputPropsSpec = {
defaultValue: Type.String({
title:'Default Value',
category:Category.Basic,
weight: 0
title: 'Default Value',
category: Category.Basic,
weight: 0,
}),
placeholder: Type.String({
title:'Placeholder',
category:Category.Basic,
weight: 1
title: 'Placeholder',
category: Category.Basic,
weight: 1,
}),
allowClear: Type.Boolean({
title:'Allow Clear',
category:Category.Basic,
title: 'Allow Clear',
category: Category.Basic,
}),
disabled: Type.Boolean({
title:'Disabled',
category:Category.Basic,
title: 'Disabled',
category: Category.Basic,
}),
readOnly: Type.Boolean({
title:'Read Only',
category:Category.Basic,
title: 'Read Only',
category: Category.Basic,
}),
error: Type.Boolean({
title:'Error',
category:Category.Basic,
title: 'Error',
category: Category.Basic,
}),
size: StringUnion(['default', 'mini', 'small', 'large'], {
title:'Size',
category: Category.Style
title: 'Size',
category: Category.Style,
}),
};

View File

@ -1,26 +1,25 @@
import { Type } from "@sinclair/typebox";
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const SiderPropsSpec = {
theme: StringUnion(['dark', 'light'],{
category:Category.Style
theme: StringUnion(['dark', 'light'], {
category: Category.Style,
}),
collapsed: Type.Boolean({
category:Category.Style
category: Category.Style,
}),
collapsible: Type.Boolean({
category:Category.Style
category: Category.Style,
}),
collapsedWidth: Type.Number({
category:Category.Style
category: Category.Style,
}),
reverseArrow: Type.Boolean({
category:Category.Style
category: Category.Style,
}),
breakpoint: StringUnion(['xxl', 'xl', 'lg', 'md', 'sm', 'xs'], {
Description: 'Breakpoint in responsive layout',
category: Category.Layout,
}),
breakpoint: StringUnion(['xxl', 'xl', 'lg', 'md', 'sm', 'xs'],{
Description:'Breakpoint in responsive layout',
category:Category.Layout
})
};

View File

@ -1,29 +1,28 @@
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const LinkPropsSpec = {
href: Type.String({
title:'Href',
category: Category.Basic,
weight: 2
}),
content: Type.String({
title:'Content',
category: Category.Basic,
weight: 1
}),
hoverable: Type.Boolean({
title:'Hoverable',
category: Category.Style
}),
status: StringUnion(['success', 'warning', 'error'], {
title:'Status',
category: Category.Style
}),
disabled: Type.Boolean({
title:'Disabled',
category: Category.Basic
}),
}
href: Type.String({
title: 'Href',
category: Category.Basic,
weight: 2,
}),
content: Type.String({
title: 'Content',
category: Category.Basic,
weight: 1,
}),
hoverable: Type.Boolean({
title: 'Hoverable',
category: Category.Style,
}),
status: StringUnion(['success', 'warning', 'error'], {
title: 'Status',
category: Category.Style,
}),
disabled: Type.Boolean({
title: 'Disabled',
category: Category.Basic,
}),
};

View File

@ -1,43 +1,41 @@
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const ModalPropsSpec = {
title: Type.String({
title:'Title',
category:Category.Basic,
weight:10
}),
mask: Type.Boolean({
'title':'Mask',
category: Category.Style
}),
simple: Type.Boolean({
title:'Simple',
category: Category.Style
}),
okText: Type.String({
title:'Ok Text',
category:Category.Basic,
weight:2
}),
cancelText: Type.String({
title:'Cancel Text',
category:Category.Basic,
weight:1
}),
closable: Type.Boolean({
title:'Closable',
category:Category.Basic,
}),
maskClosable: Type.Boolean({
title:'Mask Closable',
description:'Whether enable click mask to close Modal',
category:Category.Basic,
}),
confirmLoading: Type.Boolean({
title:'Confirm Loading',
category: Category.Basic
}),
}
title: Type.String({
title: 'Title',
category: Category.Basic,
weight: 10,
}),
mask: Type.Boolean({
title: 'Mask',
category: Category.Style,
}),
simple: Type.Boolean({
title: 'Simple',
category: Category.Style,
}),
okText: Type.String({
title: 'Ok Text',
category: Category.Basic,
weight: 2,
}),
cancelText: Type.String({
title: 'Cancel Text',
category: Category.Basic,
weight: 1,
}),
closable: Type.Boolean({
title: 'Closable',
category: Category.Basic,
}),
maskClosable: Type.Boolean({
title: 'Mask Closable',
description: 'Whether enable click mask to close Modal',
category: Category.Basic,
}),
confirmLoading: Type.Boolean({
title: 'Confirm Loading',
category: Category.Basic,
}),
};

View File

@ -1,44 +1,43 @@
import { Type } from "@sinclair/typebox";
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const PaginationPropsSpec = {
pageSize: Type.Number({
title:'Page Size',
category:Category.Basic,
title: 'Page Size',
category: Category.Basic,
}),
total: Type.Number({
title:'Total',
category:Category.Basic,
title: 'Total',
category: Category.Basic,
}),
defaultCurrent: Type.Number({
title:'Current Page',
category:Category.Basic,
title: 'Current Page',
category: Category.Basic,
}),
disabled: Type.Boolean({
title:'Disabled',
category:Category.Basic,
title: 'Disabled',
category: Category.Basic,
}),
hideOnSinglePage: Type.Boolean({
title:'Hide On Single Page',
category:Category.Basic
title: 'Hide On Single Page',
category: Category.Basic,
}),
size: StringUnion(['mini', 'small', 'default', 'large'], {
title:'Size',
category: Category.Style
title: 'Size',
category: Category.Style,
}),
sizeCanChange: Type.Boolean({
title:'Size Can Change',
category:Category.Basic,
title: 'Size Can Change',
category: Category.Basic,
}),
simple: Type.Boolean({
title:'Simple',
category: Category.Basic
title: 'Simple',
category: Category.Basic,
}),
showJumper: Type.Boolean({
title:'Show Jumper',
category:Category.Basic,
description: 'Whether to display quick jump'
title: 'Show Jumper',
category: Category.Basic,
description: 'Whether to display quick jump',
}),
};

View File

@ -1,13 +1,12 @@
import { Type } from "@sinclair/typebox";
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const PasswordInputPropsSpec = {
placeholder: Type.String({
title: 'Placeholder',
category: Category.Basic,
weight: 1
weight: 1,
}),
disabled: Type.Boolean({
title: 'Disabled',
@ -15,15 +14,15 @@ export const PasswordInputPropsSpec = {
}),
size: StringUnion(['default', 'mini', 'small', 'large'], {
title: 'Size',
category: Category.Style
category: Category.Style,
}),
visibilityToggle: Type.Boolean({
title: 'Visibility Toggle',
description: 'Show a toggle to make the password text visible',
category:Category.Basic
category: Category.Basic,
}),
error: Type.Boolean({
title:'Error',
category:Category.Basic,
title: 'Error',
category: Category.Basic,
}),
};

View File

@ -1,32 +1,33 @@
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const PopoverPropsSpec = {
title: Type.String({
title:'Title',
category: Category.Basic,
}),
trigger: StringUnion(["click", "hover", "focus", "contextMenu"], {
title:'Trigger',
category: Category.Basic,
}),
disabled: Type.Boolean({
title:'Disabled',
category: Category.Basic,
}),
color: Type.String({
title:'Color',
category: Category.Style
}),
position: StringUnion(['top', 'tl', 'tr', 'bottom', 'bl', 'br', 'left', 'lt', 'lb', 'right', 'rt', 'rb'], {
title:'Position',
category: Category.Layout
}),
controlled: Type.Boolean({
title:'Controlled',
category: Category.Basic,
})
}
title: Type.String({
title: 'Title',
category: Category.Basic,
}),
trigger: StringUnion(['click', 'hover', 'focus', 'contextMenu'], {
title: 'Trigger',
category: Category.Basic,
}),
disabled: Type.Boolean({
title: 'Disabled',
category: Category.Basic,
}),
color: Type.String({
title: 'Color',
category: Category.Style,
}),
position: StringUnion(
['top', 'tl', 'tr', 'bottom', 'bl', 'br', 'left', 'lt', 'lb', 'right', 'rt', 'rb'],
{
title: 'Position',
category: Category.Layout,
}
),
controlled: Type.Boolean({
title: 'Controlled',
category: Category.Basic,
}),
};

View File

@ -1,41 +1,39 @@
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const ProgressPropsSpec = {
percent: Type.Number({
title:'Percent',
category:Category.Basic
}),
type: StringUnion(['line', 'circle'],{
title:'Type',
category:Category.Style
}),
status: StringUnion(['success', 'error', 'normal', 'warning'],{
title:'Status',
category:Category.Style
}),
color: Type.String({
title:'Color',
category:Category.Style,
description:"Please input a color name such as 'red' or a color code such as '#c10'"
}),
trailColor:Type.String({
title:'Trail Color',
category:Category.Style
}),
showText:Type.Boolean({
title:'Show Text',
category:Category.Basic
}),
width:Type.Number({
title:'Width',
category:Category.Style
}),
size:StringUnion(['small' , 'default' , 'mini' , 'large'],{
title:'Size',
category:Category.Style
}),
}
percent: Type.Number({
title: 'Percent',
category: Category.Basic,
}),
type: StringUnion(['line', 'circle'], {
title: 'Type',
category: Category.Style,
}),
status: StringUnion(['success', 'error', 'normal', 'warning'], {
title: 'Status',
category: Category.Style,
}),
color: Type.String({
title: 'Color',
category: Category.Style,
description: "Please input a color name such as 'red' or a color code such as '#c10'",
}),
trailColor: Type.String({
title: 'Trail Color',
category: Category.Style,
}),
showText: Type.Boolean({
title: 'Show Text',
category: Category.Basic,
}),
width: Type.Number({
title: 'Width',
category: Category.Style,
}),
size: StringUnion(['small', 'default', 'mini', 'large'], {
title: 'Size',
category: Category.Style,
}),
};

View File

@ -1,7 +1,6 @@
import { Type } from "@sinclair/typebox";
import { StringUnion } from "../../sunmao-helper";
import { Category } from '../../constants/category'
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category';
export const SkeletonTextPropsSpec = {
rows: Type.Number(),
@ -9,37 +8,35 @@ export const SkeletonTextPropsSpec = {
Type.Union([
Type.Number(),
Type.String(),
Type.Array(
Type.Union([Type.Union([Type.Number()]), Type.Union([Type.String()])])
),
Type.Array(Type.Union([Type.Union([Type.Number()]), Type.Union([Type.String()])])),
])
),
};
export const SkeletonImagePropsSpec = {
shape: StringUnion(["circle", "square"]),
size: StringUnion(["small", "default", "large"]),
position: StringUnion(["left", "right"]),
shape: StringUnion(['circle', 'square']),
size: StringUnion(['small', 'default', 'large']),
position: StringUnion(['left', 'right']),
};
export const SkeletonPropsSpec = {
animation: Type.Boolean({
title:'Animation',
category:Category.Basic
title: 'Animation',
category: Category.Basic,
}),
loading: Type.Boolean({
title:'Loading',
category:Category.Basic
title: 'Loading',
category: Category.Basic,
}),
// TODO remove union type
image: Type.Union([Type.Boolean(), Type.Object(SkeletonImagePropsSpec)],{
title:'Image Placeholder',
description:'Whether to show the picture placeholder',
category:Category.Basic
image: Type.Union([Type.Boolean(), Type.Object(SkeletonImagePropsSpec)], {
title: 'Image Placeholder',
description: 'Whether to show the picture placeholder',
category: Category.Basic,
}),
text: Type.Union([Type.Boolean(), Type.Object(SkeletonTextPropsSpec)], {
title: 'Text Placeholder',
description: 'Whether to show text placeholder',
category: Category.Basic,
}),
text: Type.Union([Type.Boolean(), Type.Object(SkeletonTextPropsSpec)],{
title:'Text Placeholder',
description:'Whether to show text placeholder',
category:Category.Basic
})
};

View File

@ -1,22 +1,21 @@
import { Type } from "@sinclair/typebox";
import { Category } from "../../constants/category";
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const SpacePropsSpec = {
align: StringUnion(['start', 'end', 'center', 'baseline'], {
category: Category.Layout
category: Category.Layout,
}),
direction: StringUnion(['vertical', 'horizontal'], {
category: Category.Layout
category: Category.Layout,
}),
wrap: Type.Boolean({
category: Category.Layout
}),
size: Type.Union([
Type.Optional(StringUnion(["mini", "small", "medium", "large"])),
Type.Number(),
],{
category: Category.Style
category: Category.Layout,
}),
size: Type.Union(
[Type.Optional(StringUnion(['mini', 'small', 'medium', 'large'])), Type.Number()],
{
category: Category.Style,
}
),
};

View File

@ -1,41 +1,40 @@
import { Type } from "@sinclair/typebox";
import { Category } from "../../constants/category";
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const StepItemSpec = Type.Object({
title: Type.String(),
description: Type.String()
})
description: Type.String(),
});
export const StepsPropsSpec = {
type: StringUnion(['default', 'arrow', 'dot', 'navigation'], {
title: 'Type',
category: Category.Basic
category: Category.Basic,
}),
current: Type.Number({
title: 'Current Step',
category: Category.Basic
category: Category.Basic,
}),
size: StringUnion(['default', 'small'], {
title: 'Size',
category: Category.Style
category: Category.Style,
}),
direction: StringUnion(['vertical', 'horizontal'], {
title: 'Direction',
category: Category.Layout
category: Category.Layout,
}),
status: StringUnion(['wait', 'process', 'finish', 'error'], {
title: 'Status',
category: Category.Style
category: Category.Style,
}),
lineless: Type.Boolean({
title: 'Lineless',
category: Category.Style
category: Category.Style,
}),
items: Type.Array(StepItemSpec, {
title: 'Items',
category: Category.Basic,
weight: 10
})
weight: 10,
}),
};

View File

@ -1,27 +1,26 @@
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const SwitchPropsSpec = {
defaultChecked:Type.Boolean({
title:'Default Checked',
category:Category.Basic,
}),
disabled: Type.Boolean({
title:'Disabled',
category:Category.Basic,
}),
type: StringUnion(['circle' , 'round' , 'line'],{
title:'Type',
category:Category.Style,
}),
size: StringUnion([ 'small', 'default'],{
title:'Size',
category:Category.Style,
}),
loading:Type.Boolean({
title:'Loading',
category:Category.Basic,
}),
}
defaultChecked: Type.Boolean({
title: 'Default Checked',
category: Category.Basic,
}),
disabled: Type.Boolean({
title: 'Disabled',
category: Category.Basic,
}),
type: StringUnion(['circle', 'round', 'line'], {
title: 'Type',
category: Category.Style,
}),
size: StringUnion(['small', 'default'], {
title: 'Size',
category: Category.Style,
}),
loading: Type.Boolean({
title: 'Loading',
category: Category.Basic,
}),
};

View File

@ -32,13 +32,18 @@ export const ColumnSpec = Type.Object({
category: Category.Basic,
description: 'The text you want to display instead of raw text.',
}),
width: Type.Optional(Type.Number({
title: 'Width',
})),
ellipsis:Type.Optional(Type.Boolean({
title:'Ellipsis',
description:'If the cell content exceeds the length, whether it is automatically omitted and displays ...,After setting this property, the table-layout of the table will automatically become fixed.'
})),
width: Type.Optional(
Type.Number({
title: 'Width',
})
),
ellipsis: Type.Optional(
Type.Boolean({
title: 'Ellipsis',
description:
'If the cell content exceeds the length, whether it is automatically omitted and displays ...,After setting this property, the table-layout of the table will automatically become fixed.',
})
),
sorter: Type.Boolean({
title: 'Enable Sort',
}),
@ -117,7 +122,7 @@ export const TablePropsSpec = Type.Object({
rowClick: Type.Boolean({
title: 'Row Click',
category: Category.Basic,
description: 'If on, the table can be selected without setting the rowSelectionType'
description: 'If on, the table can be selected without setting the rowSelectionType',
}),
loading: Type.Boolean({
title: 'Show Loading',

View File

@ -6,7 +6,7 @@ export const TabsPropsSpec = {
defaultActiveTab: Type.String({
title: 'Default Active Tab Index',
category: Category.Basic,
description: 'The index of default active Tab. Start with 0.'
description: 'The index of default active Tab. Start with 0.',
}),
tabNames: Type.Array(Type.String(), {
title: 'Tab Names',

View File

@ -1,36 +1,35 @@
import { Type } from "@sinclair/typebox";
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category'
import { Category } from '../../constants/category';
export const TextAreaPropsSpec = {
defaultValue: Type.String({
title: 'Default Value',
category: Category.Basic,
}),
placeholder: Type.String({
title: 'Placeholder',
category: Category.Basic,
}),
autoSize: Type.Boolean({
category: Category.Basic,
title: 'Auto Size',
}),
disabled: Type.Boolean({
title: 'Disabled',
category: Category.Basic,
}),
defaultValue: Type.String({
title: 'Default Value',
category: Category.Basic,
}),
placeholder: Type.String({
title: 'Placeholder',
category: Category.Basic,
}),
autoSize: Type.Boolean({
category: Category.Basic,
title: 'Auto Size',
}),
disabled: Type.Boolean({
title: 'Disabled',
category: Category.Basic,
}),
size: StringUnion(['default', 'mini', 'small', 'large'], {
title: 'Size',
category: Category.Style
}),
allowClear: Type.Boolean({
title: 'Allow Clear',
category: Category.Basic,
}),
error: Type.Boolean({
title: 'Error',
category: Category.Basic,
}),
size: StringUnion(['default', 'mini', 'small', 'large'], {
title: 'Size',
category: Category.Style,
}),
allowClear: Type.Boolean({
title: 'Allow Clear',
category: Category.Basic,
}),
error: Type.Boolean({
title: 'Error',
category: Category.Basic,
}),
};

View File

@ -2,33 +2,29 @@ import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
import { Category } from '../../constants/category';
export const TimelineItemPropsSpec = {
label: Type.String(),
content: Type.String(),
dotColor: Type.String(),
lineType: StringUnion(['solid', 'dashed', 'dotted']),
lineColor: Type.String(),
dotType: StringUnion(['hollow', 'solid'])
}
label: Type.String(),
content: Type.String(),
dotColor: Type.String(),
lineType: StringUnion(['solid', 'dashed', 'dotted']),
lineColor: Type.String(),
dotType: StringUnion(['hollow', 'solid']),
};
export const TimelinePropsSpec = {
items: Type.Array(Type.Object(
TimelineItemPropsSpec
),{
category:Category.Data
}),
reverse: Type.Boolean({
category:Category.Style
}),
direction: StringUnion(['horizontal', 'vertical'],{
category:Category.Style
}),
mode: StringUnion(['left', 'right', 'alternate'],{
category:Category.Style
}),
labelPosition: StringUnion(['relative', 'same'],{
category:Category.Style
}),
}
items: Type.Array(Type.Object(TimelineItemPropsSpec), {
category: Category.Data,
}),
reverse: Type.Boolean({
category: Category.Style,
}),
direction: StringUnion(['horizontal', 'vertical'], {
category: Category.Style,
}),
mode: StringUnion(['left', 'right', 'alternate'], {
category: Category.Style,
}),
labelPosition: StringUnion(['relative', 'same'], {
category: Category.Style,
}),
};

View File

@ -1,37 +1,39 @@
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const TooltipPropsSpec = {
color: Type.String({
title:'Color',
category: Category.Style
}),
position: StringUnion(['top', 'tl', 'tr', 'bottom', 'bl', 'br', 'left', 'lt', 'lb', 'right', 'rt', 'rb'], {
title:'Position',
category: Category.Layout
}),
mini: Type.Boolean({
title:'Mini',
category: Category.Style
}),
disabled: Type.Boolean({
title:'Disabled',
category: Category.Basic
}),
content: Type.String({
title:'Content',
category:Category.Basic,
weight: 100
}),
controlled: Type.Boolean({
title:'Controlled',
category: Category.Basic
}),
trigger: StringUnion(["click", "hover"],{
title:'Trigger',
category: Category.Basic,
weight:3
}),
}
color: Type.String({
title: 'Color',
category: Category.Style,
}),
position: StringUnion(
['top', 'tl', 'tr', 'bottom', 'bl', 'br', 'left', 'lt', 'lb', 'right', 'rt', 'rb'],
{
title: 'Position',
category: Category.Layout,
}
),
mini: Type.Boolean({
title: 'Mini',
category: Category.Style,
}),
disabled: Type.Boolean({
title: 'Disabled',
category: Category.Basic,
}),
content: Type.String({
title: 'Content',
category: Category.Basic,
weight: 100,
}),
controlled: Type.Boolean({
title: 'Controlled',
category: Category.Basic,
}),
trigger: StringUnion(['click', 'hover'], {
title: 'Trigger',
category: Category.Basic,
weight: 3,
}),
};

View File

@ -1,6 +1,6 @@
import { Type } from "@sinclair/typebox";
import { Category } from "../../constants/category";
import { StringUnion } from "../../sunmao-helper";
import { Type } from '@sinclair/typebox';
import { Category } from '../../constants/category';
import { StringUnion } from '../../sunmao-helper';
export const TreeNodeSpec = Type.Object({
title: Type.String(),
@ -8,24 +8,24 @@ export const TreeNodeSpec = Type.Object({
children: Type.Optional(Type.Array(Type.Any())),
selectable: Type.Optional(Type.Boolean()),
checkable: Type.Optional(Type.Boolean()),
path:Type.Optional(Type.Array(Type.String()))
path: Type.Optional(Type.Array(Type.String())),
});
export const TreePropsSpec = Type.Object({
data: Type.Array(TreeNodeSpec, {
category: Category.Data,
title: "Tree Data",
title: 'Tree Data',
}),
size: StringUnion(["mini", "small", "medium", "large"], {
size: StringUnion(['mini', 'small', 'medium', 'large'], {
category: Category.Style,
title: "Size",
title: 'Size',
}),
multiple: Type.Boolean({
category: Category.Basic,
title: "Multiple Select",
title: 'Multiple Select',
}),
autoExpandParent: Type.Boolean({
category: Category.Basic,
title: "Auto Expand Node",
title: 'Auto Expand Node',
}),
});

View File

@ -1 +1 @@
export { ArcoDesignLib } from "./lib";
export { ArcoDesignLib } from './lib';

View File

@ -1,8 +1,8 @@
// move to @sunmao-ui/runtime in the future?
import { ComponentMetadata } from "@sunmao-ui/core/lib/metadata";
import { ComponentImplProps } from "@sunmao-ui/runtime";
import { TLiteral, Type } from "@sinclair/typebox";
import { ComponentMetadata } from '@sunmao-ui/core/lib/metadata';
import { ComponentImplProps } from '@sunmao-ui/runtime';
import { TLiteral, Type } from '@sinclair/typebox';
export type IntoStringUnion<T> = {
[K in keyof T]: T[K] extends string ? TLiteral<T[K]> : never;
@ -15,19 +15,15 @@ export function StringUnion<T extends string[]>(values: [...T], options?: any) {
prev[cur] = Type.Boolean();
return prev;
}, {} as Record<T[number], any>)
), {
title: options?.title,
description: options?.description,
category: options?.category,
weight: options?.weight
}
),
options
);
}
export const FALLBACK_METADATA: ComponentMetadata = {
name: "",
description: "",
displayName: "",
name: '',
description: '',
displayName: '',
isDraggable: true,
isResizable: true,
exampleProperties: {},

View File

@ -14,27 +14,20 @@ const PropsSpec = Type.Object({
listData: Type.Array(Type.Record(Type.String(), Type.String()), {
title: 'Data',
category: BASIC,
widget: 'core/v1/Expression'
}),
template: ModuleSpec,
});
const exampleProperties = {
listData: [
{
id: '1',
name: 'Bowen Tan',
},
],
listData: [{ id: '1' }, { id: '2' }, { id: '3' }],
template: {
id: 'listItemName-{{$listItem.id}}',
type: 'core/v1/text',
type: 'custom/v1/myModule0',
properties: {
value: {
raw: 'Name{{$listItem.name}}',
format: 'plain',
},
value: '{{$listItem.id}}',
},
traits: [],
handlers: [],
},
};

View File

@ -7,34 +7,36 @@ import {
LIST_ITEM_INDEX_EXP,
ModuleRenderer,
UIServices,
ExpressionError
ExpressionError,
} from '@sunmao-ui/runtime';
export const TableTd: React.FC<{
index: number;
item: any;
column: Static<typeof ColumnSpec>;
rawColumn: Static<typeof ColumnsPropertySpec>[0]
rawColumn: Static<typeof ColumnsPropertySpec>[0];
onClickItem: () => void;
services: UIServices;
app?: RuntimeApplication;
}> = props => {
const { item, index, column, rawColumn, onClickItem, services, app } = props;
const evalOptions = {
evalListItem: true,
scopeObject: {
[LIST_ITEM_EXP]: item,
},
};
let value = item[column.key];
let buttonConfig = column.buttonConfig;
if (column.displayValue) {
const result = services.stateManager.maskedEval(column.displayValue, true, {
[LIST_ITEM_EXP]: item,
});
const result = services.stateManager.maskedEval(column.displayValue, evalOptions);
value = result instanceof ExpressionError ? '' : result;
}
if (column.buttonConfig) {
buttonConfig = services.stateManager.deepEval(column.buttonConfig, true, {
[LIST_ITEM_EXP]: item,
});
buttonConfig = services.stateManager.deepEval(column.buttonConfig, evalOptions);
}
let content = value;
@ -57,9 +59,7 @@ export const TableTd: React.FC<{
const onClick = () => {
onClickItem();
rawColumn.buttonConfig.handlers.forEach(handler => {
const evaledHandler = services.stateManager.deepEval(handler, true, {
[LIST_ITEM_EXP]: item,
});
const evaledHandler = services.stateManager.deepEval(handler, evalOptions);
services.apiService.send('uiMethod', {
componentId: evaledHandler.componentId,
name: evaledHandler.method.name,

View File

@ -1,7 +1,6 @@
import { JSONSchema7Object } from 'json-schema';
import { parseVersion } from './version';
import { parseVersion, Version } from './version';
import { Metadata } from './metadata';
import { Version } from './version';
import { ComponentSchema } from './application';
// spec

View File

@ -45,7 +45,7 @@ export const ArrayTable: React.FC<Props> = props => {
<Th width="24px" />
{keys.map((key: string) => {
const propertySpec = itemSpec.properties?.[key];
const title = isJSONSchema(propertySpec) ? propertySpec.title : key;
const title = isJSONSchema(propertySpec) ? (propertySpec.title || key) : key;
return <Th key={key}>{title}</Th>;
})}

View File

@ -155,7 +155,8 @@ export const ExpressionWidget: React.FC<
const evalCode = useCallback(
(code: string) => {
try {
const result = services.stateManager.maskedEval(getParsedValue(code, type));
const value = getParsedValue(code, type);
const result = isExpression(code) ? services.stateManager.maskedEval(value) : value;
if (result instanceof ExpressionError) {
throw result;

View File

@ -18,6 +18,7 @@ import {
import { Static, Type } from '@sinclair/typebox';
import { EditorServices } from '../../../types';
import { ComponentSchema } from '@sunmao-ui/core';
import { SpecWidget } from '@sunmao-ui/editor-sdk';
type Values = Static<typeof FetchTraitPropertiesSpec>;
type EventHandler = Static<typeof EventCallBackHandlerSpec>;
@ -93,8 +94,14 @@ const Handler = (props: HandlerProps) => {
);
};
const DisabledSpec = Type.Boolean({
widgetOptions: { isShowAsideExpressionButton: true },
});
const EmptyArray: string[] = [];
export const Basic: React.FC<Props> = props => {
const { formik } = props;
const { formik, api, services } = props;
const onAddHandler = (type: HandlerType) => {
const newHandler: EventHandler = {
@ -113,6 +120,14 @@ export const Basic: React.FC<Props> = props => {
formik.setFieldValue(type, [...(formik.values[type] || []), newHandler]);
};
const onDisabledChange = useCallback(
val => {
formik.setFieldValue('disabled', val);
formik.handleSubmit();
},
[formik]
);
const generateHandlers = (type: HandlerType) => (
<FormControl>
<HStack width="full" alignItems="center" mb={0}>
@ -145,6 +160,21 @@ export const Basic: React.FC<Props> = props => {
onBlur={() => formik.handleSubmit()}
/>
</FormControl>
<FormControl display="flex" alignItems="center">
<FormLabel margin="0" marginRight="2">
Disabled
</FormLabel>
<SpecWidget
component={api}
spec={DisabledSpec}
value={formik.values.disabled}
path={EmptyArray}
level={1}
services={services}
onChange={onDisabledChange}
/>
</FormControl>
{generateHandlers('onComplete')}
{generateHandlers('onError')}
</VStack>

View File

@ -21,11 +21,12 @@ import { ComponentForm } from './ComponentForm';
import ErrorBoundary from './ErrorBoundary';
import { PreviewModal } from './PreviewModal';
import { WarningArea } from './WarningArea';
import { EditorServices } from '../types';
import { EditorServices, UIPros } from '../types';
import { css } from '@emotion/css';
import { EditorMaskWrapper } from './EditorMaskWrapper';
import { AppModel } from '../AppModel/AppModel';
import { LocalStorageForm } from './DataSource/LocalStorageForm';
import { Explorer } from './Explorer';
import { Resizable } from 're-resizable';
type ReturnOfInit = ReturnType<typeof initSunmaoUI>;
@ -38,6 +39,7 @@ type Props = {
services: EditorServices;
libs: SunmaoLib[];
onRefresh: () => void;
uiProps: UIPros;
};
const ApiFormStyle = css`
@ -50,7 +52,7 @@ const ApiFormStyle = css`
`;
export const Editor: React.FC<Props> = observer(
({ App, registry, stateStore, services, libs, onRefresh: onRefreshApp }) => {
({ App, registry, stateStore, services, libs, uiProps, onRefresh: onRefreshApp }) => {
const { eventBus, editorStore } = services;
const {
components,
@ -228,6 +230,7 @@ export const Editor: React.FC<Props> = observer(
display="flex"
flexDirection="column"
textAlign="left"
lazyBehavior={uiProps.explorerMenuLazyBehavior}
isLazy
index={explorerMenuTab}
onChange={activatedTab => {
@ -235,15 +238,15 @@ export const Editor: React.FC<Props> = observer(
}}
>
<TabList background="gray.50" whiteSpace="nowrap" justifyContent="center">
{/* <Tab>Explorer</Tab> */}
<Tab>Explorer</Tab>
<Tab>UI</Tab>
<Tab>Data</Tab>
<Tab>State</Tab>
</TabList>
<TabPanels flex="1" overflow="auto">
{/* <TabPanel>
<Explorer services={services} />
</TabPanel> */}
<TabPanel p={0}>
<Explorer services={services} />
</TabPanel>
<TabPanel p={0}>
<StructureTree
components={components}

View File

@ -3,6 +3,7 @@ import ErrorBoundary from '../ErrorBoundary';
import { ExplorerForm } from './ExplorerForm/ExplorerForm';
import { ExplorerTree } from './ExplorerTree';
import { EditorServices } from '../../types';
import { Box } from '@chakra-ui/react';
type Props = {
services: EditorServices;
@ -25,21 +26,25 @@ export const Explorer: React.FC<Props> = ({ services }) => {
if (isEditingMode) {
return (
<ErrorBoundary>
<ExplorerForm
formType={formType}
version={currentVersion}
name={currentName}
setCurrentVersion={setCurrentVersion}
setCurrentName={setCurrentName}
onBack={onBack}
services={services}
/>
<Box padding={4}>
<ExplorerForm
formType={formType}
version={currentVersion}
name={currentName}
setCurrentVersion={setCurrentVersion}
setCurrentName={setCurrentName}
onBack={onBack}
services={services}
/>
</Box>
</ErrorBoundary>
);
}
return (
<ErrorBoundary>
<ExplorerTree onEdit={onEdit} services={services} />
<Box padding={4}>
<ExplorerTree onEdit={onEdit} services={services} />
</Box>
</ErrorBoundary>
);
};

View File

@ -15,7 +15,7 @@ import {
} from '@chakra-ui/react';
import { initEventBus } from './services/eventBus';
import { EditorStore } from './services/EditorStore';
import { StorageHandler } from './types';
import { StorageHandler, UIPros } from './types';
import { AppStorage } from './services/AppStorage';
import { Application, Module } from '@sunmao-ui/core';
import './styles.css';
@ -27,6 +27,7 @@ type SunmaoUIEditorProps = {
storageHandler?: StorageHandler;
defaultApplication?: Application;
defaultModules?: Module[];
uiProps?: UIPros;
};
export function initSunmaoUIEditor(props: SunmaoUIEditorProps = {}) {
@ -110,6 +111,7 @@ export function initSunmaoUIEditor(props: SunmaoUIEditorProps = {}) {
services={services}
libs={props.libs || []}
onRefresh={onRefresh}
uiProps={props.uiProps||{}}
/>
</ChakraProvider>
);

View File

@ -28,6 +28,9 @@ const { Editor, registry } = initSunmaoUIEditor({
},
defaultApplication: lsManager.getAppFromLS(),
defaultModules: lsManager.getModulesFromLS(),
uiProps: {
explorerMenuLazyBehavior: 'keepMounted',
},
});
export default function renderApp(options: Options = {}) {

View File

@ -2,12 +2,14 @@ import { observable, makeObservable, action, toJS } from 'mobx';
import { Application, ComponentSchema, Module, RuntimeModule } from '@sunmao-ui/core';
import { produce } from 'immer';
import { DefaultNewModule, EmptyAppSchema } from '../constants';
import { addModuleId } from '../utils/addModuleId';
import { addModuleId, removeModuleId } from '../utils/addModuleId';
import { StorageHandler } from '../types';
export class AppStorage {
app: Application;
modules: Module[];
// modules that have {{$moduleId}}__
rawModules: Module[];
static AppLSKey = 'schema';
static ModulesLSKey = 'modules';
@ -17,20 +19,23 @@ export class AppStorage {
private storageHandler?: StorageHandler
) {
this.app = defaultApplication || EmptyAppSchema;
this.modules = defaultModules || [];
this.modules = defaultModules?.map(removeModuleId) || [];
this.rawModules = defaultModules || [];
makeObservable(this, {
app: observable.shallow,
modules: observable.shallow,
rawModules: observable.shallow,
setApp: action,
setModules: action,
setRawModules: action,
});
}
createModule() {
let index = this.modules.length;
this.modules.forEach((module) => {
this.modules.forEach(module => {
if (module.metadata.name === `myModule${index}`) {
index++;
}
@ -46,10 +51,11 @@ export class AppStorage {
metadata: {
...DefaultNewModule.metadata,
name,
}
},
};
this.setModules([...this.modules, newModule]);
this.setRawModules(this.modules.map(addModuleId));
this.saveModules();
}
@ -59,6 +65,7 @@ export class AppStorage {
({ version, metadata: { name } }) => version !== v || name !== n
)
);
this.setRawModules(this.modules.map(addModuleId));
this.saveModules();
}
@ -84,6 +91,8 @@ export class AppStorage {
draft[i].impl = components;
});
this.setModules(newModules);
const rawModules = newModules.map(addModuleId);
this.setRawModules(rawModules);
this.saveModules();
break;
}
@ -118,7 +127,10 @@ export class AppStorage {
draft[i].spec.stateMap = stateMap;
draft[i].version = version;
});
this.setModules(newModules);
const rawModules = newModules.map(addModuleId);
this.setRawModules(rawModules);
this.saveModules();
}
@ -127,8 +139,9 @@ export class AppStorage {
}
private saveModules() {
const modules = this.modules.map(addModuleId);
this.storageHandler?.onSaveModules && this.storageHandler?.onSaveModules(modules);
// save rawModules rather than modules because rawModules have {{$moduleId}}__
this.storageHandler?.onSaveModules &&
this.storageHandler?.onSaveModules(this.rawModules);
}
setApp(app: Application) {
@ -138,4 +151,8 @@ export class AppStorage {
setModules(modules: Module[]) {
this.modules = modules;
}
setRawModules(modules: Module[]) {
this.rawModules = modules;
}
}

View File

@ -5,7 +5,6 @@ import { Registry, StateManager } from '@sunmao-ui/runtime';
import { EventBusType } from './eventBus';
import { AppStorage } from './AppStorage';
import { SchemaValidator } from '../validator';
import { removeModuleId } from '../utils/addModuleId';
import { DataSourceType } from '../components/DataSource';
import { genOperation } from '../operations';
import { ExplorerMenuTabs, ToolMenuTabs } from '../constants/enum';
@ -27,7 +26,7 @@ enum DataSourceName {
LOCALSTORAGE = 'localStorage',
}
type DataSourceId = `${DataSourceName}${number}`
type DataSourceId = `${DataSourceName}${number}`;
export class EditorStore {
components: ComponentSchema[] = [];
// currentEditingComponents, it could be app's or module's components
@ -93,7 +92,11 @@ export class EditorStore {
this.eventBus.send('componentsRefresh', this.originComponents);
this.setComponents(this.originComponents);
if (this.APICount === -1 || this.stateCount === -1 || this.localStorageCount === -1) {
if (
this.APICount === -1 ||
this.stateCount === -1 ||
this.localStorageCount === -1
) {
this.initDataSourceCount();
}
}
@ -122,6 +125,10 @@ export class EditorStore {
return this.appStorage.modules;
}
get rawModules() {
return this.appStorage.rawModules;
}
get selectedComponent() {
return this.components.find(c => c.id === this._selectedComponentId);
}
@ -153,10 +160,7 @@ export class EditorStore {
m.version === this.currentEditingTarget.version &&
m.metadata.name === this.currentEditingTarget.name
);
if (module) {
return removeModuleId(module).impl;
}
return [];
return module?.impl || [];
case 'app':
return this.app.spec.components;
}
@ -189,8 +193,11 @@ export class EditorStore {
clearSunmaoGlobalState() {
this.stateManager.clear();
// reregister all modules
this.modules.forEach(m => {
this.setSelectedComponentId('');
// Remove old modules and re-register all modules,
this.registry.unregisterAllModules();
this.rawModules.forEach(m => {
const modules = createModule(m);
this.registry.registerModule(modules, true);
});
@ -258,7 +265,11 @@ export class EditorStore {
const { apis, states, localStorages } = this.dataSources;
let id: DataSourceId;
const getCount = (dataSource: ComponentSchema[], dataSourceName: DataSourceName, count: number): number => {
const getCount = (
dataSource: ComponentSchema[],
dataSourceName: DataSourceName,
count: number
): number => {
const ids = dataSource.map(({ id }) => id);
let id: DataSourceId = `${dataSourceName}${count}`;
while (ids.includes(id)) {
@ -277,7 +288,11 @@ export class EditorStore {
id = `state${this.stateCount}`;
break;
case DataSourceType.LOCALSTORAGE:
this.localStorageCount = getCount(localStorages, DataSourceName.LOCALSTORAGE, this.localStorageCount);
this.localStorageCount = getCount(
localStorages,
DataSourceName.LOCALSTORAGE,
this.localStorageCount
);
id = `localStorage${this.localStorageCount}`;
break;
}

View File

@ -22,3 +22,7 @@ export type StorageHandler = {
onSaveApp?: (app: Application) => void;
onSaveModules?: (module: Module[]) => void;
};
export type UIPros = {
explorerMenuLazyBehavior?: 'keepMounted' | 'unmount'
}

View File

@ -1,4 +1,8 @@
import { StateManager, parseExpression, ExpressionError } from '../src/services/StateManager';
import {
StateManager,
parseExpression,
ExpressionError,
} from '../src/services/StateManager';
describe('parseExpression function', () => {
it('can parse {{}} expression', () => {
@ -79,44 +83,78 @@ describe('evalExpression function', () => {
value: 'ok',
},
};
const stateStore = new StateManager();
const stateManager = new StateManager();
it('can eval {{}} expression', () => {
expect(stateStore.maskedEval('value', false, scope)).toEqual('value');
expect(stateStore.maskedEval('{{true}}', false, scope)).toEqual(true);
expect(stateStore.maskedEval('{{ false }}', false, scope)).toEqual(false);
expect(stateStore.maskedEval('{{[]}}', false, scope)).toEqual([]);
expect(stateStore.maskedEval('{{ [] }}', false, scope)).toEqual([]);
expect(stateStore.maskedEval('{{ [1,2,3] }}', false, scope)).toEqual([1, 2, 3]);
const evalOptions = { evalListItem: false, scopeObject: scope };
expect(stateStore.maskedEval('{{ {} }}', false, scope)).toEqual({});
expect(stateStore.maskedEval('{{ {id: 123} }}', false, scope)).toEqual({ id: 123 });
expect(stateStore.maskedEval('{{nothing}}', false, scope) instanceof ExpressionError).toEqual(true);
expect(stateManager.maskedEval('value', evalOptions)).toEqual('value');
expect(stateManager.maskedEval('{{true}}', evalOptions)).toEqual(true);
expect(stateManager.maskedEval('{{ false }}', evalOptions)).toEqual(false);
expect(stateManager.maskedEval('{{[]}}', evalOptions)).toEqual([]);
expect(stateManager.maskedEval('{{ [] }}', evalOptions)).toEqual([]);
expect(stateManager.maskedEval('{{ [1,2,3] }}', evalOptions)).toEqual([1, 2, 3]);
expect(stateStore.maskedEval('{{input1.value}}', false, scope)).toEqual('world');
expect(stateStore.maskedEval('{{checkbox.value}}', false, scope)).toEqual(true);
expect(stateStore.maskedEval('{{fetch.data}}', false, scope)).toMatchObject([
expect(stateManager.maskedEval('{{ {} }}', evalOptions)).toEqual({});
expect(stateManager.maskedEval('{{ {id: 123} }}', evalOptions)).toEqual({ id: 123 });
expect(stateManager.maskedEval('{{nothing}}', evalOptions)).toBeInstanceOf(
ExpressionError
);
expect(stateManager.maskedEval('{{input1.value}}', evalOptions)).toEqual('world');
expect(stateManager.maskedEval('{{checkbox.value}}', evalOptions)).toEqual(true);
expect(stateManager.maskedEval('{{fetch.data}}', evalOptions)).toMatchObject([
{ id: 1 },
{ id: 2 },
]);
expect(stateStore.maskedEval('{{{{}}}}', false, scope)).toEqual(undefined);
expect(stateManager.maskedEval('{{{{}}}}', evalOptions)).toEqual(undefined);
expect(
stateStore.maskedEval('{{ value }}, {{ input1.value }}!', false, scope)
stateManager.maskedEval('{{ value }}, {{ input1.value }}!', evalOptions)
).toEqual('Hello, world!');
});
it('can eval $listItem expression', () => {
expect(stateStore.maskedEval('{{ $listItem.value }}', false, scope)).toEqual(
'{{ $listItem.value }}'
);
expect(stateStore.maskedEval('{{ $listItem.value }}', true, scope)).toEqual('foo');
expect(
stateStore.maskedEval(
stateManager.maskedEval('{{ $listItem.value }}', {
evalListItem: false,
scopeObject: scope,
})
).toEqual('{{ $listItem.value }}');
expect(
stateManager.maskedEval('{{ $listItem.value }}', {
evalListItem: true,
scopeObject: scope,
})
).toEqual('foo');
expect(
stateManager.maskedEval(
'{{ {{$listItem.value}}Input.value + {{$moduleId}}Fetch.value }}!',
true,
scope
{ evalListItem: true, scopeObject: scope }
)
).toEqual('Yes, ok!');
});
it('can override scope', () => {
expect(
stateManager.maskedEval('{{value}}', {
scopeObject: { override: 'foo' },
overrideScope: true,
})
).toBeInstanceOf(ExpressionError);
expect(
stateManager.maskedEval('{{override}}', {
scopeObject: { override: 'foo' },
overrideScope: true,
})
).toEqual('foo');
});
it('can fallback to specific value when error', () => {
expect(
stateManager.maskedEval('{{wrongExp}}', {
fallbackWhenError: exp => exp,
})
).toEqual('{{wrongExp}}');
});
});

View File

@ -51,6 +51,7 @@ export const App: React.FC<AppProps> = props => {
app={app}
gridCallbacks={gridCallbacks}
hooks={hooks}
isInModule={false}
/>
);
})}

View File

@ -1,13 +1,12 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { merge } from 'lodash-es';
import { RuntimeComponentSchema, RuntimeTraitSchema } from '@sunmao-ui/core';
import { ExpressionError } from '../../services/StateManager';
import { watch } from '../../utils/watchReactivity';
import { ImplWrapperProps, TraitResult } from '../../types';
import { shallowCompareArray } from '../../utils/shallowCompareArray';
const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props, ref) => {
const { component: c, app, children, services, childrenMap, hooks } = props;
const { component: c, app, children, services, childrenMap, hooks, isInModule } = props;
const { registry, stateManager, globalHandlerMap, apiService, eleMap } = props.services;
const childrenCache = new Map<RuntimeComponentSchema, React.ReactElement>();
@ -20,18 +19,24 @@ const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props,
const handlerMap = useRef(globalHandlerMap.get(c.id)!);
const eleRef = useRef<HTMLElement>();
const onRef = (ele: HTMLElement) => {
eleMap.set(c.id, ele);
// If a component is in module, it should not have mask, so we needn't set it
if (!isInModule) {
eleMap.set(c.id, ele);
}
hooks?.didDomUpdate && hooks?.didDomUpdate();
};
useEffect(() => {
if (eleRef.current) {
// If a component is in module, it should not have mask, so we needn't set it
if (eleRef.current && !isInModule) {
eleMap.set(c.id, eleRef.current);
}
return () => {
eleMap.delete(c.id);
if (!isInModule) {
eleMap.delete(c.id);
}
};
}, [c.id, eleMap]);
}, [c.id, eleMap, isInModule]);
useEffect(() => {
const handler = (s: { componentId: string; name: string; parameters?: any }) => {
@ -106,7 +111,8 @@ const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props,
return newResults;
});
stops.push(stop);
}
},
{ fallbackWhenError: () => undefined }
);
properties.push(result);
});
@ -142,7 +148,10 @@ const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props,
// component properties
const [evaledComponentProperties, setEvaledComponentProperties] = useState(() => {
return merge(stateManager.deepEval(c.properties), propsFromTraits);
return merge(
stateManager.deepEval(c.properties, { fallbackWhenError: () => undefined }),
propsFromTraits
);
});
// eval component properties
useEffect(() => {
@ -150,7 +159,8 @@ const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props,
c.properties,
({ result: newResult }: any) => {
setEvaledComponentProperties({ ...newResult });
}
},
{ fallbackWhenError: () => undefined }
);
// must keep this line, reason is the same as above
setEvaledComponentProperties({ ...result });
@ -158,22 +168,18 @@ const _ImplWrapper = React.forwardRef<HTMLDivElement, ImplWrapperProps>((props,
return stop;
}, [c.properties, stateManager]);
useEffect(() => {
if (unmount) {
delete stateManager.store[c.id];
}
return () => {
delete stateManager.store[c.id];
};
}, [c.id, stateManager.store]);
const mergedProps = useMemo(() => {
const allProps: Record<string, any> = { ...evaledComponentProperties, ...propsFromTraits };
for (const key in allProps) {
if (allProps[key] instanceof ExpressionError) {
allProps[key] = undefined;
}
}
return allProps;
}, [evaledComponentProperties, propsFromTraits]);
}, [c.id, stateManager.store, unmount]);
const mergedProps = useMemo(
() => ({ ...evaledComponentProperties, ...propsFromTraits }),
[evaledComponentProperties, propsFromTraits]
);
function genSlotsElements() {
if (!childrenMap[c.id]) {

View File

@ -1,5 +1,5 @@
import { Static } from '@sinclair/typebox';
import React, { useCallback, useEffect, useMemo } from 'react';
import React, { useEffect, useMemo } from 'react';
import { get } from 'lodash-es';
import { useDeepCompareMemo } from 'use-deep-compare';
import {
@ -17,6 +17,7 @@ import {
ModuleSpec,
} from '../../types';
import { resolveChildrenMap } from '../../utils/resolveChildrenMap';
import { initStateAndMethod } from '../../utils/initStateAndMethod';
import { ExpressionError } from '../../services/StateManager';
type Props = Static<typeof ModuleSpec> & {
@ -29,7 +30,7 @@ export const ModuleRenderer = React.forwardRef<HTMLDivElement, Props>((props, re
const { type, services } = props;
try {
const moduleSpec = services.registry.getModuleByType(type);
return <ModuleRendererContent {...props} moduleSpec={moduleSpec} />;
return <ModuleRendererContent {...props} ref={ref} moduleSpec={moduleSpec} />;
} catch {
return <div ref={ref}>Cannot find Module {type}.</div>;
}
@ -40,32 +41,20 @@ const ModuleRendererContent = React.forwardRef<
Props & { moduleSpec: ImplementedRuntimeModule }
>((props, ref) => {
const { moduleSpec, properties, handlers, evalScope, services, app } = props;
const moduleId = services.stateManager.maskedEval(props.id, true, evalScope) as string | ExpressionError;
const evalOptions = { evalListItem: true, scopeObject: evalScope };
const moduleId = services.stateManager.maskedEval(props.id, evalOptions) as
| string
| ExpressionError;
function evalObject<T extends Record<string, any>>(obj: T): T {
return services.stateManager.mapValuesDeep({ obj }, ({ value }) => {
if (typeof value === 'string') {
return services.stateManager.maskedEval(value, true, evalScope);
return services.stateManager.maskedEval(value, evalOptions);
}
return value;
}).obj;
}
const evalWithScope = useCallback(
<T extends Record<string, any>>(obj: T, scope: Record<string, any>): T => {
const hasScopeKey = (exp: string) => {
return Object.keys(scope).some(key => exp.includes('{{') && exp.includes(key));
};
return services.stateManager.mapValuesDeep({ obj }, ({ value }) => {
if (typeof value === 'string' && hasScopeKey(value)) {
return services.stateManager.maskedEval(value, true, scope);
}
return value;
}).obj;
},
[services.stateManager]
);
// first eval the property, handlers, id of module
const evaledProperties = evalObject(properties);
const parsedTemplate = useMemo(
@ -76,16 +65,28 @@ const ModuleRendererContent = React.forwardRef<
// then eval the template and stateMap of module
const evaledStateMap = useMemo(() => {
// stateMap only use state i
return evalWithScope(moduleSpec.spec.stateMap, { $moduleId: moduleId });
}, [evalWithScope, moduleSpec.spec.stateMap, moduleId]);
return services.stateManager.deepEval(moduleSpec.spec.stateMap, {
evalListItem: false,
scopeObject: { $moduleId: moduleId },
overrideScope: true,
});
}, [services.stateManager, moduleSpec.spec.stateMap, moduleId]);
const evaledModuleTemplate = useDeepCompareMemo(() => {
// here should only eval with evaledProperties, any other key not in evaledProperties should be ignored
// so we can assume that template will not change if evaledProperties is the same
return evalWithScope(parsedTemplate, {
...evaledProperties,
$moduleId: moduleId,
});
return services.stateManager.deepEval(
{ template: parsedTemplate },
{
evalListItem: false,
scopeObject: {
...evaledProperties,
$moduleId: moduleId,
},
overrideScope: true,
fallbackWhenError: exp => exp,
}
).template;
}, [parsedTemplate, evaledProperties, moduleId]);
// listen component state change
@ -128,10 +129,10 @@ const ModuleRendererContent = React.forwardRef<
if (!handlers) return;
const _handlers = handlers as Array<Static<typeof EventHandlerSpec>>;
const moduleEventHandlers: any[] = [];
_handlers.forEach((h) => {
_handlers.forEach(h => {
const moduleEventHandler = ({ fromId, eventType }: Record<string, string>) => {
if (eventType === h.type && fromId === moduleId) {
const evaledHandler = services.stateManager.deepEval(h, true, evalScope);
const evaledHandler = services.stateManager.deepEval(h, evalOptions);
services.apiService.send('uiMethod', {
componentId: evaledHandler.componentId,
name: evaledHandler.method.name,
@ -151,6 +152,8 @@ const ModuleRendererContent = React.forwardRef<
}, [evalScope, handlers, moduleId, services.apiService, services.stateManager]);
const result = useMemo(() => {
// Must init components' state, otherwise store cannot listen these components' state changing
initStateAndMethod(services.registry, services.stateManager, evaledModuleTemplate);
const { childrenMap, topLevelComponents } = resolveChildrenMap(evaledModuleTemplate);
return topLevelComponents.map(c => {
return (
@ -160,12 +163,17 @@ const ModuleRendererContent = React.forwardRef<
services={services}
app={app}
childrenMap={childrenMap}
isInModule={true}
/>
);
});
}, [evaledModuleTemplate, services, app]);
return <div ref={ref}>{result}</div>;
return (
<div className="module-container" ref={ref}>
{result}
</div>
);
});
function parseTypeComponents(

View File

@ -29,10 +29,10 @@ export default implementRuntimeComponent({
},
})(({ id, type, properties, handlers, services, app, elementRef }) => {
if (!type) {
return <span>Please choose a module to render.</span>;
return <span ref={elementRef}>Please choose a module to render.</span>;
}
if (!id) {
return <span>Please set a id for module.</span>;
return <span ref={elementRef}>Please set a id for module.</span>;
}
return (

View File

@ -170,6 +170,10 @@ export class Registry {
return this.getModule(version, name);
}
unregisterAllModules() {
this.modules = new Map<string, Map<string, ImplementedRuntimeModule>>();
}
registerUtilMethod<T>(m: UtilMethod<T>) {
if (this.utilMethods.get(m.name)) {
throw new Error(`Already has utilMethod ${m.name} in this registry.`);

View File

@ -16,6 +16,12 @@ dayjs.extend(LocalizedFormat);
dayjs.locale('zh-cn');
type ExpChunk = string | ExpChunk[];
type EvalOptions = {
evalListItem?: boolean;
scopeObject?: Record<string, any>;
overrideScope?: boolean;
fallbackWhenError?: (exp: string) => any;
};
// TODO: use web worker
const DefaultDependencies = {
@ -43,12 +49,13 @@ export class StateManager {
this.store = reactive<Record<string, any>>({});
};
evalExp = (expChunk: ExpChunk, scopeObject = {}): unknown => {
evalExp = (expChunk: ExpChunk, options: EvalOptions): unknown => {
if (typeof expChunk === 'string') {
return expChunk;
}
const evalText = expChunk.map(ex => this.evalExp(ex, scopeObject)).join('');
const { scopeObject = {}, overrideScope = false } = options;
const evalText = expChunk.map(ex => this.evalExp(ex, { scopeObject })).join('');
// eslint-disable-next-line no-useless-call, no-new-func
const evaled = new Function(
@ -58,12 +65,20 @@ export class StateManager {
/^\s+/g,
''
)} } } }`
).call(null, this.store, this.dependencies, scopeObject);
).call(
null,
overrideScope ? {} : this.store,
overrideScope ? {} : this.dependencies,
scopeObject
);
return evaled;
};
maskedEval(raw: string, evalListItem = false, scopeObject = {}): unknown | ExpressionError {
maskedEval(raw: string, options: EvalOptions = {}): unknown | ExpressionError {
const { evalListItem = false, fallbackWhenError } = options;
let result: unknown[] = [];
try {
if (isNumeric(raw)) {
return toNumber(raw);
@ -75,12 +90,13 @@ export class StateManager {
return false;
}
const expChunk = parseExpression(raw, evalListItem);
if (typeof expChunk === 'string') {
return expChunk;
}
const result = expChunk.map(e => this.evalExp(e, scopeObject));
result = expChunk.map(e => this.evalExp(e, options));
if (result.length === 1) {
return result[0];
}
@ -88,12 +104,10 @@ export class StateManager {
} catch (error) {
if (error instanceof Error) {
const expressionError = new ExpressionError(error.message);
console.error(expressionError);
return expressionError;
return fallbackWhenError ? fallbackWhenError(raw) : expressionError;
}
return undefined;
}
}
@ -121,17 +135,13 @@ export class StateManager {
}) as T;
}
deepEval<T extends Record<string, unknown>>(
obj: T,
evalListItem = false,
scopeObject = {}
): T {
deepEval<T extends Record<string, unknown>>(obj: T, options: EvalOptions = {}): T {
// just eval
const evaluated = this.mapValuesDeep(obj, ({ value }) => {
if (typeof value !== 'string') {
return value;
}
return this.maskedEval(value, evalListItem, scopeObject);
return this.maskedEval(value, options);
});
return evaluated;
@ -140,13 +150,12 @@ export class StateManager {
deepEvalAndWatch<T extends Record<string, unknown>>(
obj: T,
watcher: (params: { result: T }) => void,
evalListItem = false,
scopeObject = {}
options: EvalOptions = {}
) {
const stops: ReturnType<typeof watch>[] = [];
// just eval
const evaluated = this.deepEval(obj, evalListItem, scopeObject);
const evaluated = this.deepEval(obj, options);
// watch change
let resultCache: T = evaluated;
@ -159,7 +168,7 @@ export class StateManager {
const stop = watch(
() => {
const result = this.maskedEval(value, evalListItem, scopeObject);
const result = this.maskedEval(value, options);
return result;
},

View File

@ -9,7 +9,6 @@ import { generateCallback } from './Event';
const FetchTraitFactory: TraitImplFactory<Static<typeof FetchTraitPropertiesSpec>> =
() => {
const hasFetchedMap = new Map<string, boolean>();
return ({
trait,
url,
@ -24,14 +23,13 @@ const FetchTraitFactory: TraitImplFactory<Static<typeof FetchTraitPropertiesSpec
services,
subscribeMethods,
componentId,
disabled,
}) => {
const hashId = `#${componentId}@${'fetch'}`;
const hasFetched = hasFetchedMap.get(hashId);
const lazy = _lazy === undefined ? true : _lazy;
const fetchData = () => {
if (disabled) return;
// TODO: clear when component destroy
hasFetchedMap.set(hashId, true);
// FIXME: listen to the header change
const headers = new Headers();
if (_headers) {
@ -143,7 +141,7 @@ const FetchTraitFactory: TraitImplFactory<Static<typeof FetchTraitPropertiesSpec
typeof FetchTraitPropertiesSpec
>['onError'];
rawOnError?.forEach(handler => {
const evaledHandler = services.stateManager.deepEval(handler, false);
const evaledHandler = services.stateManager.deepEval(handler, { evalListItem: false });
services.apiService.send('uiMethod', {
componentId: evaledHandler.componentId,
name: evaledHandler.method.name,
@ -155,7 +153,7 @@ const FetchTraitFactory: TraitImplFactory<Static<typeof FetchTraitPropertiesSpec
};
// non lazy query, listen to the change and query;
if (!lazy && url && !hasFetched) {
if (!lazy && url) {
fetchData();
}
@ -166,13 +164,7 @@ const FetchTraitFactory: TraitImplFactory<Static<typeof FetchTraitPropertiesSpec
});
return {
props: {
effects: [
() => {
hasFetchedMap.set(hashId, false);
},
],
},
props: null,
};
};
};

View File

@ -12,6 +12,7 @@ export type ImplWrapperProps<KSlot extends string = string> = {
component: RuntimeComponentSchema;
childrenMap: ChildrenMap<KSlot>;
services: UIServices;
isInModule: boolean;
app?: RuntimeApplication;
} & ComponentParamsFromApp;

View File

@ -14,13 +14,14 @@ export const ModuleSpec = Type.Object({
properties: Type.Record(Type.String(), Type.Any(), {
title: 'Module Properties',
category: 'Basic',
widget: 'core/v1/KeyValue',
}),
handlers: Type.Array(EventHandlerSpec, {
title: 'Module Handlers',
category: 'Basic',
}),
}, {
category: 'Appearance',
category: 'Basic',
});
export type ImplementedRuntimeModule = RuntimeModule;

View File

@ -50,6 +50,7 @@ export const FetchTraitPropertiesSpec = Type.Object({
{ title: 'Method' },
), // {pattern: /^(get|post|put|delete)$/i}
lazy: Type.Boolean({ title: 'Lazy' }),
disabled: Type.Boolean({ title: 'Disabled' }),
headers: Type.Record(Type.String(), Type.String(), {
title: 'Headers',
}),

View File

@ -1,6 +1,5 @@
import { RuntimeComponentSchema } from '@sunmao-ui/core';
import { ChildrenMap } from '../types';
import { isFetchTraitComponent } from '../utils/trait';
export function resolveChildrenMap(components: RuntimeComponentSchema[]): {
childrenMap: ChildrenMap<string>;
@ -8,16 +7,11 @@ export function resolveChildrenMap(components: RuntimeComponentSchema[]): {
} {
const childrenMap: ChildrenMap<string> = {};
const topLevelComponents: RuntimeComponentSchema[] = [];
const fetchTraitComponents: RuntimeComponentSchema[] = [];
for (const c of components) {
const slotTrait = c.traits.find(t => t.parsedType.name === 'slot');
if (!slotTrait) {
if (isFetchTraitComponent(c)) {
fetchTraitComponents.push(c);
} else {
topLevelComponents.push(c);
}
topLevelComponents.push(c);
continue;
}
const { id, slot } = slotTrait.properties.container as any;
@ -64,6 +58,6 @@ export function resolveChildrenMap(components: RuntimeComponentSchema[]): {
return {
childrenMap,
topLevelComponents: [...topLevelComponents, ...fetchTraitComponents],
topLevelComponents,
};
}

Some files were not shown because too many files have changed in this diff Show More