@opentiny/tiny-engine-canvas 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +42 -0
- package/README.md +7 -0
- package/canvas.html +212 -0
- package/dist/index.js +48919 -0
- package/index.html +13 -0
- package/package.json +30 -0
- package/public/favicon.ico +0 -0
- package/src/Design.vue +53 -0
- package/src/assets/logo.png +0 -0
- package/src/canvas.js +34 -0
- package/src/components/builtin/CanvasBox.vue +22 -0
- package/src/components/builtin/CanvasCol.vue +89 -0
- package/src/components/builtin/CanvasCollection.js +278 -0
- package/src/components/builtin/CanvasCollection.vue +106 -0
- package/src/components/builtin/CanvasIcon.vue +30 -0
- package/src/components/builtin/CanvasImg.vue +18 -0
- package/src/components/builtin/CanvasPlaceholder.vue +26 -0
- package/src/components/builtin/CanvasRow.vue +67 -0
- package/src/components/builtin/CanvasRowColContainer.vue +42 -0
- package/src/components/builtin/CanvasSlot.vue +22 -0
- package/src/components/builtin/CanvasText.vue +18 -0
- package/src/components/builtin/builtin.json +955 -0
- package/src/components/builtin/helper.js +46 -0
- package/src/components/builtin/index.js +33 -0
- package/src/components/common/index.js +158 -0
- package/src/components/container/CanvasAction.vue +554 -0
- package/src/components/container/CanvasContainer.vue +244 -0
- package/src/components/container/CanvasDivider.vue +246 -0
- package/src/components/container/CanvasDragItem.vue +38 -0
- package/src/components/container/CanvasFooter.vue +86 -0
- package/src/components/container/CanvasMenu.vue +214 -0
- package/src/components/container/CanvasResize.vue +195 -0
- package/src/components/container/CanvasResizeBorder.vue +219 -0
- package/src/components/container/container.js +791 -0
- package/src/components/container/keyboard.js +147 -0
- package/src/components/container/shortCutPopover.vue +181 -0
- package/src/components/render/CanvasEmpty.vue +14 -0
- package/src/components/render/RenderMain.js +408 -0
- package/src/components/render/context.js +53 -0
- package/src/components/render/render.js +689 -0
- package/src/components/render/runner.js +140 -0
- package/src/i18n/en.json +5 -0
- package/src/i18n/zh.json +5 -0
- package/src/i18n.js +21 -0
- package/src/index.js +96 -0
- package/src/locale.js +19 -0
- package/src/lowcode.js +104 -0
- package/src/main.js +17 -0
- package/test/form.json +690 -0
- package/test/group.json +99 -0
- package/test/jsslot.json +427 -0
- package/vite.config.js +73 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2023 - present TinyEngine Authors.
|
|
3
|
+
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license.
|
|
6
|
+
*
|
|
7
|
+
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
|
|
8
|
+
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
|
|
9
|
+
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
getCurrent,
|
|
15
|
+
insertNode,
|
|
16
|
+
selectNode,
|
|
17
|
+
getSchema,
|
|
18
|
+
POSITION,
|
|
19
|
+
removeNodeById,
|
|
20
|
+
allowInsert,
|
|
21
|
+
getConfigure,
|
|
22
|
+
clearHover,
|
|
23
|
+
hoverState
|
|
24
|
+
} from './container'
|
|
25
|
+
import { useHistory } from '@opentiny/tiny-engine-controller'
|
|
26
|
+
import { copyObject, getClipboardSchema, setClipboardSchema } from '../common'
|
|
27
|
+
|
|
28
|
+
const KEY_Y = 89
|
|
29
|
+
const KEY_Z = 90
|
|
30
|
+
const KEY_RIGHT = 39
|
|
31
|
+
const KEY_LEFT = 37
|
|
32
|
+
const KEY_UP = 38
|
|
33
|
+
const KEY_DOWN = 40
|
|
34
|
+
const KEY_DEL = 46
|
|
35
|
+
|
|
36
|
+
function handlerLeft({ parent }) {
|
|
37
|
+
selectNode(parent?.id)
|
|
38
|
+
}
|
|
39
|
+
function handlerRight({ schema }) {
|
|
40
|
+
const id = schema.children?.[0]?.id
|
|
41
|
+
id && selectNode(id)
|
|
42
|
+
}
|
|
43
|
+
function handlerUp({ index, parent }) {
|
|
44
|
+
const id = (parent.children[index - 1] || parent)?.id
|
|
45
|
+
id && selectNode(id)
|
|
46
|
+
}
|
|
47
|
+
function handlerDown({ index, parent }) {
|
|
48
|
+
const id = parent.children[index + 1]?.id
|
|
49
|
+
id && selectNode(id)
|
|
50
|
+
}
|
|
51
|
+
function handlerDelete({ schema }) {
|
|
52
|
+
if (hoverState.id === schema.id) {
|
|
53
|
+
clearHover()
|
|
54
|
+
}
|
|
55
|
+
removeNodeById(schema.id)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const handlerArrow = (keyCode) => {
|
|
59
|
+
let { schema, parent } = getCurrent()
|
|
60
|
+
let index = null
|
|
61
|
+
|
|
62
|
+
if (schema) {
|
|
63
|
+
index = parent.children.indexOf(schema)
|
|
64
|
+
} else {
|
|
65
|
+
schema = getSchema()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let obj = {
|
|
69
|
+
[KEY_LEFT]: handlerLeft,
|
|
70
|
+
[KEY_RIGHT]: handlerRight,
|
|
71
|
+
[KEY_UP]: handlerUp,
|
|
72
|
+
[KEY_DOWN]: handlerDown,
|
|
73
|
+
[KEY_DEL]: handlerDelete
|
|
74
|
+
}
|
|
75
|
+
if (obj[keyCode]) {
|
|
76
|
+
obj[keyCode]({ index, schema, parent })
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const handlerCtrl = (keyCode) => {
|
|
81
|
+
switch (keyCode) {
|
|
82
|
+
case KEY_Y:
|
|
83
|
+
useHistory().forward()
|
|
84
|
+
break
|
|
85
|
+
case KEY_Z:
|
|
86
|
+
useHistory().back()
|
|
87
|
+
break
|
|
88
|
+
default:
|
|
89
|
+
break
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const handleClipboardCut = (event, schema) => {
|
|
94
|
+
if (setClipboardSchema(event, copyObject(schema))) {
|
|
95
|
+
removeNodeById(schema?.id)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const handleClipboardPaste = (node, schema, parent) => {
|
|
100
|
+
if (node?.componentName && schema?.componentName && allowInsert(getConfigure(schema.componentName), node)) {
|
|
101
|
+
insertNode({ parent, node: schema, data: { ...node } }, POSITION.IN)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const handlerClipboardEvent = (event) => {
|
|
106
|
+
const { schema, parent } = getCurrent()
|
|
107
|
+
const node = getClipboardSchema(event)
|
|
108
|
+
switch (event.type) {
|
|
109
|
+
case 'copy':
|
|
110
|
+
setClipboardSchema(event, copyObject(schema))
|
|
111
|
+
break
|
|
112
|
+
case 'paste':
|
|
113
|
+
handleClipboardPaste(node, schema, parent)
|
|
114
|
+
break
|
|
115
|
+
case 'cut':
|
|
116
|
+
handleClipboardCut(event, schema)
|
|
117
|
+
break
|
|
118
|
+
default:
|
|
119
|
+
break
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const keyboardHandler = (event) => {
|
|
124
|
+
if (event.ctrlKey) {
|
|
125
|
+
getCurrent()?.schema && handlerCtrl(event.keyCode)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
handlerArrow(event.keyCode)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const removeHostkeyEvent = (dom) => {
|
|
132
|
+
dom.removeEventListener('keydown', keyboardHandler)
|
|
133
|
+
dom.removeEventListener('copy', handlerClipboardEvent)
|
|
134
|
+
dom.removeEventListener('cut', handlerClipboardEvent)
|
|
135
|
+
dom.removeEventListener('paste', handlerClipboardEvent)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const registerHostkeyEvent = (dom) => {
|
|
139
|
+
removeHostkeyEvent(dom)
|
|
140
|
+
|
|
141
|
+
dom.addEventListener('keydown', keyboardHandler)
|
|
142
|
+
dom.addEventListener('copy', handlerClipboardEvent)
|
|
143
|
+
dom.addEventListener('cut', handlerClipboardEvent)
|
|
144
|
+
dom.addEventListener('paste', handlerClipboardEvent)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export { registerHostkeyEvent, removeHostkeyEvent }
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div class="header">
|
|
4
|
+
<icon-setting class="icon-setting"></icon-setting>
|
|
5
|
+
<div>属性设置</div>
|
|
6
|
+
<span class="icon-wrap">
|
|
7
|
+
<icon-close class="icon-close" @click="closePanel"></icon-close>
|
|
8
|
+
</span>
|
|
9
|
+
</div>
|
|
10
|
+
<config-group :group="propertiesList" :index="0">
|
|
11
|
+
<template #item="{ data, propIndex }">
|
|
12
|
+
<config-item
|
|
13
|
+
:key="propIndex"
|
|
14
|
+
:property="data"
|
|
15
|
+
:data-prop-index="propIndex"
|
|
16
|
+
:data-group-index="groupIndex"
|
|
17
|
+
:isTopLayer="true"
|
|
18
|
+
>
|
|
19
|
+
<template #prefix>
|
|
20
|
+
<slot name="prefix" :data="data"></slot>
|
|
21
|
+
</template>
|
|
22
|
+
<template v-if="!data.noBinding" #suffix>
|
|
23
|
+
<slot name="suffix" :data="data"></slot>
|
|
24
|
+
</template>
|
|
25
|
+
</config-item>
|
|
26
|
+
</template>
|
|
27
|
+
</config-group>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script>
|
|
32
|
+
import { computed, ref } from 'vue'
|
|
33
|
+
import { useResource, useProperties, useCanvas, useProperty } from '@opentiny/tiny-engine-controller'
|
|
34
|
+
import { ConfigGroup, ConfigItem } from '@opentiny/tiny-engine-common'
|
|
35
|
+
import { iconSetting, iconClose } from '@opentiny/vue-icon'
|
|
36
|
+
|
|
37
|
+
export default {
|
|
38
|
+
components: {
|
|
39
|
+
ConfigGroup,
|
|
40
|
+
ConfigItem,
|
|
41
|
+
IconSetting: iconSetting(),
|
|
42
|
+
IconClose: iconClose()
|
|
43
|
+
},
|
|
44
|
+
setup(props, { emit }) {
|
|
45
|
+
const { getMaterial } = useResource()
|
|
46
|
+
const { pageState } = useCanvas()
|
|
47
|
+
const { properties } = useProperty({ pageState })
|
|
48
|
+
const active = ref('props')
|
|
49
|
+
|
|
50
|
+
const propertiesList = computed(() => {
|
|
51
|
+
const quickProps = []
|
|
52
|
+
|
|
53
|
+
const schema = useProperties().getSchema()
|
|
54
|
+
if (!schema) return []
|
|
55
|
+
const nodeType = getMaterial(schema.componentName)
|
|
56
|
+
const shortcuts = nodeType.configure?.shortcuts?.properties || []
|
|
57
|
+
|
|
58
|
+
properties.value.forEach((group) => {
|
|
59
|
+
group.content.forEach((prop) => {
|
|
60
|
+
shortcuts.includes(prop.property) && quickProps.push(prop)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// 如果目标元素的快速设置值没有,则取属性值放置
|
|
64
|
+
if (!quickProps.length) {
|
|
65
|
+
quickProps.push(...group.content.slice(0, 2))
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
content: quickProps
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const closePanel = () => {
|
|
75
|
+
emit('active', 'props')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
active,
|
|
80
|
+
propertiesList,
|
|
81
|
+
closePanel
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<style lang="less" scoped>
|
|
88
|
+
.header {
|
|
89
|
+
display: flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
padding: 0 10px;
|
|
92
|
+
border-bottom: 1px solid var(--ti-lowcode-toolbar-border-color, #333);
|
|
93
|
+
height: 36px;
|
|
94
|
+
|
|
95
|
+
div {
|
|
96
|
+
flex: 1;
|
|
97
|
+
margin: 0 10px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.icon-setting {
|
|
101
|
+
font-size: 16px;
|
|
102
|
+
fill: var(--ti-lowcode-toolbar-breadcrumb-color, #d9d9d9);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.icon-wrap {
|
|
106
|
+
width: 20px;
|
|
107
|
+
height: 20px;
|
|
108
|
+
fill: var(--ti-lowcode-text-color, #6a6a6a);
|
|
109
|
+
font-size: 16px;
|
|
110
|
+
border-radius: 2px;
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
display: inline-flex;
|
|
113
|
+
justify-content: center;
|
|
114
|
+
align-items: center;
|
|
115
|
+
transition: 0.3s;
|
|
116
|
+
&:hover {
|
|
117
|
+
fill: var(--ti-lowcode-toolbar-icon-color, #fff);
|
|
118
|
+
background: var(--ti-lowcode-icon-hover-bg, rgba(255, 255, 255, 0.1));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
.body {
|
|
123
|
+
padding: 0 12px;
|
|
124
|
+
|
|
125
|
+
.properties-item {
|
|
126
|
+
width: 100%;
|
|
127
|
+
padding: 8px 0;
|
|
128
|
+
display: flex;
|
|
129
|
+
justify-content: space-between;
|
|
130
|
+
align-items: center;
|
|
131
|
+
.item-label {
|
|
132
|
+
width: 40%;
|
|
133
|
+
word-break: break-all;
|
|
134
|
+
}
|
|
135
|
+
.item-component {
|
|
136
|
+
width: 100%;
|
|
137
|
+
padding-left: 8px;
|
|
138
|
+
}
|
|
139
|
+
.nolabel {
|
|
140
|
+
width: 100%;
|
|
141
|
+
}
|
|
142
|
+
&.col-6 {
|
|
143
|
+
width: 50%;
|
|
144
|
+
display: flex;
|
|
145
|
+
flex-direction: row;
|
|
146
|
+
align-items: flex-start;
|
|
147
|
+
.item-label {
|
|
148
|
+
width: auto;
|
|
149
|
+
margin-bottom: 6px;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
&.col-4 {
|
|
153
|
+
width: 33.33%;
|
|
154
|
+
flex-direction: column;
|
|
155
|
+
align-items: flex-start;
|
|
156
|
+
.item-label {
|
|
157
|
+
width: auto;
|
|
158
|
+
margin-bottom: 6px;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
.footer {
|
|
164
|
+
padding: 8px;
|
|
165
|
+
cursor: pointer;
|
|
166
|
+
span {
|
|
167
|
+
width: 100%;
|
|
168
|
+
padding: 4px 0;
|
|
169
|
+
display: inline-block;
|
|
170
|
+
background: var(--ti-lowcode-toolbar-view-hover-bg, #4d4d4d);
|
|
171
|
+
border-radius: 2px;
|
|
172
|
+
display: flex;
|
|
173
|
+
justify-content: center;
|
|
174
|
+
align-items: center;
|
|
175
|
+
}
|
|
176
|
+
svg {
|
|
177
|
+
fill: var(--ti-lowcode-toolbar-breadcrumb-color, #d9d9d9);
|
|
178
|
+
margin-left: 4px;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
</style>
|