Merge pull request #6 from webzard-io/component-treelike

implement treeselect & timeline
This commit is contained in:
tanbowensg 2022-01-19 17:53:32 +08:00 committed by Bowen Tan
parent 4d6b95ab48
commit f5d3ffdcc7
5 changed files with 280 additions and 0 deletions

View File

@ -0,0 +1,87 @@
import { Timeline as BaseTimeline } 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 { TimelinePropsSchema as BaseTimelinePropsSchema } from "../generated/types/Timeline";
const TimelinePropsSchema = Type.Object(BaseTimelinePropsSchema);
const TimelineStateSchema = Type.Object({});
const TimelineImpl: ComponentImpl<Static<typeof TimelinePropsSchema>> = (
props
) => {
const { items, className, ...cProps } = getComponentProps(props);
const { customStyle } = props;
return (
<BaseTimeline
className={cx(className, css(customStyle?.content))}
{...cProps}
>
{items?.map((item, idx) => (
<BaseTimeline.Item
key={idx}
label={item.label}
dotColor={item.dotColor}
lineType={item.lineType}
lineColor={item.lineColor}
dotType={item.dotType}
>
{item.content}
</BaseTimeline.Item>
))}
</BaseTimeline>
);
};
const exampleProperties: Static<typeof TimelinePropsSchema> = {
className: "",
reverse: false,
direction: "vertical",
mode: "alternate",
labelPosition: "same",
items: [
{
label: "2017-03-10",
content: "The first milestone",
dotColor: "#00B42A",
lineType: "dashed",
lineColor: "#00B42A",
dotType: "hollow",
},
{ label: "2018-05-12", content: "The second milestone" },
{
label: "2020-06-22",
content: "The third milestone",
dotColor: "#F53F3F",
lineType: "dotted",
},
{
label: "2020-09-30",
content: "The fourth milestone",
dotColor: "#C9CDD4",
},
],
};
const options = {
version: "arco/v1",
metadata: {
...FALLBACK_METADATA,
name: "Timeline",
displayName: "Timeline",
exampleProperties,
},
spec: {
properties: TimelinePropsSchema,
state: TimelineStateSchema,
methods: {},
slots: [],
styleSlots: ["content"],
events: [],
},
};
export const Timeline = implementRuntimeComponent(options)(
TimelineImpl as typeof TimelineImpl & undefined
);

View File

@ -0,0 +1,119 @@
import { TreeSelect as BaseTreeSelect } 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 {
TreeSelectPropsSchema as BaseTreeSelectPropsSchema,
TreeSelectValueSchema,
} from "../generated/types/TreeSelect";
import { useState, useEffect } from "react";
const TreeSelectPropsSchema = Type.Object(BaseTreeSelectPropsSchema);
const TreeSelectStateSchema = Type.Object({
value: Type.String(),
});
type TreeSelectValue = Static<typeof TreeSelectValueSchema>;
const TreeSelectImpl: ComponentImpl<Static<typeof TreeSelectPropsSchema>> = (
props
) => {
const { defaultValue, ...cProps } = getComponentProps(props);
const { customStyle, className, mergeState } = props;
const [value, setValue] = useState<TreeSelectValue>(defaultValue!);
useEffect(() => {
mergeState({ value });
}, [mergeState, value]);
const handleChange = (value: TreeSelectValue) => {
setValue(value);
};
const filterTreeNode = (inputText: string, treeNode: any) => {
return (
treeNode.props.title.toLowerCase().indexOf(inputText.toLowerCase()) > -1
);
};
return (
<BaseTreeSelect
onChange={handleChange}
className={cx(className, css(customStyle?.content))}
filterTreeNode={filterTreeNode}
{...cProps}
value={value}
></BaseTreeSelect>
);
};
const exampleProperties: Static<typeof TreeSelectPropsSchema> = {
unmountOnExit: false,
treeCheckable: false,
defaultValue: "node1",
treeData: [
{
key: "node1",
title: "Trunk",
disabled: true,
children: [
{
key: "node2",
title: "Leaf1",
},
],
},
{
key: "node3",
title: "Trunk2",
children: [
{
key: "node4",
title: "Leaf2",
},
{
key: "node5",
title: "Leaf3",
},
],
},
],
treeCheckStrictly: false,
bordered: false,
placeholder: "please ...",
className: "",
labelInValue: true,
size: "default",
disabled: false,
error: false,
showSearch: true,
loading: false,
allowClear: true,
allowCreate: true,
maxTagCount: 20,
animation: false,
};
const options = {
version: "arco/v1",
metadata: {
...FALLBACK_METADATA,
name: "TreeSelect",
displayName: "TreeSelect",
exampleProperties,
},
spec: {
properties: TreeSelectPropsSchema,
state: TreeSelectStateSchema,
methods: {},
slots: [],
styleSlots: ["content"],
events: [],
},
};
export const TreeSelect = implementRuntimeComponent(options)(
TreeSelectImpl as typeof TreeSelectImpl & undefined
);

View File

@ -0,0 +1,24 @@
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
export const TimelineItemPropsSchema = {
className: Type.Optional(Type.String()),
label: Type.Optional(Type.String()),
content: Type.String(),
dotColor: Type.Optional(Type.String()),
lineType: Type.Optional(StringUnion(['solid', 'dashed', 'dotted'])),
lineColor: Type.Optional(Type.String()),
dotType: Type.Optional(StringUnion(['hollow', 'solid']))
}
export const TimelinePropsSchema = {
className: Type.Optional(Type.String()),
reverse: Type.Optional(Type.Boolean()),
direction: StringUnion(['horizontal', 'vertical']),
mode: StringUnion(['left', 'right', 'alternate']),
labelPosition: StringUnion(['relative', 'same']),
items: Type.Optional(Type.Array(Type.Object(
TimelineItemPropsSchema
)))
}

View File

@ -0,0 +1,46 @@
import { Type } from '@sinclair/typebox';
import { StringUnion } from '../../sunmao-helper';
const TreeSelectNodeSchema = Type.Object({
label: Type.String(),
value: Type.String(),
disabled: Type.Optional(Type.Boolean())
})
export const TreeSelectValueSchema = Type.Union([
Type.String(),
Type.Array(Type.String()),
TreeSelectNodeSchema,
Type.Array(TreeSelectNodeSchema)
])
export const TreeSelectPropsSchema = {
defaultValue: Type.Optional(TreeSelectValueSchema),
multiple: Type.Optional(Type.Boolean()),
unmountOnExit: Type.Optional(Type.Boolean()),
treeCheckable: Type.Optional(Type.Boolean()),
treeCheckStrictly: Type.Optional(Type.Boolean()),
bordered: Type.Optional(Type.Boolean()),
placeholder: Type.Optional(Type.String()),
className: Type.Optional(Type.String()),
size: Type.Optional(StringUnion(['mini', 'small', 'default', 'large'])),
disabled: Type.Optional(Type.Boolean()),
showSearch: Type.Optional(Type.Boolean()),
error: Type.Optional(Type.Boolean()),
labelInValue: Type.Optional(Type.Boolean()),
loading: Type.Optional(Type.Boolean()),
allowClear: Type.Optional(Type.Boolean()),
allowCreate: Type.Optional(Type.Boolean()),
maxTagCount: Type.Optional(Type.Number()),
animation: Type.Optional(Type.Boolean()),
treeData: Type.Array(
Type.Rec(Self => Type.Object({
key: Type.String(),
title: Type.String(),
disabled: Type.Optional(Type.Boolean()),
children: Type.Array(Self)
}))
),
}

View File

@ -19,12 +19,15 @@ import { Popover } from "./components/Popover";
import { Collapse, CollapseItem } from "./components/Collapse";
import { Cascader } from "./components/Cascader";
import { Skeleton } from "./components/Skeleton";
import { Timeline } from "./components/Timeline";
import { TreeSelect } from "./components/TreeSelect";
type Component = Parameters<Registry["registerComponent"]>[0];
type Trait = Parameters<Registry["registerTrait"]>[0];
type Module = Parameters<Registry["registerModule"]>[0];
export const components: Component[] = [
TreeSelect,
Button,
Header,
Content,
@ -49,6 +52,7 @@ export const components: Component[] = [
CollapseItem,
Cascader,
Skeleton,
Timeline
];
export const traits: Trait[] = [];
export const modules: Module[] = [];