@mixd-id/web-scaffold 0.1.230406109 → 0.1.230406111
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/package.json +1 -1
- package/src/components/Ahref.vue +175 -7
- package/src/components/CopyToClipboard.vue +6 -31
- package/src/components/TreeView.vue +17 -2
- package/src/components/TreeViewItem.vue +49 -29
- package/src/index.js +2 -0
- package/src/utils/helpers.mjs +38 -1
- package/src/widgets/AhrefItem.vue +25 -0
- package/src/widgets/AhrefSetting.vue +91 -0
- package/src/widgets/ComponentSetting.vue +1 -1
- package/src/widgets/WebPageBuilder.vue +35 -5
package/package.json
CHANGED
package/src/components/Ahref.vue
CHANGED
|
@@ -1,31 +1,199 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<a v-if="isExternalLink" :href="href" :target="target">
|
|
3
|
-
<slot
|
|
2
|
+
<a v-if="isExternalLink" :href="href" :target="target" :class="compClass">
|
|
3
|
+
<slot>{{ text }}</slot>
|
|
4
4
|
</a>
|
|
5
|
-
<router-link v-else :to="href" :target="target">
|
|
6
|
-
<slot
|
|
5
|
+
<router-link v-else :to="href" :target="target" :class="compClass">
|
|
6
|
+
<slot>{{ text }}</slot>
|
|
7
7
|
</router-link>
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script>
|
|
11
11
|
|
|
12
|
+
import {componentMixin} from "../mixin/component";
|
|
13
|
+
|
|
12
14
|
export default {
|
|
13
15
|
|
|
16
|
+
mixins: [ componentMixin ],
|
|
17
|
+
|
|
14
18
|
props: {
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
|
|
20
|
+
href: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: ''
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
target: String,
|
|
26
|
+
|
|
27
|
+
text: String,
|
|
28
|
+
|
|
29
|
+
variant: {
|
|
30
|
+
type: [ String, Number ],
|
|
31
|
+
default: "primary" // primary|secondary|outline, default:primary
|
|
32
|
+
},
|
|
17
33
|
},
|
|
18
34
|
|
|
19
35
|
computed: {
|
|
20
36
|
|
|
21
37
|
isExternalLink() {
|
|
22
38
|
return typeof this.href === 'string' && this.href.indexOf('://') > 0
|
|
23
|
-
}
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
compClass(){
|
|
42
|
+
return [
|
|
43
|
+
this.$style.button,
|
|
44
|
+
this.$style['button-' + this.variant]
|
|
45
|
+
]
|
|
46
|
+
.filter(_ => _)
|
|
47
|
+
.join(' ')
|
|
48
|
+
},
|
|
24
49
|
},
|
|
25
50
|
}
|
|
26
51
|
</script>
|
|
27
52
|
|
|
28
53
|
<style module>
|
|
29
54
|
|
|
55
|
+
.button{
|
|
56
|
+
@apply p-2 h-[var(--h-cp)];
|
|
57
|
+
@apply relative flex items-center justify-center;
|
|
58
|
+
@apply whitespace-nowrap text-ellipsis overflow-hidden;
|
|
59
|
+
@apply rounded-lg;
|
|
60
|
+
background-image: v-bind(bgImages[0]);
|
|
61
|
+
}
|
|
62
|
+
.button>*:first-child{
|
|
63
|
+
@apply flex items-center justify-center
|
|
64
|
+
}
|
|
65
|
+
.button:disabled{
|
|
66
|
+
@apply opacity-60;
|
|
67
|
+
}
|
|
68
|
+
.button:active{
|
|
69
|
+
@apply top-[1px] left-[1px] relative;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.button-primary{
|
|
73
|
+
@apply bg-primary-500 text-white rounded-lg;
|
|
74
|
+
box-shadow: 0 2px 1px rgba(0, 0, 0, .05);
|
|
75
|
+
outline: solid 1px rgb(var(--primary-700));
|
|
76
|
+
border: solid 1px rgb(var(--primary-400));
|
|
77
|
+
}
|
|
78
|
+
.button-primary:focus{
|
|
79
|
+
outline-color: rgb(var(--primary-800));
|
|
80
|
+
border-color: rgb(var(--primary-600));
|
|
81
|
+
}
|
|
82
|
+
.button-primary:hover{
|
|
83
|
+
@apply bg-primary-600;
|
|
84
|
+
outline-color: rgb(var(--primary-800))
|
|
85
|
+
}
|
|
86
|
+
.button-primary:disabled{
|
|
87
|
+
@apply bg-primary-500 opacity-50 top-0 left-0 cursor-not-allowed;
|
|
88
|
+
@apply top-0 left-0;
|
|
89
|
+
outline: solid 1px rgb(var(--primary-700));
|
|
90
|
+
}
|
|
91
|
+
.button-primary *{
|
|
92
|
+
@apply text-white fill-white;
|
|
93
|
+
}
|
|
94
|
+
.button-primary.loading *{
|
|
95
|
+
@apply fill-transparent
|
|
96
|
+
}
|
|
97
|
+
.button-primary .svgBg{
|
|
98
|
+
stroke: #fff;
|
|
99
|
+
stroke-opacity: 25%;
|
|
100
|
+
}
|
|
101
|
+
.button-primary .svgHg{
|
|
102
|
+
fill: #fff;
|
|
103
|
+
fill-opacity: 75%;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.button-outline{
|
|
107
|
+
@apply bg-transparent text-primary-500;
|
|
108
|
+
outline: solid 1px rgb(var(--primary-700));
|
|
109
|
+
}
|
|
110
|
+
.button-outline:hover{
|
|
111
|
+
outline-color: rgb(var(--primary-800))
|
|
112
|
+
}
|
|
113
|
+
.button-outline:disabled{
|
|
114
|
+
@apply opacity-50 top-0 left-0 cursor-not-allowed;
|
|
115
|
+
@apply text-text border-primary-500;
|
|
116
|
+
}
|
|
117
|
+
.button-outline *{
|
|
118
|
+
@apply text-primary-500 fill-primary-500;
|
|
119
|
+
}
|
|
120
|
+
.button-outline.loading *{
|
|
121
|
+
@apply fill-transparent
|
|
122
|
+
}
|
|
123
|
+
.button-outline .svgBg{
|
|
124
|
+
stroke: rgb(var(--primary-600));
|
|
125
|
+
stroke-opacity: 50%;
|
|
126
|
+
}
|
|
127
|
+
.button-outline .svgHg{
|
|
128
|
+
fill: rgb(var(--primary));
|
|
129
|
+
fill-opacity: 100%;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.button-secondary{
|
|
133
|
+
@apply bg-secondary text-text-500 rounded-lg;
|
|
134
|
+
box-shadow: 0 2px 1px rgba(0, 0, 0, .05);
|
|
135
|
+
outline: solid 1px rgb(var(--secondary-700));
|
|
136
|
+
border: solid 1px rgb(var(--secondary-400));
|
|
137
|
+
}
|
|
138
|
+
.button-secondary:hover{
|
|
139
|
+
@apply bg-secondary-600;
|
|
140
|
+
outline-color: rgb(var(--secondary-800))
|
|
141
|
+
}
|
|
142
|
+
.button-secondary:disabled{
|
|
143
|
+
@apply bg-secondary-500 opacity-50 top-0 left-0 cursor-not-allowed;
|
|
144
|
+
outline: solid 1px rgb(var(--secondary-700));
|
|
145
|
+
}
|
|
146
|
+
.button-secondary *{
|
|
147
|
+
@apply text-text-500 fill-white;
|
|
148
|
+
}
|
|
149
|
+
.button-secondary.loading *{
|
|
150
|
+
@apply fill-transparent
|
|
151
|
+
}
|
|
152
|
+
.button-secondary .svgBg{
|
|
153
|
+
stroke: rgb(var(--text-400));
|
|
154
|
+
stroke-opacity: 25%;
|
|
155
|
+
}
|
|
156
|
+
.button-secondary .svgHg{
|
|
157
|
+
fill: rgb(var(--text-500));
|
|
158
|
+
fill-opacity: 75%;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.button-red{
|
|
162
|
+
@apply bg-red-500 text-white rounded-md border-[2px] border-red-500;
|
|
163
|
+
}
|
|
164
|
+
.button-red:hover{
|
|
165
|
+
@apply bg-red-600 border-red-600;
|
|
166
|
+
}
|
|
167
|
+
.button-red:disabled{
|
|
168
|
+
@apply bg-red-500 border-red-500 opacity-50 top-0 left-0 cursor-not-allowed;
|
|
169
|
+
}
|
|
170
|
+
.button-red *{
|
|
171
|
+
@apply text-white fill-white;
|
|
172
|
+
}
|
|
173
|
+
.button-red.loading *{
|
|
174
|
+
@apply fill-transparent
|
|
175
|
+
}
|
|
176
|
+
.button-red .svgBg{
|
|
177
|
+
@apply stroke-red-400;
|
|
178
|
+
stroke-opacity: 50%;
|
|
179
|
+
}
|
|
180
|
+
.button-red .svgHg{
|
|
181
|
+
@apply fill-text-500;
|
|
182
|
+
fill-opacity: 100%;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.button-minimal{
|
|
186
|
+
@apply border-[2px] border-transparent;
|
|
187
|
+
}
|
|
188
|
+
.button-minimal:hover{
|
|
189
|
+
}
|
|
190
|
+
.button-minimal .svgBg{
|
|
191
|
+
stroke: rgb(var(--text-500));
|
|
192
|
+
stroke-opacity: 25%;
|
|
193
|
+
}
|
|
194
|
+
.button-minimal .svgHg{
|
|
195
|
+
fill: rgb(var(--text));
|
|
196
|
+
fill-opacity: 75%;
|
|
197
|
+
}
|
|
30
198
|
|
|
31
199
|
</style>
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
<script>
|
|
8
8
|
|
|
9
|
+
import {copyToClipboard} from "../utils/helpers.mjs";
|
|
10
|
+
|
|
9
11
|
export default{
|
|
10
12
|
|
|
11
13
|
emits: [ 'copied', 'error' ],
|
|
@@ -19,41 +21,14 @@ export default{
|
|
|
19
21
|
|
|
20
22
|
methods: {
|
|
21
23
|
|
|
22
|
-
fallbackCopyTextToClipboard(text){
|
|
23
|
-
var textArea = document.createElement("textarea");
|
|
24
|
-
textArea.value = this.value;
|
|
25
|
-
textArea.style.top = "0";
|
|
26
|
-
textArea.style.left = "0";
|
|
27
|
-
textArea.style.position = "fixed";
|
|
28
|
-
document.body.appendChild(textArea);
|
|
29
|
-
textArea.focus();
|
|
30
|
-
textArea.select();
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
document.execCommand('copy')
|
|
34
|
-
this.$emit('copied')
|
|
35
|
-
} catch (err) {
|
|
36
|
-
this.$emit('error')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
document.body.removeChild(textArea);
|
|
40
|
-
},
|
|
41
|
-
|
|
42
24
|
copyToClipboard(){
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
navigator.clipboard.writeText(this.value).then(() => {
|
|
49
|
-
this.$emit('copied')
|
|
50
|
-
}, (err) => {
|
|
51
|
-
this.$emit('error')
|
|
52
|
-
});
|
|
25
|
+
copyToClipboard(this.value)
|
|
26
|
+
.then(() => this.$emit('copied'))
|
|
27
|
+
.catch(() => this.$emit('error'))
|
|
53
28
|
}
|
|
54
29
|
|
|
55
30
|
}
|
|
56
31
|
|
|
57
32
|
}
|
|
58
33
|
|
|
59
|
-
</script>
|
|
34
|
+
</script>
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
@movedown="moveDown(item)"
|
|
10
10
|
@change="$emit('change')"
|
|
11
11
|
@remove="confirm($t('Remove this item?'), { onConfirm: () => { modelValue.splice(index, 1);$emit('change') }})"
|
|
12
|
-
@add="(items) => $emit('add', items)"
|
|
12
|
+
@add="(items) => $emit('add', items)"
|
|
13
|
+
@paste.stop.prevent="(e) => paste(e, item)"
|
|
14
|
+
@item-paste="(p1, p2, p3) => $emit('item-paste', p1, p2, p3)">
|
|
13
15
|
<template #default="{ item }">
|
|
14
16
|
<slot :item="item"></slot>
|
|
15
17
|
</template>
|
|
@@ -26,7 +28,7 @@ export default{
|
|
|
26
28
|
|
|
27
29
|
components: {TreeViewItem},
|
|
28
30
|
|
|
29
|
-
emits: [ 'add', 'change' ],
|
|
31
|
+
emits: [ 'add', 'change', 'item-paste' ],
|
|
30
32
|
|
|
31
33
|
inject: [ 'confirm' ],
|
|
32
34
|
|
|
@@ -40,6 +42,19 @@ export default{
|
|
|
40
42
|
|
|
41
43
|
methods: {
|
|
42
44
|
|
|
45
|
+
paste(event, subItem){
|
|
46
|
+
const clipboardData = event.clipboardData || window.clipboardData;
|
|
47
|
+
const pastedText = clipboardData.getData('text');
|
|
48
|
+
|
|
49
|
+
try{
|
|
50
|
+
const newItem = JSON.parse(pastedText)
|
|
51
|
+
this.$emit('item-paste', this.modelValue, subItem, newItem)
|
|
52
|
+
}
|
|
53
|
+
catch(e){
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
43
58
|
moveDown(item){
|
|
44
59
|
const idx = this.modelValue.indexOf(item)
|
|
45
60
|
if(idx < this.modelValue.length - 1){
|
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
2
|
+
<div @copy.stop.prevent="copy">
|
|
3
3
|
<div ref="item" :class="itemClass"
|
|
4
|
-
@mouseover="hoverMouseOver"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<div class="flex flex-col hidden">
|
|
9
|
-
<button type="button" @click="$emit('moveup')">
|
|
10
|
-
<svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M32.032 352h255.93c28.425 0 42.767-34.488 22.627-54.627l-127.962-128c-12.496-12.496-32.758-12.497-45.255 0l-127.968 128C-10.695 317.472 3.55 352 32.032 352zM160 192l128 128H32l128-128z"/></svg>
|
|
11
|
-
</button>
|
|
12
|
-
<button type="button" @click="$emit('movedown')">
|
|
13
|
-
<svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M287.968 160H32.038c-28.425 0-42.767 34.488-22.627 54.627l127.962 128c12.496 12.496 32.758 12.497 45.255 0l127.968-128C330.695 194.528 316.45 160 287.968 160zM160 320L32 192h256L160 320z"/></svg>
|
|
14
|
-
</button>
|
|
15
|
-
</div>
|
|
16
|
-
<slot :item="item"></slot>
|
|
17
|
-
<button type="button" class="py-2" @click="$emit('remove')">
|
|
18
|
-
<svg width="16" height="16" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M193.94 256L296.5 153.44l21.15-21.15c3.12-3.12 3.12-8.19 0-11.31l-22.63-22.63c-3.12-3.12-8.19-3.12-11.31 0L160 222.06 36.29 98.34c-3.12-3.12-8.19-3.12-11.31 0L2.34 120.97c-3.12 3.12-3.12 8.19 0 11.31L126.06 256 2.34 379.71c-3.12 3.12-3.12 8.19 0 11.31l22.63 22.63c3.12 3.12 8.19 3.12 11.31 0L160 289.94 262.56 392.5l21.15 21.15c3.12 3.12 8.19 3.12 11.31 0l22.63-22.63c3.12-3.12 3.12-8.19 0-11.31L193.94 256z"/></svg>
|
|
19
|
-
</button>
|
|
4
|
+
@mouseover="hoverMouseOver"
|
|
5
|
+
@mouseout="hoverMouseOut"
|
|
6
|
+
@mousedown="mouseDown"
|
|
7
|
+
@mouseup="hoverMouseUp">
|
|
20
8
|
<button type="button" class="py-2" v-if="Array.isArray((item ?? {}).items) && item.items.length > 0"
|
|
21
|
-
|
|
9
|
+
@click="childCollapsed = !childCollapsed">
|
|
22
10
|
<svg v-if="!childCollapsed" width="16" height="16" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"/></svg>
|
|
23
11
|
<svg v-else width="16" height="16" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path d="M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z"/></svg>
|
|
24
12
|
</button>
|
|
13
|
+
<div v-else class="pl-1"></div>
|
|
14
|
+
<slot :item="item"></slot>
|
|
15
|
+
<button type="button" class="py-2" @click="$emit('remove')">
|
|
16
|
+
<svg width="16" height="16" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M193.94 256L296.5 153.44l21.15-21.15c3.12-3.12 3.12-8.19 0-11.31l-22.63-22.63c-3.12-3.12-8.19-3.12-11.31 0L160 222.06 36.29 98.34c-3.12-3.12-8.19-3.12-11.31 0L2.34 120.97c-3.12 3.12-3.12 8.19 0 11.31L126.06 256 2.34 379.71c-3.12 3.12-3.12 8.19 0 11.31l22.63 22.63c3.12 3.12 8.19 3.12 11.31 0L160 289.94 262.56 392.5l21.15 21.15c3.12 3.12 8.19 3.12 11.31 0l22.63-22.63c3.12-3.12 3.12-8.19 0-11.31L193.94 256z"/></svg>
|
|
17
|
+
</button>
|
|
25
18
|
</div>
|
|
26
19
|
<div ref="container" v-if="item && Array.isArray(item.items) && !childCollapsed" class="ml-4">
|
|
27
20
|
<TreeViewItem v-for="(subItem, index) in item.items"
|
|
@@ -32,7 +25,9 @@
|
|
|
32
25
|
@movedown="moveDown(subItem)"
|
|
33
26
|
@remove="confirm($t('Remove this item?'), { onConfirm: () => { item.items.splice(index, 1);$emit('change') }})"
|
|
34
27
|
@add="(items) => $emit('add', items)"
|
|
35
|
-
@change="$emit('change')"
|
|
28
|
+
@change="$emit('change')"
|
|
29
|
+
@paste.stop.prevent="(e) => paste(e, subItem)"
|
|
30
|
+
@item-paste="(p1, p2, p3) => $emit('item-paste', p1, p2, p3)">
|
|
36
31
|
<template #default="{ item }">
|
|
37
32
|
<slot :item="item"></slot>
|
|
38
33
|
</template>
|
|
@@ -50,13 +45,15 @@
|
|
|
50
45
|
|
|
51
46
|
<script>
|
|
52
47
|
|
|
48
|
+
import {copyToClipboard} from "../utils/helpers.mjs";
|
|
49
|
+
|
|
53
50
|
let dragged = null
|
|
54
51
|
|
|
55
52
|
export default{
|
|
56
53
|
|
|
57
|
-
emits: [ 'add', 'change', 'moveup', 'movedown', 'remove' ],
|
|
54
|
+
emits: [ 'add', 'change', 'moveup', 'movedown', 'remove', 'item-paste' ],
|
|
58
55
|
|
|
59
|
-
inject: [ 'confirm' ],
|
|
56
|
+
inject: [ 'confirm', 'toast' ],
|
|
60
57
|
|
|
61
58
|
props: {
|
|
62
59
|
item: Object,
|
|
@@ -73,6 +70,24 @@ export default{
|
|
|
73
70
|
|
|
74
71
|
methods: {
|
|
75
72
|
|
|
73
|
+
copy(){
|
|
74
|
+
copyToClipboard(JSON.stringify(this.item))
|
|
75
|
+
this.toast(this.item.type + ' copied')
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
paste(event, subItem){
|
|
79
|
+
const clipboardData = event.clipboardData || window.clipboardData;
|
|
80
|
+
const pastedText = clipboardData.getData('text');
|
|
81
|
+
|
|
82
|
+
try{
|
|
83
|
+
const newItem = JSON.parse(pastedText)
|
|
84
|
+
this.$emit('item-paste', this.item.items, subItem, newItem)
|
|
85
|
+
}
|
|
86
|
+
catch(e){
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
|
|
76
91
|
moveDown(item){
|
|
77
92
|
const idx = this.item.items.indexOf(item)
|
|
78
93
|
if(idx < this.item.items.length - 1){
|
|
@@ -94,13 +109,16 @@ export default{
|
|
|
94
109
|
},
|
|
95
110
|
|
|
96
111
|
mouseDown(e){
|
|
97
|
-
|
|
98
112
|
e.preventDefault()
|
|
99
113
|
|
|
114
|
+
const rect = this.$el.getBoundingClientRect()
|
|
115
|
+
const startX = e.clientX
|
|
116
|
+
const startY = e.clientY
|
|
117
|
+
|
|
100
118
|
const cloned = this.$el.cloneNode(true)
|
|
101
119
|
cloned.style.position = 'absolute'
|
|
102
|
-
cloned.style.left =
|
|
103
|
-
cloned.style.top =
|
|
120
|
+
cloned.style.left = rect.x + "px"
|
|
121
|
+
cloned.style.top = rect.y + "px"
|
|
104
122
|
cloned.style.width = this.$el.clientWidth + "px"
|
|
105
123
|
cloned.style.pointerEvents = 'none'
|
|
106
124
|
document.body.appendChild(cloned)
|
|
@@ -111,8 +129,10 @@ export default{
|
|
|
111
129
|
}
|
|
112
130
|
|
|
113
131
|
const mouseMove = (e) => {
|
|
114
|
-
|
|
115
|
-
|
|
132
|
+
const distanceX = e.clientX - startX
|
|
133
|
+
const distanceY = e.clientY - startY
|
|
134
|
+
cloned.style.left = (rect.x + distanceX) + "px"
|
|
135
|
+
cloned.style.top = (rect.y + distanceY) + "px"
|
|
116
136
|
}
|
|
117
137
|
|
|
118
138
|
const mouseUp = (e) => {
|
|
@@ -170,7 +190,7 @@ export default{
|
|
|
170
190
|
delete dragged.targetParent
|
|
171
191
|
}
|
|
172
192
|
|
|
173
|
-
}
|
|
193
|
+
},
|
|
174
194
|
|
|
175
195
|
},
|
|
176
196
|
|
|
@@ -201,8 +221,8 @@ export default{
|
|
|
201
221
|
<style module>
|
|
202
222
|
|
|
203
223
|
.item{
|
|
204
|
-
@apply bg-base-300 dark:bg-base-400 flex flex-row gap-2 px-
|
|
205
|
-
@apply border-[1px] border-transparent;
|
|
224
|
+
@apply bg-base-300 dark:bg-base-400 flex flex-row gap-2 px-2 items-center rounded-lg mb-1;
|
|
225
|
+
@apply border-[1px] border-transparent cursor-pointer;
|
|
206
226
|
}
|
|
207
227
|
.item.active{
|
|
208
228
|
@apply border-primary;
|
package/src/index.js
CHANGED
|
@@ -354,6 +354,8 @@ export default{
|
|
|
354
354
|
app.component('BlockSetting', defineAsyncComponent(() => import("./widgets/BlockSetting.vue")))
|
|
355
355
|
app.component('BoxItem', defineAsyncComponent(() => import("./widgets/BoxItem.vue")))
|
|
356
356
|
app.component('BoxSetting', defineAsyncComponent(() => import("./widgets/BoxSetting.vue")))
|
|
357
|
+
app.component('AhrefItem', defineAsyncComponent(() => import("./widgets/AhrefItem.vue")))
|
|
358
|
+
app.component('AhrefSetting', defineAsyncComponent(() => import("./widgets/AhrefSetting.vue")))
|
|
357
359
|
app.component('ButtonItem', defineAsyncComponent(() => import("./widgets/ButtonItem.vue")))
|
|
358
360
|
app.component('ButtonSetting', defineAsyncComponent(() => import("./widgets/ButtonSetting.vue")))
|
|
359
361
|
app.component('CarouselItem', defineAsyncComponent(() => import("./widgets/CarouselItem.vue")))
|
package/src/utils/helpers.mjs
CHANGED
|
@@ -177,6 +177,42 @@ const _applyClass = function(props, defaultClass = {}){
|
|
|
177
177
|
return []
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
const fallbackCopyTextToClipboard = function(obj){
|
|
181
|
+
return new Promise((resolve, reject) => {
|
|
182
|
+
var textArea = document.createElement("textarea");
|
|
183
|
+
textArea.value = obj;
|
|
184
|
+
textArea.style.top = "0";
|
|
185
|
+
textArea.style.left = "0";
|
|
186
|
+
textArea.style.position = "fixed";
|
|
187
|
+
document.body.appendChild(textArea);
|
|
188
|
+
textArea.focus();
|
|
189
|
+
textArea.select();
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
document.execCommand('copy')
|
|
193
|
+
document.body.removeChild(textArea);
|
|
194
|
+
resolve()
|
|
195
|
+
} catch (err) {
|
|
196
|
+
reject(err)
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const copyToClipboard = function(obj){
|
|
202
|
+
|
|
203
|
+
if (!navigator.clipboard) {
|
|
204
|
+
return fallbackCopyTextToClipboard(obj);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return new Promise((resolve, reject) => {
|
|
208
|
+
navigator.clipboard.writeText(obj).then(() => {
|
|
209
|
+
resolve()
|
|
210
|
+
}, (err) => {
|
|
211
|
+
reject(err)
|
|
212
|
+
});
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
180
216
|
export {
|
|
181
217
|
downsizeImage,
|
|
182
218
|
uid,
|
|
@@ -187,7 +223,8 @@ export {
|
|
|
187
223
|
getQueryString,
|
|
188
224
|
accessNestedObject,
|
|
189
225
|
mediaPrefixes,
|
|
190
|
-
_applyClass
|
|
226
|
+
_applyClass,
|
|
227
|
+
copyToClipboard
|
|
191
228
|
}
|
|
192
229
|
|
|
193
230
|
function observeInit(){
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex-1 flex flex-row items-center gap-2">
|
|
3
|
+
{{ item.props.name ?? item.type }}
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
|
|
9
|
+
export default{
|
|
10
|
+
|
|
11
|
+
props: {
|
|
12
|
+
item: Object
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<style module>
|
|
20
|
+
|
|
21
|
+
.comp{
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="$style.comp">
|
|
3
|
+
|
|
4
|
+
<div>
|
|
5
|
+
<label class="flex-1 text-text-400">Text</label>
|
|
6
|
+
<Textbox v-model="item.props.text" @keyup.enter="$emit('change')"/>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div>
|
|
10
|
+
<label class="flex-1 text-text-400">Href</label>
|
|
11
|
+
<Textbox v-model="item.props.href" @keyup.enter="$emit('change')"/>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div>
|
|
15
|
+
<label class="flex-1 text-text-400">Target</label>
|
|
16
|
+
<Dropdown v-model="item.props.target" @change="$emit('change')">
|
|
17
|
+
<option value="_self">Self</option>
|
|
18
|
+
<option value="_blank">Blank</option>
|
|
19
|
+
<option value="_parent">Parent</option>
|
|
20
|
+
<option value="_top">Top</option>
|
|
21
|
+
</Dropdown>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div>
|
|
25
|
+
<label class="flex-1 text-text-400">Variant</label>
|
|
26
|
+
<Dropdown v-model="item.props.variant"
|
|
27
|
+
@change="$emit('change')">
|
|
28
|
+
<option value="primary">Primary</option>
|
|
29
|
+
<option value="secondary">Secondary</option>
|
|
30
|
+
<option value="red">Red</option>
|
|
31
|
+
<option value="minimal">Minimal</option>
|
|
32
|
+
<option value="outline">Outline</option>
|
|
33
|
+
<option value="">Not Set</option>
|
|
34
|
+
</Dropdown>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<ComponentSetting :item="item"
|
|
38
|
+
:view-type="viewType"
|
|
39
|
+
:view-types="viewTypes"
|
|
40
|
+
defaultDisplay="flex"
|
|
41
|
+
@change="$emit('change')" />
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<script>
|
|
47
|
+
|
|
48
|
+
export default{
|
|
49
|
+
|
|
50
|
+
emits: [ 'change' ],
|
|
51
|
+
|
|
52
|
+
props: {
|
|
53
|
+
|
|
54
|
+
item: {
|
|
55
|
+
type: Object,
|
|
56
|
+
required: true
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
viewType: String,
|
|
60
|
+
|
|
61
|
+
viewTypes: Array,
|
|
62
|
+
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
data(){
|
|
66
|
+
return {
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
inject: [ 'confirm', 'imageSrc' ],
|
|
71
|
+
|
|
72
|
+
methods: {
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
computed: {
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<style module>
|
|
86
|
+
|
|
87
|
+
.comp{
|
|
88
|
+
@apply flex flex-col gap-4;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
</style>
|
|
@@ -421,7 +421,7 @@
|
|
|
421
421
|
|
|
422
422
|
<div class="flex flex-col gap-4">
|
|
423
423
|
|
|
424
|
-
<
|
|
424
|
+
<strong class="flex-1 text-text-400">Shadow</strong>
|
|
425
425
|
|
|
426
426
|
<div class="flex flex-row items-center gap-4">
|
|
427
427
|
<label class="flex-1 text-text-400">Box Shadow</label>
|
|
@@ -144,7 +144,8 @@
|
|
|
144
144
|
v-model="layout.headers"
|
|
145
145
|
:selected-item="currentItem"
|
|
146
146
|
@add="openSelector"
|
|
147
|
-
@change="saveLayout"
|
|
147
|
+
@change="saveLayout"
|
|
148
|
+
@item-paste="onLayoutItemPaste">
|
|
148
149
|
<template #default="{ item }">
|
|
149
150
|
<component :is="`${(item ?? {}).type}Item`" :item="item"
|
|
150
151
|
@click="store.selectedComponent = [ item.uid ]"/>
|
|
@@ -161,7 +162,8 @@
|
|
|
161
162
|
v-model="layout.footers"
|
|
162
163
|
:selected-item="currentItem"
|
|
163
164
|
@add="openSelector"
|
|
164
|
-
@change="saveLayout"
|
|
165
|
+
@change="saveLayout"
|
|
166
|
+
@item-paste="onLayoutItemPaste">
|
|
165
167
|
<template #default="{ item }">
|
|
166
168
|
<component :is="`${(item ?? {}).type}Item`" :item="item"
|
|
167
169
|
@click="store.selectedComponent = [ item.uid ]"/>
|
|
@@ -178,7 +180,8 @@
|
|
|
178
180
|
v-model="page.components"
|
|
179
181
|
:selected-item="currentItem"
|
|
180
182
|
@add="openSelector"
|
|
181
|
-
@change="save"
|
|
183
|
+
@change="save"
|
|
184
|
+
@item-paste="onItemPaste">
|
|
182
185
|
|
|
183
186
|
<template #default="{ item }">
|
|
184
187
|
<component :is="`${(item ?? {}).type}Item`" :item="item"
|
|
@@ -253,7 +256,7 @@
|
|
|
253
256
|
</template>
|
|
254
257
|
<template #end>
|
|
255
258
|
<div class="flex flex-row gap-4">
|
|
256
|
-
<CopyToClipboard :value="iframeSrc" @copied="toast('
|
|
259
|
+
<CopyToClipboard :value="iframeSrc" @copied="toast($t('Copied'))">
|
|
257
260
|
<svg width="14" height="14" class="fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM352 32.491a15.88 15.88 0 0 1 7.431 4.195l51.882 51.883A15.885 15.885 0 0 1 415.508 96H352V32.491zM288 464c0 8.822-7.178 16-16 16H48c-8.822 0-16-7.178-16-16V144c0-8.822 7.178-16 16-16h80v240c0 26.51 21.49 48 48 48h112v48zm128-96c0 8.822-7.178 16-16 16H176c-8.822 0-16-7.178-16-16V48c0-8.822 7.178-16 16-16h144v72c0 13.2 10.8 24 24 24h72v240z"/></svg>
|
|
258
261
|
</CopyToClipboard>
|
|
259
262
|
<a type="button" class="w-[21px]" :href="iframeSrc" target="_blank">
|
|
@@ -467,7 +470,7 @@ export default{
|
|
|
467
470
|
enabled: true
|
|
468
471
|
})
|
|
469
472
|
|
|
470
|
-
obj.uid = md5(obj.type +
|
|
473
|
+
obj.uid = md5(obj.type + Math.random())
|
|
471
474
|
|
|
472
475
|
if([ 'headers', 'footers' ].includes(to)){
|
|
473
476
|
this.layout[to].push(obj)
|
|
@@ -777,6 +780,29 @@ export default{
|
|
|
777
780
|
this.$refs.iframe.contentWindow.postMessage({ uid, data }, '*')
|
|
778
781
|
},
|
|
779
782
|
|
|
783
|
+
onLayoutItemPaste(items, currentItem, newItem){
|
|
784
|
+
this.onItemPaste(items, currentItem, newItem, true)
|
|
785
|
+
},
|
|
786
|
+
|
|
787
|
+
onItemPaste(items, currentItem, newItem, isLayout = false){
|
|
788
|
+
|
|
789
|
+
const setUid = (item) => {
|
|
790
|
+
item.uid = md5(newItem.type + Math.random())
|
|
791
|
+
|
|
792
|
+
if(Array.isArray(item.items)){
|
|
793
|
+
for(let subItem of item.items){
|
|
794
|
+
setUid(subItem)
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
setUid(newItem)
|
|
800
|
+
items.splice(items.indexOf(currentItem) + 1, 0, newItem)
|
|
801
|
+
this.store.selectedComponent = [ newItem.uid ]
|
|
802
|
+
|
|
803
|
+
isLayout ? this.saveLayout() : this.save()
|
|
804
|
+
},
|
|
805
|
+
|
|
780
806
|
findCompByUid(uid, components){
|
|
781
807
|
|
|
782
808
|
for(let i in components){
|
|
@@ -971,6 +997,10 @@ export default{
|
|
|
971
997
|
htmlText:'', images:{},
|
|
972
998
|
}},
|
|
973
999
|
|
|
1000
|
+
{ type:'Ahref', name:'Ahref', group:'Components', props:{
|
|
1001
|
+
name:'Ahref', text:'Ahref'
|
|
1002
|
+
}},
|
|
1003
|
+
|
|
974
1004
|
{ type:'Button', name:'Button', group:'Components', props:{
|
|
975
1005
|
name:'Button', text:'Button'
|
|
976
1006
|
}},
|