@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.
Files changed (54) hide show
  1. package/package.json +1 -1
  2. package/src/components/Button.vue +7 -13
  3. package/src/components/Carousel.vue +2 -2
  4. package/src/components/HTMLEditor.vue +2 -2
  5. package/src/components/Image.vue +1 -1
  6. package/src/components/ListItem.vue +7 -5
  7. package/src/components/Modal.vue +99 -4
  8. package/src/components/Paragraph.vue +27 -0
  9. package/src/components/Radio.vue +29 -4
  10. package/src/components/Tabs.vue +3 -4
  11. package/src/components/Textbox.vue +5 -5
  12. package/src/components/TreeView.vue +8 -3
  13. package/src/components/TreeViewItem.vue +60 -32
  14. package/src/index.js +5 -20
  15. package/src/mixin/component.js +10 -0
  16. package/src/themes/default/index.js +20 -14
  17. package/src/utils/helpers.mjs +32 -0
  18. package/src/widgets/ComponentSetting.vue +1256 -667
  19. package/src/widgets/FeatureListSetting.vue +3 -3
  20. package/src/widgets/FlexSetting.vue +1 -1
  21. package/src/widgets/Header.vue +4 -39
  22. package/src/widgets/Header1.vue +50 -0
  23. package/src/widgets/Header2.vue +103 -0
  24. package/src/widgets/HeaderSetting.vue +212 -4
  25. package/src/widgets/IconListSetting.vue +3 -3
  26. package/src/widgets/ImageSetting.vue +2 -2
  27. package/src/widgets/MarginSetting.vue +4 -4
  28. package/src/widgets/MultiValueSetting.vue +121 -0
  29. package/src/widgets/PaddingSetting.vue +4 -4
  30. package/src/widgets/ParagraphSetting.vue +86 -0
  31. package/src/widgets/TextBlockSetting.vue +1 -1
  32. package/src/widgets/WebDatasourceSelector.vue +3 -3
  33. package/src/widgets/WebPageBuilder.vue +1324 -1159
  34. package/tailwind.config.js +121 -13
  35. package/src/widgets/AhrefItem.vue +0 -25
  36. package/src/widgets/ArticleItem.vue +0 -25
  37. package/src/widgets/BlockItem.vue +0 -25
  38. package/src/widgets/BoxItem.vue +0 -25
  39. package/src/widgets/ButtonItem.vue +0 -25
  40. package/src/widgets/CarouselItem.vue +0 -19
  41. package/src/widgets/ContactFormItem.vue +0 -25
  42. package/src/widgets/EmbeddedVideoItem.vue +0 -25
  43. package/src/widgets/FAQItem.vue +0 -25
  44. package/src/widgets/FeatureListItem.vue +0 -25
  45. package/src/widgets/FlexItem.vue +0 -27
  46. package/src/widgets/GridItem.vue +0 -29
  47. package/src/widgets/HeaderItem.vue +0 -25
  48. package/src/widgets/IconListItem.vue +0 -25
  49. package/src/widgets/ImageItem.vue +0 -19
  50. package/src/widgets/ReviewItem.vue +0 -25
  51. package/src/widgets/ShareItem.vue +0 -25
  52. package/src/widgets/TableItem.vue +0 -25
  53. package/src/widgets/TestimonialItem.vue +0 -25
  54. package/src/widgets/TextBlockItem.vue +0 -25
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mixd-id/web-scaffold",
3
3
  "private": false,
4
- "version": "0.1.230406174",
4
+ "version": "0.1.230406176",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -132,7 +132,7 @@ export default{
132
132
  <style module>
133
133
 
134
134
  .button{
135
- @apply p-2 h-[var(--h-cp)];
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-700));
215
- border: solid 1px rgb(var(--secondary-400));
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-600;
219
- outline-color: rgb(var(--secondary-800))
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 {
@@ -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] text-primary" 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>
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
- this.$el.querySelectorAll('[data-reorder]').forEach((comp) => {
113
- comp.addEventListener('mousedown', this.onDrag)
114
- comp.addEventListener('touchstart', this.onDrag)
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>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div>
3
3
  <Teleport to=".bW9k">
4
- <Transition :name="transition"
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: { type: String, default: 'slideup' },
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 items-center justify-center;
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 flex;
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>
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <div :class="$style.comp + (cChecked ? ' ' + $style.checked : '') + (isDisabled ? ' ' + $style.disabled : '')" @click="onChange">
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 h-[var(--h-cp)] flex items-center cursor-pointer;
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>
@@ -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 v-if="$slots.tab" name="tab" :="{ item, index }"></slot>
6
- <div v-else :class="$style.item">
7
- {{ item.text }}
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-2 bg-transparent;
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="py-1" v-if="Array.isArray((item ?? {}).items) && item.items.length > 0"
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="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>
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>
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
- <slot :item="item"></slot>
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 gap-2 items-center">
19
+ <div class="flex flex-row items-center">
18
20
  <button v-if="item && Array.isArray(item.items)"
19
21
  type="button"
20
- class="py-1"
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="py-1"
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
- <div ref="container"
34
- v-if="item && Array.isArray(item.items) && !childCollapsed" class="ml-4"
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
- <TreeViewItem v-for="(subItem, index) in item.items"
38
- :item="subItem"
39
- :parent="item.items"
40
- :selected-item="selectedItem"
41
- @moveup="moveUp(subItem)"
42
- @movedown="moveDown(subItem)"
43
- @remove="confirm({ title:$t('Remove this item?'), onConfirm: () => { item.items.splice(index, 1);$emit('change') }})"
44
- @add="(items) => $emit('add', items)"
45
- @change="$emit('change')">
46
- <template #default="{ item }">
47
- <slot :item="item"></slot>
48
- </template>
49
- </TreeViewItem>
50
- </div>
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 = false
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
- /*if(to){
360
- this.$el.scrollIntoView({
361
- behavior: 'smooth',
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 gap-2 px-2 py-1 items-center rounded-lg mb-1;
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{