mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-02-17 17:40:31 +08:00
feat(runtime): remove react-grid-layout
BREAKING CHANGE: remove core/v1/grid-layout component BREAKING CHANGE: remove core/v1/grid-layout component (+1 squashed commit) Squashed commits: [549fea0] feat(remove react-grid-layout): wip BREAKING CHANGE: remove core/v1/grid-layout component
This commit is contained in:
parent
fd60c796db
commit
fe68def8da
@ -1,124 +0,0 @@
|
||||
{
|
||||
"app": {
|
||||
"kind": "Application",
|
||||
"version": "example/v1",
|
||||
"metadata": {
|
||||
"name": "basic_grid_layout",
|
||||
"description": "basic grid layout example"
|
||||
},
|
||||
"spec": {
|
||||
"components": [
|
||||
{
|
||||
"id": "root",
|
||||
"type": "chakra_ui/v1/root",
|
||||
"properties": {},
|
||||
"traits": []
|
||||
},
|
||||
{
|
||||
"id": "grid",
|
||||
"type": "core/v1/grid_layout",
|
||||
"properties": {
|
||||
"layout": [
|
||||
{
|
||||
"w": 8,
|
||||
"h": 1,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"i": "input"
|
||||
},
|
||||
{
|
||||
"w": 4,
|
||||
"h": 9,
|
||||
"x": 0,
|
||||
"y": 2,
|
||||
"i": "box1",
|
||||
"moved": false,
|
||||
"static": false
|
||||
},
|
||||
{
|
||||
"w": 2,
|
||||
"h": 12,
|
||||
"x": 8,
|
||||
"y": 0,
|
||||
"i": "box2",
|
||||
"moved": false,
|
||||
"static": false
|
||||
},
|
||||
{
|
||||
"w": 3,
|
||||
"h": 1,
|
||||
"x": 3,
|
||||
"y": 11,
|
||||
"i": "component0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"traits": [
|
||||
{
|
||||
"type": "core/v1/slot",
|
||||
"properties": { "container": { "id": "root", "slot": "root" } }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "input",
|
||||
"type": "chakra_ui/v1/input",
|
||||
"properties": {
|
||||
"variant": "filled",
|
||||
"placeholder": "This a example",
|
||||
"colorScheme": "pink",
|
||||
"focusBorderColor": "pink.500",
|
||||
"isDisabled": false,
|
||||
"isRequired": true,
|
||||
"left": { "type": "addon", "children": "https://" },
|
||||
"right": {
|
||||
"type": "element",
|
||||
"children": ".com",
|
||||
"color": "red",
|
||||
"fontSize": "16px"
|
||||
}
|
||||
},
|
||||
"traits": [
|
||||
{
|
||||
"type": "core/v1/slot",
|
||||
"properties": { "container": { "id": "grid", "slot": "content" } }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "box1",
|
||||
"type": "chakra_ui/v1/box",
|
||||
"properties": {},
|
||||
"traits": [
|
||||
{
|
||||
"type": "core/v1/slot",
|
||||
"properties": { "container": { "id": "grid", "slot": "content" } }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "box2",
|
||||
"type": "chakra_ui/v1/box",
|
||||
"properties": { "bgColor": "pink", "w": "100%", "h": "100%" },
|
||||
"traits": [
|
||||
{
|
||||
"type": "core/v1/slot",
|
||||
"properties": { "container": { "id": "grid", "slot": "content" } }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "component0",
|
||||
"type": "chakra_ui/v1/button",
|
||||
"properties": { "text": { "raw": "Submit" } },
|
||||
"traits": [
|
||||
{
|
||||
"type": "core/v1/slot",
|
||||
"properties": { "container": { "id": "grid", "slot": "content" } }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -12,14 +12,11 @@ export const Row = implementRuntimeComponent({
|
||||
name: 'row',
|
||||
displayName: 'Row',
|
||||
description: '',
|
||||
isDraggable: false,
|
||||
isResizable: false,
|
||||
exampleProperties: {
|
||||
gutter: 16,
|
||||
align: 'start',
|
||||
justify: 'start',
|
||||
},
|
||||
exampleSize: [1, 1],
|
||||
annotations: {
|
||||
category: 'Layout',
|
||||
},
|
||||
@ -55,8 +52,6 @@ export const Col = implementRuntimeComponent({
|
||||
name: 'col',
|
||||
displayName: 'Col',
|
||||
description: '',
|
||||
isDraggable: false,
|
||||
isResizable: false,
|
||||
exampleProperties: {
|
||||
offset: 0,
|
||||
pull: 0,
|
||||
@ -64,7 +59,6 @@ export const Col = implementRuntimeComponent({
|
||||
span: 12,
|
||||
order: 0,
|
||||
},
|
||||
exampleSize: [1, 1],
|
||||
annotations: {
|
||||
category: 'Layout',
|
||||
},
|
||||
|
@ -28,10 +28,7 @@ export const FALLBACK_METADATA: ComponentMetadata = {
|
||||
name: '',
|
||||
description: '',
|
||||
displayName: '',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {},
|
||||
exampleSize: [1, 1],
|
||||
};
|
||||
|
||||
export const getComponentProps = <
|
||||
@ -51,7 +48,6 @@ export const getComponentProps = <
|
||||
childrenMap,
|
||||
services,
|
||||
app,
|
||||
gridCallbacks,
|
||||
customStyle,
|
||||
callbackMap,
|
||||
mergeState,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { Box as BaseBox } from '@chakra-ui/react';
|
||||
import { implementRuntimeComponent, GRID_HEIGHT } from '@sunmao-ui/runtime';
|
||||
import { implementRuntimeComponent } from '@sunmao-ui/runtime';
|
||||
import { pick } from 'lodash-es';
|
||||
import { css } from '@emotion/css';
|
||||
import { LAYOUT, BACKGROUND, BORDER } from './constants/category';
|
||||
@ -108,12 +108,10 @@ export default implementRuntimeComponent({
|
||||
metadata: {
|
||||
name: 'box',
|
||||
displayName: 'Box',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
description: 'chakra-ui box',
|
||||
exampleProperties: {
|
||||
w: GRID_HEIGHT,
|
||||
h: GRID_HEIGHT,
|
||||
w: 0,
|
||||
h: 0,
|
||||
minW: '',
|
||||
maxW: '',
|
||||
minH: '',
|
||||
@ -135,7 +133,6 @@ export default implementRuntimeComponent({
|
||||
border: '1px solid black',
|
||||
borderRadius: '',
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: LAYOUT,
|
||||
},
|
||||
|
@ -29,8 +29,6 @@ export default implementRuntimeComponent({
|
||||
name: 'button',
|
||||
displayName: 'Button',
|
||||
description: 'chakra-ui button',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
text: {
|
||||
raw: 'text',
|
||||
@ -39,7 +37,6 @@ export default implementRuntimeComponent({
|
||||
isLoading: false,
|
||||
colorScheme: 'blue',
|
||||
},
|
||||
exampleSize: [2, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -73,8 +73,6 @@ export default implementRuntimeComponent({
|
||||
name: 'checkbox',
|
||||
description: 'chakra-ui checkbox',
|
||||
displayName: 'Checkbox',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
text: {
|
||||
raw: 'Checkbox',
|
||||
@ -91,7 +89,6 @@ export default implementRuntimeComponent({
|
||||
spacing: '',
|
||||
colorScheme: 'blue',
|
||||
},
|
||||
exampleSize: [3, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -27,14 +27,11 @@ export default implementRuntimeComponent({
|
||||
name: 'checkbox_group',
|
||||
displayName: 'Checkbox Group',
|
||||
description: 'chakra-ui checkbox group',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
size: '',
|
||||
isDisabled: false,
|
||||
defaultValue: [],
|
||||
},
|
||||
exampleSize: [3, 3],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -53,15 +53,12 @@ export default implementRuntimeComponent({
|
||||
name: 'dialog',
|
||||
displayName: 'Dialog',
|
||||
description: 'chakra_ui dialog',
|
||||
isDraggable: false,
|
||||
isResizable: false,
|
||||
exampleProperties: {
|
||||
title: 'Dialog',
|
||||
confirmButton: 'Confirm',
|
||||
cancelButton: 'Cancel',
|
||||
disableConfirm: false,
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -9,10 +9,7 @@ export default implementRuntimeComponent({
|
||||
name: 'divider',
|
||||
displayName: 'Divider',
|
||||
description: 'chakra-ui divider',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {},
|
||||
exampleSize: [4, 1],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -18,12 +18,9 @@ export default implementRuntimeComponent({
|
||||
name: 'form',
|
||||
displayName: 'Form',
|
||||
description: 'chakra-ui form',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
hideSubmit: false,
|
||||
},
|
||||
exampleSize: [4, 6],
|
||||
annotations: {
|
||||
category: 'Layout',
|
||||
},
|
||||
|
@ -42,8 +42,6 @@ export default implementRuntimeComponent({
|
||||
version: 'chakra_ui/v1',
|
||||
metadata: {
|
||||
name: 'formControl',
|
||||
isResizable: false,
|
||||
isDraggable: true,
|
||||
displayName: 'Form Control',
|
||||
description: 'chakra-ui formControl',
|
||||
exampleProperties: {
|
||||
@ -52,7 +50,6 @@ export default implementRuntimeComponent({
|
||||
isRequired: false,
|
||||
helperText: '',
|
||||
},
|
||||
exampleSize: [4, 2],
|
||||
annotations: {
|
||||
category: 'Layout',
|
||||
},
|
||||
|
@ -31,9 +31,6 @@ export default implementRuntimeComponent({
|
||||
justify: '',
|
||||
spacing: '24px',
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
annotations: {
|
||||
category: 'Layout',
|
||||
},
|
||||
|
@ -136,8 +136,6 @@ export default implementRuntimeComponent({
|
||||
name: 'image',
|
||||
displayName: 'Image',
|
||||
description: 'chakra_ui image',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
src: 'https://bit.ly/dan-abramov',
|
||||
fallbackSrc: 'https://via.placeholder.com/150',
|
||||
@ -150,7 +148,6 @@ export default implementRuntimeComponent({
|
||||
htmlWidth: '',
|
||||
borderRadius: 5,
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -108,8 +108,6 @@ export default implementRuntimeComponent({
|
||||
name: 'input',
|
||||
displayName: 'Input',
|
||||
description: 'chakra_ui input',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
variant: 'outline',
|
||||
placeholder: 'Please input value',
|
||||
@ -119,7 +117,6 @@ export default implementRuntimeComponent({
|
||||
isRequired: false,
|
||||
defaultValue: '',
|
||||
},
|
||||
exampleSize: [4, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -18,15 +18,12 @@ export default implementRuntimeComponent({
|
||||
name: 'kbd',
|
||||
displayName: 'Kbd',
|
||||
description: 'chakra-ui keyboard',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
text: {
|
||||
raw: 'enter',
|
||||
format: 'plain',
|
||||
},
|
||||
},
|
||||
exampleSize: [2, 1],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -24,8 +24,6 @@ export default implementRuntimeComponent({
|
||||
name: 'link',
|
||||
displayName: 'Link',
|
||||
description: 'chakra-ui link',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
text: {
|
||||
raw: 'link',
|
||||
@ -34,7 +32,6 @@ export default implementRuntimeComponent({
|
||||
href: 'https://www.google.com',
|
||||
isExternal: false,
|
||||
},
|
||||
exampleSize: [2, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -38,10 +38,7 @@ export default implementRuntimeComponent({
|
||||
name: 'list',
|
||||
description: 'chakra-ui list',
|
||||
displayName: 'List',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties,
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -103,10 +103,7 @@ export default implementRuntimeComponent({
|
||||
name: 'multiSelect',
|
||||
displayName: 'MultiSelect',
|
||||
description: 'chakra-ui MultiSelect',
|
||||
isResizable: true,
|
||||
isDraggable: true,
|
||||
exampleProperties,
|
||||
exampleSize: [4, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -118,8 +118,6 @@ export default implementRuntimeComponent({
|
||||
name: 'numberInput',
|
||||
description: 'chakra_ui number input',
|
||||
displayName: 'Number Input',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
defaultValue: 0,
|
||||
min: Number.MIN_SAFE_INTEGER,
|
||||
@ -130,7 +128,6 @@ export default implementRuntimeComponent({
|
||||
allowMouseWheel: false,
|
||||
size: 'md',
|
||||
},
|
||||
exampleSize: [4, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -67,8 +67,6 @@ export default implementRuntimeComponent({
|
||||
name: 'radio',
|
||||
displayName: 'Radio',
|
||||
description: 'chakra-ui radio',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
text: {
|
||||
raw: 'Radio',
|
||||
@ -78,7 +76,6 @@ export default implementRuntimeComponent({
|
||||
isDisabled: false,
|
||||
size: 'md',
|
||||
},
|
||||
exampleSize: [3, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -27,13 +27,10 @@ export default implementRuntimeComponent({
|
||||
name: 'radioGroup',
|
||||
displayName: 'RadioGroup',
|
||||
description: 'chakra-ui radio group',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
defaultValue: 0,
|
||||
isNumerical: true,
|
||||
},
|
||||
exampleSize: [3, 3],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -8,10 +8,7 @@ export default implementRuntimeComponent({
|
||||
name: 'root',
|
||||
displayName: 'Root',
|
||||
description: 'chakra-ui provider',
|
||||
isDraggable: false,
|
||||
isResizable: true,
|
||||
exampleProperties: {},
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Advance',
|
||||
},
|
||||
|
@ -115,10 +115,7 @@ export default implementRuntimeComponent({
|
||||
name: 'select',
|
||||
displayName: 'Select',
|
||||
description: 'chakra-ui select',
|
||||
isResizable: true,
|
||||
isDraggable: true,
|
||||
exampleProperties,
|
||||
exampleSize: [4, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -67,13 +67,10 @@ export default implementRuntimeComponent({
|
||||
name: 'stack',
|
||||
displayName: 'Stack',
|
||||
description: 'chakra-ui stack',
|
||||
isResizable: true,
|
||||
isDraggable: true,
|
||||
exampleProperties: {
|
||||
direction: 'column',
|
||||
spacing: 10,
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Layout',
|
||||
},
|
||||
|
@ -34,12 +34,9 @@ export default implementRuntimeComponent({
|
||||
name: 'switch',
|
||||
displayName: 'Switch',
|
||||
description: 'chakra-ui switch',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
isDisabled: false,
|
||||
},
|
||||
exampleSize: [2, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -54,10 +54,7 @@ export const implementTable = implementRuntimeComponent({
|
||||
name: 'table',
|
||||
displayName: 'Table',
|
||||
description: 'chakra-ui table',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties,
|
||||
exampleSize: [8, 6],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -33,13 +33,10 @@ export default implementRuntimeComponent({
|
||||
name: 'tabs',
|
||||
displayName: 'Tabs',
|
||||
description: 'chakra-ui tabs',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
tabNames: [],
|
||||
initialSelectedTabIndex: 0,
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -61,8 +61,6 @@ export default implementRuntimeComponent({
|
||||
name: 'tooltip',
|
||||
description: 'chakra-ui tooltip',
|
||||
displayName: 'Tooltip',
|
||||
isDraggable: false,
|
||||
isResizable: false,
|
||||
exampleProperties: {
|
||||
text: 'tooltip',
|
||||
defaultIsOpen: false,
|
||||
@ -73,7 +71,6 @@ export default implementRuntimeComponent({
|
||||
hasArrow: true,
|
||||
colorScheme: 'blue',
|
||||
},
|
||||
exampleSize: [2, 1],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -27,9 +27,6 @@ export default implementRuntimeComponent({
|
||||
exampleProperties: {
|
||||
spacing: '24px',
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
annotations: {
|
||||
direction: 'column',
|
||||
wrap: 'wrap',
|
||||
|
@ -6,12 +6,9 @@ describe('component', () => {
|
||||
const c = createComponent({
|
||||
version: 'core/v1',
|
||||
metadata: {
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
displayName: 'test_component',
|
||||
name: 'test_component',
|
||||
exampleProperties: {},
|
||||
exampleSize: [1, 1],
|
||||
},
|
||||
spec: {
|
||||
properties: Type.Object({
|
||||
|
@ -14,10 +14,7 @@ type ComponentCategory =
|
||||
|
||||
export type ComponentMetadata = Metadata<{ category?: ComponentCategory }> & {
|
||||
// TODO:(yanzhen): move to annotations
|
||||
isDraggable: boolean;
|
||||
isResizable: boolean;
|
||||
displayName: string;
|
||||
icon?: string;
|
||||
exampleProperties: Record<string, unknown>;
|
||||
exampleSize: [number, number];
|
||||
};
|
||||
|
@ -1,443 +0,0 @@
|
||||
import { Application } from '../../core/lib';
|
||||
|
||||
export const ApplicationFixture: Record<string, Application> = {
|
||||
adjustOrderOperation: {
|
||||
kind: 'Application',
|
||||
version: 'example/v1',
|
||||
metadata: { name: 'dialog_component', description: 'dialog component example' },
|
||||
spec: {
|
||||
components: [
|
||||
{
|
||||
id: 'grid_layout1',
|
||||
type: 'core/v1/grid_layout',
|
||||
properties: {
|
||||
layout: [
|
||||
{
|
||||
w: 10,
|
||||
h: 15,
|
||||
x: 0,
|
||||
y: 0,
|
||||
i: 'tabs1',
|
||||
moved: false,
|
||||
static: false,
|
||||
isDraggable: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
traits: [],
|
||||
},
|
||||
{
|
||||
id: 'fetchUsers',
|
||||
type: 'core/v1/dummy',
|
||||
properties: {},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/fetch',
|
||||
properties: {
|
||||
url: 'https://6177d4919c328300175f5b99.mockapi.io/users',
|
||||
method: 'get',
|
||||
lazy: false,
|
||||
headers: {},
|
||||
body: {},
|
||||
onComplete: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'usersTable',
|
||||
type: 'chakra_ui/v1/table',
|
||||
properties: {
|
||||
data: '{{fetchUsers.fetch.data}}',
|
||||
columns: [
|
||||
{ key: 'username', title: '用户名', type: 'link' },
|
||||
{ key: 'job', title: '职位', type: 'text' },
|
||||
{ key: 'area', title: '地区', type: 'text' },
|
||||
{
|
||||
key: 'createdTime',
|
||||
title: '创建时间',
|
||||
displayValue: "{{dayjs($listItem.createdTime).format('LL')}}",
|
||||
},
|
||||
],
|
||||
majorKey: 'id',
|
||||
rowsPerPage: '3',
|
||||
isMultiSelect: 'false',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'tabContentVStack', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'userInfoContainer',
|
||||
type: 'chakra_ui/v1/vstack',
|
||||
properties: { spacing: '2', align: 'stretch' },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'tabContentVStack', slot: 'content' } },
|
||||
},
|
||||
{
|
||||
type: 'core/v1/style',
|
||||
properties: {
|
||||
styles: [
|
||||
{
|
||||
styleSlot: 'content',
|
||||
style: "{{!usersTable.selectedItem ? 'display: none' : ''}}",
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'userInfoTitle',
|
||||
type: 'core/v1/text',
|
||||
properties: { value: { raw: '**基本信息**', format: 'md' } },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'userInfoContainer', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'hstack1',
|
||||
type: 'chakra_ui/v1/hstack',
|
||||
properties: { spacing: '24px', hideBorder: '' },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'userInfoContainer', slot: 'content' } },
|
||||
},
|
||||
{
|
||||
type: 'core/v1/style',
|
||||
properties: { styles: [{styleSlot: 'content', style: 'padding: 0; border: none' }]},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'usernameLabel',
|
||||
type: 'core/v1/text',
|
||||
properties: { value: { raw: '**用户名**', format: 'md' } },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'hstack1', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'usernameValue',
|
||||
type: 'core/v1/text',
|
||||
properties: {
|
||||
value: {
|
||||
raw: "{{usersTable.selectedItem ? usersTable.selectedItem.username : ''}}",
|
||||
format: 'plain',
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'hstack1', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'divider1',
|
||||
type: 'chakra_ui/v1/divider',
|
||||
properties: {},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'userInfoContainer', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'jobLabel',
|
||||
type: 'core/v1/text',
|
||||
properties: { value: { raw: '**职位**', format: 'md' } },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'hstack2', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'hstack2',
|
||||
type: 'chakra_ui/v1/hstack',
|
||||
properties: { spacing: '24px', hideBorder: '' },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'userInfoContainer', slot: 'content' } },
|
||||
},
|
||||
{
|
||||
type: 'core/v1/style',
|
||||
properties: { styles: [{styleSlot: 'content', style: 'padding: 0; border: none' }]},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'areaLabel',
|
||||
type: 'core/v1/text',
|
||||
properties: { value: { raw: '**地区**', format: 'md' } },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'hstack3', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'areaValue',
|
||||
type: 'core/v1/text',
|
||||
properties: {
|
||||
value: {
|
||||
raw: "{{usersTable.selectedItem ? usersTable.selectedItem.area : ''}}",
|
||||
format: 'plain',
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'hstack3', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'divider2',
|
||||
type: 'chakra_ui/v1/divider',
|
||||
properties: {},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'userInfoContainer', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'createdTimeLabel',
|
||||
type: 'core/v1/text',
|
||||
properties: { value: { raw: '**创建时间**', format: 'md' } },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'hstack4', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'createdTimeValue',
|
||||
type: 'core/v1/text',
|
||||
properties: {
|
||||
value: {
|
||||
raw: "{{usersTable.selectedItem ? dayjs(usersTable.selectedItem.createdTime).format('LL') : ''}}",
|
||||
format: 'plain',
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'hstack4', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'hstack3',
|
||||
type: 'chakra_ui/v1/hstack',
|
||||
properties: { spacing: '24px', hideBorder: '' },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'userInfoContainer', slot: 'content' } },
|
||||
},
|
||||
{
|
||||
type: 'core/v1/style',
|
||||
properties: { styles: [{styleSlot: 'content', style: 'padding: 0; border: none' }]},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'divider3',
|
||||
type: 'chakra_ui/v1/divider',
|
||||
properties: {},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'userInfoContainer', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'hstack4',
|
||||
type: 'chakra_ui/v1/hstack',
|
||||
properties: { spacing: '24px', hideBorder: '' },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'userInfoContainer', slot: 'content' } },
|
||||
},
|
||||
{
|
||||
type: 'core/v1/style',
|
||||
properties: { styles: [{styleSlot: 'content', style: 'padding: 0; border: none' }]},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'tabs1',
|
||||
type: 'chakra_ui/v1/tabs',
|
||||
properties: { tabNames: ['用户信息', '角色'], initialSelectedTabIndex: 0 },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'grid_layout1', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'tabContentVStack',
|
||||
type: 'chakra_ui/v1/vstack',
|
||||
properties: { spacing: '24px' },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'tabs1', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'testtext',
|
||||
type: 'core/v1/text',
|
||||
properties: { value: { raw: '**测试角色**', format: 'md' } },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'tabs1', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'jobValue',
|
||||
type: 'chakra_ui/v1/vstack',
|
||||
properties: { spacing: '1', align: 'stretch' },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'hstack2', slot: 'content' } },
|
||||
},
|
||||
{
|
||||
type: 'core/v1/style',
|
||||
properties: { styles: [{styleSlot: 'content', style: 'padding: 0; border: none' }]},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'link1',
|
||||
type: 'chakra_ui/v1/link',
|
||||
properties: {
|
||||
text: {
|
||||
raw: "{{usersTable.selectedItem ? usersTable.selectedItem.job : ''}}",
|
||||
format: 'plain',
|
||||
},
|
||||
href: 'https://www.google.com',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'jobValue', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'link2',
|
||||
type: 'chakra_ui/v1/link',
|
||||
properties: {
|
||||
text: {
|
||||
raw: "{{usersTable.selectedItem ? usersTable.selectedItem.job : ''}}",
|
||||
format: 'plain',
|
||||
},
|
||||
href: 'https://www.google.com',
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'jobValue', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'grid_layout2',
|
||||
type: 'core/v1/grid_layout',
|
||||
properties: {
|
||||
layout: [
|
||||
{ i: 'text10', x: 0, y: 0, w: 0, h: 0 },
|
||||
{ i: 'form1', x: 0, y: 0, w: 0, h: 0 },
|
||||
],
|
||||
},
|
||||
traits: [],
|
||||
},
|
||||
{
|
||||
id: 'form1',
|
||||
type: 'chakra_ui/v1/form',
|
||||
properties: { hideSubmit: false },
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'grid_layout2', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'button1',
|
||||
type: 'chakra_ui/v1/button',
|
||||
properties: {
|
||||
text: { raw: 'text', format: 'plain' },
|
||||
colorScheme: 'blue',
|
||||
isLoading: false,
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'form1', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'button2',
|
||||
type: 'chakra_ui/v1/button',
|
||||
properties: {
|
||||
text: { raw: 'text', format: 'plain' },
|
||||
colorScheme: 'blue',
|
||||
isLoading: false,
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'form1', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'button3',
|
||||
type: 'chakra_ui/v1/button',
|
||||
properties: {
|
||||
text: { raw: 'text', format: 'plain' },
|
||||
colorScheme: 'blue',
|
||||
isLoading: false,
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/slot',
|
||||
properties: { container: { id: 'form1', slot: 'content' } },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
@ -12,12 +12,7 @@ import {
|
||||
InputRightElement,
|
||||
Tag,
|
||||
} from '@chakra-ui/react';
|
||||
import { DROP_EXAMPLE_SIZE_PREFIX } from '@sunmao-ui/runtime';
|
||||
import {
|
||||
encodeDragDataTransfer,
|
||||
CoreComponentName,
|
||||
CORE_VERSION,
|
||||
} from '@sunmao-ui/shared';
|
||||
import { CoreComponentName, CORE_VERSION } from '@sunmao-ui/shared';
|
||||
import { groupBy, sortBy } from 'lodash-es';
|
||||
import { EditorServices } from '../../types';
|
||||
import { ExplorerMenuTabs } from '../../constants/enum';
|
||||
@ -63,10 +58,7 @@ const tagStyle = css`
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const IGNORE_COMPONENTS: string[] = [
|
||||
CoreComponentName.Dummy,
|
||||
CoreComponentName.GridLayout,
|
||||
];
|
||||
const IGNORE_COMPONENTS: string[] = [CoreComponentName.Dummy];
|
||||
|
||||
export const ComponentList: React.FC<Props> = ({ services }) => {
|
||||
const { registry, editorStore } = services;
|
||||
@ -138,16 +130,6 @@ export const ComponentList: React.FC<Props> = ({ services }) => {
|
||||
'component',
|
||||
`${c.version}/${c.metadata.name}`
|
||||
);
|
||||
// pass the exampleSize to gridlayout to render placeholder
|
||||
e.dataTransfer.setData(
|
||||
encodeDragDataTransfer(
|
||||
`${DROP_EXAMPLE_SIZE_PREFIX}${JSON.stringify(
|
||||
c.metadata.exampleSize
|
||||
)}`
|
||||
),
|
||||
''
|
||||
);
|
||||
|
||||
editorStore.setExplorerMenuTab(ExplorerMenuTabs.UI_TREE);
|
||||
editorStore.setIsDraggingNewComponent(true);
|
||||
};
|
||||
|
@ -1,11 +1,6 @@
|
||||
import React, { useMemo, useState, useCallback, useEffect } from 'react';
|
||||
import { Application } from '@sunmao-ui/core';
|
||||
import {
|
||||
GridCallbacks,
|
||||
DIALOG_CONTAINER_ID,
|
||||
initSunmaoUI,
|
||||
SunmaoLib,
|
||||
} from '@sunmao-ui/runtime';
|
||||
import { DIALOG_CONTAINER_ID, initSunmaoUI, SunmaoLib } from '@sunmao-ui/runtime';
|
||||
import { Box, Tabs, TabList, Tab, TabPanels, TabPanel, Flex } from '@chakra-ui/react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { StructureTree } from './StructureTree';
|
||||
@ -16,7 +11,6 @@ import { StateViewer } from './CodeEditor';
|
||||
import { DataSource } from './DataSource';
|
||||
import { DataSourceType, DATASOURCE_TRAIT_TYPE_MAP } from '../constants/dataSource';
|
||||
import { ApiForm } from './DataSource/ApiForm';
|
||||
import { genOperation } from '../operations';
|
||||
import { ComponentForm } from './ComponentForm';
|
||||
import ErrorBoundary from './ErrorBoundary';
|
||||
import { PreviewModal } from './PreviewModal';
|
||||
@ -51,8 +45,8 @@ const ApiFormStyle = css`
|
||||
`;
|
||||
|
||||
export const Editor: React.FC<Props> = observer(
|
||||
({ App, registry, stateStore, services, libs, onRefresh: onRefreshApp }) => {
|
||||
const { eventBus, editorStore } = services;
|
||||
({ App, stateStore, services, libs, onRefresh: onRefreshApp }) => {
|
||||
const { editorStore } = services;
|
||||
const {
|
||||
components,
|
||||
selectedComponentId,
|
||||
@ -70,34 +64,6 @@ export const Editor: React.FC<Props> = observer(
|
||||
const [codeMode, setCodeMode] = useState(false);
|
||||
const [isDisplayApp, setIsDisplayApp] = useState(true);
|
||||
|
||||
const gridCallbacks: GridCallbacks = useMemo(() => {
|
||||
return {
|
||||
// drag an existing component
|
||||
onDragStop(id, layout) {
|
||||
eventBus.send(
|
||||
'operation',
|
||||
genOperation(registry, 'modifyComponentProperty', {
|
||||
componentId: id,
|
||||
properties: { layout },
|
||||
})
|
||||
);
|
||||
},
|
||||
// drag a new component from tool box
|
||||
onDrop(id, layout, _, e) {
|
||||
const component = e.dataTransfer?.getData('component') || '';
|
||||
eventBus.send(
|
||||
'operation',
|
||||
genOperation(registry, 'createComponent', {
|
||||
componentType: component,
|
||||
parentId: id,
|
||||
slot: 'content',
|
||||
layout,
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
||||
}, [eventBus, registry]);
|
||||
|
||||
const app = useMemo<Application>(() => {
|
||||
return {
|
||||
version: 'sunmao/v1',
|
||||
@ -114,10 +80,10 @@ export const Editor: React.FC<Props> = observer(
|
||||
const appComponent = useMemo(() => {
|
||||
return isDisplayApp ? (
|
||||
<ErrorBoundary>
|
||||
<App options={app} gridCallbacks={gridCallbacks} />
|
||||
<App options={app} />
|
||||
</ErrorBoundary>
|
||||
) : null;
|
||||
}, [App, app, gridCallbacks, isDisplayApp]);
|
||||
}, [App, app, isDisplayApp]);
|
||||
|
||||
const inspectForm = useMemo(() => {
|
||||
if (activeDataSource && activeDataSourceType) {
|
||||
|
@ -1,21 +1,16 @@
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import ReactGridLayout from 'react-grid-layout';
|
||||
import produce from 'immer';
|
||||
import { ComponentId, ComponentType, SlotName } from '../../../AppModel/IAppModel';
|
||||
import {
|
||||
AdjustComponentOrderLeafOperation,
|
||||
CreateComponentLeafOperation,
|
||||
ModifyComponentPropertiesLeafOperation,
|
||||
} from '../../leaf';
|
||||
import { BaseBranchOperation } from '../../type';
|
||||
import { CORE_VERSION, CoreComponentName } from '@sunmao-ui/shared';
|
||||
|
||||
export type CreateComponentBranchOperationContext = {
|
||||
componentType: string;
|
||||
componentId?: string;
|
||||
slot?: string;
|
||||
parentId?: string;
|
||||
layout?: ReactGridLayout.Layout[];
|
||||
targetId?: string;
|
||||
direction?: 'prev' | 'next';
|
||||
};
|
||||
@ -42,49 +37,6 @@ export class CreateComponentBranchOperation extends BaseBranchOperation<CreateCo
|
||||
|
||||
if (!parentComponent) {
|
||||
console.warn("insert element has an invalid parent, it won't show in the view");
|
||||
} else if (parentComponent.type === `${CORE_VERSION}/${CoreComponentName.GridLayout}`) {
|
||||
this.operationStack.insert(
|
||||
// update grid layout for the new created component, it was pushed into layout by react-grid-layout, so we need to find it and update its id
|
||||
new ModifyComponentPropertiesLeafOperation(this.registry, {
|
||||
componentId: parentComponent.id,
|
||||
properties: {
|
||||
layout: (prev: Array<ReactGridLayout.Layout>) => {
|
||||
const newLayout = produce(prev, () => {
|
||||
// find dropping element
|
||||
if (!this.context.layout) {
|
||||
prev.push({
|
||||
i: this.context.componentId!,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 0,
|
||||
h: 0,
|
||||
});
|
||||
return prev;
|
||||
}
|
||||
const layout = this.context.layout.find(
|
||||
layout => layout.i === '__dropping-elem__'
|
||||
);
|
||||
if (layout) {
|
||||
layout.i = this.context.componentId!;
|
||||
} else {
|
||||
console.warn('layout was not updated');
|
||||
this.context.layout.push({
|
||||
i: this.context.componentId!,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 0,
|
||||
h: 0,
|
||||
});
|
||||
}
|
||||
return this.context.layout;
|
||||
});
|
||||
// update layout in context
|
||||
this.context.layout = newLayout;
|
||||
return newLayout;
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,6 @@
|
||||
import produce from 'immer';
|
||||
import ReactGridLayout from 'react-grid-layout';
|
||||
import { AppModel } from '../../../AppModel/AppModel';
|
||||
import { ComponentId } from '../../../AppModel/IAppModel';
|
||||
import {
|
||||
ModifyComponentPropertiesLeafOperation,
|
||||
RemoveComponentLeafOperation,
|
||||
} from '../../leaf';
|
||||
import { RemoveComponentLeafOperation } from '../../leaf';
|
||||
import { BaseBranchOperation } from '../../type';
|
||||
import { CORE_VERSION, CoreComponentName } from '@sunmao-ui/shared';
|
||||
|
||||
export type RemoveComponentBranchOperationContext = {
|
||||
componentId: string;
|
||||
@ -15,33 +8,11 @@ export type RemoveComponentBranchOperationContext = {
|
||||
|
||||
export class RemoveComponentBranchOperation extends BaseBranchOperation<RemoveComponentBranchOperationContext> {
|
||||
do(prev: AppModel): AppModel {
|
||||
const parent = prev.getComponentById(this.context.componentId as ComponentId);
|
||||
|
||||
if (parent && parent.type === `${CORE_VERSION}/${CoreComponentName.GridLayout}`) {
|
||||
// modify layout property of parent grid layout component
|
||||
this.operationStack.insert(
|
||||
new ModifyComponentPropertiesLeafOperation(this.registry, {
|
||||
componentId: parent.id,
|
||||
properties: {
|
||||
layout: (prev: Array<ReactGridLayout.Layout>) => {
|
||||
return produce(prev, draft => {
|
||||
const removeIndex = draft.findIndex(
|
||||
item => item.i === this.context.componentId
|
||||
);
|
||||
if (removeIndex === -1) {
|
||||
console.warn("parent element doesn' contain specific child");
|
||||
}
|
||||
draft.splice(removeIndex, 1);
|
||||
});
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// free component from schema
|
||||
this.operationStack.insert(
|
||||
new RemoveComponentLeafOperation(this.registry, { componentId: this.context.componentId })
|
||||
new RemoveComponentLeafOperation(this.registry, {
|
||||
componentId: this.context.componentId,
|
||||
})
|
||||
);
|
||||
|
||||
// do the operation in order
|
||||
|
@ -1,4 +1,3 @@
|
||||
@import 'react-grid-layout/css/styles.css';
|
||||
@import 'react-resizable/css/styles.css';
|
||||
|
||||
@import '@sunmao-ui/arco-lib/dist/index.css';
|
||||
|
@ -44,7 +44,6 @@
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"react": "^17.0.0",
|
||||
"react-dom": "^17.0.0",
|
||||
"react-grid-layout": "^1.3.0",
|
||||
"react-markdown": "^7.1.0",
|
||||
"react-resize-detector": "^6.7.6",
|
||||
"react-simple-code-editor": "^0.11.0",
|
||||
@ -63,7 +62,6 @@
|
||||
"@types/lodash-es": "^4.17.5",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@types/react-grid-layout": "^1.1.2",
|
||||
"@vitejs/plugin-react": "^1.0.1",
|
||||
"babel-jest": "^27.1.0",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
|
@ -14,14 +14,7 @@ export function genApp(services: UIServices, hooks?: AppHooks) {
|
||||
}
|
||||
|
||||
export const App: React.FC<AppProps> = props => {
|
||||
const {
|
||||
options,
|
||||
services,
|
||||
gridCallbacks,
|
||||
debugStore = false,
|
||||
debugEvent = false,
|
||||
hooks,
|
||||
} = props;
|
||||
const { options, services, debugStore = false, debugEvent = false, hooks } = props;
|
||||
const runtimeAppSchemaManager = useRef(new RuntimeAppSchemaManager());
|
||||
const app = runtimeAppSchemaManager.current.update(options);
|
||||
initStateAndMethod(services.registry, services.stateManager, app.spec.components);
|
||||
@ -49,7 +42,6 @@ export const App: React.FC<AppProps> = props => {
|
||||
services={services}
|
||||
childrenMap={childrenMap}
|
||||
app={app}
|
||||
gridCallbacks={gridCallbacks}
|
||||
hooks={hooks}
|
||||
isInModule={false}
|
||||
/>
|
||||
|
@ -1,55 +0,0 @@
|
||||
import RGL from 'react-grid-layout';
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { useResizeDetector } from 'react-resize-detector';
|
||||
import { DROP_EXAMPLE_SIZE_PREFIX, GRID_HEIGHT } from '../../constants';
|
||||
import { decodeDragDataTransfer } from '@sunmao-ui/shared';
|
||||
|
||||
const GridLayout: React.FC<RGL.ReactGridLayoutProps> = props => {
|
||||
const { children } = props;
|
||||
const spacing = 10;
|
||||
const { width, ref } = useResizeDetector();
|
||||
|
||||
const bgCss = css`
|
||||
height: 100%;
|
||||
background: white;
|
||||
background-image: linear-gradient(#eee 1px, transparent 0),
|
||||
linear-gradient(90deg, #eee 1px, transparent 0);
|
||||
background-size: ${(width || 0) / 12}px ${GRID_HEIGHT + spacing}px;
|
||||
background-position: 0px ${spacing / 2}px;
|
||||
`;
|
||||
|
||||
const onDropDragOver = (e: any) => {
|
||||
// Here we need to get data in dataTransfer
|
||||
// but normally we cannot access dataTransfer in onDragOver, so I use a hack
|
||||
// I use the key of dataTransfer to store data, the key will look like 'exampleSize: [1,4]'
|
||||
// https://stackoverflow.com/questions/28487352/dragndrop-datatransfer-getdata-empty
|
||||
const key = (e as React.DragEvent).dataTransfer.types
|
||||
.map(decodeDragDataTransfer)
|
||||
.find(t => t.startsWith(DROP_EXAMPLE_SIZE_PREFIX));
|
||||
if (key) {
|
||||
const componentSize = JSON.parse(key?.replace(DROP_EXAMPLE_SIZE_PREFIX, '') || '');
|
||||
return { w: componentSize[0], h: componentSize[1] };
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={ref} className={bgCss}>
|
||||
<RGL
|
||||
cols={12}
|
||||
compactType={null}
|
||||
preventCollision={true}
|
||||
rowHeight={GRID_HEIGHT}
|
||||
width={width || 0}
|
||||
margin={[spacing, spacing]}
|
||||
isDroppable={true}
|
||||
onDropDragOver={onDropDragOver}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</RGL>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GridLayout;
|
@ -7,7 +7,6 @@ import { useRuntimeFunctions } from './hooks/useRuntimeFunctions';
|
||||
import { getSlotElements } from './hooks/useSlotChildren';
|
||||
import { useGlobalHandlerMap } from './hooks/useGlobalHandlerMap';
|
||||
import { useEleRef } from './hooks/useEleMap';
|
||||
import { useGridLayout } from './hooks/useGridLayout';
|
||||
import { initStateAndMethod } from '../../../utils/initStateAndMethod';
|
||||
|
||||
export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps>(
|
||||
@ -161,7 +160,6 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
|
||||
childrenMap: props.childrenMap,
|
||||
children: props.children,
|
||||
component: props.component,
|
||||
gridCallbacks: props.gridCallbacks,
|
||||
services: props.services,
|
||||
hooks: props.hooks,
|
||||
isInModule: props.isInModule,
|
||||
@ -169,6 +167,7 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
|
||||
|
||||
const C = unmount ? null : (
|
||||
<Impl
|
||||
ref={ref}
|
||||
key={c.id}
|
||||
{...omit(props, 'slotProps')}
|
||||
{...mergedProps}
|
||||
@ -180,16 +179,12 @@ export const ImplWrapperMain = React.forwardRef<HTMLDivElement, ImplWrapperProps
|
||||
/>
|
||||
);
|
||||
|
||||
const result = (
|
||||
return (
|
||||
<React.Fragment key={c.id}>
|
||||
{C}
|
||||
{children}
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
const element = useGridLayout(props, result, ref);
|
||||
|
||||
return element;
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,34 +0,0 @@
|
||||
import React from 'react';
|
||||
import { ImplWrapperProps } from '../../../../types';
|
||||
import { CORE_VERSION, CoreTraitName, CoreComponentName } from '@sunmao-ui/shared';
|
||||
|
||||
export function useGridLayout(
|
||||
props: ImplWrapperProps,
|
||||
node: React.ReactNode,
|
||||
ref: React.ForwardedRef<HTMLDivElement>
|
||||
) {
|
||||
const { component: c, app } = props;
|
||||
|
||||
let parentComponent;
|
||||
|
||||
const slotTrait = c.traits.find(t => t.type === `${CORE_VERSION}/${CoreTraitName.Slot}`);
|
||||
|
||||
if (slotTrait && app) {
|
||||
parentComponent = app.spec.components.find(
|
||||
c => c.id === (slotTrait.properties.container as any).id
|
||||
);
|
||||
}
|
||||
|
||||
if (parentComponent?.parsedType.name === CoreComponentName.GridLayout) {
|
||||
/* eslint-disable */
|
||||
const { component, services, app, gridCallbacks, ...restProps } = props;
|
||||
/* eslint-enable */
|
||||
return (
|
||||
<div key={c.id} data-sunmao-ui-id={c.id} ref={ref} {...restProps}>
|
||||
{node}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <>{node}</>;
|
||||
}
|
@ -8,10 +8,7 @@ export default implementRuntimeComponent({
|
||||
name: CoreComponentName.Dummy,
|
||||
displayName: 'Dummy',
|
||||
description: 'Dummy Invisible component',
|
||||
isDraggable: false,
|
||||
isResizable: false,
|
||||
exampleProperties: {},
|
||||
exampleSize: [1, 1],
|
||||
annotations: {
|
||||
category: 'Advance',
|
||||
},
|
||||
|
@ -39,14 +39,11 @@ export default implementRuntimeComponent({
|
||||
name: 'fileInput',
|
||||
displayName: 'File Input',
|
||||
description: 'Select file',
|
||||
isDraggable: true,
|
||||
isResizable: false,
|
||||
exampleProperties: {
|
||||
multiple: false,
|
||||
hideDefaultInput: false,
|
||||
fileTypes: [],
|
||||
},
|
||||
exampleSize: [1, 1],
|
||||
annotations: {
|
||||
category: 'Input',
|
||||
},
|
||||
|
@ -1,87 +0,0 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { implementRuntimeComponent } from '../../utils/buildKit';
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { partial } from 'lodash-es';
|
||||
import { css } from '@emotion/css';
|
||||
import { CORE_VERSION, CoreComponentName } from '@sunmao-ui/shared';
|
||||
|
||||
const BaseGridLayout = React.lazy(() => import('../_internal/GridLayout'));
|
||||
|
||||
const PropsSpec = Type.Object({
|
||||
layout: Type.Array(
|
||||
Type.Object({
|
||||
x: Type.Number({
|
||||
title: 'X',
|
||||
}),
|
||||
y: Type.Number({
|
||||
title: 'Y',
|
||||
}),
|
||||
w: Type.Number({
|
||||
title: 'Width',
|
||||
}),
|
||||
h: Type.Number({
|
||||
title: 'Height',
|
||||
}),
|
||||
i: Type.String(),
|
||||
isResizable: Type.Boolean({
|
||||
title: 'Resizable',
|
||||
}),
|
||||
}),
|
||||
{
|
||||
title: 'Layout',
|
||||
category: 'Layout',
|
||||
}
|
||||
),
|
||||
});
|
||||
|
||||
export default implementRuntimeComponent({
|
||||
version: CORE_VERSION,
|
||||
metadata: {
|
||||
name: CoreComponentName.GridLayout,
|
||||
displayName: 'Grid Layout',
|
||||
description: 'drag and drop to layout in a grid',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
layout: [],
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Layout',
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
properties: PropsSpec,
|
||||
state: {},
|
||||
methods: {},
|
||||
slots: {
|
||||
content: { slotProps: Type.Object({}) },
|
||||
},
|
||||
styleSlots: ['content'],
|
||||
events: [],
|
||||
},
|
||||
})(({ layout = [], gridCallbacks, component, customStyle, slotsElements }) => {
|
||||
const onDragStop = gridCallbacks?.onDragStop
|
||||
? partial(gridCallbacks.onDragStop, component.id)
|
||||
: undefined;
|
||||
const onDrop = gridCallbacks?.onDrop
|
||||
? partial(gridCallbacks.onDrop, component.id)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<BaseGridLayout
|
||||
isDraggable={!!gridCallbacks}
|
||||
isResizable={!!gridCallbacks}
|
||||
onDragStop={onDragStop}
|
||||
onDrop={onDrop}
|
||||
layout={layout}
|
||||
className={css`
|
||||
${customStyle?.content}
|
||||
`}
|
||||
>
|
||||
{slotsElements.content ? slotsElements.content({}) : null}
|
||||
</BaseGridLayout>
|
||||
</Suspense>
|
||||
);
|
||||
});
|
@ -10,15 +10,12 @@ export default implementRuntimeComponent({
|
||||
name: CoreComponentName.Iframe,
|
||||
displayName: 'Iframe',
|
||||
description: '',
|
||||
isDraggable: false,
|
||||
isResizable: false,
|
||||
exampleProperties: {
|
||||
src: 'https://www.openstreetmap.org/export/embed.html?bbox=-0.004017949104309083%2C51.47612752641776%2C0.00030577182769775396%2C51.478569861898606&layer=mapnik',
|
||||
referrerpolicy: 'unset',
|
||||
sandbox: 'unset',
|
||||
fetchpriority: 'auto',
|
||||
},
|
||||
exampleSize: [1, 1],
|
||||
annotations: {
|
||||
category: 'Advance',
|
||||
},
|
||||
|
@ -22,10 +22,7 @@ export default implementRuntimeComponent({
|
||||
name: 'list',
|
||||
description: 'core list',
|
||||
displayName: 'List',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties,
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -8,13 +8,10 @@ export default implementRuntimeComponent({
|
||||
name: CoreComponentName.ModuleContainer,
|
||||
displayName: 'ModuleContainer',
|
||||
description: 'ModuleContainer component',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
id: 'myModule',
|
||||
type: 'custom/v1/module',
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
annotations: {
|
||||
category: 'Advance',
|
||||
},
|
||||
|
@ -44,12 +44,9 @@ export default implementRuntimeComponent({
|
||||
name: 'router',
|
||||
displayName: 'Router',
|
||||
description: 'create a router-controlled component',
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
exampleProperties: {
|
||||
switchPolicy: [],
|
||||
},
|
||||
exampleSize: [6, 6],
|
||||
},
|
||||
spec: {
|
||||
properties: PropsSpec,
|
||||
|
@ -77,8 +77,6 @@ export default implementRuntimeComponent({
|
||||
name: 'stack',
|
||||
displayName: 'Stack',
|
||||
description: '',
|
||||
isDraggable: true,
|
||||
isResizable: false,
|
||||
exampleProperties: {
|
||||
spacing: 12,
|
||||
direction: 'horizontal',
|
||||
@ -86,7 +84,6 @@ export default implementRuntimeComponent({
|
||||
wrap: '',
|
||||
justify: '',
|
||||
},
|
||||
exampleSize: [4, 1],
|
||||
annotations: {
|
||||
category: 'Layout',
|
||||
},
|
||||
|
@ -17,15 +17,12 @@ export default implementRuntimeComponent({
|
||||
name: CoreComponentName.Text,
|
||||
displayName: 'Text',
|
||||
description: 'support plain and markdown formats',
|
||||
isDraggable: true,
|
||||
isResizable: false,
|
||||
exampleProperties: {
|
||||
value: {
|
||||
raw: 'text',
|
||||
format: 'plain',
|
||||
},
|
||||
},
|
||||
exampleSize: [4, 1],
|
||||
annotations: {
|
||||
category: 'Display',
|
||||
},
|
||||
|
@ -5,6 +5,4 @@ export {
|
||||
GLOBAL_MODULE_ID,
|
||||
} from '@sunmao-ui/shared';
|
||||
|
||||
export const GRID_HEIGHT = 40;
|
||||
export const DIALOG_CONTAINER_ID = 'sunmao-ui-dialog-container';
|
||||
export const DROP_EXAMPLE_SIZE_PREFIX = 'exampleSize: ';
|
||||
|
@ -2,7 +2,6 @@ import { parseType } from '@sunmao-ui/core';
|
||||
// components
|
||||
/* --- core --- */
|
||||
import CoreText from '../components/core/Text';
|
||||
import CoreGridLayout from '../components/core/GridLayout';
|
||||
import CoreRouter from '../components/core/Router';
|
||||
import CoreDummy from '../components/core/Dummy';
|
||||
import CoreModuleContainer from '../components/core/ModuleContainer';
|
||||
@ -238,7 +237,6 @@ export function initRegistry(
|
||||
): Registry {
|
||||
const registry = new Registry(services, utilMethodManager);
|
||||
registry.registerComponent(CoreText);
|
||||
registry.registerComponent(CoreGridLayout);
|
||||
registry.registerComponent(CoreRouter);
|
||||
registry.registerComponent(CoreDummy);
|
||||
registry.registerComponent(CoreModuleContainer);
|
||||
|
@ -1,2 +1 @@
|
||||
@import 'react-grid-layout/css/styles.css';
|
||||
@import 'react-resizable/css/styles.css';
|
||||
|
@ -1,4 +1,3 @@
|
||||
import RGL from 'react-grid-layout';
|
||||
import { ApiService } from '../services/apiService';
|
||||
import { GlobalHandlerMap } from '../services/handler';
|
||||
import { RegistryInterface } from '../services/Registry';
|
||||
@ -13,13 +12,7 @@ export type UIServices = {
|
||||
eleMap: Map<string, HTMLElement>;
|
||||
};
|
||||
|
||||
export type GridCallbacks = {
|
||||
onDragStop?: (id: string, layout: RGL.Layout[]) => void;
|
||||
onDrop?: (id: string, layout: RGL.Layout[], item: RGL.Layout, event: DragEvent) => void;
|
||||
};
|
||||
|
||||
export type ComponentParamsFromApp = {
|
||||
gridCallbacks?: GridCallbacks;
|
||||
hooks?: AppHooks;
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,6 @@ export declare const STYLE_VERSION = 'style/v1';
|
||||
export enum CoreComponentName {
|
||||
Dummy = 'dummy',
|
||||
ModuleContainer = 'moduleContainer',
|
||||
GridLayout = 'grid_layout',
|
||||
Text = 'text',
|
||||
Iframe = 'iframe',
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
// https://stackoverflow.com/questions/28487352/dragndrop-datatransfer-getdata-empty
|
||||
const UPPERCASE_PREFIX = '^{';
|
||||
const UPPERCASE_SUFFIX = '}^';
|
||||
|
||||
export function encodeDragDataTransfer(str: string): string {
|
||||
return str.replace(/([A-Z]+)/g, `${UPPERCASE_PREFIX}$1${UPPERCASE_SUFFIX}`);
|
||||
}
|
||||
|
||||
export function decodeDragDataTransfer(str: string): string {
|
||||
const escapeRegExp = (escape: string) => ['', ...escape.split('')].join('\\');
|
||||
|
||||
return str.replace(
|
||||
new RegExp(
|
||||
`${escapeRegExp(UPPERCASE_PREFIX)}(.*?)${escapeRegExp(UPPERCASE_SUFFIX)}`,
|
||||
'g'
|
||||
),
|
||||
(_, p1: string) => p1.toUpperCase()
|
||||
);
|
||||
}
|
@ -5,4 +5,3 @@ export * from './expression';
|
||||
export * from './console';
|
||||
export * from './object';
|
||||
export * from './function';
|
||||
export * from './drag';
|
||||
|
30
yarn.lock
30
yarn.lock
@ -3738,13 +3738,6 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-grid-layout@^1.1.2":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/@types/react-grid-layout/-/react-grid-layout-1.3.0.tgz"
|
||||
integrity sha512-Pytm7lvm4h91yN9CpdjV8IpU/hgVRHrUhDEIX593e4Mx9V14Pr3gWtj21WHzy5bDqU//jnGGVVSYJ3QVuI1NaQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-resizable@^1.7.4":
|
||||
version "1.7.4"
|
||||
resolved "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-1.7.4.tgz"
|
||||
@ -4712,11 +4705,6 @@ cjs-module-lexer@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz"
|
||||
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
|
||||
|
||||
classnames@2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz"
|
||||
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
|
||||
|
||||
clean-stack@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz"
|
||||
@ -8260,11 +8248,6 @@ lodash.debounce@^4.0.8:
|
||||
resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"
|
||||
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||
|
||||
lodash.isequal@^4.0.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz"
|
||||
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
|
||||
|
||||
lodash.ismatch@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz"
|
||||
@ -9908,7 +9891,7 @@ react-dom@^17.0.0, react-dom@^17.0.2:
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react-draggable@^4.0.0, react-draggable@^4.0.3:
|
||||
react-draggable@^4.0.3:
|
||||
version "4.4.4"
|
||||
resolved "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.4.tgz"
|
||||
integrity sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==
|
||||
@ -9950,17 +9933,6 @@ react-focus-lock@^2.2.1:
|
||||
use-callback-ref "^1.2.5"
|
||||
use-sidecar "^1.0.5"
|
||||
|
||||
react-grid-layout@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.3.0.tgz"
|
||||
integrity sha512-WqFwybAItXu0AaSt9YL8+9xE5YotIzMcCYE0Q9XBqSKNyShTxPbC0LjObV/tOWZoADNWJ+osseVfRoZsjzwWXg==
|
||||
dependencies:
|
||||
classnames "2.3.1"
|
||||
lodash.isequal "^4.0.0"
|
||||
prop-types "^15.0.0"
|
||||
react-draggable "^4.0.0"
|
||||
react-resizable "^3.0.4"
|
||||
|
||||
react-input-autosize@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user