@mixd-id/web-scaffold 0.1.230406174 → 0.1.230406176
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/Button.vue +7 -13
- package/src/components/Carousel.vue +2 -2
- package/src/components/HTMLEditor.vue +2 -2
- package/src/components/Image.vue +1 -1
- package/src/components/ListItem.vue +7 -5
- package/src/components/Modal.vue +99 -4
- package/src/components/Paragraph.vue +27 -0
- package/src/components/Radio.vue +29 -4
- package/src/components/Tabs.vue +3 -4
- package/src/components/Textbox.vue +5 -5
- package/src/components/TreeView.vue +8 -3
- package/src/components/TreeViewItem.vue +60 -32
- package/src/index.js +5 -20
- package/src/mixin/component.js +10 -0
- package/src/themes/default/index.js +20 -14
- package/src/utils/helpers.mjs +32 -0
- package/src/widgets/ComponentSetting.vue +1256 -667
- package/src/widgets/FeatureListSetting.vue +3 -3
- package/src/widgets/FlexSetting.vue +1 -1
- package/src/widgets/Header.vue +4 -39
- package/src/widgets/Header1.vue +50 -0
- package/src/widgets/Header2.vue +103 -0
- package/src/widgets/HeaderSetting.vue +212 -4
- package/src/widgets/IconListSetting.vue +3 -3
- package/src/widgets/ImageSetting.vue +2 -2
- package/src/widgets/MarginSetting.vue +4 -4
- package/src/widgets/MultiValueSetting.vue +121 -0
- package/src/widgets/PaddingSetting.vue +4 -4
- package/src/widgets/ParagraphSetting.vue +86 -0
- package/src/widgets/TextBlockSetting.vue +1 -1
- package/src/widgets/WebDatasourceSelector.vue +3 -3
- package/src/widgets/WebPageBuilder.vue +1324 -1159
- package/tailwind.config.js +121 -13
- package/src/widgets/AhrefItem.vue +0 -25
- package/src/widgets/ArticleItem.vue +0 -25
- package/src/widgets/BlockItem.vue +0 -25
- package/src/widgets/BoxItem.vue +0 -25
- package/src/widgets/ButtonItem.vue +0 -25
- package/src/widgets/CarouselItem.vue +0 -19
- package/src/widgets/ContactFormItem.vue +0 -25
- package/src/widgets/EmbeddedVideoItem.vue +0 -25
- package/src/widgets/FAQItem.vue +0 -25
- package/src/widgets/FeatureListItem.vue +0 -25
- package/src/widgets/FlexItem.vue +0 -27
- package/src/widgets/GridItem.vue +0 -29
- package/src/widgets/HeaderItem.vue +0 -25
- package/src/widgets/IconListItem.vue +0 -25
- package/src/widgets/ImageItem.vue +0 -19
- package/src/widgets/ReviewItem.vue +0 -25
- package/src/widgets/ShareItem.vue +0 -25
- package/src/widgets/TableItem.vue +0 -25
- package/src/widgets/TestimonialItem.vue +0 -25
- package/src/widgets/TextBlockItem.vue +0 -25
package/package.json
CHANGED
|
@@ -132,7 +132,7 @@ export default{
|
|
|
132
132
|
<style module>
|
|
133
133
|
|
|
134
134
|
.button{
|
|
135
|
-
@apply p-2
|
|
135
|
+
@apply p-2;
|
|
136
136
|
@apply relative flex items-center justify-center;
|
|
137
137
|
@apply whitespace-nowrap text-ellipsis overflow-hidden;
|
|
138
138
|
@apply rounded-lg;
|
|
@@ -209,14 +209,15 @@ export default{
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
.button-secondary{
|
|
212
|
-
@apply bg-secondary text-text-500 rounded-lg;
|
|
212
|
+
@apply bg-secondary-200 text-text-500 rounded-lg;
|
|
213
213
|
box-shadow: 0 2px 1px rgba(0, 0, 0, .05);
|
|
214
|
-
outline: solid 1px rgb(var(--secondary-
|
|
215
|
-
border: solid 1px rgb(var(--secondary-
|
|
214
|
+
outline: solid 1px rgb(var(--secondary-200));
|
|
215
|
+
border: solid 1px rgb(var(--secondary-200));
|
|
216
216
|
}
|
|
217
217
|
.button-secondary:hover{
|
|
218
|
-
@apply bg-secondary-
|
|
219
|
-
outline-color: rgb(var(--secondary-
|
|
218
|
+
@apply bg-secondary-100;
|
|
219
|
+
outline-color: rgb(var(--secondary-100));
|
|
220
|
+
border-color: rgb(var(--secondary-100));
|
|
220
221
|
}
|
|
221
222
|
.button-secondary:disabled{
|
|
222
223
|
@apply bg-secondary-500 opacity-50 top-0 left-0 cursor-not-allowed;
|
|
@@ -275,13 +276,6 @@ export default{
|
|
|
275
276
|
fill-opacity: 75%;
|
|
276
277
|
}
|
|
277
278
|
|
|
278
|
-
.size-sm{
|
|
279
|
-
@apply h-[var(--h-cp-sm)];
|
|
280
|
-
}
|
|
281
|
-
.size-lg{
|
|
282
|
-
@apply h-[var(--h-cp-lg)];
|
|
283
|
-
}
|
|
284
|
-
|
|
285
279
|
.loadingPane{
|
|
286
280
|
@apply absolute left-0 top-0 right-0 bottom-0 flex items-center justify-center pl-1;
|
|
287
281
|
}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
<div ref="inner" :class="computedContainerClass">
|
|
5
5
|
<div v-for="item in items" :class="computedItemClass">
|
|
6
6
|
<component :is="item.type"
|
|
7
|
-
:="item"
|
|
7
|
+
:="item"
|
|
8
|
+
edit-selectable="false" />
|
|
8
9
|
</div>
|
|
9
10
|
</div>
|
|
10
11
|
|
|
@@ -27,7 +28,6 @@
|
|
|
27
28
|
</slot>
|
|
28
29
|
</div>
|
|
29
30
|
</div>
|
|
30
|
-
|
|
31
31
|
</div>
|
|
32
32
|
</template>
|
|
33
33
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="$style.comp">
|
|
3
3
|
|
|
4
|
-
<div class="overflow-x-auto">
|
|
4
|
+
<div class="overflow-x-auto bg-text-50">
|
|
5
5
|
<div class="flex flex-row">
|
|
6
6
|
<button class="p-3" type="button" @click="format('bold')">
|
|
7
7
|
<svg width="14" height="14" class="fill-text-400 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M0 64C0 46.3 14.3 32 32 32H80 96 224c70.7 0 128 57.3 128 128c0 31.3-11.3 60.1-30 82.3c37.1 22.4 62 63.1 62 109.7c0 70.7-57.3 128-128 128H96 80 32c-17.7 0-32-14.3-32-32s14.3-32 32-32H48V256 96H32C14.3 96 0 81.7 0 64zM224 224c35.3 0 64-28.7 64-64s-28.7-64-64-64H112V224H224zM112 288V416H256c35.3 0 64-28.7 64-64s-28.7-64-64-64H224 112z"/></svg>
|
|
@@ -545,7 +545,7 @@ export default{
|
|
|
545
545
|
<style module>
|
|
546
546
|
|
|
547
547
|
.comp{
|
|
548
|
-
@apply flex-1 flex flex-col;
|
|
548
|
+
@apply flex-1 flex flex-col border-[1px] border-text-200 rounded-lg;
|
|
549
549
|
}
|
|
550
550
|
|
|
551
551
|
.comp article {
|
package/src/components/Image.vue
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
<slot v-else-if="status === 1" name="loading">
|
|
7
7
|
<div :class="$style.loading + (spinnerType === 'shimmer' ? ' ' + $style.shimmer : '')">
|
|
8
|
-
<svg v-if="spinnerType !== 'shimmer'" class="animate-spin aspect-square w-[15%] min-w-[14px]
|
|
8
|
+
<svg v-if="spinnerType !== 'shimmer'" class="animate-spin aspect-square w-[15%] min-w-[14px]" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
|
9
9
|
</div>
|
|
10
10
|
</slot>
|
|
11
11
|
|
|
@@ -109,10 +109,12 @@ export default{
|
|
|
109
109
|
},
|
|
110
110
|
|
|
111
111
|
attachReorder(){
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
if(this.$el && this.$el.nodeType === 1){
|
|
113
|
+
this.$el.querySelectorAll('[data-reorder]').forEach((comp) => {
|
|
114
|
+
comp.addEventListener('mousedown', this.onDrag)
|
|
115
|
+
comp.addEventListener('touchstart', this.onDrag)
|
|
116
|
+
})
|
|
117
|
+
}
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
},
|
|
@@ -144,4 +146,4 @@ export default{
|
|
|
144
146
|
@apply opacity-50
|
|
145
147
|
}
|
|
146
148
|
|
|
147
|
-
</style>
|
|
149
|
+
</style>
|
package/src/components/Modal.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
<Teleport to=".bW9k">
|
|
4
|
-
<Transition :name="
|
|
4
|
+
<Transition :name="computedTransition"
|
|
5
5
|
appear
|
|
6
6
|
@after-leave="onAfterLeave(); $emit('hide')"
|
|
7
7
|
@after-enter="$emit('show')">
|
|
@@ -81,7 +81,7 @@ export default{
|
|
|
81
81
|
|
|
82
82
|
state: [ Number, Boolean, String ],
|
|
83
83
|
|
|
84
|
-
transition:
|
|
84
|
+
transition: String,
|
|
85
85
|
|
|
86
86
|
width: String,
|
|
87
87
|
|
|
@@ -176,6 +176,26 @@ export default{
|
|
|
176
176
|
}
|
|
177
177
|
},
|
|
178
178
|
|
|
179
|
+
computedTransition(){
|
|
180
|
+
if(this.transition){
|
|
181
|
+
return this.transition
|
|
182
|
+
}
|
|
183
|
+
else{
|
|
184
|
+
switch(this.position){
|
|
185
|
+
case 'top':
|
|
186
|
+
return 'slidedown'
|
|
187
|
+
case 'bottom':
|
|
188
|
+
return 'slideup'
|
|
189
|
+
case 'left':
|
|
190
|
+
return 'slideright'
|
|
191
|
+
case 'right':
|
|
192
|
+
return 'slideleft'
|
|
193
|
+
case 'center':
|
|
194
|
+
return 'slideout'
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
|
|
179
199
|
computedState(){
|
|
180
200
|
return this.state ? Boolean(this.state) : this._state
|
|
181
201
|
},
|
|
@@ -233,11 +253,11 @@ export default{
|
|
|
233
253
|
<style>
|
|
234
254
|
|
|
235
255
|
.bW9k{
|
|
236
|
-
@apply fixed z-20 top-0 left-0 bottom-0 right-0 hidden
|
|
256
|
+
@apply fixed z-20 top-0 left-0 bottom-0 right-0 hidden;
|
|
237
257
|
@apply bg-black/50 backdrop-blur-md;
|
|
238
258
|
}
|
|
239
259
|
.bW9l{
|
|
240
|
-
@apply
|
|
260
|
+
@apply grid;
|
|
241
261
|
}
|
|
242
262
|
|
|
243
263
|
</style>
|
|
@@ -286,11 +306,28 @@ html[data-theme='dark'] .overlay{
|
|
|
286
306
|
width: 100vw !important;
|
|
287
307
|
}
|
|
288
308
|
|
|
309
|
+
.modal-left{
|
|
310
|
+
justify-self: start;
|
|
311
|
+
align-self: center;
|
|
312
|
+
}
|
|
313
|
+
|
|
289
314
|
.modal-center{
|
|
315
|
+
justify-self: center;
|
|
290
316
|
align-self: center;
|
|
291
317
|
}
|
|
292
318
|
|
|
319
|
+
.modal-right{
|
|
320
|
+
justify-self: end;
|
|
321
|
+
align-self: center;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.modal-top{
|
|
325
|
+
justify-self: center;
|
|
326
|
+
align-self: start;
|
|
327
|
+
}
|
|
328
|
+
|
|
293
329
|
.modal-bottom{
|
|
330
|
+
justify-self: center;
|
|
294
331
|
align-self: end;
|
|
295
332
|
}
|
|
296
333
|
|
|
@@ -301,6 +338,8 @@ html[data-theme='dark'] .overlay{
|
|
|
301
338
|
.modal {
|
|
302
339
|
max-width: 90vw;
|
|
303
340
|
width: 480px;
|
|
341
|
+
justify-self: center;
|
|
342
|
+
align-self: center;
|
|
304
343
|
}
|
|
305
344
|
|
|
306
345
|
}
|
|
@@ -323,4 +362,60 @@ html[data-theme='dark'] .overlay{
|
|
|
323
362
|
transform: translate3d(0, 10px, 0);
|
|
324
363
|
}
|
|
325
364
|
|
|
365
|
+
.slidedown-enter-active,
|
|
366
|
+
.slidedown-leave-active {
|
|
367
|
+
transition: all 300ms cubic-bezier(0.25, 1, 0.5, 1);
|
|
368
|
+
}
|
|
369
|
+
.slidedown-enter-active,
|
|
370
|
+
.slidedown-leave-active {
|
|
371
|
+
transform: translate3d(0, 0, 0);
|
|
372
|
+
}
|
|
373
|
+
.slidedown-enter-from,
|
|
374
|
+
.slidedown-leave-to {
|
|
375
|
+
opacity: 0;
|
|
376
|
+
transform: translate3d(0, -10px, 0);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.slideleft-enter-active,
|
|
380
|
+
.slideleft-leave-active {
|
|
381
|
+
transition: all 300ms cubic-bezier(0.25, 1, 0.5, 1);
|
|
382
|
+
}
|
|
383
|
+
.slideleft-enter-active,
|
|
384
|
+
.slideleft-leave-active {
|
|
385
|
+
transform: translate3d(0, 0, 0);
|
|
386
|
+
}
|
|
387
|
+
.slideleft-enter-from,
|
|
388
|
+
.slideleft-leave-to {
|
|
389
|
+
opacity: 0;
|
|
390
|
+
transform: translate3d(10px, 0, 0);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.slideright-enter-active,
|
|
394
|
+
.slideright-leave-active {
|
|
395
|
+
transition: all 300ms cubic-bezier(0.25, 1, 0.5, 1);
|
|
396
|
+
}
|
|
397
|
+
.slideright-enter-active,
|
|
398
|
+
.slideright-leave-active {
|
|
399
|
+
transform: translate3d(0, 0, 0);
|
|
400
|
+
}
|
|
401
|
+
.slideright-enter-from,
|
|
402
|
+
.slideright-leave-to {
|
|
403
|
+
opacity: 0;
|
|
404
|
+
transform: translate3d(-10px, 0, 0);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.slideout-enter-active,
|
|
408
|
+
.slideout-leave-active {
|
|
409
|
+
transition: all 300ms cubic-bezier(0.25, 1, 0.5, 1);
|
|
410
|
+
}
|
|
411
|
+
.slideout-enter-active,
|
|
412
|
+
.slideout-leave-active {
|
|
413
|
+
transform: scale(1);
|
|
414
|
+
}
|
|
415
|
+
.slideout-enter-from,
|
|
416
|
+
.slideout-leave-to {
|
|
417
|
+
opacity: 0;
|
|
418
|
+
transform: scale(.9);
|
|
419
|
+
}
|
|
420
|
+
|
|
326
421
|
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<p :class="$style.comp" v-html="html"></p>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
|
|
7
|
+
import {componentMixin} from "../mixin/component";
|
|
8
|
+
|
|
9
|
+
export default{
|
|
10
|
+
|
|
11
|
+
mixins: [ componentMixin ],
|
|
12
|
+
|
|
13
|
+
props: {
|
|
14
|
+
html: String
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<style module>
|
|
22
|
+
|
|
23
|
+
.comp{
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
</style>
|
package/src/components/Radio.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :class="
|
|
3
|
-
<div :class="$style.indicator">
|
|
2
|
+
<div :class="compClass" @click="onChange">
|
|
3
|
+
<div :class="$style.indicator" v-if="variant === 'radio'">
|
|
4
4
|
<div>
|
|
5
5
|
<svg width="14" height="14" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>
|
|
6
6
|
</div>
|
|
@@ -22,11 +22,25 @@ export default{
|
|
|
22
22
|
checked: undefined,
|
|
23
23
|
modelValue: undefined,
|
|
24
24
|
value: undefined,
|
|
25
|
-
disabled: undefined
|
|
25
|
+
disabled: undefined,
|
|
26
|
+
variant: {
|
|
27
|
+
type: String,
|
|
28
|
+
default: 'radio', // radio|square
|
|
29
|
+
}
|
|
26
30
|
},
|
|
27
31
|
|
|
28
32
|
computed: {
|
|
29
33
|
|
|
34
|
+
compClass(){
|
|
35
|
+
return [
|
|
36
|
+
this.$style.comp,
|
|
37
|
+
(this.cChecked ? ' ' + this.$style.checked : ''),
|
|
38
|
+
(this.isDisabled ? ' ' + this.$style.disabled : ''),
|
|
39
|
+
this.$style[this.variant]
|
|
40
|
+
]
|
|
41
|
+
.join(' ')
|
|
42
|
+
},
|
|
43
|
+
|
|
30
44
|
id(){
|
|
31
45
|
return this.$style.comp + this.uniqid()
|
|
32
46
|
},
|
|
@@ -58,7 +72,7 @@ export default{
|
|
|
58
72
|
<style module>
|
|
59
73
|
|
|
60
74
|
.comp{
|
|
61
|
-
@apply
|
|
75
|
+
@apply flex items-center cursor-pointer;
|
|
62
76
|
@apply flex flex-row items-center gap-2
|
|
63
77
|
}
|
|
64
78
|
|
|
@@ -84,4 +98,15 @@ export default{
|
|
|
84
98
|
@apply border-primary;
|
|
85
99
|
}
|
|
86
100
|
|
|
101
|
+
.radio{
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.square{
|
|
106
|
+
@apply border-[2px] border-transparent;
|
|
107
|
+
}
|
|
108
|
+
.square.checked{
|
|
109
|
+
@apply border-primary;
|
|
110
|
+
}
|
|
111
|
+
|
|
87
112
|
</style>
|
package/src/components/Tabs.vue
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
<div :class="computedClass">
|
|
3
3
|
<button v-for="(item, index) in filteredItems" :class="tabClass(item)"
|
|
4
4
|
@click="onClick(item)" type="button" >
|
|
5
|
-
<slot
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
</div>
|
|
5
|
+
<slot name="tab" :="{ item, index }">
|
|
6
|
+
{{ item.text }}
|
|
7
|
+
</slot>
|
|
9
8
|
</button>
|
|
10
9
|
</div>
|
|
11
10
|
</template>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<input :type="computedType" :disabled="isDisabled" @focus="isActive = true" @input="onInput" @blur="onBlur"
|
|
5
5
|
:placeholder="placeholder" :maxlength="maxlength" ref="input" autocomplete="new-password"
|
|
6
6
|
:value="displayedValue" :readonly="Boolean(readonly)" @paste="onPaste"
|
|
7
|
+
:class="itemClass"
|
|
7
8
|
@keydown="onKeyDown"/>
|
|
8
9
|
<button class="mr-2" v-if="Boolean(clearable) && !Boolean(readonly) && state >= 1 && modelValue" type="button" @click="$emit('clear')">
|
|
9
10
|
<svg :class="$style.svg" width="19" height="19" viewBox="0 0 24 24" class="fill-text-200" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -50,7 +51,9 @@ export default{
|
|
|
50
51
|
placeholder: String,
|
|
51
52
|
readonly: undefined,
|
|
52
53
|
maxlength: [ String, Number ],
|
|
53
|
-
type: String // text, tel, password, number,
|
|
54
|
+
type: String, // text, tel, password, number,
|
|
55
|
+
|
|
56
|
+
itemClass: String
|
|
54
57
|
|
|
55
58
|
},
|
|
56
59
|
|
|
@@ -172,7 +175,6 @@ export default{
|
|
|
172
175
|
<style module>
|
|
173
176
|
|
|
174
177
|
.textbox{
|
|
175
|
-
@apply min-h-[var(--h-cp)];
|
|
176
178
|
@apply flex items-center border-[1px] border-text-200;
|
|
177
179
|
@apply rounded-lg overflow-hidden;
|
|
178
180
|
}
|
|
@@ -181,13 +183,11 @@ export default{
|
|
|
181
183
|
@apply bg-text-50;
|
|
182
184
|
}
|
|
183
185
|
|
|
184
|
-
.size-sm{ @apply min-h-[var(--h-cp-sm)]; }
|
|
185
186
|
.size-sm input{ @apply text-sm; }
|
|
186
187
|
|
|
187
|
-
.size-lg{ @apply min-h-[var(--h-cp-lg)]; }
|
|
188
188
|
|
|
189
189
|
.textbox>input{
|
|
190
|
-
@apply flex-1 outline-none p-
|
|
190
|
+
@apply flex-1 outline-none p-3 bg-transparent;
|
|
191
191
|
font-size: inherit;
|
|
192
192
|
}
|
|
193
193
|
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
@change="$emit('change')"
|
|
11
11
|
@remove="confirm({ title:$t('Remove this item?'), onConfirm: () => { modelValue.splice(index, 1);$emit('change') }})"
|
|
12
12
|
@add="(items) => $emit('add', items)">
|
|
13
|
-
<template #default="{ item }">
|
|
14
|
-
<slot :item="item"></slot>
|
|
13
|
+
<template #default="{ item, parent }">
|
|
14
|
+
<slot :item="item" :parent="parent"></slot>
|
|
15
15
|
</template>
|
|
16
16
|
</TreeViewItem>
|
|
17
17
|
|
|
@@ -82,7 +82,12 @@ export default{
|
|
|
82
82
|
|
|
83
83
|
mounted() {
|
|
84
84
|
window.addEventListener('keydown', this.onKeyUp)
|
|
85
|
-
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
watch: {
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
}
|
|
86
91
|
|
|
87
92
|
}
|
|
88
93
|
|
|
@@ -5,49 +5,51 @@
|
|
|
5
5
|
:class="itemClass"
|
|
6
6
|
@mousedown="mouseDown">
|
|
7
7
|
|
|
8
|
-
<button type="button" class="
|
|
8
|
+
<button type="button" class="p-1 w-[18px]"
|
|
9
|
+
v-if="Array.isArray((item ?? {}).items) && item.items.length > 0"
|
|
9
10
|
@click="childCollapsed = !childCollapsed">
|
|
10
|
-
<svg v-if="!childCollapsed" width="
|
|
11
|
-
<svg v-else width="
|
|
11
|
+
<svg v-if="!childCollapsed" width="14" height="14" class="fill-text-300 pointer-events-none" 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>
|
|
12
|
+
<svg v-else width="14" height="14" class="fill-text-300 pointer-events-none" 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>
|
|
12
13
|
</button>
|
|
13
|
-
<div v-else class="px-2"></div>
|
|
14
14
|
|
|
15
|
-
<
|
|
15
|
+
<div class="flex-1 flex px-3">
|
|
16
|
+
<slot :item="item" :parent="parent"></slot>
|
|
17
|
+
</div>
|
|
16
18
|
|
|
17
|
-
<div class="flex flex-row
|
|
19
|
+
<div class="flex flex-row items-center">
|
|
18
20
|
<button v-if="item && Array.isArray(item.items)"
|
|
19
21
|
type="button"
|
|
20
|
-
class="
|
|
22
|
+
class="p-1"
|
|
21
23
|
@click="add">
|
|
22
24
|
<svg width="16" height="16" class="fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M376 232H216V72c0-4.42-3.58-8-8-8h-32c-4.42 0-8 3.58-8 8v160H8c-4.42 0-8 3.58-8 8v32c0 4.42 3.58 8 8 8h160v160c0 4.42 3.58 8 8 8h32c4.42 0 8-3.58 8-8V280h160c4.42 0 8-3.58 8-8v-32c0-4.42-3.58-8-8-8z"/></svg>
|
|
23
25
|
</button>
|
|
24
26
|
|
|
25
27
|
<button type="button"
|
|
26
|
-
class="
|
|
28
|
+
class="p-1"
|
|
27
29
|
@click="$emit('remove')">
|
|
28
30
|
<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>
|
|
29
31
|
</button>
|
|
30
32
|
</div>
|
|
31
33
|
|
|
32
34
|
</div>
|
|
33
|
-
|
|
34
|
-
v-
|
|
35
|
+
<div ref="container"
|
|
36
|
+
v-show="item && Array.isArray(item.items) && !childCollapsed" class="ml-6"
|
|
35
37
|
@mousemove.stop=""
|
|
36
38
|
@mouseout.stop="">
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
<TreeViewItem v-for="(subItem, index) in item.items"
|
|
40
|
+
:item="subItem"
|
|
41
|
+
:parent="item.items"
|
|
42
|
+
:selected-item="selectedItem"
|
|
43
|
+
@moveup="moveUp(subItem)"
|
|
44
|
+
@movedown="moveDown(subItem)"
|
|
45
|
+
@remove="confirm({ title:$t('Remove this item?'), onConfirm: () => { item.items.splice(index, 1);$emit('change') }})"
|
|
46
|
+
@add="(items) => $emit('add', items)"
|
|
47
|
+
@change="$emit('change')">
|
|
48
|
+
<template #default="{ item }">
|
|
49
|
+
<slot :item="item"></slot>
|
|
50
|
+
</template>
|
|
51
|
+
</TreeViewItem>
|
|
52
|
+
</div>
|
|
51
53
|
</div>
|
|
52
54
|
</template>
|
|
53
55
|
|
|
@@ -101,6 +103,8 @@ export default{
|
|
|
101
103
|
},
|
|
102
104
|
|
|
103
105
|
mouseDown(e){
|
|
106
|
+
if(!this.$el || this.$el.nodeType !== 1) return
|
|
107
|
+
|
|
104
108
|
e.preventDefault()
|
|
105
109
|
|
|
106
110
|
const startX = e.clientX
|
|
@@ -327,18 +331,16 @@ export default{
|
|
|
327
331
|
},
|
|
328
332
|
|
|
329
333
|
mounted() {
|
|
330
|
-
|
|
331
334
|
if(this.componentStore){
|
|
332
335
|
this.childCollapsed = this.componentStore[this.item.uid] ?? this.childCollapsed
|
|
333
336
|
}
|
|
334
|
-
|
|
335
337
|
},
|
|
336
338
|
|
|
337
339
|
watch: {
|
|
338
340
|
|
|
339
341
|
item: {
|
|
340
342
|
handler(){
|
|
341
|
-
this.childCollapsed =
|
|
343
|
+
this.childCollapsed = this.componentStore[this.item.uid] ?? this.childCollapsed
|
|
342
344
|
},
|
|
343
345
|
deep: true
|
|
344
346
|
},
|
|
@@ -356,11 +358,37 @@ export default{
|
|
|
356
358
|
},
|
|
357
359
|
|
|
358
360
|
isSelected(to){
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
361
|
+
if(to){
|
|
362
|
+
|
|
363
|
+
// Expand all parents
|
|
364
|
+
let parent = this.$parent
|
|
365
|
+
while('childCollapsed' in parent){
|
|
366
|
+
parent.childCollapsed = false
|
|
367
|
+
parent = parent.$parent
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Scroll into view
|
|
371
|
+
this.$nextTick(() => {
|
|
372
|
+
let parentContainer = this.$el.parentNode
|
|
373
|
+
do{
|
|
374
|
+
if([ 'auto' ].includes(window.getComputedStyle(parentContainer).overflowY)){
|
|
375
|
+
break
|
|
376
|
+
}
|
|
377
|
+
parentContainer = parentContainer.parentNode
|
|
378
|
+
}
|
|
379
|
+
while(parentContainer && parentContainer.tagName !== 'BODY')
|
|
380
|
+
|
|
381
|
+
let isInViewPort = this.$el.offsetTop > parentContainer.scrollTop &&
|
|
382
|
+
this.$el.offsetTop < (parentContainer.scrollTop + parentContainer.clientHeight)
|
|
383
|
+
|
|
384
|
+
if(!isInViewPort){
|
|
385
|
+
this.$el.scrollIntoView({
|
|
386
|
+
behavior: 'smooth',
|
|
387
|
+
})
|
|
388
|
+
}
|
|
362
389
|
})
|
|
363
|
-
|
|
390
|
+
|
|
391
|
+
}
|
|
364
392
|
}
|
|
365
393
|
|
|
366
394
|
},
|
|
@@ -372,7 +400,7 @@ export default{
|
|
|
372
400
|
<style module>
|
|
373
401
|
|
|
374
402
|
.item{
|
|
375
|
-
@apply bg-base-300 dark:bg-base-400 flex flex-row
|
|
403
|
+
@apply bg-base-300 dark:bg-base-400 flex flex-row py-1 items-center rounded-lg mb-1;
|
|
376
404
|
@apply border-[1px] border-transparent cursor-pointer;
|
|
377
405
|
}
|
|
378
406
|
.item.active{
|