Skip to content

Commit

Permalink
feat(designable-antd): support markup schema view
Browse files Browse the repository at this point in the history
  • Loading branch information
janryWang committed Jul 1, 2021
1 parent 99f31d8 commit 2acb103
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 132 deletions.
8 changes: 4 additions & 4 deletions designable/antd/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"start": "webpack-dev-server --config playground/webpack.dev.ts"
},
"devDependencies": {
"@designable/react-settings-form": "^0.3.15",
"@designable/react-settings-form": "^0.3.21",
"autoprefixer": "^9.0",
"file-loader": "^5.0.2",
"fs-extra": "^8.1.0",
Expand All @@ -56,9 +56,9 @@
"react-is": ">=16.8.0 || >=17.0.0"
},
"dependencies": {
"@designable/core": "^0.3.17",
"@designable/formily": "^0.3.17",
"@designable/react": "^0.3.17",
"@designable/core": "^0.3.21",
"@designable/formily": "^0.3.21",
"@designable/react": "^0.3.21",
"@formily/antd": "2.0.0-beta.73",
"@formily/core": "2.0.0-beta.73",
"@formily/react": "2.0.0-beta.73",
Expand Down
10 changes: 8 additions & 2 deletions designable/antd/playground/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
ActionsWidget,
PreviewWidget,
SchemaEditorWidget,
MarkupSchemaWidget,
} from './widgets'
import 'antd/dist/antd.less'

Expand Down Expand Up @@ -79,7 +80,9 @@ const App = () => {
<WorkspacePanel>
<ToolbarPanel>
<DesignerToolsWidget />
<ViewToolsWidget />
<ViewToolsWidget
use={['DESIGNABLE', 'JSONTREE', 'MARKUP', 'PREVIEW']}
/>
</ToolbarPanel>
<ViewportPanel>
<ViewPanel type="DESIGNABLE">
Expand All @@ -92,11 +95,14 @@ const App = () => {
/>
)}
</ViewPanel>
<ViewPanel type="JSONTREE">
<ViewPanel type="JSONTREE" scrollable={false}>
{(tree, onChange) => (
<SchemaEditorWidget tree={tree} onChange={onChange} />
)}
</ViewPanel>
<ViewPanel type="MARKUP" scrollable={false}>
{(tree) => <MarkupSchemaWidget tree={tree} />}
</ViewPanel>
<ViewPanel type="PREVIEW">
{(tree) => <PreviewWidget tree={tree} />}
</ViewPanel>
Expand Down
137 changes: 137 additions & 0 deletions designable/antd/playground/widgets/MarkupSchemaWidget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React from 'react'
import { TreeNode } from '@designable/core'
import { MonacoInput } from '@designable/react-settings-form'
import { isEmpty, isPlainObj } from '@formily/shared'

export interface IMarkupSchemaWidgetProps {
tree: TreeNode
}

const transformToMarkupSchemaCode = (tree: TreeNode) => {
const printAttribute = (node: TreeNode) => {
if (!node) return ''
return `${Object.keys(node.props || {})
.map((key) => {
if (
key === '_designableId' ||
key === '_isJSONSchemaObject' ||
key === 'version'
)
return ''
const value = node.props[key]
if (isPlainObj(value) && isEmpty(value)) return ''
if (typeof value === 'string') return `${key}="${value}"`
return `${key}={${JSON.stringify(value)}}`
})
.join(' ')}`
}
const printChildren = (node: TreeNode) => {
if (!node) return ''
return node.children
.map((child) => {
return printNode(child)
})
.join('')
}
const printNode = (node: TreeNode) => {
if (!node) return ''
return `<SchemaField.Markup ${printAttribute(node)} ${
node.children.length
? `>${printChildren(node)}</SchemaField.Markup>`
: '/>'
}`
}
const root = tree.find((child) => {
return child.componentName === 'Root'
})
return `import React, { useMemo } from 'react'
import { createForm } from '@formily/core'
import { createSchemaField } from '@formily/react'
import {
Form,
FormItem,
DatePicker,
Checkbox,
Cascader,
Editable,
Input,
NumberPicker,
Switch,
Password,
PreviewText,
Radio,
Reset,
Select,
Space,
Submit,
TimePicker,
Transfer,
TreeSelect,
Upload,
FormGrid,
FormLayout,
FormTab,
FormCollapse,
ArrayTable,
ArrayCards,
} from '@formily/antd'
import { Card, Slider, Rate } from 'antd'
const SchemaField = createSchemaField({
components: {
Space,
FormGrid,
FormLayout,
FormTab,
FormCollapse,
ArrayTable,
ArrayCards,
FormItem,
DatePicker,
Checkbox,
Cascader,
Editable,
Input,
NumberPicker,
Switch,
Password,
PreviewText,
Radio,
Reset,
Select,
Submit,
TimePicker,
Transfer,
TreeSelect,
Upload,
Card,
Slider,
Rate,
},
})
export default ()=>{
const form = useMemo(()=>createForm(),[])
return <Form form={form} ${printAttribute(root)}>
<SchemaField>
${printChildren(root)}
</SchemaField>
</Form>
}
`
}

export const MarkupSchemaWidget: React.FC<IMarkupSchemaWidgetProps> = (
props
) => {
return (
<MonacoInput
{...props}
options={{ readOnly: true }}
value={transformToMarkupSchemaCode(props.tree)}
language="typescript"
/>
)
}
106 changes: 9 additions & 97 deletions designable/antd/playground/widgets/SchemaEditorWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React, { useEffect, useState, useRef } from 'react'
import MonacoEditor from 'react-monaco-editor'
import monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'
import React from 'react'
import { transformToSchema, transformToTreeNode } from '@designable/formily'
import { TreeNode, ITreeNode } from '@designable/core'
import { TextWidget } from '@designable/react'
import { notification, Button } from 'antd'
import { MonacoInput } from '@designable/react-settings-form'

export interface ISchemaEditorWidgetProps {
tree: TreeNode
Expand All @@ -19,99 +16,14 @@ const Parser = {
export const SchemaEditorWidget: React.FC<ISchemaEditorWidgetProps> = (
props
) => {
const propsValue = JSON.stringify(
transformToSchema(props.tree, Parser),
null,
2
)
const [value, setValue] = useState(propsValue)
const [saved, setSaved] = useState(false)
const valueRef = useRef('')
const containerRef = useRef<HTMLDivElement>()
const editorRef = useRef<monacoEditor.editor.IStandaloneCodeEditor>()

const onSave = () => {
try {
const schema = JSON.parse(valueRef.current)
props.onChange?.(transformToTreeNode(schema, Parser))
setSaved(true)
} catch (e) {
notification.error({
message: `Coder Error`,
description: 'JSON格式解析失败~',
key: 'parser',
})
}
}

useEffect(() => {
setValue(propsValue)
}, [propsValue])

useEffect(() => {
if (containerRef.current) {
const observer = new ResizeObserver(() => {
editorRef.current.layout()
})
observer.observe(containerRef.current)
return () => {
observer.disconnect()
}
}
}, [])

valueRef.current = value

return (
<div
ref={containerRef}
style={{
height: '100%',
overflow: 'hidden',
position: 'relative',
<MonacoInput
{...props}
value={JSON.stringify(transformToSchema(props.tree, Parser), null, 2)}
onChange={(value) => {
props.onChange?.(transformToTreeNode(JSON.parse(value), Parser))
}}
>
<MonacoEditor
width="100%"
height="100%"
language="json"
value={value}
editorDidMount={(editor, monaco) => {
editor.addCommand(
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S,
function () {
onSave()
}
)
editorRef.current = editor
}}
onChange={(value: string) => {
setValue(value)
setSaved(false)
}}
/>
<div
style={{
height: 50,
position: 'absolute',
zIndex: 2,
left: 0,
bottom: value === propsValue || saved ? -20 : 0,
opacity: value === propsValue || saved ? 0 : 1,
transition: 'all 0.3s ease-in-out',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderTop: '1px solid #eee',
background: '#fff',
width: '100%',
boxShadow: '0 0 10px #cacaca',
}}
>
<Button onClick={onSave}>
<TextWidget>Save</TextWidget>
</Button>
</div>
</div>
language="json"
/>
)
}
1 change: 1 addition & 0 deletions designable/antd/playground/widgets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './LogoWidget'
export * from './ActionsWidget'
export * from './PreviewWidget'
export * from './SchemaEditorWidget'
export * from './MarkupSchemaWidget'
Loading

0 comments on commit 2acb103

Please sign in to comment.