mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
Merge pull request #507 from smartxworks/feat/arco
Add NumberInput、Tag、Carousel component
This commit is contained in:
commit
cc3f699407
90
packages/arco-lib/src/components/Carousel.tsx
Normal file
90
packages/arco-lib/src/components/Carousel.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
import { Carousel as BaseCarousel } from '@arco-design/web-react';
|
||||
import { implementRuntimeComponent } from '@sunmao-ui/runtime';
|
||||
import { css } from '@emotion/css';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { CarouselPropsSpec as BaseCarouselPropsSpec } from '../generated/types/Carousel';
|
||||
import { useRef, useEffect } from 'react';
|
||||
import { CarouselHandle } from '@arco-design/web-react/es/Carousel/interface';
|
||||
|
||||
const InputPropsSpec = Type.Object({
|
||||
...BaseCarouselPropsSpec,
|
||||
});
|
||||
const InputStateSpec = Type.Object({
|
||||
value: Type.Number(),
|
||||
});
|
||||
|
||||
const defaultCarouselStyle = css`
|
||||
height: 240px;
|
||||
`;
|
||||
|
||||
const exampleProperties: Static<typeof InputPropsSpec> = {
|
||||
imageSrc: [
|
||||
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/cd7a1aaea8e1c5e3d26fe2591e561798.png~tplv-uwbnlip3yd-webp.webp',
|
||||
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/6480dbc69be1b5de95010289787d64f1.png~tplv-uwbnlip3yd-webp.webp',
|
||||
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/0265a04fddbd77a19602a15d9d55d797.png~tplv-uwbnlip3yd-webp.webp',
|
||||
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/24e0dd27418d2291b65db1b21aa62254.png~tplv-uwbnlip3yd-webp.webp',
|
||||
],
|
||||
indicatorPosition: 'bottom',
|
||||
indicatorType: 'dot',
|
||||
showArrow: 'always',
|
||||
direction: 'horizontal',
|
||||
animation: 'slide',
|
||||
autoPlay: false,
|
||||
autoPlayInterval: 3000,
|
||||
autoPlayHoverToPause: true,
|
||||
moveSpeed: 500,
|
||||
timingFunc: 'cubic-bezier(0.34, 0.69, 0.1, 1)',
|
||||
};
|
||||
|
||||
export const Carousel = implementRuntimeComponent({
|
||||
version: 'arco/v1',
|
||||
metadata: {
|
||||
...FALLBACK_METADATA,
|
||||
name: 'carousel',
|
||||
displayName: 'Carousel',
|
||||
exampleProperties,
|
||||
annotations: {
|
||||
category: 'Data Display',
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
properties: InputPropsSpec,
|
||||
state: InputStateSpec,
|
||||
methods: {},
|
||||
slots: {},
|
||||
styleSlots: ['carousel', 'image'],
|
||||
events: ['onChange', 'onBlur', 'onFocus'],
|
||||
},
|
||||
})(props => {
|
||||
const { getElement, customStyle } = props;
|
||||
const { imageSrc, autoPlay, autoPlayHoverToPause, autoPlayInterval, ...cProps } =
|
||||
getComponentProps(props);
|
||||
const ref = useRef<CarouselHandle>(null as any);
|
||||
|
||||
useEffect(() => {
|
||||
const ele = ref.current?.dom;
|
||||
if (getElement && ele) {
|
||||
getElement(ele);
|
||||
}
|
||||
}, [getElement, ref]);
|
||||
|
||||
return (
|
||||
<BaseCarousel
|
||||
carousel={ref}
|
||||
autoPlay={
|
||||
autoPlay && { interval: autoPlayInterval, hoverToPause: autoPlayHoverToPause }
|
||||
}
|
||||
className={css(customStyle?.carousel, defaultCarouselStyle)}
|
||||
{...cProps}
|
||||
>
|
||||
{imageSrc.map((src, idx) => {
|
||||
return (
|
||||
<div className={css(customStyle?.image)} key={idx}>
|
||||
<img style={{ width: '100%' }} src={src} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</BaseCarousel>
|
||||
);
|
||||
});
|
97
packages/arco-lib/src/components/NumberInput.tsx
Normal file
97
packages/arco-lib/src/components/NumberInput.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
import { InputNumber } from '@arco-design/web-react';
|
||||
import { implementRuntimeComponent } from '@sunmao-ui/runtime';
|
||||
import { css } from '@emotion/css';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { NumberInputPropsSpec as BaseNumberInputPropsSpec } from '../generated/types/NumberInput';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { RefInputType } from '@arco-design/web-react/es/Input/interface';
|
||||
import { useStateValue } from 'src/hooks/useStateValue';
|
||||
|
||||
const InputPropsSpec = Type.Object({
|
||||
...BaseNumberInputPropsSpec,
|
||||
});
|
||||
const InputStateSpec = Type.Object({
|
||||
value: Type.Number(),
|
||||
});
|
||||
|
||||
const exampleProperties: Static<typeof InputPropsSpec> = {
|
||||
defaultValue: 1,
|
||||
disabled: false,
|
||||
placeholder: 'please input',
|
||||
error: false,
|
||||
size: 'default',
|
||||
buttonMode: false,
|
||||
min: 0,
|
||||
max: 5,
|
||||
readOnly: false,
|
||||
step: 1,
|
||||
precision: 1,
|
||||
updateWhenDefaultValueChanges: false,
|
||||
};
|
||||
|
||||
export const NumberInput = implementRuntimeComponent({
|
||||
version: 'arco/v1',
|
||||
metadata: {
|
||||
...FALLBACK_METADATA,
|
||||
name: 'numberInput',
|
||||
displayName: 'Number Input',
|
||||
exampleProperties,
|
||||
annotations: {
|
||||
category: 'Data Entry',
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
properties: InputPropsSpec,
|
||||
state: InputStateSpec,
|
||||
methods: {},
|
||||
slots: {
|
||||
prefix: { slotProps: Type.Object({}) },
|
||||
suffix: { slotProps: Type.Object({}) },
|
||||
},
|
||||
styleSlots: ['input'],
|
||||
events: ['onChange', 'onBlur', 'onFocus'],
|
||||
},
|
||||
})(props => {
|
||||
const { getElement, slotsElements, customStyle, callbackMap, mergeState } = props;
|
||||
const { buttonMode, defaultValue, updateWhenDefaultValueChanges, ...cProps } =
|
||||
getComponentProps(props);
|
||||
const [value, setValue] = useStateValue(
|
||||
defaultValue,
|
||||
mergeState,
|
||||
updateWhenDefaultValueChanges
|
||||
);
|
||||
const ref = useRef<RefInputType | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const ele = ref.current?.dom;
|
||||
if (getElement && ele) {
|
||||
getElement(ele);
|
||||
}
|
||||
}, [getElement, ref]);
|
||||
|
||||
return (
|
||||
<InputNumber
|
||||
ref={ref}
|
||||
className={css(customStyle?.input)}
|
||||
onChange={value => {
|
||||
setValue(value);
|
||||
mergeState({
|
||||
value,
|
||||
});
|
||||
callbackMap?.onChange?.();
|
||||
}}
|
||||
onBlur={() => {
|
||||
callbackMap?.onBlur?.();
|
||||
}}
|
||||
onFocus={() => {
|
||||
callbackMap?.onFocus?.();
|
||||
}}
|
||||
value={value}
|
||||
{...cProps}
|
||||
prefix={slotsElements.prefix ? slotsElements.prefix({}) : null}
|
||||
suffix={slotsElements.suffix ? slotsElements.suffix({}) : null}
|
||||
mode={buttonMode ? 'button' : 'embed'}
|
||||
/>
|
||||
);
|
||||
});
|
92
packages/arco-lib/src/components/Tag.tsx
Normal file
92
packages/arco-lib/src/components/Tag.tsx
Normal file
@ -0,0 +1,92 @@
|
||||
import { Tag as BaseTag } from '@arco-design/web-react';
|
||||
import { implementRuntimeComponent } from '@sunmao-ui/runtime';
|
||||
import { css } from '@emotion/css';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { TagPropsSpec as BaseTagPropsSpec } from '../generated/types/Tag';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const TagPropsSpec = Type.Object(BaseTagPropsSpec);
|
||||
const TagStateSpec = Type.Object({
|
||||
checked: Type.Boolean(),
|
||||
});
|
||||
|
||||
const exampleProperties: Static<typeof TagPropsSpec> = {
|
||||
content: 'tag',
|
||||
closable: false,
|
||||
checkable: false,
|
||||
defaultChecked: false,
|
||||
color: '',
|
||||
size: 'large',
|
||||
bordered: false,
|
||||
defaultVisible: true,
|
||||
};
|
||||
|
||||
export const Tag = implementRuntimeComponent({
|
||||
version: 'arco/v1',
|
||||
metadata: {
|
||||
...FALLBACK_METADATA,
|
||||
name: 'tag',
|
||||
displayName: 'Tag',
|
||||
exampleProperties,
|
||||
annotations: {
|
||||
category: 'Data Display',
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
properties: TagPropsSpec,
|
||||
state: TagStateSpec,
|
||||
methods: {},
|
||||
slots: {
|
||||
content: {
|
||||
slotProps: Type.Object({}),
|
||||
},
|
||||
icon: {
|
||||
slotProps: Type.Object({}),
|
||||
},
|
||||
},
|
||||
styleSlots: ['content'],
|
||||
events: ['onCheck', 'onClose'],
|
||||
},
|
||||
})(props => {
|
||||
const { content, defaultChecked, defaultVisible, checkable, ...cProps } =
|
||||
getComponentProps(props);
|
||||
const { slotsElements, customStyle, elementRef, callbackMap, mergeState } = props;
|
||||
|
||||
const [checked, setChecked] = useState<boolean | undefined>(defaultChecked);
|
||||
const [visible, setVisible] = useState(defaultVisible);
|
||||
useEffect(() => {
|
||||
if (!checkable) {
|
||||
setChecked(undefined);
|
||||
mergeState({ checked: undefined });
|
||||
} else {
|
||||
setChecked(defaultChecked);
|
||||
mergeState({ checked: defaultChecked });
|
||||
}
|
||||
}, [checkable, defaultChecked, mergeState, setChecked]);
|
||||
|
||||
return (
|
||||
<BaseTag
|
||||
checked={checked}
|
||||
className={css(customStyle?.content)}
|
||||
ref={elementRef}
|
||||
checkable={checkable}
|
||||
visible={visible}
|
||||
onCheck={() => {
|
||||
setChecked(prev => !prev);
|
||||
mergeState({ checked: !checked });
|
||||
callbackMap?.onCheck?.();
|
||||
}}
|
||||
onClose={() => {
|
||||
setVisible(false);
|
||||
setChecked(undefined);
|
||||
mergeState({ checked: undefined });
|
||||
callbackMap?.onClose?.();
|
||||
}}
|
||||
icon={slotsElements.icon ? slotsElements.icon({}) : null}
|
||||
{...cProps}
|
||||
>
|
||||
{(slotsElements.content && slotsElements.content({})) || content}
|
||||
</BaseTag>
|
||||
);
|
||||
});
|
62
packages/arco-lib/src/generated/types/Carousel.ts
Normal file
62
packages/arco-lib/src/generated/types/Carousel.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { Category } from '../../constants/category';
|
||||
import { StringUnion } from '../../sunmao-helper';
|
||||
|
||||
export const CarouselPropsSpec = {
|
||||
imageSrc: Type.Array(Type.String(), {
|
||||
title: 'Image Src',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
indicatorType: StringUnion(['dot', 'line', 'slider'], {
|
||||
title: 'Indicator Type',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
indicatorPosition: StringUnion(['left', 'right', 'top', 'bottom', 'outer'], {
|
||||
title: 'Indicator Type',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
direction: StringUnion(['vertical', 'horizontal'], {
|
||||
title: 'Direction',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
showArrow: StringUnion(['always', 'hover', 'never'], {
|
||||
title: 'Show Arrow',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
animation: StringUnion(['slide', 'card', 'fade'], {
|
||||
title: 'Animation',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
moveSpeed: Type.Number({
|
||||
title: 'Move Speed',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
trigger: Type.Optional(
|
||||
StringUnion(['click', 'hover'], {
|
||||
title: 'Trigger',
|
||||
category: Category.Behavior,
|
||||
})
|
||||
),
|
||||
autoPlay: Type.Boolean({
|
||||
title: 'Auto Play',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
autoPlayInterval: Type.Optional(
|
||||
Type.Number({
|
||||
title: 'Auto Play Interval',
|
||||
category: Category.Behavior,
|
||||
conditions: [{ key: 'autoPlay', value: true }],
|
||||
})
|
||||
),
|
||||
autoPlayHoverToPause: Type.Optional(
|
||||
Type.Boolean({
|
||||
title: 'Auto Play Hover To Pause',
|
||||
category: Category.Behavior,
|
||||
conditions: [{ key: 'autoPlay', value: true }],
|
||||
})
|
||||
),
|
||||
timingFunc: Type.String({
|
||||
title: 'Timing Func',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
};
|
54
packages/arco-lib/src/generated/types/NumberInput.ts
Normal file
54
packages/arco-lib/src/generated/types/NumberInput.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { StringUnion } from '../../sunmao-helper';
|
||||
import { Category } from '../../constants/category';
|
||||
|
||||
export const NumberInputPropsSpec = {
|
||||
defaultValue: Type.Number({
|
||||
title: 'Default Value',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
updateWhenDefaultValueChanges: Type.Boolean({
|
||||
title: 'Update When Default Value Changes',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
min: Type.Number({
|
||||
title: 'Min',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
max: Type.Number({
|
||||
title: 'Max',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
placeholder: Type.String({
|
||||
title: 'Placeholder',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
disabled: Type.Boolean({
|
||||
title: 'Disabled',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
buttonMode: Type.Boolean({
|
||||
title: 'Button Mode',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
precision: Type.Number({
|
||||
title: 'Precision',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
step: Type.Number({
|
||||
title: 'Step',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
size: StringUnion(['default', 'mini', 'small', 'large'], {
|
||||
title: 'Size',
|
||||
category: Category.Style,
|
||||
}),
|
||||
readOnly: Type.Boolean({
|
||||
title: 'Read Only',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
error: Type.Boolean({
|
||||
title: 'Error',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
};
|
40
packages/arco-lib/src/generated/types/Tag.ts
Normal file
40
packages/arco-lib/src/generated/types/Tag.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { Category } from '../../constants/category';
|
||||
import { StringUnion } from '../../sunmao-helper';
|
||||
|
||||
export const TagPropsSpec = {
|
||||
content: Type.String({
|
||||
title: 'Content',
|
||||
category: Category.Basic,
|
||||
}),
|
||||
closable: Type.Boolean({
|
||||
title: 'Closable',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
checkable: Type.Boolean({
|
||||
title: 'Checkable',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
defaultChecked: Type.Boolean({
|
||||
title: 'Default Checked',
|
||||
category: Category.Behavior,
|
||||
conditions: [{ key: 'checkable', value: true }],
|
||||
}),
|
||||
defaultVisible: Type.Boolean({
|
||||
title: 'Default Visible',
|
||||
category: Category.Behavior,
|
||||
}),
|
||||
color: Type.String({
|
||||
title: 'Color',
|
||||
category: Category.Style,
|
||||
widget: 'core/v1/color',
|
||||
}),
|
||||
size: StringUnion(['large', 'medium', 'default', 'small'], {
|
||||
title: 'Size',
|
||||
category: Category.Style,
|
||||
}),
|
||||
bordered: Type.Boolean({
|
||||
title: 'Bordered',
|
||||
category: Category.Style,
|
||||
}),
|
||||
};
|
@ -31,6 +31,7 @@ import { Alert } from './components/Alert';
|
||||
import { Link } from './components/Link';
|
||||
import { Switch } from './components/Switch';
|
||||
import { PasswordInput } from './components/PasswordInput';
|
||||
import { NumberInput } from './components/NumberInput';
|
||||
import { TextArea } from './components/TextArea';
|
||||
import { Tabs } from './components/Tabs';
|
||||
import { FormControl } from './components/Form/FormControl';
|
||||
@ -39,11 +40,14 @@ import { Row, Col } from './components/Grid';
|
||||
import { Slider } from './components/Slider';
|
||||
import { DatePicker } from './components/DatePicker';
|
||||
import { TimePicker } from './components/TimePicker';
|
||||
import { Carousel } from './components/Carousel';
|
||||
import { Tag } from './components/Tag';
|
||||
|
||||
import './style.css';
|
||||
import { MessageUtilMethodFactory } from './methods/Message';
|
||||
|
||||
export const components: SunmaoLib['components'] = [
|
||||
Tag,
|
||||
Table,
|
||||
Pagination,
|
||||
Steps,
|
||||
@ -86,6 +90,8 @@ export const components: SunmaoLib['components'] = [
|
||||
Slider,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
NumberInput,
|
||||
Carousel,
|
||||
];
|
||||
export const traits: SunmaoLib['traits'] = [];
|
||||
export const modules: SunmaoLib['modules'] = [];
|
||||
|
Loading…
Reference in New Issue
Block a user