migrate components and traits to v2 eval

This commit is contained in:
Yanzhen Yu 2021-08-10 15:48:12 +08:00
parent e790ab1604
commit d976e2d526
11 changed files with 126 additions and 130 deletions

View File

@ -4,7 +4,6 @@ import { Static, Type } from "@sinclair/typebox";
import { Box as BaseBox } from "@chakra-ui/react";
import { ComponentImplementation } from "../../registry";
import Slot from "../_internal/Slot";
import { useExpression } from "../../store";
import { pick } from "lodash";
const CssGlobals = Type.KeyOf(
@ -278,14 +277,6 @@ const Box: ComponentImplementation<Static<typeof StyleSchema>> = ({
...restProps
}) => {
const styleProps = pick(restProps, StyleProps);
Object.entries(styleProps).forEach((item) => {
const key = item[0] as keyof typeof styleProps;
const value = item[1];
if (typeof value === "string" && value.startsWith("{{")) {
const raw = useExpression(value);
styleProps[key] = raw;
}
});
return (
<BaseBox {...styleProps}>

View File

@ -4,7 +4,6 @@ import { Static, Type } from "@sinclair/typebox";
import { Button as BaseButton } from "@chakra-ui/react";
import Text, { TextProps, TextPropertySchema } from "../_internal/Text";
import { ComponentImplementation } from "../../registry";
import { useExpression } from "../../store";
const Button: ComponentImplementation<{
text: TextProps["value"];
@ -19,10 +18,9 @@ const Button: ComponentImplementation<{
colorScheme,
isLoading,
}) => {
const raw = useExpression(text.raw);
useEffect(() => {
mergeState({ value: raw });
}, [raw]);
mergeState({ value: text.raw });
}, [text.raw]);
const ref = useRef<HTMLButtonElement>(null);
useEffect(() => {
@ -35,7 +33,7 @@ const Button: ComponentImplementation<{
return (
<BaseButton {...{ colorScheme, isLoading }} ref={ref} onClick={onClick}>
<Text value={{ ...text, raw }} />
<Text value={text} />
</BaseButton>
);
};

View File

@ -1,16 +1,22 @@
import React, { useEffect, useRef } from "react";
import { Input as BaseInput, InputGroup, InputLeftAddon, InputLeftElement, InputRightAddon, InputRightElement } from "@chakra-ui/react";
import React, { useEffect } from "react";
import {
Input as BaseInput,
InputGroup,
InputLeftAddon,
InputLeftElement,
InputRightAddon,
InputRightElement,
} from "@chakra-ui/react";
import { createComponent } from "@meta-ui/core";
import { Static, Type } from "@sinclair/typebox";
import { ComponentImplementation } from "../../registry";
const VariantPropertySchema = Type.KeyOf(
Type.Object({
outline: Type.String(),
unstyled: Type.String(),
filled: Type.String(),
flushed: Type.String()
flushed: Type.String(),
})
);
@ -21,7 +27,7 @@ const SizePropertySchema = Type.KeyOf(
sm: Type.String(),
md: Type.String(),
lg: Type.String(),
xs: Type.String()
xs: Type.String(),
})
);
@ -32,15 +38,15 @@ const IsRequiredPropertySchema = Type.Optional(Type.Boolean());
const AppendElementPropertySchema = Type.Union([
Type.Object({
type: Type.KeyOf(Type.Object({ addon: Type.String() })),
children: Type.Optional(Type.String()) // TODO: ReactNode
children: Type.Optional(Type.String()), // TODO: ReactNode
}),
Type.Object({
type: Type.KeyOf(Type.Object({ element: Type.String() })),
children: Type.Optional(Type.String()), // TODO: ReactNode
fontSize: Type.Optional(Type.String()),
color: Type.Optional(Type.String()),
})
])
}),
]);
const Input: ComponentImplementation<{
variant?: Static<typeof VariantPropertySchema>;
@ -60,10 +66,11 @@ const Input: ComponentImplementation<{
isRequired,
left,
right,
mergeState
mergeState,
}) => {
const [value, setValue] = React.useState(""); // TODO: pin input
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => setValue(event.target.value);
const onChange = (event: React.ChangeEvent<HTMLInputElement>) =>
setValue(event.target.value);
useEffect(() => {
mergeState({ value });
@ -71,11 +78,19 @@ const Input: ComponentImplementation<{
return (
<InputGroup size={size}>
{left ? left.type === "addon"
? <InputLeftAddon children={left.children} />
: <InputLeftElement children={left.children} fontSize={left.fontSize} color={left.color} />
: <></>
}
{left ? (
left.type === "addon" ? (
<InputLeftAddon children={left.children} />
) : (
<InputLeftElement
children={left.children}
fontSize={left.fontSize}
color={left.color}
/>
)
) : (
<></>
)}
<BaseInput
variant={variant}
placeholder={placeholder}
@ -84,13 +99,22 @@ const Input: ComponentImplementation<{
isRequired={isRequired}
onChange={onChange}
/>
{right ? right.type === "addon"
? <InputRightAddon children={right.children} />
: <InputRightElement children={right.children} fontSize={right.fontSize} color={right.color} />
: <></>}
{right ? (
right.type === "addon" ? (
<InputRightAddon children={right.children} />
) : (
<InputRightElement
children={right.children}
fontSize={right.fontSize}
color={right.color}
/>
)
) : (
<></>
)}
</InputGroup>
);
}
};
const StateSchema = Type.Object({
value: Type.String(),
@ -106,42 +130,42 @@ export default {
spec: {
properties: [
{
name: 'variant',
...VariantPropertySchema
name: "variant",
...VariantPropertySchema,
},
{
name: 'placeholder',
...PlaceholderPropertySchema
name: "placeholder",
...PlaceholderPropertySchema,
},
{
name: 'size',
...SizePropertySchema
name: "size",
...SizePropertySchema,
},
{
name: 'focusBorderColor',
...FocusBorderColorPropertySchema
name: "focusBorderColor",
...FocusBorderColorPropertySchema,
},
{
name: 'isDisabled',
...IsDisabledPropertySchema
name: "isDisabled",
...IsDisabledPropertySchema,
},
{
name: 'isRequired',
...IsRequiredPropertySchema
name: "isRequired",
...IsRequiredPropertySchema,
},
{
name: 'left',
...AppendElementPropertySchema
name: "left",
...AppendElementPropertySchema,
},
{
name: 'right',
...AppendElementPropertySchema
}
name: "right",
...AppendElementPropertySchema,
},
],
acceptTraits: [],
state: StateSchema,
methods: [],
}
},
}),
impl: Input,
}
};

View File

@ -4,19 +4,17 @@ import { Type } from "@sinclair/typebox";
import { createComponent } from "@meta-ui/core";
import { ComponentImplementation } from "../../registry";
import Text, { TextProps, TextPropertySchema } from "../_internal/Text";
import { useExpression } from "../../store";
const Kbd: ComponentImplementation<{
text: TextProps["value"];
}> = ({ text, mergeState }) => {
const raw = useExpression(text.raw);
useEffect(() => {
mergeState({ value: raw });
}, [raw]);
mergeState({ value: text.raw });
}, [text.raw]);
return (
<BaseKbd>
<Text value={{ ...text, raw }} />
<Text value={text} />
</BaseKbd>
);
};

View File

@ -23,7 +23,7 @@ const SizePropertySchema = Type.KeyOf(
sm: Type.String(),
md: Type.String(),
lg: Type.String(),
xs: Type.String()
xs: Type.String(),
})
);
@ -31,19 +31,19 @@ const CustomerStepStylePropertySchema = Type.Object({
bg: Type.Optional(Type.String()),
children: Type.Optional(Type.String()),
_active: Type.Object(Type.Object({ bg: Type.String() })),
})
});
const NumberInput: ComponentImplementation<{
defaultValue?: Static<typeof DefaultValuePropertySchema>
min?: Static<typeof MinPropertySchema>
max?: Static<typeof MaxPropertySchema>
step?: Static<typeof StepPropertySchema>
precision?: Static<typeof PrecisionPropertySchema>
clampValueOnBlur?: Static<typeof ClampValueOnBlurPropertySchema>
allowMouseWheel?: Static<typeof AllowMouseWheelPropertySchema>
size?: Static<typeof SizePropertySchema>
customerIncrement?: Static<typeof CustomerStepStylePropertySchema>
customerDecrement?: Static<typeof CustomerStepStylePropertySchema>
defaultValue?: Static<typeof DefaultValuePropertySchema>;
min?: Static<typeof MinPropertySchema>;
max?: Static<typeof MaxPropertySchema>;
step?: Static<typeof StepPropertySchema>;
precision?: Static<typeof PrecisionPropertySchema>;
clampValueOnBlur?: Static<typeof ClampValueOnBlurPropertySchema>;
allowMouseWheel?: Static<typeof AllowMouseWheelPropertySchema>;
size?: Static<typeof SizePropertySchema>;
customerIncrement?: Static<typeof CustomerStepStylePropertySchema>;
customerDecrement?: Static<typeof CustomerStepStylePropertySchema>;
}> = ({
defaultValue = 0,
min,
@ -55,10 +55,11 @@ const NumberInput: ComponentImplementation<{
size,
customerIncrement,
customerDecrement,
mergeState
mergeState,
}) => {
const [value, setValue] = useState(defaultValue)
const onChange = (valueAsString: string, valueAsNumber: number) => setValue(valueAsNumber);
const [value, setValue] = useState(defaultValue);
const onChange = (valueAsString: string, valueAsNumber: number) =>
setValue(valueAsNumber);
useEffect(() => {
mergeState({ value });
@ -83,7 +84,7 @@ const NumberInput: ComponentImplementation<{
</NumberInputStepper>
</BaseNumberInput>
);
}
};
const StateSchema = Type.Object({
value: Type.Number(),
@ -99,50 +100,50 @@ export default {
spec: {
properties: [
{
name: 'defaultValue',
...DefaultValuePropertySchema
name: "defaultValue",
...DefaultValuePropertySchema,
},
{
name: 'min',
...MinPropertySchema
name: "min",
...MinPropertySchema,
},
{
name: 'max',
...MaxPropertySchema
name: "max",
...MaxPropertySchema,
},
{
name: 'step',
...StepPropertySchema
name: "step",
...StepPropertySchema,
},
{
name: 'precision',
...PrecisionPropertySchema
name: "precision",
...PrecisionPropertySchema,
},
{
name: 'clampValueOnBlur',
...ClampValueOnBlurPropertySchema
name: "clampValueOnBlur",
...ClampValueOnBlurPropertySchema,
},
{
name: 'allowMouseWheel',
...AllowMouseWheelPropertySchema
name: "allowMouseWheel",
...AllowMouseWheelPropertySchema,
},
{
name: 'size',
...SizePropertySchema
name: "size",
...SizePropertySchema,
},
{
name: 'customerIncrement',
...CustomerStepStylePropertySchema
name: "customerIncrement",
...CustomerStepStylePropertySchema,
},
{
name: 'customerDecrement',
...CustomerStepStylePropertySchema
name: "customerDecrement",
...CustomerStepStylePropertySchema,
},
],
acceptTraits: [],
state: StateSchema,
methods: [],
}
},
}),
impl: NumberInput,
}
};

View File

@ -3,7 +3,6 @@ import { Table as BaseTable, Thead, Tr, Th, Tbody, Td } from "@chakra-ui/react";
import { ComponentImplementation } from "../../registry";
import { createComponent } from "@meta-ui/core";
import { Static, Type } from "@sinclair/typebox";
import { useExpression } from "../../store";
function normalizeData(data: Static<typeof DataPropertySchema>): {
normalizedData: Array<Record<string, string>>;
@ -28,8 +27,7 @@ function normalizeData(data: Static<typeof DataPropertySchema>): {
const Table: ComponentImplementation<{
data: Static<typeof DataPropertySchema>;
size: Static<typeof SizePropertySchema>;
}> = ({ data: _data, size, mergeState }) => {
const data = useExpression(_data) || [];
}> = ({ data = [], size, mergeState }) => {
const { normalizedData, keys } = normalizeData(data);
useEffect(() => {
mergeState({ data });
@ -59,7 +57,7 @@ const Table: ComponentImplementation<{
);
};
const DataPropertySchema = Type.Union([Type.Array(Type.Any()), Type.String()]);
const DataPropertySchema = Type.Array(Type.Any());
const SizePropertySchema = Type.KeyOf(
Type.Object({
sm: Type.String(),

View File

@ -3,16 +3,13 @@ import { createComponent } from "@meta-ui/core";
import { Type } from "@sinclair/typebox";
import { ComponentImplementation } from "../../registry";
import _Text, { TextProps, TextPropertySchema } from "../_internal/Text";
import { useExpression } from "../../store";
const Text: ComponentImplementation<TextProps> = ({ value, mergeState }) => {
const raw = useExpression(value.raw);
useEffect(() => {
mergeState({ value: raw });
}, [raw]);
mergeState({ value: value.raw });
}, [value.raw]);
return <_Text value={{ ...value, raw }} />;
return <_Text value={value} />;
};
const StateSchema = Type.Object({

View File

@ -3,16 +3,14 @@ import { createComponent } from "@meta-ui/core";
import { Type } from "@sinclair/typebox";
import Text, { TextProps, TextPropertySchema } from "../_internal/Text";
import { ComponentImplementation } from "../../registry";
import { useExpression } from "../../store";
const Button: ComponentImplementation<{
text: TextProps["value"];
onClick?: () => void;
}> = ({ text, mergeState, subscribeMethods, onClick }) => {
const raw = useExpression(text.raw);
useEffect(() => {
mergeState({ value: raw });
}, [raw]);
mergeState({ value: text.raw });
}, [text.raw]);
const ref = useRef<HTMLButtonElement>(null);
useEffect(() => {
@ -25,7 +23,7 @@ const Button: ComponentImplementation<{
return (
<button ref={ref} onClick={onClick}>
<Text value={{ ...text, raw }} />
<Text value={text} />
</button>
);
};

View File

@ -4,7 +4,7 @@ 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";
import { emitter } from "../../store";
const useEventTrait: TraitImplementation<{
events: Static<typeof EventsPropertySchema>;
@ -36,18 +36,15 @@ const useEventTrait: TraitImplementation<{
for (const event of events) {
const handler = () => {
let disabled = false;
const currentStoreState = useStore.getState();
if (typeof event.disabled === "boolean") {
disabled = event.disabled;
} else if (typeof event.disabled === "string") {
disabled = evalInContext(event.disabled, currentStoreState);
}
if (disabled) {
return;
}
emitter.emit(event.componentId, {
name: event.method.name,
parameters: evalInContext(event.method.parameters, currentStoreState),
parameters: event.method.parameters,
});
};
if (!handlerMap.current[event.event]) {
@ -85,7 +82,7 @@ const EventsPropertySchema = Type.Array(
componentId: Type.String(),
method: Type.Object({
name: Type.String(),
parameters: Type.String(),
parameters: Type.Any(),
}),
wait: Type.Object({
type: Type.KeyOf(
@ -97,7 +94,7 @@ const EventsPropertySchema = Type.Array(
),
time: Type.Number(),
}),
disabled: Type.Union([Type.Boolean(), Type.String()]),
disabled: Type.Boolean(),
})
);

View File

@ -2,7 +2,6 @@ import { useCallback, useEffect, useMemo } from "react";
import { createTrait } from "@meta-ui/core";
import { Static, Type } from "@sinclair/typebox";
import { TraitImplementation } from "../../registry";
import { evalInContext, useExpression, useStore } from "../../store";
const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
name,
@ -18,8 +17,6 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
return _lazy === undefined ? method.toLowerCase() !== "get" : _lazy;
}, [method, _lazy]);
const urlExpression = useExpression(url);
const fetchData = useCallback(() => {
// before fetching, initial data
mergeState({
@ -34,12 +31,11 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
if (_headers) {
for (let i = 0; i < _headers.length; i++) {
const header = _headers[i];
const value = evalInContext(_headers[i].value, useStore.getState());
headers.append(header.key, value);
headers.append(header.key, _headers[i].value);
}
}
// fetch data
fetch(urlExpression, {
fetch(url, {
method,
headers,
body,
@ -81,7 +77,7 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
});
}
);
}, [urlExpression, method, _headers, body, lazy]);
}, [url, method, _headers, body, lazy]);
// intialize data
useEffect(() => {
@ -96,11 +92,11 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
// non lazy query, listen to the change and query;
useEffect(() => {
if (lazy || !urlExpression) {
if (lazy || !url) {
return;
}
fetchData();
}, [urlExpression, method, _headers, body, lazy]);
}, [url, method, _headers, body, lazy]);
// only subscribe non lazy fetch trait
if (lazy) {

View File

@ -2,14 +2,12 @@ import React from "react";
import { createTrait } from "@meta-ui/core";
import { Static, Type } from "@sinclair/typebox";
import { TraitImplementation } from "../../registry";
import { useExpression } from "../../store";
type HiddenProps = {
hidden: Static<typeof HiddenPropertySchema>;
};
const Hidden: React.FC<HiddenProps> = ({ hidden: _hidden, children }) => {
const hidden = useExpression(_hidden.toString());
const Hidden: React.FC<HiddenProps> = ({ hidden, children }) => {
if (hidden) {
return null;
}