@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.
Files changed (52) hide show
  1. package/.eslintrc.js +42 -0
  2. package/README.md +7 -0
  3. package/canvas.html +212 -0
  4. package/dist/index.js +48919 -0
  5. package/index.html +13 -0
  6. package/package.json +30 -0
  7. package/public/favicon.ico +0 -0
  8. package/src/Design.vue +53 -0
  9. package/src/assets/logo.png +0 -0
  10. package/src/canvas.js +34 -0
  11. package/src/components/builtin/CanvasBox.vue +22 -0
  12. package/src/components/builtin/CanvasCol.vue +89 -0
  13. package/src/components/builtin/CanvasCollection.js +278 -0
  14. package/src/components/builtin/CanvasCollection.vue +106 -0
  15. package/src/components/builtin/CanvasIcon.vue +30 -0
  16. package/src/components/builtin/CanvasImg.vue +18 -0
  17. package/src/components/builtin/CanvasPlaceholder.vue +26 -0
  18. package/src/components/builtin/CanvasRow.vue +67 -0
  19. package/src/components/builtin/CanvasRowColContainer.vue +42 -0
  20. package/src/components/builtin/CanvasSlot.vue +22 -0
  21. package/src/components/builtin/CanvasText.vue +18 -0
  22. package/src/components/builtin/builtin.json +955 -0
  23. package/src/components/builtin/helper.js +46 -0
  24. package/src/components/builtin/index.js +33 -0
  25. package/src/components/common/index.js +158 -0
  26. package/src/components/container/CanvasAction.vue +554 -0
  27. package/src/components/container/CanvasContainer.vue +244 -0
  28. package/src/components/container/CanvasDivider.vue +246 -0
  29. package/src/components/container/CanvasDragItem.vue +38 -0
  30. package/src/components/container/CanvasFooter.vue +86 -0
  31. package/src/components/container/CanvasMenu.vue +214 -0
  32. package/src/components/container/CanvasResize.vue +195 -0
  33. package/src/components/container/CanvasResizeBorder.vue +219 -0
  34. package/src/components/container/container.js +791 -0
  35. package/src/components/container/keyboard.js +147 -0
  36. package/src/components/container/shortCutPopover.vue +181 -0
  37. package/src/components/render/CanvasEmpty.vue +14 -0
  38. package/src/components/render/RenderMain.js +408 -0
  39. package/src/components/render/context.js +53 -0
  40. package/src/components/render/render.js +689 -0
  41. package/src/components/render/runner.js +140 -0
  42. package/src/i18n/en.json +5 -0
  43. package/src/i18n/zh.json +5 -0
  44. package/src/i18n.js +21 -0
  45. package/src/index.js +96 -0
  46. package/src/locale.js +19 -0
  47. package/src/lowcode.js +104 -0
  48. package/src/main.js +17 -0
  49. package/test/form.json +690 -0
  50. package/test/group.json +99 -0
  51. package/test/jsslot.json +427 -0
  52. 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>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <p class="empty-text">从左侧面板拖入组件,以构建页面</p>
3
+ </template>
4
+
5
+ <style lang="less" scoped>
6
+ .empty-text {
7
+ position: absolute;
8
+ top: 250px;
9
+ left: 50%;
10
+ transform: translate(-50%);
11
+ color: #808080;
12
+ font-size: 12px;
13
+ }
14
+ </style>