diff --git a/packages/runtime/src/components/_internal/Space.tsx b/packages/runtime/src/components/_internal/Space.tsx new file mode 100644 index 00000000..deaadfa3 --- /dev/null +++ b/packages/runtime/src/components/_internal/Space.tsx @@ -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 & { + 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( + ( + { + 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 ( +
+ {children} +
+ ); + } +); + +export default Space; diff --git a/packages/runtime/src/components/core/Space.tsx b/packages/runtime/src/components/core/Space.tsx new file mode 100644 index 00000000..a77783d5 --- /dev/null +++ b/packages/runtime/src/components/core/Space.tsx @@ -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} + + ); +}); diff --git a/packages/runtime/src/services/Registry.tsx b/packages/runtime/src/services/Registry.tsx index 5114df8d..b80cb169 100644 --- a/packages/runtime/src/services/Registry.tsx +++ b/packages/runtime/src/services/Registry.tsx @@ -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); diff --git a/packages/runtime/src/utils/stringUnion.ts b/packages/runtime/src/utils/stringUnion.ts new file mode 100644 index 00000000..61ec3a12 --- /dev/null +++ b/packages/runtime/src/utils/stringUnion.ts @@ -0,0 +1,22 @@ +import { TLiteral, Type } from "@sinclair/typebox"; + + +export type IntoStringUnion = { + [K in keyof T]: T[K] extends string ? TLiteral : never; +}; + +export function StringUnion(values: [...T], options?: any) { + return Type.KeyOf( + Type.Object( + values.reduce((prev, cur) => { + prev[cur] = Type.Boolean(); + return prev; + }, {} as Record) + ), { + title: options?.title, + description: options?.description, + category: options?.category, + weight: options?.weight + } + ); +} \ No newline at end of file