Merge pull request #67 from webzard-io/cep/radio

feat: impl radio and radioGroup
This commit is contained in:
tanbowensg 2021-09-17 10:11:49 +08:00 committed by GitHub
commit 7894db3215
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 401 additions and 57 deletions

View File

@ -0,0 +1,140 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>meta-ui runtime example: radio component</title>
</head>
<body>
<div id="root"></div>
<script type="module">
import renderApp from '../../src/main.tsx';
renderApp({
version: 'example/v1',
metadata: {
name: 'radio',
description: 'radio',
},
spec: {
components: [
{
id: 'root',
type: 'chakra_ui/v1/root',
properties: {},
traits: [],
},
{
id: 'radio_group',
type: 'chakra_ui/v1/radio_group',
properties: {
defaultValue: 1,
isNumerical: true,
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: 'root',
slot: 'root',
},
},
},
],
},
{
id: 'stack',
type: 'chakra_ui/v1/stack',
properties: {
direction: 'row',
spacing: 8,
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: 'radio_group',
slot: 'content',
},
},
},
],
},
{
id: 'radio_1',
type: 'chakra_ui/v1/radio',
properties: {
text: {
raw: 'Radio1',
format: 'plain',
},
value: 1,
size: 'sm',
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: 'stack',
slot: 'content',
},
},
},
],
},
{
id: 'radio_2',
type: 'chakra_ui/v1/radio',
properties: {
text: {
raw: 'Radio2',
format: 'plain',
},
value: 2,
size: 'md',
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: 'stack',
slot: 'content',
},
},
},
],
},
{
id: 'radio_3',
type: 'chakra_ui/v1/radio',
properties: {
text: {
raw: 'Radio3',
format: 'plain',
},
value: 3,
size: 'lg',
isDisabled: true
},
traits: [
{
type: 'core/v1/slot',
properties: {
container: {
id: 'stack',
slot: 'content',
},
},
},
],
},
],
},
});
</script>
</body>
</html>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>meta-ui runtime example: checkbox component</title> <title>meta-ui runtime example: select component</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

@ -1,13 +1,23 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { createComponent } from '@meta-ui/core'; import { createComponent } from '@meta-ui/core';
import { Static, Type } from '@sinclair/typebox'; import { Static, Type } from '@sinclair/typebox';
import { Checkbox as BaseCheckbox } from '@chakra-ui/react'; import {
Checkbox as BaseCheckbox,
useCheckboxGroupContext,
} from '@chakra-ui/react';
import { ComponentImplementation } from '../../registry'; import { ComponentImplementation } from '../../registry';
import Text, { TextProps, TextPropertySchema } from '../_internal/Text'; import Text, { TextProps, TextPropertySchema } from '../_internal/Text';
import { ColorSchemePropertySchema } from './Types/ColorScheme'; import { ColorSchemePropertySchema } from './Types/ColorScheme';
import _ from 'lodash';
const ValueSchema = Type.Union([Type.String(), Type.Number()]);
const DefaultIsCheckedSchema = Type.Optional(Type.Boolean()); const DefaultIsCheckedSchema = Type.Optional(Type.Boolean());
export const IsDisabledSchema = Type.Optional(Type.Boolean()); export const IsDisabledSchema = Type.Optional(Type.Boolean());
const IsFocusableSchema = Type.Optional(Type.Boolean());
const IsInvalidSchema = Type.Optional(Type.Boolean());
const IsReadOnlySchema = Type.Optional(Type.Boolean());
const IsRequiredSchema = Type.Optional(Type.Boolean());
const SpacingSchema = Type.Optional(Type.String());
export const SizePropertySchema = Type.KeyOf( export const SizePropertySchema = Type.KeyOf(
Type.Object({ Type.Object({
sm: Type.String(), sm: Type.String(),
@ -15,53 +25,56 @@ export const SizePropertySchema = Type.KeyOf(
lg: Type.String(), lg: Type.String(),
}) })
); );
const IsFocusableSchema = Type.Optional(Type.Boolean());
const IsInvalidSchema = Type.Optional(Type.Boolean()); const StateSchema = Type.Object({
const IsReadOnlySchema = Type.Optional(Type.Boolean()); value: Type.String(),
const IsRequiredSchema = Type.Optional(Type.Boolean()); });
const SpacingSchema = Type.Optional(Type.String());
const IsCheckedSchema = Type.Optional(Type.Boolean());
const IsIndeterminateSchema = Type.Optional(Type.Boolean());
const ValueSchema = Type.Optional(Type.Union([Type.String(), Type.Number()]));
const Checkbox: ComponentImplementation<{ const Checkbox: ComponentImplementation<{
text: TextProps['value']; text: TextProps['value'];
value: Static<typeof ValueSchema>;
defaultIsChecked?: Static<typeof DefaultIsCheckedSchema>; defaultIsChecked?: Static<typeof DefaultIsCheckedSchema>;
isDisabled?: Static<typeof IsDisabledSchema>; isDisabled?: Static<typeof IsDisabledSchema>;
isFocusable?: Static<typeof IsFocusableSchema>; isFocusable?: Static<typeof IsFocusableSchema>;
isInValid?: Static<typeof IsInvalidSchema>;
isReadOnly?: Static<typeof IsReadOnlySchema>; isReadOnly?: Static<typeof IsReadOnlySchema>;
isRequired?: Static<typeof IsRequiredSchema>; isRequired?: Static<typeof IsRequiredSchema>;
colorScheme?: Static<typeof ColorSchemePropertySchema>;
size?: Static<typeof SizePropertySchema>; size?: Static<typeof SizePropertySchema>;
isInValid?: Static<typeof IsInvalidSchema>;
spacing?: Static<typeof SpacingSchema>; spacing?: Static<typeof SpacingSchema>;
isChecked?: Static<typeof IsCheckedSchema>; colorScheme?: Static<typeof ColorSchemePropertySchema>;
isIndeterminate?: Static<typeof IsIndeterminateSchema>;
value?: Static<typeof ValueSchema>;
}> = ({ }> = ({
text, text,
value,
defaultIsChecked, defaultIsChecked,
isDisabled, isDisabled,
isFocusable, isFocusable,
isInValid,
isReadOnly, isReadOnly,
isRequired, isRequired,
colorScheme,
size, size,
isInValid,
spacing, spacing,
isChecked, colorScheme,
isIndeterminate,
value,
mergeState, mergeState,
}) => { }) => {
const [checked, setChecked] = useState(defaultIsChecked); const groupContext = useCheckboxGroupContext();
let _defaultIsChecked = false;
if (typeof defaultIsChecked === 'boolean') {
_defaultIsChecked = defaultIsChecked;
} else if (groupContext) {
_defaultIsChecked = groupContext.value.some(val => val === value);
}
const [checked, setChecked] = useState(_defaultIsChecked);
useEffect(() => { useEffect(() => {
mergeState({ value: text.raw }); mergeState({ text: text.raw });
}, [text.raw]); }, [text.raw]);
useEffect(() => { useEffect(() => {
mergeState({ value: checked }); mergeState({ value });
}, [value]);
useEffect(() => {
mergeState({ checked });
}, [checked]); }, [checked]);
const args: { const args: {
@ -73,17 +86,16 @@ const Checkbox: ComponentImplementation<{
return ( return (
<BaseCheckbox <BaseCheckbox
{...args} value={value}
defaultChecked={defaultIsChecked} defaultChecked={defaultIsChecked}
isDisabled={isDisabled} isDisabled={isDisabled}
isFocusable={isFocusable} isFocusable={isFocusable}
isInvalid={isInValid}
isReadOnly={isReadOnly} isReadOnly={isReadOnly}
isRequired={isRequired} isRequired={isRequired}
isInvalid={isInValid} size={size}
spacing={spacing} spacing={spacing}
isChecked={isChecked} colorScheme={colorScheme}
isIndeterminate={isIndeterminate}
value={value}
onChange={e => { onChange={e => {
setChecked(e.target.checked); setChecked(e.target.checked);
}}> }}>
@ -105,6 +117,10 @@ export default {
name: 'text', name: 'text',
...TextPropertySchema, ...TextPropertySchema,
}, },
{
name: 'value',
...ValueSchema,
},
{ {
name: 'defaultIsChecked', name: 'defaultIsChecked',
...DefaultIsCheckedSchema, ...DefaultIsCheckedSchema,
@ -117,6 +133,10 @@ export default {
name: 'isFocusable', name: 'isFocusable',
...IsFocusableSchema, ...IsFocusableSchema,
}, },
{
name: 'isInValid',
...IsInvalidSchema,
},
{ {
name: 'isReadOnly', name: 'isReadOnly',
...IsReadOnlySchema, ...IsReadOnlySchema,
@ -125,37 +145,21 @@ export default {
name: 'isRequired', name: 'isRequired',
...IsReadOnlySchema, ...IsReadOnlySchema,
}, },
{
name: 'colorScheme',
...ColorSchemePropertySchema,
},
{ {
name: 'size', name: 'size',
...SizePropertySchema, ...SizePropertySchema,
}, },
{
name: 'isInValid',
...IsInvalidSchema,
},
{ {
name: 'spacing', name: 'spacing',
...SpacingSchema, ...SpacingSchema,
}, },
{ {
name: 'isChecked', name: 'colorScheme',
...IsCheckedSchema, ...ColorSchemePropertySchema,
},
{
name: 'isIndeterminate',
...IsIndeterminateSchema,
},
{
name: 'value',
...ValueSchema,
}, },
], ],
acceptTraits: [], acceptTraits: [],
state: {}, state: StateSchema,
methods: [], methods: [],
}, },
}), }),

View File

@ -5,19 +5,20 @@ import { CheckboxGroup as BaseCheckboxGroup } from '@chakra-ui/react';
import { ComponentImplementation } from '../../registry'; import { ComponentImplementation } from '../../registry';
import Slot from '../_internal/Slot'; import Slot from '../_internal/Slot';
import { SizePropertySchema, IsDisabledSchema } from './Checkbox'; import { SizePropertySchema, IsDisabledSchema } from './Checkbox';
import { ColorSchemePropertySchema } from './Types/ColorScheme';
const DefaultValueSchema = Type.Optional( const DefaultValueSchema = Type.Optional(
Type.Array(Type.Union([Type.String(), Type.Number()])) Type.Array(Type.Union([Type.String(), Type.Number()]))
); );
const StateSchema = Type.Object({
value: Type.String(),
});
const CheckboxGroup: ComponentImplementation<{ const CheckboxGroup: ComponentImplementation<{
colorScheme?: Static<typeof ColorSchemePropertySchema>;
size?: Static<typeof SizePropertySchema>; size?: Static<typeof SizePropertySchema>;
defaultValue?: Static<typeof DefaultValueSchema>; defaultValue?: Static<typeof DefaultValueSchema>;
isDisabled?: Static<typeof IsDisabledSchema>; isDisabled?: Static<typeof IsDisabledSchema>;
}> = ({ }> = ({
colorScheme,
size, size,
defaultValue, defaultValue,
isDisabled, isDisabled,
@ -31,7 +32,6 @@ const CheckboxGroup: ComponentImplementation<{
return ( return (
<BaseCheckboxGroup <BaseCheckboxGroup
colorScheme={colorScheme}
size={size} size={size}
defaultValue={defaultValue} defaultValue={defaultValue}
isDisabled={isDisabled} isDisabled={isDisabled}
@ -50,10 +50,6 @@ export default {
}, },
spec: { spec: {
properties: [ properties: [
{
name: 'colorScheme',
...ColorSchemePropertySchema,
},
{ {
name: 'size', name: 'size',
...SizePropertySchema, ...SizePropertySchema,
@ -68,7 +64,7 @@ export default {
}, },
], ],
acceptTraits: [], acceptTraits: [],
state: {}, state: StateSchema,
methods: [], methods: [],
}, },
}), }),

View File

@ -0,0 +1,140 @@
import React, { useEffect } from 'react';
import { createComponent } from '@meta-ui/core';
import { Static, Type } from '@sinclair/typebox';
import { Radio as BaseRadio } from '@chakra-ui/react';
import { ComponentImplementation } from '../../registry';
import Text, { TextProps, TextPropertySchema } from '../_internal/Text';
import { ColorSchemePropertySchema } from './Types/ColorScheme';
const IsDisabledSchema = Type.Optional(Type.Boolean());
const IsFocusableSchema = Type.Optional(Type.Boolean());
const IsInvalidSchema = Type.Optional(Type.Boolean());
const IsReadOnlySchema = Type.Optional(Type.Boolean());
const IsRequiredSchema = Type.Optional(Type.Boolean());
const NameSchema = Type.Optional(Type.String());
const ValueSchema = Type.Union([Type.String(), Type.Number()]);
const SizePropertySchema = Type.KeyOf(
Type.Object({
sm: Type.String(),
md: Type.String(),
lg: Type.String(),
})
);
const SpacingSchema = Type.Optional(Type.String());
const StateSchema = Type.Object({
value: Type.String(),
});
const Radio: ComponentImplementation<{
text: TextProps['value'];
value: Static<typeof ValueSchema>;
isDisabled?: Static<typeof IsDisabledSchema>;
isFocusable?: Static<typeof IsFocusableSchema>;
isInValid?: Static<typeof IsInvalidSchema>;
isReadOnly?: Static<typeof IsReadOnlySchema>;
isRequired?: Static<typeof IsRequiredSchema>;
name?: Static<typeof NameSchema>;
size?: Static<typeof SizePropertySchema>;
spacing?: Static<typeof SpacingSchema>;
colorScheme?: Static<typeof ColorSchemePropertySchema>;
}> = ({
text,
value,
isDisabled,
isFocusable,
isInValid,
isReadOnly,
isRequired,
name,
size,
spacing,
colorScheme,
mergeState,
}) => {
useEffect(() => {
mergeState({ text: text.raw });
}, [text.raw]);
useEffect(() => {
mergeState({ value });
}, [value]);
return (
<BaseRadio
value={value}
isDisabled={isDisabled}
isFocusable={isFocusable}
isInvalid={isInValid}
isReadOnly={isReadOnly}
isRequired={isRequired}
name={name}
size={size}
spacing={spacing}
colorScheme={colorScheme}>
<Text value={text} />
</BaseRadio>
);
};
export default {
...createComponent({
version: 'chakra_ui/v1',
metadata: {
name: 'radio',
description: 'chakra-ui radio',
},
spec: {
properties: [
{
name: 'text',
...TextPropertySchema,
},
{
name: 'value',
...ValueSchema,
},
{
name: 'isDisabled',
...IsDisabledSchema,
},
{
name: 'isFocusable',
...IsFocusableSchema,
},
{
name: 'isInValid',
...IsInvalidSchema,
},
{
name: 'isReadOnly',
...IsReadOnlySchema,
},
{
name: 'isRequired',
...IsReadOnlySchema,
},
{
name: 'name',
...NameSchema,
},
{
name: 'size',
...SizePropertySchema,
},
{
name: 'spacing',
...SpacingSchema,
},
{
name: 'colorScheme',
...ColorSchemePropertySchema,
},
],
acceptTraits: [],
state: StateSchema,
methods: [],
},
}),
impl: Radio,
};

View File

@ -0,0 +1,56 @@
import React, { useState, useEffect } from 'react';
import { createComponent } from '@meta-ui/core';
import { Static, Type } from '@sinclair/typebox';
import { RadioGroup as BaseRadioGroup } from '@chakra-ui/react';
import { ComponentImplementation } from '../../registry';
import Slot from '../_internal/Slot';
const DefaultValueSchema = Type.Union([Type.String(), Type.Number()]);
const IsNumericalSchema = Type.Optional(Type.Boolean());
const StateSchema = Type.Object({
value: Type.String(),
});
const RadioGroup: ComponentImplementation<{
defaultValue?: Static<typeof DefaultValueSchema>;
isNumerical?: Static<typeof IsNumericalSchema>;
}> = ({ defaultValue, isNumerical, slotsMap, mergeState }) => {
const [value, setValue] = useState(defaultValue);
useEffect(() => {
mergeState({ value });
}, [value]);
return (
<BaseRadioGroup
value={value}
onChange={val => setValue(isNumerical ? Number(val) : val)}>
<Slot slotsMap={slotsMap} slot="content" />
</BaseRadioGroup>
);
};
export default {
...createComponent({
version: 'chakra_ui/v1',
metadata: {
name: 'radio_group',
description: 'chakra-ui radio group',
},
spec: {
properties: [
{
name: 'defaultValue',
...DefaultValueSchema,
},
{
name: 'isNumerical',
...IsNumericalSchema,
},
],
acceptTraits: [],
state: StateSchema,
methods: [],
},
}),
impl: RadioGroup,
};

View File

@ -35,6 +35,10 @@ const VariantSchema = Type.KeyOf(
}) })
); );
const StateSchema = Type.Object({
value: Type.String(),
});
const Select: ComponentImplementation<{ const Select: ComponentImplementation<{
options: Static<typeof OptionsSchema>; options: Static<typeof OptionsSchema>;
placeholder?: Static<typeof PlaceholderSchema>; placeholder?: Static<typeof PlaceholderSchema>;
@ -144,7 +148,7 @@ export default {
}, },
], ],
acceptTraits: [], acceptTraits: [],
state: {}, state: StateSchema,
methods: [], methods: [],
}, },
}), }),

View File

@ -31,6 +31,8 @@ import ChakraUIVStack from './components/chakra-ui/VStack';
import ChakraUIImage from './components/chakra-ui/Image'; import ChakraUIImage from './components/chakra-ui/Image';
import ChakraUIDialog from './components/chakra-ui/Dialog'; import ChakraUIDialog from './components/chakra-ui/Dialog';
import ChakraUISelect from './components/chakra-ui/Select'; import ChakraUISelect from './components/chakra-ui/Select';
import ChakraUIRadioGroup from './components/chakra-ui/RadioGroup';
import ChakraUIRadio from './components/chakra-ui/Radio';
/* --- lab --- */ /* --- lab --- */
import LabEditor from './components/lab/Editor'; import LabEditor from './components/lab/Editor';
// traits // traits
@ -158,6 +160,8 @@ registry.registerComponent(ChakraUIVStack);
registry.registerComponent(ChakraUIImage); registry.registerComponent(ChakraUIImage);
registry.registerComponent(ChakraUIDialog); registry.registerComponent(ChakraUIDialog);
registry.registerComponent(ChakraUISelect); registry.registerComponent(ChakraUISelect);
registry.registerComponent(ChakraUIRadioGroup);
registry.registerComponent(ChakraUIRadio);
registry.registerComponent(LabEditor); registry.registerComponent(LabEditor);
registry.registerComponent(CoreRouter); registry.registerComponent(CoreRouter);
registry.registerComponent(CoreDummy); registry.registerComponent(CoreDummy);