feat: implement core space component

This commit is contained in:
xzdry 2022-02-28 10:07:06 +08:00
parent df5409c180
commit 065cdf438b
4 changed files with 167 additions and 0 deletions

View File

@ -0,0 +1,101 @@
import React, { ReactNode } from 'react';
import { css, CSSObject } from '@emotion/css';
import { Static, Type } from '@sinclair/typebox';
import { StringUnion } from '../../utils/stringUnion';
export const SpacePropertySchema = Type.Object({
align: StringUnion(['start', 'end', 'center', 'baseline'],{
title:'Align',
category:'Layout'
}),
direction: StringUnion(['vertical', 'horizontal'],{
title:'Direction',
category:'Layout'
}),
justifyContent: StringUnion([
'flex-start',
'flex-end',
'center',
'space-between',
'space-around',
],{
title:'Justify Content',
category:'Layout'
}),
size: Type.Union([StringUnion(['mini', 'small', 'middle', 'large']), Type.Number()],{
title:'Size',
category:'Layout'
}),
wrap: Type.Boolean({
title:'Wrap',
category:'Layout',
description:'Auto wrap line, when horizontal effective'
}),
});
export type SpaceProps = Static<typeof SpacePropertySchema> & {
cssStyle?: string;
};
const spaceSize = {
mini: 4,
small: 8,
middle: 16,
large: 24,
};
type SpaceSize = SpaceProps['size'];
function getNumberSize(size: SpaceSize) {
return typeof size === 'string' ? spaceSize[size] : size || 0;
}
const Space = React.forwardRef<HTMLDivElement, SpaceProps & { children: ReactNode }>(
(
{
cssStyle,
align,
direction = 'horizontal',
size = 'small',
children,
wrap,
justifyContent,
},
ref
) => {
const [horizontalSize, verticalSize] = React.useMemo(
() =>
((Array.isArray(size) ? size : [size, size]) as [SpaceSize, SpaceSize]).map(
item => getNumberSize(item)
),
[size]
);
const style: CSSObject = {
alignItems: align,
justifyContent,
flexDirection: direction === 'vertical' ? 'column' : 'row',
display: 'inline-flex',
columnGap: horizontalSize,
rowGap: verticalSize,
};
if (wrap) {
style.flexWrap = 'wrap';
}
return (
<div
ref={ref}
className={css`
${style}
${cssStyle}
`}
>
{children}
</div>
);
}
);
export default Space;

View File

@ -0,0 +1,41 @@
import { Type } from '@sinclair/typebox';
import _Space, { SpacePropertySchema } from '../_internal/Space';
import { implementRuntimeComponent } from '../../utils/buildKit';
const StateSchema = Type.Object({});
export default implementRuntimeComponent({
version: 'core/v1',
metadata: {
name: 'space',
displayName: 'Space',
description: '',
isDraggable: true,
isResizable: false,
exampleProperties: {
size: 'small',
direction: 'horizontal',
align: 'start',
wrap: '',
justifyContent:''
},
exampleSize: [4, 1],
annotations: {
category: 'Layout',
},
},
spec: {
properties: SpacePropertySchema,
state: StateSchema,
methods: {},
slots: ['content'],
styleSlots: ['content'],
events: [],
},
})(({ customStyle, elementRef, slotsElements, ...restProps }) => {
return (
<_Space cssStyle={customStyle?.content} ref={elementRef} {...restProps}>
{slotsElements.content}
</_Space>
);
});

View File

@ -7,6 +7,8 @@ import CoreGridLayout from '../components/core/GridLayout';
import CoreRouter from '../components/core/Router';
import CoreDummy from '../components/core/Dummy';
import CoreModuleContainer from '../components/core/ModuleContainer';
import CoreSpace from '../components/core/Space';
// traits
import CoreArrayState from '../traits/core/ArrayState';
@ -211,6 +213,7 @@ export function initRegistry(apiService: ApiService): Registry {
registry.registerComponent(CoreRouter);
registry.registerComponent(CoreDummy);
registry.registerComponent(CoreModuleContainer);
registry.registerComponent(CoreSpace);
registry.registerTrait(CoreState);
registry.registerTrait(CoreArrayState);

View File

@ -0,0 +1,22 @@
import { TLiteral, Type } from "@sinclair/typebox";
export type IntoStringUnion<T> = {
[K in keyof T]: T[K] extends string ? TLiteral<T[K]> : never;
};
export function StringUnion<T extends string[]>(values: [...T], options?: any) {
return Type.KeyOf(
Type.Object(
values.reduce((prev, cur) => {
prev[cur] = Type.Boolean();
return prev;
}, {} as Record<T[number], any>)
), {
title: options?.title,
description: options?.description,
category: options?.category,
weight: options?.weight
}
);
}