close #6 Use typebox to build JSON schema

This commit is contained in:
Yanzhen Yu 2021-07-26 13:40:07 +08:00
parent aaa8caa998
commit 96e409f1dc
7 changed files with 112 additions and 118 deletions

View File

@ -9,6 +9,7 @@
"@emotion/react": "^11",
"@emotion/styled": "^11",
"@meta-ui/core": "^0.1.0",
"@sinclair/typebox": "^0.19.2",
"framer-motion": "^4",
"lodash": "^4.17.21",
"mitt": "^3.0.0",

View File

@ -1,11 +1,19 @@
import React from "react";
import ReactMarkdown from "react-markdown";
import { Static, Type } from "@sinclair/typebox";
export const TextPropertySchema = Type.Object({
raw: Type.String(),
format: Type.KeyOf(
Type.Object({
plain: Type.String(),
md: Type.String(),
})
),
});
export type TextProps = {
value: {
raw: string;
format: "plain" | "md";
};
value: Static<typeof TextPropertySchema>;
};
const Text: React.FC<TextProps> = ({ value }) => {

View File

@ -1,20 +1,17 @@
import React, { useEffect, useRef } from "react";
import { createComponent } from "@meta-ui/core";
import {
Button as BaseButton,
ChakraProvider,
ButtonProps as BaseButtonProps,
} from "@chakra-ui/react";
import Text, { TextProps } from "../_internal/Text";
import { Static, Type } from "@sinclair/typebox";
import { Button as BaseButton, ChakraProvider } from "@chakra-ui/react";
import Text, { TextProps, TextPropertySchema } from "../_internal/Text";
import { ComponentImplementation } from "../../registry";
import { useExpression } from "../../store";
const Button: ComponentImplementation<
BaseButtonProps & {
text: TextProps["value"];
onClick?: () => void;
}
> = ({ text, mergeState, subscribeMethods, onClick, ...rest }) => {
const Button: ComponentImplementation<{
text: TextProps["value"];
colorScheme?: Static<typeof ColorSchemePropertySchema>;
isLoading?: Static<typeof IsLoadingPropertySchema>;
onClick?: () => void;
}> = ({ text, mergeState, subscribeMethods, onClick, ...rest }) => {
const raw = useExpression(text.raw);
useEffect(() => {
mergeState({ value: raw });
@ -38,6 +35,36 @@ const Button: ComponentImplementation<
);
};
const ColorSchemePropertySchema = Type.Optional(
Type.KeyOf(
Type.Object({
whiteAlpha: Type.String(),
blackAlpha: Type.String(),
gray: Type.String(),
red: Type.String(),
orange: Type.String(),
yellow: Type.String(),
green: Type.String(),
teal: Type.String(),
blue: Type.String(),
cyan: Type.String(),
purple: Type.String(),
pink: Type.String(),
linkedin: Type.String(),
facebook: Type.String(),
messenger: Type.String(),
whatsapp: Type.String(),
twitter: Type.String(),
telegram: Type.String(),
})
)
);
const IsLoadingPropertySchema = Type.Optional(Type.Boolean());
const StateSchema = Type.Object({
value: Type.String(),
});
export default {
...createComponent({
version: "chakra_ui/v1",
@ -49,55 +76,19 @@ export default {
properties: [
{
name: "text",
type: "object",
properties: {
raw: {
type: "string",
},
format: {
type: "string",
enum: ["plain", "md"],
},
},
...TextPropertySchema,
},
{
name: "colorScheme",
type: "string",
enum: [
"whiteAlpha",
"blackAlpha",
"gray",
"red",
"orange",
"yellow",
"green",
"teal",
"blue",
"cyan",
"purple",
"pink",
"linkedin",
"facebook",
"messenger",
"whatsapp",
"twitter",
"telegram",
],
...ColorSchemePropertySchema,
},
{
name: "isLoading",
type: "boolean",
...IsLoadingPropertySchema,
},
],
acceptTraits: [],
state: {
type: "object",
properties: {
value: {
type: "string",
},
},
},
state: StateSchema,
methods: [
{
name: "click",

View File

@ -1,7 +1,8 @@
import React, { useEffect } from "react";
import { createComponent } from "@meta-ui/core";
import { Type } from "@sinclair/typebox";
import { ComponentImplementation } from "../../registry";
import _Text, { TextProps } from "../_internal/Text";
import _Text, { TextProps, TextPropertySchema } from "../_internal/Text";
import { useExpression } from "../../store";
const Text: ComponentImplementation<TextProps> = ({ value, mergeState }) => {
@ -14,6 +15,10 @@ const Text: ComponentImplementation<TextProps> = ({ value, mergeState }) => {
return <_Text value={{ ...value, raw }} />;
};
const StateSchema = Type.Object({
value: Type.String(),
});
export default {
...createComponent({
version: "core/v1",
@ -25,27 +30,11 @@ export default {
properties: [
{
name: "value",
type: "object",
properties: {
raw: {
type: "string",
},
format: {
type: "string",
enum: ["plain", "md"],
},
},
...TextPropertySchema,
},
],
acceptTraits: [],
state: {
type: "object",
properties: {
value: {
type: "string",
},
},
},
state: StateSchema,
methods: [],
},
}),

View File

@ -1,6 +1,7 @@
import React, { useEffect, useRef } from "react";
import { createComponent } from "@meta-ui/core";
import Text, { TextProps } from "../_internal/Text";
import { Type } from "@sinclair/typebox";
import Text, { TextProps, TextPropertySchema } from "../_internal/Text";
import { ComponentImplementation } from "../../registry";
import { useExpression } from "../../store";
@ -29,6 +30,10 @@ const Button: ComponentImplementation<{
);
};
const StateSchema = Type.Object({
value: Type.String(),
});
export default {
...createComponent({
version: "plain/v1",
@ -40,27 +45,11 @@ export default {
properties: [
{
name: "text",
type: "object",
properties: {
raw: {
type: "string",
},
format: {
type: "string",
enum: ["plain", "md"],
},
},
...TextPropertySchema,
},
],
acceptTraits: [],
state: {
type: "object",
properties: {
value: {
type: "string",
},
},
},
state: StateSchema,
methods: [
{
name: "click",

View File

@ -1,24 +1,13 @@
import { useEffect, useMemo, useRef } from "react";
import { createTrait } from "@meta-ui/core";
import { Static, Type } from "@sinclair/typebox";
import { nanoid } from "nanoid";
import { debounce, throttle, delay } from "lodash";
import { TraitImplementation } from "../../registry";
import { emitter, evalInContext, useStore } from "../../store";
const useEventTrait: TraitImplementation<{
events: Array<{
event: string;
componentId: string;
method: {
name: string;
parameters: string;
};
wait: {
type: "debounce" | "throttle" | "delay";
time: number;
};
disabled: boolean | string;
}>;
events: Static<typeof EventsPropertySchema>;
}> = ({ events }) => {
const hookId = useMemo(() => {
return nanoid();
@ -88,6 +77,28 @@ const useEventTrait: TraitImplementation<{
return hub;
};
const EventsPropertySchema = Type.Array(
Type.Object({
event: Type.String(),
componentId: Type.String(),
method: Type.Object({
name: Type.String(),
parameters: Type.String(),
}),
wait: Type.Object({
type: Type.KeyOf(
Type.Object({
debounce: Type.String(),
throttle: Type.String(),
delay: Type.String(),
})
),
time: Type.Number(),
}),
disabled: Type.Union([Type.Boolean(), Type.String()]),
})
);
export default {
...createTrait({
version: "core/v1",
@ -96,7 +107,12 @@ export default {
description: "export component events with advance features",
},
spec: {
properties: [],
properties: [
{
name: "events",
...EventsPropertySchema,
},
],
state: {},
methods: [],
},

View File

@ -1,10 +1,11 @@
import { useEffect } from "react";
import { createTrait } from "@meta-ui/core";
import { Static, Type } from "@sinclair/typebox";
import { TraitImplementation } from "../../registry";
const useStateTrait: TraitImplementation<{
key: string;
initialValue: any;
key: Static<typeof KeyPropertySchema>;
initialValue: Static<typeof InitialValuePropertySchema>;
}> = ({ key, initialValue, mergeState, subscribeMethods }) => {
useEffect(() => {
mergeState({ [key]: initialValue });
@ -20,6 +21,9 @@ const useStateTrait: TraitImplementation<{
}, []);
};
const KeyPropertySchema = Type.String();
const InitialValuePropertySchema = Type.Any();
export default {
...createTrait({
version: "core/v1",
@ -31,22 +35,18 @@ export default {
properties: [
{
name: "key",
type: "string",
...KeyPropertySchema,
},
{
name: "initialValue",
type: "any",
...InitialValuePropertySchema,
},
],
state: {
type: "any",
},
state: Type.Any(),
methods: [
{
name: "setValue",
parameters: {
type: "any",
},
parameters: Type.Any(),
},
{
name: "reset",